// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview This implements a table header.
*/
cr.define('cr.ui.table', function() {
/** @const */ var TableSplitter = cr.ui.TableSplitter;
/**
* Creates a new table header.
* @param {Object=} opt_propertyBag Optional properties.
* @constructor
* @extends {HTMLDivElement}
*/
var TableHeader = cr.ui.define('div');
TableHeader.prototype = {
__proto__: HTMLDivElement.prototype,
table_: null,
/**
* Initializes the element.
*/
decorate: function() {
this.className = 'table-header';
this.headerInner_ = this.ownerDocument.createElement('div');
this.headerInner_.className = 'table-header-inner';
this.appendChild(this.headerInner_);
},
/**
* Updates table header width. Header width depends on list having a
* vertical scrollbar.
*/
updateWidth: function() {
// Header should not span over the vertical scrollbar of the list.
var list = this.table_.querySelector('list');
this.headerInner_.style.width = list.clientWidth + 'px';
},
/**
* Resizes columns.
*/
resize: function() {
var cm = this.table_.columnModel;
var headerCells = this.querySelectorAll('.table-header-cell');
if (headerCells.length != cm.size) {
this.redraw();
return;
}
this.headerInner_.textContent = '';
for (var i = 0; i < cm.size; i++) {
headerCells[i].style.width = cm.getWidth(i) + '%';
this.headerInner_.appendChild(headerCells[i]);
}
this.appendSplitters_();
},
batchCount_: 0,
startBatchUpdates: function() {
this.batchCount_++;
},
endBatchUpdates: function() {
this.batchCount_--;
if (this.batchCount_ == 0)
this.redraw();
},
/**
* Redraws table header.
*/
redraw: function() {
if (this.batchCount_ != 0)
return;
var cm = this.table_.columnModel;
var dm = this.table_.dataModel;
this.updateWidth();
this.headerInner_.textContent = '';
if (!cm || ! dm) {
return;
}
for (var i = 0; i < cm.size; i++) {
var cell = this.ownerDocument.createElement('div');
cell.style.width = cm.getWidth(i) + '%';
cell.className = 'table-header-cell';
if (dm.isSortable(cm.getId(i)))
cell.addEventListener('click',
this.createSortFunction_(i).bind(this));
cell.appendChild(this.createHeaderLabel_(i));
this.headerInner_.appendChild(cell);
}
this.appendSplitters_();
},
/**
* Appends column splitters to the table header.
*/
appendSplitters_: function() {
var cm = this.table_.columnModel;
var leftPercent = 0;
for (var i = 0; i < cm.size - 1; i++) {
leftPercent += cm.getWidth(i);
// splitter should use CSS for background image.
var splitter = new TableSplitter({table: this.table_});
splitter.columnIndex = i;
var rtl = this.ownerDocument.defaultView.getComputedStyle(this).
direction == 'rtl';
splitter.style.left = rtl ? 100 - leftPercent + '%' : leftPercent + '%';
this.headerInner_.appendChild(splitter);
}
},
/**
* Renders column header. Appends text label and sort arrow if needed.
* @param {number} index Column index.
*/
createHeaderLabel_: function(index) {
var cm = this.table_.columnModel;
var dm = this.table_.dataModel;
var labelDiv = this.ownerDocument.createElement('div');
labelDiv.className = 'table-header-label';
if (cm.isEndAlign(index))
labelDiv.style.textAlign = 'end';
var span = this.ownerDocument.createElement('span');
span.appendChild(cm.renderHeader(index, this.table_));
span.style.padding = '0';
if (dm) {
if (dm.sortStatus.field == cm.getId(index)) {
if (dm.sortStatus.direction == 'desc')
span.className = 'table-header-sort-image-desc';
else
span.className = 'table-header-sort-image-asc';
}
}
labelDiv.appendChild(span);
return labelDiv;
},
/**
* Creates sort function for given column.
* @param {number} index The index of the column to sort by.
*/
createSortFunction_: function(index) {
return function() {
this.table_.sort(index);
}.bind(this);
},
};
/**
* The table associated with the header.
* @type {cr.ui.Table}
*/
cr.defineProperty(TableHeader, 'table');
return {
TableHeader: TableHeader
};
});