| 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 /** | 5 /** |
| 6 * @constructor | 6 * @constructor |
| 7 * @extends {WebInspector.AccessibilitySubPane} | 7 * @extends {WebInspector.AccessibilitySubPane} |
| 8 */ | 8 */ |
| 9 WebInspector.AXTreePane = function() | 9 WebInspector.AXTreePane = function() |
| 10 { | 10 { |
| 11 WebInspector.AccessibilitySubPane.call(this, WebInspector.UIString("Accessib
ility Tree")); | 11 WebInspector.AccessibilitySubPane.call(this, WebInspector.UIString("Accessib
ility Tree")); |
| 12 | 12 |
| 13 this._treeOutline = this.createTreeOutline(); | 13 this._treeOutline = this.createTreeOutline(); |
| 14 | 14 |
| 15 this.element.classList.add("accessibility-computed"); | 15 this.element.classList.add("accessibility-computed"); |
| 16 |
| 17 this._expandedNodes = new Set(); |
| 16 }; | 18 }; |
| 17 | 19 |
| 18 | 20 |
| 19 WebInspector.AXTreePane.prototype = { | 21 WebInspector.AXTreePane.prototype = { |
| 20 /** | 22 /** |
| 21 * @param {!Array<!WebInspector.AccessibilityNode>} nodes | 23 * @param {?WebInspector.AccessibilityNode} axNode |
| 24 * @override |
| 22 */ | 25 */ |
| 23 setAXNodeAndAncestors: function(nodes) | 26 setAXNode : function(axNode) |
| 24 { | 27 { |
| 25 this._nodes = nodes; | 28 this._axNode = axNode; |
| 26 | 29 |
| 27 var target = this.node().target(); | |
| 28 var treeOutline = this._treeOutline; | 30 var treeOutline = this._treeOutline; |
| 29 treeOutline.removeChildren(); | 31 treeOutline.removeChildren(); |
| 32 |
| 33 // TODO(aboxhall): show no node UI |
| 34 if (!axNode) |
| 35 return; |
| 36 |
| 30 treeOutline.element.classList.remove("hidden"); | 37 treeOutline.element.classList.remove("hidden"); |
| 31 var previous = treeOutline.rootElement(); | 38 var previousTreeElement = treeOutline.rootElement(); |
| 32 while (nodes.length) { | 39 var inspectedNodeTreeElement = new WebInspector.AXNodeTreeElement(axNode
, this); |
| 33 var ancestor = nodes.pop(); | 40 inspectedNodeTreeElement.setInspected(true); |
| 34 var ancestorTreeElement = new WebInspector.AXNodeTreeElement(ancesto
r, target); | 41 |
| 35 previous.appendChild(ancestorTreeElement); | 42 var parent = axNode.parentNode(); |
| 36 previous.expand(); | 43 if (parent) { |
| 37 previous = ancestorTreeElement; | 44 this.setExpanded(parent.domNode(), false); |
| 45 |
| 46 var chain = []; |
| 47 var ancestor = parent.parentNode(); |
| 48 while (ancestor) { |
| 49 chain.unshift(ancestor); |
| 50 ancestor = ancestor.parentNode(); |
| 51 } |
| 52 for (var ancestorNode of chain) { |
| 53 var ancestorTreeElement = new WebInspector.AXNodeTreeElement(anc
estorNode, this); |
| 54 previousTreeElement.appendChild(ancestorTreeElement); |
| 55 previousTreeElement.expand(); |
| 56 previousTreeElement = ancestorTreeElement; |
| 57 } |
| 58 var parentTreeElement = new WebInspector.AXNodeTreeParentElement(par
ent, inspectedNodeTreeElement, this); |
| 59 if (this.isExpanded(parent.domNode())) |
| 60 parentTreeElement.appendSiblings(); |
| 61 else |
| 62 parentTreeElement.appendChild(inspectedNodeTreeElement); |
| 63 previousTreeElement.appendChild(parentTreeElement); |
| 64 previousTreeElement.expand(); |
| 65 previousTreeElement = parentTreeElement; |
| 66 } else { |
| 67 previousTreeElement.appendChild(inspectedNodeTreeElement); |
| 38 } | 68 } |
| 39 previous.selectable = true; | 69 |
| 40 previous.select(true /* omitFocus */); | 70 previousTreeElement.expand(); |
| 71 |
| 72 for (var child of axNode.children()) { |
| 73 var childTreeElement = new WebInspector.AXNodeTreeElement(child, thi
s); |
| 74 inspectedNodeTreeElement.appendChild(childTreeElement); |
| 75 } |
| 76 |
| 77 inspectedNodeTreeElement.selectable = true; |
| 78 inspectedNodeTreeElement.select(!this._selectedByUser /* omitFocus */, f
alse); |
| 79 if (this.isExpanded(axNode.domNode())) |
| 80 inspectedNodeTreeElement.expand(); |
| 81 this.clearSelectedByUser(); |
| 82 }, |
| 83 |
| 84 /** |
| 85 * @param {boolean} selectedByUser |
| 86 */ |
| 87 setSelectedByUser: function(selectedByUser) |
| 88 { |
| 89 this._selectedByUser = true; |
| 90 }, |
| 91 |
| 92 clearSelectedByUser: function() |
| 93 { |
| 94 delete this._selectedByUser; |
| 95 }, |
| 96 |
| 97 /** |
| 98 * @return {!WebInspector.Target} |
| 99 */ |
| 100 target: function() |
| 101 { |
| 102 return this.node().target(); |
| 103 }, |
| 104 |
| 105 /** |
| 106 * @param {?WebInspector.DOMNode} domNode |
| 107 * @param {boolean} expanded |
| 108 */ |
| 109 setExpanded: function(domNode, expanded) |
| 110 { |
| 111 if (!domNode) |
| 112 return; |
| 113 if (expanded) |
| 114 this._expandedNodes.add(domNode.id); |
| 115 else |
| 116 this._expandedNodes.delete(domNode.id); |
| 117 }, |
| 118 |
| 119 /** |
| 120 * @param {?WebInspector.DOMNode} domNode |
| 121 * @return {boolean} |
| 122 */ |
| 123 isExpanded: function(domNode) |
| 124 { |
| 125 if (!domNode) |
| 126 return false; |
| 127 |
| 128 return this._expandedNodes.has(domNode.id); |
| 41 }, | 129 }, |
| 42 | 130 |
| 43 __proto__: WebInspector.AccessibilitySubPane.prototype | 131 __proto__: WebInspector.AccessibilitySubPane.prototype |
| 44 }; | 132 }; |
| 45 | 133 |
| 46 /** | 134 /** |
| 47 * @constructor | 135 * @constructor |
| 48 * @extends {TreeElement} | 136 * @extends {TreeElement} |
| 49 * @param {!WebInspector.AccessibilityNode} axNode | 137 * @param {!WebInspector.AccessibilityNode} axNode |
| 50 * @param {!WebInspector.Target} target | 138 * @param {!WebInspector.AXTreePane} treePane |
| 51 */ | 139 */ |
| 52 WebInspector.AXNodeTreeElement = function(axNode, target) | 140 WebInspector.AXNodeTreeElement = function(axNode, treePane) |
| 53 { | 141 { |
| 54 /** @type {!WebInspector.AccessibilityNode} */ | 142 /** @type {!WebInspector.AccessibilityNode} */ |
| 55 this._axNode = axNode; | 143 this._axNode = axNode; |
| 56 | 144 |
| 57 /** @type {!WebInspector.Target} */ | 145 /** @type {!WebInspector.AXTreePane} */ |
| 58 this._target = target; | 146 this._treePane = treePane; |
| 59 | 147 |
| 60 // Pass an empty title, the title gets made later in onattach. | 148 // Pass an empty title, the title gets made later in onattach. |
| 61 TreeElement.call(this, ""); | 149 TreeElement.call(this, "", true); |
| 62 | 150 |
| 63 this.selectable = false; | 151 if (!this._axNode.domNode()) |
| 152 this.listItemElement.classList.add("no-dom-node"); |
| 153 |
| 154 this.selectable = true; |
| 64 }; | 155 }; |
| 65 | 156 |
| 66 /** @type {!Object<string, string>} */ | 157 /** @type {!Object<string, string>} */ |
| 67 WebInspector.AXNodeTreeElement.RoleStyles = { | 158 WebInspector.AXNodeTreeElement.RoleStyles = { |
| 68 internalRole: "ax-internal-role", | 159 internalRole: "ax-internal-role", |
| 69 role: "ax-role", | 160 role: "ax-role", |
| 70 }; | 161 }; |
| 71 | 162 |
| 72 WebInspector.AXNodeTreeElement.prototype = { | 163 WebInspector.AXNodeTreeElement.prototype = { |
| 73 /** | 164 /** |
| 165 * @return {!WebInspector.AccessibilityNode} |
| 166 */ |
| 167 axNode: function() |
| 168 { |
| 169 return this._axNode; |
| 170 }, |
| 171 |
| 172 /** |
| 173 * @param {boolean} inspected |
| 174 */ |
| 175 setInspected: function(inspected) |
| 176 { |
| 177 if (inspected) |
| 178 this.listItemElement.classList.add("inspected"); |
| 179 else |
| 180 this.listItemElement.classList.remove("inspected"); |
| 181 }, |
| 182 |
| 183 /** |
| 184 * @override |
| 185 * @return {boolean} |
| 186 */ |
| 187 onenter: function() |
| 188 { |
| 189 this.inspectDOMNode(); |
| 190 return true; |
| 191 }, |
| 192 |
| 193 /** |
| 194 * @override |
| 195 * @param {!Event} event |
| 196 * @return {boolean} |
| 197 */ |
| 198 ondblclick: function(event) |
| 199 { |
| 200 this.inspectDOMNode(); |
| 201 return true; |
| 202 }, |
| 203 |
| 204 inspectDOMNode: function() |
| 205 { |
| 206 this._treePane.setSelectedByUser(true); |
| 207 WebInspector.Revealer.reveal(this._axNode.domNode()); |
| 208 }, |
| 209 |
| 210 /** |
| 74 * @override | 211 * @override |
| 75 */ | 212 */ |
| 76 onattach: function() | 213 onattach: function() |
| 77 { | 214 { |
| 78 this._update(); | 215 this._update(); |
| 79 }, | 216 }, |
| 80 | 217 |
| 81 _update: function() | 218 _update: function() |
| 82 { | 219 { |
| 83 this.listItemElement.removeChildren(); | 220 this.listItemElement.removeChildren(); |
| 84 | 221 |
| 85 if (this._axNode.ignored()) { | 222 if (this._axNode.ignored()) { |
| 86 this._appendIgnoredNodeElement(); | 223 this._appendIgnoredNodeElement(); |
| 87 } else { | 224 } else { |
| 88 this._appendRoleElement(this._axNode.role()); | 225 this._appendRoleElement(this._axNode.role()); |
| 89 if ("name" in this._axNode && this._axNode.name().value) { | 226 if ("name" in this._axNode && this._axNode.name().value) { |
| 90 this.listItemElement.createChild("span", "separator").textConten
t = "\u00A0"; | 227 this.listItemElement.createChild("span", "separator").textConten
t = "\u00A0"; |
| 91 this._appendNameElement(/** @type {string} */ (this._axNode.name
().value)); | 228 this._appendNameElement(/** @type {string} */ (this._axNode.name
().value)); |
| 92 } | 229 } |
| 93 } | 230 } |
| 231 |
| 232 if (this._axNode.hasOnlyUnloadedChildren()) { |
| 233 this._hasOnlyUnloadedChildren = true; |
| 234 this.listItemElement.classList.add("children-unloaded"); |
| 235 this.setExpandable(true); |
| 236 } else { |
| 237 this.setExpandable(!!this._axNode.numChildren()); |
| 238 } |
| 94 }, | 239 }, |
| 95 | 240 |
| 96 /** | 241 /** |
| 242 * @override |
| 243 */ |
| 244 expand: function() |
| 245 { |
| 246 if (this._hasOnlyUnloadedChildren) |
| 247 return; |
| 248 |
| 249 this._treePane.setExpanded(this._axNode.domNode(), true); |
| 250 TreeElement.prototype.expand.call(this); |
| 251 }, |
| 252 |
| 253 /** |
| 254 * @override |
| 255 */ |
| 256 collapse: function() |
| 257 { |
| 258 if (this._hasOnlyUnloadedChildren) |
| 259 return; |
| 260 |
| 261 this._treePane.setExpanded(this._axNode.domNode(), false); |
| 262 TreeElement.prototype.collapse.call(this); |
| 263 }, |
| 264 |
| 265 /** |
| 97 * @param {string} name | 266 * @param {string} name |
| 98 */ | 267 */ |
| 99 _appendNameElement: function(name) | 268 _appendNameElement: function(name) |
| 100 { | 269 { |
| 101 var nameElement = createElement("span"); | 270 var nameElement = createElement("span"); |
| 102 nameElement.textContent = '"' + name + '"'; | 271 nameElement.textContent = '"' + name + '"'; |
| 103 nameElement.classList.add("ax-readable-string"); | 272 nameElement.classList.add("ax-readable-string"); |
| 104 this.listItemElement.appendChild(nameElement); | 273 this.listItemElement.appendChild(nameElement); |
| 105 }, | 274 }, |
| 106 | 275 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 120 }, | 289 }, |
| 121 | 290 |
| 122 _appendIgnoredNodeElement: function() | 291 _appendIgnoredNodeElement: function() |
| 123 { | 292 { |
| 124 var ignoredNodeElement = createElementWithClass("span", "monospace"); | 293 var ignoredNodeElement = createElementWithClass("span", "monospace"); |
| 125 ignoredNodeElement.textContent = WebInspector.UIString("Ignored"); | 294 ignoredNodeElement.textContent = WebInspector.UIString("Ignored"); |
| 126 ignoredNodeElement.classList.add("ax-tree-ignored-node"); | 295 ignoredNodeElement.classList.add("ax-tree-ignored-node"); |
| 127 this.listItemElement.appendChild(ignoredNodeElement); | 296 this.listItemElement.appendChild(ignoredNodeElement); |
| 128 }, | 297 }, |
| 129 | 298 |
| 299 /** |
| 300 * @param {boolean=} omitFocus |
| 301 * @param {boolean=} selectedByUser |
| 302 * @return {boolean} |
| 303 * @override |
| 304 */ |
| 305 select: function(omitFocus, selectedByUser) |
| 306 { |
| 307 this._ensureSelection(); |
| 308 |
| 309 this._treePane.setSelectedByUser(!!selectedByUser); |
| 310 if (selectedByUser) |
| 311 WebInspector.context.setFlavor(WebInspector.AccessibilityNode, this.
_axNode); |
| 312 |
| 313 return TreeElement.prototype.select.call(this, omitFocus, selectedByUser
); |
| 314 }, |
| 315 |
| 130 __proto__: TreeElement.prototype | 316 __proto__: TreeElement.prototype |
| 131 }; | 317 }; |
| 318 |
| 319 /** |
| 320 * @constructor |
| 321 * @param {!WebInspector.AXNodeTreeParentElement} treeElement |
| 322 */ |
| 323 WebInspector.ExpandSiblingsButton = function(treeElement) |
| 324 { |
| 325 this._treeElement = treeElement; |
| 326 |
| 327 this.element = createElementWithClass("button", "expand-siblings"); |
| 328 this.element.addEventListener("mousedown", this._handleMouseDown.bind(this))
; |
| 329 }; |
| 330 |
| 331 WebInspector.ExpandSiblingsButton.prototype = { |
| 332 _handleMouseDown: function(event) { |
| 333 this._treeElement.expandSiblings(); |
| 334 event.consume(); |
| 335 } |
| 336 }; |
| 337 |
| 338 |
| 339 /** |
| 340 * @constructor |
| 341 * @extends {WebInspector.AXNodeTreeElement} |
| 342 * @param {!WebInspector.AccessibilityNode} axNode |
| 343 * @param {!WebInspector.AXNodeTreeElement} inspectedNodeTreeElement |
| 344 * @param {!WebInspector.AXTreePane} treePane |
| 345 */ |
| 346 WebInspector.AXNodeTreeParentElement = function(axNode, inspectedNodeTreeElement
, treePane) |
| 347 { |
| 348 this._inspectedNodeTreeElement = inspectedNodeTreeElement; |
| 349 this._treePane = treePane; |
| 350 |
| 351 WebInspector.AXNodeTreeElement.call(this, axNode, treePane); |
| 352 |
| 353 this._expandSibingsButton = new WebInspector.ExpandSiblingsButton(this); |
| 354 this._partiallyExpanded = false; |
| 355 }; |
| 356 |
| 357 WebInspector.AXNodeTreeParentElement.prototype = { |
| 358 /** |
| 359 * @override |
| 360 */ |
| 361 onattach: function(){ |
| 362 WebInspector.AXNodeTreeElement.prototype.onattach.call(this); |
| 363 if (this._treePane.isExpanded(this._axNode.domNode())) |
| 364 this._listItemNode.classList.add("siblings-expanded"); |
| 365 if (this._axNode.numChildren() > 1) |
| 366 this._listItemNode.appendChild(this._expandSibingsButton.element); |
| 367 }, |
| 368 |
| 369 /** |
| 370 * @param {boolean} altKey |
| 371 * @return {boolean} |
| 372 * @override |
| 373 */ |
| 374 descendOrExpand: function(altKey) |
| 375 { |
| 376 if (!this.expanded || !this._partiallyExpanded) |
| 377 return TreeElement.prototype.descendOrExpand.call(this, altKey); |
| 378 |
| 379 this.expandSiblings(); |
| 380 if (altKey) |
| 381 this.expandRecursively(); |
| 382 return true; |
| 383 }, |
| 384 |
| 385 /** |
| 386 * @override |
| 387 */ |
| 388 expand: function() |
| 389 { |
| 390 TreeElement.prototype.expand.call(this); |
| 391 this._partiallyExpanded = true; |
| 392 }, |
| 393 |
| 394 expandSiblings: function() |
| 395 { |
| 396 this._listItemNode.classList.add("siblings-expanded"); |
| 397 this.appendSiblings(); |
| 398 this.expanded = true; |
| 399 this._partiallyExpanded = false; |
| 400 this._treePane.setExpanded(this._axNode.domNode(), true); |
| 401 }, |
| 402 |
| 403 appendSiblings: function() |
| 404 { |
| 405 var inspectedAXNode = this._inspectedNodeTreeElement.axNode(); |
| 406 var nextIndex = 0; |
| 407 var foundInspectedNode = false; |
| 408 for (var sibling of this._axNode.children()) { |
| 409 var siblingTreeElement = null; |
| 410 if (sibling === inspectedAXNode) { |
| 411 foundInspectedNode = true; |
| 412 continue; |
| 413 } |
| 414 siblingTreeElement = new WebInspector.AXNodeTreeElement(sibling, thi
s._treePane); |
| 415 if (foundInspectedNode) |
| 416 this.appendChild(siblingTreeElement); |
| 417 else |
| 418 this.insertChild(siblingTreeElement, nextIndex++); |
| 419 } |
| 420 }, |
| 421 |
| 422 __proto__: WebInspector.AXNodeTreeElement.prototype |
| 423 }; |
| OLD | NEW |