| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 | $(document).ready(function() {    highlightResult('top')();    $('.result').on('click', function() {        highlightResult($(this))();    });    var vimKeys = {        27: {            key: 'Escape',            fun: removeFocus,            des: 'remove focus from the focused input',            cat: 'Control'        },        73: {            key: 'i',            fun: searchInputFocus,            des: 'focus on the search input',            cat: 'Control'        },        66: {            key: 'b',            fun: scrollPage(-window.innerHeight),            des: 'scroll one page up',            cat: 'Navigation'        },        70: {            key: 'f',            fun: scrollPage(window.innerHeight),            des: 'scroll one page down',            cat: 'Navigation'        },        85: {            key: 'u',            fun: scrollPage(-window.innerHeight / 2),            des: 'scroll half a page up',            cat: 'Navigation'        },        68: {            key: 'd',            fun: scrollPage(window.innerHeight / 2),            des: 'scroll half a page down',            cat: 'Navigation'        },        71: {            key: 'g',            fun: scrollPageTo(-document.body.scrollHeight, 'top'),            des: 'scroll to the top of the page',            cat: 'Navigation'        },        86: {            key: 'v',            fun: scrollPageTo(document.body.scrollHeight, 'bottom'),            des: 'scroll to the bottom of the page',            cat: 'Navigation'        },        75: {            key: 'k',            fun: highlightResult('up'),            des: 'select previous search result',            cat: 'Results'        },        74: {            key: 'j',            fun: highlightResult('down'),            des: 'select next search result',            cat: 'Results'        },        80: {            key: 'p',            fun: pageButtonClick(0),            des: 'go to previous page',            cat: 'Results'        },        78: {            key: 'n',            fun: pageButtonClick(1),            des: 'go to next page',            cat: 'Results'        },        79: {            key: 'o',            fun: openResult(false),            des: 'open search result',            cat: 'Results'        },        84: {            key: 't',            fun: openResult(true),            des: 'open the result in a new tab',            cat: 'Results'        },        82: {            key: 'r',            fun: reloadPage,            des: 'reload page from the server',            cat: 'Control'        },        72: {            key: 'h',            fun: toggleHelp,            des: 'toggle help window',            cat: 'Other'        }    };    $(document).keyup(function(e) {        // check for modifiers so we don't break browser's hotkeys        if (vimKeys.hasOwnProperty(e.keyCode)            && !e.ctrlKey            && !e.altKey            && !e.shiftKey            && !e.metaKey)        {            if (e.keyCode === 27) {                if (e.target.tagName.toLowerCase() === 'input') {                    vimKeys[e.keyCode].fun();                }            } else {                if (e.target === document.body) {                    vimKeys[e.keyCode].fun();                }            }        }    });    function highlightResult(which) {        return function() {            var current = $('.result[data-vim-selected]');            if (current.length === 0) {                current = $('.result:first');                if (current.length === 0) {                    return;                }            }            var next;            if (typeof which !== 'string') {                next = which;            } else {                switch (which) {                    case 'visible':                        var top = $(window).scrollTop();                        var bot = top + $(window).height();                        var results = $('.result');                        for (var i = 0; i < results.length; i++) {                            next = $(results[i]);                            var etop = next.offset().top;                            var ebot = etop + next.height();                            if ((ebot <= bot) && (etop > top)) {                                break;                            }                        }                        break;                    case 'down':                        next = current.next('.result');                        if (next.length === 0) {                            next = $('.result:first');                        }                        break;                    case 'up':                        next = current.prev('.result');                        if (next.length === 0) {                            next = $('.result:last');                        }                        break;                    case 'bottom':                        next = $('.result:last');                        break;                    case 'top':                    default:                        next = $('.result:first');                }            }            if (next) {                current.removeAttr('data-vim-selected').removeClass('well well-sm');                next.attr('data-vim-selected', 'true').addClass('well well-sm');                scrollPageToSelected();            }        }    }    function reloadPage() {        document.location.reload(false);    }    function removeFocus() {        if (document.activeElement) {            document.activeElement.blur();        }    }    function pageButtonClick(num) {        return function() {            var buttons = $('div#pagination button[type="submit"]');            if (buttons.length !== 2) {                console.log('page navigation with this theme is not supported');                return;            }            if (num >= 0 && num < buttons.length) {                buttons[num].click();            } else {                console.log('pageButtonClick(): invalid argument');            }        }    }    function scrollPageToSelected() {        var sel = $('.result[data-vim-selected]');        if (sel.length !== 1) {            return;        }        var wnd = $(window);        var wtop = wnd.scrollTop();        var etop = sel.offset().top;        var offset = 30;        if (wtop > etop) {            wnd.scrollTop(etop - offset);        } else  {            var ebot = etop + sel.height();            var wbot = wtop + wnd.height();            if (wbot < ebot) {                wnd.scrollTop(ebot - wnd.height() + offset);            }        }    }    function scrollPage(amount) {        return function() {            window.scrollBy(0, amount);            highlightResult('visible')();        }    }    function scrollPageTo(position, nav) {        return function() {            window.scrollTo(0, position);            highlightResult(nav)();        }    }    function searchInputFocus() {        $('input#q').focus();    }    function openResult(newTab) {        return function() {            var link = $('.result[data-vim-selected] .result_header a');            if (link.length) {                var url = link.attr('href');                if (newTab) {                    window.open(url);                } else {                    window.location.href = url;                }            }        };    }    function toggleHelp() {        var helpPanel = $('#vim-hotkeys-help');        if (helpPanel.length) {            helpPanel.toggleClass('hidden');            return;        }        var categories = {};        for (var k in vimKeys) {            var key = vimKeys[k];            categories[key.cat] = categories[key.cat] || [];            categories[key.cat].push(key);        }        var sorted = Object.keys(categories).sort(function(a, b) {            return categories[b].length - categories[a].length;        });        if (sorted.length === 0) {            return;        }        var html = '<div id="vim-hotkeys-help" class="well vim-hotkeys-help">';        html += '<div class="container-fluid">';        html += '<div class="row">';        html += '<div class="col-sm-12">';        html += '<h3>How to navigate searx with Vim-like hotkeys</h3>';        html += '</div>'; // col-sm-12        html += '</div>'; // row        for (var i = 0; i < sorted.length; i++) {            var cat = categories[sorted[i]];            var lastCategory = i === (sorted.length - 1);            var first = i % 2 === 0;            if (first) {                html += '<div class="row dflex">';            }            html += '<div class="col-sm-' + (first && lastCategory ? 12 : 6) + ' dflex">';            html += '<div class="panel panel-default iflex">';            html += '<div class="panel-heading">' + cat[0].cat + '</div>';            html += '<div class="panel-body">';            html += '<ul class="list-unstyled">';            for (var cj in cat) {                html += '<li><kbd>' + cat[cj].key + '</kbd> ' + cat[cj].des + '</li>';            }            html += '</ul>';            html += '</div>'; // panel-body            html += '</div>'; // panel            html += '</div>'; // col-sm-*            if (!first || lastCategory) {                html += '</div>'; // row            }        }        html += '</div>'; // container-fluid        html += '</div>'; // vim-hotkeys-help        $('body').append(html);    }});
 |