| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 | 
							- <!DOCTYPE html>
 
- <html>
 
- <head>
 
-   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
-   <title>The source code</title>
 
-   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
 
-   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
 
-   <style type="text/css">
 
-     .highlight { display: block; background-color: #ddd; }
 
-   </style>
 
-   <script type="text/javascript">
 
-     function highlight() {
 
-       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
 
-     }
 
-   </script>
 
- </head>
 
- <body onload="prettyPrint(); highlight();">
 
-   <pre class="prettyprint lang-js"><span id='Ext-selection-Model'>/**
 
- </span> * Tracks what records are currently selected in a databound component.
 
-  *
 
-  * This is an abstract class and is not meant to be directly used. Databound UI widgets such as
 
-  * {@link Ext.grid.Panel Grid} and {@link Ext.tree.Panel Tree} should subclass Ext.selection.Model
 
-  * and provide a way to binding to the component.
 
-  *
 
-  * The abstract methods `onSelectChange` and `onLastFocusChanged` should be implemented in these
 
-  * subclasses to update the UI widget.
 
-  */
 
- Ext.define('Ext.selection.Model', {
 
-     extend: 'Ext.util.Observable',
 
-     alternateClassName: 'Ext.AbstractSelectionModel',
 
-     requires: ['Ext.data.StoreManager'],
 
-     mixins: {
 
-         bindable: 'Ext.util.Bindable'    
 
-     },
 
-     // lastSelected
 
- <span id='Ext-selection-Model-cfg-mode'>    /**
 
- </span>     * @cfg {String} mode
 
-      * Mode of selection.  Valid values are:
 
-      *
 
-      * - **SINGLE** - Only allows selecting one item at a time.  Use {@link #allowDeselect} to allow
 
-      *   deselecting that item.  This is the default.
 
-      * - **SIMPLE** - Allows simple selection of multiple items one-by-one. Each click in grid will either
 
-      *   select or deselect an item.
 
-      * - **MULTI** - Allows complex selection of multiple items using Ctrl and Shift keys.
 
-      */
 
- <span id='Ext-selection-Model-cfg-allowDeselect'>    /**
 
- </span>     * @cfg {Boolean} allowDeselect
 
-      * Allow users to deselect a record in a DataView, List or Grid.
 
-      * Only applicable when the {@link #mode} is 'SINGLE'.
 
-      */
 
-     allowDeselect: false,
 
- <span id='Ext-selection-Model-property-selected'>    /**
 
- </span>     * @property {Ext.util.MixedCollection} [selected=undefined]
 
-      * A MixedCollection that maintains all of the currently selected records.
 
-      * @readonly
 
-      */
 
-     selected: null,
 
- <span id='Ext-selection-Model-cfg-pruneRemoved'>    /**
 
- </span>     * @cfg {Boolean} pruneRemoved
 
-      * Prune records when they are removed from the store from the selection.
 
-      * This is a private flag. For an example of its usage, take a look at
 
-      * Ext.selection.TreeModel.
 
-      */
 
-     pruneRemoved: true,
 
-     constructor: function(cfg) {
 
-         var me = this;
 
-         cfg = cfg || {};
 
-         Ext.apply(me, cfg);
 
-         me.addEvents(
 
- <span id='Ext-selection-Model-event-selectionchange'>            /**
 
- </span>             * @event
 
-              * Fired after a selection change has occurred
 
-              * @param {Ext.selection.Model} this
 
-              * @param {Ext.data.Model[]} selected The selected records
 
-              */
 
-             'selectionchange',
 
- <span id='Ext-selection-Model-event-focuschange'>            /**
 
- </span>             * @event
 
-              * Fired when a row is focused
 
-              * @param {Ext.selection.Model} this
 
-              * @param {Ext.data.Model} oldFocused The previously focused record
 
-              * @param {Ext.data.Model} newFocused The newly focused record
 
-              */
 
-             'focuschange'
 
-         );
 
-         me.modes = {
 
-             SINGLE: true,
 
-             SIMPLE: true,
 
-             MULTI: true
 
-         };
 
-         // sets this.selectionMode
 
-         me.setSelectionMode(cfg.mode || me.mode);
 
-         // maintains the currently selected records.
 
-         me.selected = new Ext.util.MixedCollection();
 
-         me.callParent(arguments);
 
-     },
 
-     // binds the store to the selModel.
 
-     bindStore: function(store, initial){
 
-         var me = this;
 
-         me.mixins.bindable.bindStore.apply(me, arguments);
 
-         if(me.store && !initial) {
 
-             me.refresh();
 
-         }
 
-     },
 
-     
 
-     getStoreListeners: function() {
 
-         var me = this;
 
-         return {
 
-             add: me.onStoreAdd,
 
-             clear: me.onStoreClear,
 
-             remove: me.onStoreRemove,
 
-             update: me.onStoreUpdate    
 
-         }; 
 
-     },
 
- <span id='Ext-selection-Model-method-selectAll'>    /**
 
- </span>     * Selects all records in the view.
 
-      * @param {Boolean} suppressEvent True to suppress any select events
 
-      */
 
-     selectAll: function(suppressEvent) {
 
-         var me = this,
 
-             selections = me.store.getRange(),
 
-             i = 0,
 
-             len = selections.length,
 
-             start = me.getSelection().length;
 
-         me.bulkChange = true;
 
-         for (; i < len; i++) {
 
-             me.doSelect(selections[i], true, suppressEvent);
 
-         }
 
-         delete me.bulkChange;
 
-         // fire selection change only if the number of selections differs
 
-         me.maybeFireSelectionChange(me.getSelection().length !== start);
 
-     },
 
- <span id='Ext-selection-Model-method-deselectAll'>    /**
 
- </span>     * Deselects all records in the view.
 
-      * @param {Boolean} suppressEvent True to suppress any deselect events
 
-      */
 
-     deselectAll: function(suppressEvent) {
 
-         var me = this,
 
-             selections = me.getSelection(),
 
-             i = 0,
 
-             len = selections.length,
 
-             start = me.getSelection().length;
 
-         me.bulkChange = true;
 
-         for (; i < len; i++) {
 
-             me.doDeselect(selections[i], suppressEvent);
 
-         }
 
-         delete me.bulkChange;
 
-         // fire selection change only if the number of selections differs
 
-         me.maybeFireSelectionChange(me.getSelection().length !== start);
 
-     },
 
-     // Provides differentiation of logic between MULTI, SIMPLE and SINGLE
 
-     // selection modes. Requires that an event be passed so that we can know
 
-     // if user held ctrl or shift.
 
-     selectWithEvent: function(record, e, keepExisting) {
 
-         var me = this;
 
-         switch (me.selectionMode) {
 
-             case 'MULTI':
 
-                 if (e.ctrlKey && me.isSelected(record)) {
 
-                     me.doDeselect(record, false);
 
-                 } else if (e.shiftKey && me.lastFocused) {
 
-                     me.selectRange(me.lastFocused, record, e.ctrlKey);
 
-                 } else if (e.ctrlKey) {
 
-                     me.doSelect(record, true, false);
 
-                 } else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
 
-                     me.doSelect(record, keepExisting, false);
 
-                 } else {
 
-                     me.doSelect(record, false);
 
-                 }
 
-                 break;
 
-             case 'SIMPLE':
 
-                 if (me.isSelected(record)) {
 
-                     me.doDeselect(record);
 
-                 } else {
 
-                     me.doSelect(record, true);
 
-                 }
 
-                 break;
 
-             case 'SINGLE':
 
-                 // if allowDeselect is on and this record isSelected, deselect it
 
-                 if (me.allowDeselect && me.isSelected(record)) {
 
-                     me.doDeselect(record);
 
-                 // select the record and do NOT maintain existing selections
 
-                 } else {
 
-                     me.doSelect(record, false);
 
-                 }
 
-                 break;
 
-         }
 
-     },
 
- <span id='Ext-selection-Model-method-selectRange'>    /**
 
- </span>     * Selects a range of rows if the selection model {@link #isLocked is not locked}.
 
-      * All rows in between startRow and endRow are also selected.
 
-      * @param {Ext.data.Model/Number} startRow The record or index of the first row in the range
 
-      * @param {Ext.data.Model/Number} endRow The record or index of the last row in the range
 
-      * @param {Boolean} keepExisting (optional) True to retain existing selections
 
-      */
 
-     selectRange : function(startRow, endRow, keepExisting, dir){
 
-         var me = this,
 
-             store = me.store,
 
-             selectedCount = 0,
 
-             i,
 
-             tmp,
 
-             dontDeselect,
 
-             records = [];
 
-         if (me.isLocked()){
 
-             return;
 
-         }
 
-         if (!keepExisting) {
 
-             me.deselectAll(true);
 
-         }
 
-         if (!Ext.isNumber(startRow)) {
 
-             startRow = store.indexOf(startRow);
 
-         }
 
-         if (!Ext.isNumber(endRow)) {
 
-             endRow = store.indexOf(endRow);
 
-         }
 
-         // swap values
 
-         if (startRow > endRow){
 
-             tmp = endRow;
 
-             endRow = startRow;
 
-             startRow = tmp;
 
-         }
 
-         for (i = startRow; i <= endRow; i++) {
 
-             if (me.isSelected(store.getAt(i))) {
 
-                 selectedCount++;
 
-             }
 
-         }
 
-         if (!dir) {
 
-             dontDeselect = -1;
 
-         } else {
 
-             dontDeselect = (dir == 'up') ? startRow : endRow;
 
-         }
 
-         for (i = startRow; i <= endRow; i++){
 
-             if (selectedCount == (endRow - startRow + 1)) {
 
-                 if (i != dontDeselect) {
 
-                     me.doDeselect(i, true);
 
-                 }
 
-             } else {
 
-                 records.push(store.getAt(i));
 
-             }
 
-         }
 
-         me.doMultiSelect(records, true);
 
-     },
 
- <span id='Ext-selection-Model-method-select'>    /**
 
- </span>     * Selects a record instance by record instance or index.
 
-      * @param {Ext.data.Model[]/Number} records An array of records or an index
 
-      * @param {Boolean} [keepExisting=false] True to retain existing selections
 
-      * @param {Boolean} [suppressEvent=false] True to not fire a select event
 
-      */
 
-     select: function(records, keepExisting, suppressEvent) {
 
-         // Automatically selecting eg store.first() or store.last() will pass undefined, so that must just return;
 
-         if (Ext.isDefined(records)) {
 
-             this.doSelect(records, keepExisting, suppressEvent);
 
-         }
 
-     },
 
- <span id='Ext-selection-Model-method-deselect'>    /**
 
- </span>     * Deselects a record instance by record instance or index.
 
-      * @param {Ext.data.Model[]/Number} records An array of records or an index
 
-      * @param {Boolean} [suppressEvent=false] True to not fire a deselect event
 
-      */
 
-     deselect: function(records, suppressEvent) {
 
-         this.doDeselect(records, suppressEvent);
 
-     },
 
-     doSelect: function(records, keepExisting, suppressEvent) {
 
-         var me = this,
 
-             record;
 
-         if (me.locked || !me.store) {
 
-             return;
 
-         }
 
-         if (typeof records === "number") {
 
-             records = [me.store.getAt(records)];
 
-         }
 
-         if (me.selectionMode == "SINGLE" && records) {
 
-             record = records.length ? records[0] : records;
 
-             me.doSingleSelect(record, suppressEvent);
 
-         } else {
 
-             me.doMultiSelect(records, keepExisting, suppressEvent);
 
-         }
 
-     },
 
-     doMultiSelect: function(records, keepExisting, suppressEvent) {
 
-         var me = this,
 
-             selected = me.selected,
 
-             change = false,
 
-             i = 0,
 
-             len, record;
 
-         if (me.locked) {
 
-             return;
 
-         }
 
-         records = !Ext.isArray(records) ? [records] : records;
 
-         len = records.length;
 
-         if (!keepExisting && selected.getCount() > 0) {
 
-             if (me.doDeselect(me.getSelection(), suppressEvent) === false) {
 
-                 return;
 
-             }
 
-             // TODO - coalesce the selectionchange event in deselect w/the one below...
 
-         }
 
-         function commit () {
 
-             selected.add(record);
 
-             change = true;
 
-         }
 
-         for (; i < len; i++) {
 
-             record = records[i];
 
-             if (keepExisting && me.isSelected(record)) {
 
-                 continue;
 
-             }
 
-             me.lastSelected = record;
 
-             me.onSelectChange(record, true, suppressEvent, commit);
 
-         }
 
-         if (!me.preventFocus) {
 
-             me.setLastFocused(record, suppressEvent);
 
-         }
 
-         // fire selchange if there was a change and there is no suppressEvent flag
 
-         me.maybeFireSelectionChange(change && !suppressEvent);
 
-     },
 
-     // records can be an index, a record or an array of records
 
-     doDeselect: function(records, suppressEvent) {
 
-         var me = this,
 
-             selected = me.selected,
 
-             i = 0,
 
-             len, record,
 
-             attempted = 0,
 
-             accepted = 0;
 
-         if (me.locked || !me.store) {
 
-             return false;
 
-         }
 
-         if (typeof records === "number") {
 
-             records = [me.store.getAt(records)];
 
-         } else if (!Ext.isArray(records)) {
 
-             records = [records];
 
-         }
 
-         function commit () {
 
-             ++accepted;
 
-             selected.remove(record);
 
-         }
 
-         len = records.length;
 
-         for (; i < len; i++) {
 
-             record = records[i];
 
-             if (me.isSelected(record)) {
 
-                 if (me.lastSelected == record) {
 
-                     me.lastSelected = selected.last();
 
-                 }
 
-                 ++attempted;
 
-                 me.onSelectChange(record, false, suppressEvent, commit);
 
-             }
 
-         }
 
-         // fire selchange if there was a change and there is no suppressEvent flag
 
-         me.maybeFireSelectionChange(accepted > 0 && !suppressEvent);
 
-         return accepted === attempted;
 
-     },
 
-     doSingleSelect: function(record, suppressEvent) {
 
-         var me = this,
 
-             changed = false,
 
-             selected = me.selected;
 
-         if (me.locked) {
 
-             return;
 
-         }
 
-         // already selected.
 
-         // should we also check beforeselect?
 
-         if (me.isSelected(record)) {
 
-             return;
 
-         }
 
-         function commit () {
 
-             me.bulkChange = true;
 
-             if (selected.getCount() > 0 && me.doDeselect(me.lastSelected, suppressEvent) === false) {
 
-                 delete me.bulkChange;
 
-                 return false;
 
-             }
 
-             delete me.bulkChange;
 
-             selected.add(record);
 
-             me.lastSelected = record;
 
-             changed = true;
 
-         }
 
-         me.onSelectChange(record, true, suppressEvent, commit);
 
-         if (changed) {
 
-             if (!suppressEvent) {
 
-                 me.setLastFocused(record);
 
-             }
 
-             me.maybeFireSelectionChange(!suppressEvent);
 
-         }
 
-     },
 
- <span id='Ext-selection-Model-method-setLastFocused'>    /**
 
- </span>     * Sets a record as the last focused record. This does NOT mean
 
-      * that the record has been selected.
 
-      * @param {Ext.data.Model} record
 
-      */
 
-     setLastFocused: function(record, supressFocus) {
 
-         var me = this,
 
-             recordBeforeLast = me.lastFocused;
 
-         me.lastFocused = record;
 
-          
 
-         // Only call the changed method if in fact the selected record *has* changed.
 
-         if (record !== recordBeforeLast) {
 
-             me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
 
-         }
 
-     },
 
- <span id='Ext-selection-Model-method-isFocused'>    /**
 
- </span>     * Determines if this record is currently focused.
 
-      * @param {Ext.data.Model} record
 
-      */
 
-     isFocused: function(record) {
 
-         return record === this.getLastFocused();
 
-     },
 
-     // fire selection change as long as true is not passed
 
-     // into maybeFireSelectionChange
 
-     maybeFireSelectionChange: function(fireEvent) {
 
-         var me = this;
 
-         if (fireEvent && !me.bulkChange) {
 
-             me.fireEvent('selectionchange', me, me.getSelection());
 
-         }
 
-     },
 
- <span id='Ext-selection-Model-method-getLastSelected'>    /**
 
- </span>     * Returns the last selected record.
 
-      */
 
-     getLastSelected: function() {
 
-         return this.lastSelected;
 
-     },
 
-     getLastFocused: function() {
 
-         return this.lastFocused;
 
-     },
 
- <span id='Ext-selection-Model-method-getSelection'>    /**
 
- </span>     * Returns an array of the currently selected records.
 
-      * @return {Ext.data.Model[]} The selected records
 
-      */
 
-     getSelection: function() {
 
-         return this.selected.getRange();
 
-     },
 
- <span id='Ext-selection-Model-method-getSelectionMode'>    /**
 
- </span>     * Returns the current selectionMode.
 
-      * @return {String} The selectionMode: 'SINGLE', 'MULTI' or 'SIMPLE'.
 
-      */
 
-     getSelectionMode: function() {
 
-         return this.selectionMode;
 
-     },
 
- <span id='Ext-selection-Model-method-setSelectionMode'>    /**
 
- </span>     * Sets the current selectionMode.
 
-      * @param {String} selMode 'SINGLE', 'MULTI' or 'SIMPLE'.
 
-      */
 
-     setSelectionMode: function(selMode) {
 
-         selMode = selMode ? selMode.toUpperCase() : 'SINGLE';
 
-         // set to mode specified unless it doesnt exist, in that case
 
-         // use single.
 
-         this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE';
 
-     },
 
- <span id='Ext-selection-Model-method-isLocked'>    /**
 
- </span>     * Returns true if the selections are locked.
 
-      * @return {Boolean}
 
-      */
 
-     isLocked: function() {
 
-         return this.locked;
 
-     },
 
- <span id='Ext-selection-Model-method-setLocked'>    /**
 
- </span>     * Locks the current selection and disables any changes from happening to the selection.
 
-      * @param {Boolean} locked  True to lock, false to unlock.
 
-      */
 
-     setLocked: function(locked) {
 
-         this.locked = !!locked;
 
-     },
 
- <span id='Ext-selection-Model-method-isSelected'>    /**
 
- </span>     * Returns true if the specified row is selected.
 
-      * @param {Ext.data.Model/Number} record The record or index of the record to check
 
-      * @return {Boolean}
 
-      */
 
-     isSelected: function(record) {
 
-         record = Ext.isNumber(record) ? this.store.getAt(record) : record;
 
-         return this.selected.indexOf(record) !== -1;
 
-     },
 
- <span id='Ext-selection-Model-method-hasSelection'>    /**
 
- </span>     * Returns true if there are any a selected records.
 
-      * @return {Boolean}
 
-      */
 
-     hasSelection: function() {
 
-         return this.selected.getCount() > 0;
 
-     },
 
-     refresh: function() {
 
-         var me = this,
 
-             store = me.store,
 
-             toBeSelected = [],
 
-             oldSelections = me.getSelection(),
 
-             len = oldSelections.length,
 
-             selection,
 
-             change,
 
-             i = 0,
 
-             lastFocused = me.getLastFocused();
 
-         // Not been bound yet.
 
-         if (!store) {
 
-             return;
 
-         }
 
-         // check to make sure that there are no records
 
-         // missing after the refresh was triggered, prune
 
-         // them from what is to be selected if so
 
-         for (; i < len; i++) {
 
-             selection = oldSelections[i];
 
-             if (!me.pruneRemoved || store.indexOf(selection) !== -1) {
 
-                 toBeSelected.push(selection);
 
-             }
 
-         }
 
-         // there was a change from the old selected and
 
-         // the new selection
 
-         if (me.selected.getCount() != toBeSelected.length) {
 
-             change = true;
 
-         }
 
-         me.clearSelections();
 
-         if (store.indexOf(lastFocused) !== -1) {
 
-             // restore the last focus but supress restoring focus
 
-             me.setLastFocused(lastFocused, true);
 
-         }
 
-         if (toBeSelected.length) {
 
-             // perform the selection again
 
-             me.doSelect(toBeSelected, false, true);
 
-         }
 
-         me.maybeFireSelectionChange(change);
 
-     },
 
- <span id='Ext-selection-Model-method-clearSelections'>    /**
 
- </span>     * A fast reset of the selections without firing events, updating the ui, etc.
 
-      * For private usage only.
 
-      * @private
 
-      */
 
-     clearSelections: function() {
 
-         // reset the entire selection to nothing
 
-         this.selected.clear();
 
-         this.lastSelected = null;
 
-         this.setLastFocused(null);
 
-     },
 
-     // when a record is added to a store
 
-     onStoreAdd: Ext.emptyFn,
 
-     // when a store is cleared remove all selections
 
-     // (if there were any)
 
-     onStoreClear: function() {
 
-         if (this.selected.getCount > 0) {
 
-             this.clearSelections();
 
-             this.maybeFireSelectionChange(true);
 
-         }
 
-     },
 
-     // prune records from the SelectionModel if
 
-     // they were selected at the time they were
 
-     // removed.
 
-     onStoreRemove: function(store, record, index) {
 
-         var me = this,
 
-             selected = me.selected;
 
-         if (me.locked || !me.pruneRemoved) {
 
-             return;
 
-         }
 
-         if (selected.remove(record)) {
 
-             if (me.lastSelected == record) {
 
-                 me.lastSelected = null;
 
-             }
 
-             if (me.getLastFocused() == record) {
 
-                 me.setLastFocused(null);
 
-             }
 
-             me.maybeFireSelectionChange(true);
 
-         }
 
-     },
 
- <span id='Ext-selection-Model-method-getCount'>    /**
 
- </span>     * Returns the count of selected records.
 
-      * @return {Number} The number of selected records
 
-      */
 
-     getCount: function() {
 
-         return this.selected.getCount();
 
-     },
 
-     // cleanup.
 
-     destroy: Ext.emptyFn,
 
-     // if records are updated
 
-     onStoreUpdate: Ext.emptyFn,
 
- <span id='Ext-selection-Model-method-onStoreLoad'>    /**
 
- </span>     * @abstract
 
-      * @private
 
-      */
 
-     onStoreLoad: Ext.emptyFn,
 
-     // @abstract
 
-     onSelectChange: Ext.emptyFn,
 
-     // @abstract
 
-     onLastFocusChanged: function(oldFocused, newFocused) {
 
-         this.fireEvent('focuschange', this, oldFocused, newFocused);
 
-     },
 
-     // @abstract
 
-     onEditorKey: Ext.emptyFn,
 
-     // @abstract
 
-     bindComponent: Ext.emptyFn,
 
-     // @abstract
 
-     beforeViewRender: Ext.emptyFn
 
- });
 
- </pre>
 
- </body>
 
- </html>
 
 
  |