Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2164)

Unified Diff: tracing/tracing/ui/base/table.html

Issue 2162963002: [polymer] Merge of master into polymer10-migration (Closed) Base URL: git@github.com:catapult-project/catapult.git@polymer10-migration
Patch Set: Sync to head Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tracing/tracing/ui/base/table.html
diff --git a/tracing/tracing/ui/base/table.html b/tracing/tracing/ui/base/table.html
index a610892ab3e91714af47663ba7a00f0b39a65b68..64693c27701db597d6a0b9082eec561e4abe5f4e 100644
--- a/tracing/tracing/ui/base/table.html
+++ b/tracing/tracing/ui/base/table.html
@@ -57,7 +57,7 @@ tr.exportTo('tr.ui.b', function() {
});
</script>
-<dom-module id='tr-ui-b-table'>
+<dom-module id="tr-ui-b-table">
<template>
<style>
:host {
@@ -78,7 +78,7 @@ tr.exportTo('tr.ui.b', function() {
tr > td {
padding: 2px 4px 2px 4px;
- vertical-align: text-top;
+ vertical-align: top;
}
tr:focus,
@@ -153,6 +153,10 @@ tr.exportTo('tr.ui.b', function() {
background-color: rgb(171, 217, 202); /* semi-light turquoise */
}
+ table > colgroup > col[selected] {
+ background-color: #e6e6e6; /* grey */
+ }
+
table > tbody > tr.empty-row > td {
color: #666;
font-style: italic;
@@ -181,6 +185,8 @@ tr.exportTo('tr.ui.b', function() {
}
</style>
<table>
+ <colgroup id="cols">
+ </colgroup>
<thead id="head">
</thead>
<tbody id="body">
@@ -190,1192 +196,1294 @@ tr.exportTo('tr.ui.b', function() {
</table>
</template>
</dom-module>
- <script>
- 'use strict';
- (function() {
- var RIGHT_ARROW = String.fromCharCode(0x25b6);
- var UNSORTED_ARROW = String.fromCharCode(0x25BF);
- var ASCENDING_ARROW = String.fromCharCode(0x25B4);
- var DESCENDING_ARROW = String.fromCharCode(0x25BE);
- var BASIC_INDENTATION = 8;
-
- var SelectionMode = tr.ui.b.TableFormat.SelectionMode;
- var HighlightStyle = tr.ui.b.TableFormat.HighlightStyle;
- var ColumnAlignment = tr.ui.b.TableFormat.ColumnAlignment;
-
- Polymer({
- is: 'tr-ui-b-table',
-
- created: function() {
- this.selectionMode_ = SelectionMode.NONE;
- this.rowHighlightStyle_ = HighlightStyle.DEFAULT;
- this.cellHighlightStyle_ = HighlightStyle.DEFAULT;
- this.selectedTableRowInfo_ = undefined;
- this.selectedColumnIndex_ = undefined;
+<script>
+'use strict';
+(function() {
+ var RIGHT_ARROW = String.fromCharCode(0x25b6);
+ var UNSORTED_ARROW = String.fromCharCode(0x25BF);
+ var ASCENDING_ARROW = String.fromCharCode(0x25B4);
+ var DESCENDING_ARROW = String.fromCharCode(0x25BE);
+ var BASIC_INDENTATION = 8;
+
+ var SelectionMode = tr.ui.b.TableFormat.SelectionMode;
+ var HighlightStyle = tr.ui.b.TableFormat.HighlightStyle;
+ var ColumnAlignment = tr.ui.b.TableFormat.ColumnAlignment;
+
+ Polymer({
+ is: 'tr-ui-b-table',
+
+ created: function() {
+ this.selectionMode_ = SelectionMode.NONE;
+ this.rowHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.cellHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.selectedTableRowInfo_ = undefined;
+ this.selectedColumnIndex_ = undefined;
+
+ this.tableColumns_ = [];
+ this.tableRows_ = [];
+ this.tableRowsInfo_ = new WeakMap();
+ this.tableFooterRows_ = [];
+ this.tableFooterRowsInfo_ = new WeakMap();
+ this.sortColumnIndex_ = undefined;
+ this.sortDescending_ = false;
+ this.columnsWithExpandButtons_ = [];
+ this.headerCells_ = [];
+ this.showHeader_ = true;
+ this.emptyValue_ = undefined;
+ this.subRowsPropertyName_ = 'subRows';
+ this.customizeTableRowCallback_ = undefined;
+ },
+
+ ready: function() {
+ this.$.body.addEventListener(
+ 'keydown', this.onKeyDown_.bind(this), true);
+ },
+
+ clear: function() {
+ this.selectionMode_ = SelectionMode.NONE;
+ this.rowHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.cellHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.selectedTableRowInfo_ = undefined;
+ this.selectedColumnIndex_ = undefined;
+
+ Polymer.dom(this).textContent = '';
+ this.tableColumns_ = [];
+ this.tableRows_ = [];
+ this.tableRowsInfo_ = new WeakMap();
+ this.tableFooterRows_ = [];
+ this.tableFooterRowsInfo_ = new WeakMap();
+ this.sortColumnIndex_ = undefined;
+ this.sortDescending_ = false;
+ this.columnsWithExpandButtons_ = [];
+ this.headerCells_ = [];
+ this.subRowsPropertyName_ = 'subRows';
+ this.defaultExpansionStateCallback_ = undefined;
+ },
+
+ get showHeader() {
+ return this.showHeader_;
+ },
+
+ set showHeader(showHeader) {
+ this.showHeader_ = showHeader;
+ this.scheduleRebuildHeaders_();
+ },
+
+ set subRowsPropertyName(name) {
+ this.subRowsPropertyName_ = name;
+ },
+
+ /**
+ * This callback will be called whenever a body row is built
+ * for a userRow that has subRows and does not have an explicit
+ * isExpanded field.
+ * The callback should return true if the row should be expanded,
+ * or false if the row should be collapsed.
+ * @param {function(userRow, parentUserRow): boolean} cb The callback.
+ */
+ set defaultExpansionStateCallback(cb) {
+ this.defaultExpansionStateCallback_ = cb;
+ this.scheduleRebuildBody_();
+ },
+
+ /**
+ * This callback will be called whenever a body row is built.
+ * The callback's return value is ignored.
+ * @param {function(userRow, trElement)} cb The callback.
+ */
+ set customizeTableRowCallback(cb) {
+ this.customizeTableRowCallback_ = cb;
+ this.scheduleRebuildBody_();
+ },
+
+ get emptyValue() {
+ return this.emptyValue_;
+ },
+
+ set emptyValue(emptyValue) {
+ var previousEmptyValue = this.emptyValue_;
+ this.emptyValue_ = emptyValue;
+ if (this.tableRows_.length === 0 && emptyValue !== previousEmptyValue)
+ this.scheduleRebuildBody_();
+ },
+
+ /**
+ * Data objects should have the following fields:
+ * mandatory: title, value
+ * optional: width {string}, cmp {function}, colSpan {number},
+ * showExpandButtons {boolean},
+ * align {tr.ui.b.TableFormat.ColumnAlignment}
+ *
+ * @param {Array} columns An array of data objects.
+ */
+ set tableColumns(columns) {
+ // Figure out the columns with expand buttons...
+ var columnsWithExpandButtons = [];
+ for (var i = 0; i < columns.length; i++) {
+ if (columns[i].showExpandButtons)
+ columnsWithExpandButtons.push(i);
+ }
+ if (columnsWithExpandButtons.length === 0) {
+ // First column if none have specified.
+ columnsWithExpandButtons = [0];
+ }
- this.tableColumns_ = [];
- this.tableRows_ = [];
- this.tableRowsInfo_ = new WeakMap();
- this.tableFooterRows_ = [];
- this.tableFooterRowsInfo_ = new WeakMap();
- this.sortColumnIndex_ = undefined;
- this.sortDescending_ = false;
- this.columnsWithExpandButtons_ = [];
- this.headerCells_ = [];
- this.showHeader_ = true;
- this.emptyValue_ = undefined;
- this.subRowsPropertyName_ = 'subRows';
- this.customizeTableRowCallback_ = undefined;
- },
-
- ready: function() {
- this.$.body.addEventListener(
- 'keydown', this.onKeyDown_.bind(this), true);
- },
-
- clear: function() {
- this.selectionMode_ = SelectionMode.NONE;
- this.rowHighlightStyle_ = HighlightStyle.DEFAULT;
- this.cellHighlightStyle_ = HighlightStyle.DEFAULT;
- this.selectedTableRowInfo_ = undefined;
- this.selectedColumnIndex_ = undefined;
+ // Sanity check columns.
+ for (var i = 0; i < columns.length; i++) {
+ var colInfo = columns[i];
+ if (colInfo.width === undefined)
+ continue;
- Polymer.dom(this).textContent = '';
- this.tableColumns_ = [];
- this.tableRows_ = [];
- this.tableRowsInfo_ = new WeakMap();
- this.tableFooterRows_ = [];
- this.tableFooterRowsInfo_ = new WeakMap();
- this.sortColumnIndex_ = undefined;
- this.sortDescending_ = false;
- this.columnsWithExpandButtons_ = [];
- this.headerCells_ = [];
- this.subRowsPropertyName_ = 'subRows';
- this.defaultExpansionStateCallback_ = undefined;
- },
-
- get showHeader() {
- return this.showHeader_;
- },
-
- set showHeader(showHeader) {
- this.showHeader_ = showHeader;
- this.scheduleRebuildHeaders_();
- },
-
- set subRowsPropertyName(name) {
- this.subRowsPropertyName_ = name;
- },
-
- /**
- * This callback will be called whenever a body row is built
- * for a userRow that has subRows and does not have an explicit
- * isExpanded field.
- * The callback should return true if the row should be expanded,
- * or false if the row should be collapsed.
- * @param {function(userRow, parentUserRow): boolean} cb The callback.
- */
- set defaultExpansionStateCallback(cb) {
- this.defaultExpansionStateCallback_ = cb;
- this.scheduleRebuildBody_();
- },
-
- /**
- * This callback will be called whenever a body row is built.
- * The callback's return value is ignored.
- * @param {function(userRow, trElement)} cb The callback.
- */
- set customizeTableRowCallback(cb) {
- this.customizeTableRowCallback_ = cb;
- this.scheduleRebuildBody_();
- },
-
- get emptyValue() {
- return this.emptyValue_;
- },
-
- set emptyValue(emptyValue) {
- var previousEmptyValue = this.emptyValue_;
- this.emptyValue_ = emptyValue;
- if (this.tableRows_.length === 0 && emptyValue !== previousEmptyValue)
- this.scheduleRebuildBody_();
- },
-
- /**
- * Data objects should have the following fields:
- * mandatory: title, value
- * optional: width {string}, cmp {function}, colSpan {number},
- * showExpandButtons {boolean},
- * align {tr.ui.b.TableFormat.ColumnAlignment}
- *
- * @param {Array} columns An array of data objects.
- */
- set tableColumns(columns) {
- // Figure out the columns with expand buttons...
- var columnsWithExpandButtons = [];
- for (var i = 0; i < columns.length; i++) {
- if (columns[i].showExpandButtons)
- columnsWithExpandButtons.push(i);
- }
- if (columnsWithExpandButtons.length === 0) {
- // First column if none have specified.
- columnsWithExpandButtons = [0];
- }
+ var hasExpandButton = columnsWithExpandButtons.indexOf(i) !== -1;
- // Sanity check columns.
- for (var i = 0; i < columns.length; i++) {
- var colInfo = columns[i];
- if (colInfo.width === undefined)
+ var w = colInfo.width;
+ if (w) {
+ if (/\d+px/.test(w)) {
continue;
-
- var hasExpandButton = columnsWithExpandButtons.indexOf(i) !== -1;
-
- var w = colInfo.width;
- if (w) {
- if (/\d+px/.test(w)) {
- continue;
- } else if (/\d+%/.test(w)) {
- if (hasExpandButton) {
- throw new Error('Columns cannot be %-sized and host ' +
- ' an expand button');
- }
- } else {
- throw new Error('Unrecognized width string');
+ } else if (/\d+%/.test(w)) {
+ if (hasExpandButton) {
+ throw new Error('Columns cannot be %-sized and host ' +
+ ' an expand button');
}
+ } else {
+ throw new Error('Unrecognized width string');
}
}
+ }
- // Commit the change.
- this.tableColumns_ = columns;
- this.headerCells_ = [];
- this.columnsWithExpandButtons_ = columnsWithExpandButtons;
- this.sortColumnIndex = undefined;
- this.scheduleRebuildHeaders_();
-
- // Blow away the table rows, too.
- this.tableRows = this.tableRows_;
- },
-
- get tableColumns() {
- return this.tableColumns_;
- },
-
- /**
- * @param {Array} rows An array of 'row' objects with the following
- * fields:
- * optional: subRows An array of objects that have the same 'row'
- * structure. Set subRowsPropertyName to use an
- * alternative field name.
- */
- set tableRows(rows) {
- this.selectedTableRowInfo_ = undefined;
- this.selectedColumnIndex_ = undefined;
- this.maybeUpdateSelectedRow_();
- this.tableRows_ = rows;
- this.tableRowsInfo_ = new WeakMap();
- this.scheduleRebuildBody_();
- },
+ // Commit the change.
+ this.tableColumns_ = columns;
+ this.headerCells_ = [];
+ this.columnsWithExpandButtons_ = columnsWithExpandButtons;
+ this.sortColumnIndex = undefined;
+ this.scheduleRebuildHeaders_();
+
+ // Blow away the table rows, too.
+ this.tableRows = this.tableRows_;
+ },
+
+ get tableColumns() {
+ return this.tableColumns_;
+ },
+
+ /**
+ * @param {Array} rows An array of 'row' objects with the following
+ * fields:
+ * optional: subRows An array of objects that have the same 'row'
+ * structure. Set subRowsPropertyName to use an
+ * alternative field name.
+ */
+ set tableRows(rows) {
+ this.selectedTableRowInfo_ = undefined;
+ this.selectedColumnIndex_ = undefined;
+ this.maybeUpdateSelectedRow_();
+ this.tableRows_ = rows;
+ this.tableRowsInfo_ = new WeakMap();
+ this.scheduleRebuildBody_();
+ },
+
+ get tableRows() {
+ return this.tableRows_;
+ },
+
+ set footerRows(rows) {
+ this.tableFooterRows_ = rows;
+ this.tableFooterRowsInfo_ = new WeakMap();
+ this.scheduleRebuildFooter_();
+ },
+
+ get footerRows() {
+ return this.tableFooterRows_;
+ },
+
+ set sortColumnIndex(number) {
+ if (number === this.sortColumnIndex_)
+ return;
+
+ if (number === undefined) {
+ this.sortColumnIndex_ = undefined;
+ this.updateHeaderArrows_();
+ this.dispatchSortingChangedEvent_();
+ return;
+ }
- get tableRows() {
- return this.tableRows_;
- },
+ if (this.tableColumns_.length <= number)
+ throw new Error('Column number ' + number + ' is out of bounds.');
+ if (!this.tableColumns_[number].cmp)
+ throw new Error('Column ' + number + ' does not have a comparator.');
- set footerRows(rows) {
- this.tableFooterRows_ = rows;
- this.tableFooterRowsInfo_ = new WeakMap();
- this.scheduleRebuildFooter_();
- },
+ this.sortColumnIndex_ = number;
+ this.updateHeaderArrows_();
+ this.scheduleRebuildBody_();
+ this.dispatchSortingChangedEvent_();
+ },
- get footerRows() {
- return this.tableFooterRows_;
- },
+ get sortColumnIndex() {
+ return this.sortColumnIndex_;
+ },
- set sortColumnIndex(number) {
- if (number === this.sortColumnIndex_)
- return;
+ set sortDescending(value) {
+ var newValue = !!value;
- if (number === undefined) {
- this.sortColumnIndex_ = undefined;
- this.updateHeaderArrows_();
- this.dispatchSortingChangedEvent_();
- return;
- }
-
- if (this.tableColumns_.length <= number)
- throw new Error('Column number ' + number + ' is out of bounds.');
- if (!this.tableColumns_[number].cmp)
- throw new Error('Column ' + number + ' does not have a comparator.');
-
- this.sortColumnIndex_ = number;
+ if (newValue !== this.sortDescending_) {
+ this.sortDescending_ = newValue;
this.updateHeaderArrows_();
this.scheduleRebuildBody_();
this.dispatchSortingChangedEvent_();
- },
-
- get sortColumnIndex() {
- return this.sortColumnIndex_;
- },
+ }
+ },
- set sortDescending(value) {
- var newValue = !!value;
+ get sortDescending() {
+ return this.sortDescending_;
+ },
- if (newValue !== this.sortDescending_) {
- this.sortDescending_ = newValue;
- this.updateHeaderArrows_();
- this.scheduleRebuildBody_();
- this.dispatchSortingChangedEvent_();
+ updateHeaderArrows_: function() {
+ for (var i = 0; i < this.headerCells_.length; i++) {
+ if (!this.tableColumns_[i].cmp) {
+ this.headerCells_[i].sideContent = '';
+ continue;
}
- },
-
- get sortDescending() {
- return this.sortDescending_;
- },
-
- updateHeaderArrows_: function() {
- for (var i = 0; i < this.headerCells_.length; i++) {
- if (!this.tableColumns_[i].cmp) {
- this.headerCells_[i].sideContent = '';
- continue;
- }
- if (i !== this.sortColumnIndex_) {
- this.headerCells_[i].sideContent = UNSORTED_ARROW;
- continue;
- }
- this.headerCells_[i].sideContent = this.sortDescending_ ?
- DESCENDING_ARROW : ASCENDING_ARROW;
+ if (i !== this.sortColumnIndex_) {
+ this.headerCells_[i].sideContent = UNSORTED_ARROW;
+ continue;
}
- },
+ this.headerCells_[i].sideContent = this.sortDescending_ ?
+ DESCENDING_ARROW : ASCENDING_ARROW;
+ }
+ },
- sortRows_: function(rows) {
- rows.sort(function(rowA, rowB) {
- if (this.sortDescending_)
- return this.tableColumns_[this.sortColumnIndex_].cmp(
- rowB.userRow, rowA.userRow);
+ sortRows_: function(rows) {
+ rows.sort(function(rowA, rowB) {
+ if (this.sortDescending_)
return this.tableColumns_[this.sortColumnIndex_].cmp(
- rowA.userRow, rowB.userRow);
- }.bind(this));
- // Sort expanded sub rows recursively.
- for (var i = 0; i < rows.length; i++) {
- if (this.getExpandedForUserRow_(rows[i]))
- this.sortRows_(rows[i][this.subRowsPropertyName_]);
- }
- },
-
- generateHeaderColumns_: function() {
- this.headerCells_ = [];
- Polymer.dom(this.$.head).textContent = '';
- if (!this.showHeader_)
- return;
-
- var tr = this.appendNewElement_(this.$.head, 'tr');
- for (var i = 0; i < this.tableColumns_.length; i++) {
- var td = this.appendNewElement_(tr, 'td');
-
- var headerCell = document.createElement('tr-ui-b-table-header-cell');
- headerCell.cellTitle = this.tableColumns_[i].title;
- headerCell.align = this.tableColumns_[i].align;
-
- // If the table can be sorted by this column, attach a tap callback
- // to the column.
- if (this.tableColumns_[i].cmp) {
- Polymer.dom(td).classList.add('sensitive');
- headerCell.tapCallback = this.createSortCallback_(i);
- // Set arrow position, depending on the sortColumnIndex.
- if (this.sortColumnIndex_ === i)
- headerCell.sideContent = this.sortDescending_ ?
- DESCENDING_ARROW : ASCENDING_ARROW;
- else
- headerCell.sideContent = UNSORTED_ARROW;
- }
-
- Polymer.dom(td).appendChild(headerCell);
- this.headerCells_.push(headerCell);
+ rowB.userRow, rowA.userRow);
+ return this.tableColumns_[this.sortColumnIndex_].cmp(
+ rowA.userRow, rowB.userRow);
+ }.bind(this));
+ // Sort expanded sub rows recursively.
+ for (var i = 0; i < rows.length; i++) {
+ if (this.getExpandedForUserRow_(rows[i]))
+ this.sortRows_(rows[i][this.subRowsPropertyName_]);
+ }
+ },
+
+ generateHeaderColumns_: function() {
+ this.headerCells_ = [];
+ Polymer.dom(this.$.head).textContent = '';
+ if (!this.showHeader_)
+ return;
+
+ var tr = this.appendNewElement_(this.$.head, 'tr');
+ for (var i = 0; i < this.tableColumns_.length; i++) {
+ var td = this.appendNewElement_(tr, 'td');
+
+ var headerCell = document.createElement('tr-ui-b-table-header-cell');
+ headerCell.column = this.tableColumns_[i];
+
+ headerCell.addEventListener('selected-column-changed',
+ this.onSelectedColumnChanged_.bind(this));
+
+ // If the table can be sorted by this column, attach a tap callback
+ // to the column.
+ if (this.tableColumns_[i].cmp) {
+ Polymer.dom(td).classList.add('sensitive');
+ headerCell.tapCallback = this.createSortCallback_(i);
+ // Set arrow position, depending on the sortColumnIndex.
+ if (this.sortColumnIndex_ === i)
+ headerCell.sideContent = this.sortDescending_ ?
+ DESCENDING_ARROW : ASCENDING_ARROW;
+ else
+ headerCell.sideContent = UNSORTED_ARROW;
}
- },
- applySizes_: function() {
- if (this.tableRows_.length === 0 && !this.showHeader)
- return;
- var rowToRemoveSizing;
- var rowToSize;
- if (this.showHeader) {
- rowToSize = this.$.head.children[0];
- rowToRemoveSizing = this.$.body.children[0];
+ Polymer.dom(td).appendChild(headerCell);
+ this.headerCells_.push(headerCell);
+ }
+ },
+
+ onSelectedColumnChanged_: function(event) {
+ // Unselect all other columns.
+ for (var i = 0; i < this.headerCells_.length; ++i) {
+ var colElement = Polymer.dom(this.$.cols).children[i];
+ var headerCell = this.headerCells_[i];
+ if ((event.column === headerCell.column) && event.selected) {
+ Polymer.dom(colElement).setAttribute('selected', true);
} else {
- rowToSize = this.$.body.children[0];
- rowToRemoveSizing = this.$.head.children[0];
+ headerCell.selected = false;
+ Polymer.dom(colElement).removeAttribute('selected');
+ }
+ }
+ },
+
+ applySizes_: function() {
+ if (this.tableRows_.length === 0 && !this.showHeader)
+ return;
+ var rowToRemoveSizing;
+ var rowToSize;
+ if (this.showHeader) {
+ rowToSize = Polymer.dom(this.$.head).children[0];
+ rowToRemoveSizing = Polymer.dom(this.$.body).children[0];
+ } else {
+ rowToSize = Polymer.dom(this.$.body).children[0];
+ rowToRemoveSizing = Polymer.dom(this.$.head).children[0];
+ }
+ for (var i = 0; i < this.tableColumns_.length; i++) {
+ if (rowToRemoveSizing && Polymer.dom(rowToRemoveSizing).children[i]) {
+ var tdToRemoveSizing = Polymer.dom(rowToRemoveSizing).children[i];
+ tdToRemoveSizing.style.minWidth = '';
+ tdToRemoveSizing.style.width = '';
}
- for (var i = 0; i < this.tableColumns_.length; i++) {
- if (rowToRemoveSizing && rowToRemoveSizing.children[i]) {
- var tdToRemoveSizing = rowToRemoveSizing.children[i];
- tdToRemoveSizing.style.minWidth = '';
- tdToRemoveSizing.style.width = '';
- }
-
- // Apply sizing.
- var td = rowToSize.children[i];
-
- var delta;
- if (this.columnsWithExpandButtons_.indexOf(i) !== -1) {
- td.style.paddingLeft = BASIC_INDENTATION + 'px';
- delta = BASIC_INDENTATION + 'px';
- } else {
- delta = undefined;
- }
- function calc(base, delta) {
- if (delta)
- return 'calc(' + base + ' - ' + delta + ')';
- else
- return base;
- }
+ // Apply sizing.
+ var td = Polymer.dom(rowToSize).children[i];
- var w = this.tableColumns_[i].width;
- if (w) {
- if (/\d+px/.test(w)) {
- td.style.minWidth = calc(w, delta);
- } else if (/\d+%/.test(w)) {
- td.style.width = w;
- } else {
- throw new Error('Unrecognized width string: ' + w);
- }
- }
+ var delta;
+ if (this.columnsWithExpandButtons_.indexOf(i) !== -1) {
+ td.style.paddingLeft = BASIC_INDENTATION + 'px';
+ delta = BASIC_INDENTATION + 'px';
+ } else {
+ delta = undefined;
}
- },
-
- createSortCallback_: function(columnNumber) {
- return function() {
- var previousIndex = this.sortColumnIndex;
- this.sortColumnIndex = columnNumber;
- if (previousIndex !== columnNumber)
- this.sortDescending = false;
+
+ function calc(base, delta) {
+ if (delta)
+ return 'calc(' + base + ' - ' + delta + ')';
else
- this.sortDescending = !this.sortDescending;
- }.bind(this);
- },
-
- generateTableRowNodes_: function(tableSection, userRows, rowInfoMap,
- indentation, lastAddedRow,
- parentRowInfo) {
- if (this.sortColumnIndex_ !== undefined &&
- tableSection === this.$.body) {
- userRows = userRows.slice(); // Don't mess with the input data.
- userRows.sort(function(rowA, rowB) {
- var c = this.tableColumns_[this.sortColumnIndex_].cmp(
- rowA, rowB);
- if (this.sortDescending_)
- c = -c;
- return c;
- }.bind(this));
+ return base;
}
- for (var i = 0; i < userRows.length; i++) {
- var userRow = userRows[i];
- var rowInfo = this.getOrCreateRowInfoFor_(rowInfoMap, userRow,
- parentRowInfo);
- var htmlNode = this.getHTMLNodeForRowInfo_(
- tableSection, rowInfo, rowInfoMap, indentation);
-
- if (lastAddedRow === undefined) {
- // Put first into the table.
- Polymer.dom(tableSection).insertBefore(
- htmlNode, Polymer.dom(tableSection).firstChild);
+ var w = this.tableColumns_[i].width;
+ if (w) {
+ if (/\d+px/.test(w)) {
+ td.style.minWidth = calc(w, delta);
+ } else if (/\d+%/.test(w)) {
+ td.style.width = w;
} else {
- // This is shorthand for insertAfter(htmlNode, lastAdded).
- var nextSiblingOfLastAdded = Polymer.dom(lastAddedRow).nextSibling;
- Polymer.dom(tableSection).insertBefore(
- htmlNode, nextSiblingOfLastAdded);
+ throw new Error('Unrecognized width string: ' + w);
}
- this.updateTabIndexForTableRowNode_(htmlNode);
-
- lastAddedRow = htmlNode;
- if (!rowInfo.isExpanded)
- continue;
-
- // Append subrows now.
- lastAddedRow = this.generateTableRowNodes_(
- tableSection, userRow[this.subRowsPropertyName_], rowInfoMap,
- indentation + 1, lastAddedRow, rowInfo);
}
- return lastAddedRow;
- },
-
- getOrCreateRowInfoFor_: function(rowInfoMap, userRow, parentRowInfo) {
- var rowInfo = undefined;
+ }
+ },
+
+ createSortCallback_: function(columnNumber) {
+ return function() {
+ var previousIndex = this.sortColumnIndex;
+ this.sortColumnIndex = columnNumber;
+ if (previousIndex !== columnNumber)
+ this.sortDescending = false;
+ else
+ this.sortDescending = !this.sortDescending;
+ }.bind(this);
+ },
+
+ generateTableColNodes_: function() {
+ for (var i = 0; i < this.headerCells_.length; ++i) {
+ var colElement = document.createElement('col');
+ if (this.headerCells_[i].selected)
+ Polymer.dom(colElement).setAttribute('selected', true);
+ Polymer.dom(this.$.cols).appendChild(colElement);
+ }
+ },
+
+ generateTableRowNodes_: function(tableSection, userRows, rowInfoMap,
+ indentation, lastAddedRow,
+ parentRowInfo) {
+ if (this.sortColumnIndex_ !== undefined &&
+ tableSection === this.$.body) {
+ userRows = userRows.slice(); // Don't mess with the input data.
+ userRows.sort(function(rowA, rowB) {
+ var c = this.tableColumns_[this.sortColumnIndex_].cmp(
+ rowA, rowB);
+ if (this.sortDescending_)
+ c = -c;
+ return c;
+ }.bind(this));
+ }
- if (rowInfoMap.has(userRow)) {
- rowInfo = rowInfoMap.get(userRow);
+ for (var i = 0; i < userRows.length; i++) {
+ var userRow = userRows[i];
+ var rowInfo = this.getOrCreateRowInfoFor_(rowInfoMap, userRow,
+ parentRowInfo);
+ var htmlNode = this.getHTMLNodeForRowInfo_(
+ tableSection, rowInfo, rowInfoMap, indentation);
+
+ if (lastAddedRow === undefined) {
+ // Put first into the table.
+ Polymer.dom(tableSection).insertBefore(
+ htmlNode, Polymer.dom(tableSection).firstChild);
} else {
- rowInfo = {
- userRow: userRow,
- htmlNode: undefined,
- parentRowInfo: parentRowInfo
- };
- rowInfoMap.set(userRow, rowInfo);
- }
-
- // Recompute isExpanded in case defaultExpansionStateCallback_ has
- // changed.
- rowInfo.isExpanded = this.getExpandedForUserRow_(userRow);
-
- return rowInfo;
- },
-
- customizeTableRow_: function(userRow, trElement) {
- if (!this.customizeTableRowCallback_)
- return;
- this.customizeTableRowCallback_(userRow, trElement);
- },
-
- getHTMLNodeForRowInfo_: function(tableSection, rowInfo,
- rowInfoMap, indentation) {
- if (rowInfo.htmlNode) {
- this.customizeTableRow_(rowInfo.userRow, rowInfo.htmlNode);
- return rowInfo.htmlNode;
+ // This is shorthand for insertAfter(htmlNode, lastAdded).
+ var nextSiblingOfLastAdded = Polymer.dom(lastAddedRow).nextSibling;
+ Polymer.dom(tableSection).insertBefore(
+ htmlNode, nextSiblingOfLastAdded);
}
+ this.updateTabIndexForTableRowNode_(htmlNode);
- var INDENT_SPACE = indentation * 16;
- var INDENT_SPACE_NO_BUTTON = indentation * 16 + BASIC_INDENTATION;
- var trElement = this.ownerDocument.createElement('tr');
- rowInfo.htmlNode = trElement;
- rowInfo.indentation = indentation;
- trElement.rowInfo = rowInfo;
- this.customizeTableRow_(rowInfo.userRow, trElement);
-
- for (var i = 0; i < this.tableColumns_.length;) {
- var td = this.appendNewElement_(trElement, 'td');
- td.columnIndex = i;
-
- var column = this.tableColumns_[i];
- var value = column.value(rowInfo.userRow);
- var colSpan = column.colSpan ? column.colSpan : 1;
- td.style.colSpan = colSpan;
-
- switch (column.align) {
- case undefined:
- case ColumnAlignment.LEFT:
- break;
-
- case ColumnAlignment.RIGHT:
- td.style.textAlign = 'right';
- break;
-
- default:
- throw new Error('Invalid alignment of column at index=' + i +
- ': ' + column.align);
- }
-
- if (this.doesColumnIndexSupportSelection(i))
- Polymer.dom(td).classList.add('supports-selection');
-
- if (this.columnsWithExpandButtons_.indexOf(i) != -1) {
- if (rowInfo.userRow[this.subRowsPropertyName_] &&
- rowInfo.userRow[this.subRowsPropertyName_].length > 0) {
- td.style.paddingLeft = INDENT_SPACE + 'px';
- var expandButton = this.appendNewElement_(td,
- 'expand-button');
- Polymer.dom(expandButton).textContent = RIGHT_ARROW;
- if (rowInfo.isExpanded)
- Polymer.dom(expandButton).classList.add('button-expanded');
- } else {
- td.style.paddingLeft = INDENT_SPACE_NO_BUTTON + 'px';
- }
- }
-
- if (value !== undefined)
- Polymer.dom(td).appendChild(
- tr.ui.b.asHTMLOrTextNode(value, this.ownerDocument));
-
- i += colSpan;
- }
+ lastAddedRow = htmlNode;
+ if (!rowInfo.isExpanded)
+ continue;
- var isSelectable = tableSection === this.$.body;
- var isExpandable = rowInfo.userRow[this.subRowsPropertyName_] &&
- rowInfo.userRow[this.subRowsPropertyName_].length;
-
- if (isSelectable || isExpandable) {
- trElement.addEventListener('click', function(e) {
- e.stopPropagation();
- if (e.target.tagName == 'EXPAND-BUTTON') {
- this.setExpandedForUserRow_(
- tableSection, rowInfoMap,
- rowInfo.userRow, !rowInfo.isExpanded);
- return;
- }
+ // Append subrows now.
+ lastAddedRow = this.generateTableRowNodes_(
+ tableSection, userRow[this.subRowsPropertyName_], rowInfoMap,
+ indentation + 1, lastAddedRow, rowInfo);
+ }
+ return lastAddedRow;
+ },
+
+ getOrCreateRowInfoFor_: function(rowInfoMap, userRow, parentRowInfo) {
+ var rowInfo = undefined;
+
+ if (rowInfoMap.has(userRow)) {
+ rowInfo = rowInfoMap.get(userRow);
+ } else {
+ rowInfo = {
+ userRow: userRow,
+ htmlNode: undefined,
+ parentRowInfo: parentRowInfo
+ };
+ rowInfoMap.set(userRow, rowInfo);
+ }
- function getTD(cur) {
- if (cur === trElement)
- throw new Error('woah');
- if (cur.parentElement === trElement)
- return cur;
- return getTD(cur.parentElement);
- }
+ // Recompute isExpanded in case defaultExpansionStateCallback_ has
+ // changed.
+ rowInfo.isExpanded = this.getExpandedForUserRow_(userRow);
- // If the row/cell can be selected and it's not selected yet,
- // select it.
- if (isSelectable && this.selectionMode_ !== SelectionMode.NONE) {
- var shouldSelect = false;
- var columnIndex = getTD(e.target).columnIndex;
- switch (this.selectionMode_) {
- case SelectionMode.ROW:
- shouldSelect = this.selectedTableRowInfo_ !== rowInfo;
- break;
-
- case SelectionMode.CELL:
- if (this.doesColumnIndexSupportSelection(columnIndex)) {
- shouldSelect = this.selectedTableRowInfo_ !== rowInfo ||
- this.selectedColumnIndex_ !== columnIndex;
- }
- break;
-
- default:
- throw new Error('Invalid selection mode ' +
- this.selectionMode_);
- }
- if (shouldSelect) {
- this.didTableRowInfoGetClicked_(rowInfo, columnIndex);
- return;
- }
- }
+ return rowInfo;
+ },
- // Otherwise, if the row is expandable, expand/collapse it.
- if (isExpandable) {
- this.setExpandedForUserRow_(tableSection, rowInfoMap,
- rowInfo.userRow, !rowInfo.isExpanded);
- }
- }.bind(this));
- }
+ customizeTableRow_: function(userRow, trElement) {
+ if (!this.customizeTableRowCallback_)
+ return;
+ this.customizeTableRowCallback_(userRow, trElement);
+ },
+ getHTMLNodeForRowInfo_: function(tableSection, rowInfo,
+ rowInfoMap, indentation) {
+ if (rowInfo.htmlNode) {
+ this.customizeTableRow_(rowInfo.userRow, rowInfo.htmlNode);
return rowInfo.htmlNode;
- },
-
- removeSubNodes_: function(tableSection, rowInfo, rowInfoMap) {
- if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
- return;
- for (var i = 0;
- i < rowInfo.userRow[this.subRowsPropertyName_].length; i++) {
- var subRow = rowInfo.userRow[this.subRowsPropertyName_][i];
- var subRowInfo = rowInfoMap.get(subRow);
- if (!subRowInfo)
- continue;
-
- var subNode = subRowInfo.htmlNode;
- if (subNode && Polymer.dom(subNode).parentNode === tableSection) {
- Polymer.dom(tableSection).removeChild(subNode);
- this.removeSubNodes_(tableSection, subRowInfo, rowInfoMap);
- }
- }
- },
-
- scheduleRebuildHeaders_: function() {
- this.headerDirty_ = true;
- this.scheduleRebuild_();
- },
-
- scheduleRebuildBody_: function() {
- this.bodyDirty_ = true;
- this.scheduleRebuild_();
- },
-
- scheduleRebuildFooter_: function() {
- this.footerDirty_ = true;
- this.scheduleRebuild_();
- },
+ }
- scheduleRebuild_: function() {
- if (this.rebuildPending_)
- return;
- this.rebuildPending_ = true;
- setTimeout(function() {
- this.rebuildPending_ = false;
- this.rebuild();
- }.bind(this), 0);
- },
-
- rebuildIfNeeded_: function() {
- this.rebuild();
- },
+ var INDENT_SPACE = indentation * 16;
+ var INDENT_SPACE_NO_BUTTON = indentation * 16 + BASIC_INDENTATION;
+ var trElement = this.ownerDocument.createElement('tr');
+ rowInfo.htmlNode = trElement;
+ rowInfo.indentation = indentation;
+ trElement.rowInfo = rowInfo;
+ this.customizeTableRow_(rowInfo.userRow, trElement);
+
+ for (var i = 0; i < this.tableColumns_.length;) {
+ var td = this.appendNewElement_(trElement, 'td');
+ td.columnIndex = i;
+
+ var column = this.tableColumns_[i];
+ var value = column.value(rowInfo.userRow);
+ var colSpan = column.colSpan ? column.colSpan : 1;
+ td.style.colSpan = colSpan;
+
+ switch (column.align) {
+ case undefined:
+ case ColumnAlignment.LEFT:
+ break;
- rebuild: function() {
- var wasBodyOrHeaderDirty = this.headerDirty_ || this.bodyDirty_;
+ case ColumnAlignment.RIGHT:
+ td.style.textAlign = 'right';
+ break;
- if (this.headerDirty_) {
- this.generateHeaderColumns_();
- this.headerDirty_ = false;
- }
- if (this.bodyDirty_) {
- Polymer.dom(this.$.body).textContent = '';
- this.generateTableRowNodes_(
- this.$.body,
- this.tableRows_, this.tableRowsInfo_, 0,
- undefined, undefined);
- if (this.tableRows_.length === 0 && this.emptyValue_ !== undefined) {
- var trElement = this.ownerDocument.createElement('tr');
- Polymer.dom(this.$.body).appendChild(trElement);
- Polymer.dom(trElement).classList.add('empty-row');
- var td = this.ownerDocument.createElement('td');
- Polymer.dom(trElement).appendChild(td);
- td.colSpan = this.tableColumns_.length;
- var emptyValue = this.emptyValue_;
- Polymer.dom(td).appendChild(
- tr.ui.b.asHTMLOrTextNode(emptyValue, this.ownerDocument));
- }
- this.bodyDirty_ = false;
+ default:
+ throw new Error('Invalid alignment of column at index=' + i +
+ ': ' + column.align);
}
- if (wasBodyOrHeaderDirty)
- this.applySizes_();
-
- if (this.footerDirty_) {
- Polymer.dom(this.$.foot).textContent = '';
- this.generateTableRowNodes_(
- this.$.foot,
- this.tableFooterRows_, this.tableFooterRowsInfo_, 0,
- undefined, undefined);
- if (this.tableFooterRowsInfo_.length) {
- Polymer.dom(this.$.body).classList.add('has-footer');
+ if (this.doesColumnIndexSupportSelection(i))
+ Polymer.dom(td).classList.add('supports-selection');
+
+ if (this.columnsWithExpandButtons_.indexOf(i) != -1) {
+ if (rowInfo.userRow[this.subRowsPropertyName_] &&
+ rowInfo.userRow[this.subRowsPropertyName_].length > 0) {
+ td.style.paddingLeft = INDENT_SPACE + 'px';
+ var expandButton = this.appendNewElement_(td,
+ 'expand-button');
+ Polymer.dom(expandButton).textContent = RIGHT_ARROW;
+ if (rowInfo.isExpanded)
+ Polymer.dom(expandButton).classList.add('button-expanded');
} else {
- Polymer.dom(this.$.body).classList.remove('has-footer');
+ td.style.paddingLeft = INDENT_SPACE_NO_BUTTON + 'px';
}
- this.footerDirty_ = false;
}
- },
-
- appendNewElement_: function(parent, tagName) {
- var element = parent.ownerDocument.createElement(tagName);
- Polymer.dom(parent).appendChild(element);
- return element;
- },
-
- getExpandedForTableRow: function(userRow) {
- this.rebuildIfNeeded_();
- var rowInfo = this.tableRowsInfo_.get(userRow);
- if (rowInfo === undefined)
- throw new Error('Row has not been seen, must expand its parents');
- return rowInfo.isExpanded;
- },
-
- getExpandedForUserRow_: function(userRow) {
- if (userRow[this.subRowsPropertyName_] === undefined)
- return false;
- if (userRow[this.subRowsPropertyName_].length === 0)
- return false;
- if (userRow.isExpanded)
- return true;
- if (userRow.isExpanded === false)
- return false;
-
- var rowInfo = this.tableRowsInfo_.get(userRow);
- if (rowInfo && rowInfo.isExpanded)
- return true;
-
- if (this.defaultExpansionStateCallback_ === undefined)
- return false;
-
- var parentUserRow = undefined;
- if (rowInfo && rowInfo.parentRowInfo)
- parentUserRow = rowInfo.parentRowInfo.userRow;
-
- return this.defaultExpansionStateCallback_(
- userRow, parentUserRow);
- },
-
- setExpandedForTableRow: function(userRow, expanded) {
- this.rebuildIfNeeded_();
- var rowInfo = this.tableRowsInfo_.get(userRow);
- if (rowInfo === undefined)
- throw new Error('Row has not been seen, must expand its parents');
- return this.setExpandedForUserRow_(this.$.body, this.tableRowsInfo_,
- userRow, expanded);
- },
-
- setExpandedForUserRow_: function(tableSection, rowInfoMap,
- userRow, expanded) {
- this.rebuildIfNeeded_();
-
- var rowInfo = rowInfoMap.get(userRow);
- if (rowInfo === undefined)
- throw new Error('Row has not been seen, must expand its parents');
-
- rowInfo.isExpanded = !!expanded;
- // If no node, then nothing further needs doing.
- if (rowInfo.htmlNode === undefined)
- return;
- // If its detached, then nothing needs doing.
- if (rowInfo.htmlNode.parentElement !== tableSection)
- return;
-
- // Otherwise, rebuild.
- var expandButton = Polymer.dom(rowInfo.htmlNode)
- .querySelector('expand-button');
- if (rowInfo.isExpanded) {
- Polymer.dom(expandButton).classList.add('button-expanded');
- var lastAddedRow = rowInfo.htmlNode;
- if (rowInfo.userRow[this.subRowsPropertyName_]) {
- this.generateTableRowNodes_(
- tableSection,
- rowInfo.userRow[this.subRowsPropertyName_], rowInfoMap,
- rowInfo.indentation + 1,
- lastAddedRow, rowInfo);
- }
- } else {
- Polymer.dom(expandButton).classList.remove('button-expanded');
- this.removeSubNodes_(tableSection, rowInfo, rowInfoMap);
+ if (value !== undefined) {
+ Polymer.dom(td).appendChild(
+ tr.ui.b.asHTMLOrTextNode(value, this.ownerDocument));
}
- this.maybeUpdateSelectedRow_();
- },
+ i += colSpan;
+ }
- get selectionMode() {
- return this.selectionMode_;
- },
+ var isSelectable = tableSection === this.$.body;
+ var isExpandable = rowInfo.userRow[this.subRowsPropertyName_] &&
+ rowInfo.userRow[this.subRowsPropertyName_].length;
+
+ if (isSelectable || isExpandable) {
+ trElement.addEventListener('click', function(e) {
+ e.stopPropagation();
+ if (e.target.tagName == 'EXPAND-BUTTON') {
+ this.setExpandedForUserRow_(
+ tableSection, rowInfoMap,
+ rowInfo.userRow, !rowInfo.isExpanded);
+ return;
+ }
- set selectionMode(selectionMode) {
- if (!tr.b.dictionaryContainsValue(SelectionMode, selectionMode))
- throw new Error('Invalid selection mode ' + selectionMode);
- this.rebuildIfNeeded_();
- this.selectionMode_ = selectionMode;
- this.didSelectionStateChange_();
- },
+ function getTD(cur) {
+ if (cur === trElement)
+ throw new Error('woah');
+ if (cur.parentElement === trElement)
+ return cur;
+ return getTD(cur.parentElement);
+ }
- get rowHighlightStyle() {
- return this.rowHighlightStyle_;
- },
-
- set rowHighlightStyle(rowHighlightStyle) {
- if (!tr.b.dictionaryContainsValue(HighlightStyle, rowHighlightStyle))
- throw new Error('Invalid row highlight style ' + rowHighlightStyle);
- this.rebuildIfNeeded_();
- this.rowHighlightStyle_ = rowHighlightStyle;
- this.didSelectionStateChange_();
- },
-
- get resolvedRowHighlightStyle() {
- if (this.rowHighlightStyle_ !== HighlightStyle.DEFAULT)
- return this.rowHighlightStyle_;
- switch (this.selectionMode_) {
- case SelectionMode.NONE:
- return HighlightStyle.NONE;
- case SelectionMode.ROW:
- return HighlightStyle.DARK;
- case SelectionMode.CELL:
- return HighlightStyle.LIGHT;
- default:
- throw new Error('Invalid selection mode ' + selectionMode);
- }
- },
+ // If the row/cell can be selected and it's not selected yet,
+ // select it.
+ if (isSelectable && this.selectionMode_ !== SelectionMode.NONE) {
+ var shouldSelect = false;
+ var columnIndex = getTD(e.target).columnIndex;
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ shouldSelect = this.selectedTableRowInfo_ !== rowInfo;
+ break;
+
+ case SelectionMode.CELL:
+ if (this.doesColumnIndexSupportSelection(columnIndex)) {
+ shouldSelect = this.selectedTableRowInfo_ !== rowInfo ||
+ this.selectedColumnIndex_ !== columnIndex;
+ }
+ break;
+
+ default:
+ throw new Error('Invalid selection mode ' +
+ this.selectionMode_);
+ }
+ if (shouldSelect) {
+ this.didTableRowInfoGetClicked_(rowInfo, columnIndex);
+ return;
+ }
+ }
- get cellHighlightStyle() {
- return this.cellHighlightStyle_;
- },
-
- set cellHighlightStyle(cellHighlightStyle) {
- if (!tr.b.dictionaryContainsValue(HighlightStyle, cellHighlightStyle))
- throw new Error('Invalid cell highlight style ' + cellHighlightStyle);
- this.rebuildIfNeeded_();
- this.cellHighlightStyle_ = cellHighlightStyle;
- this.didSelectionStateChange_();
- },
-
- get resolvedCellHighlightStyle() {
- if (this.cellHighlightStyle_ !== HighlightStyle.DEFAULT)
- return this.cellHighlightStyle_;
- switch (this.selectionMode_) {
- case SelectionMode.NONE:
- case SelectionMode.ROW:
- return HighlightStyle.NONE;
- case SelectionMode.CELL:
- return HighlightStyle.DARK;
- default:
- throw new Error('Invalid selection mode ' + selectionMode);
- }
- },
+ // Otherwise, if the row is expandable, expand/collapse it.
+ if (isExpandable) {
+ this.setExpandedForUserRow_(tableSection, rowInfoMap,
+ rowInfo.userRow, !rowInfo.isExpanded);
+ }
+ }.bind(this));
+ }
- setHighlightStyle_: function(highlightAttribute, resolvedHighlightStyle) {
- switch (resolvedHighlightStyle) {
- case HighlightStyle.NONE:
- Polymer.dom(this.$.body).removeAttribute(highlightAttribute);
- break;
- case HighlightStyle.LIGHT:
- Polymer.dom(this.$.body).setAttribute(highlightAttribute, 'light');
- break;
- case HighlightStyle.DARK:
- Polymer.dom(this.$.body).setAttribute(highlightAttribute, 'dark');
- break;
- default:
- throw new Error('Invalid resolved highlight style ' +
- resolvedHighlightStyle);
+ return rowInfo.htmlNode;
+ },
+
+ removeSubNodes_: function(tableSection, rowInfo, rowInfoMap) {
+ if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
+ return;
+ for (var i = 0;
+ i < rowInfo.userRow[this.subRowsPropertyName_].length; i++) {
+ var subRow = rowInfo.userRow[this.subRowsPropertyName_][i];
+ var subRowInfo = rowInfoMap.get(subRow);
+ if (!subRowInfo)
+ continue;
+
+ var subNode = subRowInfo.htmlNode;
+ if (subNode && Polymer.dom(subNode).parentNode === tableSection) {
+ Polymer.dom(tableSection).removeChild(subNode);
+ this.removeSubNodes_(tableSection, subRowInfo, rowInfoMap);
}
- },
-
- didSelectionStateChange_: function() {
- this.setHighlightStyle_('row-highlight-style',
- this.resolvedRowHighlightStyle);
- this.setHighlightStyle_('cell-highlight-style',
- this.resolvedCellHighlightStyle);
-
- for (var i = 0; i < this.$.body.children.length; i++)
- this.updateTabIndexForTableRowNode_(this.$.body.children[i]);
- this.maybeUpdateSelectedRow_();
- },
+ }
+ },
+
+ scheduleRebuildHeaders_: function() {
+ this.headerDirty_ = true;
+ this.scheduleRebuild_();
+ },
+
+ scheduleRebuildBody_: function() {
+ this.bodyDirty_ = true;
+ this.scheduleRebuild_();
+ },
+
+ scheduleRebuildFooter_: function() {
+ this.footerDirty_ = true;
+ this.scheduleRebuild_();
+ },
+
+ scheduleRebuild_: function() {
+ if (this.rebuildPending_)
+ return;
+ this.rebuildPending_ = true;
+ setTimeout(function() {
+ this.rebuildPending_ = false;
+ this.rebuild();
+ }.bind(this), 0);
+ },
- maybeUpdateSelectedRow_: function() {
- if (this.selectedTableRowInfo_ === undefined)
- return;
+ rebuildIfNeeded_: function() {
+ this.rebuild();
+ },
- // Selection may be off.
- if (this.selectionMode_ === SelectionMode.NONE) {
- this.removeSelectedState_();
- this.selectedTableRowInfo_ = undefined;
- return;
- }
+ rebuild: function() {
+ var wasBodyOrHeaderDirty = this.headerDirty_ || this.bodyDirty_;
- // selectedUserRow may not be visible
- function isVisible(rowInfo) {
- if (!rowInfo.htmlNode)
- return false;
- return !!rowInfo.htmlNode.parentElement;
- }
- if (isVisible(this.selectedTableRowInfo_)) {
- this.updateSelectedState_();
- return;
+ if (this.headerDirty_) {
+ this.generateHeaderColumns_();
+ this.headerDirty_ = false;
+ }
+ if (this.bodyDirty_) {
+ Polymer.dom(this.$.cols).textContent = '';
+ this.generateTableColNodes_();
+ Polymer.dom(this.$.body).textContent = '';
+ this.generateTableRowNodes_(
+ this.$.body,
+ this.tableRows_, this.tableRowsInfo_, 0,
+ undefined, undefined);
+ if (this.tableRows_.length === 0 && this.emptyValue_ !== undefined) {
+ var trElement = this.ownerDocument.createElement('tr');
+ Polymer.dom(this.$.body).appendChild(trElement);
+ Polymer.dom(trElement).classList.add('empty-row');
+ var td = this.ownerDocument.createElement('td');
+ Polymer.dom(trElement).appendChild(td);
+ td.colSpan = this.tableColumns_.length;
+ var emptyValue = this.emptyValue_;
+ Polymer.dom(td).appendChild(
+ tr.ui.b.asHTMLOrTextNode(emptyValue, this.ownerDocument));
}
+ this.bodyDirty_ = false;
+ }
- this.removeSelectedState_();
- var curRowInfo = this.selectedTableRowInfo_;
- while (curRowInfo && !isVisible(curRowInfo))
- curRowInfo = curRowInfo.parentRowInfo;
-
- this.selectedTableRowInfo_ = curRowInfo;
- if (this.selectedTableRowInfo_)
- this.updateSelectedState_();
- },
-
- didTableRowInfoGetClicked_: function(rowInfo, columnIndex) {
- switch (this.selectionMode_) {
- case SelectionMode.NONE:
- return;
-
- case SelectionMode.CELL:
- if (!this.doesColumnIndexSupportSelection(columnIndex))
- return;
- if (this.selectedColumnIndex !== columnIndex)
- this.selectedColumnIndex = columnIndex;
- // Fall through.
-
- case SelectionMode.ROW:
- if (this.selectedTableRowInfo_ !== rowInfo)
- this.selectedTableRow = rowInfo.userRow;
- }
- },
-
- get selectedTableRow() {
- if (!this.selectedTableRowInfo_)
- return undefined;
- return this.selectedTableRowInfo_.userRow;
- },
-
- set selectedTableRow(userRow) {
- this.rebuildIfNeeded_();
- if (this.selectionMode_ === SelectionMode.NONE)
- throw new Error('Selection is off.');
-
- var rowInfo;
- if (userRow === undefined) {
- rowInfo = undefined;
+ if (wasBodyOrHeaderDirty)
+ this.applySizes_();
+
+ if (this.footerDirty_) {
+ Polymer.dom(this.$.foot).textContent = '';
+ this.generateTableRowNodes_(
+ this.$.foot,
+ this.tableFooterRows_, this.tableFooterRowsInfo_, 0,
+ undefined, undefined);
+ if (this.tableFooterRowsInfo_.length) {
+ Polymer.dom(this.$.body).classList.add('has-footer');
} else {
- rowInfo = this.tableRowsInfo_.get(userRow);
- if (!rowInfo)
- throw new Error('Row has not been seen, must expand its parents.');
+ Polymer.dom(this.$.body).classList.remove('has-footer');
}
+ this.footerDirty_ = false;
+ }
+ },
+
+ appendNewElement_: function(parent, tagName) {
+ var element = parent.ownerDocument.createElement(tagName);
+ Polymer.dom(parent).appendChild(element);
+ return element;
+ },
+
+ getExpandedForTableRow: function(userRow) {
+ this.rebuildIfNeeded_();
+ var rowInfo = this.tableRowsInfo_.get(userRow);
+ if (rowInfo === undefined)
+ throw new Error('Row has not been seen, must expand its parents');
+ return rowInfo.isExpanded;
+ },
+
+ getExpandedForUserRow_: function(userRow) {
+ if (userRow[this.subRowsPropertyName_] === undefined)
+ return false;
+ if (userRow[this.subRowsPropertyName_].length === 0)
+ return false;
+ if (userRow.isExpanded)
+ return true;
+ if (userRow.isExpanded === false)
+ return false;
- var e = this.prepareToChangeSelection_();
- this.selectedTableRowInfo_ = rowInfo;
+ var rowInfo = this.tableRowsInfo_.get(userRow);
+ if (rowInfo && rowInfo.isExpanded)
+ return true;
- if (this.selectedTableRowInfo_ === undefined) {
- this.selectedColumnIndex_ = undefined;
- this.removeSelectedState_();
- } else {
- switch (this.selectionMode_) {
- case SelectionMode.ROW:
- this.selectedColumnIndex_ = undefined;
- break;
-
- case SelectionMode.CELL:
- if (this.selectedColumnIndex_ === undefined) {
- var i = this.getFirstSelectableColumnIndex_();
- if (i == -1)
- throw new Error('Cannot find a selectable column.');
- this.selectedColumnIndex_ = i;
- }
- break;
-
- default:
- throw new Error('Invalid selection mode ' + this.selectionMode_);
- }
- this.updateSelectedState_();
+ if (this.defaultExpansionStateCallback_ === undefined)
+ return false;
+
+ var parentUserRow = undefined;
+ if (rowInfo && rowInfo.parentRowInfo)
+ parentUserRow = rowInfo.parentRowInfo.userRow;
+
+ return this.defaultExpansionStateCallback_(
+ userRow, parentUserRow);
+ },
+
+ setExpandedForTableRow: function(userRow, expanded) {
+ this.rebuildIfNeeded_();
+ var rowInfo = this.tableRowsInfo_.get(userRow);
+ if (rowInfo === undefined)
+ throw new Error('Row has not been seen, must expand its parents');
+ return this.setExpandedForUserRow_(this.$.body, this.tableRowsInfo_,
+ userRow, expanded);
+ },
+
+ setExpandedForUserRow_: function(tableSection, rowInfoMap,
+ userRow, expanded) {
+ this.rebuildIfNeeded_();
+
+ var rowInfo = rowInfoMap.get(userRow);
+ if (rowInfo === undefined)
+ throw new Error('Row has not been seen, must expand its parents');
+
+ rowInfo.isExpanded = !!expanded;
+ // If no node, then nothing further needs doing.
+ if (rowInfo.htmlNode === undefined)
+ return;
+
+ // If its detached, then nothing needs doing.
+ if (rowInfo.htmlNode.parentElement !== tableSection)
+ return;
+
+ // Otherwise, rebuild.
+ var expandButton =
+ Polymer.dom(rowInfo.htmlNode).querySelector('expand-button');
+ if (rowInfo.isExpanded) {
+ Polymer.dom(expandButton).classList.add('button-expanded');
+ var lastAddedRow = rowInfo.htmlNode;
+ if (rowInfo.userRow[this.subRowsPropertyName_]) {
+ this.generateTableRowNodes_(
+ tableSection,
+ rowInfo.userRow[this.subRowsPropertyName_], rowInfoMap,
+ rowInfo.indentation + 1,
+ lastAddedRow, rowInfo);
}
+ } else {
+ Polymer.dom(expandButton).classList.remove('button-expanded');
+ this.removeSubNodes_(tableSection, rowInfo, rowInfoMap);
+ }
- this.dispatchEvent(e);
- },
+ this.maybeUpdateSelectedRow_();
+ },
+
+ get selectionMode() {
+ return this.selectionMode_;
+ },
+
+ set selectionMode(selectionMode) {
+ if (!tr.b.dictionaryContainsValue(SelectionMode, selectionMode))
+ throw new Error('Invalid selection mode ' + selectionMode);
+ this.rebuildIfNeeded_();
+ this.selectionMode_ = selectionMode;
+ this.didSelectionStateChange_();
+ },
+
+ get rowHighlightStyle() {
+ return this.rowHighlightStyle_;
+ },
+
+ set rowHighlightStyle(rowHighlightStyle) {
+ if (!tr.b.dictionaryContainsValue(HighlightStyle, rowHighlightStyle))
+ throw new Error('Invalid row highlight style ' + rowHighlightStyle);
+ this.rebuildIfNeeded_();
+ this.rowHighlightStyle_ = rowHighlightStyle;
+ this.didSelectionStateChange_();
+ },
+
+ get resolvedRowHighlightStyle() {
+ if (this.rowHighlightStyle_ !== HighlightStyle.DEFAULT)
+ return this.rowHighlightStyle_;
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
+ return HighlightStyle.NONE;
+ case SelectionMode.ROW:
+ return HighlightStyle.DARK;
+ case SelectionMode.CELL:
+ return HighlightStyle.LIGHT;
+ default:
+ throw new Error('Invalid selection mode ' + selectionMode);
+ }
+ },
+
+ get cellHighlightStyle() {
+ return this.cellHighlightStyle_;
+ },
+
+ set cellHighlightStyle(cellHighlightStyle) {
+ if (!tr.b.dictionaryContainsValue(HighlightStyle, cellHighlightStyle))
+ throw new Error('Invalid cell highlight style ' + cellHighlightStyle);
+ this.rebuildIfNeeded_();
+ this.cellHighlightStyle_ = cellHighlightStyle;
+ this.didSelectionStateChange_();
+ },
+
+ get resolvedCellHighlightStyle() {
+ if (this.cellHighlightStyle_ !== HighlightStyle.DEFAULT)
+ return this.cellHighlightStyle_;
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
+ case SelectionMode.ROW:
+ return HighlightStyle.NONE;
+ case SelectionMode.CELL:
+ return HighlightStyle.DARK;
+ default:
+ throw new Error('Invalid selection mode ' + selectionMode);
+ }
+ },
+
+ setHighlightStyle_: function(highlightAttribute, resolvedHighlightStyle) {
+ switch (resolvedHighlightStyle) {
+ case HighlightStyle.NONE:
+ Polymer.dom(this.$.body).removeAttribute(highlightAttribute);
+ break;
+ case HighlightStyle.LIGHT:
+ Polymer.dom(this.$.body).setAttribute(highlightAttribute, 'light');
+ break;
+ case HighlightStyle.DARK:
+ Polymer.dom(this.$.body).setAttribute(highlightAttribute, 'dark');
+ break;
+ default:
+ throw new Error('Invalid resolved highlight style ' +
+ resolvedHighlightStyle);
+ }
+ },
- updateTabIndexForTableRowNode_: function(row) {
- if (this.selectionMode_ === SelectionMode.ROW)
- row.tabIndex = 0;
- else
- Polymer.dom(row).removeAttribute('tabIndex');
+ didSelectionStateChange_: function() {
+ this.setHighlightStyle_('row-highlight-style',
+ this.resolvedRowHighlightStyle);
+ this.setHighlightStyle_('cell-highlight-style',
+ this.resolvedCellHighlightStyle);
- var enableCellTab = this.selectionMode_ === SelectionMode.CELL;
- for (var i = 0; i < this.tableColumns_.length; i++) {
- var cell = row.children[i];
- if (enableCellTab && this.doesColumnIndexSupportSelection(i))
- cell.tabIndex = 0;
- else
- Polymer.dom(cell).removeAttribute('tabIndex');
- }
- },
+ for (var i = 0; i < Polymer.dom(this.$.body).children.length; i++) {
+ this.updateTabIndexForTableRowNode_(
+ Polymer.dom(this.$.body).children[i]);
+ }
+ this.maybeUpdateSelectedRow_();
+ },
- prepareToChangeSelection_: function() {
- var e = new tr.b.Event('selection-changed');
- var previousSelectedRowInfo = this.selectedTableRowInfo_;
- if (previousSelectedRowInfo)
- e.previousSelectedTableRow = previousSelectedRowInfo.userRow;
- else
- e.previousSelectedTableRow = undefined;
+ maybeUpdateSelectedRow_: function() {
+ if (this.selectedTableRowInfo_ === undefined)
+ return;
+ // Selection may be off.
+ if (this.selectionMode_ === SelectionMode.NONE) {
this.removeSelectedState_();
+ this.selectedTableRowInfo_ = undefined;
+ return;
+ }
- return e;
- },
+ // selectedUserRow may not be visible
+ function isVisible(rowInfo) {
+ if (!rowInfo.htmlNode)
+ return false;
+ return !!rowInfo.htmlNode.parentElement;
+ }
+ if (isVisible(this.selectedTableRowInfo_)) {
+ this.updateSelectedState_();
+ return;
+ }
- removeSelectedState_: function() {
- this.setSelectedState_(false);
- },
+ this.removeSelectedState_();
+ var curRowInfo = this.selectedTableRowInfo_;
+ while (curRowInfo && !isVisible(curRowInfo))
+ curRowInfo = curRowInfo.parentRowInfo;
- updateSelectedState_: function() {
- this.setSelectedState_(true);
- },
+ this.selectedTableRowInfo_ = curRowInfo;
+ if (this.selectedTableRowInfo_)
+ this.updateSelectedState_();
+ },
- setSelectedState_: function(select) {
- if (this.selectedTableRowInfo_ === undefined)
+ didTableRowInfoGetClicked_: function(rowInfo, columnIndex) {
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
return;
- // Row selection.
- var rowNode = this.selectedTableRowInfo_.htmlNode;
- if (select)
- Polymer.dom(rowNode).setAttribute('selected', true);
- else
- Polymer.dom(rowNode).removeAttribute('selected');
-
- // Cell selection (if applicable).
- var cellNode = rowNode.children[this.selectedColumnIndex_];
- if (!cellNode)
- return;
- if (select)
- Polymer.dom(cellNode).setAttribute('selected', true);
- else
- Polymer.dom(cellNode).removeAttribute('selected');
- },
+ case SelectionMode.CELL:
+ if (!this.doesColumnIndexSupportSelection(columnIndex))
+ return;
+ if (this.selectedColumnIndex !== columnIndex)
+ this.selectedColumnIndex = columnIndex;
+ // Fall through.
- doesColumnIndexSupportSelection: function(columnIndex) {
- var columnInfo = this.tableColumns_[columnIndex];
- var scs = columnInfo.supportsCellSelection;
- if (scs === false)
- return false;
- return true;
- },
+ case SelectionMode.ROW:
+ if (this.selectedTableRowInfo_ !== rowInfo)
+ this.selectedTableRow = rowInfo.userRow;
+ }
+ },
+
+ /**
+ * If the selectionMode is CELL and a cell is selected,
+ * return an object containing the row, column, and value of the selected
+ * cell.
+ *
+ * @return {undefined|!Object}
+ */
+ get selectedCell() {
+ var row = this.selectedTableRow;
+ var columnIndex = this.selectedColumnIndex;
+ if (row === undefined || columnIndex === undefined ||
+ this.tableColumns_.length <= columnIndex)
+ return undefined;
+ var column = this.tableColumns_[columnIndex];
+ return {
+ row: row,
+ column: column,
+ value: column.value(row)
+ };
+ },
+
+ /**
+ * If a selectable column is selected, return the object describing the
+ * selected column.
+ *
+ * Columns with |selectable:true| can be selected independently of rows
+ * and cells. So it is possible to select column 0 and cell [0,0], or
+ * column 1 and cell [0,0], for example. See |selectedCell| for how to
+ * access the selected cell when the selectionMode is CELL.
+ *
+ * |selectedTableColumn| is entirely independent of |selectedColumnIndex|.
+ * When the table selectionMode is CELL, use |selectedTableRow| and
+ * |selectedColumnIndex| to find the selected cell.
+ * When one or more columns have |selectable:true|, then use
+ * |selectedTableColumn| to find the selected column, which may be either
+ * the same as or different from |selectedColumnIndex|, if a cell is also
+ * selected.
+ *
+ * @return {undefined|!Object} column
+ */
+ get selectedTableColumn() {
+ for (var i = 0; i < this.headerCells_.length; i++) {
+ if (this.headerCells_[i].selected)
+ return this.tableColumns_[i];
+ }
+ return undefined;
+ },
+
+ /**
+ * See |get selectedTableColumn()|. |column| must be one of the elements
+ * of this.tableColumns.
+ *
+ * @param {!Object} column
+ */
+ set selectedTableColumn(column) {
+ if (column !== undefined) {
+ var index = this.tableColumns.indexOf(column);
+ if (index < 0)
+ throw new Error('Cannot select unknown column', column);
+
+ if (!column.selectable)
+ throw new Error('Cannot select un-selectable column', column);
+
+ var cell = this.headerCells_[index];
+ cell.selected = true;
+ }
+ var e = new tr.b.Event('selected-column-changed');
+ e.column = column;
+ e.selected = column !== undefined;
+ cell.dispatchEvent(e);
+ },
+
+ get selectedTableRow() {
+ if (!this.selectedTableRowInfo_)
+ return undefined;
+ return this.selectedTableRowInfo_.userRow;
+ },
+
+ set selectedTableRow(userRow) {
+ this.rebuildIfNeeded_();
+ if (this.selectionMode_ === SelectionMode.NONE)
+ throw new Error('Selection is off.');
+
+ var rowInfo;
+ if (userRow === undefined) {
+ rowInfo = undefined;
+ } else {
+ rowInfo = this.tableRowsInfo_.get(userRow);
+ if (!rowInfo)
+ throw new Error('Row has not been seen, must expand its parents.');
+ }
- getFirstSelectableColumnIndex_: function() {
- for (var i = 0; i < this.tableColumns_.length; i++) {
- if (this.doesColumnIndexSupportSelection(i))
- return i;
- }
- return -1;
- },
+ var e = this.prepareToChangeSelection_();
+ this.selectedTableRowInfo_ = rowInfo;
- getSelectableNodeGivenTableRowNode_: function(htmlNode) {
+ if (this.selectedTableRowInfo_ === undefined) {
+ this.selectedColumnIndex_ = undefined;
+ this.removeSelectedState_();
+ } else {
switch (this.selectionMode_) {
case SelectionMode.ROW:
- return htmlNode;
+ this.selectedColumnIndex_ = undefined;
+ break;
case SelectionMode.CELL:
- return htmlNode.children[this.selectedColumnIndex_];
+ if (this.selectedColumnIndex_ === undefined) {
+ var i = this.getFirstSelectableColumnIndex_();
+ if (i == -1)
+ throw new Error('Cannot find a selectable column.');
+ this.selectedColumnIndex_ = i;
+ }
+ break;
default:
throw new Error('Invalid selection mode ' + this.selectionMode_);
}
- },
-
- get selectedColumnIndex() {
- if (this.selectionMode_ !== SelectionMode.CELL)
- return undefined;
- return this.selectedColumnIndex_;
- },
-
- set selectedColumnIndex(selectedColumnIndex) {
- this.rebuildIfNeeded_();
- if (this.selectionMode_ === SelectionMode.NONE)
- throw new Error('Selection is off.');
- if (selectedColumnIndex < 0 ||
- selectedColumnIndex >= this.tableColumns_.length)
- throw new Error('Invalid index');
- if (!this.doesColumnIndexSupportSelection(selectedColumnIndex))
- throw new Error('Selection is not supported on this column');
-
- var e = this.prepareToChangeSelection_();
- this.selectedColumnIndex_ = selectedColumnIndex;
- if (this.selectedColumnIndex_ === undefined)
- this.selectedTableRowInfo_ = undefined;
this.updateSelectedState_();
+ }
- this.dispatchEvent(e);
- },
+ this.dispatchEvent(e);
+ },
- onKeyDown_: function(e) {
- if (this.selectionMode_ === SelectionMode.NONE)
- return;
- if (this.selectedTableRowInfo_ === undefined)
+ updateTabIndexForTableRowNode_: function(row) {
+ if (this.selectionMode_ === SelectionMode.ROW)
+ row.tabIndex = 0;
+ else
+ Polymer.dom(row).removeAttribute('tabIndex');
+
+ var enableCellTab = this.selectionMode_ === SelectionMode.CELL;
+ for (var i = 0; i < this.tableColumns_.length; i++) {
+ var cell = Polymer.dom(row).children[i];
+ if (enableCellTab && this.doesColumnIndexSupportSelection(i))
+ cell.tabIndex = 0;
+ else
+ Polymer.dom(cell).removeAttribute('tabIndex');
+ }
+ },
+
+ prepareToChangeSelection_: function() {
+ var e = new tr.b.Event('selection-changed');
+ var previousSelectedRowInfo = this.selectedTableRowInfo_;
+ if (previousSelectedRowInfo)
+ e.previousSelectedTableRow = previousSelectedRowInfo.userRow;
+ else
+ e.previousSelectedTableRow = undefined;
+
+ this.removeSelectedState_();
+
+ return e;
+ },
+
+ removeSelectedState_: function() {
+ this.setSelectedState_(false);
+ },
+
+ updateSelectedState_: function() {
+ this.setSelectedState_(true);
+ },
+
+ setSelectedState_: function(select) {
+ if (this.selectedTableRowInfo_ === undefined)
+ return;
+
+ // Row selection.
+ var rowNode = this.selectedTableRowInfo_.htmlNode;
+ if (select)
+ Polymer.dom(rowNode).setAttribute('selected', true);
+ else
+ Polymer.dom(rowNode).removeAttribute('selected');
+
+ // Cell selection (if applicable).
+ var cellNode = Polymer.dom(rowNode).children[this.selectedColumnIndex_];
+ if (!cellNode)
+ return;
+ if (select)
+ Polymer.dom(cellNode).setAttribute('selected', true);
+ else
+ Polymer.dom(cellNode).removeAttribute('selected');
+ },
+
+ doesColumnIndexSupportSelection: function(columnIndex) {
+ var columnInfo = this.tableColumns_[columnIndex];
+ var scs = columnInfo.supportsCellSelection;
+ if (scs === false)
+ return false;
+ return true;
+ },
+
+ getFirstSelectableColumnIndex_: function() {
+ for (var i = 0; i < this.tableColumns_.length; i++) {
+ if (this.doesColumnIndexSupportSelection(i))
+ return i;
+ }
+ return -1;
+ },
+
+ getSelectableNodeGivenTableRowNode_: function(htmlNode) {
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ return htmlNode;
+
+ case SelectionMode.CELL:
+ return Polymer.dom(htmlNode).children[this.selectedColumnIndex_];
+
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
+ }
+ },
+
+ get selectedColumnIndex() {
+ if (this.selectionMode_ !== SelectionMode.CELL)
+ return undefined;
+ return this.selectedColumnIndex_;
+ },
+
+ set selectedColumnIndex(selectedColumnIndex) {
+ this.rebuildIfNeeded_();
+ if (this.selectionMode_ === SelectionMode.NONE)
+ throw new Error('Selection is off.');
+ if (selectedColumnIndex < 0 ||
+ selectedColumnIndex >= this.tableColumns_.length)
+ throw new Error('Invalid index');
+ if (!this.doesColumnIndexSupportSelection(selectedColumnIndex))
+ throw new Error('Selection is not supported on this column');
+
+ var e = this.prepareToChangeSelection_();
+ this.selectedColumnIndex_ = selectedColumnIndex;
+ if (this.selectedColumnIndex_ === undefined)
+ this.selectedTableRowInfo_ = undefined;
+ this.updateSelectedState_();
+
+ this.dispatchEvent(e);
+ },
+
+ onKeyDown_: function(e) {
+ if (this.selectionMode_ === SelectionMode.NONE)
+ return;
+ if (this.selectedTableRowInfo_ === undefined)
+ return;
+
+ var code_to_command_names = {
+ 13: 'ENTER',
+ 37: 'ARROW_LEFT',
+ 38: 'ARROW_UP',
+ 39: 'ARROW_RIGHT',
+ 40: 'ARROW_DOWN'
+ };
+ var cmdName = code_to_command_names[e.keyCode];
+ if (cmdName === undefined)
+ return;
+
+ e.stopPropagation();
+ e.preventDefault();
+ this.performKeyCommand_(cmdName);
+ },
+
+ performKeyCommand_: function(cmdName) {
+ this.rebuildIfNeeded_();
+
+ var rowInfo = this.selectedTableRowInfo_;
+ var htmlNode = rowInfo.htmlNode;
+ if (cmdName === 'ARROW_UP') {
+ var prev = htmlNode.previousElementSibling;
+ if (prev) {
+ tr.ui.b.scrollIntoViewIfNeeded(prev);
+ this.selectedTableRow = prev.rowInfo.userRow;
+ this.focusSelected_();
return;
+ }
+ return;
+ }
- var code_to_command_names = {
- 13: 'ENTER',
- 37: 'ARROW_LEFT',
- 38: 'ARROW_UP',
- 39: 'ARROW_RIGHT',
- 40: 'ARROW_DOWN'
- };
- var cmdName = code_to_command_names[e.keyCode];
- if (cmdName === undefined)
+ if (cmdName === 'ARROW_DOWN') {
+ var next = htmlNode.nextElementSibling;
+ if (next) {
+ tr.ui.b.scrollIntoViewIfNeeded(next);
+ this.selectedTableRow = next.rowInfo.userRow;
+ this.focusSelected_();
return;
+ }
+ return;
+ }
+
+ if (cmdName === 'ARROW_RIGHT') {
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
+ return;
+ if (rowInfo.userRow[this.subRowsPropertyName_].length === 0)
+ return;
- e.stopPropagation();
- e.preventDefault();
- this.performKeyCommand_(cmdName);
- },
-
- performKeyCommand_: function(cmdName) {
- this.rebuildIfNeeded_();
-
- var rowInfo = this.selectedTableRowInfo_;
- var htmlNode = rowInfo.htmlNode;
- if (cmdName === 'ARROW_UP') {
- var prev = htmlNode.previousElementSibling;
- if (prev) {
- tr.ui.b.scrollIntoViewIfNeeded(prev);
- this.selectedTableRow = prev.rowInfo.userRow;
+ if (!rowInfo.isExpanded)
+ this.setExpandedForTableRow(rowInfo.userRow, true);
+ this.selectedTableRow =
+ htmlNode.nextElementSibling.rowInfo.userRow;
this.focusSelected_();
return;
- }
- return;
- }
- if (cmdName === 'ARROW_DOWN') {
- var next = htmlNode.nextElementSibling;
- if (next) {
- tr.ui.b.scrollIntoViewIfNeeded(next);
- this.selectedTableRow = next.rowInfo.userRow;
+ case SelectionMode.CELL:
+ var newIndex = this.selectedColumnIndex_ + 1;
+ if (newIndex >= this.tableColumns_.length)
+ return;
+ if (!this.doesColumnIndexSupportSelection(newIndex))
+ return;
+ this.selectedColumnIndex = newIndex;
this.focusSelected_();
return;
- }
- return;
+
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
}
+ }
- if (cmdName === 'ARROW_RIGHT') {
- switch (this.selectionMode_) {
- case SelectionMode.ROW:
- if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
- return;
- if (rowInfo.userRow[this.subRowsPropertyName_].length === 0)
- return;
-
- if (!rowInfo.isExpanded)
- this.setExpandedForTableRow(rowInfo.userRow, true);
- this.selectedTableRow =
- Polymer.dom(htmlNode).nextElementSibling.rowInfo.userRow;
+ if (cmdName === 'ARROW_LEFT') {
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ if (rowInfo.isExpanded) {
+ this.setExpandedForTableRow(rowInfo.userRow, false);
this.focusSelected_();
return;
+ }
- case SelectionMode.CELL:
- var newIndex = this.selectedColumnIndex_ + 1;
- if (newIndex >= this.tableColumns_.length)
- return;
- if (!this.doesColumnIndexSupportSelection(newIndex))
- return;
- this.selectedColumnIndex = newIndex;
+ // Not expanded. Select parent...
+ var parentRowInfo = rowInfo.parentRowInfo;
+ if (parentRowInfo) {
+ this.selectedTableRow = parentRowInfo.userRow;
this.focusSelected_();
return;
+ }
+ return;
- default:
- throw new Error('Invalid selection mode ' + this.selectionMode_);
- }
- }
-
- if (cmdName === 'ARROW_LEFT') {
- switch (this.selectionMode_) {
- case SelectionMode.ROW:
- if (rowInfo.isExpanded) {
- this.setExpandedForTableRow(rowInfo.userRow, false);
- this.focusSelected_();
- return;
- }
-
- // Not expanded. Select parent...
- var parentRowInfo = rowInfo.parentRowInfo;
- if (parentRowInfo) {
- this.selectedTableRow = parentRowInfo.userRow;
- this.focusSelected_();
- return;
- }
+ case SelectionMode.CELL:
+ var newIndex = this.selectedColumnIndex_ - 1;
+ if (newIndex < 0)
return;
-
- case SelectionMode.CELL:
- var newIndex = this.selectedColumnIndex_ - 1;
- if (newIndex < 0)
- return;
- if (!this.doesColumnIndexSupportSelection(newIndex))
- return;
- this.selectedColumnIndex = newIndex;
- this.focusSelected_();
+ if (!this.doesColumnIndexSupportSelection(newIndex))
return;
+ this.selectedColumnIndex = newIndex;
+ this.focusSelected_();
+ return;
- default:
- throw new Error('Invalid selection mode ' + this.selectionMode_);
- }
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
}
+ }
- if (cmdName === 'ENTER') {
- if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
- return;
- if (rowInfo.userRow[this.subRowsPropertyName_].length === 0)
- return;
- this.setExpandedForTableRow(rowInfo.userRow, !rowInfo.isExpanded);
- this.focusSelected_();
+ if (cmdName === 'ENTER') {
+ if (rowInfo.userRow[this.subRowsPropertyName_] === undefined)
return;
- }
+ if (rowInfo.userRow[this.subRowsPropertyName_].length === 0)
+ return;
+ this.setExpandedForTableRow(rowInfo.userRow, !rowInfo.isExpanded);
+ this.focusSelected_();
+ return;
+ }
- throw new Error('Unrecognized command ' + cmdName);
- },
+ throw new Error('Unrecognized command ' + cmdName);
+ },
+
+ focusSelected_: function() {
+ if (!this.selectedTableRowInfo_)
+ return;
+ var node = this.getSelectableNodeGivenTableRowNode_(
+ this.selectedTableRowInfo_.htmlNode);
+ node.focus();
+ },
+
+ dispatchSortingChangedEvent_: function() {
+ var e = new tr.b.Event('sort-column-changed');
+ e.sortColumnIndex = this.sortColumnIndex_;
+ e.sortDescending = this.sortDescending_;
+ this.dispatchEvent(e);
+ }
+ });
+})();
+</script>
- focusSelected_: function() {
- if (!this.selectedTableRowInfo_)
- return;
- var node = this.getSelectableNodeGivenTableRowNode_(
- this.selectedTableRowInfo_.htmlNode);
- node.focus();
- },
-
- dispatchSortingChangedEvent_: function() {
- var e = new tr.b.Event('sort-column-changed');
- e.sortColumnIndex = this.sortColumnIndex_;
- e.sortDescending = this.sortDescending_;
- this.dispatchEvent(e);
- }
- });
- })();
- </script>
-
-<dom-module id='tr-ui-b-table-header-cell'>
+<dom-module id="tr-ui-b-table-header-cell">
<template>
<style>
:host {
@@ -1387,22 +1495,38 @@ tr.exportTo('tr.ui.b', function() {
flex: 0 1 auto;
}
- side-element {
+ #side {
-webkit-user-select: none;
flex: 0 0 auto;
- padding-left: 4px;
+ padding-left: 2px;
+ padding-right: 2px;
vertical-align: top;
font-size: 15px;
font-family: sans-serif;
display: inline;
line-height: 85%;
+ margin-left: 5px;
+ }
+
+ #button {
+ font-weight: bold;
+ font-size: 12px;
+ }
+
+ #title:empty, #button:empty, #side:empty {
+ display: none;
+ }
+
+ #button[selected] {
+ background: darkgrey;
}
</style>
- <span id="title"></span><side-element id="side"></side-element>
+ <span id="title"></span>
+ <button id="button"></button>
+ <button id="side"></button>
</template>
</dom-module>
-
<script>
'use strict';
@@ -1411,14 +1535,59 @@ var ColumnAlignment = tr.ui.b.TableFormat.ColumnAlignment;
Polymer({
is: 'tr-ui-b-table-header-cell',
- listeners: {
- 'tap': 'onTap_'
- },
-
created: function() {
this.tapCallback_ = undefined;
this.cellTitle_ = '';
this.align_ = undefined;
+ this.selectable_ = false;
+ this.column_ = undefined;
+ },
+
+ ready: function() {
+ this.$.button.addEventListener('click', this.onSelect_.bind(this));
+ this.$.side.addEventListener('click', this.onTap_.bind(this));
+ },
+
+ onSelect_: function() {
+ this.selected = this.$.button.getAttribute('selected') !== 'true';
+ var e = new tr.b.Event('selected-column-changed');
+ e.column = this.column;
+ e.selected = this.selected;
+ this.dispatchEvent(e);
+ },
+
+ set column(column) {
+ this.column_ = column;
+ this.selectable = column.selectable;
+ this.align = column.align;
+ this.cellTitle = column.title;
+ },
+
+ get column() {
+ return this.column_;
+ },
+
+ set selectable(selectable) {
+ this.selectable_ = selectable;
+ this.cellTitle = this.$.title.childNodes[0] ||
+ this.$.button.childNodes[0];
+ },
+
+ get selectable() {
+ return this.selectable_;
+ },
+
+ set selected(selected) {
+ if (selected)
+ this.$.button.setAttribute('selected', true);
+ else
+ this.$.button.removeAttribute('selected');
+ },
+
+ get selected() {
+ if (!this.selectable_)
+ return false;
+ return this.$.button.getAttribute('selected') === 'true';
},
set cellTitle(value) {
@@ -1428,7 +1597,12 @@ Polymer({
this.cellTitle_, this.ownerDocument);
this.$.title.innerText = '';
- Polymer.dom(this.$.title).appendChild(titleNode);
+ this.$.button.innerText = '';
+
+ if (this.selectable_)
+ this.$.button.appendChild(titleNode);
+ else
+ this.$.title.appendChild(titleNode);
},
get cellTitle() {
@@ -1458,15 +1632,16 @@ Polymer({
},
clearSideContent: function() {
- Polymer.dom(this.$.side).textContent = '';
+ this.$.side.textContent = '';
},
set sideContent(content) {
- Polymer.dom(this.$.side).textContent = content;
+ this.$.side.textContent = content;
+ this.$.side.style.display = content ? 'inline' : 'none';
},
get sideContent() {
- return Polymer.dom(this.$.side).textContent;
+ return this.$.side.textContent;
},
set tapCallback(callback) {

Powered by Google App Engine
This is Rietveld 408576698