pkg-grid-editor-debug.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:20k
源码类别:

中间件编程

开发平台:

JavaScript

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