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.