1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** 6 * @fileoverview This implements a table header. 7 */ 8 9cr.define('cr.ui.table', function() { 10 const TableSplitter = cr.ui.TableSplitter; 11 12 /** 13 * Creates a new table header. 14 * @param {Object=} opt_propertyBag Optional properties. 15 * @constructor 16 * @extends {HTMLDivElement} 17 */ 18 var TableHeader = cr.ui.define('div'); 19 20 TableHeader.prototype = { 21 __proto__: HTMLDivElement.prototype, 22 23 table_: null, 24 25 /** 26 * Initializes the element. 27 */ 28 decorate: function() { 29 this.className = 'table-header'; 30 31 this.headerInner_ = this.ownerDocument.createElement('div'); 32 this.headerInner_.className = 'table-header-inner'; 33 this.appendChild(this.headerInner_); 34 }, 35 36 /** 37 * Updates table header width. Header width depends on list having a 38 * vertical scrollbar. 39 */ 40 updateWidth: function() { 41 // Header should not span over the vertical scrollbar of the list. 42 var list = this.table_.querySelector('list'); 43 this.headerInner_.style.width = list.clientWidth + 'px'; 44 }, 45 46 /** 47 * Resizes columns. 48 */ 49 resize: function() { 50 var cm = this.table_.columnModel; 51 52 var headerCells = this.querySelectorAll('.table-header-cell'); 53 if (headerCells.length != cm.size) { 54 this.redraw(); 55 return; 56 } 57 this.headerInner_.textContent = ''; 58 for (var i = 0; i < cm.size; i++) { 59 headerCells[i].style.width = cm.getWidth(i) + '%'; 60 this.headerInner_.appendChild(headerCells[i]); 61 } 62 this.appendSplitters_(); 63 }, 64 65 /** 66 * Redraws table header. 67 */ 68 redraw: function() { 69 var cm = this.table_.columnModel; 70 var dm = this.table_.dataModel; 71 72 this.updateWidth(); 73 this.headerInner_.textContent = ''; 74 75 if (!cm || ! dm) { 76 return; 77 } 78 79 for (var i = 0; i < cm.size; i++) { 80 var cell = this.ownerDocument.createElement('div'); 81 cell.style.width = cm.getWidth(i) + '%'; 82 cell.className = 'table-header-cell'; 83 cell.addEventListener('click', this.createSortFunction_(i).bind(this)); 84 85 cell.appendChild(this.createHeaderLabel_(i)); 86 this.headerInner_.appendChild(cell); 87 } 88 this.appendSplitters_(); 89 }, 90 91 /** 92 * Appends column splitters to the table header. 93 */ 94 appendSplitters_: function() { 95 var cm = this.table_.columnModel; 96 97 var leftPercent = 0; 98 for (var i = 0; i < cm.size - 1; i++) { 99 leftPercent += cm.getWidth(i); 100 101 // splitter should use CSS for background image. 102 var splitter = new TableSplitter({table: this.table_}); 103 splitter.columnIndex = i; 104 105 var rtl = this.ownerDocument.defaultView.getComputedStyle(this). 106 direction == 'rtl'; 107 splitter.style.left = rtl ? 100 - leftPercent + '%' : leftPercent + '%'; 108 109 this.headerInner_.appendChild(splitter); 110 } 111 }, 112 113 /** 114 * Renders column header. Appends text label and sort arrow if needed. 115 * @param {number} index Column index. 116 */ 117 createHeaderLabel_: function(index) { 118 var cm = this.table_.columnModel; 119 var dm = this.table_.dataModel; 120 121 var labelDiv = this.ownerDocument.createElement('div'); 122 labelDiv.className = 'table-header-label'; 123 124 var span = this.ownerDocument.createElement('span'); 125 span.textContent = cm.getName(index); 126 var rtl = this.ownerDocument.defaultView.getComputedStyle(this). 127 direction == 'rtl'; 128 if (rtl) { 129 span.style.backgroundPosition = 'left'; 130 span.style.paddingRight= '0'; 131 } else { 132 span.style.backgroundPosition = 'right'; 133 span.style.paddingLeft= '0'; 134 } 135 if (dm) { 136 if (dm.sortStatus.field == cm.getId(index)) { 137 if (dm.sortStatus.direction == 'desc') 138 span.className = 'table-header-sort-image-desc'; 139 else 140 span.className = 'table-header-sort-image-asc'; 141 } 142 } 143 labelDiv.appendChild(span); 144 return labelDiv; 145 }, 146 147 /** 148 * Creates sort function for given column. 149 * @param {number} index The index of the column to sort by. 150 */ 151 createSortFunction_: function(index) { 152 return function() { 153 this.table_.sort(index); 154 }.bind(this); 155 }, 156 }; 157 158 /** 159 * The table associated with the header. 160 * @type {cr.ui.Table} 161 */ 162 cr.defineProperty(TableHeader, 'table'); 163 164 return { 165 TableHeader: TableHeader 166 }; 167}); 168