PageSourceSearch

https://www.eventtia.com/assets/js/blog-index.87981ccf.js

js eventtia.com collected 2026-10-02 09:49:57 UTC 7,077 bytes, 150 lines download raw bytes

1// One collection drives topic filters, full-archive search, and explicit paging.
2(function () {
3  var root = document.querySelector('[data-blog-journal]');
4  if (!root) return;
5  var BATCH_SIZE = 12;
6  var input = root.querySelector('#journalSearch');
7  var picker = root.querySelector('[data-journal-picker]');
8  var toggle = root.querySelector('[data-journal-toggle]');
9  var panel = root.querySelector('[data-journal-panel]');
10  var pickerLabel = root.querySelector('[data-journal-picker-label]');
11  var options = Array.from(panel.querySelectorAll('[data-journal-category]'));
12  var chips = Array.from(root.querySelectorAll('[data-journal-category]'));
13  var featured = root.querySelector('[data-journal-featured]');
14  var more = root.querySelector('[data-journal-more]');
15  var pagination = root.querySelector('[data-journal-pagination]');
16  var empty = root.querySelector('[data-journal-empty]');
17  var count = root.querySelector('[data-journal-count]');
18  var heading = root.querySelector('#journalArchiveTitle');
19  var clear = root.querySelector('[data-journal-clear]');
20  var category = '';
21  var limit = BATCH_SIZE;
22
23  function normalize(value) {
24    return value.toLocaleLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').trim();
25  }
26  var records = Array.from(root.querySelectorAll('[data-journal-card]')).map(function (card) {
27    return { element: card, text: normalize(card.dataset.search), category: card.dataset.category, technology: card.dataset.technology === 'true', featured: card.dataset.featured === 'true' };
28  });
29  var matching = [];
30  root.classList.add('journal-enhanced');
31
32  function render() {
33    var query = normalize(input.value);
34    var terms = query.split(/\s+/).filter(Boolean);
35    var filtering = Boolean(query || category);
36    matching = records.filter(function (record) {
37      return (filtering || !record.featured) && (!category || (category === 'ai-technology' ? record.technology : record.category === category)) && terms.every(function (term) { return record.text.includes(term); });
38    });
39    records.forEach(function (record) { record.element.hidden = true; });
40    matching.slice(0, limit).forEach(function (record) { record.element.hidden = false; });
41    if (featured) featured.hidden = filtering;
42    var selected = chips.find(function (chip) { return chip.dataset.journalCategory === category; });
43    var secondary = selected && panel.contains(selected);
44    pickerLabel.textContent = secondary ? selected.textContent.trim() : root.dataset.moreLabel;
45    toggle.classList.toggle('is-selected', Boolean(secondary));
46    chips.forEach(function (chip) { chip.setAttribute('aria-pressed', String(chip.dataset.journalCategory === category)); });
47    clear.hidden = !input.value;
48    empty.hidden = matching.length !== 0;
49    pagination.hidden = limit >= matching.length;
50    heading.textContent = query ? root.dataset.resultsLabel : (category && selected ? selected.textContent.trim() : root.dataset.latestLabel);
51    count.textContent = root.dataset.countTemplate.replace('{shown}', String(Math.min(limit, matching.length))).replace('{total}', String(matching.length));
52  }
53  function resetPage() { limit = BATCH_SIZE; render(); }
54  chips.forEach(function (chip) {
55    chip.addEventListener('click', function () {
56      category = chip.dataset.journalCategory;
57      closePicker(panel.contains(chip));
58      resetPage();
59    });
60  });
61  // Disclosure buttons retain normal Tab navigation, with optional arrow-key navigation.
62  function closePicker(restoreFocus) {
63    panel.hidden = true;
64    toggle.setAttribute('aria-expanded', 'false');
65    if (restoreFocus) toggle.focus();
66  }
67  function openPicker(focusOption, last) {
68    panel.hidden = false;
69    toggle.setAttribute('aria-expanded', 'true');
70    if (focusOption && options.length) {
71      var selected = options.find(function (option) { return option.dataset.journalCategory === category; });
72      (last ? options[options.length - 1] : selected || options[0]).focus();
73    }
74  }
75  toggle.addEventListener('click', function () {
76    if (panel.hidden) openPicker(false); else closePicker(false);
77  });
78  toggle.addEventListener('keydown', function (event) {
79    if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
80      event.preventDefault(); openPicker(true, event.key === 'ArrowUp');
81    }
82  });
83  picker.addEventListener('keydown', function (event) {
84    if (event.key === 'Escape' && !panel.hidden) { event.preventDefault(); closePicker(true); }
85  });
86  panel.addEventListener('keydown', function (event) {
87    var index = options.indexOf(document.activeElement);
88    var next;
89    if (event.key === 'ArrowDown') next = (index + 1) % options.length;
90    if (event.key === 'ArrowUp') next = (index + options.length - 1) % options.length;
91    if (event.key === 'Home') next = 0;
92    if (event.key === 'End') next = options.length - 1;
93    if (next !== undefined) { event.preventDefault(); options[next].focus(); }
94  });
95  document.addEventListener('pointerdown', function (event) {
96    if (!picker.contains(event.target)) closePicker(false);
97  });
98  document.addEventListener('focusin', function (event) {
99    if (!picker.contains(event.target)) closePicker(false);
100  });
101  input.addEventListener('input', resetPage);
102  clear.addEventListener('click', function () { input.value = ''; resetPage(); input.focus(); });
103  root.querySelector('[data-journal-reset]').addEventListener('click', function () {
104    input.value = ''; category = ''; resetPage(); input.focus();
105  });
106  more.addEventListener('click', function () {
107    var firstNew = matching[limit];
108    limit += BATCH_SIZE;
109    render();
110    if (firstNew) firstNew.element.focus({ preventScroll: true });
111  });
112  render();
113})();
114
115(function () {
116  var form = document.querySelector('.blog-newsletter-form');
117  if (!form) return;
118
119  var PORTAL_ID = '4235311';
120  var FORM_IDS = {
121    en: '462da299-9a1f-4d61-a630-dcc3d474ec39',
122    es: '6f61fc1f-80a1-4927-ab70-5e84e79e70fc',
123    fr: '52323858-459b-4012-8472-841227a29632'
124  };
125  var SUCCESS_TEXT = { en: 'Thanks ✓', es: '¡Gracias! ✓', fr: 'Merci ✓' };
126  var lang = document.documentElement.lang || 'en';
127  var formId = FORM_IDS[lang] || FORM_IDS.en;
128
129  form.addEventListener('submit', function (e) {
130    e.preventDefault();
131    var input = form.querySelector('input[type="email"]');
132    var button = form.querySelector('button');
133    var email = input ? input.value.trim() : '';
134    if (!email) return;
135
136    fetch('https://api.hsforms.com/submissions/v3/integration/submit/' 
136+ PORTAL_ID + '/' + formId, {
137      method: 'POST',
138      headers: { 'Content-Type': 'application/json' },
139      body: JSON.stringify({
140        fields: [{ objectTypeId: '0-1', name: 'email', value: email }],
141        context: { pageUri: window.location.href, pageName: document.title }
142      })
143    }).then(function () {
144      if (input) input.value = '';
145      if (button) button.textContent = SUCCESS_TEXT[lang] || SUCCESS_TEXT.en;
146    }).catch(function () {
147      if (button) button.textContent = SUCCESS_TEXT[lang] || SUCCESS_TEXT.en;
148    });
149  });
150})();

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.