Index: third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js b/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js |
index 3b5f34bf7d85e0f2f98a8c1ae53885f857af44cd..e97377aaa305b92f4cfacd87268bb5176ac380ce 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js |
+++ b/third_party/WebKit/Source/devtools/front_end/ui_lazy/DataGrid.js |
@@ -22,22 +22,23 @@ |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
- |
/** |
- * @constructor |
- * @extends {WebInspector.Object} |
- * @param {!Array.<!WebInspector.DataGrid.ColumnDescriptor>} columnsArray |
- * @param {function(!WebInspector.DataGridNode, string, string, string)=} editCallback |
- * @param {function(!WebInspector.DataGridNode)=} deleteCallback |
- * @param {function()=} refreshCallback |
+ * @unrestricted |
*/ |
-WebInspector.DataGrid = function(columnsArray, editCallback, deleteCallback, refreshCallback) |
-{ |
- this.element = createElementWithClass("div", "data-grid"); |
- WebInspector.appendStyle(this.element, "ui_lazy/dataGrid.css"); |
+WebInspector.DataGrid = class extends WebInspector.Object { |
+ /** |
+ * @param {!Array.<!WebInspector.DataGrid.ColumnDescriptor>} columnsArray |
+ * @param {function(!WebInspector.DataGridNode, string, string, string)=} editCallback |
+ * @param {function(!WebInspector.DataGridNode)=} deleteCallback |
+ * @param {function()=} refreshCallback |
+ */ |
+ constructor(columnsArray, editCallback, deleteCallback, refreshCallback) { |
+ super(); |
+ this.element = createElementWithClass('div', 'data-grid'); |
+ WebInspector.appendStyle(this.element, 'ui_lazy/dataGrid.css'); |
this.element.tabIndex = 0; |
- this.element.addEventListener("keydown", this._keyDown.bind(this), false); |
- this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true); |
+ this.element.addEventListener('keydown', this._keyDown.bind(this), false); |
+ this.element.addEventListener('contextmenu', this._contextMenu.bind(this), true); |
/** @type {function(!WebInspector.DataGridNode, string, string, string)|undefined} */ |
this._editCallback = editCallback; |
@@ -46,22 +47,22 @@ WebInspector.DataGrid = function(columnsArray, editCallback, deleteCallback, ref |
/** @type {function()|undefined} */ |
this._refreshCallback = refreshCallback; |
- var headerContainer = this.element.createChild("div", "header-container"); |
+ var headerContainer = this.element.createChild('div', 'header-container'); |
/** @type {!Element} */ |
- this._headerTable = headerContainer.createChild("table", "header"); |
+ this._headerTable = headerContainer.createChild('table', 'header'); |
/** @type {!Object.<string, !Element>} */ |
this._headerTableHeaders = {}; |
/** @type {!Element} */ |
- this._scrollContainer = this.element.createChild("div", "data-container"); |
+ this._scrollContainer = this.element.createChild('div', 'data-container'); |
/** @type {!Element} */ |
- this._dataTable = this._scrollContainer.createChild("table", "data"); |
+ this._dataTable = this._scrollContainer.createChild('table', 'data'); |
// FIXME: Add a createCallback which is different from editCallback and has different |
// behavior when creating a new node. |
if (editCallback) |
- this._dataTable.addEventListener("dblclick", this._ondblclick.bind(this), false); |
- this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this)); |
- this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true); |
+ this._dataTable.addEventListener('dblclick', this._ondblclick.bind(this), false); |
+ this._dataTable.addEventListener('mousedown', this._mouseDownInDataTable.bind(this)); |
+ this._dataTable.addEventListener('click', this._clickInDataTable.bind(this), true); |
/** @type {boolean} */ |
this._inline = false; |
@@ -79,23 +80,23 @@ WebInspector.DataGrid = function(columnsArray, editCallback, deleteCallback, ref |
this._cellClass = null; |
/** @type {!Element} */ |
- this._headerTableColumnGroup = this._headerTable.createChild("colgroup"); |
+ this._headerTableColumnGroup = this._headerTable.createChild('colgroup'); |
/** @type {!Element} */ |
- this._headerTableBody = this._headerTable.createChild("tbody"); |
+ this._headerTableBody = this._headerTable.createChild('tbody'); |
/** @type {!Element} */ |
- this._headerRow = this._headerTableBody.createChild("tr"); |
+ this._headerRow = this._headerTableBody.createChild('tr'); |
/** @type {!Element} */ |
- this._dataTableColumnGroup = this._dataTable.createChild("colgroup"); |
+ this._dataTableColumnGroup = this._dataTable.createChild('colgroup'); |
/** |
* @protected |
* @type {!Element} |
*/ |
- this.dataTableBody = this._dataTable.createChild("tbody"); |
+ this.dataTableBody = this._dataTable.createChild('tbody'); |
/** @type {!Element} */ |
- this._topFillerRow = this.dataTableBody.createChild("tr", "data-grid-filler-row revealed"); |
+ this._topFillerRow = this.dataTableBody.createChild('tr', 'data-grid-filler-row revealed'); |
/** @type {!Element} */ |
- this._bottomFillerRow = this.dataTableBody.createChild("tr", "data-grid-filler-row revealed"); |
+ this._bottomFillerRow = this.dataTableBody.createChild('tr', 'data-grid-filler-row revealed'); |
this.setVerticalPadding(0, 0); |
this._refreshHeader(); |
@@ -122,6 +123,1025 @@ WebInspector.DataGrid = function(columnsArray, editCallback, deleteCallback, ref |
this._headerContextMenuCallback = null; |
/** @type {?function(!WebInspector.ContextMenu, !WebInspector.DataGridNode)} */ |
this._rowContextMenuCallback = null; |
+ } |
+ |
+ /** |
+ * @return {!Element} |
+ */ |
+ headerTableBody() { |
+ return this._headerTableBody; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGrid.ColumnDescriptor} column |
+ * @param {number=} position |
+ */ |
+ _innerAddColumn(column, position) { |
+ var columnId = column.id; |
+ if (columnId in this._columns) |
+ this._innerRemoveColumn(columnId); |
+ |
+ if (position === undefined) |
+ position = this._columnsArray.length; |
+ |
+ this._columnsArray.splice(position, 0, column); |
+ this._columns[columnId] = column; |
+ if (column.disclosure) |
+ this.disclosureColumnId = columnId; |
+ |
+ var cell = createElement('th'); |
+ cell.className = columnId + '-column'; |
+ cell[WebInspector.DataGrid._columnIdSymbol] = columnId; |
+ this._headerTableHeaders[columnId] = cell; |
+ |
+ var div = createElement('div'); |
+ if (column.titleDOMFragment) |
+ div.appendChild(column.titleDOMFragment); |
+ else |
+ div.textContent = column.title; |
+ cell.appendChild(div); |
+ |
+ if (column.sort) { |
+ cell.classList.add(column.sort); |
+ this._sortColumnCell = cell; |
+ } |
+ |
+ if (column.sortable) { |
+ cell.addEventListener('click', this._clickInHeaderCell.bind(this), false); |
+ cell.classList.add('sortable'); |
+ cell.createChild('div', 'sort-order-icon-container').createChild('div', 'sort-order-icon'); |
+ } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGrid.ColumnDescriptor} column |
+ * @param {number=} position |
+ */ |
+ addColumn(column, position) { |
+ this._innerAddColumn(column, position); |
+ } |
+ |
+ /** |
+ * @param {string} columnId |
+ */ |
+ _innerRemoveColumn(columnId) { |
+ var column = this._columns[columnId]; |
+ if (!column) |
+ return; |
+ delete this._columns[columnId]; |
+ var index = this._columnsArray.findIndex(columnConfig => columnConfig.id === columnId); |
+ this._columnsArray.splice(index, 1); |
+ var cell = this._headerTableHeaders[columnId]; |
+ if (cell.parentElement) |
+ cell.parentElement.removeChild(cell); |
+ delete this._headerTableHeaders[columnId]; |
+ } |
+ |
+ /** |
+ * @param {string} columnId |
+ */ |
+ removeColumn(columnId) { |
+ this._innerRemoveColumn(columnId); |
+ } |
+ |
+ /** |
+ * @param {string} cellClass |
+ */ |
+ setCellClass(cellClass) { |
+ this._cellClass = cellClass; |
+ } |
+ |
+ _refreshHeader() { |
+ this._headerTableColumnGroup.removeChildren(); |
+ this._dataTableColumnGroup.removeChildren(); |
+ this._headerRow.removeChildren(); |
+ this._topFillerRow.removeChildren(); |
+ this._bottomFillerRow.removeChildren(); |
+ |
+ for (var i = 0; i < this._visibleColumnsArray.length; ++i) { |
+ var column = this._visibleColumnsArray[i]; |
+ var columnId = column.id; |
+ var headerColumn = this._headerTableColumnGroup.createChild('col'); |
+ var dataColumn = this._dataTableColumnGroup.createChild('col'); |
+ if (column.width) { |
+ headerColumn.style.width = column.width; |
+ dataColumn.style.width = column.width; |
+ } |
+ this._headerRow.appendChild(this._headerTableHeaders[columnId]); |
+ this._topFillerRow.createChild('td', 'top-filler-td'); |
+ this._bottomFillerRow.createChild('td', 'bottom-filler-td')[WebInspector.DataGrid._columnIdSymbol] = columnId; |
+ } |
+ |
+ this._headerRow.createChild('th', 'corner'); |
+ this._topFillerRow.createChild('td', 'corner').classList.add('top-filler-td'); |
+ this._bottomFillerRow.createChild('td', 'corner').classList.add('bottom-filler-td'); |
+ this._headerTableColumnGroup.createChild('col', 'corner'); |
+ this._dataTableColumnGroup.createChild('col', 'corner'); |
+ } |
+ |
+ /** |
+ * @param {number} top |
+ * @param {number} bottom |
+ * @protected |
+ */ |
+ setVerticalPadding(top, bottom) { |
+ this._topFillerRow.style.height = top + 'px'; |
+ if (top || bottom) |
+ this._bottomFillerRow.style.height = bottom + 'px'; |
+ else |
+ this._bottomFillerRow.style.height = 'auto'; |
+ this.dispatchEventToListeners(WebInspector.DataGrid.Events.PaddingChanged); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGridNode} rootNode |
+ * @protected |
+ */ |
+ setRootNode(rootNode) { |
+ if (this._rootNode) { |
+ this._rootNode.removeChildren(); |
+ this._rootNode.dataGrid = null; |
+ this._rootNode._isRoot = false; |
+ } |
+ /** @type {!WebInspector.DataGridNode} */ |
+ this._rootNode = rootNode; |
+ rootNode._isRoot = true; |
+ rootNode.hasChildren = false; |
+ rootNode._expanded = true; |
+ rootNode._revealed = true; |
+ rootNode.selectable = false; |
+ rootNode.dataGrid = this; |
+ } |
+ |
+ /** |
+ * @return {!WebInspector.DataGridNode} |
+ */ |
+ rootNode() { |
+ return this._rootNode; |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _ondblclick(event) { |
+ if (this._editing || this._editingNode) |
+ return; |
+ |
+ var columnId = this.columnIdFromNode(/** @type {!Node} */ (event.target)); |
+ if (!columnId || !this._columns[columnId].editable) |
+ return; |
+ this._startEditing(/** @type {!Node} */ (event.target)); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGridNode} node |
+ * @param {number} cellIndex |
+ */ |
+ _startEditingColumnOfDataGridNode(node, cellIndex) { |
+ this._editing = true; |
+ /** @type {?WebInspector.DataGridNode} */ |
+ this._editingNode = node; |
+ this._editingNode.select(); |
+ |
+ var element = this._editingNode._element.children[cellIndex]; |
+ WebInspector.InplaceEditor.startEditing(element, this._startEditingConfig(element)); |
+ element.getComponentSelection().setBaseAndExtent(element, 0, element, 1); |
+ } |
+ |
+ /** |
+ * @param {!Node} target |
+ */ |
+ _startEditing(target) { |
+ var element = /** @type {?Element} */ (target.enclosingNodeOrSelfWithNodeName('td')); |
+ if (!element) |
+ return; |
+ |
+ this._editingNode = this.dataGridNodeFromNode(target); |
+ if (!this._editingNode) { |
+ if (!this.creationNode) |
+ return; |
+ this._editingNode = this.creationNode; |
+ } |
+ |
+ // Force editing the 1st column when editing the creation node |
+ if (this._editingNode.isCreationNode) { |
+ this._startEditingColumnOfDataGridNode(this._editingNode, this._nextEditableColumn(-1)); |
+ return; |
+ } |
+ |
+ this._editing = true; |
+ WebInspector.InplaceEditor.startEditing(element, this._startEditingConfig(element)); |
+ |
+ element.getComponentSelection().setBaseAndExtent(element, 0, element, 1); |
+ } |
+ |
+ renderInline() { |
+ this.element.classList.add('inline'); |
+ this._cornerWidth = 0; |
+ this._inline = true; |
+ this.updateWidths(); |
+ } |
+ |
+ /** |
+ * @param {!Element} element |
+ * @return {!WebInspector.InplaceEditor.Config} |
+ */ |
+ _startEditingConfig(element) { |
+ return new WebInspector.InplaceEditor.Config( |
+ this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); |
+ } |
+ |
+ /** |
+ * @param {!Element} element |
+ * @param {string} newText |
+ * @param {string} oldText |
+ * @param {string|undefined} context |
+ * @param {string} moveDirection |
+ */ |
+ _editingCommitted(element, newText, oldText, context, moveDirection) { |
+ var columnId = this.columnIdFromNode(element); |
+ if (!columnId) { |
+ this._editingCancelled(element); |
+ return; |
+ } |
+ var column = this._columns[columnId]; |
+ var cellIndex = this._visibleColumnsArray.indexOf(column); |
+ var textBeforeEditing = /** @type {string} */ (this._editingNode.data[columnId]); |
+ var currentEditingNode = this._editingNode; |
+ |
+ /** |
+ * @param {boolean} wasChange |
+ * @this {WebInspector.DataGrid} |
+ */ |
+ function moveToNextIfNeeded(wasChange) { |
+ if (!moveDirection) |
+ return; |
+ |
+ if (moveDirection === 'forward') { |
+ var firstEditableColumn = this._nextEditableColumn(-1); |
+ if (currentEditingNode.isCreationNode && cellIndex === firstEditableColumn && !wasChange) |
+ return; |
+ |
+ var nextEditableColumn = this._nextEditableColumn(cellIndex); |
+ if (nextEditableColumn !== -1) { |
+ this._startEditingColumnOfDataGridNode(currentEditingNode, nextEditableColumn); |
+ return; |
+ } |
+ |
+ var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true); |
+ if (nextDataGridNode) { |
+ this._startEditingColumnOfDataGridNode(nextDataGridNode, firstEditableColumn); |
+ return; |
+ } |
+ if (currentEditingNode.isCreationNode && wasChange) { |
+ this.addCreationNode(false); |
+ this._startEditingColumnOfDataGridNode(this.creationNode, firstEditableColumn); |
+ return; |
+ } |
+ return; |
+ } |
+ |
+ if (moveDirection === 'backward') { |
+ var prevEditableColumn = this._nextEditableColumn(cellIndex, true); |
+ if (prevEditableColumn !== -1) { |
+ this._startEditingColumnOfDataGridNode(currentEditingNode, prevEditableColumn); |
+ return; |
+ } |
+ |
+ var lastEditableColumn = this._nextEditableColumn(this._visibleColumnsArray.length, true); |
+ var nextDataGridNode = currentEditingNode.traversePreviousNode(true, true); |
+ if (nextDataGridNode) |
+ this._startEditingColumnOfDataGridNode(nextDataGridNode, lastEditableColumn); |
+ return; |
+ } |
+ } |
+ |
+ if (textBeforeEditing === newText) { |
+ this._editingCancelled(element); |
+ moveToNextIfNeeded.call(this, false); |
+ return; |
+ } |
+ |
+ // Update the text in the datagrid that we typed |
+ this._editingNode.data[columnId] = newText; |
+ |
+ // Make the callback - expects an editing node (table row), the column number that is being edited, |
+ // the text that used to be there, and the new text. |
+ this._editCallback(this._editingNode, columnId, textBeforeEditing, newText); |
+ |
+ if (this._editingNode.isCreationNode) |
+ this.addCreationNode(false); |
+ |
+ this._editingCancelled(element); |
+ moveToNextIfNeeded.call(this, true); |
+ } |
+ |
+ /** |
+ * @param {!Element} element |
+ */ |
+ _editingCancelled(element) { |
+ this._editing = false; |
+ this._editingNode = null; |
+ } |
+ |
+ /** |
+ * @param {number} cellIndex |
+ * @param {boolean=} moveBackward |
+ * @return {number} |
+ */ |
+ _nextEditableColumn(cellIndex, moveBackward) { |
+ var increment = moveBackward ? -1 : 1; |
+ var columns = this._visibleColumnsArray; |
+ for (var i = cellIndex + increment; (i >= 0) && (i < columns.length); i += increment) { |
+ if (columns[i].editable) |
+ return i; |
+ } |
+ return -1; |
+ } |
+ |
+ /** |
+ * @return {?string} |
+ */ |
+ sortColumnId() { |
+ if (!this._sortColumnCell) |
+ return null; |
+ return this._sortColumnCell[WebInspector.DataGrid._columnIdSymbol]; |
+ } |
+ |
+ /** |
+ * @return {?string} |
+ */ |
+ sortOrder() { |
+ if (!this._sortColumnCell || this._sortColumnCell.classList.contains(WebInspector.DataGrid.Order.Ascending)) |
+ return WebInspector.DataGrid.Order.Ascending; |
+ if (this._sortColumnCell.classList.contains(WebInspector.DataGrid.Order.Descending)) |
+ return WebInspector.DataGrid.Order.Descending; |
+ return null; |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ isSortOrderAscending() { |
+ return !this._sortColumnCell || this._sortColumnCell.classList.contains(WebInspector.DataGrid.Order.Ascending); |
+ } |
+ |
+ /** |
+ * @param {!Array.<number>} widths |
+ * @param {number} minPercent |
+ * @param {number=} maxPercent |
+ * @return {!Array.<number>} |
+ */ |
+ _autoSizeWidths(widths, minPercent, maxPercent) { |
+ if (minPercent) |
+ minPercent = Math.min(minPercent, Math.floor(100 / widths.length)); |
+ var totalWidth = 0; |
+ for (var i = 0; i < widths.length; ++i) |
+ totalWidth += widths[i]; |
+ var totalPercentWidth = 0; |
+ for (var i = 0; i < widths.length; ++i) { |
+ var width = Math.round(100 * widths[i] / totalWidth); |
+ if (minPercent && width < minPercent) |
+ width = minPercent; |
+ else if (maxPercent && width > maxPercent) |
+ width = maxPercent; |
+ totalPercentWidth += width; |
+ widths[i] = width; |
+ } |
+ var recoupPercent = totalPercentWidth - 100; |
+ |
+ while (minPercent && recoupPercent > 0) { |
+ for (var i = 0; i < widths.length; ++i) { |
+ if (widths[i] > minPercent) { |
+ --widths[i]; |
+ --recoupPercent; |
+ if (!recoupPercent) |
+ break; |
+ } |
+ } |
+ } |
+ |
+ while (maxPercent && recoupPercent < 0) { |
+ for (var i = 0; i < widths.length; ++i) { |
+ if (widths[i] < maxPercent) { |
+ ++widths[i]; |
+ ++recoupPercent; |
+ if (!recoupPercent) |
+ break; |
+ } |
+ } |
+ } |
+ |
+ return widths; |
+ } |
+ |
+ /** |
+ * @param {number} minPercent |
+ * @param {number=} maxPercent |
+ * @param {number=} maxDescentLevel |
+ */ |
+ autoSizeColumns(minPercent, maxPercent, maxDescentLevel) { |
+ var widths = []; |
+ for (var i = 0; i < this._columnsArray.length; ++i) |
+ widths.push((this._columnsArray[i].title || '').length); |
+ |
+ maxDescentLevel = maxDescentLevel || 0; |
+ var children = this._enumerateChildren(this._rootNode, [], maxDescentLevel + 1); |
+ for (var i = 0; i < children.length; ++i) { |
+ var node = children[i]; |
+ for (var j = 0; j < this._columnsArray.length; ++j) { |
+ var text = node.data[this._columnsArray[j].id]; |
+ if (text.length > widths[j]) |
+ widths[j] = text.length; |
+ } |
+ } |
+ |
+ widths = this._autoSizeWidths(widths, minPercent, maxPercent); |
+ |
+ for (var i = 0; i < this._columnsArray.length; ++i) |
+ this._columnsArray[i].weight = widths[i]; |
+ this._columnWidthsInitialized = false; |
+ this.updateWidths(); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGridNode} rootNode |
+ * @param {!Array<!WebInspector.DataGridNode>} result |
+ * @param {number} maxLevel |
+ * @return {!Array<!WebInspector.DataGridNode>} |
+ */ |
+ _enumerateChildren(rootNode, result, maxLevel) { |
+ if (!rootNode._isRoot) |
+ result.push(rootNode); |
+ if (!maxLevel) |
+ return []; |
+ for (var i = 0; i < rootNode.children.length; ++i) |
+ this._enumerateChildren(rootNode.children[i], result, maxLevel - 1); |
+ return result; |
+ } |
+ |
+ onResize() { |
+ this.updateWidths(); |
+ } |
+ |
+ // 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() { |
+ // Do not attempt to use offsetes if we're not attached to the document tree yet. |
+ if (!this._columnWidthsInitialized && this.element.offsetWidth) { |
+ // 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. |
+ var headerTableColumns = this._headerTableColumnGroup.children; |
+ |
+ // Use container size to avoid changes of table width caused by change of column widths. |
+ var tableWidth = this.element.offsetWidth - this._cornerWidth; |
+ var cells = this._headerTableBody.rows[0].cells; |
+ var numColumns = cells.length - 1; // Do not process corner column. |
+ for (var i = 0; i < numColumns; i++) { |
+ var column = this._visibleColumnsArray[i]; |
+ if (!column.weight) |
+ column.weight = 100 * cells[i].offsetWidth / tableWidth; |
+ } |
+ this._columnWidthsInitialized = true; |
+ } |
+ this._applyColumnWeights(); |
+ } |
+ |
+ /** |
+ * @param {string} name |
+ */ |
+ setName(name) { |
+ this._columnWeightsSetting = WebInspector.settings.createSetting('dataGrid-' + name + '-columnWeights', {}); |
+ this._loadColumnWeights(); |
+ } |
+ |
+ _loadColumnWeights() { |
+ if (!this._columnWeightsSetting) |
+ return; |
+ var weights = this._columnWeightsSetting.get(); |
+ for (var i = 0; i < this._columnsArray.length; ++i) { |
+ var column = this._columnsArray[i]; |
+ var weight = weights[column.id]; |
+ if (weight) |
+ column.weight = weight; |
+ } |
+ this._applyColumnWeights(); |
+ } |
+ |
+ _saveColumnWeights() { |
+ if (!this._columnWeightsSetting) |
+ return; |
+ var weights = {}; |
+ for (var i = 0; i < this._columnsArray.length; ++i) { |
+ var column = this._columnsArray[i]; |
+ weights[column.id] = column.weight; |
+ } |
+ this._columnWeightsSetting.set(weights); |
+ } |
+ |
+ wasShown() { |
+ this._loadColumnWeights(); |
+ } |
+ |
+ willHide() { |
+ } |
+ |
+ _applyColumnWeights() { |
+ var tableWidth = this.element.offsetWidth - this._cornerWidth; |
+ if (tableWidth <= 0) |
+ return; |
+ |
+ var sumOfWeights = 0.0; |
+ var fixedColumnWidths = []; |
+ for (var i = 0; i < this._visibleColumnsArray.length; ++i) { |
+ var column = this._visibleColumnsArray[i]; |
+ if (column.fixedWidth) { |
+ var width = this._headerTableColumnGroup.children[i][WebInspector.DataGrid._preferredWidthSymbol] || |
+ this._headerTableBody.rows[0].cells[i].offsetWidth; |
+ fixedColumnWidths[i] = width; |
+ tableWidth -= width; |
+ } else { |
+ sumOfWeights += this._visibleColumnsArray[i].weight; |
+ } |
+ } |
+ var sum = 0; |
+ var lastOffset = 0; |
+ |
+ for (var i = 0; i < this._visibleColumnsArray.length; ++i) { |
+ var column = this._visibleColumnsArray[i]; |
+ var width; |
+ if (column.fixedWidth) { |
+ width = fixedColumnWidths[i]; |
+ } else { |
+ sum += column.weight; |
+ var offset = (sum * tableWidth / sumOfWeights) | 0; |
+ width = offset - lastOffset; |
+ lastOffset = offset; |
+ } |
+ this._setPreferredWidth(i, width); |
+ } |
+ |
+ this._positionResizers(); |
+ this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized); |
+ } |
+ |
+ /** |
+ * @param {!Object.<string, boolean>} columnsVisibility |
+ */ |
+ setColumnsVisiblity(columnsVisibility) { |
+ this._visibleColumnsArray = []; |
+ for (var i = 0; i < this._columnsArray.length; ++i) { |
+ var column = this._columnsArray[i]; |
+ if (columnsVisibility[column.id]) |
+ this._visibleColumnsArray.push(column); |
+ } |
+ this._refreshHeader(); |
+ this._applyColumnWeights(); |
+ var nodes = this._enumerateChildren(this.rootNode(), [], -1); |
+ for (var i = 0; i < nodes.length; ++i) |
+ nodes[i].refresh(); |
+ } |
+ |
+ get scrollContainer() { |
+ return this._scrollContainer; |
+ } |
+ |
+ _positionResizers() { |
+ var headerTableColumns = this._headerTableColumnGroup.children; |
+ var numColumns = headerTableColumns.length - 1; // Do not process corner column. |
+ var left = []; |
+ var resizers = this._resizers; |
+ |
+ while (resizers.length > numColumns - 1) |
+ resizers.pop().remove(); |
+ |
+ for (var i = 0; i < numColumns - 1; i++) { |
+ // 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[i] = (left[i - 1] || 0) + this._headerTableBody.rows[0].cells[i].offsetWidth; |
+ } |
+ |
+ // Make n - 1 resizers for n columns. |
+ for (var i = 0; i < numColumns - 1; i++) { |
+ var resizer = resizers[i]; |
+ if (!resizer) { |
+ // This is the first call to updateWidth, so the resizers need |
+ // to be created. |
+ resizer = createElement('div'); |
+ resizer.__index = i; |
+ resizer.classList.add('data-grid-resizer'); |
+ // This resizer is associated with the column to its right. |
+ WebInspector.installDragHandle( |
+ resizer, this._startResizerDragging.bind(this), this._resizerDragging.bind(this), |
+ this._endResizerDragging.bind(this), 'col-resize'); |
+ this.element.appendChild(resizer); |
+ resizers.push(resizer); |
+ } |
+ if (resizer.__position !== left[i]) { |
+ resizer.__position = left[i]; |
+ resizer.style.left = left[i] + 'px'; |
+ } |
+ } |
+ } |
+ |
+ addCreationNode(hasChildren) { |
+ if (this.creationNode) |
+ this.creationNode.makeNormal(); |
+ |
+ var emptyData = {}; |
+ for (var column in this._columns) |
+ emptyData[column] = null; |
+ this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren); |
+ this.rootNode().appendChild(this.creationNode); |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _keyDown(event) { |
+ if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing) |
+ return; |
+ |
+ var handled = false; |
+ var nextSelectedNode; |
+ if (event.key === 'ArrowUp' && !event.altKey) { |
+ nextSelectedNode = this.selectedNode.traversePreviousNode(true); |
+ while (nextSelectedNode && !nextSelectedNode.selectable) |
+ nextSelectedNode = nextSelectedNode.traversePreviousNode(true); |
+ handled = nextSelectedNode ? true : false; |
+ } else if (event.key === 'ArrowDown' && !event.altKey) { |
+ nextSelectedNode = this.selectedNode.traverseNextNode(true); |
+ while (nextSelectedNode && !nextSelectedNode.selectable) |
+ nextSelectedNode = nextSelectedNode.traverseNextNode(true); |
+ handled = nextSelectedNode ? true : false; |
+ } else if (event.key === 'ArrowLeft') { |
+ if (this.selectedNode.expanded) { |
+ if (event.altKey) |
+ this.selectedNode.collapseRecursively(); |
+ else |
+ this.selectedNode.collapse(); |
+ handled = true; |
+ } else if (this.selectedNode.parent && !this.selectedNode.parent._isRoot) { |
+ 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.key === 'ArrowRight') { |
+ 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(); |
+ } |
+ } |
+ } else if (event.keyCode === 8 || event.keyCode === 46) { |
+ if (this._deleteCallback) { |
+ handled = true; |
+ this._deleteCallback(this.selectedNode); |
+ } |
+ } else if (isEnterKey(event)) { |
+ if (this._editCallback) { |
+ handled = true; |
+ this._startEditing(this.selectedNode._element.children[this._nextEditableColumn(-1)]); |
+ } |
+ } |
+ |
+ if (nextSelectedNode) { |
+ nextSelectedNode.reveal(); |
+ nextSelectedNode.select(); |
+ } |
+ if (handled) |
+ event.consume(true); |
+ } |
+ |
+ /** |
+ * @param {?WebInspector.DataGridNode} root |
+ * @param {boolean} onlyAffectsSubtree |
+ */ |
+ updateSelectionBeforeRemoval(root, onlyAffectsSubtree) { |
+ var ancestor = this.selectedNode; |
+ while (ancestor && ancestor !== root) |
+ ancestor = ancestor.parent; |
+ // Selection is not in the subtree being deleted. |
+ if (!ancestor) |
+ return; |
+ |
+ var nextSelectedNode; |
+ // Skip subtree being deleted when looking for the next selectable node. |
+ for (ancestor = root; ancestor && !ancestor.nextSibling; ancestor = ancestor.parent) { |
+ } |
+ if (ancestor) |
+ nextSelectedNode = ancestor.nextSibling; |
+ while (nextSelectedNode && !nextSelectedNode.selectable) |
+ nextSelectedNode = nextSelectedNode.traverseNextNode(true); |
+ |
+ if (!nextSelectedNode || nextSelectedNode.isCreationNode) { |
+ nextSelectedNode = root.traversePreviousNode(true); |
+ while (nextSelectedNode && !nextSelectedNode.selectable) |
+ nextSelectedNode = nextSelectedNode.traversePreviousNode(true); |
+ } |
+ if (nextSelectedNode) { |
+ nextSelectedNode.reveal(); |
+ nextSelectedNode.select(); |
+ } else { |
+ this.selectedNode.deselect(); |
+ } |
+ } |
+ |
+ /** |
+ * @param {!Node} target |
+ * @return {?WebInspector.DataGridNode} |
+ */ |
+ dataGridNodeFromNode(target) { |
+ var rowElement = target.enclosingNodeOrSelfWithNodeName('tr'); |
+ return rowElement && rowElement._dataGridNode; |
+ } |
+ |
+ /** |
+ * @param {!Node} target |
+ * @return {?string} |
+ */ |
+ columnIdFromNode(target) { |
+ var cellElement = target.enclosingNodeOrSelfWithNodeName('td'); |
+ return cellElement && cellElement[WebInspector.DataGrid._columnIdSymbol]; |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _clickInHeaderCell(event) { |
+ var cell = event.target.enclosingNodeOrSelfWithNodeName('th'); |
+ if (!cell || (cell[WebInspector.DataGrid._columnIdSymbol] === undefined) || !cell.classList.contains('sortable')) |
+ return; |
+ |
+ var sortOrder = WebInspector.DataGrid.Order.Ascending; |
+ if ((cell === this._sortColumnCell) && this.isSortOrderAscending()) |
+ sortOrder = WebInspector.DataGrid.Order.Descending; |
+ |
+ if (this._sortColumnCell) |
+ this._sortColumnCell.classList.remove( |
+ WebInspector.DataGrid.Order.Ascending, WebInspector.DataGrid.Order.Descending); |
+ this._sortColumnCell = cell; |
+ |
+ cell.classList.add(sortOrder); |
+ |
+ this.dispatchEventToListeners(WebInspector.DataGrid.Events.SortingChanged); |
+ } |
+ |
+ /** |
+ * @param {string} columnId |
+ * @param {!WebInspector.DataGrid.Order} sortOrder |
+ */ |
+ markColumnAsSortedBy(columnId, sortOrder) { |
+ if (this._sortColumnCell) |
+ this._sortColumnCell.classList.remove( |
+ WebInspector.DataGrid.Order.Ascending, WebInspector.DataGrid.Order.Descending); |
+ this._sortColumnCell = this._headerTableHeaders[columnId]; |
+ this._sortColumnCell.classList.add(sortOrder); |
+ } |
+ |
+ /** |
+ * @param {string} columnId |
+ * @return {!Element} |
+ */ |
+ headerTableHeader(columnId) { |
+ return this._headerTableHeaders[columnId]; |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _mouseDownInDataTable(event) { |
+ var target = /** @type {!Node} */ (event.target); |
+ var gridNode = this.dataGridNodeFromNode(target); |
+ if (!gridNode || !gridNode.selectable || gridNode.isEventWithinDisclosureTriangle(event)) |
+ return; |
+ |
+ var columnId = this.columnIdFromNode(target); |
+ if (columnId && this._columns[columnId].nonSelectable) |
+ return; |
+ |
+ if (event.metaKey) { |
+ if (gridNode.selected) |
+ gridNode.deselect(); |
+ else |
+ gridNode.select(); |
+ } else |
+ gridNode.select(); |
+ } |
+ |
+ /** |
+ * @param {?function(!WebInspector.ContextMenu)} callback |
+ */ |
+ setHeaderContextMenuCallback(callback) { |
+ this._headerContextMenuCallback = callback; |
+ } |
+ |
+ /** |
+ * @param {?function(!WebInspector.ContextMenu, !WebInspector.DataGridNode)} callback |
+ */ |
+ setRowContextMenuCallback(callback) { |
+ this._rowContextMenuCallback = callback; |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _contextMenu(event) { |
+ var contextMenu = new WebInspector.ContextMenu(event); |
+ var target = /** @type {!Node} */ (event.target); |
+ |
+ if (target.isSelfOrDescendant(this._headerTableBody)) { |
+ if (this._headerContextMenuCallback) |
+ this._headerContextMenuCallback(contextMenu); |
+ return; |
+ } |
+ |
+ var gridNode = this.dataGridNodeFromNode(target); |
+ if (this._refreshCallback && (!gridNode || gridNode !== this.creationNode)) |
+ contextMenu.appendItem(WebInspector.UIString('Refresh'), this._refreshCallback.bind(this)); |
+ |
+ if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) { |
+ if (this._editCallback) { |
+ if (gridNode === this.creationNode) |
+ contextMenu.appendItem(WebInspector.UIString.capitalize('Add ^new'), this._startEditing.bind(this, target)); |
+ else { |
+ var columnId = this.columnIdFromNode(target); |
+ if (columnId && this._columns[columnId].editable) |
+ contextMenu.appendItem( |
+ WebInspector.UIString('Edit "%s"', this._columns[columnId].title), |
+ this._startEditing.bind(this, target)); |
+ } |
+ } |
+ if (this._deleteCallback && gridNode !== this.creationNode) |
+ contextMenu.appendItem(WebInspector.UIString.capitalize('Delete'), this._deleteCallback.bind(this, gridNode)); |
+ if (this._rowContextMenuCallback) |
+ this._rowContextMenuCallback(contextMenu, gridNode); |
+ } |
+ |
+ contextMenu.show(); |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _clickInDataTable(event) { |
+ var gridNode = this.dataGridNodeFromNode(/** @type {!Node} */ (event.target)); |
+ if (!gridNode || !gridNode.hasChildren || !gridNode.isEventWithinDisclosureTriangle(event)) |
+ return; |
+ |
+ if (gridNode.expanded) { |
+ if (event.altKey) |
+ gridNode.collapseRecursively(); |
+ else |
+ gridNode.collapse(); |
+ } else { |
+ if (event.altKey) |
+ gridNode.expandRecursively(); |
+ else |
+ gridNode.expand(); |
+ } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGrid.ResizeMethod} method |
+ */ |
+ setResizeMethod(method) { |
+ this._resizeMethod = method; |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ * @return {boolean} |
+ */ |
+ _startResizerDragging(event) { |
+ this._currentResizer = event.target; |
+ return true; |
+ } |
+ |
+ _endResizerDragging() { |
+ this._currentResizer = null; |
+ this._saveColumnWeights(); |
+ this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized); |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ */ |
+ _resizerDragging(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(); |
+ var firstRowCells = this._headerTableBody.rows[0].cells; |
+ var leftEdgeOfPreviousColumn = 0; |
+ // 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 leftCellIndex = resizer.__index; |
+ var rightCellIndex = leftCellIndex + 1; |
+ for (var i = 0; i < leftCellIndex; i++) |
+ leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth; |
+ |
+ // Differences for other resize methods |
+ if (this._resizeMethod === WebInspector.DataGrid.ResizeMethod.Last) { |
+ rightCellIndex = this._resizers.length; |
+ } else if (this._resizeMethod === WebInspector.DataGrid.ResizeMethod.First) { |
+ leftEdgeOfPreviousColumn += firstRowCells[leftCellIndex].offsetWidth - firstRowCells[0].offsetWidth; |
+ leftCellIndex = 0; |
+ } |
+ |
+ var rightEdgeOfNextColumn = |
+ leftEdgeOfPreviousColumn + firstRowCells[leftCellIndex].offsetWidth + firstRowCells[rightCellIndex].offsetWidth; |
+ |
+ // Give each column some padding so that they don't disappear. |
+ var leftMinimum = leftEdgeOfPreviousColumn + WebInspector.DataGrid.ColumnResizePadding; |
+ var rightMaximum = rightEdgeOfNextColumn - WebInspector.DataGrid.ColumnResizePadding; |
+ if (leftMinimum > rightMaximum) |
+ return; |
+ |
+ dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum); |
+ |
+ var position = (dragPoint - WebInspector.DataGrid.CenterResizerOverBorderAdjustment); |
+ resizer.__position = position; |
+ resizer.style.left = position + 'px'; |
+ |
+ this._setPreferredWidth(leftCellIndex, dragPoint - leftEdgeOfPreviousColumn); |
+ this._setPreferredWidth(rightCellIndex, rightEdgeOfNextColumn - dragPoint); |
+ |
+ var leftColumn = this._visibleColumnsArray[leftCellIndex]; |
+ var rightColumn = this._visibleColumnsArray[rightCellIndex]; |
+ if (leftColumn.weight || rightColumn.weight) { |
+ var sumOfWeights = leftColumn.weight + rightColumn.weight; |
+ var delta = rightEdgeOfNextColumn - leftEdgeOfPreviousColumn; |
+ leftColumn.weight = (dragPoint - leftEdgeOfPreviousColumn) * sumOfWeights / delta; |
+ rightColumn.weight = (rightEdgeOfNextColumn - dragPoint) * sumOfWeights / delta; |
+ } |
+ |
+ this._positionResizers(); |
+ event.preventDefault(); |
+ this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized); |
+ } |
+ |
+ /** |
+ * @param {number} columnIndex |
+ * @param {number} width |
+ */ |
+ _setPreferredWidth(columnIndex, width) { |
+ var pxWidth = width + 'px'; |
+ this._headerTableColumnGroup.children[columnIndex][WebInspector.DataGrid._preferredWidthSymbol] = width; |
+ this._headerTableColumnGroup.children[columnIndex].style.width = pxWidth; |
+ this._dataTableColumnGroup.children[columnIndex].style.width = pxWidth; |
+ } |
+ |
+ /** |
+ * @param {string} columnId |
+ * @return {number} |
+ */ |
+ columnOffset(columnId) { |
+ if (!this.element.offsetWidth) |
+ return 0; |
+ for (var i = 1; i < this._visibleColumnsArray.length; ++i) { |
+ if (columnId === this._visibleColumnsArray[i].id) { |
+ if (this._resizers[i - 1]) |
+ return this._resizers[i - 1].__position; |
+ } |
+ } |
+ return 0; |
+ } |
+ |
+ /** |
+ * @return {!WebInspector.DataGridWidget} |
+ */ |
+ asWidget() { |
+ if (!this._dataGridWidget) |
+ this._dataGridWidget = new WebInspector.DataGridWidget(this); |
+ return this._dataGridWidget; |
+ } |
}; |
// Keep in sync with .data-grid col.corner style rule. |
@@ -147,1115 +1167,48 @@ WebInspector.DataGrid.ColumnDescriptor; |
/** @enum {symbol} */ |
WebInspector.DataGrid.Events = { |
- SelectedNode: Symbol("SelectedNode"), |
- DeselectedNode: Symbol("DeselectedNode"), |
- SortingChanged: Symbol("SortingChanged"), |
- ColumnsResized: Symbol("ColumnsResized"), |
- PaddingChanged: Symbol("PaddingChanged") |
+ SelectedNode: Symbol('SelectedNode'), |
+ DeselectedNode: Symbol('DeselectedNode'), |
+ SortingChanged: Symbol('SortingChanged'), |
+ ColumnsResized: Symbol('ColumnsResized'), |
+ PaddingChanged: Symbol('PaddingChanged') |
}; |
/** @enum {string} */ |
WebInspector.DataGrid.Order = { |
- Ascending: "sort-ascending", |
- Descending: "sort-descending" |
+ Ascending: 'sort-ascending', |
+ Descending: 'sort-descending' |
}; |
/** @enum {string} */ |
WebInspector.DataGrid.Align = { |
- Center: "center", |
- Right: "right" |
+ Center: 'center', |
+ Right: 'right' |
}; |
-WebInspector.DataGrid._preferredWidthSymbol = Symbol("preferredWidth"); |
-WebInspector.DataGrid._columnIdSymbol = Symbol("columnId"); |
- |
-WebInspector.DataGrid.prototype = { |
- /** |
- * @return {!Element} |
- */ |
- headerTableBody: function() |
- { |
- return this._headerTableBody; |
- }, |
- |
- /** |
- * @param {!WebInspector.DataGrid.ColumnDescriptor} column |
- * @param {number=} position |
- */ |
- _innerAddColumn: function(column, position) |
- { |
- var columnId = column.id; |
- if (columnId in this._columns) |
- this._innerRemoveColumn(columnId); |
- |
- if (position === undefined) |
- position = this._columnsArray.length; |
- |
- this._columnsArray.splice(position, 0, column); |
- this._columns[columnId] = column; |
- if (column.disclosure) |
- this.disclosureColumnId = columnId; |
- |
- var cell = createElement("th"); |
- cell.className = columnId + "-column"; |
- cell[WebInspector.DataGrid._columnIdSymbol] = columnId; |
- this._headerTableHeaders[columnId] = cell; |
- |
- var div = createElement("div"); |
- if (column.titleDOMFragment) |
- div.appendChild(column.titleDOMFragment); |
- else |
- div.textContent = column.title; |
- cell.appendChild(div); |
- |
- if (column.sort) { |
- cell.classList.add(column.sort); |
- this._sortColumnCell = cell; |
- } |
- |
- if (column.sortable) { |
- cell.addEventListener("click", this._clickInHeaderCell.bind(this), false); |
- cell.classList.add("sortable"); |
- cell.createChild("div", "sort-order-icon-container").createChild("div", "sort-order-icon"); |
- } |
- }, |
- |
- /** |
- * @param {!WebInspector.DataGrid.ColumnDescriptor} column |
- * @param {number=} position |
- */ |
- addColumn: function(column, position) |
- { |
- this._innerAddColumn(column, position); |
- }, |
- |
- /** |
- * @param {string} columnId |
- */ |
- _innerRemoveColumn: function(columnId) |
- { |
- var column = this._columns[columnId]; |
- if (!column) |
- return; |
- delete this._columns[columnId]; |
- var index = this._columnsArray.findIndex(columnConfig => columnConfig.id === columnId); |
- this._columnsArray.splice(index, 1); |
- var cell = this._headerTableHeaders[columnId]; |
- if (cell.parentElement) |
- cell.parentElement.removeChild(cell); |
- delete this._headerTableHeaders[columnId]; |
- }, |
- |
- /** |
- * @param {string} columnId |
- */ |
- removeColumn: function(columnId) |
- { |
- this._innerRemoveColumn(columnId); |
- }, |
- |
- /** |
- * @param {string} cellClass |
- */ |
- setCellClass: function(cellClass) |
- { |
- this._cellClass = cellClass; |
- }, |
- |
- _refreshHeader: function() |
- { |
- this._headerTableColumnGroup.removeChildren(); |
- this._dataTableColumnGroup.removeChildren(); |
- this._headerRow.removeChildren(); |
- this._topFillerRow.removeChildren(); |
- this._bottomFillerRow.removeChildren(); |
- |
- for (var i = 0; i < this._visibleColumnsArray.length; ++i) { |
- var column = this._visibleColumnsArray[i]; |
- var columnId = column.id; |
- var headerColumn = this._headerTableColumnGroup.createChild("col"); |
- var dataColumn = this._dataTableColumnGroup.createChild("col"); |
- if (column.width) { |
- headerColumn.style.width = column.width; |
- dataColumn.style.width = column.width; |
- } |
- this._headerRow.appendChild(this._headerTableHeaders[columnId]); |
- this._topFillerRow.createChild("td", "top-filler-td"); |
- this._bottomFillerRow.createChild("td", "bottom-filler-td")[WebInspector.DataGrid._columnIdSymbol] = columnId; |
- } |
- |
- this._headerRow.createChild("th", "corner"); |
- this._topFillerRow.createChild("td", "corner").classList.add("top-filler-td"); |
- this._bottomFillerRow.createChild("td", "corner").classList.add("bottom-filler-td"); |
- this._headerTableColumnGroup.createChild("col", "corner"); |
- this._dataTableColumnGroup.createChild("col", "corner"); |
- }, |
- |
- /** |
- * @param {number} top |
- * @param {number} bottom |
- * @protected |
- */ |
- setVerticalPadding: function(top, bottom) |
- { |
- this._topFillerRow.style.height = top + "px"; |
- if (top || bottom) |
- this._bottomFillerRow.style.height = bottom + "px"; |
- else |
- this._bottomFillerRow.style.height = "auto"; |
- this.dispatchEventToListeners(WebInspector.DataGrid.Events.PaddingChanged); |
- }, |
- |
- /** |
- * @param {!WebInspector.DataGridNode} rootNode |
- * @protected |
- */ |
- setRootNode: function(rootNode) |
- { |
- if (this._rootNode) { |
- this._rootNode.removeChildren(); |
- this._rootNode.dataGrid = null; |
- this._rootNode._isRoot = false; |
- } |
- /** @type {!WebInspector.DataGridNode} */ |
- this._rootNode = rootNode; |
- rootNode._isRoot = true; |
- rootNode.hasChildren = false; |
- rootNode._expanded = true; |
- rootNode._revealed = true; |
- rootNode.selectable = false; |
- rootNode.dataGrid = this; |
- }, |
- |
- /** |
- * @return {!WebInspector.DataGridNode} |
- */ |
- rootNode: function() |
- { |
- return this._rootNode; |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _ondblclick: function(event) |
- { |
- if (this._editing || this._editingNode) |
- return; |
- |
- var columnId = this.columnIdFromNode(/** @type {!Node} */ (event.target)); |
- if (!columnId || !this._columns[columnId].editable) |
- return; |
- this._startEditing(/** @type {!Node} */ (event.target)); |
- }, |
- |
- /** |
- * @param {!WebInspector.DataGridNode} node |
- * @param {number} cellIndex |
- */ |
- _startEditingColumnOfDataGridNode: function(node, cellIndex) |
- { |
- this._editing = true; |
- /** @type {?WebInspector.DataGridNode} */ |
- this._editingNode = node; |
- this._editingNode.select(); |
- |
- var element = this._editingNode._element.children[cellIndex]; |
- WebInspector.InplaceEditor.startEditing(element, this._startEditingConfig(element)); |
- element.getComponentSelection().setBaseAndExtent(element, 0, element, 1); |
- }, |
- |
- /** |
- * @param {!Node} target |
- */ |
- _startEditing: function(target) |
- { |
- var element = /** @type {?Element} */ (target.enclosingNodeOrSelfWithNodeName("td")); |
- if (!element) |
- return; |
- |
- this._editingNode = this.dataGridNodeFromNode(target); |
- if (!this._editingNode) { |
- if (!this.creationNode) |
- return; |
- this._editingNode = this.creationNode; |
- } |
- |
- // Force editing the 1st column when editing the creation node |
- if (this._editingNode.isCreationNode) { |
- this._startEditingColumnOfDataGridNode(this._editingNode, this._nextEditableColumn(-1)); |
- return; |
- } |
- |
- this._editing = true; |
- WebInspector.InplaceEditor.startEditing(element, this._startEditingConfig(element)); |
- |
- element.getComponentSelection().setBaseAndExtent(element, 0, element, 1); |
- }, |
- |
- renderInline: function() |
- { |
- this.element.classList.add("inline"); |
- this._cornerWidth = 0; |
- this._inline = true; |
- this.updateWidths(); |
- }, |
- |
- /** |
- * @param {!Element} element |
- * @return {!WebInspector.InplaceEditor.Config} |
- */ |
- _startEditingConfig: function(element) |
- { |
- return new WebInspector.InplaceEditor.Config(this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); |
- }, |
- |
- /** |
- * @param {!Element} element |
- * @param {string} newText |
- * @param {string} oldText |
- * @param {string|undefined} context |
- * @param {string} moveDirection |
- */ |
- _editingCommitted: function(element, newText, oldText, context, moveDirection) |
- { |
- var columnId = this.columnIdFromNode(element); |
- if (!columnId) { |
- this._editingCancelled(element); |
- return; |
- } |
- var column = this._columns[columnId]; |
- var cellIndex = this._visibleColumnsArray.indexOf(column); |
- var textBeforeEditing = /** @type {string} */ (this._editingNode.data[columnId]); |
- var currentEditingNode = this._editingNode; |
- |
- /** |
- * @param {boolean} wasChange |
- * @this {WebInspector.DataGrid} |
- */ |
- function moveToNextIfNeeded(wasChange) |
- { |
- if (!moveDirection) |
- return; |
- |
- if (moveDirection === "forward") { |
- var firstEditableColumn = this._nextEditableColumn(-1); |
- if (currentEditingNode.isCreationNode && cellIndex === firstEditableColumn && !wasChange) |
- return; |
- |
- var nextEditableColumn = this._nextEditableColumn(cellIndex); |
- if (nextEditableColumn !== -1) { |
- this._startEditingColumnOfDataGridNode(currentEditingNode, nextEditableColumn); |
- return; |
- } |
- |
- var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true); |
- if (nextDataGridNode) { |
- this._startEditingColumnOfDataGridNode(nextDataGridNode, firstEditableColumn); |
- return; |
- } |
- if (currentEditingNode.isCreationNode && wasChange) { |
- this.addCreationNode(false); |
- this._startEditingColumnOfDataGridNode(this.creationNode, firstEditableColumn); |
- return; |
- } |
- return; |
- } |
- |
- if (moveDirection === "backward") { |
- var prevEditableColumn = this._nextEditableColumn(cellIndex, true); |
- if (prevEditableColumn !== -1) { |
- this._startEditingColumnOfDataGridNode(currentEditingNode, prevEditableColumn); |
- return; |
- } |
- |
- var lastEditableColumn = this._nextEditableColumn(this._visibleColumnsArray.length, true); |
- var nextDataGridNode = currentEditingNode.traversePreviousNode(true, true); |
- if (nextDataGridNode) |
- this._startEditingColumnOfDataGridNode(nextDataGridNode, lastEditableColumn); |
- return; |
- } |
- } |
- |
- if (textBeforeEditing === newText) { |
- this._editingCancelled(element); |
- moveToNextIfNeeded.call(this, false); |
- return; |
- } |
- |
- // Update the text in the datagrid that we typed |
- this._editingNode.data[columnId] = newText; |
- |
- // Make the callback - expects an editing node (table row), the column number that is being edited, |
- // the text that used to be there, and the new text. |
- this._editCallback(this._editingNode, columnId, textBeforeEditing, newText); |
- |
- if (this._editingNode.isCreationNode) |
- this.addCreationNode(false); |
- |
- this._editingCancelled(element); |
- moveToNextIfNeeded.call(this, true); |
- }, |
- |
- /** |
- * @param {!Element} element |
- */ |
- _editingCancelled: function(element) |
- { |
- this._editing = false; |
- this._editingNode = null; |
- }, |
- |
- /** |
- * @param {number} cellIndex |
- * @param {boolean=} moveBackward |
- * @return {number} |
- */ |
- _nextEditableColumn: function(cellIndex, moveBackward) |
- { |
- var increment = moveBackward ? -1 : 1; |
- var columns = this._visibleColumnsArray; |
- for (var i = cellIndex + increment; (i >= 0) && (i < columns.length); i += increment) { |
- if (columns[i].editable) |
- return i; |
- } |
- return -1; |
- }, |
- |
- /** |
- * @return {?string} |
- */ |
- sortColumnId: function() |
- { |
- if (!this._sortColumnCell) |
- return null; |
- return this._sortColumnCell[WebInspector.DataGrid._columnIdSymbol]; |
- }, |
- |
- /** |
- * @return {?string} |
- */ |
- sortOrder: function() |
- { |
- if (!this._sortColumnCell || this._sortColumnCell.classList.contains(WebInspector.DataGrid.Order.Ascending)) |
- return WebInspector.DataGrid.Order.Ascending; |
- if (this._sortColumnCell.classList.contains(WebInspector.DataGrid.Order.Descending)) |
- return WebInspector.DataGrid.Order.Descending; |
- return null; |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- isSortOrderAscending: function() |
- { |
- return !this._sortColumnCell || this._sortColumnCell.classList.contains(WebInspector.DataGrid.Order.Ascending); |
- }, |
- |
- /** |
- * @param {!Array.<number>} widths |
- * @param {number} minPercent |
- * @param {number=} maxPercent |
- * @return {!Array.<number>} |
- */ |
- _autoSizeWidths: function(widths, minPercent, maxPercent) |
- { |
- if (minPercent) |
- minPercent = Math.min(minPercent, Math.floor(100 / widths.length)); |
- var totalWidth = 0; |
- for (var i = 0; i < widths.length; ++i) |
- totalWidth += widths[i]; |
- var totalPercentWidth = 0; |
- for (var i = 0; i < widths.length; ++i) { |
- var width = Math.round(100 * widths[i] / totalWidth); |
- if (minPercent && width < minPercent) |
- width = minPercent; |
- else if (maxPercent && width > maxPercent) |
- width = maxPercent; |
- totalPercentWidth += width; |
- widths[i] = width; |
- } |
- var recoupPercent = totalPercentWidth - 100; |
- |
- while (minPercent && recoupPercent > 0) { |
- for (var i = 0; i < widths.length; ++i) { |
- if (widths[i] > minPercent) { |
- --widths[i]; |
- --recoupPercent; |
- if (!recoupPercent) |
- break; |
- } |
- } |
- } |
- |
- while (maxPercent && recoupPercent < 0) { |
- for (var i = 0; i < widths.length; ++i) { |
- if (widths[i] < maxPercent) { |
- ++widths[i]; |
- ++recoupPercent; |
- if (!recoupPercent) |
- break; |
- } |
- } |
- } |
- |
- return widths; |
- }, |
- |
- /** |
- * @param {number} minPercent |
- * @param {number=} maxPercent |
- * @param {number=} maxDescentLevel |
- */ |
- autoSizeColumns: function(minPercent, maxPercent, maxDescentLevel) |
- { |
- var widths = []; |
- for (var i = 0; i < this._columnsArray.length; ++i) |
- widths.push((this._columnsArray[i].title || "").length); |
- |
- maxDescentLevel = maxDescentLevel || 0; |
- var children = this._enumerateChildren(this._rootNode, [], maxDescentLevel + 1); |
- for (var i = 0; i < children.length; ++i) { |
- var node = children[i]; |
- for (var j = 0; j < this._columnsArray.length; ++j) { |
- var text = node.data[this._columnsArray[j].id]; |
- if (text.length > widths[j]) |
- widths[j] = text.length; |
- } |
- } |
- |
- widths = this._autoSizeWidths(widths, minPercent, maxPercent); |
- |
- for (var i = 0; i < this._columnsArray.length; ++i) |
- this._columnsArray[i].weight = widths[i]; |
- this._columnWidthsInitialized = false; |
- this.updateWidths(); |
- }, |
- |
- /** |
- * @param {!WebInspector.DataGridNode} rootNode |
- * @param {!Array<!WebInspector.DataGridNode>} result |
- * @param {number} maxLevel |
- * @return {!Array<!WebInspector.DataGridNode>} |
- */ |
- _enumerateChildren: function(rootNode, result, maxLevel) |
- { |
- if (!rootNode._isRoot) |
- result.push(rootNode); |
- if (!maxLevel) |
- return []; |
- for (var i = 0; i < rootNode.children.length; ++i) |
- this._enumerateChildren(rootNode.children[i], result, maxLevel - 1); |
- return result; |
- }, |
- |
- onResize: function() |
- { |
- this.updateWidths(); |
- }, |
- |
- // 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() |
- { |
- // Do not attempt to use offsetes if we're not attached to the document tree yet. |
- if (!this._columnWidthsInitialized && this.element.offsetWidth) { |
- // 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. |
- var headerTableColumns = this._headerTableColumnGroup.children; |
- |
- // Use container size to avoid changes of table width caused by change of column widths. |
- var tableWidth = this.element.offsetWidth - this._cornerWidth; |
- var cells = this._headerTableBody.rows[0].cells; |
- var numColumns = cells.length - 1; // Do not process corner column. |
- for (var i = 0; i < numColumns; i++) { |
- var column = this._visibleColumnsArray[i]; |
- if (!column.weight) |
- column.weight = 100 * cells[i].offsetWidth / tableWidth; |
- } |
- this._columnWidthsInitialized = true; |
- } |
- this._applyColumnWeights(); |
- }, |
- |
- /** |
- * @param {string} name |
- */ |
- setName: function(name) |
- { |
- this._columnWeightsSetting = WebInspector.settings.createSetting("dataGrid-" + name + "-columnWeights", {}); |
- this._loadColumnWeights(); |
- }, |
- |
- _loadColumnWeights: function() |
- { |
- if (!this._columnWeightsSetting) |
- return; |
- var weights = this._columnWeightsSetting.get(); |
- for (var i = 0; i < this._columnsArray.length; ++i) { |
- var column = this._columnsArray[i]; |
- var weight = weights[column.id]; |
- if (weight) |
- column.weight = weight; |
- } |
- this._applyColumnWeights(); |
- }, |
- |
- _saveColumnWeights: function() |
- { |
- if (!this._columnWeightsSetting) |
- return; |
- var weights = {}; |
- for (var i = 0; i < this._columnsArray.length; ++i) { |
- var column = this._columnsArray[i]; |
- weights[column.id] = column.weight; |
- } |
- this._columnWeightsSetting.set(weights); |
- }, |
- |
- wasShown: function() |
- { |
- this._loadColumnWeights(); |
- }, |
- |
- willHide: function() |
- { |
- }, |
- |
- _applyColumnWeights: function() |
- { |
- var tableWidth = this.element.offsetWidth - this._cornerWidth; |
- if (tableWidth <= 0) |
- return; |
- |
- var sumOfWeights = 0.0; |
- var fixedColumnWidths = []; |
- for (var i = 0; i < this._visibleColumnsArray.length; ++i) { |
- var column = this._visibleColumnsArray[i]; |
- if (column.fixedWidth) { |
- var width = this._headerTableColumnGroup.children[i][WebInspector.DataGrid._preferredWidthSymbol] || this._headerTableBody.rows[0].cells[i].offsetWidth; |
- fixedColumnWidths[i] = width; |
- tableWidth -= width; |
- } else { |
- sumOfWeights += this._visibleColumnsArray[i].weight; |
- } |
- } |
- var sum = 0; |
- var lastOffset = 0; |
- |
- for (var i = 0; i < this._visibleColumnsArray.length; ++i) { |
- var column = this._visibleColumnsArray[i]; |
- var width; |
- if (column.fixedWidth) { |
- width = fixedColumnWidths[i]; |
- } else { |
- sum += column.weight; |
- var offset = (sum * tableWidth / sumOfWeights) | 0; |
- width = offset - lastOffset; |
- lastOffset = offset; |
- } |
- this._setPreferredWidth(i, width); |
- } |
- |
- this._positionResizers(); |
- this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized); |
- }, |
- |
- /** |
- * @param {!Object.<string, boolean>} columnsVisibility |
- */ |
- setColumnsVisiblity: function(columnsVisibility) |
- { |
- this._visibleColumnsArray = []; |
- for (var i = 0; i < this._columnsArray.length; ++i) { |
- var column = this._columnsArray[i]; |
- if (columnsVisibility[column.id]) |
- this._visibleColumnsArray.push(column); |
- } |
- this._refreshHeader(); |
- this._applyColumnWeights(); |
- var nodes = this._enumerateChildren(this.rootNode(), [], -1); |
- for (var i = 0; i < nodes.length; ++i) |
- nodes[i].refresh(); |
- }, |
- |
- get scrollContainer() |
- { |
- return this._scrollContainer; |
- }, |
- |
- _positionResizers: function() |
- { |
- var headerTableColumns = this._headerTableColumnGroup.children; |
- var numColumns = headerTableColumns.length - 1; // Do not process corner column. |
- var left = []; |
- var resizers = this._resizers; |
- |
- while (resizers.length > numColumns - 1) |
- resizers.pop().remove(); |
- |
- for (var i = 0; i < numColumns - 1; i++) { |
- // 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[i] = (left[i - 1] || 0) + this._headerTableBody.rows[0].cells[i].offsetWidth; |
- } |
- |
- // Make n - 1 resizers for n columns. |
- for (var i = 0; i < numColumns - 1; i++) { |
- var resizer = resizers[i]; |
- if (!resizer) { |
- // This is the first call to updateWidth, so the resizers need |
- // to be created. |
- resizer = createElement("div"); |
- resizer.__index = i; |
- resizer.classList.add("data-grid-resizer"); |
- // This resizer is associated with the column to its right. |
- WebInspector.installDragHandle(resizer, this._startResizerDragging.bind(this), this._resizerDragging.bind(this), this._endResizerDragging.bind(this), "col-resize"); |
- this.element.appendChild(resizer); |
- resizers.push(resizer); |
- } |
- if (resizer.__position !== left[i]) { |
- resizer.__position = left[i]; |
- resizer.style.left = left[i] + "px"; |
- } |
- } |
- }, |
- |
- addCreationNode: function(hasChildren) |
- { |
- if (this.creationNode) |
- this.creationNode.makeNormal(); |
- |
- var emptyData = {}; |
- for (var column in this._columns) |
- emptyData[column] = null; |
- this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren); |
- this.rootNode().appendChild(this.creationNode); |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _keyDown: function(event) |
- { |
- if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing) |
- return; |
- |
- var handled = false; |
- var nextSelectedNode; |
- if (event.key === "ArrowUp" && !event.altKey) { |
- nextSelectedNode = this.selectedNode.traversePreviousNode(true); |
- while (nextSelectedNode && !nextSelectedNode.selectable) |
- nextSelectedNode = nextSelectedNode.traversePreviousNode(true); |
- handled = nextSelectedNode ? true : false; |
- } else if (event.key === "ArrowDown" && !event.altKey) { |
- nextSelectedNode = this.selectedNode.traverseNextNode(true); |
- while (nextSelectedNode && !nextSelectedNode.selectable) |
- nextSelectedNode = nextSelectedNode.traverseNextNode(true); |
- handled = nextSelectedNode ? true : false; |
- } else if (event.key === "ArrowLeft") { |
- if (this.selectedNode.expanded) { |
- if (event.altKey) |
- this.selectedNode.collapseRecursively(); |
- else |
- this.selectedNode.collapse(); |
- handled = true; |
- } else if (this.selectedNode.parent && !this.selectedNode.parent._isRoot) { |
- 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.key === "ArrowRight") { |
- 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(); |
- } |
- } |
- } else if (event.keyCode === 8 || event.keyCode === 46) { |
- if (this._deleteCallback) { |
- handled = true; |
- this._deleteCallback(this.selectedNode); |
- } |
- } else if (isEnterKey(event)) { |
- if (this._editCallback) { |
- handled = true; |
- this._startEditing(this.selectedNode._element.children[this._nextEditableColumn(-1)]); |
- } |
- } |
- |
- if (nextSelectedNode) { |
- nextSelectedNode.reveal(); |
- nextSelectedNode.select(); |
- } |
- if (handled) |
- event.consume(true); |
- }, |
- |
- /** |
- * @param {?WebInspector.DataGridNode} root |
- * @param {boolean} onlyAffectsSubtree |
- */ |
- updateSelectionBeforeRemoval: function(root, onlyAffectsSubtree) |
- { |
- var ancestor = this.selectedNode; |
- while (ancestor && ancestor !== root) |
- ancestor = ancestor.parent; |
- // Selection is not in the subtree being deleted. |
- if (!ancestor) |
- return; |
- |
- var nextSelectedNode; |
- // Skip subtree being deleted when looking for the next selectable node. |
- for (ancestor = root; ancestor && !ancestor.nextSibling; ancestor = ancestor.parent) { } |
- if (ancestor) |
- nextSelectedNode = ancestor.nextSibling; |
- while (nextSelectedNode && !nextSelectedNode.selectable) |
- nextSelectedNode = nextSelectedNode.traverseNextNode(true); |
- |
- if (!nextSelectedNode || nextSelectedNode.isCreationNode) { |
- nextSelectedNode = root.traversePreviousNode(true); |
- while (nextSelectedNode && !nextSelectedNode.selectable) |
- nextSelectedNode = nextSelectedNode.traversePreviousNode(true); |
- } |
- if (nextSelectedNode) { |
- nextSelectedNode.reveal(); |
- nextSelectedNode.select(); |
- } else { |
- this.selectedNode.deselect(); |
- } |
- }, |
- |
- /** |
- * @param {!Node} target |
- * @return {?WebInspector.DataGridNode} |
- */ |
- dataGridNodeFromNode: function(target) |
- { |
- var rowElement = target.enclosingNodeOrSelfWithNodeName("tr"); |
- return rowElement && rowElement._dataGridNode; |
- }, |
- |
- /** |
- * @param {!Node} target |
- * @return {?string} |
- */ |
- columnIdFromNode: function(target) |
- { |
- var cellElement = target.enclosingNodeOrSelfWithNodeName("td"); |
- return cellElement && cellElement[WebInspector.DataGrid._columnIdSymbol]; |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _clickInHeaderCell: function(event) |
- { |
- var cell = event.target.enclosingNodeOrSelfWithNodeName("th"); |
- if (!cell || (cell[WebInspector.DataGrid._columnIdSymbol] === undefined) || !cell.classList.contains("sortable")) |
- return; |
- |
- var sortOrder = WebInspector.DataGrid.Order.Ascending; |
- if ((cell === this._sortColumnCell) && this.isSortOrderAscending()) |
- sortOrder = WebInspector.DataGrid.Order.Descending; |
- |
- if (this._sortColumnCell) |
- this._sortColumnCell.classList.remove(WebInspector.DataGrid.Order.Ascending, WebInspector.DataGrid.Order.Descending); |
- this._sortColumnCell = cell; |
- |
- cell.classList.add(sortOrder); |
- |
- this.dispatchEventToListeners(WebInspector.DataGrid.Events.SortingChanged); |
- }, |
- |
- /** |
- * @param {string} columnId |
- * @param {!WebInspector.DataGrid.Order} sortOrder |
- */ |
- markColumnAsSortedBy: function(columnId, sortOrder) |
- { |
- if (this._sortColumnCell) |
- this._sortColumnCell.classList.remove(WebInspector.DataGrid.Order.Ascending, WebInspector.DataGrid.Order.Descending); |
- this._sortColumnCell = this._headerTableHeaders[columnId]; |
- this._sortColumnCell.classList.add(sortOrder); |
- }, |
- |
- /** |
- * @param {string} columnId |
- * @return {!Element} |
- */ |
- headerTableHeader: function(columnId) |
- { |
- return this._headerTableHeaders[columnId]; |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _mouseDownInDataTable: function(event) |
- { |
- var target = /** @type {!Node} */ (event.target); |
- var gridNode = this.dataGridNodeFromNode(target); |
- if (!gridNode || !gridNode.selectable || gridNode.isEventWithinDisclosureTriangle(event)) |
- return; |
- |
- var columnId = this.columnIdFromNode(target); |
- if (columnId && this._columns[columnId].nonSelectable) |
- return; |
- |
- if (event.metaKey) { |
- if (gridNode.selected) |
- gridNode.deselect(); |
- else |
- gridNode.select(); |
- } else |
- gridNode.select(); |
- }, |
- |
- /** |
- * @param {?function(!WebInspector.ContextMenu)} callback |
- */ |
- setHeaderContextMenuCallback: function(callback) |
- { |
- this._headerContextMenuCallback = callback; |
- }, |
- |
- /** |
- * @param {?function(!WebInspector.ContextMenu, !WebInspector.DataGridNode)} callback |
- */ |
- setRowContextMenuCallback: function(callback) |
- { |
- this._rowContextMenuCallback = callback; |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _contextMenu: function(event) |
- { |
- var contextMenu = new WebInspector.ContextMenu(event); |
- var target = /** @type {!Node} */ (event.target); |
- |
- if (target.isSelfOrDescendant(this._headerTableBody)) { |
- if (this._headerContextMenuCallback) |
- this._headerContextMenuCallback(contextMenu); |
- return; |
- } |
- |
- var gridNode = this.dataGridNodeFromNode(target); |
- if (this._refreshCallback && (!gridNode || gridNode !== this.creationNode)) |
- contextMenu.appendItem(WebInspector.UIString("Refresh"), this._refreshCallback.bind(this)); |
- |
- if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) { |
- if (this._editCallback) { |
- if (gridNode === this.creationNode) |
- contextMenu.appendItem(WebInspector.UIString.capitalize("Add ^new"), this._startEditing.bind(this, target)); |
- else { |
- var columnId = this.columnIdFromNode(target); |
- if (columnId && this._columns[columnId].editable) |
- contextMenu.appendItem(WebInspector.UIString("Edit \"%s\"", this._columns[columnId].title), this._startEditing.bind(this, target)); |
- } |
- } |
- if (this._deleteCallback && gridNode !== this.creationNode) |
- contextMenu.appendItem(WebInspector.UIString.capitalize("Delete"), this._deleteCallback.bind(this, gridNode)); |
- if (this._rowContextMenuCallback) |
- this._rowContextMenuCallback(contextMenu, gridNode); |
- } |
- |
- contextMenu.show(); |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _clickInDataTable: function(event) |
- { |
- var gridNode = this.dataGridNodeFromNode(/** @type {!Node} */ (event.target)); |
- if (!gridNode || !gridNode.hasChildren || !gridNode.isEventWithinDisclosureTriangle(event)) |
- return; |
- |
- if (gridNode.expanded) { |
- if (event.altKey) |
- gridNode.collapseRecursively(); |
- else |
- gridNode.collapse(); |
- } else { |
- if (event.altKey) |
- gridNode.expandRecursively(); |
- else |
- gridNode.expand(); |
- } |
- }, |
- |
- /** |
- * @param {!WebInspector.DataGrid.ResizeMethod} method |
- */ |
- setResizeMethod: function(method) |
- { |
- this._resizeMethod = method; |
- }, |
- |
- /** |
- * @param {!Event} event |
- * @return {boolean} |
- */ |
- _startResizerDragging: function(event) |
- { |
- this._currentResizer = event.target; |
- return true; |
- }, |
- |
- _endResizerDragging: function() |
- { |
- this._currentResizer = null; |
- this._saveColumnWeights(); |
- this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized); |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _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(); |
- var firstRowCells = this._headerTableBody.rows[0].cells; |
- var leftEdgeOfPreviousColumn = 0; |
- // 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 leftCellIndex = resizer.__index; |
- var rightCellIndex = leftCellIndex + 1; |
- for (var i = 0; i < leftCellIndex; i++) |
- leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth; |
- |
- // Differences for other resize methods |
- if (this._resizeMethod === WebInspector.DataGrid.ResizeMethod.Last) { |
- rightCellIndex = this._resizers.length; |
- } else if (this._resizeMethod === WebInspector.DataGrid.ResizeMethod.First) { |
- leftEdgeOfPreviousColumn += firstRowCells[leftCellIndex].offsetWidth - firstRowCells[0].offsetWidth; |
- leftCellIndex = 0; |
- } |
- |
- var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[leftCellIndex].offsetWidth + firstRowCells[rightCellIndex].offsetWidth; |
+WebInspector.DataGrid._preferredWidthSymbol = Symbol('preferredWidth'); |
+WebInspector.DataGrid._columnIdSymbol = Symbol('columnId'); |
- // Give each column some padding so that they don't disappear. |
- var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding; |
- var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding; |
- if (leftMinimum > rightMaximum) |
- return; |
- |
- dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum); |
- |
- var position = (dragPoint - this.CenterResizerOverBorderAdjustment); |
- resizer.__position = position; |
- resizer.style.left = position + "px"; |
- |
- this._setPreferredWidth(leftCellIndex, dragPoint - leftEdgeOfPreviousColumn); |
- this._setPreferredWidth(rightCellIndex, rightEdgeOfNextColumn - dragPoint); |
- |
- var leftColumn = this._visibleColumnsArray[leftCellIndex]; |
- var rightColumn = this._visibleColumnsArray[rightCellIndex]; |
- if (leftColumn.weight || rightColumn.weight) { |
- var sumOfWeights = leftColumn.weight + rightColumn.weight; |
- var delta = rightEdgeOfNextColumn - leftEdgeOfPreviousColumn; |
- leftColumn.weight = (dragPoint - leftEdgeOfPreviousColumn) * sumOfWeights / delta; |
- rightColumn.weight = (rightEdgeOfNextColumn - dragPoint) * sumOfWeights / delta; |
- } |
- |
- this._positionResizers(); |
- event.preventDefault(); |
- this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized); |
- }, |
- |
- /** |
- * @param {number} columnIndex |
- * @param {number} width |
- */ |
- _setPreferredWidth: function(columnIndex, width) |
- { |
- var pxWidth = width + "px"; |
- this._headerTableColumnGroup.children[columnIndex][WebInspector.DataGrid._preferredWidthSymbol] = width; |
- this._headerTableColumnGroup.children[columnIndex].style.width = pxWidth; |
- this._dataTableColumnGroup.children[columnIndex].style.width = pxWidth; |
- }, |
- |
- /** |
- * @param {string} columnId |
- * @return {number} |
- */ |
- columnOffset: function(columnId) |
- { |
- if (!this.element.offsetWidth) |
- return 0; |
- for (var i = 1; i < this._visibleColumnsArray.length; ++i) { |
- if (columnId === this._visibleColumnsArray[i].id) { |
- if (this._resizers[i - 1]) |
- return this._resizers[i - 1].__position; |
- } |
- } |
- return 0; |
- }, |
- |
- /** |
- * @return {!WebInspector.DataGridWidget} |
- */ |
- asWidget: function() |
- { |
- if (!this._dataGridWidget) |
- this._dataGridWidget = new WebInspector.DataGridWidget(this); |
- return this._dataGridWidget; |
- }, |
- |
- ColumnResizePadding: 24, |
- |
- CenterResizerOverBorderAdjustment: 3, |
- |
- __proto__: WebInspector.Object.prototype |
-}; |
+WebInspector.DataGrid.ColumnResizePadding = 24; |
+WebInspector.DataGrid.CenterResizerOverBorderAdjustment = 3; |
/** @enum {string} */ |
WebInspector.DataGrid.ResizeMethod = { |
- Nearest: "nearest", |
- First: "first", |
- Last: "last" |
+ Nearest: 'nearest', |
+ First: 'first', |
+ Last: 'last' |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.Object} |
- * @param {?Object.<string, *>=} data |
- * @param {boolean=} hasChildren |
+ * @unrestricted |
*/ |
-WebInspector.DataGridNode = function(data, hasChildren) |
-{ |
+WebInspector.DataGridNode = class extends WebInspector.Object { |
+ /** |
+ * @param {?Object.<string, *>=} data |
+ * @param {boolean=} hasChildren |
+ */ |
+ constructor(data, hasChildren) { |
+ super(); |
/** @type {?Element} */ |
this._element = null; |
/** @type {boolean} */ |
@@ -1288,752 +1241,711 @@ WebInspector.DataGridNode = function(data, hasChildren) |
this.nextSibling = null; |
/** @type {number} */ |
this.disclosureToggleWidth = 10; |
-}; |
-WebInspector.DataGridNode.prototype = { |
/** @type {boolean} */ |
- selectable: true, |
+ this.selectable = true; |
/** @type {boolean} */ |
- _isRoot: false, |
- |
- /** |
- * @return {!Element} |
- */ |
- element: function() |
- { |
- if (!this._element) { |
- this.createElement(); |
- this.createCells(); |
- } |
- return /** @type {!Element} */ (this._element); |
- }, |
- |
- /** |
- * @protected |
- */ |
- createElement: function() |
- { |
- this._element = createElement("tr"); |
- this._element._dataGridNode = this; |
- |
- if (this.hasChildren) |
- this._element.classList.add("parent"); |
- if (this.expanded) |
- this._element.classList.add("expanded"); |
- if (this.selected) |
- this._element.classList.add("selected"); |
- if (this.revealed) |
- this._element.classList.add("revealed"); |
- }, |
- |
- /** |
- * @protected |
- */ |
- createCells: function() |
- { |
- this._element.removeChildren(); |
- var columnsArray = this.dataGrid._visibleColumnsArray; |
- for (var i = 0; i < columnsArray.length; ++i) |
- this._element.appendChild(this.createCell(columnsArray[i].id)); |
- this._element.appendChild(this._createTDWithClass("corner")); |
- }, |
- |
- /** |
- * @return {!Object.<string, *>} |
- */ |
- get data() |
- { |
- return this._data; |
- }, |
- |
- set data(x) |
- { |
- this._data = x || {}; |
- this.refresh(); |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- get revealed() |
- { |
- if (this._revealed !== undefined) |
- return this._revealed; |
- |
- var currentAncestor = this.parent; |
- while (currentAncestor && !currentAncestor._isRoot) { |
- if (!currentAncestor.expanded) { |
- this._revealed = false; |
- return false; |
- } |
- |
- currentAncestor = currentAncestor.parent; |
- } |
- |
- this._revealed = true; |
- return true; |
- }, |
- |
- set revealed(x) |
- { |
- if (this._revealed === x) |
- return; |
- |
- this._revealed = x; |
- |
- if (this._element) |
- this._element.classList.toggle("revealed", this._revealed); |
- |
- for (var i = 0; i < this.children.length; ++i) |
- this.children[i].revealed = x && this.expanded; |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- get hasChildren() |
- { |
- return this._hasChildren; |
- }, |
- |
- set hasChildren(x) |
- { |
- if (this._hasChildren === x) |
- return; |
- |
- this._hasChildren = x; |
- |
- if (!this._element) |
- return; |
- |
- this._element.classList.toggle("parent", this._hasChildren); |
- this._element.classList.toggle("expanded", this._hasChildren && this.expanded); |
- }, |
- |
- /** |
- * @return {number} |
- */ |
- get depth() |
- { |
- if (this._depth !== undefined) |
- return this._depth; |
- if (this.parent && !this.parent._isRoot) |
- this._depth = this.parent.depth + 1; |
- else |
- this._depth = 0; |
- return this._depth; |
- }, |
- |
- /** |
- * @return {number} |
- */ |
- get leftPadding() |
- { |
- return this.depth * this.dataGrid.indentWidth; |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- get shouldRefreshChildren() |
- { |
- return this._shouldRefreshChildren; |
- }, |
- |
- set shouldRefreshChildren(x) |
- { |
- this._shouldRefreshChildren = x; |
- if (x && this.expanded) |
- this.expand(); |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- get selected() |
- { |
- return this._selected; |
- }, |
- |
- set selected(x) |
- { |
- if (x) |
- this.select(); |
- else |
- this.deselect(); |
- }, |
- |
- /** |
- * @return {boolean} |
- */ |
- get expanded() |
- { |
- return this._expanded; |
- }, |
- |
- set expanded(x) |
- { |
- if (x) |
- this.expand(); |
- else |
- this.collapse(); |
- }, |
- |
- refresh: function() |
- { |
- if (!this.dataGrid) |
- this._element = null; |
- if (!this._element) |
- return; |
- this.createCells(); |
- }, |
- |
- /** |
- * @param {string} className |
- * @return {!Element} |
- */ |
- _createTDWithClass: function(className) |
- { |
- var cell = createElementWithClass("td", className); |
- var cellClass = this.dataGrid._cellClass; |
- if (cellClass) |
- cell.classList.add(cellClass); |
- return cell; |
- }, |
- |
- /** |
- * @param {string} columnId |
- * @return {!Element} |
- */ |
- createTD: function(columnId) |
- { |
- var cell = this._createTDWithClass(columnId + "-column"); |
- cell[WebInspector.DataGrid._columnIdSymbol] = columnId; |
- |
- var alignment = this.dataGrid._columns[columnId].align; |
- if (alignment) |
- cell.classList.add(alignment); |
- |
- if (columnId === this.dataGrid.disclosureColumnId) { |
- cell.classList.add("disclosure"); |
- if (this.leftPadding) |
- cell.style.setProperty("padding-left", this.leftPadding + "px"); |
- } |
- |
- return cell; |
- }, |
- |
- /** |
- * @param {string} columnId |
- * @return {!Element} |
- */ |
- createCell: function(columnId) |
- { |
- var cell = this.createTD(columnId); |
+ this._isRoot = false; |
+ } |
+ |
+ /** |
+ * @return {!Element} |
+ */ |
+ element() { |
+ if (!this._element) { |
+ this.createElement(); |
+ this.createCells(); |
+ } |
+ return /** @type {!Element} */ (this._element); |
+ } |
+ |
+ /** |
+ * @protected |
+ */ |
+ createElement() { |
+ this._element = createElement('tr'); |
+ this._element._dataGridNode = this; |
+ |
+ if (this.hasChildren) |
+ this._element.classList.add('parent'); |
+ if (this.expanded) |
+ this._element.classList.add('expanded'); |
+ if (this.selected) |
+ this._element.classList.add('selected'); |
+ if (this.revealed) |
+ this._element.classList.add('revealed'); |
+ } |
+ |
+ /** |
+ * @protected |
+ */ |
+ createCells() { |
+ this._element.removeChildren(); |
+ var columnsArray = this.dataGrid._visibleColumnsArray; |
+ for (var i = 0; i < columnsArray.length; ++i) |
+ this._element.appendChild(this.createCell(columnsArray[i].id)); |
+ this._element.appendChild(this._createTDWithClass('corner')); |
+ } |
+ |
+ /** |
+ * @return {!Object.<string, *>} |
+ */ |
+ get data() { |
+ return this._data; |
+ } |
+ |
+ /** |
+ * @param {!Object.<string, *>} x |
+ */ |
+ set data(x) { |
+ this._data = x || {}; |
+ this.refresh(); |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ get revealed() { |
+ if (this._revealed !== undefined) |
+ return this._revealed; |
+ |
+ var currentAncestor = this.parent; |
+ while (currentAncestor && !currentAncestor._isRoot) { |
+ if (!currentAncestor.expanded) { |
+ this._revealed = false; |
+ return false; |
+ } |
+ |
+ currentAncestor = currentAncestor.parent; |
+ } |
+ |
+ this._revealed = true; |
+ return true; |
+ } |
+ |
+ /** |
+ * @param {boolean} x |
+ */ |
+ set revealed(x) { |
+ if (this._revealed === x) |
+ return; |
+ |
+ this._revealed = x; |
+ |
+ if (this._element) |
+ this._element.classList.toggle('revealed', this._revealed); |
+ |
+ for (var i = 0; i < this.children.length; ++i) |
+ this.children[i].revealed = x && this.expanded; |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ get hasChildren() { |
+ return this._hasChildren; |
+ } |
+ |
+ /** |
+ * @param {boolean} x |
+ */ |
+ set hasChildren(x) { |
+ if (this._hasChildren === x) |
+ return; |
+ |
+ this._hasChildren = x; |
+ |
+ if (!this._element) |
+ return; |
+ |
+ this._element.classList.toggle('parent', this._hasChildren); |
+ this._element.classList.toggle('expanded', this._hasChildren && this.expanded); |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ get depth() { |
+ if (this._depth !== undefined) |
+ return this._depth; |
+ if (this.parent && !this.parent._isRoot) |
+ this._depth = this.parent.depth + 1; |
+ else |
+ this._depth = 0; |
+ return this._depth; |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ get leftPadding() { |
+ return this.depth * this.dataGrid.indentWidth; |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ get shouldRefreshChildren() { |
+ return this._shouldRefreshChildren; |
+ } |
+ |
+ /** |
+ * @param {boolean} x |
+ */ |
+ set shouldRefreshChildren(x) { |
+ this._shouldRefreshChildren = x; |
+ if (x && this.expanded) |
+ this.expand(); |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ get selected() { |
+ return this._selected; |
+ } |
+ |
+ /** |
+ * @param {boolean} x |
+ */ |
+ set selected(x) { |
+ if (x) |
+ this.select(); |
+ else |
+ this.deselect(); |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ get expanded() { |
+ return this._expanded; |
+ } |
+ |
+ /** |
+ * @param {boolean} x |
+ */ |
+ set expanded(x) { |
+ if (x) |
+ this.expand(); |
+ else |
+ this.collapse(); |
+ } |
+ |
+ refresh() { |
+ if (!this.dataGrid) |
+ this._element = null; |
+ if (!this._element) |
+ return; |
+ this.createCells(); |
+ } |
+ |
+ /** |
+ * @param {string} className |
+ * @return {!Element} |
+ */ |
+ _createTDWithClass(className) { |
+ var cell = createElementWithClass('td', className); |
+ var cellClass = this.dataGrid._cellClass; |
+ if (cellClass) |
+ cell.classList.add(cellClass); |
+ return cell; |
+ } |
+ |
+ /** |
+ * @param {string} columnId |
+ * @return {!Element} |
+ */ |
+ createTD(columnId) { |
+ var cell = this._createTDWithClass(columnId + '-column'); |
+ cell[WebInspector.DataGrid._columnIdSymbol] = columnId; |
+ |
+ var alignment = this.dataGrid._columns[columnId].align; |
+ if (alignment) |
+ cell.classList.add(alignment); |
+ |
+ if (columnId === this.dataGrid.disclosureColumnId) { |
+ cell.classList.add('disclosure'); |
+ if (this.leftPadding) |
+ cell.style.setProperty('padding-left', this.leftPadding + 'px'); |
+ } |
+ |
+ return cell; |
+ } |
+ |
+ /** |
+ * @param {string} columnId |
+ * @return {!Element} |
+ */ |
+ createCell(columnId) { |
+ var cell = this.createTD(columnId); |
+ |
+ var data = this.data[columnId]; |
+ if (data instanceof Node) { |
+ cell.appendChild(data); |
+ } else { |
+ cell.textContent = data; |
+ if (this.dataGrid._columns[columnId].longText) |
+ cell.title = data; |
+ } |
+ |
+ return cell; |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ nodeSelfHeight() { |
+ return 16; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGridNode} child |
+ */ |
+ appendChild(child) { |
+ this.insertChild(child, this.children.length); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGridNode} child |
+ * @param {number} index |
+ */ |
+ insertChild(child, index) { |
+ if (!child) |
+ throw 'insertChild: Node can\'t be undefined or null.'; |
+ if (child.parent === this) { |
+ var currentIndex = this.children.indexOf(child); |
+ if (currentIndex < 0) |
+ console.assert(false, 'Inconsistent DataGrid state'); |
+ if (currentIndex === index) |
+ return; |
+ if (currentIndex < index) |
+ --index; |
+ } |
+ |
+ child.remove(); |
+ |
+ this.children.splice(index, 0, child); |
+ this.hasChildren = true; |
+ |
+ child.parent = this; |
+ child.dataGrid = this.dataGrid; |
+ child.recalculateSiblings(index); |
+ |
+ child._depth = undefined; |
+ child._revealed = undefined; |
+ child._attached = false; |
+ child._shouldRefreshChildren = true; |
+ |
+ var current = child.children[0]; |
+ while (current) { |
+ current.dataGrid = this.dataGrid; |
+ current._depth = undefined; |
+ current._revealed = undefined; |
+ current._attached = false; |
+ current._shouldRefreshChildren = true; |
+ current = current.traverseNextNode(false, child, true); |
+ } |
+ |
+ if (this.expanded) |
+ child._attach(); |
+ if (!this.revealed) |
+ child.revealed = false; |
+ } |
+ |
+ remove() { |
+ if (this.parent) |
+ this.parent.removeChild(this); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.DataGridNode} child |
+ */ |
+ removeChild(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.'; |
+ |
+ if (this.dataGrid) |
+ this.dataGrid.updateSelectionBeforeRemoval(child, false); |
+ child._detach(); |
+ |
+ 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() { |
+ if (this.dataGrid) |
+ this.dataGrid.updateSelectionBeforeRemoval(this, true); |
+ for (var i = 0; i < this.children.length; ++i) { |
+ var child = this.children[i]; |
+ child._detach(); |
+ child.dataGrid = null; |
+ child.parent = null; |
+ child.nextSibling = null; |
+ child.previousSibling = null; |
+ } |
- var data = this.data[columnId]; |
- if (data instanceof Node) { |
- cell.appendChild(data); |
- } else { |
- cell.textContent = data; |
- if (this.dataGrid._columns[columnId].longText) |
- cell.title = data; |
- } |
- |
- return cell; |
- }, |
- |
- /** |
- * @return {number} |
- */ |
- nodeSelfHeight: function() |
- { |
- return 16; |
- }, |
- |
- /** |
- * @param {!WebInspector.DataGridNode} child |
- */ |
- appendChild: function(child) |
- { |
- this.insertChild(child, this.children.length); |
- }, |
+ this.children = []; |
+ this.hasChildren = false; |
+ } |
+ |
+ /** |
+ * @param {number} myIndex |
+ */ |
+ recalculateSiblings(myIndex) { |
+ if (!this.parent) |
+ return; |
+ |
+ var previousChild = this.parent.children[myIndex - 1] || null; |
+ if (previousChild) |
+ previousChild.nextSibling = this; |
+ this.previousSibling = previousChild; |
+ |
+ var nextChild = this.parent.children[myIndex + 1] || null; |
+ if (nextChild) |
+ nextChild.previousSibling = this; |
+ this.nextSibling = nextChild; |
+ } |
+ |
+ collapse() { |
+ if (this._isRoot) |
+ return; |
+ if (this._element) |
+ this._element.classList.remove('expanded'); |
- /** |
- * @param {!WebInspector.DataGridNode} child |
- * @param {number} index |
- */ |
- insertChild: function(child, index) |
- { |
- if (!child) |
- throw "insertChild: Node can't be undefined or null."; |
- if (child.parent === this) { |
- var currentIndex = this.children.indexOf(child); |
- if (currentIndex < 0) |
- console.assert(false, "Inconsistent DataGrid state"); |
- if (currentIndex === index) |
- return; |
- if (currentIndex < index) |
- --index; |
- } |
+ this._expanded = false; |
- child.remove(); |
+ for (var i = 0; i < this.children.length; ++i) |
+ this.children[i].revealed = false; |
+ } |
- this.children.splice(index, 0, child); |
- this.hasChildren = true; |
+ collapseRecursively() { |
+ var item = this; |
+ while (item) { |
+ if (item.expanded) |
+ item.collapse(); |
+ item = item.traverseNextNode(false, this, true); |
+ } |
+ } |
- child.parent = this; |
- child.dataGrid = this.dataGrid; |
- child.recalculateSiblings(index); |
+ populate() { |
+ } |
- child._depth = undefined; |
- child._revealed = undefined; |
- child._attached = false; |
- child._shouldRefreshChildren = true; |
+ expand() { |
+ if (!this.hasChildren || this.expanded) |
+ return; |
+ if (this._isRoot) |
+ return; |
- var current = child.children[0]; |
- while (current) { |
- current.dataGrid = this.dataGrid; |
- current._depth = undefined; |
- current._revealed = undefined; |
- current._attached = false; |
- current._shouldRefreshChildren = true; |
- current = current.traverseNextNode(false, child, true); |
- } |
+ if (this.revealed && !this._shouldRefreshChildren) |
+ for (var i = 0; i < this.children.length; ++i) |
+ this.children[i].revealed = true; |
- if (this.expanded) |
- child._attach(); |
- if (!this.revealed) |
- child.revealed = false; |
- }, |
+ if (this._shouldRefreshChildren) { |
+ for (var i = 0; i < this.children.length; ++i) |
+ this.children[i]._detach(); |
- remove: function() |
- { |
- if (this.parent) |
- this.parent.removeChild(this); |
- }, |
+ this.populate(); |
- /** |
- * @param {!WebInspector.DataGridNode} child |
- */ |
- 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."; |
- |
- if (this.dataGrid) |
- this.dataGrid.updateSelectionBeforeRemoval(child, false); |
- child._detach(); |
- |
- 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() |
- { |
- if (this.dataGrid) |
- this.dataGrid.updateSelectionBeforeRemoval(this, true); |
+ if (this._attached) { |
for (var i = 0; i < this.children.length; ++i) { |
- var child = this.children[i]; |
- child._detach(); |
- child.dataGrid = null; |
- child.parent = null; |
- child.nextSibling = null; |
- child.previousSibling = null; |
- } |
- |
- this.children = []; |
- this.hasChildren = false; |
- }, |
- |
- /** |
- * @param {number} myIndex |
- */ |
- recalculateSiblings: function(myIndex) |
- { |
- if (!this.parent) |
- return; |
- |
- var previousChild = this.parent.children[myIndex - 1] || null; |
- if (previousChild) |
- previousChild.nextSibling = this; |
- this.previousSibling = previousChild; |
- |
- var nextChild = this.parent.children[myIndex + 1] || null; |
- if (nextChild) |
- nextChild.previousSibling = this; |
- this.nextSibling = nextChild; |
- }, |
- |
- collapse: function() |
- { |
- if (this._isRoot) |
- return; |
- if (this._element) |
- this._element.classList.remove("expanded"); |
- |
- this._expanded = false; |
- |
- for (var i = 0; i < this.children.length; ++i) |
- this.children[i].revealed = false; |
- }, |
- |
- collapseRecursively: function() |
- { |
- var item = this; |
- while (item) { |
- if (item.expanded) |
- item.collapse(); |
- item = item.traverseNextNode(false, this, true); |
+ var child = this.children[i]; |
+ if (this.revealed) |
+ child.revealed = true; |
+ child._attach(); |
} |
- }, |
- |
- populate: function() { }, |
- |
- expand: function() |
- { |
- if (!this.hasChildren || this.expanded) |
- return; |
- if (this._isRoot) |
- 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.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(); |
- } |
- } |
- |
- this._shouldRefreshChildren = false; |
- } |
- |
- if (this._element) |
- this._element.classList.add("expanded"); |
- |
- this._expanded = true; |
- }, |
- |
- expandRecursively: function() |
- { |
- var item = this; |
- while (item) { |
- item.expand(); |
- item = item.traverseNextNode(false, this); |
- } |
- }, |
- |
- reveal: function() |
- { |
- if (this._isRoot) |
- return; |
- var currentAncestor = this.parent; |
- while (currentAncestor && !currentAncestor._isRoot) { |
- if (!currentAncestor.expanded) |
- currentAncestor.expand(); |
- currentAncestor = currentAncestor.parent; |
- } |
- |
- this.element().scrollIntoViewIfNeeded(false); |
- }, |
- |
- /** |
- * @param {boolean=} supressSelectedEvent |
- */ |
- 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.classList.add("selected"); |
- |
- if (!supressSelectedEvent) |
- this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.SelectedNode); |
- }, |
- |
- revealAndSelect: function() |
- { |
- if (this._isRoot) |
- return; |
- this.reveal(); |
- this.select(); |
- }, |
- |
- /** |
- * @param {boolean=} supressDeselectedEvent |
- */ |
- deselect: function(supressDeselectedEvent) |
- { |
- if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected) |
- return; |
+ } |
+ |
+ this._shouldRefreshChildren = false; |
+ } |
+ |
+ if (this._element) |
+ this._element.classList.add('expanded'); |
+ |
+ this._expanded = true; |
+ } |
+ |
+ expandRecursively() { |
+ var item = this; |
+ while (item) { |
+ item.expand(); |
+ item = item.traverseNextNode(false, this); |
+ } |
+ } |
+ |
+ reveal() { |
+ if (this._isRoot) |
+ return; |
+ var currentAncestor = this.parent; |
+ while (currentAncestor && !currentAncestor._isRoot) { |
+ if (!currentAncestor.expanded) |
+ currentAncestor.expand(); |
+ currentAncestor = currentAncestor.parent; |
+ } |
+ |
+ this.element().scrollIntoViewIfNeeded(false); |
+ } |
+ |
+ /** |
+ * @param {boolean=} supressSelectedEvent |
+ */ |
+ select(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.classList.add('selected'); |
+ |
+ if (!supressSelectedEvent) |
+ this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.SelectedNode); |
+ } |
+ |
+ revealAndSelect() { |
+ if (this._isRoot) |
+ return; |
+ this.reveal(); |
+ this.select(); |
+ } |
+ |
+ /** |
+ * @param {boolean=} supressDeselectedEvent |
+ */ |
+ deselect(supressDeselectedEvent) { |
+ if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected) |
+ return; |
- this._selected = false; |
- this.dataGrid.selectedNode = null; |
- |
- if (this._element) |
- this._element.classList.remove("selected"); |
- |
- if (!supressDeselectedEvent) |
- this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.DeselectedNode); |
- }, |
- |
- /** |
- * @param {boolean} skipHidden |
- * @param {?WebInspector.DataGridNode=} stayWithin |
- * @param {boolean=} dontPopulate |
- * @param {!Object=} info |
- * @return {?WebInspector.DataGridNode} |
- */ |
- traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info) |
- { |
- if (!dontPopulate && this.hasChildren) |
- this.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._isRoot && !((!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; |
- }, |
- |
- /** |
- * @param {boolean} skipHidden |
- * @param {boolean=} dontPopulate |
- * @return {?WebInspector.DataGridNode} |
- */ |
- traversePreviousNode: function(skipHidden, dontPopulate) |
- { |
- var node = (!skipHidden || this.revealed) ? this.previousSibling : null; |
- if (!dontPopulate && node && node.hasChildren) |
- node.populate(); |
- |
- while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) { |
- if (!dontPopulate && node.hasChildren) |
- node.populate(); |
- node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null); |
- } |
- |
- if (node) |
- return node; |
- |
- if (!this.parent || this.parent._isRoot) |
- return null; |
- |
- return this.parent; |
- }, |
- |
- /** |
- * @param {!Event} event |
- * @return {boolean} |
- */ |
- isEventWithinDisclosureTriangle: function(event) |
- { |
- if (!this.hasChildren) |
- return false; |
- var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); |
- if (!cell || !cell.classList.contains("disclosure")) |
- return false; |
- |
- var left = cell.totalOffsetLeft() + this.leftPadding; |
- return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth; |
- }, |
- |
- _attach: function() |
- { |
- if (!this.dataGrid || this._attached) |
- return; |
- |
- this._attached = true; |
- |
- var previousNode = this.traversePreviousNode(true, true); |
- var previousElement = previousNode ? previousNode.element() : this.dataGrid._topFillerRow; |
- this.dataGrid.dataTableBody.insertBefore(this.element(), previousElement.nextSibling); |
- |
- 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; |
+ this._selected = false; |
+ this.dataGrid.selectedNode = null; |
+ |
+ if (this._element) |
+ this._element.classList.remove('selected'); |
+ |
+ if (!supressDeselectedEvent) |
+ this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.DeselectedNode); |
+ } |
+ |
+ /** |
+ * @param {boolean} skipHidden |
+ * @param {?WebInspector.DataGridNode=} stayWithin |
+ * @param {boolean=} dontPopulate |
+ * @param {!Object=} info |
+ * @return {?WebInspector.DataGridNode} |
+ */ |
+ traverseNextNode(skipHidden, stayWithin, dontPopulate, info) { |
+ if (!dontPopulate && this.hasChildren) |
+ this.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._isRoot && !((!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; |
+ } |
+ |
+ /** |
+ * @param {boolean} skipHidden |
+ * @param {boolean=} dontPopulate |
+ * @return {?WebInspector.DataGridNode} |
+ */ |
+ traversePreviousNode(skipHidden, dontPopulate) { |
+ var node = (!skipHidden || this.revealed) ? this.previousSibling : null; |
+ if (!dontPopulate && node && node.hasChildren) |
+ node.populate(); |
+ |
+ while (node && |
+ ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) { |
+ if (!dontPopulate && node.hasChildren) |
+ node.populate(); |
+ node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null); |
+ } |
+ |
+ if (node) |
+ return node; |
+ |
+ if (!this.parent || this.parent._isRoot) |
+ return null; |
+ |
+ return this.parent; |
+ } |
+ |
+ /** |
+ * @param {!Event} event |
+ * @return {boolean} |
+ */ |
+ isEventWithinDisclosureTriangle(event) { |
+ if (!this.hasChildren) |
+ return false; |
+ var cell = event.target.enclosingNodeOrSelfWithNodeName('td'); |
+ if (!cell || !cell.classList.contains('disclosure')) |
+ return false; |
+ |
+ var left = cell.totalOffsetLeft() + this.leftPadding; |
+ return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth; |
+ } |
+ |
+ _attach() { |
+ if (!this.dataGrid || this._attached) |
+ return; |
+ |
+ this._attached = true; |
+ |
+ var previousNode = this.traversePreviousNode(true, true); |
+ var previousElement = previousNode ? previousNode.element() : this.dataGrid._topFillerRow; |
+ this.dataGrid.dataTableBody.insertBefore(this.element(), previousElement.nextSibling); |
+ |
+ if (this.expanded) { |
+ for (var i = 0; i < this.children.length; ++i) |
+ this.children[i]._attach(); |
+ } |
+ } |
+ |
+ _detach() { |
+ if (!this._attached) |
+ return; |
- if (this._element) |
- this._element.remove(); |
+ this._attached = false; |
- for (var i = 0; i < this.children.length; ++i) |
- this.children[i]._detach(); |
+ if (this._element) |
+ this._element.remove(); |
- this.wasDetached(); |
- }, |
+ for (var i = 0; i < this.children.length; ++i) |
+ this.children[i]._detach(); |
- wasDetached: function() |
- { |
- }, |
+ this.wasDetached(); |
+ } |
- savePosition: function() |
- { |
- if (this._savedPosition) |
- return; |
+ wasDetached() { |
+ } |
- if (!this.parent) |
- throw "savePosition: Node must have a parent."; |
- this._savedPosition = { |
- parent: this.parent, |
- index: this.parent.children.indexOf(this) |
- }; |
- }, |
+ savePosition() { |
+ if (this._savedPosition) |
+ return; |
- restorePosition: function() |
- { |
- if (!this._savedPosition) |
- return; |
+ if (!this.parent) |
+ throw 'savePosition: Node must have a parent.'; |
+ this._savedPosition = {parent: this.parent, index: this.parent.children.indexOf(this)}; |
+ } |
- if (this.parent !== this._savedPosition.parent) |
- this._savedPosition.parent.insertChild(this, this._savedPosition.index); |
+ restorePosition() { |
+ if (!this._savedPosition) |
+ return; |
- this._savedPosition = null; |
- }, |
+ if (this.parent !== this._savedPosition.parent) |
+ this._savedPosition.parent.insertChild(this, this._savedPosition.index); |
- __proto__: WebInspector.Object.prototype |
+ this._savedPosition = null; |
+ } |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.DataGridNode} |
+ * @unrestricted |
*/ |
-WebInspector.CreationDataGridNode = function(data, hasChildren) |
-{ |
- WebInspector.DataGridNode.call(this, data, hasChildren); |
+WebInspector.CreationDataGridNode = class extends WebInspector.DataGridNode { |
+ constructor(data, hasChildren) { |
+ super(data, hasChildren); |
/** @type {boolean} */ |
this.isCreationNode = true; |
-}; |
+ } |
-WebInspector.CreationDataGridNode.prototype = { |
- makeNormal: function() |
- { |
- this.isCreationNode = false; |
- }, |
- |
- __proto__: WebInspector.DataGridNode.prototype |
+ makeNormal() { |
+ this.isCreationNode = false; |
+ } |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.VBox} |
- * @param {!WebInspector.DataGrid} dataGrid |
+ * @unrestricted |
*/ |
-WebInspector.DataGridWidget = function(dataGrid) |
-{ |
- WebInspector.VBox.call(this); |
+WebInspector.DataGridWidget = class extends WebInspector.VBox { |
+ /** |
+ * @param {!WebInspector.DataGrid} dataGrid |
+ */ |
+ constructor(dataGrid) { |
+ super(); |
this._dataGrid = dataGrid; |
this.element.appendChild(dataGrid.element); |
-}; |
- |
-WebInspector.DataGridWidget.prototype = { |
- /** |
- * @override |
- */ |
- wasShown: function() |
- { |
- this._dataGrid.wasShown(); |
- }, |
- |
- /** |
- * @override |
- */ |
- willHide: function() |
- { |
- this._dataGrid.willHide(); |
- }, |
- |
- /** |
- * @override |
- */ |
- onResize: function() |
- { |
- this._dataGrid.onResize(); |
- }, |
- |
- /** |
- * @override |
- * @return {!Array.<!Element>} |
- */ |
- elementsToRestoreScrollPositionsFor: function() |
- { |
- return [ this._dataGrid._scrollContainer ]; |
- }, |
- |
- /** |
- * @override |
- */ |
- detachChildWidgets: function() |
- { |
- WebInspector.Widget.prototype.detachChildWidgets.call(this); |
- for (var dataGrid of this._dataGrids) |
- this.element.removeChild(dataGrid.element); |
- this._dataGrids = []; |
- }, |
- |
- __proto__: WebInspector.VBox.prototype |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ wasShown() { |
+ this._dataGrid.wasShown(); |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ willHide() { |
+ this._dataGrid.willHide(); |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ onResize() { |
+ this._dataGrid.onResize(); |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {!Array.<!Element>} |
+ */ |
+ elementsToRestoreScrollPositionsFor() { |
+ return [this._dataGrid._scrollContainer]; |
+ } |
+ |
+ /** |
+ * @override |
+ */ |
+ detachChildWidgets() { |
+ super.detachChildWidgets(); |
+ for (var dataGrid of this._dataGrids) |
+ this.element.removeChild(dataGrid.element); |
+ this._dataGrids = []; |
+ } |
}; |