Show:
                        /**
                        * HTML5 canvas visual directed graph creation tool 
                        *
                        * @module raska
                        * @main installUsing
                        */
                        (function (w, d) {
                        
                            'use strict';
                        
                            /**
                             * An utility that wraps the commom taks to avoid code repetition
                             *
                             * @module raska
                             * @submodule _helpers
                             */
                            var $ = d.querySelector.bind(d),
                                _helpers = (function () {
                        
                                    /// A shim to allow a better animation frame timing
                                    w.requestAnimationFrame = function () {
                                        var _timer = null;
                                        return w.requestAnimationFrame || w.webkitRequestAnimationFrame ||
                                            w.mozRequestAnimationFrame || w.msRequestAnimationFrame ||
                                            w.oRequestAnimationFrame || function (f) {
                                                if (_timer !== null) {
                                                    w.clearTimeout(_timer);
                                                }
                                                _timer = w.setTimeout(f, _activeConfiguration.frameRefreshRate);
                                            }
                                    }();
                        
                                    return {
                        
                                        /**
                                        * DOM manipulation related helpers
                                        *
                                        * @class $dom
                                        * @module raska
                                        * @submodule _helpers
                                        * @static
                                        */
                                        $dom: (function () {
                        
                                            var DOMElementHelper = function (ele) {
                        
                                                if (_helpers.$obj.is(ele.raw, "function")) {
                                                    ele = ele.raw();
                                                }
                        
                                                return {
                        
                                                    /**
                                                    * Get/Sets the styling of a given element
                                                    * 
                                                    * @method css
                                                    * @param {string} name Style attribute
                                                    * @param {string} value Style value
                                                    * @chainable
                                                    */
                                                    css: function (name, value) {
                                                        if (_helpers.$obj.isType(name, "string")) {
                                                            if (_helpers.$obj.isUndefined(value)) {
                                                                return ele.style[name];
                                                            }
                                                            if (value === "") {
                                                                return DOMElementHelper(ele).removeCss(name);
                                                            }
                                                            ele.style[name] = value;
                                                        } else {
                                                            for (var attr in name) {
                                                                DOMElementHelper(ele).css(attr, name[attr]);
                                                            }
                                                        }
                                                        return DOMElementHelper(ele);
                                                    },
                        
                                                    /**
                                                    * Removes the styling attrribute of a given element
                                                    * 
                                                    * @method css
                                                    * @param {string} name Style attribute
                                                    * @chainable
                                                    */
                                                    removeCss: function (name) {
                                                        if (ele.style.removeProperty) {
                                                            ele.style.removeProperty(name);
                                                        } else {
                                                            ele.style[name] = "";
                                                        }
                                                        return DOMElementHelper(ele);
                                                    },
                        
                                                    /**
                                                    * Gets/Sets the value for a given attribute of an HTML element
                                                    * 
                                                    * @method attr
                                                    * @param {string} name Attribute name
                                                    * @param {string} value Attribute value
                                                    * @chainable
                                                    */
                                                    attr: function (name, value) {
                                                        if (_helpers.$obj.isType(name, "string")) {
                                                            if (_helpers.$obj.isUndefined(value)) {
                                                                return ele.getAttribute(name);
                                                            }
                                                            ele.setAttribute(name, value);
                        
                                                        } else {
                                                            for (var attr in name) {
                                                                DOMElementHelper(ele).attr(attr, name[attr]);
                                                            }
                                                        }
                                                        return DOMElementHelper(ele);
                                                    },
                        
                                                    /**
                                                    * Retrieves the raw HTML element wraped by this helper
                                                    * 
                                                    * @method raw
                                                    * @return {HTMLElement} The element itself
                                                    */
                                                    raw: function () {
                                                        return ele;
                                                    },
                        
                        
                                                    /**
                                                    * Gathers UI iteraction X/Y coordinates from an event
                                                    * 
                                                    * @method getXYPositionFrom
                                                    * @param {HTMLElement} container The element that contains the bounding rect we'll use to gather relative positioning data
                                                    * @param {event} evt The event we're extracting information from 
                                                    * @return {x,y} Values
                                                    */
                                                    getXYPositionFrom: function (evt) {
                                                        if (_helpers.$device.isTouch
                                                            && _helpers.$obj.is(evt.touches.length, "number")
                                                            && evt.touches.length > 0) {
                                                            evt = evt.touches[0];
                                                        }
                        
                                                        var eleRect = ele.getBoundingClientRect();
                                                        return {
                                                            x: ((evt.clientX - eleRect.left) * (ele.width / eleRect.width)),
                                                            y: ((evt.clientY - eleRect.top) * (ele.height / eleRect.height))
                                                        };
                                                    },
                        
                                                    /**
                                                    * Creates a new child element relative to this HTML element
                                                    * 
                                                    * @method addChild
                                                    * @param {string} type Element node type
                                                    * @chainable
                                                    */
                                                    addChild: function (type) {
                                                        if (_helpers.$obj.isType(type, "string")) {
                                                            var childElement = $thisDOM.create(type);
                                                            ele.appendChild(childElement.raw());
                                                            return childElement;
                                                        } else {
                                                            ele.appendChild(type);
                                                            return DOMElementHelper(type);
                                                        }
                                                    },
                        
                                                    /**
                                                    * Get the node name for this element
                                                    * 
                                                    * @method type
                                                    * @return {string} The node name for this element
                                                    */
                                                    type: function () {
                                                        return ele.nodeName;
                                                    },
                        
                                                    /**
                                                    * Gets the parent node for this element
                                                    * 
                                                    * @method getParent
                                                    * @chainable
                                                    */
                                                    getParent: function () {
                                                        return DOMElementHelper((ele.parentElement) ? ele.parentElement : ele.parentNode);
                                                    },
                        
                                                    /**
                                                    * Adds a sibling element
                                                    * 
                                                    * @method addSibling
                                                    * @param {string} type Element node type
                                                    * @chainable
                                                    */
                                                    addSibling: function (type) {
                                                        return DOMElementHelper(ele).getParent().addChild(type);
                                                    },
                        
                                                    /**
                                                    * Gets\Sets the innerHTML content for the HTML element
                                                    * 
                                                    * @method html
                                                    * @param {string} content 
                                                    * @chainable
                                                    */
                                                    html: function (content) {
                                                        if (_helpers.$obj.isType(content, "string")) {
                                                            ele.innerHTML = content;
                                                            return DOMElementHelper(ele);
                                                        }
                                                        return ele.innerHTML;
                                                    },
                        
                                                    /**
                                                    * Gets\Sets the innerText content for the HTML element
                                                    * 
                                                    * @method html
                                                    * @param {string} content 
                                                    * @chainable
                                                    */
                                                    text: function (content) {
                                                        if (_helpers.$obj.isType(content, "string")) {
                                                            ele.innerText = content;
                                                            return DOMElementHelper(ele);
                                                        }
                                                        return ele.innerText;
                                                    },
                        
                                                    /**
                                                    * Registers a delegate to a given element event
                                                    * 
                                                    * @method on
                                                    * @param {HTMLElement} targetElement The element that we're interested in
                                                    * @param {String} iteractionType The event name
                                                    * @param {Function} triggerWrapper The delegate
                                                    * @chainable
                                                    */
                                                    on: function (iteractionType, triggerWrapper) {
                                                        // modern browsers including IE9+
                                                        if (w.addEventListener) { ele.addEventListener(iteractionType, triggerWrapper, false); }
                                                            // IE8 and below
                                                        else if (w.attachEvent) { ele.attachEvent("on" + iteractionType, triggerWrapper); }
                                                        else { ele["on" + iteractionType] = triggerWrapper; }
                                                        return DOMElementHelper(ele);
                                                    },
                        
                                                    /**
                                                    * Selects the first occurent of child elements that matches the selector
                                                    * 
                                                    * @method child
                                                    * @param {string} selector Element's selector
                                                    * @return {DOMElementHelper} The element wraped in a helper object
                                                    */
                                                    first: function (selector) {
                        
                                                        //https://developer.mozilla.org/en-US/docs/Web/CSS/:scope#Browser_compatibility
                                                        var result = ele.querySelectorAll(":scope > " + selector);
                                                        if (_helpers.$obj.isType(result, "nodelist")) {
                                                            return DOMElementHelper(result[0]);
                                                        }
                                                        return null;
                                                    }
                                                };
                                            },
                                            $thisDOM = {
                        
                                                /**
                                                * Creates and returns an element
                                                * 
                                                * @method create
                                                * @param {string} type Element node type
                                                * @param {HTMLElement} parent Element's parent node
                                                * @return {DOMElementHelper} The element wraped in a helper object
                                                */
                                                create: function (type, parent) {
                                                    var newElement = d.createElement(type);
                                                    newElement.id = _helpers.$obj.generateId();
                                                    if (_helpers.$obj.isValid(parent)) {
                                                        DOMElementHelper(parent).addChild(newElement);
                                                    }
                                                    return DOMElementHelper(newElement);
                                                },
                        
                                                /**
                                                * Gathers an element using a given selector query
                                                * 
                                                * @method get
                                                * @param {string} selector Element's selector
                                                * @return {DOMElementHelper} The element wraped in a helper object
                                                */
                                                get: function (selector) {
                                                    var element = _helpers.$obj.isType(selector, "string") ? $(selector) : selector;
                                                    return DOMElementHelper(element);
                                                },
                        
                                                /**
                                                * Gathers an element using a given id
                                                * 
                                                * @method getById
                                                * @param {string} id Element's id
                                                * @return {DOMElementHelper} The element wraped in a helper object
                                                */
                                                getById: function (id) {
                                                    return DOMElementHelper($("#" + id));
                                                }
                                            };
                        
                                            return $thisDOM;
                                        })(),
                        
                                        /**
                                        * Device related helpers
                                        *
                                        * @class $device
                                        * @module raska
                                        * @submodule _helpers
                                        * @static
                                        */
                                        $device: (function () {
                        
                                            var _isTouch = (('ontouchstart' in w)
                                                     || (navigator.MaxTouchPoints > 0)
                                                     || (navigator.msMaxTouchPoints > 0)),
                                                _this = {
                        
                                                    /**
                                                    * Whether or not to the current devide is touchscreen
                                                    *
                                                    * @property isTouch
                                                    * @type Bool
                                                    */
                                                    isTouch: _isTouch,
                        
                                                    /**
                                                    * Gathers UI iteraction X/Y coordinates from an event
                                                    * 
                                                    * @method gathersXYPositionFrom
                                                    * @param {HTMLElement} container The element that contains the bounding rect we'll use to gather relative positioning data
                                                    * @param {event} evt The event we're extracting information from 
                                                    * @return {x,y} Values
                                                    */
                                                    gathersXYPositionFrom: function (container, evt) {
                        
                                                        return _helpers.$dom.get(container).getXYPositionFrom(evt);
                                                    },
                        
                                                    /**
                                                   * Registers a delegate to a given element event
                                                   * 
                                                   * @method on
                                                   * @param {HTMLElement} targetElement The element that we're interested in
                                                   * @param {String} iteractionType The event name
                                                   * @param {Function} triggerWrapper The delegate
                                                   * @chainable
                                                   */
                                                    on: function (targetElement, iteractionType, triggerWrapper) {
                        
                                                        _helpers.$dom.get(targetElement).on(iteractionType, triggerWrapper);
                                                        return _this;
                                                    }
                                                };
                        
                                            return _this;
                                        })(),
                        
                                        /**
                                         * Outputs messages to the 'console'
                                         *
                                         * @class $log
                                         * @module raska
                                         * @submodule _helpers
                                         * @static
                                         */
                                        $log: {
                        
                                            /**
                                             * Whether or not to actually log the messages (should be 'false' in production code)
                                             *
                                             * @property active
                                             * @type Bool
                                             * @default false
                                             */
                                            active: false,
                        
                                            /**
                                            * Prints an informational message to the console
                                            * 
                                            * @method info
                                            * @param {String} msg The message to be shown
                                            * @param {Any} o Any extra message data
                                            */
                                            info: function (msg, o) {
                                                if (this.active === true) {
                                                    console.info(msg, o);
                                                }
                                            }
                        
                                        },
                        
                                        /**
                                         * Handles commom prototype element' tasks
                                         *
                                         * @class $obj
                                         * @module raska
                                         * @submodule _helpers
                                         * @static
                                         */
                                        $obj: (function () {
                        
                                            var _this;
                        
                                            function s4() {
                                                return Math.floor((1 + Math.random()) * 0x10000)
                                                  .toString(16)
                                                  .substring(1);
                                            }
                        
                                            function normalizeChain(elementRoot, resultFull) {
                                                var item, links;
                                                for (var i = 0; i < elementRoot.length; i++) {
                        
                                                    item = elementRoot[i];
                                                    if ((item.graphNode === true) && (((links = item.getLinksFrom()) === null) || (links.length === 0))
                                                        && (((links = item.getLinksTo()) === null) || (links.length === 0))) {
                                                        throw new _defaultConfigurations.errors.elementDoesNotHaveALink(item.name);
                                                    }
                        
                                                    if (item.isSerializable()) {
                        
                                                        /// Adds the normalized item
                                                        resultFull.push(item.normalize());
                        
                                                        /// Check for child elements
                                                        normalizeChain(item.getChildElements(), resultFull);
                                                    }
                                                }
                                            }
                        
                                            return _this = {
                        
                                                /**
                                                * Executes a given delegate for each item in the collection
                                                * 
                                                * @method forEach
                                                * @param {Array} arr The array that need to be enumerated
                                                * @param {Delegate} what What to do to a given item (obj item, number index)
                                                * @return Array of data acquired during array enumaration
                                                */
                                                forEach: function (arr, what) {
                                                    var result = [];
                                                    if (_this.isArray(arr)) {
                                                        for (var i = 0; i < arr.length; i++) {
                                                            result.push(what(arr[i], i));
                                                        }
                                                    }
                                                    return result;
                                                },
                        
                                                /**
                                                * Whether or not a given object type is of the type you expect (typeof)
                                                * 
                                                * @method is
                                                * @param {Object} obj The object we whant to know about
                                                * @param {String} what The string representing the name of the type
                                                * @return {Bool} Whether or not the object matches the specified type
                                                */
                                                is: function (obj, what) {
                                                    return typeof obj === what;
                                                },
                        
                                                /**
                                               * Whether or not a given object type is of the type you expect (constructor call)
                                               * 
                                               * @method isType
                                               * @param {Object} obj The object we whant to know about
                                               * @param {String} typeName The string representing the name of the type
                                               * @return {Bool} Whether or not the object matches the specified type
                                               */
                                                isType: function (obj, typeName) {
                                                    return this.isValid(obj) && Object.prototype.toString.call(obj).toLowerCase() === "[object " + typeName.toLowerCase() + "]";
                                                },
                        
                                                /**
                                                * Generates a pseudo-random Id
                                                * 
                                                * @method generateId
                                                * @return {String} A pseudo-random Id
                                                */
                                                generateId: function () {
                        
                                                    return "__" + s4() + s4() + s4() + s4() + s4() + s4() + s4() + s4();
                                                },
                        
                                                /**
                                                * Whether or not a given object type is valid to be handled
                                                * 
                                                * @method isValid
                                                * @param {Object} obj The object we whant to know if it's valid to be handled
                                                * @return {Bool} Whether or not the object is valid to be handled
                                                */
                                                isValid: function (obj) {
                                                    return !this.is(obj, 'undefined') && obj !== null;
                                                },
                        
                                                /**
                                                * Whether or not a given object is an Array
                                                * 
                                                * @method isArray
                                                * @param {Object} obj The object we whant to know is it's valid to be handled
                                                * @return {Bool} Whether or not the object is valid to be handled
                                                */
                                                isArray: function (obj) {
                                                    return this.isValid(obj) && this.isType(obj, "Array");
                                                },
                        
                                                /**
                                                * Whether or not a given object type is undefined
                                                * 
                                                * @method isUndefined
                                                * @param {Object} obj The object we whant to know if it's undefined
                                                * @return {Bool} Whether or not the object is undefined
                                                */
                                                isUndefined: function (obj) {
                                                    return this.is(obj, 'undefined');
                                                },
                        
                                                /**
                                                * Serializes a given _basicElement array to a JSON string
                                                * 
                                                * @method deconstruct
                                                * @param {_basicElement[]} basicElementArray The array of _basicElement we're going to work with
                                                * @return {string} The corresponding string
                                                */
                                                deconstruct: function (elements) {
                                                    var resultFull = [];
                                                    if (_helpers.$obj.isArray(elements)) {
                                                        normalizeChain(elements, resultFull);
                                                    }
                                                    return JSON.stringify(resultFull);
                                                },
                        
                                                /**
                                                * Tries to recreate a previously serialized object into a new raska instance
                                                * 
                                                * @method recreate
                                                * @param {JSON} jsonElement The JSON representation of a raska object
                                                * @return {_basicElement} The recreated element or null if the element type is invalid
                                                */
                                                recreate: function (jsonElement) {
                                                    if (this.isValid(jsonElement.type) && (jsonElement.type in _elementTypes)) {
                        
                                                        var resultElement = this.extend(new _defaultConfigurations[jsonElement.type], jsonElement);
                        
                                                        resultElement.getType = function () { return jsonElement.type; }
                        
                                                        return resultElement;
                        
                                                    }
                                                    return null;
                                                },
                        
                                                /**
                                                * Recreate all links of the object
                                                * 
                                                * @method recreate                                     
                                                */
                                                recreateLinks: function (targetElement, baseElement, findElementDelegate) {
                        
                                                    /// Copy data back as it should be
                                                    this.forEach(this.forEach(baseElement.linksTo, findElementDelegate),
                                                        targetElement.addLinkTo.bind(targetElement));
                                                    this.forEach(this.forEach(baseElement.childElements, findElementDelegate),
                                                            targetElement.addChild.bind(targetElement));
                        
                                                    if (baseElement.parent !== null) {
                                                        findElementDelegate(baseElement.parent).addChild(targetElement);
                                                    }
                                                },
                        
                                                /**
                                                * Extends any object using a base template object as reference
                                                * 
                                                * @method extend
                                                * @param {Object} baseObject The object we whant to copy from
                                                * @param {Object} impl The object with the data we want use 
                                                * @param {Bool} addNewMembers Whether or not we allow new members on the 'impl' object to be used in the result
                                                * @return {Object} Extended object
                                                */
                                                extend: function (baseObject, impl, addNewMembers) {
                                                    var result = {}, element = null;
                                                    if (this.isUndefined(impl)) {
                                                        for (element in baseObject) {
                                                            result[element] = baseObject[element];
                                                        }
                                                    } else {
                        
                                                        if (addNewMembers === true) { result = impl; }
                                                        for (element in baseObject) {
                                                            if (!result.hasOwnProperty(element)) {
                                                                result[element] = impl.hasOwnProperty(element) ? impl[element] : baseObject[element];
                                                            }
                                                        }
                                                    }
                                                    return result;
                                                }
                                            };
                                        })()
                                    };
                                })(),
                        
                            /**
                            * Gathers all elements being ploted to the canvas and organizes it as a directed graph JSON
                            * 
                            * @private
                            * @class  _graphNodeInfo
                            * @param {_basicElement} nodeElement Element whose dependencies we're about to transpose searching for links
                            * @param {_graphNodeInfo} parentNode The parent no to this element
                            * @param {array} links The linked data to this element
                            */
                            _graphNodeInfo = function (nodeElement, parentNode, links) {
                        
                                var _parent = parentNode || null,
                                    _links = [];
                        
                                /**
                                 * The element wraped by this node
                                 *
                                 * @property element
                                 * @type _basicElement
                                 * @final
                                 */
                                this.element = nodeElement;
                        
                                /**
                                 * Whether or not this node has a parent element
                                 *
                                 * @property hasParent
                                 * @type bool
                                 * @final
                                 */
                                this.hasParent = function (node) {
                                    return ((_parent !== null)
                                        && ((_parent.element === node) || (_parent.getName() === node.name) || _parent.hasParent(node)));
                                };
                        
                                /**
                                * Tries to find a parent node compatible with the element passed as parameter
                                *
                                * @method getParentGraphNodeFor
                                * @param {_basicElement} bElement Element wraped by a parent node
                                * @type _graphNodeInfo
                                */
                                this.getParentGraphNodeFor = function (bElement) {
                        
                                    if ((this.element === bElement) || (this.getName() === bElement.name)) {
                                        return this;
                                    }
                        
                                    if (_parent !== null) {
                                        return this.getParent(bElement);
                                    }
                        
                                    return null;
                                };
                                this.getName = function () {
                                    return nodeElement.name;
                                };
                                this.getParent = function () {
                                    return _parent;
                                };
                                this.getLinks = function () {
                                    return _links;
                                };
                        
                                for (var j = 0; j < links.length; j++) {
                                    if (links[j].graphNode === true) {
                        
                                        if (this.hasParent(links[j])) {
                        
                                            /// We've reached a recursive relation. In this case, simply gathers the reference to the parent and 
                                            /// link it here for better navegability between nodes dependecies
                                            _helpers.$log.info("ingored parent node", this.getParentGraphNodeFor(links[j]));
                                        } else {
                        
                                            _links.push(new _graphNodeInfo(links[j], this, links[j].getLinksTo()));
                                        }
                                    }
                                }
                            },
                        
                            /**
                             * The valid position types for a Raskel element
                             *
                             * @private
                             * @property _positionTypes
                             * @static
                             * @final
                             */
                            _positionTypes = {
                        
                                /**
                                * Element position will be relative to its parent (if any)
                                *
                                * @property relative
                                * @type Number
                                * @default 50
                                * @readOnly
                                */
                                relative: 0,
                        
                                /**
                                * Element position will be absolute and will have no regard about its parent position whatsoever
                                *
                                * @property relative
                                * @type Number
                                * @default 50
                                * @readOnly
                                */
                                absolute: 1
                            },
                        
                            _elementTypes = {
                                basic: "basic",
                                html: "htmlElement",
                                arrow: "arrow",
                                circle: "circle",
                                square: "square",
                                label: "label",
                                triangle: "triangle"
                            },
                        
                            /**
                            * The basic shape of an Raska element
                            *
                            * @private
                            * @class _basicElement
                            * @module raska
                            */
                            _basicElement = function () {
                        
                                var
                                    /**
                                     * A simple canvas used to perform a pixel model hit test agains this element
                                     *
                                     * @property $hitTestCanvas
                                     * @type {CanvasRenderingContext2D}
                        	         * @protected
                                     */
                                    $hitTestCanvas = _helpers.$dom.create("canvas").attr({ "width": "1", "height": "1" }),
                                    $hitTestContext = $hitTestCanvas.raw().getContext("2d"),
                        
                                    /**
                                     * A simple helper function to be used whenever this instance gets disable (if ever)
                                     *
                                     * @private
                                     * @method $disabled
                                     */
                                    $disabled = function () { },
                                    $wasDisabled = false,
                        
                                    /**
                                     * Points to a parent Raska element (if any)
                                     *
                                     * @private
                                     * @property $parent
                                     * @default null
                                     */
                                    $parent = null,
                        
                                    /**
                                     * Points to a Raska element [as an arrow] (if any) related as a dependency from this node
                                     *
                                     * @private
                                     * @property $linksTo
                                     * @type _basicElement
                                     * @default []
                                     */
                                    $linksTo = [],
                        
                                    /**
                                     * Points to a Raska element [as an arrow] (if any) that depends on this instance
                                     * 
                                     * @private
                                     * @property $linksFrom
                                     * @type _basicElement
                                     * @default []
                                     */
                                    $linksFrom = [],
                        
                                    /**
                                     * Holds the reference to the delegate triggered before a link gets removed from an element
                                     * @property $beforeRemoveLinkFrom
                                     * @type function
                                     * @default null
                                     */
                                    $beforeRemoveLinkFrom = null,
                        
                                    /**
                                     * Holds the reference to the delegate triggered before a link gets removed to an element
                                     * @property $beforeRemoveLinkTo
                                     * @type function
                                     * @default null
                                     */
                                    $beforeRemoveLinkTo = null,
                        
                                    /**
                                     * Points to series of child Raska element (if any) that, usually, are contained inside this node
                                     *
                                     * @private
                                     * @property $childElements
                                     * @type _basicElement
                                     * @default []
                                     */
                                    $childElements = [], $this, $disabledStateSubscribers = [];
                        
                                /**
                                * Clears all links that point to and from this Raska element
                                * 
                                * @private
                                * @method clearLinksFrom
                                * @param {Object} source Object that defines the source of the link removal (start node)
                                * @param {Function} each Delegates that handle the process of removing the references
                                * @return {Array} Empty array
                                */
                                function clearLinksFrom(source, each) {
                                    for (var i = 0; i < source.length; i++) {
                                        each(source[i]);
                                    }
                                    return [];
                                }
                        
                                return $this = {
                                    /**
                                     * Just an empty attribute bag where you can save extra stuff that you need/want to serialize
                                     *
                                     * @property attr
                                     * @default "{}"
                                     * @type Object
                                     */
                                    attr: {},
                        
                                    /**
                                     * The element name
                                     *
                                     * @property name
                                     * @default "anonymous"
                                     * @type String
                                     */
                                    name: "anonymous",
                        
                                    /**
                                     * The element type
                                     *
                                     * @property getType
                                     * @default _elementTypes.basic
                                     * @type _elementTypes
                                     */
                                    getType: function () { return _elementTypes.basic; },
                        
                                    /**
                                     * Wheter or not this element is part of the graph as a node
                                     *
                                     * @property graphNode
                                     * @default true
                                     * @type Bool
                                     */
                                    graphNode: true,
                        
                                    /**
                                    * Allows to better check whether or not a new link can be created beteen two elements
                                    * 
                                    * @method canLink
                                    * @param {_basicElement} from Element that will be linked as a source
                                    * @param {_basicElement} to Element that will be linked as a destination
                                    * @return {Bool} Whether or not the link can be created
                                    */
                                    canLink: function (from, to) {
                                        if (from === this) {
                                            return _helpers.$obj.isValid(to) && (to.canReach(this) === false);
                                        }
                                        return true;
                                    },
                        
                                    /**
                                    * Clears all references and child elements from this instance
                                    * 
                                    * @method disable
                                    * @chainable
                                    */
                                    disable: function () {
                                        $wasDisabled = true;
                                        _helpers.$obj.forEach($disabledStateSubscribers, function (target) {
                                            if (_helpers.$obj.is(target, "function")) {
                                                target(this);
                                            } else {
                                                target.elementDisabledNotification(this);
                                            }
                                        }.bind(this));
                                        $disabledStateSubscribers.length = 0; /// Let us free some space
                                        this.clearAllLinks();
                                        _helpers.$obj.forEach($childElements, function (ele) { ele.disable(); });
                                        $childElements.length = 0;
                                        this.drawTo = $disabled;
                                        return this;
                                    },
                        
                                    /**
                                    * Notifies a given element whenever (if ever) this element gets disabled
                                    * 
                                    * @method notifyDisableStateOn
                                    * @chainable
                                    */
                                    notifyDisableStateOn: function (target) {
                                        if (($disabledStateSubscribers.indexOf(target) === -1)
                                            && (_helpers.$obj.isValid(target.elementDisabledNotification) || _helpers.$obj.is(target, "function"))) {
                        
                                            $disabledStateSubscribers.push(target);
                                        }
                                        return this;
                                    },
                        
                                    /**
                                    * Handles element disabling notifications
                                    * 
                                    * @method elementDisabledNotification
                                    * @chainable
                                    */
                                    elementDisabledNotification: function (element) {
                                        return this;
                                    },
                        
                                    /**
                                    * Whether or not this element can reach another element via a linked relation
                                    * 
                                    * @method canReach
                                    * @return {Bool} Whether or not a link exists
                                    */
                                    canReach: function (node) {
                                        if ($linksTo.length > 0) {
                                            for (var i = 0; i < $linksTo.length; i++) {
                                                if ($linksTo[i].canReach(node)) {
                                                    return true;
                                                }
                                            }
                                        }
                                        return (this === node);
                                    },
                        
                                    /**
                                    * Is this element passive of being linked at all?
                                    * 
                                    * @method isLinkable
                                    * @return {Bool} Whether or not a link can be created either from or to this element
                                    */
                                    isLinkable: function () {
                                        return !$wasDisabled;
                                    },
                        
                                    /**
                                    * Is this element passive of being serialized at all?
                                    * 
                                    * @method isSerializable
                                    * @return {Bool} Whether or not this element is suposed to be serialized
                                    */
                                    isSerializable: function () {
                                        return !$wasDisabled;
                                    },
                        
                                    /**
                                    * Creates a link between this and another element, using the later as a dependency of this instance
                                    * 
                                    * @method addLinkTo
                                    * @param {_basicElement} element Element that will be linked as a destination from this element node
                                    * @return {Bool} Whether or not the link was added
                                    */
                                    addLinkTo: function (element) {
                                        if (_helpers.$obj.isValid(element.isLinkable) && element.isLinkable()
                                            && this.isLinkable() && ($linksTo.indexOf(element) === -1)
                                            && (element !== this) && this.canLink(this, element)) {
                                            $linksTo.push(element);
                                            element.addLinkFrom(this);
                                            return true;
                                        }
                                        return false;
                                    },
                        
                                    /**
                                     * Links this element to another Raska element as this instance being the target node
                                     * 
                                     * @method addLinkFrom
                                     * @param {_basicElement} element Element that will be linked as a source from this element node
                                     * @return {Bool} Whether or not the link was added
                                     */
                                    addLinkFrom: function (element) {
                                        if (_helpers.$obj.isValid(element.isLinkable) && element.isLinkable()
                                            && this.isLinkable() && ($linksFrom.indexOf(element) === -1)
                                            && (element !== this) && this.canLink(element, this)) {
                                            $linksFrom.push(element);
                                            element.addLinkTo(this);
                                            return true;
                                        }
                                        return false;
                                    },
                        
                                    /**
                                    * Removes the dependency from this element to another Raska element
                                    * 
                                    * @method removeLinkTo
                                    * @param {_basicElement} element Element that will have its link to this element removed
                                    * @return {_basicElement} Updated Raska element reference
                                    * @chainable
                                    */
                                    removeLinkTo: function (element) {
                                        if ($linksTo.indexOf(element) > -1) {
                                            $linksTo.splice($linksTo.indexOf(element), 1);
                                            if (_helpers.$obj.isType($beforeRemoveLinkFrom, "function") === true) {
                                                $beforeRemoveLinkFrom.call(this, element);
                                            }
                                            element.removeLinkFrom(this);
                                        }
                                        return this;
                                    },
                        
                                    /**
                                    * Event triggered before a link gets removed from this element
                                    * 
                                    * @method beforeRemoveLinkFrom
                                    * @param {function} doWhat A delegate with the 'this' poiting to this instance and the first 
                                    *                           paramenter being the reference to the element which is being remove as a link to this instance
                                    * @chainable
                                    */
                                    beforeRemoveLinkFrom: function (doWhat) {
                                        $beforeRemoveLinkFrom = doWhat;
                                        return this;
                                    },
                        
                                    /**
                                   * Transposes the getter data to a field attached to this instance
                                   * 
                                   * @method normalize
                                   * @chainable
                                   */
                                    normalize: function () {
                                        var n = function (item) { return item.name; };
                                        var normalized = _helpers.$obj.extend(this, {
                                            linksTo: _helpers.$obj.forEach(this.getLinksTo(), n),
                                            childElements: _helpers.$obj.forEach(this.getChildElements(), n),
                                            parent: _helpers.$obj.isValid($parent) ? $parent.name : null,
                                            type: this.getType()
                                        }, true);
                                        delete normalized.on; /// We don't want/need this
                                        return normalized;
                                    },
                        
                                    /**
                                    * Gathers all elements that this instance depends on
                                    * 
                                    * @method getLinksTo
                                    * @return {Array} All elements that this node references TO
                                    */
                                    getLinksTo: function () {
                                        return $linksTo;
                                    },
                        
                                    /**
                                    * Gathers all dependecies/linked elements related to this instance
                                    * 
                                    * @method getLinksFrom
                                    * @return {Array} All elements that this node references from
                                    */
                                    getLinksFrom: function () {
                                        return $linksFrom;
                                    },
                        
                                    /**
                                    * Removes the link to this element from another Raska element
                                    * 
                                    * @method removeLinkFrom
                                    * @param {_basicElement} element Element that will have its link from this element removed
                                    * @return {_basicElement} Updated Raska element reference
                                    * @chainable
                                    */
                                    removeLinkFrom: function (element) {
                                        if ($linksFrom.indexOf(element) > -1) {
                                            $linksFrom.splice($linksFrom.indexOf(element), 1);
                                            if (_helpers.$obj.isType($beforeRemoveLinkTo, "function") === true) {
                                                $beforeRemoveLinkTo.call(this, element);
                                            }
                                            element.removeLinkTo(this);
                                        }
                                        return this;
                                    },
                        
                                    /**
                                    * Event triggered before a link gets removed to this element
                                    * 
                                    * @method beforeRemoveLinkTo
                                    * @param {function} doWhat A delegate with the 'this' poiting to this instance and the first 
                                    *                           paramenter being the reference to the element which is being remove as a link from this instance
                                    * @chainable
                                    */
                                    beforeRemoveLinkTo: function (doWhat) {
                                        $beforeRemoveLinkTo = doWhat;
                                        return this;
                                    },
                        
                                    /**
                                    * Removes every and each link that references this element
                                    * 
                                    * @method clearAllLinks
                                    * @return {_basicElement} Updated Raska element reference
                                    * @chainable
                                    */
                                    clearAllLinks: function () {
                                        $linksTo = clearLinksFrom($linksTo, function (e) { e.removeLinkFrom(this); }.bind(this));
                                        $linksFrom = clearLinksFrom($linksFrom, function (e) { e.removeLinkTo(this); }.bind(this));
                                        return this;
                                    },
                        
                                    /**
                                    * Gathers all child elements from this node
                                    * 
                                    * @method getChildElements
                                    * @return {Array} All child elements
                                    */
                                    getChildElements: function () {
                                        return $childElements;
                                    },
                        
                                    /**
                                    * Adds a new child element to this node
                                    * 
                                    * @method addChild
                                    * @param {_basicElement} child Element that will be added to the child array into this element
                                    * @return {_basicElement} Updated Raska element reference
                                    * @chainable
                                    */
                                    addChild: function (child) {
                                        child.setParent(this);
                                        $childElements.push(child);
                                        return this;
                                    },
                        
                                    /**
                                    * Get the parent node to this element
                                    * 
                                    * @method getParent
                                    * @return {_basicElement} Reference to de parent node (null if none)
                                    */
                                    getParent: function () {
                                        return $parent;
                                    },
                        
                                    /**
                                    * Retrieves the element boundaries information
                                    * 
                                    * @method getBoundaries
                                    * @return {Object} Data regarding x, y, minX and minY from this element
                                    */
                                    getBoundaries: function () {
                                        return {
                                            x: this.getWidth(),
                                            y: this.getHeight(),
                                            minX: 0,
                                            minY: 0
                                        };
                                    },
                        
                                    /**
                                    * Sets the parent node to this element
                                    * 
                                    * @method setParent
                                    * @param {_basicElement} parent Element that will be added as a parent to this element
                                    * @return {_basicElement} Updated Raska element reference
                                    * @chainable
                                    */
                                    setParent: function (parent) {
                                        $parent = parent;
                                        return this;
                                    },
                        
                                    /**
                                     * Details regarding this element' border
                                     *
                                     * @attribute border
                                     */
                                    border: {
                                        /**
                                        * Element border color
                                        *
                                        * @property color
                                        * @type String
                                        * @default null
                                        */
                                        color: null,
                        
                                        /**
                                        * Whether or not a border should be rendered
                                        *
                                        * @property active
                                        * @type Bool
                                        * @default false
                                        */
                                        active: false,
                        
                                        /**
                                        * Border width
                                        *
                                        * @property width
                                        * @type Number
                                        * @default 0
                                        */
                                        width: 0
                                    },
                        
                                    /**
                                    * Element position type
                                    *
                                    * @property position
                                    * @type _positionTypes
                                    * @default _positionTypes.relative
                                    */
                                    position: _positionTypes.relative,
                        
                                    /**
                                    * Element x position
                                    *
                                    * @property x
                                    * @type Number
                                    * @default 50
                                    */
                                    x: 50,
                        
                                    /**
                                    * Element y position
                                    *
                                    * @property y
                                    * @type Number
                                    * @default 50
                                    */
                                    y: 50,
                        
                                    /**
                                    * Gathers adjusted x/y coordinates for the currente element taking into consideration 
                                    * the type of positining set to it and wheter or not a parent node is present
                                    * 
                                    * @method getAdjustedCoordinates
                                    * @return {x:Number,y:Number} Adjusted coordinates
                                    */
                                    getAdjustedCoordinates: function () {
                                        if ((this.position === _positionTypes.relative) && ($parent !== null)) {
                                            var adjustedParent = $parent.getAdjustedCoordinates();
                                            return {
                                                x: this.x + adjustedParent.x,
                                                y: this.y + adjustedParent.y
                                            };
                                        }
                                        return { x: this.x, y: this.y };
                                    },
                        
                                    /**
                                     * Whether or not this element handle event interactions
                                     * 
                                     * @property canHandleEvents
                                     * @type bool
                                     * @default false
                                     */
                                    canHandleEvents: function () { return true; },
                        
                                    on: (function () {
                        
                                        var __clickDelegates = [],
                                            __releaseDelegates = [];
                        
                                        function triggerDelegatesUsing(x, y, ele, evt, arr) {
                                            _helpers.$obj.forEach(arr, function (el) {
                                                el(x, y, ele, evt);
                                            });
                                        }
                        
                                        return {
                        
                                            /**
                                             * Triggered whenever a click iteraction occurs within the boundaries of this element.
                                             *  - This event is only supported on selected elements. Check for the *canHandleEvents*
                                             *    property value before relying on this delegate
                                             * 
                                             * @function click
                                             * @param {number} x Element's current X position
                                             * @param {number} y Element's current Y position
                                             * @param {_basicElement} ele The element that was clicked
                                             * @param {event} evt Event that triggered the delegate
                                             * @chainable
                                             */
                                            click: function (x, y, ele, evt) {
                                                if (_helpers.$obj.isType(x, "number") === true) {
                                                    var foundInner = false;
                                                    if ($childElements.length > 0) {
                                                        var parentAdjustedPosition = ele.getAdjustedCoordinates();
                                                        _helpers.$obj.forEach($childElements, function (el) {
                                                            var newPosition = {
                                                                x: x - parentAdjustedPosition.x,
                                                                y: y - parentAdjustedPosition.y
                                                            }
                                                            if (el.canHandleEvents() && el.existsIn(newPosition.x, newPosition.y)) {
                                                                el.on.click(newPosition.x, newPosition.y, el, evt);
                                                                foundInner = true;
                                                            }
                                                        });
                                                    }
                                                    if (foundInner === false) {
                                                        triggerDelegatesUsing(x, y, ele, evt, __clickDelegates);
                                                    }
                                                } else if (_helpers.$obj.isType(x, "function") === true) {
                                                    __clickDelegates.push(x);
                                                }
                        
                                                return $this;
                                            },
                        
                                            /**
                                             * Triggered whenever a 'clickUp' iteraction occurs within the boundaries of this element.
                                             *  - This event is only supported on selected elements. Check for the *canHandleEvents*
                                             *    property value before relying on this delegate
                                             * 
                                             * @function release
                                             * @param {number} x Element's current X position
                                             * @param {number} y Element's current Y position
                                             * @param {_basicElement} ele The element that was clicked
                                             * @param {event} evt Event that triggered the delegate
                                             * @chainable
                                             */
                                            release: function (x, y, ele, evt) {
                                                if (_helpers.$obj.isType(x, "number") === true) {
                                                    var foundInner = false;
                                                    if ($childElements.length > 0) {
                                                        var parentAdjustedPosition = ele.getAdjustedCoordinates();
                                                        _helpers.$obj.forEach($childElements, function (el) {
                                                            var newPosition = {
                                                                x: x - parentAdjustedPosition.x,
                                                                y: y - parentAdjustedPosition.y
                                                            }
                                                            if (el.canHandleEvents() && el.existsIn(newPosition.x, newPosition.y)) {
                                                                el.on.release(newPosition.x, newPosition.y, el, evt);
                                                                foundInner = true;
                                                            }
                                                        });
                                                    }
                                                    if (foundInner === false) {
                                                        triggerDelegatesUsing(x, y, ele, evt, __releaseDelegates);
                                                    }
                                                } else if (_helpers.$obj.isType(x, "function") === true) {
                                                    __releaseDelegates.push(x);
                                                }
                        
                                                return $this;
                                            }
                                        };
                                    })(),
                        
                                    /**
                                     * Whether or not this element existis withing the boudaries of 
                                     * the given x/y coordinates
                                     * 
                                     * @method existsIn
                                     * @param {Number} x X Coordinate
                                     * @param {Number} y Y Coordinate
                                     * @return {Bool} If this element is contained within the X/Y coordinates
                                     */
                                    existsIn: function (x, y) {
                                        $hitTestContext.setTransform(1, 0, 0, 1, -x, -y);
                                        this.drawTo($hitTestCanvas, $hitTestContext);
                                        var hit = false;
                                        try { hit = $hitTestContext.getImageData(0, 0, 1, 1).data[3] > 1; }
                                        catch (e) { }
                                        $hitTestContext.setTransform(1, 0, 0, 1, 0, 0);
                                        $hitTestContext.clearRect(0, 0, 2, 2);
                                        return hit;
                                    },
                        
                                    /**
                                    * [ABSTRACT] Adjusts the position of the current element taking in consideration it's parent 
                                    * positioning constraints
                                    * 
                                    * @method adjustPosition
                                    * @param {Number} newX X position
                                    * @param {Number} newY Y position
                                    * @chainable
                                    */
                                    adjustPosition: function (newX, newY) {
                                        console.error(_defaultConfigurations.errors.notImplementedException);
                                        throw _defaultConfigurations.errors.notImplementedException;
                                    },
                        
                                    /**
                                    * [ABSTRACT] Sets the current width for this element
                                    * 
                                    * @method setWidth
                                    * @param {Number} newWidth The width for this element
                                    * @chainable
                                    * @throws {_defaultConfigurations.errors.notImplementedException} Not implemented
                                    */
                                    setWidth: function (newWidth) {
                                        console.error(_defaultConfigurations.errors.notImplementedException);
                                        throw _defaultConfigurations.errors.notImplementedException;
                                    },
                        
                                    /**
                                   * [ABSTRACT] Gets the current width for this element
                                   * 
                                   * @method getWidth
                                   * @return {Number} The width of this element
                                   * @throws {_defaultConfigurations.errors.notImplementedException} Not implemented
                                   */
                                    getWidth: function () {
                                        console.error(_defaultConfigurations.errors.notImplementedException);
                                        throw _defaultConfigurations.errors.notImplementedException;
                                    },
                                    getAdjustedWidth: function () { return this.getWidth(); },
                        
                                    /**
                                    * [ABSTRACT] Sets the current Height for this element
                                    * 
                                    * @method setHeight
                                    * @param {Number} newHeight The height for this element
                                    * @chainable
                                    * @throws {_defaultConfigurations.errors.notImplementedException} Not implemented
                                    */
                                    setHeight: function (newHeight) {
                                        console.error(_defaultConfigurations.errors.notImplementedException);
                                        throw _defaultConfigurations.errors.notImplementedException;
                                    },
                        
                                    /**
                                     * [ABSTRACT] Gets the current Height for this element
                                     * 
                                     * @method getHeight
                                     * @return {Number} The Height of this element
                                     * @throws {_defaultConfigurations.errors.notImplementedException} Not implemented
                                     */
                                    getHeight: function () {
                                        console.error(_defaultConfigurations.errors.notImplementedException);
                                        throw _defaultConfigurations.errors.notImplementedException;
                                    },
                                    getAdjustedHeight: function () { return this.getHeight(); },
                        
                                    /**
                                     * [ABSTRACT] Whether or not this element existis withing the boudaries of 
                                     * the given x/y coordinates
                                     * 
                                     * @method existsIn
                                     * @param {HTMLElement|Node} The Canvas element
                                     * @param {Node} tdContext Canvas' 2d context
                                     * @throws {_defaultConfigurations.errors.notImplementedException} Not implemented
                                     */
                                    drawTo: function (canvasElement, tdContext) {
                                        console.error(_defaultConfigurations.errors.notImplementedException);
                                        throw _defaultConfigurations.errors.notImplementedException;
                                    }
                                };
                            },
                        
                             /**
                             * A utility module to control complex canvas' (HTML) iteraction
                             *
                             * @private
                             * @module raska
                             * @submodule _canvasController
                             * @readOnly
                             */
                            _canvasController = (function () {
                        
                                var _inFullscreen = false,
                                    _defaultValues = {
                                        container: {
                                            "width": 0,
                                            "height": 0,
                                            "position": 0,
                                            "z-index": 0,
                                            "left": 0,
                                            "top": 0
                                        },
                                        canvas: {
                                            "width": 0,
                                            "height": 0
                                        }
                                    };
                        
                                return {
                        
                                    /**
                                     * Toggles canvas in/out fullscreen mode
                                     * 
                                     * @method toggleFullScreen
                                     * @param {HTMLElement|Node} The Canvas element
                                     * @param {string} strContainerId The id for the canvas toolbar (or undefined if nothing needs to be done there)
                                     */
                                    toggleFullScreen: function (canvas, strContainerId) {
                                        var canvasElementContainer = _helpers.$dom.getById(_activeConfiguration.targetCanvasContainerId),
                                            canvasElement = _helpers.$dom.get(canvas),
                                            bottomPadding = strContainerId ? 40/*the estimated Height size for the toolbox*/ : 0;
                        
                                        if (_inFullscreen === false) {
                        
                                            /// Recovery mode for the container
                                            for (var attr in _defaultValues.container) {
                                                _defaultValues.container[attr] = canvasElementContainer.css(attr);
                                            }
                                            canvasElementContainer.css({
                                                "width": d.body.clientWidth,
                                                "height": d.body.clientHeight - bottomPadding,
                                                "position": "fixed",
                                                "z-index": 1000,
                                                "background-color": "white",
                                                "left": 0,
                                                "top": 0
                                            });
                        
                                            /// Recovery mode for the canvas
                                            for (var attr in _defaultValues.canvas) {
                                                _defaultValues.canvas[attr] = canvasElement.attr(attr);
                                            }
                                            canvasElement.attr({ "width": d.body.clientWidth, "height": d.body.clientHeight - bottomPadding });
                        
                                            if (_helpers.$obj.isValid(strContainerId)) {
                                                _helpers.$dom.getById(strContainerId)
                                                    .first("button")
                                                    .html("<span class='glyphicon glyphicon-resize-small'></span>&nbsp;Back to normal");
                                            }
                                            _inFullscreen = true;
                                        } else {
                                            for (var attr in _defaultValues.container) {
                                                canvasElementContainer.css(attr, _defaultValues.container[attr]);
                                            }
                                            for (var attr in _defaultValues.canvas) {
                                                canvasElement.attr(attr, _defaultValues.canvas[attr]);
                                            }
                                            if (_helpers.$obj.isValid(strContainerId)) {
                                                _helpers.$dom.getById(strContainerId)
                                                    .first("button")
                                                    .html("<span class='glyphicon glyphicon-resize-full'></span>&nbsp;Fullscreen");
                                            }
                                            _inFullscreen = false;
                                        }
                                    }
                                };
                            })(),
                        
                             /**
                             * A utility container that holds default instance information for the Raska library
                             *
                             * @private
                             * @module raska
                             * @submodule _defaultConfigurations
                             * @readOnly
                             */
                            _defaultConfigurations = {
                        
                                /**
                                 * Raska's default configuration data
                                 *
                                 * @property library
                                 * @static
                                 * @final
                                 */
                                library: {
                                    readonly: false,
                                    frameRefreshRate: 30,
                                    targetCanvasId: "",
                                    targetCanvasContainerId: "____raska" + _helpers.$obj.generateId(),
                                    toolboxButtons: [
                                        {
                                            /// THIS WILL BE SET AUTOMATICALLY WHEN THE BUTTON GETS RENDERED
                                            id: "", /// THIS WILL BE SET AUTOMATICALLY WHEN THE BUTTON GETS RENDERED
                                            /// THIS WILL BE SET AUTOMATICALLY WHEN THE BUTTON GETS RENDERED
                                            name: "fullscreen",
                                            enabled: true,
                                            onclick: function (canvas) {
                                                _canvasController.toggleFullScreen(canvas, this.id);
                                            },
                                            template: "<button class='btn btn-primary btn-sm'><span class='glyphicon glyphicon-resize-full'></span>&nbsp;Fullscreen</button>"
                                        }
                                    ]
                                },
                        
                                /**
                                 * Raska's exception types
                                 *
                                 * @property errors
                                 * @static
                                 * @final
                                 */
                                errors: {
                                    notImplementedException: {
                                        message: "Not implemented",
                                        code: 0
                                    },
                                    nullParameterException: function (parameterName) {
                        
                                        if ((typeof parameterName === 'undefined') || (parameterName === null)) {
                                            throw new this.nullParameterException("parameterName");
                                        }
                        
                                        this.message = "Parameter can't be null";
                                        this.parameterName = parameterName;
                                        this.code = 1;
                                    },
                                    elementDoesNotHaveALink: function (elementName) {
                        
                                        if ((typeof elementName === 'undefined') || (elementName === null)) {
                                            throw new this.nullParameterException("elementName");
                                        }
                        
                                        return {
                                            message: "Element '" + elementName + "' doesn't have a valid linked sibling",
                                            elementName: elementName,
                                            code: 2
                                        };
                                    },
                                    itemNotFoundException: function (elementName) {
                        
                                        if ((typeof elementName === 'undefined') || (elementName === null)) {
                                            throw new this.nullParameterException("elementName");
                                        }
                        
                                        return {
                                            message: "Element '" + elementName + "' wasn't found",
                                            elementName: elementName,
                                            code: 3
                                        };
                                    }
                                },
                        
                                /**
                                 * Creates a label
                                 * 
                                 * @class label
                                 * @extends _basicElement
                                 */
                                label: function () {
                                    return _helpers.$obj.extend(new _basicElement(), {
                                        name: "label" + _helpers.$obj.generateId(),
                                        graphNode: false,
                                        getType: function () { return _elementTypes.label; },
                                        canLink: function () { return false; },
                                        isLinkable: function () { return false; },
                                        text: "",
                                        color: "gray",
                                        x: 0,
                                        y: 0,
                                        border: { color: "white", active: true, width: 2 },
                                        font: { family: "Arial", size: "12px", decoration: "" },
                                        getWidth: function () {
                                            return this.text.length * 5;
                                        },
                                        getHeight: function () {
                                            return this.font.size;
                                        },
                                        drawTo: function (canvas, context) {
                                            var coordinates = this.getAdjustedCoordinates();
                                            context.save();
                                            context.font = (this.font.decoration || "") + " " + this.font.size + " " + this.font.family;
                                            if (this.border.active === true) {
                                                context.lineJoin = "round";
                                                context.lineWidth = this.border.width;
                                                context.strokeStyle = this.border.color;
                                                context.strokeText(this.text, coordinates.x, coordinates.y);
                                            }
                                            context.fillStyle = this.color;
                                            context.fillText(this.text, coordinates.x, coordinates.y);
                                            context.restore();
                                        },
                                        existsIn: function (x, y) {
                                            /// Efective as a non-draggable element
                                            return false;
                                        }
                                    }, true);
                                },
                        
                                /**
                                 * Creates a square 
                                 * 
                                 * @class square
                                 * @extends _basicElement
                                 */
                                square: function (desiredDimensions) {
                        
                                    var _dimensions = desiredDimensions || {
                                        width: 50,
                                        height: 50
                                    }, ctx = null;
                        
                                    return _helpers.$obj.extend(new _basicElement(), {
                                        name: "square" + _helpers.$obj.generateId(),
                                        getType: function () { return _elementTypes.square; },
                                        border: { color: "gray", active: true, width: 2 },
                                        fillColor: "silver",
                                        dimensions: _dimensions,
                                        globalAlpha: 1,
                                        getWidth: function () {
                                            return this.dimensions.width;
                                        },
                                        getHeight: function () {
                                            return this.dimensions.height;
                                        },
                                        drawTo: function (canvas, context) {
                                            var coordinates = this.getAdjustedCoordinates();
                                            context.beginPath();
                                            context.rect(coordinates.x, coordinates.y, this.dimensions.width, this.dimensions.height);
                                            context.fillStyle = this.fillColor;
                                            if (this.border.active === true) {
                                                context.lineWidth = this.border.width;
                                                context.strokeStyle = this.border.color;
                                            }
                                            context.globalAlpha = this.globalAlpha;
                                            context.fill();
                                            context.stroke();
                                        },
                                        existsIn: function (x, y) {
                                            return ((x >= this.x) && (x <= this.x + this.dimensions.width)
                                                && (y >= this.y) && (y <= this.y + this.dimensions.height));
                                        },
                                        adjustPosition: function (newX, newY) {
                                            var $parent = this.getParent();
                                            if ((this.position === _positionTypes.relative) && ($parent !== null)) {
                        
                                                var adjustedParent = $parent.getAdjustedCoordinates();
                                                var w = $parent.getWidth() / 2;
                                                var h = $parent.getHeight() / 2;
                                                var diffX = (newX - adjustedParent.x) - w;
                                                var diffH = (newY - adjustedParent.y) - h;
                                                this.x = diffX < 0 ? Math.max(diffX, w * -1) : Math.min(diffX, w);;
                                                this.y = diffH < 0 ? Math.max(diffH, h * -1) : Math.min(diffH, h);
                        
                                            } else {
                                                this.x = newX;
                                                this.y = newY;
                                            }
                                            return this;
                                        }
                                    }, true);
                                },
                        
                                /**
                                 * Creates an arrow 
                                 * 
                                 * @class arrow
                                 * @extends _basicElement
                                 */
                                arrow: function (target) {
                        
                                    if (_helpers.$obj.isUndefined(target) || (target === null)) {
                                        throw new _defaultConfigurations.errors.nullParameterException("target");
                                    }
                        
                                    var _target = target,
                                        _drawArrowhead = function (context, x, y, radians, sizeW, sizeH, arrowColor) {
                                            context.fillStyle = arrowColor;
                                            context.save();
                                            context.beginPath();
                                            context.translate(x, y);
                                            context.rotate(radians);
                                            context.moveTo(0, -10);
                                            context.lineTo(sizeH, sizeW);
                                            context.lineTo(sizeH * -1, sizeW);
                                            context.closePath();
                                            context.restore();
                                            context.fill();
                                        };
                        
                                    return _helpers.$obj.extend(new _basicElement(), {
                                        name: "arrow" + _helpers.$obj.generateId(),
                                        clearAllLinks: function () {
                                            if (_helpers.$obj.isValid(this.getParent())
                                                && _helpers.$obj.is(this.getParent().removeLinkFrom, "function")
                                                && _helpers.$obj.is(_target.removeLinkTo, "function")) {
                                                this.getParent().removeLinkFrom(_target).removeLinkTo(_target);
                                                _target.removeLinkFrom(this.getParent()).removeLinkTo(this.getParent());
                                            }
                                            return this;
                                        },
                                        elementDisabledNotification: function (element) {
                                            if ((element === _target) || (element === this.getParent())) {
                                                this.disable();
                                            }
                                        },
                                        graphNode: false,
                                        canHandleEvents: function () { return false; },
                                        isSerializable: function () { return false; },
                                        getType: function () { return _elementTypes.arrow; },
                                        canLink: function () { return false; },
                                        isLinkable: function () { return false; },
                                        border: { color: "gray", active: true, width: 2 },
                                        fillColor: "rgba(0,0,0,0.3)",
                                        getWidth: function () { return 1; },
                                        getHeight: function () { return 1; },
                                        drawTo: function (canvas, context) {
                        
                                            if (_helpers.$obj.isValid(_target.notifyDisableStateOn)) {
                                                _target.notifyDisableStateOn(this);
                                            }
                        
                                            if (_helpers.$obj.isValid(this.getParent().notifyDisableStateOn)) {
                                                this.getParent().notifyDisableStateOn(this);
                                            }
                        
                                            var adjustedTargedCoordinates = _target.getAdjustedCoordinates ? _target.getAdjustedCoordinates() : { x: _target.x, y: _target.y },
                                                parent = this.getParent(),
                                                adjustedParentCoordinates = parent.getAdjustedCoordinates(),
                                                parentX = (adjustedParentCoordinates.x + (parent.getAdjustedWidth ? (parent.getAdjustedWidth() / 2) : 0)),
                                                parentY = (adjustedParentCoordinates.y + (parent.getAdjustedHeight ? (parent.getAdjustedHeight() / 2) : 0));
                        
                                            this.x = (adjustedTargedCoordinates.x + (_target.getAdjustedWidth ? (_target.getAdjustedWidth() / 2) : 0));
                                            this.y = (adjustedTargedCoordinates.y + (_target.getAdjustedHeight ? (_target.getAdjustedHeight() / 2) : 0));
                                            context.beginPath();
                                            context.fillStyle = this.fillColor;
                                            if (this.border.active === true) {
                                                var grad = context.createLinearGradient(this.x, this.y, parentX, parentY);
                                                grad.addColorStop(0, this.border.color);
                                                grad.addColorStop(0.5, this.fillColor);
                                                grad.addColorStop(1, this.border.color);
                        
                                                context.lineWidth = this.border.width;
                                                context.strokeStyle = grad;
                                            }
                                            context.moveTo(this.x, this.y);
                                            context.lineTo(parentX, parentY);
                                            context.stroke();
                                            var startRadians = Math.atan((parentY - this.y) / (parentX - this.x));
                                            startRadians += ((parentX > this.x) ? -90 : 90) * Math.PI / 180;
                                            _drawArrowhead(context, this.x, this.y, startRadians, 5, 8, this.fillColor);
                                            if (this.border.active === true) {
                                                _drawArrowhead(context, this.x, this.y, startRadians, 3, 5, this.border.color);
                                            } else {
                                                _drawArrowhead(context, this.x, this.y, startRadians, 3, 5, "white");
                                            }
                                        }
                                    }, true);
                                },
                        
                                /**
                                 * Wraps any HTML element as a Raska element
                                 * 
                                 * @class htmlElement
                                 * @constructor
                                 * @extends _basicElement
                                 */
                                htmlElement: function (element) {
                        
                                    if (!_helpers.$obj.isValid(element)) {
                                        var nullObj = new _defaultConfigurations.errors.nullParameterException("element");
                                        console.error(nullObj.message);
                                        throw nullObj;
                                    }
                                    var targetElement = element;
                                    return _helpers.$obj.extend(new _basicElement(), {
                                        name: "htmlElement" + _helpers.$obj.generateId(),
                                        canHandleEvents: function () { return false; },
                                        getType: function () { return _elementTypes.html; },
                                        graphNode: false,
                                        isSerializable: function () { return false; },
                                        canLink: function () { return false; },
                                        isLinkable: function () { return false; },
                                        border: { active: false },
                                        fillColor: "",
                                        getWidth: function () { return element.clientWidth; },
                                        getHeight: function () { return element.clientHeight; },
                                        drawTo: function (canvas, context) { },
                                        existsIn: function (x, y) { return false; },
                                        handleInteractions: true,
                                        onIteraction: function (iteractionType, trigger) {
                        
                                            var triggerWrapper = function (evt) {
                                                trigger(evt, targetElement, iteractionType);
                                            };
                        
                                            _helpers.$device.on(targetElement, iteractionType, triggerWrapper);
                                        }
                                    }, true);
                                },
                        
                                /**
                                 * Creates a triangle.
                                 * 
                                 * @class triangle
                                 * @extends _basicElement
                                 */
                                triangle: function (pointingUp) {
                                    var _bcData = {
                                        p2: { x: 0, y: 0 },
                                        p3: { x: 0, y: 0 }
                                    };
                        
                                    return _helpers.$obj.extend(new _basicElement(), {
                                        name: "triangle" + _helpers.$obj.generateId(),
                                        border: { color: "gray", active: true, width: 2 },
                                        getType: function () { return _elementTypes.triangle; },
                                        fillColor: "silver",
                                        pointingUp: (pointingUp !== false),
                                        dimensions: {
                                            width: 50,
                                            height: 50
                                        },
                                        setWidth: function (width) {
                                            this.dimensions.width = width;
                                            return this;
                                        },
                                        getWidth: function () {
                                            return this.dimensions.width;
                                        },
                                        setHeight: function (height) {
                                            this.dimensions.height = height;
                                            return this;
                                        },
                                        getAdjustedHeight: function () {
                                            return (this.pointingUp === true) ? (this.dimensions.height * -1) : (this.dimensions.height / 2);
                                        },
                                        getHeight: function () {
                                            return this.dimensions.height;
                                        },
                                        drawTo: function (canvas, context) {
                                            var trasform = this.pointingUp === false ? function (x, y) { return x + y; } : function (x, y) { return x - y; },
                                                coordinates = this.getAdjustedCoordinates();
                        
                                            context.beginPath();
                                            context.fillStyle = this.fillColor;
                                            context.moveTo(coordinates.x, coordinates.y);
                                            context.lineTo(_bcData.p2.x = (coordinates.x + (this.dimensions.width / 2)),
                                                _bcData.p2.y = trasform(coordinates.y, this.dimensions.height));
                                            context.lineTo(_bcData.p3.x = coordinates.x + this.dimensions.width,
                                                _bcData.p3.y = coordinates.y);
                                            context.closePath();
                                            if (this.border.active === true) {
                                                context.lineWidth = this.border.width;
                                                context.strokeStyle = this.border.color;
                                            }
                                            context.fill();
                                            context.stroke();
                                        },
                                        existsIn: function (x, y) {
                                            //https://en.wikipedia.org/wiki/Barycentric_coordinate_system_%28mathematics%29
                                            var coordinates = this.getAdjustedCoordinates();
                                            var p1 = coordinates, p2 = _bcData.p2, p3 = _bcData.p3, p = { x: x, y: y };
                        
                                            var alpha = ((p2.y - p3.y) * (p.x - p3.x) + (p3.x - p2.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y)),
                                                beta = ((p3.y - p1.y) * (p.x - p3.x) + (p1.x - p3.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y)),
                                                gamma = 1 - alpha - beta;
                        
                                            return alpha > 0 && beta > 0 && gamma > 0;
                                        },
                                        adjustPosition: function (newX, newY) {
                                            var $parent = this.getParent();
                                            if ((this.position === _positionTypes.relative) && ($parent !== null)) {
                        
                                                var adjustedParent = $parent.getAdjustedCoordinates();
                                                var w = $parent.getWidth() / 2;
                                                var h = $parent.getHeight() / 2;
                                                var diffX = (newX - adjustedParent.x) - w;
                                                var diffH = (newY - adjustedParent.y) - h;
                                                this.x = diffX < 0 ? Math.max(diffX, w * -1) : Math.min(diffX, w);;
                                                this.y = diffH < 0 ? Math.max(diffH, h * -1) : Math.min(diffH, h);
                        
                                            } else {
                                                this.x = newX;
                                                this.y = newY;
                                            }
                                            return this;
                                        }
                                    }, true);
                                },
                        
                                /**
                                 * Creates a cricle.
                                 * 
                                 * @class circle
                                 * @extends _basicElement
                                 */
                                circle: function () {
                                    return _helpers.$obj.extend(new _basicElement(), {
                                        name: "circle" + _helpers.$obj.generateId(),
                                        border: { color: "gray", active: true, width: 2 },
                                        getType: function () { return _elementTypes.circle; },
                                        fillColor: "silver",
                                        radius: 20,
                                        setWidth: function (r) {
                                            this.radius = r / 2;
                                            return this;
                                        },
                                        getWidth: function () {
                                            return this.radius * 2;
                                        },
                                        getAdjustedWidth: function () {
                                            return this.radius / 2;
                                        },
                                        setHeight: function (r) {
                                            this.radius = r / 2;
                                            return this;
                                        },
                                        getAdjustedHeight: function () {
                                            return this.radius / 2;
                                        },
                                        getHeight: function () {
                                            return this.radius * 2;
                                        },
                                        drawTo: function (canvas, context) {
                                            var coordinates = this.getAdjustedCoordinates();
                                            context.beginPath();
                                            context.arc(coordinates.x, coordinates.y, this.radius, 0, 2 * Math.PI, false);
                                            context.fillStyle = this.fillColor;
                                            context.fill();
                                            if (this.border.active === true) {
                                                context.lineWidth = this.border.width;
                                                context.strokeStyle = this.border.color;
                                                context.stroke();
                                            }
                                        },
                                        existsIn: function (x, y) {
                                            var dx = this.x - x;
                                            var dy = this.y - y;
                                            return (dx * dx + dy * dy < this.radius * this.radius);
                                        },
                                        getBoundaries: function () {
                                            var p = this.radius / 2;
                                            return {
                                                x: p,
                                                y: p,
                                                minX: p * -1,
                                                minY: p * -1
                                            };
                                        },
                                        adjustPosition: function (newX, newY) {
                                            var $parent = this.getParent();
                                            if ((this.position === _positionTypes.relative) && ($parent !== null)) {
                        
                                                var adjustedParent = $parent.getAdjustedCoordinates();
                                                var parentBoundaries = $parent.getBoundaries();
                                                var w = parentBoundaries.x;
                                                var h = parentBoundaries.y;
                                                var diffX = (newX - adjustedParent.x) - w;
                                                var diffH = (newY - adjustedParent.y) - h;
                                                this.x = diffX < 0 ? Math.max(diffX, parentBoundaries.minX) : Math.min(diffX, w);;
                                                this.y = diffH < 0 ? Math.max(diffH, parentBoundaries.minY) : Math.min(diffH, h);
                                            } else {
                                                this.x = newX;
                                                this.y = newY;
                                            }
                                            return this;
                                        }
                                    }, true);
                                }
                            },
                        
                            /**
                             * Holds the value for the active configuration on this Raska instance
                             *
                             * @private
                             * @attribute _activeConfiguration
                             * @default null
                             * @module raska
                             */
                            _activeConfiguration = null,
                        
                            _elementInteractionEventData = (function () {
                        
                                var interactionTypes = { "click": 0, "mousemove": 1 },
                                    createTriggerUsing = function (originalTrigger) {
                                        return function (evt, targetElement, interactionType) {
                                            originalTrigger({
                                                x: _drawing.mouseHelper.getX(evt),
                                                y: _drawing.mouseHelper.getY(evt),
                                                details: {
                                                    interactionType: interactionType,
                                                    targetElement: targetElement
                                                }
                                            });
                                        };
                                    };
                        
                                return {
                                    getInteractionTypes: interactionTypes,
                                    register: function (targetElement, iteractionType, trigger) {
                        
                                        if ((iteractionType in interactionTypes)
                                            && _helpers.$obj.isValid(targetElement)
                                            && (targetElement.handleInteractions === true)) {
                        
                                            targetElement.onIteraction(iteractionType, createTriggerUsing(trigger));
                                        }
                                    }
                                };
                            })(),
                        
                            /**
                             * An utility container that holds all the drawing related implementations
                             *
                             * @class _drawing
                             * @module raska
                             * @readOnly
                             * @static
                             */
                            _drawing = (function () {
                        
                                var
                        
                                    /**
                                    * Holds the elements that are to be drawn to the target canvas
                                    *
                                    * @private
                                    * @property _elements
                                    * @type Array
                                    * @default []
                                    */
                                    _elements = [],
                        
                                    /**
                                    * Whether or not we have a timer running
                                    *
                                    * @private
                                    * @property _timerRunning
                                    * @type Bool
                                    * @default false
                                    */
                                    _timerRunning = false,
                        
                                    /**
                                    * The Canvas element we're targeting
                                    *
                                    * @private
                                    * @property _canvas
                                    * @type HTMLElement
                                    * @default null
                                    */
                                    _canvas = null,
                        
                                    /**
                                    * The Canvas element (wraped by a Raska _basicElement)
                                    *
                                    * @private
                                    * @property _canvasElement
                                    * @type _basicElement
                                    * @default null
                                    */
                                    _canvasElement = null,
                        
                                    /**
                                    * The 2dContext from the canvas element we're targeting
                                    *
                                    * @private
                                    * @property _2dContext
                                    * @type Object
                                    * @default null
                                    */
                                    _2dContext = null,
                        
                                    /**
                                     * Handles the periodic draw of the elements in this Raska instance
                                     *
                                     * @method _timedDrawing
                                     * @private
                                     */
                                    _timedDrawing = function () {
                        
                                        if (_timerRunning === true) {
                        
                                            _draw();
                                            w.requestAnimationFrame(_timedDrawing);
                                        }
                                    },
                        
                                    /**
                                     * Plots the element itself and all its related nodes into the canvas
                                     *
                                     * @method _drawAllIn
                                     * @param {_basicElement} element The element being drawn to the canvas
                                     * @private
                                     */
                                    _drawAllIn = function (element) {
                        
                                        element.drawTo(_canvas, _2dContext);
                        
                                        var childElements = element.getChildElements();
                                        for (var i = 0; i < childElements.length; i++) {
                                            _drawAllIn(childElements[i]);
                                        }
                                    },
                        
                                    /**
                                     * A utility that detects mouse's relative position on the canvas
                                     *
                                     * @class _mouse
                                     * @for _drawing
                                     * @static
                                     */
                                    _mouse = {
                        
                                        /**
                                        * Gets mouses's X position relative to the current canvas
                                        *
                                        * @method getX
                                        * @param {Event} evt Event we're bubbling in
                                        * @for _mouse
                                        * @return {Number} X value
                                        * @static
                                        */
                                        getX: function (evt) {
                                            return _helpers.$device.gathersXYPositionFrom(_canvas, evt).x;
                                        },
                        
                                        /**
                                         * Gets mouses's Y position relative to the current canvas
                                         *
                                         * @method getY
                                         * @param {Event} evt Event we're bubbling in
                                         * @for _mouse
                                         * @return {Number} Y value
                                         * @static
                                         */
                                        getY: function (evt) {
                                            return _helpers.$device.gathersXYPositionFrom(_canvas, evt).y;
                                        },
                        
                                        /**
                                        * Gathers the mouse coordinates without the need of an event bubble
                                        *
                                        * @class staticCoordinates
                                        * @for _mouse
                                        * @static
                                        */
                                        staticCoordinates: (function () {
                        
                                            var _evt = { clientX: 0, clientY: 0 },
                                                started = false;
                        
                                            return {
                                                /**
                                                * Gets mouses' X and Y positions relative to the current canvas
                                                *
                                                * @method getXY
                                                * @return {Object} X and Y values
                                                * @static
                                                */
                                                getXY: function () {
                                                    if (!started) {
                                                        _canvas.onmousemove = function (e) {
                                                            _evt.clientX = e.clientX;
                                                            _evt.clientY = e.clientY + 30;
                                                        }
                                                        started = true;
                                                    }
                                                    return {
                                                        x: _mouse.getX(_evt),
                                                        y: _mouse.getY(_evt)
                                                    };
                                                }
                                            };
                                        })()
                                    },
                        
                                    /**
                                     * A utility that tracks the state of the element being draged (if any)
                                     *
                                     * @class _elementBeingDraged
                                     * @for _drawing
                                     */
                                    _elementBeingDraged = {
                        
                                        /**
                                        * The element being draged
                                        *
                                        * @property reference
                                        * @type _basicElement
                                        * @default null
                                        * @for _elementBeingDraged
                                        * @static
                                        */
                                        reference: null,
                        
                                        /**
                                        * Whether or not the user is holding the CTRL key
                                        *
                                        * @property holdingCTRL
                                        * @type Bool
                                        * @default false
                                        * @for _elementBeingDraged
                                        * @static
                                        */
                                        holdingCTRL: false,
                        
                                        /**
                                        * A copy from the original border specification for the element being draged
                                        *
                                        * @property originalBorder
                                        * @type Object
                                        * @default {}
                                        * @for _elementBeingDraged
                                        * @static
                                        */
                                        originalBorder: {},
                        
                                        /**
                                         * The types of drag that can be applied to an element
                                         * 
                                         * It can be either: 
                                         *      1 - moving
                                         *      3 - linking
                                         * 
                                         * @attribute dragTypes
                                         */
                                        dragTypes: {
                        
                                            /**
                                             * The element is being moved
                                             * 
                                             * @element moving
                                             * @parents dragTypes
                                             */
                                            moving: 1,
                        
                                            /**
                                             * The element is being linked
                                             * 
                                             * @element moving
                                             * @parents dragTypes
                                             */
                                            linking: 3
                                        },
                        
                                        /**
                                        * Default drag type
                                        *
                                        * @property dragType
                                        * @type Number
                                        * @default 0
                                        * @for _elementBeingDraged
                                        * @static
                                        */
                                        dragType: 0,
                        
                                        temporaryLinkArrow: (function () {
                        
                                            return {
                        
                                                /**
                                                * Whenever possible/necessary it plots the linking arrow to the canvas
                                                *
                                                * @method tryRender
                                                * @private
                                                */
                                                tryRender: function () {
                                                    if ((_elementBeingDraged.reference !== null)
                                                        && (_elementBeingDraged.dragType === _elementBeingDraged.dragTypes.linking)
                                                        && _elementBeingDraged.reference.isLinkable() === true) {
                        
                                                        var targetXY = _mouse.staticCoordinates.getXY(),
                                                            arrow = new _defaultConfigurations.arrow({
                                                                x: targetXY.x,
                                                                y: targetXY.y - 30,
                                                                getHeight: function () { return 0; }
                                                            });
                                                        arrow.name = "_temp";
                                                        arrow.setParent(_elementBeingDraged.reference);
                                                        arrow.drawTo(_canvas, _2dContext);
                                                    }
                                                    return this;
                                                }
                                            };
                                        })(),
                        
                                        border: {
                                            whenMoving: {
                                                color: "yellow",
                                                active: true
                                            },
                                            whenLiking: {
                                                color: "green",
                                                active: true
                                            }
                                        }
                                    },
                        
                                    /**
                                    * Handles de mouse move envent
                                    *
                                    * @method _whenMouseMove
                                    * @param {Event} evt Event we're bubbling in
                                    * @for _drawing
                                    * @private
                                    */
                                    _whenMouseMove = function (evt) {
                                        if ((_elementBeingDraged.reference !== null)
                                            && (_elementBeingDraged.dragType === _elementBeingDraged.dragTypes.moving)) {
                        
                                            _helpers.$log.info("Moving element", _elementBeingDraged);
                                            _elementBeingDraged.reference.x = _mouse.getX(evt);
                                            _elementBeingDraged.reference.y = _mouse.getY(evt);
                                        }
                                    },
                        
                                    /**
                                    * Handles de mouse up envent
                                    *
                                    * @method _whenMouseUp
                                    * @param {Event} evt Event we're bubbling in
                                    * @private
                                    */
                                    _whenMouseUp = function (evt) {
                                        if (_elementBeingDraged.reference !== null) {
                        
                                            if (_elementBeingDraged.dragType === _elementBeingDraged.dragTypes.linking) {
                                                for (var i = 0; i < _elements.length; i++) {
                                                    if (_elements[i] !== _elementBeingDraged.reference
                                                        && _elements[i].existsIn(_mouse.getX(evt), _mouse.getY(evt))) {
                        
                                                        if (_elementBeingDraged.reference.addLinkTo(_elements[i])) {
                                                            _elements.push(new _defaultConfigurations
                                                                .arrow(_elements[i])
                                                                .setParent(_elementBeingDraged.reference));
                                                            break;
                                                        }
                                                    }
                                                }
                                            }
                        
                                            _elementBeingDraged.reference.on.release(_mouse.getX(evt), _mouse.getY(evt),
                                                       _elementBeingDraged.reference, evt);
                        
                                            _elementBeingDraged.reference.border = _elementBeingDraged.originalBorder;
                                            _elementBeingDraged.reference = null;
                                        }
                                    },
                        
                        
                                    /**
                                    * Removes a given element from the canvas
                                    *
                                    * @method _removeElement
                                    * @param {_basicElement} e Element that is to be removed
                                    * @private
                                    * @chainable
                                    */
                                    _removeElement = function (e) {
                                        _helpers.$log.info("Removing element", e);
                                        e.disable();
                                        _elements.splice(_elements.indexOf(e), 1);
                                        return this;
                                    },
                        
                                    /**
                                    * Adds a given element from the canvas
                                    *
                                    * @method _addElement
                                    * @param {_basicElement} e Element that is to be added
                                    * @private
                                    * @chainable
                                    */
                                    _addElement = function (e) {
                                        _helpers.$log.info("Adding element", e);
                                        _elements.push(e);
                                        return this;
                                    },
                        
                                    /**
                                    * Handles de key up envent
                                    *
                                    * @method _whenKeyUp
                                    * @param {Event} evt Event we're bubbling in
                                    * @private
                                    * @chainable
                                    */
                                    _whenKeyUp = function (evt) {
                                        _elementBeingDraged.holdingCTRL = false;
                                        return this;
                                    },
                        
                                    /**
                                    * Handles de key down envent
                                    *
                                    * @method _whenKeyDown
                                    * @param {Event} evt Event we're bubbling in
                                    * @private
                                    * @chainable
                                    */
                                    _whenKeyDown = function (e) {
                                        var key = e.keyCode || e.charCode;
                                        if (((key === 46) || (key === 8))
                                            && (_elementBeingDraged.reference !== null)) {
                                            _removeElement(_elementBeingDraged.reference.clearAllLinks());
                                            _elementBeingDraged.reference = null;
                                        } else {
                                            _elementBeingDraged.holdingCTRL = (key === 17);
                                        }
                                        return this;
                                    },
                        
                                    /**
                                    * Handles the click event
                                    *
                                    * @method _checkClick
                                    * @param {Event} evt Event we're bubbling in
                                    * @private
                                    */
                                    _checkClick = function (evt) {
                        
                                        evt = evt || w.event;
                                        for (var i = 0; i < _elements.length; i++) {
                                            if (_elements[i].existsIn(_mouse.getX(evt), _mouse.getY(evt))) {
                                                if ((_elementBeingDraged.reference = _elements[i]).canHandleEvents()) {
                                                    _elementBeingDraged.reference.on.click(
                                                        _mouse.getX(evt),
                                                        _mouse.getY(evt),
                                                        _elementBeingDraged.reference, evt);
                                                }
                                            }
                                        }
                        
                                        if (_elementBeingDraged.reference !== null) {
                                            var dragType = _elementBeingDraged.dragTypes.moving;
                                            if (!_helpers.$device.isTouch) {
                                                dragType = _elementBeingDraged.holdingCTRL === true && _elementBeingDraged.reference.isLinkable() === true ?
                                                    _elementBeingDraged.dragTypes.linking :
                                                    evt.which;
                                            }
                                            _elementBeingDraged.originalBorder = _elementBeingDraged.reference.border;
                                            _elementBeingDraged.reference.border =
                                                ((_elementBeingDraged.dragType = dragType) === _elementBeingDraged.dragTypes.moving) ?
                                                _elementBeingDraged.border.whenMoving :
                                                _elementBeingDraged.border.whenLiking;
                                            _helpers.$log.info("Dragging element", { r: _elementBeingDraged.reference, d: dragType });
                                        }
                        
                                        if (evt.preventDefault) {
                                            evt.preventDefault();
                                        } else if (evt.returnValue) {
                                            evt.returnValue = false;
                                        }
                                        return false;
                                    },
                        
                                    /**
                                    * Plots each and every element to the canvas and registers all the event handlers delegates
                                    *
                                    * @method _draw
                                    * @private
                                    * @chainable
                                    */
                                    _draw = function () {
                        
                                        if (_canvas === null) {
                                            _2dContext = (_canvas = $("#" + _activeConfiguration.targetCanvasId))
                                                .getContext("2d");
                        
                                            /// Canvas related events
                                            _helpers.$dom.get(_canvas)
                                                .on("mousedown", _checkClick)
                                                .on("mousemove", _whenMouseMove)
                                                .on("contextmenu", function (e) {
                                                    e.preventDefault();
                                                    return false;
                                                });
                        
                                            if (_helpers.$obj.isArray(_activeConfiguration.toolboxButtons)) {
                                                var wCanvas = _helpers.$dom.get(_canvas);
                        
                                                if (wCanvas.getParent().attr("id") !== _activeConfiguration.targetCanvasContainerId) {
                                                    wCanvas
                                                        .getParent()
                                                        .addChild("div")
                                                        .attr("id", _activeConfiguration.targetCanvasContainerId)
                                                        .addChild(wCanvas.raw());
                                                }
                                                _helpers.$obj.forEach(_activeConfiguration.toolboxButtons, function (button) {
                                                    wCanvas
                                                        .addSibling("div").attr("id", button.id = _helpers.$obj.generateId())
                                                        .html(button.template)
                                                        .on("click", function () {
                                                            button.onclick(_canvas);
                                                        });
                                                });
                                            }
                        
                                            /// Window events
                                            _helpers.$dom.get(w)
                                                .on("mouseup", _whenMouseUp)
                                                .on("keydown", _whenKeyDown)
                                                .on("keyup", _whenKeyUp);
                        
                                            if (_helpers.$device.isTouch === true) {
                                                /// If we're in a touch device
                        
                                                _helpers.$dom.get(_canvas)
                                                    .on("touchstart", _checkClick)
                                                    .on("touchmove", _whenMouseMove);
                                                _helpers.$dom.get(w)
                                                    .on("touchend", _whenMouseUp)
                                                    .on("touchcancel", _whenMouseUp);
                                            }
                                            _canvasElement = _helpers.$obj.extend(new _defaultConfigurations.htmlElement(_canvas), {});
                                        }
                        
                                        _2dContext.clearRect(0, 0, _canvas.width, _canvas.height);
                                        for (var i = 0; i < _elements.length; i++) {
                                            _drawAllIn(_elements[i]);
                                        }
                                        _elementBeingDraged.temporaryLinkArrow.tryRender();
                        
                                        return this;
                                    },
                        
                                    /**
                                    * Gathers all elements being ploted to the canvas and organizes it as a directed graph JSON
                                    * 
                                    * @method  _getElementsSlim
                                    * @return {_graphNodeInfo} Graph node information
                                    * @private
                                    */
                                    _getElementsSlim = function () {
                        
                                        var result = {},
                                            element,
                                            links;
                        
                                        for (var i = 0; i < _elements.length; i++) {
                        
                                            element = _elements[i];
                        
                                            if (element.graphNode === true) {
                                                if ((((links = element.getLinksFrom()) === null) || (links.length === 0))
                                                    && (((links = element.getLinksTo()) === null) || (links.length === 0))) {
                                                    throw new _defaultConfigurations.errors.elementDoesNotHaveALink(element.name);
                                                }
                        
                                                result[element.name] = new _graphNodeInfo(element, null, element.getLinksTo());
                                            }
                                        }
                        
                                        return result;
                                    };
                        
                                return {
                        
                                    mouseHelper: _mouse,
                        
                                    /**
                                     * Add a given element to the drawing elements array
                                     * 
                                     * @method  addElement
                                     * @param {_basicElement} element The element to be drawn
                                     * @chainable
                                     */
                                    addElement: function (element) {
                                        _addElement(element);
                                        return this;
                                    },
                        
                                    /**
                                    * Gets the canvas' dataURL
                                    * 
                                    * @method  getDataUrl
                                    * @param {bool} cropImage Whether or not to crop the exported image
                                    */
                                    getDataUrl: function (cropImage) {
                                        if (cropImage === true) {
                        
                                            var silkCanvas = _helpers.$dom.create("canvas").raw(),
                                                silkCanvasContext = silkCanvas.getContext("2d"),
                                                sorter = function (a, b) { return a - b },
                                                sourceCanvasWidth = _canvas.width,
                                                sourceCanvasHeight = _canvas.height,
                                                pix = { x: [], y: [] },
                                                imageData = _2dContext.getImageData(0, 0, sourceCanvasWidth, sourceCanvasHeight),
                                                index = 0;
                        
                                            for (var y = 0; y < sourceCanvasHeight; y++) {
                                                for (var x = 0; x < sourceCanvasWidth; x++) {
                                                    index = (y * sourceCanvasWidth + x) * 4;
                                                    if (imageData.data[index + 3] > 0) {
                                                        pix.x.push(x);
                                                        pix.y.push(y);
                                                    }
                                                }
                                            }
                        
                                            pix.x.sort(sorter);
                                            pix.y.sort(sorter);
                        
                                            var n = pix.x.length - 1;
                                            sourceCanvasWidth = pix.x[n] - pix.x[0];
                                            sourceCanvasHeight = pix.y[n] - pix.y[0];
                        
                                            var cut = _2dContext.getImageData(pix.x[0], pix.y[0], sourceCanvasWidth, sourceCanvasHeight);
                        
                                            silkCanvas.width = sourceCanvasWidth;
                                            silkCanvas.height = sourceCanvasHeight;
                                            silkCanvasContext.putImageData(cut, 0, 0);
                                            return silkCanvas.toDataURL();
                                        }
                                        return _canvas.toDataURL();
                                    },
                        
                                    /**
                                     * Removes a given element from the canvas
                                     *
                                     * @method remove
                                     * @param {_basicElement} element Element that is to be removed
                                     * @private
                                     * @chainable
                                     */
                                    remove: function (element) {
                                        _removeElement(element);
                                        return this;
                                    },
                        
                                    /**
                                    * Gathers all elements being ploted to the canvas and organizes it as a directed graph JSON
                                    * 
                                    * @method  getElementsSlim
                                    * @return {_graphNodeInfo} Graph node information
                                    */
                                    getElementsSlim: function () {
                                        return _getElementsSlim();
                                    },
                        
                                    /**
                                     * Gathers all elements being ploted to the canvas
                                     * 
                                     * @method  getElements
                                     * @return {_basicElement[]} Graph node information
                                     */
                                    getElements: function () {
                                        return _elements;
                                    },
                        
                                    /**
                                    * Redefines the elements that are supposed to be ploted to the canvas
                                    *
                                    * @method reloadUsing
                                    * @param {_basicElements[]} elements The elements that are going to be ploted
                                    * @static
                                    * @chainable
                                    */
                                    reloadUsing: function (elements) {
                                        _elements = elements;
                                        this.initializeTimedDrawing();
                                    },
                        
                                    /**
                                    * Returns the corresponding Raska Canvas element
                                    * 
                                    * @method  getCanvasElement
                                    */
                                    getCanvasElement: function () {
                                        return _canvasElement;
                                    },
                        
                                    /**
                                    * Returns the corresponding Raska Canvas element
                                    * 
                                    * @method  getCanvasElement
                                    * @return {HTMLElement} Canvas
                                    */
                                    getCanvas: function () {
                                        return _canvas;
                                    },
                        
                                    /**
                                    * Initializes the drawing process
                                    * 
                                    * @method  initializeTimedDrawing
                                    */
                                    initializeTimedDrawing: function () {
                                        if (_timerRunning === false) {
                                            _timerRunning = true;
                                            _timedDrawing();
                                        }
                                    }
                                };
                            })(),
                        
                            /**
                            * All public avaliable methods from the Raska library
                            *
                            * @class _public
                            */
                            _public = {
                        
                                /**
                                * Adds a new Label to the target canvas
                                *
                                * @method newLabel
                                * @return {_defaultConfigurations.label} Copy of '_defaultConfigurations.label' object
                                * @static
                                */
                                newLabel: function (defaultConfiguration) {
                                    return _helpers.$obj.extend(new _defaultConfigurations.label(), defaultConfiguration);
                                },
                        
                                /**
                                * Adds a new Square to the target canvas
                                *
                                * @method newSquare
                                * @return {_defaultConfigurations.square} Copy of '_defaultConfigurations.square' object
                                * @static
                                */
                                newSquare: function () {
                                    return _helpers.$obj.extend(new _defaultConfigurations.square(), {});
                                },
                        
                        
                                /**
                                * Adds a new Triangle to the target canvas
                                *
                                * @method newTriangle
                                * @return {_defaultConfigurations.square} Copy of '_defaultConfigurations.triangle' object
                                * @static
                                */
                                newTriangle: function (pointingUp) {
                                    return _helpers.$obj.extend(new _defaultConfigurations.triangle(pointingUp), {});
                                },
                        
                                /**
                                * Adds a new Circle to the target canvas
                                *
                                * @method newCircle
                                * @return {_defaultConfigurations.circle} Copy of '_defaultConfigurations.circle' object
                                * @static
                                */
                                newCircle: function () {
                                    return _helpers.$obj.extend(new _defaultConfigurations.circle(), {});
                                },
                        
                                /**
                                * Plots an element to the canvas
                                *
                                * @method plot
                                * @return {_public} Reference to the '_public' pointer
                                * @static
                                * @chainable
                                */
                                plot: function (element) {
                                    _drawing.addElement(element);
                                    return _public;
                                },
                        
                                /**
                                * Exports current canvas data as an image to a new window
                                *
                                * @method exportImage
                                * @param {bool} cropImage Whether or not to crop the exported image
                                * @return {_public} Reference to the '_public' pointer
                                * @chainable
                                * @static
                                */
                                exportImage: function (cropImage) {
                                    w.open(_drawing.getDataUrl(cropImage), '_blank');
                                    return _public;
                                },
                        
                                /**
                                * Retrieves the raw elements from the drawing stack
                                *
                                * @method getElementsRaw
                                * @return {json} The JSON object that represents ALL the Raska elements in the canvas
                                * @static
                                */
                                getElementsRaw: function () {
                                    return _drawing.getElements();
                                },
                        
                                /**
                                * Retrieves the directed graph represented by the elements in the canvas 
                                *
                                * @method getElementsSlim
                                * @return {json} The JSON object that represents the current directed graph drawn to the canvas
                                * @static
                                */
                                getElementsSlim: function () {
                                    return _drawing.getElementsSlim();
                                },
                        
                                /**
                                * Retrieves the ENTIRE directed graph represented by the elements in the canvas 
                                *
                                * @method getElementsData
                                * @return {String} The stringfied JSON that represents the current directed graph drawn to the canvas
                                * @static
                                */
                                getElementsString: function () {
                                    return _helpers.$obj.deconstruct(_drawing.getElements());
                                },
                        
                                /**
                                * Redefines the elements that are supposed to be ploted to the canvas
                                *
                                * @method loadElementsFrom
                                * @param {_basicElements[]} source The elements that are going to be ploted
                                * @static
                                * @chainable
                                */
                                loadElementsFrom: function (source) {
                                    var preparsedSource = JSON.parse(source);
                                    if (_helpers.$obj.isArray(preparsedSource)) {
                        
                                        var realSource = [], childElements = [], i = 0, parsed = null;
                                        /// Create a basic element instance
                                        for (i = 0; i < preparsedSource.length; i++) {
                                            if ((parsed = _helpers.$obj.recreate(preparsedSource[i])) === null) {
                                                alert("Invalid JSON. See the console for more info");
                                                console.error("Could not deserialize this element", preparsedSource[i]);
                                                return this;
                                            }
                                            if (preparsedSource[i].parent === null) {
                                                parsed.originalIndex = i;
                                                realSource.push(parsed);
                                            } else {
                                                childElements.push(parsed);
                                            }
                                        }
                        
                                        /// Adds back the links between elements
                                        var findElement = function (itemName) {
                                            if (!_helpers.$obj.isValid(itemName)) {
                                                return null;
                                            }
                        
                                            function find(arr) {
                                                for (var j = 0; j < arr.length; j++) {
                                                    if (arr[j].name === itemName) {
                                                        return arr[j];
                                                    }
                                                }
                                            }
                        
                                            var itemFound = find(realSource) || find(childElements);
                                            if (!itemFound) {
                                                throw _defaultConfigurations.errors.itemNotFoundException(itemName);
                                            }
                                            return itemFound;
                                        };
                                        for (i = 0; i < realSource.length; i++) {
                                            _helpers.$obj.recreateLinks(realSource[i], preparsedSource[realSource[i].originalIndex], findElement);
                                            delete realSource[i].originalIndex;
                                        }
                        
                                        /// Recriates all arrows
                                        var linksTo = [], item;
                                        for (i = 0; i < realSource.length; i++) {
                                            item = realSource[i];
                                            if ((item.isLinkable() === true)
                                                && ((linksTo = item.getLinksTo()).length > 0)) {
                                                for (var k = 0; k < linksTo.length; k++) {
                                                    realSource.push(new _defaultConfigurations
                                                        .arrow(linksTo[k])
                                                        .setParent(item));
                                                }
                                            }
                                        }
                                        _drawing.reloadUsing(realSource);
                                    }
                                    return this;
                                },
                        
                                /**
                                * Toggles fullscreen mode on/off
                                *
                                * @property toggleFullScreen
                                * @static
                                * @chainable
                                */
                                toggleFullScreen: function () {
                                    _canvasController.toggleFullScreen(_drawing.getCanvas());
                                    return _public;
                                },
                        
                                /**
                                * Retrieves all possible position types
                                *
                                * @property positionTypes
                                * @type _positionTypes
                                * @static
                                */
                                positionTypes: (function () {
                                    return _positionTypes;
                                })(),
                        
                                /**
                                * Configures the Raska library to target a given canvas using the configuration passed
                                * as a parameter
                                *
                                * @method installUsing
                                * @param {_defaultConfigurations.library} configuration Configuration data that should be used to configure this Raska instance
                                * @return {_public} Reference to the '_public' pointer
                                * @static
                                * @chainable
                                */
                                installUsing: function (configuration) {
                                    _activeConfiguration = _helpers.$obj.extend(_defaultConfigurations.library, configuration);
                                    _drawing.initializeTimedDrawing();
                                    return _public;
                                },
                        
                                /**
                                * Registers a handler to be trigered by any interaction taken place against the canvas
                                *
                                * @method onElementInteraction
                                * @param {string} iteractionType When to trigger the iteraction handler
                                * @param {Function} trigger What to do whenever an element iteraction happens
                                * @static
                                * @chainable
                                */
                                onCanvasInteraction: function (iteractionType, trigger) {
                                    _elementInteractionEventData.register(_drawing.getCanvasElement(), iteractionType, trigger);
                                    return this;
                                },
                        
                                /**
                                * Checks whether or not an element does exists at a given coordinate
                                *
                                * @method checkCollisionOn
                                * @param {number} x X position
                                * @param {number} y Y position
                                * @return {bool} Wheter or not an element can be found at these coordinates
                                * @static
                                */
                                checkCollisionOn: function (x, y) {
                                    return _public.tryGetElementOn(x, y) !== null;
                                },
                        
                                /**
                                * Tries to get the element that exists at a given coordinate
                                *
                                * @method tryGetElementOn
                                * @param {number} x X position
                                * @param {number} y Y position
                                * @return {_basicElement} Raska basic element (if any) or null
                                * @static
                                */
                                tryGetElementOn: function (x, y) {
                                    var elements = _drawing.getElements();
                                    for (var i = 0; i < elements.length; i++) {
                                        if (elements[i].existsIn(x, y) === true) {
                                            return elements[i];
                                        }
                                    }
                                    return null;
                                },
                        
                                /**
                                * Removes a given element from the canvas
                                *
                                * @method remove
                                * @param {_basicElement} element Element that is to be removed
                                * @private
                                * @chainable
                                */
                                remove: function (element) {
                                    _drawing.remove(element);
                                    return this;
                                },
                        
                                /**
                                * Gathers the target canvas boundaries
                                *
                                * @method getCanvasBoundaries
                                * @static
                                * @return {maxW:number, maxH:number}
                                */
                                getCanvasBoundaries: function () {
                                    var el = _drawing.getCanvasElement();
                                    return { maxH: el.getHeight(), maxW: el.getWidth() };
                                },
                        
                                /**
                                * Clears all elements from the canvas
                                *
                                * @method clear
                                * @static
                                * @chainable
                                */
                                clear: function () {
                                    _drawing.reloadUsing([]);
                                    return this;
                                },
                        
                                $$: { $h: _helpers, $q: $, $c: _activeConfiguration }
                            };
                        
                            w.raska = _public;
                        })(window, document);