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

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

Issue 2390783006: [DevTools] Accessibility: Show siblings and children of selected node (Closed)
Patch Set: UI feedback from Chris 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 (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 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 WebInspector.AccessibilityNode = class extends WebInspector.SDKObject { 7 WebInspector.AccessibilityNode = class extends WebInspector.SDKObject {
8 /** 8 /**
9 * @param {!WebInspector.AccessibilityModel} accessibilityModel 9 * @param {!WebInspector.AccessibilityModel} accessibilityModel
10 * @param {!AccessibilityAgent.AXNode} payload 10 * @param {!AccessibilityAgent.AXNode} payload
11 */ 11 */
12 constructor(accessibilityModel, payload) { 12 constructor(accessibilityModel, payload) {
13 super(accessibilityModel.target()); 13 super(accessibilityModel.target());
14 this._accessibilityModel = accessibilityModel; 14 this._accessibilityModel = accessibilityModel;
15 this._agent = accessibilityModel._agent; 15 this._agent = accessibilityModel._agent;
16 16
17 this._id = payload.nodeId; 17 this._id = payload.nodeId;
18 accessibilityModel._setAXNodeForAXId(this._id, this); 18 accessibilityModel._setAXNodeForAXId(this._id, this);
19 19
20 this._ignored = payload.ignored; 20 this._ignored = payload.ignored;
21 if (this._ignored && 'ignoredReasons' in payload) 21 if (this._ignored && 'ignoredReasons' in payload)
22 this._ignoredReasons = payload.ignoredReasons; 22 this._ignoredReasons = payload.ignoredReasons;
23 23
24 this._role = payload.role || null; 24 this._role = payload.role || null;
25 this._name = payload.name || null; 25 this._name = payload.name || null;
26 this._description = payload.description || null; 26 this._description = payload.description || null;
27 this._value = payload.value || null; 27 this._value = payload.value || null;
28 this._properties = payload.properties || null; 28 this._properties = payload.properties || null;
29 this._parentId = payload.parentId || null;
30 this._childIds = payload.childIds || null; 29 this._childIds = payload.childIds || null;
31 this._domNodeId = payload.domNodeId || null; 30 this._backendDomNodeId = payload.backendDomNodeId || null;
31 this._parentNode = null;
32 } 32 }
33 33
34 /** 34 /**
35 * @return {boolean} 35 * @return {boolean}
36 */ 36 */
37 ignored() { 37 ignored() {
38 return this._ignored; 38 return this._ignored;
39 } 39 }
40 40
41 /** 41 /**
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 * @return {?Array<!AccessibilityAgent.AXProperty>} 93 * @return {?Array<!AccessibilityAgent.AXProperty>}
94 */ 94 */
95 properties() { 95 properties() {
96 return this._properties || null; 96 return this._properties || null;
97 } 97 }
98 98
99 /** 99 /**
100 * @return {?WebInspector.AccessibilityNode} 100 * @return {?WebInspector.AccessibilityNode}
101 */ 101 */
102 parentNode() { 102 parentNode() {
103 if (!this._parentId) 103 return this._parentNode;
104 return null; 104 }
105 return this._accessibilityModel.axNodeForId(this._parentId); 105
106 /**
107 * @param {?WebInspector.AccessibilityNode} parentNode
108 */
109 _setParentNode(parentNode) {
110 this._parentNode = parentNode;
111 }
112
113 /**
114 * @return {boolean}
115 */
116 isDOMNode() {
117 return !!this._backendDomNodeId;
118 }
119
120 /**
121 * @return {?WebInspector.DOMNode}
122 */
123 domNode() {
124 return this._domNode || null;
125 }
126
127 /**
128 * @param {?WebInspector.DOMNode} domNode
129 */
130 _setDOMNode(domNode) {
131 this._domNode = domNode;
132 if (domNode)
133 this._accessibilityModel.setAXNodeForDOMNode(domNode, this);
134 }
135
136 /**
137 * @return {!Promise<?WebInspector.DOMNode>}
138 */
139 resolveDOMNode() {
140 if (this._domNode)
141 return Promise.resolve(this._domNode);
142 if (!this._backendDomNodeId)
143 return Promise.resolve(/** @type {?WebInspector.DOMNode} */ (null));
144
145 var deferredNode = new WebInspector.DeferredDOMNode(this.target(), this._bac kendDomNodeId);
146 return deferredNode.resolvePromise().then((domNode) => {
147 this._setDOMNode(domNode);
148 return domNode;
149 });
150 }
151
152 /**
153 * @return {!Array<!WebInspector.AccessibilityNode>}
154 */
155 children() {
156 var children = [];
157 if (!this._childIds)
158 return children;
159
160 for (var childId of this._childIds) {
161 var child = this._accessibilityModel.axNodeForId(childId);
162 if (child)
163 children.push(child);
164 }
165
166 return children;
167 }
168
169 /**
170 * @return {number}
171 */
172 numChildren() {
173 if (!this._childIds)
174 return 0;
175 return this._childIds.length;
176 }
177
178 /**
179 * @return {boolean}
180 */
181 hasOnlyUnloadedChildren() {
182 if (!this._childIds || !this._childIds.length)
183 return false;
184
185 return !this._childIds.some((id) => this._accessibilityModel.axNodeForId(id) !== undefined);
186 }
187
188 /**
189 * TODO(aboxhall): Remove once protocol is stable.
190 * @param {!WebInspector.AccessibilityNode} inspectedNode
191 * @param {string=} leadingSpace
192 * @return {string}
193 */
194 printSelfAndChildren(inspectedNode, leadingSpace) {
195 var string = leadingSpace || '';
196 if (this._role)
197 string += this._role.value;
198 else
199 string += '<no role>';
200 string += (this._name ? ' ' + this._name.value : '');
201 string += ' ' + this._id;
202 if (this._domNode)
203 string += ' (' + this._domNode.nodeName() + ')';
204 if (this === inspectedNode)
205 string += ' *';
206 for (var child of this.children())
207 string += '\n' + child.printSelfAndChildren(inspectedNode, (leadingSpace | | '') + ' ');
208 return string;
106 } 209 }
107 }; 210 };
108 211
109 /** 212 /**
110 * @unrestricted 213 * @unrestricted
111 */ 214 */
112 WebInspector.AccessibilityModel = class extends WebInspector.SDKModel { 215 WebInspector.AccessibilityModel = class extends WebInspector.SDKModel {
113 /** 216 /**
114 * @param {!WebInspector.Target} target 217 * @param {!WebInspector.Target} target
115 */ 218 */
116 constructor(target) { 219 constructor(target) {
117 super(WebInspector.AccessibilityModel, target); 220 super(WebInspector.AccessibilityModel, target);
118 this._agent = target.accessibilityAgent(); 221 this._agent = target.accessibilityAgent();
119 222
120 /** @type {!Map<string, !WebInspector.AccessibilityNode>} */ 223 /** @type {!Map<string, !WebInspector.AccessibilityNode>} */
121 this._axIdToAXNode = new Map(); 224 this._axIdToAXNode = new Map();
225 this._domNodeToAXNode = new Map();
122 } 226 }
123 227
124 /** 228 /**
125 * @param {!WebInspector.Target} target 229 * @param {!WebInspector.Target} target
126 * @return {!WebInspector.AccessibilityModel} 230 * @return {!WebInspector.AccessibilityModel}
127 */ 231 */
128 static fromTarget(target) { 232 static fromTarget(target) {
129 if (!target[WebInspector.AccessibilityModel._symbol]) 233 if (!target[WebInspector.AccessibilityModel._symbol])
130 target[WebInspector.AccessibilityModel._symbol] = new WebInspector.Accessi bilityModel(target); 234 target[WebInspector.AccessibilityModel._symbol] = new WebInspector.Accessi bilityModel(target);
131 235
132 return target[WebInspector.AccessibilityModel._symbol]; 236 return target[WebInspector.AccessibilityModel._symbol];
133 } 237 }
134 238
135 /** 239 /**
136 * @param {string} axId
137 * @return {?WebInspector.AccessibilityNode}
138 */
139 axNodeForId(axId) {
140 return this._axIdToAXNode.get(axId);
141 }
142
143 /**
144 * @param {string} axId
145 * @param {!WebInspector.AccessibilityNode} axNode
146 */
147 _setAXNodeForAXId(axId, axNode) {
148 this._axIdToAXNode.set(axId, axNode);
149 }
150
151 /**
152 * @param {!WebInspector.DOMNode} node 240 * @param {!WebInspector.DOMNode} node
153 * @return {!Promise<?Array<!WebInspector.AccessibilityNode>>} 241 * @return {!Promise<?WebInspector.AccessibilityNode>}
154 */ 242 */
155 getAXNodeChain(node) { 243 setDOMNode(node) {
156 this._axIdToAXNode.clear(); 244 this._axIdToAXNode.clear();
245 this._inspectedDOMNode = node;
157 246
247 return this._requestPartialAXTree(node);
248 }
249
250 /**
251 * @param {!WebInspector.DOMNode} node
252 * @return {!Promise}
253 */
254 _requestPartialAXTree(node) {
158 /** 255 /**
159 * @this {WebInspector.AccessibilityModel} 256 * @this {WebInspector.AccessibilityModel}
160 * @param {?string} error 257 * @param {?string} error
161 * @param {!Array<!AccessibilityAgent.AXNode>=} payloads 258 * @param {!Array<!AccessibilityAgent.AXNode>=} payloads
162 * @return {?Array<!WebInspector.AccessibilityNode>}
163 */ 259 */
164 function parsePayload(error, payloads) { 260 function parsePayload(error, payloads) {
165 if (error) { 261 if (error) {
166 console.error('AccessibilityAgent.getAXNodeChain(): ' + error); 262 console.error('AccessibilityAgent.getAXNodeChain(): ' + error);
167 return null; 263 return null;
168 } 264 }
169 265
170 if (!payloads) 266 if (!payloads)
171 return null; 267 return;
172 268
173 var nodes = [];
174 for (var payload of payloads) 269 for (var payload of payloads)
175 nodes.push(new WebInspector.AccessibilityNode(this, payload)); 270 new WebInspector.AccessibilityNode(this, payload);
176 271
177 return nodes; 272 for (var axNode of this._axIdToAXNode.values()) {
273 for (var axChild of axNode.children()) {
274 axChild._setParentNode(axNode);
275 }
276 }
178 } 277 }
179 return this._agent.getAXNodeChain(node.id, true, parsePayload.bind(this)); 278 return this._agent.getPartialAXTree(node.id, true, parsePayload.bind(this));
279 }
280
281 /**
282 * @return {?WebInspector.AccessibilityNode}
283 */
284 getInspectedAXNode() {
285 return this._domNodeToAXNode.get(this._inspectedDOMNode);
286 }
287
288 /**
289 * @param {string} axId
290 * @return {?WebInspector.AccessibilityNode}
291 */
292 axNodeForId(axId) {
293 return this._axIdToAXNode.get(axId);
294 }
295
296 /**
297 * @param {string} axId
298 * @param {!WebInspector.AccessibilityNode} axNode
299 */
300 _setAXNodeForAXId(axId, axNode) {
301 this._axIdToAXNode.set(axId, axNode);
302 }
303
304 /**
305 * @param {!WebInspector.DOMNode} domNode
306 * @return {?WebInspector.AccessibilityNode}
307 */
308 axNodeForDOMNode(domNode) {
309 return this._domNodeToAXNode.get(domNode);
310 }
311
312 /**
313 * @param {!WebInspector.DOMNode} domNode
314 * @param {!WebInspector.AccessibilityNode} axNode
315 */
316 setAXNodeForDOMNode(domNode, axNode) {
317 this._domNodeToAXNode.set(domNode, axNode);
318 }
319
320 // TODO(aboxhall): Remove once protocol is stable.
321 logTree() {
322 var inspectedNode = this._domNodeToAXNode.get(this._inspectedDOMNode);
323 if (!inspectedNode)
324 return;
325 var rootNode = inspectedNode;
326 while (rootNode.parentNode())
327 rootNode = rootNode.parentNode();
328 console.log(rootNode.printSelfAndChildren(inspectedNode));
329 }
330
331 /**
332 * @return {!Promise}
333 */
334 resolveAllDOMNodes() {
335 var promises = [];
336 for (var axNode of this._axIdToAXNode.values())
337 promises.push(axNode.resolveDOMNode());
338 return Promise.all(promises);
180 } 339 }
181 }; 340 };
182 341
183 WebInspector.AccessibilityModel._symbol = Symbol('AccessibilityModel'); 342 WebInspector.AccessibilityModel._symbol = Symbol('AccessibilityModel');
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698