      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