1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 cr.define('cr.ui', function() {
6 /** @const */ var EventTarget = cr.EventTarget;
9 * Creates a new selection model that is to be used with lists. This only
10 * allows a single index to be selected.
12 * @param {number=} opt_length The number items in the selection.
15 * @extends {cr.EventTarget}
17 function ListSingleSelectionModel(opt_length) {
18 this.length_ = opt_length || 0;
19 this.selectedIndex = -1;
21 // True if any item could be lead or anchor. False if only selected ones.
22 this.independentLeadItem_ = !cr.isMac && !cr.isChromeOS;
25 ListSingleSelectionModel.prototype = {
26 __proto__: EventTarget.prototype,
29 * The number of items in the model.
37 * @type {!Array} The selected indexes.
39 get selectedIndexes() {
40 var i = this.selectedIndex;
41 return i != -1 ? [this.selectedIndex] : [];
43 set selectedIndexes(indexes) {
44 this.selectedIndex = indexes.length ? indexes[0] : -1;
48 * Convenience getter which returns the first selected index.
49 * Setter also changes lead and anchor indexes if value is nonegative.
53 return this.selectedIndex_;
55 set selectedIndex(selectedIndex) {
56 var oldSelectedIndex = this.selectedIndex;
57 var i = Math.max(-1, Math.min(this.length_ - 1, selectedIndex));
59 if (i != oldSelectedIndex) {
61 this.selectedIndex_ = i;
62 this.leadIndex = i >= 0 ? i : this.leadIndex;
68 * Selects a range of indexes, starting with {@code start} and ends with
70 * @param {number} start The first index to select.
71 * @param {number} end The last index to select.
73 selectRange: function(start, end) {
74 // Only select first index.
75 this.selectedIndex = Math.min(start, end);
79 * Selects all indexes.
81 selectAll: function() {
82 // Select all is not allowed on a single selection model
86 * Clears the selection
91 this.selectedIndex = this.anchorIndex = this.leadIndex = -1;
96 * Unselects all selected items.
98 unselectAll: function() {
99 this.selectedIndex = -1;
103 * Sets the selected state for an index.
104 * @param {number} index The index to set the selected state for.
105 * @param {boolean} b Whether to select the index or not.
107 setIndexSelected: function(index, b) {
108 // Only allow selection
109 var oldSelected = index == this.selectedIndex_;
110 if (oldSelected == b)
114 this.selectedIndex = index;
115 else if (index == this.selectedIndex_)
116 this.selectedIndex = -1;
120 * Whether a given index is selected or not.
121 * @param {number} index The index to check.
122 * @return {boolean} Whether an index is selected.
124 getIndexSelected: function(index) {
125 return index == this.selectedIndex_;
129 * This is used to begin batching changes. Call {@code endChange} when you
130 * are done making changes.
132 beginChange: function() {
133 if (!this.changeCount_) {
134 this.changeCount_ = 0;
135 this.selectedIndexBefore_ = this.selectedIndex_;
141 * Call this after changes are done and it will dispatch a change event if
142 * any changes were actually done.
144 endChange: function() {
146 if (!this.changeCount_) {
147 if (this.selectedIndexBefore_ != this.selectedIndex_) {
148 var beforeChange = this.createChangeEvent('beforeChange');
149 if (this.dispatchEvent(beforeChange))
150 this.dispatchEvent(this.createChangeEvent('change'));
152 this.selectedIndex_ = this.selectedIndexBefore_;
158 * Creates event with specified name and fills its {changes} property.
159 * @param {string} eventName Event name.
161 createChangeEvent: function(eventName) {
162 var e = new Event(eventName);
163 var indexes = [this.selectedIndexBefore_, this.selectedIndex_];
164 e.changes = indexes.filter(function(index) {
166 }).map(function(index) {
169 selected: index == this.selectedIndex_
179 * The leadIndex is used with multiple selection and it is the index that
180 * the user is moving using the arrow keys.
184 return this.leadIndex_;
186 set leadIndex(leadIndex) {
187 var li = this.adjustIndex_(leadIndex);
188 if (li != this.leadIndex_) {
189 var oldLeadIndex = this.leadIndex_;
190 this.leadIndex_ = li;
191 cr.dispatchPropertyChange(this, 'leadIndex', li, oldLeadIndex);
192 cr.dispatchPropertyChange(this, 'anchorIndex', li, oldLeadIndex);
196 adjustIndex_: function(index) {
197 index = Math.max(-1, Math.min(this.length_ - 1, index));
198 if (!this.independentLeadItem_)
199 index = this.selectedIndex;
204 * The anchorIndex is used with multiple selection.
208 return this.leadIndex;
210 set anchorIndex(anchorIndex) {
211 this.leadIndex = anchorIndex;
215 * Whether the selection model supports multiple selected items.
223 * Adjusts the selection after reordering of items in the table.
224 * @param {!Array.<number>} permutation The reordering permutation.
226 adjustToReordering: function(permutation) {
227 if (this.leadIndex != -1)
228 this.leadIndex = permutation[this.leadIndex];
230 var oldSelectedIndex = this.selectedIndex;
231 if (oldSelectedIndex != -1) {
232 this.selectedIndex = permutation[oldSelectedIndex];
237 * Adjusts selection model length.
238 * @param {number} length New selection model length.
240 adjustLength: function(length) {
241 this.length_ = length;
246 ListSingleSelectionModel: ListSingleSelectionModel