list.js revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// require: array_data_model.js 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// require: list_selection_model.js 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// require: list_selection_controller.js 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// require: list_item.js 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview This implements a list control. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('cr.ui', function() { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** @const */ var ListSelectionModel = cr.ui.ListSelectionModel; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** @const */ var ListSelectionController = cr.ui.ListSelectionController; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether a mouse event is inside the element viewport. This will return 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * false if the mouseevent was generated over a border or a scrollbar. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!HTMLElement} el The element to test the event with. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Event} e The mouse event. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} Whether the mouse event was inside the viewport. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function inViewport(el, e) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rect = el.getBoundingClientRect(); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var x = e.clientX; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var y = e.clientY; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x >= rect.left + el.clientLeft && 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x < rect.left + el.clientLeft + el.clientWidth && 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y >= rect.top + el.clientTop && 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y < rect.top + el.clientTop + el.clientHeight; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getComputedStyle(el) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return el.ownerDocument.defaultView.getComputedStyle(el); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates a new list element. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Object=} opt_propertyBag Optional properties. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @extends {HTMLUListElement} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var List = cr.ui.define('list'); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) List.prototype = { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __proto__: HTMLUListElement.prototype, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Measured size of list items. This is lazily calculated the first time it 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is needed. Note that lead item is allowed to have a different height, to 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * accommodate lists where a single item at a time can be expanded to show 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * more detail. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {{height: number, marginTop: number, marginBottom:number, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * width: number, marginLeft: number, marginRight:number}} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measured_: undefined, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether or not the list is autoexpanding. If true, the list resizes 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * its height to accomadate all children. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {boolean} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) autoExpands_: false, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether or not the rows on list have various heights. If true, all the 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * rows have the same fixed height. Otherwise, each row resizes its height 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to accommodate all contents. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {boolean} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fixedHeight_: true, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether or not the list view has a blank space below the last row. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {boolean} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remainingSpace_: true, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Function used to create grid items. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {function(): !ListItem} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itemConstructor_: cr.ui.ListItem, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Function used to create grid items. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {function(): !ListItem} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get itemConstructor() { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.itemConstructor_; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set itemConstructor(func) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (func != this.itemConstructor_) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.itemConstructor_ = func; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dataModel_: null, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The data model driving the list. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {ArrayDataModel} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set dataModel(dataModel) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dataModel_ != dataModel) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.boundHandleDataModelPermuted_) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleDataModelPermuted_ = 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.handleDataModelPermuted_.bind(this); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleDataModelChange_ = 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.handleDataModelChange_.bind(this); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dataModel_) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.removeEventListener( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'permuted', 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleDataModelPermuted_); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.removeEventListener('change', 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleDataModelChange_); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_ = dataModel; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_ = {}; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel.clear(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dataModel) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel.adjustLength(dataModel.length); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dataModel_) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.addEventListener( 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'permuted', 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleDataModelPermuted_); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.addEventListener('change', 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleDataModelChange_); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get dataModel() { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.dataModel_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Cached item for measuring the default item size by measureItem(). 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {ListItem} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cachedMeasuredItem_: null, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The selection model to use. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {cr.ui.ListSelectionModel} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get selectionModel() { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.selectionModel_; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set selectionModel(sm) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var oldSm = this.selectionModel_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (oldSm == sm) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.boundHandleOnChange_) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleOnChange_ = this.handleOnChange_.bind(this); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleLeadChange_ = this.handleLeadChange_.bind(this); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (oldSm) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oldSm.removeEventListener('change', this.boundHandleOnChange_); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oldSm.removeEventListener('leadIndexChange', 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.boundHandleLeadChange_); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel_ = sm; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionController_ = this.createSelectionController(sm); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sm) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.addEventListener('change', this.boundHandleOnChange_); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.addEventListener('leadIndexChange', this.boundHandleLeadChange_); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether or not the list auto-expands. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {boolean} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get autoExpands() { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.autoExpands_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set autoExpands(autoExpands) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.autoExpands_ == autoExpands) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.autoExpands_ = autoExpands; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether or not the rows on list have various heights. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {boolean} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get fixedHeight() { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.fixedHeight_; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set fixedHeight(fixedHeight) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_ == fixedHeight) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fixedHeight_ = fixedHeight; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Convenience alias for selectionModel.selectedItem 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {*} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get selectedItem() { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dataModel) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.selectionModel.selectedIndex; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != -1) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dataModel.item(index); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set selectedItem(selectedItem) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dataModel) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.dataModel.indexOf(selectedItem); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel.selectedIndex = index; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Convenience alias for selectionModel.selectedItems 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {!Array<*>} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get selectedItems() { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var indexes = this.selectionModel.selectedIndexes; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dataModel) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return indexes.map(function(i) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dataModel.item(i); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return []; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The HTML elements representing the items. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {HTMLCollection} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get items() { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Array.prototype.filter.call(this.children, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.isItem, this); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if the child is a list item. Subclasses may override this 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to filter out certain elements. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Node} child Child of the list. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if a list item. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isItem: function(child) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child.nodeType == Node.ELEMENT_NODE && 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child != this.beforeFiller_ && child != this.afterFiller_; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) batchCount_: 0, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When making a lot of updates to the list, the code could be wrapped in 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the startBatchUpdates and finishBatchUpdates to increase performance. Be 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sure that the code will not return without calling endBatchUpdates or the 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * list will not be correctly updated. 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startBatchUpdates: function() { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.batchCount_++; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See startBatchUpdates. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) endBatchUpdates: function() { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.batchCount_--; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.batchCount_ == 0) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Initializes the element. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decorate: function() { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add fillers. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.beforeFiller_ = this.ownerDocument.createElement('div'); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.afterFiller_ = this.ownerDocument.createElement('div'); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.beforeFiller_.className = 'spacer'; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.afterFiller_.className = 'spacer'; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.textContent = ''; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(this.beforeFiller_); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(this.afterFiller_); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var length = this.dataModel ? this.dataModel.length : 0; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel = new ListSelectionModel(length); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.addEventListener('dblclick', this.handleDoubleClick_); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('mousedown', this.handlePointerDownUp_); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('mouseup', this.handlePointerDownUp_); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('keydown', this.handleKeyDown); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('focus', this.handleElementFocus_, true); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('blur', this.handleElementBlur_, true); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('scroll', this.handleScroll.bind(this)); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setAttribute('role', 'list'); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make list focusable 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.hasAttribute('tabindex')) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tabIndex = 0; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to get an unique id prefix from the id of this element or the 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nearest ancestor with an id. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element = this; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (element && !element.id) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element = element.parentElement; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (element && element.id) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.uniqueIdPrefix_ = element.id; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.uniqueIdPrefix_ = 'list'; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The next id suffix to use when giving each item an unique id. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.nextUniqueIdSuffix_ = 0; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem=} item The list item to measure. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of the given item. If the fixed height on CSS 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is set by 'px', uses that value as height. Otherwise, measures the size. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measureItemHeight_: function(item) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.measureItem(item).height; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of default item, measuring it if necessary. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getDefaultItemHeight_: function() { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getDefaultItemSize_().height; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of the item, measuring it if necessary. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemHeightByIndex_: function(index) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |this.fixedHeight_| is true, all the rows have same default height. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getDefaultItemHeight_(); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.cachedItemHeights_[index]) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.cachedItemHeights_[index]; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = this.getListItemByIndex(index); 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item) { 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var h = this.measureItemHeight_(item); 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.cachedItemHeights_[index] = h; 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return h; 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getDefaultItemHeight_(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{height: number, width: number}} The height and width 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of default item, measuring it if necessary. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getDefaultItemSize_: function() { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.measured_ || !this.measured_.height) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.measured_ = this.measureItem(); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.measured_; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates an item (dataModel.item(0)) and measures its height. The item is 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cached instead of creating a new one every time.. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem=} opt_item The list item to use to do the measuring. If 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this is not provided an item will be created based on the first value 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the model. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{height: number, marginTop: number, marginBottom:number, 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * width: number, marginLeft: number, marginRight:number}} 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The height and width of the item, taking 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * margins into account, and the top, bottom, left and right margins 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * themselves. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measureItem: function(opt_item) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dataModel || !dataModel.length) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = opt_item || this.cachedMeasuredItem_ || 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.createItem(dataModel.item(0)); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opt_item) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedMeasuredItem_ = item; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(item); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rect = item.getBoundingClientRect(); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cs = getComputedStyle(item); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mt = parseFloat(cs.marginTop); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mb = parseFloat(cs.marginBottom); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ml = parseFloat(cs.marginLeft); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mr = parseFloat(cs.marginRight); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var h = rect.height; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var w = rect.width; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mh = 0; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mv = 0; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle margin collapsing. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mt < 0 && mb < 0) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv = Math.min(mt, mb); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (mt >= 0 && mb >= 0) { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv = Math.max(mt, mb); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv = mt + mb; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h += mv; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ml < 0 && mr < 0) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mh = Math.min(ml, mr); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ml >= 0 && mr >= 0) { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mh = Math.max(ml, mr); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mh = ml + mr; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) w += mh; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opt_item) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(item); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height: Math.max(0, h), 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) marginTop: mt, marginBottom: mb, 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width: Math.max(0, w), 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) marginLeft: ml, marginRight: mr}; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Callback for the double click event. 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Event} e The mouse event object. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handleDoubleClick_: function(e) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.disabled) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var target = e.target; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target = this.getListItemAncestor(target); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.activateItemAtIndex(this.getIndexOfListItem(target)); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Callback for mousedown and mouseup events. 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Event} e The mouse event object. 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handlePointerDownUp_: function(e) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.disabled) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var target = e.target; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the target was this element we need to make sure that the user did 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not click on a border or a scrollbar. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target == this) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inViewport(target, e)) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionController_.handlePointerDownUp(e, -1); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target = this.getListItemAncestor(target); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.getIndexOfListItem(target); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionController_.handlePointerDownUp(e, index); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when an element in the list is focused. Marks the list as having 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a focused element, and dispatches an event if it didn't have focus. 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The focus event. 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleElementFocus_: function(e) { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.hasElementFocus) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.hasElementFocus = true; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when an element in the list is blurred. If focus moves outside 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the list, marks the list as no longer having focus and dispatches an 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * event. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The blur event. 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleElementBlur_: function(e) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the blur event happens we do not know who is getting focus so we 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delay this a bit until we know if the new focus node is outside the 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list. 518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // We need 51 msec delay because InlineEditableList sets focus after 519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // 50 msec. 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var list = this; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var doc = e.target.ownerDocument; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.setTimeout(function() { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var activeElement = doc.activeElement; 524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!list.contains(activeElement)) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list.hasElementFocus = false; 526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch }, 51); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the list item element containing the given element, or null if 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it doesn't belong to any list item element. 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} element The element. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The list item containing |element|, or null. 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItemAncestor: function(element) { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var container = element; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (container && container.parentNode != this) { 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container = container.parentNode; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return container; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle a keydown event. 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The keydown event. 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether the key event was handled. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleKeyDown: function(e) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.disabled) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.selectionController_.handleKeyDown(e); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle a scroll event. 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The scroll event. 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleScroll: function(e) { 5607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch requestAnimationFrame(this.redraw.bind(this)); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Callback from the selection model. We dispatch {@code change} events 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * when the selection changes. 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!cr.Event} e Event with change info. 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleOnChange_: function(ce) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ce.changes.forEach(function(change) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = this.getListItemByIndex(change.index); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (listItem) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.selected = change.selected; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (change.selected) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.setAttribute('aria-posinset', change.index + 1); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.setAttribute('aria-setsize', this.dataModel.length); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setAttribute('aria-activedescendant', listItem.id); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.removeAttribute('aria-posinset'); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.removeAttribute('aria-setsize'); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, this); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.dispatchSimpleEvent(this, 'change'); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles a change of the lead item from the selection model. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} pe The property change event. 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleLeadChange_: function(pe) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.oldValue != -1) { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((element = this.getListItemByIndex(pe.oldValue))) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.lead = false; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.newValue != -1) { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((element = this.getListItemByIndex(pe.newValue))) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.lead = true; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.oldValue != pe.newValue) { 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.scrollIndexIntoView(pe.newValue); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the lead item has a different height than other items, then we 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may run into a problem that requires a second attempt to scroll 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it into view. The first scroll attempt will trigger a redraw, 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which will clear out the list and repopulate it with new items. 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // During the redraw, the list may shrink temporarily, which if the 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lead item is the last item, will move the scrollTop up since it 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot extend beyond the end of the list. (Sadly, being scrolled to 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the bottom of the list is not "sticky.") So, we set a timeout to 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rescroll the list after this all gets sorted out. This is perhaps 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not the most elegant solution, but no others seem obvious. 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.setTimeout(function() { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollIndexIntoView(pe.newValue); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This handles data model 'permuted' event. 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this event is dispatched as a part of sort or splice. 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We need to 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - adjust the cache. 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - adjust selection. 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - redraw. (called in this.endBatchUpdates()) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * It is important that the cache adjustment happens before selection model 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * adjustments. 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The 'permuted' event. 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleDataModelPermuted_: function(e) { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCachedItems = {}; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var index in this.cachedItems_) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.permutation[index] != -1) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newIndex = e.permutation[index]; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItems[newIndex] = this.cachedItems_[index]; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItems[newIndex].listIndex = newIndex; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = newCachedItems; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCachedItemHeights = {}; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var index in this.cachedItemHeights_) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.permutation[index] != -1) { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItemHeights[e.permutation[index]] = 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[index]; 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_ = newCachedItemHeights; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.startBatchUpdates(); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sm = this.selectionModel; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.adjustLength(e.newLength); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.adjustToReordering(e.permutation); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.endBatchUpdates(); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleDataModelChange_: function(e) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[e.index]; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItemHeights_[e.index]; 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedMeasuredItem_ = null; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.index >= this.firstIndex_ && 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (e.index < this.lastIndex_ || this.remainingSpace_)) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The top position of the item inside the list. 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemTop: function(index) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) { 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index * itemHeight; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.ensureAllItemSizesInCache(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = 0; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < index; i++) { 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top += this.getItemHeightByIndex_(i); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return top; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The row of the item. May vary in the case 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of multiple columns. 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemRow: function(index) { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} row The row. 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the first item in the row. 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getFirstItemInRow: function(row) { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ensures that a given index is inside the viewport. 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item to scroll into view. 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether any scrolling was needed. 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scrollIndexIntoView: function(index) { 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dataModel || index < 0 || index >= dataModel.length) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getItemHeightByIndex_(index); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var scrollTop = this.scrollTop; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = this.getItemTop(index); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var clientHeight = this.clientHeight; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Function to adjust the tops of viewport and row. 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function scrollToAdjustTop() { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollTop = top; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Function to adjust the bottoms of viewport and row. 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function scrollToAdjustBottom() { 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cs = getComputedStyle(self); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var paddingY = parseInt(cs.paddingTop, 10) + 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parseInt(cs.paddingBottom, 10); 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top + itemHeight > scrollTop + clientHeight - paddingY) { 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollTop = top + itemHeight - clientHeight + paddingY; 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the entire of given indexed row can be shown in the viewport. 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (itemHeight <= clientHeight) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top < scrollTop) 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustTop(); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scrollTop + clientHeight < top + itemHeight) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustBottom(); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scrollTop < top) 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustTop(); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top + itemHeight < scrollTop + clientHeight) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustBottom(); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!ClientRect} The rect to use for the context menu. 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getRectForContextMenu: function() { 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(arv): Add trait support so we can share more code between trees 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and lists. 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.selectionModel.selectedIndex; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var el = this.getListItemByIndex(index); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (el) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return el.getBoundingClientRect(); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getBoundingClientRect(); 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Takes a value from the data model and finds the associated list item. 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {*} value The value in the data model that we want to get the list 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * item for. 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The first found list item or null if not found. 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItem: function(value) { 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dataModel) { 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = dataModel.indexOf(value); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getListItemByIndex(index); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the list item element at the given index. 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the list item to get. 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The found list item or null if not found. 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItemByIndex: function(index) { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.cachedItems_[index] || null; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the index of the given list item element. 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem} item The list item to get the index of. 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the list item, or -1 if not found. 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getIndexOfListItem: function(item) { 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = item.listIndex; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.cachedItems_[index] == item) { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates a new list item. 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {*} value The value to use for the item. 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!ListItem} The newly created list item. 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createItem: function(value) { 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = new this.itemConstructor_(value); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.label = value; 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.id = this.uniqueIdPrefix_ + '-' + this.nextUniqueIdSuffix_++; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof item.decorate == 'function') 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.decorate(); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates the selection controller to use internally. 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {cr.ui.ListSelectionModel} sm The underlying selection model. 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!cr.ui.ListSelectionController} The newly created selection 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * controller. 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createSelectionController: function(sm) { 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new ListSelectionController(sm); 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the heights (in pixels) of the top of the given item index within 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the list, and the height of the given item itself, accounting for the 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * possibility that the lead item may be a different height. 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index to find the top height of. 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{top: number, height: number}} The heights for the given index. 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getHeightsForIndex_: function(index) { 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getItemHeightByIndex_(index); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = this.getItemTop(index); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return {top: top, height: itemHeight}; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the index of the list item containing the given y offset (measured 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in pixels from the top) within the list. In the case of multiple columns, 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returns the first index in the row. 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} offset The y offset in pixels to get the index of. 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the list item. Returns the list size if 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given offset exceeds the height of list. 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getIndexForListOffset_: function(offset) { 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!itemHeight) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.dataModel.length; 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getFirstItemInRow(Math.floor(offset / itemHeight)); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If offset exceeds the height of list. 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastHeight = 0; 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dataModel.length) { 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var h = this.getHeightsForIndex_(this.dataModel.length - 1); 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastHeight = h.top + h.height; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lastHeight < offset) 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.dataModel.length; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Estimates index. 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var estimatedIndex = Math.min(Math.floor(offset / itemHeight), 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel.length - 1); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var isIncrementing = this.getItemTop(estimatedIndex) < offset; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Searchs the correct index. 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var heights = this.getHeightsForIndex_(estimatedIndex); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = heights.top; 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var height = heights.height; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top <= offset && offset <= (top + height)) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isIncrementing ? ++estimatedIndex : --estimatedIndex; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0 < estimatedIndex && estimatedIndex < this.dataModel.length); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return estimatedIndex; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the number of items that occupy the range of heights between the 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * top of the start item and the end offset. 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} startIndex The index of the first visible item. 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} endOffset The y offset in pixels of the end of the list. 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The number of list items visible. 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) countItemsInRange_: function(startIndex, endOffset) { 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var endIndex = this.getIndexForListOffset_(endOffset); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return endIndex - startIndex + 1; 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculates the number of items fitting in the given viewport. 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} scrollTop The scroll top position. 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} clientHeight The height of viewport. 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{first: number, length: number, last: number}} The index of 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * first item in view port, The number of items, The item past the last. 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemsInViewPort: function(scrollTop, clientHeight) { 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.autoExpands_) { 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first: 0, 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length: this.dataModel.length, 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last: this.dataModel.length}; 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var firstIndex = this.getIndexForListOffset_(scrollTop); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastIndex = this.getIndexForListOffset_(scrollTop + clientHeight); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first: firstIndex, 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length: lastIndex - firstIndex + 1, 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last: lastIndex + 1}; 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Merges list items currently existing in the list with items in the range 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [firstIndex, lastIndex). Removes or adds items if needed. 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Doesn't delete {@code this.pinnedItem_} if it is present (instead hides 9337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * it if it is out of the range). 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} firstIndex The index of first item, inclusively. 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} lastIndex The index of last item, exclusively. 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch mergeItems: function(firstIndex, lastIndex) { 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var currentIndex = firstIndex; 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function insert() { 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataItem = dataModel.item(currentIndex); 9447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var newItem = self.cachedItems_[currentIndex] || 9457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.createItem(dataItem); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newItem.listIndex = currentIndex; 9477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.cachedItems_[currentIndex] = newItem; 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.insertBefore(newItem, item); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentIndex++; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function remove() { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var next = item.nextSibling; 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item != self.pinnedItem_) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.removeChild(item); 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = next; 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var item = this.beforeFiller_.nextSibling; 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item != this.afterFiller_ && currentIndex < lastIndex;) { 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.isItem(item)) { 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = item.listIndex; 9677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (this.cachedItems_[index] != item || index < currentIndex) { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove(); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (index == currentIndex) { 9707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[currentIndex] = item; 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentIndex++; 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // index > currentIndex 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (item != this.afterFiller_) { 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.isItem(item)) 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove(); 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_) { 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.pinnedItem_.listIndex; 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_.hidden = index < firstIndex || index >= lastIndex; 9887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[index] = this.pinnedItem_; 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= lastIndex) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = this.pinnedItem_; // Insert new items before this one. 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (currentIndex < lastIndex) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(); 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ensures that all the item sizes in the list have been already cached. 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureAllItemSizesInCache: function() { 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var measuringIndexes = []; 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var isElementAppended = []; 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < this.dataModel.length; y++) { 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.cachedItemHeights_[y]) { 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measuringIndexes.push(y); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isElementAppended.push(false); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var measuringItems = []; 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds temporary elements. 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = measuringIndexes[y]; 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataItem = this.dataModel.item(index); 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = this.cachedItems_[index] || this.createItem(dataItem); 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.listIndex = index; 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |listItems| is not on the list, apppends it to the list and sets 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the flag. 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listItem.parentNode) { 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(listItem); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isElementAppended[y] = true; 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_[index] = listItem; 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measuringItems.push(listItem); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All mesurings must be placed after adding all the elements, to prevent 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // performance reducing. 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = measuringIndexes[y]; 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[index] = 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.measureItemHeight_(measuringItems[y]); 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes all the temprary elements. 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the list item has been appended above, removes it. 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isElementAppended[y]) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(measuringItems[y]); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the height of after filler in the list. 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} lastIndex The index of item past the last in viewport. 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of after filler. 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getAfterFillerHeight: function(lastIndex) { 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) { 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (this.dataModel.length - lastIndex) * itemHeight; 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var height = 0; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = lastIndex; i < this.dataModel.length; i++) 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height += this.getItemHeightByIndex_(i); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return height; 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redraws the viewport. 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redraw: function() { 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.batchCount_ != 0) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dataModel || !this.autoExpands_ && this.clientHeight == 0) { 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstIndex_ = 0; 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastIndex_ = 0; 10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.remainingSpace_ = this.clientHeight != 0; 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergeItems(0, 0, {}, {}); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the previous positions before any manipulation of elements. 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var scrollTop = this.scrollTop; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var clientHeight = this.clientHeight; 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store all the item sizes into the cache in advance, to prevent 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interleave measuring with mutating dom. 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.fixedHeight_) 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.ensureAllItemSizesInCache(); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var autoExpands = this.autoExpands_; 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemsInViewPort = this.getItemsInViewPort(scrollTop, clientHeight); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draws the hidden rows just above/below the viewport to prevent 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flashing in scroll. 10937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var firstIndex = Math.max( 10947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 0, 10957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Math.min(dataModel.length - 1, itemsInViewPort.first - 1)); 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastIndex = Math.min(itemsInViewPort.last + 1, dataModel.length); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var beforeFillerHeight = 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.autoExpands ? 0 : this.getItemTop(firstIndex); 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var afterFillerHeight = 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.autoExpands ? 0 : this.getAfterFillerHeight(lastIndex); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.beforeFiller_.style.height = beforeFillerHeight + 'px'; 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sm = this.selectionModel; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var leadIndex = sm.leadIndex; 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If the pinned item is hidden and it is not the lead item, then remove 1109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // it from cache. Note, that we restore the hidden status to false, since 1110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the item is still in cache, and may be reused. 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_ && 11127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.pinnedItem_ != this.cachedItems_[leadIndex]) { 1113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (this.pinnedItem_.hidden) { 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(this.pinnedItem_); 1115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) this.pinnedItem_.hidden = false; 1116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = undefined; 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.mergeItems(firstIndex, lastIndex); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!this.pinnedItem_ && this.cachedItems_[leadIndex] && 11237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[leadIndex].parentNode == this) { 11247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.pinnedItem_ = this.cachedItems_[leadIndex]; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.afterFiller_.style.height = afterFillerHeight + 'px'; 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set the lead or selected properties until after adding all 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // items, in case they force relayout in response to these events. 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = null; 11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (leadIndex != -1 && this.cachedItems_[leadIndex]) 11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[leadIndex].lead = true; 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = firstIndex; y < lastIndex; y++) { 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sm.getIndexSelected(y)) 11367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[y].selected = true; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (y != leadIndex) 11387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch listItem = this.cachedItems_[y]; 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstIndex_ = firstIndex; 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastIndex_ = lastIndex; 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.remainingSpace_ = itemsInViewPort.last > dataModel.length; 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mesurings must be placed after adding all the elements, to prevent 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // performance reducing. 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.fixedHeight_) { 11497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (var y = firstIndex; y < lastIndex; y++) { 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[y] = 11517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.measureItemHeight_(this.cachedItems_[y]); 11527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Restore the lead item that is present in the list but may be updated 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the data model (supposed to be used inside a batch update). Usually 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * such an item would be recreated in the redraw method. If reinsertion 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is undesirable (for instance to prevent losing focus) the item may be 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * updated and restored. Assumed the listItem relates to the same data item 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as the lead item in the begin of the batch update. 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem} leadItem Already existing lead item. 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restoreLeadItem: function(leadItem) { 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[leadItem.listIndex]; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leadItem.listIndex = this.selectionModel.leadIndex; 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = this.cachedItems_[leadItem.listIndex] = leadItem; 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Invalidates list by removing cached items. 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invalidate: function() { 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemSized_ = {}; 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redraws a single item. 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The row index to redraw. 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redrawItem: function(index) { 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= this.firstIndex_ && 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (index < this.lastIndex_ || this.remainingSpace_)) { 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[index]; 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when a list item is activated, currently only by a double click 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * event. 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the activated item. 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) activateItemAtIndex: function(index) { 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a ListItem for the leadIndex. If the item isn't present in the 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * list creates it and inserts to the list (may be invisible if it's out of 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the visible range). 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Item returned from this method won't be removed until it remains a lead 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * item or til the data model changes (unlike other items that could be 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * removed when they go out of the visible range). 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {cr.ui.ListItem} The lead item for the list. 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureLeadItemExists: function() { 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.selectionModel.leadIndex; 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < 0) 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cachedItems = this.cachedItems_ || {}; 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = cachedItems[index] || 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.createItem(this.dataModel.item(index)); 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_ != item && this.pinnedItem_ && 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_.hidden) { 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(this.pinnedItem_); 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = item; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cachedItems[index] = item; 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.listIndex = index; 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item.parentNode == this) 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.batchCount_ != 0) 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.hidden = true; 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Item will get to the right place in redraw. Choose place to insert 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reducing items reinsertion. 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index <= this.firstIndex_) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(item, this.beforeFiller_.nextSibling); 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(item, this.afterFiller_); 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 1243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) /** 1244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * Starts drag selection by reacting 'dragstart' event. 1245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * @param {Event} event Event of dragstart. 1246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) */ 1247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) startDragSelection: function(event) { 1248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) event.preventDefault(); 1249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var border = document.createElement('div'); 1250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.className = 'drag-selection-border'; 1251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var rect = this.getBoundingClientRect(); 1252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var startX = event.clientX - rect.left + this.scrollLeft; 1253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var startY = event.clientY - rect.top + this.scrollTop; 1254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.left = startX + 'px'; 1255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.top = startY + 'px'; 1256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var onMouseMove = function(event) { 1257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var inRect = this.getBoundingClientRect(); 1258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var x = event.clientX - inRect.left + this.scrollLeft; 1259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var y = event.clientY - inRect.top + this.scrollTop; 1260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.left = Math.min(startX, x) + 'px'; 1261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.top = Math.min(startY, y) + 'px'; 1262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.width = Math.abs(startX - x) + 'px'; 1263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.height = Math.abs(startY - y) + 'px'; 1264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }.bind(this); 1265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var onMouseUp = function() { 1266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) this.removeChild(border); 1267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.removeEventListener('mousemove', onMouseMove, true); 1268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.removeEventListener('mouseup', onMouseUp, true); 1269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }.bind(this); 1270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.addEventListener('mousemove', onMouseMove, true); 1271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.addEventListener('mouseup', onMouseUp, true); 1272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) this.appendChild(border); 1273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }, 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.defineProperty(List, 'disabled', cr.PropertyKind.BOOL_ATTR); 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether the list or one of its descendents has focus. This is necessary 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * because list items can contain controls that can be focused, and for some 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * purposes (e.g., styling), the list can still be conceptually focused at 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that point even though it doesn't actually have the page focus. 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) List: List 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}); 1290