_SelectionPreserver.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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.enhanced.plugins._SelectionPreserver"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.grid.enhanced.plugins._SelectionPreserver"] = true;
  8. dojo.provide("dojox.grid.enhanced.plugins._SelectionPreserver");
  9. dojo.declare("dojox.grid.enhanced.plugins._SelectionPreserver", null, {
  10. // summary:
  11. // Preserve selections across various user actions.
  12. //
  13. // description:
  14. // When this feature turned on, Grid will try to preserve selections across various user actions, e.g. sorting, filtering etc.
  15. // Precondition - Identifier(id) is required for store, as id is used for differentiating row items.
  16. // Known issue - The preserved selections might be inaccurate if some unloaded rows are selected by range previously(e.g.SHIFT + click)
  17. //
  18. // example:
  19. // | //To turn on this - set 'keepSelection' attribute to true
  20. // | <div dojoType="dojox.grid.EnhancedGrid" keepSelection = true .../>
  21. //_connects: Array
  22. // List of all connections.
  23. _connects: [],
  24. constructor: function(selection){
  25. this.selection = selection;
  26. var grid = this.grid = selection.grid;
  27. grid.onSelectedById = this.onSelectedById;
  28. this.reset();
  29. var oldClearData = grid._clearData;
  30. var _this = this;
  31. grid._clearData = function(){
  32. _this._updateMapping(!grid._noInternalMapping);
  33. _this._trustSelection = [];
  34. oldClearData.apply(grid, arguments);
  35. };
  36. this.connect(grid, '_setStore', 'reset');
  37. this.connect(grid, '_addItem', '_reSelectById');
  38. this.connect(selection, 'addToSelection', dojo.hitch(this, '_selectById', true));
  39. this.connect(selection, 'deselect', dojo.hitch(this, '_selectById', false));
  40. this.connect(selection, 'selectRange', dojo.hitch(this, '_updateMapping', true, true, false));
  41. this.connect(selection, 'deselectRange', dojo.hitch(this, '_updateMapping', true, false, false));
  42. this.connect(selection, 'deselectAll', dojo.hitch(this, '_updateMapping', true, false, true));
  43. },
  44. destroy: function(){
  45. this.reset();
  46. dojo.forEach(this._connects, dojo.disconnect);
  47. delete this._connects;
  48. },
  49. connect: function(obj, event, method){
  50. // summary:
  51. // Connects specified obj/event to specified method of this object.
  52. var conn = dojo.connect(obj, event, this, method);
  53. this._connects.push(conn);
  54. return conn;
  55. },
  56. reset: function(){
  57. this._idMap = [];
  58. this._selectedById = {};
  59. this._trustSelection = [];
  60. this._defaultSelected = false;
  61. },
  62. _reSelectById: function(item, index){
  63. // summary:
  64. // When some rows is fetched, determine whether it should be selected.
  65. // When this function is called, grid.selection.selected[] is not trustable.
  66. var s = this.selection, g = this.grid;
  67. if(item && g._hasIdentity){
  68. var id = g.store.getIdentity(item);
  69. if(this._selectedById[id] === undefined){
  70. if(!this._trustSelection[index]){
  71. s.selected[index] = this._defaultSelected;
  72. }
  73. }else{
  74. s.selected[index] = this._selectedById[id];
  75. }
  76. this._idMap.push(id);
  77. g.onSelectedById(id, index, s.selected[index]);
  78. }
  79. },
  80. _selectById: function(toSelect, inItemOrIndex){
  81. // summary:
  82. // Record selected rows by ID.
  83. if(this.selection.mode == 'none' || !this.grid._hasIdentity){ return; }
  84. var item = inItemOrIndex;
  85. if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
  86. var entry = this.grid._by_idx[inItemOrIndex];
  87. item = entry && entry.item;
  88. }
  89. if(item){
  90. var id = this.grid.store.getIdentity(item);
  91. this._selectedById[id] = !!toSelect;
  92. }else{
  93. this._trustSelection[inItemOrIndex] = true;
  94. }
  95. },
  96. onSelectedById: function(id, rowIndex, value){},
  97. _updateMapping: function(trustSelection, isSelect, isForAll, from, to){
  98. // summary:
  99. // This function trys to keep the selection info updated when range selection is performed.
  100. // 1. Calculate how many unloaded rows are there;
  101. // 2. update _selectedById data if grid.selection._selected can be trusted, so loaded but unselected rows can
  102. // be properly recorded.
  103. var s = this.selection, g = this.grid, flag = 0, unloaded = 0, i, id;
  104. for(i = g.rowCount - 1; i >= 0; --i){
  105. if(!g._by_idx[i]){
  106. ++unloaded;
  107. flag += s.selected[i] ? 1 : -1;
  108. }else{
  109. id = g._by_idx[i].idty;
  110. if(id && (trustSelection || this._selectedById[id] === undefined)){
  111. this._selectedById[id] = !!s.selected[i];
  112. }
  113. }
  114. }
  115. if(unloaded){
  116. this._defaultSelected = flag > 0;
  117. }
  118. if(!isForAll && from !== undefined && to !== undefined){
  119. isForAll = !g.usingPagination && Math.abs(to - from + 1) === g.rowCount;
  120. }
  121. // When deselectAll, make sure every thing is deselected, even if it was selected but not loaded now.
  122. // This occurs only when pagination's "All" is used.
  123. if(isForAll && !g.usingPagination){
  124. for(i = this._idMap.length; i >= 0; --i){
  125. this._selectedById[this._idMap[i]] = isSelect;
  126. }
  127. }
  128. }
  129. });
  130. }