• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2012 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 extends cr.ui.List for use in the table.
7 */
8
9cr.define('cr.ui.table', function() {
10  /** @const */ var List = cr.ui.List;
11  /** @const */ var TableRow = cr.ui.table.TableRow;
12  /** @const */ var ListItem = cr.ui.ListItem;
13
14  /**
15   * Creates a new table list element.
16   * @param {Object=} opt_propertyBag Optional properties.
17   * @constructor
18   * @extends {cr.ui.List}
19   */
20  var TableList = cr.ui.define('list');
21
22  TableList.prototype = {
23    __proto__: List.prototype,
24
25    table_: null,
26
27     /**
28     * Initializes the element.
29     */
30    decorate: function() {
31      List.prototype.decorate.apply(this);
32      this.className = 'list';
33    },
34
35    /**
36     * Resizes columns. Called when column width changed.
37     */
38    resize: function() {
39      if (this.updateScrollbars_())
40        List.prototype.redraw.call(this);  // Redraw items only.
41      this.resizeCells_();
42    },
43
44    /**
45     * Updates width of cells.
46     */
47    resizeCells_: function() {
48      var cm = this.table_.columnModel;
49      for (var row = this.firstElementChild; row;
50           row = row.nextElementSibling) {
51        if (row.tagName != 'LI')
52          continue;
53
54        for (var i = 0; i < cm.size; i++) {
55          row.children[i].style.width = cm.getWidth(i) + 'px';
56        }
57        row.style.width = cm.totalWidth + 'px';
58      }
59      this.afterFiller_.style.width = cm.totalWidth + 'px';
60    },
61
62    /**
63     * Redraws the viewport.
64     */
65    redraw: function() {
66      if (this.batchCount_ != 0)
67        return;
68      this.updateScrollbars_();
69
70      List.prototype.redraw.call(this);
71      this.resizeCells_();
72    },
73
74    /**
75     * Returns the height of after filler in the list.
76     * @param {number} lastIndex The index of item past the last in viewport.
77     * @return {number} The height of after filler.
78     * @override
79     */
80    getAfterFillerHeight: function(lastIndex) {
81      // If the list is empty set height to 1 to show horizontal
82      // scroll bar.
83      return lastIndex == 0 ? 1 :
84          cr.ui.List.prototype.getAfterFillerHeight.call(this, lastIndex);
85    },
86
87    /**
88     * Shows or hides vertical and horizontal scroll bars in the list.
89     * @return {boolean} True if horizontal scroll bar changed.
90     */
91    updateScrollbars_: function() {
92      var cm = this.table.columnModel;
93      var style = this.style;
94      if (!cm || cm.size == 0) {
95        if (style.overflow != 'hidden') {
96          style.overflow = 'hidden';
97          return true;
98        } else {
99          return false;
100        }
101      }
102
103      var height = this.offsetHeight;
104      var changed = false;
105      var offsetWidth = this.offsetWidth;
106      if (cm.totalWidth > offsetWidth) {
107        if (style.overflowX != 'scroll') {
108          style.overflowX = 'scroll';
109        }
110        // Once we sure there will be horizontal
111        // scrollbar calculate with this height.
112        height = this.clientHeight;
113      }
114      if (this.areAllItemsVisible_(height)) {
115        if (cm.totalWidth <= offsetWidth && style.overflowX != 'hidden') {
116          style.overflowX = 'hidden';
117        }
118        changed = this.showVerticalScrollBar_(false);
119      } else {
120        changed = this.showVerticalScrollBar_(true);
121        var x = cm.totalWidth <= this.clientWidth ? 'hidden' : 'scroll';
122        if (style.overflowX != x) {
123          style.overflowX = x;
124        }
125      }
126      return changed;
127    },
128
129    /**
130     * Shows or hides vertical scroll bar.
131     * @param {boolean} show True to show.
132     * @return {boolean} True if visibility changed.
133     */
134    showVerticalScrollBar_: function(show) {
135      var style = this.style;
136      if (show && style.overflowY == 'scroll')
137        return false;
138      if (!show && style.overflowY == 'hidden')
139        return false;
140      style.overflowY = show ? 'scroll' : 'hidden';
141      return true;
142    },
143
144    /**
145     * @param {number} visibleHeight Height in pixels.
146     * @return {boolean} True if all rows could be accomodiated in
147     *                   visibleHeight pixels.
148     */
149    areAllItemsVisible_: function(visibleHeight) {
150      if (!this.dataModel || this.dataModel.length == 0)
151        return true;
152      return this.getItemTop(this.dataModel.length) <= visibleHeight;
153    },
154
155    /**
156     * Creates a new list item.
157     * @param {*} dataItem The value to use for the item.
158     * @return {!ListItem} The newly created list item.
159     */
160    createItem: function(dataItem) {
161      return this.table_.getRenderFunction().call(null, dataItem, this.table_);
162    },
163
164    renderFunction_: function(dataItem, table) {
165      // `This` must not be accessed here, since it may be anything, especially
166      // not a pointer to this object.
167
168      var cm = table.columnModel;
169      var listItem = List.prototype.createItem.call(table.list, '');
170      listItem.className = 'table-row';
171
172      for (var i = 0; i < cm.size; i++) {
173        var cell = table.ownerDocument.createElement('div');
174        cell.style.width = cm.getWidth(i) + 'px';
175        cell.className = 'table-row-cell';
176        if (cm.isEndAlign(i))
177          cell.style.textAlign = 'end';
178        cell.appendChild(
179            cm.getRenderFunction(i).call(null, dataItem, cm.getId(i), table));
180
181        listItem.appendChild(cell);
182      }
183      listItem.style.width = cm.totalWidth + 'px';
184
185      return listItem;
186    },
187  };
188
189  /**
190   * The table associated with the list.
191   * @type {cr.ui.Table}
192   */
193  cr.defineProperty(TableList, 'table');
194
195  return {
196    TableList: TableList
197  };
198});
199