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. 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return {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. 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @type {?{height: number, marginTop: number, marginBottom: number, 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * width: number, marginLeft: number, marginRight: number}} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci measured_: null, 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. 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @type {function(new:cr.ui.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. 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return {function(new:cr.ui.ListItem, Object)} 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 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @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); 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.addEventListener('dragstart', handleDragStart, true); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('mouseup', this.handlePointerDownUp_); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('keydown', this.handleKeyDown); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('focus', this.handleElementFocus_, true); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('blur', this.handleElementBlur_, true); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.addEventListener('scroll', this.handleScroll.bind(this)); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setAttribute('role', 'list'); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make list focusable 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.hasAttribute('tabindex')) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.tabIndex = 0; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to get an unique id prefix from the id of this element or the 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nearest ancestor with an id. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element = this; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (element && !element.id) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element = element.parentElement; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (element && element.id) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.uniqueIdPrefix_ = element.id; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.uniqueIdPrefix_ = 'list'; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The next id suffix to use when giving each item an unique id. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.nextUniqueIdSuffix_ = 0; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem=} item The list item to measure. 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of the given item. If the fixed height on CSS 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is set by 'px', uses that value as height. Otherwise, measures the size. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measureItemHeight_: function(item) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.measureItem(item).height; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of default item, measuring it if necessary. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getDefaultItemHeight_: function() { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getDefaultItemSize_().height; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of the item, measuring it if necessary. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemHeightByIndex_: function(index) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |this.fixedHeight_| is true, all the rows have same default height. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getDefaultItemHeight_(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.cachedItemHeights_[index]) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.cachedItemHeights_[index]; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = this.getListItemByIndex(index); 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item) { 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var h = this.measureItemHeight_(item); 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.cachedItemHeights_[index] = h; 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return h; 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getDefaultItemHeight_(); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{height: number, width: number}} The height and width 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of default item, measuring it if necessary. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getDefaultItemSize_: function() { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.measured_ || !this.measured_.height) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.measured_ = this.measureItem(); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.measured_; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates an item (dataModel.item(0)) and measures its height. The item is 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cached instead of creating a new one every time.. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem=} opt_item The list item to use to do the measuring. If 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this is not provided an item will be created based on the first value 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the model. 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return {{height: number, marginTop: number, marginBottom: number, 4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * width: number, marginLeft: number, marginRight: number}} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The height and width of the item, taking 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * margins into account, and the top, bottom, left and right margins 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * themselves. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measureItem: function(opt_item) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!dataModel || !dataModel.length) { 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return {height: 0, marginTop: 0, marginBottom: 0, 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci width: 0, marginLeft: 0, marginRight: 0}; 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = opt_item || this.cachedMeasuredItem_ || 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.createItem(dataModel.item(0)); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opt_item) { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedMeasuredItem_ = item; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(item); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var rect = item.getBoundingClientRect(); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cs = getComputedStyle(item); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mt = parseFloat(cs.marginTop); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mb = parseFloat(cs.marginBottom); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ml = parseFloat(cs.marginLeft); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mr = parseFloat(cs.marginRight); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var h = rect.height; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var w = rect.width; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mh = 0; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mv = 0; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle margin collapsing. 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mt < 0 && mb < 0) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv = Math.min(mt, mb); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (mt >= 0 && mb >= 0) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv = Math.max(mt, mb); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv = mt + mb; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h += mv; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ml < 0 && mr < 0) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mh = Math.min(ml, mr); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ml >= 0 && mr >= 0) { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mh = Math.max(ml, mr); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mh = ml + mr; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) w += mh; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opt_item) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(item); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height: Math.max(0, h), 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) marginTop: mt, marginBottom: mb, 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width: Math.max(0, w), 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) marginLeft: ml, marginRight: mr}; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Callback for the double click event. 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Event} e The mouse event object. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handleDoubleClick_: function(e) { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.disabled) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var target = /** @type {HTMLElement} */(e.target); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var ancestor = this.getListItemAncestor(target); 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var index = -1; 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (ancestor) { 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci index = this.getIndexOfListItem(ancestor); 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.activateItemAtIndex(index); 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var sm = this.selectionModel; 4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var indexSelected = sm.getIndexSelected(index); 4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!indexSelected) 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.handlePointerDownUp_(e); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Callback for mousedown and mouseup events. 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Event} e The mouse event object. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handlePointerDownUp_: function(e) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.disabled) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var target = /** @type {HTMLElement} */(e.target); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the target was this element we need to make sure that the user did 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not click on a border or a scrollbar. 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target == this) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inViewport(target, e)) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionController_.handlePointerDownUp(e, -1); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target = this.getListItemAncestor(target); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.getIndexOfListItem(target); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionController_.handlePointerDownUp(e, index); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when an element in the list is focused. Marks the list as having 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a focused element, and dispatches an event if it didn't have focus. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The focus event. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleElementFocus_: function(e) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.hasElementFocus) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.hasElementFocus = true; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when an element in the list is blurred. If focus moves outside 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the list, marks the list as no longer having focus and dispatches an 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * event. 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The blur event. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleElementBlur_: function(e) { 5264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!this.contains(e.relatedTarget)) 5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.hasElementFocus = false; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the list item element containing the given element, or null if 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it doesn't belong to any list item element. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} element The element. 5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return {HTMLLIElement} The list item containing |element|, or null. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItemAncestor: function(element) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var container = element; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (container && container.parentNode != this) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container = container.parentNode; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return container && assertInstanceof(container, HTMLLIElement); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle a keydown event. 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The keydown event. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleKeyDown: function(e) { 5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!this.disabled) 5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.selectionController_.handleKeyDown(e); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle a scroll event. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The scroll event. 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleScroll: function(e) { 5587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch requestAnimationFrame(this.redraw.bind(this)); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Callback from the selection model. We dispatch {@code change} events 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * when the selection changes. 5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {!Event} ce Event with change info. 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleOnChange_: function(ce) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ce.changes.forEach(function(change) { 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = this.getListItemByIndex(change.index); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (listItem) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.selected = change.selected; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (change.selected) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.setAttribute('aria-posinset', change.index + 1); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.setAttribute('aria-setsize', this.dataModel.length); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setAttribute('aria-activedescendant', listItem.id); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.removeAttribute('aria-posinset'); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.removeAttribute('aria-setsize'); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, this); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.dispatchSimpleEvent(this, 'change'); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles a change of the lead item from the selection model. 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} pe The property change event. 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleLeadChange_: function(pe) { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var element; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.oldValue != -1) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((element = this.getListItemByIndex(pe.oldValue))) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.lead = false; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.newValue != -1) { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((element = this.getListItemByIndex(pe.newValue))) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) element.lead = true; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pe.oldValue != pe.newValue) { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.scrollIndexIntoView(pe.newValue); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the lead item has a different height than other items, then we 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may run into a problem that requires a second attempt to scroll 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it into view. The first scroll attempt will trigger a redraw, 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which will clear out the list and repopulate it with new items. 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // During the redraw, the list may shrink temporarily, which if the 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lead item is the last item, will move the scrollTop up since it 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot extend beyond the end of the list. (Sadly, being scrolled to 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the bottom of the list is not "sticky.") So, we set a timeout to 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rescroll the list after this all gets sorted out. This is perhaps 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not the most elegant solution, but no others seem obvious. 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.setTimeout(function() { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollIndexIntoView(pe.newValue); 6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }, 0); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This handles data model 'permuted' event. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this event is dispatched as a part of sort or splice. 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We need to 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - adjust the cache. 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - adjust selection. 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - redraw. (called in this.endBatchUpdates()) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * It is important that the cache adjustment happens before selection model 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * adjustments. 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The 'permuted' event. 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleDataModelPermuted_: function(e) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCachedItems = {}; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var index in this.cachedItems_) { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.permutation[index] != -1) { 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newIndex = e.permutation[index]; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItems[newIndex] = this.cachedItems_[index]; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItems[newIndex].listIndex = newIndex; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = newCachedItems; 6420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch this.pinnedItem_ = null; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCachedItemHeights = {}; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var index in this.cachedItemHeights_) { 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.permutation[index] != -1) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCachedItemHeights[e.permutation[index]] = 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[index]; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_ = newCachedItemHeights; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.startBatchUpdates(); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sm = this.selectionModel; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.adjustLength(e.newLength); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm.adjustToReordering(e.permutation); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.endBatchUpdates(); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handleDataModelChange_: function(e) { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[e.index]; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItemHeights_[e.index]; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedMeasuredItem_ = null; 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.index >= this.firstIndex_ && 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (e.index < this.lastIndex_ || this.remainingSpace_)) { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The top position of the item inside the list. 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemTop: function(index) { 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index * itemHeight; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.ensureAllItemSizesInCache(); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = 0; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < index; i++) { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top += this.getItemHeightByIndex_(i); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return top; 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item. 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The row of the item. May vary in the case 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of multiple columns. 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemRow: function(index) { 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} row The row. 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the first item in the row. 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getFirstItemInRow: function(row) { 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ensures that a given index is inside the viewport. 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the item to scroll into view. 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether any scrolling was needed. 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scrollIndexIntoView: function(index) { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dataModel || index < 0 || index >= dataModel.length) 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getItemHeightByIndex_(index); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var scrollTop = this.scrollTop; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = this.getItemTop(index); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var clientHeight = this.clientHeight; 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var cs = getComputedStyle(this); 724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var paddingY = parseInt(cs.paddingTop, 10) + 725a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parseInt(cs.paddingBottom, 10); 726a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var availableHeight = clientHeight - paddingY; 727a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Function to adjust the tops of viewport and row. 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function scrollToAdjustTop() { 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.scrollTop = top; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Function to adjust the bottoms of viewport and row. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function scrollToAdjustBottom() { 736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.scrollTop = top + itemHeight - availableHeight; 737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the entire of given indexed row can be shown in the viewport. 741a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (itemHeight <= availableHeight) { 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top < scrollTop) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustTop(); 744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (scrollTop + availableHeight < top + itemHeight) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustBottom(); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scrollTop < top) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustTop(); 749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (top + itemHeight < scrollTop + availableHeight) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scrollToAdjustBottom(); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!ClientRect} The rect to use for the context menu. 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getRectForContextMenu: function() { 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(arv): Add trait support so we can share more code between trees 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and lists. 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.selectionModel.selectedIndex; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var el = this.getListItemByIndex(index); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (el) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return el.getBoundingClientRect(); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getBoundingClientRect(); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Takes a value from the data model and finds the associated list item. 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {*} value The value in the data model that we want to get the list 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * item for. 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The first found list item or null if not found. 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItem: function(value) { 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dataModel) { 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = dataModel.indexOf(value); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getListItemByIndex(index); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the list item element at the given index. 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the list item to get. 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ListItem} The found list item or null if not found. 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getListItemByIndex: function(index) { 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.cachedItems_[index] || null; 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the index of the given list item element. 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem} item The list item to get the index of. 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the list item, or -1 if not found. 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getIndexOfListItem: function(item) { 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = item.listIndex; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.cachedItems_[index] == item) { 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates a new list item. 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {*} value The value to use for the item. 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!ListItem} The newly created list item. 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createItem: function(value) { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = new this.itemConstructor_(value); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.label = value; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.id = this.uniqueIdPrefix_ + '-' + this.nextUniqueIdSuffix_++; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof item.decorate == 'function') 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.decorate(); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates the selection controller to use internally. 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {cr.ui.ListSelectionModel} sm The underlying selection model. 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!cr.ui.ListSelectionController} The newly created selection 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * controller. 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) createSelectionController: function(sm) { 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new ListSelectionController(sm); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the heights (in pixels) of the top of the given item index within 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the list, and the height of the given item itself, accounting for the 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * possibility that the lead item may be a different height. 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index to find the top height of. 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{top: number, height: number}} The heights for the given index. 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getHeightsForIndex_: function(index) { 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getItemHeightByIndex_(index); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = this.getItemTop(index); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return {top: top, height: itemHeight}; 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find the index of the list item containing the given y offset (measured 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in pixels from the top) within the list. In the case of multiple columns, 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returns the first index in the row. 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} offset The y offset in pixels to get the index of. 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The index of the list item. Returns the list size if 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given offset exceeds the height of list. 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getIndexForListOffset_: function(offset) { 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!itemHeight) 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.dataModel.length; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getFirstItemInRow(Math.floor(offset / itemHeight)); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If offset exceeds the height of list. 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastHeight = 0; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dataModel.length) { 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var h = this.getHeightsForIndex_(this.dataModel.length - 1); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastHeight = h.top + h.height; 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lastHeight < offset) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.dataModel.length; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Estimates index. 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var estimatedIndex = Math.min(Math.floor(offset / itemHeight), 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel.length - 1); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var isIncrementing = this.getItemTop(estimatedIndex) < offset; 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Searchs the correct index. 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var heights = this.getHeightsForIndex_(estimatedIndex); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var top = heights.top; 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var height = heights.height; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top <= offset && offset <= (top + height)) 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isIncrementing ? ++estimatedIndex : --estimatedIndex; 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (0 < estimatedIndex && estimatedIndex < this.dataModel.length); 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return estimatedIndex; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return the number of items that occupy the range of heights between the 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * top of the start item and the end offset. 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} startIndex The index of the first visible item. 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} endOffset The y offset in pixels of the end of the list. 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The number of list items visible. 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) countItemsInRange_: function(startIndex, endOffset) { 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var endIndex = this.getIndexForListOffset_(endOffset); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return endIndex - startIndex + 1; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculates the number of items fitting in the given viewport. 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} scrollTop The scroll top position. 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} clientHeight The height of viewport. 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{first: number, length: number, last: number}} The index of 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * first item in view port, The number of items, The item past the last. 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getItemsInViewPort: function(scrollTop, clientHeight) { 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.autoExpands_) { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first: 0, 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length: this.dataModel.length, 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last: this.dataModel.length}; 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var firstIndex = this.getIndexForListOffset_(scrollTop); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastIndex = this.getIndexForListOffset_(scrollTop + clientHeight); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first: firstIndex, 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length: lastIndex - firstIndex + 1, 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last: lastIndex + 1}; 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Merges list items currently existing in the list with items in the range 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [firstIndex, lastIndex). Removes or adds items if needed. 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Doesn't delete {@code this.pinnedItem_} if it is present (instead hides 9307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * it if it is out of the range). 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} firstIndex The index of first item, inclusively. 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} lastIndex The index of last item, exclusively. 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch mergeItems: function(firstIndex, lastIndex) { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var currentIndex = firstIndex; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function insert() { 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataItem = dataModel.item(currentIndex); 9417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var newItem = self.cachedItems_[currentIndex] || 9427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.createItem(dataItem); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newItem.listIndex = currentIndex; 9447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.cachedItems_[currentIndex] = newItem; 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.insertBefore(newItem, item); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentIndex++; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function remove() { 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var next = item.nextSibling; 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item != self.pinnedItem_) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.removeChild(item); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = next; 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var item = this.beforeFiller_.nextSibling; 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item != this.afterFiller_ && currentIndex < lastIndex;) { 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.isItem(item)) { 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = item.listIndex; 9647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (this.cachedItems_[index] != item || index < currentIndex) { 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove(); 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (index == currentIndex) { 9677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[currentIndex] = item; 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentIndex++; 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // index > currentIndex 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (item != this.afterFiller_) { 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.isItem(item)) 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remove(); 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = item.nextSibling; 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_) { 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.pinnedItem_.listIndex; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_.hidden = index < firstIndex || index >= lastIndex; 9857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[index] = this.pinnedItem_; 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= lastIndex) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item = this.pinnedItem_; // Insert new items before this one. 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (currentIndex < lastIndex) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ensures that all the item sizes in the list have been already cached. 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureAllItemSizesInCache: function() { 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var measuringIndexes = []; 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var isElementAppended = []; 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < this.dataModel.length; y++) { 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.cachedItemHeights_[y]) { 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measuringIndexes.push(y); 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isElementAppended.push(false); 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var measuringItems = []; 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds temporary elements. 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = measuringIndexes[y]; 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataItem = this.dataModel.item(index); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var listItem = this.cachedItems_[index] || this.createItem(dataItem); 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listItem.listIndex = index; 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |listItems| is not on the list, apppends it to the list and sets 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the flag. 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listItem.parentNode) { 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(listItem); 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isElementAppended[y] = true; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_[index] = listItem; 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) measuringItems.push(listItem); 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All mesurings must be placed after adding all the elements, to prevent 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // performance reducing. 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = measuringIndexes[y]; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[index] = 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.measureItemHeight_(measuringItems[y]); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes all the temprary elements. 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = 0; y < measuringIndexes.length; y++) { 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the list item has been appended above, removes it. 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isElementAppended[y]) 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(measuringItems[y]); 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the height of after filler in the list. 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} lastIndex The index of item past the last in viewport. 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The height of after filler. 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getAfterFillerHeight: function(lastIndex) { 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.fixedHeight_) { 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemHeight = this.getDefaultItemHeight_(); 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (this.dataModel.length - lastIndex) * itemHeight; 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var height = 0; 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = lastIndex; i < this.dataModel.length; i++) 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height += this.getItemHeightByIndex_(i); 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return height; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redraws the viewport. 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redraw: function() { 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.batchCount_ != 0) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var dataModel = this.dataModel; 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dataModel || !this.autoExpands_ && this.clientHeight == 0) { 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstIndex_ = 0; 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastIndex_ = 0; 10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.remainingSpace_ = this.clientHeight != 0; 10721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.mergeItems(0, 0); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the previous positions before any manipulation of elements. 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var scrollTop = this.scrollTop; 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var clientHeight = this.clientHeight; 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store all the item sizes into the cache in advance, to prevent 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interleave measuring with mutating dom. 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.fixedHeight_) 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.ensureAllItemSizesInCache(); 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var autoExpands = this.autoExpands_; 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemsInViewPort = this.getItemsInViewPort(scrollTop, clientHeight); 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draws the hidden rows just above/below the viewport to prevent 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flashing in scroll. 10907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch var firstIndex = Math.max( 10917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 0, 10927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Math.min(dataModel.length - 1, itemsInViewPort.first - 1)); 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastIndex = Math.min(itemsInViewPort.last + 1, dataModel.length); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var beforeFillerHeight = 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.autoExpands ? 0 : this.getItemTop(firstIndex); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var afterFillerHeight = 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.autoExpands ? 0 : this.getAfterFillerHeight(lastIndex); 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.beforeFiller_.style.height = beforeFillerHeight + 'px'; 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sm = this.selectionModel; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var leadIndex = sm.leadIndex; 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If the pinned item is hidden and it is not the lead item, then remove 1106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // it from cache. Note, that we restore the hidden status to false, since 1107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the item is still in cache, and may be reused. 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_ && 11097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.pinnedItem_ != this.cachedItems_[leadIndex]) { 1110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (this.pinnedItem_.hidden) { 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(this.pinnedItem_); 1112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) this.pinnedItem_.hidden = false; 1113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = undefined; 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.mergeItems(firstIndex, lastIndex); 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!this.pinnedItem_ && this.cachedItems_[leadIndex] && 11207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[leadIndex].parentNode == this) { 11217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.pinnedItem_ = this.cachedItems_[leadIndex]; 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.afterFiller_.style.height = afterFillerHeight + 'px'; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Restores the number of pixels scrolled, since it might be changed while 11274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // DOM operations. 11284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.scrollTop = scrollTop; 11294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set the lead or selected properties until after adding all 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // items, in case they force relayout in response to these events. 11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (leadIndex != -1 && this.cachedItems_[leadIndex]) 11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.cachedItems_[leadIndex].lead = true; 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var y = firstIndex; y < lastIndex; y++) { 1135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (sm.getIndexSelected(y) != this.cachedItems_[y].selected) 1136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.cachedItems_[y].selected = !this.cachedItems_[y].selected; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstIndex_ = firstIndex; 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastIndex_ = lastIndex; 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.remainingSpace_ = itemsInViewPort.last > dataModel.length; 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mesurings must be placed after adding all the elements, to prevent 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // performance reducing. 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.fixedHeight_) { 11477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (var y = firstIndex; y < lastIndex; y++) { 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemHeights_[y] = 11497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this.measureItemHeight_(this.cachedItems_[y]); 11507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Restore the lead item that is present in the list but may be updated 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the data model (supposed to be used inside a batch update). Usually 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * such an item would be recreated in the redraw method. If reinsertion 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is undesirable (for instance to prevent losing focus) the item may be 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * updated and restored. Assumed the listItem relates to the same data item 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as the lead item in the begin of the batch update. 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ListItem} leadItem Already existing lead item. 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restoreLeadItem: function(leadItem) { 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[leadItem.listIndex]; 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leadItem.listIndex = this.selectionModel.leadIndex; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = this.cachedItems_[leadItem.listIndex] = leadItem; 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Invalidates list by removing cached items. 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invalidate: function() { 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItems_ = {}; 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cachedItemSized_ = {}; 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redraws a single item. 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The row index to redraw. 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redrawItem: function(index) { 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= this.firstIndex_ && 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (index < this.lastIndex_ || this.remainingSpace_)) { 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.cachedItems_[index]; 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when a list item is activated, currently only by a double click 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * event. 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the activated item. 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) activateItemAtIndex: function(index) { 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a ListItem for the leadIndex. If the item isn't present in the 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * list creates it and inserts to the list (may be invisible if it's out of 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the visible range). 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Item returned from this method won't be removed until it remains a lead 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * item or til the data model changes (unlike other items that could be 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * removed when they go out of the visible range). 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {cr.ui.ListItem} The lead item for the list. 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ensureLeadItemExists: function() { 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.selectionModel.leadIndex; 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < 0) 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cachedItems = this.cachedItems_ || {}; 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = cachedItems[index] || 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.createItem(this.dataModel.item(index)); 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.pinnedItem_ != item && this.pinnedItem_ && 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_.hidden) { 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(this.pinnedItem_); 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.pinnedItem_ = item; 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cachedItems[index] = item; 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.listIndex = index; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item.parentNode == this) 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.batchCount_ != 0) 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item.hidden = true; 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Item will get to the right place in redraw. Choose place to insert 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reducing items reinsertion. 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index <= this.firstIndex_) 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(item, this.beforeFiller_.nextSibling); 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(item, this.afterFiller_); 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 1241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) /** 1242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * Starts drag selection by reacting 'dragstart' event. 1243b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) * @param {Event} event Event of dragstart. 1244b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) */ 1245b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) startDragSelection: function(event) { 1246b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) event.preventDefault(); 1247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var border = document.createElement('div'); 1248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.className = 'drag-selection-border'; 1249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var rect = this.getBoundingClientRect(); 1250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var startX = event.clientX - rect.left + this.scrollLeft; 1251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var startY = event.clientY - rect.top + this.scrollTop; 1252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.left = startX + 'px'; 1253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.top = startY + 'px'; 1254b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var onMouseMove = function(event) { 1255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var inRect = this.getBoundingClientRect(); 1256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var x = event.clientX - inRect.left + this.scrollLeft; 1257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var y = event.clientY - inRect.top + this.scrollTop; 1258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.left = Math.min(startX, x) + 'px'; 1259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.top = Math.min(startY, y) + 'px'; 1260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.width = Math.abs(startX - x) + 'px'; 1261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) border.style.height = Math.abs(startY - y) + 'px'; 1262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }.bind(this); 1263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) var onMouseUp = function() { 1264b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) this.removeChild(border); 1265b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.removeEventListener('mousemove', onMouseMove, true); 1266b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.removeEventListener('mouseup', onMouseUp, true); 1267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }.bind(this); 1268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.addEventListener('mousemove', onMouseMove, true); 1269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) document.addEventListener('mouseup', onMouseUp, true); 1270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) this.appendChild(border); 1271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) }, 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.defineProperty(List, 'disabled', cr.PropertyKind.BOOL_ATTR); 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Whether the list or one of its descendents has focus. This is necessary 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * because list items can contain controls that can be focused, and for some 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * purposes (e.g., styling), the list can still be conceptually focused at 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that point even though it doesn't actually have the page focus. 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 12854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Mousedown event handler. 12861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @this {cr.ui.List} 12871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Event} e The mouse event object. 12884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 12894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) function handleMouseDown(e) { 12901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci e.target = /** @type {!HTMLElement} */(e.target); 12910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) var listItem = this.getListItemAncestor(e.target); 12920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) var wasSelected = listItem && listItem.selected; 12934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this.handlePointerDownUp_(e); 12944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 12950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (e.defaultPrevented || e.button != 0) 12960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 12970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 12980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // The following hack is required only if the listItem gets selected. 12990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!listItem || wasSelected || !listItem.selected) 13004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 13014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 13024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If non-focusable area in a list item is clicked and the item still 13034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // contains the focused element, the item did a special focus handling 13044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // [1] and we should not focus on the list. 13054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // 13064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // [1] For example, clicking non-focusable area gives focus on the first 13074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // form control in the item. 1308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!containsFocusableElement(e.target, listItem) && 13094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) listItem.contains(listItem.ownerDocument.activeElement)) { 13104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) e.preventDefault(); 13114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 13144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) /** 1315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Dragstart event handler. 1316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * If there is an item at starting position of drag operation and the item 1317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * is not selected, select it. 13181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @this {cr.ui.List} 13191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Event} e The event object for 'dragstart'. 1320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 1321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) function handleDragStart(e) { 13221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci e = /** @type {MouseEvent} */(e); 1323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var element = e.target.ownerDocument.elementFromPoint(e.clientX, e.clientY); 1324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var listItem = this.getListItemAncestor(element); 1325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!listItem) 1326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 1327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var index = this.getIndexOfListItem(listItem); 1329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (index == -1) 1330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 1331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var isAlreadySelected = this.selectionModel_.getIndexSelected(index); 1333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!isAlreadySelected) 1334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this.selectionModel_.selectedIndex = index; 1335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 1338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Check if |start| or its ancestor under |root| is focusable. 13394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * This is a helper for handleMouseDown. 1340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {!Element} start An element which we start to check. 1341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {!Element} root An element which we finish to check. 1342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @return {boolean} True if we found a focusable element. 13434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 1344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) function containsFocusableElement(start, root) { 13454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (var element = start; element && element != root; 13464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) element = element.parentElement) { 1347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (element.tabIndex >= 0 && !element.disabled) 13484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 13494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 13514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 13524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) List: List 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}); 1357