Bug 925418 - replace richgrid.children with .items references, plus minor nits. r=mbrubeck

This commit is contained in:
Sam Foster 2013-10-14 09:33:12 -07:00
parent ececc0544e
commit b732c16d32
4 changed files with 80 additions and 79 deletions

View File

@ -26,6 +26,10 @@
<field name="controller">null</field>
<!-- collection of child items excluding empty tiles -->
<property name="items" readonly="true" onget="return this.querySelectorAll('richgriditem');"/>
<property name="itemCount" readonly="true" onget="return this.items.length;"/>
<!-- nsIDOMXULMultiSelectControlElement (not fully implemented) -->
<method name="clearSelection">
@ -158,8 +162,6 @@
<!-- nsIDOMXULSelectControlElement -->
<property name="itemCount" readonly="true" onget="return this.children.length;"/>
<field name="_selectedItem">null</field>
<property name="selectedItem" onget="return this._selectedItem;">
<setter>
@ -202,7 +204,7 @@
<parameter name="aSkipArrange"/>
<body>
<![CDATA[
let addition = this.createItemElement(aLabel, aValue);
let addition = this._createItemElement(aLabel, aValue);
this.appendChild(addition);
if (!aSkipArrange)
this.arrangeItems();
@ -232,7 +234,7 @@
<body>
<![CDATA[
let existing = this.getItemAtIndex(anIndex);
let addition = this.createItemElement(aLabel, aValue);
let addition = this._createItemElement(aLabel, aValue);
if (existing) {
this.insertBefore(addition, existing);
} else {
@ -250,7 +252,9 @@
<body>
<![CDATA[
let item = this.getItemAtIndex(anIndex);
return item ? this.removeItem(item, aSkipArrange) : null;
if (!item)
return null;
return this.removeItem(item, aSkipArrange);
]]>
</body>
</method>
@ -260,7 +264,9 @@
<parameter name="aSkipArrange"/>
<body>
<![CDATA[
let removal = aItem.parentNode == this && this.removeChild(aItem);
if (!aItem || Array.indexOf(this.items, aItem) < 0)
return null;
let removal = this.removeChild(aItem);
if (removal && !aSkipArrange)
this.arrangeItems();
@ -271,7 +277,6 @@
</body>
</method>
<method name="getIndexOfItem">
<parameter name="anItem"/>
<body>
@ -279,7 +284,7 @@
if (!anItem)
return -1;
return Array.indexOf(this.children, anItem);
return Array.indexOf(this.items, anItem);
]]>
</body>
</method>
@ -290,7 +295,7 @@
<![CDATA[
if (!this._isIndexInBounds(anIndex))
return null;
return this.children.item(anIndex);
return this.items.item(anIndex);
]]>
</body>
</method>
@ -609,16 +614,18 @@
</body>
</method>
<method name="createItemElement">
<method name="_createItemElement">
<parameter name="aLabel"/>
<parameter name="aValue"/>
<body>
<![CDATA[
let item = this.ownerDocument.createElement("richgriditem");
item.setAttribute("label", aLabel);
if (aValue) {
item.setAttribute("value", aValue);
}
if (aLabel) {
item.setAttribute("label", aLabel);
}
if(this.hasAttribute("tiletype")) {
item.setAttribute("tiletype", this.getAttribute("tiletype"));
}
@ -860,7 +867,7 @@
<property name="control">
<getter><![CDATA[
let parent = this.parentNode;
while (parent) {
while (parent && parent != this.ownerDocument.documentElement) {
if (parent instanceof Components.interfaces.nsIDOMXULSelectControlElement)
return parent;
parent = parent.parentNode;

View File

@ -100,7 +100,7 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
case "pin":
let pinIndices = [];
Array.forEach(selectedTiles, function(aNode) {
pinIndices.push( Array.indexOf(aNode.control.children, aNode) );
pinIndices.push( Array.indexOf(aNode.control.items, aNode) );
aNode.contextActions.delete('pin');
aNode.contextActions.add('unpin');
});
@ -153,7 +153,6 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
// flush, recreate all
this.isUpdating = true;
// destroy and recreate all item nodes, skip calling arrangeItems
grid.clearAll(true);
this.populateGrid();
}
},
@ -165,14 +164,18 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
let filepath = PageThumbsStorage.getFilePathForURL(aSite.url);
if (yield OS.File.exists(filepath)) {
aSite.backgroundImage = 'url("'+PageThumbs.getThumbnailURL(aSite.url)+'")';
if ('backgroundImage' in aTileNode) {
aTileNode.backgroundImage = aSite.backgroundImage;
} else {
aTileNode.setAttribute("customImage", aSite.backgroundImage);
if (aTileNode.refresh) {
aTileNode.refresh()
}
}
});
aSite.applyToTileNode(aTileNode);
if (aTileNode.refresh) {
aTileNode.refresh();
}
if (aArrangeGrid) {
this._set.arrangeItems();
}
@ -182,25 +185,20 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
this.isUpdating = true;
let sites = TopSites.getSites();
let length = Math.min(sites.length, this._topSitesMax || Infinity);
let tileset = this._set;
// if we're updating with a collection that is smaller than previous
// remove any extra tiles
while (tileset.children.length > length) {
tileset.removeChild(tileset.children[tileset.children.length -1]);
if (this._topSitesMax) {
sites = sites.slice(0, this._topSitesMax);
}
let tileset = this._set;
tileset.clearAll(true);
for (let idx=0; idx < length; idx++) {
let isNew = !tileset.children[idx],
site = sites[idx];
let item = isNew ? tileset.createItemElement(site.title, site.url) : tileset.children[idx];
for (let site of sites) {
// call to private _createItemElement is a temp measure
// we'll eventually just request the next slot
let item = tileset._createItemElement(site.title, site.url);
this.updateTile(item, site);
if (isNew) {
tileset.appendChild(item);
}
}
tileset.arrangeItems();
this.isUpdating = false;
},

View File

@ -18,8 +18,8 @@ gTests.push({
ok(grid, "#grid1 is found");
is(typeof grid.clearSelection, "function", "#grid1 has the binding applied");
is(grid.children.length, 2, "#grid1 has a 2 items");
is(grid.children[0].control, grid, "#grid1 item's control points back at #grid1'");
is(grid.items.length, 2, "#grid1 has a 2 items");
is(grid.items[0].control, grid, "#grid1 item's control points back at #grid1'");
}
});
@ -29,7 +29,7 @@ gTests.push({
let grid = doc.querySelector("#grid1");
is(typeof grid.handleItemClick, "function", "grid.handleItemClick is a function");
let handleStub = stubMethod(grid, 'handleItemClick');
let itemId = "grid1_item1"; // grid.children[0].getAttribute("id");
let itemId = "grid1_item1"; // grid.items[0].getAttribute("id");
// send click to item and wait for next tick;
EventUtils.sendMouseEvent({type: 'click'}, itemId, doc.defaultView);
@ -114,9 +114,8 @@ gTests.push({
grid.clearAll();
is(grid.itemCount, 0, "grid has 0 itemCount after clearAll");
is(grid.children.length, 0, "grid has 0 children after clearAll");
is(grid.rowCount, 0, "grid has 0 rows when empty");
is(grid.columnCount, 0, "grid has 0 cols when empty");
is(grid.items.length, 0, "grid has 0 items after clearAll");
// now that we use slots, an empty grid may still have non-zero rows & columns
is(arrangeSpy.callCount, 1, "arrangeItems is called once when we clearAll");
arrangeSpy.restore();
@ -150,13 +149,13 @@ gTests.push({
let grid = doc.querySelector("#emptygrid");
is(grid.itemCount, 0, "0 itemCount when empty");
is(grid.children.length, 0, "0 children when empty");
is(grid.items.length, 0, "0 items when empty");
is(typeof grid.appendItem, "function", "appendItem is a function on the grid");
let arrangeStub = stubMethod(grid, "arrangeItems");
let newItem = grid.appendItem("test title", "about:blank");
ok(newItem && grid.children[0]==newItem, "appendItem gives back the item");
ok(newItem && grid.items[0]==newItem, "appendItem gives back the item");
is(grid.itemCount, 1, "itemCount is incremented when we appendItem");
is(newItem.getAttribute("label"), "test title", "title ends up on label attribute");
is(newItem.getAttribute("value"), "about:blank", "url ends up on value attribute");
@ -193,7 +192,7 @@ gTests.push({
ok(removedItem, "removeItemAt gives back an item");
is(removedItem.getAttribute("id"), "grid2_item1", "removeItemAt gives back the correct item");
is(grid.children[0].getAttribute("id"), "grid2_item2", "2nd item becomes the first item");
is(grid.items[0].getAttribute("id"), "grid2_item2", "2nd item becomes the first item");
is(grid.itemCount, 1, "itemCount is decremented when we removeItemAt");
is(arrangeStub.callCount, 1, "arrangeItems is called when we removeItemAt");
@ -215,10 +214,10 @@ gTests.push({
let insertedItem = grid.insertItemAt(1, "inserted item", "http://example.com/inserted");
ok(insertedItem, "insertItemAt gives back an item");
is(grid.children[1], insertedItem, "item is inserted at the correct index");
is(grid.items[1], insertedItem, "item is inserted at the correct index");
is(insertedItem.getAttribute("label"), "inserted item", "insertItemAt creates item with the correct label");
is(insertedItem.getAttribute("value"), "http://example.com/inserted", "insertItemAt creates item with the correct url value");
is(grid.children[2].getAttribute("id"), "grid3_item2", "following item ends up at the correct index");
is(grid.items[2].getAttribute("id"), "grid3_item2", "following item ends up at the correct index");
is(grid.itemCount, 3, "itemCount is incremented when we insertItemAt");
is(arrangeStub.callCount, 1, "arrangeItems is called when we insertItemAt");
@ -275,11 +274,11 @@ gTests.push({
is(typeof grid.removeItem, "function", "removeItem is a function on the grid");
let arrangeStub = stubMethod(grid, "arrangeItems");
let removedFirst = grid.removeItem( grid.children[0] );
let removedFirst = grid.removeItem( grid.items[0] );
is(arrangeStub.callCount, 1, "arrangeItems is called when we removeItem");
let removed2nd = grid.removeItem( grid.children[0], true);
let removed2nd = grid.removeItem( grid.items[0], true);
is(removed2nd.getAttribute("label"), "2nd item", "the next item was returned");
is(grid.itemCount, 2, "2 items remain");
@ -316,23 +315,23 @@ gTests.push({
is(grid.itemCount, 2, "2 items initially");
is(grid.selectedItems.length, 0, "nothing selected initially");
grid.toggleItemSelection(grid.children[1]);
ok(grid.children[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
grid.toggleItemSelection(grid.items[1]);
ok(grid.items[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
is(grid.selectedIndex, 1, "selectedIndex is correct");
grid.toggleItemSelection(grid.children[1]);
ok(!grid.children[1].selected, "toggleItemSelection sets falsy selected prop on previously-selected item");
grid.toggleItemSelection(grid.items[1]);
ok(!grid.items[1].selected, "toggleItemSelection sets falsy selected prop on previously-selected item");
is(grid.selectedIndex, -1, "selectedIndex reports correctly with nothing selected");
// item selection
grid.selectItem(grid.children[1]);
ok(grid.children[1].selected, "Item selected property is truthy after grid.selectItem");
ok(grid.children[1].getAttribute("selected"), "Item selected attribute is truthy after grid.selectItem");
grid.selectItem(grid.items[1]);
ok(grid.items[1].selected, "Item selected property is truthy after grid.selectItem");
ok(grid.items[1].getAttribute("selected"), "Item selected attribute is truthy after grid.selectItem");
ok(grid.selectedItems.length, "There are selectedItems after grid.selectItem");
// clearSelection
grid.selectItem(grid.children[0]);
grid.selectItem(grid.children[1]);
grid.selectItem(grid.items[0]);
grid.selectItem(grid.items[1]);
grid.clearSelection();
is(grid.selectedItems.length, 0, "Nothing selected when we clearSelection");
is(grid.selectedIndex, -1, "selectedIndex resets after clearSelection");
@ -347,10 +346,10 @@ gTests.push({
doc.defaultView.addEventListener("select", handler, false);
info("select listener added");
info("calling selectItem, currently it is:" + grid.children[0].selected);
info("calling selectItem, currently it is:" + grid.items[0].selected);
// Note: A richgrid in seltype=single mode fires "select" events from selectItem
grid.selectItem(grid.children[0]);
info("calling selectItem, now it is:" + grid.children[0].selected);
grid.selectItem(grid.items[0]);
info("calling selectItem, now it is:" + grid.items[0].selected);
yield waitForMs(0);
is(handlerStub.callCount, 1, "select event handler was called when we selected an item");
@ -378,22 +377,22 @@ gTests.push({
is(grid.itemCount, 2, "2 items initially");
is(grid.selectedItems.length, 0, "nothing selected initially");
grid.toggleItemSelection(grid.children[1]);
ok(grid.children[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
grid.toggleItemSelection(grid.items[1]);
ok(grid.items[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
is(grid.selectedItems.length, 1, "1 item selected when we first toggleItemSelection");
is(grid.selectedItems[0], grid.children[1], "the right item is selected");
is(grid.selectedItems[0], grid.items[1], "the right item is selected");
is(grid.selectedIndex, 1, "selectedIndex is correct");
grid.toggleItemSelection(grid.children[1]);
grid.toggleItemSelection(grid.items[1]);
is(grid.selectedItems.length, 0, "Nothing selected when we toggleItemSelection again");
// clearSelection
grid.children[0].selected=true;
grid.children[1].selected=true;
grid.items[0].selected=true;
grid.items[1].selected=true;
is(grid.selectedItems.length, 2, "Both items are selected before calling clearSelection");
grid.clearSelection();
is(grid.selectedItems.length, 0, "Nothing selected when we clearSelection");
ok(!(grid.children[0].selected || grid.children[1].selected), "selected properties all falsy when we clearSelection");
ok(!(grid.items[0].selected || grid.items[1].selected), "selected properties all falsy when we clearSelection");
// selectionchange events
// in seltype=multiple mode, we track selected state on all items
@ -405,10 +404,10 @@ gTests.push({
doc.defaultView.addEventListener("selectionchange", handler, false);
info("selectionchange listener added");
info("calling toggleItemSelection, currently it is:" + grid.children[0].selected);
info("calling toggleItemSelection, currently it is:" + grid.items[0].selected);
// Note: A richgrid in seltype=single mode fires "select" events from selectItem
grid.toggleItemSelection(grid.children[0]);
info("/calling toggleItemSelection, now it is:" + grid.children[0].selected);
grid.toggleItemSelection(grid.items[0]);
info("/calling toggleItemSelection, now it is:" + grid.items[0].selected);
yield waitForMs(0);
is(handlerStub.callCount, 1, "selectionchange event handler was called when we selected an item");
@ -418,6 +417,3 @@ gTests.push({
doc.defaultView.removeEventListener("selectionchange", handler, false);
}
});
// implements a getItemAtIndex method (or grid.children[idx] ?)

View File

@ -194,7 +194,7 @@ gTests.push({
},
run: function() {
let grid = TopSitesTestHelper.grid;
let items = grid.children;
let items = grid.items;
is(items.length, 8, "should be 8 topsites"); // i.e. not 10
if(items.length) {
let firstitem = items[0];
@ -230,7 +230,7 @@ gTests.push({
run: function() {
// test that pinned state of each site as rendered matches our expectations
let pins = this.pins.split(",");
let items = TopSitesTestHelper.grid.children;
let items = TopSitesTestHelper.grid.items;
is(items.length, 8, "should be 8 topsites in the grid");
is(TopSitesTestHelper.document.querySelectorAll("#start-topsites-grid > [pinned]").length, 3, "should be 3 children with 'pinned' attribute");
@ -273,10 +273,10 @@ gTests.push({
// test that site is pinned as expected
// and that sites fill positions around it
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 4, this.desc + ": should be 4 topsites");
let tile = grid.children[2],
let tile = grid.items[2],
url = tile.getAttribute("value"),
title = tile.getAttribute("label");
@ -291,7 +291,7 @@ gTests.push({
return !grid.controller.isUpdating;
});
let thirdTile = grid.children[2];
let thirdTile = grid.items[2];
ok( thirdTile.hasAttribute("pinned"), thirdTile.getAttribute("value")+ " should look pinned" );
// visit some more sites
@ -329,7 +329,7 @@ gTests.push({
// unpin a pinned site
// test that sites are unpinned as expected
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 8, this.desc + ": should be 8 topsites");
let site = {
url: items[1].getAttribute("value"),
@ -346,7 +346,7 @@ gTests.push({
return !grid.controller.isUpdating;
});
let secondTile = grid.children[1];
let secondTile = grid.items[1];
ok( !secondTile.hasAttribute("pinned"), "2nd item should no longer be marked as pinned" );
ok( !NewTabUtils.pinnedLinks.isPinned(site), "2nd item should no longer be pinned" );
}
@ -371,7 +371,7 @@ gTests.push({
// block a site
// test that sites are removed from the grid as expected
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 8, this.desc + ": should be 8 topsites");
let brianSite = TopSitesTestHelper.siteFromNode(items[0]);
@ -426,7 +426,7 @@ gTests.push({
is( grid.querySelectorAll("[value='"+dougalSite.url+"']").length, 1, "Unblocked site is back in the grid");
// ..and that a previously pinned site is re-pinned after being blocked, then restored
ok( NewTabUtils.pinnedLinks.isPinned(dougalSite), "Restoring previously pinned site makes it pinned again" );
is( grid.children[1].getAttribute("value"), dougalSite.url, "Blocked Site restored to pinned index" );
is( grid.items[1].getAttribute("value"), dougalSite.url, "Blocked Site restored to pinned index" );
ok( !NewTabUtils.blockedLinks.isBlocked(dylanSite), "site was unblocked" );
is( grid.querySelectorAll("[value='"+dylanSite.url+"']").length, 1, "Unblocked site is back in the grid");
@ -458,7 +458,7 @@ gTests.push({
// delete a both pinned and unpinned sites
// test that sites are removed from the grid
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 4, this.desc + ": should be 4 topsites");
let brianTile = grid.querySelector('richgriditem[value$="brian"]');