1 /**
  2  * @ignore
  3  */
  4 var Ozone = Ozone ? Ozone : {};
  5 
  6 /**
  7  * @ignore
  8  * @namespace
  9  */
 10 Ozone.dragAndDrop = Ozone.dragAndDrop ? Ozone.dragAndDrop : {};
 11 
 12 Ozone.dragAndDrop.WidgetDragAndDropContainer = function(cfg) {
 13 
 14     this.callback = cfg.callback;
 15 
 16     //set initial drag text
 17     this.dragIndicatorText = cfg.dragIndicatorText ? cfg.dragIndicatorText : 'Dragging Data';
 18 
 19     //create drag indicator
 20     this.dragIndicator = this.createDragIndicator();
 21     this.dragIndicatorTextNode = owfdojo.query('span.ddText',this.dragIndicator)[0];
 22 
 23     //subscribe to channels
 24     this.eventingContainer = cfg.eventingContainer;
 25     this.eventingContainer.subscribe(this.dragStartName, owfdojo.hitch(this, this.onStartDrag));
 26     this.eventingContainer.subscribe(this.dragStopInWidgetName, owfdojo.hitch(this, this.onDragStopInWidget));
 27     this.eventingContainer.subscribe(this.dragSendDataName, owfdojo.hitch(this, this.onDragSendData));
 28 
 29     //hook mouse move and mouse up
 30     this.listeners = {};
 31 
 32     this.callbacks = {};
 33 
 34     var lastEl;
 35 
 36     function fireMouseEvent(el, type, msg) {
 37         var evt;
 38         if(document.createEvent) {
 39             evt = document.createEvent('MouseEvents');
 40             evt.initMouseEvent(type, true, true, window, 1, 
 41                 msg.screenX, msg.screenY, msg.pageX, msg.pageY, 
 42                 false, false, false, false, null, null
 43             );
 44             el.dispatchEvent(evt);
 45         }
 46         else if(document.createEventObject) {
 47             evt = document.createEventObject();
 48             el.fireEvent('on' + type, evt);
 49         }
 50     }
 51 
 52     gadgets.rpc.register('_fake_mouse_move', owfdojo.hitch(this, function(msg) {
 53         var senderObj = gadgets.json.parse(msg.sender);
 54         var iframeId = gadgets.json.stringify({id:senderObj.id});
 55         var position = Ext.get(iframeId).getOffsetsTo(Ext.getBody());
 56         var el = document.elementFromPoint(position[0]+msg.pageX, position[1]+msg.pageY);
 57 
 58         // convert widget pageX and pageY to container pageX and pageY
 59         msg.pageX += position[0];
 60         msg.pageY += position[1];
 61 
 62         if(lastEl && lastEl !== el) {
 63             if(lastEl.nodeName === 'IFRAME') {
 64                 this.eventingContainer.publish(this.dragOutName, null, lastEl.id);
 65             }
 66             else {
 67                 fireMouseEvent(lastEl, 'mouseout', msg);
 68                 fireMouseEvent(el, 'mouseover', msg);
 69             }
 70         }
 71         if(el && el.nodeName === 'IFRAME') {
 72             var elPos = Ext.get(el.id).getOffsetsTo(Ext.getBody());
 73 
 74             // convert container pageX and pageY to sending widget's pageX and pageY to 
 75             msg.pageX -= elPos[0];
 76             msg.pageY -= elPos[1];
 77 
 78             gadgets.rpc.call(el.id, '_fire_mouse_move', null, msg);
 79             this.hideDragIndicator();
 80         }
 81         else if(el){
 82             fireMouseEvent(el, 'mousemove', msg);
 83         }
 84         // update lastEl
 85         lastEl = el;
 86     }));
 87 
 88     gadgets.rpc.register('_fake_mouse_out', owfdojo.hitch(this, this.hideDragIndicator));
 89 
 90     gadgets.rpc.register('_fake_mouse_up', owfdojo.hitch(this, function(msg) {
 91         var senderObj = gadgets.json.parse(msg.sender);
 92         var iframeId = gadgets.json.stringify({id:senderObj.id});
 93         var position = Ext.get(iframeId).getOffsetsTo(Ext.getBody());
 94         var el = document.elementFromPoint(position[0]+msg.pageX, position[1]+msg.pageY);
 95 
 96         msg.pageX += position[0];
 97         msg.pageY += position[1];
 98 
 99         if(el.nodeName === 'IFRAME') {
100             var elPos = Ext.get(el.id).getOffsetsTo(Ext.getBody())
101             msg.pageX -= elPos[0];
102             msg.pageY -= elPos[1];
103             gadgets.rpc.call(el.id, '_fire_mouse_up', null, msg);
104         }
105         else {
106             fireMouseEvent(el, 'mouseup', msg);
107         }
108         lastEl = null;
109     }));
110 };
111 
112 Ozone.dragAndDrop.WidgetDragAndDropContainer.prototype = {
113 
114   //public events
115   dragStart: 'dragStart',
116   dragStop: 'dragStop',
117   dropReceive: 'dropReceive',
118 
119   //private events
120   dragStartName: '_dragStart',
121   dragOverWidgetName: '_dragOverWidget',  
122   dragOutName: '_dragOutName',
123   dragStopInContainerName: '_dragStopInContainer',
124   dragStopInWidgetName: '_dragStopInWidget',
125   dragSendDataName: "_dragSendData",
126   dropReceiveDataName: "_dropReceiveData",
127   version: Ozone.version.owfversion + Ozone.version.dragAndDrop,
128   dragDropData: null,
129 
130 
131   createDragIndicator: function () {
132     return owfdojo.create('span', {
133       className: 'ddBox ddBoxCannotDrop',
134       style: 'display: none',
135       innerHTML: '<span class="ddText">' + this.dragIndicatorText + '</span>'
136     },
137     owfdojo.body()
138     );
139   },
140 
141   onStartDrag : function(sender, msg) {
142     this.dragging = true;
143 
144     if (owfdojo.isFunction(this.callbacks[this.dragStart])) {
145       //execute callback if false is returned don't continue
146       if (this.callbacks[this.dragStart](sender,msg) === false) {
147         return;
148       }
149     }
150 
151     this.dragIndicatorText = msg.dragDropLabel;
152 
153     if (this.listeners.onmousemove == null) {
154         this.listeners.onmousemove = owfdojo.connect(document, 'onmousemove', this, this.mouseMove);
155     }
156     if (this.listeners.onmouseup == null) {
157       this.listeners.onmouseup = owfdojo.connect(document, 'onmouseup', this, this.mouseUp);
158     }
159     if (this.listeners.onmouseout == null) {
160       this.listeners.onmouseout = owfdojo.connect(document, 'onmouseout', this, this.mouseOut);
161     }
162   },
163 
164   getMouseCoordinates: function (e) {
165     var returnValue = null;
166     if (e.pageX || e.pageY) {
167       returnValue = {
168         x : e.pageX,
169         y : e.pageY
170       };
171     }
172     else {
173       returnValue = {
174         x : e.clientX + document.body.scrollLeft - document.body.clientLeft,
175         y : e.clientY + document.body.scrollTop - document.body.clientTop
176       };
177     }
178     return returnValue;
179   },
180 
181   mouseMove : function(e) {
182     var clientWidth = null;
183     var clientHeight = null;
184     var mousePosition = this.getMouseCoordinates(e);
185     var leftWidth = mousePosition.x;
186     var topHeight = mousePosition.y;
187 
188     // Hide the drag indicator box while we move it
189     this.hideDragIndicator();
190 
191     if (e === undefined) {
192       e = window.event;
193     }
194 
195     // flipping mechanism when the cursor reaches the right or bottom edge of the widget
196     this.dragIndicator.style.top = topHeight + 19 + "px";
197     if (owfdojo.isIE) {
198       clientWidth = document.body.clientWidth;
199       clientHeight = document.body.clientHeight;
200     }
201     else {
202       clientWidth = window.innerWidth;
203       clientHeight = window.innerHeight;
204     }
205 
206     var rightLimit = clientWidth - 100;
207     if ((leftWidth < clientWidth) && (leftWidth > rightLimit)) {
208       this.dragIndicator.style.left = leftWidth - 88 + "px";
209     }
210     else {
211       this.dragIndicator.style.left = leftWidth + 12 + "px";
212     }
213     var bottomLimit = clientHeight - 40;
214     if ((topHeight > bottomLimit) && (topHeight < clientHeight)) {
215       this.dragIndicator.style.top = topHeight - 30 + "px";
216     }
217 
218     // set text on indicator
219     this.dragIndicatorTextNode.innerHTML = this.dragIndicatorText;
220     owfdojo.style(this.dragIndicator, {
221       display: 'block'
222     });
223   },
224 
225   onDragStopInWidget : function(sender, msg) {
226     this.hideDragIndicator();
227 
228     //disconnect listeners
229     for (l in this.listeners) {
230       owfdojo.disconnect(this.listeners[l]);
231       this.listeners[l] = null;
232     }
233 
234     //actually send data
235     this.eventingContainer.publish(this.dropReceiveDataName, this.dragDropData,sender);
236     // Publish event to let widgets know that the mouse button was released
237     this.eventingContainer.publish(this.dragStopInContainerName, null);
238 
239     this.dragging = false;
240 
241     if (owfdojo.isFunction(this.callbacks[this.dragStop])) {
242       //execute callback if false is returned don't continue
243       this.callbacks[this.dragStop](msg);
244     }
245   },
246 
247   mouseUp: function() {
248     this.hideDragIndicator();
249 
250     //disconnect listeners
251     for (l in this.listeners) {
252       owfdojo.disconnect(this.listeners[l]);
253       this.listeners[l] = null;
254     }
255 
256     // Publish event to let widgets know that the mouse button was released
257     this.eventingContainer.publish(this.dragStopInContainerName, null);
258 
259     this.dragging = false;
260 
261     if (owfdojo.isFunction(this.callbacks[this.dragStop])) {
262       //execute callback if false is returned don't continue
263       this.callbacks[this.dragStop]();
264     }
265   },
266 
267   mouseOut : function(e) {
268     if (e === undefined) {
269       e = window.event;
270     }
271     var mouseOutTarget = null;
272     if (e.toElement === undefined) {
273       mouseOutTarget = e.relatedTarget;
274     }
275     else {
276       mouseOutTarget = e.toElement;
277     }
278     if (mouseOutTarget) {
279 
280       this.hideDragIndicator();
281 
282       // Mouse cursor is moving into the desktop or another widget,
283       //  so we send an event informing widgets of this
284       this.eventingContainer.publish(this.dragOutName, null);
285     }
286   },
287 
288   onDragSendData: function(sender,data) {
289      this.dragDropData = data;
290   },
291 
292   addCallback : function(eventName, cb) {
293     this.callbacks[eventName] = cb;
294   },
295 
296   /**
297    * @description returns whether a drag is in progress
298    */
299   isDragging : function() {
300     return this.dragging;
301   },
302 
303     hideDragIndicator: function() {
304         owfdojo.style(this.dragIndicator, {
305             display: 'none'
306         });
307     }
308 };
309