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

Unified Diff: third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js

Issue 2390783006: [DevTools] Accessibility: Show siblings and children of selected node (Closed)
Patch Set: Rebase tests again and be consistent about backendDOMNodeId Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js
index 9de87bb1eb8510475b4c2b11902734ca78af7ab8..3e3e482df56b3f7ddae93cd688fd118b07f58114 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AXTreePane.js
@@ -11,28 +11,133 @@ WebInspector.AXTreePane = class extends WebInspector.AccessibilitySubPane {
this._treeOutline = this.createTreeOutline();
this.element.classList.add('accessibility-computed');
+
+ this._expandedNodes = new Set();
}
/**
- * @param {!Array<!WebInspector.AccessibilityNode>} nodes
+ * @param {?WebInspector.AccessibilityNode} axNode
+ * @override
*/
- setAXNodeAndAncestors(nodes) {
- this._nodes = nodes;
+ setAXNode(axNode) {
+ this._axNode = axNode;
- var target = this.node().target();
var treeOutline = this._treeOutline;
treeOutline.removeChildren();
+
+ // TODO(aboxhall): show no node UI
+ if (!axNode)
+ return;
+
treeOutline.element.classList.remove('hidden');
- var previous = treeOutline.rootElement();
- while (nodes.length) {
- var ancestor = nodes.pop();
- var ancestorTreeElement = new WebInspector.AXNodeTreeElement(ancestor, target);
- previous.appendChild(ancestorTreeElement);
- previous.expand();
- previous = ancestorTreeElement;
+ var previousTreeElement = treeOutline.rootElement();
+ var inspectedNodeTreeElement = new WebInspector.AXNodeTreeElement(axNode, this);
+ inspectedNodeTreeElement.setInspected(true);
+
+ var parent = axNode.parentNode();
+ if (parent) {
+ this.setExpanded(parent.backendDOMNodeId(), false);
+
+ var chain = [];
+ var ancestor = parent.parentNode();
+ while (ancestor) {
+ chain.unshift(ancestor);
+ ancestor = ancestor.parentNode();
+ }
+ for (var ancestorNode of chain) {
+ var ancestorTreeElement = new WebInspector.AXNodeTreeElement(ancestorNode, this);
+ previousTreeElement.appendChild(ancestorTreeElement);
+ previousTreeElement.expand();
+ previousTreeElement = ancestorTreeElement;
+ }
+ var parentTreeElement = new WebInspector.AXNodeTreeParentElement(parent, inspectedNodeTreeElement, this);
+ previousTreeElement.appendChild(parentTreeElement);
+ if (this.isExpanded(parent.backendDOMNodeId()))
+ parentTreeElement.appendSiblings();
+ else
+ parentTreeElement.appendChild(inspectedNodeTreeElement);
+ previousTreeElement.expand();
+ previousTreeElement = parentTreeElement;
+ } else {
+ previousTreeElement.appendChild(inspectedNodeTreeElement);
+ }
+
+ previousTreeElement.expand();
+
+ for (var child of axNode.children()) {
+ var childTreeElement = new WebInspector.AXNodeTreeElement(child, this);
+ inspectedNodeTreeElement.appendChild(childTreeElement);
}
- previous.selectable = true;
- previous.select(true /* omitFocus */);
+
+ inspectedNodeTreeElement.selectable = true;
+ inspectedNodeTreeElement.select(!this._selectedByUser /* omitFocus */, false);
+ if (this.isExpanded(axNode.backendDOMNodeId()))
+ inspectedNodeTreeElement.expand();
+ this.clearSelectedByUser();
+ }
+
+ /**
+ * @param {boolean} selectedByUser
+ */
+ setSelectedByUser(selectedByUser) {
+ this._selectedByUser = true;
+ }
+
+ clearSelectedByUser() {
+ delete this._selectedByUser;
+ }
+
+ /**
+ * @return {!WebInspector.Target}
+ */
+ target() {
+ return this.node().target();
+ }
+
+ /**
+ * @param {?number} backendDOMNodeId
+ * @param {boolean} expanded
+ */
+ setExpanded(backendDOMNodeId, expanded) {
+ if (!backendDOMNodeId)
+ return;
+ if (expanded)
+ this._expandedNodes.add(backendDOMNodeId);
+ else
+ this._expandedNodes.delete(backendDOMNodeId);
+ }
+
+ /**
+ * @param {?number} backendDOMNodeId
+ * @return {boolean}
+ */
+ isExpanded(backendDOMNodeId) {
+ if (!backendDOMNodeId)
+ return false;
+
+ return this._expandedNodes.has(backendDOMNodeId);
+ }
+};
+
+WebInspector.InspectNodeButton = class {
+ /**
+ * @param {!WebInspector.AccessibilityNode} axNode
+ * @param {!WebInspector.AXTreePane} treePane
+ */
+ constructor(axNode, treePane) {
+ this._axNode = axNode;
+ this._treePane = treePane;
+
+ this.element = createElementWithClass('button', 'inspect-dom-node');
+ this.element.addEventListener('mousedown', this._handleMouseDown.bind(this));
+ }
+
+ /**
+ * @param {!Event} event
+ */
+ _handleMouseDown(event) {
+ this._treePane.setSelectedByUser(true);
+ WebInspector.Revealer.reveal(this._axNode.deferredDOMNode());
}
};
@@ -42,19 +147,61 @@ WebInspector.AXTreePane = class extends WebInspector.AccessibilitySubPane {
WebInspector.AXNodeTreeElement = class extends TreeElement {
/**
* @param {!WebInspector.AccessibilityNode} axNode
- * @param {!WebInspector.Target} target
+ * @param {!WebInspector.AXTreePane} treePane
*/
- constructor(axNode, target) {
+ constructor(axNode, treePane) {
// Pass an empty title, the title gets made later in onattach.
super('');
/** @type {!WebInspector.AccessibilityNode} */
this._axNode = axNode;
- /** @type {!WebInspector.Target} */
- this._target = target;
+ /** @type {!WebInspector.AXTreePane} */
+ this._treePane = treePane;
- this.selectable = false;
+ this.selectable = true;
+
+ this._inspectNodeButton =
+ new WebInspector.InspectNodeButton(axNode, treePane);
+ }
+
+ /**
+ * @return {!WebInspector.AccessibilityNode}
+ */
+ axNode() {
+ return this._axNode;
+ }
+
+ /**
+ * @param {boolean} inspected
+ */
+ setInspected(inspected) {
+ this._inspected = inspected;
+ this.listItemElement.classList.toggle('inspected', this._inspected);
+ }
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ onenter() {
+ this.inspectDOMNode();
+ return true;
+ }
+
+ /**
+ * @override
+ * @param {!Event} event
+ * @return {boolean}
+ */
+ ondblclick(event) {
+ this.inspectDOMNode();
+ return true;
+ }
+
+ inspectDOMNode() {
+ this._treePane.setSelectedByUser(true);
+ WebInspector.Revealer.reveal(this._axNode.deferredDOMNode());
}
/**
@@ -71,11 +218,45 @@ WebInspector.AXNodeTreeElement = class extends TreeElement {
this._appendIgnoredNodeElement();
} else {
this._appendRoleElement(this._axNode.role());
- if ('name' in this._axNode && this._axNode.name().value) {
+ if (this._axNode.name().value) {
this.listItemElement.createChild('span', 'separator').textContent = '\u00A0';
this._appendNameElement(/** @type {string} */ (this._axNode.name().value));
}
}
+
+ if (this._axNode.hasOnlyUnloadedChildren()) {
+ this.listItemElement.classList.add('children-unloaded');
+ this.setExpandable(true);
+ } else {
+ this.setExpandable(!!this._axNode.numChildren());
+ }
+
+ if (!this._axNode.isDOMNode())
+ this.listItemElement.classList.add('no-dom-node');
+ this.listItemElement.appendChild(this._inspectNodeButton.element);
+ }
+
+ /**
+ * @override
+ */
+ expand() {
+ if (!this._axNode || this._axNode.hasOnlyUnloadedChildren())
+ return;
+
+ this._treePane.setExpanded(this._axNode.backendDOMNodeId(), true);
+ super.expand();
+ }
+
+ /**
+ * @override
+ */
+ collapse() {
+ if (!this._axNode || this._axNode.hasOnlyUnloadedChildren())
+ return;
+
+ if (this._treePane)
+ this._treePane.setExpanded(this._axNode.backendDOMNodeId(), false);
+ super.collapse();
}
/**
@@ -108,6 +289,18 @@ WebInspector.AXNodeTreeElement = class extends TreeElement {
ignoredNodeElement.classList.add('ax-tree-ignored-node');
this.listItemElement.appendChild(ignoredNodeElement);
}
+
+ /**
+ * @param {boolean=} omitFocus
+ * @param {boolean=} selectedByUser
+ * @return {boolean}
+ * @override
+ */
+ select(omitFocus, selectedByUser) {
+ this._treePane.setSelectedByUser(!!selectedByUser);
+
+ return super.select(omitFocus, selectedByUser);
+ }
};
/** @type {!Object<string, string>} */
@@ -115,3 +308,110 @@ WebInspector.AXNodeTreeElement.RoleStyles = {
internalRole: 'ax-internal-role',
role: 'ax-role',
};
+
+/**
+ * @unrestricted
+ */
+WebInspector.ExpandSiblingsButton = class {
+ /**
+ * @param {!WebInspector.AXNodeTreeParentElement} treeElement
+ * @param {number} numSiblings
+ */
+ constructor(treeElement, numSiblings) {
+ this._treeElement = treeElement;
+
+ this.element = createElementWithClass('button', 'expand-siblings');
+ this.element.textContent = WebInspector.UIString(
+ (numSiblings === 1 ? '+ %d node' : '+ %d nodes'), numSiblings);
+ this.element.addEventListener('mousedown', this._handleMouseDown.bind(this));
+ }
+
+ /**
+ * @param {!Event} event
+ */
+ _handleMouseDown(event) {
+ this._treeElement.expandSiblings();
+ event.consume();
+ }
+};
+
+/**
+ * @unrestricted
+ */
+WebInspector.AXNodeTreeParentElement = class extends WebInspector.AXNodeTreeElement {
+ /**
+ * @param {!WebInspector.AccessibilityNode} axNode
+ * @param {!WebInspector.AXNodeTreeElement} inspectedNodeTreeElement
+ * @param {!WebInspector.AXTreePane} treePane
+ */
+ constructor(axNode, inspectedNodeTreeElement, treePane) {
+ super(axNode, treePane);
+
+ this._inspectedNodeTreeElement = inspectedNodeTreeElement;
+ var numSiblings = axNode.children().length - 1;
+ this._expandSiblingsButton = new WebInspector.ExpandSiblingsButton(this, numSiblings);
+ this._partiallyExpanded = false;
+ }
+
+ /**
+ * @override
+ */
+ onattach() {
+ super.onattach();
+ if (this._treePane.isExpanded(this._axNode.backendDOMNodeId()))
+ this._listItemNode.classList.add('siblings-expanded');
+ if (this._axNode.numChildren() > 1) {
+ this._listItemNode.insertBefore(this._expandSiblingsButton.element,
+ this._inspectNodeButton.element);
+ }
+ }
+
+ /**
+ * @param {boolean} altKey
+ * @return {boolean}
+ * @override
+ */
+ descendOrExpand(altKey) {
+ if (!this.expanded || !this._partiallyExpanded)
+ return super.descendOrExpand(altKey);
+
+ this.expandSiblings();
+ if (altKey)
+ this.expandRecursively();
+ return true;
+ }
+
+ /**
+ * @override
+ */
+ expand() {
+ super.expand();
+ this._partiallyExpanded = true;
+ }
+
+ expandSiblings() {
+ this._listItemNode.classList.add('siblings-expanded');
+ this.appendSiblings();
+ this.expanded = true;
+ this._partiallyExpanded = false;
+ this._treePane.setExpanded(this._axNode.backendDOMNodeId(), true);
+ }
+
+ appendSiblings() {
+ var inspectedAXNode = this._inspectedNodeTreeElement.axNode();
+ var nextIndex = 0;
+ var foundInspectedNode = false;
+ for (var sibling of this._axNode.children()) {
+ var siblingTreeElement = null;
+ if (sibling === inspectedAXNode) {
+ foundInspectedNode = true;
+ continue;
+ }
+ siblingTreeElement = new WebInspector.AXNodeTreeElement(sibling, this._treePane);
+ if (foundInspectedNode)
+ this.appendChild(siblingTreeElement);
+ else
+ this.insertChild(siblingTreeElement, nextIndex++);
+ }
+ }
+};

Powered by Google App Engine
This is Rietveld 408576698