Bug 1058249 - Allow TableWidget to append DOMNodes as Cell values. r=bgrins, f=Optimizer
authorGabriel Luong <gabriel.luong@gmail.com>
Tue, 26 Aug 2014 17:08:00 -0400
changeset 223428 cad3710aa5228df8b1bba6a9d0832a7074a27187
parent 223427 76cce82c11164e34b98430ae5297b03a47b8369b
child 223429 21496f6351e4843befe15395fbc009175cd0405f
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1058249
milestone34.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 1058249 - Allow TableWidget to append DOMNodes as Cell values. r=bgrins, f=Optimizer
browser/devtools/shared/test/browser_tableWidget_basic.js
browser/devtools/shared/widgets/TableWidget.js
--- a/browser/devtools/shared/test/browser_tableWidget_basic.js
+++ b/browser/devtools/shared/test/browser_tableWidget_basic.js
@@ -103,21 +103,25 @@ function populateTable() {
     somethingExtra: "Hello World!"
   });
   table.push({
     col1: "id8",
     col2: "value11",
     col3: "value27",
     col4: "value34"
   });
+
+  let span = doc.createElement("span");
+  span.textContent = "domnode";
+
   table.push({
     col1: "id9",
     col2: "value11",
     col3: "value23",
-    col4: "value38"
+    col4: span
   });
 }
 
 /**
  * Test if the nodes are inserted correctly in the table.
  */
 function testTreeItemInsertedCorrectly() {
   is(table.tbody.children.length, 4*2 /* double because splitters */,
@@ -130,17 +134,17 @@ function testTreeItemInsertedCorrectly()
   }
   for (let i = 1; i < 10; i++) {
     is(table.tbody.firstChild.firstChild.children[i].value, "id" + i,
      "Correct value in row " + i);
   }
 }
 
 /**
- * Tests if the API exposed by TreeWidget works properly
+ * Tests if the API exposed by TableWidget works properly
  */
 function testAPI() {
   info("Testing TableWidget API");
   // Check if selectRow and selectedRow setter works as expected
   // Nothing should be selected beforehand
   ok(!doc.querySelector(".theme-selected"), "Nothing is selected");
   table.selectRow("id4");
   let node = doc.querySelector(".theme-selected");
@@ -295,27 +299,53 @@ function testAPI() {
   table.sortBy("col1");
   for (let i = 1; i < 10; i++) {
     is(table.tbody.firstChild.firstChild.children[i].value, "id" + (10 - i),
      "Correct value in row " + i + " after descending sort by on col1");
   }
   // Calling it on an unsorted column should sort by it in ascending manner
   table.sortBy("col2");
   let cell = table.tbody.children[2].firstChild.children[2];
-  while(cell) {
-    ok(cell.value >= cell.previousSibling.value, "Sorting is in ascending order");
-    cell = cell.nextSibling;
-  }
+  checkAscendingOrder(cell);
+
   // Calling it again should sort by it in descending manner
   table.sortBy("col2");
   let cell = table.tbody.children[2].firstChild.lastChild.previousSibling;
-  while(cell != cell.parentNode.firstChild) {
-    ok(cell.value >= cell.nextSibling.value, "Sorting is in descending order");
-    cell = cell.previousSibling;
-  }
+  checkDescendingOrder(cell);
+
   // Calling it again should sort by it in ascending manner
   table.sortBy("col2");
   let cell = table.tbody.children[2].firstChild.children[2];
+  checkAscendingOrder(cell);
+
+  table.clear();
+  populateTable();
+
+  // testing if sorting works should sort by ascending manner
+  table.sortBy("col4");
+  let cell = table.tbody.children[6].firstChild.children[1];
+  is(cell.textContent, "domnode", "DOMNode sorted correctly");
+  checkAscendingOrder(cell.nextSibling);
+
+  // Calling it again should sort it in descending order
+  table.sortBy("col4");
+  let cell = table.tbody.children[6].firstChild.children[9];
+  is(cell.textContent, "domnode", "DOMNode sorted correctly");
+  checkDescendingOrder(cell.previousSibling);
+}
+
+function checkAscendingOrder(cell) {
   while(cell) {
-    ok(cell.value >= cell.previousSibling.value, "Sorting is in ascending order");
+    let currentCell = cell.value || cell.textContent;
+    let prevCell = cell.previousSibling.value || cell.previousSibling.textContent;
+    ok(currentCell >= prevCell, "Sorting is in ascending order");
     cell = cell.nextSibling;
   }
 }
+
+function checkDescendingOrder(cell) {
+  while(cell != cell.parentNode.firstChild) {
+    let currentCell = cell.value || cell.textContent;
+    let nextCell = cell.nextSibling.value || cell.nextSibling.textContent;
+    ok(currentCell >= nextCell, "Sorting is in descending order");
+    cell = cell.previousSibling;
+  }
+}
--- a/browser/devtools/shared/widgets/TableWidget.js
+++ b/browser/devtools/shared/widgets/TableWidget.js
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
-const { Cu } = require("chrome");
+const {Cc, Ci, Cu} = require("chrome");
 
 const EventEmitter = require("devtools/toolkit/event-emitter");
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
 
 // Different types of events emitted by the Various components of the TableWidget
 const EVENTS = {
@@ -749,25 +749,32 @@ Column.prototype = {
     }
   },
 
   /**
    * Sorts the given items and returns the sorted list if the table was sorted
    * by this column.
    */
   sort: function(items) {
-
     // Only sort the array if we are sorting based on this column
     if (this.sorted == 1) {
       items.sort((a, b) => {
-        return a[this.id] > b[this.id]
+        let val1 = (a[this.id] instanceof Ci.nsIDOMNode) ?
+            a[this.id].textContent : a[this.id];
+        let val2 = (b[this.id] instanceof Ci.nsIDOMNode) ?
+            b[this.id].textContent : b[this.id];
+        return val1 > val2;
       });
     } else if (this.sorted > 1) {
       items.sort((a, b) => {
-        return b[this.id] > a[this.id]
+        let val1 = (a[this.id] instanceof Ci.nsIDOMNode) ?
+            a[this.id].textContent : a[this.id];
+        let val2 = (b[this.id] instanceof Ci.nsIDOMNode) ?
+            b[this.id].textContent : b[this.id];
+        return val2 > val1;
       });
     }
 
     if (this.selectedRow) {
       this.cells[this.items[this.selectedRow]].toggleClass("theme-selected");
     }
     this.items = {};
     // Otherwise, just use the sorted array passed to update the cells value.
@@ -801,18 +808,28 @@ Column.prototype = {
    * Mousedown event handler for the column. Used to select rows.
    */
   onMousedown: function(event) {
     if (event.originalTarget == this.column ||
         event.originalTarget == this.header) {
       return;
     }
     if (event.button == 0) {
-      this.table.emit(EVENTS.ROW_SELECTED,
-        event.originalTarget.getAttribute("data-id"));
+      let target = event.originalTarget;
+      let dataid = null;
+
+      while (target) {
+        dataid = target.getAttribute("data-id");
+        if (dataid) {
+          break;
+        }
+        target = target.parentNode;
+      }
+
+      this.table.emit(EVENTS.ROW_SELECTED, dataid);
     }
   },
 
   /**
    * Keydown event handler for the column. Used for keyboard navigation amongst
    * rows.
    */
   onKeydown: function(event) {
@@ -849,17 +866,19 @@ Column.prototype = {
 };
 
 /**
  * A single cell in a column
  *
  * @param {Column} column
  *        The column object to which the cell belongs.
  * @param {object} item
- *        The object representing the row.
+ *        The object representing the row. It contains a key value pair
+ *        representing the column id and its associated value. The value
+ *        can be a DOMNode that is appended or a string value.
  * @param {Cell} nextCell
  *        The cell object which is next to this cell. null if this cell is last
  *        cell of the column
  */
 function Cell(column, item, nextCell) {
   let document = column.document;
 
   this.label = document.createElementNS(XUL_NS, "label");
@@ -887,20 +906,33 @@ Cell.prototype = {
   },
 
   set value(value) {
     this._value = value;
     if (!value) {
       this.label.setAttribute("value", "");
       return;
     }
-    if (value.length > MAX_VISIBLE_STRING_SIZE) {
+
+    if (!(value instanceof Ci.nsIDOMNode) &&
+        value.length > MAX_VISIBLE_STRING_SIZE) {
       value = value .substr(0, MAX_VISIBLE_STRING_SIZE) + "\u2026"; // …
     }
-    this.label.setAttribute("value", value + "");
+
+    if (value instanceof Ci.nsIDOMNode) {
+      this.label.removeAttribute("value");
+
+      while (this.label.firstChild) {
+        this.label.removeChild(this.label.firstChild);
+      }
+
+      this.label.appendChild(value);
+    } else {
+      this.label.setAttribute("value", value + "");
+    }
   },
 
   get value() {
     return this._value;
   },
 
   toggleClass: function(className) {
     this.label.classList.toggle(className);