Bug 865478 - Add getItemsByUrl and removeItem methods to richgrid + tests. r=mbrubeck
authorSam Foster <sfoster@mozilla.com>
Fri, 26 Apr 2013 10:29:59 +0100
changeset 140988 34413bab9ad5ea4515976a0b491810d5ea46c60d
parent 140987 ef735506cb13a73079602bb2c964ed980c9f8ff2
child 140989 17b205981e76e2c6993d42b343cbc4cc76ea6ff3
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs865478
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 865478 - Add getItemsByUrl and removeItem methods to richgrid + tests. r=mbrubeck
browser/metro/base/content/bindings/grid.xml
browser/metro/base/tests/mochitest/browser_tilegrid.xul
browser/metro/base/tests/mochitest/browser_tiles.js
--- a/browser/metro/base/content/bindings/grid.xml
+++ b/browser/metro/base/content/bindings/grid.xml
@@ -220,48 +220,71 @@
           ]]>
         </body>
       </method>
       <method name="removeItemAt">
         <parameter name="anIndex"/>
         <parameter name="aSkipArrange"/>
         <body>
           <![CDATA[
-            let removal = this.getItemAtIndex(anIndex);
-            this.removeChild(removal);
-            if (!aSkipArrange)
-              this.arrangeItems();
+            let item = this.getItemAtIndex(anIndex);
+            return item ? this.removeItem(item, aSkipArrange) : null;
+          ]]>
+        </body>
+      </method>
+
+      <method name="removeItem">
+        <parameter name="aItem"/>
+        <parameter name="aSkipArrange"/>
+        <body>
+          <![CDATA[
+            let removal = aItem.parentNode == this && this.removeChild(aItem);
+            if (removal && !aSkipArrange)
+                this.arrangeItems();
+
+            // note that after removal the node is unbound
+            // so none of the richgriditem binding methods & properties are available
             return removal;
           ]]>
         </body>
       </method>
 
+
       <method name="getIndexOfItem">
         <parameter name="anItem"/>
         <body>
           <![CDATA[
             if (!anItem)
               return -1;
 
-            return Array.prototype.indexOf.call(this.children, anItem);
+            return Array.indexOf(this.children, anItem);
           ]]>
         </body>
       </method>
 
       <method name="getItemAtIndex">
         <parameter name="anIndex"/>
         <body>
           <![CDATA[
             if (!this._isIndexInBounds(anIndex))
               return null;
             return this.children.item(anIndex);
           ]]>
         </body>
       </method>
 
+      <method name="getItemsByUrl">
+        <parameter name="aUrl"/>
+        <body>
+          <![CDATA[
+            return this.querySelectorAll('richgriditem[value="'+aUrl+'"]');
+          ]]>
+        </body>
+      </method>
+
     <!-- Interface for offsetting selection and checking bounds -->
 
       <property name="isSelectionAtStart" readonly="true"
                 onget="return this.selectedIndex == 0;"/>
 
       <property name="isSelectionAtEnd" readonly="true"
                 onget="return this.selectedIndex == (this.itemCount - 1);"/>
 
--- a/browser/metro/base/tests/mochitest/browser_tilegrid.xul
+++ b/browser/metro/base/tests/mochitest/browser_tilegrid.xul
@@ -35,16 +35,29 @@
     </hbox>
     <hbox>
       <richgrid id="grid4" seltype="single" flex="1">
         <richgriditem value="about:blank" id="grid4_item1" label="First item"/>
         <richgriditem value="about:blank" id="grid4_item2" label="2nd item"/>
       </richgrid>
     </hbox>
     <hbox>
