PageSourceSearch

https://www.aragon.es/o/aragon-theme/js/aria/accordion.js

js aragon.es collected 2026-09-24 08:28:12 UTC 11,105 bytes, 264 lines download raw bytes

1export function accordion(aria) {
2  /*
3  *   This content is licensed according to the W3C Software License at
4  *   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
5  *
6  *   Simple accordion pattern example
7  */
8
9  'use strict';
10
11  Array.prototype.slice.call(document.querySelectorAll('.c-accordion')).forEach(function (accordion) {
12
13    // Allow for multiple accordion sections to be expanded at the same time
14    var allowMultiple = accordion.hasAttribute('data-allow-multiple');
15    // Allow for each toggle to both open and close individually
16    var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');
17
18    // Create the array of toggle elements for the accordion group
19    var triggers = Array.prototype.slice.call(accordion.querySelectorAll('.c-accordion__trigger'));
20    var panels = Array.prototype.slice.call(accordion.querySelectorAll('.c-accordion__panel'));
21
22
23    accordion.addEventListener('click', function (event) {
24      var target = event.target;
25
26      if(target.classList.contains('c-accordion__toggle-all')) {
27        toggleAllAccordion(target)
28      }
29
30      if (target.classList.contains('c-accordion__trigger')) {
31        // Check if the current toggle is expanded.
32        var isExpanded = target.getAttribute('aria-expanded') == 'true';
33        var active = accordion.querySelector('[aria-expanded="true"]');
34
35        // without allowMultiple, close the open accordion
36        if (!allowMultiple && active && active !== target) {
37          // Set the expanded state on the triggering element
38          active.setAttribute('aria-expanded', 'false');
39          //active.querySelector('span').innerText = 'Mostrar';
40          active.querySelector('.c-accordion__show').classList.remove('hidden');
41          active.querySelector('.c-accordion__hide').classList.add('hidden');
42          // Hide the accordion sections, using aria-controls to specify the desired section
43          document.getElementById(active.getAttribute('aria-controls')).setAttribute('hidden', '');
44
45          // When toggling is not allowed, clean up disabled state
46          if (!allowToggle) {
47            active.removeAttribute('aria-disabled');
48          }
49        }
50
51        if (!isExpanded) {
52          // Set the expanded state on the triggering element
53          target.setAttribute('aria-expanded', 'true');
54          //target.querySelector('span').innerText = 'Ocultar';
55          target.querySelector('.c-accordion__show').classList.toggle('hidden');
56          target.querySelector('.c-accordion__hide').classList.toggle('hidden');
57          // Hide the accordion sections, using aria-controls to specify the desired section
58          document.getElementById(target.getAttribute('aria-controls')).removeAttribute('hidden');
59
60          // If toggling is not allowed, set disabled state on trigger
61          if (!allowToggle) {
62            target.setAttribute('aria-disabled', 'true');
63            target.querySelector('.c-accordion__show').classList.add('hidden');
64            target.querySelector('.c-accordion__hide').classList.add('hidden');
65          }
66        }
67        else if (allowToggle && isExpanded) {
68          // Set the expanded state on the triggering element
69          target.setAttribute('aria-expanded', 'false');
70          // target.querySelector('span').innerText = 'Mostrar';
71          target.querySelector('.c-accordion__show').classList.toggle('hidden');
72          target.querySelector('.c-accordion__hide').classList.toggle('hidden');
73
74          // Hide the accordion sections, using aria-controls to specify the desired section
75          document.getElementById(target.getAttribute('aria-controls')).setAttribute('hidden', '');
76        }
77
78        event.preventDefault();
79      }
80
81      if(accordion.querySelector('.c-accordion__toggle-all') && !target.classList.contains('c-accordion__toggle-all')) {
82        checkIfAllPanelAreOpenOrClosed()
83      }
84    });
85
86    // Bind keyboard behaviors on the main accordion container
87    accordion.addEventListener('keydown', function (event) {
88      var target = event.target;
89      var key = event.which.toString();
90
91      var isExpanded = target.getAttribute('aria-expanded') == 'true';
92      var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');
93
94      // 33 = Page Up, 34 = Page Down
95      var ctrlModifier = (event.ctrlKey && key.match(/33|34/));
96
97      // Is this coming from an accordion header?
98      if (target.classList.contains('c-accordion__trigger')) {
99        // Up/ Down arrow and Control + Page Up/ Page Down keyboard operations
100        // 38 = Up, 40 = Down
101        if (key.match(/38|40/) || ctrlModifier) {
102          var index = triggers.indexOf(target);
103          var direction = (key.match(/34|40/)) ? 1 : -1;
104          var length = triggers.length;
105          var newIndex = (index + length + direction) % length;
106
107          triggers[newIndex].focus();
108
109          event.preventDefault();
110        }
111        else if (key.match(/35|36/)) {
112          // 35 = End, 36 = Home keyboard operations
113          switch (key) {
114            // Go to first accordion
115            case '36':
116              triggers[0].focus();
117              break;
118              // Go to last accordion
119            case '35':
120              triggers[triggers.length - 1].focus();
121              break;
122          }
123          event.preventDefault();
124
125        }
126
127      }
128    });
129
130    // These are used to style the accordion when one of the buttons has focus
131    accordion.querySelectorAll('.c-accordion__trigger').forEach(function (trigger) {
132
133      trigger.addEventListener('focus', function (event) {
134        accordion.classList.add('focus');
135      });
136
137      trigger.addEventListener('blur', function (event) {
138        accordion.classList.remove('focus');
139      });
140
141    });
142
143    // Minor setup: will set disabled state, via aria-disabled, to an
144    // expanded/ active accordion which is not allowed to be toggled close
145    if (!allowToggle) {
146      // Get the first expanded/ active accordion
147      var expanded = accordion.querySelector('[aria-expanded="true"]');
148
149      // If an expanded/ active accordion is found, disable
150      if (expanded) {
151        expanded.setAttribute('aria-disabled', 'true');
152        expanded.querySelector('.c-accordion__show').classList.add('hidden');
153        expanded.querySelector('.c-accordion__hide').classList.add('hidden');
154      }
155    }
156
157    function toggleAllAccordion(target, show = null) {
158      const getAllElementsShow = target.parentElement.parentElement.querySelectorAll('.c-accordion__show')
159      const getAllElementsHide = target.parentElement.parentElement.querySelectorAll('.c-accordion__hide')
160      const getAllPanels = target.parentElement.parentElement.querySelectorAll('.c-accordion__panel')
161      const getAllTriggers = target.parentElement.parentElement.querySelectorAll('.c-accordion__trigger')
162      if(target.textContent.includes('Mostrar todo') || show === true) {
163        getAllElementsShow.forEach(element => {
164          element.classList.add('hidden')
165        })
166        getAllElementsHide.forEach(element => {
167          element.classList.remove('hidden')
168        })
169        getAllPanels.forEach(element => {
170          element.removeAttribute('hidden')
171        })
172        getAllTriggers.forEach(element => {
173          element.setAttribute('aria-expanded', 'true');
174        })
175        target.textContent = 'Ocultar todo'
176      } else {
177        getAllElementsShow.forEach(element => {
178          element.classList.remove('hidden')
179        })
180        getAllElementsHide.forEach(element => {
181          element.classList.add('hidden')
182        })
183        getAllPanels.forEach(element => {
184          element.setAttribute('hidden', "")
185        })
186        getAllTriggers.forEach(element => {
187          element.setAttribute('aria-expanded', 'false');
188        })
189        target.textContent = 'Mostrar todo'
190      }
191    }
192
193    function checkIfAllPanelAreOpenOrClosed() {
194      const getAccordionTrigger = accordion.querySelectorAll('.c-accordion__trigger');
195      let arrayAccordionTrigger = [...getAccordionTrigger].map(element => element.getAttribute('aria-expanded'));
196
197      if(arrayAccordionTrigger.every(element => element === 'true')) {
198        accordion.querySelector('.c-accordion__toggle-all').textContent = 'Ocultar todo';
199      }
200
201      if(arrayAccordionTrigger.every(element => element === 'false')) {
202        accordion.querySelector('.c-accordion__toggle-all').textContent = 'Mostrar todo';
203      }
204    }
205
206    window.activateItemAccordion = function (menuId, activeItemId) {
207      const menu = document.getElementById(menuId);
208      if (menu) {
209        const activeItem = document.querySelector(`#${menuId} #${activeItemId}`);
210        if (activeItem) {
211          activateElement(menuId, activeItemId);
212          return [menu, activeItem]
213        } else {
214          console.log('There is no item with this id in the menu.');
215          return null;
216        }
217      } else {
218        console.log('There is no accordion with this id in the document.');
219        return null;
220      }
221    };
222
223    window.activateAllAccordion = function (element, show) {
224      const button = document.getElementById(element);
225      if (button) {
226        toggleAllAccordion(button, show);
227        return [button, show]
228      } else {
229        console.log('There is no accordion with this id in the menu.');
230        return null;
231      }
232    };
233
234    function activateElement(menu, activeItem) {
235      const getAccordion = document.querySelector(`#${menu}`);
236      const allowMultiple = getAccordion.hasAttribute('data-allow-multiple');
237      const allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');
238      const selectAllTriggers = document.querySelectorAll(`#${menu} .c-accordion__trigger`);
239      [...selectAllTriggers].forEach((trigger) => {
240        const getPanel = trigger.parentElement.parentElement.querySelector('.c-accordion__panel');
241        const getShowMessage = trigger.querySelector('.c-accordion__show');
242        const getHideMessage = trigger.querySelector('.c-accordion__hide');
243        if (isActive(trigger)) {
244          trigger.setAttribute('aria-expanded', 'true');
245          getPanel.removeAttribute('hidden');
246          getShowMessage.classList.add('hidden');
247          getHideMessage.classList.remove('hidden');
248        } else {
249          trigger.setAttribute('aria-expanded', 'false');
250          getPanel.setAttribute('hidden', 'true');
251          getShowMessage.classList.remove('hidden');
252          getHideMessage.classList.add('hidden');
253        }
254      });
255
256      function isActive(element){
257        const { id } = element;
258        return typeof activeItem === "object" && allowToggle
259          ? activeItem.includes(id)
260          : id === activeItem;
261      }
262    }
263  });
264}

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.