PageSourceSearch

https://economiaitaliana.org/wp-content/plugins/frames-plugin/clas…/accordion/js/accordion.js?ver=1720765840

js economiaitaliana.org collected 2026-10-01 15:58:31 UTC 14,806 bytes, 533 lines download raw bytes

1
2function accordion_script(wpgbAccordion = null) {
3
4	const accordionInstances = new WeakMap();
5
6	class Accordion {
7		constructor(element, options) {
8			this.element = element;
9			this.options = options;
10
11			// new order
12			if (!this.validateStructure()) {
13				return;
14			}
15
16			this.removePlaceholder()
17			// end new order
18
19			this.removePlaceholderChild();
20			this.accordionItems = this.element.querySelectorAll(':scope > .fr-accordion__item')
21			this.lastOpenedItem = null;
22			this.init();
23			accordionInstances.set(this.element, this);
24		}
25
26		init() {
27        	this.setEventListeners();
28			this.handleFirstItemOpened();
29			this.handleAllItemsExpanded();
30			this.handleExpandedClass();
31			this.handleScrollToHash();
32			this.handleShowDuration();
33			this.addTabindex();
34			this.addIdToBody();
35			this.addAriaControls();
36			this.addIdToHeader();
37			this.addAriaLabelledBy();
38			this.addFaqSchema();
39			this.addRoleButton();
40
41			this.ITEMS(item => {
42				if (this.HEADER(item).getAttribute('aria-expanded') !== 'true') {
43					this.updateFocusableTabIndex(item, false);
44				}
45			});
46
47			this.ITEMS(item => {
48				if (this.hasCurrentPageLink(item) ) {
49					this.expandItem(item);
50				}
51			});
52
53		}
54
55		BODY(item) {
56			//return item.querySelector('.fr-accordion__body') || item.children[1];
57			const body = item.querySelector('.fr-accordion__body');
58			if (!body && item.children.length > 1 && item.children[1].tagName !== 'STYLE') {
59					return item.children[1];
60			}
61			return body;
62		}
63
64		HEADER(item) {
65			//return item.querySelector('.fr-accordion__header') || item.children[0];
66			const header = item.querySelector('.fr-accordion__header');
67			if (!header && item.children.length > 0 && item.children[0].tagName !== 'STYLE') {
68					return item.children[0];
69			}
70			return header;
71		}
72
73		ITEMS(init) {
74			this.accordionItems.forEach(item => {
75				if (item.tagName !== 'STYLE' &&
76					!item.classList.contains('brx-nestable-children-placeholder') &&
77					!(item.tagName === 'DIV' && item.classList.contains('brx-query-trail'))) {
78					init(item);
79				}
80			})
81		}
82
83
84		removePlaceholder() {
85			const placeholder = this.element.querySelector('.brx-nestable-children-placeholder');
86			const accordionChildren = this.element.querySelectorAll('.fr-accordion__item');
87
88			if (placeholder) {
89				placeholder.remove();
90			}
91
92			// If there are no children of accordion, add the placeholder back
93			if (accordionChildren.length === 0) {
94				const newPlaceholder = document.createElement('li');
95				newPlaceholder.className = 'brx-nestable-children-placeholder fr-accordion__item';
96				this.element.appendChild(newPlaceholder);
97			}
98		}
99
100
101		setEventListeners() {
102			this.ITEMS((item) => this.attachHeaderListeners(item));
103		}
104
105		attachHeaderListeners(item) {
106			const header = this.HEADER(item);
107			header.addEventListener('click', () => {
108				this.headerInteraction(item);
109			});
110			header.addEventListener('keydown', (e) => {
111				if (e.key === 'Enter') {
112					this.headerInteraction(item);
113				}
114			});
115			header.addEventListener('keyup', (e) => {
116				if (e.key === ' ') {
117					this.headerInteraction(item);
118				}
119			});
120		}
121
122		headerInteraction(item) {
123			if (window.innerWidth <= this.options.scrollToHeadingOn) {
124        		this.scrollToItemHeader(item);
125    		}
126
127			if (this.options.closePreviousItem && this.options.allItemsExpanded) {
128				this.ITEMS((otherItem) => {
129					if (otherItem !== item) {
130						this.collapseItem(otherItem);
131					}
132				});
133			} else if (this.options.closePreviousItem && this.lastOpenedItem && this.lastOpenedItem !== item) {
134				this.collapseItem(this.lastOpenedItem);
135			}
136			this.toggleItem(item);
137			this.lastOpenedItem = this.HEADER(item).getAttribute('aria-expanded') === 'true' ? item : null;
138
139
140		}
141
142		scrollToItemHeader(item) {
143
144			if (!this.options.scrollToHeading) return
145
146			setTimeout(() => {
147			this.HEADER(item).scrollIntoView({
148				behavior: 'smooth',
149					block: 'start',
150					inline: 'nearest'
151				});
152			}, this.options.showDuration);
153
154		}
155
156
157
158		toggleItem(item) {
159			if (this.HEADER(item).getAttribute('aria-expanded') === 'true') {
160				this.collapseItem(item);
161			} else {
162				this.expandItem(item);
163			}
164		}
165
166		collapseItem(item) {
167			const body = this.BODY(item);
168			body.style.height = body.offsetHeight + 'px';
169			setTimeout(() => {
170				body.style.height = 0;
171			}, 0);
172			this.HEADER(item).setAttribute('aria-expanded', 'false');
173			// Dispatch the 'accordionItemCollapsed' event
174			const collapseEvent = new CustomEvent('accordionItemCollapsed', { detail: { item: item } });
175			this.element.dispatchEvent(collapseEvent);
176			this.flipIcon(item);
177			this.updateFocusableTabIndex(item, false);
178		}
179
180		expandItem(item) {
181			const body = this.BODY(item);
182			body.style.height = body.scrollHeight + 'px';
183			this.HEADER(item).setAttribute('aria-expanded', 'true');
184			// Dispatch the 'accordionItemExpanded' event
185			const expandEvent = new CustomEvent('accordionItemExpanded', { detail: { item: item } });
186			this.element.dispatchEvent(expandEvent);
187			this.flipIcon(item);
188			this.updateFocusableTabIndex(item, true);
189		}
190
191		// fr-accordion__icon flip icon on expand and collapse
192		flipIcon(item) {
193			const icon = this.HEADER(item).querySelector('.fr-accordion__icon');
194			if (icon) {
195				// add transition property with time of showDuration
196				icon.style.transition = `transform ${this.options.showDuration}ms ease-in-out`;
197				icon.classList.toggle('fr-accordion__icon--flipped');
198			}
199		}
200
201
202		handleFirstItemOpened() {
203			if (!this.options.firstItemOpened) return
204			this.expandItem(this.accordionItems[0]);
205			this.lastOpenedItem = this.accordionItems[0];
206		}
207
208		handleAllItemsExpanded() {
209			if (!this.options.allItemsExpanded) return
210			this.ITEMS((item) => this.expandItem(item));
211		}
212
213		handleExpandedClass() {
214			if (!this.options.expandedClass) return
215			this.ITEMS((item) => {
216				if (item.classList.contains('fr-accordion__item--expanded')) {
217					this.expandItem(item);
218				}
219			});
220		}
221
222		handleScrollToHash() {
223			if (!this.options.scrollToHash) return
224			const hash = window.location.hash;
225			if (hash) {
226				const item = this.element.querySelector(hash);
227				if (item) {
228					this.scrollToItemAndExpand(item);
229				}
230			} else {
231				this.ITEMS((item) => {
232					const id = item.id;
233					if (id) {
234						const links = document.querySelectorAll(`a[href="#${id}"]`);
235						links.forEach((link) => {
236							link.addEventListener('click', (e) => {
237								this.scrollToItemAndExpand(item);
238							});
239						});
240					}
241				});
242			}
243		}
244
245		scrollToItemAndExpand(item) {
246			this.expandItem(item);
247			const header = this.HEADER(item);
248			const headerOffset = header.offsetTop;
249			const headerHeight = header.offsetHeight;
250			const offsetPosition = headerOffset - headerHeight - this.options.scrollToHashOffset;
251			window.scrollTo({
252				top: offsetPosition,
253				behavior: 'smooth'
254			});
255		}
256
257
258
259
260
261		handleShowDuration() {
262			if (!this.options.showDuration) return
263			this.ITEMS((item) => {
264				this.BODY(item).style.transitionDuration = this.options.showDuration + 'ms';
265				// for header transition
266				this.HEADER(item).style.transitionDuration = this.options.showDuration + 'ms';
267				// for __title in header
268				this.HEADER(item).querySelector('.fr-accordion__title').style.transitionDuration = this.options.showDuration + 'ms';
269			});
270		}
271
272		addTabindex() {
273			this.ITEMS((item) => {
274				this.HEADER(item).setAttribute('tabindex', 0);
275			});
276		}
277
278		addIdToBody() {
279			this.ITEMS((item) => {
280				if (!this.BODY(item).id) {
281					this.BODY(item).id = 'fr-accordion__body-' + Math.random().toString(36).substr(2, 9);
282				}
283			});
284		}
285
286		addIdToHeader() {
287			this.ITEMS((item) => {
288				if (!this.HEADER(item).id) {
289					this.HEADER(item).id = 'fr-accordion__header-' + Math.random().toString(36).substr(2, 9);
290				}
291			});
292		}
293
294		addAriaControls() {
295			this.ITEMS((item) => {
296				this.HEADER(item).setAttribute('aria-controls', this.BODY(item).id);
297			});
298		}
299
300
301		addAriaLabelledBy() {
302			this.ITEMS((item) => {
303				this.BODY(item).setAttribute('aria-labelledby', this.HEADER(item).id);
304			});
305		}
306
307		addRoleRegion() {
308			this.ITEMS((item) => {
309				this.BODY(item).setAttribute('role', 'region');
310			});
311		}
312
313		addRoleButton() {
314			this.ITEMS((item) => {
315				this.HEADER(item).setAttribute('role', 'button');
316			});
317		}
318
319		addFaqSchema() {
320			if (this.options.faqSchema) {
321
322				const faqData = [];
323
324				this.ITEMS((item) => {
325					const question = this.HEADER(item).textContent.trim();
326					const answer = this.BODY(item).textContent.trim();
327
328					faqData.push({
329						"@type": "Question",
330						"name": question,
331						"acceptedAnswer": {
332							"@type": "Answer",
333							"text": answer,
334						},
335					});
336				});
337
338				const faqSchema = {
339					"@context": "https://schema.org",
340					"@type": "FAQPage",
341					"mainEntity": faqData,
342				};
343
344				const script = document.createElement('script');
345				script.type = 'application/ld+json';
346				script.innerHTML = JSON.stringify(faqSchema);
347				document.head.appendChild(script);
348			}
349		}
350
351
352		validateStructure() {
353			if (this.element.children.length === 0) {
354				console.warn('The fr-accordion has no children.', this.element);
355				return false;
356			}
357
358			// Validation
359			const validChildren = {
360				'UL': (child) => child.tagName === 'LI' || child.tagName === 'STYLE' || (child.tagName === 'DIV' && child.classList.contains('brx-query-trail')),
361				'OL': (child) => child.tagName === 'LI' || child.tagName === 'STYLE' || (child.tagName === 'DIV' && child.classList.contains('brx-query-trail'))
362			}
363
364			for (const child of this.element.children) {
365
366				if (child.tagName === 'STYLE') {
367					console.log('found a STYLE, continuing', child)
368					continue
369				}
370
371				if (!child.classList.contains('fr-accordion__item')) {
372					child.classList.add('fr-accordion__item');
373				}
374
375				const body = child.querySelector('.fr-accordion__body')
376				const header = child.querySelector('.fr-accordion__header')
377				if (!header || !body) {
378					console.warn('Accordion items do not have a Header or a Body element', child)
379					return false
380				}
381
382				if (child.children.length > 2) {
383					console.warn('Remove extra children elements from accordion item:', child);
384					return false;
385				}
386
387				if (child.children.length < 2 && child.children.length > 0) {
388					console.warn('Add a header and a body to accordion item:', child);
389					return false;
390				}
391
392				// if element tag is ul or or and direct children are not li elements
393				// add warning "add li elements to ul or ol"
394				if (this.element.tagName === 'UL' || this.element.tagName === 'OL') {
395					if (!validChildren[this.element.tagName](child)) {
396						console.warn(`Direct child of the "ul" or "ol" element should have a tag of "li" instead of "${child.tagName}"`, child);
397					}
398				}
399
400			}
401			return true;
402		}
403
404		removePlaceholderChild() {
405			if (this.element.querySelectorAll('.brx-nestable-children-placeholder')) {
406				this.element.querySelectorAll('.brx-nestable-children-placeholder').forEach(el => {
407					el.remove();
408				});
409			}
410		}
411
412		updateFocusableTabIndex(item, isOpened) {
413			const focusableSelectors = 'a[href], button, textarea, input[type="text"], input[type="radio"], input[type="checkbox"], select';
414			const focusables = item.querySelectorAll(focusableSelectors);
415			focusables.forEach(el => {
416				el.setAttribute('tabindex', isOpened ? '0' : '-1');
417			});
418		}
419
420		hasCurrentPageLink(item) {
421			return this.BODY(item).querySelector('a[aria-current="page"]');
422		}
423
424
425		// end of class Accordion
426	}
427
428	function framesGetAccordionInstance(element) {
429		return accordionInstances.get(element);
430	}
431
432	window.getAccordionInstance = framesGetAccordionInstance;
433
434	// * Differentiate between a normal accordion and a wpgb accordion so we can call the appropriate one to re-init
435	// const accordions = document.querySelectorAll('.fr-accordion');
436	// accordions.forEach(accordion => {
437
438	// 	if (!accordion.dataset.frAccordionOptions) {
439	// 		console.warn('Options not provided for the following fr-accordion element:', accordion);
440	// 		return;
441	// 	}
442
443	// 	const options = JSON.parse(accordion.dataset.frAccordionOptions);
444	// 	new Accordion(accordion, options);
445	// });
446	if (wpgbAccordion) {
447		if (!wpgbAccordion.dataset.frAccordionOptions) {
448			console.warn('Options not provided for the following fr-accordion element:', wpgbAccordion);
449			return;
450		}
451
452		const options = JSON.parse(wpgbAccordion.dataset.frAccordionOptions);
453		new Accordion(wpgbAccordion, options);
454	} else {
455		const accordions = document.querySelectorAll('.fr-accordion');
456		accordions.forEach(accordion => {
457			if (!accordion.dataset.frAccordionOptions) {
458				console.warn('Options not provided for the following fr-accordion element:', accordion);
459				return;
460			}
461
462			const options = JSON.parse(accordion.dataset.frAccordionOptions);
463			new Accordion(accordion, options);
464		});
465	}
466
467
468
469	function accordion_script_builder() {
470
471		if (!document.querySelector('.brx-body.iframe.mounted')) return;
472
473		const accordions = document.querySelectorAll('.fr-accordion');
474		accordions.forEach(accordion => {
475			const items = Array.from(accordion.children);
476			items.forEach(item => {
477				const header = item.children[0];
478				const body = item.children[1];
479				// toggle height auto on body on header click
480				header.addEventListener('click', () => {
481					body.style.height = body.style.height === 'auto' ? '0px' : 'auto';
482					// toggle aria-expanded on header
483					header.setAttribute('aria-expanded', header.getAttribute('aria-expanded') === 'true' ? 'false' : 'true');
484				});
485			});
486		});
487	}
488
489	accordion_script_builder()
490
491}
492
493
494function wpgb_accordion_script() {
495	window.WP_Grid_Builder && WP_Grid_Builder.on('init', function (wpgb) {
496
497		console.dir(wpgb); // Holds all instances.
498		console.log('console logging WPGB:', wpgb)
499
500		wpgb.facets.on('appended', function (nodes) {
501
502			// We create a set to store Unique wpgb Accordions
503			// if wpgbAccordion then we add to the Set the wpgbAccordions found
504			const wpgbAccordionsSet = new Set();
505            nodes.forEach(node => {
506                const wpgbAccordion = node.closest('.fr-accordion.wpgb-enabled');
507                if (wpgbAccordion) {
508                    wpgbAccordionsSet.add(wpgbAccordion);
509                }
510            });
511
512			// For each accordion on the set we init them on facets appended ( appended works when filtering / stopping filtering)
513            wpgbAccordionsSet.forEach(wpgbAccordion => {
514                const instance = window.getAccordionInstance(wpgbAccordion);
515                if (instance) {
516                    accordion_script(wpgbAccordion);
517                }
518            });
519
520		});
521
522	});
523}
524
525
526document.addEventListener("DOMContentLoaded", function (e) {
527	bricksIsFrontend && accordion_script()
528	bricksIsFrontend && wpgb_accordion_script()
529
530});
531
532
533// We listen every time a grid/template/content is initialized.

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.