| Index: chrome/resources/inspector/DataGrid.js
|
| ===================================================================
|
| --- chrome/resources/inspector/DataGrid.js (revision 0)
|
| +++ chrome/resources/inspector/DataGrid.js (revision 0)
|
| @@ -0,0 +1,1041 @@
|
| +/*
|
| + * Copyright (C) 2008 Apple Inc. All Rights Reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions
|
| + * are met:
|
| + * 1. Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * 2. Redistributions in binary form must reproduce the above copyright
|
| + * notice, this list of conditions and the following disclaimer in the
|
| + * documentation and/or other materials provided with the distribution.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
| + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
| + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
| + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
| + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
| + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
| + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
| + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + */
|
| +
|
| +WebInspector.DataGrid = function(columns)
|
| +{
|
| + this.element = document.createElement("div");
|
| + this.element.className = "data-grid";
|
| + this.element.tabIndex = 0;
|
| + this.element.addEventListener("keydown", this._keyDown.bind(this), false);
|
| +
|
| + this._headerTable = document.createElement("table");
|
| + this._headerTable.className = "header";
|
| +
|
| + this._dataTable = document.createElement("table");
|
| + this._dataTable.className = "data";
|
| +
|
| + this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true);
|
| + this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true);
|
| +
|
| + this.aligned = {};
|
| +
|
| + var scrollContainer = document.createElement("div");
|
| + scrollContainer.className = "data-container";
|
| + scrollContainer.appendChild(this._dataTable);
|
| +
|
| + this.element.appendChild(this._headerTable);
|
| + this.element.appendChild(scrollContainer);
|
| +
|
| + var headerRow = document.createElement("tr");
|
| + var columnGroup = document.createElement("colgroup");
|
| + var columnCount = 0;
|
| +
|
| + for (var columnIdentifier in columns) {
|
| + var column = columns[columnIdentifier];
|
| + if (column.disclosure)
|
| + this.disclosureColumnIdentifier = columnIdentifier;
|
| +
|
| + var col = document.createElement("col");
|
| + if (column.width)
|
| + col.style.width = column.width;
|
| + columnGroup.appendChild(col);
|
| +
|
| + var cell = document.createElement("th");
|
| + cell.className = columnIdentifier + "-column";
|
| + cell.columnIdentifier = columnIdentifier;
|
| +
|
| + var div = document.createElement("div");
|
| + div.textContent = column.title;
|
| + cell.appendChild(div);
|
| +
|
| + if (column.sort) {
|
| + cell.addStyleClass("sort-" + column.sort);
|
| + this._sortColumnCell = cell;
|
| + }
|
| +
|
| + if (column.sortable) {
|
| + cell.addEventListener("click", this._clickInHeaderCell.bind(this), false);
|
| + cell.addStyleClass("sortable");
|
| + }
|
| +
|
| + if (column.aligned) {
|
| + cell.addStyleClass(column.aligned);
|
| + this.aligned[columnIdentifier] = column.aligned;
|
| + }
|
| +
|
| + headerRow.appendChild(cell);
|
| +
|
| + ++columnCount;
|
| + }
|
| +
|
| + columnGroup.span = columnCount;
|
| +
|
| + var cell = document.createElement("th");
|
| + cell.className = "corner";
|
| + headerRow.appendChild(cell);
|
| +
|
| + this._headerTableColumnGroup = columnGroup;
|
| + this._headerTable.appendChild(this._headerTableColumnGroup);
|
| + this.headerTableBody.appendChild(headerRow);
|
| +
|
| + var fillerRow = document.createElement("tr");
|
| + fillerRow.className = "filler";
|
| +
|
| + for (var i = 0; i < columnCount; ++i) {
|
| + var cell = document.createElement("td");
|
| + fillerRow.appendChild(cell);
|
| + }
|
| +
|
| + this._dataTableColumnGroup = columnGroup.cloneNode(true);
|
| + this._dataTable.appendChild(this._dataTableColumnGroup);
|
| + this.dataTableBody.appendChild(fillerRow);
|
| +
|
| + this.columns = columns || {};
|
| + this.children = [];
|
| + this.selectedNode = null;
|
| + this.expandNodesWhenArrowing = false;
|
| + this.root = true;
|
| + this.hasChildren = false;
|
| + this.expanded = true;
|
| + this.revealed = true;
|
| + this.selected = false;
|
| + this.dataGrid = this;
|
| + this.indentWidth = 15;
|
| + this.resizers = [];
|
| + this.columnWidthsInitialized = false;
|
| +}
|
| +
|
| +WebInspector.DataGrid.prototype = {
|
| + get sortColumnIdentifier()
|
| + {
|
| + if (!this._sortColumnCell)
|
| + return null;
|
| + return this._sortColumnCell.columnIdentifier;
|
| + },
|
| +
|
| + get sortOrder()
|
| + {
|
| + if (!this._sortColumnCell || this._sortColumnCell.hasStyleClass("sort-ascending"))
|
| + return "ascending";
|
| + if (this._sortColumnCell.hasStyleClass("sort-descending"))
|
| + return "descending";
|
| + return null;
|
| + },
|
| +
|
| + get headerTableBody()
|
| + {
|
| + if ("_headerTableBody" in this)
|
| + return this._headerTableBody;
|
| +
|
| + this._headerTableBody = this._headerTable.getElementsByTagName("tbody")[0];
|
| + if (!this._headerTableBody) {
|
| + this._headerTableBody = this.element.ownerDocument.createElement("tbody");
|
| + this._headerTable.insertBefore(this._headerTableBody, this._headerTable.tFoot);
|
| + }
|
| +
|
| + return this._headerTableBody;
|
| + },
|
| +
|
| + get dataTableBody()
|
| + {
|
| + if ("_dataTableBody" in this)
|
| + return this._dataTableBody;
|
| +
|
| + this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0];
|
| + if (!this._dataTableBody) {
|
| + this._dataTableBody = this.element.ownerDocument.createElement("tbody");
|
| + this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tFoot);
|
| + }
|
| +
|
| + return this._dataTableBody;
|
| + },
|
| +
|
| + // Updates the widths of the table, including the positions of the column
|
| + // resizers.
|
| + //
|
| + // IMPORTANT: This function MUST be called once after the element of the
|
| + // DataGrid is attached to its parent element and every subsequent time the
|
| + // width of the parent element is changed in order to make it possible to
|
| + // resize the columns.
|
| + //
|
| + // If this function is not called after the DataGrid is attached to its
|
| + // parent element, then the DataGrid's columns will not be resizable.
|
| + updateWidths: function()
|
| + {
|
| + var headerTableColumns = this._headerTableColumnGroup.children;
|
| +
|
| + var left = 0;
|
| + var tableWidth = this._dataTable.offsetWidth;
|
| + var numColumns = headerTableColumns.length;
|
| +
|
| + if (!this.columnWidthsInitialized) {
|
| + // Give all the columns initial widths now so that during a resize,
|
| + // when the two columns that get resized get a percent value for
|
| + // their widths, all the other columns already have percent values
|
| + // for their widths.
|
| + for (var i = 0; i < numColumns; i++) {
|
| + var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWidth;
|
| + var percentWidth = ((columnWidth / tableWidth) * 100) + "%";
|
| + this._headerTableColumnGroup.children[i].style.width = percentWidth;
|
| + this._dataTableColumnGroup.children[i].style.width = percentWidth;
|
| + }
|
| + this.columnWidthsInitialized = true;
|
| + }
|
| +
|
| + // Make n - 1 resizers for n columns.
|
| + for (var i = 0; i < numColumns - 1; i++) {
|
| + var resizer = this.resizers[i];
|
| +
|
| + if (!resizer) {
|
| + // This is the first call to updateWidth, so the resizers need
|
| + // to be created.
|
| + resizer = document.createElement("div");
|
| + resizer.addStyleClass("data-grid-resizer");
|
| + // This resizer is associated with the column to its right.
|
| + resizer.rightNeighboringColumnID = i + 1;
|
| + resizer.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
|
| + this.element.appendChild(resizer);
|
| + this.resizers[i] = resizer;
|
| + }
|
| +
|
| + // Get the width of the cell in the first (and only) row of the
|
| + // header table in order to determine the width of the column, since
|
| + // it is not possible to query a column for its width.
|
| + left += this.headerTableBody.rows[0].cells[i].offsetWidth;
|
| +
|
| + resizer.style.left = left + "px";
|
| + }
|
| + },
|
| +
|
| + addCreationNode: function(hasChildren)
|
| + {
|
| + if (this.creationNode)
|
| + this.creationNode.makeNormal();
|
| +
|
| + var emptyData = {};
|
| + for (var column in this.columns)
|
| + emptyData[column] = '';
|
| + this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren);
|
| + this.appendChild(this.creationNode);
|
| + },
|
| +
|
| + appendChild: function(child)
|
| + {
|
| + this.insertChild(child, this.children.length);
|
| + },
|
| +
|
| + insertChild: function(child, index)
|
| + {
|
| + if (!child)
|
| + throw("insertChild: Node can't be undefined or null.");
|
| + if (child.parent === this)
|
| + throw("insertChild: Node is already a child of this node.");
|
| +
|
| + if (child.parent)
|
| + child.parent.removeChild(child);
|
| +
|
| + this.children.splice(index, 0, child);
|
| + this.hasChildren = true;
|
| +
|
| + child.parent = this;
|
| + child.dataGrid = this.dataGrid;
|
| + child._recalculateSiblings(index);
|
| +
|
| + delete child._depth;
|
| + delete child._revealed;
|
| + delete child._attached;
|
| +
|
| + var current = child.children[0];
|
| + while (current) {
|
| + current.dataGrid = this.dataGrid;
|
| + delete current._depth;
|
| + delete current._revealed;
|
| + delete current._attached;
|
| + current = current.traverseNextNode(false, child, true);
|
| + }
|
| +
|
| + if (this.expanded)
|
| + child._attach();
|
| + },
|
| +
|
| + removeChild: function(child)
|
| + {
|
| + if (!child)
|
| + throw("removeChild: Node can't be undefined or null.");
|
| + if (child.parent !== this)
|
| + throw("removeChild: Node is not a child of this node.");
|
| +
|
| + child.deselect();
|
| +
|
| + this.children.remove(child, true);
|
| +
|
| + if (child.previousSibling)
|
| + child.previousSibling.nextSibling = child.nextSibling;
|
| + if (child.nextSibling)
|
| + child.nextSibling.previousSibling = child.previousSibling;
|
| +
|
| + child.dataGrid = null;
|
| + child.parent = null;
|
| + child.nextSibling = null;
|
| + child.previousSibling = null;
|
| +
|
| + if (this.children.length <= 0)
|
| + this.hasChildren = false;
|
| + },
|
| +
|
| + removeChildren: function()
|
| + {
|
| + for (var i = 0; i < this.children.length; ++i) {
|
| + var child = this.children[i];
|
| + child.deselect();
|
| + child._detach();
|
| +
|
| + child.dataGrid = null;
|
| + child.parent = null;
|
| + child.nextSibling = null;
|
| + child.previousSibling = null;
|
| + }
|
| +
|
| + this.children = [];
|
| + this.hasChildren = false;
|
| + },
|
| +
|
| + removeChildrenRecursive: function()
|
| + {
|
| + var childrenToRemove = this.children;
|
| +
|
| + var child = this.children[0];
|
| + while (child) {
|
| + if (child.children.length)
|
| + childrenToRemove = childrenToRemove.concat(child.children);
|
| + child = child.traverseNextNode(false, this, true);
|
| + }
|
| +
|
| + for (var i = 0; i < childrenToRemove.length; ++i) {
|
| + var child = childrenToRemove[i];
|
| + child.deselect();
|
| + child._detach();
|
| +
|
| + child.children = [];
|
| + child.dataGrid = null;
|
| + child.parent = null;
|
| + child.nextSibling = null;
|
| + child.previousSibling = null;
|
| + }
|
| +
|
| + this.children = [];
|
| + },
|
| +
|
| + handleKeyEvent: function(event)
|
| + {
|
| + if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey)
|
| + return false;
|
| +
|
| + var handled = false;
|
| + var nextSelectedNode;
|
| + if (event.keyIdentifier === "Up" && !event.altKey) {
|
| + nextSelectedNode = this.selectedNode.traversePreviousNode(true);
|
| + while (nextSelectedNode && !nextSelectedNode.selectable)
|
| + nextSelectedNode = nextSelectedNode.traversePreviousNode(!this.expandTreeNodesWhenArrowing);
|
| + handled = nextSelectedNode ? true : false;
|
| + } else if (event.keyIdentifier === "Down" && !event.altKey) {
|
| + nextSelectedNode = this.selectedNode.traverseNextNode(true);
|
| + while (nextSelectedNode && !nextSelectedNode.selectable)
|
| + nextSelectedNode = nextSelectedNode.traverseNextNode(!this.expandTreeNodesWhenArrowing);
|
| + handled = nextSelectedNode ? true : false;
|
| + } else if (event.keyIdentifier === "Left") {
|
| + if (this.selectedNode.expanded) {
|
| + if (event.altKey)
|
| + this.selectedNode.collapseRecursively();
|
| + else
|
| + this.selectedNode.collapse();
|
| + handled = true;
|
| + } else if (this.selectedNode.parent && !this.selectedNode.parent.root) {
|
| + handled = true;
|
| + if (this.selectedNode.parent.selectable) {
|
| + nextSelectedNode = this.selectedNode.parent;
|
| + handled = nextSelectedNode ? true : false;
|
| + } else if (this.selectedNode.parent)
|
| + this.selectedNode.parent.collapse();
|
| + }
|
| + } else if (event.keyIdentifier === "Right") {
|
| + if (!this.selectedNode.revealed) {
|
| + this.selectedNode.reveal();
|
| + handled = true;
|
| + } else if (this.selectedNode.hasChildren) {
|
| + handled = true;
|
| + if (this.selectedNode.expanded) {
|
| + nextSelectedNode = this.selectedNode.children[0];
|
| + handled = nextSelectedNode ? true : false;
|
| + } else {
|
| + if (event.altKey)
|
| + this.selectedNode.expandRecursively();
|
| + else
|
| + this.selectedNode.expand();
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (nextSelectedNode) {
|
| + nextSelectedNode.reveal();
|
| + nextSelectedNode.select();
|
| + }
|
| +
|
| + if (handled) {
|
| + event.preventDefault();
|
| + event.stopPropagation();
|
| + }
|
| +
|
| + return handled;
|
| + },
|
| +
|
| + expand: function()
|
| + {
|
| + // This is the root, do nothing.
|
| + },
|
| +
|
| + collapse: function()
|
| + {
|
| + // This is the root, do nothing.
|
| + },
|
| +
|
| + reveal: function()
|
| + {
|
| + // This is the root, do nothing.
|
| + },
|
| +
|
| + dataGridNodeFromEvent: function(event)
|
| + {
|
| + var rowElement = event.target.enclosingNodeOrSelfWithNodeName("tr");
|
| + return rowElement._dataGridNode;
|
| + },
|
| +
|
| + dataGridNodeFromPoint: function(x, y)
|
| + {
|
| + var node = this._dataTable.ownerDocument.elementFromPoint(x, y);
|
| + var rowElement = node.enclosingNodeOrSelfWithNodeName("tr");
|
| + return rowElement._dataGridNode;
|
| + },
|
| +
|
| + _keyDown: function(event)
|
| + {
|
| + this.handleKeyEvent(event);
|
| + },
|
| +
|
| + _clickInHeaderCell: function(event)
|
| + {
|
| + var cell = event.target.enclosingNodeOrSelfWithNodeName("th");
|
| + if (!cell || !cell.columnIdentifier || !cell.hasStyleClass("sortable"))
|
| + return;
|
| +
|
| + var sortOrder = this.sortOrder;
|
| +
|
| + if (this._sortColumnCell) {
|
| + this._sortColumnCell.removeStyleClass("sort-ascending");
|
| + this._sortColumnCell.removeStyleClass("sort-descending");
|
| + }
|
| +
|
| + if (cell == this._sortColumnCell) {
|
| + if (sortOrder == "ascending")
|
| + sortOrder = "descending";
|
| + else
|
| + sortOrder = "ascending";
|
| + }
|
| +
|
| + this._sortColumnCell = cell;
|
| +
|
| + cell.addStyleClass("sort-" + sortOrder);
|
| +
|
| + this.dispatchEventToListeners("sorting changed");
|
| + },
|
| +
|
| + _mouseDownInDataTable: function(event)
|
| + {
|
| + var gridNode = this.dataGridNodeFromEvent(event);
|
| + if (!gridNode || !gridNode.selectable)
|
| + return;
|
| +
|
| + if (gridNode.isEventWithinDisclosureTriangle(event))
|
| + return;
|
| +
|
| + if (event.metaKey) {
|
| + if (gridNode.selected)
|
| + gridNode.deselect();
|
| + else
|
| + gridNode.select();
|
| + } else
|
| + gridNode.select();
|
| + },
|
| +
|
| + _clickInDataTable: function(event)
|
| + {
|
| + var gridNode = this.dataGridNodeFromEvent(event);
|
| + if (!gridNode || !gridNode.hasChildren)
|
| + return;
|
| +
|
| + if (!gridNode.isEventWithinDisclosureTriangle(event))
|
| + return;
|
| +
|
| + if (gridNode.expanded) {
|
| + if (event.altKey)
|
| + gridNode.collapseRecursively();
|
| + else
|
| + gridNode.collapse();
|
| + } else {
|
| + if (event.altKey)
|
| + gridNode.expandRecursively();
|
| + else
|
| + gridNode.expand();
|
| + }
|
| + },
|
| +
|
| + _startResizerDragging: function(event)
|
| + {
|
| + this.currentResizer = event.target;
|
| + if (!this.currentResizer.rightNeighboringColumnID)
|
| + return;
|
| + WebInspector.elementDragStart(this.lastResizer, this._resizerDragging.bind(this),
|
| + this._endResizerDragging.bind(this), event, "col-resize");
|
| + },
|
| +
|
| + _resizerDragging: function(event)
|
| + {
|
| + var resizer = this.currentResizer;
|
| + if (!resizer)
|
| + return;
|
| +
|
| + // Constrain the dragpoint to be within the containing div of the
|
| + // datagrid.
|
| + var dragPoint = event.clientX - this.element.totalOffsetLeft;
|
| + // Constrain the dragpoint to be within the space made up by the
|
| + // column directly to the left and the column directly to the right.
|
| + var leftEdgeOfPreviousColumn = 0;
|
| + var firstRowCells = this.headerTableBody.rows[0].cells;
|
| + for (var i = 0; i < resizer.rightNeighboringColumnID - 1; i++)
|
| + leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth;
|
| +
|
| + var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[resizer.rightNeighboringColumnID - 1].offsetWidth + firstRowCells[resizer.rightNeighboringColumnID].offsetWidth;
|
| +
|
| + // Give each column some padding so that they don't disappear.
|
| + var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding;
|
| + var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding;
|
| +
|
| + dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);
|
| +
|
| + resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px";
|
| +
|
| + var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%";
|
| + this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn;
|
| + this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn;
|
| +
|
| + var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%";
|
| + this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn;
|
| + this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn;
|
| +
|
| + event.preventDefault();
|
| + },
|
| +
|
| + _endResizerDragging: function(event)
|
| + {
|
| + WebInspector.elementDragEnd(event);
|
| + this.currentResizer = null;
|
| + },
|
| +
|
| + ColumnResizePadding: 10,
|
| +
|
| + CenterResizerOverBorderAdjustment: 3,
|
| +}
|
| +
|
| +WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype;
|
| +
|
| +WebInspector.DataGridNode = function(data, hasChildren)
|
| +{
|
| + this._expanded = false;
|
| + this._selected = false;
|
| + this._shouldRefreshChildren = true;
|
| + this._data = data || {};
|
| + this.hasChildren = hasChildren || false;
|
| + this.children = [];
|
| + this.dataGrid = null;
|
| + this.parent = null;
|
| + this.previousSibling = null;
|
| + this.nextSibling = null;
|
| + this.disclosureToggleWidth = 10;
|
| +}
|
| +
|
| +WebInspector.DataGridNode.prototype = {
|
| + selectable: true,
|
| +
|
| + get element()
|
| + {
|
| + if (this._element)
|
| + return this._element;
|
| +
|
| + if (!this.dataGrid)
|
| + return null;
|
| +
|
| + this._element = document.createElement("tr");
|
| + this._element._dataGridNode = this;
|
| +
|
| + if (this.hasChildren)
|
| + this._element.addStyleClass("parent");
|
| + if (this.expanded)
|
| + this._element.addStyleClass("expanded");
|
| + if (this.selected)
|
| + this._element.addStyleClass("selected");
|
| + if (this.revealed)
|
| + this._element.addStyleClass("revealed");
|
| +
|
| + for (var columnIdentifier in this.dataGrid.columns) {
|
| + var cell = this.createCell(columnIdentifier);
|
| + this._element.appendChild(cell);
|
| + }
|
| +
|
| + return this._element;
|
| + },
|
| +
|
| + get data()
|
| + {
|
| + return this._data;
|
| + },
|
| +
|
| + set data(x)
|
| + {
|
| + this._data = x || {};
|
| + this.refresh();
|
| + },
|
| +
|
| + get revealed()
|
| + {
|
| + if ("_revealed" in this)
|
| + return this._revealed;
|
| +
|
| + var currentAncestor = this.parent;
|
| + while (currentAncestor && !currentAncestor.root) {
|
| + if (!currentAncestor.expanded) {
|
| + this._revealed = false;
|
| + return false;
|
| + }
|
| +
|
| + currentAncestor = currentAncestor.parent;
|
| + }
|
| +
|
| + this._revealed = true;
|
| + return true;
|
| + },
|
| +
|
| + set hasChildren(x)
|
| + {
|
| + if (this._hasChildren === x)
|
| + return;
|
| +
|
| + this._hasChildren = x;
|
| +
|
| + if (!this._element)
|
| + return;
|
| +
|
| + if (this._hasChildren)
|
| + {
|
| + this._element.addStyleClass("parent");
|
| + if (this.expanded)
|
| + this._element.addStyleClass("expanded");
|
| + }
|
| + else
|
| + {
|
| + this._element.removeStyleClass("parent");
|
| + this._element.removeStyleClass("expanded");
|
| + }
|
| + },
|
| +
|
| + get hasChildren()
|
| + {
|
| + return this._hasChildren;
|
| + },
|
| +
|
| + set revealed(x)
|
| + {
|
| + if (this._revealed === x)
|
| + return;
|
| +
|
| + this._revealed = x;
|
| +
|
| + if (this._element) {
|
| + if (this._revealed)
|
| + this._element.addStyleClass("revealed");
|
| + else
|
| + this._element.removeStyleClass("revealed");
|
| + }
|
| +
|
| + for (var i = 0; i < this.children.length; ++i)
|
| + this.children[i].revealed = x && this.expanded;
|
| + },
|
| +
|
| + get depth()
|
| + {
|
| + if ("_depth" in this)
|
| + return this._depth;
|
| + if (this.parent && !this.parent.root)
|
| + this._depth = this.parent.depth + 1;
|
| + else
|
| + this._depth = 0;
|
| + return this._depth;
|
| + },
|
| +
|
| + get shouldRefreshChildren()
|
| + {
|
| + return this._shouldRefreshChildren;
|
| + },
|
| +
|
| + set shouldRefreshChildren(x)
|
| + {
|
| + this._shouldRefreshChildren = x;
|
| + if (x && this.expanded)
|
| + this.expand();
|
| + },
|
| +
|
| + get selected()
|
| + {
|
| + return this._selected;
|
| + },
|
| +
|
| + set selected(x)
|
| + {
|
| + if (x)
|
| + this.select();
|
| + else
|
| + this.deselect();
|
| + },
|
| +
|
| + get expanded()
|
| + {
|
| + return this._expanded;
|
| + },
|
| +
|
| + set expanded(x)
|
| + {
|
| + if (x)
|
| + this.expand();
|
| + else
|
| + this.collapse();
|
| + },
|
| +
|
| + refresh: function()
|
| + {
|
| + if (!this._element || !this.dataGrid)
|
| + return;
|
| +
|
| + this._element.removeChildren();
|
| +
|
| + for (var columnIdentifier in this.dataGrid.columns) {
|
| + var cell = this.createCell(columnIdentifier);
|
| + this._element.appendChild(cell);
|
| + }
|
| + },
|
| +
|
| + createCell: function(columnIdentifier)
|
| + {
|
| + var cell = document.createElement("td");
|
| + cell.className = columnIdentifier + "-column";
|
| +
|
| + var alignment = this.dataGrid.aligned[columnIdentifier];
|
| + if (alignment)
|
| + cell.addStyleClass(alignment);
|
| +
|
| + var div = document.createElement("div");
|
| + div.textContent = this.data[columnIdentifier];
|
| + cell.appendChild(div);
|
| +
|
| + if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
|
| + cell.addStyleClass("disclosure");
|
| + if (this.depth)
|
| + cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
|
| + }
|
| +
|
| + return cell;
|
| + },
|
| +
|
| + // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
|
| + appendChild: WebInspector.DataGrid.prototype.appendChild,
|
| + insertChild: WebInspector.DataGrid.prototype.insertChild,
|
| + removeChild: WebInspector.DataGrid.prototype.removeChild,
|
| + removeChildren: WebInspector.DataGrid.prototype.removeChildren,
|
| + removeChildrenRecursive: WebInspector.DataGrid.prototype.removeChildrenRecursive,
|
| +
|
| + _recalculateSiblings: function(myIndex)
|
| + {
|
| + if (!this.parent)
|
| + return;
|
| +
|
| + var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);
|
| +
|
| + if (previousChild) {
|
| + previousChild.nextSibling = this;
|
| + this.previousSibling = previousChild;
|
| + } else
|
| + this.previousSibling = null;
|
| +
|
| + var nextChild = this.parent.children[myIndex + 1];
|
| +
|
| + if (nextChild) {
|
| + nextChild.previousSibling = this;
|
| + this.nextSibling = nextChild;
|
| + } else
|
| + this.nextSibling = null;
|
| + },
|
| +
|
| + collapse: function()
|
| + {
|
| + if (this._element)
|
| + this._element.removeStyleClass("expanded");
|
| +
|
| + this._expanded = false;
|
| +
|
| + for (var i = 0; i < this.children.length; ++i)
|
| + this.children[i].revealed = false;
|
| +
|
| + this.dispatchEventToListeners("collapsed");
|
| + },
|
| +
|
| + collapseRecursively: function()
|
| + {
|
| + var item = this;
|
| + while (item) {
|
| + if (item.expanded)
|
| + item.collapse();
|
| + item = item.traverseNextNode(false, this, true);
|
| + }
|
| + },
|
| +
|
| + expand: function()
|
| + {
|
| + if (!this.hasChildren || this.expanded)
|
| + return;
|
| +
|
| + if (this.revealed && !this._shouldRefreshChildren)
|
| + for (var i = 0; i < this.children.length; ++i)
|
| + this.children[i].revealed = true;
|
| +
|
| + if (this._shouldRefreshChildren) {
|
| + for (var i = 0; i < this.children.length; ++i)
|
| + this.children[i]._detach();
|
| +
|
| + this.dispatchEventToListeners("populate");
|
| +
|
| + if (this._attached) {
|
| + for (var i = 0; i < this.children.length; ++i) {
|
| + var child = this.children[i];
|
| + if (this.revealed)
|
| + child.revealed = true;
|
| + child._attach();
|
| + }
|
| + }
|
| +
|
| + delete this._shouldRefreshChildren;
|
| + }
|
| +
|
| + if (this._element)
|
| + this._element.addStyleClass("expanded");
|
| +
|
| + this._expanded = true;
|
| +
|
| + this.dispatchEventToListeners("expanded");
|
| + },
|
| +
|
| + expandRecursively: function()
|
| + {
|
| + var item = this;
|
| + while (item) {
|
| + item.expand();
|
| + item = item.traverseNextNode(false, this);
|
| + }
|
| + },
|
| +
|
| + reveal: function()
|
| + {
|
| + var currentAncestor = this.parent;
|
| + while (currentAncestor && !currentAncestor.root) {
|
| + if (!currentAncestor.expanded)
|
| + currentAncestor.expand();
|
| + currentAncestor = currentAncestor.parent;
|
| + }
|
| +
|
| + this.element.scrollIntoViewIfNeeded(false);
|
| +
|
| + this.dispatchEventToListeners("revealed");
|
| + },
|
| +
|
| + select: function(supressSelectedEvent)
|
| + {
|
| + if (!this.dataGrid || !this.selectable || this.selected)
|
| + return;
|
| +
|
| + if (this.dataGrid.selectedNode)
|
| + this.dataGrid.selectedNode.deselect();
|
| +
|
| + this._selected = true;
|
| + this.dataGrid.selectedNode = this;
|
| +
|
| + if (this._element)
|
| + this._element.addStyleClass("selected");
|
| +
|
| + if (!supressSelectedEvent)
|
| + this.dispatchEventToListeners("selected");
|
| + },
|
| +
|
| + deselect: function(supressDeselectedEvent)
|
| + {
|
| + if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
|
| + return;
|
| +
|
| + this._selected = false;
|
| + this.dataGrid.selectedNode = null;
|
| +
|
| + if (this._element)
|
| + this._element.removeStyleClass("selected");
|
| +
|
| + if (!supressDeselectedEvent)
|
| + this.dispatchEventToListeners("deselected");
|
| + },
|
| +
|
| + traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info)
|
| + {
|
| + if (!dontPopulate && this.hasChildren)
|
| + this.dispatchEventToListeners("populate");
|
| +
|
| + if (info)
|
| + info.depthChange = 0;
|
| +
|
| + var node = (!skipHidden || this.revealed) ? this.children[0] : null;
|
| + if (node && (!skipHidden || this.expanded)) {
|
| + if (info)
|
| + info.depthChange = 1;
|
| + return node;
|
| + }
|
| +
|
| + if (this === stayWithin)
|
| + return null;
|
| +
|
| + node = (!skipHidden || this.revealed) ? this.nextSibling : null;
|
| + if (node)
|
| + return node;
|
| +
|
| + node = this;
|
| + while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
|
| + if (info)
|
| + info.depthChange -= 1;
|
| + node = node.parent;
|
| + }
|
| +
|
| + if (!node)
|
| + return null;
|
| +
|
| + return (!skipHidden || node.revealed) ? node.nextSibling : null;
|
| + },
|
| +
|
| + traversePreviousNode: function(skipHidden, dontPopulate)
|
| + {
|
| + var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
|
| + if (!dontPopulate && node && node.hasChildren)
|
| + node.dispatchEventToListeners("populate");
|
| +
|
| + while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) {
|
| + if (!dontPopulate && node.hasChildren)
|
| + node.dispatchEventToListeners("populate");
|
| + node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null);
|
| + }
|
| +
|
| + if (node)
|
| + return node;
|
| +
|
| + if (!this.parent || this.parent.root)
|
| + return null;
|
| +
|
| + return this.parent;
|
| + },
|
| +
|
| + isEventWithinDisclosureTriangle: function(event)
|
| + {
|
| + if (!this.hasChildren)
|
| + return false;
|
| + var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
|
| + if (!cell.hasStyleClass("disclosure"))
|
| + return false;
|
| + var computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
|
| + var left = cell.totalOffsetLeft + computedLeftPadding;
|
| + return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
|
| + },
|
| +
|
| + _attach: function()
|
| + {
|
| + if (!this.dataGrid || this._attached)
|
| + return;
|
| +
|
| + this._attached = true;
|
| +
|
| + var nextNode = null;
|
| + var previousNode = this.traversePreviousNode(true, true);
|
| + if (previousNode && previousNode.element.parentNode && previousNode.element.nextSibling)
|
| + var nextNode = previousNode.element.nextSibling;
|
| + if (!nextNode)
|
| + nextNode = this.dataGrid.dataTableBody.lastChild;
|
| + this.dataGrid.dataTableBody.insertBefore(this.element, nextNode);
|
| +
|
| + if (this.expanded)
|
| + for (var i = 0; i < this.children.length; ++i)
|
| + this.children[i]._attach();
|
| + },
|
| +
|
| + _detach: function()
|
| + {
|
| + if (!this._attached)
|
| + return;
|
| +
|
| + this._attached = false;
|
| +
|
| + if (this._element && this._element.parentNode)
|
| + this._element.parentNode.removeChild(this._element);
|
| +
|
| + for (var i = 0; i < this.children.length; ++i)
|
| + this.children[i]._detach();
|
| + }
|
| +}
|
| +
|
| +WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype;
|
| +
|
| +WebInspector.CreationDataGridNode = function(data, hasChildren)
|
| +{
|
| + WebInspector.DataGridNode.call(this, data, hasChildren);
|
| + this.isCreationNode = true;
|
| +}
|
| +
|
| +WebInspector.CreationDataGridNode.prototype = {
|
| + makeNormal: function()
|
| + {
|
| + delete this.isCreationNode;
|
| + delete this.makeNormal;
|
| + }
|
| +}
|
| +
|
| +WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
|
|
|
| Property changes on: chrome/resources/inspector/DataGrid.js
|
| ___________________________________________________________________
|
| Added: svn:executable
|
| + *
|
|
|
|
|