PageSourceSearch

https://theanalyst.com/wp-content/plugins/the-analyst-promo-bar/assets/view.js?ver=0.2.6

js theanalyst.com collected 2026-10-02 03:38:43 UTC 3,142 bytes, 91 lines download raw bytes

1(function () {
2  'use strict';
3
4  /**
5   * Promo bar front-end behavior: tracks two directional states —
6   * can-scroll-left (scrolled away from the start) and can-scroll-right
7   * (more content past the right edge). Each toggles a class on the bar
8   * that drives the matching edge fade + chevron (see promo-bar.scss).
9   * Re-evaluated on scroll and on resize (ResizeObserver).
10   */
11
12  const LEFT_CLASS = 'promo-bar--can-scroll-left';
13  const RIGHT_CLASS = 'promo-bar--can-scroll-right';
14  const EDGE_TOLERANCE = 1;
15  const FADE_OFFSET = 25;
16
17  function init(bar) {
18    const list = bar.querySelector('.promo-bar__list');
19    const prevBtn = bar.querySelector('.promo-bar__scroll--prev');
20    const nextBtn = bar.querySelector('.promo-bar__scroll--next');
21    if (!list || !prevBtn || !nextBtn) return;
22
23    function update() {
24      const canLeft = list.scrollLeft > EDGE_TOLERANCE;
25      const canRight =
26        list.scrollLeft + list.clientWidth < list.scrollWidth - EDGE_TOLERANCE;
27      bar.classList.toggle(LEFT_CLASS, canLeft);
28      bar.classList.toggle(RIGHT_CLASS, canRight);
29    }
30
31    function step(direction) {
32      // Advance by one item boundary. Targets the next/previous item
33      // relative to the list's left edge, so a click works even when a
34      // single item is wider than the viewport (mobile).
35      const items = list.querySelectorAll('.promo-bar__item');
36      if (!items.length) return;
37      const listRect = list.getBoundingClientRect();
38      let target = null;
39      if (direction > 0) {
40        // First item past the landing zone — anything already at or before
41        // the landing zone is "already shown clear of the fade."
42        for (const item of items) {
43          if (item.getBoundingClientRect().left - listRect.left > FADE_OFFSET + EDGE_TOLERANCE) {
44            target = item;
45            break;
46          }
47        }
48      } else {
49        // Last item that hasn't reached the landing zone yet.
50        for (let i = items.length - 1; i >= 0; i--) {
51          if (items[i].getBoundingClientRect().left - listRect.left < FADE_OFFSET - EDGE_TOLERANCE) {
52            target = items[i];
53            break;
54          }
55        }
56      }
57      if (!target) return;
58      const left =
59        list.scrollLeft +
60        (target.getBoundingClientRect().left - listRect.left) -
61        FADE_OFFSET;
62      const reduce =
63        window.matchMedia &&
64        window.matchMedia('(prefers-reduced-motion: reduce)').matches;
65      list.scrollTo({ left, behavior: reduce ? 'auto' : 'smooth' });
66    }
67
68    prevBtn.addEventListener('click', () => step(-1));
69    nextBtn.addEventListener('click', () => step(1));
70
71    list.addEventListener('scroll', update, { passive: true });
72
73    if (typeof window.ResizeObserver !== 'undefined') {
74      new window.ResizeObserver(update).observe(list);
75    } else {
76      window.addEventListener('resize', update);
77    }
78
79    update();
80  }
81
82  function setup() {
83    document.querySelectorAll('.promo-bar').forEach(init);
84  }
85
86  if (document.readyState === 'loading') {
87    document.addEventListener('DOMContentLoaded', setup);
88  } else {
89    setup();
90  }
91})();

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.