17ca9be1f8f9ad4e13d5a69c1b310ae9ff78627c
[ccsdk/features.git] / sdnr / wt / devicemanager / provider / src / main / resources / elasticsearch / plugins / head / src / app / ux / dragdrop.js
1 (function( $, app ) {
2
3         var ux = app.ns("ux");
4
5         /**
6          * Provides drag and drop functionality<br>
7          * a DragDrop instance is created for each usage pattern and then used over and over again<br>
8          * first a dragObj is defined - this is the jquery node that will be dragged around<br>
9          * second, the event callbacks are defined - these allow you control the ui during dragging and run functions when successfully dropping<br>
10          * thirdly drop targets are defined - this is a list of DOM nodes, the constructor works in one of two modes:
11          * <li>without targets - objects can be picked up and dragged around, dragStart and dragStop events fire</li>
12          * <li>with targets - as objects are dragged over targets dragOver, dragOut and DragDrop events fire
13          * to start dragging call the DragDrop.pickup_handler() function, dragging stops when the mouse is released.
14          * @constructor
15          * The following options are supported
16          * <dt>targetSelector</dt>
17          *   <dd>an argument passed directly to jquery to create a list of targets, as such it can be a CSS style selector, or an array of DOM nodes<br>if target selector is null the DragDrop does Drag only and will not fire dragOver dragOut and dragDrop events</dd>
18          * <dt>pickupSelector</dt>
19          *   <dd>a jquery selector. The pickup_handler is automatically bound to matched elements (eg clicking on these elements starts the drag). if pickupSelector is null, the pickup_handler must be manually bound <code>$(el).bind("mousedown", dragdrop.pickup_handler)</code></dd>
20          * <dt>dragObj</dt>
21          *   <dd>the jQuery element to drag around when pickup is called. If not defined, dragObj must be set in onDragStart</dd>
22          * <dt>draggingClass</dt>
23          *   <dd>the class(es) added to items when they are being dragged</dd>
24          * The following observables are supported
25          * <dt>dragStart</dt>
26          *   <dd>a callback when start to drag<br><code>function(jEv)</code></dd>
27          * <dt>dragOver</dt>
28          *   <dd>a callback when we drag into a target<br><code>function(jEl)</code></dd>
29          * <dt>dragOut</dt>
30          *   <dd>a callback when we drag out of a target, or when we drop over a target<br><code>function(jEl)</code></dd>
31          * <dt>dragDrop</dt>
32          *   <dd>a callback when we drop on a target<br><code>function(jEl)</code></dd>
33          * <dt>dragStop</dt>
34          *   <dd>a callback when we stop dragging<br><code>function(jEv)</code></dd>
35          */
36         ux.DragDrop = ux.Observable.extend({
37                 defaults : {
38                         targetsSelector : null,
39                         pickupSelector:   null,
40                         dragObj :         null,
41                         draggingClass :   "dragging"
42                 },
43
44                 init: function(options) {
45                         this._super(); // call the class initialiser
46                 
47                         this.drag_handler = this.drag.bind(this);
48                         this.drop_handler = this.drop.bind(this);
49                         this.pickup_handler = this.pickup.bind(this);
50                         this.targets = [];
51                         this.dragObj = null;
52                         this.dragObjOffset = null;
53                         this.currentTarget = null;
54                         if(this.config.pickupSelector) {
55                                 $(this.config.pickupSelector).bind("mousedown", this.pickup_handler);
56                         }
57                 },
58
59                 drag : function(jEv) {
60                         jEv.preventDefault();
61                         var mloc = acx.vector( this.lockX || jEv.pageX, this.lockY || jEv.pageY );
62                         this.dragObj.css(mloc.add(this.dragObjOffset).asOffset());
63                         if(this.targets.length === 0) {
64                                 return;
65                         }
66                         if(this.currentTarget !== null && mloc.within(this.currentTarget[1], this.currentTarget[2])) {
67                                 return;
68                         }
69                         if(this.currentTarget !== null) {
70                                 this.fire('dragOut', this.currentTarget[0]);
71                                 this.currentTarget = null;
72                         }
73                         for(var i = 0; i < this.targets.length; i++) {
74                                 if(mloc.within(this.targets[i][1], this.targets[i][2])) {
75                                         this.currentTarget = this.targets[i];
76                                         break;
77                                 }
78                         }
79                         if(this.currentTarget !== null) {
80                                 this.fire('dragOver', this.currentTarget[0]);
81                         }
82                 },
83                 
84                 drop : function(jEv) {
85                         $(document).unbind("mousemove", this.drag_handler);
86                         $(document).unbind("mouseup", this.drop_handler);
87                         this.dragObj.removeClass(this.config.draggingClass);
88                         if(this.currentTarget !== null) {
89                                 this.fire('dragOut', this.currentTarget[0]);
90                                 this.fire('dragDrop', this.currentTarget[0]);
91                         }
92                         this.fire('dragStop', jEv);
93                         this.dragObj = null;
94                 },
95                 
96                 pickup : function(jEv, opts) {
97                         $.extend(this.config, opts);
98                         this.fire('dragStart', jEv);
99                         this.dragObj = this.dragObj || this.config.dragObj;
100                         this.dragObjOffset = this.config.dragObjOffset || acx.vector(this.dragObj.offset()).sub(jEv.pageX, jEv.pageY);
101                         this.lockX = this.config.lockX ? jEv.pageX : 0;
102                         this.lockY = this.config.lockY ? jEv.pageY : 0;
103                         this.dragObj.addClass(this.config.draggingClass);
104                         if(!this.dragObj.get(0).parentNode || this.dragObj.get(0).parentNode.nodeType === 11) { // 11 = document fragment
105                                 $(document.body).append(this.dragObj);
106                         }
107                         if(this.config.targetsSelector) {
108                                 this.currentTarget = null;
109                                 var targets = ( this.targets = [] );
110                                 // create an array of elements optimised for rapid collision detection calculation
111                                 $(this.config.targetsSelector).each(function(i, el) {
112                                         var jEl = $(el);
113                                         var tl = acx.vector(jEl.offset());
114                                         var br = tl.add(jEl.width(), jEl.height());
115                                         targets.push([jEl, tl, br]);
116                                 });
117                         }
118                         $(document).bind("mousemove", this.drag_handler);
119                         $(document).bind("mouseup", this.drop_handler);
120                         this.drag_handler(jEv);
121                 }
122         });
123
124 })( this.jQuery, this.app );