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 Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa ne { | 5 Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa ne { |
6 /** | 6 /** |
7 * @param {!Accessibility.AccessibilitySidebarView} axSidebarView | 7 * @param {!Accessibility.AccessibilitySidebarView} axSidebarView |
8 */ | 8 */ |
9 constructor(axSidebarView) { | 9 constructor(axSidebarView) { |
10 super(Common.UIString('Accessibility Tree')); | 10 super(Common.UIString('Accessibility Tree')); |
11 | 11 |
12 this.element.classList.add('ax-subpane'); | 12 this.element.classList.add('ax-subpane'); |
13 UI.ARIAUtils.markAsTree(this.element); | |
13 | 14 |
14 this._axSidebarView = axSidebarView; | 15 this._axSidebarView = axSidebarView; |
15 | 16 |
16 /** @type {?Accessibility.AXBreadcrumb} */ | 17 /** @type {?Accessibility.AXBreadcrumb} */ |
17 this._preselectedBreadcrumb = null; | 18 this._preselectedBreadcrumb = null; |
18 | 19 |
19 this._selectedByUser = true; | 20 this._selectedByUser = true; |
20 | 21 |
21 this._hoveredBreadcrumb = null; | 22 this._hoveredBreadcrumb = null; |
22 this._rootElement = this.element.createChild('div', 'ax-breadcrumbs'); | 23 this._rootElement = this.element.createChild('div', 'ax-breadcrumbs'); |
(...skipping 23 matching lines...) Expand all Loading... | |
46 var ancestorChain = []; | 47 var ancestorChain = []; |
47 var ancestor = axNode; | 48 var ancestor = axNode; |
48 while (ancestor) { | 49 while (ancestor) { |
49 ancestorChain.push(ancestor); | 50 ancestorChain.push(ancestor); |
50 ancestor = ancestor.parentNode(); | 51 ancestor = ancestor.parentNode(); |
51 } | 52 } |
52 ancestorChain.reverse(); | 53 ancestorChain.reverse(); |
53 | 54 |
54 var depth = 0; | 55 var depth = 0; |
55 var breadcrumb = null; | 56 var breadcrumb = null; |
57 var parent = null; | |
56 for (ancestor of ancestorChain) { | 58 for (ancestor of ancestorChain) { |
57 breadcrumb = new Accessibility.AXBreadcrumb(ancestor, depth, (ancestor === axNode)); | 59 breadcrumb = new Accessibility.AXBreadcrumb(ancestor, depth, (ancestor === axNode)); |
58 if (ancestor.children().length) | 60 if (parent) |
59 breadcrumb.element().classList.add('parent'); | 61 parent.appendChild(breadcrumb); |
60 this._rootElement.appendChild(breadcrumb.element()); | 62 else |
63 this._rootElement.appendChild(breadcrumb.element()); | |
64 parent = breadcrumb; | |
61 depth++; | 65 depth++; |
62 } | 66 } |
63 | 67 |
64 var inspectedNodeBreadcrumb = breadcrumb; | 68 var inspectedNodeBreadcrumb = breadcrumb; |
65 inspectedNodeBreadcrumb.setPreselected(true, this._selectedByUser); | 69 inspectedNodeBreadcrumb.setPreselected(true, this._selectedByUser); |
66 | 70 |
67 this._setPreselectedBreadcrumb(inspectedNodeBreadcrumb); | 71 this._setPreselectedBreadcrumb(inspectedNodeBreadcrumb); |
68 | 72 |
69 for (var child of axNode.children()) { | 73 for (var child of axNode.children()) { |
70 var childBreadcrumb = new Accessibility.AXBreadcrumb(child, depth, false); | 74 var childBreadcrumb = new Accessibility.AXBreadcrumb(child, depth, false); |
71 this._rootElement.appendChild(childBreadcrumb.element()); | 75 inspectedNodeBreadcrumb.appendChild(childBreadcrumb); |
72 } | 76 } |
73 | 77 |
74 this._selectedByUser = false; | 78 this._selectedByUser = false; |
75 } | 79 } |
76 | 80 |
77 /** | 81 /** |
78 * @override | 82 * @override |
79 */ | 83 */ |
80 wasShown() { | 84 wasShown() { |
81 this._selectedByUser = true; | 85 this._selectedByUser = true; |
(...skipping 26 matching lines...) Expand all Loading... | |
108 handled = this._inspectDOMNode(this._preselectedBreadcrumb.axNode()); | 112 handled = this._inspectDOMNode(this._preselectedBreadcrumb.axNode()); |
109 | 113 |
110 if (handled) | 114 if (handled) |
111 event.consume(true); | 115 event.consume(true); |
112 } | 116 } |
113 | 117 |
114 /** | 118 /** |
115 * @return {boolean} | 119 * @return {boolean} |
116 */ | 120 */ |
117 _preselectPrevious() { | 121 _preselectPrevious() { |
118 var previousElement = this._preselectedBreadcrumb.element().previousSibling; | 122 var previousBreadcrumb = this._preselectedBreadcrumb.previousBreadcrumb(); |
119 if (!previousElement) | 123 if (!previousBreadcrumb) |
120 return false; | 124 return false; |
121 this._selectedByUser = true; | 125 this._selectedByUser = true; |
122 this._setPreselectedBreadcrumb(previousElement.breadcrumb); | 126 this._setPreselectedBreadcrumb(previousBreadcrumb); |
123 return true; | 127 return true; |
124 } | 128 } |
125 | 129 |
126 /** | 130 /** |
127 * @return {boolean} | 131 * @return {boolean} |
128 */ | 132 */ |
129 _preselectNext() { | 133 _preselectNext() { |
130 var nextElement = this._preselectedBreadcrumb.element().nextSibling; | 134 var nextBreadcrumb = this._preselectedBreadcrumb.nextBreadcrumb(); |
131 if (!nextElement) | 135 if (!nextBreadcrumb) |
132 return false; | 136 return false; |
133 this._selectedByUser = true; | 137 this._selectedByUser = true; |
134 this._setPreselectedBreadcrumb(nextElement.breadcrumb); | 138 this._setPreselectedBreadcrumb(nextBreadcrumb); |
135 return true; | 139 return true; |
136 } | 140 } |
137 | 141 |
138 /** | 142 /** |
139 * @param {?Accessibility.AXBreadcrumb} breadcrumb | 143 * @param {?Accessibility.AXBreadcrumb} breadcrumb |
140 */ | 144 */ |
141 _setPreselectedBreadcrumb(breadcrumb) { | 145 _setPreselectedBreadcrumb(breadcrumb) { |
142 if (breadcrumb === this._preselectedBreadcrumb) | 146 if (breadcrumb === this._preselectedBreadcrumb) |
143 return; | 147 return; |
144 if (this._preselectedBreadcrumb) | 148 if (this._preselectedBreadcrumb) |
145 this._preselectedBreadcrumb.setPreselected(false, this._selectedByUser); | 149 this._preselectedBreadcrumb.setPreselected(false, this._selectedByUser); |
146 this._preselectedBreadcrumb = breadcrumb; | 150 this._preselectedBreadcrumb = breadcrumb; |
147 if (this._preselectedBreadcrumb) | 151 if (this._preselectedBreadcrumb) |
148 this._preselectedBreadcrumb.setPreselected(true, this._selectedByUser); | 152 this._preselectedBreadcrumb.setPreselected(true, this._selectedByUser); |
149 else if (this._selectedByUser) | 153 else if (this._selectedByUser) |
150 SDK.OverlayModel.hideDOMNodeHighlight(); | 154 SDK.OverlayModel.hideDOMNodeHighlight(); |
151 } | 155 } |
152 | 156 |
153 /** | 157 /** |
154 * @param {!Event} event | 158 * @param {!Event} event |
155 */ | 159 */ |
156 _onMouseLeave(event) { | 160 _onMouseLeave(event) { |
157 this._setHoveredBreadcrumb(null); | 161 this._setHoveredBreadcrumb(null); |
158 } | 162 } |
159 | 163 |
160 /** | 164 /** |
161 * @param {!Event} event | 165 * @param {!Event} event |
162 */ | 166 */ |
163 _onMouseMove(event) { | 167 _onMouseMove(event) { |
164 var breadcrumbElement = event.target.enclosingNodeOrSelfWithClass('ax-node') ; | 168 var breadcrumbElement = event.target.enclosingNodeOrSelfWithClass('ax-breadc rumb'); |
165 if (!breadcrumbElement) { | 169 if (!breadcrumbElement) { |
166 this._setHoveredBreadcrumb(null); | 170 this._setHoveredBreadcrumb(null); |
167 return; | 171 return; |
168 } | 172 } |
169 var breadcrumb = breadcrumbElement.breadcrumb; | 173 var breadcrumb = breadcrumbElement.breadcrumb; |
170 if (breadcrumb.preselected() || breadcrumb.inspected() || !breadcrumb.isDOMN ode()) | 174 if (breadcrumb.preselected() || breadcrumb.inspected() || !breadcrumb.isDOMN ode()) |
171 return; | 175 return; |
172 this._setHoveredBreadcrumb(breadcrumb); | 176 this._setHoveredBreadcrumb(breadcrumb); |
173 } | 177 } |
174 | 178 |
175 /** | 179 /** |
176 * @param {!Event} event | 180 * @param {!Event} event |
177 */ | 181 */ |
178 _onClick(event) { | 182 _onClick(event) { |
179 var breadcrumbElement = event.target.enclosingNodeOrSelfWithClass('ax-node') ; | 183 var breadcrumbElement = event.target.enclosingNodeOrSelfWithClass('ax-breadc rumb'); |
180 if (!breadcrumbElement) { | 184 if (!breadcrumbElement) { |
181 this._setHoveredBreadcrumb(null); | 185 this._setHoveredBreadcrumb(null); |
182 return; | 186 return; |
183 } | 187 } |
184 var breadcrumb = breadcrumbElement.breadcrumb; | 188 var breadcrumb = breadcrumbElement.breadcrumb; |
185 if (breadcrumb.inspected()) { | 189 if (breadcrumb.inspected()) { |
186 // If the user is clicking the inspected breadcrumb, they probably want to | 190 // If the user is clicking the inspected breadcrumb, they probably want to |
187 // focus it. | 191 // focus it. |
188 breadcrumb.element().focus(); | 192 breadcrumb.element().focus(); |
189 return; | 193 return; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
242 Accessibility.AXBreadcrumb = class { | 246 Accessibility.AXBreadcrumb = class { |
243 /** | 247 /** |
244 * @param {!Accessibility.AccessibilityNode} axNode | 248 * @param {!Accessibility.AccessibilityNode} axNode |
245 * @param {number} depth | 249 * @param {number} depth |
246 * @param {boolean} inspected | 250 * @param {boolean} inspected |
247 */ | 251 */ |
248 constructor(axNode, depth, inspected) { | 252 constructor(axNode, depth, inspected) { |
249 /** @type {!Accessibility.AccessibilityNode} */ | 253 /** @type {!Accessibility.AccessibilityNode} */ |
250 this._axNode = axNode; | 254 this._axNode = axNode; |
251 | 255 |
252 this._element = createElementWithClass('div', 'ax-node'); | 256 this._element = createElementWithClass('div', 'ax-breadcrumb'); |
257 UI.ARIAUtils.markAsTreeitem(this._element); | |
253 this._element.breadcrumb = this; | 258 this._element.breadcrumb = this; |
254 | 259 |
260 this._nodeElement = createElementWithClass('div', 'ax-node'); | |
261 this._element.appendChild(this._nodeElement); | |
262 this._nodeWrapper = createElementWithClass('div', 'wrapper'); | |
263 this._nodeElement.appendChild(this._nodeWrapper); | |
264 | |
255 this._selectionElement = createElementWithClass('div', 'selection fill'); | 265 this._selectionElement = createElementWithClass('div', 'selection fill'); |
256 this._element.appendChild(this._selectionElement); | 266 this._nodeElement.appendChild(this._selectionElement); |
257 | 267 |
258 this._nodeWrapper = createElementWithClass('span', 'wrapper'); | 268 this._childrenGroupElement = createElementWithClass('div', 'children'); |
259 this._element.appendChild(this._nodeWrapper); | 269 UI.ARIAUtils.markAsGroup(this._childrenGroupElement); |
270 this._element.appendChild(this._childrenGroupElement); | |
260 | 271 |
261 this._hovered = false; | 272 this._hovered = false; |
262 this._preselected = false; | 273 this._preselected = false; |
274 this._children = []; | |
lushnikov
2017/07/06 15:49:09
let's add jsdoc for this
aboxhall
2017/07/06 22:14:14
Done.
| |
275 this._parent = null; | |
263 | 276 |
264 this._inspected = inspected; | 277 this._inspected = inspected; |
265 this.element().classList.toggle('inspected', inspected); | 278 this._nodeElement.classList.toggle('inspected', inspected); |
266 | 279 |
267 this._element.style.paddingLeft = (16 * depth + 4) + 'px'; | 280 this._nodeElement.style.paddingLeft = (16 * depth + 4) + 'px'; |
268 | 281 |
269 if (this._axNode.ignored()) { | 282 if (this._axNode.ignored()) { |
270 this._appendIgnoredNodeElement(); | 283 this._appendIgnoredNodeElement(); |
271 } else { | 284 } else { |
272 this._appendRoleElement(this._axNode.role()); | 285 this._appendRoleElement(this._axNode.role()); |
273 if (this._axNode.name() && this._axNode.name().value) { | 286 if (this._axNode.name() && this._axNode.name().value) { |
274 this._nodeWrapper.createChild('span', 'separator').textContent = '\u00A0 '; | 287 this._nodeWrapper.createChild('span', 'separator').textContent = '\u00A0 '; |
275 this._appendNameElement(/** @type {string} */ (this._axNode.name().value )); | 288 this._appendNameElement(/** @type {string} */ (this._axNode.name().value )); |
276 } | 289 } |
277 } | 290 } |
278 | 291 |
279 if (this._axNode.hasOnlyUnloadedChildren()) | 292 if (this._axNode.hasOnlyUnloadedChildren()) |
280 this._element.classList.add('children-unloaded'); | 293 this._nodeElement.classList.add('children-unloaded'); |
281 | 294 |
282 if (!this._axNode.isDOMNode()) | 295 if (!this._axNode.isDOMNode()) |
283 this._element.classList.add('no-dom-node'); | 296 this._nodeElement.classList.add('no-dom-node'); |
284 } | 297 } |
285 | 298 |
286 /** | 299 /** |
287 * @return {!Element} | 300 * @return {!Element} |
288 */ | 301 */ |
289 element() { | 302 element() { |
290 return this._element; | 303 return this._element; |
291 } | 304 } |
292 | 305 |
293 /** | 306 /** |
307 * @param {!Accessibility.AXBreadcrumb} breadcrumb | |
308 */ | |
309 appendChild(breadcrumb) { | |
310 this._children.push(breadcrumb); | |
311 breadcrumb.setParent(this); | |
312 this._nodeElement.classList.add('parent'); | |
313 UI.ARIAUtils.setExpanded(this._element, true); | |
314 this._childrenGroupElement.appendChild(breadcrumb.element()); | |
315 } | |
316 | |
317 /** | |
318 * @param {!Accessibility.AXBreadcrumb} breadcrumb | |
319 */ | |
320 setParent(breadcrumb) { | |
321 this._parent = breadcrumb; | |
322 } | |
323 | |
324 /** | |
294 * @return {boolean} | 325 * @return {boolean} |
295 */ | 326 */ |
296 preselected() { | 327 preselected() { |
297 return this._preselected; | 328 return this._preselected; |
298 } | 329 } |
299 | 330 |
300 /** | 331 /** |
301 * @param {boolean} preselected | 332 * @param {boolean} preselected |
302 * @param {boolean} selectedByUser | 333 * @param {boolean} selectedByUser |
303 */ | 334 */ |
304 setPreselected(preselected, selectedByUser) { | 335 setPreselected(preselected, selectedByUser) { |
305 if (this._preselected === preselected) | 336 if (this._preselected === preselected) |
306 return; | 337 return; |
307 this._preselected = preselected; | 338 this._preselected = preselected; |
308 this.element().classList.toggle('preselected', preselected); | 339 this._nodeElement.classList.toggle('preselected', preselected); |
309 if (preselected) | 340 if (preselected) |
310 this.element().setAttribute('tabIndex', 0); | 341 this._nodeElement.setAttribute('tabIndex', 0); |
311 else | 342 else |
312 this.element().removeAttribute('tabIndex'); | 343 this._nodeElement.removeAttribute('tabIndex'); |
313 if (this._preselected) { | 344 if (this._preselected) { |
314 if (selectedByUser) | 345 if (selectedByUser) |
315 this.element().focus(); | 346 this._nodeElement.focus(); |
316 if (!this._inspected) | 347 if (!this._inspected) |
317 this._axNode.highlightDOMNode(); | 348 this._axNode.highlightDOMNode(); |
318 else | 349 else |
319 SDK.OverlayModel.hideDOMNodeHighlight(); | 350 SDK.OverlayModel.hideDOMNodeHighlight(); |
320 } | 351 } |
321 } | 352 } |
322 | 353 |
323 /** | 354 /** |
324 * @param {boolean} hovered | 355 * @param {boolean} hovered |
325 */ | 356 */ |
326 setHovered(hovered) { | 357 setHovered(hovered) { |
327 if (this._hovered === hovered) | 358 if (this._hovered === hovered) |
328 return; | 359 return; |
329 this._hovered = hovered; | 360 this._hovered = hovered; |
330 this.element().classList.toggle('hovered', hovered); | 361 this._nodeElement.classList.toggle('hovered', hovered); |
331 if (this._hovered) { | 362 if (this._hovered) { |
332 this.element().classList.toggle('hovered', true); | 363 this._nodeElement.classList.toggle('hovered', true); |
333 this._axNode.highlightDOMNode(); | 364 this._axNode.highlightDOMNode(); |
334 } | 365 } |
335 } | 366 } |
336 | 367 |
337 /** | 368 /** |
338 * @return {!Accessibility.AccessibilityNode} | 369 * @return {!Accessibility.AccessibilityNode} |
339 */ | 370 */ |
340 axNode() { | 371 axNode() { |
341 return this._axNode; | 372 return this._axNode; |
342 } | 373 } |
343 | 374 |
344 /** | 375 /** |
345 * @return {boolean} | 376 * @return {boolean} |
346 */ | 377 */ |
347 inspected() { | 378 inspected() { |
348 return this._inspected; | 379 return this._inspected; |
349 } | 380 } |
350 | 381 |
351 /** | 382 /** |
352 * @return {boolean} | 383 * @return {boolean} |
353 */ | 384 */ |
354 isDOMNode() { | 385 isDOMNode() { |
355 return this._axNode.isDOMNode(); | 386 return this._axNode.isDOMNode(); |
356 } | 387 } |
357 | 388 |
358 /** | 389 /** |
390 * @return {?Accessibility.AXBreadcrumb} | |
391 */ | |
392 nextBreadcrumb() { | |
393 if (this._children.length) | |
394 return this._children[0]; | |
395 var nextSibling = this.element().nextSibling; | |
396 if (nextSibling) | |
397 return nextSibling.breadcrumb; | |
398 return null; | |
399 } | |
400 | |
401 /** | |
402 * @return {?Accessibility.AXBreadcrumb} | |
403 */ | |
404 previousBreadcrumb() { | |
405 var previousSibling = this.element().previousSibling; | |
406 if (previousSibling) | |
407 return previousSibling.breadcrumb; | |
408 | |
409 return this._parent; | |
410 } | |
411 | |
412 /** | |
359 * @param {string} name | 413 * @param {string} name |
360 */ | 414 */ |
361 _appendNameElement(name) { | 415 _appendNameElement(name) { |
362 var nameElement = createElement('span'); | 416 var nameElement = createElement('span'); |
363 nameElement.textContent = '"' + name + '"'; | 417 nameElement.textContent = '"' + name + '"'; |
364 nameElement.classList.add('ax-readable-string'); | 418 nameElement.classList.add('ax-readable-string'); |
365 this._nodeWrapper.appendChild(nameElement); | 419 this._nodeWrapper.appendChild(nameElement); |
366 } | 420 } |
367 | 421 |
368 /** | 422 /** |
(...skipping 16 matching lines...) Expand all Loading... | |
385 ignoredNodeElement.classList.add('ax-breadcrumbs-ignored-node'); | 439 ignoredNodeElement.classList.add('ax-breadcrumbs-ignored-node'); |
386 this._nodeWrapper.appendChild(ignoredNodeElement); | 440 this._nodeWrapper.appendChild(ignoredNodeElement); |
387 } | 441 } |
388 }; | 442 }; |
389 | 443 |
390 /** @type {!Object<string, string>} */ | 444 /** @type {!Object<string, string>} */ |
391 Accessibility.AXBreadcrumb.RoleStyles = { | 445 Accessibility.AXBreadcrumb.RoleStyles = { |
392 internalRole: 'ax-internal-role', | 446 internalRole: 'ax-internal-role', |
393 role: 'ax-role', | 447 role: 'ax-role', |
394 }; | 448 }; |
OLD | NEW |