summaryrefslogtreecommitdiff
path: root/searx/static/themes/simple/src/js/main
diff options
context:
space:
mode:
authorAlexandre Flament <alex@al-f.net>2022-01-23 11:37:57 +0100
committerAlexandre Flament <alex@al-f.net>2022-02-20 22:58:51 +0100
commit56e34947a6368e6154064c52fa23d21ecda7ab4c (patch)
treebad1463a0c3056896cfacb205039586b85a2c04d /searx/static/themes/simple/src/js/main
parent36aee70c247fe347c69abb17ec3bdc31781204c6 (diff)
downloadsearxng-56e34947a6368e6154064c52fa23d21ecda7ab4c.tar.gz
searxng-56e34947a6368e6154064c52fa23d21ecda7ab4c.zip
[mod] infinite_scroll as preference
* oscar theme: code from searx/plugins/infinite_scroll.py * simple theme: new implementation Co-authored-by: Markus Heiser <markus.heiser@darmarIT.de>
Diffstat (limited to 'searx/static/themes/simple/src/js/main')
-rw-r--r--searx/static/themes/simple/src/js/main/00_toolkit.js81
-rw-r--r--searx/static/themes/simple/src/js/main/infinite_scroll.js88
-rw-r--r--searx/static/themes/simple/src/js/main/preferences.js10
-rw-r--r--searx/static/themes/simple/src/js/main/results.js4
4 files changed, 145 insertions, 38 deletions
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; }
- };
-
- try {
- req.open(method, url, true);
+ 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 () {
+ 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"));
+ }
- // On load
- req.onload = function () {
- if (req.status == 200) {
- resolve(req.response, req.responseType);
+ // 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) {
@@ -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 <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);
+ }
+
+});
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();