PageSourceSearch

https://www.kotoba.fr/wp-content/plugins/kotoba-reactions/assets/frontend.js?ver=1.2.3

js kotoba.fr collected 2026-09-25 00:51:20 UTC 3,996 bytes, 117 lines download raw bytes

1(function () {
2  'use strict';
3
4  var config = window.KotobaReactions || {};
5
6  function request(path, options) {
7    options = options || {};
8    options.credentials = 'same-origin';
9    options.headers = options.headers || {};
10    options.headers.Accept = 'application/json';
11    if (config.nonce) {
12      options.headers['X-WP-Nonce'] = config.nonce;
13    }
14    return window.fetch(config.restUrl + path, options).then(function (response) {
15      return response.json().catch(function () { return {}; }).then(function (body) {
16        if (!response.ok) {
17          throw new Error(body.message || config.errorMessage);
18        }
19        return body;
20      });
21    });
22  }
23
24  function updateWidget(widget, state) {
25    var buttons = widget.querySelectorAll('[data-reaction]');
26    Array.prototype.forEach.call(buttons, function (button) {
27      var selected = button.getAttribute('data-reaction') === state.selected;
28      button.classList.toggle('is-selected', selected);
29      button.setAttribute('aria-pressed', selected ? 'true' : 'false');
30      var count = button.querySelector('[data-count]');
31      if (state.results_visible && state.counts && count) {
32        count.textContent = String(state.counts[button.getAttribute('data-reaction')] || 0);
33        count.hidden = false;
34      } else if (count) {
35        count.hidden = true;
36      }
37    });
38    widget.classList.toggle('has-results', !!state.results_visible);
39  }
40
41  function setBusy(widget, busy) {
42    widget.classList.toggle('is-loading', busy);
43    Array.prototype.forEach.call(widget.querySelectorAll('button'), function (button) {
44      button.disabled = busy;
45    });
46  }
47
48  function initWidget(widget) {
49    if (widget.getAttribute('data-initialized') === 'true') {
50      return;
51    }
52    widget.setAttribute('data-initialized', 'true');
53    var postId = widget.getAttribute('data-post-id');
54    var feedback = widget.querySelector('[data-feedback]');
55
56    request('post/' + encodeURIComponent(postId)).then(function (state) {
57      updateWidget(widget, state);
58    }).catch(function () {
59      /* Le vote reste disponible si la lecture de l'état échoue. */
60    });
61
62    widget.addEventListener('click', function (event) {
63      var button = event.target.closest ? event.target.closest('[data-reaction]') : null;
64      if (!button || !widget.contains(button) || button.disabled) {
65        return;
66      }
67
68      setBusy(widget, true);
69      if (feedback) {
70        feedback.textContent = '';
71      }
72      request('vote', {
73        method: 'POST',
74        headers: { 'Content-Type': 'application/json' },
75        body: JSON.stringify({ post_id: Number(postId), reaction: button.getAttribute('data-reaction') })
76      }).then(function (state) {
77        updateWidget(widget, state);
78        if (feedback) {
79          feedback.textContent = config.thanks || 'Merci pour votre réaction !';
80        }
81      }).catch(function (error) {
82        if (feedback) {
83          feedback.textContent = error.message || config.errorMessage;
84        }
85      }).then(function () {
86        setBusy(widget, false);
87      });
88    });
89  }
90
91  function initAll(root) {
92    Array.prototype.forEach.call((root || document).querySelectorAll('[data-kr-widget]'), initWidget);
93  }
94
95  if (document.readyState === 'loading') {
96    document.addEventListener('DOMContentLoaded', function () { initAll(document); });
97  } else {
98    initAll(document);
99  }
100
101  /* Certaines applications mobiles réinjectent le contenu sans recharger la page. */
102  if (window.MutationObserver) {
103    new MutationObserver(function (mutations) {
104      mutations.forEach(function (mutation) {
105        Array.prototype.forEach.call(mutation.addedNodes || [], function (node) {
106          if (node.nodeType === 1) {
107            if (node.matches && node.matches('[data-kr-widget]')) {
108              initWidget(node);
109            }
110            initAll(node);
111          }
112        });
113      });
114    }).observe(document.documentElement, { childList: true, subtree: true });
115  }
116}());
117

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.