source: trunk/web/addons/job_monarch/lib/extjs/source/widgets/grid/RowSelectionModel.js @ 619

Last change on this file since 619 was 619, checked in by ramonb, 15 years ago

lib/:

  • added new AJAX dependancies: ExtJS, pChart, Lightbox2
File size: 15.2 KB
Line 
1/*
2 * Ext JS Library 2.2.1
3 * Copyright(c) 2006-2009, Ext JS, LLC.
4 * licensing@extjs.com
5 *
6 * http://extjs.com/license
7 */
8
9/**
10 @class Ext.grid.RowSelectionModel
11 * @extends Ext.grid.AbstractSelectionModel
12 * The default SelectionModel used by {@link Ext.grid.GridPanel}.
13 * It supports multiple selections and keyboard selection/navigation. The objects stored
14 * as selections and returned by {@link #getSelected}, and {@link #getSelections} are
15 * the {@link Ext.data.Record Record}s which provide the data for the selected rows.
16 * @constructor
17 * @param {Object} config
18 */
19Ext.grid.RowSelectionModel = function(config){
20    Ext.apply(this, config);
21    this.selections = new Ext.util.MixedCollection(false, function(o){
22        return o.id;
23    });
24
25    this.last = false;
26    this.lastActive = false;
27
28    this.addEvents(
29        /**
30             * @event selectionchange
31             * Fires when the selection changes
32             * @param {SelectionModel} this
33             */
34            "selectionchange",
35        /**
36             * @event beforerowselect
37             * Fires when a row is being selected, return false to cancel.
38             * @param {SelectionModel} this
39             * @param {Number} rowIndex The index to be selected
40             * @param {Boolean} keepExisting False if other selections will be cleared
41             * @param {Record} record The record to be selected
42             */
43            "beforerowselect",
44        /**
45             * @event rowselect
46             * Fires when a row is selected.
47             * @param {SelectionModel} this
48             * @param {Number} rowIndex The selected index
49             * @param {Ext.data.Record} r The selected record
50             */
51            "rowselect",
52        /**
53             * @event rowdeselect
54             * Fires when a row is deselected.
55             * @param {SelectionModel} this
56             * @param {Number} rowIndex
57             * @param {Record} record
58             */
59            "rowdeselect"
60    );
61
62    Ext.grid.RowSelectionModel.superclass.constructor.call(this);
63};
64
65Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {
66    /**
67     * @cfg {Boolean} singleSelect
68     * True to allow selection of only one row at a time (defaults to false)
69     */
70    singleSelect : false,
71
72        /**
73         * @cfg {Boolean} moveEditorOnEnter
74         * False to turn off moving the editor to the next cell when the enter key is pressed
75         */
76    // private
77    initEvents : function(){
78
79        if(!this.grid.enableDragDrop && !this.grid.enableDrag){
80            this.grid.on("rowmousedown", this.handleMouseDown, this);
81        }else{ // allow click to work like normal
82            this.grid.on("rowclick", function(grid, rowIndex, e) {
83                if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
84                    this.selectRow(rowIndex, false);
85                    grid.view.focusRow(rowIndex);
86                }
87            }, this);
88        }
89
90        this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
91            "up" : function(e){
92                if(!e.shiftKey || this.singleSelect){
93                    this.selectPrevious(false);
94                }else if(this.last !== false && this.lastActive !== false){
95                    var last = this.last;
96                    this.selectRange(this.last,  this.lastActive-1);
97                    this.grid.getView().focusRow(this.lastActive);
98                    if(last !== false){
99                        this.last = last;
100                    }
101                }else{
102                    this.selectFirstRow();
103                }
104            },
105            "down" : function(e){
106                if(!e.shiftKey || this.singleSelect){
107                    this.selectNext(false);
108                }else if(this.last !== false && this.lastActive !== false){
109                    var last = this.last;
110                    this.selectRange(this.last,  this.lastActive+1);
111                    this.grid.getView().focusRow(this.lastActive);
112                    if(last !== false){
113                        this.last = last;
114                    }
115                }else{
116                    this.selectFirstRow();
117                }
118            },
119            scope: this
120        });
121
122        var view = this.grid.view;
123        view.on("refresh", this.onRefresh, this);
124        view.on("rowupdated", this.onRowUpdated, this);
125        view.on("rowremoved", this.onRemove, this);
126    },
127
128    // private
129    onRefresh : function(){
130        var ds = this.grid.store, index;
131        var s = this.getSelections();
132        this.clearSelections(true);
133        for(var i = 0, len = s.length; i < len; i++){
134            var r = s[i];
135            if((index = ds.indexOfId(r.id)) != -1){
136                this.selectRow(index, true);
137            }
138        }
139        if(s.length != this.selections.getCount()){
140            this.fireEvent("selectionchange", this);
141        }
142    },
143
144    // private
145    onRemove : function(v, index, r){
146        if(this.selections.remove(r) !== false){
147            this.fireEvent('selectionchange', this);
148        }
149    },
150
151    // private
152    onRowUpdated : function(v, index, r){
153        if(this.isSelected(r)){
154            v.onRowSelect(index);
155        }
156    },
157
158    /**
159     * Select records.
160     * @param {Array} records The records to select
161     * @param {Boolean} keepExisting (optional) True to keep existing selections
162     */
163    selectRecords : function(records, keepExisting){
164        if(!keepExisting){
165            this.clearSelections();
166        }
167        var ds = this.grid.store;
168        for(var i = 0, len = records.length; i < len; i++){
169            this.selectRow(ds.indexOf(records[i]), true);
170        }
171    },
172
173    /**
174     * Gets the number of selected rows.
175     * @return {Number}
176     */
177    getCount : function(){
178        return this.selections.length;
179    },
180
181    /**
182     * Selects the first row in the grid.
183     */
184    selectFirstRow : function(){
185        this.selectRow(0);
186    },
187
188    /**
189     * Select the last row.
190     * @param {Boolean} keepExisting (optional) True to keep existing selections
191     */
192    selectLastRow : function(keepExisting){
193        this.selectRow(this.grid.store.getCount() - 1, keepExisting);
194    },
195
196    /**
197     * Selects the row immediately following the last selected row.
198     * @param {Boolean} keepExisting (optional) True to keep existing selections
199     * @return {Boolean} True if there is a next row, else false
200     */
201    selectNext : function(keepExisting){
202        if(this.hasNext()){
203            this.selectRow(this.last+1, keepExisting);
204            this.grid.getView().focusRow(this.last);
205                        return true;
206        }
207                return false;
208    },
209
210    /**
211     * Selects the row that precedes the last selected row.
212     * @param {Boolean} keepExisting (optional) True to keep existing selections
213     * @return {Boolean} True if there is a previous row, else false
214     */
215    selectPrevious : function(keepExisting){
216        if(this.hasPrevious()){
217            this.selectRow(this.last-1, keepExisting);
218            this.grid.getView().focusRow(this.last);
219                        return true;
220        }
221                return false;
222    },
223
224    /**
225     * Returns true if there is a next record to select
226     * @return {Boolean}
227     */
228    hasNext : function(){
229        return this.last !== false && (this.last+1) < this.grid.store.getCount();
230    },
231
232    /**
233     * Returns true if there is a previous record to select
234     * @return {Boolean}
235     */
236    hasPrevious : function(){
237        return !!this.last;
238    },
239
240
241    /**
242     * Returns the selected records
243     * @return {Array} Array of selected records
244     */
245    getSelections : function(){
246        return [].concat(this.selections.items);
247    },
248
249    /**
250     * Returns the first selected record.
251     * @return {Record}
252     */
253    getSelected : function(){
254        return this.selections.itemAt(0);
255    },
256
257    /**
258     * Calls the passed function with each selection. If the function returns false, iteration is
259     * stopped and this function returns false. Otherwise it returns true.
260     * @param {Function} fn
261     * @param {Object} scope (optional)
262     * @return {Boolean} true if all selections were iterated
263     */
264    each : function(fn, scope){
265        var s = this.getSelections();
266        for(var i = 0, len = s.length; i < len; i++){
267            if(fn.call(scope || this, s[i], i) === false){
268                return false;
269            }
270        }
271        return true;
272    },
273
274    /**
275     * Clears all selections.
276     */
277    clearSelections : function(fast){
278        if(this.isLocked()) return;
279        if(fast !== true){
280            var ds = this.grid.store;
281            var s = this.selections;
282            s.each(function(r){
283                this.deselectRow(ds.indexOfId(r.id));
284            }, this);
285            s.clear();
286        }else{
287            this.selections.clear();
288        }
289        this.last = false;
290    },
291
292
293    /**
294     * Selects all rows.
295     */
296    selectAll : function(){
297        if(this.isLocked()) return;
298        this.selections.clear();
299        for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
300            this.selectRow(i, true);
301        }
302    },
303
304    /**
305     * Returns True if there is a selection.
306     * @return {Boolean}
307     */
308    hasSelection : function(){
309        return this.selections.length > 0;
310    },
311
312    /**
313     * Returns True if the specified row is selected.
314     * @param {Number/Record} record The record or index of the record to check
315     * @return {Boolean}
316     */
317    isSelected : function(index){
318        var r = typeof index == "number" ? this.grid.store.getAt(index) : index;
319        return (r && this.selections.key(r.id) ? true : false);
320    },
321
322    /**
323     * Returns True if the specified record id is selected.
324     * @param {String} id The id of record to check
325     * @return {Boolean}
326     */
327    isIdSelected : function(id){
328        return (this.selections.key(id) ? true : false);
329    },
330
331    // private
332    handleMouseDown : function(g, rowIndex, e){
333        if(e.button !== 0 || this.isLocked()){
334            return;
335        };
336        var view = this.grid.getView();
337        if(e.shiftKey && !this.singleSelect && this.last !== false){
338            var last = this.last;
339            this.selectRange(last, rowIndex, e.ctrlKey);
340            this.last = last; // reset the last
341            view.focusRow(rowIndex);
342        }else{
343            var isSelected = this.isSelected(rowIndex);
344            if(e.ctrlKey && isSelected){
345                this.deselectRow(rowIndex);
346            }else if(!isSelected || this.getCount() > 1){
347                this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
348                view.focusRow(rowIndex);
349            }
350        }
351    },
352
353    /**
354     * Selects multiple rows.
355     * @param {Array} rows Array of the indexes of the row to select
356     * @param {Boolean} keepExisting (optional) True to keep existing selections (defaults to false)
357     */
358    selectRows : function(rows, keepExisting){
359        if(!keepExisting){
360            this.clearSelections();
361        }
362        for(var i = 0, len = rows.length; i < len; i++){
363            this.selectRow(rows[i], true);
364        }
365    },
366
367    /**
368     * Selects a range of rows. All rows in between startRow and endRow are also selected.
369     * @param {Number} startRow The index of the first row in the range
370     * @param {Number} endRow The index of the last row in the range
371     * @param {Boolean} keepExisting (optional) True to retain existing selections
372     */
373    selectRange : function(startRow, endRow, keepExisting){
374        if(this.isLocked()) return;
375        if(!keepExisting){
376            this.clearSelections();
377        }
378        if(startRow <= endRow){
379            for(var i = startRow; i <= endRow; i++){
380                this.selectRow(i, true);
381            }
382        }else{
383            for(var i = startRow; i >= endRow; i--){
384                this.selectRow(i, true);
385            }
386        }
387    },
388
389    /**
390     * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
391     * @param {Number} startRow The index of the first row in the range
392     * @param {Number} endRow The index of the last row in the range
393     */
394    deselectRange : function(startRow, endRow, preventViewNotify){
395        if(this.isLocked()) return;
396        for(var i = startRow; i <= endRow; i++){
397            this.deselectRow(i, preventViewNotify);
398        }
399    },
400
401    /**
402     * Selects a row.
403     * @param {Number} row The index of the row to select
404     * @param {Boolean} keepExisting (optional) True to keep existing selections
405     */
406    selectRow : function(index, keepExisting, preventViewNotify){
407        if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || this.isSelected(index)) return;
408        var r = this.grid.store.getAt(index);
409        if(r && this.fireEvent("beforerowselect", this, index, keepExisting, r) !== false){
410            if(!keepExisting || this.singleSelect){
411                this.clearSelections();
412            }
413            this.selections.add(r);
414            this.last = this.lastActive = index;
415            if(!preventViewNotify){
416                this.grid.getView().onRowSelect(index);
417            }
418            this.fireEvent("rowselect", this, index, r);
419            this.fireEvent("selectionchange", this);
420        }
421    },
422
423    /**
424     * Deselects a row.
425     * @param {Number} row The index of the row to deselect
426     */
427    deselectRow : function(index, preventViewNotify){
428        if(this.isLocked()) return;
429        if(this.last == index){
430            this.last = false;
431        }
432        if(this.lastActive == index){
433            this.lastActive = false;
434        }
435        var r = this.grid.store.getAt(index);
436        if(r){
437            this.selections.remove(r);
438            if(!preventViewNotify){
439                this.grid.getView().onRowDeselect(index);
440            }
441            this.fireEvent("rowdeselect", this, index, r);
442            this.fireEvent("selectionchange", this);
443        }
444    },
445
446    // private
447    restoreLast : function(){
448        if(this._last){
449            this.last = this._last;
450        }
451    },
452
453    // private
454    acceptsNav : function(row, col, cm){
455        return !cm.isHidden(col) && cm.isCellEditable(col, row);
456    },
457
458    // private
459    onEditorKey : function(field, e){
460        var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
461        var shift = e.shiftKey;
462        if(k == e.TAB){
463            e.stopEvent();
464            ed.completeEdit();
465            if(shift){
466                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
467            }else{
468                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
469            }
470        }else if(k == e.ENTER){
471            e.stopEvent();
472            ed.completeEdit();
473                        if(this.moveEditorOnEnter !== false){
474                                if(shift){
475                                        newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this);
476                                }else{
477                                        newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this);
478                                }
479                        }
480        }else if(k == e.ESC){
481            ed.cancelEdit();
482        }
483        if(newCell){
484            g.startEditing(newCell[0], newCell[1]);
485        }
486    }
487});
Note: See TracBrowser for help on using the repository browser.