reservation plugin - unbound request (unclean
[unfold.git] / portal / static / unbound_reservation_static / src / dom.jsPlumb.js
1 /*
2  * jsPlumb
3  * 
4  * Title:jsPlumb 1.5.5
5  * 
6  * Provides a way to visually connect elements on an HTML page, using either SVG, Canvas
7  * elements, or VML.  
8  * 
9  * This file contains the basic adapter that does not require any support library such as jquery, yui or mootools.
10
11         but it's not yet there.  currently this is a copy of the jquery adapter.
12
13  *
14  * Copyright (c) 2010 - 2013 Simon Porritt (http://jsplumb.org)
15  * 
16  * http://jsplumb.org
17  * http://github.com/sporritt/jsplumb
18  * http://code.google.com/p/jsplumb
19  * 
20  * Dual licensed under the MIT and GPL2 licenses.
21  */ 
22 /* 
23  * the library specific functions, such as find offset, get id, get attribute, extend etc.  
24  * the full list is:
25  * 
26  * addClass                             adds a class to the given element
27  * animate                              calls the underlying library's animate functionality
28  * appendElement                appends a child element to a parent element.
29  * bind                                 binds some event to an element
30  * dragEvents                   a dictionary of event names
31  * extend                               extend some js object with another.  probably not overly necessary; jsPlumb could just do this internally.
32  * getAttribute                 gets some attribute from an element
33  * getDragObject                gets the object that is being dragged, by extracting it from the arguments passed to a drag callback
34  * getDragScope                 gets the drag scope for a given element.
35  * getDropScope                 gets the drop scope for a given element.
36  * getElementObject             turns an id or dom element into an element object of the underlying library's type.
37  * getOffset                    gets an element's offset
38  * getOriginalEvent     gets the original browser event from some wrapper event
39  * getPageXY                    gets the page event's xy location.
40  * getParent                    gets the parent of some element.
41  * getScrollLeft                gets an element's scroll left.  TODO: is this actually used?  will it be?
42  * getScrollTop                 gets an element's scroll top.  TODO: is this actually used?  will it be?
43  * getSize                              gets an element's size.
44  * getUIPosition                gets the position of some element that is currently being dragged, by extracting it from the arguments passed to a drag callback.
45  * hasClass                             returns whether or not the given element has the given class.
46  * initDraggable                initializes an element to be draggable 
47  * initDroppable                initializes an element to be droppable
48  * isDragSupported              returns whether or not drag is supported for some element.
49  * isDropSupported              returns whether or not drop is supported for some element.
50  * removeClass                  removes a class from a given element.
51  * removeElement                removes some element completely from the DOM.
52  * setAttribute                 sets an attribute on some element.
53  * setDraggable                 sets whether or not some element should be draggable.
54  * setDragScope                 sets the drag scope for a given element.
55  * setOffset                    sets the offset of some element.
56  * trigger                              triggers some event on an element.
57  * unbind                               unbinds some listener from some element.
58  */
59 (function($) {  
60         
61         //var getBoundingClientRectSupported = "getBoundingClientRect" in document.documentElement;
62
63     /*
64
65     METHODS TO USE/INVESTIGATE:
66
67         getBoundingClientRect
68         element.matches(...)
69         document.querySelector/querySelectorAll
70         element.classList (has add and remove methods)
71
72      */
73
74     
75     var _setClassName = function(el, val) {        
76             if (el.className.baseVal) 
77                 el.className.baseVal = val;
78             else 
79                 el.className = val;
80         },
81         _getClassName = function(el) {
82             return el.className.baseVal != null ? el.className.baseVal : el.className;
83         },
84         _classManip = function(el, add, clazz) {
85                   var classesToAddOrRemove = clazz.split(" "),                  
86                           curClasses = _getClassName(el).split(" ");
87                         
88             for (var i = 0; i < classesToAddOrRemove.length; i++) {
89                 if (add) {
90                     if (curClasses.indexOf(classesToAddOrRemove[i]) == -1)
91                         curClasses.push(classesToAddOrRemove[i]);
92                 }
93                 else {
94                     var idx = curClasses.indexOf(classesToAddOrRemove[i]);
95                     if (idx != -1)
96                         curClasses.splice(idx, 1);
97                 }
98             }
99             
100             _setClassName(el, curClasses.join(" "));
101         },
102         _addClass = function(el, clazz) {
103             _classManip(el, true, clazz);
104         },
105         _removeClass = function(el, clazz) {
106             _classManip(el, false, clazz);
107         };
108     
109
110         jsPlumb.CurrentLibrary = {                                              
111                 
112                 /**
113                  * adds the given class to the element object.
114                  */
115                 addClass : function(el, clazz) {
116                         el = jsPlumb.CurrentLibrary.getElementObject(el);
117                         try {
118                                 if (el[0].className.constructor == SVGAnimatedString) {
119                                         jsPlumbUtil.svg.addClass(el[0], clazz);                    
120                                 }
121                         }
122                         catch (e) {
123                                 // SVGAnimatedString not supported; no problem.
124                         }
125             try {                
126                 el.addClass(clazz);
127             }
128             catch (e) {
129                 // you probably have jQuery 1.9 and Firefox.  
130             }
131                 },
132                 
133                 /**
134                  * animates the given element.
135                  */
136                 animate : function(el, properties, options) {
137                         el.animate(properties, options);
138                 },                              
139                 
140                 /**
141                  * appends the given child to the given parent.
142                  */
143                 appendElement : function(child, parent) {
144                         jsPlumb.CurrentLibrary.getElementObject(parent).append(child);                  
145                 },   
146
147                 /**
148                 * executes an ajax call.
149                 */
150                 ajax : function(params) {
151                         params = params || {};
152                         params.type = params.type || "get";
153                         $.ajax(params);
154                 },
155                 
156                 /**
157                  * event binding wrapper.  it just so happens that jQuery uses 'bind' also.  yui3, for example,
158                  * uses 'on'.
159                  */
160                 bind : function(el, event, callback) {
161                         el = jsPlumb.CurrentLibrary.getElementObject(el);
162                         el.bind(event, callback);
163                 },
164                 
165                 /**
166          * mapping of drag events for jQuery
167          */
168                 dragEvents : {
169                         'start':'start', 'stop':'stop', 'drag':'drag', 'step':'step',
170                         'over':'over', 'out':'out', 'drop':'drop', 'complete':'complete'
171                 },
172                                 
173                 /**
174                  * wrapper around the library's 'extend' functionality (which it hopefully has.
175                  * otherwise you'll have to do it yourself). perhaps jsPlumb could do this for you
176                  * instead.  it's not like its hard.
177                  */
178                 extend : function(o1, o2) {
179                         return $.extend(o1, o2);
180                 },
181                 
182                 /**
183                  * gets the named attribute from the given element object.  
184                  */
185                 getAttribute : function(el, attName) {
186                         return el.attr(attName);
187                 },
188                 
189                 getClientXY : function(eventObject) {
190                         return [eventObject.clientX, eventObject.clientY];
191                 },
192                 
193                 /**
194                  * takes the args passed to an event function and returns you an object representing that which is being dragged.
195                  */
196                 getDragObject : function(eventArgs) {
197                         return eventArgs[1].draggable || eventArgs[1].helper;
198                 },
199                 
200                 getDragScope : function(el) {
201                         return el.draggable("option", "scope");
202                 },
203
204                 getDropEvent : function(args) {
205                         return args[0];
206                 },
207                 
208                 getDropScope : function(el) {
209                         return el.droppable("option", "scope");         
210                 },
211
212                 /**
213                 * gets a DOM element from the given input, which might be a string (in which case we just do document.getElementById),
214                 * a selector (in which case we return el[0]), or a DOM element already (we assume this if it's not either of the other
215                 * two cases).  this is the opposite of getElementObject below.
216                 */
217                 getDOMElement : function(el) {
218                         if (typeof(el) == "string") return document.getElementById(el);
219                         else if (el.context || el.length != null) return el[0];
220                         else return el;
221                 },
222         
223                 /**
224                  * gets an "element object" from the given input.  this means an object that is used by the
225                  * underlying library on which jsPlumb is running.  'el' may already be one of these objects,
226                  * in which case it is returned as-is.  otherwise, 'el' is a String, the library's lookup 
227                  * function is used to find the element, using the given String as the element's id.
228                  * 
229                  */             
230                 getElementObject : function(el) {                       
231                         return typeof(el) == "string" ? $("#" + el) : $(el);
232                 },
233                 
234                 /**
235                   * gets the offset for the element object.  this should return a js object like this:
236                   *
237                   * { left:xxx, top: xxx }
238                  */
239                 getOffset : function(el) {
240                         return el.offset();
241                 },
242
243                 getOriginalEvent : function(e) {
244                         return e.originalEvent;
245                 },
246                 
247                 getPageXY : function(eventObject) {
248                         return [eventObject.pageX, eventObject.pageY];
249                 },
250                 
251                 getParent : function(el) {
252                         return jsPlumb.CurrentLibrary.getElementObject(el).parent();
253                 },
254                                                                                                                 
255                 getScrollLeft : function(el) {
256                         return el.scrollLeft();
257                 },
258                 
259                 getScrollTop : function(el) {
260                         return el.scrollTop();
261                 },
262                 
263                 getSelector : function(context, spec) {
264             if (arguments.length == 2)
265                 return jsPlumb.CurrentLibrary.getElementObject(context).find(spec);
266             else
267                 return $(context);
268                 },
269                 
270                 /**
271                  * gets the size for the element object, in an array : [ width, height ].
272                  */
273                 getSize : function(el) {
274                         return [el.outerWidth(), el.outerHeight()];
275                 },
276
277         getTagName : function(el) {
278             var e = jsPlumb.CurrentLibrary.getElementObject(el);
279             return e.length > 0 ? e[0].tagName : null;
280         },
281                 
282                 /**
283                  * takes the args passed to an event function and returns you an object that gives the
284                  * position of the object being moved, as a js object with the same params as the result of
285                  * getOffset, ie: { left: xxx, top: xxx }.
286                  * 
287                  * different libraries have different signatures for their event callbacks.  
288                  * see getDragObject as well
289                  */
290                 getUIPosition : function(eventArgs, zoom) {
291                         
292                         zoom = zoom || 1;
293                         // this code is a workaround for the case that the element being dragged has a margin set on it. jquery UI passes
294                         // in the wrong offset if the element has a margin (it doesn't take the margin into account).  the getBoundingClientRect
295                         // method, which is in pretty much all browsers now, reports the right numbers.  but it introduces a noticeable lag, which
296                         // i don't like.
297             
298                         /*if ( getBoundingClientRectSupported ) {
299                                 var r = eventArgs[1].helper[0].getBoundingClientRect();
300                                 return { left : r.left, top: r.top };
301                         } else {*/
302                         if (eventArgs.length == 1) {
303                                 ret = { left: eventArgs[0].pageX, top:eventArgs[0].pageY };
304                         }
305                         else {
306                                 var ui = eventArgs[1],
307                                   _offset = ui.offset;
308                                   
309                                 ret = _offset || ui.absolutePosition;
310                                 
311                                 // adjust ui position to account for zoom, because jquery ui does not do this.
312                                 ui.position.left /= zoom;
313                                 ui.position.top /= zoom;
314                         }
315             return { left:ret.left / zoom, top: ret.top / zoom };
316                 },              
317                 
318                 hasClass : function(el, clazz) {
319                         return el.hasClass(clazz);
320                 },
321                 
322                 /**
323                  * initialises the given element to be draggable.
324                  */
325                 initDraggable : function(el, options, isPlumbedComponent) {
326                         options = options || {};
327                         // remove helper directive if present and no override
328                         if (!options.doNotRemoveHelper)
329                                 options.helper = null;
330                         if (isPlumbedComponent)
331                                 options['scope'] = options['scope'] || jsPlumb.Defaults.Scope;
332                         el.draggable(options);
333                 },
334                 
335                 /**
336                  * initialises the given element to be droppable.
337                  */
338                 initDroppable : function(el, options) {
339                         options['scope'] = options['scope'] || jsPlumb.Defaults.Scope;
340                         el.droppable(options);
341                 },
342                 
343                 isAlreadyDraggable : function(el) {
344                         el = jsPlumb.CurrentLibrary.getElementObject(el);
345                         return el.hasClass("ui-draggable");
346                 },
347                 
348                 /**
349                  * returns whether or not drag is supported (by the library, not whether or not it is disabled) for the given element.
350                  */
351                 isDragSupported : function(el, options) {
352                         return el.draggable;
353                 },                              
354                                                 
355                 /**
356                  * returns whether or not drop is supported (by the library, not whether or not it is disabled) for the given element.
357                  */
358                 isDropSupported : function(el, options) {
359                         return el.droppable;
360                 },                                                      
361                 
362                 /**
363                  * removes the given class from the element object.
364                  */
365                 removeClass : function(el, clazz) {
366                         el = jsPlumb.CurrentLibrary.getElementObject(el);
367                         try {
368                                 if (el[0].className.constructor == SVGAnimatedString) {
369                                         jsPlumbUtil.svg.removeClass(el[0], clazz);
370                     return;
371                                 }
372                         }
373                         catch (e) {
374                                 // SVGAnimatedString not supported; no problem.
375                         }
376                         el.removeClass(clazz);
377                 },
378                 
379                 removeElement : function(element) {                     
380                         jsPlumb.CurrentLibrary.getElementObject(element).remove();
381                 },
382                 
383                 /**
384                  * sets the named attribute on the given element object.  
385                  */
386                 setAttribute : function(el, attName, attValue) {
387                         el.attr(attName, attValue);
388                 },
389                 
390                 /**
391                  * sets the draggable state for the given element
392                  */
393                 setDraggable : function(el, draggable) {
394                         el.draggable("option", "disabled", !draggable);
395                 },
396                 
397                 /**
398                  * sets the drag scope.  probably time for a setDragOption method (roll this and the one above together)
399                  * @param el
400                  * @param scope
401                  */
402                 setDragScope : function(el, scope) {
403                         el.draggable("option", "scope", scope);
404                 },
405                 
406                 setOffset : function(el, o) {
407                         jsPlumb.CurrentLibrary.getElementObject(el).offset(o);
408                 },
409                 
410                 /**
411                  * note that jquery ignores the name of the event you wanted to trigger, and figures it out for itself.
412                  * the other libraries do not.  yui, in fact, cannot even pass an original event.  we have to pull out stuff
413                  * from the originalEvent to put in an options object for YUI. 
414                  * @param el
415                  * @param event
416                  * @param originalEvent
417                  */
418                 trigger : function(el, event, originalEvent) {
419                         //originalEvent.stopPropagation();
420                         //jsPlumb.CurrentLibrary.getElementObject(el).trigger(originalEvent);
421             var h = jQuery._data(jsPlumb.CurrentLibrary.getElementObject(el)[0], "handle");
422             h(originalEvent);
423             //originalEvent.stopPropagation();
424                 },
425                 
426                 /**
427                  * event unbinding wrapper.  it just so happens that jQuery uses 'unbind' also.  yui3, for example,
428                  * uses..something else.
429                  */
430                 unbind : function(el, event, callback) {
431                         el = jsPlumb.CurrentLibrary.getElementObject(el);
432                         el.unbind(event, callback);
433                 }
434         };
435         
436         $(document).ready(jsPlumb.init);
437         
438 })(jQuery);