]> err.no Git - scalable-opengroupware.org/blob - UI/WebServerResources/SOGoDragAndDrop.js
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1153 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     document._currentMouseGestureObject._removeGestureHandlers();
27   },
28   dragGestureMouseMoveHandler: function (event) {
29     var deltaX = event.clientX - document._dragGestureStartPoint[0];
30     var deltaY = event.clientY - document._dragGestureStartPoint[1];
31     if (Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)) > 10) {
32       event.returnValue = true;
33       event.cancelBubble = true;
34       var object = document._currentMouseGestureObject;
35       var point = document._dragGestureStartPoint;
36       document.DNDManager.startDragging(object, point);
37       document._currentMouseGestureObject._removeGestureHandlers();
38     }
39   }
40 }
41
42 /* DNDManager */
43 document.DNDManager = {
44   lastSource: 0,
45   lastDestination: 0,
46   sources: new Array(),
47   destinations: new Array(),
48   registerSource: function (source) {
49     var id = source.getAttribute("id");
50     if (!id) {
51       id = "_dndSource" + (this.lastSource + 1);
52       source.setAttribute("id", id);
53     }
54     this.sources[id] = source;
55     this.lastSource++;
56     source.addInterface(SOGODragAndDropSourceInterface);
57   },
58   registerDestination: function (destination) {
59     var id = destination.getAttribute("id");
60     if (!id) {
61       id = "_dndDestination" + (this.lastDestination + 1);
62       destination.setAttribute("id", id);
63     }
64     this.destinations[id] = destination;
65     this.lastDestination++;
66   },
67   _lookupSource: function (target) {
68     var source = null;
69     var id = target.getAttribute("id");
70     if (id)
71       source = document.DNDManager.sources[id];
72     return source;
73   },
74   _lookupDestination: function (target) {
75     var destination = null;
76     var id = target.getAttribute("id");
77     if (id)
78       destination = document.DNDManager.destinations[id];
79     return destination;
80   },
81   startDragging: function (object, point) {
82     var source = document.DNDManager._lookupSource (object);
83     if (source) {
84       document.DNDManager.currentDndOperation = new document.DNDOperation(source, point);
85       window.addEventListener("mouseup",
86                               document.DNDManager.destinationDrop, false);
87       window.addEventListener("mouseover",
88                               document.DNDManager.destinationEnter, false);
89       window.addEventListener("mousemove",
90                               document.DNDManager.destinationOver, false);
91       window.addEventListener("mouseout",
92                               document.DNDManager.destinationExit, false);
93     }
94   },
95   destinationEnter: function (event) {
96     var operation = document.DNDManager.currentDndOperation;
97     var destination = document.DNDManager._lookupDestination (event.target);
98     if (operation && destination && destination.dndAcceptType) {
99       operation.type = null;
100       var i = 0;
101       while (operation.type == null
102              && i < operation.types.length) {
103         if (destination.dndAcceptType(operation.types[i])) {
104           operation.type = operation.types[i];
105           operation.setDestination(destination);
106           if (destination.dndEnter)
107             destination.dndEnter(event, operation.source, operation.type);
108         }
109         else
110           i++;
111       }
112     }
113   },
114   destinationExit: function (event) {
115     var operation = document.DNDManager.currentDndOperation;
116     if (operation
117         && operation.destination == event.target) {
118       if (operation.destination.dndExit)
119         event.target.dndExit();
120       operation.setDestination(null);
121     }
122   },
123   destinationOver: function (event) {
124   },
125   destinationDrop: function (event) {
126     var operation = document.DNDManager.currentDndOperation;
127     if (operation) {
128       window.removeEventListener("mouseup",
129                                  document.DNDManager.destinationDrop, false);
130       window.removeEventListener("mouseover",
131                                  document.DNDManager.destinationEnter, false);
132       window.removeEventListener("mousemove",
133                                  document.DNDManager.destinationOver, false);
134       window.removeEventListener("mouseout",
135                                  document.DNDManager.destinationExit, false);
136       if (operation.destination == event.target) {
137         if (operation.destination.dndExit) {
138           operation.destination.dndExit();
139         }
140         if (operation.destination.dndDrop) {
141           var data = null;
142           if (operation.source.dndDataForType)
143             data = operation.source.dndDataForType(operation.type);
144           var result = operation.destination.dndDrop(data);
145           if (operation.ghost) {
146             if (result)
147               operation.bustGhost();
148             else
149               operation.chaseGhost();
150           }
151         }
152         else
153           if (operation.ghost)
154             operation.chaseGhost();
155       } else {
156         if (operation.ghost)
157           operation.chaseGhost();
158       }
159       document.DNDManager.currentDndOperation = null;
160     }
161   },
162   currentDndOperation: null
163 }
164
165 /* DNDOperation */
166 document.DNDOperation = function (source, point) {
167   this.startPoint = point;
168   this.source = source;
169   if (source.dndTypes) {
170     this.types = source.dndTypes();
171   }
172   this.type = null;
173   this.destination = null;
174   if (source.dndGhost) {
175     var ghost = source.dndGhost();
176     ghost.style.position = "absolute;";
177     ghost.style.zIndex = 10000;
178     ghost.style.MozOpacity = 0.8;
179     document.body.appendChild(ghost);
180     this.ghost = ghost;
181
182     document.addEventListener("mousemove", this.moveGhost, false);
183   }
184
185   return this;
186 };
187
188 document.DNDOperation.prototype.setDestination = function(destination) {
189   this.destination = destination;
190 }
191
192 document.DNDOperation.prototype.moveGhost = function(event) {
193   var offsetX = event.clientX;
194   var offsetY = event.clientY;
195   if (document.DNDManager.currentDndOperation.ghost.ghostOffsetX)
196     offsetX += document.DNDManager.currentDndOperation.ghost.ghostOffsetX;
197   if (document.DNDManager.currentDndOperation.ghost.ghostOffsetY)
198     offsetY += document.DNDManager.currentDndOperation.ghost.ghostOffsetY;
199
200   document.DNDManager.currentDndOperation.ghost.style.left = offsetX + "px;";
201   document.DNDManager.currentDndOperation.ghost.style.top = offsetY + "px;";
202 }
203
204 document.DNDOperation.prototype.bustGhost = function() {
205   document._dyingOperation = this;
206   document.removeEventListener("mousemove", this.moveGhost, false);
207   this.ghost.bustStep = 10;
208   setTimeout("document._dyingOperation._fadeGhost();", 50);
209 }
210
211 document.DNDOperation.prototype.chaseGhost = function() {
212   document._dyingOperation = this;
213   document.removeEventListener("mousemove", this.moveGhost, false);
214   this.ghost.bustStep = 25;
215   this.ghost.chaseStep = 25;
216   this.ghost.style.overflow = "hidden;"
217   this.ghost.style.whiteSpace = "nowrap;";
218   this.ghost.chaseDeltaX = ((this.ghost.cascadeLeftOffset() - this.startPoint[0])
219                            / this.ghost.chaseStep);
220   this.ghost.chaseDeltaY = ((this.ghost.cascadeTopOffset() - this.startPoint[1])
221                            / this.ghost.chaseStep);
222   setTimeout("document._dyingOperation._chaseGhost();", 20);
223 }
224
225 document.DNDOperation.prototype._chaseGhost = function() {
226   if (this.ghost.chaseStep) {
227     var newLeft = this.ghost.cascadeLeftOffset() - this.ghost.chaseDeltaX; 
228     var newTop = this.ghost.cascadeTopOffset() - this.ghost.chaseDeltaY;
229     this.ghost.style.MozOpacity = (0.04 * this.ghost.chaseStep);
230     this.ghost.style.left = newLeft + "px;";
231     this.ghost.style.top = newTop + "px;";
232     this.ghost.chaseStep--;
233     setTimeout("document._dyingOperation._chaseGhost();", 20);
234   }
235   else {
236     document.body.removeChild(this.ghost);
237     this.ghost = null;
238   }
239 }
240
241 document.DNDOperation.prototype._fadeGhost = function() {
242   if (this.ghost.bustStep) {
243     this.ghost.style.MozOpacity = (0.1 * this.ghost.bustStep);
244     this.ghost.style.width = (this.ghost.offsetWidth * .7) + "px;";
245     this.ghost.style.height = (this.ghost.offsetHeight * .7) + "px;";
246     this.ghost.bustStep--;
247     setTimeout("document._dyingOperation._fadeGhost();", 50);
248   }
249   else {
250     document.body.removeChild(this.ghost);
251     this.ghost = null;
252   }
253 }