Path: blob/trunk/third_party/closure/goog/ui/selectionmodel.js
4503 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Single-selection model implemenation.8*9* TODO(attila): Add keyboard & mouse event hooks?10* TODO(attila): Add multiple selection?11*/121314goog.provide('goog.ui.SelectionModel');1516goog.require('goog.array');17goog.require('goog.events.EventTarget');18goog.require('goog.events.EventType');19202122/**23* Single-selection model. Dispatches a {@link goog.events.EventType.SELECT}24* event when a selection is made.25* @param {Array<Object>=} opt_items Array of items; defaults to empty.26* @extends {goog.events.EventTarget}27* @constructor28*/29goog.ui.SelectionModel = function(opt_items) {30'use strict';31goog.events.EventTarget.call(this);3233/**34* Array of items controlled by the selection model. If the items support35* the `setSelected(Boolean)` interface, they will be (de)selected36* as needed.37* @type {!Array<Object>}38* @private39*/40this.items_ = [];41this.addItems(opt_items);42};43goog.inherits(goog.ui.SelectionModel, goog.events.EventTarget);444546/**47* The currently selected item (null if none).48* @type {?Object}49* @private50*/51goog.ui.SelectionModel.prototype.selectedItem_ = null;525354/**55* Selection handler function. Called with two arguments (the item to be56* selected or deselected, and a Boolean indicating whether the item is to57* be selected or deselected).58* @type {?Function}59* @private60*/61goog.ui.SelectionModel.prototype.selectionHandler_ = null;626364/**65* Returns the selection handler function used by the selection model to change66* the internal selection state of items under its control.67* @return {Function} Selection handler function (null if none).68*/69goog.ui.SelectionModel.prototype.getSelectionHandler = function() {70'use strict';71return this.selectionHandler_;72};737475/**76* Sets the selection handler function to be used by the selection model to77* change the internal selection state of items under its control. The78* function must take two arguments: an item and a Boolean to indicate whether79* the item is to be selected or deselected. Selection handler functions are80* only needed if the items in the selection model don't natively support the81* `setSelected(Boolean)` interface.82* @param {Function} handler Selection handler function.83*/84goog.ui.SelectionModel.prototype.setSelectionHandler = function(handler) {85'use strict';86this.selectionHandler_ = handler;87};888990/**91* Returns the number of items controlled by the selection model.92* @return {number} Number of items.93*/94goog.ui.SelectionModel.prototype.getItemCount = function() {95'use strict';96return this.items_.length;97};9899100/**101* Returns the 0-based index of the given item within the selection model, or102* -1 if no such item is found.103* @param {Object|undefined} item Item to look for.104* @return {number} Index of the given item (-1 if none).105*/106goog.ui.SelectionModel.prototype.indexOfItem = function(item) {107'use strict';108return item ? this.items_.indexOf(item) : -1;109};110111112/**113* @return {Object|undefined} The first item, or undefined if there are no items114* in the model.115*/116goog.ui.SelectionModel.prototype.getFirst = function() {117'use strict';118return this.items_[0];119};120121122/**123* @return {Object|undefined} The last item, or undefined if there are no items124* in the model.125*/126goog.ui.SelectionModel.prototype.getLast = function() {127'use strict';128return this.items_[this.items_.length - 1];129};130131132/**133* Returns the item at the given 0-based index.134* @param {number} index Index of the item to return.135* @return {Object} Item at the given index (null if none).136*/137goog.ui.SelectionModel.prototype.getItemAt = function(index) {138'use strict';139return this.items_[index] || null;140};141142143/**144* Bulk-adds items to the selection model. This is more efficient than calling145* {@link #addItem} for each new item.146* @param {Array<Object>|undefined} items New items to add.147*/148goog.ui.SelectionModel.prototype.addItems = function(items) {149'use strict';150if (items) {151// New items shouldn't be selected.152items.forEach(function(item) {153'use strict';154this.selectItem_(item, false);155}, this);156goog.array.extend(this.items_, items);157}158};159160161/**162* Adds an item at the end of the list.163* @param {Object} item Item to add.164*/165goog.ui.SelectionModel.prototype.addItem = function(item) {166'use strict';167this.addItemAt(item, this.getItemCount());168};169170171/**172* Adds an item at the given index.173* @param {Object} item Item to add.174* @param {number} index Index at which to add the new item.175*/176goog.ui.SelectionModel.prototype.addItemAt = function(item, index) {177'use strict';178if (item) {179// New items must not be selected.180this.selectItem_(item, false);181goog.array.insertAt(this.items_, item, index);182}183};184185186/**187* Removes the given item (if it exists). Dispatches a `SELECT` event if188* the removed item was the currently selected item.189* @param {Object} item Item to remove.190*/191goog.ui.SelectionModel.prototype.removeItem = function(item) {192'use strict';193if (item && goog.array.remove(this.items_, item)) {194if (item == this.selectedItem_) {195this.selectedItem_ = null;196this.dispatchEvent(goog.events.EventType.SELECT);197}198}199};200201202/**203* Removes the item at the given index.204* @param {number} index Index of the item to remove.205*/206goog.ui.SelectionModel.prototype.removeItemAt = function(index) {207'use strict';208this.removeItem(this.getItemAt(index));209};210211212/**213* @return {Object} The currently selected item, or null if none.214*/215goog.ui.SelectionModel.prototype.getSelectedItem = function() {216'use strict';217return this.selectedItem_;218};219220221/**222* @return {!Array<Object>} All items in the selection model.223*/224goog.ui.SelectionModel.prototype.getItems = function() {225'use strict';226return goog.array.clone(this.items_);227};228229230/**231* Selects the given item, deselecting any previously selected item, and232* dispatches a `SELECT` event.233* @param {Object} item Item to select (null to clear the selection).234*/235goog.ui.SelectionModel.prototype.setSelectedItem = function(item) {236'use strict';237if (item != this.selectedItem_) {238this.selectItem_(this.selectedItem_, false);239this.selectedItem_ = item;240this.selectItem_(item, true);241}242243// Always dispatch a SELECT event; let listeners decide what to do if the244// selected item hasn't changed.245this.dispatchEvent(goog.events.EventType.SELECT);246};247248249/**250* @return {number} The 0-based index of the currently selected item, or -1251* if none.252*/253goog.ui.SelectionModel.prototype.getSelectedIndex = function() {254'use strict';255return this.indexOfItem(this.selectedItem_);256};257258259/**260* Selects the item at the given index, deselecting any previously selected261* item, and dispatches a `SELECT` event.262* @param {number} index Index to select (-1 to clear the selection).263*/264goog.ui.SelectionModel.prototype.setSelectedIndex = function(index) {265'use strict';266this.setSelectedItem(this.getItemAt(index));267};268269270/**271* Clears the selection model by removing all items from the selection.272*/273goog.ui.SelectionModel.prototype.clear = function() {274'use strict';275goog.array.clear(this.items_);276this.selectedItem_ = null;277};278279280/** @override */281goog.ui.SelectionModel.prototype.disposeInternal = function() {282'use strict';283goog.ui.SelectionModel.superClass_.disposeInternal.call(this);284delete this.items_;285this.selectedItem_ = null;286};287288289/**290* Private helper; selects or deselects the given item based on the value of291* the `select` argument. If a selection handler has been registered292* (via {@link #setSelectionHandler}, calls it to update the internal selection293* state of the item. Otherwise, attempts to call `setSelected(Boolean)`294* on the item itself, provided the object supports that interface.295* @param {Object} item Item to select or deselect.296* @param {boolean} select If true, the object will be selected; if false, it297* will be deselected.298* @private299*/300goog.ui.SelectionModel.prototype.selectItem_ = function(item, select) {301'use strict';302if (item) {303if (typeof this.selectionHandler_ == 'function') {304// Use the registered selection handler function.305this.selectionHandler_(item, select);306} else if (typeof item.setSelected == 'function') {307// Call setSelected() on the item, if it supports it.308item.setSelected(select);309}310}311};312313314