]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/SOGoDragAndDrop.js
initial sync
[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           event.target.dndExit();
165         if (operation.destination.dndDrop) {
166           var data = null;
167           if (operation.source.dndDataForType)
168             data = operation.source.dndDataForType(operation.type);
169           var result = event.target.dndDrop(data);
170           if (operation.ghost) {
171             if (result)
172               operation.bustGhost();
173             else
174               operation.chaseGhost();
175           }
176         }
177         else
178           if (operation.ghost)
179             operation.chaseGhost();
180       } else {
181         if (operation.ghost)
182           operation.chaseGhost();
183       }
184       document.DNDManager.currentDndOperation = null;
185     }
186   },
187   currentDndOperation: null,
188 }
189
190 /* DNDOperation */
191 document.DNDOperation = function (source, point) {
192   this.startPoint = point;
193   this.source = source;
194   if (source.dndTypes) {
195     this.types = source.dndTypes();
196   }
197   this.type = null;
198   this.destination = null;
199   if (source.dndGhost) {
200     var ghost = source.dndGhost();
201     ghost.style.position = "absolute;";
202     ghost.style.zIndex = 10000;
203     ghost.style.MozOpacity = 0.8;
204     document.body.appendChild(ghost);
205     this.ghost = ghost;
206
207     document.addEventListener("mousemove", this.moveGhost, false);
208   }
209
210   return this;
211 };
212
213 document.DNDOperation.prototype.setDestination = function(destination) {
214   this.destination = destination;
215 }
216
217 document.DNDOperation.prototype.moveGhost = function(event) {
218   var offsetX = event.clientX;
219   var offsetY = event.clientY;
220   if (document.DNDManager.currentDndOperation.ghost.ghostOffsetX)
221     offsetX += document.DNDManager.currentDndOperation.ghost.ghostOffsetX;
222   if (document.DNDManager.currentDndOperation.ghost.ghostOffsetY)
223     offsetY += document.DNDManager.currentDndOperation.ghost.ghostOffsetY;
224
225   document.DNDManager.currentDndOperation.ghost.style.left = offsetX + "px;";
226   document.DNDManager.currentDndOperation.ghost.style.top = offsetY + "px;";
227 }
228
229 document.DNDOperation.prototype.bustGhost = function() {
230   document._dyingOperation = this;
231   document.removeEventListener("mousemove", this.moveGhost, false);
232   this.ghost.bustStep = 10;
233   setTimeout("document._dyingOperation._fadeGhost();", 50);
234 }
235
236 document.DNDOperation.prototype.chaseGhost = function() {
237   document._dyingOperation = this;
238   document.removeEventListener("mousemove", this.moveGhost, false);
239   this.ghost.bustStep = 25;
240   this.ghost.chaseStep = 25;
241   this.ghost.chaseDeltaX = ((this.ghost.cascadeLeftOffset() - this.startPoint[0])
242                            / this.ghost.chaseStep);
243   this.ghost.chaseDeltaY = ((this.ghost.cascadeTopOffset() - this.startPoint[1])
244                            / this.ghost.chaseStep);
245   setTimeout("document._dyingOperation._chaseGhost();", 20);
246 }
247
248 document.DNDOperation.prototype._chaseGhost = function() {
249   if (this.ghost.chaseStep) {
250     var newLeft = this.ghost.cascadeLeftOffset() - this.ghost.chaseDeltaX; 
251     var newTop = this.ghost.cascadeTopOffset() - this.ghost.chaseDeltaY;
252     this.ghost.style.MozOpacity = (0.04 * this.ghost.chaseStep);
253     this.ghost.style.left = newLeft + "px;";
254     this.ghost.style.top = newTop + "px;";
255     this.ghost.chaseStep--;
256     setTimeout("document._dyingOperation._chaseGhost();", 20);
257   }
258   else {
259     document.body.removeChild(this.ghost);
260     this.ghost = null;
261   }
262 }
263
264 document.DNDOperation.prototype._fadeGhost = function() {
265   if (this.ghost.bustStep) {
266     this.ghost.style.MozOpacity = (0.1 * this.ghost.bustStep);
267     this.ghost.bustStep--;
268     setTimeout("document._dyingOperation._fadeGhost();", 50);
269   }
270   else {
271     document.body.removeChild(this.ghost);
272     this.ghost = null;
273   }
274 }