summaryrefslogtreecommitdiff
path: root/client/simple/src/js/main/infinite_scroll.js
blob: 07db3305a6c6c4ba48344af3612a265919f38aea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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.settings.translations.error_loading_next_page;
        e.classList.add('dialog-error');
        e.setAttribute('role', 'alert');
        replaceChildrenWith(d.querySelector('#pagination'), [ e ]);
      }
    )
  }

  if (searxng.settings.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);
  }

});