From 56e34947a6368e6154064c52fa23d21ecda7ab4c Mon Sep 17 00:00:00 2001 From: Alexandre Flament Date: Sun, 23 Jan 2022 11:37:57 +0100 Subject: [PATCH 1/2] [mod] infinite_scroll as preference * oscar theme: code from searx/plugins/infinite_scroll.py * simple theme: new implementation Co-authored-by: Markus Heiser --- searx/plugins/infinite_scroll.py | 9 -- searx/preferences.py | 11 +++ searx/settings.yml | 1 - searx/settings_defaults.py | 1 + searx/static/plugins/js/infinite_scroll.js | 40 -------- .../themes/__common__/js/image_layout.js | 95 +++++++++++++------ searx/static/themes/oscar/gruntfile.js | 2 +- searx/static/themes/oscar/src/js/01_init.js | 1 + .../themes/oscar/src/js/infinite_scroll.js | 50 ++++++++++ .../oscar/src/less/infinite_scroll.less} | 4 +- .../oscar/src/less/logicodev-dark/oscar.less | 1 + .../oscar/src/less/logicodev/oscar.less | 1 + .../themes/oscar/src/less/pointhi/oscar.less | 1 + .../themes/simple/src/js/main/00_toolkit.js | 79 ++++++++------- .../simple/src/js/main/infinite_scroll.js | 88 +++++++++++++++++ .../themes/simple/src/js/main/preferences.js | 10 +- .../themes/simple/src/js/main/results.js | 4 + .../static/themes/simple/src/less/style.less | 8 +- searx/templates/oscar/base.html | 1 + searx/templates/oscar/preferences.html | 11 +++ searx/templates/simple/base.html | 2 +- searx/templates/simple/preferences.html | 12 +++ searx/webapp.py | 3 + 23 files changed, 314 insertions(+), 121 deletions(-) delete mode 100644 searx/plugins/infinite_scroll.py delete mode 100644 searx/static/plugins/js/infinite_scroll.js create mode 100644 searx/static/themes/oscar/src/js/infinite_scroll.js rename searx/static/{plugins/css/infinite_scroll.css => themes/oscar/src/less/infinite_scroll.less} (91%) create mode 100644 searx/static/themes/simple/src/js/main/infinite_scroll.js diff --git a/searx/plugins/infinite_scroll.py b/searx/plugins/infinite_scroll.py deleted file mode 100644 index e3726671a..000000000 --- a/searx/plugins/infinite_scroll.py +++ /dev/null @@ -1,9 +0,0 @@ -from flask_babel import gettext - -name = gettext('Infinite scroll') -description = gettext('Automatically load next page when scrolling to bottom of current page') -default_on = False -preference_section = 'ui' - -js_dependencies = ('plugins/js/infinite_scroll.js',) -css_dependencies = ('plugins/css/infinite_scroll.css',) diff --git a/searx/preferences.py b/searx/preferences.py index 570d0901b..e493dadc0 100644 --- a/searx/preferences.py +++ b/searx/preferences.py @@ -394,6 +394,17 @@ class Preferences: 'False': False } ), + 'infinite_scroll': MapSetting( + settings['ui']['infinite_scroll'], + locked=is_locked('infinite_scroll'), + map={ + '': settings['ui']['infinite_scroll'], + '0': False, + '1': True, + 'True': True, + 'False': False + } + ), # fmt: on } diff --git a/searx/settings.yml b/searx/settings.yml index cec9889b2..7e069a831 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -169,7 +169,6 @@ outgoing: # - 'Ahmia blacklist' # activation depends on outgoing.using_tor_proxy # # these plugins are disabled if nothing is configured .. # - 'Hostname replace' # see hostname_replace configuration below -# - 'Infinite scroll' # - 'Open Access DOI rewrite' # - 'Vim-like hotkeys' diff --git a/searx/settings_defaults.py b/searx/settings_defaults.py index 15b4524c6..0721899a2 100644 --- a/searx/settings_defaults.py +++ b/searx/settings_defaults.py @@ -186,6 +186,7 @@ SCHEMA = { 'results_on_new_tab': SettingsValue(bool, False), 'advanced_search': SettingsValue(bool, False), 'query_in_title': SettingsValue(bool, False), + 'infinite_scroll': SettingsValue(bool, False), }, 'preferences': { 'lock': SettingsValue(list, []), diff --git a/searx/static/plugins/js/infinite_scroll.js b/searx/static/plugins/js/infinite_scroll.js deleted file mode 100644 index cd8096571..000000000 --- a/searx/static/plugins/js/infinite_scroll.js +++ /dev/null @@ -1,40 +0,0 @@ -function hasScrollbar() { - var root = document.compatMode=='BackCompat'? document.body : document.documentElement; - return root.scrollHeight>root.clientHeight; -} - -function loadNextPage() { - var formData = $('#pagination form:last').serialize(); - if (formData) { - $('#pagination').html('
'); - $.ajax({ - type: "POST", - url: $('#search_form').prop('action'), - data: formData, - dataType: 'html', - success: function(data) { - var body = $(data); - $('#pagination').remove(); - $('#main_results').append('
'); - $('#main_results').append(body.find('.result')); - $('#main_results').append(body.find('#pagination')); - if(!hasScrollbar()) { - loadNextPage(); - } - } - }); - } -} - -$(document).ready(function() { - var win = $(window); - if(!hasScrollbar()) { - loadNextPage(); - } - win.scroll(function() { - $("#pagination button").css("visibility", "hidden"); - if ($(document).height() - win.height() - win.scrollTop() < 150) { - loadNextPage(); - } - }); -}); diff --git a/searx/static/themes/__common__/js/image_layout.js b/searx/static/themes/__common__/js/image_layout.js index e37058dfa..329fa46a8 100644 --- a/searx/static/themes/__common__/js/image_layout.js +++ b/searx/static/themes/__common__/js/image_layout.js @@ -29,7 +29,8 @@ this.verticalMargin = verticalMargin; this.horizontalMargin = horizontalMargin; this.maxHeight = maxHeight; - this.isAlignDone = true; + this.trottleCallToAlign = null; + this.alignAfterThrotteling = false; } /** @@ -72,12 +73,12 @@ // not loaded image : make it square as _getHeigth said it imgWidth = height; } - img.style.width = imgWidth + 'px'; - img.style.height = height + 'px'; - img.style.marginLeft = this.horizontalMargin + 'px'; - img.style.marginTop = this.horizontalMargin + 'px'; - img.style.marginRight = this.verticalMargin - 7 + 'px'; // -4 is the negative margin of the inline element - img.style.marginBottom = this.verticalMargin - 7 + 'px'; + img.setAttribute('width', Math.round(imgWidth)); + img.setAttribute('height', Math.round(height)); + img.style.marginLeft = Math.round(this.horizontalMargin) + 'px'; + img.style.marginTop = Math.round(this.horizontalMargin) + 'px'; + img.style.marginRight = Math.round(this.verticalMargin - 7) + 'px'; // -4 is the negative margin of the inline element + img.style.marginBottom = Math.round(this.verticalMargin - 7) + 'px'; resultNode = img.parentNode.parentNode; if (!resultNode.classList.contains('js')) { resultNode.classList.add('js'); @@ -112,6 +113,23 @@ } }; + ImageLayout.prototype.throttleAlign = function () { + var obj = this; + if (obj.trottleCallToAlign) { + obj.alignAfterThrotteling = true; + } else { + obj.alignAfterThrotteling = false; + obj.align(); + obj.trottleCallToAlign = setTimeout(function () { + if (obj.alignAfterThrotteling) { + obj.align(); + } + obj.alignAfterThrotteling = false; + obj.trottleCallToAlign = null; + }, 20); + } + } + ImageLayout.prototype.align = function () { var i; var results_selectorNode = d.querySelectorAll(this.results_selector); @@ -141,9 +159,9 @@ } }; - ImageLayout.prototype.watch = function () { + ImageLayout.prototype._monitorImages = function () { var i, img; - var obj = this; + var objthrottleAlign = this.throttleAlign.bind(this); var results_nodes = d.querySelectorAll(this.results_selector); var results_length = results_nodes.length; @@ -152,34 +170,53 @@ event.originalTarget.src = w.searxng.static_path + w.searxng.theme.img_load_error; } - function throttleAlign () { - if (obj.isAlignDone) { - obj.isAlignDone = false; - setTimeout(function () { - obj.align(); - obj.isAlignDone = true; - }, 100); - } - } - - // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event - w.addEventListener('pageshow', throttleAlign); - // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event - w.addEventListener('load', throttleAlign); - // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event - w.addEventListener('resize', throttleAlign); - for (i = 0; i < results_length; i++) { img = results_nodes[i].querySelector(this.img_selector); - if (img !== null && img !== undefined) { - img.addEventListener('load', throttleAlign); + if (img !== null && img !== undefined && !img.classList.contains('aligned')) { + img.addEventListener('load', objthrottleAlign); // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror - img.addEventListener('error', throttleAlign); + img.addEventListener('error', objthrottleAlign); + img.addEventListener('timeout', objthrottleAlign); if (w.searxng.theme.img_load_error) { img.addEventListener('error', img_load_error, {once: true}); } + img.classList.add('aligned'); } } + } + + ImageLayout.prototype.watch = function () { + var objthrottleAlign = this.throttleAlign.bind(this); + + // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event + w.addEventListener('pageshow', objthrottleAlign); + // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event + w.addEventListener('load', objthrottleAlign); + // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event + w.addEventListener('resize', objthrottleAlign); + + this._monitorImages(); + + var obj = this; + + let observer = new MutationObserver(entries => { + let newElement = false; + for (let i = 0; i < entries.length; i++) { + if (entries[i].addedNodes.length > 0 && entries[i].addedNodes[0].classList.contains('result')) { + newElement = true; + break; + } + } + if (newElement) { + obj._monitorImages(); + } + }); + observer.observe(d.querySelector(this.container_selector), { + childList: true, + subtree: true, + attributes: false, + characterData: false, + }) }; w.searxng.ImageLayout = ImageLayout; diff --git a/searx/static/themes/oscar/gruntfile.js b/searx/static/themes/oscar/gruntfile.js index 8e118afd6..2f87e289f 100644 --- a/searx/static/themes/oscar/gruntfile.js +++ b/searx/static/themes/oscar/gruntfile.js @@ -78,7 +78,7 @@ module.exports = function(grunt) { } }, jshint: { - files: ['gruntfile.js', 'src/js/*.js', '../__common__/js/image_layout.js'], + files: ['gruntfile.js', 'src/js/*.js'], // files in __common__ are linted by es lint in simple theme options: { reporterOutput: "", esversion: 6, diff --git a/searx/static/themes/oscar/src/js/01_init.js b/searx/static/themes/oscar/src/js/01_init.js index 8853d9909..f72b0078b 100644 --- a/searx/static/themes/oscar/src/js/01_init.js +++ b/searx/static/themes/oscar/src/js/01_init.js @@ -19,6 +19,7 @@ window.searxng = (function(d) { return { autocompleter: script.getAttribute('data-autocompleter') === 'true', + infinite_scroll: script.getAttribute('data-infinite-scroll') === 'true', method: script.getAttribute('data-method'), translations: JSON.parse(script.getAttribute('data-translations')) }; diff --git a/searx/static/themes/oscar/src/js/infinite_scroll.js b/searx/static/themes/oscar/src/js/infinite_scroll.js new file mode 100644 index 000000000..6dbff5fef --- /dev/null +++ b/searx/static/themes/oscar/src/js/infinite_scroll.js @@ -0,0 +1,50 @@ +/** + * @license + * (C) Copyright Contributors to the SearXNG project. + * (C) Copyright Contributors to the searx project (2014 - 2021). + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +$(document).ready(function() { + function hasScrollbar() { + var root = document.compatMode=='BackCompat'? document.body : document.documentElement; + return root.scrollHeight>root.clientHeight; + } + + function loadNextPage() { + var formData = $('#pagination form:last').serialize(); + if (formData) { + $('#pagination').html('
'); + $.ajax({ + type: "POST", + url: $('#search_form').prop('action'), + data: formData, + dataType: 'html', + success: function(data) { + var body = $(data); + $('#pagination').remove(); + $('#main_results').append('
'); + $('#main_results').append(body.find('.result')); + $('#main_results').append(body.find('#pagination')); + if(!hasScrollbar()) { + loadNextPage(); + } + } + }); + } + } + + if (searxng.infinite_scroll) { + var win = $(window); + $("html").addClass('infinite_scroll'); + if(!hasScrollbar()) { + loadNextPage(); + } + win.on('scroll', function() { + if ($(document).height() - win.height() - win.scrollTop() < 150) { + loadNextPage(); + } + }); + } + +}); diff --git a/searx/static/plugins/css/infinite_scroll.css b/searx/static/themes/oscar/src/less/infinite_scroll.less similarity index 91% rename from searx/static/plugins/css/infinite_scroll.css rename to searx/static/themes/oscar/src/less/infinite_scroll.less index 07b9f6de9..f66373651 100644 --- a/searx/static/plugins/css/infinite_scroll.css +++ b/searx/static/themes/oscar/src/less/infinite_scroll.less @@ -2,6 +2,7 @@ 0% { transform: rotate(0deg) } 100% { transform: rotate(360deg) } } + .loading-spinner { animation-duration: 0.75s; animation-iteration-count: infinite; @@ -14,6 +15,7 @@ border-radius: 50% !important; margin: 0 auto; } -#pagination button { + +html.infinite_scroll #pagination button { visibility: hidden; } diff --git a/searx/static/themes/oscar/src/less/logicodev-dark/oscar.less b/searx/static/themes/oscar/src/less/logicodev-dark/oscar.less index 14f23111f..71821a259 100644 --- a/searx/static/themes/oscar/src/less/logicodev-dark/oscar.less +++ b/searx/static/themes/oscar/src/less/logicodev-dark/oscar.less @@ -4,6 +4,7 @@ @import "../../../../__common__/less/result_templates.less"; @import "../../less/result_templates.less"; @import "../../less/preferences.less"; +@import "../infinite_scroll.less"; @import "../../generated/pygments-logicodev.less"; @stacked-bar-chart: rgb(213, 216, 215, 1); diff --git a/searx/static/themes/oscar/src/less/logicodev/oscar.less b/searx/static/themes/oscar/src/less/logicodev/oscar.less index 187368f71..61e03745b 100644 --- a/searx/static/themes/oscar/src/less/logicodev/oscar.less +++ b/searx/static/themes/oscar/src/less/logicodev/oscar.less @@ -4,6 +4,7 @@ @import "../../../../__common__/less/result_templates.less"; @import "../../less/result_templates.less"; @import "../../less/preferences.less"; +@import "../infinite_scroll.less"; @import "../../generated/pygments-logicodev.less"; @import "navbar.less"; diff --git a/searx/static/themes/oscar/src/less/pointhi/oscar.less b/searx/static/themes/oscar/src/less/pointhi/oscar.less index e9851458d..d54fa28d9 100644 --- a/searx/static/themes/oscar/src/less/pointhi/oscar.less +++ b/searx/static/themes/oscar/src/less/pointhi/oscar.less @@ -4,6 +4,7 @@ @import "../../../../__common__/less/result_templates.less"; @import "../../less/result_templates.less"; @import "../../less/preferences.less"; +@import "../infinite_scroll.less"; @import "../../generated/pygments-pointhi.less"; @import "footer.less"; diff --git a/searx/static/themes/simple/src/js/main/00_toolkit.js b/searx/static/themes/simple/src/js/main/00_toolkit.js index c5b7fe578..f53842d72 100644 --- a/searx/static/themes/simple/src/js/main/00_toolkit.js +++ b/searx/static/themes/simple/src/js/main/00_toolkit.js @@ -59,43 +59,45 @@ window.searxng = (function (w, d) { } }; - searxng.http = function (method, url) { - var req = new XMLHttpRequest(), - resolve = function () {}, - reject = function () {}, - promise = { - then: function (callback) { resolve = callback; return promise; }, - catch: function (callback) { reject = callback; return promise; } - }; + searxng.http = function (method, url, data = null) { + return new Promise(function (resolve, reject) { + try { + var req = new XMLHttpRequest(); + req.open(method, url, true); + req.timeout = 20000; - try { - req.open(method, url, true); + // On load + req.onload = function () { + if (req.status == 200) { + resolve(req.response, req.responseType); + } else { + reject(Error(req.statusText)); + } + }; - // On load - req.onload = function () { - if (req.status == 200) { - resolve(req.response, req.responseType); - } else { - reject(Error(req.statusText)); + // Handle network errors + req.onerror = function () { + reject(Error("Network Error")); + }; + + req.onabort = function () { + reject(Error("Transaction is aborted")); + }; + + req.ontimeout = function () { + reject(Error("Timeout")); } - }; - // Handle network errors - req.onerror = function () { - reject(Error("Network Error")); - }; - - req.onabort = function () { - reject(Error("Transaction is aborted")); - }; - - // Make the request - req.send(); - } catch (ex) { - reject(ex); - } - - return promise; + // Make the request + if (data) { + req.send(data) + } else { + req.send(); + } + } catch (ex) { + reject(ex); + } + }); }; searxng.loadStyle = function (src) { @@ -148,5 +150,16 @@ window.searxng = (function (w, d) { this.parentNode.classList.add('invisible'); }); + function getEndpoint () { + for (var className of d.getElementsByTagName('body')[0].classList.values()) { + if (className.endsWith('_endpoint')) { + return className.split('_')[0]; + } + } + return ''; + } + + searxng.endpoint = getEndpoint(); + return searxng; })(window, document); diff --git a/searx/static/themes/simple/src/js/main/infinite_scroll.js b/searx/static/themes/simple/src/js/main/infinite_scroll.js new file mode 100644 index 000000000..b900e66e2 --- /dev/null +++ b/searx/static/themes/simple/src/js/main/infinite_scroll.js @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later + +/* global searxng */ + +searxng.ready(function () { + 'use strict'; + + searxng.infinite_scroll_supported = ( + 'IntersectionObserver' in window && + 'IntersectionObserverEntry' in window && + 'intersectionRatio' in window.IntersectionObserverEntry.prototype); + + if (searxng.endpoint !== 'results') { + return; + } + + if (!searxng.infinite_scroll_supported) { + console.log('IntersectionObserver not supported'); + return; + } + + let d = document; + var onlyImages = d.getElementById('results').classList.contains('only_template_images'); + + function newLoadSpinner () { + var loader = d.createElement('div'); + loader.classList.add('loader'); + return loader; + } + + function replaceChildrenWith (element, children) { + element.textContent = ''; + children.forEach(child => element.appendChild(child)); + } + + function loadNextPage (callback) { + var form = d.querySelector('#pagination form.next_page'); + if (!form) { + return + } + replaceChildrenWith(d.querySelector('#pagination'), [ newLoadSpinner() ]); + var formData = new FormData(form); + searxng.http('POST', d.querySelector('#search').getAttribute('action'), formData).then( + function (response) { + var nextPageDoc = new DOMParser().parseFromString(response, 'text/html'); + var articleList = nextPageDoc.querySelectorAll('#urls article'); + var paginationElement = nextPageDoc.querySelector('#pagination'); + d.querySelector('#pagination').remove(); + if (articleList.length > 0 && !onlyImages) { + // do not add
element when there are only images + d.querySelector('#urls').appendChild(d.createElement('hr')); + } + articleList.forEach(articleElement => { + d.querySelector('#urls').appendChild(articleElement); + }); + if (paginationElement) { + d.querySelector('#results').appendChild(paginationElement); + callback(); + } + } + ).catch( + function (err) { + console.log(err); + var e = d.createElement('div'); + e.textContent = searxng.translations.error_loading_next_page; + e.classList.add('dialog-error'); + e.setAttribute('role', 'alert'); + replaceChildrenWith(d.querySelector('#pagination'), [ e ]); + } + ) + } + + if (searxng.infinite_scroll && searxng.infinite_scroll_supported) { + const intersectionObserveOptions = { + rootMargin: "20rem", + }; + const observedSelector = 'article.result:last-child'; + const observer = new IntersectionObserver(entries => { + const paginationEntry = entries[0]; + if (paginationEntry.isIntersecting) { + observer.unobserve(paginationEntry.target); + loadNextPage(() => observer.observe(d.querySelector(observedSelector), intersectionObserveOptions)); + } + }); + observer.observe(d.querySelector(observedSelector), intersectionObserveOptions); + } + +}); diff --git a/searx/static/themes/simple/src/js/main/preferences.js b/searx/static/themes/simple/src/js/main/preferences.js index 343f20826..09f9cdde4 100644 --- a/searx/static/themes/simple/src/js/main/preferences.js +++ b/searx/static/themes/simple/src/js/main/preferences.js @@ -2,6 +2,10 @@ (function (w, d, searxng) { 'use strict'; + if (searxng.endpoint !== 'preferences') { + return; + } + searxng.ready(function () { let engine_descriptions = null; function load_engine_descriptions () { @@ -19,10 +23,8 @@ } } - if (d.querySelector('body[class="preferences_endpoint"]')) { - for (const el of d.querySelectorAll('[data-engine-name]')) { - searxng.on(el, 'mouseenter', load_engine_descriptions); - } + for (const el of d.querySelectorAll('[data-engine-name]')) { + searxng.on(el, 'mouseenter', load_engine_descriptions); } }); })(window, document, window.searxng); diff --git a/searx/static/themes/simple/src/js/main/results.js b/searx/static/themes/simple/src/js/main/results.js index b9bd43394..609bd8ecd 100644 --- a/searx/static/themes/simple/src/js/main/results.js +++ b/searx/static/themes/simple/src/js/main/results.js @@ -2,6 +2,10 @@ (function (w, d, searxng) { 'use strict'; + if (searxng.endpoint !== 'results') { + return; + } + searxng.ready(function () { searxng.image_thumbnail_layout = new searxng.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 14, 6, 200); searxng.image_thumbnail_layout.watch(); diff --git a/searx/static/themes/simple/src/less/style.less b/searx/static/themes/simple/src/less/style.less index dd038cdf7..29cf554b0 100644 --- a/searx/static/themes/simple/src/less/style.less +++ b/searx/static/themes/simple/src/less/style.less @@ -771,15 +771,19 @@ article[data-vim-selected].category-social { margin: 1rem @results-tablet-offset 0 @results-tablet-offset; display: grid; grid-template-columns: 100%; - grid-template-rows: min-content min-content 1fr min-content min-content; + grid-template-rows: min-content min-content min-content 1fr min-content; gap: 0; grid-template-areas: "corrections" - "urls" "answers" "sidebar" + "urls" "pagination"; + #sidebar { + display: none; + } + #urls { width: inherit; margin: 0; diff --git a/searx/templates/oscar/base.html b/searx/templates/oscar/base.html index de7d05bf6..dbc0699df 100644 --- a/searx/templates/oscar/base.html +++ b/searx/templates/oscar/base.html @@ -100,6 +100,7 @@ {% for script in scripts %} {{""}} diff --git a/searx/templates/oscar/preferences.html b/searx/templates/oscar/preferences.html index 71ee57a62..1a5219b07 100644 --- a/searx/templates/oscar/preferences.html +++ b/searx/templates/oscar/preferences.html @@ -248,6 +248,17 @@ {{ preferences_item_footer(info, label, rtl) }} {% endif %} + {% if 'infinite_scroll' not in locked_preferences %} + {% set label = _('Infinite scroll') %} + {% set info = _('Automatically load next page when scrolling to bottom of current page') %} + {{ preferences_item_header(info, label, rtl, 'infinite_scroll') }} + + {{ preferences_item_footer(info, label, rtl) }} + {% endif %} + {{ plugin_of_category('ui' )}} diff --git a/searx/templates/simple/base.html b/searx/templates/simple/base.html index ffd648171..644c6df9a 100644 --- a/searx/templates/simple/base.html +++ b/searx/templates/simple/base.html @@ -23,7 +23,7 @@ data-method="{{ method or 'POST' }}" data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}" data-search-on-category-select="{{ 'true' if 'plugins/js/search_on_category_select.js' in scripts else 'false'}}" - data-infinite-scroll="{{ 'true' if 'plugins/js/infinite_scroll.js' in scripts else 'false' }}" + data-infinite-scroll="{% if infinite_scroll %}true{% else %}false{% endif %}" data-hotkeys="{{ 'true' if 'plugins/js/vim_hotkeys.js' in scripts else 'false' }}" data-static-path="{{ url_for('static', filename='themes/simple') }}/" data-translations="{{ translations }}"> diff --git a/searx/templates/simple/preferences.html b/searx/templates/simple/preferences.html index b47cbc774..275a53bf7 100644 --- a/searx/templates/simple/preferences.html +++ b/searx/templates/simple/preferences.html @@ -226,6 +226,18 @@
{{_('Open result links on new browser tabs') }}
{% endif %} + {% if 'infinite_scroll' not in locked_preferences %} +
+ {{ _('Infinite scroll') }} +

+ +

+
{{ _('Automatically load next page when scrolling to bottom of current page') }}
+
+ {% endif %} {{ plugin_preferences('ui') }} {{ tab_footer() }} diff --git a/searx/webapp.py b/searx/webapp.py index eb08d63d9..1314fc276 100755 --- a/searx/webapp.py +++ b/searx/webapp.py @@ -431,6 +431,8 @@ def get_translations(): 'no_item_found': gettext('No item found'), # /preferences: the source of the engine description (wikipedata, wikidata, website) 'Source': gettext('Source'), + # infinite scroll + 'error_loading_next_page': gettext('Error loading the next page'), } @@ -463,6 +465,7 @@ def render(template_name: str, override_theme: str = None, **kwargs): kwargs['preferences'] = request.preferences kwargs['method'] = request.preferences.get_value('method') kwargs['autocomplete'] = request.preferences.get_value('autocomplete') + kwargs['infinite_scroll'] = request.preferences.get_value('infinite_scroll') kwargs['results_on_new_tab'] = request.preferences.get_value('results_on_new_tab') kwargs['advanced_search'] = request.preferences.get_value('advanced_search') kwargs['query_in_title'] = request.preferences.get_value('query_in_title') From 1832ec742a378f0fd2162e3c07b7c279544c86f8 Mon Sep 17 00:00:00 2001 From: Alexandre Flament Date: Sun, 20 Feb 2022 19:46:51 +0100 Subject: [PATCH 2/2] [build] /static --- .../themes/oscar/css/logicodev-dark.css | 23 +++ .../themes/oscar/css/logicodev-dark.min.css | Bin 21811 -> 22206 bytes .../oscar/css/logicodev-dark.min.css.map | Bin 11613 -> 11830 bytes searx/static/themes/oscar/css/logicodev.css | 23 +++ .../static/themes/oscar/css/logicodev.min.css | Bin 18163 -> 18558 bytes .../themes/oscar/css/logicodev.min.css.map | Bin 10142 -> 10360 bytes searx/static/themes/oscar/css/pointhi.css | 23 +++ searx/static/themes/oscar/css/pointhi.min.css | Bin 13554 -> 13949 bytes .../themes/oscar/css/pointhi.min.css.map | Bin 8074 -> 8291 bytes searx/static/themes/oscar/js/searxng.js | 146 ++++++++++++++---- searx/static/themes/oscar/js/searxng.min.js | Bin 9231 -> 11017 bytes .../static/themes/oscar/js/searxng.min.js.map | Bin 9011 -> 10840 bytes .../themes/simple/css/searxng-rtl.min.css | Bin 59319 -> 59388 bytes .../themes/simple/css/searxng-rtl.min.css.map | Bin 97752 -> 97809 bytes .../static/themes/simple/css/searxng.min.css | Bin 58291 -> 58360 bytes .../themes/simple/css/searxng.min.css.map | Bin 96145 -> 96202 bytes searx/static/themes/simple/js/searxng.min.js | Bin 26292 -> 29011 bytes .../themes/simple/js/searxng.min.js.map | Bin 89208 -> 97156 bytes 18 files changed, 186 insertions(+), 29 deletions(-) diff --git a/searx/static/themes/oscar/css/logicodev-dark.css b/searx/static/themes/oscar/css/logicodev-dark.css index 8d5e16be2..2a344c14f 100644 --- a/searx/static/themes/oscar/css/logicodev-dark.css +++ b/searx/static/themes/oscar/css/logicodev-dark.css @@ -382,6 +382,29 @@ .col-stat { width: 10rem; } +@keyframes rotate-forever { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} +.loading-spinner { + animation-duration: 0.75s; + animation-iteration-count: infinite; + animation-name: rotate-forever; + animation-timing-function: linear; + height: 30px; + width: 30px; + border: 8px solid #666; + border-right-color: transparent; + border-radius: 50% !important; + margin: 0 auto; +} +html.infinite_scroll #pagination button { + visibility: hidden; +} /* this file is generated automatically by searxng_extra/update/update_pygments.py using pygments version 2.11.2 diff --git a/searx/static/themes/oscar/css/logicodev-dark.min.css b/searx/static/themes/oscar/css/logicodev-dark.min.css index 9d62caf4433fd0cc249d77fbc5cd19dcfdc242a0..e2051038ac1a250bfd9fb8b6339e0ae3b446f57f 100644 GIT binary patch delta 412 zcmZvXL2AP=5Jky4^bRf|&@3EOLfj&6y6q{79Le@jX=Fy@G$9yYp*=%)g+d|wo~?46 zlrFlP`R_~f|M6q;{W_#lQTk#)Q zWkQ>3(REAfl?JTR&;VlmMj<%G;4#%Lod&tQTZeqq`vCx(k)#{nB1^y$Fp6i-V8NL1 z9O4r24`pz}$+E@Ga7kJ~qbRQpR5i<$XmYo%X Xv&X|00$deff%mcotqmSur|*wHF*}`9 delta 18 acmdnDmT~hc#tjp>CoA$vY&PNT@&o`#vIe*S diff --git a/searx/static/themes/oscar/css/logicodev-dark.min.css.map b/searx/static/themes/oscar/css/logicodev-dark.min.css.map index 32293f3a43cc80ffe3356a30a41c213dc1fbcf2d..e9928c467685b813cbaf6cfbbf9c84246d8a7cb7 100644 GIT binary patch delta 260 zcmcZ`wJl~sC3A9q%0zSdiN{nX9yE!Ru0h_36e<$DNhEg0kK>`gtw!+nUhYr zv!io{vrafj#NRn3b+Zo7Ofkl!$;XuP7?U@fDmO4QI#1rFrpJ+51ahLY>*RmxlABr8 GBiI0fOihRY delta 64 zcmV-G0KfmXT-{obd6Rzv7LkZ`vmgOq0g-tRlWYPBvz`L42?9x3vjq*A76C((pCfJo WVzUk;fCB+zlaD7Z0b{eiCwK<*8WpSn diff --git a/searx/static/themes/oscar/css/logicodev.css b/searx/static/themes/oscar/css/logicodev.css index dcfcd2b8c..08cf93703 100644 --- a/searx/static/themes/oscar/css/logicodev.css +++ b/searx/static/themes/oscar/css/logicodev.css @@ -382,6 +382,29 @@ .col-stat { width: 10rem; } +@keyframes rotate-forever { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} +.loading-spinner { + animation-duration: 0.75s; + animation-iteration-count: infinite; + animation-name: rotate-forever; + animation-timing-function: linear; + height: 30px; + width: 30px; + border: 8px solid #666; + border-right-color: transparent; + border-radius: 50% !important; + margin: 0 auto; +} +html.infinite_scroll #pagination button { + visibility: hidden; +} /* this file is generated automatically by searxng_extra/update/update_pygments.py using pygments version 2.11.2 diff --git a/searx/static/themes/oscar/css/logicodev.min.css b/searx/static/themes/oscar/css/logicodev.min.css index be5f3f2af30868146f018635079d1e745217a965..efccb4d0af95365c31a3e89e084a37298e7eb320 100644 GIT binary patch delta 412 zcmZvXL2AP=5Jky4^bRf|&@3EOLfj&6dXpksvOQE9nb9~+2*xKUq&F$_Xx*2}aZJ1Jei%LqgWo96o$AvIk7vj>hHyWV3P@L z>Q&#btydbbPD2Zb@f(HU6obc9cXS@)`e7ULNgqZ4Y$lSHzC)IP6<`!Ep3#Ca;U&a1 z;2+B1#*nI)<5#mPnaIXN4@8gj?Dcx4Qw zh64%b948%bI6vLV(Y?e;CljnJ*U8b*5h&^G2+{{+27{QXAXX|u&>zI~pKPcqJb5Rx zpaqZv(H994PX;MY2CD$ETtS4lqq~`tPPwzAbB41{I7r0bIVE+o2G1FB#tbon(YPw#Jjvs)~9AxCs(BV~>Q>w1@?} zng6~$|9`=^{dixTo?gtMCFM-a$g^Tow4Th)&{3?8ObTP#ot)X7$j5u}A6QpHn=T*6 z(t4!jz{B*a9Z;;+ZU%5?(@F1OA~5 zZaUcxxScLZ3uqM8y@9T0xfWqxzk=p|9ve^EkbDgLES|gtoh_@Xs%N>N=}ih^J;`(b zpvWNq;?!=4awAr^;DRSsi8)0bpcI)J*pEFsTV6Xn$1Qnlvt>}pa_*ls1GC5D4kFw% QV1W;^2dxc$zAc*k2P0pc?EnA( delta 16 XcmeyH^C@$~MDEFod=i^Ycs(@%L<9y= diff --git a/searx/static/themes/oscar/css/pointhi.min.css.map b/searx/static/themes/oscar/css/pointhi.min.css.map index f9b7975e1e4edaee13391120bfe93a7feaf083ed..3a1619ec7723da1f782000d1935b8825884aff93 100644 GIT binary patch delta 213 zcmeCOf9$Y9zqw*uymSnl9GyLN+#MbLbwV8- z!-0fzj+2fzoS*LG=w9NalL=Oq>*VO@2$Xbo1nC1ZgF(zx5GxfS=nrE0Po5|xJb67g z>trr*E-SDWi0(*`Y%)koGFTmm3d8^a diff --git a/searx/static/themes/oscar/js/searxng.js b/searx/static/themes/oscar/js/searxng.js index 45272607f..edeeaee84 100644 --- a/searx/static/themes/oscar/js/searxng.js +++ b/searx/static/themes/oscar/js/searxng.js @@ -19,6 +19,7 @@ window.searxng = (function(d) { return { autocompleter: script.getAttribute('data-autocompleter') === 'true', + infinite_scroll: script.getAttribute('data-infinite-scroll') === 'true', method: script.getAttribute('data-method'), translations: JSON.parse(script.getAttribute('data-translations')) }; @@ -189,6 +190,56 @@ $(document).ready(function(){ * SPDX-License-Identifier: AGPL-3.0-or-later */ +$(document).ready(function() { + function hasScrollbar() { + var root = document.compatMode=='BackCompat'? document.body : document.documentElement; + return root.scrollHeight>root.clientHeight; + } + + function loadNextPage() { + var formData = $('#pagination form:last').serialize(); + if (formData) { + $('#pagination').html('
'); + $.ajax({ + type: "POST", + url: $('#search_form').prop('action'), + data: formData, + dataType: 'html', + success: function(data) { + var body = $(data); + $('#pagination').remove(); + $('#main_results').append('
'); + $('#main_results').append(body.find('.result')); + $('#main_results').append(body.find('#pagination')); + if(!hasScrollbar()) { + loadNextPage(); + } + } + }); + } + } + + if (searxng.infinite_scroll) { + var win = $(window); + $("html").addClass('infinite_scroll'); + if(!hasScrollbar()) { + loadNextPage(); + } + win.on('scroll', function() { + if ($(document).height() - win.height() - win.scrollTop() < 150) { + loadNextPage(); + } + }); + } + +}); +;/** + * @license + * (C) Copyright Contributors to the SearXNG project. + * (C) Copyright Contributors to the searx project (2014 - 2021). + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + window.addEventListener('load', function() { // Hide infobox toggle if shrunk size already fits all content. $('.infobox').each(function() { @@ -348,7 +399,8 @@ $(document).ready(function(){ this.verticalMargin = verticalMargin; this.horizontalMargin = horizontalMargin; this.maxHeight = maxHeight; - this.isAlignDone = true; + this.trottleCallToAlign = null; + this.alignAfterThrotteling = false; } /** @@ -391,12 +443,12 @@ $(document).ready(function(){ // not loaded image : make it square as _getHeigth said it imgWidth = height; } - img.style.width = imgWidth + 'px'; - img.style.height = height + 'px'; - img.style.marginLeft = this.horizontalMargin + 'px'; - img.style.marginTop = this.horizontalMargin + 'px'; - img.style.marginRight = this.verticalMargin - 7 + 'px'; // -4 is the negative margin of the inline element - img.style.marginBottom = this.verticalMargin - 7 + 'px'; + img.setAttribute('width', Math.round(imgWidth)); + img.setAttribute('height', Math.round(height)); + img.style.marginLeft = Math.round(this.horizontalMargin) + 'px'; + img.style.marginTop = Math.round(this.horizontalMargin) + 'px'; + img.style.marginRight = Math.round(this.verticalMargin - 7) + 'px'; // -4 is the negative margin of the inline element + img.style.marginBottom = Math.round(this.verticalMargin - 7) + 'px'; resultNode = img.parentNode.parentNode; if (!resultNode.classList.contains('js')) { resultNode.classList.add('js'); @@ -431,6 +483,23 @@ $(document).ready(function(){ } }; + ImageLayout.prototype.throttleAlign = function () { + var obj = this; + if (obj.trottleCallToAlign) { + obj.alignAfterThrotteling = true; + } else { + obj.alignAfterThrotteling = false; + obj.align(); + obj.trottleCallToAlign = setTimeout(function () { + if (obj.alignAfterThrotteling) { + obj.align(); + } + obj.alignAfterThrotteling = false; + obj.trottleCallToAlign = null; + }, 20); + } + } + ImageLayout.prototype.align = function () { var i; var results_selectorNode = d.querySelectorAll(this.results_selector); @@ -460,9 +529,9 @@ $(document).ready(function(){ } }; - ImageLayout.prototype.watch = function () { + ImageLayout.prototype._monitorImages = function () { var i, img; - var obj = this; + var objthrottleAlign = this.throttleAlign.bind(this); var results_nodes = d.querySelectorAll(this.results_selector); var results_length = results_nodes.length; @@ -471,34 +540,53 @@ $(document).ready(function(){ event.originalTarget.src = w.searxng.static_path + w.searxng.theme.img_load_error; } - function throttleAlign () { - if (obj.isAlignDone) { - obj.isAlignDone = false; - setTimeout(function () { - obj.align(); - obj.isAlignDone = true; - }, 100); - } - } - - // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event - w.addEventListener('pageshow', throttleAlign); - // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event - w.addEventListener('load', throttleAlign); - // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event - w.addEventListener('resize', throttleAlign); - for (i = 0; i < results_length; i++) { img = results_nodes[i].querySelector(this.img_selector); - if (img !== null && img !== undefined) { - img.addEventListener('load', throttleAlign); + if (img !== null && img !== undefined && !img.classList.contains('aligned')) { + img.addEventListener('load', objthrottleAlign); // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror - img.addEventListener('error', throttleAlign); + img.addEventListener('error', objthrottleAlign); + img.addEventListener('timeout', objthrottleAlign); if (w.searxng.theme.img_load_error) { img.addEventListener('error', img_load_error, {once: true}); } + img.classList.add('aligned'); } } + } + + ImageLayout.prototype.watch = function () { + var objthrottleAlign = this.throttleAlign.bind(this); + + // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event + w.addEventListener('pageshow', objthrottleAlign); + // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event + w.addEventListener('load', objthrottleAlign); + // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event + w.addEventListener('resize', objthrottleAlign); + + this._monitorImages(); + + var obj = this; + + let observer = new MutationObserver(entries => { + let newElement = false; + for (let i = 0; i < entries.length; i++) { + if (entries[i].addedNodes.length > 0 && entries[i].addedNodes[0].classList.contains('result')) { + newElement = true; + break; + } + } + if (newElement) { + obj._monitorImages(); + } + }); + observer.observe(d.querySelector(this.container_selector), { + childList: true, + subtree: true, + attributes: false, + characterData: false, + }) }; w.searxng.ImageLayout = ImageLayout; diff --git a/searx/static/themes/oscar/js/searxng.min.js b/searx/static/themes/oscar/js/searxng.min.js index ab237e17c9a65834736c6de668357e5706d470d9..e0573b8886ce7d2de94dbf519a14f8d5a1777245 100644 GIT binary patch delta 2921 zcma)8-ESL35SK}cS{2$+C@S_h`*tbH-uF2FYv$m05 zL1K^Zs$=D@3^(5&_u%>K@hkAmpXdkmYbSo|zTY*pv)1I1W`bv_=eIV9%xdh+l4yNS z)Eh)Q7*|BptW&OoC|N0s3cb`>TNRbfV&|{@aV4g9M<}UoN}kn0>hM*{sx>_WC&diJ z$?uNd?s&jE9@rQfq{=u+Tw4>eUW|#-5SF5nk(hk|?uOcRy@RTtP}B9;8!uJZMmB;y z3OlhN6~?QRs=+v?(wQkufplivM`OVbd5_%jT6(iVi_V)jZ!I{eDdVC&RZ$|N+KM#} z$2O#Bcn(Rha(q-FniO^NT1fUA1dtS;2c%C(X z_ngY84qXB=G(J_#|h#-Vt&y)Jll6M`FR!KLwO%b3&%X!q|y^UYB@J=m9u5i;B4I~ z3NvypdrG!$_QAu!K_Tr5$<&6)Fy8DiM^sZqXE zSe|f7Q*6d}LI&vpN?%<5>NE|PS%Q35R%$sqX3ZWjW z{PLQna-nARXbk0sa|JUr7<7R-b7QdoI>&m6E&Bn~bW@UekyUifb@L_OUP;@-B{G3K zONr7{=Qq_T67$XA1fcQr;N(sc4AwzRc~#et!1+*=SSThYe1h{O&sr7FV3l6%Sb4fp zzzuqjzO1!mt4&Qk=Qc#JSaVRB=vp8}6N->PDIHcz$$UVKrfPaKra?Ucd!DXoyze0M z%Ruj#KjAd)IQGDOn!x|VitbYt-?Gj2fNIZh@Ay+yXCY^zepvV9o~}nQH!H)_fcX94 zxf6Tz!I3HC&Y8c4&-n_c-2mvU?brZxDz~i5mirPnh*b0qu7TxbWWZb-Ir)M*xahBn zy_t|;KPe|wm@l=H8Ull%5-85)5y6F!lsfr#T^bTdHDozZF^i}NDn9ZUP6)jM4q49V zn#axWBV#=rsuk&uGBMfgAWTG@o!-$2b7PuvyInG!iDb_Ub?{^vT++c2^v@T)BV`5X zgvmDO{>iC5hpWpF=lt>!`(1bc?jy`w6HmIERP8pJ&ilS0*>`96${12?tC`^?=ygdA z(WHhT_i6n!B;8=5srE+uEw*ZFJcofAncNgmqmUczvOQxlH#xUb7jSnG@{KyFQiTtL zX?swbpaY->t9FiApluJoo1K_qnCumH*ghjGl93t+$?WwYUV!qUkbD_oW&X|eLbvaA zM*4v-8p6=f3bf@11cxzDh?t(y3m3MwDDVwt)jU)7Uc)sEUl?2olC(==9G* zf2X#UU)g{Qi`AykZ9RudDI`?p)1{i#DNLC}u8bZnjtkThJfg*1e%o$&Y#WZ=XVx@x z7e@aN84Pvwl{3_>eWa|9>Bmpbzz(dWv_Am9Wthb@jH%92%<1iHxv7(j)y-A7O+nWO zU}joY%%N!~W5@oa0Md2_ERJl=%a`bqUbdLf$_=;+sy(^ut{f7;INBHKW0X7hlopuF zhpUp3^=&&-gM++*+lU|1K%`E3oqmH`QH{kFn+*UIu3W2HQj0Aj?dGhCxdMu6M8bWI X%Gc~&EmwfSh*V(y>_2OM7{&hqL@w;P delta 1286 zcma)6&u<$=6xPj8dax=qbtd+R&CGUZ zoB$?5+$a)MVGfmg<1ZkU59Pw2fO6{rAyq;>fVlU-iMN}?B2o@qW_I4ZnfJ~2eQ)o7 z{NUQbBWwJdb>Fh+cr#-s(-&D}O;Ojac~147gZv#DdUQN~X+2|6W92*;8@a16M!5o{ zf1CR|JH9wg&p|}w3zjh7TR1~>j$xDBx0oL^2r&(EEwfTbzM-_JkJ7GvB)qphLn zX)Z-sdm6(DEHK9kjSQ*I8dYk+xgSgRIf2cyifw)^P1_3V0ard(Z-u-s-jRZlN?;bs zeg+PkwQ}JDN_3asLB61R7}M}J-_!%w4LbBBa*gr+K))fHWD-h~mM6=jj8$O{%1wB{ z@8#B4DKw(}kcqw?U`2wq>hQK|HjyAf$4jcJ|524SCRNTZ3M}|ae;zV_H$hHB(}_NF z8k6WCMNe27o(c-uryK3TtVwDts{ z<|pS8@bQOpC3h?p>6v{uZw8G#l4O^QO}PvH&{yPkG}LT!BYB7iW{OEfW5wPR8f^2p zx?mnvFI<$TgXpgEdm(2+r_8kCmTU)|6Uy7*7O++#Hx^{2Ejkl5T$i;42mu=SD&#%p zK?=eiC#hFH0YHhOdf-vhsnw<^<_POavM^C?5uEm2?UFfMy74w8Vi<-{B%L_vLer#j zvs7*%;z;T!W;=%oDd|o_jMF5{IXdz^Q*N zHJ3RN$9`&08bNs)jkGUg4tmn?7U;_0RdJ8R=Igp`#pYqX)H-P!>7fz*Z!@^AcWO;4 zE7)9LnyFKtCJo~uu*~V^*~2SAfY4sTZfuIEn3bTHc^wswKDub301*uoXmGqv91r|d z2xuY9VSOnJMOl&$znz=#Ocuv7c5r&j!+O!|d&Mb*M^g0IY9-i%QgHpxjhp`hx5KFB diff --git a/searx/static/themes/oscar/js/searxng.min.js.map b/searx/static/themes/oscar/js/searxng.min.js.map index c5965158668d0d89fc92d6662710d33b82b9b9ae..6156eea02f118070e1d59c0622256422e26d8d0c 100644 GIT binary patch delta 4673 zcmaJ^&2Jmm5r>;L{x~G4?Z&bl*^W`5NW29_QM9D^P`vkcxmr>rO;a>Y0Y$JRSN!Hu z%jJiJq(l!rwn(vmLoYeC(5yAd=u!#r6K|iz35dYgt2edy2{wVs- zd&b$lAD>-`{`-?}KMMmt4EvsP`~3r7^gAs&g!i|G;wbcjgEsAZ{m!rzee?eB?|GpJ z!=O{2g!Ib18@BNi_>*DtEOphoa&y2h4f#~xBYV+ruYLK+7Xu&I`hhb*yyUfC@2)Bh zqwlVj7XGk7R{c6Kn0kbGeiFK2#~&6iL_=?O0kYd{dd&hdp>6Ux9BZ^Y{pNmW%z2p9 z!@y&JmY$PxqwNN60}(RpzcwBZ+{nBB*Jeu!(XouO5N)$ySV9zYhAV_?%%o6(vW%h- zrRS>~o=|CNlTt$&IU#b&$P1BwxvDdfqAf?tP@*TB`N+NT`G-Sklwhi4bYOU|a`w%Q zKVDrAEEaY$22O|*X*fbS-3$wR(W{$J9`yAh)|g1^8UNX$JXAv~8r-CoRng9^2kT3tfI|#qN&EiH7PYiWXQHpx)}ya)ee|;@go;Y)^Zb^M+>ONT z+tI&ny?<@OfK(DB_y8eHsr2AprEN#w-&(s4%(1F=?dZ|%waf;uda`em)QW?%wbPW9 zgxqA6#_(+#o~WhdmU;G@+r1wxMyz3L8%3ZK zh`W&lDL%4m&N#ngltT39J0C50<#I|}QgJhJbCwdMZ;gl|gnoaE@G^7r72jsk=T(DC zdoGD0Qc^RVMv@(=fJlf}Ys^FFbfI%PvB@EEECu$!3{x$h>7KwAiRW^z#b^}_3Xg>& zd8&mQHqj31o>W7b)Y8q@ETpt}%jRf=@i~;cGOeXgmtFujII*pzJ2uae84*MyAu&kc zeyx{@etxfbJ(1;h9ps`f?*%2jD(~oygGajODhS>_HK)sy%oEI}Rpt<$grzq1kJF_D z?g`3bv1diUx_|cuTeSj-m(=gSypG`m2g=y|+x@i#udI5Hg-)3hM!CaGxfr8V$C$e> z=-^U^xP4V;n}=PfVoNnHVMPPZ-CHrWs~5l(Tq^tpwS`KVB{r=O5uJ!y_T7j0O!Cqh zo5^wi%`?li0vm7`-nDC%SKhVYk?LtW(-atcc==!+lwo>w5Y$H~fbS7nRnTBPRGbk# zi;+*&RdrIT)>zJClX@VRpt8aSvd=pwGP=9|3oGQ=VNd7>#Kzn=kX@!k~F|fG25re8)W$);P-F?+kye{SyI-= zD$u0>p@wuP)Hre<+}VS3SS2NUC!Dmy7`OH~{7pVzER)Jmj&#n@90282+!V7t?%F~0 z?SqHcVT?Fl9!LLs@bMz4Z7nslttQ)#Z(ZTJMU+If#rK?D!Z}w+TtX5T2n?JSB?SW? z?g%H~X!1K;Ernej`=-OpRY(Da1(dd&Wpjf3(h|{8axbKS?OZx0a8)*ByNg(M^Q|9B8WVy+QZObzw!yj*h*!2%xxB!eL%plwG?g@ zm;o1A9JBFBLAM5!E;QZ&KJJG}B&~@1CMPD3YZLjlO?PAPKYu$kVjcjd@zQwr4- z0zs@V7Fm5`v4-X{R&;Ak1CdyUbFq1WQtHi3nt4kI<0@?B$gGuXQ()H14Za>axXU8s zDtukgJzIl}4?DC{A7hk4z%>SGb)km~1W9rTlQuM`t`>>TWvRWqD`+!xe844=kg>*q zLKZge%EU;?0;+Q%8kit(rgV9e6{nX57p0jlblVx+b(g-?5f+}YR+&>~9%pBtIMjZ@ zbF}Pm3v{`U-ZHG{26N2!#8Xp$?^Y?~SMjjKjU1}#xO#1wx V&It2hP9mUDOdQ8dT-WUaIgaB;{D|X6 zoCxG!K-Fs4vtWUcSb&0Hi^L8I*6a}fpc~fkopZ-|bb%M+x#xWM+;hJ3xbx@capL*! zKm0X$G5GD$gEx1o&FvX$rc$bwE8XLlmwpt^x7u>q`@kCu(8Cc3#RVh@` zKi<0b;>z@%W??yDVS_l7mMer?NwBaQyfrziYi1E5dQz|O&k=r8H4`gvF5OCyO`K$r zt5#0vxP)PNtgXBd`L+)Jz46Y|t`W73x4Xu5_GZf_aABK+vC6QuD~l`&K`n?{QdwC< zt`n?r*j1|t65=vw-@G$Dve*E)AsyrAiX-xI71hCaH)A&zZOaiVs(7m+GgTSa!M%yM zCw4)~vV?CCW|vrYJttIOc8qBGjHt(=T*U0m3pJ1jEZUWo1X&B7Owti>&7Cf>yP?V4`Nr9SOS1vMVEw z{^r1P&>h#B!hg0h*=`YM758O@sm@n*(7%%&Uvjy>s;j{t zclI-8N&^dZ!H;C5E5;cNbqx2*N@tvNvgBN#iU1h6! zU*eD-?>-tf*#Uo+8FU>EnN#MvC^n~}7@)U8fX`L-h@Kgr4$6U9wIn~Gch_hKnxgQD zBBU4UxIDL8p-4p`?odvK-U)YvjHvV(LmXOuiGk;F%ja+o&7dL*osvAt5ZfV}bvtv$ zrppnccMNvRq|<;?LN#qlj41Flc8la`PQbi+LZeA!!^TM?pXw1IbAH&tG*%I}7m-~q zy-{X5!8iBb*G)-ar$vA0U2gA&jC&;2i>9xmrqofT7=~(~8sQL#c*JMAycSH(JX^1O z)GB#&l8#bm+M>a|Nq(zMTmi7?(!&v`0O4U~W8s@^Szxg$0Ok_gjo{_X%_N+|Dk|AK z;i7?woY@3Nf57|GK0%tY;<65v4Ne}172ONRQ;>e|?hwXk0?S?c7ezcAoQ7AI3!*?H zV5e)27;Q91P$|((M@%+P&H?MW1$JI@y2C)An%pz8n-t{LVIp;Qv-12_eb;QjgnugWs=za$ORaKsW9 zPw|LI(qMq@j5*$0mVE~~)_op~B6Z+UUzIqQsUw~(I_mO_Z>6|fqvwR}6wj4a>~i)s z8}^9GWQEKRg*#6zqSj+(G+{-bMif$AR(PJ|DCA938}2Ukh*|}0l(P{UWr>8QM2_yC zb-{B|_wCV_4O%_lNKzCL88_aA%3=83W3;hXv{2I6HOhfRmC~W~KnK$6nVNB_X%nE& zUS(Zsj?u+|q7HG;(Db!)S_HUgH2CL9>tYh0`3N)TEy;?R+^0%R2cMN_!Z41I`V*FM zk$^Z{y5!#Zoe%kQp-eZmP$nzZd`hI2Y}_b-kJ4DB2_T9TMa_fX3S&s)vxmM9OEaJU E2Wa&t9RL6T diff --git a/searx/static/themes/simple/css/searxng-rtl.min.css b/searx/static/themes/simple/css/searxng-rtl.min.css index 8ba69f8df59303f0b952498c56643ffbde53f0f0..929fe1aa9f03bdc04c883ce0417240b8aafddb12 100644 GIT binary patch delta 59 zcmV-B0L1^d&jb9=1F)jsla1aRlfB<6liuDZlMdi86mw~0Wny7+dt_;IaBN|DI&N=n RWs~pS8j~O26|+3xdk2@P9NPc@ delta 52 zcmex!o_YIu<_(MPPhNMQe{#<~p2>UfYYCPX}%og7d3@#syBk7%ehc)}4Lwiy$7}k}9BiP-%n74-=x9@+z9` z61UqWGDeF}@2y~zp1!4m(Q$ftIV1mcp-M*KX~~Q%)1@mJ<=BfeQ&N)>i>80fV3eJF N;2g_#i%P}?ECA2>QiuQm delta 240 zcmbREhxNv9)(sKylVjuACqImn74~=ZanlKPbaaFeiH`n`ljq0FY3EcpIqLX=#JwFo zK?H~umB(w!Zh!*o1BYJ7tVDiN~f zlfx21giR}*3Y>J3!A1n9R{@O+oP04_WU{O~`{WlvJiIwoKpjx&;>jNqqM7u|oBa~E z`z10)i%;KL!N@;-P6Z>+^dl9Fj?>jE8TqESmjlH_Dj9{Rn^rQ4Y%i*0oX-LPYdTEp diff --git a/searx/static/themes/simple/css/searxng.min.css b/searx/static/themes/simple/css/searxng.min.css index 8144bbdec4ee348bad6d8a8bafb671480e230ea0..c08637a7efdb481d371ee53154d115097e367cde 100644 GIT binary patch delta 55 zcmV-70LcHd#{>As1F)Lkld9hflaSsJldRrRlLp{06mw~0Wny7+dt_;IaBN|DI&N=n NWs_0hF|#({eFG6d8b1I4 delta 51 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 delta 3661 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 delta 19572 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