Rearrange.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  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.Rearrange"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.grid.enhanced.plugins.Rearrange"] = true;
  8. dojo.provide("dojox.grid.enhanced.plugins.Rearrange");
  9. dojo.require("dojox.grid.enhanced._Plugin");
  10. dojo.require("dojox.grid.enhanced.plugins._RowMapLayer");
  11. dojo.declare("dojox.grid.enhanced.plugins.Rearrange", dojox.grid.enhanced._Plugin, {
  12. // summary:
  13. // Provides a set of method to re-arrange the structure of grid.
  14. // name: String
  15. // plugin name
  16. name: "rearrange",
  17. constructor: function(grid, args){
  18. this.grid = grid;
  19. this.setArgs(args);
  20. var rowMapLayer = new dojox.grid.enhanced.plugins._RowMapLayer(grid);
  21. dojox.grid.enhanced.plugins.wrap(grid, "_storeLayerFetch", rowMapLayer);
  22. },
  23. setArgs: function(args){
  24. this.args = dojo.mixin(this.args || {}, args || {});
  25. this.args.setIdentifierForNewItem = this.args.setIdentifierForNewItem || function(v){return v;};
  26. },
  27. destroy: function(){
  28. this.inherited(arguments);
  29. this.grid.unwrap("rowmap");
  30. },
  31. onSetStore: function(store){
  32. this.grid.layer("rowmap").clearMapping();
  33. },
  34. _hasIdentity: function(points){
  35. var g = this.grid, s = g.store, cells = g.layout.cells;
  36. if(s.getFeatures()["dojo.data.api.Identity"]){
  37. if(dojo.some(points, function(point){
  38. return s.getIdentityAttributes(g._by_idx[point.r].item) == cells[point.c].field;
  39. })){
  40. return true;
  41. }
  42. }
  43. return false;
  44. },
  45. moveColumns: function(colsToMove, targetPos){
  46. // summary:
  47. // Move a set of columns to a given position.
  48. // tag:
  49. // public
  50. // colsToMove: Integer[]
  51. // Array of column indexes.
  52. // targetPos: Integer
  53. // The target position
  54. var g = this.grid,
  55. layout = g.layout,
  56. cells = layout.cells,
  57. colIndex, i, delta = 0,
  58. before = true, tmp = {}, mapping = {};
  59. colsToMove.sort(function(a, b){
  60. return a - b;
  61. });
  62. for(i = 0; i < colsToMove.length; ++i){
  63. tmp[colsToMove[i]] = i;
  64. if(colsToMove[i] < targetPos){
  65. ++delta;
  66. }
  67. }
  68. var leftCount = 0;
  69. var rightCount = 0;
  70. var maxCol = Math.max(colsToMove[colsToMove.length - 1], targetPos);
  71. if(maxCol == cells.length){
  72. --maxCol;
  73. }
  74. for(i = colsToMove[0]; i <= maxCol; ++i){
  75. var j = tmp[i];
  76. if(j >= 0){
  77. if(i != targetPos - delta + j){
  78. mapping[i] = targetPos - delta + j;
  79. }
  80. leftCount = j + 1;
  81. rightCount = colsToMove.length - j - 1;
  82. }else if(i < targetPos && leftCount > 0){
  83. mapping[i] = i - leftCount;
  84. }else if(i >= targetPos && rightCount > 0){
  85. mapping[i] = i + rightCount;
  86. }
  87. }
  88. //console.log("mapping:", mapping, ", colsToMove:", colsToMove,", target:", targetPos);
  89. delta = 0;
  90. if(targetPos == cells.length){
  91. --targetPos;
  92. before = false;
  93. }
  94. g._notRefreshSelection = true;
  95. for(i = 0; i < colsToMove.length; ++i){
  96. colIndex = colsToMove[i];
  97. if(colIndex < targetPos){
  98. colIndex -= delta;
  99. }
  100. ++delta;
  101. if(colIndex != targetPos){
  102. layout.moveColumn(cells[colIndex].view.idx, cells[targetPos].view.idx, colIndex, targetPos, before);
  103. cells = layout.cells;
  104. }
  105. if(targetPos <= colIndex){
  106. ++targetPos;
  107. }
  108. }
  109. delete g._notRefreshSelection;
  110. dojo.publish("dojox/grid/rearrange/move/" + g.id, ["col", mapping, colsToMove]);
  111. },
  112. moveRows: function(rowsToMove, targetPos){
  113. // summary:
  114. // Move a set of rows to a given position
  115. // tag:
  116. // public
  117. // rowsToMove: Integer[]
  118. // Array of row indexes.
  119. // targetPos: Integer
  120. // The target position
  121. var g = this.grid,
  122. mapping = {},
  123. preRowsToMove = [],
  124. postRowsToMove = [],
  125. len = rowsToMove.length,
  126. i, r, k, arr, rowMap, lastPos;
  127. for(i = 0; i < len; ++i){
  128. r = rowsToMove[i];
  129. if(r >= targetPos){
  130. break;
  131. }
  132. preRowsToMove.push(r);
  133. }
  134. postRowsToMove = rowsToMove.slice(i);
  135. arr = preRowsToMove;
  136. len = arr.length;
  137. if(len){
  138. rowMap = {};
  139. dojo.forEach(arr, function(r){
  140. rowMap[r] = true;
  141. });
  142. mapping[arr[0]] = targetPos - len;
  143. for(k = 0, i = arr[k] + 1, lastPos = i - 1; i < targetPos; ++i){
  144. if(!rowMap[i]){
  145. mapping[i] = lastPos;
  146. ++lastPos;
  147. }else{
  148. ++k;
  149. mapping[i] = targetPos - len + k;
  150. }
  151. }
  152. }
  153. arr = postRowsToMove;
  154. len = arr.length;
  155. if(len){
  156. rowMap = {};
  157. dojo.forEach(arr, function(r){
  158. rowMap[r] = true;
  159. });
  160. mapping[arr[len - 1]] = targetPos + len - 1;
  161. for(k = len - 1, i = arr[k] - 1, lastPos = i + 1; i >= targetPos; --i){
  162. if(!rowMap[i]){
  163. mapping[i] = lastPos;
  164. --lastPos;
  165. }else{
  166. --k;
  167. mapping[i] = targetPos + k;
  168. }
  169. }
  170. }
  171. var tmpMapping = dojo.clone(mapping);
  172. g.layer("rowmap").setMapping(mapping);
  173. g.forEachLayer(function(layer){
  174. if(layer.name() != "rowmap"){
  175. layer.invalidate();
  176. return true;
  177. }else{
  178. return false;
  179. }
  180. }, false);
  181. g.selection.selected = [];
  182. g._noInternalMapping = true;
  183. g._refresh();
  184. setTimeout(function(){
  185. dojo.publish("dojox/grid/rearrange/move/" + g.id, ["row", tmpMapping, rowsToMove]);
  186. g._noInternalMapping = false;
  187. }, 0);
  188. },
  189. moveCells: function(cellsToMove, target){
  190. var g = this.grid,
  191. s = g.store;
  192. if(s.getFeatures()["dojo.data.api.Write"]){
  193. if(cellsToMove.min.row == target.min.row && cellsToMove.min.col == target.min.col){
  194. //Same position, no need to move
  195. return;
  196. }
  197. var cells = g.layout.cells,
  198. cnt = cellsToMove.max.row - cellsToMove.min.row + 1,
  199. r, c, tr, tc,
  200. sources = [], targets = [];
  201. for(r = cellsToMove.min.row, tr = target.min.row; r <= cellsToMove.max.row; ++r, ++tr){
  202. for(c = cellsToMove.min.col, tc = target.min.col; c <= cellsToMove.max.col; ++c, ++tc){
  203. while(cells[c] && cells[c].hidden){
  204. ++c;
  205. }
  206. while(cells[tc] && cells[tc].hidden){
  207. ++tc;
  208. }
  209. sources.push({
  210. "r": r,
  211. "c": c
  212. });
  213. targets.push({
  214. "r": tr,
  215. "c": tc,
  216. "v": cells[c].get(r, g._by_idx[r].item)
  217. });
  218. }
  219. }
  220. if(this._hasIdentity(sources.concat(targets))){
  221. console.warn("Can not write to identity!");
  222. return;
  223. }
  224. dojo.forEach(sources, function(point){
  225. s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
  226. });
  227. dojo.forEach(targets, function(point){
  228. s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
  229. });
  230. s.save({
  231. onComplete: function(){
  232. dojo.publish("dojox/grid/rearrange/move/" + g.id, ["cell", {
  233. "from": cellsToMove,
  234. "to": target
  235. }]);
  236. }
  237. });
  238. }
  239. },
  240. copyCells: function(cellsToMove, target){
  241. var g = this.grid,
  242. s = g.store;
  243. if(s.getFeatures()["dojo.data.api.Write"]){
  244. if(cellsToMove.min.row == target.min.row && cellsToMove.min.col == target.min.col){
  245. return;
  246. }
  247. var cells = g.layout.cells,
  248. cnt = cellsToMove.max.row - cellsToMove.min.row + 1,
  249. r, c, tr, tc,
  250. targets = [];
  251. for(r = cellsToMove.min.row, tr = target.min.row; r <= cellsToMove.max.row; ++r, ++tr){
  252. for(c = cellsToMove.min.col, tc = target.min.col; c <= cellsToMove.max.col; ++c, ++tc){
  253. while(cells[c] && cells[c].hidden){
  254. ++c;
  255. }
  256. while(cells[tc] && cells[tc].hidden){
  257. ++tc;
  258. }
  259. targets.push({
  260. "r": tr,
  261. "c": tc,
  262. "v": cells[c].get(r, g._by_idx[r].item)
  263. });
  264. }
  265. }
  266. if(this._hasIdentity(targets)){
  267. console.warn("Can not write to identity!");
  268. return;
  269. }
  270. dojo.forEach(targets, function(point){
  271. s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
  272. });
  273. s.save({
  274. onComplete: function(){
  275. setTimeout(function(){
  276. dojo.publish("dojox/grid/rearrange/copy/" + g.id, ["cell", {
  277. "from": cellsToMove,
  278. "to": target
  279. }]);
  280. }, 0);
  281. }
  282. });
  283. }
  284. },
  285. changeCells: function(sourceGrid, cellsToMove, target){
  286. var g = this.grid,
  287. s = g.store;
  288. if(s.getFeatures()["dojo.data.api.Write"]){
  289. var srcg = sourceGrid,
  290. cells = g.layout.cells,
  291. srccells = srcg.layout.cells,
  292. cnt = cellsToMove.max.row - cellsToMove.min.row + 1,
  293. r, c, tr, tc, targets = [];
  294. for(r = cellsToMove.min.row, tr = target.min.row; r <= cellsToMove.max.row; ++r, ++tr){
  295. for(c = cellsToMove.min.col, tc = target.min.col; c <= cellsToMove.max.col; ++c, ++tc){
  296. while(srccells[c] && srccells[c].hidden){
  297. ++c;
  298. }
  299. while(cells[tc] && cells[tc].hidden){
  300. ++tc;
  301. }
  302. targets.push({
  303. "r": tr,
  304. "c": tc,
  305. "v": srccells[c].get(r, srcg._by_idx[r].item)
  306. });
  307. }
  308. }
  309. if(this._hasIdentity(targets)){
  310. console.warn("Can not write to identity!");
  311. return;
  312. }
  313. dojo.forEach(targets, function(point){
  314. s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
  315. });
  316. s.save({
  317. onComplete: function(){
  318. dojo.publish("dojox/grid/rearrange/change/" + g.id, ["cell", target]);
  319. }
  320. });
  321. }
  322. },
  323. clearCells: function(cellsToClear){
  324. var g = this.grid,
  325. s = g.store;
  326. if(s.getFeatures()["dojo.data.api.Write"]){
  327. var cells = g.layout.cells,
  328. cnt = cellsToClear.max.row - cellsToClear.min.row + 1,
  329. r, c, targets = [];
  330. for(r = cellsToClear.min.row; r <= cellsToClear.max.row; ++r){
  331. for(c = cellsToClear.min.col; c <= cellsToClear.max.col; ++c){
  332. while(cells[c] && cells[c].hidden){
  333. ++c;
  334. }
  335. targets.push({
  336. "r": r,
  337. "c": c
  338. });
  339. }
  340. }
  341. if(this._hasIdentity(targets)){
  342. console.warn("Can not write to identity!");
  343. return;
  344. }
  345. dojo.forEach(targets, function(point){
  346. s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
  347. });
  348. s.save({
  349. onComplete: function(){
  350. dojo.publish("dojox/grid/rearrange/change/" + g.id, ["cell", cellsToClear]);
  351. }
  352. });
  353. }
  354. },
  355. insertRows: function(sourceGrid, rowsToMove, targetPos){
  356. try{
  357. var g = this.grid,
  358. s = g.store,
  359. rowCnt = g.rowCount,
  360. mapping = {},
  361. obj = {idx: 0},
  362. newRows = [], i,
  363. _this = this;
  364. var len = rowsToMove.length;
  365. for(i = targetPos; i < g.rowCount; ++i){
  366. mapping[i] = i + len;
  367. }
  368. if(s.getFeatures()['dojo.data.api.Write']){
  369. if(sourceGrid){
  370. var srcg = sourceGrid,
  371. srcs = srcg.store,
  372. thisItem;
  373. for(i = 0; !thisItem; ++i){
  374. thisItem = g._by_idx[i];
  375. }
  376. var attrs = s.getAttributes(thisItem.item);
  377. var rowsToFetch = [];
  378. dojo.forEach(rowsToMove, function(rowIndex, i){
  379. var item = {};
  380. var srcItem = srcg._by_idx[rowIndex];
  381. if(srcItem){
  382. dojo.forEach(attrs, function(attr){
  383. item[attr] = srcs.getValue(srcItem.item, attr);
  384. });
  385. item = _this.args.setIdentifierForNewItem(item, s, rowCnt + obj.idx) || item;
  386. try{
  387. s.newItem(item);
  388. newRows.push(targetPos + i);
  389. mapping[rowCnt + obj.idx] = targetPos + i;
  390. ++obj.idx;
  391. }catch(e){
  392. console.log("insertRows newItem:",e,item);
  393. }
  394. }else{
  395. rowsToFetch.push(rowIndex);
  396. }
  397. });
  398. }else if(rowsToMove.length && dojo.isObject(rowsToMove[0])){
  399. dojo.forEach(rowsToMove, function(rowData, i){
  400. var item = _this.args.setIdentifierForNewItem(rowData, s, rowCnt + obj.idx) || rowData;
  401. try{
  402. s.newItem(item);
  403. newRows.push(targetPos + i);
  404. mapping[rowCnt + obj.idx] = targetPos + i;
  405. ++obj.idx;
  406. }catch(e){
  407. console.log("insertRows newItem:",e,item);
  408. }
  409. });
  410. }else{
  411. return;
  412. }
  413. g.layer("rowmap").setMapping(mapping);
  414. s.save({
  415. onComplete: function(){
  416. g._refresh();
  417. setTimeout(function(){
  418. dojo.publish("dojox/grid/rearrange/insert/" + g.id, ["row", newRows]);
  419. }, 0);
  420. }
  421. });
  422. }
  423. }catch(e){
  424. console.log("insertRows:",e);
  425. }
  426. },
  427. removeRows: function(rowsToRemove){
  428. var g = this.grid;
  429. var s = g.store;
  430. try{
  431. dojo.forEach(dojo.map(rowsToRemove, function(rowIndex){
  432. return g._by_idx[rowIndex];
  433. }), function(row){
  434. if(row){
  435. s.deleteItem(row.item);
  436. }
  437. });
  438. s.save({
  439. onComplete: function(){
  440. dojo.publish("dojox/grid/rearrange/remove/" + g.id, ["row", rowsToRemove]);
  441. }
  442. });
  443. }catch(e){
  444. console.log("removeRows:",e);
  445. }
  446. },
  447. _getPageInfo: function(){
  448. // summary:
  449. // Find pages that contain visible rows
  450. // return: Object
  451. // {topPage: xx, bottomPage: xx, invalidPages: [xx,xx,...]}
  452. var scroller = this.grid.scroller,
  453. topPage = scroller.page,
  454. bottomPage = scroller.page,
  455. firstVisibleRow = scroller.firstVisibleRow,
  456. lastVisibleRow = scroller.lastVisibleRow,
  457. rowsPerPage = scroller.rowsPerPage,
  458. renderedPages = scroller.pageNodes[0],
  459. topRow, bottomRow, matched,
  460. invalidPages = [];
  461. dojo.forEach(renderedPages, function(page, pageIndex){
  462. if(!page){ return; }
  463. matched = false;
  464. topRow = pageIndex * rowsPerPage;
  465. bottomRow = (pageIndex + 1) * rowsPerPage - 1;
  466. if(firstVisibleRow >= topRow && firstVisibleRow <= bottomRow){
  467. topPage = pageIndex;
  468. matched = true;
  469. }
  470. if(lastVisibleRow >= topRow && lastVisibleRow <= bottomRow){
  471. bottomPage = pageIndex;
  472. matched = true;
  473. }
  474. if(!matched && (topRow > lastVisibleRow || bottomRow < firstVisibleRow)){
  475. invalidPages.push(pageIndex);
  476. }
  477. });
  478. return {topPage: topPage, bottomPage: bottomPage, invalidPages: invalidPages};
  479. }
  480. });
  481. dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Rearrange/*name:'rearrange'*/);
  482. }