PageSourceSearch

https://www.fernstudi.net/media/templates/site/ontheme/js/news.js?1.0.0

js fernstudi.net collected 2026-10-02 06:36:56 UTC 3,182 bytes, 111 lines download raw bytes

1/**
2 * Load more on the news overview.
3 *
4 * Appends the next batch of cards after the ones already rendered. The month state travels
5 * with the request: the endpoint runs in its own PHP process and would otherwise repeat the
6 * heading of a month that is already open at the batch boundary.
7 *
8 * @copyright  Copyright (C) 2026 onblur.media GmbH. All rights reserved.
9 * @license    GNU General Public License version 2 or later; see LICENSE.txt
10 */
11(function () {
12  'use strict';
13
14  const button = document.getElementById('button-loadmore');
15  const errorBox = document.getElementById('loadmore-error');
16
17  if (!button) {
18    return;
19  }
20
21  const total = parseInt(button.dataset.total, 10) || 0;
22  const limitEnd = parseInt(button.dataset.limitend, 10) || 25;
23  const label = button.innerHTML;
24  let busy = false;
25
26  /**
27   * Toggle the loading state of the button.
28   *
29   * @param   {boolean}  loading  Whether a request is in flight
30   *
31   * @returns {void}
32   */
33  const setLoading = function (loading) {
34    busy = loading;
35    button.disabled = loading;
36    button.setAttribute('aria-busy', loading ? 'true' : 'false');
37    button.innerHTML = loading
38      ? '<i class="fas fa-circle-notch fa-spin" aria-hidden="true"></i> ' + button.dataset.labelLoading
39      : label;
40  };
41
42  button.addEventListener('click', function () {
43    if (busy) {
44      return;
45    }
46
47    const limitStart = (parseInt(button.dataset.limitstart, 10) || 0) + limitEnd;
48    const container = document.getElementById('container-news');
49
50    if (!container) {
51      return;
52    }
53
54    const params = new URLSearchParams({
55      option: 'com_ontemplate',
56      view: 'ajax',
57      layout: 'items.news',
58      limitstart: String(limitStart),
59      limitend: String(limitEnd),
60      catid: button.dataset.catid || '0',
61      lastmonth: button.dataset.lastmonth || '',
62      ordering: button.dataset.ordering || 'rdate',
63    });
64
65    if (errorBox) {
66      errorBox.hidden = true;
67    }
68
69    setLoading(true);
70
71    fetch(button.dataset.endpoint + '?' + params.toString(), {
72      credentials: 'same-origin',
73      headers: { 'X-Requested-With': 'XMLHttpRequest' },
74    })
75      .then(function (response) {
76        if (!response.ok) {
77          throw new Error('HTTP ' + response.status);
78        }
79
80        return response.text();
81      })
82      .then(function (html) {
83        container.outerHTML = html;
84        button.dataset.limitstart = String(limitStart);
85
86        // The replacement carries the month that was open when the batch ended
87        const fresh = document.getElementById('container-news');
88
89        if (fresh) {
90          button.dataset.lastmonth = fresh.dataset.lastmonth || '';
91        }
92
93        if (limitStart + limitEnd >= total) {
94          button.hidden = true;
95        }
96
97        if (window._paq) {
98          window._paq.push(['trackEvent', 'News', 'LoadMore', String(limitStart)]);
99        }
100      })
101      .catch(function () {
102        // A dialog would block every following interaction, so the message stays in the page
103        if (errorBox) {
104          errorBox.hidden = false;
105        }
106      })
107      .finally(function () {
108        setLoading(false);
109      });
110  });
111}());

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.