X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/7a654f8d43fdb43d78b63d90528bed6e86b608cc..refs/heads/master:/docs/source/Model2.html diff --git a/docs/source/Model2.html b/docs/source/Model2.html index 3ac66bb3..7a717ec3 100644 --- a/docs/source/Model2.html +++ b/docs/source/Model2.html @@ -1,45 +1,61 @@ -
+ +/** - * @class Ext.selection.Model - * @extends Ext.util.Observable - * - * Tracks what records are currently selected in a databound widget. - * - * This is an abstract class and is not meant to be directly used. + + + + +\ No newline at end of file +});The source code + + + + + + +/** + * Tracks what records are currently selected in a databound component. * - * DataBound UI widgets such as GridPanel, TreePanel, and ListView - * should subclass AbstractStoreSelectionModel and provide a way - * to binding to the 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. + * 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.AbstractStoreSelectionModel', + alternateClassName: 'Ext.AbstractSelectionModel', requires: ['Ext.data.StoreManager'], // lastSelected - /** + /** * @cfg {String} mode - * Modes of selection. - * Valid values are SINGLE, SIMPLE, and MULTI. Defaults to 'SINGLE' + * 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. */ - - /** + + /** * @cfg {Boolean} allowDeselect - * Allow users to deselect a record in a DataView, List or Grid. Only applicable when the SelectionModel's mode is 'SINGLE'. Defaults to false. + * Allow users to deselect a record in a DataView, List or Grid. + * Only applicable when the {@link #mode} is 'SINGLE'. */ allowDeselect: false, - /** - * @property selected - * READ-ONLY A MixedCollection that maintains all of the currently selected - * records. + /** + * @property {Ext.util.MixedCollection} selected + * A MixedCollection that maintains all of the currently selected records. Read-only. */ selected: null, - - - /** + + /** * 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. @@ -49,18 +65,18 @@ Ext.define('Ext.selection.Model', { constructor: function(cfg) { var me = this; - + cfg = cfg || {}; Ext.apply(me, cfg); - + me.addEvents( - /** - * @event selectionchange + /** + * @event * Fired after a selection change has occurred * @param {Ext.selection.Model} this - * @param {Array} selected The selected records + * @param {Ext.data.Model[]} selected The selected records */ - 'selectionchange' + 'selectionchange' ); me.modes = { @@ -74,17 +90,17 @@ Ext.define('Ext.selection.Model', { // maintains the currently selected records. me.selected = Ext.create('Ext.util.MixedCollection'); - + me.callParent(arguments); }, // binds the store to the selModel. bind : function(store, initial){ var me = this; - + if(!initial && me.store){ if(store !== me.store && me.store.autoDestroy){ - me.store.destroy(); + me.store.destroyStore(); }else{ me.store.un("add", me.onStoreAdd, me); me.store.un("clear", me.onStoreClear, me); @@ -108,32 +124,52 @@ Ext.define('Ext.selection.Model', { } }, - selectAll: function(silent) { - var selections = this.store.getRange(), + /** + * 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; - + len = selections.length, + start = me.getSelection().length; + + me.bulkChange = true; for (; i < len; i++) { - this.doSelect(selections[i], true, silent); + 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); }, - deselectAll: function() { - var selections = this.getSelection(), + /** + * 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; - + len = selections.length, + start = me.getSelection().length; + + me.bulkChange = true; for (; i < len; i++) { - this.doDeselect(selections[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) { + selectWithEvent: function(record, e, keepExisting) { var me = this; - + switch (me.selectionMode) { case 'MULTI': if (e.ctrlKey && me.isSelected(record)) { @@ -143,7 +179,7 @@ Ext.define('Ext.selection.Model', { } 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, false, false); + me.doSelect(record, keepExisting, false); } else { me.doSelect(record, false); } @@ -167,12 +203,12 @@ Ext.define('Ext.selection.Model', { } }, - /** + /** * 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 + * @param {Boolean} [keepExisting] True to retain existing selections */ selectRange : function(startRow, endRow, keepExisting, dir){ var me = this, @@ -182,22 +218,22 @@ Ext.define('Ext.selection.Model', { tmp, dontDeselect, records = []; - + if (me.isLocked()){ return; } - + if (!keepExisting) { - me.clearSelections(); + 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; @@ -216,7 +252,7 @@ Ext.define('Ext.selection.Model', { } else { dontDeselect = (dir == 'up') ? startRow : endRow; } - + for (i = startRow; i <= endRow; i++){ if (selectedCount == (endRow - startRow + 1)) { if (i != dontDeselect) { @@ -228,30 +264,33 @@ Ext.define('Ext.selection.Model', { } me.doMultiSelect(records, true); }, - - /** + + /** * Selects a record instance by record instance or index. - * @param {Ext.data.Model/Index} records An array of records or an index - * @param {Boolean} keepExisting - * @param {Boolean} suppressEvent Set to false to not fire a select event + * @param {Ext.data.Model[]/Number} records An array of records or an index + * @param {Boolean} [keepExisting] True to retain existing selections + * @param {Boolean} [suppressEvent] Set to true to not fire a select event */ select: function(records, keepExisting, suppressEvent) { - this.doSelect(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); + } }, - /** + /** * Deselects a record instance by record instance or index. - * @param {Ext.data.Model/Index} records An array of records or an index - * @param {Boolean} suppressEvent Set to false to not fire a deselect event + * @param {Ext.data.Model[]/Number} records An array of records or an index + * @param {Boolean} [suppressEvent] Set to 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) { return; } @@ -272,17 +311,24 @@ Ext.define('Ext.selection.Model', { 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; - me.doDeselect(me.getSelection(), true); } for (; i < len; i++) { @@ -290,11 +336,9 @@ Ext.define('Ext.selection.Model', { if (keepExisting && me.isSelected(record)) { continue; } - change = true; me.lastSelected = record; - selected.add(record); - me.onSelectChange(record, true, suppressEvent); + me.onSelectChange(record, true, suppressEvent, commit); } me.setLastFocused(record, suppressEvent); // fire selchange if there was a change and there is no suppressEvent flag @@ -305,38 +349,49 @@ Ext.define('Ext.selection.Model', { doDeselect: function(records, suppressEvent) { var me = this, selected = me.selected, - change = false, i = 0, - len, record; - + len, record, + attempted = 0, + accepted = 0; + if (me.locked) { - return; + return false; } if (typeof records === "number") { records = [me.store.getAt(records)]; + } else if (!Ext.isArray(records)) { + records = [records]; + } + + function commit () { + ++accepted; + selected.remove(record); } - records = !Ext.isArray(records) ? [records] : records; len = records.length; + for (; i < len; i++) { record = records[i]; - if (selected.remove(record)) { + if (me.isSelected(record)) { if (me.lastSelected == record) { me.lastSelected = selected.last(); } - me.onSelectChange(record, false, suppressEvent); - change = true; + ++attempted; + me.onSelectChange(record, false, suppressEvent, commit); } } + // fire selchange if there was a change and there is no suppressEvent flag - me.maybeFireSelectionChange(change && !suppressEvent); + me.maybeFireSelectionChange(accepted > 0 && !suppressEvent); + return accepted === attempted; }, doSingleSelect: function(record, suppressEvent) { var me = this, + changed = false, selected = me.selected; - + if (me.locked) { return; } @@ -345,22 +400,34 @@ Ext.define('Ext.selection.Model', { if (me.isSelected(record)) { return; } - if (selected.getCount() > 0) { - me.doDeselect(me.lastSelected, suppressEvent); + + 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; } - selected.add(record); - me.lastSelected = record; - me.onSelectChange(record, true, suppressEvent); - if (!suppressEvent) { - me.setLastFocused(record); + + me.onSelectChange(record, true, suppressEvent, commit); + + if (changed) { + if (!suppressEvent) { + me.setLastFocused(record); + } + me.maybeFireSelectionChange(!suppressEvent); } - me.maybeFireSelectionChange(!suppressEvent); }, - /** - * @param {Ext.data.Model} record - * Set a record as the last focused record. This does NOT mean + /** + * 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, @@ -368,10 +435,10 @@ Ext.define('Ext.selection.Model', { me.lastFocused = record; me.onLastFocusChanged(recordBeforeLast, record, supressFocus); }, - - /** + + /** * Determines if this record is currently focused. - * @param Ext.data.Record record + * @param {Ext.data.Model} record */ isFocused: function(record) { return record === this.getLastFocused(); @@ -381,39 +448,42 @@ Ext.define('Ext.selection.Model', { // fire selection change as long as true is not passed // into maybeFireSelectionChange maybeFireSelectionChange: function(fireEvent) { - if (fireEvent) { - var me = this; + var me = this; + if (fireEvent && !me.bulkChange) { me.fireEvent('selectionchange', me, me.getSelection()); } }, - /** + /** * Returns the last selected record. */ getLastSelected: function() { return this.lastSelected; }, - + getLastFocused: function() { return this.lastFocused; }, - /** + /** * Returns an array of the currently selected records. + * @return {Ext.data.Model[]} The selected records */ getSelection: function() { return this.selected.getRange(); }, - /** - * Returns the current selectionMode. SINGLE, MULTI or SIMPLE. + /** + * Returns the current selectionMode. + * @return {String} The selectionMode: 'SINGLE', 'MULTI' or 'SIMPLE'. */ getSelectionMode: function() { return this.selectionMode; }, - /** - * Sets the current selectionMode. SINGLE, MULTI or SIMPLE. + /** + * Sets the current selectionMode. + * @param {String} selModel 'SINGLE', 'MULTI' or 'SIMPLE'. */ setSelectionMode: function(selMode) { selMode = selMode ? selMode.toUpperCase() : 'SINGLE'; @@ -422,7 +492,7 @@ Ext.define('Ext.selection.Model', { this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE'; }, - /** + /** * Returns true if the selections are locked. * @return {Boolean} */ @@ -430,27 +500,26 @@ Ext.define('Ext.selection.Model', { return this.locked; }, - /** - * Locks the current selection and disables any changes from - * happening to the selection. - * @param {Boolean} locked + /** + * 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; }, - /** - * Returns <tt>true</tt> if the specified row is selected. - * @param {Record/Number} record The record or index of the record to check + /** + * 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; }, - - /** - * Returns true if there is a selected record. + + /** + * Returns true if there are any a selected records. * @return {Boolean} */ hasSelection: function() { @@ -484,7 +553,7 @@ Ext.define('Ext.selection.Model', { } me.clearSelections(); - + if (me.store.indexOf(lastFocused) !== -1) { // restore the last focus but supress restoring focus this.setLastFocused(lastFocused, true); @@ -494,16 +563,20 @@ Ext.define('Ext.selection.Model', { // perform the selection again me.doSelect(toBeSelected, false, true); } - + me.maybeFireSelectionChange(change); }, + /** + * 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 - var me = this; - me.selected.clear(); - me.lastSelected = null; - me.setLastFocused(null); + this.selected.clear(); + this.lastSelected = null; + this.setLastFocused(null); }, // when a record is added to a store @@ -514,14 +587,9 @@ Ext.define('Ext.selection.Model', { // when a store is cleared remove all selections // (if there were any) onStoreClear: function() { - var me = this, - selected = this.selected; - - if (selected.getCount > 0) { - selected.clear(); - me.lastSelected = null; - me.setLastFocused(null); - me.maybeFireSelectionChange(true); + if (this.selected.getCount > 0) { + this.clearSelections(); + this.maybeFireSelectionChange(true); } }, @@ -531,7 +599,7 @@ Ext.define('Ext.selection.Model', { onStoreRemove: function(store, record) { var me = this, selected = me.selected; - + if (me.locked || !me.pruneRemoved) { return; } @@ -547,6 +615,10 @@ Ext.define('Ext.selection.Model', { } }, + /** + * Returns the count of selected records. + * @return {Number} The number of selected records + */ getCount: function() { return this.selected.getCount(); }, @@ -580,4 +652,6 @@ Ext.define('Ext.selection.Model', { bindComponent: function(cmp) { } -});