var SuperSearch = (function ($) { 'use strict'; var me = { config: { inputBuffer: 300 // in milliseconds }, storage: { $input: null, $overlay: null, $details: null, $results: null, $lastUpdate: null, debounceBuffer: null, hasResults: false, isOpen: false }, init: function () { me.storage.$input = $('#supersearch-input'); if (me.storage.$input.length === 0) { return; } me.registerEvents(); }, registerEvents: function () { me.storage.$input.on('keyup.SuperSearch', me.onKeyUpSearchInput); // Overlay anzeigen bei Focus in das Such-Eingabefeld; nur wenn es schon mal geöffnet war me.storage.$input.on('focus.SuperSearch', me.onFocusSearchInput); // Overlay mit ESC schließen $(document).bind('keydown', function(e) { if (me.storage.$overlay === null) { return; } if (me.storage.isOpen !== true) { return; } // ESC if (e.keyCode === 27) { me.hideOverlay(); } }); }, /** * @return {jQuery} */ getOverlay: function () { if (typeof me.storage.$overlay === 'undefined' || me.storage.$overlay === null) { me.storage.$overlay = me.createOverlay(); me.storage.$details = me.storage.$overlay.find('section.detail'); me.storage.$results = me.storage.$overlay.find('section.result'); me.storage.$lastUpdate = me.storage.$overlay.find('section.last-update'); } return me.storage.$overlay; }, showOverlay: function () { var $overlay = me.getOverlay(); $overlay.show(); me.storage.isOpen = true; me.showDetails(); }, hideOverlay: function () { me.getOverlay().hide(); me.storage.isOpen = false; }, /** * @return {jQuery} */ createOverlay: function () { var overlaySelector = '#supersearch-overlay'; if ($(overlaySelector).length > 0) { return $(overlaySelector); } var overlayTemplate = '' + '
' + '
Keine Suchergebnisse gefunden
' + '
' + '
' + '
' + '
' + '
' + '
' + '
'; var overlayIdAttr = overlaySelector.substr(1); var $overlay = $('
').attr('id', overlayIdAttr).addClass('supersearch-overlay').html(overlayTemplate); $overlay.off('click.SuperSearch', '#supersearch-icon-close'); $overlay.on('click.SuperSearch', '#supersearch-icon-close', function (event) { event.preventDefault(); me.hideOverlay(); }); $overlay.hide(); $overlay.appendTo('#header'); me.storage.isOpen = false; return $overlay; }, /** * @param {Event} event */ onKeyUpSearchInput: function (event) { event.preventDefault(); var controlKeyCodes = [ 9, // Tab 13, // Enter 16, // Shift 17, // Strg 18, // Alt 20, // Caps lock 27, // ESC 37, // Cursor Left 38, // Cursor Up 39, // Cursor Right 40 // Cursor Down ]; if ($.inArray(event.keyCode, controlKeyCodes) !== -1) { return; } var that = this; me.debounce(function () { var searchQuery = $(that).val(); me.fetchSearchResults(searchQuery).then(me.renderSearchResults); }, me.config.inputBuffer); }, /** * Overlay anzeigen bei Focus in das Such-Eingabefeld; nur wenn es schon mal geöffnet war * * @param {Event} event */ onFocusSearchInput: function (event) { event.preventDefault(); if (me.storage.$overlay === null) { return; } if (me.storage.hasResults === false) { return; } me.showOverlay(); }, /** * @param {string} searchQuery * * @return {jqXHR} */ fetchSearchResults: function (searchQuery) { if (typeof searchQuery !== 'string') { searchQuery = ''; } return $.ajax({ url: 'index.php?module=supersearch&action=ajax&cmd=search', method: 'post', dataType: 'json', data: { search_query: searchQuery }, error: function (jqXHR, textStatus, errorThrown) { var errorMessage = 'SuperSearch - Unbekannter Fehler #31: ' + errorThrown; // PHP-Skript hat Fehler geliefert (z.b. 404) if (textStatus === 'error') { errorMessage = 'SuperSearch - Unbekannter Server-Fehler beim Laden der Such-Ergebnisse: '; errorMessage += errorThrown; } // PHP-Skript liefert JSON-Error-Response if (jqXHR.hasOwnProperty('responseJSON') && jqXHR.responseJSON.hasOwnProperty('error')) { errorMessage = 'SuperSearch - Server-Fehler beim Laden der Such-Ergebnisse: '; errorMessage += jqXHR.responseJSON.error; if (jqXHR.responseJSON.hasOwnProperty('data') && jqXHR.responseJSON.data === 'index-empty') { me.showErrorMessage('Fehler: ' + jqXHR.responseJSON.error); return; } } alert(errorMessage); } }); }, /** * @param {Array} rawResult */ renderSearchResults: function (rawResult) { var $overlay = me.getOverlay(); var $resultContainer = $overlay.find('section.result'); $resultContainer.html(''); if (rawResult.length === 0 || !rawResult.hasOwnProperty('data')) { $resultContainer.html('Fehler: Suche hat fehlerhaftes Ergebnis geliefert.'); me.storage.hasResults = false; me.hideResults(); return; } // Overlay ausblenden, wenn Suchbegriff zu kurz if (rawResult.data === null) { me.storage.hasResults = false; me.hideOverlay(); return; } // Anzeigen wann der Such-Index das letzte Mal aktualisiert wurde if (rawResult.data.hasOwnProperty('last_index_update_formatted')) { if (rawResult.data.last_index_update_formatted !== null) { var lastIndexUpdate = rawResult.data.last_index_update_formatted; me.storage.$lastUpdate.text('Such-Index vom ' + lastIndexUpdate).show(); } else { me.storage.$lastUpdate.text('').hide(); } } var resultCount = rawResult.data.count; var searchResults = rawResult.data.results; if (resultCount === 0) { me.storage.hasResults = false; me.showEmptyResults(); return; } me.storage.$details.html(''); Object.keys(searchResults).forEach(function (group) { var groupResult = searchResults[group]; var $groupHtml = me.buildGroupResult(groupResult.key, groupResult.title, groupResult.items); $resultContainer.append($groupHtml); }); me.storage.hasResults = true; me.showResults(); me.showOverlay(); }, /** * @param {string} groupKey * @param {string} groupTitle * @param {array} items * * @return {jQuery} */ buildGroupResult: function (groupKey, groupTitle, items) { if (items.length === 0) { return; } if (typeof groupTitle === 'undefined') { groupTitle = 'Ergebnis'; } var $resultWrapper = $('
'); var $resultList = $('