| 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 Accessibility.AXBreadcrumb = class { | 271 Accessibility.AXBreadcrumb = class { |
| 268 /** | 272 /** |
| 269 * @param {!Accessibility.AccessibilityNode} axNode | 273 * @param {!Accessibility.AccessibilityNode} axNode |
| 270 * @param {number} depth | 274 * @param {number} depth |
| 271 * @param {boolean} inspected | 275 * @param {boolean} inspected |
| 272 */ | 276 */ |
| 273 constructor(axNode, depth, inspected) { | 277 constructor(axNode, depth, inspected) { |
| 274 /** @type {!Accessibility.AccessibilityNode} */ | 278 /** @type {!Accessibility.AccessibilityNode} */ |
| 275 this._axNode = axNode; | 279 this._axNode = axNode; |
| 276 | 280 |
| 277 this._element = createElementWithClass('div', 'ax-node'); | 281 this._element = createElementWithClass('div', 'ax-breadcrumb'); |
| 282 UI.ARIAUtils.markAsTreeitem(this._element); |
| 278 this._element.breadcrumb = this; | 283 this._element.breadcrumb = this; |
| 279 | 284 |
| 285 this._nodeElement = createElementWithClass('div', 'ax-node'); |
| 286 this._element.appendChild(this._nodeElement); |
| 287 this._nodeWrapper = createElementWithClass('div', 'wrapper'); |
| 288 this._nodeElement.appendChild(this._nodeWrapper); |
| 289 |
| 280 this._selectionElement = createElementWithClass('div', 'selection fill'); | 290 this._selectionElement = createElementWithClass('div', 'selection fill'); |
| 281 this._element.appendChild(this._selectionElement); | 291 this._nodeElement.appendChild(this._selectionElement); |
| 282 | 292 |
| 283 this._nodeWrapper = createElementWithClass('span', 'wrapper'); | 293 this._childrenGroupElement = createElementWithClass('div', 'children'); |
| 284 this._element.appendChild(this._nodeWrapper); | 294 UI.ARIAUtils.markAsGroup(this._childrenGroupElement); |
| 295 this._element.appendChild(this._childrenGroupElement); |
| 285 | 296 |
| 297 /** @type !Array<!Accessibility.AXBreadcrumb> */ |
| 298 this._children = []; |
| 286 this._hovered = false; | 299 this._hovered = false; |
| 287 this._preselected = false; | 300 this._preselected = false; |
| 301 this._parent = null; |
| 288 | 302 |
| 289 this._inspected = inspected; | 303 this._inspected = inspected; |
| 290 this.element().classList.toggle('inspected', inspected); | 304 this._nodeElement.classList.toggle('inspected', inspected); |
| 291 | 305 |
| 292 this._element.style.paddingLeft = (16 * depth + 4) + 'px'; | 306 this._nodeElement.style.paddingLeft = (16 * depth + 4) + 'px'; |
| 293 | 307 |
| 294 if (this._axNode.ignored()) { | 308 if (this._axNode.ignored()) { |
| 295 this._appendIgnoredNodeElement(); | 309 this._appendIgnoredNodeElement(); |
| 296 } else { | 310 } else { |
| 297 this._appendRoleElement(this._axNode.role()); | 311 this._appendRoleElement(this._axNode.role()); |
| 298 if (this._axNode.name() && this._axNode.name().value) { | 312 if (this._axNode.name() && this._axNode.name().value) { |
| 299 this._nodeWrapper.createChild('span', 'separator').textContent = '\u00A0
'; | 313 this._nodeWrapper.createChild('span', 'separator').textContent = '\u00A0
'; |
| 300 this._appendNameElement(/** @type {string} */ (this._axNode.name().value
)); | 314 this._appendNameElement(/** @type {string} */ (this._axNode.name().value
)); |
| 301 } | 315 } |
| 302 } | 316 } |
| 303 | 317 |
| 304 if (this._axNode.hasOnlyUnloadedChildren()) | 318 if (this._axNode.hasOnlyUnloadedChildren()) |
| 305 this._element.classList.add('children-unloaded'); | 319 this._nodeElement.classList.add('children-unloaded'); |
| 306 | 320 |
| 307 if (!this._axNode.isDOMNode()) | 321 if (!this._axNode.isDOMNode()) |
| 308 this._element.classList.add('no-dom-node'); | 322 this._nodeElement.classList.add('no-dom-node'); |
| 309 } | 323 } |
| 310 | 324 |
| 311 /** | 325 /** |
| 312 * @return {!Element} | 326 * @return {!Element} |
| 313 */ | 327 */ |
| 314 element() { | 328 element() { |
| 315 return this._element; | 329 return this._element; |
| 316 } | 330 } |
| 317 | 331 |
| 318 /** | 332 /** |
| 333 * @param {!Accessibility.AXBreadcrumb} breadcrumb |
| 334 */ |
| 335 appendChild(breadcrumb) { |
| 336 this._children.push(breadcrumb); |
| 337 breadcrumb.setParent(this); |
| 338 this._nodeElement.classList.add('parent'); |
| 339 UI.ARIAUtils.setExpanded(this._element, true); |
| 340 this._childrenGroupElement.appendChild(breadcrumb.element()); |
| 341 } |
| 342 |
| 343 /** |
| 344 * @param {!Accessibility.AXBreadcrumb} breadcrumb |
| 345 */ |
| 346 setParent(breadcrumb) { |
| 347 this._parent = breadcrumb; |
| 348 } |
| 349 |
| 350 /** |
| 319 * @return {boolean} | 351 * @return {boolean} |
| 320 */ | 352 */ |
| 321 preselected() { | 353 preselected() { |
| 322 return this._preselected; | 354 return this._preselected; |
| 323 } | 355 } |
| 324 | 356 |
| 325 /** | 357 /** |
| 326 * @param {boolean} preselected | 358 * @param {boolean} preselected |
| 327 * @param {boolean} selectedByUser | 359 * @param {boolean} selectedByUser |
| 328 */ | 360 */ |
| 329 setPreselected(preselected, selectedByUser) { | 361 setPreselected(preselected, selectedByUser) { |
| 330 if (this._preselected === preselected) | 362 if (this._preselected === preselected) |
| 331 return; | 363 return; |
| 332 this._preselected = preselected; | 364 this._preselected = preselected; |
| 333 this.element().classList.toggle('preselected', preselected); | 365 this._nodeElement.classList.toggle('preselected', preselected); |
| 334 if (preselected) | 366 if (preselected) |
| 335 this.element().setAttribute('tabIndex', 0); | 367 this._nodeElement.setAttribute('tabIndex', 0); |
| 336 else | 368 else |
| 337 this.element().removeAttribute('tabIndex'); | 369 this._nodeElement.removeAttribute('tabIndex'); |
| 338 if (this._preselected) { | 370 if (this._preselected) { |
| 339 if (selectedByUser) | 371 if (selectedByUser) |
| 340 this.element().focus(); | 372 this._nodeElement.focus(); |
| 341 if (!this._inspected) | 373 if (!this._inspected) |
| 342 this._axNode.highlightDOMNode(); | 374 this._axNode.highlightDOMNode(); |
| 343 else | 375 else |
| 344 SDK.OverlayModel.hideDOMNodeHighlight(); | 376 SDK.OverlayModel.hideDOMNodeHighlight(); |
| 345 } | 377 } |
| 346 } | 378 } |
| 347 | 379 |
| 348 /** | 380 /** |
| 349 * @param {boolean} hovered | 381 * @param {boolean} hovered |
| 350 */ | 382 */ |
| 351 setHovered(hovered) { | 383 setHovered(hovered) { |
| 352 if (this._hovered === hovered) | 384 if (this._hovered === hovered) |
| 353 return; | 385 return; |
| 354 this._hovered = hovered; | 386 this._hovered = hovered; |
| 355 this.element().classList.toggle('hovered', hovered); | 387 this._nodeElement.classList.toggle('hovered', hovered); |
| 356 if (this._hovered) { | 388 if (this._hovered) { |
| 357 this.element().classList.toggle('hovered', true); | 389 this._nodeElement.classList.toggle('hovered', true); |
| 358 this._axNode.highlightDOMNode(); | 390 this._axNode.highlightDOMNode(); |
| 359 } | 391 } |
| 360 } | 392 } |
| 361 | 393 |
| 362 /** | 394 /** |
| 363 * @return {!Accessibility.AccessibilityNode} | 395 * @return {!Accessibility.AccessibilityNode} |
| 364 */ | 396 */ |
| 365 axNode() { | 397 axNode() { |
| 366 return this._axNode; | 398 return this._axNode; |
| 367 } | 399 } |
| 368 | 400 |
| 369 /** | 401 /** |
| 370 * @return {boolean} | 402 * @return {boolean} |
| 371 */ | 403 */ |
| 372 inspected() { | 404 inspected() { |
| 373 return this._inspected; | 405 return this._inspected; |
| 374 } | 406 } |
| 375 | 407 |
| 376 /** | 408 /** |
| 377 * @return {boolean} | 409 * @return {boolean} |
| 378 */ | 410 */ |
| 379 isDOMNode() { | 411 isDOMNode() { |
| 380 return this._axNode.isDOMNode(); | 412 return this._axNode.isDOMNode(); |
| 381 } | 413 } |
| 382 | 414 |
| 383 /** | 415 /** |
| 416 * @return {?Accessibility.AXBreadcrumb} |
| 417 */ |
| 418 nextBreadcrumb() { |
| 419 if (this._children.length) |
| 420 return this._children[0]; |
| 421 var nextSibling = this.element().nextSibling; |
| 422 if (nextSibling) |
| 423 return nextSibling.breadcrumb; |
| 424 return null; |
| 425 } |
| 426 |
| 427 /** |
| 428 * @return {?Accessibility.AXBreadcrumb} |
| 429 */ |
| 430 previousBreadcrumb() { |
| 431 var previousSibling = this.element().previousSibling; |
| 432 if (previousSibling) |
| 433 return previousSibling.breadcrumb; |
| 434 |
| 435 return this._parent; |
| 436 } |
| 437 |
| 438 /** |
| 384 * @param {string} name | 439 * @param {string} name |
| 385 */ | 440 */ |
| 386 _appendNameElement(name) { | 441 _appendNameElement(name) { |
| 387 var nameElement = createElement('span'); | 442 var nameElement = createElement('span'); |
| 388 nameElement.textContent = '"' + name + '"'; | 443 nameElement.textContent = '"' + name + '"'; |
| 389 nameElement.classList.add('ax-readable-string'); | 444 nameElement.classList.add('ax-readable-string'); |
| 390 this._nodeWrapper.appendChild(nameElement); | 445 this._nodeWrapper.appendChild(nameElement); |
| 391 } | 446 } |
| 392 | 447 |
| 393 /** | 448 /** |
| (...skipping 16 matching lines...) Expand all Loading... |
| 410 ignoredNodeElement.classList.add('ax-breadcrumbs-ignored-node'); | 465 ignoredNodeElement.classList.add('ax-breadcrumbs-ignored-node'); |
| 411 this._nodeWrapper.appendChild(ignoredNodeElement); | 466 this._nodeWrapper.appendChild(ignoredNodeElement); |
| 412 } | 467 } |
| 413 }; | 468 }; |
| 414 | 469 |
| 415 /** @type {!Object<string, string>} */ | 470 /** @type {!Object<string, string>} */ |
| 416 Accessibility.AXBreadcrumb.RoleStyles = { | 471 Accessibility.AXBreadcrumb.RoleStyles = { |
| 417 internalRole: 'ax-internal-role', | 472 internalRole: 'ax-internal-role', |
| 418 role: 'ax-role', | 473 role: 'ax-role', |
| 419 }; | 474 }; |
| OLD | NEW |