_EditManager.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.grid._EditManager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.grid._EditManager"] = true;
  8. dojo.provide("dojox.grid._EditManager");
  9. dojo.require("dojox.grid.util");
  10. dojo.declare("dojox.grid._EditManager", null, {
  11. // summary:
  12. // Controls grid cell editing process. Owned by grid and used internally for editing.
  13. constructor: function(inGrid){
  14. // inGrid: dojox.Grid
  15. // The dojox.Grid this editor should be attached to
  16. this.grid = inGrid;
  17. if(dojo.isIE){
  18. this.connections = [dojo.connect(document.body, "onfocus", dojo.hitch(this, "_boomerangFocus"))];
  19. }else{
  20. this.connections = [dojo.connect(this.grid, 'onBlur', this, 'apply')];
  21. }
  22. },
  23. info: {},
  24. destroy: function(){
  25. dojo.forEach(this.connections,dojo.disconnect);
  26. },
  27. cellFocus: function(inCell, inRowIndex){
  28. // summary:
  29. // Invoke editing when cell is focused
  30. // inCell: cell object
  31. // Grid cell object
  32. // inRowIndex: Integer
  33. // Grid row index
  34. if(this.grid.singleClickEdit || this.isEditRow(inRowIndex)){
  35. // if same row or quick editing, edit
  36. this.setEditCell(inCell, inRowIndex);
  37. }else{
  38. // otherwise, apply any pending row edits
  39. this.apply();
  40. }
  41. // if dynamic or static editing...
  42. if(this.isEditing() || (inCell && inCell.editable && inCell.alwaysEditing)){
  43. // let the editor focus itself as needed
  44. this._focusEditor(inCell, inRowIndex);
  45. }
  46. },
  47. rowClick: function(e){
  48. if(this.isEditing() && !this.isEditRow(e.rowIndex)){
  49. this.apply();
  50. }
  51. },
  52. styleRow: function(inRow){
  53. if(inRow.index == this.info.rowIndex){
  54. inRow.customClasses += ' dojoxGridRowEditing';
  55. }
  56. },
  57. dispatchEvent: function(e){
  58. var c = e.cell, ed = (c && c["editable"]) ? c : 0;
  59. return ed && ed.dispatchEvent(e.dispatch, e);
  60. },
  61. // Editing
  62. isEditing: function(){
  63. // summary:
  64. // Indicates editing state of the grid.
  65. // returns: Boolean
  66. // True if grid is actively editing
  67. return this.info.rowIndex !== undefined;
  68. },
  69. isEditCell: function(inRowIndex, inCellIndex){
  70. // summary:
  71. // Indicates if the given cell is being edited.
  72. // inRowIndex: Integer
  73. // Grid row index
  74. // inCellIndex: Integer
  75. // Grid cell index
  76. // returns: Boolean
  77. // True if given cell is being edited
  78. return (this.info.rowIndex === inRowIndex) && (this.info.cell.index == inCellIndex);
  79. },
  80. isEditRow: function(inRowIndex){
  81. // summary:
  82. // Indicates if the given row is being edited.
  83. // inRowIndex: Integer
  84. // Grid row index
  85. // returns: Boolean
  86. // True if given row is being edited
  87. return this.info.rowIndex === inRowIndex;
  88. },
  89. setEditCell: function(inCell, inRowIndex){
  90. // summary:
  91. // Set the given cell to be edited
  92. // inRowIndex: Integer
  93. // Grid row index
  94. // inCell: Object
  95. // Grid cell object
  96. if(!this.isEditCell(inRowIndex, inCell.index) && this.grid.canEdit && this.grid.canEdit(inCell, inRowIndex)){
  97. this.start(inCell, inRowIndex, this.isEditRow(inRowIndex) || inCell.editable);
  98. }
  99. },
  100. _focusEditor: function(inCell, inRowIndex){
  101. dojox.grid.util.fire(inCell, "focus", [inRowIndex]);
  102. },
  103. focusEditor: function(){
  104. if(this.isEditing()){
  105. this._focusEditor(this.info.cell, this.info.rowIndex);
  106. }
  107. },
  108. // implement fix for focus boomerang effect on IE
  109. _boomerangWindow: 500,
  110. _shouldCatchBoomerang: function(){
  111. return this._catchBoomerang > new Date().getTime();
  112. },
  113. _boomerangFocus: function(){
  114. //console.log("_boomerangFocus");
  115. if(this._shouldCatchBoomerang()){
  116. // make sure we don't utterly lose focus
  117. this.grid.focus.focusGrid();
  118. // let the editor focus itself as needed
  119. this.focusEditor();
  120. // only catch once
  121. this._catchBoomerang = 0;
  122. }
  123. },
  124. _doCatchBoomerang: function(){
  125. // give ourselves a few ms to boomerang IE focus effects
  126. if(dojo.isIE){this._catchBoomerang = new Date().getTime() + this._boomerangWindow;}
  127. },
  128. // end boomerang fix API
  129. start: function(inCell, inRowIndex, inEditing){
  130. if(!this._isValidInput()){
  131. return;
  132. }
  133. if(dojo.isIE && this.grid._autoHeight){
  134. this._avoidUpdate();//workaround for #11101
  135. }
  136. this.grid.beginUpdate();
  137. this.editorApply();
  138. if(this.isEditing() && !this.isEditRow(inRowIndex)){
  139. this.applyRowEdit();
  140. this.grid.updateRow(inRowIndex);
  141. }
  142. if(inEditing){
  143. this.info = { cell: inCell, rowIndex: inRowIndex };
  144. this.grid.doStartEdit(inCell, inRowIndex);
  145. this.grid.updateRow(inRowIndex);
  146. }else{
  147. this.info = {};
  148. }
  149. this.grid.endUpdate();
  150. // make sure we don't utterly lose focus
  151. this.grid.focus.focusGrid();
  152. // let the editor focus itself as needed
  153. this._focusEditor(inCell, inRowIndex);
  154. // give ourselves a few ms to boomerang IE focus effects
  155. this._doCatchBoomerang();
  156. },
  157. _editorDo: function(inMethod){
  158. var c = this.info.cell;
  159. //c && c.editor && c.editor[inMethod](c, this.info.rowIndex);
  160. if(c && c.editable){
  161. c[inMethod](this.info.rowIndex);
  162. }
  163. },
  164. editorApply: function(){
  165. this._editorDo("apply");
  166. },
  167. editorCancel: function(){
  168. this._editorDo("cancel");
  169. },
  170. applyCellEdit: function(inValue, inCell, inRowIndex){
  171. if(this.grid.canEdit(inCell, inRowIndex)){
  172. this.grid.doApplyCellEdit(inValue, inRowIndex, inCell.field);
  173. }
  174. },
  175. applyRowEdit: function(){
  176. this.grid.doApplyEdit(this.info.rowIndex, this.info.cell.field);
  177. },
  178. apply: function(){
  179. // summary:
  180. // Apply a grid edit
  181. if(this.isEditing() && this._isValidInput()){
  182. this.grid.beginUpdate();
  183. this.editorApply();
  184. this.applyRowEdit();
  185. this.info = {};
  186. this.grid.endUpdate();
  187. this.grid.focus.focusGrid();
  188. this._doCatchBoomerang();
  189. }
  190. },
  191. cancel: function(){
  192. // summary:
  193. // Cancel a grid edit
  194. if(this.isEditing()){
  195. this.grid.beginUpdate();
  196. this.editorCancel();
  197. this.info = {};
  198. this.grid.endUpdate();
  199. this.grid.focus.focusGrid();
  200. this._doCatchBoomerang();
  201. }
  202. },
  203. save: function(inRowIndex, inView){
  204. // summary:
  205. // Save the grid editing state
  206. // inRowIndex: Integer
  207. // Grid row index
  208. // inView: Object
  209. // Grid view
  210. var c = this.info.cell;
  211. if(this.isEditRow(inRowIndex) && (!inView || c.view==inView) && c.editable){
  212. c.save(c, this.info.rowIndex);
  213. }
  214. },
  215. restore: function(inView, inRowIndex){
  216. // summary:
  217. // Restores the grid editing state
  218. // inRowIndex: Integer
  219. // Grid row index
  220. // inView: Object
  221. // Grid view
  222. var c = this.info.cell;
  223. if(this.isEditRow(inRowIndex) && c.view == inView && c.editable){
  224. c.restore(c, this.info.rowIndex);
  225. }
  226. },
  227. _isValidInput: function(){
  228. var w = (this.info.cell || {}).widget;
  229. if(!w || !w.isValid){
  230. //no validation needed
  231. return true;
  232. }
  233. w.focused = true;
  234. return w.isValid(true);
  235. },
  236. _avoidUpdate: function(){
  237. // Use a flag to temporarily skip grid.update() so that dijit.form.Form.resize()
  238. // or similar containers will not result into a deadlock(see #11101)
  239. var self = this;
  240. self._noUpdate = true;
  241. if(self._avoidUpdateHandler){
  242. clearTimeout(self._avoidUpdateHandler);
  243. }
  244. self._avoidUpdateHandler = setTimeout(function(){
  245. self._noUpdate = false;
  246. }, 100);
  247. }
  248. });
  249. }