+      <richgrid id="grid5" seltype="single" flex="1">
+        <richgriditem value="about:blank" id="grid5_item1" label="First item"/>
+        <richgriditem value="http://bugzilla.mozilla.org/" id="grid5_item2" label="2nd item"/>
+        <richgriditem value="about:blank" id="grid5_item3" label="3rd item"/>
+        <richgriditem value="http://bugzilla.mozilla.org/" id="grid5_item4" label="4th item"/>
+      </richgrid>
+    </hbox>
+    <hbox>
+      <richgrid id="grid6" seltype="single" flex="1">
+        <richgriditem value="about:blank" id="grid6_item1" label="First item"/>
+      </richgrid>
+    </hbox>
+    <hbox>
       <richgrid id="grid-select1" seltype="single" flex="1">
         <richgriditem value="about:blank" id="grid-select1_item1" label="First item"/>
         <richgriditem value="about:blank" id="grid-select1_item2" label="2nd item"/>
       </richgrid>
     </hbox>
     <hbox>
       <richgrid id="grid-select2" seltype="multiple" flex="1">
         <richgriditem value="about:blank" id="grid-select2_item1" label="First item"/>
--- a/browser/metro/base/tests/mochitest/browser_tiles.js
+++ b/browser/metro/base/tests/mochitest/browser_tiles.js
@@ -1,9 +1,9 @@
-let doc, win;
+let doc;
 
 function test() {
   waitForExplicitFinish();
   Task.spawn(function(){
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
     info(chromeRoot + "browser_tilegrid.xul");
     yield addTab(chromeRoot + "browser_tilegrid.xul");
@@ -166,16 +166,70 @@ gTests.push({
     let badItem = doc.createElement("richgriditem");
 
     is(grid.getIndexOfItem(item), 1, "getIndexOfItem returns the correct value for an item");
     is(grid.getIndexOfItem(badItem), -1, "getIndexOfItem returns -1 for items it doesn't contain");
   }
 });
 
 gTests.push({
+  desc: "getItemsByUrl",
+  run: function() {
+    let grid = doc.querySelector("#grid5");
+
+    is(grid.itemCount, 4, "4 items total");
+    is(typeof grid.getItemsByUrl, "function", "getItemsByUrl is a function on the grid");
+
+    ['about:blank', 'http://bugzilla.mozilla.org/'].forEach(function(testUrl) {
+      let items = grid.getItemsByUrl(testUrl);
+      is(items.length, 2, "2 matching items in the test grid");
+      is(items.item(0).url, testUrl, "Matched item has correct url property");
+      is(items.item(1).url, testUrl, "Matched item has correct url property");
+    });
+
+    let badUrl = 'http://gopher.well.com:70/';
+    let items = grid.getItemsByUrl(badUrl);
+    is(items.length, 0, "0 items matched url: "+badUrl);
+
+  }
+});
+
+gTests.push({
+  desc: "removeItem",
+  run: function() {
+    let grid = doc.querySelector("#grid5");
+
+    is(grid.itemCount, 4, "4 items total");
+    is(typeof grid.removeItem, "function", "removeItem is a function on the grid");
+
+    let arrangeStub = stubMethod(grid, "arrangeItems");
+    let removedFirst = grid.removeItem( grid.children[0] );
+
+    is(arrangeStub.callCount, 1, "arrangeItems is called when we removeItem");
+
+    let removed2nd = grid.removeItem( grid.children[0], true);
+    is(removed2nd.getAttribute("label"), "2nd item", "the next item was returned");
+    is(grid.itemCount, 2, "2 items remain");
+
+    // callCount should still be at 1
+    is(arrangeStub.callCount, 1, "arrangeItems is not called when we pass the truthy skipArrange param");
+
+    let otherItem = grid.ownerDocument.querySelector("#grid6_item1");
+    let removedFail = grid.removeItem(otherItem);
+    ok(!removedFail, "Falsy value returned when non-child item passed");
+    is(grid.itemCount, 2, "2 items remain");
+
+    // callCount should still be at 1
+    is(arrangeStub.callCount, 1, "arrangeItems is not called when nothing is matched");
+
+    arrangeStub.restore();
+  }
+});
+
+gTests.push({
   desc: "selections (single)",
   run: function() {
      // when seltype is single,
      //      maintains a selectedItem property
      //      maintains a selectedIndex property
      //     clearSelection, selectItem, toggleItemSelection methods are implemented
      //     'select' events are implemented
     let grid = doc.querySelector("#grid-select1");