Merge pull request #916 from dalf/pref_infinite_scroll2

Convert the infinite_scroll plugin as a preference (second version)
This commit is contained in:
Alexandre Flament 2022-02-21 12:49:04 +01:00 committed by GitHub
commit 8230603f48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 528 additions and 171 deletions

View file

@ -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',)

View file

@ -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
}

View file

@ -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'

View file

@ -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, []),

View file

@ -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('<div class="loading-spinner"></div>');
$.ajax({
type: "POST",
url: $('#search_form').prop('action'),
data: formData,
dataType: 'html',
success: function(data) {
var body = $(data);
$('#pagination').remove();
$('#main_results').append('<hr/>');
$('#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();
}
});
});

View file

@ -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;

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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,

View file

@ -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('<div class="loading-spinner"></div>');
$.ajax({
type: "POST",
url: $('#search_form').prop('action'),
data: formData,
dataType: 'html',
success: function(data) {
var body = $(data);
$('#pagination').remove();
$('#main_results').append('<hr/>');
$('#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;

View file

@ -4,7 +4,7 @@
* (C) Copyright Contributors to the searx project (2014 - 2021).
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
window.searxng=function(t){"use strict";t.getElementsByTagName("html")[0].className="js";t=t.currentScript||(t=t.getElementsByTagName("script"))[t.length-1];return{autocompleter:"true"===t.getAttribute("data-autocompleter"),method:t.getAttribute("data-method"),translations:JSON.parse(t.getAttribute("data-translations"))}}(document),
window.searxng=function(t){"use strict";t.getElementsByTagName("html")[0].className="js";t=t.currentScript||(t=t.getElementsByTagName("script"))[t.length-1];return{autocompleter:"true"===t.getAttribute("data-autocompleter"),infinite_scroll:"true"===t.getAttribute("data-infinite-scroll"),method:t.getAttribute("data-method"),translations:JSON.parse(t.getAttribute("data-translations"))}}(document),
/**
* @license
* (C) Copyright Contributors to the SearXNG project.
@ -12,7 +12,7 @@ window.searxng=function(t){"use strict";t.getElementsByTagName("html")[0].classN
* (C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
$(document).ready(function(){var t,a="";searxng.autocompleter&&((t=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:{url:"./autocompleter?q=%QUERY",wildcard:"%QUERY"}})).initialize(),$("#q").on("keydown",function(t){13==t.which&&(a=$("#q").val())}),$("#q").typeahead({name:"search-results",highlight:!1,hint:!0,displayKey:function(t){return t},classNames:{input:"tt-input",hint:"tt-hint",menu:"tt-dropdown-menu",dataset:"tt-dataset-search-results"}},{name:"autocomplete",source:t}),$("#q").bind("typeahead:select",function(t,e){a&&$("#q").val(a),$("#search_form").submit()}))}),
$(document).ready(function(){var t,n="";searxng.autocompleter&&((t=new Bloodhound({datumTokenizer:Bloodhound.tokenizers.obj.whitespace("value"),queryTokenizer:Bloodhound.tokenizers.whitespace,remote:{url:"./autocompleter?q=%QUERY",wildcard:"%QUERY"}})).initialize(),$("#q").on("keydown",function(t){13==t.which&&(n=$("#q").val())}),$("#q").typeahead({name:"search-results",highlight:!1,hint:!0,displayKey:function(t){return t},classNames:{input:"tt-input",hint:"tt-hint",menu:"tt-dropdown-menu",dataset:"tt-dataset-search-results"}},{name:"autocomplete",source:t}),$("#q").bind("typeahead:select",function(t,e){n&&$("#q").val(n),$("#search_form").submit()}))}),
/**
* @license
* (C) Copyright Contributors to the SearXNG project.
@ -20,7 +20,14 @@ $(document).ready(function(){var t,a="";searxng.autocompleter&&((t=new Bloodhoun
* (C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
$(document).ready(function(){$("#q.autofocus").focus(),$("#clear_search").click(function(){document.getElementById("q").value=""}),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var t=$(this).data("btn-text-collapsed"),e=$(this).data("btn-text-not-collapsed");""!==t&&""!==e&&(new_html=$(this).hasClass("collapsed")?$(this).html().replace(t,e):$(this).html().replace(e,t),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var t="btn-"+$(this).data("btn-class"),e=$(this).data("btn-label-default"),a=$(this).data("btn-label-toggled");""!==a&&(new_html=$(this).hasClass("btn-default")?$(this).html().replace(e,a):$(this).html().replace(a,e),$(this).html(new_html)),$(this).toggleClass(t),$(this).toggleClass("btn-default")}),$(".media-loader").click(function(){var t=$(this).data("target"),t=$(t+" > iframe"),e=t.attr("src");void 0!==e&&!1!==e||t.attr("src",t.data("src"))}),$(".btn-sm").dblclick(function(){var t="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(t),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(t),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))}),$(".nav-tabs").click(function(t){$(t.target).parents("ul").children().attr("aria-selected","false"),$(t.target).parent().attr("aria-selected","true")}),searxng.image_thumbnail_layout=new searxng.ImageLayout("#main_results","#main_results .result-images","img.img-thumbnail",15,3,200),searxng.image_thumbnail_layout.watch()}),
$(document).ready(function(){$("#q.autofocus").focus(),$("#clear_search").click(function(){document.getElementById("q").value=""}),$(".select-all-on-click").click(function(){$(this).select()}),$(".btn-collapse").click(function(){var t=$(this).data("btn-text-collapsed"),e=$(this).data("btn-text-not-collapsed");""!==t&&""!==e&&(new_html=$(this).hasClass("collapsed")?$(this).html().replace(t,e):$(this).html().replace(e,t),$(this).html(new_html))}),$(".btn-toggle .btn").click(function(){var t="btn-"+$(this).data("btn-class"),e=$(this).data("btn-label-default"),n=$(this).data("btn-label-toggled");""!==n&&(new_html=$(this).hasClass("btn-default")?$(this).html().replace(e,n):$(this).html().replace(n,e),$(this).html(new_html)),$(this).toggleClass(t),$(this).toggleClass("btn-default")}),$(".media-loader").click(function(){var t=$(this).data("target"),t=$(t+" > iframe"),e=t.attr("src");void 0!==e&&!1!==e||t.attr("src",t.data("src"))}),$(".btn-sm").dblclick(function(){var t="btn-"+$(this).data("btn-class");$(this).hasClass("btn-default")?($(".btn-sm > input").attr("checked","checked"),$(".btn-sm > input").prop("checked",!0),$(".btn-sm").addClass(t),$(".btn-sm").addClass("active"),$(".btn-sm").removeClass("btn-default")):($(".btn-sm > input").attr("checked",""),$(".btn-sm > input").removeAttr("checked"),$(".btn-sm > input").checked=!1,$(".btn-sm").removeClass(t),$(".btn-sm").removeClass("active"),$(".btn-sm").addClass("btn-default"))}),$(".nav-tabs").click(function(t){$(t.target).parents("ul").children().attr("aria-selected","false"),$(t.target).parent().attr("aria-selected","true")}),searxng.image_thumbnail_layout=new searxng.ImageLayout("#main_results","#main_results .result-images","img.img-thumbnail",15,3,200),searxng.image_thumbnail_layout.watch()}),
/**
* @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 e(){var t="BackCompat"==document.compatMode?document.body:document.documentElement;return t.scrollHeight>t.clientHeight}function n(){var t=$("#pagination form:last").serialize();t&&($("#pagination").html('<div class="loading-spinner"></div>'),$.ajax({type:"POST",url:$("#search_form").prop("action"),data:t,dataType:"html",success:function(t){t=$(t);$("#pagination").remove(),$("#main_results").append("<hr/>"),$("#main_results").append(t.find(".result")),$("#main_results").append(t.find("#pagination")),e()||n()}}))}var t;searxng.infinite_scroll&&(t=$(window),$("html").addClass("infinite_scroll"),e()||n(),t.on("scroll",function(){$(document).height()-t.height()-t.scrollTop()<150&&n()}))}),
/**
* @license
* (C) Copyright Contributors to the SearXNG project.
@ -35,14 +42,14 @@ window.addEventListener("load",function(){$(".infobox").each(function(){var t=$(
* (C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
$(document).ready(function(){$(".searxng_init_map").on("click",function(t){var e=$(this).data("leaflet-target"),a=$(this).data("map-lon"),n=$(this).data("map-lat"),i=$(this).data("map-zoom"),s=$(this).data("map-boundingbox"),o=$(this).data("map-geojson"),r=(s&&(southWest=L.latLng(s[0],s[2]),northEast=L.latLng(s[1],s[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/themes/oscar/css/images/",L.map(e)),s=new L.TileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{minZoom:1,maxZoom:19,attribution:'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'}),e=(new L.TileLayer("https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",{minZoom:1,maxZoom:19,attribution:'Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'}),setTimeout(function(){map_bounds?r.fitBounds(map_bounds,{maxZoom:17}):a&&n&&(i?r.setView(new L.LatLng(n,a),i):r.setView(new L.LatLng(n,a),8))},0),r.addLayer(s),{"OSM Mapnik":s});L.control.layers(e).addTo(r),o&&L.geoJson(o).addTo(r),$(this).off(t)})}),
$(document).ready(function(){$(".searxng_init_map").on("click",function(t){var e=$(this).data("leaflet-target"),n=$(this).data("map-lon"),a=$(this).data("map-lat"),i=$(this).data("map-zoom"),o=$(this).data("map-boundingbox"),s=$(this).data("map-geojson"),r=(o&&(southWest=L.latLng(o[0],o[2]),northEast=L.latLng(o[1],o[3]),map_bounds=L.latLngBounds(southWest,northEast)),L.Icon.Default.imagePath="./static/themes/oscar/css/images/",L.map(e)),o=new L.TileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{minZoom:1,maxZoom:19,attribution:'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'}),e=(new L.TileLayer("https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",{minZoom:1,maxZoom:19,attribution:'Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors'}),setTimeout(function(){map_bounds?r.fitBounds(map_bounds,{maxZoom:17}):n&&a&&(i?r.setView(new L.LatLng(a,n),i):r.setView(new L.LatLng(a,n),8))},0),r.addLayer(o),{"OSM Mapnik":o});L.control.layers(e).addTo(r),s&&L.geoJson(s).addTo(r),$(this).off(t)})}),
/**
* @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(){let s=null;document.querySelector('body[class="preferences_endpoint"]')&&$("[data-engine-name]").hover(function(){null==s&&$.ajax("engine_descriptions.json",dataType="json").done(function(t){s=t;for(var[e,a]of Object.entries(t))for(const i of $('[data-engine-name="'+e+'"] .description')){var n=" (<i>"+searxng.translations.Source+":&nbsp;"+a[1]+"</i>)";i.innerHTML=a[0]+n}})})}),
$(document).ready(function(){let o=null;document.querySelector('body[class="preferences_endpoint"]')&&$("[data-engine-name]").hover(function(){null==o&&$.ajax("engine_descriptions.json",dataType="json").done(function(t){o=t;for(var[e,n]of Object.entries(t))for(const i of $('[data-engine-name="'+e+'"] .description')){var a=" (<i>"+searxng.translations.Source+":&nbsp;"+n[1]+"</i>)";i.innerHTML=n[0]+a}})})}),
/**
* @license
* (C) Copyright Contributors to the SearXNG project.
@ -71,5 +78,5 @@ $(document).ready(function(){$("#allow-all-engines").click(function(){$(".onoffs
* );
* searxng.image_thumbnail_layout.watch();
*/
function(r,c){function t(t,e,a,n,i,s){this.container_selector=t,this.results_selector=e,this.img_selector=a,this.verticalMargin=n,this.horizontalMargin=i,this.maxHeight=s,this.isAlignDone=!0}t.prototype._getHeigth=function(t,e){for(var a,n=0,i=0;i<t.length;i++)0<(a=t[i]).naturalWidth&&0<a.naturalHeight?n+=a.naturalWidth/a.naturalHeight:n+=1;return(e-t.length*this.verticalMargin)/n},t.prototype._setSize=function(t,e){for(var a,n,i=t.length,s=0;s<i;s++)n=0<(a=t[s]).naturalWidth&&0<a.naturalHeight?e*a.naturalWidth/a.naturalHeight:e,a.style.width=n+"px",a.style.height=e+"px",a.style.marginLeft=this.horizontalMargin+"px",a.style.marginTop=this.horizontalMargin+"px",a.style.marginRight=this.verticalMargin-7+"px",a.style.marginBottom=this.verticalMargin-7+"px",(n=a.parentNode.parentNode).classList.contains("js")||n.classList.add("js")},t.prototype._alignImgs=function(t){for(var e,a,n,i,s=c.querySelector(this.container_selector),o=window.getComputedStyle(s),r=parseInt(o.getPropertyValue("padding-left"),10),o=parseInt(o.getPropertyValue("padding-right"),10),l=s.clientWidth-r-o;0<t.length;){for(e=!0,n=1;n<=t.length&&e;n++)a=t.slice(0,n),(i=this._getHeigth(a,l))<this.maxHeight&&(this._setSize(a,i),t=t.slice(n),e=!1);if(e){this._setSize(a,Math.min(this.maxHeight,i));break}}},t.prototype.align=function(){for(var t=c.querySelectorAll(this.results_selector),e=t.length,a=null,n=null,i=[],s=0;s<e;s++)(n=t[s]).previousElementSibling!==a&&0<i.length&&(this._alignImgs(i),i=[]),i.push(n.querySelector(this.img_selector)),a=n;0<i.length&&this._alignImgs(i)},t.prototype.watch=function(){var t,e,a=this,n=c.querySelectorAll(this.results_selector),i=n.length;function s(t){t.originalTarget.src=r.searxng.static_path+r.searxng.theme.img_load_error}function o(){a.isAlignDone&&(a.isAlignDone=!1,setTimeout(function(){a.align(),a.isAlignDone=!0},100))}for(r.addEventListener("pageshow",o),r.addEventListener("load",o),r.addEventListener("resize",o),t=0;t<i;t++)null!=(e=n[t].querySelector(this.img_selector))&&(e.addEventListener("load",o),e.addEventListener("error",o),r.searxng.theme.img_load_error&&e.addEventListener("error",s,{once:!0}))},r.searxng.ImageLayout=t}(window,document);
function(s,c){function t(t,e,n,a,i,o){this.container_selector=t,this.results_selector=e,this.img_selector=n,this.verticalMargin=a,this.horizontalMargin=i,this.maxHeight=o,this.trottleCallToAlign=null,this.alignAfterThrotteling=!1}t.prototype._getHeigth=function(t,e){for(var n,a=0,i=0;i<t.length;i++)0<(n=t[i]).naturalWidth&&0<n.naturalHeight?a+=n.naturalWidth/n.naturalHeight:a+=1;return(e-t.length*this.verticalMargin)/a},t.prototype._setSize=function(t,e){for(var n,a,i=t.length,o=0;o<i;o++)a=0<(n=t[o]).naturalWidth&&0<n.naturalHeight?e*n.naturalWidth/n.naturalHeight:e,n.setAttribute("width",Math.round(a)),n.setAttribute("height",Math.round(e)),n.style.marginLeft=Math.round(this.horizontalMargin)+"px",n.style.marginTop=Math.round(this.horizontalMargin)+"px",n.style.marginRight=Math.round(this.verticalMargin-7)+"px",n.style.marginBottom=Math.round(this.verticalMargin-7)+"px",(a=n.parentNode.parentNode).classList.contains("js")||a.classList.add("js")},t.prototype._alignImgs=function(t){for(var e,n,a,i,o=c.querySelector(this.container_selector),s=window.getComputedStyle(o),r=parseInt(s.getPropertyValue("padding-left"),10),s=parseInt(s.getPropertyValue("padding-right"),10),l=o.clientWidth-r-s;0<t.length;){for(e=!0,a=1;a<=t.length&&e;a++)n=t.slice(0,a),(i=this._getHeigth(n,l))<this.maxHeight&&(this._setSize(n,i),t=t.slice(a),e=!1);if(e){this._setSize(n,Math.min(this.maxHeight,i));break}}},t.prototype.throttleAlign=function(){var t=this;t.trottleCallToAlign?t.alignAfterThrotteling=!0:(t.alignAfterThrotteling=!1,t.align(),t.trottleCallToAlign=setTimeout(function(){t.alignAfterThrotteling&&t.align(),t.alignAfterThrotteling=!1,t.trottleCallToAlign=null},20))},t.prototype.align=function(){for(var t=c.querySelectorAll(this.results_selector),e=t.length,n=null,a=null,i=[],o=0;o<e;o++)(a=t[o]).previousElementSibling!==n&&0<i.length&&(this._alignImgs(i),i=[]),i.push(a.querySelector(this.img_selector)),n=a;0<i.length&&this._alignImgs(i)},t.prototype._monitorImages=function(){var t,e,n=this.throttleAlign.bind(this),a=c.querySelectorAll(this.results_selector),i=a.length;function o(t){t.originalTarget.src=s.searxng.static_path+s.searxng.theme.img_load_error}for(t=0;t<i;t++)null==(e=a[t].querySelector(this.img_selector))||e.classList.contains("aligned")||(e.addEventListener("load",n),e.addEventListener("error",n),e.addEventListener("timeout",n),s.searxng.theme.img_load_error&&e.addEventListener("error",o,{once:!0}),e.classList.add("aligned"))},t.prototype.watch=function(){var t=this.throttleAlign.bind(this),a=(s.addEventListener("pageshow",t),s.addEventListener("load",t),s.addEventListener("resize",t),this._monitorImages(),this);let e=new MutationObserver(e=>{let n=!1;for(let t=0;t<e.length;t++)if(0<e[t].addedNodes.length&&e[t].addedNodes[0].classList.contains("result")){n=!0;break}n&&a._monitorImages()});e.observe(c.querySelector(this.container_selector),{childList:!0,subtree:!0,attributes:!1,characterData:!1})},s.searxng.ImageLayout=t}(window,document);
//# sourceMappingURL=searxng.min.js.map

File diff suppressed because one or more lines are too long

View file

@ -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'))
};

View file

@ -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('<div class="loading-spinner"></div>');
$.ajax({
type: "POST",
url: $('#search_form').prop('action'),
data: formData,
dataType: 'html',
success: function(data) {
var body = $(data);
$('#pagination').remove();
$('#main_results').append('<hr/>');
$('#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();
}
});
}
});

View file

@ -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;
}

