Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * LiveSearch.js
- * @author Oliver Dixon (2017)
- *
- * Allows the user to get search results as they're typing (800ms lag to
- * prevent too much of a heavy load on the database/server).
- */
- /* jshint -W097 */
- "use strict";
- /*
- * "Live Search" stuff
- * Allows users to get instant search results by performing AJAX requests.
- * */
- var target = document.getElementById("searchOutput");
- var container = document.getElementById("searchContainer");
- var searchBox = document.getElementById("searchBox");
- var errOutput = document.getElementById("searchErr");
- searchBox.addEventListener("keyup", invokeLS);
- /**
- * Function invokeLS
- *
- * Invokes the liveSearch function, passing in the search terms.
- *
- * I wrapped this in a function so it's friendly with the awful addEventListener
- * and removeEventListener functions...
- *
- * It also waits for 800ms of keyUp inactivity before it invokes liveSearch,
- * so the server doesn't constantly get hammered with requests.
- */
- var timeout;
- function invokeLS() {
- // If there is no query, no point to have any lag, just get rid of the output box!
- if (searchBox.value.length === 0) {
- /* The outputSearchResults function takes care of resetting target.innerHTML etc.
- * before showing any new results. */
- container.style.display = "none";
- return;
- }
- // Otherwise, wait for 0.8 seconds of key inactivity then send the request.
- clearTimeout(timeout);
- timeout = setTimeout(function() {
- liveSearch(searchBox.value);
- }, 800);
- }
- /**
- * Function errHandler
- *
- * Should be called when a fatal error happens with the liveSearch function.
- *
- * When called, it disables the textbox and disconnects the event listener, and displays
- * an error.
- *
- * @param {string} msg
- */
- function errHandler(msg) {
- errOutput.innerHTML = "<div style='color: #f00;'>An error occurred (" + msg + "). Check the console for more details.</div>";
- searchBox.value = ""; // allow placeholder
- searchBox.placeholder = "An error occurred. Try refreshing the page.";
- searchBox.removeEventListener("keyup", invokeLS);
- searchBox.disabled = true;
- }
- /**
- * Function liveSearch
- *
- * Performs the AJAX request and deals with error handling.
- * If everything is OK, send to outputSearchResults to display them.
- *
- * Expects a JSON response from the server.
- *
- * @param {string} query - the search term to send to the server
- */
- function liveSearch(query) {
- if (query.length !== 0) {
- var xmlhttp = new XMLHttpRequest();
- /**
- * Anonymous error function
- *
- * Fired when a network-level error occurs on the XMLHTTPRequest.
- * Also gets fired when an attempted cross-domain request is made.
- */
- xmlhttp.onerror = function() {
- errHandler(this.error);
- };
- xmlhttp.ontimeout = function() {
- errHandler("the timeout was exceeded, try the <a href='search.php'>advanced search</a> page");
- };
- /**
- * Anonymous onreadystatechange function
- *
- * Gets fired when something about the XMLHTTPRequest object has changed.
- * Usually it means it has completed, this can be checked if xmlhttp.status = 200.
- */
- xmlhttp.onreadystatechange = function() {
- if (this.readyState === 4) {
- if (this.status === 200) {
- var json = null;
- try {
- json = JSON.parse(this.responseText);
- } catch (e) {
- // Error parsing JSON (invalid response)
- errHandler("The response was not valid JSON!");
- return;
- }
- /* Error checking
- * If the err attribute is set, and error has happened */
- //noinspection JSUnresolvedVariable
- if (json.err !== undefined) {
- //noinspection JSUnresolvedVariable
- errHandler(json.err);
- return;
- }
- if (json.length === 0) {
- target.innerHTML = "No results were found.<br />Try widening your search.";
- return;
- }
- outputSearchResults(json);
- } else {
- errHandler("invalid HTTP response code of " + this.status);
- }
- }
- };
- xmlhttp.open("GET", "apiResponder.php?mode=0&query=" + query, true);
- xmlhttp.timeout = 3000;
- xmlhttp.send();
- }
- }
- /**
- * Output search results
- * @param {string} results (JSON)
- */
- function outputSearchResults(results) {
- target.innerHTML = "";
- container.style.display = "block";
- var successful = 0;
- for (var i = 0; i < results.length - 1; i++) {
- if (i === 40) { // max of 40 values
- break;
- }
- if (
- results[i] !== undefined &&
- results[i].title !== /** @type {string} */ undefined &&
- results[i].url !== /** @type {string} */ undefined
- ) {
- target.innerHTML +=
- "<div class='result'><div style='padding: 0.6em;'><h3>" +
- results[i].title + "</h3><h4>" + results[i].url + "</h4></div></div><br />";
- successful++;
- } else {
- console.warn("Invalid JSON at index " + i + ": " + results[i]);
- }
- }
- if (
- results[results.length - 1] !== undefined &&
- results[results.length - 1].title !== /** @type {string} */ undefined &&
- results[results.length - 1].url !== /** @type {string} */ undefined
- ) {
- target.innerHTML +=
- "<div class='result'><div style='padding: 0.6em;'><h3>" +
- results[results.length - 1].title + "</h3><h4>" + results[results.length - 1].url + "</h4></div></div>";
- successful++;
- } else {
- console.warn("Invalid JSON at index " + i + ": " + results[i]);
- }
- if (successful === 0) {
- target.innerHTML = "No results were found.<br />Try widening your search.";
- }
- }
Add Comment
Please, Sign In to add comment