]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/SOGoDragAndDrop.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1036 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / WebServerResources / SOGoDragAndDrop.js
1 /* drag and drop */
2
3 /* HTMLElement interface */
4 var SOGODragAndDropSourceInterface = {
5   _removeGestureHandlers: function () {
6     window.removeEventListener("mousemove", this.dragGestureMouseMoveHandler, false);
7     window.removeEventListener("mouseup", this.dragGestureMouseUpHandler, false);
8     document._dragGestureStartPoint = null;
9     document._currentMouseGestureObject = null;
10   },
11   bind: function() {
12     this.addEventListener("mousedown", this.dragGestureMouseDownHandler, false);
13   },
14   dragGestureMouseDownHandler: function (event) {
15     if (event.button == 0) {
16       document._dragGestureStartPoint = new Array(event.clientX,
17                                                   event.clientY);
18       document._currentMouseGestureObject = this;
19       window.addEventListener("mousemove", this.dragGestureMouseMoveHandler,
20                               false);
21       window.addEventListener("mouseup", this.dragGestureMouseUpHandler,
22                               false);
23     }
24   },
25   dragGestureMouseUpHandler: function (event) {
26 //     log("mouseup");
27     document._currentMouseGestureObject._removeGestureHandlers();
28   },
29   dragGestureMouseMoveHandler: function (event) {
30 //     log("source mouse move (target: " + event.target + ")");
31     var deltaX = event.clientX - document._dragGestureStartPoint[0];
32     var deltaY = event.clientY - document._dragGestureStartPoint[1];
33     if (Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)) > 10) {
34 //       log("event: " + event);
35 //       event.stopPropagation();
36 //       event.preventDefault();
37       event.returnValue = true;
38       event.cancelBubble = true;
39       var object = document._currentMouseGestureObject;
40       var point = document._dragGestureStartPoint;
41       document.DNDManager.startDragging(object, point);
42       document._currentMouseGestureObject._removeGestureHandlers();
43 //       var mouseup = document.createEvent("MouseEvent");
44 //       mouseup.initEvent("mouseup", true, true);
45 //       event.target.dispatchEvent(mouseup);
46 //       var dragStart = document.createEvent("MouseEvents");
47 //       dragStart.initMouseEvent("draggesture-hack", true, true, window,
48 //                                event.detail, event.screenX, event.screenY,
49 //                                event.clientX, event.clientY, event.ctrlKey,
50 //                                event.altKey, event.shiftKey, event.metaKey,
51 //                                event.button, null);
52 //       this.dispatchEvent(dragStart);
53     }
54   }
55 }
56
57 /* DNDManager */
58 document.DNDManager = {
59   lastSource: 0,
60   lastDestination: 0,
61   sources: new Array(),
62   destinations: new Array(),
63   registerSource: function (source) {
64     var id = source.getAttribute("id");
65     if (!id) {
66       id = "_dndSource" + (this.lastSource + 1);
67       source.setAttribute("id", id);
68     }
69     this.sources[id] = source;
70     this.lastSource++;
71     source.addInterface(SOGODragAndDropSourceInterface);
72   },
73   registerDestination: function (destination) {
74     var id = destination.getAttribute("id");
75     if (!id) {
76       id = "_dndDestination" + (this.lastDestination + 1);
77       destination.setAttribute("id", id);
78     }
79     this.destinations[id] = destination;
80     this.lastDestination++;
81   },
82   _lookupSource: function (target) {
83     var source = null;
84     var id = target.getAttribute("id");
85     if (id)
86       source = document.DNDManager.sources[id];
87     return source;
88   },
89   _lookupDestination: function (target) {
90     var destination = null;
91     var id = target.getAttribute("id");
92     if (id)
93       destination = document.DNDManager.destinations[id];
94     return destination;
95   },
96   startDragging: function (object, point) {
97 //     log("source gesture intercepted (source: " + object + ")");
98     var source = document.DNDManager._lookupSource (object);
99     if (source) {
100 //       log("source known");
101       document.DNDManager.currentDndOperation = new document.DNDOperation(source, point);
102       window.addEventListener("mouseup",
103                               document.DNDManager.destinationDrop, false);
104       window.addEventListener("mouseover",
105                               document.DNDManager.destinationEnter, false);
106       window.addEventListener("mousemove",
107                               document.DNDManager.destinationOver, false);
108       window.addEventListener("mouseout",
109                               document.DNDManager.destinationExit, false);
110     }
111   },
112   destinationEnter: function (event) {
113     var operation = document.DNDManager.currentDndOperation;
114     var destination = document.DNDManager._lookupDestination (event.target);
115     if (operation && destination && destination.dndAcceptType) {
116 //       log("enter: " + event.target);
117       operation.type = null;
118       var i = 0;
119       while (operation.type == null
120              && i < operation.types.length) {
121         if (destination.dndAcceptType(operation.types[i])) {
122           operation.type = operation.types[i];
123           operation.setDestination(destination);
124           if (destination.dndEnter)
125             destination.dndEnter(event, operation.source, operation.type);
126         }
127         else
128           i++;
129       }
130     }
131   },
132   destinationExit: function (event) {
133     var operation = document.DNDManager.currentDndOperation;
134     if (operation
135         && operation.destination == event.target) {
136 //       log("exit: " + event.target);
137       if (operation.destination.dndExit)
138         event.target.dndExit();
139       operation.setDestination(null);
140     }
141   },
142   destinationOver: function (event) {
143 //     log("over: " + event.target);
144 //     var operation = document.DNDManager.currentDndOperation;
145 //     if (operation
146 //         && operation.destination == event.target)
147 //       log("over: " + event.target);
148   },
149   destinationDrop: function (event) {
150 //     log ("drop...");
151     var operation = document.DNDManager.currentDndOperation;
152     if (operation) {
153       window.removeEventListener("mouseup",
154                                  document.DNDManager.destinationDrop, false);
155       window.removeEventListener("mouseover",
156                                  document.DNDManager.destinationEnter, false);
157       window.removeEventListener("mousemove",
158                                  document.DNDManager.destinationOver, false);
159       window.removeEventListener("mouseout",
160                                  document.DNDManager.destinationExit, false);
161       if (operation.destination == event.target) {
162 //         log("drag / drop: " + operation.source + " to " + operation.destination);
163         if (operation.destination.dndExit) {
164 //           log ("destination.dndExit...");
165           operation.destination.dndExit();
166         }
167         if (operation.destination.dndDrop) {
168 //           log ("destination.dndDrop...");
169           var data = null;
170 //           log ("optype: " + operation.type);
171           if (operation.source.dndDataForType)
172             data = operation.source.dndDataForType(operation.type);
173 //           log ("data: " + data);
174           var result = operation.destination.dndDrop(data);
175 //           log ("result: " + result);
176           if (operation.ghost) {
177             if (result)
178               operation.bustGhost();
179             else
180               operation.chaseGhost();
181           }
182         }
183         else
184           if (operation.ghost)
185             operation.chaseGhost();
186       } else {
187         if (operation.ghost)
188           operation.chaseGhost();
189       }
190       document.DNDManager.currentDndOperation = null;
191     }
192   },
193   currentDndOperation: null,
194 }
195
196 /* DNDOperation */
197 document.DNDOperation = function (source, point) {
198   this.startPoint = point;
199   this.source = source;
200   if (source.dndTypes) {
201     this.types = source.dndTypes();
202   }
203   this.type = null;
204   this.destination = null;
205   if (source.dndGhost) {
206     var ghost = source.dndGhost();
207     ghost.style.position = "absolute;";
208     ghost.style.zIndex = 10000;
209     ghost.style.MozOpacity = 0.8;
210     document.body.appendChild(ghost);
211     this.ghost = ghost;
212
213     document.addEventListener("mousemove", this.moveGhost, false);
214   }
215
216   return this;
217 };
218
219 document.DNDOperation.prototype.setDestination = function(destination) {
220   this.destination = destination;
221 }
222
223 document.DNDOperation.prototype.moveGhost = function(event) {
224   var offsetX = event.clientX;
225   var offsetY = event.clientY;
226   if (document.DNDManager.currentDndOperation.ghost.ghostOffsetX)
227     offsetX += document.DNDManager.currentDndOperation.ghost.ghostOffsetX;
228   if (document.DNDManager.currentDndOperation.ghost.ghostOffsetY)
229     offsetY += document.DNDManager.currentDndOperation.ghost.ghostOffsetY;
230
231   document.DNDManager.currentDndOperation.ghost.style.left = offsetX + "px;";
232   document.DNDManager.currentDndOperation.ghost.style.top = offsetY + "px;";
233 }
234
235 document.DNDOperation.prototype.bustGhost = function() {
236   document._dyingOperation = this;
237   document.removeEventListener("mousemove", this.moveGhost, false);
238   this.ghost.bustStep = 10;
239   setTimeout("document._dyingOperation._fadeGhost();", 50);
240 }
241
242 document.DNDOperation.prototype.chaseGhost = function() {
243   document._dyingOperation = this;
244   document.removeEventListener("mousemove", this.moveGhost, false);
245   this.ghost.bustStep = 25;
246   this.ghost.chaseStep = 25;
247   this.ghost.chaseDeltaX = ((this.ghost.cascadeLeftOffset() - this.startPoint[0])
248                            / this.ghost.chaseStep);
249   this.ghost.chaseDeltaY = ((this.ghost.cascadeTopOffset() - this.startPoint[1])
250                            / this.ghost.chaseStep);
251   setTimeout("document._dyingOperation._chaseGhost();", 20);
252 }
253
254 document.DNDOperation.prototype._chaseGhost = function() {
255   if (this.ghost.chaseStep) {
256     var newLeft = this.ghost.cascadeLeftOffset() - this.ghost.chaseDeltaX; 
257     var newTop = this.ghost.cascadeTopOffset() - this.ghost.chaseDeltaY;
258     this.ghost.style.MozOpacity = (0.04 * this.ghost.chaseStep);
259     this.ghost.style.left = newLeft + "px;";
260     this.ghost.style.top = newTop + "px;";
261     this.ghost.chaseStep--;
262     setTimeout("document._dyingOperation._chaseGhost();", 20);
263   }
264   else {
265     document.body.removeChild(this.ghost);
266     this.ghost = null;
267   }
268 }
269
270 document.DNDOperation.prototype._fadeGhost = function() {
271   if (this.ghost.bustStep) {
272     this.ghost.style.MozOpacity = (0.1 * this.ghost.bustStep);
273     this.ghost.bustStep--;
274     setTimeout("document._dyingOperation._fadeGhost();", 50);
275   }
276   else {
277     document.body.removeChild(this.ghost);
278     this.ghost = null;
279   }
280 }