1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 /** 6 * @constructor 7 * @extends {WebInspector.ViewportDataGrid} 8 * @param {!Array.<!WebInspector.DataGrid.ColumnDescriptor>} columnsArray 9 * @param {function(!WebInspector.DataGridNode, string, string, string)=} editCallback 10 * @param {function(!WebInspector.DataGridNode)=} deleteCallback 11 * @param {function()=} refreshCallback 12 * @param {function(!WebInspector.ContextMenu, !WebInspector.DataGridNode)=} contextMenuCallback 13 */ 14 WebInspector.SortableDataGrid = function(columnsArray, editCallback, deleteCallback, refreshCallback, contextMenuCallback) 15 { 16 WebInspector.ViewportDataGrid.call(this, columnsArray, editCallback, deleteCallback, refreshCallback, contextMenuCallback); 17 /** @type {!WebInspector.SortableDataGrid.NodeComparator} */ 18 this._sortingFunction = WebInspector.SortableDataGrid.TrivialComparator; 19 this.setRootNode(new WebInspector.SortableDataGridNode()); 20 } 21 22 /** @typedef {function(!WebInspector.DataGridNode, !WebInspector.DataGridNode):number} */ 23 WebInspector.SortableDataGrid.NodeComparator; 24 25 /** 26 * @param {!WebInspector.DataGridNode} a 27 * @param {!WebInspector.DataGridNode} b 28 * @return {number} 29 */ 30 WebInspector.SortableDataGrid.TrivialComparator = function(a, b) 31 { 32 return 0; 33 } 34 35 /** 36 * @param {string} columnIdentifier 37 * @param {!WebInspector.DataGridNode} a 38 * @param {!WebInspector.DataGridNode} b 39 * @return {number} 40 */ 41 WebInspector.SortableDataGrid.NumericComparator = function(columnIdentifier, a, b) 42 { 43 var aValue = a.data[columnIdentifier]; 44 var bValue = b.data[columnIdentifier]; 45 var aNumber = Number(aValue instanceof Node ? aValue.textContent : aValue); 46 var bNumber = Number(bValue instanceof Node ? bValue.textContent : bValue); 47 return aNumber < bNumber ? -1 : (aNumber > bNumber ? 1 : 0); 48 } 49 50 /** 51 * @param {string} columnIdentifier 52 * @param {!WebInspector.DataGridNode} a 53 * @param {!WebInspector.DataGridNode} b 54 * @return {number} 55 */ 56 WebInspector.SortableDataGrid.StringComparator = function(columnIdentifier, a, b) 57 { 58 var aValue = a.data[columnIdentifier]; 59 var bValue = b.data[columnIdentifier]; 60 var aString = aValue instanceof Node ? aValue.textContent : String(aValue); 61 var bString = bValue instanceof Node ? bValue.textContent : String(bValue); 62 return aString < bString ? -1 : (aString > bString ? 1 : 0); 63 } 64 65 /** 66 * @param {!WebInspector.SortableDataGrid.NodeComparator} comparator 67 * @param {boolean} reverseMode 68 * @param {!WebInspector.DataGridNode} a 69 * @param {!WebInspector.DataGridNode} b 70 * @return {number} 71 */ 72 WebInspector.SortableDataGrid.Comparator = function(comparator, reverseMode, a, b) 73 { 74 return reverseMode ? comparator(b, a) : comparator(a, b); 75 } 76 77 /** 78 * @param {!Array.<string>} columnNames 79 * @param {!Array.<string>} values 80 * @return {?WebInspector.SortableDataGrid} 81 */ 82 WebInspector.SortableDataGrid.create = function(columnNames, values) 83 { 84 var numColumns = columnNames.length; 85 if (!numColumns) 86 return null; 87 88 var columns = []; 89 for (var i = 0; i < columnNames.length; ++i) 90 columns.push({ title: columnNames[i], width: columnNames[i].length, sortable: true }); 91 92 var nodes = []; 93 for (var i = 0; i < values.length / numColumns; ++i) { 94 var data = {}; 95 for (var j = 0; j < columnNames.length; ++j) 96 data[j] = values[numColumns * i + j]; 97 98 var node = new WebInspector.SortableDataGridNode(data); 99 node.selectable = false; 100 nodes.push(node); 101 } 102 103 var dataGrid = new WebInspector.SortableDataGrid(columns); 104 var length = nodes.length; 105 var rootNode = dataGrid.rootNode(); 106 for (var i = 0; i < length; ++i) 107 rootNode.appendChild(nodes[i]); 108 109 dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, sortDataGrid); 110 111 function sortDataGrid() 112 { 113 var nodes = dataGrid.rootNode().children; 114 var sortColumnIdentifier = dataGrid.sortColumnIdentifier(); 115 if (!sortColumnIdentifier) 116 return; 117 118 var columnIsNumeric = true; 119 for (var i = 0; i < nodes.length; i++) { 120 var value = nodes[i].data[sortColumnIdentifier]; 121 if (isNaN(value instanceof Node ? value.textContent : value)) { 122 columnIsNumeric = false; 123 break; 124 } 125 } 126 127 var comparator = columnIsNumeric ? WebInspector.SortableDataGrid.NumericComparator : WebInspector.SortableDataGrid.StringComparator; 128 dataGrid.sortNodes(comparator.bind(null, sortColumnIdentifier), !dataGrid.isSortOrderAscending()); 129 } 130 return dataGrid; 131 } 132 133 WebInspector.SortableDataGrid.prototype = { 134 /** 135 * @param {!WebInspector.DataGridNode} node 136 */ 137 insertChild: function(node) 138 { 139 var parentNode = this.rootNode(); 140 parentNode.insertChild(node, parentNode.children.upperBound(node, this._sortingFunction)); 141 }, 142 143 /** 144 * @param {!WebInspector.SortableDataGrid.NodeComparator} comparator 145 * @param {boolean} reverseMode 146 */ 147 sortNodes: function(comparator, reverseMode) 148 { 149 this._sortingFunction = WebInspector.SortableDataGrid.Comparator.bind(null, comparator, reverseMode); 150 var children = this._rootNode.children; 151 children.sort(this._sortingFunction); 152 for (var i = 0; i < children.length; ++i) 153 children[i].recalculateSiblings(i); 154 this.scheduleUpdate(); 155 }, 156 157 __proto__: WebInspector.ViewportDataGrid.prototype 158 } 159 160 /** 161 * @constructor 162 * @extends {WebInspector.ViewportDataGridNode} 163 * @param {?Object.<string, *>=} data 164 */ 165 WebInspector.SortableDataGridNode = function(data) 166 { 167 WebInspector.ViewportDataGridNode.call(this, data); 168 } 169 170 WebInspector.SortableDataGridNode.prototype = { 171 __proto__: WebInspector.ViewportDataGridNode.prototype 172 } 173