1/** 2 * FAQ accordion â click question to show/hide answer (editor + live pages). 3 * Uses document-level delegation so ContentBox / new sections do not break handlers. 4 */ 5(function (global) { 6 'use strict'; 7 8 /* Footer + page templates may both include this file â only bind handlers once. */ 9 if (global.__bwFaqAccordionBooted) { 10 return; 11 } 12 global.__bwFaqAccordionBooted = true; 13 14 var preparedLists = typeof WeakSet !== 'undefined' ? new WeakSet() : null; 15 16 function isEditorMode() { 17 if (global.BW_IS_CONTENTBOX_EDITOR || global.BW_IS_AIBOX_EDITOR) { 18 return true; 19 } 20 if (global.BwIsContentboxEditor) { 21 return global.BwIsContentboxEditor(); 22 } 23 if (global.BwContentboxClickfix && typeof global.BwContentboxClickfix.isEditorMode === 'function') { 24 return global.BwContentboxClickfix.isEditorMode(); 25 } 26 if (document.body && document.body.classList.contains('bw-page-editor')) { 27 return true; 28 } 29 return false; 30 } 31 32 function findAnswer(li) { 33 for (var i = 0; i < li.children.length; i++) { 34 var ch = li.children[i]; 35 if (ch.nodeType !== 1) { 36 continue; 37 } 38 if ( 39 ch.classList.contains('answer') || 40 ch.classList.contains('bw-faq-answer') || 41 ch.classList.contains('faq-answer') 42 ) { 43 return ch; 44 } 45 } 46 return null; 47 } 48 49 function findQuestion(li) { 50 for (var i = 0; i < li.children.length; i++) { 51 var ch = li.children[i]; 52 if (ch.nodeType !== 1) { 53 continue; 54 } 55 var tag = ch.tagName; 56 if (tag === 'H3' || tag === 'H4' || ch.classList.contains('faq-question')) { 57 return ch; 58 } 59 } 60 return null; 61 } 62 63 function closeAllInList(ul) { 64 ul.querySelectorAll(':scope > li').forEach(function (li) { 65 var answer = findAnswer(li); 66 var question = findQuestion(li); 67 if (answer) { 68 answer.style.removeProperty('display'); 69 } 70 if (question) { 71 question.classList.remove('bw-faq-open'); 72 question.setAttribute('aria-expanded', 'false'); 73 } 74 li.classList.remove('active'); 75 }); 76 } 77 78 function prepareAccordionList(ul) { 79 if (!ul) { 80 return; 81 } 82 var editor = isEditorMode(); 83 if (!editor && preparedLists && preparedLists.has(ul)) { 84 return; 85 } 86 if (preparedLists) { 87 preparedLists.add(ul); 88 } 89 ul.removeAttribute('data-bw-faq-prepared'); 90 91 ul.querySelectorAll(':scope > li').forEach(function (li) { 92 var question = findQuestion(li); 93 var answer = findAnswer(li); 94 if (!question || !answer) { 95 return; 96 } 97 li.classList.remove('active'); 98 question.classList.remove('bw-faq-open'); 99 question.setAttribute('aria-expanded', 'false'); 100 answer.style.removeProperty('display'); 101 question.style.cursor = 'pointer'; 102 question.setAttribute('role', 'button'); 103 if (!question.hasAttribute('tabindex')) { 104 question.setAttribute('tabindex', '0'); 105 } 106 }); 107 } 108 109 function toggleAccordionItem(li) { 110 var ul = li.parentElement; 111 if (!ul || !ul.classList.contains('accordion-list')) { 112 return; 113 } 114 var answer = findAnswer(li); 115 var question = findQuestion(li); 116 if (!answer || !question) { 117 return; 118 } 119 var isOpen = li.classList.contains('active'); 120 if (isOpen) { 121 li.classList.remove('active'); 122 question.classList.remove('bw-faq-open'); 123 question.setAttribute('aria-expanded', 'false'); 124 } else { 125 li.classList.add('active'); 126 question.classList.add('bw-faq-open'); 127 question.setAttribute('aria-expanded', 'true'); 128 } 129 } 130 131 var delegatedDocs = typeof WeakSet !== 'undefined' ? new WeakSet() : null; 132 var delegatedBoundLegacy = false;
133 134 function bindDelegation(doc) { 135 doc = doc || document; 136 if (delegatedDocs) { 137 if (delegatedDocs.has(doc)) { 138 return; 139 } 140 delegatedDocs.add(doc); 141 } else if (doc === document) { 142 if (delegatedBoundLegacy) { 143 return; 144 } 145 delegatedBoundLegacy = true; 146 } 147 148 doc.addEventListener('click', function (e) { 149 if (isEditorMode()) { 150 return; 151 } 152 if (e.target.closest('a, button, input, select, textarea, label')) { 153 return; 154 } 155 var li = e.target.closest('ul.accordion-list > li'); 156 if (!li) { 157 return; 158 } 159 var ul = li.closest('ul.accordion-list'); 160 if (!ul || !findQuestion(li) || !findAnswer(li)) { 161 return; 162 } 163 e.preventDefault(); 164 e.stopPropagation(); 165 toggleAccordionItem(li); 166 }, true); 167 168 doc.addEventListener('keydown', function (e) { 169 if (isEditorMode()) { 170 return; 171 } 172 if (e.key !== 'Enter' && e.key !== ' ') { 173 return; 174 } 175 var question = e.target.closest('ul.accordion-list > li > h3, ul.accordion-list > li > h4, ul.accordion-list > li > .faq-question'); 176 if (!question) { 177 return; 178 } 179 e.preventDefault(); 180 var li = question.parentElement; 181 if (li) { 182 toggleAccordionItem(li); 183 } 184 }, true); 185 } 186 187 function bindStaticFaqItems(root) { 188 var doc = (root && root.nodeType === 9) ? root : ((root && root.ownerDocument) || document); 189 root.querySelectorAll('.faq-item').forEach(function (item) { 190 if (item.closest('ul.accordion-list') || item.getAttribute('data-bw-faq-bound') === '1') { 191 return; 192 } 193 var h = item.querySelector('h3, h4, .faq-question'); 194 if (!h) { 195 return; 196 } 197 var bodyNodes = []; 198 Array.prototype.forEach.call(item.childNodes, function (ch) { 199 if (ch.nodeType !== 1) { 200 return; 201 } 202 if (ch === h || ch.tagName === 'H3' || ch.tagName === 'H4' || ch.classList.contains('faq-question')) { 203 return; 204 } 205 bodyNodes.push(ch); 206 }); 207 if (bodyNodes.length === 0) { 208 return; 209 } 210 item.setAttribute('data-bw-faq-bound', '1'); 211 var wrap = doc.createElement('div'); 212 wrap.className = 'answer'; 213 bodyNodes.forEach(function (n) { 214 wrap.appendChild(n); 215 }); 216 item.appendChild(wrap); 217 item.classList.remove('active'); 218 h.style.cursor = 'pointer'; 219 h.addEventListener('click', function (ev) { 220 if (isEditorMode()) { 221 return; 222 } 223 ev.preventDefault(); 224 ev.stopPropagation(); 225 var open = item.classList.contains('active'); 226 root.querySelectorAll('.faq-item').forEach(function (x) { 227 x.classList.remove('active'); 228 }); 229 root.querySelectorAll('.faq-item h3, .faq-item h4, .faq-item .faq-question').forEach(function (q) { 230 q.classList.remove('bw-faq-open'); 231 }); 232 if (!open) { 233 item.classList.add('active'); 234 h.classList.add('bw-faq-open'); 235 } 236 }); 237 }); 238 } 239 240 function prepareDetailsFaqs(root) { 241 root.querySelectorAll('details.bw-faq-item[open]').forEach(function (el) { 242 if (!isEditorMode()) { 243 el.removeAttribute('open'); 244 } 245 }); 246 } 247 248 function init(root) { 249 root = root || document; 250 var doc = (root.nodeType === 9) ? root : (root.ownerDocument || document); 251 var scope = (root.nodeType === 9) ? (root.body || root) : root; 252 bindDelegation(doc); 253 scope.querySelectorAll('ul.accordion-list').forEach(prepareAccordionList); 254 bindStaticFaqItems(scope); 255 prepareDetailsFaqs(scope); 256 } 257 258 function watch() { 259 init(document); 260 if (typeof MutationObserver === 'undefined') { 261 return; 262 } 263 var obs = new MutationObserver(function () { 264 init(document); 265 }); 266 var target = document.querySelector('.is-wrapper') || document.body; 267 if (target) { 268 obs.observe(target, { childList: true, subtree: true }); 269 } 270 } 271 272 global.BwFaqAccordion = { init: init, watch: watch }; 273 274 function boot() { 275 watch(); 276 window.addEventListener('load', function () { 277 init(document); 278 }); 279 } 280 281 if (document.readyState === 'loading') { 282 document.addEventListener('DOMContentLoaded', boot); 283 } else { 284 boot(); 285 } 286})(typeof window !== 'undefined' ? window : this);
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.