define(["dojo/_base/declare", "dojo/_base/array", "dojo/_base/lang", "dojo/Stateful"], function(declare, arr, lang, Stateful){ return declare("dojox.widget.Selection", Stateful, { // summary: // Base class for widgets that manage a list of selected data items. constructor: function(){ this.selectedItems = []; }, // selectionMode: String // Valid values are: // // 1. "none": No selection can be done. // 2. "single": Only one item can be selected at a time. // 3. "multiple": Several item can be selected using the control key modifier. // Default value is "single". selectionMode: "single", _setSelectionModeAttr: function(value){ if(value != "none" && value != "single" && value != "multiple"){ value = "single"; //default value } if(value != this.selectionMode){ this.selectionMode = value; if(value == "none"){ this.set("selectedItems", null); }else if(value == "single"){ this.set("selectedItem", this.selectedItem); // null or last selected item } } }, // selectedItem: Object // In single selection mode, the selected item or in multiple selection mode the last selected item. // Warning: Do not use this property directly, make sure to call set() or get() methods. selectedItem: null, _setSelectedItemAttr: function(value){ if(this.selectedItem != value){ this._set("selectedItem", value); this.set("selectedItems", value ? [value] : null); } }, // selectedItems: Object[] // The list of selected items. // Warning: Do not use this property directly, make sure to call set() or get() methods. selectedItems: null, _setSelectedItemsAttr: function(value){ var oldSelectedItems = this.selectedItems; this.selectedItems = value; this.selectedItem = null; if(oldSelectedItems != null && oldSelectedItems.length>0){ this.updateRenderers(oldSelectedItems, true); } if(this.selectedItems && this.selectedItems.length>0){ this.selectedItem = this.selectedItems[0]; this.updateRenderers(this.selectedItems, true); } }, _getSelectedItemsAttr: function(){ return this.selectedItems == null ? [] : this.selectedItems.concat(); }, isItemSelected: function(item){ // summary: // Returns wether an item is selected or not. // item: Object // The item to test the selection for. if(this.selectedItems == null || this.selectedItems.length== 0){ return false; } return arr.some(this.selectedItems, lang.hitch(this, function(sitem){ return this.getIdentity(sitem) == this.getIdentity(item); })); }, getIdentity: function(item){ // summary: // This function must be implemented to return the id of a item. // item: Object // The item to query the identity for. }, setItemSelected: function(item, value){ // summary: // Change the selection state of an item. // item: Object // The item to change the selection state for. // value: Boolean // True to select the item, false to deselect it. if(this.selectionMode == "none" || item == null){ return; } // copy is returned var sel = this.get("selectedItems"); var old = this.get("selectedItems"); if(this.selectionMode == "single"){ if(value){ this.set("selectedItem", item); }else if(this.isItemSelected(item)){ this.set("selectedItems", null); } }else{ // multiple if(value){ if(this.isItemSelected(item)){ return; // already selected } if(sel == null){ sel = [item]; }else{ sel.unshift(item); } this.set("selectedItems", sel); }else{ var res = arr.filter(sel, function(sitem){ return sitem.id != item.id; }); if(res == null || res.length == sel.length){ return; // already not selected } this.set("selectedItems", res); } } }, selectFromEvent: function(e, item, renderer, dispatch){ // summary: // Applies selection triggered by an user interaction // e: Event // The source event of the user interaction. // item: Object // The render item that has been selected/deselected. // renderer: Object // The visual renderer of the selected/deselected item. // dispatch: Boolean // Whether an event must be dispatched or not. // returns: Boolean // Returns true if the selection has changed and false otherwise. // tags: // protected if(this.selectionMode == "none"){ return false; } var changed; var oldSelectedItem = this.get("selectedItem"); var selected = item ? this.isItemSelected(item): false; if(item == null){ if(!e.ctrlKey && this.selectedItem != null){ this.set("selectedItem", null); changed = true; } }else if(this.selectionMode == "multiple"){ if(e.ctrlKey){ this.setItemSelected(item, !selected); changed = true; }else{ this.set("selectedItem", item); changed = true; } }else{ // single if(e.ctrlKey){ //if the object is selected deselects it. this.set("selectedItem", selected ? null : item); changed = true; }else{ if(!selected){ this.set("selectedItem", item); changed = true; } } } if(dispatch && changed){ this.dispatchChange(oldSelectedItem, this.get("selectedItem"), renderer, e); } return changed; }, dispatchChange: function(oldSelectedItem, newSelectedItem, renderer, triggerEvent){ // summary: // Dispatch a selection change event. // oldSelectedItem: Object // The previously selectedItem. // newSelectedItem: Object // The new selectedItem. // renderer: Object // The visual renderer of the selected/deselected item. // triggerEvent: Event // The event that lead to the selection of the item. this.onChange({ oldValue: oldSelectedItem, newValue: newSelectedItem, renderer: renderer, triggerEvent: triggerEvent }); }, onChange: function(){ // summary: // Called when the selection changed. // tags: // callback } }); });