blob: 8f88d2688a5d3290b22f0eb15c197b5a865aadd2 [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
5import {AccessibilityNode} from './AccessibilityModel.js'; // eslint-disable-line no-unused-vars
6import {AXAttributes, AXNativeSourceTypes, AXSourceTypes} from './AccessibilityStrings.js';
7import {AccessibilitySubPane} from './AccessibilitySubPane.js';
8
Blink Reformat4c46d092018-04-07 15:32:379/**
10 * @unrestricted
11 */
Tim van der Lippe6d1e03c2020-01-22 14:05:5812export class AXNodeSubPane extends AccessibilitySubPane {
Blink Reformat4c46d092018-04-07 15:32:3713 constructor() {
14 super(ls`Computed Properties`);
15
Tim van der Lippe6d1e03c2020-01-22 14:05:5816 /**
17 * @protected
18 * @suppress {accessControls}
19 */
20 this._axNode = null;
21
Blink Reformat4c46d092018-04-07 15:32:3722 this.contentElement.classList.add('ax-subpane');
23
24 this._noNodeInfo = this.createInfo(ls`No accessibility node`);
25 this._ignoredInfo = this.createInfo(ls`Accessibility node not exposed`, 'ax-ignored-info hidden');
26
27 this._treeOutline = this.createTreeOutline();
28 this._ignoredReasonsTree = this.createTreeOutline();
29
30 this.element.classList.add('accessibility-computed');
31 this.registerRequiredCSS('accessibility/accessibilityNode.css');
Rob Paveza84d41442019-10-10 23:01:0932 this._treeOutline.setFocusable(true);
Blink Reformat4c46d092018-04-07 15:32:3733 }
34
35 /**
Tim van der Lippe6d1e03c2020-01-22 14:05:5836 * @param {?AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:3737 * @override
38 */
39 setAXNode(axNode) {
Tim van der Lippe1d6e57a2019-09-30 11:55:3440 if (this._axNode === axNode) {
Blink Reformat4c46d092018-04-07 15:32:3741 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3442 }
Blink Reformat4c46d092018-04-07 15:32:3743 this._axNode = axNode;
44
45 const treeOutline = this._treeOutline;
46 treeOutline.removeChildren();
47 const ignoredReasons = this._ignoredReasonsTree;
48 ignoredReasons.removeChildren();
49
50 if (!axNode) {
51 treeOutline.element.classList.add('hidden');
52 this._ignoredInfo.classList.add('hidden');
53 ignoredReasons.element.classList.add('hidden');
54
55 this._noNodeInfo.classList.remove('hidden');
56 this.element.classList.add('ax-ignored-node-pane');
57
58 return;
59 }
60
61 if (axNode.ignored()) {
62 this._noNodeInfo.classList.add('hidden');
63 treeOutline.element.classList.add('hidden');
64 this.element.classList.add('ax-ignored-node-pane');
65
66 this._ignoredInfo.classList.remove('hidden');
67 ignoredReasons.element.classList.remove('hidden');
68 /**
69 * @param {!Protocol.Accessibility.AXProperty} property
70 */
71 function addIgnoredReason(property) {
Tim van der Lippe6d1e03c2020-01-22 14:05:5872 ignoredReasons.appendChild(
73 new AXNodeIgnoredReasonTreeElement(property, /** @type {!AccessibilityNode} */ (axNode)));
Blink Reformat4c46d092018-04-07 15:32:3774 }
75 const ignoredReasonsArray = /** @type {!Array<!Protocol.Accessibility.AXProperty>} */ (axNode.ignoredReasons());
Tim van der Lippe1d6e57a2019-09-30 11:55:3476 for (const reason of ignoredReasonsArray) {
Blink Reformat4c46d092018-04-07 15:32:3777 addIgnoredReason(reason);
Tim van der Lippe1d6e57a2019-09-30 11:55:3478 }
79 if (!ignoredReasons.firstChild()) {
Blink Reformat4c46d092018-04-07 15:32:3780 ignoredReasons.element.classList.add('hidden');
Tim van der Lippe1d6e57a2019-09-30 11:55:3481 }
Blink Reformat4c46d092018-04-07 15:32:3782 return;
83 }
84 this.element.classList.remove('ax-ignored-node-pane');
85
86 this._ignoredInfo.classList.add('hidden');
87 ignoredReasons.element.classList.add('hidden');
88 this._noNodeInfo.classList.add('hidden');
89
90 treeOutline.element.classList.remove('hidden');
91
92 /**
93 * @param {!Protocol.Accessibility.AXProperty} property
94 */
95 function addProperty(property) {
Tim van der Lippe6d1e03c2020-01-22 14:05:5896 treeOutline.appendChild(
97 new AXNodePropertyTreePropertyElement(property, /** @type {!AccessibilityNode} */ (axNode)));
Blink Reformat4c46d092018-04-07 15:32:3798 }
99
Tim van der Lippe1d6e57a2019-09-30 11:55:34100 for (const property of axNode.coreProperties()) {
Blink Reformat4c46d092018-04-07 15:32:37101 addProperty(property);
Tim van der Lippe1d6e57a2019-09-30 11:55:34102 }
Blink Reformat4c46d092018-04-07 15:32:37103
104 const roleProperty = /** @type {!Protocol.Accessibility.AXProperty} */ ({name: 'role', value: axNode.role()});
105 addProperty(roleProperty);
Tim van der Lippe1d6e57a2019-09-30 11:55:34106 for (const property of /** @type {!Array.<!Protocol.Accessibility.AXProperty>} */ (axNode.properties())) {
Blink Reformat4c46d092018-04-07 15:32:37107 addProperty(property);
Tim van der Lippe1d6e57a2019-09-30 11:55:34108 }
Rob Paveza84d41442019-10-10 23:01:09109
110 const firstNode = treeOutline.firstChild();
111 if (firstNode) {
112 firstNode.select(/* omitFocus= */ true, /* selectedByUser= */ false);
113 }
Blink Reformat4c46d092018-04-07 15:32:37114 }
115
116 /**
117 * @override
118 * @param {?SDK.DOMNode} node
119 */
120 setNode(node) {
121 super.setNode(node);
122 this._axNode = null;
123 }
Paul Lewisf16142c2019-11-07 15:56:04124}
Blink Reformat4c46d092018-04-07 15:32:37125
126/**
127 * @unrestricted
128 */
Paul Lewisf16142c2019-11-07 15:56:04129export class AXNodePropertyTreeElement extends UI.TreeElement {
Blink Reformat4c46d092018-04-07 15:32:37130 /**
Tim van der Lippe6d1e03c2020-01-22 14:05:58131 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37132 */
133 constructor(axNode) {
134 // Pass an empty title, the title gets made later in onattach.
135 super('');
136 this._axNode = axNode;
137 }
138
139 /**
140 * @param {?Protocol.Accessibility.AXValueType} type
141 * @param {string} value
142 * @return {!Element}
143 */
144 static createSimpleValueElement(type, value) {
145 let valueElement;
146 const AXValueType = Protocol.Accessibility.AXValueType;
Tim van der Lippe1d6e57a2019-09-30 11:55:34147 if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString) {
Blink Reformat4c46d092018-04-07 15:32:37148 valueElement = createElement('span');
Tim van der Lippe1d6e57a2019-09-30 11:55:34149 } else {
Blink Reformat4c46d092018-04-07 15:32:37150 valueElement = createElementWithClass('span', 'monospace');
Tim van der Lippe1d6e57a2019-09-30 11:55:34151 }
Blink Reformat4c46d092018-04-07 15:32:37152 let valueText;
Tim van der Lippe6d1e03c2020-01-22 14:05:58153 const isStringProperty = type && StringProperties.has(type);
Blink Reformat4c46d092018-04-07 15:32:37154 if (isStringProperty) {
155 // Render \n as a nice unicode cr symbol.
156 valueText = '"' + value.replace(/\n/g, '\u21B5') + '"';
157 valueElement._originalTextContent = value;
158 } else {
159 valueText = String(value);
160 }
161
Tim van der Lippe6d1e03c2020-01-22 14:05:58162 if (type && type in TypeStyles) {
163 valueElement.classList.add(TypeStyles[type]);
Tim van der Lippe1d6e57a2019-09-30 11:55:34164 }
Blink Reformat4c46d092018-04-07 15:32:37165
166 valueElement.setTextContentTruncatedIfNeeded(valueText || '');
167
168 valueElement.title = String(value) || '';
169
170 return valueElement;
171 }
172
173 /**
174 * @param {string} tooltip
175 * @return {!Element}
176 */
177 static createExclamationMark(tooltip) {
Joel Einbinder7fbe24c2019-01-24 05:19:01178 const exclamationElement = createElement('span', 'dt-icon-label');
Blink Reformat4c46d092018-04-07 15:32:37179 exclamationElement.type = 'smallicon-warning';
180 exclamationElement.title = tooltip;
181 return exclamationElement;
182 }
183
184 /**
185 * @param {string} name
186 */
187 appendNameElement(name) {
188 const nameElement = createElement('span');
Blink Reformat4c46d092018-04-07 15:32:37189 if (name in AXAttributes) {
Mandy Chenba6de382019-06-07 21:38:50190 nameElement.textContent = AXAttributes[name].name;
Blink Reformat4c46d092018-04-07 15:32:37191 nameElement.title = AXAttributes[name].description;
192 nameElement.classList.add('ax-readable-name');
193 } else {
194 nameElement.textContent = name;
195 nameElement.classList.add('ax-name');
196 nameElement.classList.add('monospace');
197 }
198 this.listItemElement.appendChild(nameElement);
199 }
200
201 /**
202 * @param {!Protocol.Accessibility.AXValue} value
203 */
204 appendValueElement(value) {
205 const AXValueType = Protocol.Accessibility.AXValueType;
206 if (value.type === AXValueType.Idref || value.type === AXValueType.Node || value.type === AXValueType.IdrefList ||
207 value.type === AXValueType.NodeList) {
208 this.appendRelatedNodeListValueElement(value);
209 return;
210 } else if (value.sources) {
211 const sources = value.sources;
212 for (let i = 0; i < sources.length; i++) {
213 const source = sources[i];
Tim van der Lippe6d1e03c2020-01-22 14:05:58214 const child = new AXValueSourceTreeElement(source, this._axNode);
Blink Reformat4c46d092018-04-07 15:32:37215 this.appendChild(child);
216 }
217 this.expand();
218 }
Tim van der Lippe6d1e03c2020-01-22 14:05:58219 const element = AXNodePropertyTreeElement.createSimpleValueElement(value.type, String(value.value));
Blink Reformat4c46d092018-04-07 15:32:37220 this.listItemElement.appendChild(element);
221 }
222
223 /**
224 * @param {!Protocol.Accessibility.AXRelatedNode} relatedNode
225 * @param {number} index
226 */
227 appendRelatedNode(relatedNode, index) {
228 const deferredNode =
229 new SDK.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
Tim van der Lippe6d1e03c2020-01-22 14:05:58230 const nodeTreeElement = new AXRelatedNodeSourceTreeElement({deferredNode: deferredNode}, relatedNode);
Blink Reformat4c46d092018-04-07 15:32:37231 this.appendChild(nodeTreeElement);
232 }
233
234 /**
235 * @param {!Protocol.Accessibility.AXRelatedNode} relatedNode
236 */
237 appendRelatedNodeInline(relatedNode) {
238 const deferredNode =
239 new SDK.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
Tim van der Lippe6d1e03c2020-01-22 14:05:58240 const linkedNode = new AXRelatedNodeElement({deferredNode: deferredNode}, relatedNode);
Blink Reformat4c46d092018-04-07 15:32:37241 this.listItemElement.appendChild(linkedNode.render());
242 }
243
244 /**
245 * @param {!Protocol.Accessibility.AXValue} value
246 */
247 appendRelatedNodeListValueElement(value) {
248 if (value.relatedNodes.length === 1 && !value.value) {
249 this.appendRelatedNodeInline(value.relatedNodes[0]);
250 return;
251 }
252
253 value.relatedNodes.forEach(this.appendRelatedNode, this);
Tim van der Lippe1d6e57a2019-09-30 11:55:34254 if (value.relatedNodes.length <= 3) {
Blink Reformat4c46d092018-04-07 15:32:37255 this.expand();
Tim van der Lippe1d6e57a2019-09-30 11:55:34256 } else {
Blink Reformat4c46d092018-04-07 15:32:37257 this.collapse();
Tim van der Lippe1d6e57a2019-09-30 11:55:34258 }
Blink Reformat4c46d092018-04-07 15:32:37259 }
Paul Lewisf16142c2019-11-07 15:56:04260}
Blink Reformat4c46d092018-04-07 15:32:37261
262/** @type {!Object<string, string>} */
Paul Lewisf16142c2019-11-07 15:56:04263export const TypeStyles = {
Blink Reformat4c46d092018-04-07 15:32:37264 attribute: 'ax-value-string',
265 boolean: 'object-value-boolean',
266 booleanOrUndefined: 'object-value-boolean',
267 computedString: 'ax-readable-string',
268 idref: 'ax-value-string',
269 idrefList: 'ax-value-string',
270 integer: 'object-value-number',
271 internalRole: 'ax-internal-role',
272 number: 'ax-value-number',
273 role: 'ax-role',
274 string: 'ax-value-string',
275 tristate: 'object-value-boolean',
276 valueUndefined: 'ax-value-undefined'
277};
278
279/** @type {!Set.<!Protocol.Accessibility.AXValueType>} */
Paul Lewisf16142c2019-11-07 15:56:04280export const StringProperties = new Set([
Blink Reformat4c46d092018-04-07 15:32:37281 Protocol.Accessibility.AXValueType.String, Protocol.Accessibility.AXValueType.ComputedString,
282 Protocol.Accessibility.AXValueType.IdrefList, Protocol.Accessibility.AXValueType.Idref
283]);
284
285/**
286 * @unrestricted
287 */
Paul Lewisf16142c2019-11-07 15:56:04288export class AXNodePropertyTreePropertyElement extends AXNodePropertyTreeElement {
Blink Reformat4c46d092018-04-07 15:32:37289 /**
290 * @param {!Protocol.Accessibility.AXProperty} property
Tim van der Lippe6d1e03c2020-01-22 14:05:58291 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37292 */
293 constructor(property, axNode) {
294 super(axNode);
295
296 this._property = property;
297 this.toggleOnClick = true;
Blink Reformat4c46d092018-04-07 15:32:37298
299 this.listItemElement.classList.add('property');
300 }
301
302 /**
303 * @override
304 */
305 onattach() {
306 this._update();
307 }
308
309 _update() {
310 this.listItemElement.removeChildren();
311
312 this.appendNameElement(this._property.name);
313
Mathias Bynens7d8cd342019-09-17 13:32:10314 this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
Blink Reformat4c46d092018-04-07 15:32:37315
316 this.appendValueElement(this._property.value);
317 }
Paul Lewisf16142c2019-11-07 15:56:04318}
Blink Reformat4c46d092018-04-07 15:32:37319
320/**
321 * @unrestricted
322 */
Paul Lewisf16142c2019-11-07 15:56:04323export class AXValueSourceTreeElement extends AXNodePropertyTreeElement {
Blink Reformat4c46d092018-04-07 15:32:37324 /**
325 * @param {!Protocol.Accessibility.AXValueSource} source
Tim van der Lippe6d1e03c2020-01-22 14:05:58326 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37327 */
328 constructor(source, axNode) {
329 super(axNode);
330 this._source = source;
Blink Reformat4c46d092018-04-07 15:32:37331 }
332
333 /**
334 * @override
335 */
336 onattach() {
337 this._update();
338 }
339
340 /**
341 * @param {!Protocol.Accessibility.AXRelatedNode} relatedNode
342 * @param {number} index
343 * @param {string} idref
344 */
345 appendRelatedNodeWithIdref(relatedNode, index, idref) {
346 const deferredNode =
347 new SDK.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
Tim van der Lippe6d1e03c2020-01-22 14:05:58348 const nodeTreeElement = new AXRelatedNodeSourceTreeElement({deferredNode: deferredNode, idref: idref}, relatedNode);
Blink Reformat4c46d092018-04-07 15:32:37349 this.appendChild(nodeTreeElement);
350 }
351
352 /**
353 * @param {!Protocol.Accessibility.AXValue} value
354 */
355 appendIDRefValueElement(value) {
356 const relatedNodes = value.relatedNodes;
357
358 const idrefs = value.value.trim().split(/\s+/);
359 if (idrefs.length === 1) {
360 const idref = idrefs[0];
361 const matchingNode = relatedNodes.find(node => node.idref === idref);
Tim van der Lippe1d6e57a2019-09-30 11:55:34362 if (matchingNode) {
Blink Reformat4c46d092018-04-07 15:32:37363 this.appendRelatedNodeWithIdref(matchingNode, 0, idref);
Tim van der Lippe1d6e57a2019-09-30 11:55:34364 } else {
Tim van der Lippe6d1e03c2020-01-22 14:05:58365 this.listItemElement.appendChild(new AXRelatedNodeElement({idref: idref}).render());
Tim van der Lippe1d6e57a2019-09-30 11:55:34366 }
Blink Reformat4c46d092018-04-07 15:32:37367
368 } else {
369 // TODO(aboxhall): exclamation mark if not idreflist type
370 for (let i = 0; i < idrefs.length; ++i) {
371 const idref = idrefs[i];
372 const matchingNode = relatedNodes.find(node => node.idref === idref);
Tim van der Lippe1d6e57a2019-09-30 11:55:34373 if (matchingNode) {
Blink Reformat4c46d092018-04-07 15:32:37374 this.appendRelatedNodeWithIdref(matchingNode, i, idref);
Tim van der Lippe1d6e57a2019-09-30 11:55:34375 } else {
Tim van der Lippe6d1e03c2020-01-22 14:05:58376 this.appendChild(new AXRelatedNodeSourceTreeElement({idref: idref}));
Tim van der Lippe1d6e57a2019-09-30 11:55:34377 }
Blink Reformat4c46d092018-04-07 15:32:37378 }
379 }
380 }
381
382 /**
383 * @param {!Protocol.Accessibility.AXValue} value
384 * @override
385 */
386 appendRelatedNodeListValueElement(value) {
387 const relatedNodes = value.relatedNodes;
388 const numNodes = relatedNodes.length;
389
390 if (value.type === Protocol.Accessibility.AXValueType.IdrefList ||
Tim van der Lippe1d6e57a2019-09-30 11:55:34391 value.type === Protocol.Accessibility.AXValueType.Idref) {
Blink Reformat4c46d092018-04-07 15:32:37392 this.appendIDRefValueElement(value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34393 } else {
Blink Reformat4c46d092018-04-07 15:32:37394 super.appendRelatedNodeListValueElement(value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34395 }
Blink Reformat4c46d092018-04-07 15:32:37396
397
Tim van der Lippe1d6e57a2019-09-30 11:55:34398 if (numNodes <= 3) {
Blink Reformat4c46d092018-04-07 15:32:37399 this.expand();
Tim van der Lippe1d6e57a2019-09-30 11:55:34400 } else {
Blink Reformat4c46d092018-04-07 15:32:37401 this.collapse();
Tim van der Lippe1d6e57a2019-09-30 11:55:34402 }
Blink Reformat4c46d092018-04-07 15:32:37403 }
404
405 /**
406 * @param {!Protocol.Accessibility.AXValueSource} source
407 */
408 appendSourceNameElement(source) {
409 const nameElement = createElement('span');
410 const AXValueSourceType = Protocol.Accessibility.AXValueSourceType;
411 const type = source.type;
412 switch (type) {
413 case AXValueSourceType.Attribute:
414 case AXValueSourceType.Placeholder:
415 case AXValueSourceType.RelatedElement:
416 if (source.nativeSource) {
Blink Reformat4c46d092018-04-07 15:32:37417 const nativeSource = source.nativeSource;
Mandy Chenba6de382019-06-07 21:38:50418 nameElement.textContent = AXNativeSourceTypes[nativeSource].name;
419 nameElement.title = AXNativeSourceTypes[nativeSource].description;
Blink Reformat4c46d092018-04-07 15:32:37420 nameElement.classList.add('ax-readable-name');
421 break;
422 }
423 nameElement.textContent = source.attribute;
424 nameElement.classList.add('ax-name');
425 nameElement.classList.add('monospace');
426 break;
427 default:
Blink Reformat4c46d092018-04-07 15:32:37428 if (type in AXSourceTypes) {
Mandy Chenba6de382019-06-07 21:38:50429 nameElement.textContent = AXSourceTypes[type].name;
430 nameElement.title = AXSourceTypes[type].description;
Blink Reformat4c46d092018-04-07 15:32:37431 nameElement.classList.add('ax-readable-name');
432 } else {
433 console.warn(type, 'not in AXSourceTypes');
Mandy Chenba6de382019-06-07 21:38:50434 nameElement.textContent = type;
Blink Reformat4c46d092018-04-07 15:32:37435 }
436 }
437 this.listItemElement.appendChild(nameElement);
438 }
439
440 _update() {
441 this.listItemElement.removeChildren();
442
443 if (this._source.invalid) {
Tim van der Lippe6d1e03c2020-01-22 14:05:58444 const exclamationMark = AXNodePropertyTreeElement.createExclamationMark(ls`Invalid source.`);
Blink Reformat4c46d092018-04-07 15:32:37445 this.listItemElement.appendChild(exclamationMark);
446 this.listItemElement.classList.add('ax-value-source-invalid');
447 } else if (this._source.superseded) {
448 this.listItemElement.classList.add('ax-value-source-unused');
449 }
450
451 this.appendSourceNameElement(this._source);
452
Mathias Bynens7d8cd342019-09-17 13:32:10453 this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
Blink Reformat4c46d092018-04-07 15:32:37454
455 if (this._source.attributeValue) {
456 this.appendValueElement(this._source.attributeValue);
Mathias Bynens7d8cd342019-09-17 13:32:10457 this.listItemElement.createTextChild('\xA0');
Blink Reformat4c46d092018-04-07 15:32:37458 } else if (this._source.nativeSourceValue) {
459 this.appendValueElement(this._source.nativeSourceValue);
Mathias Bynens7d8cd342019-09-17 13:32:10460 this.listItemElement.createTextChild('\xA0');
Tim van der Lippe1d6e57a2019-09-30 11:55:34461 if (this._source.value) {
Blink Reformat4c46d092018-04-07 15:32:37462 this.appendValueElement(this._source.value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34463 }
Blink Reformat4c46d092018-04-07 15:32:37464 } else if (this._source.value) {
465 this.appendValueElement(this._source.value);
466 } else {
Tim van der Lippe6d1e03c2020-01-22 14:05:58467 const valueElement = AXNodePropertyTreeElement.createSimpleValueElement(
Blink Reformat4c46d092018-04-07 15:32:37468 Protocol.Accessibility.AXValueType.ValueUndefined, ls`Not specified`);
469 this.listItemElement.appendChild(valueElement);
470 this.listItemElement.classList.add('ax-value-source-unused');
471 }
472
Tim van der Lippe1d6e57a2019-09-30 11:55:34473 if (this._source.value && this._source.superseded) {
Blink Reformat4c46d092018-04-07 15:32:37474 this.listItemElement.classList.add('ax-value-source-superseded');
Tim van der Lippe1d6e57a2019-09-30 11:55:34475 }
Blink Reformat4c46d092018-04-07 15:32:37476 }
Paul Lewisf16142c2019-11-07 15:56:04477}
Blink Reformat4c46d092018-04-07 15:32:37478
479/**
480 * @unrestricted
481 */
Paul Lewisf16142c2019-11-07 15:56:04482export class AXRelatedNodeSourceTreeElement extends UI.TreeElement {
Blink Reformat4c46d092018-04-07 15:32:37483 /**
484 * @param {{deferredNode: (!SDK.DeferredDOMNode|undefined), idref: (string|undefined)}} node
485 * @param {!Protocol.Accessibility.AXRelatedNode=} value
486 */
487 constructor(node, value) {
488 super('');
489
490 this._value = value;
Tim van der Lippe6d1e03c2020-01-22 14:05:58491 this._axRelatedNodeElement = new AXRelatedNodeElement(node, value);
Rob Paveza84d41442019-10-10 23:01:09492 this.selectable = true;
Blink Reformat4c46d092018-04-07 15:32:37493 }
494
495 /**
496 * @override
497 */
498 onattach() {
499 this.listItemElement.appendChild(this._axRelatedNodeElement.render());
Tim van der Lippe1d6e57a2019-09-30 11:55:34500 if (!this._value) {
Blink Reformat4c46d092018-04-07 15:32:37501 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34502 }
Blink Reformat4c46d092018-04-07 15:32:37503
504 if (this._value.text) {
Tim van der Lippe6d1e03c2020-01-22 14:05:58505 this.listItemElement.appendChild(AXNodePropertyTreeElement.createSimpleValueElement(
Blink Reformat4c46d092018-04-07 15:32:37506 Protocol.Accessibility.AXValueType.ComputedString, this._value.text));
507 }
508 }
Rob Paveza84d41442019-10-10 23:01:09509
510 /**
511 * @override
512 */
513 onenter() {
514 this._axRelatedNodeElement.revealNode();
515 return true;
516 }
Paul Lewisf16142c2019-11-07 15:56:04517}
Blink Reformat4c46d092018-04-07 15:32:37518
519/**
520 * @unrestricted
521 */
Paul Lewisf16142c2019-11-07 15:56:04522export class AXRelatedNodeElement {
Blink Reformat4c46d092018-04-07 15:32:37523 /**
524 * @param {{deferredNode: (!SDK.DeferredDOMNode|undefined), idref: (string|undefined)}} node
525 * @param {!Protocol.Accessibility.AXRelatedNode=} value
526 */
527 constructor(node, value) {
528 this._deferredNode = node.deferredNode;
529 this._idref = node.idref;
530 this._value = value;
531 }
532
533 /**
534 * @return {!Element}
535 */
536 render() {
537 const element = createElement('span');
538 let valueElement;
539
540 if (this._deferredNode) {
541 valueElement = createElement('span');
542 element.appendChild(valueElement);
Alice Boxhall6ac43432018-11-22 08:24:18543 this._deferredNode.resolvePromise().then(node => {
Jeff Fisher3f5f19c2019-08-28 19:10:02544 Common.Linkifier.linkify(node, {preventKeyboardFocus: true})
545 .then(linkfied => valueElement.appendChild(linkfied));
Alice Boxhall6ac43432018-11-22 08:24:18546 });
Blink Reformat4c46d092018-04-07 15:32:37547 } else if (this._idref) {
548 element.classList.add('invalid');
Tim van der Lippe6d1e03c2020-01-22 14:05:58549 valueElement = AXNodePropertyTreeElement.createExclamationMark(ls`No node with this ID.`);
Blink Reformat4c46d092018-04-07 15:32:37550 valueElement.createTextChild(this._idref);
551 element.appendChild(valueElement);
552 }
553
554 return element;
555 }
Rob Paveza84d41442019-10-10 23:01:09556
557 /**
558 * Attempts to cause the node referred to by the related node to be selected in the tree.
559 */
560 revealNode() {
561 this._deferredNode.resolvePromise().then(node => Common.Revealer.reveal(node));
562 }
Paul Lewisf16142c2019-11-07 15:56:04563}
Blink Reformat4c46d092018-04-07 15:32:37564
565/**
566 * @unrestricted
567 */
Paul Lewisf16142c2019-11-07 15:56:04568export class AXNodeIgnoredReasonTreeElement extends AXNodePropertyTreeElement {
Blink Reformat4c46d092018-04-07 15:32:37569 /**
570 * @param {!Protocol.Accessibility.AXProperty} property
Tim van der Lippe6d1e03c2020-01-22 14:05:58571 * @param {!AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37572 */
573 constructor(property, axNode) {
574 super(axNode);
575 this._property = property;
576 this._axNode = axNode;
577 this.toggleOnClick = true;
578 this.selectable = false;
579 }
580
581 /**
582 * @param {?string} reason
Tim van der Lippe6d1e03c2020-01-22 14:05:58583 * @param {?AccessibilityNode} axNode
Blink Reformat4c46d092018-04-07 15:32:37584 * @return {?Element}
585 */
586 static createReasonElement(reason, axNode) {
587 let reasonElement = null;
588 switch (reason) {
589 case 'activeModalDialog':
Mathias Bynens7d8cd342019-09-17 13:32:10590 reasonElement = UI.formatLocalized('Element is hidden by active modal dialog:\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37591 break;
592 case 'ancestorIsLeafNode':
Mathias Bynens7d8cd342019-09-17 13:32:10593 reasonElement = UI.formatLocalized('Ancestor\'s children are all presentational:\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37594 break;
595 case 'ariaHiddenElement': {
596 const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
597 reasonElement = UI.formatLocalized('Element is %s.', [ariaHiddenSpan]);
598 break;
599 }
600 case 'ariaHiddenSubtree': {
601 const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
602 const trueSpan = createElement('span', 'source-code').textContent = 'true';
Mathias Bynens7d8cd342019-09-17 13:32:10603 reasonElement = UI.formatLocalized('%s is %s on ancestor:\xA0', [ariaHiddenSpan, trueSpan]);
Blink Reformat4c46d092018-04-07 15:32:37604 break;
605 }
606 case 'emptyAlt':
607 reasonElement = UI.formatLocalized('Element has empty alt text.', []);
608 break;
609 case 'emptyText':
610 reasonElement = UI.formatLocalized('No text content.', []);
611 break;
612 case 'inertElement':
613 reasonElement = UI.formatLocalized('Element is inert.', []);
614 break;
615 case 'inertSubtree':
Mathias Bynens7d8cd342019-09-17 13:32:10616 reasonElement = UI.formatLocalized('Element is in an inert subtree from\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37617 break;
618 case 'inheritsPresentation':
Mathias Bynens7d8cd342019-09-17 13:32:10619 reasonElement = UI.formatLocalized('Element inherits presentational role from\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37620 break;
621 case 'labelContainer':
Mathias Bynens7d8cd342019-09-17 13:32:10622 reasonElement = UI.formatLocalized('Part of label element:\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37623 break;
624 case 'labelFor':
Mathias Bynens7d8cd342019-09-17 13:32:10625 reasonElement = UI.formatLocalized('Label for\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37626 break;
627 case 'notRendered':
628 reasonElement = UI.formatLocalized('Element is not rendered.', []);
629 break;
630 case 'notVisible':
631 reasonElement = UI.formatLocalized('Element is not visible.', []);
632 break;
633 case 'presentationalRole': {
634 const rolePresentationSpan = createElement('span', 'source-code').textContent = 'role=' + axNode.role().value;
635 reasonElement = UI.formatLocalized('Element has %s.', [rolePresentationSpan]);
636 break;
637 }
638 case 'probablyPresentational':
639 reasonElement = UI.formatLocalized('Element is presentational.', []);
640 break;
641 case 'staticTextUsedAsNameFor':
Mathias Bynens7d8cd342019-09-17 13:32:10642 reasonElement = UI.formatLocalized('Static text node is used as name for\xA0', []);
Blink Reformat4c46d092018-04-07 15:32:37643 break;
644 case 'uninteresting':
645 reasonElement = UI.formatLocalized('Element not interesting for accessibility.', []);
646 break;
647 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34648 if (reasonElement) {
Blink Reformat4c46d092018-04-07 15:32:37649 reasonElement.classList.add('ax-reason');
Tim van der Lippe1d6e57a2019-09-30 11:55:34650 }
Blink Reformat4c46d092018-04-07 15:32:37651 return reasonElement;
652 }
653
654 /**
655 * @override
656 */
657 onattach() {
658 this.listItemElement.removeChildren();
659
Tim van der Lippe6d1e03c2020-01-22 14:05:58660 this._reasonElement = AXNodeIgnoredReasonTreeElement.createReasonElement(this._property.name, this._axNode);
Blink Reformat4c46d092018-04-07 15:32:37661 this.listItemElement.appendChild(this._reasonElement);
662
663 const value = this._property.value;
Tim van der Lippe1d6e57a2019-09-30 11:55:34664 if (value.type === Protocol.Accessibility.AXValueType.Idref) {
Blink Reformat4c46d092018-04-07 15:32:37665 this.appendRelatedNodeListValueElement(value);
Tim van der Lippe1d6e57a2019-09-30 11:55:34666 }
Blink Reformat4c46d092018-04-07 15:32:37667 }
Paul Lewisf16142c2019-11-07 15:56:04668}