| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 /** | 4 /** |
| 5 * @unrestricted | 5 * @unrestricted |
| 6 */ | 6 */ |
| 7 Accessibility.AXTreePane = class extends Accessibility.AccessibilitySubPane { | 7 Accessibility.AXTreePane = class extends Accessibility.AccessibilitySubPane { |
| 8 /** | 8 /** |
| 9 * @param {!Accessibility.AccessibilitySidebarView} axSidebarView | 9 * @param {!Accessibility.AccessibilitySidebarView} axSidebarView |
| 10 */ | 10 */ |
| 11 constructor(axSidebarView) { | 11 constructor(axSidebarView) { |
| 12 super(Common.UIString('Accessibility Tree')); | 12 super(Common.UIString('Accessibility Tree')); |
| 13 | 13 |
| 14 this._axSidebarView = axSidebarView; | 14 this._axSidebarView = axSidebarView; |
| 15 this._treeOutline = this.createTreeOutline(); | 15 this._treeOutline = this.createTreeOutline(); |
| 16 this._treeOutline.setPaddingSize(12); | 16 this._treeOutline.setPaddingSize(12); |
| 17 | 17 |
| 18 this.element.classList.add('accessibility-computed'); | 18 this.element.classList.add('accessibility-computed'); |
| 19 | |
| 20 this._expandedNodes = new Set(); | |
| 21 } | 19 } |
| 22 | 20 |
| 23 /** | 21 /** |
| 24 * @param {?Accessibility.AccessibilityNode} axNode | 22 * @param {?Accessibility.AccessibilityNode} axNode |
| 25 * @override | 23 * @override |
| 26 */ | 24 */ |
| 27 setAXNode(axNode) { | 25 setAXNode(axNode) { |
| 28 this._axNode = axNode; | 26 this._axNode = axNode; |
| 29 | 27 |
| 30 var treeOutline = this._treeOutline; | 28 var treeOutline = this._treeOutline; |
| 31 treeOutline.removeChildren(); | 29 treeOutline.removeChildren(); |
| 32 | 30 |
| 33 // TODO(aboxhall): show no node UI | 31 // TODO(aboxhall): show no node UI |
| 34 if (!axNode) | 32 if (!axNode) |
| 35 return; | 33 return; |
| 36 | 34 |
| 37 treeOutline.element.classList.remove('hidden'); | 35 treeOutline.element.classList.remove('hidden'); |
| 38 var previousTreeElement = treeOutline.rootElement(); | 36 var previousTreeElement = treeOutline.rootElement(); |
| 39 var inspectedNodeTreeElement = new Accessibility.AXNodeTreeElement(axNode, t
his); | 37 var inspectedNodeTreeElement = new Accessibility.AXNodeTreeElement(axNode, t
his); |
| 40 inspectedNodeTreeElement.setInspected(true); | 38 inspectedNodeTreeElement.setInspected(true); |
| 41 | 39 |
| 42 var parent = axNode.parentNode(); | 40 var parent = axNode.parentNode(); |
| 43 if (parent) { | 41 if (parent) { |
| 44 this.setExpanded(parent.backendDOMNodeId(), false); | 42 var ancestorChain = []; |
| 45 | 43 var ancestor = parent; |
| 46 var chain = []; | |
| 47 var ancestor = parent.parentNode(); | |
| 48 while (ancestor) { | 44 while (ancestor) { |
| 49 chain.unshift(ancestor); | 45 ancestorChain.unshift(ancestor); |
| 50 ancestor = ancestor.parentNode(); | 46 ancestor = ancestor.parentNode(); |
| 51 } | 47 } |
| 52 for (var ancestorNode of chain) { | 48 for (var ancestorNode of ancestorChain) { |
| 53 var ancestorTreeElement = new Accessibility.AXNodeTreeElement(ancestorNo
de, this); | 49 var ancestorTreeElement = new Accessibility.AXNodeTreeElement(ancestorNo
de, this); |
| 54 previousTreeElement.appendChild(ancestorTreeElement); | 50 previousTreeElement.appendChild(ancestorTreeElement); |
| 55 previousTreeElement.expand(); | 51 previousTreeElement.expand(); |
| 56 previousTreeElement = ancestorTreeElement; | 52 previousTreeElement = ancestorTreeElement; |
| 57 } | 53 } |
| 58 var parentTreeElement = new Accessibility.AXNodeTreeParentElement(parent,
inspectedNodeTreeElement, this); | |
| 59 previousTreeElement.appendChild(parentTreeElement); | |
| 60 if (this.isExpanded(parent.backendDOMNodeId())) | |
| 61 parentTreeElement.appendSiblings(); | |
| 62 else | |
| 63 parentTreeElement.appendChild(inspectedNodeTreeElement); | |
| 64 previousTreeElement.expand(); | |
| 65 previousTreeElement = parentTreeElement; | |
| 66 } else { | |
| 67 previousTreeElement.appendChild(inspectedNodeTreeElement); | |
| 68 } | 54 } |
| 69 | 55 |
| 56 previousTreeElement.appendChild(inspectedNodeTreeElement); |
| 70 previousTreeElement.expand(); | 57 previousTreeElement.expand(); |
| 71 | 58 |
| 72 for (var child of axNode.children()) { | |
| 73 var childTreeElement = new Accessibility.AXNodeTreeElement(child, this); | |
| 74 inspectedNodeTreeElement.appendChild(childTreeElement); | |
| 75 } | |
| 76 | |
| 77 inspectedNodeTreeElement.selectable = true; | 59 inspectedNodeTreeElement.selectable = true; |
| 78 inspectedNodeTreeElement.select(!this._selectedByUser /* omitFocus */, false
); | 60 inspectedNodeTreeElement.select(!this._selectedByUser /* omitFocus */, false
); |
| 79 if (this.isExpanded(axNode.backendDOMNodeId())) | 61 inspectedNodeTreeElement.expand(); |
| 80 inspectedNodeTreeElement.expand(); | |
| 81 this.clearSelectedByUser(); | 62 this.clearSelectedByUser(); |
| 82 } | 63 } |
| 83 | 64 |
| 84 /** | 65 /** |
| 85 * @param {!Accessibility.AccessibilityNode} axNode | 66 * @param {!Accessibility.AccessibilityNode} axNode |
| 86 */ | 67 */ |
| 87 setSelectedNode(axNode) { | 68 setSelectedNode(axNode) { |
| 88 if (axNode.parentNode()) { | 69 if (axNode.parentNode()) { |
| 89 Common.Revealer.reveal(axNode.deferredDOMNode()); | 70 Common.Revealer.reveal(axNode.deferredDOMNode()); |
| 90 } else { | 71 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 106 clearSelectedByUser() { | 87 clearSelectedByUser() { |
| 107 delete this._selectedByUser; | 88 delete this._selectedByUser; |
| 108 } | 89 } |
| 109 | 90 |
| 110 /** | 91 /** |
| 111 * @return {!SDK.Target} | 92 * @return {!SDK.Target} |
| 112 */ | 93 */ |
| 113 target() { | 94 target() { |
| 114 return this.node().target(); | 95 return this.node().target(); |
| 115 } | 96 } |
| 116 | |
| 117 /** | |
| 118 * @param {?number} backendDOMNodeId | |
| 119 * @param {boolean} expanded | |
| 120 */ | |
| 121 setExpanded(backendDOMNodeId, expanded) { | |
| 122 if (!backendDOMNodeId) | |
| 123 return; | |
| 124 if (expanded) | |
| 125 this._expandedNodes.add(backendDOMNodeId); | |
| 126 else | |
| 127 this._expandedNodes.delete(backendDOMNodeId); | |
| 128 } | |
| 129 | |
| 130 /** | |
| 131 * @param {?number} backendDOMNodeId | |
| 132 * @return {boolean} | |
| 133 */ | |
| 134 isExpanded(backendDOMNodeId) { | |
| 135 if (!backendDOMNodeId) | |
| 136 return false; | |
| 137 | |
| 138 return this._expandedNodes.has(backendDOMNodeId); | |
| 139 } | |
| 140 }; | 97 }; |
| 141 | 98 |
| 142 Accessibility.InspectNodeButton = class { | 99 Accessibility.InspectNodeButton = class { |
| 143 /** | 100 /** |
| 144 * @param {!Accessibility.AccessibilityNode} axNode | 101 * @param {!Accessibility.AccessibilityNode} axNode |
| 145 * @param {!Accessibility.AXTreePane} treePane | 102 * @param {!Accessibility.AXTreePane} treePane |
| 146 */ | 103 */ |
| 147 constructor(axNode, treePane) { | 104 constructor(axNode, treePane) { |
| 148 this._axNode = axNode; | 105 this._axNode = axNode; |
| 149 this._treePane = treePane; | 106 this._treePane = treePane; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 /** | 197 /** |
| 241 * @override | 198 * @override |
| 242 * @param {!Event} event | 199 * @param {!Event} event |
| 243 * @return {boolean} | 200 * @return {boolean} |
| 244 */ | 201 */ |
| 245 ondblclick(event) { | 202 ondblclick(event) { |
| 246 this.inspectDOMNode(); | 203 this.inspectDOMNode(); |
| 247 return true; | 204 return true; |
| 248 } | 205 } |
| 249 | 206 |
| 207 /** |
| 208 * @override |
| 209 */ |
| 210 onpopulate() { |
| 211 for (var child of this._axNode.children()) { |
| 212 var childTreeElement = new Accessibility.AXNodeTreeElement(child, this._tr
eePane); |
| 213 this.appendChild(childTreeElement); |
| 214 if (childTreeElement.isExpandable() && !child.hasOnlyUnloadedChildren()) |
| 215 childTreeElement.expand(); |
| 216 } |
| 217 } |
| 218 |
| 250 inspectDOMNode() { | 219 inspectDOMNode() { |
| 251 this._treePane.setSelectedByUser(true); | 220 this._treePane.setSelectedByUser(true); |
| 252 this._treePane.setSelectedNode(this._axNode); | 221 this._treePane.setSelectedNode(this._axNode); |
| 253 } | 222 } |
| 254 | 223 |
| 255 /** | 224 /** |
| 256 * @override | 225 * @override |
| 257 */ | 226 */ |
| 258 onattach() { | 227 onattach() { |
| 259 this._update(); | 228 this._update(); |
| 260 } | 229 } |
| 261 | 230 |
| 262 _update() { | 231 _update() { |
| 263 this.titleElement().removeChildren(); | 232 this.titleElement().removeChildren(); |
| 264 | 233 |
| 265 if (this._axNode.ignored()) { | 234 if (this._axNode.ignored()) { |
| 266 this._appendIgnoredNodeElement(); | 235 this._appendIgnoredNodeElement(); |
| 267 } else { | 236 } else { |
| 268 this._appendRoleElement(this._axNode.role()); | 237 this._appendRoleElement(this._axNode.role()); |
| 269 if (this._axNode.name().value) { | 238 if (this._axNode.name() && this._axNode.name().value) { |
| 270 this.titleElement().createChild('span', 'separator').textContent = '\u00
A0'; | 239 this.titleElement().createChild('span', 'separator').textContent = '\u00
A0'; |
| 271 this._appendNameElement(/** @type {string} */ (this._axNode.name().value
)); | 240 this._appendNameElement(/** @type {string} */ (this._axNode.name().value
)); |
| 272 } | 241 } |
| 273 } | 242 } |
| 274 | 243 |
| 275 if (this._axNode.hasOnlyUnloadedChildren()) { | 244 if (this._axNode.hasOnlyUnloadedChildren()) { |
| 276 this.titleElement().classList.add('children-unloaded'); | 245 this.listItemElement.classList.add('children-unloaded'); |
| 277 this.setExpandable(true); | 246 this.setExpandable(true); |
| 278 } else { | 247 } else { |
| 279 this.setExpandable(!!this._axNode.numChildren()); | 248 this.setExpandable(!!this._axNode.numChildren()); |
| 280 } | 249 } |
| 281 | 250 |
| 282 if (!this._axNode.isDOMNode()) | 251 if (!this._axNode.isDOMNode()) |
| 283 this.titleElement().classList.add('no-dom-node'); | 252 this.listItemElement.classList.add('no-dom-node'); |
| 284 this.titleElement().appendChild(this._inspectNodeButton.element); | 253 this.titleElement().appendChild(this._inspectNodeButton.element); |
| 285 } | 254 } |
| 286 | 255 |
| 287 /** | 256 /** |
| 288 * @override | 257 * @override |
| 289 */ | 258 */ |
| 290 expand() { | 259 expand() { |
| 291 if (!this._axNode || this._axNode.hasOnlyUnloadedChildren()) | 260 if (!this._axNode || this._axNode.hasOnlyUnloadedChildren()) |
| 292 return; | 261 return; |
| 293 | |
| 294 this._treePane.setExpanded(this._axNode.backendDOMNodeId(), true); | |
| 295 super.expand(); | 262 super.expand(); |
| 296 } | 263 } |
| 297 | 264 |
| 298 /** | 265 /** |
| 299 * @override | 266 * @override |
| 300 */ | 267 */ |
| 301 collapse() { | 268 collapse() { |
| 302 if (!this._axNode || this._axNode.hasOnlyUnloadedChildren()) | 269 if (!this._axNode || this._axNode.hasOnlyUnloadedChildren()) |
| 303 return; | 270 return; |
| 304 | 271 |
| 305 if (this._treePane) | |
| 306 this._treePane.setExpanded(this._axNode.backendDOMNodeId(), false); | |
| 307 super.collapse(); | 272 super.collapse(); |
| 308 } | 273 } |
| 309 | 274 |
| 310 /** | 275 /** |
| 311 * @param {string} name | 276 * @param {string} name |
| 312 */ | 277 */ |
| 313 _appendNameElement(name) { | 278 _appendNameElement(name) { |
| 314 var nameElement = createElement('span'); | 279 var nameElement = createElement('span'); |
| 315 nameElement.textContent = '"' + name + '"'; | 280 nameElement.textContent = '"' + name + '"'; |
| 316 nameElement.classList.add('ax-readable-string'); | 281 nameElement.classList.add('ax-readable-string'); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 return super.select(omitFocus, selectedByUser); | 315 return super.select(omitFocus, selectedByUser); |
| 351 } | 316 } |
| 352 }; | 317 }; |
| 353 | 318 |
| 354 /** @type {!Object<string, string>} */ | 319 /** @type {!Object<string, string>} */ |
| 355 Accessibility.AXNodeTreeElement.RoleStyles = { | 320 Accessibility.AXNodeTreeElement.RoleStyles = { |
| 356 internalRole: 'ax-internal-role', | 321 internalRole: 'ax-internal-role', |
| 357 role: 'ax-role', | 322 role: 'ax-role', |
| 358 }; | 323 }; |
| 359 | 324 |
| 360 /** | |
| 361 * @unrestricted | |
| 362 */ | |
| 363 Accessibility.ExpandSiblingsButton = class { | |
| 364 /** | |
| 365 * @param {!Accessibility.AXNodeTreeParentElement} treeElement | |
| 366 * @param {number} numSiblings | |
| 367 */ | |
| 368 constructor(treeElement, numSiblings) { | |
| 369 this._treeElement = treeElement; | |
| 370 | |
| 371 this.element = createElementWithClass('button', 'expand-siblings'); | |
| 372 this.element.textContent = Common.UIString((numSiblings === 1 ? '+ %d node'
: '+ %d nodes'), numSiblings); | |
| 373 this.element.addEventListener('mousedown', this._handleMouseDown.bind(this))
; | |
| 374 } | |
| 375 | |
| 376 /** | |
| 377 * @param {!Event} event | |
| 378 */ | |
| 379 _handleMouseDown(event) { | |
| 380 this._treeElement.expandSiblings(); | |
| 381 event.consume(); | |
| 382 } | |
| 383 }; | |
| 384 | |
| 385 /** | |
| 386 * @unrestricted | |
| 387 */ | |
| 388 Accessibility.AXNodeTreeParentElement = class extends Accessibility.AXNodeTreeEl
ement { | |
| 389 /** | |
| 390 * @param {!Accessibility.AccessibilityNode} axNode | |
| 391 * @param {!Accessibility.AXNodeTreeElement} inspectedNodeTreeElement | |
| 392 * @param {!Accessibility.AXTreePane} treePane | |
| 393 */ | |
| 394 constructor(axNode, inspectedNodeTreeElement, treePane) { | |
| 395 super(axNode, treePane); | |
| 396 | |
| 397 this._inspectedNodeTreeElement = inspectedNodeTreeElement; | |
| 398 var numSiblings = axNode.children().length - 1; | |
| 399 this._expandSiblingsButton = new Accessibility.ExpandSiblingsButton(this, nu
mSiblings); | |
| 400 this._partiallyExpanded = false; | |
| 401 } | |
| 402 | |
| 403 /** | |
| 404 * @override | |
| 405 */ | |
| 406 onattach() { | |
| 407 super.onattach(); | |
| 408 if (this._treePane.isExpanded(this._axNode.backendDOMNodeId())) | |
| 409 this.listItemElement.classList.add('siblings-expanded'); | |
| 410 if (this._axNode.numChildren() > 1) | |
| 411 this.titleElement().insertBefore(this._expandSiblingsButton.element, this.
_inspectNodeButton.element); | |
| 412 } | |
| 413 | |
| 414 /** | |
| 415 * @param {boolean} altKey | |
| 416 * @return {boolean} | |
| 417 * @override | |
| 418 */ | |
| 419 descendOrExpand(altKey) { | |
| 420 if (!this.expanded || !this._partiallyExpanded) | |
| 421 return super.descendOrExpand(altKey); | |
| 422 | |
| 423 this.expandSiblings(); | |
| 424 if (altKey) | |
| 425 this.expandRecursively(); | |
| 426 return true; | |
| 427 } | |
| 428 | |
| 429 /** | |
| 430 * @override | |
| 431 */ | |
| 432 expand() { | |
| 433 super.expand(); | |
| 434 this._partiallyExpanded = true; | |
| 435 } | |
| 436 | |
| 437 expandSiblings() { | |
| 438 this.listItemElement.classList.add('siblings-expanded'); | |
| 439 this.appendSiblings(); | |
| 440 this.expanded = true; | |
| 441 this._partiallyExpanded = false; | |
| 442 this._treePane.setExpanded(this._axNode.backendDOMNodeId(), true); | |
| 443 } | |
| 444 | |
| 445 appendSiblings() { | |
| 446 var inspectedAXNode = this._inspectedNodeTreeElement.axNode(); | |
| 447 var nextIndex = 0; | |
| 448 var foundInspectedNode = false; | |
| 449 for (var sibling of this._axNode.children()) { | |
| 450 var siblingTreeElement = null; | |
| 451 if (sibling === inspectedAXNode) { | |
| 452 foundInspectedNode = true; | |
| 453 continue; | |
| 454 } | |
| 455 siblingTreeElement = new Accessibility.AXNodeTreeElement(sibling, this._tr
eePane); | |
| 456 if (foundInspectedNode) | |
| 457 this.appendChild(siblingTreeElement); | |
| 458 else | |
| 459 this.insertChild(siblingTreeElement, nextIndex++); | |
| 460 } | |
| 461 } | |
| 462 }; | |
| OLD | NEW |