View file

@ -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);

View file

@ -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";

View file

@ -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";

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -59,17 +59,12 @@ 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;
// On load
req.onload = function () {
@ -89,13 +84,20 @@ window.searxng = (function (w, d) {
reject(Error("Transaction is aborted"));
};
req.ontimeout = function () {
reject(Error("Timeout"));
}
// Make the request
if (data) {
req.send(data)
} else {
req.send();
}
} catch (ex) {
reject(ex);
}
return promise;
});
};
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);

View file

@ -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 <hr> 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);
}
});

View file

@ -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);
}
}
});
})(window, document, window.searxng);

View file

@ -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();

View file

@ -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;

View file

@ -100,6 +100,7 @@
<script src="{{ url_for('static', filename='js/searxng.min.js') }}"
data-method="{{ method or 'POST' }}"
data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}"
data-infinite-scroll="{% if infinite_scroll %}true{% else %}false{% endif %}"
data-translations="{{ translations }}"></script>
{% for script in scripts %}
{{""}}<script src="{{ url_for('static', filename=script) }}"></script>

View file

@ -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') }}
<select class="form-control {{ custom_select_class(rtl) }}" name="infinite_scroll" id="infinite_scroll">
<option value="1" {% if infinite_scroll %}selected="selected"{% endif %}>{{ _('On') }}</option>
<option value="0" {% if not infinite_scroll %}selected="selected"{% endif %}>{{ _('Off')}}</option>
</select>
{{ preferences_item_footer(info, label, rtl) }}
{% endif %}
{{ plugin_of_category('ui' )}}
</div>
</fieldset>

View file

@ -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 }}"></script>

View file

@ -226,6 +226,18 @@
<div class="description">{{_('Open result links on new browser tabs') }}</div>
</fieldset>
{% endif %}
{% if 'infinite_scroll' not in locked_preferences %}
<fieldset>
<legend>{{ _('Infinite scroll') }}</legend>
<p class="value">
<select name='infinite_scroll'>
<option value="1" {% if infinite_scroll %}selected="selected"{% endif %}>{{ _('On') }}</option>
<option value="0" {% if not infinite_scroll %}selected="selected"{% endif %}>{{ _('Off')}}</option>
</select>
</p>
<div class="description">{{ _('Automatically load next page when scrolling to bottom of current page') }}</div>
</fieldset>
{% endif %}
{{ plugin_preferences('ui') }}
{{ tab_footer() }}

View file

@ -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')