PageSourceSearch

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

js aragon.es collected 2026-09-24 08:28:32 UTC 9,263 bytes, 335 lines download raw bytes

1export function Treeitem(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  *   File:   Treeitem.js
7  *
8  *   Desc:   Treeitem widget that implements ARIA Authoring Practices
9  *           for a tree being used as a file viewer
10  */
11
12  /*
13  *   @constructor
14  *
15  *   @desc
16  *       Treeitem object for representing the state and user interactions for a
17  *       treeItem widget
18  *
19  *   @param node
20  *       An element with the role=tree attribute
21  */
22
23  aria.Treeitem = function (node, treeObj, group) {
24
25    // Check whether node is a DOM element
26    if (typeof node !== 'object') {
27      return;
28    }
29
30 // node.tabIndex = -1
31    this.tree = treeObj;
32    this.groupTreeitem = group;
33    this.domNode = node;
34    this.label = node.textContent.trim();
35
36    if(this.domNode.getAttribute("aria-current")) {
37      var getLabel = this.domNode.querySelector('label')
38      getLabel.setAttribute("aria-current", "page")
39    }
40
41    if (node.getAttribute('aria-label')) {
42      this.label = node.getAttribute('aria-label').trim();
43    }
44
45    this.isExpandable = false;
46    this.isVisible = false;
47    this.inGroup = false;
48
49    if (group) {
50      this.inGroup = true;
51    }
52
53    var elem = node.firstElementChild;
54
55    while (elem) {
56
57      if (elem.tagName.toLowerCase() == 'ul') {
58        elem.setAttribute('role', 'group');
59        this.isExpandable = true;
60        break;
61      }
62
63      elem = elem.nextElementSibling;
64    }
65
66    this.keyCode = Object.freeze({
67      RETURN: 13,
68      SPACE: 32,
69      PAGEUP: 33,
70      PAGEDOWN: 34,
71      END: 35,
72      HOME: 36,
73      LEFT: 37,
74      UP: 38,
75      RIGHT: 39,
76      DOWN: 40
77    });
78  };
79
80  aria.Treeitem.prototype.init = function () {
81// this.domNode.tabIndex = -1;
82
83    if (!this.domNode.getAttribute('role')) {
84      this.domNode.setAttribute('role', 'treeitem');
85    }
86
87    if(!this.domNode.getAttribute('disabled')){
88      this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
89      this.domNode.addEventListener('click', this.handleClick.bind(this));
90      this.domNode.addEventListener('focus', this.handleFocus.bind(this));
91      this.domNode.addEventListener('blur', this.handleBlur.bind(this));
92    }
93
94    if (!this.isExpandable) {
95      this.domNode.addEventListener('mouseover', this.handleMouseOver.bind(this));
96      this.domNode.addEventListener('mouseout', this.handleMouseOut.bind(this));
97    }
98
99    const getCheckboxes = document.querySelectorAll('.c-checkboxes__indeterminate-active');
100    Array.from(getCheckboxes).forEach((checkbox) => {
101      checkbox.readOnly = true
102      checkbox.indeterminate = true
103    });
104  };
105
106  aria.Treeitem.prototype.isExpanded = function () {
107
108    if (this.isExpandable) {
109      return this.domNode.getAttribute('aria-expanded') === 'true';
110    }
111
112    return false;
113
114  };
115
116  /* EVENT HANDLERS */
117
118  aria.Treeitem.prototype.handleKeydown = function (event) {
119
120    const targetElement = event.currentTarget;
121    let flag = false;
122    let char = event.key;
123    const getCurrentCheckbox = targetElement.querySelector('input');
124    const getAllChildrenOfTree = targetElement.parentElement.querySelectorAll('input');
125
126    function isPrintableCharacter (str) {
127      return str.length === 1 && str.match(/\S/);
128    }
129
130    function printableCharacter (item) {
131      if (char == '*') {
132        item.tree.expandAllSiblingItems(item);
133        flag = true;
134      }
135      else {
136        if (isPrintableCharacter(char)) {
137          item.tree.setFocusByFirstCharacter(item, char);
138          flag = true;
139        }
140      }
141    }
142
143    if (event.altKey || event.ctrlKey || event.metaKey) {
144      return;
145    }
146
147    if (event.shift) {
148      if (isPrintableCharacter(char)) {
149        printableCharacter(this);
150      }
151    }
152    else {
153      switch (event.keyCode) {
154        case this.keyCode.SPACE:
155        case this.keyCode.RETURN:
156          const typeOfInput = getCurrentCheckbox.type
157          if(typeOfInput === 'radio') {
158            for (let item of getAllChildrenOfTree) {
159              item.checked = false
160            }
161          }
162          getCurrentCheckbox.checked = getCurrentCheckbox.checked === true ? false : true
163          flag = true;
164          break;
165
166        case this.keyCode.UP:
167          this.tree.setFocusToPreviousItem(this);
168          flag = true;
169          break;
170
171        case this.keyCode.DOWN:
172          this.tree.setFocusToNextItem(this);
173          flag = true;
174          break;
175
176        case this.keyCode.RIGHT:
177          if (this.isExpandable) {
178            if (this.isExpanded()) {
179              this.tree.setFocusToNextItem(this);
180            }
181            else {
182              this.tree.expandTreeitem(this);
183            }
184          }
185          flag = true;
186          break;
187
188        case this.keyCode.LEFT:
189          if (this.isExpandable && this.isExpanded()) {
190            this.tree.collapseTreeitem(this);
191            flag = true;
192          }
193          else {
194            if (this.inGroup) {
195              this.tree.setFocusToParentItem(this);
196              flag = true;
197            }
198          }
199          break;
200
201        case this.keyCode.HOME:
202          this.tree.setFocusToFirstItem();
203          flag = true;
204          break;
205
206        case this.keyCode.END:
207          this.tree.setFocusToLastItem();
208          flag = true;
209          break;
210
211        default:
212          if (isPrintableCharacter(char)) {
213            printableCharacter(this);
214          }
215          break;
216      }
217
218    }
219
220    if (flag) {
221      event.stopPropagation();
222      event.preventDefault();
223    }
224  };
225
226  aria.Treeitem.prototype.handleClick = function (event) {
227    if (this.isExpandable) {
228      if (this.isExpanded()) {
229        this.tree.collapseTreeitem(this);
230      }
231      else {
232        this.tree.expandTreeitem(this);
233      }
234      event.stopPropagation();
235    }
236    else {
237      this.tree.setFocusToItem(this);
238    }
239  };
240
241  aria.Treeitem.prototype.handleFocus = function (event) {
242    var node = this.domNode;
243    if (this.isExpandable) {
244      node = node.firstElementChild;
245    }
246    node.classList.add('c-tree__item--focus');
247  };
248
249  aria.Treeitem.prototype.handleBlur = function (event) {
250    var node = this.domNode;
251    if (this.isExpandable) {
252      node = node.firstElementChild;
253    }
254    node.classList.remove('c-tree__item--focus');
255  };
256
257  aria.Treeitem.prototype.handleMouseOver = function (event) {
258    event.currentTarget.classList.add('c-tree__item--hover');
259  };
260
261  aria.Treeitem.prototype.handleMouseOut = function (event) {
262    event.currentTarget.classList.remove('c-tree__item--hover');
263  };
264
265  window.activateItemsTree = function (elementId, itemsIds, open = null) {
266    const element = document.getElementById(elementId);
267    if (element) {
268      arrayOrSingleElement(elementId, itemsIds, open);
269      return [elementId, itemsIds, open];
270    } else {
271      returnMessage()
272    }
273  };
274
275  function arrayOrSingleElement(elementId, itemsIds, open) {
276    if(typeof itemsIds === 'object' && open !== null) {
277      itemsIds.forEach((item) => {
278        const selectItem = document.querySelector(`#${elementId} #${item}`)
279        if(selectItem) {
280          activateElement(selectItem, open)
281        } else {
282          returnMessage()
283        }
284      })
285    }
286
287    if(typeof itemsIds !== 'object' && open !== null) {
288      const selectItem = document.querySelector(`#${elementId} #${itemsIds}`)
289      if(selectItem) {
290        activateElement(selectItem, open)
291      } else {
292        returnMessage()
293      }
294    }
295
296    if(typeof itemsIds === 'object' && open === null) {
297      itemsIds.forEach((item) => {
298        const selectItem = document.querySelector(`#${elementId} #${item[0]}`)
299        if(selectItem) {
300          activateElement(selectItem, item[1])
301        } else {
302          console.log('There is no item with this id in the document.');
303          return null;
304        }
305      })
306    }
307  }
308
309  function activateElement(item, open) {
310    if(open === true) {
311      item.setAttribute('aria-expanded', 'true');
312      recursiveParent(item)
313    } else {
314      item.setAttribute('aria-expanded', 'false');
315    }
316  }
317
318  function recursiveParent(item) {
319    if(item.parentNode.tagName === "UL" && typeof item.parentNode.id === "string" && item.parentNode.id.length === 0) {
320      recursiveParent(item.parentNode)
321    } else if(item.parentNode.tagName === "LI" && item.parentNode.getAttribute('aria-expanded') === "true") {
322      recursiveParent(item.parentNode)
323    }
323 else if(item.parentNode.getAttribute('aria-expanded') === "false") {
324      item.parentNode.setAttribute('aria-expanded', 'true');
325      if(item.parentNode.parentNode.parentNode.getAttribute('aria-expanded') === "false") {
326        recursiveParent(item.parentNode)
327      }
328    }
329  }
330
331  function returnMessage() {
332    console.log('There is no item with this id in the document.');
333    return null;
334  }
335}

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.