Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js

Issue 2390783006: [DevTools] Accessibility: Show siblings and children of selected node (Closed)
Patch Set: Handle indirect children better Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // Pass an empty title, the title gets made later in onattach. 142 // Pass an empty title, the title gets made later in onattach.
55 TreeElement.call(this, ""); 143 TreeElement.call(this, "");
56 144
57 /** @type {!WebInspector.AccessibilityNode} */ 145 /** @type {!WebInspector.AccessibilityNode} */
58 this._axNode = axNode; 146 this._axNode = axNode;
59 147
60 /** @type {!WebInspector.Target} */ 148 /** @type {!WebInspector.AXTreePane} */
61 this._target = target; 149 this._treePane = treePane;
62 150
63 this.selectable = false; 151 this.selectable = false;
64 }; 152 };
65 153
66 /** @type {!Object<string, string>} */ 154 /** @type {!Object<string, string>} */
67 WebInspector.AXNodeTreeElement.RoleStyles = { 155 WebInspector.AXNodeTreeElement.RoleStyles = {
68 internalRole: "ax-internal-role", 156 internalRole: "ax-internal-role",
69 role: "ax-role", 157 role: "ax-role",
70 }; 158 };
71 159
72 WebInspector.AXNodeTreeElement.prototype = { 160 WebInspector.AXNodeTreeElement.prototype = {
73 /** 161 /**
162 * @return {!WebInspector.AccessibilityNode}
163 */
164 axNode: function()
165 {
166 return this._axNode;
167 },
168
169 /**
170 * @param {boolean} inspected
171 */
172 setInspected: function(inspected)
173 {
174 if (inspected)
175 this.listItemElement.classList.add("inspected");
176 else
177 this.listItemElement.classList.remove("inspected");
178 },
179
180 /**
181 * @override
182 * @return {boolean}
183 */
184 onenter: function()
185 {
186 this.inspectDOMNode();
187 return true;
188 },
189
190 /**
191 * @override
192 * @param {!Event} event
193 * @return {boolean}
194 */
195 ondblclick: function(event)
196 {
197 this.inspectDOMNode();
198 return true;
199 },
200
201 inspectDOMNode: function()
202 {
203 this._treePane.setSelectedByUser(true);
204 WebInspector.Revealer.reveal(this._axNode.domNode());
205 },
206
207 /**
74 * @override 208 * @override
75 */ 209 */
76 onattach: function() 210 onattach: function()
77 { 211 {
78 this._update(); 212 this._update();
79 }, 213 },
80 214
81 _update: function() 215 _update: function()
82 { 216 {
83 this.listItemElement.removeChildren(); 217 this.listItemElement.removeChildren();
84 218
85 if (this._axNode.ignored()) { 219 if (this._axNode.ignored()) {
86 this._appendIgnoredNodeElement(); 220 this._appendIgnoredNodeElement();
87 } else { 221 } else {
88 this._appendRoleElement(this._axNode.role()); 222 this._appendRoleElement(this._axNode.role());
89 if ("name" in this._axNode && this._axNode.name().value) { 223 if (this._axNode && this._axNode.name().value) {
90 this.listItemElement.createChild("span", "separator").textConten t = "\u00A0"; 224 this.listItemElement.createChild("span", "separator").textConten t = "\u00A0";
91 this._appendNameElement(/** @type {string} */ (this._axNode.name ().value)); 225 this._appendNameElement(/** @type {string} */ (this._axNode.name ().value));
92 } 226 }
93 } 227 }
228
229 if (this._axNode.hasOnlyUnloadedChildren()) {
230 this._hasOnlyUnloadedChildren = true;
231 this.listItemElement.classList.add("children-unloaded");
232 this.setExpandable(true);
233 } else {
234 this.setExpandable(!!this._axNode.numChildren());
235 }
94 }, 236 },
95 237
96 /** 238 /**
239 * @override
240 */
241 expand: function()
242 {
243 if (this._hasOnlyUnloadedChildren)
244 return;
245
246 this._treePane.setExpanded(this._axNode.domNode(), true);
247 TreeElement.prototype.expand.call(this);
248 },
249
250 /**
251 * @override
252 */
253 collapse: function()
254 {
255 if (this._hasOnlyUnloadedChildren)
256 return;
257
258 if (this._treePane)
259 this._treePane.setExpanded(this._axNode.domNode(), false);
260 TreeElement.prototype.collapse.call(this);
261 },
262
263 /**
97 * @param {string} name 264 * @param {string} name
98 */ 265 */
99 _appendNameElement: function(name) 266 _appendNameElement: function(name)
100 { 267 {
101 var nameElement = createElement("span"); 268 var nameElement = createElement("span");
102 nameElement.textContent = '"' + name + '"'; 269 nameElement.textContent = '"' + name + '"';
103 nameElement.classList.add("ax-readable-string"); 270 nameElement.classList.add("ax-readable-string");
104 this.listItemElement.appendChild(nameElement); 271 this.listItemElement.appendChild(nameElement);
105 }, 272 },
106 273
(...skipping 13 matching lines...) Expand all
120 }, 287 },
121 288
122 _appendIgnoredNodeElement: function() 289 _appendIgnoredNodeElement: function()
123 { 290 {
124 var ignoredNodeElement = createElementWithClass("span", "monospace"); 291 var ignoredNodeElement = createElementWithClass("span", "monospace");
125 ignoredNodeElement.textContent = WebInspector.UIString("Ignored"); 292 ignoredNodeElement.textContent = WebInspector.UIString("Ignored");
126 ignoredNodeElement.classList.add("ax-tree-ignored-node"); 293 ignoredNodeElement.classList.add("ax-tree-ignored-node");
127 this.listItemElement.appendChild(ignoredNodeElement); 294 this.listItemElement.appendChild(ignoredNodeElement);
128 }, 295 },
129 296
297 /**
298 * @param {boolean=} omitFocus
299 * @param {boolean=} selectedByUser
300 * @return {boolean}
301 * @override
302 */
303 select: function(omitFocus, selectedByUser)
304 {
305 this._ensureSelection();
306
307 this._treePane.setSelectedByUser(!!selectedByUser);
308 if (selectedByUser)
309 WebInspector.context.setFlavor(WebInspector.AccessibilityNode, this. _axNode);
dgozman 2016/10/31 21:36:30 Where is this flavor being used?
aboxhall 2016/10/31 22:45:15 Ah, thanks for catching - I was using it earlier b
310
311 return TreeElement.prototype.select.call(this, omitFocus, selectedByUser );
312 },
313
130 __proto__: TreeElement.prototype 314 __proto__: TreeElement.prototype
131 }; 315 };
316
317 /**
318 * @constructor
319 * @param {!WebInspector.AXNodeTreeParentElement} treeElement
320 */
321 WebInspector.ExpandSiblingsButton = function(treeElement)
322 {
323 this._treeElement = treeElement;
324
325 this.element = createElementWithClass("button", "expand-siblings");
326 this.element.addEventListener("mousedown", this._handleMouseDown.bind(this)) ;
327 };
328
329 WebInspector.ExpandSiblingsButton.prototype = {
330 _handleMouseDown: function(event) {
dgozman 2016/10/31 21:36:30 style: { on next line (here and below)
aboxhall 2016/10/31 22:45:15 Done.
331 this._treeElement.expandSiblings();
332 event.consume();
333 }
334 };
335
336
337 /**
338 * @constructor
339 * @extends {WebInspector.AXNodeTreeElement}
340 * @param {!WebInspector.AccessibilityNode} axNode
341 * @param {!WebInspector.AXNodeTreeElement} inspectedNodeTreeElement
342 * @param {!WebInspector.AXTreePane} treePane
343 */
344 WebInspector.AXNodeTreeParentElement = function(axNode, inspectedNodeTreeElement , treePane)
345 {
346 WebInspector.AXNodeTreeElement.call(this, axNode, treePane);
347
348 this._inspectedNodeTreeElement = inspectedNodeTreeElement;
349 this._expandSibingsButton = new WebInspector.ExpandSiblingsButton(this);
350 this._partiallyExpanded = false;
351 };
352
353 WebInspector.AXNodeTreeParentElement.prototype = {
354 /**
355 * @override
356 */
357 onattach: function(){
358 WebInspector.AXNodeTreeElement.prototype.onattach.call(this);
359 if (this._treePane.isExpanded(this._axNode.domNode()))
360 this._listItemNode.classList.add("siblings-expanded");
361 if (this._axNode.numChildren() > 1)
362 this._listItemNode.appendChild(this._expandSibingsButton.element);
363 },
364
365 /**
366 * @param {boolean} altKey
367 * @return {boolean}
368 * @override
369 */
370 descendOrExpand: function(altKey)
371 {
372 if (!this.expanded || !this._partiallyExpanded)
373 return TreeElement.prototype.descendOrExpand.call(this, altKey);
374
375 this.expandSiblings();
376 if (altKey)
377 this.expandRecursively();
378 return true;
379 },
380
381 /**
382 * @override
383 */
384 expand: function()
385 {
386 TreeElement.prototype.expand.call(this);
387 this._partiallyExpanded = true;
388 },
389
390 expandSiblings: function()
391 {
392 this._listItemNode.classList.add("siblings-expanded");
393 this.appendSiblings();
394 this.expanded = true;
395 this._partiallyExpanded = false;
396 this._treePane.setExpanded(this._axNode.domNode(), true);
397 },
398
399 appendSiblings: function()
400 {
401 var inspectedAXNode = this._inspectedNodeTreeElement.axNode();
402 var nextIndex = 0;
403 var foundInspectedNode = false;
404 for (var sibling of this._axNode.children()) {
405 var siblingTreeElement = null;
406 if (sibling === inspectedAXNode) {
407 foundInspectedNode = true;
408 continue;
409 }
410 siblingTreeElement = new WebInspector.AXNodeTreeElement(sibling, thi s._treePane);
411 if (foundInspectedNode)
412 this.appendChild(siblingTreeElement);
413 else
414 this.insertChild(siblingTreeElement, nextIndex++);
415 }
416 },
417
418 __proto__: WebInspector.AXNodeTreeElement.prototype
419 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698