| Index: Source/devtools/front_end/ui/SortableDataGrid.js
|
| diff --git a/Source/devtools/front_end/ui/SortableDataGrid.js b/Source/devtools/front_end/ui/SortableDataGrid.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f2178bbb4ecd7e193f8f0ebaae846dc4f50d8457
|
| --- /dev/null
|
| +++ b/Source/devtools/front_end/ui/SortableDataGrid.js
|
| @@ -0,0 +1,208 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * @constructor
|
| + * @extends {WebInspector.DataGrid}
|
| + * @param {!Array.<!WebInspector.DataGrid.ColumnDescriptor>} columnsArray
|
| + * @param {function(!WebInspector.DataGridNode, string, string, string)=} editCallback
|
| + * @param {function(!WebInspector.DataGridNode)=} deleteCallback
|
| + * @param {function()=} refreshCallback
|
| + * @param {function(!WebInspector.ContextMenu, !WebInspector.DataGridNode)=} contextMenuCallback
|
| + */
|
| +WebInspector.SortableDataGrid = function(columnsArray, editCallback, deleteCallback, refreshCallback, contextMenuCallback)
|
| +{
|
| + WebInspector.DataGrid.call(this, columnsArray, editCallback, deleteCallback, refreshCallback, contextMenuCallback);
|
| + /** @type {!WebInspector.SortableDataGrid.NodeComparator} */
|
| + this._sortingFunction = WebInspector.SortableDataGrid.TrivialComparator;
|
| + this.setRootNode(new WebInspector.SortableDataGridNode());
|
| +}
|
| +
|
| +/** @typedef {function(!WebInspector.DataGridNode, !WebInspector.DataGridNode):number} */
|
| +WebInspector.SortableDataGrid.NodeComparator;
|
| +
|
| +/**
|
| + * @param {!WebInspector.DataGridNode} a
|
| + * @param {!WebInspector.DataGridNode} b
|
| + * @return {number}
|
| + */
|
| +WebInspector.SortableDataGrid.TrivialComparator = function(a, b)
|
| +{
|
| + return 0;
|
| +}
|
| +
|
| +/**
|
| + * @param {string} columnIdentifier
|
| + * @param {!WebInspector.DataGridNode} a
|
| + * @param {!WebInspector.DataGridNode} b
|
| + * @return {number}
|
| + */
|
| +WebInspector.SortableDataGrid.NumericComparator = function(columnIdentifier, a, b)
|
| +{
|
| + var aValue = a.data[columnIdentifier];
|
| + var bValue = b.data[columnIdentifier];
|
| + var aNumber = Number(aValue instanceof Node ? aValue.textContent : aValue);
|
| + var bNumber = Number(bValue instanceof Node ? bValue.textContent : bValue);
|
| + return aNumber < bNumber ? -1 : (aNumber > bNumber ? 1 : 0);
|
| +}
|
| +
|
| +/**
|
| + * @param {string} columnIdentifier
|
| + * @param {!WebInspector.DataGridNode} a
|
| + * @param {!WebInspector.DataGridNode} b
|
| + * @return {number}
|
| + */
|
| +WebInspector.SortableDataGrid.StringComparator = function(columnIdentifier, a, b)
|
| +{
|
| + var aValue = a.data[columnIdentifier];
|
| + var bValue = b.data[columnIdentifier];
|
| + var aString = aValue instanceof Node ? aValue.textContent : String(aValue);
|
| + var bString = bValue instanceof Node ? bValue.textContent : String(bValue);
|
| + return aString < bString ? -1 : (aString > bString ? 1 : 0);
|
| +}
|
| +
|
| +/**
|
| + * @param {!WebInspector.SortableDataGrid.NodeComparator} comparator
|
| + * @param {boolean} reverseMode
|
| + * @param {!WebInspector.DataGridNode} a
|
| + * @param {!WebInspector.DataGridNode} b
|
| + * @return {number}
|
| + */
|
| +WebInspector.SortableDataGrid.Comparator = function(comparator, reverseMode, a, b)
|
| +{
|
| + return reverseMode ? comparator(b, a) : comparator(a, b);
|
| +}
|
| +
|
| +/**
|
| + * @param {!Array.<string>} columnNames
|
| + * @param {!Array.<string>} values
|
| + * @return {?WebInspector.SortableDataGrid}
|
| + */
|
| +WebInspector.SortableDataGrid.create = function(columnNames, values)
|
| +{
|
| + var numColumns = columnNames.length;
|
| + if (!numColumns)
|
| + return null;
|
| +
|
| + var columns = [];
|
| + for (var i = 0; i < columnNames.length; ++i)
|
| + columns.push({ title: columnNames[i], width: columnNames[i].length, sortable: true });
|
| +
|
| + var nodes = [];
|
| + for (var i = 0; i < values.length / numColumns; ++i) {
|
| + var data = {};
|
| + for (var j = 0; j < columnNames.length; ++j)
|
| + data[j] = values[numColumns * i + j];
|
| +
|
| + var node = new WebInspector.SortableDataGridNode(data);
|
| + node.selectable = false;
|
| + nodes.push(node);
|
| + }
|
| +
|
| + var dataGrid = new WebInspector.SortableDataGrid(columns);
|
| + var length = nodes.length;
|
| + var rootNode = dataGrid.rootNode();
|
| + for (var i = 0; i < length; ++i)
|
| + rootNode.appendChild(nodes[i]);
|
| +
|
| + dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, sortDataGrid);
|
| +
|
| + function sortDataGrid()
|
| + {
|
| + var nodes = dataGrid.rootNode().children;
|
| + var sortColumnIdentifier = dataGrid.sortColumnIdentifier();
|
| + if (!sortColumnIdentifier)
|
| + return;
|
| +
|
| + var columnIsNumeric = true;
|
| + for (var i = 0; i < nodes.length; i++) {
|
| + var value = nodes[i].data[sortColumnIdentifier];
|
| + if (isNaN(value instanceof Node ? value.textContent : value)) {
|
| + columnIsNumeric = false;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + var comparator = columnIsNumeric ? WebInspector.SortableDataGrid.NumericComparator : WebInspector.SortableDataGrid.StringComparator;
|
| + dataGrid.sortNodes(comparator.bind(null, sortColumnIdentifier), !dataGrid.isSortOrderAscending());
|
| + }
|
| + return dataGrid;
|
| +}
|
| +
|
| +WebInspector.SortableDataGrid.prototype = {
|
| + /**
|
| + * @param {!WebInspector.DataGridNode} node
|
| + */
|
| + insertChild: function(node)
|
| + {
|
| + var parentNode = this.rootNode();
|
| + parentNode.insertChild(node, parentNode.children.upperBound(node, this._sortingFunction));
|
| + },
|
| +
|
| + /**
|
| + * @param {!WebInspector.SortableDataGrid.NodeComparator} comparator
|
| + * @param {boolean} reverseMode
|
| + */
|
| + sortNodes: function(comparator, reverseMode)
|
| + {
|
| + var sortingFunction = WebInspector.SortableDataGrid.Comparator.bind(null, comparator, reverseMode);
|
| + this._sortingFunction = sortingFunction;
|
| +
|
| + /**
|
| + * @param {!Element} a
|
| + * @param {!Element} b
|
| + * @return {number}
|
| + */
|
| + function comparatorWrapper(a, b)
|
| + {
|
| + return sortingFunction(a._dataGridNode, b._dataGridNode);
|
| + }
|
| +
|
| + var tbody = this.dataTableBody;
|
| + var tbodyParent = tbody.parentElement;
|
| + tbodyParent.removeChild(tbody);
|
| +
|
| + var childNodes = tbody.childNodes;
|
| + var sortedRows = Array.prototype.slice.call(childNodes, 1, childNodes.length - 1);
|
| + sortedRows.sort(comparatorWrapper);
|
| + var sortedRowsLength = sortedRows.length;
|
| +
|
| + var rootNode = this.rootNode();
|
| + rootNode.children = [];
|
| + tbody.removeChildren();
|
| + tbody.appendChild(this._topFillerRow);
|
| + var previousSiblingNode = null;
|
| + for (var i = 0; i < sortedRowsLength; ++i) {
|
| + var row = sortedRows[i];
|
| + var node = row._dataGridNode;
|
| + node.previousSibling = previousSiblingNode;
|
| + if (previousSiblingNode)
|
| + previousSiblingNode.nextSibling = node;
|
| + rootNode.children.push(node);
|
| + tbody.appendChild(row);
|
| + previousSiblingNode = node;
|
| + }
|
| + if (previousSiblingNode)
|
| + previousSiblingNode.nextSibling = null;
|
| +
|
| + tbody.appendChild(this._bottomFillerRow);
|
| + tbodyParent.appendChild(tbody);
|
| + },
|
| +
|
| + __proto__: WebInspector.DataGrid.prototype
|
| +}
|
| +
|
| +/**
|
| + * @constructor
|
| + * @extends {WebInspector.DataGridNode}
|
| + * @param {?Object.<string, *>=} data
|
| + */
|
| +WebInspector.SortableDataGridNode = function(data)
|
| +{
|
| + WebInspector.DataGridNode.call(this, data, false);
|
| +}
|
| +
|
| +WebInspector.SortableDataGridNode.prototype = {
|
| + __proto__: WebInspector.DataGridNode.prototype
|
| +}
|
|
|