source: Dev/trunk/src/client/dojox/grid/enhanced/plugins/Rearrange.js

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

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