Bug 1014923 - TreeWidget should have an option for unsorted tree. r=bgrins

This commit is contained in:
Gabriel Luong 2014-05-29 08:26:00 -04:00
Родитель c2dff795e4
Коммит ea405c4c4d
2 изменённых файлов: 63 добавлений и 13 удалений

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

@ -34,6 +34,8 @@ function startTests() {
populateTree(); populateTree();
testTreeItemInsertedCorrectly(); testTreeItemInsertedCorrectly();
testAPI(); testAPI();
populateUnsortedTree();
testUnsortedTreeItemInsertedCorrectly();
endTests(); endTests();
} }
@ -119,6 +121,41 @@ function testTreeItemInsertedCorrectly() {
"Newly added node is inserted at the right location"); "Newly added node is inserted at the right location");
} }
/**
* Populate the unsorted tree.
*/
function populateUnsortedTree() {
tree.sorted = false;
tree.add([{ id: "g-1", label: "g-1"}])
tree.add(["g-1", { id: "d-2", label: "d-2.1"}]);
tree.add(["g-1", { id: "b-2", label: "b-2.2"}]);
tree.add(["g-1", { id: "a-2", label: "a-2.3"}]);
}
/**
* Test if the nodes are inserted correctly in the unsorted tree.
*/
function testUnsortedTreeItemInsertedCorrectly() {
ok(tree.root.items.has("g-1"), "g-1 top level element exists");
is(tree.root.children.firstChild.lastChild.children.length, 3,
"Number of children for g-1 matches");
is(tree.root.children.firstChild.dataset.id, JSON.stringify(["g-1"]),
"Data id of g-1 matches");
is(tree.root.children.firstChild.firstChild.textContent, "g-1",
"Text content of g-1 matches");
is(tree.root.children.firstChild.lastChild.firstChild.dataset.id,
JSON.stringify(["g-1", "d-2"]),
"Data id of d-2 matches");
is(tree.root.children.firstChild.lastChild.firstChild.textContent, "d-2.1",
"Text content of d-2 matches");
is(tree.root.children.firstChild.lastChild.firstChild.nextSibling.textContent,
"b-2.2", "Text content of b-2 matches");
is(tree.root.children.firstChild.lastChild.lastChild.textContent, "a-2.3",
"Text content of a-2 matches");
}
/** /**
* Tests if the API exposed by TreeWidget works properly * Tests if the API exposed by TreeWidget works properly
*/ */

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

@ -18,6 +18,8 @@ const EventEmitter = require("devtools/toolkit/event-emitter");
* @param {Object} options * @param {Object} options
* - emptyText {string}: text to display when no entries in the table. * - emptyText {string}: text to display when no entries in the table.
* - defaultType {string}: The default type of the tree items. For ex. 'js' * - defaultType {string}: The default type of the tree items. For ex. 'js'
* - sorted {boolean}: Defaults to true. If true, tree items are kept in
* lexical order. If false, items will be kept in insertion order.
*/ */
function TreeWidget(node, options={}) { function TreeWidget(node, options={}) {
EventEmitter.decorate(this); EventEmitter.decorate(this);
@ -26,9 +28,9 @@ function TreeWidget(node, options={}) {
this.window = this.document.defaultView; this.window = this.document.defaultView;
this._parent = node; this._parent = node;
let {emptyText, defaultType} = options; this.emptyText = options.emptyText || "";
this.emptyText = emptyText || ""; this.defaultType = options.defaultType;
this.defaultType = defaultType; this.sorted = options.sorted !== false;
this.setupRoot(); this.setupRoot();
@ -245,7 +247,7 @@ TreeWidget.prototype = {
* its id. * its id.
*/ */
add: function(items) { add: function(items) {
this.root.add(items, this.defaultType); this.root.add(items, this.defaultType, this.sorted);
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (items[i].attachment) { if (items[i].attachment) {
this.attachments.set(JSON.stringify( this.attachments.set(JSON.stringify(
@ -459,8 +461,11 @@ TreeItem.prototype = {
* Same as TreeWidget.add method's argument * Same as TreeWidget.add method's argument
* @param {string} defaultType * @param {string} defaultType
* The default type of the item to be used when items[i].type is null * The default type of the item to be used when items[i].type is null
* @param {boolean} sorted
* true if the tree items are inserted in a lexically sorted manner.
* Otherwise, false if the item are to be appended to their parent.
*/ */
add: function(items, defaultType) { add: function(items, defaultType, sorted) {
if (items.length == this.level) { if (items.length == this.level) {
// This is the exit condition of recursive TreeItem.add calls // This is the exit condition of recursive TreeItem.add calls
return; return;
@ -470,7 +475,7 @@ TreeItem.prototype = {
if (this.items.has(id)) { if (this.items.has(id)) {
// An item with same id already exists, thus calling the add method of that // An item with same id already exists, thus calling the add method of that
// child to add the passed node at correct position. // child to add the passed node at correct position.
this.items.get(id).add(items, defaultType); this.items.get(id).add(items, defaultType, sorted);
return; return;
} }
// No item with the id `id` exists, so we create one and call the add // No item with the id `id` exists, so we create one and call the add
@ -486,19 +491,27 @@ TreeItem.prototype = {
} }
let treeItem = new TreeItem(this.document, this, node || label, let treeItem = new TreeItem(this.document, this, node || label,
items[this.level].type || defaultType); items[this.level].type || defaultType);
let nextSibling = [...this.items.values()].find(child => {
return child.label.textContent >= label; treeItem.add(items, defaultType, sorted);
});
treeItem.add(items, defaultType);
treeItem.node.setAttribute("data-id", JSON.stringify( treeItem.node.setAttribute("data-id", JSON.stringify(
items.slice(0, this.level + 1).map(item => item.id || item) items.slice(0, this.level + 1).map(item => item.id || item)
)); ));
// Inserting this newly created item at correct position
if (nextSibling) { if (sorted) {
this.children.insertBefore(treeItem.node, nextSibling.node); // Inserting this newly created item at correct position
let nextSibling = [...this.items.values()].find(child => {
return child.label.textContent >= label;
});
if (nextSibling) {
this.children.insertBefore(treeItem.node, nextSibling.node);
} else {
this.children.appendChild(treeItem.node);
}
} else { } else {
this.children.appendChild(treeItem.node); this.children.appendChild(treeItem.node);
} }
if (this.label) { if (this.label) {
this.label.removeAttribute("empty"); this.label.removeAttribute("empty");
} }