Bug 1265686 - Add PageUp/PageDown/Home/End navigation in AbstractTreeItem; r=gregtatum

MozReview-Commit-ID: 1LkKblI5ghz

--HG--
extra : rebase_source : 60fc6c0852d0e193b2de27a07dc49124540a4da6
This commit is contained in:
Luke Chang 2016-07-13 19:12:31 +08:00
Родитель 711bee9e8d
Коммит cee31bc485
3 изменённых файлов: 177 добавлений и 1 удалений

Просмотреть файл

@ -102,6 +102,7 @@ support-files =
[browser_perf-tree-abstract-02.js]
[browser_perf-tree-abstract-03.js]
[browser_perf-tree-abstract-04.js]
[browser_perf-tree-abstract-05.js]
[browser_perf-tree-view-01.js]
[browser_perf-tree-view-02.js]
[browser_perf-tree-view-03.js]

Просмотреть файл

@ -0,0 +1,104 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Tests if the abstract tree base class for the profiler's tree view
* supports PageUp/PageDown/Home/End keys.
*/
const { appendAndWaitForPaint } = require("devtools/client/performance/test/helpers/dom-utils");
const { synthesizeCustomTreeClass } = require("devtools/client/performance/test/helpers/synth-utils");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
add_task(function* () {
let { MyCustomTreeItem } = synthesizeCustomTreeClass();
let container = document.createElement("vbox");
container.style.height = '100%';
container.style.overflow = 'scroll';
yield appendAndWaitForPaint(gBrowser.selectedBrowser.parentNode, container);
let myDataSrc = {
label: "root",
children: []
};
for (let i = 0; i < 1000; i++) {
myDataSrc.children.push({
label: "child-" + i,
children: []
});
}
let treeRoot = new MyCustomTreeItem(myDataSrc, { parent: null });
treeRoot.attachTo(container);
treeRoot.focus();
treeRoot.expand();
is(document.commandDispatcher.focusedElement, treeRoot.target,
"The root node is focused.");
// Test HOME and END
key("VK_END");
is(document.commandDispatcher.focusedElement,
treeRoot.getChild(myDataSrc.children.length - 1).target,
"The last node is focused.");
key("VK_HOME");
is(document.commandDispatcher.focusedElement, treeRoot.target,
"The first (root) node is focused.");
// Test PageUp and PageDown
let nodesPerPageSize = treeRoot._getNodesPerPageSize();
key("VK_PAGE_DOWN");
is(document.commandDispatcher.focusedElement,
treeRoot.getChild(nodesPerPageSize - 1).target,
"The first node in the second page is focused.");
key("VK_PAGE_DOWN");
is(document.commandDispatcher.focusedElement,
treeRoot.getChild(nodesPerPageSize * 2 - 1).target,
"The first node in the third page is focused.");
key("VK_PAGE_UP");
is(document.commandDispatcher.focusedElement,
treeRoot.getChild(nodesPerPageSize - 1).target,
"The first node in the second page is focused.");
key("VK_PAGE_UP");
is(document.commandDispatcher.focusedElement, treeRoot.target,
"The first (root) node is focused.");
// Test PageUp in the middle of the first page
let middleIndex = Math.floor(nodesPerPageSize / 2);
treeRoot.getChild(middleIndex).target.focus();
is(document.commandDispatcher.focusedElement,
treeRoot.getChild(middleIndex).target,
"The middle node in the first page is focused.");
key("VK_PAGE_UP");
is(document.commandDispatcher.focusedElement, treeRoot.target,
"The first (root) node is focused.");
// Test PageDown in the middle of the last page
middleIndex = Math.ceil(myDataSrc.children.length - middleIndex);
treeRoot.getChild(middleIndex).target.focus();
is(document.commandDispatcher.focusedElement,
treeRoot.getChild(middleIndex).target,
"The middle node in the last page is focused.");
key("VK_PAGE_DOWN");
is(document.commandDispatcher.focusedElement,
treeRoot.getChild(myDataSrc.children.length - 1).target,
"The last node is focused.");
container.remove();
});

Просмотреть файл

@ -478,7 +478,48 @@ AbstractTreeItem.prototype = {
_getSiblingAtDelta: function (delta) {
let childNodes = this._containerNode.childNodes;
let indexOfSelf = Array.indexOf(childNodes, this._targetNode);
return childNodes[indexOfSelf + delta];
if (indexOfSelf + delta >= 0) {
return childNodes[indexOfSelf + delta];
}
return undefined;
},
_getNodesPerPageSize: function() {
let childNodes = this._containerNode.childNodes;
let nodeHeight = this._getHeight(childNodes[childNodes.length - 1]);
let containerHeight = this.bounds.height;
return Math.ceil(containerHeight / nodeHeight);
},
_getHeight: function(elem) {
let win = this.document.defaultView;
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
return utils.getBoundsWithoutFlushing(elem).height;
},
/**
* Focuses the first item in this tree.
*/
_focusFirstNode: function () {
let childNodes = this._containerNode.childNodes;
// The root node of the tree may be hidden in practice, so uses for-loop
// here to find the next visible node.
for (let i = 0; i < childNodes.length; i++) {
// The height will be 0 if an element is invisible.
if (this._getHeight(childNodes[i])) {
childNodes[i].focus();
return;
}
}
},
/**
* Focuses the last item in this tree.
*/
_focusLastNode: function () {
let childNodes = this._containerNode.childNodes;
childNodes[childNodes.length - 1].focus();
},
/**
@ -570,6 +611,36 @@ AbstractTreeItem.prototype = {
this._focusNextNode();
}
return;
case e.DOM_VK_PAGE_UP:
let pageUpElement =
this._getSiblingAtDelta(-this._getNodesPerPageSize());
// There's a chance that the root node is hidden. In this case, its
// height will be 0.
if (pageUpElement && this._getHeight(pageUpElement)) {
pageUpElement.focus();
} else {
this._focusFirstNode();
}
return;
case e.DOM_VK_PAGE_DOWN:
let pageDownElement =
this._getSiblingAtDelta(this._getNodesPerPageSize());
if (pageDownElement) {
pageDownElement.focus();
} else {
this._focusLastNode();
}
return;
case e.DOM_VK_HOME:
this._focusFirstNode();
return;
case e.DOM_VK_END:
this._focusLastNode();
return;
}
},