📄 datagrid.js
字号:
/* * 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); 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"); } headerRow.appendChild(cell); ++columnCount; } columnGroup.span = columnCount; var cell = document.createElement("th"); cell.className = "corner"; headerRow.appendChild(cell); this._headerTable.appendChild(columnGroup); 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._dataTable.appendChild(columnGroup.cloneNode(true)); 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;}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; }, appendChild: function(child) { this.insertChild(child, this.children.length); }, insertChild: function(child, index) { if (!child) throw("Node can't be undefined or null."); if (child.parent === this) throw("Node is already a child of this node."); if (child.parent) child.parent.removeChild(child); var previousChild = (index > 0 ? this.children[index - 1] : null); if (previousChild) { previousChild.nextSibling = child; child.previousSibling = previousChild; } else child.previousSibling = null; var nextChild = this.children[index]; if (nextChild) { nextChild.previousSibling = child; child.nextSibling = nextChild; } else child.nextSibling = null; this.children.splice(index, 0, child); this.hasChildren = true; child.parent = this; child.dataGrid = this.dataGrid; 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("Node can't be undefined or null."); if (child.parent !== this) throw("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; }, 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 = []; }, 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -