/(function ($) { /** * Attaches the autocomplete behavior to all required fields. */ Drupal.behaviors.autocomplete = { attach: function (context, settings) { var acdb = []; $('input.autocomplete', context).once('autocomplete', function () { var uri = this.value; if (!acdb[uri]) { acdb[uri] = new Drupal.ACDB(uri); } var $input = $('#' + this.id.substr(0, this.id.length - 13)) .attr('autocomplete', 'OFF') .attr('aria-autocomplete', 'list'); $($input[0].form).submit(Drupal.autocompleteSubmit); $input.parent() .attr('role', 'application') .append($('') .attr('id', $input.attr('id') + '-autocomplete-aria-live') ); new Drupal.jsAC($input, acdb[uri]); }); } }; /** * Prevents the form from submitting if the suggestions popup is open * and closes the suggestions popup when doing so. */ Drupal.autocompleteSubmit = function () { return $('#autocomplete').each(function () { this.owner.hidePopup(); }).length == 0; }; /** * An AutoComplete object. */ Drupal.jsAC = function ($input, db) { var ac = this; this.input = $input[0]; this.ariaLive = $('#' + this.input.id + '-autocomplete-aria-live'); this.db = db; $input .keydown(function (event) { return ac.onkeydown(this, event); }) .keyup(function (event) { ac.onkeyup(this, event); }) .blur(function () { ac.hidePopup(); ac.db.cancel(); }); }; /** * Handler for the "keydown" event. */ Drupal.jsAC.prototype.onkeydown = function (input, e) { if (!e) { e = window.event; } switch (e.keyCode) { case 40: // down arrow. this.selectDown(); return false; case 38: // up arrow. this.selectUp(); return false; default: // All other keys. return true; } }; /** * Handler for the "keyup" event. */ Drupal.jsAC.prototype.onkeyup = function (input, e) { if (!e) { e = window.event; } switch (e.keyCode) { case 16: // Shift. case 17: // Ctrl. case 18: // Alt. case 20: // Caps lock. case 33: // Page up. case 34: // Page down. case 35: // End. case 36: // Home. case 37: // Left arrow. case 38: // Up arrow. case 39: // Right arrow. case 40: // Down arrow. return true; case 9: // Tab. case 13: // Enter. case 27: // Esc. this.hidePopup(e.keyCode); return true; default: // All other keys. if (input.value.length > 0 && !input.readOnly) { this.populatePopup(); } else { this.hidePopup(e.keyCode); } return true; } }; /** * Puts the currently highlighted suggestion into the autocomplete field. */ Drupal.jsAC.prototype.select = function (node) { this.input.value = $(node).data('autocompleteValue'); $(this.input).trigger('autocompleteSelect', [node]); }; /** * Highlights the next suggestion. */ Drupal.jsAC.prototype.selectDown = function () { if (this.selected && this.selected.nextSibling) { this.highlight(this.selected.nextSibling); } else if (this.popup) { var lis = $('li', this.popup); if (lis.length > 0) { this.highlight(lis.get(0)); } } }; /** * Highlights the previous suggestion. */ Drupal.jsAC.prototype.selectUp = function () { if (this.selected && this.selected.previousSibling) { this.highlight(this.selected.previousSibling); } }; /** * Highlights a suggestion. */ Drupal.jsAC.prototype.highlight = function (node) { if (this.selected) { $(this.selected).removeClass('selected'); } $(node).addClass('selected'); this.selected = node; $(this.ariaLive).html($(this.selected).html()); }; /** * Unhighlights a suggestion. */ Drupal.jsAC.prototype.unhighlight = function (node) { $(node).removeClass('selected'); this.selected = false; $(this.ariaLive).empty(); }; /** * Hides the autocomplete suggestions. */ Drupal.jsAC.prototype.hidePopup = function (keycode) { // Select item if the right key or mousebutton was pressed. if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) { this.select(this.selected); } // Hide popup. var popup = this.popup; if (popup) { this.popup = null; $(popup).fadeOut('fast', function () { $(popup).remove(); }); } this.selected = false; $(this.ariaLive).empty(); }; /** * Positions the suggestions popup and starts a search. */ Drupal.jsAC.prototype.populatePopup = function () { var $input = $(this.input); var position = $input.position(); // Show popup. if (this.popup) { $(this.popup).remove(); } this.selected = false; this.popup = $('
')[0]; this.popup.owner = this; $(this.popup).css({ top: parseInt(position.top + this.input.offsetHeight, 10) + 'px', left: parseInt(position.left, 10) + 'px', width: $input.innerWidth() + 'px', display: 'none' }); $input.before(this.popup); // Do search. this.db.owner = this; this.db.search(this.input.value); }; /** * Fills the suggestion popup with any matches received. */ Drupal.jsAC.prototype.found = function (matches) { // If no value in the textfield, do not show the popup. if (!this.input.value.length) { return false; } // Prepare matches. var ul = $(''); var ac = this; for (key in matches) { $('
  • ') .html($('
    ').html(matches[key])) .mousedown(function () { ac.hidePopup(this); }) .mouseover(function () { ac.highlight(this); }) .mouseout(function () { ac.unhighlight(this); }) .data('autocompleteValue', key) .appendTo(ul); } // Show popup with matches, if any. if (this.popup) { if (ul.children().length) { $(this.popup).empty().append(ul).show(); $(this.ariaLive).html(Drupal.t('Autocomplete popup')); } else { $(this.popup).css({ visibility: 'hidden' }); this.hidePopup(); } } }; Drupal.jsAC.prototype.setStatus = function (status) { switch (status) { case 'begin': $(this.input).addClass('throbbing'); $(this.ariaLive).html(Drupal.t('Searching for matches...')); break; case 'cancel': case 'error': case 'found': $(this.input).removeClass('throbbing'); break; } }; /** * An AutoComplete DataBase object. */ Drupal.ACDB = function (uri) { this.uri = uri; this.delay = 300; this.cache = {}; }; /** * Performs a cached and delayed search. */ Drupal.ACDB.prototype.search = function (searchString) { var db = this; this.searchString = searchString; // See if this string needs to be searched for anyway. The pattern ../ is // stripped since it may be misinterpreted by the browser. searchString = searchString.replace(/^\s+|\.{2,}\/|\s+$/g, ''); // Skip empty search strings, or search strings ending with a comma, since // that is the separator between search terms. if (searchString.length <= 0 || searchString.charAt(searchString.length - 1) == ',') { return; } // See if this key has been searched for before. if (this.cache[searchString]) { return this.owner.found(this.cache[searchString]); } // Initiate delayed search. if (this.timer) { clearTimeout(this.timer); } this.timer = setTimeout(function () { db.owner.setStatus('begin'); // Ajax GET request for autocompletion. We use Drupal.encodePath instead of // encodeURIComponent to allow autocomplete search terms to contain slashes. $.ajax({ type: 'GET', url: Drupal.sanitizeAjaxUrl(db.uri + '/' + Drupal.encodePath(searchString)), dataType: 'json', jsonp: false, success: function (matches) { if (typeof matches.status == 'undefined' || matches.status != 0) { db.cache[searchString] = matches; // Verify if these are still the matches the user wants to see. if (db.searchString == searchString) { db.owner.found(matches); } db.owner.setStatus('found'); } }, error: function (xmlhttp) { Drupal.displayAjaxError(Drupal.ajaxError(xmlhttp, db.uri)); } }); }, this.delay); }; /** * Cancels the current autocomplete request. */ Drupal.ACDB.prototype.cancel = function () { if (this.owner) this.owner.setStatus('cancel'); if (this.timer) clearTimeout(this.timer); this.searchString = ''; }; })(jQuery); ;/*})'"*/ ;/*})'"*/ (function ($) { // Auto-submit main search input after autocomplete if (typeof Drupal.jsAC != 'undefined') { var getSetting = function (input, setting, defaultValue) { // Earlier versions of jQuery, like the default for Drupal 7, don't properly // convert data-* attributes to camel case, so we access it via the verbatim // name from the attribute (which also works in newer versions). var search = $(input).data('search-api-autocomplete-search'); if (typeof search == 'undefined' || typeof Drupal.settings.search_api_autocomplete == 'undefined' || typeof Drupal.settings.search_api_autocomplete[search] == 'undefined' || typeof Drupal.settings.search_api_autocomplete[search][setting] == 'undefined') { return defaultValue; } return Drupal.settings.search_api_autocomplete[search][setting]; }; var oldJsAC = Drupal.jsAC; /** * An AutoComplete object. * * Overridden to set the proper "role" attribute on the input element. */ Drupal.jsAC = function ($input, db) { if ($input.data('search-api-autocomplete-search')) { $input.attr('role', 'combobox'); $input.parent().attr('role', 'search'); } oldJsAC.call(this, $input, db); }; Drupal.jsAC.prototype = oldJsAC.prototype; /** * Handler for the "keyup" event. * * Extend from Drupal's autocomplete.js to automatically submit the form * when Enter is hit. */ var default_onkeyup = Drupal.jsAC.prototype.onkeyup; Drupal.jsAC.prototype.onkeyup = function (input, e) { if (!e) { e = window.event; } // Fire standard function. default_onkeyup.call(this, input, e); if (13 == e.keyCode && $(input).hasClass('auto_submit')) { var selector = getSetting(input, 'selector', ':submit'); $(selector, input.form).trigger('click'); } }; /** * Handler for the "keydown" event. * * Extend from Drupal's autocomplete.js to avoid ajax interfering with the * autocomplete. */ var default_onkeydown = Drupal.jsAC.prototype.onkeydown; Drupal.jsAC.prototype.onkeydown = function (input, e) { if (!e) { e = window.event; } // Fire standard function. default_onkeydown.call(this, input, e); // Prevent that the ajax handling of Views fires too early and thus // misses the form update. if (13 == e.keyCode && $(input).hasClass('auto_submit')) { e.preventDefault(); return false; } }; Drupal.jsAC.prototype.select = function(node) { var autocompleteValue = $(node).data('autocompleteValue'); // Check whether this is not a suggestion but a "link". if (autocompleteValue.charAt(0) == ' ') { window.location.href = autocompleteValue.substr(1); return false; } this.input.value = autocompleteValue; $(this.input).trigger('autocompleteSelect', [node]); if ($(this.input).hasClass('auto_submit')) { if (typeof Drupal.search_api_ajax != 'undefined') { // Use Search API Ajax to submit Drupal.search_api_ajax.navigateQuery($(this.input).val()); } else { var selector = getSetting(this.input, 'selector', ':submit'); $(selector, this.input.form).trigger('click'); } return true; } }; /** * Overwrite default behaviour. * * Just always return true to make it possible to submit even when there was * an autocomplete suggestion list open. */ Drupal.autocompleteSubmit = function () { $('#autocomplete').each(function () { this.owner.hidePopup(); }); return true; }; } /** * Performs a cached and delayed search. */ Drupal.ACDB.prototype.search = function (searchString) { this.searchString = searchString; // Check allowed length of string for autocomplete. var data = $(this.owner.input).first().data('min-autocomplete-length'); if (data && searchString.length < data) { return; } // See if this string needs to be searched for anyway. if (searchString.match(/^\s*$/)) { return; } // Prepare search string. searchString = searchString.replace(/^\s+/, ''); searchString = searchString.replace(/\s+/g, ' '); // See if this key has been searched for before. if (this.cache[searchString]) { return this.owner.found(this.cache[searchString]); } var db = this; this.searchString = searchString; // Initiate delayed search. if (this.timer) { clearTimeout(this.timer); } var sendAjaxRequest = function () { db.owner.setStatus('begin'); var url; // Allow custom Search API Autocomplete overrides for specific searches. if (getSetting(db.owner.input, 'custom_path', false)) { var queryChar = db.uri.indexOf('?') >= 0 ? '&' : '?'; url = db.uri + queryChar + 'search=' + encodeURIComponent(searchString); } else { // We use Drupal.encodePath instead of encodeURIComponent to allow // autocomplete search terms to contain slashes. url = db.uri + '/' + Drupal.encodePath(searchString); } // Ajax GET request for autocompletion. $.ajax({ type: 'GET', url: url, dataType: 'json', success: function (matches) { if (typeof matches.status == 'undefined' || matches.status != 0) { db.cache[searchString] = matches; // Verify if these are still the matches the user wants to see. if (db.searchString == searchString) { db.owner.found(matches); } db.owner.setStatus('found'); } }, error: function (xmlhttp) { if (xmlhttp.status) { alert(Drupal.ajaxError(xmlhttp, db.uri)); } } }); }; // Make it possible to override the delay via a setting. var delay = getSetting(this.owner.input, 'delay', this.delay); if (delay > 0) { this.timer = setTimeout(sendAjaxRequest, delay); } else { sendAjaxRequest.apply(); } }; })(jQuery); ;/*})'"*/ ;/*})'"*/ (function ($) { Drupal.behaviors.qtip = { attach: function (context, settings) { $(function () { var instances = $.parseJSON(settings.instances); var debug = $.parseJSON(settings.qtipDebug); $('.qtip-link:not(.qtip-processed)', context).each(function() { // Call .each() so we can access $(this) in the settings/config // Check for a sibling .qtip-tooltip containing the tooltip information, otherwise (for forms) // go to the element's parent and look for .qtip-tooltip container as a sibling of the parent if ($(this, context).next('.qtip-tooltip').length) { var tooltipElement = $(this).next('.qtip-tooltip'); } else { var tooltipElement = $(this).parent().siblings('.qtip-tooltip'); } var tooltip = tooltipElement; if (!debug.leaveElement) { // Remove the tooltip element to keep the DOM clean tooltipElement.remove(); } var text = tooltip.html(); var title = (tooltip.data('qtip-title') != undefined) ? tooltip.data('qtip-title') + '' : ''; // Concatenate an empty string to make sure that the value being passed as the title is a string, otherwise it will not display var instance = (tooltip.data('qtip-instance') != undefined) ? tooltip.data('qtip-instance') : ''; var settings = (instances[instance] != undefined) ? instances[instance] : ''; if (settings) { $(this).qtip(settings); $(this).qtip('option', 'content.text', text); if (title) { $(this).qtip('option', 'content.title', title); } } // If no settings have been passed through, we still want to display a tooltip else { $(this).qtip({ content: { text: text, title: title, } }); } // Add instance class to the container to aid in styling $(this).addClass('qtip-instance-' + instance); // Add processed class to not process again on AJAX calls. $(this).addClass('qtip-processed'); }); }); } }; })(jQuery); ;/*})'"*/ ;/*})'"*/