list.js revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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_); 3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.addEventListener('mousedown', handleMouseDown); 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) { 5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!this.contains(e.relatedTarget)) 5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.hasElementFocus = false; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the list item element containing the given element, or null if 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it doesn't belong to any list item element. 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} element The element. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The list item containing |element|, or null. 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItemAncestor: function(element) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var container = element; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (container && container.parentNode != this) { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container = container.parentNode; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return container; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle a keydown event. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The keydown event. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether the key event was handled. 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleKeyDown: function(e) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.disabled) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.selectionController_.handleKeyDown(e); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle a scroll event. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The scroll event. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleScroll: function(e) { 5507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch requestAnimationFrame(this.redraw.bind(this)); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Callback from the selection model. We dispatch {@code change} events 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * when the selection changes. 5564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {!Event} e Event with change info. 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleOnChange_: function(ce) { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ce.changes.forEach(function(change) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = this.getListItemByIndex(change.index); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (listItem) { 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.selected = change.selected; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (change.selected) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.setAttribute('aria-posinset', change.index + 1); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.setAttribute('aria-setsize', this.dataModel.length); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setAttribute('aria-activedescendant', listItem.id); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.removeAttribute('aria-posinset'); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.removeAttribute('aria-setsize'); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, this); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.dispatchSimpleEvent(this, 'change'); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles a change of the lead item from the selection model. 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} pe The property change event. 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleLeadChange_: function(pe) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.oldValue != -1) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((element = this.getListItemByIndex(pe.oldValue))) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.lead = false; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.newValue != -1) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((element = this.getListItemByIndex(pe.newValue))) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.lead = true; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.oldValue != pe.newValue) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.scrollIndexIntoView(pe.newValue); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the lead item has a different height than other items, then we 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may run into a problem that requires a second attempt to scroll 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it into view. The first scroll attempt will trigger a redraw, 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which will clear out the list and repopulate it with new items. 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // During the redraw, the list may shrink temporarily, which if the 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lead item is the last item, will move the scrollTop up since it 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot extend beyond the end of the list. (Sadly, being scrolled to 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the bottom of the list is not "sticky.") So, we set a timeout to 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rescroll the list after this all gets sorted out. This is perhaps 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not the most elegant solution, but no others seem obvious. 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.setTimeout(function() { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollIndexIntoView(pe.newValue); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This handles data model 'permuted' event. 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this event is dispatched as a part of sort or splice. 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We need to 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - adjust the cache. 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - adjust selection. 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - redraw. (called in this.endBatchUpdates()) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * It is important that the cache adjustment happens before selection model 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * adjustments. 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The 'permuted' event. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleDataModelPermuted_: function(e) { 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCachedItems = {}; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var index in this.cachedItems_) { 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.permutation[index] != -1) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newIndex = e.permutation[index]; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItems[newIndex] = this.cachedItems_[index]; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItems[newIndex].listIndex = newIndex; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = newCachedItems; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCachedItemHeights = {}; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var index in this.cachedItemHeights_) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.permutation[index] != -1) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItemHeights[e.permutation[index]] = 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[index]; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_ = newCachedItemHeights; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.startBatchUpdates(); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sm = this.selectionModel; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.adjustLength(e.newLength); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.adjustToReordering(e.permutation); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.endBatchUpdates(); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleDataModelChange_: function(e) { 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[e.index]; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItemHeights_[e.index]; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedMeasuredItem_ = null; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.index >= this.firstIndex_ && 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (e.index < this.lastIndex_ || this.remainingSpace_)) { 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The top position of the item inside the list. 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemTop: function(index) { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index * itemHeight; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.ensureAllItemSizesInCache(); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = 0; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < index; i++) { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top += this.getItemHeightByIndex_(i); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return top; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The row of the item. May vary in the case 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of multiple columns. 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemRow: function(index) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} row The row. 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the first item in the row. 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getFirstItemInRow: function(row) { 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ensures that a given index is inside the viewport. 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item to scroll into view. 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether any scrolling was needed. 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scrollIndexIntoView: function(index) { 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dataModel || index < 0 || index >= dataModel.length) 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getItemHeightByIndex_(index); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var scrollTop = this.scrollTop; 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = this.getItemTop(index); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var clientHeight = this.clientHeight; 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Function to adjust the tops of viewport and row. 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function scrollToAdjustTop() { 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollTop = top; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Function to adjust the bottoms of viewport and row. 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function scrollToAdjustBottom() { 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cs = getComputedStyle(self); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var paddingY = parseInt(cs.paddingTop, 10) + 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parseInt(cs.paddingBottom, 10); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top + itemHeight > scrollTop + clientHeight - paddingY) { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollTop = top + itemHeight - clientHeight + paddingY; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the entire of given indexed row can be shown in the viewport. 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (itemHeight <= clientHeight) { 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top < scrollTop) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustTop(); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scrollTop + clientHeight < top + itemHeight) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustBottom(); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scrollTop < top) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustTop(); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top + itemHeight < scrollTop + clientHeight) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustBottom(); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!ClientRect} The rect to use for the context menu. 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getRectForContextMenu: function() { 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(arv): Add trait support so we can share more code between trees 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and lists. 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.selectionModel.selectedIndex; 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var el = this.getListItemByIndex(index); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (el) 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return el.getBoundingClientRect(); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getBoundingClientRect(); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Takes a value from the data model and finds the associated list item. 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {*} value The value in the data model that we want to get the list 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * item for. 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The first found list item or null if not found. 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItem: function(value) { 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dataModel) { 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = dataModel.indexOf(value); 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getListItemByIndex(index); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the list item element at the given index. 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the list item to get. 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The found list item or null if not found. 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItemByIndex: function(index) { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.cachedItems_[index] || null; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the index of the given list item element. 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem} item The list item to get the index of. 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the list item, or -1 if not found. 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getIndexOfListItem: function(item) { 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = item.listIndex; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.cachedItems_[index] == item) { 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates a new list item. 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {*} value The value to use for the item. 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!ListItem} The newly created list item. 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createItem: function(value) { 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = new this.itemConstructor_(value); 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.label = value; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.id = this.uniqueIdPrefix_ + '-' + this.nextUniqueIdSuffix_++; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof item.decorate == 'function') 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.decorate(); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates the selection controller to use internally. 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {cr.ui.ListSelectionModel} sm The underlying selection model. 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!cr.ui.ListSelectionController} The newly created selection 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * controller. 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createSelectionController: function(sm) { 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new ListSelectionController(sm); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the heights (in pixels) of the top of the given item index within 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the list, and the height of the given item itself, accounting for the 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * possibility that the lead item may be a different height. 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index to find the top height of. 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{top: number, height: number}} The heights for the given index. 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getHeightsForIndex_: function(index) { 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getItemHeightByIndex_(index); 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = this.getItemTop(index); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return {top: top, height: itemHeight}; 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the index of the list item containing the given y offset (measured 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in pixels from the top) within the list. In the case of multiple columns, 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returns the first index in the row. 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} offset The y offset in pixels to get the index of. 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the list item. Returns the list size if 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given offset exceeds the height of list. 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getIndexForListOffset_: function(offset) { 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!itemHeight) 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.dataModel.length; 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getFirstItemInRow(Math.floor(offset / itemHeight)); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If offset exceeds the height of list. 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastHeight = 0; 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dataModel.length) { 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var h = this.getHeightsForIndex_(this.dataModel.length - 1); 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastHeight = h.top + h.height; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lastHeight < offset) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.dataModel.length; 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Estimates index. 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var estimatedIndex = Math.min(Math.floor(offset / itemHeight), 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel.length - 1); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var isIncrementing = this.getItemTop(estimatedIndex) < offset; 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Searchs the correct index. 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var heights = this.getHeightsForIndex_(estimatedIndex); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = heights.top; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var height = heights.height; 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top <= offset && offset <= (top + height)) 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isIncrementing ? ++estimatedIndex : --estimatedIndex; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0 < estimatedIndex && estimatedIndex < this.dataModel.length); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return estimatedIndex; 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the number of items that occupy the range of heights between the 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * top of the start item and the end offset. 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} startIndex The index of the first visible item. 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} endOffset The y offset in pixels of the end of the list. 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The number of list items visible. 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) countItemsInRange_: function(startIndex, endOffset) { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var endIndex = this.getIndexForListOffset_(endOffset); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return endIndex - startIndex + 1; 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculates the number of items fitting in the given viewport. 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} scrollTop The scroll top position. 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} clientHeight The height of viewport. 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{first: number, length: number, last: number}} The index of 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * first item in view port, The number of items, The item past the last. 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemsInViewPort: function(scrollTop, clientHeight) { 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.autoExpands_) { 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first: 0, 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length: this.dataModel.length, 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last: this.dataModel.length}; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var firstIndex = this.getIndexForListOffset_(scrollTop); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastIndex = this.getIndexForListOffset_(scrollTop + clientHeight); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first: firstIndex, 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length: lastIndex - firstIndex + 1, 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last: lastIndex + 1}; 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Merges list items currently existing in the list with items in the range 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [firstIndex, lastIndex). Removes or adds items if needed. 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Doesn't delete {@code this.pinnedItem_} if it is present (instead hides 9237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * it if it is out of the range). 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} firstIndex The index of first item, inclusively. 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} lastIndex The index of last item, exclusively. 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch mergeItems: function(firstIndex, lastIndex) { 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var currentIndex = firstIndex; 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function insert() { 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataItem = dataModel.item(currentIndex); 9347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var newItem = self.cachedItems_[currentIndex] || 9357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.createItem(dataItem); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newItem.listIndex = currentIndex; 9377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.cachedItems_[currentIndex] = newItem; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.insertBefore(newItem, item); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentIndex++; 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function remove() { 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var next = item.nextSibling; 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item != self.pinnedItem_) 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.removeChild(item); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = next; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var item = this.beforeFiller_.nextSibling; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item != this.afterFiller_ && currentIndex < lastIndex;) { 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.isItem(item)) { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = item.listIndex; 9577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (this.cachedItems_[index] != item || index < currentIndex) { 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove(); 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (index == currentIndex) { 9607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[currentIndex] = item; 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentIndex++; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // index > currentIndex 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (item != this.afterFiller_) { 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.isItem(item)) 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove(); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_) { 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.pinnedItem_.listIndex; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_.hidden = index < firstIndex || index >= lastIndex; 9787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[index] = this.pinnedItem_; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= lastIndex) 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = this.pinnedItem_; // Insert new items before this one. 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (currentIndex < lastIndex) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(); 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ensures that all the item sizes in the list have been already cached. 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureAllItemSizesInCache: function() { 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var measuringIndexes = []; 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var isElementAppended = []; 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < this.dataModel.length; y++) { 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.cachedItemHeights_[y]) { 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measuringIndexes.push(y); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isElementAppended.push(false); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var measuringItems = []; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds temporary elements. 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = measuringIndexes[y]; 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataItem = this.dataModel.item(index); 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = this.cachedItems_[index] || this.createItem(dataItem); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.listIndex = index; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |listItems| is not on the list, apppends it to the list and sets 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the flag. 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listItem.parentNode) { 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(listItem); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isElementAppended[y] = true; 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_[index] = listItem; 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measuringItems.push(listItem); 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All mesurings must be placed after adding all the elements, to prevent 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // performance reducing. 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = measuringIndexes[y]; 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[index] = 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.measureItemHeight_(measuringItems[y]); 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes all the temprary elements. 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the list item has been appended above, removes it. 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isElementAppended[y]) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(measuringItems[y]); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the height of after filler in the list. 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} lastIndex The index of item past the last in viewport. 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of after filler. 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getAfterFillerHeight: function(lastIndex) { 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) { 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (this.dataModel.length - lastIndex) * itemHeight; 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var height = 0; 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = lastIndex; i < this.dataModel.length; i++) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height += this.getItemHeightByIndex_(i); 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return height; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redraws the viewport. 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redraw: function() { 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.batchCount_ != 0) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dataModel || !this.autoExpands_ && this.clientHeight == 0) { 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstIndex_ = 0; 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastIndex_ = 0; 10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.remainingSpace_ = this.clientHeight != 0; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mergeItems(0, 0, {}, {}); 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the previous positions before any manipulation of elements. 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var scrollTop = this.scrollTop; 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var clientHeight = this.clientHeight; 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store all the item sizes into the cache in advance, to prevent 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interleave measuring with mutating dom. 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.fixedHeight_) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.ensureAllItemSizesInCache(); 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var autoExpands = this.autoExpands_; 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemsInViewPort = this.getItemsInViewPort(scrollTop, clientHeight); 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draws the hidden rows just above/below the viewport to prevent 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flashing in scroll. 10837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var firstIndex = Math.max( 10847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 0, 10857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Math.min(dataModel.length - 1, itemsInViewPort.first - 1)); 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastIndex = Math.min(itemsInViewPort.last + 1, dataModel.length); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var beforeFillerHeight = 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.autoExpands ? 0 : this.getItemTop(firstIndex); 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var afterFillerHeight = 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.autoExpands ? 0 : this.getAfterFillerHeight(lastIndex); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.beforeFiller_.style.height = beforeFillerHeight + 'px'; 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sm = this.selectionModel; 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var leadIndex = sm.leadIndex; 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1098d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If the pinned item is hidden and it is not the lead item, then remove 1099d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // it from cache. Note, that we restore the hidden status to false, since 1100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the item is still in cache, and may be reused. 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_ && 11027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.pinnedItem_ != this.cachedItems_[leadIndex]) { 1103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (this.pinnedItem_.hidden) { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(this.pinnedItem_); 1105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) this.pinnedItem_.hidden = false; 1106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = undefined; 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.mergeItems(firstIndex, lastIndex); 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!this.pinnedItem_ && this.cachedItems_[leadIndex] && 11137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[leadIndex].parentNode == this) { 11147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.pinnedItem_ = this.cachedItems_[leadIndex]; 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.afterFiller_.style.height = afterFillerHeight + 'px'; 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Restores the number of pixels scrolled, since it might be changed while 11204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // DOM operations. 11214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.scrollTop = scrollTop; 11224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set the lead or selected properties until after adding all 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // items, in case they force relayout in response to these events. 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = null; 11267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (leadIndex != -1 && this.cachedItems_[leadIndex]) 11277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[leadIndex].lead = true; 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = firstIndex; y < lastIndex; y++) { 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sm.getIndexSelected(y)) 11307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[y].selected = true; 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (y != leadIndex) 11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch listItem = this.cachedItems_[y]; 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstIndex_ = firstIndex; 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastIndex_ = lastIndex; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.remainingSpace_ = itemsInViewPort.last > dataModel.length; 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mesurings must be placed after adding all the elements, to prevent 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // performance reducing. 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.fixedHeight_) { 11437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (var y = firstIndex; y < lastIndex; y++) { 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[y] = 11457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.measureItemHeight_(this.cachedItems_[y]); 11467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Restore the lead item that is present in the list but may be updated 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the data model (supposed to be used inside a batch update). Usually 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * such an item would be recreated in the redraw method. If reinsertion 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is undesirable (for instance to prevent losing focus) the item may be 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * updated and restored. Assumed the listItem relates to the same data item 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as the lead item in the begin of the batch update. 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem} leadItem Already existing lead item. 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restoreLeadItem: function(leadItem) { 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[leadItem.listIndex]; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leadItem.listIndex = this.selectionModel.leadIndex; 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = this.cachedItems_[leadItem.listIndex] = leadItem; 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Invalidates list by removing cached items. 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invalidate: function() { 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemSized_ = {}; 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redraws a single item. 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The row index to redraw. 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redrawItem: function(index) { 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= this.firstIndex_ && 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (index < this.lastIndex_ || this.remainingSpace_)) { 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[index]; 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when a list item is activated, currently only by a double click 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * event. 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the activated item. 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) activateItemAtIndex: function(index) { 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a ListItem for the leadIndex. If the item isn't present in the 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * list creates it and inserts to the list (may be invisible if it's out of 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the visible range). 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Item returned from this method won't be removed until it remains a lead 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * item or til the data model changes (unlike other items that could be 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * removed when they go out of the visible range). 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {cr.ui.ListItem} The lead item for the list. 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureLeadItemExists: function() { 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.selectionModel.leadIndex; 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < 0) 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cachedItems = this.cachedItems_ || {}; 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = cachedItems[index] || 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.createItem(this.dataModel.item(index)); 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_ != item && this.pinnedItem_ && 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_.hidden) { 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(this.pinnedItem_); 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = item; 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cachedItems[index] = item; 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.listIndex = index; 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item.parentNode == this) 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.batchCount_ != 0) 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.hidden = true; 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Item will get to the right place in redraw. Choose place to insert 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reducing items reinsertion. 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index <= this.firstIndex_) 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(item, this.beforeFiller_.nextSibling); 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(item, this.afterFiller_); 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 1237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) /** 1238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * Starts drag selection by reacting 'dragstart' event. 1239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * @param {Event} event Event of dragstart. 1240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) */ 1241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) startDragSelection: function(event) { 1242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) event.preventDefault(); 1243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var border = document.createElement('div'); 1244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.className = 'drag-selection-border'; 1245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var rect = this.getBoundingClientRect(); 1246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var startX = event.clientX - rect.left + this.scrollLeft; 1247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var startY = event.clientY - rect.top + this.scrollTop; 1248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.left = startX + 'px'; 1249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.top = startY + 'px'; 1250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var onMouseMove = function(event) { 1251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var inRect = this.getBoundingClientRect(); 1252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var x = event.clientX - inRect.left + this.scrollLeft; 1253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var y = event.clientY - inRect.top + this.scrollTop; 1254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.left = Math.min(startX, x) + 'px'; 1255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.top = Math.min(startY, y) + 'px'; 1256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.width = Math.abs(startX - x) + 'px'; 1257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.height = Math.abs(startY - y) + 'px'; 1258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }.bind(this); 1259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var onMouseUp = function() { 1260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) this.removeChild(border); 1261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.removeEventListener('mousemove', onMouseMove, true); 1262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.removeEventListener('mouseup', onMouseUp, true); 1263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }.bind(this); 1264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.addEventListener('mousemove', onMouseMove, true); 1265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.addEventListener('mouseup', onMouseUp, true); 1266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) this.appendChild(border); 1267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }, 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.defineProperty(List, 'disabled', cr.PropertyKind.BOOL_ATTR); 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether the list or one of its descendents has focus. This is necessary 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * because list items can contain controls that can be focused, and for some 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * purposes (e.g., styling), the list can still be conceptually focused at 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that point even though it doesn't actually have the page focus. 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 12814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Mousedown event handler. 12824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @this {List} 12834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {MouseEvent} e The mouse event object. 12844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 12854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) function handleMouseDown(e) { 12864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.handlePointerDownUp_(e); 12874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 12884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (e.defaultPrevented) 12894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 12904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 12914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If non-focusable area in a list item is clicked and the item still 12924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // contains the focused element, the item did a special focus handling 12934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // [1] and we should not focus on the list. 12944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // 12954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // [1] For example, clicking non-focusable area gives focus on the first 12964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // form control in the item. 12974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) var listItem = this.getListItemAncestor(e.target); 12984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (listItem && !tryFocusOnAncestor(e.target, listItem) && 12994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) listItem.contains(listItem.ownerDocument.activeElement)) { 13004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) e.preventDefault(); 13014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 13044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 13054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Try focusing on |eventTarget| or its ancestor under |root|. 13064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * This is a helper for handleMouseDown. 13074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {!Element} start An element which we start to try. 13084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {!Element} root An element which we finish to try. 13094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @return {boolean} True if we focused on an element successfully. 13104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 13114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) function tryFocusOnAncestor(start, root) { 13124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (var element = start; element && element != root; 13134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) element = element.parentElement) { 13144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) element.focus(); 13154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (root.ownerDocument.activeElement == element) 13164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 13174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 13194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) List: List 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}); 1325