1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-selection.Model'>/**
2 </span> * @class Ext.selection.Model
3 * @extends Ext.util.Observable
5 * Tracks what records are currently selected in a databound widget.
7 * This is an abstract class and is not meant to be directly used.
9 * DataBound UI widgets such as GridPanel, TreePanel, and ListView
10 * should subclass AbstractStoreSelectionModel and provide a way
11 * to binding to the component.
13 * The abstract methods onSelectChange and onLastFocusChanged should
14 * be implemented in these subclasses to update the UI widget.
16 Ext.define('Ext.selection.Model', {
17 extend: 'Ext.util.Observable',
18 alternateClassName: 'Ext.AbstractStoreSelectionModel',
19 requires: ['Ext.data.StoreManager'],
22 <span id='Ext-selection.Model-cfg-mode'> /**
23 </span> * @cfg {String} mode
25 * Valid values are SINGLE, SIMPLE, and MULTI. Defaults to 'SINGLE'
28 <span id='Ext-selection.Model-cfg-allowDeselect'> /**
29 </span> * @cfg {Boolean} allowDeselect
30 * Allow users to deselect a record in a DataView, List or Grid. Only applicable when the SelectionModel's mode is 'SINGLE'. Defaults to false.
34 <span id='Ext-selection.Model-property-selected'> /**
35 </span> * @property selected
36 * READ-ONLY A MixedCollection that maintains all of the currently selected
42 <span id='Ext-selection.Model-property-pruneRemoved'> /**
43 </span> * Prune records when they are removed from the store from the selection.
44 * This is a private flag. For an example of its usage, take a look at
45 * Ext.selection.TreeModel.
50 constructor: function(cfg) {
57 <span id='Ext-selection.Model-event-selectionchange'> /**
58 </span> * @event selectionchange
59 * Fired after a selection change has occurred
60 * @param {Ext.selection.Model} this
61 * @param {Array} selected The selected records
72 // sets this.selectionMode
73 me.setSelectionMode(cfg.mode || me.mode);
75 // maintains the currently selected records.
76 me.selected = Ext.create('Ext.util.MixedCollection');
78 me.callParent(arguments);
81 // binds the store to the selModel.
82 bind : function(store, initial){
85 if(!initial && me.store){
86 if(store !== me.store && me.store.autoDestroy){
89 me.store.un("add", me.onStoreAdd, me);
90 me.store.un("clear", me.onStoreClear, me);
91 me.store.un("remove", me.onStoreRemove, me);
92 me.store.un("update", me.onStoreUpdate, me);
96 store = Ext.data.StoreManager.lookup(store);
99 clear: me.onStoreClear,
100 remove: me.onStoreRemove,
101 update: me.onStoreUpdate,
106 if(store && !initial) {
111 selectAll: function(silent) {
112 var selections = this.store.getRange(),
114 len = selections.length;
116 for (; i < len; i++) {
117 this.doSelect(selections[i], true, silent);
121 deselectAll: function() {
122 var selections = this.getSelection(),
124 len = selections.length;
126 for (; i < len; i++) {
127 this.doDeselect(selections[i]);
131 // Provides differentiation of logic between MULTI, SIMPLE and SINGLE
132 // selection modes. Requires that an event be passed so that we can know
133 // if user held ctrl or shift.
134 selectWithEvent: function(record, e) {
137 switch (me.selectionMode) {
139 if (e.ctrlKey && me.isSelected(record)) {
140 me.doDeselect(record, false);
141 } else if (e.shiftKey && me.lastFocused) {
142 me.selectRange(me.lastFocused, record, e.ctrlKey);
143 } else if (e.ctrlKey) {
144 me.doSelect(record, true, false);
145 } else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
146 me.doSelect(record, false, false);
148 me.doSelect(record, false);
152 if (me.isSelected(record)) {
153 me.doDeselect(record);
155 me.doSelect(record, true);
159 // if allowDeselect is on and this record isSelected, deselect it
160 if (me.allowDeselect && me.isSelected(record)) {
161 me.doDeselect(record);
162 // select the record and do NOT maintain existing selections
164 me.doSelect(record, false);
170 <span id='Ext-selection.Model-method-selectRange'> /**
171 </span> * Selects a range of rows if the selection model {@link #isLocked is not locked}.
172 * All rows in between startRow and endRow are also selected.
173 * @param {Ext.data.Model/Number} startRow The record or index of the first row in the range
174 * @param {Ext.data.Model/Number} endRow The record or index of the last row in the range
175 * @param {Boolean} keepExisting (optional) True to retain existing selections
177 selectRange : function(startRow, endRow, keepExisting, dir){
191 me.clearSelections();
194 if (!Ext.isNumber(startRow)) {
195 startRow = store.indexOf(startRow);
197 if (!Ext.isNumber(endRow)) {
198 endRow = store.indexOf(endRow);
202 if (startRow > endRow){
208 for (i = startRow; i <= endRow; i++) {
209 if (me.isSelected(store.getAt(i))) {
217 dontDeselect = (dir == 'up') ? startRow : endRow;
220 for (i = startRow; i <= endRow; i++){
221 if (selectedCount == (endRow - startRow + 1)) {
222 if (i != dontDeselect) {
223 me.doDeselect(i, true);
226 records.push(store.getAt(i));
229 me.doMultiSelect(records, true);
232 <span id='Ext-selection.Model-method-select'> /**
233 </span> * Selects a record instance by record instance or index.
234 * @param {Ext.data.Model/Index} records An array of records or an index
235 * @param {Boolean} keepExisting
236 * @param {Boolean} suppressEvent Set to false to not fire a select event
238 select: function(records, keepExisting, suppressEvent) {
239 this.doSelect(records, keepExisting, suppressEvent);
242 <span id='Ext-selection.Model-method-deselect'> /**
243 </span> * Deselects a record instance by record instance or index.
244 * @param {Ext.data.Model/Index} records An array of records or an index
245 * @param {Boolean} suppressEvent Set to false to not fire a deselect event
247 deselect: function(records, suppressEvent) {
248 this.doDeselect(records, suppressEvent);
251 doSelect: function(records, keepExisting, suppressEvent) {
258 if (typeof records === "number") {
259 records = [me.store.getAt(records)];
261 if (me.selectionMode == "SINGLE" && records) {
262 record = records.length ? records[0] : records;
263 me.doSingleSelect(record, suppressEvent);
265 me.doMultiSelect(records, keepExisting, suppressEvent);
269 doMultiSelect: function(records, keepExisting, suppressEvent) {
271 selected = me.selected,
281 records = !Ext.isArray(records) ? [records] : records;
282 len = records.length;
283 if (!keepExisting && selected.getCount() > 0) {
285 me.doDeselect(me.getSelection(), true);
288 for (; i < len; i++) {
290 if (keepExisting && me.isSelected(record)) {
294 me.lastSelected = record;
295 selected.add(record);
297 me.onSelectChange(record, true, suppressEvent);
299 me.setLastFocused(record, suppressEvent);
300 // fire selchange if there was a change and there is no suppressEvent flag
301 me.maybeFireSelectionChange(change && !suppressEvent);
304 // records can be an index, a record or an array of records
305 doDeselect: function(records, suppressEvent) {
307 selected = me.selected,
316 if (typeof records === "number") {
317 records = [me.store.getAt(records)];
320 records = !Ext.isArray(records) ? [records] : records;
321 len = records.length;
322 for (; i < len; i++) {
324 if (selected.remove(record)) {
325 if (me.lastSelected == record) {
326 me.lastSelected = selected.last();
328 me.onSelectChange(record, false, suppressEvent);
332 // fire selchange if there was a change and there is no suppressEvent flag
333 me.maybeFireSelectionChange(change && !suppressEvent);
336 doSingleSelect: function(record, suppressEvent) {
338 selected = me.selected;
344 // should we also check beforeselect?
345 if (me.isSelected(record)) {
348 if (selected.getCount() > 0) {
349 me.doDeselect(me.lastSelected, suppressEvent);
351 selected.add(record);
352 me.lastSelected = record;
353 me.onSelectChange(record, true, suppressEvent);
354 if (!suppressEvent) {
355 me.setLastFocused(record);
357 me.maybeFireSelectionChange(!suppressEvent);
360 <span id='Ext-selection.Model-method-setLastFocused'> /**
361 </span> * @param {Ext.data.Model} record
362 * Set a record as the last focused record. This does NOT mean
363 * that the record has been selected.
365 setLastFocused: function(record, supressFocus) {
367 recordBeforeLast = me.lastFocused;
368 me.lastFocused = record;
369 me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
372 <span id='Ext-selection.Model-method-isFocused'> /**
373 </span> * Determines if this record is currently focused.
374 * @param Ext.data.Record record
376 isFocused: function(record) {
377 return record === this.getLastFocused();
381 // fire selection change as long as true is not passed
382 // into maybeFireSelectionChange
383 maybeFireSelectionChange: function(fireEvent) {
386 me.fireEvent('selectionchange', me, me.getSelection());
390 <span id='Ext-selection.Model-method-getLastSelected'> /**
391 </span> * Returns the last selected record.
393 getLastSelected: function() {
394 return this.lastSelected;
397 getLastFocused: function() {
398 return this.lastFocused;
401 <span id='Ext-selection.Model-method-getSelection'> /**
402 </span> * Returns an array of the currently selected records.
404 getSelection: function() {
405 return this.selected.getRange();
408 <span id='Ext-selection.Model-method-getSelectionMode'> /**
409 </span> * Returns the current selectionMode. SINGLE, MULTI or SIMPLE.
411 getSelectionMode: function() {
412 return this.selectionMode;
415 <span id='Ext-selection.Model-method-setSelectionMode'> /**
416 </span> * Sets the current selectionMode. SINGLE, MULTI or SIMPLE.
418 setSelectionMode: function(selMode) {
419 selMode = selMode ? selMode.toUpperCase() : 'SINGLE';
420 // set to mode specified unless it doesnt exist, in that case
422 this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE';
425 <span id='Ext-selection.Model-method-isLocked'> /**
426 </span> * Returns true if the selections are locked.
429 isLocked: function() {
433 <span id='Ext-selection.Model-method-setLocked'> /**
434 </span> * Locks the current selection and disables any changes from
435 * happening to the selection.
436 * @param {Boolean} locked
438 setLocked: function(locked) {
439 this.locked = !!locked;
442 <span id='Ext-selection.Model-method-isSelected'> /**
443 </span> * Returns <tt>true</tt> if the specified row is selected.
444 * @param {Record/Number} record The record or index of the record to check
447 isSelected: function(record) {
448 record = Ext.isNumber(record) ? this.store.getAt(record) : record;
449 return this.selected.indexOf(record) !== -1;
452 <span id='Ext-selection.Model-method-hasSelection'> /**
453 </span> * Returns true if there is a selected record.
456 hasSelection: function() {
457 return this.selected.getCount() > 0;
460 refresh: function() {
463 oldSelections = me.getSelection(),
464 len = oldSelections.length,
468 lastFocused = this.getLastFocused();
470 // check to make sure that there are no records
471 // missing after the refresh was triggered, prune
472 // them from what is to be selected if so
473 for (; i < len; i++) {
474 selection = oldSelections[i];
475 if (!this.pruneRemoved || me.store.indexOf(selection) !== -1) {
476 toBeSelected.push(selection);
480 // there was a change from the old selected and
482 if (me.selected.getCount() != toBeSelected.length) {
486 me.clearSelections();
488 if (me.store.indexOf(lastFocused) !== -1) {
489 // restore the last focus but supress restoring focus
490 this.setLastFocused(lastFocused, true);
493 if (toBeSelected.length) {
494 // perform the selection again
495 me.doSelect(toBeSelected, false, true);
498 me.maybeFireSelectionChange(change);
501 clearSelections: function() {
502 // reset the entire selection to nothing
505 me.lastSelected = null;
506 me.setLastFocused(null);
509 // when a record is added to a store
510 onStoreAdd: function() {
514 // when a store is cleared remove all selections
515 // (if there were any)
516 onStoreClear: function() {
518 selected = this.selected;
520 if (selected.getCount > 0) {
522 me.lastSelected = null;
523 me.setLastFocused(null);
524 me.maybeFireSelectionChange(true);
528 // prune records from the SelectionModel if
529 // they were selected at the time they were
531 onStoreRemove: function(store, record) {
533 selected = me.selected;
535 if (me.locked || !me.pruneRemoved) {
539 if (selected.remove(record)) {
540 if (me.lastSelected == record) {
541 me.lastSelected = null;
543 if (me.getLastFocused() == record) {
544 me.setLastFocused(null);
546 me.maybeFireSelectionChange(true);
550 getCount: function() {
551 return this.selected.getCount();
555 destroy: function() {
559 // if records are updated
560 onStoreUpdate: function() {
565 onSelectChange: function(record, isSelected, suppressEvent) {
570 onLastFocusChanged: function(oldFocused, newFocused) {
575 onEditorKey: function(field, e) {
580 bindComponent: function(cmp) {
583 });</pre></pre></body></html>