"use strict"; /* globals socket, app, define, ajaxify, config */ define('admin/modules/search', ['mousetrap'], function (mousetrap) { var search = {}; function find(dict, term) { var html = dict.filter(function (elem) { return elem.translations.toLowerCase().includes(term); }).map(function (params) { var namespace = params.namespace; var translations = params.translations; var title = params.title; var results = translations // remove all lines without a match .replace(new RegExp('^(?:(?!' + term + ').)*$', 'gmi'), '') // remove lines that only match the title .replace(new RegExp('(^|\\n).*?' + title + '.*?(\\n|$)', 'g'), '') // get up to 25 characters of context on both sides of the match // and wrap the match in a `.search-match` element .replace( new RegExp('^[\\s\\S]*?(.{0,25})(' + term + ')(.{0,25})[\\s\\S]*?$', 'gmi'), '...$1$2$3...
' ) // collapse whitespace .replace(/(?:\n ?)+/g, '\n') .trim(); title = title.replace( new RegExp('(^.*?)(' + term + ')(.*?$)', 'gi'), '$1$2$3' ); return ''; }).join(''); return html; } search.init = function () { socket.emit('admin.getSearchDict', {}, function (err, dict) { if (err) { app.alertError(err); throw err; } setupACPSearch(dict); }); }; function setupACPSearch(dict) { var dropdown = $('#acp-search .dropdown'); var menu = $('#acp-search .dropdown-menu'); var input = $('#acp-search input'); if (!config.searchEnabled) { menu.addClass('search-disabled'); } input.on('keyup', function () { dropdown.addClass('open'); }); $('#acp-search').parents('form').on('submit', function (ev) { var selected = menu.find('li.result > a.focus').attr('href'); if (!selected.length) { selected = menu.find('li.result > a').first().attr('href'); } var href = selected ? selected : config.relative_path + '/search/' + input.val(); ajaxify.go(href.replace(/^\//, '')); setTimeout(function () { dropdown.removeClass('open'); input.blur(); }, 150); ev.preventDefault(); return false; }); mousetrap(input[0]).bind(['up', 'down'], function (ev, key) { var next; if (key === 'up') { next = menu.find('li.result > a.focus').removeClass('focus').parent().prev('.result').children(); if (!next.length) { next = menu.find('li.result > a').last(); } next.addClass('focus'); if (menu[0].getBoundingClientRect().top > next[0].getBoundingClientRect().top) { next[0].scrollIntoView(true); } } else if (key === 'down') { next = menu.find('li.result > a.focus').removeClass('focus').parent().next('.result').children(); if (!next.length) { next = menu.find('li.result > a').first(); } next.addClass('focus'); if (menu[0].getBoundingClientRect().bottom < next[0].getBoundingClientRect().bottom) { next[0].scrollIntoView(false); } } ev.preventDefault(); }); var prevValue; input.on('keyup focus', function () { var value = input.val().toLowerCase(); if (value === prevValue) { return; } prevValue = value; menu.children('.result').remove(); var len = value.length; var results; menu.toggleClass('state-start-typing', len === 0); menu.toggleClass('state-keep-typing', len > 0 && len < 3); if (len >= 3) { menu.prepend(find(dict, value)); results = menu.children('.result').length; menu.toggleClass('state-no-results', !results); menu.toggleClass('state-yes-results', !!results); menu.find('.search-forum') .not('.divider') .find('a') .attr('href', config.relative_path + '/search/' + value) .find('strong') .html(value); } else { menu.removeClass('state-no-results state-yes-results'); } }); } return search; });