1 | define([ |
---|
2 | "dojo/_base/kernel", |
---|
3 | "dojo/_base/declare", |
---|
4 | "dojo/_base/connect", |
---|
5 | "dojo/_base/array", |
---|
6 | "dojo/_base/lang", |
---|
7 | "dojo/_base/html", |
---|
8 | "dojo/_base/json", |
---|
9 | "dojo/_base/window", |
---|
10 | "dojo/query", |
---|
11 | "dojo/keys", |
---|
12 | "dojo/dnd/Source", |
---|
13 | "dojo/dnd/Avatar", |
---|
14 | "../_Plugin", |
---|
15 | "../../EnhancedGrid", |
---|
16 | "dojo/dnd/Manager", |
---|
17 | "./Selector", |
---|
18 | "./Rearrange" |
---|
19 | ], function(dojo, declare, connect, array, lang, html, json, win, query, keys, Source, Avatar, _Plugin, EnhancedGrid, Manager){ |
---|
20 | |
---|
21 | var _devideToArrays = function(a){ |
---|
22 | a.sort(function(v1, v2){ |
---|
23 | return v1 - v2; |
---|
24 | }); |
---|
25 | var arr = [[a[0]]]; |
---|
26 | for(var i = 1, j = 0; i < a.length; ++i){ |
---|
27 | if(a[i] == a[i-1] + 1){ |
---|
28 | arr[j].push(a[i]); |
---|
29 | }else{ |
---|
30 | arr[++j] = [a[i]]; |
---|
31 | } |
---|
32 | } |
---|
33 | return arr; |
---|
34 | }, |
---|
35 | _joinToArray = function(arrays){ |
---|
36 | var a = arrays[0]; |
---|
37 | for(var i = 1; i < arrays.length; ++i){ |
---|
38 | a = a.concat(arrays[i]); |
---|
39 | } |
---|
40 | return a; |
---|
41 | }; |
---|
42 | var GridDnDElement = declare("dojox.grid.enhanced.plugins.GridDnDElement", null, { |
---|
43 | constructor: function(dndPlugin){ |
---|
44 | this.plugin = dndPlugin; |
---|
45 | this.node = html.create("div"); |
---|
46 | this._items = {}; |
---|
47 | }, |
---|
48 | destroy: function(){ |
---|
49 | this.plugin = null; |
---|
50 | html.destroy(this.node); |
---|
51 | this.node = null; |
---|
52 | this._items = null; |
---|
53 | }, |
---|
54 | createDnDNodes: function(dndRegion){ |
---|
55 | this.destroyDnDNodes(); |
---|
56 | var acceptType = ["grid/" + dndRegion.type + "s"]; |
---|
57 | var itemNodeIdBase = this.plugin.grid.id + "_dndItem"; |
---|
58 | array.forEach(dndRegion.selected, function(range, i){ |
---|
59 | var id = itemNodeIdBase + i; |
---|
60 | this._items[id] = { |
---|
61 | "type": acceptType, |
---|
62 | "data": range, |
---|
63 | "dndPlugin": this.plugin |
---|
64 | }; |
---|
65 | this.node.appendChild(html.create("div", { |
---|
66 | "id": id |
---|
67 | })); |
---|
68 | }, this); |
---|
69 | }, |
---|
70 | getDnDNodes: function(){ |
---|
71 | return array.map(this.node.childNodes, function(node){ |
---|
72 | return node; |
---|
73 | }); |
---|
74 | }, |
---|
75 | destroyDnDNodes: function(){ |
---|
76 | html.empty(this.node); |
---|
77 | this._items = {}; |
---|
78 | }, |
---|
79 | getItem: function(nodeId){ |
---|
80 | return this._items[nodeId]; |
---|
81 | } |
---|
82 | }); |
---|
83 | var GridDnDSource = declare("dojox.grid.enhanced.plugins.GridDnDSource", Source,{ |
---|
84 | accept: ["grid/cells", "grid/rows", "grid/cols"], |
---|
85 | constructor: function(node, param){ |
---|
86 | this.grid = param.grid; |
---|
87 | this.dndElem = param.dndElem; |
---|
88 | this.dndPlugin = param.dnd; |
---|
89 | this.sourcePlugin = null; |
---|
90 | }, |
---|
91 | destroy: function(){ |
---|
92 | this.inherited(arguments); |
---|
93 | this.grid = null; |
---|
94 | this.dndElem = null; |
---|
95 | this.dndPlugin = null; |
---|
96 | this.sourcePlugin = null; |
---|
97 | }, |
---|
98 | getItem: function(nodeId){ |
---|
99 | return this.dndElem.getItem(nodeId); |
---|
100 | }, |
---|
101 | checkAcceptance: function(source, nodes){ |
---|
102 | if(this != source && nodes[0]){ |
---|
103 | var item = source.getItem(nodes[0].id); |
---|
104 | if(item.dndPlugin){ |
---|
105 | var type = item.type; |
---|
106 | for(var j = 0; j < type.length; ++j){ |
---|
107 | if(type[j] in this.accept){ |
---|
108 | if(this.dndPlugin._canAccept(item.dndPlugin)){ |
---|
109 | this.sourcePlugin = item.dndPlugin; |
---|
110 | }else{ |
---|
111 | return false; |
---|
112 | } |
---|
113 | break; |
---|
114 | } |
---|
115 | } |
---|
116 | }else if("grid/rows" in this.accept){ |
---|
117 | var rows = []; |
---|
118 | array.forEach(nodes, function(node){ |
---|
119 | var item = source.getItem(node.id); |
---|
120 | if(item.data && array.indexOf(item.type, "grid/rows") >= 0){ |
---|
121 | var rowData = item.data; |
---|
122 | if(typeof item.data == "string"){ |
---|
123 | rowData = json.fromJson(item.data); |
---|
124 | } |
---|
125 | if(rowData){ |
---|
126 | rows.push(rowData); |
---|
127 | } |
---|
128 | } |
---|
129 | }); |
---|
130 | if(rows.length){ |
---|
131 | this.sourcePlugin = { |
---|
132 | _dndRegion: { |
---|
133 | type: "row", |
---|
134 | selected: [rows] |
---|
135 | } |
---|
136 | }; |
---|
137 | }else{ |
---|
138 | return false; |
---|
139 | } |
---|
140 | } |
---|
141 | } |
---|
142 | return this.inherited(arguments); |
---|
143 | }, |
---|
144 | onDraggingOver: function(){ |
---|
145 | this.dndPlugin.onDraggingOver(this.sourcePlugin); |
---|
146 | }, |
---|
147 | onDraggingOut: function(){ |
---|
148 | this.dndPlugin.onDraggingOut(this.sourcePlugin); |
---|
149 | }, |
---|
150 | onDndDrop: function(source, nodes, copy, target){ |
---|
151 | //this.inherited(arguments); |
---|
152 | this.onDndCancel(); |
---|
153 | if(this != source && this == target){ |
---|
154 | this.dndPlugin.onDragIn(this.sourcePlugin, copy); |
---|
155 | } |
---|
156 | } |
---|
157 | }); |
---|
158 | |
---|
159 | var GridDnDAvatar = declare("dojox.grid.enhanced.plugins.GridDnDAvatar", Avatar, { |
---|
160 | construct: function(){ |
---|
161 | // summary: |
---|
162 | // constructor function; |
---|
163 | // it is separate so it can be (dynamically) overwritten in case of need |
---|
164 | this._itemType = this.manager._dndPlugin._dndRegion.type; |
---|
165 | this._itemCount = this._getItemCount(); |
---|
166 | |
---|
167 | this.isA11y = html.hasClass(win.body(), "dijit_a11y"); |
---|
168 | var a = html.create("table", { |
---|
169 | "border": "0", |
---|
170 | "cellspacing": "0", |
---|
171 | "class": "dojoxGridDndAvatar", |
---|
172 | "style": { |
---|
173 | position: "absolute", |
---|
174 | zIndex: "1999", |
---|
175 | margin: "0px" |
---|
176 | } |
---|
177 | }), |
---|
178 | source = this.manager.source, |
---|
179 | b = html.create("tbody", null, a), |
---|
180 | tr = html.create("tr", null, b), |
---|
181 | td = html.create("td", { |
---|
182 | "class": "dojoxGridDnDIcon" |
---|
183 | }, tr); |
---|
184 | if(this.isA11y){ |
---|
185 | html.create("span", { |
---|
186 | "id" : "a11yIcon", |
---|
187 | "innerHTML" : this.manager.copy ? '+' : "<" |
---|
188 | }, td); |
---|
189 | } |
---|
190 | td = html.create("td", { |
---|
191 | "class" : "dojoxGridDnDItemIcon " + this._getGridDnDIconClass() |
---|
192 | }, tr); |
---|
193 | td = html.create("td", null, tr); |
---|
194 | html.create("span", { |
---|
195 | "class": "dojoxGridDnDItemCount", |
---|
196 | "innerHTML": source.generateText ? this._generateText() : "" |
---|
197 | }, td); |
---|
198 | // we have to set the opacity on IE only after the node is live |
---|
199 | html.style(tr, { |
---|
200 | "opacity": 0.9 |
---|
201 | }); |
---|
202 | this.node = a; |
---|
203 | }, |
---|
204 | _getItemCount: function(){ |
---|
205 | var selected = this.manager._dndPlugin._dndRegion.selected, |
---|
206 | count = 0; |
---|
207 | switch(this._itemType){ |
---|
208 | case "cell": |
---|
209 | selected = selected[0]; |
---|
210 | var cells = this.manager._dndPlugin.grid.layout.cells, |
---|
211 | colCount = selected.max.col - selected.min.col + 1, |
---|
212 | rowCount = selected.max.row - selected.min.row + 1; |
---|
213 | if(colCount > 1){ |
---|
214 | for(var i = selected.min.col; i <= selected.max.col; ++i){ |
---|
215 | if(cells[i].hidden){ |
---|
216 | --colCount; |
---|
217 | } |
---|
218 | } |
---|
219 | } |
---|
220 | count = colCount * rowCount; |
---|
221 | break; |
---|
222 | case "row": |
---|
223 | case "col": |
---|
224 | count = _joinToArray(selected).length; |
---|
225 | } |
---|
226 | return count; |
---|
227 | }, |
---|
228 | _getGridDnDIconClass: function(){ |
---|
229 | return { |
---|
230 | "row": ["dojoxGridDnDIconRowSingle", "dojoxGridDnDIconRowMulti"], |
---|
231 | "col": ["dojoxGridDnDIconColSingle", "dojoxGridDnDIconColMulti"], |
---|
232 | "cell": ["dojoxGridDnDIconCellSingle", "dojoxGridDnDIconCellMulti"] |
---|
233 | }[this._itemType][this._itemCount == 1 ? 0 : 1]; |
---|
234 | }, |
---|
235 | _generateText: function(){ |
---|
236 | // summary: |
---|
237 | // generates a proper text to reflect copying or moving of items |
---|
238 | return "(" + this._itemCount + ")"; |
---|
239 | } |
---|
240 | }); |
---|
241 | var DnD = declare("dojox.grid.enhanced.plugins.DnD", _Plugin, { |
---|
242 | // summary: |
---|
243 | // Provide drag and drop for grid columns/rows/cells within grid and out of grid. |
---|
244 | // The store of grid must implement dojo.data.api.Write. |
---|
245 | // |
---|
246 | // DnD selected columns: |
---|
247 | // Support moving within grid, moving/copying out of grid to a non-grid DnD target. |
---|
248 | // |
---|
249 | // DnD selected rows: |
---|
250 | // Support moving within grid, moving/copying out of grid to any DnD target. |
---|
251 | // |
---|
252 | // DnD selected cells (in rectangle shape only): |
---|
253 | // Support moving/copying within grid, moving/copying out of grid to any DnD target. |
---|
254 | |
---|
255 | // name: String, |
---|
256 | // plugin name; |
---|
257 | name: "dnd", |
---|
258 | |
---|
259 | _targetAnchorBorderWidth: 2, |
---|
260 | _copyOnly: false, |
---|
261 | _config: { |
---|
262 | "row":{ |
---|
263 | "within":true, |
---|
264 | "in":true, |
---|
265 | "out":true |
---|
266 | }, |
---|
267 | "col":{ |
---|
268 | "within":true, |
---|
269 | "in":true, |
---|
270 | "out":true |
---|
271 | }, |
---|
272 | "cell":{ |
---|
273 | "within":true, |
---|
274 | "in":true, |
---|
275 | "out":true |
---|
276 | } |
---|
277 | }, |
---|
278 | constructor: function(grid, args){ |
---|
279 | this.grid = grid; |
---|
280 | this._config = lang.clone(this._config); |
---|
281 | args = lang.isObject(args) ? args : {}; |
---|
282 | this.setupConfig(args.dndConfig); |
---|
283 | this._copyOnly = !!args.copyOnly; |
---|
284 | |
---|
285 | //Get the plugins we are dependent on. |
---|
286 | this._mixinGrid(); |
---|
287 | this.selector = grid.pluginMgr.getPlugin("selector"); |
---|
288 | this.rearranger = grid.pluginMgr.getPlugin("rearrange"); |
---|
289 | //TODO: waiting for a better plugin framework to pass args to dependent plugins. |
---|
290 | this.rearranger.setArgs(args); |
---|
291 | |
---|
292 | //Initialized the components we need. |
---|
293 | this._clear(); |
---|
294 | this._elem = new GridDnDElement(this); |
---|
295 | this._source = new GridDnDSource(this._elem.node, { |
---|
296 | "grid": grid, |
---|
297 | "dndElem": this._elem, |
---|
298 | "dnd": this |
---|
299 | }); |
---|
300 | this._container = query(".dojoxGridMasterView", this.grid.domNode)[0]; |
---|
301 | this._initEvents(); |
---|
302 | }, |
---|
303 | destroy: function(){ |
---|
304 | this.inherited(arguments); |
---|
305 | this._clear(); |
---|
306 | this._source.destroy(); |
---|
307 | this._elem.destroy(); |
---|
308 | this._container = null; |
---|
309 | this.grid = null; |
---|
310 | this.selector = null; |
---|
311 | this.rearranger = null; |
---|
312 | this._config = null; |
---|
313 | }, |
---|
314 | _mixinGrid: function(){ |
---|
315 | // summary: |
---|
316 | // Provide APIs for grid. |
---|
317 | this.grid.setupDnDConfig = lang.hitch(this, "setupConfig"); |
---|
318 | this.grid.dndCopyOnly = lang.hitch(this, "copyOnly"); |
---|
319 | }, |
---|
320 | setupConfig: function(config){ |
---|
321 | // summary: |
---|
322 | // Configure which DnD functionalities are needed. |
---|
323 | // Combination of any item from type set ("row", "col", "cell") |
---|
324 | // and any item from mode set("within", "in", "out") is configurable. |
---|
325 | // |
---|
326 | // "row", "col", "cell" are straightforward, while the other 3 are explained below: |
---|
327 | // |
---|
328 | // - "within": DnD within grid, that is, column/row reordering and cell moving/copying. |
---|
329 | // - "in": Whether allowed to accept rows/cells (currently not support columns) from another grid. |
---|
330 | // - "out": Whether allowed to drag out of grid, to another grid or even to any other DnD target. |
---|
331 | // |
---|
332 | // If not provided in the config, will use the default. |
---|
333 | // When declared together, Mode set has higher priority than type set. |
---|
334 | // config: Object |
---|
335 | // DnD configuration object. |
---|
336 | // See the examples below. |
---|
337 | // example: |
---|
338 | // The following code disables row DnD within grid, |
---|
339 | // but still can drag rows out of grid or drag rows from other gird. |
---|
340 | // | setUpConfig({ |
---|
341 | // | "row": { |
---|
342 | // | "within": false |
---|
343 | // | } |
---|
344 | // | }); |
---|
345 | // |
---|
346 | // The opposite way is also okay: |
---|
347 | // | setUpConfig({ |
---|
348 | // | "within": { |
---|
349 | // | "row": false |
---|
350 | // | } |
---|
351 | // | }); |
---|
352 | // |
---|
353 | // And if you'd like to disable/enable a whole set, here's a shortcut: |
---|
354 | // | setUpConfig({ |
---|
355 | // | "cell", true, |
---|
356 | // | "out": false |
---|
357 | // | }); |
---|
358 | // |
---|
359 | // Because mode has higher priority than type, the following will disable row dnd within grid: |
---|
360 | // | setUpConfig({ |
---|
361 | // | "within", { |
---|
362 | // | "row": false; |
---|
363 | // | }, |
---|
364 | // | "row", { |
---|
365 | // | "within": true |
---|
366 | // | } |
---|
367 | // | }); |
---|
368 | if(config && lang.isObject(config)){ |
---|
369 | var firstLevel = ["row", "col", "cell"], |
---|
370 | secondLevel = ["within", "in", "out"], |
---|
371 | cfg = this._config; |
---|
372 | array.forEach(firstLevel, function(type){ |
---|
373 | if(type in config){ |
---|
374 | var t = config[type]; |
---|
375 | if(t && lang.isObject(t)){ |
---|
376 | array.forEach(secondLevel, function(mode){ |
---|
377 | if(mode in t){ |
---|
378 | cfg[type][mode] = !!t[mode]; |
---|
379 | } |
---|
380 | }); |
---|
381 | }else{ |
---|
382 | array.forEach(secondLevel, function(mode){ |
---|
383 | cfg[type][mode] = !!t; |
---|
384 | }); |
---|
385 | } |
---|
386 | } |
---|
387 | }); |
---|
388 | array.forEach(secondLevel, function(mode){ |
---|
389 | if(mode in config){ |
---|
390 | var m = config[mode]; |
---|
391 | if(m && lang.isObject(m)){ |
---|
392 | array.forEach(firstLevel, function(type){ |
---|
393 | if(type in m){ |
---|
394 | cfg[type][mode] = !!m[type]; |
---|
395 | } |
---|
396 | }); |
---|
397 | }else{ |
---|
398 | array.forEach(firstLevel, function(type){ |
---|
399 | cfg[type][mode] = !!m; |
---|
400 | }); |
---|
401 | } |
---|
402 | } |
---|
403 | }); |
---|
404 | } |
---|
405 | }, |
---|
406 | copyOnly: function(isCopyOnly){ |
---|
407 | // summary: |
---|
408 | // Setter/getter of this._copyOnly. |
---|
409 | if(typeof isCopyOnly != "undefined"){ |
---|
410 | this._copyOnly = !!isCopyOnly; |
---|
411 | } |
---|
412 | return this._copyOnly; |
---|
413 | }, |
---|
414 | _isOutOfGrid: function(evt){ |
---|
415 | var gridPos = html.position(this.grid.domNode), x = evt.clientX, y = evt.clientY; |
---|
416 | return y < gridPos.y || y > gridPos.y + gridPos.h || |
---|
417 | x < gridPos.x || x > gridPos.x + gridPos.w; |
---|
418 | }, |
---|
419 | _onMouseMove: function(evt){ |
---|
420 | if(this._dndRegion && !this._dnding && !this._externalDnd){ |
---|
421 | this._dnding = true; |
---|
422 | this._startDnd(evt); |
---|
423 | }else{ |
---|
424 | if(this._isMouseDown && !this._dndRegion){ |
---|
425 | delete this._isMouseDown; |
---|
426 | this._oldCursor = html.style(win.body(), "cursor"); |
---|
427 | html.style(win.body(), "cursor", "not-allowed"); |
---|
428 | } |
---|
429 | //TODO: should implement as mouseenter/mouseleave |
---|
430 | //But we have an avatar under mouse when dnd, and this will cause a lot of mouseenter in FF. |
---|
431 | var isOut = this._isOutOfGrid(evt); |
---|
432 | if(!this._alreadyOut && isOut){ |
---|
433 | this._alreadyOut = true; |
---|
434 | if(this._dnding){ |
---|
435 | this._destroyDnDUI(true, false); |
---|
436 | } |
---|
437 | this._moveEvent = evt; |
---|
438 | this._source.onOutEvent(); |
---|
439 | }else if(this._alreadyOut && !isOut){ |
---|
440 | this._alreadyOut = false; |
---|
441 | if(this._dnding){ |
---|
442 | this._createDnDUI(evt, true); |
---|
443 | } |
---|
444 | this._moveEvent = evt; |
---|
445 | this._source.onOverEvent(); |
---|
446 | } |
---|
447 | } |
---|
448 | }, |
---|
449 | _onMouseUp: function(){ |
---|
450 | if(!this._extDnding && !this._isSource){ |
---|
451 | var isInner = this._dnding && !this._alreadyOut; |
---|
452 | if(isInner && this._config[this._dndRegion.type]["within"]){ |
---|
453 | this._rearrange(); |
---|
454 | } |
---|
455 | this._endDnd(isInner); |
---|
456 | } |
---|
457 | html.style(win.body(), "cursor", this._oldCursor || ""); |
---|
458 | delete this._isMouseDown; |
---|
459 | }, |
---|
460 | _initEvents: function(){ |
---|
461 | var g = this.grid, s = this.selector; |
---|
462 | this.connect(win.doc, "onmousemove", "_onMouseMove"); |
---|
463 | this.connect(win.doc, "onmouseup", "_onMouseUp"); |
---|
464 | |
---|
465 | this.connect(g, "onCellMouseOver", function(evt){ |
---|
466 | if(!this._dnding && !s.isSelecting() && !evt.ctrlKey){ |
---|
467 | this._dndReady = s.isSelected("cell", evt.rowIndex, evt.cell.index); |
---|
468 | s.selectEnabled(!this._dndReady); |
---|
469 | } |
---|
470 | }); |
---|
471 | this.connect(g, "onHeaderCellMouseOver", function(evt){ |
---|
472 | if(this._dndReady){ |
---|
473 | s.selectEnabled(true); |
---|
474 | } |
---|
475 | }); |
---|
476 | this.connect(g, "onRowMouseOver", function(evt){ |
---|
477 | if(this._dndReady && !evt.cell){ |
---|
478 | s.selectEnabled(true); |
---|
479 | } |
---|
480 | }); |
---|
481 | this.connect(g, "onCellMouseDown", function(evt){ |
---|
482 | if(!evt.ctrlKey && this._dndReady){ |
---|
483 | this._dndRegion = this._getDnDRegion(evt.rowIndex, evt.cell.index); |
---|
484 | this._isMouseDown = true; |
---|
485 | } |
---|
486 | }); |
---|
487 | this.connect(g, "onCellMouseUp", function(evt){ |
---|
488 | if(!this._dndReady && !s.isSelecting() && evt.cell){ |
---|
489 | this._dndReady = s.isSelected("cell", evt.rowIndex, evt.cell.index); |
---|
490 | s.selectEnabled(!this._dndReady); |
---|
491 | } |
---|
492 | }); |
---|
493 | this.connect(g, "onCellClick", function(evt){ |
---|
494 | if(this._dndReady && !evt.ctrlKey && !evt.shiftKey){ |
---|
495 | s.select("cell", evt.rowIndex, evt.cell.index); |
---|
496 | } |
---|
497 | }); |
---|
498 | this.connect(g, "onEndAutoScroll", function(isVertical, isForward, view, target, evt){ |
---|
499 | if(this._dnding){ |
---|
500 | this._markTargetAnchor(evt); |
---|
501 | } |
---|
502 | }); |
---|
503 | this.connect(win.doc, "onkeydown", function(evt){ |
---|
504 | if(evt.keyCode == keys.ESCAPE){ |
---|
505 | this._endDnd(false); |
---|
506 | }else if(evt.keyCode == keys.CTRL){ |
---|
507 | s.selectEnabled(true); |
---|
508 | this._isCopy = true; |
---|
509 | } |
---|
510 | }); |
---|
511 | this.connect(win.doc, "onkeyup", function(evt){ |
---|
512 | if(evt.keyCode == keys.CTRL){ |
---|
513 | s.selectEnabled(!this._dndReady); |
---|
514 | this._isCopy = false; |
---|
515 | } |
---|
516 | }); |
---|
517 | }, |
---|
518 | _clear: function(){ |
---|
519 | this._dndRegion = null; |
---|
520 | this._target = null; |
---|
521 | this._moveEvent = null; |
---|
522 | this._targetAnchor = {}; |
---|
523 | this._dnding = false; |
---|
524 | this._externalDnd = false; |
---|
525 | this._isSource = false; |
---|
526 | this._alreadyOut = false; |
---|
527 | this._extDnding = false; |
---|
528 | }, |
---|
529 | _getDnDRegion: function(rowIndex, colIndex){ |
---|
530 | var s = this.selector, |
---|
531 | selected = s._selected, |
---|
532 | flag = (!!selected.cell.length) | (!!selected.row.length << 1) | (!!selected.col.length << 2), |
---|
533 | type; |
---|
534 | switch(flag){ |
---|
535 | case 1: |
---|
536 | type = "cell"; |
---|
537 | if(!this._config[type]["within"] && !this._config[type]["out"]){ |
---|
538 | return null; |
---|
539 | } |
---|
540 | var cells = this.grid.layout.cells, |
---|
541 | getCount = function(range){ |
---|
542 | var hiddenColCnt = 0; |
---|
543 | for(var i = range.min.col; i <= range.max.col; ++i){ |
---|
544 | if(cells[i].hidden){ |
---|
545 | ++hiddenColCnt; |
---|
546 | } |
---|
547 | } |
---|
548 | return (range.max.row - range.min.row + 1) * (range.max.col - range.min.col + 1 - hiddenColCnt); |
---|
549 | }, |
---|
550 | inRange = function(item, range){ |
---|
551 | return item.row >= range.min.row && item.row <= range.max.row && |
---|
552 | item.col >= range.min.col && item.col <= range.max.col; |
---|
553 | }, |
---|
554 | range = { |
---|
555 | max: { |
---|
556 | row: -1, |
---|
557 | col: -1 |
---|
558 | }, |
---|
559 | min: { |
---|
560 | row: Infinity, |
---|
561 | col: Infinity |
---|
562 | } |
---|
563 | }; |
---|
564 | |
---|
565 | array.forEach(selected[type], function(item){ |
---|
566 | if(item.row < range.min.row){ |
---|
567 | range.min.row = item.row; |
---|
568 | } |
---|
569 | if(item.row > range.max.row){ |
---|
570 | range.max.row = item.row; |
---|
571 | } |
---|
572 | if(item.col < range.min.col){ |
---|
573 | range.min.col = item.col; |
---|
574 | } |
---|
575 | if(item.col > range.max.col){ |
---|
576 | range.max.col = item.col; |
---|
577 | } |
---|
578 | }); |
---|
579 | if(array.some(selected[type], function(item){ |
---|
580 | return item.row == rowIndex && item.col == colIndex; |
---|
581 | })){ |
---|
582 | if(getCount(range) == selected[type].length && array.every(selected[type], function(item){ |
---|
583 | return inRange(item, range); |
---|
584 | })){ |
---|
585 | return { |
---|
586 | "type": type, |
---|
587 | "selected": [range], |
---|
588 | "handle": { |
---|
589 | "row": rowIndex, |
---|
590 | "col": colIndex |
---|
591 | } |
---|
592 | }; |
---|
593 | } |
---|
594 | } |
---|
595 | return null; |
---|
596 | case 2: case 4: |
---|
597 | type = flag == 2 ? "row" : "col"; |
---|
598 | if(!this._config[type]["within"] && !this._config[type]["out"]){ |
---|
599 | return null; |
---|
600 | } |
---|
601 | var res = s.getSelected(type); |
---|
602 | if(res.length){ |
---|
603 | return { |
---|
604 | "type": type, |
---|
605 | "selected": _devideToArrays(res), |
---|
606 | "handle": flag == 2 ? rowIndex : colIndex |
---|
607 | }; |
---|
608 | } |
---|
609 | return null; |
---|
610 | } |
---|
611 | return null; |
---|
612 | }, |
---|
613 | _startDnd: function(evt){ |
---|
614 | this._createDnDUI(evt); |
---|
615 | }, |
---|
616 | _endDnd: function(destroySource){ |
---|
617 | this._destroyDnDUI(false, destroySource); |
---|
618 | this._clear(); |
---|
619 | }, |
---|
620 | _createDnDUI: function(evt, isMovingIn){ |
---|
621 | //By default the master view of grid do not have height, because the children in it are all positioned absolutely. |
---|
622 | //But we need it to contain avatars. |
---|
623 | var viewPos = html.position(this.grid.views.views[0].domNode); |
---|
624 | html.style(this._container, "height", viewPos.h + "px"); |
---|
625 | try{ |
---|
626 | //If moving in from out side, dnd source is already created. |
---|
627 | if(!isMovingIn){ |
---|
628 | this._createSource(evt); |
---|
629 | } |
---|
630 | this._createMoveable(evt); |
---|
631 | this._oldCursor = html.style(win.body(), "cursor"); |
---|
632 | html.style(win.body(), "cursor", "default"); |
---|
633 | }catch(e){ |
---|
634 | console.warn("DnD._createDnDUI() error:", e); |
---|
635 | } |
---|
636 | }, |
---|
637 | _destroyDnDUI: function(isMovingOut, destroySource){ |
---|
638 | try{ |
---|
639 | if(destroySource){ |
---|
640 | this._destroySource(); |
---|
641 | } |
---|
642 | this._unmarkTargetAnchor(); |
---|
643 | if(!isMovingOut){ |
---|
644 | this._destroyMoveable(); |
---|
645 | } |
---|
646 | html.style(win.body(), "cursor", this._oldCursor); |
---|
647 | }catch(e){ |
---|
648 | console.warn("DnD._destroyDnDUI() error:", this.grid.id, e); |
---|
649 | } |
---|
650 | }, |
---|
651 | _createSource: function(evt){ |
---|
652 | this._elem.createDnDNodes(this._dndRegion); |
---|
653 | var m = Manager.manager(); |
---|
654 | var oldMakeAvatar = m.makeAvatar; |
---|
655 | m._dndPlugin = this; |
---|
656 | m.makeAvatar = function(){ |
---|
657 | var avatar = new GridDnDAvatar(m); |
---|
658 | delete m._dndPlugin; |
---|
659 | return avatar; |
---|
660 | }; |
---|
661 | m.startDrag(this._source, this._elem.getDnDNodes(), evt.ctrlKey); |
---|
662 | m.makeAvatar = oldMakeAvatar; |
---|
663 | m.onMouseMove(evt); |
---|
664 | }, |
---|
665 | _destroySource: function(){ |
---|
666 | connect.publish("/dnd/cancel"); |
---|
667 | }, |
---|
668 | _createMoveable: function(evt){ |
---|
669 | if(!this._markTagetAnchorHandler){ |
---|
670 | this._markTagetAnchorHandler = this.connect(win.doc, "onmousemove", "_markTargetAnchor"); |
---|
671 | } |
---|
672 | }, |
---|
673 | _destroyMoveable: function(){ |
---|
674 | this.disconnect(this._markTagetAnchorHandler); |
---|
675 | delete this._markTagetAnchorHandler; |
---|
676 | }, |
---|
677 | _calcColTargetAnchorPos: function(evt, containerPos){ |
---|
678 | // summary: |
---|
679 | // Calculate the position of the column DnD avatar |
---|
680 | var i, headPos, left, target, ex = evt.clientX, |
---|
681 | cells = this.grid.layout.cells, |
---|
682 | ltr = html._isBodyLtr(), |
---|
683 | headers = this._getVisibleHeaders(); |
---|
684 | for(i = 0; i < headers.length; ++i){ |
---|
685 | headPos = html.position(headers[i].node); |
---|
686 | if(ltr ? ((i === 0 || ex >= headPos.x) && ex < headPos.x + headPos.w) : |
---|
687 | ((i === 0 || ex < headPos.x + headPos.w) && ex >= headPos.x)){ |
---|
688 | left = headPos.x + (ltr ? 0 : headPos.w); |
---|
689 | break; |
---|
690 | }else if(ltr ? (i === headers.length - 1 && ex >= headPos.x + headPos.w) : |
---|
691 | (i === headers.length - 1 && ex < headPos.x)){ |
---|
692 | ++i; |
---|
693 | left = headPos.x + (ltr ? headPos.w : 0); |
---|
694 | break; |
---|
695 | } |
---|
696 | } |
---|
697 | if(i < headers.length){ |
---|
698 | target = headers[i].cell.index; |
---|
699 | if(this.selector.isSelected("col", target) && this.selector.isSelected("col", target - 1)){ |
---|
700 | var ranges = this._dndRegion.selected; |
---|
701 | for(i = 0; i < ranges.length; ++i){ |
---|
702 | if(array.indexOf(ranges[i], target) >= 0){ |
---|
703 | target = ranges[i][0]; |
---|
704 | headPos = html.position(cells[target].getHeaderNode()); |
---|
705 | left = headPos.x + (ltr ? 0 : headPos.w); |
---|
706 | break; |
---|
707 | } |
---|
708 | } |
---|
709 | } |
---|
710 | }else{ |
---|
711 | target = cells.length; |
---|
712 | } |
---|
713 | this._target = target; |
---|
714 | return left - containerPos.x; |
---|
715 | }, |
---|
716 | _calcRowTargetAnchorPos: function(evt, containerPos){ |
---|
717 | // summary: |
---|
718 | // Calculate the position of the row DnD avatar |
---|
719 | var g = this.grid, top, i = 0, |
---|
720 | cells = g.layout.cells; |
---|
721 | while(cells[i].hidden){ ++i; } |
---|
722 | var cell = g.layout.cells[i], |
---|
723 | rowIndex = g.scroller.firstVisibleRow, |
---|
724 | cellNode = cell.getNode(rowIndex); |
---|
725 | if(!cellNode){ |
---|
726 | //if the target grid is empty, set to -1 |
---|
727 | //which will be processed in Rearrange |
---|
728 | this._target = -1; |
---|
729 | return 0; //position of the insert bar |
---|
730 | } |
---|
731 | var nodePos = html.position(cellNode); |
---|
732 | while(nodePos.y + nodePos.h < evt.clientY){ |
---|
733 | if(++rowIndex >= g.rowCount){ |
---|
734 | break; |
---|
735 | } |
---|
736 | nodePos = html.position(cell.getNode(rowIndex)); |
---|
737 | } |
---|
738 | if(rowIndex < g.rowCount){ |
---|
739 | if(this.selector.isSelected("row", rowIndex) && this.selector.isSelected("row", rowIndex - 1)){ |
---|
740 | var ranges = this._dndRegion.selected; |
---|
741 | for(i = 0; i < ranges.length; ++i){ |
---|
742 | if(array.indexOf(ranges[i], rowIndex) >= 0){ |
---|
743 | rowIndex = ranges[i][0]; |
---|
744 | nodePos = html.position(cell.getNode(rowIndex)); |
---|
745 | break; |
---|
746 | } |
---|
747 | } |
---|
748 | } |
---|
749 | top = nodePos.y; |
---|
750 | }else{ |
---|
751 | top = nodePos.y + nodePos.h; |
---|
752 | } |
---|
753 | this._target = rowIndex; |
---|
754 | return top - containerPos.y; |
---|
755 | }, |
---|
756 | _calcCellTargetAnchorPos: function(evt, containerPos, targetAnchor){ |
---|
757 | // summary: |
---|
758 | // Calculate the position of the cell DnD avatar |
---|
759 | var s = this._dndRegion.selected[0], |
---|
760 | origin = this._dndRegion.handle, |
---|
761 | g = this.grid, ltr = html._isBodyLtr(), |
---|
762 | cells = g.layout.cells, headPos, |
---|
763 | minPos, maxPos, headers, |
---|
764 | height, width, left, top, |
---|
765 | minCol, maxCol, i, |
---|
766 | preSpan = origin.col - s.min.col, |
---|
767 | postSpan = s.max.col - origin.col, |
---|
768 | leftTopDiv, rightBottomDiv; |
---|
769 | if(!targetAnchor.childNodes.length){ |
---|
770 | leftTopDiv = html.create("div", { |
---|
771 | "class": "dojoxGridCellBorderLeftTopDIV" |
---|
772 | }, targetAnchor); |
---|
773 | rightBottomDiv = html.create("div", { |
---|
774 | "class": "dojoxGridCellBorderRightBottomDIV" |
---|
775 | }, targetAnchor); |
---|
776 | }else{ |
---|
777 | leftTopDiv = query(".dojoxGridCellBorderLeftTopDIV", targetAnchor)[0]; |
---|
778 | rightBottomDiv = query(".dojoxGridCellBorderRightBottomDIV", targetAnchor)[0]; |
---|
779 | } |
---|
780 | for(i = s.min.col + 1; i < origin.col; ++i){ |
---|
781 | if(cells[i].hidden){ |
---|
782 | --preSpan; |
---|
783 | } |
---|
784 | } |
---|
785 | for(i = origin.col + 1; i < s.max.col; ++i){ |
---|
786 | if(cells[i].hidden){ |
---|
787 | --postSpan; |
---|
788 | } |
---|
789 | } |
---|
790 | headers = this._getVisibleHeaders(); |
---|
791 | //calc width |
---|
792 | for(i = preSpan; i < headers.length - postSpan; ++i){ |
---|
793 | headPos = html.position(headers[i].node); |
---|
794 | if((evt.clientX >= headPos.x && evt.clientX < headPos.x + headPos.w) || //within in this column |
---|
795 | //prior to this column, but within range |
---|
796 | (i == preSpan && (ltr ? evt.clientX < headPos.x : evt.clientX >= headPos.x + headPos.w)) || |
---|
797 | //post to this column, but within range |
---|
798 | (i == headers.length - postSpan - 1 && (ltr ? evt.clientX >= headPos.x + headPos.w : evt < headPos.x))){ |
---|
799 | minCol = headers[i - preSpan]; |
---|
800 | maxCol = headers[i + postSpan]; |
---|
801 | minPos = html.position(minCol.node); |
---|
802 | maxPos = html.position(maxCol.node); |
---|
803 | minCol = minCol.cell.index; |
---|
804 | maxCol = maxCol.cell.index; |
---|
805 | left = ltr ? minPos.x : maxPos.x; |
---|
806 | width = ltr ? (maxPos.x + maxPos.w - minPos.x) : (minPos.x + minPos.w - maxPos.x); |
---|
807 | break; |
---|
808 | } |
---|
809 | } |
---|
810 | //calc height |
---|
811 | i = 0; |
---|
812 | while(cells[i].hidden){ ++i; } |
---|
813 | var cell = cells[i], |
---|
814 | rowIndex = g.scroller.firstVisibleRow, |
---|
815 | nodePos = html.position(cell.getNode(rowIndex)); |
---|
816 | while(nodePos.y + nodePos.h < evt.clientY){ |
---|
817 | if(++rowIndex < g.rowCount){ |
---|
818 | nodePos = html.position(cell.getNode(rowIndex)); |
---|
819 | }else{ |
---|
820 | break; |
---|
821 | } |
---|
822 | } |
---|
823 | var minRow = rowIndex >= origin.row - s.min.row ? rowIndex - origin.row + s.min.row : 0; |
---|
824 | var maxRow = minRow + s.max.row - s.min.row; |
---|
825 | if(maxRow >= g.rowCount){ |
---|
826 | maxRow = g.rowCount - 1; |
---|
827 | minRow = maxRow - s.max.row + s.min.row; |
---|
828 | } |
---|
829 | minPos = html.position(cell.getNode(minRow)); |
---|
830 | maxPos = html.position(cell.getNode(maxRow)); |
---|
831 | top = minPos.y; |
---|
832 | height = maxPos.y + maxPos.h - minPos.y; |
---|
833 | this._target = { |
---|
834 | "min":{ |
---|
835 | "row": minRow, |
---|
836 | "col": minCol |
---|
837 | }, |
---|
838 | "max":{ |
---|
839 | "row": maxRow, |
---|
840 | "col": maxCol |
---|
841 | } |
---|
842 | }; |
---|
843 | var anchorBorderSize = (html.marginBox(leftTopDiv).w - html.contentBox(leftTopDiv).w) / 2; |
---|
844 | var leftTopCellPos = html.position(cells[minCol].getNode(minRow)); |
---|
845 | html.style(leftTopDiv, { |
---|
846 | "width": (leftTopCellPos.w - anchorBorderSize) + "px", |
---|
847 | "height": (leftTopCellPos.h - anchorBorderSize) + "px" |
---|
848 | }); |
---|
849 | var rightBottomCellPos = html.position(cells[maxCol].getNode(maxRow)); |
---|
850 | html.style(rightBottomDiv, { |
---|
851 | "width": (rightBottomCellPos.w - anchorBorderSize) + "px", |
---|
852 | "height": (rightBottomCellPos.h - anchorBorderSize) + "px" |
---|
853 | }); |
---|
854 | return { |
---|
855 | h: height, |
---|
856 | w: width, |
---|
857 | l: left - containerPos.x, |
---|
858 | t: top - containerPos.y |
---|
859 | }; |
---|
860 | }, |
---|
861 | _markTargetAnchor: function(evt){ |
---|
862 | try{ |
---|
863 | var t = this._dndRegion.type; |
---|
864 | if(this._alreadyOut || (this._dnding && !this._config[t]["within"]) || (this._extDnding && !this._config[t]["in"])){ |
---|
865 | return; |
---|
866 | } |
---|
867 | var height, width, left, top, |
---|
868 | targetAnchor = this._targetAnchor[t], |
---|
869 | pos = html.position(this._container); |
---|
870 | if(!targetAnchor){ |
---|
871 | targetAnchor = this._targetAnchor[t] = html.create("div", { |
---|
872 | "class": (t == "cell") ? "dojoxGridCellBorderDIV" : "dojoxGridBorderDIV" |
---|
873 | }); |
---|
874 | html.style(targetAnchor, "display", "none"); |
---|
875 | this._container.appendChild(targetAnchor); |
---|
876 | } |
---|
877 | switch(t){ |
---|
878 | case "col": |
---|
879 | height = pos.h; |
---|
880 | width = this._targetAnchorBorderWidth; |
---|
881 | left = this._calcColTargetAnchorPos(evt, pos); |
---|
882 | top = 0; |
---|
883 | break; |
---|
884 | case "row": |
---|
885 | height = this._targetAnchorBorderWidth; |
---|
886 | width = pos.w; |
---|
887 | left = 0; |
---|
888 | top = this._calcRowTargetAnchorPos(evt, pos); |
---|
889 | break; |
---|
890 | case "cell": |
---|
891 | var cellPos = this._calcCellTargetAnchorPos(evt, pos, targetAnchor); |
---|
892 | height = cellPos.h; |
---|
893 | width = cellPos.w; |
---|
894 | left = cellPos.l; |
---|
895 | top = cellPos.t; |
---|
896 | } |
---|
897 | if(typeof height == "number" && typeof width == "number" && typeof left == "number" && typeof top == "number"){ |
---|
898 | html.style(targetAnchor, { |
---|
899 | "height": height + "px", |
---|
900 | "width": width + "px", |
---|
901 | "left": left + "px", |
---|
902 | "top": top + "px" |
---|
903 | }); |
---|
904 | html.style(targetAnchor, "display", ""); |
---|
905 | }else{ |
---|
906 | this._target = null; |
---|
907 | } |
---|
908 | }catch(e){ |
---|
909 | console.warn("DnD._markTargetAnchor() error:",e); |
---|
910 | } |
---|
911 | }, |
---|
912 | _unmarkTargetAnchor: function(){ |
---|
913 | if(this._dndRegion){ |
---|
914 | var targetAnchor = this._targetAnchor[this._dndRegion.type]; |
---|
915 | if(targetAnchor){ |
---|
916 | html.style(this._targetAnchor[this._dndRegion.type], "display", "none"); |
---|
917 | } |
---|
918 | } |
---|
919 | }, |
---|
920 | _getVisibleHeaders: function(){ |
---|
921 | return array.map(array.filter(this.grid.layout.cells, function(cell){ |
---|
922 | return !cell.hidden; |
---|
923 | }), function(cell){ |
---|
924 | return { |
---|
925 | "node": cell.getHeaderNode(), |
---|
926 | "cell": cell |
---|
927 | }; |
---|
928 | }); |
---|
929 | }, |
---|
930 | _rearrange: function(){ |
---|
931 | if(this._target === null){ |
---|
932 | return; |
---|
933 | } |
---|
934 | var t = this._dndRegion.type; |
---|
935 | var ranges = this._dndRegion.selected; |
---|
936 | if(t === "cell"){ |
---|
937 | this.rearranger[(this._isCopy || this._copyOnly) ? "copyCells" : "moveCells"](ranges[0], this._target === -1 ? null : this._target); |
---|
938 | }else{ |
---|
939 | this.rearranger[t == "col" ? "moveColumns" : "moveRows"](_joinToArray(ranges), this._target === -1 ? null: this._target); |
---|
940 | } |
---|
941 | this._target = null; |
---|
942 | }, |
---|
943 | onDraggingOver: function(sourcePlugin){ |
---|
944 | if(!this._dnding && sourcePlugin){ |
---|
945 | sourcePlugin._isSource = true; |
---|
946 | this._extDnding = true; |
---|
947 | if(!this._externalDnd){ |
---|
948 | this._externalDnd = true; |
---|
949 | this._dndRegion = this._mapRegion(sourcePlugin.grid, sourcePlugin._dndRegion); |
---|
950 | } |
---|
951 | this._createDnDUI(this._moveEvent,true); |
---|
952 | this.grid.pluginMgr.getPlugin("autoScroll").readyForAutoScroll = true; |
---|
953 | } |
---|
954 | }, |
---|
955 | _mapRegion: function(srcGrid, dndRegion){ |
---|
956 | if(dndRegion.type === "cell"){ |
---|
957 | var srcRange = dndRegion.selected[0]; |
---|
958 | var cells = this.grid.layout.cells; |
---|
959 | var srcCells = srcGrid.layout.cells; |
---|
960 | var c, cnt = 0; |
---|
961 | for(c = srcRange.min.col; c <= srcRange.max.col; ++c){ |
---|
962 | if(!srcCells[c].hidden){ |
---|
963 | ++cnt; |
---|
964 | } |
---|
965 | } |
---|
966 | for(c = 0; cnt > 0; ++c){ |
---|
967 | if(!cells[c].hidden){ |
---|
968 | --cnt; |
---|
969 | } |
---|
970 | } |
---|
971 | var region = lang.clone(dndRegion); |
---|
972 | region.selected[0].min.col = 0; |
---|
973 | region.selected[0].max.col = c - 1; |
---|
974 | for(c = srcRange.min.col; c <= dndRegion.handle.col; ++c){ |
---|
975 | if(!srcCells[c].hidden){ |
---|
976 | ++cnt; |
---|
977 | } |
---|
978 | } |
---|
979 | for(c = 0; cnt > 0; ++c){ |
---|
980 | if(!cells[c].hidden){ |
---|
981 | --cnt; |
---|
982 | } |
---|
983 | } |
---|
984 | region.handle.col = c; |
---|
985 | } |
---|
986 | return dndRegion; |
---|
987 | }, |
---|
988 | onDraggingOut: function(sourcePlugin){ |
---|
989 | if(this._externalDnd){ |
---|
990 | this._extDnding = false; |
---|
991 | this._destroyDnDUI(true, false); |
---|
992 | if(sourcePlugin){ |
---|
993 | sourcePlugin._isSource = false; |
---|
994 | } |
---|
995 | } |
---|
996 | }, |
---|
997 | onDragIn: function(sourcePlugin, isCopy){ |
---|
998 | var success = false; |
---|
999 | if(this._target !== null){ |
---|
1000 | var type = sourcePlugin._dndRegion.type; |
---|
1001 | var ranges = sourcePlugin._dndRegion.selected; |
---|
1002 | switch(type){ |
---|
1003 | case "cell": |
---|
1004 | this.rearranger.changeCells(sourcePlugin.grid, ranges[0], this._target); |
---|
1005 | break; |
---|
1006 | case "row": |
---|
1007 | var range = _joinToArray(ranges); |
---|
1008 | this.rearranger.insertRows(sourcePlugin.grid, range, this._target); |
---|
1009 | break; |
---|
1010 | } |
---|
1011 | success = true; |
---|
1012 | } |
---|
1013 | this._endDnd(true); |
---|
1014 | if(sourcePlugin.onDragOut){ |
---|
1015 | sourcePlugin.onDragOut(success && !isCopy); |
---|
1016 | } |
---|
1017 | }, |
---|
1018 | onDragOut: function(isMove){ |
---|
1019 | if(isMove && !this._copyOnly){ |
---|
1020 | var type = this._dndRegion.type; |
---|
1021 | var ranges = this._dndRegion.selected; |
---|
1022 | switch(type){ |
---|
1023 | case "cell": |
---|
1024 | this.rearranger.clearCells(ranges[0]); |
---|
1025 | break; |
---|
1026 | case "row": |
---|
1027 | this.rearranger.removeRows(_joinToArray(ranges)); |
---|
1028 | break; |
---|
1029 | } |
---|
1030 | } |
---|
1031 | this._endDnd(true); |
---|
1032 | }, |
---|
1033 | _canAccept: function(sourcePlugin){ |
---|
1034 | if(!sourcePlugin){ |
---|
1035 | return false; |
---|
1036 | } |
---|
1037 | var srcRegion = sourcePlugin._dndRegion; |
---|
1038 | var type = srcRegion.type; |
---|
1039 | if(!this._config[type]["in"] || !sourcePlugin._config[type]["out"]){ |
---|
1040 | return false; |
---|
1041 | } |
---|
1042 | var g = this.grid; |
---|
1043 | var ranges = srcRegion.selected; |
---|
1044 | var colCnt = array.filter(g.layout.cells, function(cell){ |
---|
1045 | return !cell.hidden; |
---|
1046 | }).length; |
---|
1047 | var rowCnt = g.rowCount; |
---|
1048 | var res = true; |
---|
1049 | switch(type){ |
---|
1050 | case "cell": |
---|
1051 | ranges = ranges[0]; |
---|
1052 | res = g.store.getFeatures()["dojo.data.api.Write"] && |
---|
1053 | (ranges.max.row - ranges.min.row) <= rowCnt && |
---|
1054 | array.filter(sourcePlugin.grid.layout.cells, function(cell){ |
---|
1055 | return cell.index >= ranges.min.col && cell.index <= ranges.max.col && !cell.hidden; |
---|
1056 | }).length <= colCnt; |
---|
1057 | //intentional drop through - don't break |
---|
1058 | case "row": |
---|
1059 | if(sourcePlugin._allDnDItemsLoaded()){ |
---|
1060 | return res; |
---|
1061 | } |
---|
1062 | } |
---|
1063 | return false; |
---|
1064 | }, |
---|
1065 | _allDnDItemsLoaded: function(){ |
---|
1066 | if(this._dndRegion){ |
---|
1067 | var type = this._dndRegion.type, |
---|
1068 | ranges = this._dndRegion.selected, |
---|
1069 | rows = []; |
---|
1070 | switch(type){ |
---|
1071 | case "cell": |
---|
1072 | for(var i = ranges[0].min.row, max = ranges[0].max.row; i <= max; ++i){ |
---|
1073 | rows.push(i); |
---|
1074 | } |
---|
1075 | break; |
---|
1076 | case "row": |
---|
1077 | rows = _joinToArray(ranges); |
---|
1078 | break; |
---|
1079 | default: |
---|
1080 | return false; |
---|
1081 | } |
---|
1082 | var cache = this.grid._by_idx; |
---|
1083 | return array.every(rows, function(rowIndex){ |
---|
1084 | return !!cache[rowIndex]; |
---|
1085 | }); |
---|
1086 | } |
---|
1087 | return false; |
---|
1088 | } |
---|
1089 | }); |
---|
1090 | |
---|
1091 | EnhancedGrid.registerPlugin(DnD/*name:'dnd'*/, { |
---|
1092 | "dependency": ["selector", "rearrange"] |
---|
1093 | }); |
---|
1094 | |
---|
1095 | return DnD; |
---|
1096 | }); |
---|