Usage
nebula.autocompleteSearch(element, types)
Parameters
element
(Required) (Object (or String)) The jQuery object (or selector) of the search input field
Default: None
types
(Optional) (String) A comma-separated string of post types to include
Default: 'any'
Examples
Include only posts and pages in search.
nebula.loadJS(nebula.site.resources.scripts.nebula_jquery_ui, 'jquery-ui').then(function(){ //Ensure jQuery-UI JS is loaded jQuery('#example-input').on('keyup paste', function(){ //Add the listener nebula.autocompleteSearch(jQuery(this), 'post,page'); }); }); nebula.loadCSS(nebula.site.resources.styles.nebula_jquery_ui); //Load the jQuery-UI CSS too
Search all post types by simply using the WordPress core "s" class.
<input class="s" type="text" placeholder="Search this site..." />
Customize the post types in an HTML form without needing to re-write any JavaScript
<input class="search" type="text" data-types="post,page" />
Additional Notes
For an easier implementation, you could simply add the class s
to the search input. See autocompleteSearchListeners().
On keypress or paste, this function triggers nebula_autocomplete_search_start.
On autocomplete success, nebula_autocomplete_search_success is triggered.
When search results are available, nebula_autocomplete_search_results is triggered, otherwise nebula_autocomplete_search_no_results is triggered if no results are available.
On AJAX error, this function triggers nebula_autocomplete_search_error.
Source File
Located in /assets/js/modules/search.js on line 145.
No Hooks
This function does not have any filters or actions available. Request one?nebula.autocompleteSearch = async function($element, types = ''){ await nebula.yield(); if ( typeof $element === 'string' ){ $element = jQuery($element); } if ( types && Array.isArray(types) ){ types = types.join(','); //Convert an array to to a comma-separated string } nebula.dom.document.trigger('nebula_autocomplete_search_start', $element); nebula.timer('(Nebula) Autocomplete Search', 'start'); nebula.timer('(Nebula) Autocomplete Response', 'start'); if ( $element.val().trim().length ){ if ( $element.val().trim().length >= 2 ){ //This checks the length for animation but the minlength (below) handles it for autocomplete //Add "searching" class for custom Nebula styled forms $element.closest('form').addClass('searching'); setTimeout(function(){ $element.closest('form').removeClass('searching'); }, 10_000); //Swap magnifying glass on Bootstrap input-group $element.closest('.input-group, .nebula-input-group').find('.fa-magnifying-glass').removeClass('fa-magnifying-glass').addClass('fa-spin fa-spinner'); } else { $element.closest('form').removeClass('searching'); $element.closest('.input-group, .nebula-input-group').find('.fa-spin').removeClass('fa-spin fa-spinner').addClass('fa-magnifying-glass'); } let typesQuery = ''; if ( types ){ typesQuery = '&types=' + types; } if ( typeof $element.autocomplete !== 'function' ){ nebula.help('nebula.autocompleteSearch requires jQuery UI. Load that library before calling this function', '/functions/autocompletesearch/'); return false; } let minLength = 3; if ( $element.attr('data-min-length') ){ minLength = $element.attr('data-min-length'); } $element.autocomplete({ //jQuery UI dependent position: { my: 'left top-2px', at: 'left bottom', collision: 'flip', }, source: async function(request, sourceResponse){ await nebula.yield(); let searchResults = nebula.memoize('get', 'autocomplete search (' + request.term.toLowerCase() + ') [' + typesQuery + ']'); //Try from stored memory first //If we didn't find the search from stored memory, do an actual search if ( !searchResults ){ //Fetch an actual search query from the WP JSON API var fetchResponse = await fetch(nebula.site.home_url + '/wp-json/nebula/v2/autocomplete_search?term=' + request.term + typesQuery, { priority: 'high' }).then(function(fetchResponse){ return fetchResponse.json(); }).then(function(fetchData){ searchResults = nebula.memoize('set', 'autocomplete search (' + request.term.toLowerCase() + ') [' + typesQuery + ']', fetchData); //Add to stored memory }).catch(function(error){ nebula.dom.document.trigger('nebula_autocomplete_search_error', request.term); nebula.debounce(function(){ gtag('event', 'exception', { message: '(JS) Autocomplete AJAX error: ' + error, fatal: false }); nebula.crm('event', 'Autocomplete Search AJAX Error'); }, 1500, 'autocomplete error buffer'); $element.closest('form').removeClass('searching'); $element.closest('.input-group, .nebula-input-group').find('.fa-spin').removeClass('fa-spin fa-spinner').addClass('fa-magnifying-glass'); }); } nebula.dom.document.trigger('nebula_autocomplete_search_success', searchResults); var noSearchResults = ' (No Results)'; //Prep the string if ( searchResults ){ nebula.dom.document.trigger('nebula_autocomplete_search_results', searchResults); nebula.prefetch(searchResults[0].link); jQuery.each(searchResults, function(index, value){ value.label = value.label.replaceAll(/&/g, '\&'); }); noSearchResults = ''; } else { nebula.dom.document.trigger('nebula_autocomplete_search_no_results'); } nebula.debounce(function(){ let thisEvent = { event_name: 'search', event_category: 'Internal Search', event_action: 'Autocomplete Search' + noSearchResults, request: request, term: request.term.toLowerCase(), no_search_results: ( noSearchResults )? true : false, }; nebula.dom.document.trigger('nebula_event', thisEvent); gtag('event', thisEvent.event_name, nebula.gaEventObject(thisEvent)); nebula.fbq('track', 'Search', {search_string: thisEvent.term}); nebula.clarity('set', thisEvent.category, thisEvent.term); nebula.crm('identify', {internal_search: thisEvent.term}); }, 1500, 'autocomplete success buffer'); gtag('event', 'timing_complete', { name: 'Server Response', value: Math.round(nebula.timer('(Nebula) Autocomplete Search', 'lap')), event_category: 'Autocomplete Search', event_label: 'Each search until server results', }); sourceResponse(searchResults); //Respond to the jQuery UI Autocomplete now $element.closest('form').removeClass('searching').addClass('autocompleted'); $element.closest('.input-group, .nebula-input-group').find('.fa-spin').removeClass('fa-spin fa-spinner').addClass('fa-magnifying-glass'); }, focus: function(event, ui){ event.preventDefault(); //Prevent input value from changing. }, select: function(event, ui){ let thisEvent = { event_name: 'select_content', event_category: 'Internal Search', event_action: 'Autocomplete Click', ui: ui, event_label: ui.item.label, external: ( typeof ui.item.external !== 'undefined' )? true : false, }; nebula.dom.document.trigger('nebula_autocomplete_search_selected', thisEvent.ui); nebula.dom.document.trigger('nebula_event', thisEvent); gtag('event', thisEvent.event_name, nebula.gaEventObject(thisEvent)); gtag('event', 'timing_complete', { name: 'Until Navigation', value: Math.round(nebula.timer('(Nebula) Autocomplete Search', 'end')), event_category: 'Autocomplete Search', event_label: 'From first initial search until navigation', }); if ( thisEvent.external ){ window.open(ui.item.link, '_blank'); } else { window.location.href = ui.item.link; } }, open: function(){ $element.closest('form').addClass('autocompleted'); let heroAutoCompleteDropdown = jQuery('.form-identifier-nebula-hero-search'); heroAutoCompleteDropdown.css('max-width', $element.outerWidth()); }, close: function(){ $element.closest('form').removeClass('autocompleted'); }, minLength: minLength, //Require at least 3 characters (unless overridden by an attribute) }).data('ui-autocomplete')._renderItem = function(ul, item){ let thisSimilarity = ( typeof item.similarity !== 'undefined' )? item.similarity.toFixed(1) + '% Match' : ''; let listItem = jQuery("<li class='" + item.classes + "' title='" + thisSimilarity + "'></li>").data("item.autocomplete", item).append("<a href='" + item.link + "'> " + item.label.replaceAll(/\\/g, '') + "</a>").appendTo(ul); return listItem; }; let thisFormIdentifier = $element.closest('form').attr('id') || $element.closest('form').attr('name') || $element.closest('form').attr('class'); $element.autocomplete('widget').addClass('form-identifier-' + thisFormIdentifier); } };
Override
To override or disable this JavaScript function, simply redeclare it with the exact same function name. Remember: Some functionality is conditionally loaded via dynamic imports, so if your function is not overriding properly, try listening for a DOM event (described below).
For non-module import functions:
nebula.autocompleteSearch = function(element, types){ //Write your own code here, leave it blank, or return false. }
For dynamically imported module function overrides:
jQuery(window).on('load', function(){ nebula.autocompleteSearch = function(element, types){ //Write your own code here, leave it blank, or return false. } });
Custom Nebula DOM events do also exist, so you could also try the following if the Window Load listener does not work:
jQuery(document).on('nebula_module_loaded', function(module){ //Note that the module variable is also available to know which module specifically was imported if ( typeof nebula.autocompleteSearch === 'function' ){ nebula.autocompleteSearch = function(element, types){ //Write your own code here, leave it blank, or return false. } } });