PageSourceSearch

https://umbc.edu/wp-content/themes/umbc-theme-2.0/umbc-blocks/horizontal-tabs/script.js?ver=1790186982

js umbc.edu collected 2026-09-24 07:39:22 UTC 4,054 bytes, 133 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function () {
2  document.querySelectorAll('.umbc-horizontal-tabs').forEach(function (tabsBlock) {
3	const tabPanels = tabsBlock.querySelectorAll('.umbc-tab-panel');
4	const tabList = document.createElement('ul');
5	tabList.classList.add('umbc-tab-list');
6	tabList.setAttribute('role', 'tablist');
7	tabList.setAttribute('aria-label', 'Tabs');
8	tabsBlock.prepend(tabList);
9	
10	const isMobile = window.matchMedia('(max-width: 767px)').matches;
11	
12	const mobilePanelsMap = [];
13	
14	tabPanels.forEach(function (panel, index) {
15	  const titleEl = panel.querySelector('h3');
16	  const title = titleEl ? titleEl.textContent.trim() : `Tab ${index + 1}`;
17	  const tabId = `tab-${index}`;
18	  const panelId = `panel-${index}`;
19	  panel.id = panelId;
20	  
21	  const li = document.createElement('li');
22	  li.setAttribute('role', 'presentation');
23	  
24	  const button = document.createElement('button');
25	  button.classList.add('umbc-tab');
26	  button.setAttribute('role', 'tab');
27	  button.setAttribute('id', tabId);
28	  button.setAttribute('aria-controls', panelId);
29	  button.setAttribute('tabindex', index === 0 ? '0' : '-1');
30	  button.setAttribute('aria-selected', index === 0 ? 'true' : 'false');
31	  button.innerText = title;
32	  
33	  if (index === 0) {
34		button.classList.add('active');
35		panel.classList.add('active');
36		panel.removeAttribute('hidden');
37	  } else {
38		panel.setAttribute('hidden', '');
39	  }
40	  
41	  li.appendChild(button);
42	  tabList.appendChild(li);
43	  
44	  if (isMobile) {
45		const mobileWrapper = document.createElement('div');
46		mobileWrapper.classList.add('mobile-tab-panel');
47		mobileWrapper.hidden = index !== 0;
48		
49		// Move the actual content instead of copying HTML
50		while (panel.firstChild) {
51		  mobileWrapper.appendChild(panel.firstChild);
52		}
53		
54		li.appendChild(mobileWrapper);
55		mobilePanelsMap.push({ li, mobilePanel: mobileWrapper, button, originalPanel: panel });
56	  }
57	  
58	  button.addEventListener('click', function () {
59		const isActive = button.classList.contains('active');
60		
61		// Collapse on mobile if already active
62		if (isMobile && isActive) {
63		  button.classList.remove('active');
64		  button.setAttribute('aria-selected', 'false');
65		  button.setAttribute('tabindex', '-1');
66		  panel.classList.remove('active');
67		  panel.setAttribute('hidden', '');
68		  
69		  const activeMobilePanel = li.querySelector('.mobile-tab-panel');
70		  if (activeMobilePanel) activeMobilePanel.hidden = true;
71		  return;
72		}
73		
74		// Activate tab
75		tabList.querySelectorAll('.umbc-tab').forEach(btn => {
76		  btn.classList.remove('active');
77		  btn.setAttribute('aria-selected', 'false');
78		  btn.setAttribute('tabindex', '-1');
79		});
80		
81		tabPanels.forEach(p => {
82		  p.classList.remove('active');
83		  p.setAttribute('hidden', '');
84		});
85		
86		if (isMobile) {
87		  mobilePanelsMap.forEach(pair => pair.mobilePanel.hidden = true);
88		}
89		
90		button.classList.add('active');
91		button.setAttribute('aria-selected', 'true');
92		button.setAttribute('tabindex', '0');
93		panel.classList.add('active');
94		panel.removeAttribute('hidden');
95		
96		if (isMobile) {
97		  const activeMobilePanel = li.querySelector('.mobile-tab-panel');
98		  if (activeMobilePanel) {
99			activeMobilePanel.hidden = false;
100			
101			// Trigger chart reinitialization after making visible
102			setTimeout(() => {
103			  const charts = activeMobilePanel.querySelectorAll('canvas[data-chart-type]');
104			  charts.forEach(chart => {
105				// Dispatch a custom event to trigger chart re-render
106				chart.dispatchEvent(new Event('chartVisible'));
107				
108				// Or if you're using Chart.js, you might need to call resize
109				if (chart.chart) {
110				  chart.chart.resize();
111				}
112			  });
113			}, 50);
114		  }
115		}
116		
117		button.focus();
118	  });
119	});
120	
121	if (isMobile) {
122	  const mainPanelsContainer = tabsBlock.querySelector('.umbc-tab-panels');
123	  if (mainPanelsContainer) {
124		mainPanelsContainer.style.display = 'none';
125	  }
126	  
127	  mobilePanelsMap.forEach((pair, idx) => {
128		pair.mobilePanel.classList.remove('active');
129		pair.mobilePanel.hidden = idx !== 0;
130	  });
131	}
132  });
133});

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.