/* * jsPlumb * * Title:jsPlumb 1.3.6 * * Provides a way to visually connect elements on an HTML page, using either SVG, Canvas * elements, or VML. * * This file contains the jQuery adapter. * * Copyright (c) 2010 - 2012 Simon Porritt (http://jsplumb.org) * * http://jsplumb.org * http://github.com/sporritt/jsplumb * http://code.google.com/p/jsplumb * * Dual licensed under the MIT and GPL2 licenses. */ /* * the library specific functions, such as find offset, get id, get attribute, extend etc. * the full list is: * * addClass adds a class to the given element * animate calls the underlying library's animate functionality * appendElement appends a child element to a parent element. * bind binds some event to an element * dragEvents a dictionary of event names * extend extend some js object with another. probably not overly necessary; jsPlumb could just do this internally. * getAttribute gets some attribute from an element * getDragObject gets the object that is being dragged, by extracting it from the arguments passed to a drag callback * getDragScope gets the drag scope for a given element. * getDropScope gets the drop scope for a given element. * getElementObject turns an id or dom element into an element object of the underlying library's type. * getOffset gets an element's offset * getPageXY gets the page event's xy location. * getParent gets the parent of some element. * getScrollLeft gets an element's scroll left. TODO: is this actually used? will it be? * getScrollTop gets an element's scroll top. TODO: is this actually used? will it be? * getSize gets an element's size. * getUIPosition gets the position of some element that is currently being dragged, by extracting it from the arguments passed to a drag callback. * hasClass returns whether or not the given element has the given class. * initDraggable initializes an element to be draggable * initDroppable initializes an element to be droppable * isDragSupported returns whether or not drag is supported for some element. * isDropSupported returns whether or not drop is supported for some element. * removeClass removes a class from a given element. * removeElement removes some element completely from the DOM. * setAttribute sets an attribute on some element. * setDraggable sets whether or not some element should be draggable. * setDragScope sets the drag scope for a given element. * setOffset sets the offset of some element. * trigger triggers some event on an element. * unbind unbinds some listener from some element. */ (function($) { //var getBoundingClientRectSupported = "getBoundingClientRect" in document.documentElement; jsPlumb.CurrentLibrary = { /** * adds the given class to the element object. */ addClass : function(el, clazz) { el = jsPlumb.CurrentLibrary.getElementObject(el); try { if (el[0].className.constructor == SVGAnimatedString) { jsPlumb.util.svg.addClass(el[0], clazz); } } catch (e) { // SVGAnimatedString not supported; no problem. } el.addClass(clazz); }, /** * animates the given element. */ animate : function(el, properties, options) { el.animate(properties, options); }, /** * appends the given child to the given parent. */ appendElement : function(child, parent) { jsPlumb.CurrentLibrary.getElementObject(parent).append(child); }, /** * event binding wrapper. it just so happens that jQuery uses 'bind' also. yui3, for example, * uses 'on'. */ bind : function(el, event, callback) { el = jsPlumb.CurrentLibrary.getElementObject(el); el.bind(event, callback); }, /** * mapping of drag events for jQuery */ dragEvents : { 'start':'start', 'stop':'stop', 'drag':'drag', 'step':'step', 'over':'over', 'out':'out', 'drop':'drop', 'complete':'complete' }, /** * wrapper around the library's 'extend' functionality (which it hopefully has. * otherwise you'll have to do it yourself). perhaps jsPlumb could do this for you * instead. it's not like its hard. */ extend : function(o1, o2) { return $.extend(o1, o2); }, /** * gets the named attribute from the given element object. */ getAttribute : function(el, attName) { return el.attr(attName); }, getClientXY : function(eventObject) { return [eventObject.clientX, eventObject.clientY]; }, getDocumentElement : function() { return document; }, /** * takes the args passed to an event function and returns you an object representing that which is being dragged. */ getDragObject : function(eventArgs) { return eventArgs[1].draggable; }, getDragScope : function(el) { return el.draggable("option", "scope"); }, getDropScope : function(el) { return el.droppable("option", "scope"); }, /** * gets a DOM element from the given input, which might be a string (in which case we just do document.getElementById), * 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 * two cases). this is the opposite of getElementObject below. */ getDOMElement : function(el) { if (typeof(el) == "string") return document.getElementById(el); else if (el.context) return el[0]; else return el; }, /** * gets an "element object" from the given input. this means an object that is used by the * underlying library on which jsPlumb is running. 'el' may already be one of these objects, * in which case it is returned as-is. otherwise, 'el' is a String, the library's lookup * function is used to find the element, using the given String as the element's id. * */ getElementObject : function(el) { return typeof(el) == "string" ? $("#" + el) : $(el); }, /** * gets the offset for the element object. this should return a js object like this: * * { left:xxx, top: xxx } */ getOffset : function(el) { return el.offset(); }, getPageXY : function(eventObject) { return [eventObject.pageX, eventObject.pageY]; }, getParent : function(el) { return jsPlumb.CurrentLibrary.getElementObject(el).parent(); }, getScrollLeft : function(el) { return el.scrollLeft(); }, getScrollTop : function(el) { return el.scrollTop(); }, getSelector : function(spec) { return $(spec); }, /** * gets the size for the element object, in an array : [ width, height ]. */ getSize : function(el) { return [el.outerWidth(), el.outerHeight()]; }, getTagName : function(el) { var e = jsPlumb.CurrentLibrary.getElementObject(el); return e.length > 0 ? e[0].tagName : null; }, /** * takes the args passed to an event function and returns you an object that gives the * position of the object being moved, as a js object with the same params as the result of * getOffset, ie: { left: xxx, top: xxx }. * * different libraries have different signatures for their event callbacks. * see getDragObject as well */ getUIPosition : function(eventArgs) { // this code is a workaround for the case that the element being dragged has a margin set on it. jquery UI passes // in the wrong offset if the element has a margin (it doesn't take the margin into account). the getBoundingClientRect // method, which is in pretty much all browsers now, reports the right numbers. but it introduces a noticeable lag, which // i don't like. /*if ( getBoundingClientRectSupported ) { var r = eventArgs[1].helper[0].getBoundingClientRect(); return { left : r.left, top: r.top }; } else {*/ if (eventArgs.length == 1) { ret = { left: eventArgs[0].pageX, top:eventArgs[0].pageY }; } else { var ui = eventArgs[1], _offset = ui.offset; ret = _offset || ui.absolutePosition; } return ret; }, hasClass : function(el, clazz) { return el.hasClass(clazz); }, /** * initialises the given element to be draggable. */ initDraggable : function(el, options) { options = options || {}; // remove helper directive if present. options.helper = null; options['scope'] = options['scope'] || jsPlumb.Defaults.Scope; el.draggable(options); }, /** * initialises the given element to be droppable. */ initDroppable : function(el, options) { options['scope'] = options['scope'] || jsPlumb.Defaults.Scope; el.droppable(options); }, isAlreadyDraggable : function(el) { el = jsPlumb.CurrentLibrary.getElementObject(el); return el.hasClass("ui-draggable"); }, /** * returns whether or not drag is supported (by the library, not whether or not it is disabled) for the given element. */ isDragSupported : function(el, options) { return el.draggable; }, /** * returns whether or not drop is supported (by the library, not whether or not it is disabled) for the given element. */ isDropSupported : function(el, options) { return el.droppable; }, /** * removes the given class from the element object. */ removeClass : function(el, clazz) { el = jsPlumb.CurrentLibrary.getElementObject(el); try { if (el[0].className.constructor == SVGAnimatedString) { jsPlumb.util.svg.removeClass(el[0], clazz); } } catch (e) { // SVGAnimatedString not supported; no problem. } el.removeClass(clazz); }, removeElement : function(element, parent) { jsPlumb.CurrentLibrary.getElementObject(element).remove(); }, /** * sets the named attribute on the given element object. */ setAttribute : function(el, attName, attValue) { el.attr(attName, attValue); }, /** * sets the draggable state for the given element */ setDraggable : function(el, draggable) { el.draggable("option", "disabled", !draggable); }, /** * sets the drag scope. probably time for a setDragOption method (roll this and the one above together) * @param el * @param scope */ setDragScope : function(el, scope) { el.draggable("option", "scope", scope); }, setOffset : function(el, o) { jsPlumb.CurrentLibrary.getElementObject(el).offset(o); }, /** * note that jquery ignores the name of the event you wanted to trigger, and figures it out for itself. * the other libraries do not. yui, in fact, cannot even pass an original event. we have to pull out stuff * from the originalEvent to put in an options object for YUI. * @param el * @param event * @param originalEvent */ trigger : function(el, event, originalEvent) { //originalEvent.stopPropagation(); //jsPlumb.CurrentLibrary.getElementObject(el).trigger(originalEvent); var h = jQuery._data(jsPlumb.CurrentLibrary.getElementObject(el)[0], "handle"); h(originalEvent); //originalEvent.stopPropagation(); }, /** * event unbinding wrapper. it just so happens that jQuery uses 'unbind' also. yui3, for example, * uses..something else. */ unbind : function(el, event, callback) { el = jsPlumb.CurrentLibrary.getElementObject(el); el.unbind(event, callback); } }; $(document).ready(jsPlumb.init); })(jQuery);