OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 21 matching lines...) Expand all Loading... |
32 | 32 |
33 this._headerTable = document.createElement("table"); | 33 this._headerTable = document.createElement("table"); |
34 this._headerTable.className = "header"; | 34 this._headerTable.className = "header"; |
35 | 35 |
36 this._dataTable = document.createElement("table"); | 36 this._dataTable = document.createElement("table"); |
37 this._dataTable.className = "data"; | 37 this._dataTable.className = "data"; |
38 | 38 |
39 this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bin
d(this), true); | 39 this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bin
d(this), true); |
40 this._dataTable.addEventListener("click", this._clickInDataTable.bind(this),
true); | 40 this._dataTable.addEventListener("click", this._clickInDataTable.bind(this),
true); |
41 | 41 |
| 42 this.aligned = {}; |
| 43 |
42 var scrollContainer = document.createElement("div"); | 44 var scrollContainer = document.createElement("div"); |
43 scrollContainer.className = "data-container"; | 45 scrollContainer.className = "data-container"; |
44 scrollContainer.appendChild(this._dataTable); | 46 scrollContainer.appendChild(this._dataTable); |
45 | 47 |
46 this.element.appendChild(this._headerTable); | 48 this.element.appendChild(this._headerTable); |
47 this.element.appendChild(scrollContainer); | 49 this.element.appendChild(scrollContainer); |
48 | 50 |
49 var headerRow = document.createElement("tr"); | 51 var headerRow = document.createElement("tr"); |
50 var columnGroup = document.createElement("colgroup"); | 52 var columnGroup = document.createElement("colgroup"); |
51 var columnCount = 0; | 53 var columnCount = 0; |
(...skipping 19 matching lines...) Expand all Loading... |
71 if (column.sort) { | 73 if (column.sort) { |
72 cell.addStyleClass("sort-" + column.sort); | 74 cell.addStyleClass("sort-" + column.sort); |
73 this._sortColumnCell = cell; | 75 this._sortColumnCell = cell; |
74 } | 76 } |
75 | 77 |
76 if (column.sortable) { | 78 if (column.sortable) { |
77 cell.addEventListener("click", this._clickInHeaderCell.bind(this), f
alse); | 79 cell.addEventListener("click", this._clickInHeaderCell.bind(this), f
alse); |
78 cell.addStyleClass("sortable"); | 80 cell.addStyleClass("sortable"); |
79 } | 81 } |
80 | 82 |
| 83 if (column.aligned) { |
| 84 cell.addStyleClass(column.aligned); |
| 85 this.aligned[columnIdentifier] = column.aligned; |
| 86 } |
| 87 |
81 headerRow.appendChild(cell); | 88 headerRow.appendChild(cell); |
82 | 89 |
83 ++columnCount; | 90 ++columnCount; |
84 } | 91 } |
85 | 92 |
86 columnGroup.span = columnCount; | 93 columnGroup.span = columnCount; |
87 | 94 |
88 var cell = document.createElement("th"); | 95 var cell = document.createElement("th"); |
89 cell.className = "corner"; | 96 cell.className = "corner"; |
90 headerRow.appendChild(cell); | 97 headerRow.appendChild(cell); |
91 | 98 |
92 this._headerTable.appendChild(columnGroup); | 99 this._headerTableColumnGroup = columnGroup; |
| 100 this._headerTable.appendChild(this._headerTableColumnGroup); |
93 this.headerTableBody.appendChild(headerRow); | 101 this.headerTableBody.appendChild(headerRow); |
94 | 102 |
95 var fillerRow = document.createElement("tr"); | 103 var fillerRow = document.createElement("tr"); |
96 fillerRow.className = "filler"; | 104 fillerRow.className = "filler"; |
97 | 105 |
98 for (var i = 0; i < columnCount; ++i) { | 106 for (var i = 0; i < columnCount; ++i) { |
99 var cell = document.createElement("td"); | 107 var cell = document.createElement("td"); |
100 fillerRow.appendChild(cell); | 108 fillerRow.appendChild(cell); |
101 } | 109 } |
102 | 110 |
103 this._dataTable.appendChild(columnGroup.cloneNode(true)); | 111 this._dataTableColumnGroup = columnGroup.cloneNode(true); |
| 112 this._dataTable.appendChild(this._dataTableColumnGroup); |
104 this.dataTableBody.appendChild(fillerRow); | 113 this.dataTableBody.appendChild(fillerRow); |
105 | 114 |
106 this.columns = columns || {}; | 115 this.columns = columns || {}; |
107 this.children = []; | 116 this.children = []; |
108 this.selectedNode = null; | 117 this.selectedNode = null; |
109 this.expandNodesWhenArrowing = false; | 118 this.expandNodesWhenArrowing = false; |
110 this.root = true; | 119 this.root = true; |
111 this.hasChildren = false; | 120 this.hasChildren = false; |
112 this.expanded = true; | 121 this.expanded = true; |
113 this.revealed = true; | 122 this.revealed = true; |
114 this.selected = false; | 123 this.selected = false; |
115 this.dataGrid = this; | 124 this.dataGrid = this; |
116 this.indentWidth = 15; | 125 this.indentWidth = 15; |
| 126 this.resizers = []; |
| 127 this.columnWidthsInitialized = false; |
117 } | 128 } |
118 | 129 |
119 WebInspector.DataGrid.prototype = { | 130 WebInspector.DataGrid.prototype = { |
120 get sortColumnIdentifier() | 131 get sortColumnIdentifier() |
121 { | 132 { |
122 if (!this._sortColumnCell) | 133 if (!this._sortColumnCell) |
123 return null; | 134 return null; |
124 return this._sortColumnCell.columnIdentifier; | 135 return this._sortColumnCell.columnIdentifier; |
125 }, | 136 }, |
126 | 137 |
(...skipping 26 matching lines...) Expand all Loading... |
153 return this._dataTableBody; | 164 return this._dataTableBody; |
154 | 165 |
155 this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0]; | 166 this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0]; |
156 if (!this._dataTableBody) { | 167 if (!this._dataTableBody) { |
157 this._dataTableBody = this.element.ownerDocument.createElement("tbod
y"); | 168 this._dataTableBody = this.element.ownerDocument.createElement("tbod
y"); |
158 this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tF
oot); | 169 this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tF
oot); |
159 } | 170 } |
160 | 171 |
161 return this._dataTableBody; | 172 return this._dataTableBody; |
162 }, | 173 }, |
| 174 |
| 175 // Updates the widths of the table, including the positions of the column |
| 176 // resizers. |
| 177 // |
| 178 // IMPORTANT: This function MUST be called once after the element of the |
| 179 // DataGrid is attached to its parent element and every subsequent time the |
| 180 // width of the parent element is changed in order to make it possible to |
| 181 // resize the columns. |
| 182 // |
| 183 // If this function is not called after the DataGrid is attached to its |
| 184 // parent element, then the DataGrid's columns will not be resizable. |
| 185 updateWidths: function() |
| 186 { |
| 187 var headerTableColumns = this._headerTableColumnGroup.children; |
| 188 |
| 189 var left = 0; |
| 190 var tableWidth = this._dataTable.offsetWidth; |
| 191 var numColumns = headerTableColumns.length; |
| 192 |
| 193 if (!this.columnWidthsInitialized) { |
| 194 // Give all the columns initial widths now so that during a resize, |
| 195 // when the two columns that get resized get a percent value for |
| 196 // their widths, all the other columns already have percent values |
| 197 // for their widths. |
| 198 for (var i = 0; i < numColumns; i++) { |
| 199 var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWi
dth; |
| 200 var percentWidth = ((columnWidth / tableWidth) * 100) + "%"; |
| 201 this._headerTableColumnGroup.children[i].style.width = percentWi
dth; |
| 202 this._dataTableColumnGroup.children[i].style.width = percentWidt
h; |
| 203 } |
| 204 this.columnWidthsInitialized = true; |
| 205 } |
| 206 |
| 207 // Make n - 1 resizers for n columns. |
| 208 for (var i = 0; i < numColumns - 1; i++) { |
| 209 var resizer = this.resizers[i]; |
| 210 |
| 211 if (!resizer) { |
| 212 // This is the first call to updateWidth, so the resizers need |
| 213 // to be created. |
| 214 resizer = document.createElement("div"); |
| 215 resizer.addStyleClass("data-grid-resizer"); |
| 216 // This resizer is associated with the column to its right. |
| 217 resizer.rightNeighboringColumnID = i + 1; |
| 218 resizer.addEventListener("mousedown", this._startResizerDragging
.bind(this), false); |
| 219 this.element.appendChild(resizer); |
| 220 this.resizers[i] = resizer; |
| 221 } |
| 222 |
| 223 // Get the width of the cell in the first (and only) row of the |
| 224 // header table in order to determine the width of the column, since |
| 225 // it is not possible to query a column for its width. |
| 226 left += this.headerTableBody.rows[0].cells[i].offsetWidth; |
| 227 |
| 228 resizer.style.left = left + "px"; |
| 229 } |
| 230 }, |
| 231 |
| 232 addCreationNode: function(hasChildren) |
| 233 { |
| 234 if (this.creationNode) |
| 235 this.creationNode.makeNormal(); |
| 236 |
| 237 var emptyData = {}; |
| 238 for (var column in this.columns) |
| 239 emptyData[column] = ''; |
| 240 this.creationNode = new WebInspector.CreationDataGridNode(emptyData, has
Children); |
| 241 this.appendChild(this.creationNode); |
| 242 }, |
163 | 243 |
164 appendChild: function(child) | 244 appendChild: function(child) |
165 { | 245 { |
166 this.insertChild(child, this.children.length); | 246 this.insertChild(child, this.children.length); |
167 }, | 247 }, |
168 | 248 |
169 insertChild: function(child, index) | 249 insertChild: function(child, index) |
170 { | 250 { |
171 if (!child) | 251 if (!child) |
172 throw("insertChild: Node can't be undefined or null."); | 252 throw("insertChild: Node can't be undefined or null."); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 if (event.altKey) | 502 if (event.altKey) |
423 gridNode.collapseRecursively(); | 503 gridNode.collapseRecursively(); |
424 else | 504 else |
425 gridNode.collapse(); | 505 gridNode.collapse(); |
426 } else { | 506 } else { |
427 if (event.altKey) | 507 if (event.altKey) |
428 gridNode.expandRecursively(); | 508 gridNode.expandRecursively(); |
429 else | 509 else |
430 gridNode.expand(); | 510 gridNode.expand(); |
431 } | 511 } |
432 } | 512 }, |
| 513 |
| 514 _startResizerDragging: function(event) |
| 515 { |
| 516 this.currentResizer = event.target; |
| 517 if (!this.currentResizer.rightNeighboringColumnID) |
| 518 return; |
| 519 WebInspector.elementDragStart(this.lastResizer, this._resizerDragging.bi
nd(this), |
| 520 this._endResizerDragging.bind(this), event, "col-resize"); |
| 521 }, |
| 522 |
| 523 _resizerDragging: function(event) |
| 524 { |
| 525 var resizer = this.currentResizer; |
| 526 if (!resizer) |
| 527 return; |
| 528 |
| 529 // Constrain the dragpoint to be within the containing div of the |
| 530 // datagrid. |
| 531 var dragPoint = event.clientX - this.element.totalOffsetLeft; |
| 532 // Constrain the dragpoint to be within the space made up by the |
| 533 // column directly to the left and the column directly to the right. |
| 534 var leftEdgeOfPreviousColumn = 0; |
| 535 var firstRowCells = this.headerTableBody.rows[0].cells; |
| 536 for (var i = 0; i < resizer.rightNeighboringColumnID - 1; i++) |
| 537 leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth; |
| 538 |
| 539 var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[res
izer.rightNeighboringColumnID - 1].offsetWidth + firstRowCells[resizer.rightNeig
hboringColumnID].offsetWidth; |
| 540 |
| 541 // Give each column some padding so that they don't disappear.
|
| 542 var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding; |
| 543 var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding; |
| 544 |
| 545 dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum); |
| 546 |
| 547 resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment
) + "px"; |
| 548 |
| 549 var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this.
_dataTable.offsetWidth) * 100) + "%"; |
| 550 this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID -
1].style.width = percentLeftColumn; |
| 551 this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID - 1
].style.width = percentLeftColumn; |
| 552 |
| 553 var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._d
ataTable.offsetWidth) * 100) + "%"; |
| 554 this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID].
style.width = percentRightColumn; |
| 555 this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID].st
yle.width = percentRightColumn; |
| 556 |
| 557 event.preventDefault(); |
| 558 }, |
| 559 |
| 560 _endResizerDragging: function(event) |
| 561 { |
| 562 WebInspector.elementDragEnd(event); |
| 563 this.currentResizer = null; |
| 564 }, |
| 565 |
| 566 ColumnResizePadding: 10, |
| 567 |
| 568 CenterResizerOverBorderAdjustment: 3, |
433 } | 569 } |
434 | 570 |
435 WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype; | 571 WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype; |
436 | 572 |
437 WebInspector.DataGridNode = function(data, hasChildren) | 573 WebInspector.DataGridNode = function(data, hasChildren) |
438 { | 574 { |
439 this._expanded = false; | 575 this._expanded = false; |
440 this._selected = false; | 576 this._selected = false; |
441 this._shouldRefreshChildren = true; | 577 this._shouldRefreshChildren = true; |
442 this._data = data || {}; | 578 this._data = data || {}; |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 var cell = this.createCell(columnIdentifier); | 752 var cell = this.createCell(columnIdentifier); |
617 this._element.appendChild(cell); | 753 this._element.appendChild(cell); |
618 } | 754 } |
619 }, | 755 }, |
620 | 756 |
621 createCell: function(columnIdentifier) | 757 createCell: function(columnIdentifier) |
622 { | 758 { |
623 var cell = document.createElement("td"); | 759 var cell = document.createElement("td"); |
624 cell.className = columnIdentifier + "-column"; | 760 cell.className = columnIdentifier + "-column"; |
625 | 761 |
| 762 var alignment = this.dataGrid.aligned[columnIdentifier]; |
| 763 if (alignment) |
| 764 cell.addStyleClass(alignment); |
| 765 |
626 var div = document.createElement("div"); | 766 var div = document.createElement("div"); |
627 div.textContent = this.data[columnIdentifier]; | 767 div.textContent = this.data[columnIdentifier]; |
628 cell.appendChild(div); | 768 cell.appendChild(div); |
629 | 769 |
630 if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) { | 770 if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) { |
631 cell.addStyleClass("disclosure"); | 771 cell.addStyleClass("disclosure"); |
632 if (this.depth) | 772 if (this.depth) |
633 cell.style.setProperty("padding-left", (this.depth * this.dataGr
id.indentWidth) + "px"); | 773 cell.style.setProperty("padding-left", (this.depth * this.dataGr
id.indentWidth) + "px"); |
634 } | 774 } |
635 | 775 |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 | 1016 |
877 if (this._element && this._element.parentNode) | 1017 if (this._element && this._element.parentNode) |
878 this._element.parentNode.removeChild(this._element); | 1018 this._element.parentNode.removeChild(this._element); |
879 | 1019 |
880 for (var i = 0; i < this.children.length; ++i) | 1020 for (var i = 0; i < this.children.length; ++i) |
881 this.children[i]._detach(); | 1021 this.children[i]._detach(); |
882 } | 1022 } |
883 } | 1023 } |
884 | 1024 |
885 WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype; | 1025 WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype; |
| 1026 |
| 1027 WebInspector.CreationDataGridNode = function(data, hasChildren) |
| 1028 { |
| 1029 WebInspector.DataGridNode.call(this, data, hasChildren); |
| 1030 this.isCreationNode = true; |
| 1031 } |
| 1032 |
| 1033 WebInspector.CreationDataGridNode.prototype = { |
| 1034 makeNormal: function() |
| 1035 { |
| 1036 delete this.isCreationNode; |
| 1037 delete this.makeNormal; |
| 1038 } |
| 1039 } |
| 1040 |
| 1041 WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNod
e.prototype; |
OLD | NEW |