X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/ee06f37b0f6f6d94cd05a6ffae556660f7c4a2bc..c930e9176a5a85509c5b0230e2bff5c22a591432:/docs/source/RowSelectionModel.html diff --git a/docs/source/RowSelectionModel.html b/docs/source/RowSelectionModel.html new file mode 100644 index 00000000..a3b280a5 --- /dev/null +++ b/docs/source/RowSelectionModel.html @@ -0,0 +1,526 @@ + + + The source code + + + + +
/** + * @class Ext.grid.RowSelectionModel + * @extends Ext.grid.AbstractSelectionModel + * The default SelectionModel used by {@link Ext.grid.GridPanel}. + * It supports multiple selections and keyboard selection/navigation. The objects stored + * as selections and returned by {@link #getSelected}, and {@link #getSelections} are + * the {@link Ext.data.Record Record}s which provide the data for the selected rows. + * @constructor + * @param {Object} config + */ +Ext.grid.RowSelectionModel = function(config){ + Ext.apply(this, config); + this.selections = new Ext.util.MixedCollection(false, function(o){ + return o.id; + }); + + this.last = false; + this.lastActive = false; + + this.addEvents( +
/** + * @event selectionchange + * Fires when the selection changes + * @param {SelectionModel} this + */ + "selectionchange", +
/** + * @event beforerowselect + * Fires before a row is selected, return false to cancel the selection. + * @param {SelectionModel} this + * @param {Number} rowIndex The index to be selected + * @param {Boolean} keepExisting False if other selections will be cleared + * @param {Record} record The record to be selected + */ + "beforerowselect", +
/** + * @event rowselect + * Fires when a row is selected. + * @param {SelectionModel} this + * @param {Number} rowIndex The selected index + * @param {Ext.data.Record} r The selected record + */ + "rowselect", +
/** + * @event rowdeselect + * Fires when a row is deselected. To prevent deselection + * {@link Ext.grid.AbstractSelectionModel#lock lock the selections}. + * @param {SelectionModel} this + * @param {Number} rowIndex + * @param {Record} record + */ + "rowdeselect" + ); + + Ext.grid.RowSelectionModel.superclass.constructor.call(this); +}; + +Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel, { +
/** + * @cfg {Boolean} singleSelect + * true to allow selection of only one row at a time (defaults to false + * allowing multiple selections) + */ + singleSelect : false, + +
/** + * @cfg {Boolean} moveEditorOnEnter + * false to turn off moving the editor to the next row down when the enter key is pressed + * or the next row up when shift + enter keys are pressed. + */ + // private + initEvents : function(){ + + if(!this.grid.enableDragDrop && !this.grid.enableDrag){ + this.grid.on("rowmousedown", this.handleMouseDown, this); + } + + this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), { + "up" : function(e){ + if(!e.shiftKey || this.singleSelect){ + this.selectPrevious(false); + }else if(this.last !== false && this.lastActive !== false){ + var last = this.last; + this.selectRange(this.last, this.lastActive-1); + this.grid.getView().focusRow(this.lastActive); + if(last !== false){ + this.last = last; + } + }else{ + this.selectFirstRow(); + } + }, + "down" : function(e){ + if(!e.shiftKey || this.singleSelect){ + this.selectNext(false); + }else if(this.last !== false && this.lastActive !== false){ + var last = this.last; + this.selectRange(this.last, this.lastActive+1); + this.grid.getView().focusRow(this.lastActive); + if(last !== false){ + this.last = last; + } + }else{ + this.selectFirstRow(); + } + }, + scope: this + }); + + var view = this.grid.view; + view.on("refresh", this.onRefresh, this); + view.on("rowupdated", this.onRowUpdated, this); + view.on("rowremoved", this.onRemove, this); + }, + + // private + onRefresh : function(){ + var ds = this.grid.store, index; + var s = this.getSelections(); + this.clearSelections(true); + for(var i = 0, len = s.length; i < len; i++){ + var r = s[i]; + if((index = ds.indexOfId(r.id)) != -1){ + this.selectRow(index, true); + } + } + if(s.length != this.selections.getCount()){ + this.fireEvent("selectionchange", this); + } + }, + + // private + onRemove : function(v, index, r){ + if(this.selections.remove(r) !== false){ + this.fireEvent('selectionchange', this); + } + }, + + // private + onRowUpdated : function(v, index, r){ + if(this.isSelected(r)){ + v.onRowSelect(index); + } + }, + +
/** + * Select records. + * @param {Array} records The records to select + * @param {Boolean} keepExisting (optional) true to keep existing selections + */ + selectRecords : function(records, keepExisting){ + if(!keepExisting){ + this.clearSelections(); + } + var ds = this.grid.store; + for(var i = 0, len = records.length; i < len; i++){ + this.selectRow(ds.indexOf(records[i]), true); + } + }, + +
/** + * Gets the number of selected rows. + * @return {Number} + */ + getCount : function(){ + return this.selections.length; + }, + +
/** + * Selects the first row in the grid. + */ + selectFirstRow : function(){ + this.selectRow(0); + }, + +
/** + * Select the last row. + * @param {Boolean} keepExisting (optional) true to keep existing selections + */ + selectLastRow : function(keepExisting){ + this.selectRow(this.grid.store.getCount() - 1, keepExisting); + }, + +
/** + * Selects the row immediately following the last selected row. + * @param {Boolean} keepExisting (optional) true to keep existing selections + * @return {Boolean} true if there is a next row, else false + */ + selectNext : function(keepExisting){ + if(this.hasNext()){ + this.selectRow(this.last+1, keepExisting); + this.grid.getView().focusRow(this.last); + return true; + } + return false; + }, + +
/** + * Selects the row that precedes the last selected row. + * @param {Boolean} keepExisting (optional) true to keep existing selections + * @return {Boolean} true if there is a previous row, else false + */ + selectPrevious : function(keepExisting){ + if(this.hasPrevious()){ + this.selectRow(this.last-1, keepExisting); + this.grid.getView().focusRow(this.last); + return true; + } + return false; + }, + +
/** + * Returns true if there is a next record to select + * @return {Boolean} + */ + hasNext : function(){ + return this.last !== false && (this.last+1) < this.grid.store.getCount(); + }, + +
/** + * Returns true if there is a previous record to select + * @return {Boolean} + */ + hasPrevious : function(){ + return !!this.last; + }, + + +
/** + * Returns the selected records + * @return {Array} Array of selected records + */ + getSelections : function(){ + return [].concat(this.selections.items); + }, + +
/** + * Returns the first selected record. + * @return {Record} + */ + getSelected : function(){ + return this.selections.itemAt(0); + }, + +
/** + * Calls the passed function with each selection. If the function returns + * false, iteration is stopped and this function returns + * false. Otherwise it returns true. + * @param {Function} fn + * @param {Object} scope (optional) + * @return {Boolean} true if all selections were iterated + */ + each : function(fn, scope){ + var s = this.getSelections(); + for(var i = 0, len = s.length; i < len; i++){ + if(fn.call(scope || this, s[i], i) === false){ + return false; + } + } + return true; + }, + +
/** + * Clears all selections if the selection model + * {@link Ext.grid.AbstractSelectionModel#isLocked is not locked}. + * @param {Boolean} fast (optional) true to bypass the + * conditional checks and events described in {@link #deselectRow}. + */ + clearSelections : function(fast){ + if(this.isLocked()){ + return; + } + if(fast !== true){ + var ds = this.grid.store; + var s = this.selections; + s.each(function(r){ + this.deselectRow(ds.indexOfId(r.id)); + }, this); + s.clear(); + }else{ + this.selections.clear(); + } + this.last = false; + }, + + +
/** + * Selects all rows if the selection model + * {@link Ext.grid.AbstractSelectionModel#isLocked is not locked}. + */ + selectAll : function(){ + if(this.isLocked()){ + return; + } + this.selections.clear(); + for(var i = 0, len = this.grid.store.getCount(); i < len; i++){ + this.selectRow(i, true); + } + }, + +
/** + * Returns true if there is a selection. + * @return {Boolean} + */ + hasSelection : function(){ + return this.selections.length > 0; + }, + +
/** + * Returns true if the specified row is selected. + * @param {Number/Record} index The record or index of the record to check + * @return {Boolean} + */ + isSelected : function(index){ + var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index; + return (r && this.selections.key(r.id) ? true : false); + }, + +
/** + * Returns true if the specified record id is selected. + * @param {String} id The id of record to check + * @return {Boolean} + */ + isIdSelected : function(id){ + return (this.selections.key(id) ? true : false); + }, + + // private + handleMouseDown : function(g, rowIndex, e){ + if(e.button !== 0 || this.isLocked()){ + return; + } + var view = this.grid.getView(); + if(e.shiftKey && !this.singleSelect && this.last !== false){ + var last = this.last; + this.selectRange(last, rowIndex, e.ctrlKey); + this.last = last; // reset the last + view.focusRow(rowIndex); + }else{ + var isSelected = this.isSelected(rowIndex); + if(e.ctrlKey && isSelected){ + this.deselectRow(rowIndex); + }else if(!isSelected || this.getCount() > 1){ + this.selectRow(rowIndex, e.ctrlKey || e.shiftKey); + view.focusRow(rowIndex); + } + } + }, + +
/** + * Selects multiple rows. + * @param {Array} rows Array of the indexes of the row to select + * @param {Boolean} keepExisting (optional) true to keep + * existing selections (defaults to false) + */ + selectRows : function(rows, keepExisting){ + if(!keepExisting){ + this.clearSelections(); + } + for(var i = 0, len = rows.length; i < len; i++){ + this.selectRow(rows[i], true); + } + }, + +
/** + * Selects a range of rows if the selection model + * {@link Ext.grid.AbstractSelectionModel#isLocked is not locked}. + * All rows in between startRow and endRow are also selected. + * @param {Number} startRow The index of the first row in the range + * @param {Number} endRow The index of the last row in the range + * @param {Boolean} keepExisting (optional) True to retain existing selections + */ + selectRange : function(startRow, endRow, keepExisting){ + var i; + if(this.isLocked()){ + return; + } + if(!keepExisting){ + this.clearSelections(); + } + if(startRow <= endRow){ + for(i = startRow; i <= endRow; i++){ + this.selectRow(i, true); + } + }else{ + for(i = startRow; i >= endRow; i--){ + this.selectRow(i, true); + } + } + }, + +
/** + * Deselects a range of rows if the selection model + * {@link Ext.grid.AbstractSelectionModel#isLocked is not locked}. + * All rows in between startRow and endRow are also deselected. + * @param {Number} startRow The index of the first row in the range + * @param {Number} endRow The index of the last row in the range + */ + deselectRange : function(startRow, endRow, preventViewNotify){ + if(this.isLocked()){ + return; + } + for(var i = startRow; i <= endRow; i++){ + this.deselectRow(i, preventViewNotify); + } + }, + +
/** + * Selects a row. Before selecting a row, checks if the selection model + * {@link Ext.grid.AbstractSelectionModel#isLocked is locked} and fires the + * {@link #beforerowselect} event. If these checks are satisfied the row + * will be selected and followed up by firing the {@link #rowselect} and + * {@link #selectionchange} events. + * @param {Number} row The index of the row to select + * @param {Boolean} keepExisting (optional) true to keep existing selections + * @param {Boolean} preventViewNotify (optional) Specify true to + * prevent notifying the view (disables updating the selected appearance) + */ + selectRow : function(index, keepExisting, preventViewNotify){ + if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){ + return; + } + var r = this.grid.store.getAt(index); + if(r && this.fireEvent("beforerowselect", this, index, keepExisting, r) !== false){ + if(!keepExisting || this.singleSelect){ + this.clearSelections(); + } + this.selections.add(r); + this.last = this.lastActive = index; + if(!preventViewNotify){ + this.grid.getView().onRowSelect(index); + } + this.fireEvent("rowselect", this, index, r); + this.fireEvent("selectionchange", this); + } + }, + +
/** + * Deselects a row. Before deselecting a row, checks if the selection model + * {@link Ext.grid.AbstractSelectionModel#isLocked is locked}. + * If this check is satisfied the row will be deselected and followed up by + * firing the {@link #rowdeselect} and {@link #selectionchange} events. + * @param {Number} row The index of the row to deselect + * @param {Boolean} preventViewNotify (optional) Specify true to + * prevent notifying the view (disables updating the selected appearance) + */ + deselectRow : function(index, preventViewNotify){ + if(this.isLocked()){ + return; + } + if(this.last == index){ + this.last = false; + } + if(this.lastActive == index){ + this.lastActive = false; + } + var r = this.grid.store.getAt(index); + if(r){ + this.selections.remove(r); + if(!preventViewNotify){ + this.grid.getView().onRowDeselect(index); + } + this.fireEvent("rowdeselect", this, index, r); + this.fireEvent("selectionchange", this); + } + }, + + // private + restoreLast : function(){ + if(this._last){ + this.last = this._last; + } + }, + + // private + acceptsNav : function(row, col, cm){ + return !cm.isHidden(col) && cm.isCellEditable(col, row); + }, + + // private + onEditorKey : function(field, e){ + var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor; + var shift = e.shiftKey; + if(k == e.TAB){ + e.stopEvent(); + ed.completeEdit(); + if(shift){ + newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this); + }else{ + newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this); + } + }else if(k == e.ENTER){ + e.stopEvent(); + ed.completeEdit(); + if(this.moveEditorOnEnter !== false){ + if(shift){ + newCell = g.walkCells(ed.row - 1, ed.col, -1, this.acceptsNav, this); + }else{ + newCell = g.walkCells(ed.row + 1, ed.col, 1, this.acceptsNav, this); + } + } + }else if(k == e.ESC){ + ed.cancelEdit(); + } + if(newCell){ + g.startEditing(newCell[0], newCell[1]); + } + }, + + destroy: function(){ + if(this.rowNav){ + this.rowNav.disable(); + this.rowNav = null; + } + Ext.grid.RowSelectionModel.superclass.destroy.call(this); + } +});
+ + \ No newline at end of file