1;(function () { 2 var plugin_name = "fp_solr_live_search" 3 4 function FpSolrLiveSearch(element) { 5 this.config = null 6 7 // Internal properties. 8 this.input_el = element 9 this.results_id = null 10 this.results_el = null 11 this.messages = null 12 this.parent_el = null 13 this.results_showing = false 14 this.form_el = null 15 this.timer = false 16 this.last_string = "" 17 this.spinner = null 18 this.spinner_showing = false 19 this.has_results = false 20 this.current_request = false 21 this.results_destroy_on_blur = true 22 this.a11y_keys = [27, 40, 13, 38, 9] 23 24 this.init() 25 } 26 27 FpSolrLiveSearch.prototype = { 28 init: function () { 29 var self = this, 30 $input = this.input_el 31 this.form_el = $input.parents("form:eq(0)") 32 this.results_id = this.uniqid("fp_solr_live_search_results_") 33 34 var valid_config = false 35 var config_template = $input.data("fpsolrconfig") 36 if (config_template && typeof config_template !== "undefined") { 37 for (var config_key in fp_solr_live_search_params.config) { 38 if (config_template === config_key) { 39 valid_config = true 40 this.config = fp_solr_live_search_params.config[config_key] 41 } 42 } 43 } else { 44 for (var default_key in fp_solr_live_search_params.config) { 45 if ("default" === default_key) { 46 valid_config = true 47 this.config = fp_solr_live_search_params.config[default_key] 48 } 49 } 50 } 51 52 if (!valid_config) { 53 alert(fp_solr_live_search_params.msg_no_config_found) 54 } else { 55 $input.attr("autocomplete", "off") 56 57 // ARIA attributes. 58 $input.attr("aria-owns", this.results_id) 59 $input.attr("aria-autocomplete", "both") 60 61 var results_el_html = '<div aria-expanded="false" aria-live="polite" class="fp-solr-live-search-results" id="' + this.results_id + '" role="listbox" tabindex="0">' 62 results_el_html += '<div class="ajax-results"></div>'; 63 results_el_html += '</div>'; 64 65 var fpsolrparentel = $input.data("fpsolrparentel") 66 if (fpsolrparentel) { 67 this.parent_el = jQuery(fpsolrparentel) 68 this.parent_el.html(results_el_html) 69 } else if (this.config.parent_el) { 70 this.parent_el = jQuery(this.config.parent_el) 71 this.parent_el.html(results_el_html) 72 } else { 73 jQuery("body").append(jQuery(results_el_html)) 74 } 75 76 this.results_el = jQuery("#" + this.results_id); 77 this.messages = this.results_el.find('.live-ajax-messages') 78 79 this.position_results() 80 jQuery(window).on("resize", function () { 81 setTimeout(function() { 82 var form = $input.closest("form") 83 if (form.is(":hidden")) { 84 self.destroy_results() 85 } else { 86 self.position_results() 87 } 88 }, 100); 89 }) 90 91 if (typeof this.config.abort_on_enter === "undefined") { 92 this.config.abort_on_enter = true 93 } 94 95 $input 96 .on("keyup input", function (e) { 97 if (jQuery.inArray(e.keyCode, self.a11y_keys) > -1) { 98 return 99 } 100 if ( 101 self.current_request && 102 self.config.abort_on_enter && 103 e.keyCode === 13 104 ) { 105 self.current_request.abort() 106 } 107 if (!self.input_el.val().trim().length) { 108 self.destroy_results() 109 } 110 else if (self.results_showing && e.currentTarget.value.length < self.config.input.min_chars) { 111 self.destroy_results() 112 } 113 else if (!self.results_showing && e.currentTarget.value.length >= self.config.input.min_chars) { 114 self.position_results() 115 self.results_el.addClass("fp-solr-live-search-results-showing") 116 self.show_spinner(self.results_el) 117 self.results_showing = true 118 } 119 if ( 120 self.has_results && 121 !self.spinner_showing && 122 self.last_string !== self.input_el.val().trim() 123 ) { 124 self.results_el.find('.ajax-results').empty() 125 self.results_el.find('.live-ajax-messages').replaceWith(self.messages) 126 self.results_el.find('.live-ajax-messages').append( 127 "<p class='screen-reader-text' id='fp-solr-live-search-status' role='status' aria-live='polite'>" + 128 fp_solr_live_search_params.msg_loading_results + 129 "</p>" 130 ) 131 self.show_spinner(self.results_el) 132 } 133 }) 134 .on("keyup input", jQuery.proxy(this.maybe_search, this)) 135 136 if ( 137 this.config.results_destroy_on_blur || 138 typeof this.config.results_destroy_on_blur === "undefined" 139 ) { 140 jQuery("html").on("click", function (e) { 141 if ( 142 !jQuery(e.target).parents(".fp-solr-live-search-results") 143 .length 144 ) { 145 self.destroy_results() 146 } 147 }) 148 } 149 $input.on("click", function (e) { 150 e.stopPropagation() 151 }) 152 } 153 154 this.load_ajax_messages_template(); 155 }, 156 157 load_ajax_messages_template: function () { 158 if (fp_solr_live_search_params.messages_template) { 159 this.results_el.prepend(fp_solr_live_search_params.messages_template) 160 this.messages = fp_solr_live_search_params.messages_template 161 } 162 }, 163 164 search: function (e) { 165 var self = this, 166 $form = this.form_el, 167 values = $form.serialize(), 168 action = $form.attr("action") ? $form.attr("action") : "", 169 $input = this.input_el, 170 $results = this.results_el 171 172 jQuery(document).trigger("fp_solr_live_search_start", [ 173 $input, 174 $results, 175 $form, 176 action, 177 values, 178 ]) 179 180 this.aria_expanded(false) 181 182 values += 183 "&action=fp_solr_live_search&fp_solr_query=" + 184 encodeURIComponent($input.val()) 185 186 // Send fpsolrdata (post type restriction) if present on the input 187 var fpsolrdata = $input.data("fpsolrdata") 188 if (fpsolrdata) { 189 values += "&fpsolrdata=" + encodeURIComponent( 190 typeof fpsolrdata === "object" ? JSON.stringify(fpsolrdata) : fpsolrdata 191 ) 192 } 193
194 if (action.indexOf("?") !== -1) { 195 action = action.split("?") 196 values += "&" + action[1] 197 } 198 199 this.last_string = $input.val() 200 this.has_results = true 201 202 this.current_request = jQuery.ajax({ 203 url: fp_solr_live_search_params.ajaxurl, 204 type: "POST", 205 data: values, 206 complete: function () { 207 jQuery(document).trigger("fp_solr_live_search_complete", [ 208 $input, 209 $results, 210 $form, 211 action, 212 values, 213 ]) 214 self.spinner_showing = false 215 self.hide_spinner(self.results_el) 216 this.current_request = false 217 jQuery(document).trigger("fp_solr_live_search_shutdown", [ 218 $input, 219 $results, 220 $form, 221 action, 222 values, 223 ]) 224 }, 225 success: function (response) { 226 if (response === 0) { 227 response = "" 228 } 229 jQuery(document).trigger("fp_solr_live_search_success", [ 230 $input, 231 $results, 232 $form, 233 action, 234 values, 235 ]) 236 self.position_results() 237 238 $results.find('.ajax-results').html(response); 239 240 self.aria_expanded(true) 241 self.keyboard_navigation() 242 jQuery(document).trigger("fp_solr_live_search_shutdown", [ 243 $input, 244 $results, 245 $form, 246 action, 247 values, 248 ]) 249 }, 250 }) 251 }, 252 253 keyboard_navigation: function () { 254 var self = this, 255 $input = this.input_el, 256 $results = this.results_el, 257 focused_class = "fp-solr-live-search-result--focused", 258 item_class = ".fp-solr-live-search-result", 259 a11y_keys = this.a11y_keys 260 261 jQuery(document) 262 .off("keyup.fp_solr_a11y") 263 .on("keyup.fp_solr_a11y", function (e) { 264 if (!$results.hasClass("fp-solr-live-search-results-showing")) { 265 jQuery(document).off("keyup.fp_solr_a11y") 266 return 267 } 268 269 if (jQuery.inArray(e.keyCode, a11y_keys) === -1) { 270 return 271 } 272 273 e.preventDefault() 274 275 // Escape key. 276 if (e.keyCode === 27 && !$input.is(":focus")) { 277 self.destroy_results() 278 jQuery(document).off("keyup.fp_solr_a11y") 279 $input.trigger("focus") 280 jQuery(document).trigger("fp_solr_live_escape_results") 281 return 282 } 283 284 // Down arrow. 285 if (e.keyCode === 40) { 286 var $current = jQuery($results[0]).find("." + focused_class) 287 if ($current.length === 1 && $current.next().length === 1) { 288 $current 289 .removeClass(focused_class) 290 .attr("aria-selected", "false") 291 .next() 292 .addClass(focused_class) 293 .attr("aria-selected", "true") 294 .find("a") 295 .trigger("focus") 296 } else { 297 $current.removeClass(focused_class).attr("aria-selected", "false") 298 $results 299 .find(item_class + ":first") 300 .addClass(focused_class) 301 .attr("aria-selected", "true") 302 .find("a") 303 .trigger("focus") 304 } 305 jQuery(document).trigger("fp_solr_live_key_arrowdown_pressed") 306 } 307 308 // Up arrow. 309 if (e.keyCode === 38) { 310 var $currentItem = jQuery($results[0]).find("." + focused_class) 311 if ($currentItem.length === 1 && $currentItem.prev().length === 1) { 312 $currentItem 313 .removeClass(focused_class) 314 .attr("aria-selected", "false") 315 .prev() 316 .addClass(focused_class) 317 .attr("aria-selected", "true") 318 .find("a") 319 .trigger("focus") 320 } else { 321 $currentItem 322 .removeClass(focused_class) 323 .attr("aria-selected", "false") 324 $results 325 .find(item_class + ":last") 326 .addClass(focused_class) 327 .attr("aria-selected", "true") 328 .find("a") 329 .trigger("focus") 330 } 331 jQuery(document).trigger("fp_solr_live_key_arrowup_pressed") 332 } 333 334 // Enter key. 335 if (e.keyCode === 13) { 336 jQuery(document).trigger("fp_solr_live_key_enter_pressed") 337 } 338 339 // Tab key. 340 if (e.keyCode === 9) { 341 jQuery(document).trigger("fp_solr_live_key_tab_pressed") 342 } 343 }) 344 345 jQuery(document).trigger("fp_solr_live_keyboard_navigation") 346 }, 347 348 aria_expanded: function (is_expanded) { 349 var $resultsEl = this.results_el 350 351 if (is_expanded) { 352 $resultsEl.attr("aria-expanded", "true") 353 } else { 354 $resultsEl.attr("aria-expanded", "false") 355 } 356 357 jQuery(document).trigger("fp_solr_live_aria_expanded") 358 }, 359 360 position_results: function () { 361 var $input = this.input_el, 362 input_offset = $input.offset(), 363 $results = this.results_el, 364 results_top_offset = 0 365 366 var form = $input.closest("form") 367 if ($input.is(":hidden") || form.is(":hidden")) { 368 return 369 } 370 371 input_offset.top = this.better_offset(this.config.results.static_offset, $input) 372 373 if (!this.parent_el) { 374 input_offset.left += parseInt(this.config.results.offset.x, 10) 375 input_offset.top += parseInt(this.config.results.offset.y, 10) 376 377 switch (this.config.results.position) { 378 case "top": 379 results_top_offset = 0 - $results.height() 380 break 381 default: 382 results_top_offset = $input.outerHeight() 383 } 384 $results.css("left", input_offset.left) 385 $results.css("top", input_offset.top + results_top_offset + "px") 386 } else { 387 input_offset.left += parseInt(this.config.results.offset.x, 10) 388 input_offset.top += parseInt(this.config.results.offset.y, 10) 389 390 switch (this.config.results.position) { 391 case "top": 392 results_top_offset = 0 - $results.height() 393 break 394 default: 395 results_top_offset = $input.outerHeight() 396 } 397 398 $results.css("left", input_offset.left) 399 $results.css("top", input_offset.top + results_top_offset + "px") 400 } 401 402 if ("auto" === this.config.results.width) { 403 $results.width( 404 $input.outerWidth() - 405 parseInt($results.css("paddingRight").replace("px", ""), 10) - 406 parseInt($results.css("paddingLeft").replace("px", ""), 10) 407 ) 408 } 409 410 jQuery(document).trigger("fp_solr_live_position_results", [ 411 $results.css("left"), 412 $results.css("top"), 413 $results.width(), 414 ]) 415 }, 416 417 better_offset: function (is_static, e, v) { 418 is_static = (typeof is_static == 'boolean') ? is_static : true; 419 e = (typeof e == 'object') ? e : $(e); 420 if (v != undefined) {v = (typeof v == 'object') ? v : $(v);} else {v = null;} 421 422 var w = jQuery(window), 423 wp = w.scrollTop(), 424 eo = e.offset().top; 425 if (v) { 426 var vo = v.offset().top, 427 vp = v.scrollTop(); 428 } 429 430 if (is_static) { 431 return (v) ? (eo - vo) + vp : eo; 432 } else { 433 return (v) ? eo - vo : eo - wp; 434 } 435 }, 436 437 destroy_results: function (e) { 438 this.hide_spinner(this.results_el) 439 this.aria_expanded(false) 440 this.results_el.find('.ajax-results').empty(); 441 this.results_el.removeClass("fp-solr-live-search-results-showing"); 442 this.results_showing = false 443 this.has_results = false 444 445 jQuery(document).trigger("fp_solr_live_destroy_results") 446 }, 447 448 maybe_search: function (e) { 449 if (jQuery.inArray(e.keyCode, this.a11y_keys) > -1) { 450 return 451 } 452 clearTimeout(this.timer) 453 if (e.currentTarget.value.length >= this.config.input.min_chars) { 454 if (this.current_request) { 455 this.current_request.abort() 456 } 457 this.timer = setTimeout( 458 jQuery.proxy(this.search, this, e), 459 this.config.input.delay 460 ) 461 } 462 }, 463 464 show_spinner: function (results_el) { 465 jQuery('#fp-solr-live-ajax-search-spinner', results_el).addClass('fp-solr-has-spinner') 466 }, 467 468 hide_spinner: function (results_el) { 469 jQuery('#fp-solr-live-ajax-search-spinner', results_el).removeClass('fp-solr-has-spinner') 470 }, 471 472 uniqid: function (prefix, more_entropy) { 473 if (typeof prefix === "undefined") { 474 prefix = "" 475 } 476 477 var retId 478 var formatSeed = function (seed, reqWidth) { 479 seed = parseInt(seed, 10).toString(16) 480 if (reqWidth < seed.length) { 481 return seed.slice(seed.length - reqWidth) 482 } 483 if (reqWidth > seed.length) { 484 return new Array(1 + (reqWidth - seed.length)).join("0") + seed 485 } 486 return seed 487 } 488 489 if (!this.php_js) { 490 this.php_js = {} 491 } 492 if (!this.php_js.uniqidSeed) { 493 this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15) 494 } 495 this.php_js.uniqidSeed++ 496 497 retId = prefix 498 retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8) 499 retId += formatSeed(this.php_js.uniqidSeed, 5) 500 if (more_entropy) { 501 retId += (Math.random() * 10).toFixed(8).toString() 502 } 503 504 return retId 505 }, 506 } 507 508 jQuery.fn[plugin_name] = function (options) { 509 this.each(function () { 510 if (!jQuery.data(this, "plugin_" + plugin_name)) { 511 jQuery.data( 512 this, 513 "plugin_" + plugin_name, 514 new FpSolrLiveSearch(jQuery(this), options) 515 ) 516 } 517 }) 518 519 return this 520 } 521})(window.jQuery) 522 523// Bind to all applicable search inputs. 524jQuery(document).ready(function () { 525 if (typeof jQuery().fp_solr_live_search == "function") { 526 jQuery('input[data-fpsolrlive="true"]').fp_solr_live_search() 527 } 528})
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.