[mod] infinite_scroll as preference

* oscar theme: code from searx/plugins/infinite_scroll.py
* simple theme: new implementation
This commit is contained in:
Alexandre Flament 2022-01-23 11:37:57 +01:00
parent de32d543bc
commit 83a47ef70b
16 changed files with 203 additions and 44 deletions

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

@ -0,0 +1,21 @@
@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;
}

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

View file

@ -59,43 +59,40 @@ 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);
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);
// Handle network errors
req.onerror = function () {
reject(Error("Network Error"));
};
req.onabort = function () {
reject(Error("Transaction is aborted"));
};
// Make the request
if (data) {
req.send(data)
} else {
reject(Error(req.statusText));
req.send();
}
};
// 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;
} catch (ex) {
reject(ex);
}
});
};
searxng.loadStyle = function (src) {

View file

@ -0,0 +1,76 @@
/**
* @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
*/
/* global searxng */
searxng.ready(function () {
'use strict';
let w = window;
let d = document;
var root = d.compatMode == 'BackCompat' ? d.body : d.documentElement;
function hasScrollbar () {
return root.scrollHeight > root.clientHeight;
}
function loadNextPage () {
var form = d.querySelector('#pagination form.next_page');
if (!form) {
return
}
var formData = new FormData(form);
d.querySelector('#pagination').innerHTML = '<div class="loader"></div>';
searxng.http('POST', d.querySelector('#search').getAttribute('action'), formData).then(
function (response) {
var scrollYBeforeInsert = w.scrollY;
var nextPageDoc = new DOMParser().parseFromString(response, 'text/html');
var articleList = nextPageDoc.querySelectorAll('#urls article');
var paginationElement = nextPageDoc.querySelector('#pagination');
var onlyImages = d.getElementById('results').classList.contains('only_template_images');
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);
});
searxng.image_thumbnail_layout.align();
w.scrollTo(w.scrollX, scrollYBeforeInsert);
if (paginationElement) {
d.querySelector('#results').appendChild(paginationElement);
if (!hasScrollbar()) {
loadNextPage();
}
}
}
).catch(
function (err) {
console.log(err);
d.querySelector('#pagination').innerHTML = '<div class="dialog-error" role="alert"><div><p>' +
searxng.translations.error_loading_next_page +
'</p></div></div>';
}
)
}
function onScroll () {
let clientRect = root.getBoundingClientRect();
if (root.scrollHeight - root.scrollTop - clientRect.height < 150) {
loadNextPage();
}
}
if (searxng.infinite_scroll) {
d.getElementsByTagName('html')[0].classList.add('infinite_scroll')
if (!hasScrollbar()) {
loadNextPage();
}
d.addEventListener('scroll', onScroll, { passive: true });
}
});