pkg-grid-editor-debug.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:22k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!
  2.  * Ext JS Library 3.1.0
  3.  * Copyright(c) 2006-2009 Ext JS, LLC
  4.  * licensing@extjs.com
  5.  * http://www.extjs.com/license
  6.  */
  7. /**
  8.  * @class Ext.grid.CellSelectionModel
  9.  * @extends Ext.grid.AbstractSelectionModel
  10.  * This class provides the basic implementation for <i>single</i> <b>cell</b> selection in a grid.
  11.  * The object stored as the selection contains the following properties:
  12.  * <div class="mdetail-params"><ul>
  13.  * <li><b>cell</b> : see {@link #getSelectedCell} 
  14.  * <li><b>record</b> : Ext.data.record The {@link Ext.data.Record Record}
  15.  * which provides the data for the row containing the selection</li>
  16.  * </ul></div>
  17.  * @constructor
  18.  * @param {Object} config The object containing the configuration of this model.
  19.  */
  20. Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
  21.     
  22.     constructor : function(config){
  23.         Ext.apply(this, config);
  24.     this.selection = null;
  25.     this.addEvents(
  26.         /**
  27.          * @event beforecellselect
  28.          * Fires before a cell is selected, return false to cancel the selection.
  29.          * @param {SelectionModel} this
  30.          * @param {Number} rowIndex The selected row index
  31.          * @param {Number} colIndex The selected cell index
  32.          */
  33.         "beforecellselect",
  34.         /**
  35.          * @event cellselect
  36.          * Fires when a cell is selected.
  37.          * @param {SelectionModel} this
  38.          * @param {Number} rowIndex The selected row index
  39.          * @param {Number} colIndex The selected cell index
  40.          */
  41.         "cellselect",
  42.         /**
  43.          * @event selectionchange
  44.          * Fires when the active selection changes.
  45.          * @param {SelectionModel} this
  46.          * @param {Object} selection null for no selection or an object with two properties
  47.          * <div class="mdetail-params"><ul>
  48.          * <li><b>cell</b> : see {@link #getSelectedCell} 
  49.          * <li><b>record</b> : Ext.data.record<p class="sub-desc">The {@link Ext.data.Record Record}
  50.          * which provides the data for the row containing the selection</p></li>
  51.          * </ul></div>
  52.          */
  53.         "selectionchange"
  54.     );
  55.     Ext.grid.CellSelectionModel.superclass.constructor.call(this);
  56.     },
  57.     /** @ignore */
  58.     initEvents : function(){
  59.         this.grid.on('cellmousedown', this.handleMouseDown, this);
  60.         this.grid.on(Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.handleKeyDown, this);
  61.         this.grid.getView().on({
  62.             scope: this,
  63.             refresh: this.onViewChange,
  64.             rowupdated: this.onRowUpdated,
  65.             beforerowremoved: this.clearSelections,
  66.             beforerowsinserted: this.clearSelections
  67.         });
  68.         if(this.grid.isEditor){
  69.             this.grid.on('beforeedit', this.beforeEdit,  this);
  70.         }
  71.     },
  72. //private
  73.     beforeEdit : function(e){
  74.         this.select(e.row, e.column, false, true, e.record);
  75.     },
  76. //private
  77.     onRowUpdated : function(v, index, r){
  78.         if(this.selection && this.selection.record == r){
  79.             v.onCellSelect(index, this.selection.cell[1]);
  80.         }
  81.     },
  82. //private
  83.     onViewChange : function(){
  84.         this.clearSelections(true);
  85.     },
  86. /**
  87.      * Returns an array containing the row and column indexes of the currently selected cell
  88.      * (e.g., [0, 0]), or null if none selected. The array has elements:
  89.      * <div class="mdetail-params"><ul>
  90.      * <li><b>rowIndex</b> : Number<p class="sub-desc">The index of the selected row</p></li>
  91.      * <li><b>cellIndex</b> : Number<p class="sub-desc">The index of the selected cell. 
  92.      * Due to possible column reordering, the cellIndex should <b>not</b> be used as an
  93.      * index into the Record's data. Instead, use the cellIndex to determine the <i>name</i>
  94.      * of the selected cell and use the field name to retrieve the data value from the record:<pre><code>
  95. // get name
  96. var fieldName = grid.getColumnModel().getDataIndex(cellIndex);
  97. // get data value based on name
  98. var data = record.get(fieldName);
  99.      * </code></pre></p></li>
  100.      * </ul></div>
  101.      * @return {Array} An array containing the row and column indexes of the selected cell, or null if none selected.
  102.  */
  103.     getSelectedCell : function(){
  104.         return this.selection ? this.selection.cell : null;
  105.     },
  106.     /**
  107.      * If anything is selected, clears all selections and fires the selectionchange event.
  108.      * @param {Boolean} preventNotify <tt>true</tt> to prevent the gridview from
  109.      * being notified about the change.
  110.      */
  111.     clearSelections : function(preventNotify){
  112.         var s = this.selection;
  113.         if(s){
  114.             if(preventNotify !== true){
  115.                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
  116.             }
  117.             this.selection = null;
  118.             this.fireEvent("selectionchange", this, null);
  119.         }
  120.     },
  121.     /**
  122.      * Returns <tt>true</tt> if there is a selection.
  123.      * @return {Boolean}
  124.      */
  125.     hasSelection : function(){
  126.         return this.selection ? true : false;
  127.     },
  128.     /** @ignore */
  129.     handleMouseDown : function(g, row, cell, e){
  130.         if(e.button !== 0 || this.isLocked()){
  131.             return;
  132.         }
  133.         this.select(row, cell);
  134.     },
  135.     /**
  136.      * Selects a cell.  Before selecting a cell, fires the
  137.      * {@link #beforecellselect} event.  If this check is satisfied the cell
  138.      * will be selected and followed up by  firing the {@link #cellselect} and
  139.      * {@link #selectionchange} events.
  140.      * @param {Number} rowIndex The index of the row to select
  141.      * @param {Number} colIndex The index of the column to select
  142.      * @param {Boolean} preventViewNotify (optional) Specify <tt>true</tt> to
  143.      * prevent notifying the view (disables updating the selected appearance)
  144.      * @param {Boolean} preventFocus (optional) Whether to prevent the cell at
  145.      * the specified rowIndex / colIndex from being focused.
  146.      * @param {Ext.data.Record} r (optional) The record to select
  147.      */
  148.     select : function(rowIndex, colIndex, preventViewNotify, preventFocus, /*internal*/ r){
  149.         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
  150.             this.clearSelections();
  151.             r = r || this.grid.store.getAt(rowIndex);
  152.             this.selection = {
  153.                 record : r,
  154.                 cell : [rowIndex, colIndex]
  155.             };
  156.             if(!preventViewNotify){
  157.                 var v = this.grid.getView();
  158.                 v.onCellSelect(rowIndex, colIndex);
  159.                 if(preventFocus !== true){
  160.                     v.focusCell(rowIndex, colIndex);
  161.                 }
  162.             }
  163.             this.fireEvent("cellselect", this, rowIndex, colIndex);
  164.             this.fireEvent("selectionchange", this, this.selection);
  165.         }
  166.     },
  167. //private
  168.     isSelectable : function(rowIndex, colIndex, cm){
  169.         return !cm.isHidden(colIndex);
  170.     },
  171.     
  172.     // private
  173.     onEditorKey: function(field, e){
  174.         if(e.getKey() == e.TAB){
  175.             this.handleKeyDown(e);
  176.         }
  177.     },
  178.     /** @ignore */
  179.     handleKeyDown : function(e){
  180.         if(!e.isNavKeyPress()){
  181.             return;
  182.         }
  183.         
  184.         var k = e.getKey(),
  185.             g = this.grid,
  186.             s = this.selection,
  187.             sm = this,
  188.             walk = function(row, col, step){
  189.                 return g.walkCells(
  190.                     row,
  191.                     col,
  192.                     step,
  193.                     g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, // *** handle tabbing while editorgrid is in edit mode
  194.                     sm
  195.                 );
  196.             },
  197.             cell, newCell, r, c, ae;
  198.         switch(k){
  199.             case e.ESC:
  200.             case e.PAGE_UP:
  201.             case e.PAGE_DOWN:
  202.                 // do nothing
  203.                 break;
  204.             default:
  205.                 // *** call e.stopEvent() only for non ESC, PAGE UP/DOWN KEYS
  206.                 e.stopEvent();
  207.                 break;
  208.         }
  209.         if(!s){
  210.             cell = walk(0, 0, 1); // *** use private walk() function defined above
  211.             if(cell){
  212.                 this.select(cell[0], cell[1]);
  213.             }
  214.             return;
  215.         }
  216.         cell = s.cell;  // currently selected cell
  217.         r = cell[0];    // current row
  218.         c = cell[1];    // current column
  219.         
  220.         switch(k){
  221.             case e.TAB:
  222.                 if(e.shiftKey){
  223.                     newCell = walk(r, c - 1, -1);
  224.                 }else{
  225.                     newCell = walk(r, c + 1, 1);
  226.                 }
  227.                 break;
  228.             case e.DOWN:
  229.                 newCell = walk(r + 1, c, 1);
  230.                 break;
  231.             case e.UP:
  232.                 newCell = walk(r - 1, c, -1);
  233.                 break;
  234.             case e.RIGHT:
  235.                 newCell = walk(r, c + 1, 1);
  236.                 break;
  237.             case e.LEFT:
  238.                 newCell = walk(r, c - 1, -1);
  239.                 break;
  240.             case e.ENTER:
  241.                 if (g.isEditor && !g.editing) {
  242.                     g.startEditing(r, c);
  243.                     return;
  244.                 }
  245.                 break;
  246.         }
  247.         if(newCell){
  248.             // *** reassign r & c variables to newly-selected cell's row and column
  249.             r = newCell[0];
  250.             c = newCell[1];
  251.             this.select(r, c); // *** highlight newly-selected cell and update selection
  252.             if(g.isEditor && g.editing){ // *** handle tabbing while editorgrid is in edit mode
  253.                 ae = g.activeEditor;
  254.                 if(ae && ae.field.triggerBlur){
  255.                     // *** if activeEditor is a TriggerField, explicitly call its triggerBlur() method
  256.                     ae.field.triggerBlur();
  257.                 }
  258.                 g.startEditing(r, c);
  259.             }
  260.         }
  261.     },
  262.     acceptsNav : function(row, col, cm){
  263.         return !cm.isHidden(col) && cm.isCellEditable(col, row);
  264.     }
  265. });/**
  266.  * @class Ext.grid.EditorGridPanel
  267.  * @extends Ext.grid.GridPanel
  268.  * <p>This class extends the {@link Ext.grid.GridPanel GridPanel Class} to provide cell editing
  269.  * on selected {@link Ext.grid.Column columns}. The editable columns are specified by providing
  270.  * an {@link Ext.grid.ColumnModel#editor editor} in the {@link Ext.grid.Column column configuration}.</p>
  271.  * <p>Editability of columns may be controlled programatically by inserting an implementation
  272.  * of {@link Ext.grid.ColumnModel#isCellEditable isCellEditable} into the
  273.  * {@link Ext.grid.ColumnModel ColumnModel}.</p>
  274.  * <p>Editing is performed on the value of the <i>field</i> specified by the column's
  275.  * <tt>{@link Ext.grid.ColumnModel#dataIndex dataIndex}</tt> in the backing {@link Ext.data.Store Store}
  276.  * (so if you are using a {@link Ext.grid.ColumnModel#setRenderer renderer} in order to display
  277.  * transformed data, this must be accounted for).</p>
  278.  * <p>If a value-to-description mapping is used to render a column, then a {@link Ext.form.Field#ComboBox ComboBox}
  279.  * which uses the same {@link Ext.form.Field#valueField value}-to-{@link Ext.form.Field#displayFieldField description}
  280.  * mapping would be an appropriate editor.</p>
  281.  * If there is a more complex mismatch between the visible data in the grid, and the editable data in
  282.  * the {@link Edt.data.Store Store}, then code to transform the data both before and after editing can be
  283.  * injected using the {@link #beforeedit} and {@link #afteredit} events.
  284.  * @constructor
  285.  * @param {Object} config The config object
  286.  * @xtype editorgrid
  287.  */
  288. Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
  289.     /**
  290.      * @cfg {Number} clicksToEdit
  291.      * <p>The number of clicks on a cell required to display the cell's editor (defaults to 2).</p>
  292.      * <p>Setting this option to 'auto' means that mousedown <i>on the selected cell</i> starts
  293.      * editing that cell.</p>
  294.      */
  295.     clicksToEdit: 2,
  296.     
  297.     /**
  298.     * @cfg {Boolean} forceValidation
  299.     * True to force validation even if the value is unmodified (defaults to false)
  300.     */
  301.     forceValidation: false,
  302.     // private
  303.     isEditor : true,
  304.     // private
  305.     detectEdit: false,
  306. /**
  307.  * @cfg {Boolean} autoEncode
  308.  * True to automatically HTML encode and decode values pre and post edit (defaults to false)
  309.  */
  310. autoEncode : false,
  311. /**
  312.  * @cfg {Boolean} trackMouseOver @hide
  313.  */
  314.     // private
  315.     trackMouseOver: false, // causes very odd FF errors
  316.     // private
  317.     initComponent : function(){
  318.         Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
  319.         if(!this.selModel){
  320.             /**
  321.              * @cfg {Object} selModel Any subclass of AbstractSelectionModel that will provide the selection model for
  322.              * the grid (defaults to {@link Ext.grid.CellSelectionModel} if not specified).
  323.              */
  324.             this.selModel = new Ext.grid.CellSelectionModel();
  325.         }
  326.         this.activeEditor = null;
  327.     this.addEvents(
  328.             /**
  329.              * @event beforeedit
  330.              * Fires before cell editing is triggered. The edit event object has the following properties <br />
  331.              * <ul style="padding:5px;padding-left:16px;">
  332.              * <li>grid - This grid</li>
  333.              * <li>record - The record being edited</li>
  334.              * <li>field - The field name being edited</li>
  335.              * <li>value - The value for the field being edited.</li>
  336.              * <li>row - The grid row index</li>
  337.              * <li>column - The grid column index</li>
  338.              * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li>
  339.              * </ul>
  340.              * @param {Object} e An edit event (see above for description)
  341.              */
  342.             "beforeedit",
  343.             /**
  344.              * @event afteredit
  345.              * Fires after a cell is edited. The edit event object has the following properties <br />
  346.              * <ul style="padding:5px;padding-left:16px;">
  347.              * <li>grid - This grid</li>
  348.              * <li>record - The record being edited</li>
  349.              * <li>field - The field name being edited</li>
  350.              * <li>value - The value being set</li>
  351.              * <li>originalValue - The original value for the field, before the edit.</li>
  352.              * <li>row - The grid row index</li>
  353.              * <li>column - The grid column index</li>
  354.              * </ul>
  355.              *
  356.              * <pre><code> 
  357. grid.on('afteredit', afterEdit, this );
  358. function afterEdit(e) {
  359.     // execute an XHR to send/commit data to the server, in callback do (if successful):
  360.     e.record.commit();
  361. }; 
  362.              * </code></pre>
  363.              * @param {Object} e An edit event (see above for description)
  364.              */
  365.             "afteredit",
  366.             /**
  367.              * @event validateedit
  368.              * Fires after a cell is edited, but before the value is set in the record. Return false
  369.              * to cancel the change. The edit event object has the following properties <br />
  370.              * <ul style="padding:5px;padding-left:16px;">
  371.              * <li>grid - This grid</li>
  372.              * <li>record - The record being edited</li>
  373.              * <li>field - The field name being edited</li>
  374.              * <li>value - The value being set</li>
  375.              * <li>originalValue - The original value for the field, before the edit.</li>
  376.              * <li>row - The grid row index</li>
  377.              * <li>column - The grid column index</li>
  378.              * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li>
  379.              * </ul>
  380.              * Usage example showing how to remove the red triangle (dirty record indicator) from some
  381.              * records (not all).  By observing the grid's validateedit event, it can be cancelled if
  382.              * the edit occurs on a targeted row (for example) and then setting the field's new value
  383.              * in the Record directly:
  384.              * <pre><code> 
  385. grid.on('validateedit', function(e) {
  386.   var myTargetRow = 6;
  387.  
  388.   if (e.row == myTargetRow) {
  389.     e.cancel = true;
  390.     e.record.data[e.field] = e.value;
  391.   }
  392. });
  393.              * </code></pre>
  394.              * @param {Object} e An edit event (see above for description)
  395.              */
  396.             "validateedit"
  397.         );
  398.     },
  399.     // private
  400.     initEvents : function(){
  401.         Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
  402.         this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
  403.         this.on('columnresize', this.stopEditing, this, [true]);
  404.         if(this.clicksToEdit == 1){
  405.             this.on("cellclick", this.onCellDblClick, this);
  406.         }else {
  407.             var view = this.getView();
  408.             if(this.clicksToEdit == 'auto' && view.mainBody){
  409.                 view.mainBody.on('mousedown', this.onAutoEditClick, this);
  410.             }
  411.             this.on('celldblclick', this.onCellDblClick, this);
  412.         }
  413.     },
  414.     
  415.     onResize : function(){
  416.         Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
  417.         var ae = this.activeEditor;
  418.         if(this.editing && ae){
  419.             ae.realign(true);
  420.         }
  421.     },
  422.     // private
  423.     onCellDblClick : function(g, row, col){
  424.         this.startEditing(row, col);
  425.     },
  426.     // private
  427.     onAutoEditClick : function(e, t){
  428.         if(e.button !== 0){
  429.             return;
  430.         }
  431.         var row = this.view.findRowIndex(t),
  432.             col = this.view.findCellIndex(t);
  433.         if(row !== false && col !== false){
  434.             this.stopEditing();
  435.             if(this.selModel.getSelectedCell){ // cell sm
  436.                 var sc = this.selModel.getSelectedCell();
  437.                 if(sc && sc[0] === row && sc[1] === col){
  438.                     this.startEditing(row, col);
  439.                 }
  440.             }else{
  441.                 if(this.selModel.isSelected(row)){
  442.                     this.startEditing(row, col);
  443.                 }
  444.             }
  445.         }
  446.     },
  447.     // private
  448.     onEditComplete : function(ed, value, startValue){
  449.         this.editing = false;
  450.         this.activeEditor = null;
  451.         
  452. var r = ed.record,
  453.             field = this.colModel.getDataIndex(ed.col);
  454.         value = this.postEditValue(value, startValue, r, field);
  455.         if(this.forceValidation === true || String(value) !== String(startValue)){
  456.             var e = {
  457.                 grid: this,
  458.                 record: r,
  459.                 field: field,
  460.                 originalValue: startValue,
  461.                 value: value,
  462.                 row: ed.row,
  463.                 column: ed.col,
  464.                 cancel:false
  465.             };
  466.             if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
  467.                 r.set(field, e.value);
  468.                 delete e.cancel;
  469.                 this.fireEvent("afteredit", e);
  470.             }
  471.         }
  472.         this.view.focusCell(ed.row, ed.col);
  473.     },
  474.     /**
  475.      * Starts editing the specified for the specified row/column
  476.      * @param {Number} rowIndex
  477.      * @param {Number} colIndex
  478.      */
  479.     startEditing : function(row, col){
  480.         this.stopEditing();
  481.         if(this.colModel.isCellEditable(col, row)){
  482.             this.view.ensureVisible(row, col, true);
  483.             var r = this.store.getAt(row),
  484.                 field = this.colModel.getDataIndex(col),
  485.                 e = {
  486.                     grid: this,
  487.                     record: r,
  488.                     field: field,
  489.                     value: r.data[field],
  490.                     row: row,
  491.                     column: col,
  492.                     cancel:false
  493.                 };
  494.             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
  495.                 this.editing = true;
  496.                 var ed = this.colModel.getCellEditor(col, row);
  497.                 if(!ed){
  498.                     return;
  499.                 }
  500.                 if(!ed.rendered){
  501.                     ed.parentEl = this.view.getEditorParent(ed);
  502.                     ed.on({
  503.                         scope: this,
  504.                         render: {
  505.                             fn: function(c){
  506.                                 c.field.focus(false, true);
  507.                             },
  508.                             single: true,
  509.                             scope: this
  510.                         },
  511.                         specialkey: function(field, e){
  512.                             this.getSelectionModel().onEditorKey(field, e);
  513.                         },
  514.                         complete: this.onEditComplete,
  515.                         canceledit: this.stopEditing.createDelegate(this, [true])
  516.                     });
  517.                 }
  518.                 Ext.apply(ed, {
  519.                     row     : row,
  520.                     col     : col,
  521.                     record  : r
  522.                 });
  523.                 this.lastEdit = {
  524.                     row: row,
  525.                     col: col
  526.                 };
  527.                 this.activeEditor = ed;
  528.                 var v = this.preEditValue(r, field);
  529.                 ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
  530.             }
  531.         }
  532.     },
  533.     // private
  534.     preEditValue : function(r, field){
  535.         var value = r.data[field];
  536.         return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
  537.     },
  538.     // private
  539. postEditValue : function(value, originalValue, r, field){
  540. return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
  541. },
  542.     /**
  543.      * Stops any active editing
  544.      * @param {Boolean} cancel (optional) True to cancel any changes
  545.      */
  546.     stopEditing : function(cancel){
  547.         if(this.editing){
  548.             var ae = this.activeEditor;
  549.             if(ae){
  550.                 ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
  551.                 this.view.focusCell(ae.row, ae.col);
  552.             }
  553.             this.activeEditor = null;
  554.         }
  555.         this.editing = false;
  556.     }
  557. });
  558. Ext.reg('editorgrid', Ext.grid.EditorGridPanel);// private
  559. // This is a support class used internally by the Grid components
  560. Ext.grid.GridEditor = function(field, config){
  561.     Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
  562.     field.monitorTab = false;
  563. };
  564. Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
  565.     alignment: "tl-tl",
  566.     autoSize: "width",
  567.     hideEl : false,
  568.     cls: "x-small-editor x-grid-editor",
  569.     shim:false,
  570.     shadow:false
  571. });