123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- // Copyright 2007 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview Single-selection model implemenation.
- *
- * TODO(attila): Add keyboard & mouse event hooks?
- * TODO(attila): Add multiple selection?
- *
- * @author attila@google.com (Attila Bodis)
- */
- goog.provide('goog.ui.SelectionModel');
- goog.require('goog.array');
- goog.require('goog.events.EventTarget');
- goog.require('goog.events.EventType');
- /**
- * Single-selection model. Dispatches a {@link goog.events.EventType.SELECT}
- * event when a selection is made.
- * @param {Array<Object>=} opt_items Array of items; defaults to empty.
- * @extends {goog.events.EventTarget}
- * @constructor
- */
- goog.ui.SelectionModel = function(opt_items) {
- goog.events.EventTarget.call(this);
- /**
- * Array of items controlled by the selection model. If the items support
- * the {@code setSelected(Boolean)} interface, they will be (de)selected
- * as needed.
- * @type {!Array<Object>}
- * @private
- */
- this.items_ = [];
- this.addItems(opt_items);
- };
- goog.inherits(goog.ui.SelectionModel, goog.events.EventTarget);
- goog.tagUnsealableClass(goog.ui.SelectionModel);
- /**
- * The currently selected item (null if none).
- * @type {Object}
- * @private
- */
- goog.ui.SelectionModel.prototype.selectedItem_ = null;
- /**
- * Selection handler function. Called with two arguments (the item to be
- * selected or deselected, and a Boolean indicating whether the item is to
- * be selected or deselected).
- * @type {Function}
- * @private
- */
- goog.ui.SelectionModel.prototype.selectionHandler_ = null;
- /**
- * Returns the selection handler function used by the selection model to change
- * the internal selection state of items under its control.
- * @return {Function} Selection handler function (null if none).
- */
- goog.ui.SelectionModel.prototype.getSelectionHandler = function() {
- return this.selectionHandler_;
- };
- /**
- * Sets the selection handler function to be used by the selection model to
- * change the internal selection state of items under its control. The
- * function must take two arguments: an item and a Boolean to indicate whether
- * the item is to be selected or deselected. Selection handler functions are
- * only needed if the items in the selection model don't natively support the
- * {@code setSelected(Boolean)} interface.
- * @param {Function} handler Selection handler function.
- */
- goog.ui.SelectionModel.prototype.setSelectionHandler = function(handler) {
- this.selectionHandler_ = handler;
- };
- /**
- * Returns the number of items controlled by the selection model.
- * @return {number} Number of items.
- */
- goog.ui.SelectionModel.prototype.getItemCount = function() {
- return this.items_.length;
- };
- /**
- * Returns the 0-based index of the given item within the selection model, or
- * -1 if no such item is found.
- * @param {Object|undefined} item Item to look for.
- * @return {number} Index of the given item (-1 if none).
- */
- goog.ui.SelectionModel.prototype.indexOfItem = function(item) {
- return item ? goog.array.indexOf(this.items_, item) : -1;
- };
- /**
- * @return {Object|undefined} The first item, or undefined if there are no items
- * in the model.
- */
- goog.ui.SelectionModel.prototype.getFirst = function() {
- return this.items_[0];
- };
- /**
- * @return {Object|undefined} The last item, or undefined if there are no items
- * in the model.
- */
- goog.ui.SelectionModel.prototype.getLast = function() {
- return this.items_[this.items_.length - 1];
- };
- /**
- * Returns the item at the given 0-based index.
- * @param {number} index Index of the item to return.
- * @return {Object} Item at the given index (null if none).
- */
- goog.ui.SelectionModel.prototype.getItemAt = function(index) {
- return this.items_[index] || null;
- };
- /**
- * Bulk-adds items to the selection model. This is more efficient than calling
- * {@link #addItem} for each new item.
- * @param {Array<Object>|undefined} items New items to add.
- */
- goog.ui.SelectionModel.prototype.addItems = function(items) {
- if (items) {
- // New items shouldn't be selected.
- goog.array.forEach(
- items, function(item) { this.selectItem_(item, false); }, this);
- goog.array.extend(this.items_, items);
- }
- };
- /**
- * Adds an item at the end of the list.
- * @param {Object} item Item to add.
- */
- goog.ui.SelectionModel.prototype.addItem = function(item) {
- this.addItemAt(item, this.getItemCount());
- };
- /**
- * Adds an item at the given index.
- * @param {Object} item Item to add.
- * @param {number} index Index at which to add the new item.
- */
- goog.ui.SelectionModel.prototype.addItemAt = function(item, index) {
- if (item) {
- // New items must not be selected.
- this.selectItem_(item, false);
- goog.array.insertAt(this.items_, item, index);
- }
- };
- /**
- * Removes the given item (if it exists). Dispatches a {@code SELECT} event if
- * the removed item was the currently selected item.
- * @param {Object} item Item to remove.
- */
- goog.ui.SelectionModel.prototype.removeItem = function(item) {
- if (item && goog.array.remove(this.items_, item)) {
- if (item == this.selectedItem_) {
- this.selectedItem_ = null;
- this.dispatchEvent(goog.events.EventType.SELECT);
- }
- }
- };
- /**
- * Removes the item at the given index.
- * @param {number} index Index of the item to remove.
- */
- goog.ui.SelectionModel.prototype.removeItemAt = function(index) {
- this.removeItem(this.getItemAt(index));
- };
- /**
- * @return {Object} The currently selected item, or null if none.
- */
- goog.ui.SelectionModel.prototype.getSelectedItem = function() {
- return this.selectedItem_;
- };
- /**
- * @return {!Array<Object>} All items in the selection model.
- */
- goog.ui.SelectionModel.prototype.getItems = function() {
- return goog.array.clone(this.items_);
- };
- /**
- * Selects the given item, deselecting any previously selected item, and
- * dispatches a {@code SELECT} event.
- * @param {Object} item Item to select (null to clear the selection).
- */
- goog.ui.SelectionModel.prototype.setSelectedItem = function(item) {
- if (item != this.selectedItem_) {
- this.selectItem_(this.selectedItem_, false);
- this.selectedItem_ = item;
- this.selectItem_(item, true);
- }
- // Always dispatch a SELECT event; let listeners decide what to do if the
- // selected item hasn't changed.
- this.dispatchEvent(goog.events.EventType.SELECT);
- };
- /**
- * @return {number} The 0-based index of the currently selected item, or -1
- * if none.
- */
- goog.ui.SelectionModel.prototype.getSelectedIndex = function() {
- return this.indexOfItem(this.selectedItem_);
- };
- /**
- * Selects the item at the given index, deselecting any previously selected
- * item, and dispatches a {@code SELECT} event.
- * @param {number} index Index to select (-1 to clear the selection).
- */
- goog.ui.SelectionModel.prototype.setSelectedIndex = function(index) {
- this.setSelectedItem(this.getItemAt(index));
- };
- /**
- * Clears the selection model by removing all items from the selection.
- */
- goog.ui.SelectionModel.prototype.clear = function() {
- goog.array.clear(this.items_);
- this.selectedItem_ = null;
- };
- /** @override */
- goog.ui.SelectionModel.prototype.disposeInternal = function() {
- goog.ui.SelectionModel.superClass_.disposeInternal.call(this);
- delete this.items_;
- this.selectedItem_ = null;
- };
- /**
- * Private helper; selects or deselects the given item based on the value of
- * the {@code select} argument. If a selection handler has been registered
- * (via {@link #setSelectionHandler}, calls it to update the internal selection
- * state of the item. Otherwise, attempts to call {@code setSelected(Boolean)}
- * on the item itself, provided the object supports that interface.
- * @param {Object} item Item to select or deselect.
- * @param {boolean} select If true, the object will be selected; if false, it
- * will be deselected.
- * @private
- */
- goog.ui.SelectionModel.prototype.selectItem_ = function(item, select) {
- if (item) {
- if (typeof this.selectionHandler_ == 'function') {
- // Use the registered selection handler function.
- this.selectionHandler_(item, select);
- } else if (typeof item.setSelected == 'function') {
- // Call setSelected() on the item, if it supports it.
- item.setSelected(select);
- }
- }
- };
|