PageSourceSearch

https://www2.lehigh.edu/themes/custom/lehigh/js/components/scenes-media-accessibility.js?v=11.4.7

js lehigh.edu collected 2026-09-24 08:28:49 UTC 4,908 bytes, 149 lines download raw bytes

1(function ($, Drupal) {
2  'use strict';
3
4  function findScenesSubwrapper(wrapper) {
5    // Try direct siblings first.
6    var el = wrapper.nextElementSibling;
7    while (el && !el.classList?.contains('scenes-media-caption-subwrapper')) {
8      el = el.nextElementSibling;
9    }
10    if (el) return el;
11
12    // Fallback: search within the same parent column.
13    var parentCol = wrapper.closest('.scenes-media-col');
14    if (!parentCol) return null;
15
16    var allSubs = parentCol.querySelectorAll('.scenes-media-caption-subwrapper');
17    if (allSubs.length === 1) return allSubs[0];
18
19    // Last fallback: find first subwrapper after wrapper within parent.
20    var foundWrapper = false;
21    for (var i = 0; i < parentCol.children.length; i++) {
22      var child = parentCol.children[i];
23      if (child === wrapper) {
24        foundWrapper = true;
25        continue;
26      }
27      if (foundWrapper && child.classList && child.classList.contains('scenes-media-caption-subwrapper')) {
28        return child;
29      }
30    }
31    return null;
32  }
33
34  function initializeScenesCaptionWrappers(context) {
35    var wrappers = (context || document).querySelectorAll('.scenes-media-caption-wrapper');
36
37    wrappers.forEach(function (wrapper) {
38      if (wrapper.dataset.scenesInit === 'true') return;
39      wrapper.dataset.scenesInit = 'true';
40
41      var subwrapper = findScenesSubwrapper(wrapper);
42      if (!subwrapper) return;
43
44      wrapper.setAttribute('tabindex', '0');
45      wrapper.setAttribute('role', 'button');
46      subwrapper.setAttribute('aria-hidden', 'true');
47
48      var heading = subwrapper.querySelector('.scenes-media-caption-heading');
49      var headingText = heading ? heading.textContent.trim() : '';
50
51      // Manage links inside subwrapper
52      var links = subwrapper.querySelectorAll('a');
53      function setLinksFocusable(enable) {
54        links.forEach(function (link) {
55          if (enable) {
56            link.removeAttribute('tabindex');
57          } else {
58            link.setAttribute('tabindex', '-1');
59          }
60        });
61      }
62      setLinksFocusable(false);
63
64      function updateAria() {
65        var isOpen = wrapper.classList.contains('clicked');
66        var state = isOpen ? 'Close' : 'Open';
67        wrapper.setAttribute('aria-label', `${headingText} ${state}`);
68        wrapper.setAttribute('aria-pressed', isOpen ? 'true' : 'false');
69        subwrapper.setAttribute('aria-hidden', isOpen ? 'false' : 'true');
70      }
71
72      function openWrapper() {
73        wrapper.classList.add('clicked');
74        subwrapper.classList.add('visible');
75        setLinksFocusable(true);
76        updateAria();
77      }
78
79      function closeWrapper() {
80        wrapper.classList.remove('clicked');
81        subwrapper.classList.remove('visible');
82        setLinksFocusable(false);
83        updateAria();
84      }
85
86      function toggleWrapper() {
87        if (wrapper.classList.contains('clicked')) {
88          closeWrapper();
89        } else {
90          openWrapper();
91        }
92      }
93
94      updateAria();
95
96      // Click behavior
97      wrapper.addEventListener('click', function (e) {
98        if (e.target.closest('.scenes-media-caption-subwrapper a')) return;
99        toggleWrapper();
100      });
101
102      // Keyboard behavior
103      wrapper.addEventListener('keydown', function (event) {
104        if (document.activeElement !== wrapper) return;
105        var key = event.key;
106        if (key === 'Enter' || key === ' ') {
107          event.preventDefault();
108          toggleWrapper();
109        } else if (key === 'Escape') {
110          if (wrapper.classList.contains('clicked')) {
111            event.preventDefault();
112            closeWrapper();
113            wrapper.focus();
114          }
115        }
116      });
117
118      // Hover behavior (wrapper + subwrapper)
119      wrapper.addEventListener('mouseenter', openWrapper);
120      wrapper.addEventListener('mouseleave', closeWrapper);
121      subwrapper.addEventListener('mouseenter', openWrapper);
122      subwrapper.addEventListener('mouseleave', closeWrapper);
123
124      if (heading) heading.removeAttribute('tabindex');
125
126      var text = subwrapper.querySelector('.scenes-media-caption-text');
127      if (text) {
128        text.removeAttribute('tabindex');
129        links.forEach(function (link) {
130          link.addEventListener('click', function (e) { e.stopPropagation(); });
131          link.addEventListener('keydown', function (e) {
132            if (e.key === 'Enter' || e.key === ' ') e.stopPropagation();
133          });
134        });
135      }
136    });
137  }
138
139  $(document).ready(function () {
140    initializeScenesCaptionWrappers();
141  });
142
143  var originalInsertCommand = Drupal.AjaxCommands.prototype.insert;
144  Drupal.AjaxCommands.prototype.insert = function (ajax, response, status) {
145    originalInsertCommand.apply(this, arguments);
146    var scope = ajax.wrapper ? document.querySelector(ajax.wrapper) : document;
147    initializeScenesCaptionWrappers(scope);
148  };
149})(jQuery, Drupal);

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.