blob: 75ba5c5e44797fc0f21276e0166868f160c28e13 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Tim van der Lippe6d1e03c2020-01-22 14:05:584
Tim van der Lippe19a45df2020-08-28 09:34:545// @ts-nocheck
6// TODO(crbug.com/1011811): Enable TypeScript compiler checks
7
Tim van der Lippe8f15c8d2020-02-13 14:59:418import * as Common from '../common/common.js';
9import * as SDK from '../sdk/sdk.js';
10import * as UI from '../ui/ui.js';
11
Peter Marshall14e5fbd2020-09-01 11:04:1212import {AccessibilityNode, CoreAxPropertyName, CoreOrProtocolAxProperty} from './AccessibilityModel.js'; // eslint-disable-line no-unused-vars
Tim van der Lippe6d1e03c2020-01-22 14:05:5813import {AXAttributes, AXNativeSourceTypes, AXSourceTypes} from './AccessibilityStrings.js';
14import {AccessibilitySubPane} from './AccessibilitySubPane.js';
15
Blink Reformat4c46d092018-04-07 15:32:3716/**
17 * @unrestricted
18 */
Tim van der Lippe6d1e03c2020-01-22 14:05:5819export class AXNodeSubPane extends AccessibilitySubPane {
Blink Reformat4c46d092018-04-07 15:32:3720 constructor() {
21 super(ls`Computed Properties`);
22
Tim van der Lippe6d1e03c2020-01-22 14:05:5823 /**
24 * @protected
25 * @suppress {accessControls}
26 */
27 this._axNode = null;
28
Blink Reformat4c46d092018-04-07 15:32:3729 this.contentElement.classList.add('ax-subpane');
30
31 this._noNodeInfo = this.createInfo(ls`No accessibility node`);
32 this._ignoredInfo = this.createInfo(ls`Accessibility node not exposed`, 'ax-ignored-info hidden');
33
34 this._treeOutline = this.createTreeOutline();
35 this._ignoredReasonsTree = this.createTreeOutline();
36
37 this.element.classList.add('accessibility-computed');
38 this.registerRequiredCSS('accessibility/accessibilityNode.css');
Rob Paveza84d41442019-10-10 23:01:0939 this._treeOutline.setFocusable(true);
Blink Reformat4c46d092018-04-07 15:32:3740 }
41
42 /**
Tim van der Lippe6d1e03c2020-01-22 14:05:5843 * @param {?AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:3744 * @override
45 */
46 setAXNode(axNode) {
Tim van der Lippe1d6e57a2019-09-30 11:55:3447 if (this._axNode === axNode) {
Blink Reformat4c46d092018-04-07 15:32:3748 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3449 }
Blink Reformat4c46d092018-04-07 15:32:3750 this._axNode = axNode;
51
52 const treeOutline = this._treeOutline;
53 treeOutline.removeChildren();
54 const ignoredReasons = this._ignoredReasonsTree;
55 ignoredReasons.removeChildren();
56
57 if (!axNode) {
58 treeOutline.element.classList.add('hidden');
59 this._ignoredInfo.classList.add('hidden');
60 ignoredReasons.element.classList.add('hidden');
61
62 this._noNodeInfo.classList.remove('hidden');
63 this.element.classList.add('ax-ignored-node-pane');
64
65 return;
66 }
67
68 if (axNode.ignored()) {
69 this._noNodeInfo.classList.add('hidden');
70 treeOutline.element.classList.add('hidden');
71 this.element.classList.add('ax-ignored-node-pane');
72
73 this._ignoredInfo.classList.remove('hidden');
74 ignoredReasons.element.classList.remove('hidden');
75 /**
76 * @param {!Protocol.Accessibility.AXProperty} property
77 */
78 function addIgnoredReason(property) {
Tim van der Lippe6d1e03c2020-01-22 14:05:5879 ignoredReasons.appendChild(
80 new AXNodeIgnoredReasonTreeElement(property, /** @type {!AccessibilityNode} */ (axNode)));
Blink Reformat4c46d092018-04-07 15:32:3781 }
82 const ignoredReasonsArray = /** @type {!Array<!Protocol.Accessibility.AXProperty>} */ (axNode.ignoredReasons());
Tim van der Lippe1d6e57a2019-09-30 11:55:3483 for (const reason of ignoredReasonsArray) {
Blink Reformat4c46d092018-04-07 15:32:3784 addIgnoredReason(reason);
Tim van der Lippe1d6e57a2019-09-30 11:55:3485 }
86 if (!ignoredReasons.firstChild()) {
Blink Reformat4c46d092018-04-07 15:32:3787 ignoredReasons.element.classList.add('hidden');
Tim van der Lippe1d6e57a2019-09-30 11:55:3488 }
Blink Reformat4c46d092018-04-07 15:32:3789 return;
90 }
91 this.element.classList.remove('ax-ignored-node-pane');
92
93 this._ignoredInfo.classList.add('hidden');
94 ignoredReasons.element.classList.add('hidden');
95 this._noNodeInfo.classList.add('hidden');
96
97 treeOutline.element.classList.remove('hidden');
98
99 /**
Peter Marshall14e5fbd2020-09-01 11:04:12100 * @param {!CoreOrProtocolAxProperty} property
Blink Reformat4c46d092018-04-07 15:32:37101 */
102 function addProperty(property) {
Tim van der Lippe6d1e03c2020-01-22 14:05:58103 treeOutline.appendChild(
104 new AXNodePropertyTreePropertyElement(property, /** @type {!AccessibilityNode} */ (axNode)));
Blink Reformat4c46d092018-04-07 15:32:37105 }
106
Tim van der Lippe1d6e57a2019-09-30 11:55:34107 for (const property of axNode.coreProperties()) {
Blink Reformat4c46d092018-04-07 15:32:37108 addProperty(property);
Tim van der Lippe1d6e57a2019-09-30 11:55:34109 }
Blink Reformat4c46d092018-04-07 15:32:37110
Peter Marshall14e5fbd2020-09-01 11:04:12111 const role = axNode.role();
112 if (role) {
113 /** @type {!CoreOrProtocolAxProperty} */
114 const roleProperty = {name: CoreAxPropertyName.Role, value: role};
115 addProperty(roleProperty);
116 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34117 for (const property of /** @type {!Array.<!Protocol.Accessibility.AXProperty>} */ (axNode.properties())) {
Blink Reformat4c46d092018-04-07 15:32:37118 addProperty(property);
Tim van der Lippe1d6e57a2019-09-30 11:55:34119 }
Rob Paveza84d41442019-10-10 23:01:09120
121 const firstNode = treeOutline.firstChild();
122 if (firstNode) {
123 firstNode.select(/* omitFocus= */ true, /* selectedByUser= */ false);
124 }
Blink Reformat4c46d092018-04-07 15:32:37125 }
126
127 /**
128 * @override
Tim van der Lippe8f15c8d2020-02-13 14:59:41129 * @param {?SDK.DOMModel.DOMNode} node
Blink Reformat4c46d092018-04-07 15:32:37130 */
131 setNode(node) {
132 super.setNode(node);
133 this._axNode = null;
134 }
Paul Lewisf16142c2019-11-07 15:56:04135}
Blink Reformat4c46d092018-04-07 15:32:37136
137/**
138 * @unrestricted
139 */
Tim van der Lippe8f15c8d2020-02-13 14:59:41140export class AXNodePropertyTreeElement extends UI.TreeOutline.TreeElement {
Blink Reformat4c46d092018-04-07 15:32:37141 /**
Tim van der Lippe6d1e03c2020-01-22 14:05:58142 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37143 */
144 constructor(axNode) {
145 // Pass an empty title, the title gets made later in onattach.
146 super('');
147 this._axNode = axNode;
148 }
149
150 /**
151 * @param {?Protocol.Accessibility.AXValueType} type
152 * @param {string} value
153 * @return {!Element}
154 */
155 static createSimpleValueElement(type, value) {
156 let valueElement;
157 const AXValueType = Protocol.Accessibility.AXValueType;
Tim van der Lippe1d6e57a2019-09-30 11:55:34158 if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString) {
Blink Reformat4c46d092018-04-07 15:32:37159 valueElement = createElement('span');
Tim van der Lippe1d6e57a2019-09-30 11:55:34160 } else {
Tim van der Lippef49e2322020-05-01 15:03:09161 valueElement = document.createElement('span');
162 valueElement.classList.add('monospace');
Tim van der Lippe1d6e57a2019-09-30 11:55:34163 }
Blink Reformat4c46d092018-04-07 15:32:37164 let valueText;
Tim van der Lippe6d1e03c2020-01-22 14:05:58165 const isStringProperty = type && StringProperties.has(type);
Blink Reformat4c46d092018-04-07 15:32:37166 if (isStringProperty) {
167 // Render \n as a nice unicode cr symbol.
168 valueText = '"' + value.replace(/\n/g, '\u21B5') + '"';
169 valueElement._originalTextContent = value;
170 } else {
171 valueText = String(value);
172 }
173
Tim van der Lippe6d1e03c2020-01-22 14:05:58174 if (type && type in TypeStyles) {
175 valueElement.classList.add(TypeStyles[type]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34176 }
Blink Reformat4c46d092018-04-07 15:32:37177
178 valueElement.setTextContentTruncatedIfNeeded(valueText || '');
179
180 valueElement.title = String(value) || '';
181
182 return valueElement;
183 }
184
185 /**
186 * @param {string} tooltip
187 * @return {!Element}
188 */
189 static createExclamationMark(tooltip) {
Joel Einbinder7fbe24c2019-01-24 05:19:01190 const exclamationElement = createElement('span', 'dt-icon-label');
Blink Reformat4c46d092018-04-07 15:32:37191 exclamationElement.type = 'smallicon-warning';
192 exclamationElement.title = tooltip;
193 return exclamationElement;
194 }
195
196 /**
197 * @param {string} name
198 */
199 appendNameElement(name) {
200 const nameElement = createElement('span');
Blink Reformat4c46d092018-04-07 15:32:37201 if (name in AXAttributes) {
Mandy Chenba6de382019-06-07 21:38:50202 nameElement.textContent = AXAttributes[name].name;
Blink Reformat4c46d092018-04-07 15:32:37203 nameElement.title = AXAttributes[name].description;
204 nameElement.classList.add('ax-readable-name');
205 } else {
206 nameElement.textContent = name;
207 nameElement.classList.add('ax-name');
208 nameElement.classList.add('monospace');
209 }
210 this.listItemElement.appendChild(nameElement);
211 }
212
213 /**
214 * @param {!Protocol.Accessibility.AXValue} value
215 */
216 appendValueElement(value) {
217 const AXValueType = Protocol.Accessibility.AXValueType;
218 if (value.type === AXValueType.Idref || value.type === AXValueType.Node || value.type === AXValueType.IdrefList ||
219 value.type === AXValueType.NodeList) {
220 this.appendRelatedNodeListValueElement(value);
221 return;
Mathias Bynensf06e8c02020-02-28 13:58:28222 }
223 if (value.sources) {
Blink Reformat4c46d092018-04-07 15:32:37224 const sources = value.sources;
225 for (let i = 0; i < sources.length; i++) {
226 const source = sources[i];
Tim van der Lippe6d1e03c2020-01-22 14:05:58227 const child = new AXValueSourceTreeElement(source, this._axNode);
Blink Reformat4c46d092018-04-07 15:32:37228 this.appendChild(child);
229 }
230 this.expand();
231 }
Tim van der Lippe6d1e03c2020-01-22 14:05:58232 const element = AXNodePropertyTreeElement.createSimpleValueElement(value.type, String(value.value));
Blink Reformat4c46d092018-04-07 15:32:37233 this.listItemElement.appendChild(element);
234 }
235
236 /**
237 * @param {!Protocol.Accessibility.AXRelatedNode} relatedNode
238 * @param {number} index
239 */
240 appendRelatedNode(relatedNode, index) {
241 const deferredNode =
Tim van der Lippe8f15c8d2020-02-13 14:59:41242 new SDK.DOMModel.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
Tim van der Lippe6d1e03c2020-01-22 14:05:58243 const nodeTreeElement = new AXRelatedNodeSourceTreeElement({deferredNode: deferredNode}, relatedNode);
Blink Reformat4c46d092018-04-07 15:32:37244 this.appendChild(nodeTreeElement);
245 }
246
247 /**
248 * @param {!Protocol.Accessibility.AXRelatedNode} relatedNode
249 */
250 appendRelatedNodeInline(relatedNode) {
251 const deferredNode =
Tim van der Lippe8f15c8d2020-02-13 14:59:41252 new SDK.DOMModel.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
Tim van der Lippe6d1e03c2020-01-22 14:05:58253 const linkedNode = new AXRelatedNodeElement({deferredNode: deferredNode}, relatedNode);
Blink Reformat4c46d092018-04-07 15:32:37254 this.listItemElement.appendChild(linkedNode.render());
255 }
256
257 /**
258 * @param {!Protocol.Accessibility.AXValue} value
259 */
260 appendRelatedNodeListValueElement(value) {
261 if (value.relatedNodes.length === 1 && !value.value) {
262 this.appendRelatedNodeInline(value.relatedNodes[0]);
263 return;
264 }
265
266 value.relatedNodes.forEach(this.appendRelatedNode, this);
Tim van der Lippe1d6e57a2019-09-30 11:55:34267 if (value.relatedNodes.length <= 3) {
Blink Reformat4c46d092018-04-07 15:32:37268 this.expand();
Tim van der Lippe1d6e57a2019-09-30 11:55:34269 } else {
Blink Reformat4c46d092018-04-07 15:32:37270 this.collapse();
Tim van der Lippe1d6e57a2019-09-30 11:55:34271 }
Blink Reformat4c46d092018-04-07 15:32:37272 }
Paul Lewisf16142c2019-11-07 15:56:04273}
Blink Reformat4c46d092018-04-07 15:32:37274
275/** @type {!Object<string, string>} */
Paul Lewisf16142c2019-11-07 15:56:04276export const TypeStyles = {
Blink Reformat4c46d092018-04-07 15:32:37277 attribute: 'ax-value-string',
278 boolean: 'object-value-boolean',
279 booleanOrUndefined: 'object-value-boolean',
280 computedString: 'ax-readable-string',
281 idref: 'ax-value-string',
282 idrefList: 'ax-value-string',
283 integer: 'object-value-number',
284 internalRole: 'ax-internal-role',
285 number: 'ax-value-number',
286 role: 'ax-role',
287 string: 'ax-value-string',
288 tristate: 'object-value-boolean',
289 valueUndefined: 'ax-value-undefined'
290};
291
292/** @type {!Set.<!Protocol.Accessibility.AXValueType>} */
Paul Lewisf16142c2019-11-07 15:56:04293export const StringProperties = new Set([
Blink Reformat4c46d092018-04-07 15:32:37294 Protocol.Accessibility.AXValueType.String, Protocol.Accessibility.AXValueType.ComputedString,
295 Protocol.Accessibility.AXValueType.IdrefList, Protocol.Accessibility.AXValueType.Idref
296]);
297
298/**
299 * @unrestricted
300 */
Paul Lewisf16142c2019-11-07 15:56:04301export class AXNodePropertyTreePropertyElement extends AXNodePropertyTreeElement {
Blink Reformat4c46d092018-04-07 15:32:37302 /**
Peter Marshall14e5fbd2020-09-01 11:04:12303 * @param {!CoreOrProtocolAxProperty} property
Tim van der Lippe6d1e03c2020-01-22 14:05:58304 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37305 */
306 constructor(property, axNode) {
307 super(axNode);
308
309 this._property = property;
310 this.toggleOnClick = true;
Blink Reformat4c46d092018-04-07 15:32:37311
312 this.listItemElement.classList.add('property');
313 }
314
315 /**
316 * @override
317 */
318 onattach() {
319 this._update();
320 }
321
322 _update() {
323 this.listItemElement.removeChildren();
324
325 this.appendNameElement(this._property.name);
326
Mathias Bynens7d8cd342019-09-17 13:32:10327 this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
Blink Reformat4c46d092018-04-07 15:32:37328
329 this.appendValueElement(this._property.value);
330 }
Paul Lewisf16142c2019-11-07 15:56:04331}
Blink Reformat4c46d092018-04-07 15:32:37332
333/**
334 * @unrestricted
335 */
Paul Lewisf16142c2019-11-07 15:56:04336export class AXValueSourceTreeElement extends AXNodePropertyTreeElement {
Blink Reformat4c46d092018-04-07 15:32:37337 /**
338 * @param {!Protocol.Accessibility.AXValueSource} source
Tim van der Lippe6d1e03c2020-01-22 14:05:58339 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37340 */
341 constructor(source, axNode) {
342 super(axNode);
343 this._source = source;
Blink Reformat4c46d092018-04-07 15:32:37344 }
345
346 /**
347 * @override
348 */
349 onattach() {
350 this._update();
351 }
352
353 /**
354 * @param {!Protocol.Accessibility.AXRelatedNode} relatedNode
Blink Reformat4c46d092018-04-07 15:32:37355 * @param {string} idref
356 */
Meredith Lane4be4e9a2020-02-05 06:07:02357 appendRelatedNodeWithIdref(relatedNode, idref) {
Blink Reformat4c46d092018-04-07 15:32:37358 const deferredNode =
Tim van der Lippe8f15c8d2020-02-13 14:59:41359 new SDK.DOMModel.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
Tim van der Lippe6d1e03c2020-01-22 14:05:58360 const nodeTreeElement = new AXRelatedNodeSourceTreeElement({deferredNode: deferredNode, idref: idref}, relatedNode);
Blink Reformat4c46d092018-04-07 15:32:37361 this.appendChild(nodeTreeElement);
362 }
363
364 /**
365 * @param {!Protocol.Accessibility.AXValue} value
366 */
367 appendIDRefValueElement(value) {
Meredith Lane4be4e9a2020-02-05 06:07:02368 if (value.value === null) {
369 return;
370 }
371
372 const relatedNodes = value.relatedNodes || [];
373
374 // Content attribute is empty, but if the relationship was set via the IDL
375 // then there may be related nodes.
376 if (value.value === '') {
377 for (const node of relatedNodes) {
378 const idref = node.idref || '';
379 this.appendRelatedNodeWithIdref(node, idref);
380 }
381 return;
382 }
Blink Reformat4c46d092018-04-07 15:32:37383
384 const idrefs = value.value.trim().split(/\s+/);
Meredith Lane4be4e9a2020-02-05 06:07:02385 for (const idref of idrefs) {
Blink Reformat4c46d092018-04-07 15:32:37386 const matchingNode = relatedNodes.find(node => node.idref === idref);
Blink Reformat4c46d092018-04-07 15:32:37387
Meredith Lane4be4e9a2020-02-05 06:07:02388 // If there is exactly one related node, it is rendered on the same line
389 // of the label. If there are more, they are each rendered on their own
390 // line below the label.
Blink Reformat4c46d092018-04-07 15:32:37391 // TODO(aboxhall): exclamation mark if not idreflist type
Meredith Lane4be4e9a2020-02-05 06:07:02392 if (matchingNode) {
393 this.appendRelatedNodeWithIdref(matchingNode, idref);
394 } else if (idrefs.length === 1) {
395 this.listItemElement.appendChild(new Accessibility.AXRelatedNodeElement({idref: idref}).render());
396 } else {
397 this.appendChild(new Accessibility.AXRelatedNodeSourceTreeElement({idref: idref}));
Blink Reformat4c46d092018-04-07 15:32:37398 }
399 }
400 }
401
402 /**
403 * @param {!Protocol.Accessibility.AXValue} value
404 * @override
405 */
406 appendRelatedNodeListValueElement(value) {
407 const relatedNodes = value.relatedNodes;
408 const numNodes = relatedNodes.length;
409
410 if (value.type === Protocol.Accessibility.AXValueType.IdrefList ||
Tim van der Lippe1d6e57a2019-09-30 11:55:34411 value.type === Protocol.Accessibility.AXValueType.Idref) {
Blink Reformat4c46d092018-04-07 15:32:37412 this.appendIDRefValueElement(value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34413 } else {
Blink Reformat4c46d092018-04-07 15:32:37414 super.appendRelatedNodeListValueElement(value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34415 }
Blink Reformat4c46d092018-04-07 15:32:37416
417
Tim van der Lippe1d6e57a2019-09-30 11:55:34418 if (numNodes <= 3) {
Blink Reformat4c46d092018-04-07 15:32:37419 this.expand();
Tim van der Lippe1d6e57a2019-09-30 11:55:34420 } else {
Blink Reformat4c46d092018-04-07 15:32:37421 this.collapse();
Tim van der Lippe1d6e57a2019-09-30 11:55:34422 }
Blink Reformat4c46d092018-04-07 15:32:37423 }
424
425 /**
426 * @param {!Protocol.Accessibility.AXValueSource} source
427 */
428 appendSourceNameElement(source) {
429 const nameElement = createElement('span');
430 const AXValueSourceType = Protocol.Accessibility.AXValueSourceType;
431 const type = source.type;
432 switch (type) {
433 case AXValueSourceType.Attribute:
434 case AXValueSourceType.Placeholder:
435 case AXValueSourceType.RelatedElement:
436 if (source.nativeSource) {
Blink Reformat4c46d092018-04-07 15:32:37437 const nativeSource = source.nativeSource;
Mandy Chenba6de382019-06-07 21:38:50438 nameElement.textContent = AXNativeSourceTypes[nativeSource].name;
439 nameElement.title = AXNativeSourceTypes[nativeSource].description;
Blink Reformat4c46d092018-04-07 15:32:37440 nameElement.classList.add('ax-readable-name');
441 break;
442 }
443 nameElement.textContent = source.attribute;
444 nameElement.classList.add('ax-name');
445 nameElement.classList.add('monospace');
446 break;
447 default:
Blink Reformat4c46d092018-04-07 15:32:37448 if (type in AXSourceTypes) {
Mandy Chenba6de382019-06-07 21:38:50449 nameElement.textContent = AXSourceTypes[type].name;
450 nameElement.title = AXSourceTypes[type].description;
Blink Reformat4c46d092018-04-07 15:32:37451 nameElement.classList.add('ax-readable-name');
452 } else {
453 console.warn(type, 'not in AXSourceTypes');
Mandy Chenba6de382019-06-07 21:38:50454 nameElement.textContent = type;
Blink Reformat4c46d092018-04-07 15:32:37455 }
456 }
457 this.listItemElement.appendChild(nameElement);
458 }
459
460 _update() {
461 this.listItemElement.removeChildren();
462
463 if (this._source.invalid) {
Tim van der Lippe6d1e03c2020-01-22 14:05:58464 const exclamationMark = AXNodePropertyTreeElement.createExclamationMark(ls`Invalid source.`);
Blink Reformat4c46d092018-04-07 15:32:37465 this.listItemElement.appendChild(exclamationMark);
466 this.listItemElement.classList.add('ax-value-source-invalid');
467 } else if (this._source.superseded) {
468 this.listItemElement.classList.add('ax-value-source-unused');
469 }
470
471 this.appendSourceNameElement(this._source);
472
Mathias Bynens7d8cd342019-09-17 13:32:10473 this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
Blink Reformat4c46d092018-04-07 15:32:37474
475 if (this._source.attributeValue) {
476 this.appendValueElement(this._source.attributeValue);
Mathias Bynens7d8cd342019-09-17 13:32:10477 this.listItemElement.createTextChild('\xA0');
Blink Reformat4c46d092018-04-07 15:32:37478 } else if (this._source.nativeSourceValue) {
479 this.appendValueElement(this._source.nativeSourceValue);
Mathias Bynens7d8cd342019-09-17 13:32:10480 this.listItemElement.createTextChild('\xA0');
Tim van der Lippe1d6e57a2019-09-30 11:55:34481 if (this._source.value) {
Blink Reformat4c46d092018-04-07 15:32:37482 this.appendValueElement(this._source.value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34483 }
Blink Reformat4c46d092018-04-07 15:32:37484 } else if (this._source.value) {
485 this.appendValueElement(this._source.value);
486 } else {
Tim van der Lippe6d1e03c2020-01-22 14:05:58487 const valueElement = AXNodePropertyTreeElement.createSimpleValueElement(
Blink Reformat4c46d092018-04-07 15:32:37488 Protocol.Accessibility.AXValueType.ValueUndefined, ls`Not specified`);
489 this.listItemElement.appendChild(valueElement);
490 this.listItemElement.classList.add('ax-value-source-unused');
491 }
492
Tim van der Lippe1d6e57a2019-09-30 11:55:34493 if (this._source.value && this._source.superseded) {
Blink Reformat4c46d092018-04-07 15:32:37494 this.listItemElement.classList.add('ax-value-source-superseded');
Tim van der Lippe1d6e57a2019-09-30 11:55:34495 }
Blink Reformat4c46d092018-04-07 15:32:37496 }
Paul Lewisf16142c2019-11-07 15:56:04497}
Blink Reformat4c46d092018-04-07 15:32:37498
499/**
500 * @unrestricted
501 */
Tim van der Lippe8f15c8d2020-02-13 14:59:41502export class AXRelatedNodeSourceTreeElement extends UI.TreeOutline.TreeElement {
Blink Reformat4c46d092018-04-07 15:32:37503 /**
Tim van der Lippe8f15c8d2020-02-13 14:59:41504 * @param {{deferredNode: (!SDK.DOMModel.DeferredDOMNode|undefined), idref: (string|undefined)}} node
Blink Reformat4c46d092018-04-07 15:32:37505 * @param {!Protocol.Accessibility.AXRelatedNode=} value
506 */
507 constructor(node, value) {
508 super('');
509
510 this._value = value;
Tim van der Lippe6d1e03c2020-01-22 14:05:58511 this._axRelatedNodeElement = new AXRelatedNodeElement(node, value);
Rob Paveza84d41442019-10-10 23:01:09512 this.selectable = true;
Blink Reformat4c46d092018-04-07 15:32:37513 }
514
515 /**
516 * @override
517 */
518 onattach() {
519 this.listItemElement.appendChild(this._axRelatedNodeElement.render());
Tim van der Lippe1d6e57a2019-09-30 11:55:34520 if (!this._value) {
Blink Reformat4c46d092018-04-07 15:32:37521 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34522 }
Blink Reformat4c46d092018-04-07 15:32:37523
524 if (this._value.text) {
Tim van der Lippe6d1e03c2020-01-22 14:05:58525 this.listItemElement.appendChild(AXNodePropertyTreeElement.createSimpleValueElement(
Blink Reformat4c46d092018-04-07 15:32:37526 Protocol.Accessibility.AXValueType.ComputedString, this._value.text));
527 }
528 }
Rob Paveza84d41442019-10-10 23:01:09529
530 /**
531 * @override
532 */
533 onenter() {
534 this._axRelatedNodeElement.revealNode();
535 return true;
536 }
Paul Lewisf16142c2019-11-07 15:56:04537}
Blink Reformat4c46d092018-04-07 15:32:37538
539/**
540 * @unrestricted
541 */
Paul Lewisf16142c2019-11-07 15:56:04542export class AXRelatedNodeElement {
Blink Reformat4c46d092018-04-07 15:32:37543 /**
Tim van der Lippe8f15c8d2020-02-13 14:59:41544 * @param {{deferredNode: (!SDK.DOMModel.DeferredDOMNode|undefined), idref: (string|undefined)}} node
Blink Reformat4c46d092018-04-07 15:32:37545 * @param {!Protocol.Accessibility.AXRelatedNode=} value
546 */
547 constructor(node, value) {
548 this._deferredNode = node.deferredNode;
549 this._idref = node.idref;
550 this._value = value;
551 }
552
553 /**
554 * @return {!Element}
555 */
556 render() {
557 const element = createElement('span');
558 let valueElement;
559
560 if (this._deferredNode) {
561 valueElement = createElement('span');
562 element.appendChild(valueElement);
Alice Boxhall6ac43432018-11-22 08:24:18563 this._deferredNode.resolvePromise().then(node => {
Tim van der Lippe8f15c8d2020-02-13 14:59:41564 Common.Linkifier.Linkifier.linkify(node, {preventKeyboardFocus: true})
Jeff Fisher3f5f19c2019-08-28 19:10:02565 .then(linkfied => valueElement.appendChild(linkfied));
Alice Boxhall6ac43432018-11-22 08:24:18566 });
Blink Reformat4c46d092018-04-07 15:32:37567 } else if (this._idref) {
568 element.classList.add('invalid');
Tim van der Lippe6d1e03c2020-01-22 14:05:58569 valueElement = AXNodePropertyTreeElement.createExclamationMark(ls`No node with this ID.`);
Blink Reformat4c46d092018-04-07 15:32:37570 valueElement.createTextChild(this._idref);
571 element.appendChild(valueElement);
572 }
573
574 return element;
575 }
Rob Paveza84d41442019-10-10 23:01:09576
577 /**
578 * Attempts to cause the node referred to by the related node to be selected in the tree.
579 */
580 revealNode() {
581 this._deferredNode.resolvePromise().then(node => Common.Revealer.reveal(node));
582 }
Paul Lewisf16142c2019-11-07 15:56:04583}
Blink Reformat4c46d092018-04-07 15:32:37584
585/**
586 * @unrestricted
587 */
Paul Lewisf16142c2019-11-07 15:56:04588export class AXNodeIgnoredReasonTreeElement extends AXNodePropertyTreeElement {
Blink Reformat4c46d092018-04-07 15:32:37589 /**
590 * @param {!Protocol.Accessibility.AXProperty} property
Tim van der Lippe6d1e03c2020-01-22 14:05:58591 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37592 */
593 constructor(property, axNode) {
594 super(axNode);
595 this._property = property;
596 this._axNode = axNode;
597 this.toggleOnClick = true;
598 this.selectable = false;
599 }
600
601 /**
602 * @param {?string} reason
Tim van der Lippe6d1e03c2020-01-22 14:05:58603 * @param {?AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37604 * @return {?Element}
605 */
606 static createReasonElement(reason, axNode) {
607 let reasonElement = null;
608 switch (reason) {
609 case 'activeModalDialog':
Tim van der Lippe8f15c8d2020-02-13 14:59:41610 reasonElement = UI.UIUtils.formatLocalized('Element is hidden by active modal dialog:\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37611 break;
612 case 'ancestorIsLeafNode':
Tim van der Lippe8f15c8d2020-02-13 14:59:41613 reasonElement = UI.UIUtils.formatLocalized('Ancestor\'s children are all presentational:\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37614 break;
615 case 'ariaHiddenElement': {
616 const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
Tim van der Lippe8f15c8d2020-02-13 14:59:41617 reasonElement = UI.UIUtils.formatLocalized('Element is %s.', [ariaHiddenSpan]);
Blink Reformat4c46d092018-04-07 15:32:37618 break;
619 }
620 case 'ariaHiddenSubtree': {
621 const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
622 const trueSpan = createElement('span', 'source-code').textContent = 'true';
Tim van der Lippe8f15c8d2020-02-13 14:59:41623 reasonElement = UI.UIUtils.formatLocalized('%s is %s on ancestor:\xA0', [ariaHiddenSpan, trueSpan]);
Blink Reformat4c46d092018-04-07 15:32:37624 break;
625 }
626 case 'emptyAlt':
Tim van der Lippe8f15c8d2020-02-13 14:59:41627 reasonElement = UI.UIUtils.formatLocalized('Element has empty alt text.', []);
Blink Reformat4c46d092018-04-07 15:32:37628 break;
629 case 'emptyText':
Tim van der Lippe8f15c8d2020-02-13 14:59:41630 reasonElement = UI.UIUtils.formatLocalized('No text content.', []);
Blink Reformat4c46d092018-04-07 15:32:37631 break;
632 case 'inertElement':
Tim van der Lippe8f15c8d2020-02-13 14:59:41633 reasonElement = UI.UIUtils.formatLocalized('Element is inert.', []);
Blink Reformat4c46d092018-04-07 15:32:37634 break;
635 case 'inertSubtree':
Tim van der Lippe8f15c8d2020-02-13 14:59:41636 reasonElement = UI.UIUtils.formatLocalized('Element is in an inert subtree from\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37637 break;
638 case 'inheritsPresentation':
Tim van der Lippe8f15c8d2020-02-13 14:59:41639 reasonElement = UI.UIUtils.formatLocalized('Element inherits presentational role from\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37640 break;
641 case 'labelContainer':
Tim van der Lippe8f15c8d2020-02-13 14:59:41642 reasonElement = UI.UIUtils.formatLocalized('Part of label element:\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37643 break;
644 case 'labelFor':
Tim van der Lippe8f15c8d2020-02-13 14:59:41645 reasonElement = UI.UIUtils.formatLocalized('Label for\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37646 break;
647 case 'notRendered':
Tim van der Lippe8f15c8d2020-02-13 14:59:41648 reasonElement = UI.UIUtils.formatLocalized('Element is not rendered.', []);
Blink Reformat4c46d092018-04-07 15:32:37649 break;
650 case 'notVisible':
Tim van der Lippe8f15c8d2020-02-13 14:59:41651 reasonElement = UI.UIUtils.formatLocalized('Element is not visible.', []);
Blink Reformat4c46d092018-04-07 15:32:37652 break;
653 case 'presentationalRole': {
654 const rolePresentationSpan = createElement('span', 'source-code').textContent = 'role=' + axNode.role().value;
Tim van der Lippe8f15c8d2020-02-13 14:59:41655 reasonElement = UI.UIUtils.formatLocalized('Element has %s.', [rolePresentationSpan]);
Blink Reformat4c46d092018-04-07 15:32:37656 break;
657 }
658 case 'probablyPresentational':
Tim van der Lippe8f15c8d2020-02-13 14:59:41659 reasonElement = UI.UIUtils.formatLocalized('Element is presentational.', []);
Blink Reformat4c46d092018-04-07 15:32:37660 break;
661 case 'staticTextUsedAsNameFor':
Tim van der Lippe8f15c8d2020-02-13 14:59:41662 reasonElement = UI.UIUtils.formatLocalized('Static text node is used as name for\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37663 break;
664 case 'uninteresting':
Tim van der Lippe8f15c8d2020-02-13 14:59:41665 reasonElement = UI.UIUtils.formatLocalized('Element not interesting for accessibility.', []);
Blink Reformat4c46d092018-04-07 15:32:37666 break;
667 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34668 if (reasonElement) {
Blink Reformat4c46d092018-04-07 15:32:37669 reasonElement.classList.add('ax-reason');
Tim van der Lippe1d6e57a2019-09-30 11:55:34670 }
Blink Reformat4c46d092018-04-07 15:32:37671 return reasonElement;
672 }
673
674 /**
675 * @override
676 */
677 onattach() {
678 this.listItemElement.removeChildren();
679
Tim van der Lippe6d1e03c2020-01-22 14:05:58680 this._reasonElement = AXNodeIgnoredReasonTreeElement.createReasonElement(this._property.name, this._axNode);
Blink Reformat4c46d092018-04-07 15:32:37681 this.listItemElement.appendChild(this._reasonElement);
682
683 const value = this._property.value;
Tim van der Lippe1d6e57a2019-09-30 11:55:34684 if (value.type === Protocol.Accessibility.AXValueType.Idref) {
Blink Reformat4c46d092018-04-07 15:32:37685 this.appendRelatedNodeListValueElement(value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34686 }
Blink Reformat4c46d092018-04-07 15:32:37687 }
Paul Lewisf16142c2019-11-07 15:56:04688}