UNPKG

processmaker-builder

Version:

The gulp task runner for ProcessMaker building

1,494 lines (1,391 loc) 1.77 MB
/** * @class PMUI * Base class PMUI * @singleton */ var PMUI = {}; PMUI.version = '0.1.1'; PMUI.isCtrl = false; PMUI.isShift = false; PMUI.activeCanvas = null; PMUI.currentContextMenu = null; PMUI.keyCodeF5 = 116; $(document).keydown(function (e) { var elementSelected; if (PMUI.activeCanvas) { elementSelected = PMUI.activeCanvas.getCurrentSelection(); switch (e.which) { case 16: // SHIFT KEY PMUI.isShift = true; break; case 17: // CTRL KEY PMUI.isCtrl = true; break; case 116: // F5 KEY e.preventDefault(); window.location.reload(true); break; case 37: // Left if (!PMUI.activeCanvas.currentLabel) { e.preventDefault(); if (!PMUI.getCoordinatesElement(elementSelected.asArray(), "LEFT")) { PMUI.activeCanvas.moveElements(PMUI.activeCanvas, 'LEFT'); } } break; case 38: // Top if (!PMUI.activeCanvas.currentLabel) { e.preventDefault(); if (!PMUI.getCoordinatesElement(elementSelected.asArray(), "TOP")) { PMUI.activeCanvas.moveElements(PMUI.activeCanvas, 'TOP'); } } break; case 39: // Right if (!PMUI.activeCanvas.currentLabel) { e.preventDefault(); if (!PMUI.getCoordinatesElement(elementSelected.asArray(), "RIGHT")) { PMUI.activeCanvas.moveElements(PMUI.activeCanvas, 'RIGHT'); } } break; case 40: // Bottom if (!PMUI.activeCanvas.currentLabel) { e.preventDefault(); if (!PMUI.getCoordinatesElement(elementSelected.asArray(), "BOTTOM")) { PMUI.activeCanvas.moveElements(PMUI.activeCanvas, 'BOTTOM'); } } break; case 67: // char 'c' if (!PMUI.activeCanvas.currentLabel && PMUI.isCtrl) { if (PMUI.activeCanvas.copyAndPaste) { e.preventDefault(); PMUI.activeCanvas.copy(); } } break; case 86: // char 'v' if (!PMUI.activeCanvas.currentLabel && PMUI.isCtrl) { if (PMUI.activeCanvas.copyAndPaste) { e.preventDefault(); PMUI.activeCanvas.paste(); } } break; case 90: // char 'z' if (PMUI.isCtrl && !PMUI.activeCanvas.readOnly) { if (PMUI.isShift) { // ctrl + shift + z (redo) PMUI.activeCanvas.redo(); e.preventDefault(); } else { // ctrl + z (undo) PMUI.activeCanvas.undo(); e.preventDefault(); } } break; } } }).keypress(function (e) { }).keyup(function (e) { var current; if (PMUI.activeCanvas) { e.preventDefault(); switch (e.which) { case 8: //BACKSPACE if (PMUI.isCtrl) { if (PMUI.activeCanvas && !PMUI.activeCanvas.currentLabel) { PMUI.activeCanvas.removeElements(); } } break; case 13: // ENTER if (PMUI.activeCanvas && PMUI.activeCanvas.currentLabel) { PMUI.activeCanvas.currentLabel.loseFocus(); } break; case 46: // DELETE KEY if (PMUI.activeCanvas && !PMUI.activeCanvas.currentLabel) { PMUI.activeCanvas.removeElements(); } break; case 16: // SHIFT KEY PMUI.isShift = false; break; case 17: //CTRL KEY PMUI.isCtrl = false; break; case 113: //F2 KEY if (PMUI.activeCanvas && PMUI.activeCanvas.getCurrentSelection().getLast() !== null) { //Run other code here when the element // 'CurElement' is deleted current = PMUI.activeCanvas.getCurrentSelection().getLast(); if (current !== undefined && current.label.html !== null) { $(current.label.html).dblclick(); $(current.label.text.html).focus(); } } break; } } }); /** * Extends the PMUI namespace with the given `path` and making a pointer * from `path` to the given `class` (note that the `path`'s last token will be the pointer visible from outside * the definition of the class). * * // e.g. * // let's define a class inside an anonymous function * // so that the global scope is not polluted * (function () { * var Canvas = function () {...}; * * // let's extend the namespace * PMUI.extendNamespace('PMUI.core.Panel', Canvas); * * }()); * * // now PMDraw.draw.Canvas is a pointer to the class defined above * * Another example: * * // let's define a class inside an anonymous function * // so that the global scope is not polluted * (function () { * var Shape = function () {...}; * * // let's extend the namespace * PMUI.extendNamespace('PMUI.draw.RandomName', Shape); * * }()); * * // now PMUI.draw.RandomName is a pointer to the class Shape * // note that this class can only be accessed through this pointer * * @param {string} path * @param {Object} newClass * @return {Object} The argument `newClass` */ PMUI.extendNamespace = function (path, newClass) { var current, pathArray, extension, i; if (arguments.length !== 2) { throw new Error("PMUI.extendNamespace(): method needs 2 arguments"); } pathArray = path.split('.'); if (pathArray[0] === 'PMUI') { pathArray = pathArray.slice(1); } current = PMUI; // create the 'path' namespace for (i = 0; i < pathArray.length - 1; i += 1) { extension = pathArray[i]; if (typeof current[extension] === 'undefined') { current[extension] = {}; } current = current[extension]; } extension = pathArray[pathArray.length - 1]; if (current[extension]) { } current[extension] = newClass; return newClass; }; /** * Checks if `path` (a string separated with dots) is a valid path inside the `from` object if provided otherwise * checks if `path` is a valid path inside the {@link PMUI} object, * if so then returns a pointer to the object which is the last token of the string * * // e.g * validPath('PMDraw.event.Keyboard.modifiers.alt'); // returns a pointer to alt * validPath('modifiers.alt', PMUI.event.Keyboard); // returns a pointer to alt * * @param {string} path * @param {Object} [from] * @return {Object} */ PMUI.validPath = function (path, from) { var pathArray = path.split('.'), current, extension, i; if (!from) { if (pathArray[0] === 'PMUI') { pathArray = pathArray.slice(1); } current = PMUI; } else { current = from; } for (i = 0; i < pathArray.length; i += 1) { extension = pathArray[i]; if (!current[extension]) { return null; } current = current[extension]; } return current; }; /** * Creates an object whose [[Prototype]] link points to an object's prototype (the object is gathered using the * argument `path` and it's the last token in the string), since `subClass` is given it will also mimic the * creation of the property `constructor` and a pointer to its parent called `superclass`: * * // constructor pointer * subClass.prototype.constructor === subClass // true * * // let's assume that superClass is the last token in the string 'path' * subClass.superclass === superClass // true * * An example of use: * * (function () { * var Core = function () {...}; * * // extending the namespace * PMDraw.extendNamespace('PMDraw.draw.Core', Core); * * }()); * * (function () { * var BehavioralElement = function () {...}; * * // this class inherits from PMDraw.draw.Core * PMDraw.inheritFrom('PMDraw.draw.Core', BehavioralElement); * * // extending the namespace * PMDraw.extendNamespace('PMDraw.draw.BehavioralElement', BehavioralElement); * * }()); * * @param {string} path * @param {Object} subClass * @return {Object} */ PMUI.inheritFrom = function (path, subClass) { var current, extension, pathArray, i, prototype; if (arguments.length !== 2) { throw new Error("PMUI.inheritFrom(): method needs 2 arguments"); } // function used to create an object whose [[Prototype]] link // points to `object` function clone(object) { var F = function () { }; F.prototype = object; return new F(); } pathArray = path.split('.'); if (pathArray[0] === 'PMUI') { pathArray = pathArray.slice(1); } current = PMUI; // find that class the 'path' namespace for (i = 0; i < pathArray.length; i += 1) { extension = pathArray[i]; if (typeof current[extension] === 'undefined') { throw new Error("PMUI.inheritFrom(): object " + extension + " not found, full path was " + path); } current = current[extension]; } prototype = clone(current.prototype); prototype.constructor = subClass; subClass.prototype = prototype; subClass.superclass = current; }; /** * Generates 32-digits alphanumeric unique IDs * @return {String} Alphanumeric 32-char unique string */ PMUI.generateUniqueId = function () { var rand = function (min, max) { // Returns a random number // // version: 1109.2015 // discuss at: http://phpjs.org/functions/rand // + original by: Leslie Hoare // + bugfixed by: Onno Marsman // % note 1: See the commented out code below for a // version which will work with our experimental // (though probably unnecessary) srand() function) // * example 1: rand(1, 1); // * returns 1: 1 // fix for jsLint // from: var argc = arguments.length; if (typeof min === "undefined") { min = 0; } if (typeof max === "undefined") { max = 999999999; } return Math.floor(Math.random() * (max - min + 1)) + min; }, uniqid = function (prefix, more_entropy) { // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + revised by: Kankrelune (http://www.webfaktory.info/) // % note 1: Uses an internal counter (in php_js global) to avoid collision // * example 1: uniqid(); // * returns 1: 'a30285b160c14' // * example 2: uniqid('foo'); // * returns 2: 'fooa30285b1cd361' // * example 3: uniqid('bar', true); // * returns 3: 'bara20285b23dfd1.31879087' if (typeof prefix === 'undefined') { prefix = ""; } var retId, formatSeed = function (seed, reqWidth) { var tempString = "", i; seed = parseInt(seed, 10).toString(16); // to hex str if (reqWidth < seed.length) { // so long we split return seed.slice(seed.length - reqWidth); } if (reqWidth > seed.length) { // so short we pad // jsLint fix tempString = ""; for (i = 0; i < 1 + (reqWidth - seed.length); i += 1) { tempString += "0"; } return tempString + seed; } return seed; }; // BEGIN REDUNDANT if (!this.php_js) { this.php_js = {}; } // END REDUNDANT if (!this.php_js.uniqidSeed) { // init seed with big random int this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15); } this.php_js.uniqidSeed += 1; retId = prefix; // start with prefix, add current milliseconds hex string retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8); retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string if (more_entropy) { // for more entropy we add a float lower to 10 retId += (Math.random() * 10).toFixed(8).toString(); } return retId; }, sUID; do { sUID = uniqid(rand(0, 999999999), true); sUID = sUID.replace('.', '0'); } while (sUID.length !== 32); return sUID; }; /** * Creates and returns a HTML element * @param {String} type The type for the element to be created, for example: div, span, p * @return {HTMLElement} An HTML element */ PMUI.createHTMLElement = function (type) { return document.createElement(type); }; /** * Calculates the text width usign a font family * @param {String} text The text which width will be calculated * @param {String} font The font family and size (expressed as the 'font' css properties) * to be used to calculate the width * @return {Number} */ PMUI.calculateWidth = function (text, font) { var f = font || '12px arial', $o = $(this.createHTMLElement('div')), w; $o.text(text) .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f}) .appendTo($('body')); w = $o.width(); $o.remove(); return w; }; PMUI.emToPx = function (emUnits, context) { var testDiv = PMUI.createHTMLElement('div'), theWidth, $div; testDiv.style.margin = '0'; testDiv.style.padding = '0'; testDiv.style.position = 'absolute'; testDiv.style.display = 'inline-block'; testDiv.style.backgroundColor = 'none'; testDiv.style.width = emUnits + "em"; context = PMUI.isHTMLElement(context) ? context : document.body; if (context !== document.body && !jQuery(context).parents('body').length) { throw new Error("The context must be an HTML element appended to the DOM."); } context.appendChild(testDiv); $div = jQuery(testDiv); theWidth = $div.outerWidth(); $div.remove(); return theWidth; }; /** * Get PMUI Version. * @return {String} */ PMUI.getVersion = function () { return this.version; }; /** * Trigger events defined in the element * @param {PMUI.core.Element} el Element associated with the event * @param {String} eventName Event Name or alias * @param {Object} scope Calling scope for the event */ PMUI.triggerEvent = function (el, eventName, scope) { var scopeTrigger = scope || this; if (el instanceof PMUI.core.Element) { if (el.events[eventName] instanceof PMUI.event.Event) { el.events[eventName].handler.call(scopeTrigger); } else { throw new Error('Event name is not registered int this element'); } } else { throw new Error('Current Element is not able to trigger events'); } }; /** * Sets the active canvas. * @param {PMUI.draw.Canvas} canvas * @chainable */ PMUI.setActiveCanvas = function (canvas) { PMUI.activeCanvas = canvas; return this; }; /** * Gets the active canvas * @return {PMUI.draw.Canvas} */ PMUI.getActiveCanvas = function () { return PMUI.activeCanvas; }; /** * Converts the coordinates `xCoord` and `yCoord` (assuming that xCoord and yCoord are pageCoordinates) * or the page coordinates gathered from the object `e` if there is no `xCoord` or `yCoord` to * `shape` coordinates, this new coordinate also considers the scroll done in the canvas * * // e.g. * // Let's assume that: * // the canvas coordinates are [100, 100] and that it has no scroll * // the shape coordinates are [100, 100] (inside the canvas) * // e is an object containing page.X = 300, page.Y = 300 * Utils.pageCoordinatesToShapeCoordinates(shape, e) // new Point(100, 100) respect to the shape * * * @param {Object} shape * @param {Object} e * @param {number} [xCoord] * @param {number} [yCoord] * @return {PMUI.util.Point} a point relative to the canvas */ PMUI.pageCoordinatesToShapeCoordinates = function (shape, e, xCoord, yCoord, customShape) { var coordinates, x = (!xCoord) ? e.pageX : xCoord, y = (!yCoord) ? e.pageY : yCoord, orgX = (!xCoord) ? e.pageX : xCoord, orgY = (!yCoord) ? e.pageY : yCoord, canvas = shape.getCanvas(); x += canvas.getLeftScroll() - shape.getAbsoluteX() - canvas.getX(); y += canvas.getTopScroll() - shape.getAbsoluteY() - canvas.getY(); if (orgX === x) { x -= parseInt(customShape.width / 2, 10); } if (orgY === y) { y -= parseInt(customShape.height / 2, 10); } coordinates = new PMUI.util.Point(x, y); return coordinates; }; /** * Validates the parameters that represents the coordinates for create a new shape * @param {Object} canvas Represents the current canvas for the project * @param {Object} e Represents the event that triggered on the event * @param {Object} customShape Represents the object that will create a new element on the canvas * @return {Boolean} flag After the review of the coordinates the method return true if the component * will create on the canvas and false if not possible create it. */ PMUI.validCoordinatedToCreate = function (canvas, e, customShape) { return function (canvas, e, customShape) { return true; }; }; /** * Converts the coordinates of the `shape` to page coordinates, this method * also considers the scroll of the canvas in the calculation * * // e.g. * // Let's assume that: * // the canvas coordinates are [100, 100] and that it has no scroll * // the shape coordinates are [100, 100] (inside the canvas) * Utils.getPointRelativeToPage(shape) // new Point(200, 200) respect to the page * * @param {Object} shape * @return {PMUI.util.Point} a point relative to the page */ PMUI.getPointRelativeToPage = function (shape) { var canvas = shape.getCanvas(), x = shape.absoluteX + canvas.getX() - canvas.getLeftScroll() + shape.zoomWidth / 2, y = shape.absoluteY + canvas.getY() - canvas.getTopScroll() + shape.zoomHeight / 2; return new PMUI.util.Point(x, y); }; PMUI.json2xml = function (o) { var len, toXML, safeXMLValue, a; len = function (o) { var n = 0, a; for (a in o) { if (o.hasOwnProperty(a)) { n += 1; } } return n; }; toXML = function (tag, o) { var a, b, doc = '<' + tag, sw = false, i; if (typeof o === 'undefined' || o === null) { doc += '/>'; return doc; } if (typeof o !== 'object') { doc += '>' + safeXMLValue(o) + '</' + tag + '>'; return doc; } if (o.constructor === Object) { for (a in o) { if (o.hasOwnProperty(a)) { if (a.charAt(0) === '@') { if (typeof o[a] !== 'object') { doc += ' ' + a.substring(1) + '="' + o[a] + '"'; delete o[a]; } else { throw new Error((typeof o[a]) + ' being attribute is not supported.'); } } } } if (len(o) === 0) { doc += '/>'; sw = true; } else { doc += '>'; } if (sw) { return doc; } if (typeof o['#text'] !== 'undefined') { if (typeof o['#text'] !== 'object') { doc += o['#text']; delete o['#text']; } else { throw new Error((typeof o['#text']) + ' being #text is not supported.'); } } for (b in o) { if (o.hasOwnProperty(b)) { if (o[b].constructor === Array) { for (i = 0; i < o[b].length; i += 1) { if (typeof o[b][i] !== 'object' || o[b][i].constructor === Object) { doc += toXML(b, o[b][i]); } else { throw new Error((typeof o[b][i]) + ' is not supported.'); } } } else if (o[b].constructor === Object || typeof o[b] !== 'object') { doc += toXML(b, o[b]); } else { throw new Error((typeof o[b]) + ' is not supported.'); } } } doc += '</' + tag + '>'; return doc; } }; safeXMLValue = function (value) { var s = value.toString(); s = s.replace(/\&/g, '&amp;'); s = s.replace(/\"/g, '&quot;'); s = s.replace(/</g, '&lt;'); s = s.replace(/>/g, '&gt;'); return s; }; if (typeof o === 'object' && o.constructor === Object && len(o) === 1) { for (a in o) { if (o.hasOwnProperty(a)) { return toXML(a, o[a]); } } } }; PMUI.linkToPMUIObject = function (element, pmuiObject) { if (this.isHTMLElement(element) && pmuiObject instanceof PMUI.core.Element) { jQuery(element).data('pmui', pmuiObject); } else { throw new Error("PMUI.linkToPMUIObject(): the first parameter must be a HTMLElement and the second one must be " + "an instance of PMUI.core.Element."); } }; PMUI.getPMUIObject = function (element) { if (this.isHTMLElement(element)) { return jQuery(element).data("pmui"); } throw new Error("PMUI.getPMUIObject(): the parameter must be a HTMLElement."); }; PMUI.isHTMLElement = function (obj) { try { //Using W3 DOM2 (works for FF, Opera and Chrom) return obj instanceof HTMLElement; } catch (e) { //Browsers not supporting W3 DOM2 don't have HTMLElement and //an exception is thrown and we end up here. Testing some //properties that all elements have. (works on IE7) return (typeof obj === "object") && (obj.nodeType === 1) && (typeof obj.style === "object") && (typeof obj.ownerDocument === "object"); } }; PMUI.removeCurrentMenu = function () { if (PMUI.currentContextMenu && PMUI.currentContextMenu.displayed) { PMUI.currentContextMenu.hide(); PMUI.currentContextMenu = null; } }; PMUI.init = function () { String.prototype.translate = PMUI.lang.I18N.translate; String.prototype.translateContext = PMUI.lang.I18N.translateContext; if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (elt /*, from*/) { var len = this.length >>> 0; var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0) from += len; for (; from < len; from += 1) { if (from in this && this[from] === elt) return from; } return -1; }; } return this; }; PMUI.loadLanguage = function (data, lang, loaded) { PMUI.lang.I18N.loadLanguage(data, lang, loaded); return this; }; PMUI.setCurrentLanguage = function (lang) { PMUI.lang.I18N.setCurrentLanguage(lang); return this; }; PMUI.setDefaultLanguage = function (lang) { PMUI.lang.I18N.setDefaultLanguage(lang); return this; }; PMUI.convertDateFormat = function (dateInput) { //TODO Implement this method considering locate options return dateInput; }; PMUI.castValue = function (value, format) { try { switch (format) { case 'string': out = String(value); break; case 'number': if (value != '') { out = Number(value); } else { out = 'NaN'; } break; case 'date': out = PMUI.convertDateFormat(value); break; case 'boolean': out = Boolean(value); break; default: out = value; } return out; } catch (e) { throw new Error("The value cannot be showed in '" + format + "' format"); } }; /** * validates that the items do not leave the parent container * @param elements array of items selecteds * @param direction string of cursor key * @returns {boolean} */ PMUI.getCoordinatesElement = function (elements, direction) { var element, factorPixel, swError, factorZoom, ParentPoints, ShapePoints, limitTop, limitRight, limitBottom, limitLeft; swError = false; if (elements.length > 0) { if (elements[0].parent.parent !== null) { element = elements[0]; factorPixel = [4, 4, 4, 2]; factorZoom = element.getCanvas().getZoomFactor(); ParentPoints = PMUI.getCoordenatesParent(element.parent, factorZoom); ShapePoints = PMUI.getAbsoluteShape(elements, factorZoom); limitTop = ParentPoints.PInit.getY() + (factorPixel[0] * factorZoom); limitRight = ParentPoints.PFinal.getX() - (factorPixel[1] * factorZoom); limitBottom = ParentPoints.PFinal.getY() - (factorPixel[2] * factorZoom); limitLeft = ParentPoints.PInit.getX() + (factorPixel[3] * factorZoom); switch (direction) { case 'TOP': if (limitTop > ShapePoints.PInit.getY()) { swError = true; } break; case 'RIGHT': if (limitRight < ShapePoints.PFinal.getX()) { swError = true; } break; case 'BOTTOM': if (limitBottom < ShapePoints.PFinal.getY()) { swError = true; } break; case 'LEFT': if (limitLeft > ShapePoints.PInit.getX()) { swError = true; } break; } } } return swError; }; /** * Get the parent coordenates * @param parent Object parent of the item selected * @param factorZoom * @returns {Object of Objects Point} */ PMUI.getCoordenatesParent = function (parent, factorZoom) { var coordenatesParent, xInit, yInit, xFinal, yFinal, pointInit, pointFinal, headParent; headParent = 0; if (parent.type === "PMPool") { headParent = parent.headLineCoord * factorZoom; } xInit = parent.getAbsoluteX() + headParent; yInit = parent.getAbsoluteY(); xFinal = parent.getAbsoluteX() + (parent.getWidth() * factorZoom); yFinal = parent.getAbsoluteY() + (parent.getHeight() * factorZoom); pointInit = new PMUI.util.Point(xInit, yInit); pointFinal = new PMUI.util.Point(xFinal, yFinal); coordenatesParent = { "PInit": pointInit, "PFinal": pointFinal }; return coordenatesParent; }; /** * Get coordenates min y max of the items selecteds * @param shapes Array of items selecteds * @param factorZoom * @returns {Object of Objects Point} */ PMUI.getAbsoluteShape = function (shapes, factorZoom) { var coordenatesShapeAux, coordenatesShape, arrayShapesAux = [], pointShapeInit, pointShapeFinal, shape, xFinalAux, yFinalAux, i; for (i = 0; i < shapes.length; i += 1) { shape = shapes[i]; xFinalAux = shape.getAbsoluteX() + (shape.getWidth() * factorZoom); yFinalAux = shape.getAbsoluteY() + (shape.getHeight() * factorZoom); pointShapeInit = new PMUI.util.Point(shape.getAbsoluteX(), shape.getAbsoluteY()); pointShapeFinal = new PMUI.util.Point(xFinalAux, yFinalAux); coordenatesShapeAux = { "PInit": pointShapeInit, "PFinal": pointShapeFinal }; arrayShapesAux.push(coordenatesShapeAux); } coordenatesShape = PMUI.getMinMaxCoordenates(arrayShapesAux); return coordenatesShape; }; /** * Get the Min y Max coordenates of a array of Objects Point * @param coordenates array of Objects Point * @returns {Object of Objects Point} */ PMUI.getMinMaxCoordenates = function (coordenates) { var objectCoordenates, xInit, yInit, xFinal, yFinal, j; xInit = coordenates[0].PInit.getX(); yInit = coordenates[0].PInit.getY(); xFinal = coordenates[0].PFinal.getX(); yFinal = coordenates[0].PFinal.getY(); for (j = 0; j < coordenates.length; j += 1) { if (coordenates[j].PInit.getX() < xInit) { xInit = coordenates[j].PInit.getX(); } if (coordenates[j].PInit.getY() < yInit) { yInit = coordenates[j].PInit.getY(); } if (coordenates[j].PFinal.getX() > xFinal) { xFinal = coordenates[j].PFinal.getX(); } if (coordenates[j].PFinal.getY() > yFinal) { yFinal = coordenates[j].PFinal.getY(); } } objectCoordenates = { "PInit": new PMUI.util.Point(xInit, yInit), "PFinal": new PMUI.util.Point(xFinal, yFinal) }; return objectCoordenates; }; PMUI.isInDOM = function (html) { var targetHTML = html instanceof PMUI.core.Element ? html.html : html, aux; if (targetHTML === null) { return false; } else if (!PMUI.isHTMLElement(targetHTML)) { throw new Error('isInDOM(): invalid parameter, only HTML or instance of PMUI.core.Element are allowed.'); } aux = jQuery(html).parents('html')[0]; return !!aux && aux.parentNode === document; }; String.prototype.capitalize = function () { return this.toLowerCase().replace(/(^|\s)([a-z])/g, function (m, p1, p2) { return p1 + p2.toUpperCase(); }); }; if (typeof exports !== "undefined") { module.exports = PMUI; } (function () { /** * @class PMUI.util.ArrayList * Construct a List similar to Java's ArrayList that encapsulates methods for * making a list that supports operations like get, insert and others. * * some examples: * var item, * arrayList = new ArrayList(); * arrayList.getSize() // 0 * arrayList.insert({ // insert an object * id: 100, * width: 100, * height: 100 * }); * arrayList.getSize(); // 1 * arrayList.asArray(); // [{id : 100, ...}] * item = arrayList.find('id', 100); // finds the first element with an id that equals 100 * arrayList.remove(item); // remove item from the arrayList * arrayList.getSize(); // 0 * arrayList.isEmpty(); // true because the arrayList has no elements * * @constructor Returns an instance of the class ArrayList */ var ArrayList = function () { /** * The elements of the arrayList * @property {Array} * @private */ var elements = [], /** * The size of the array * @property {number} [size=0] * @private */ size = 0, index, i; return { /** * The ID of this ArrayList is generated using the function Math.random * @property {number} id */ id: Math.random(), /** * Gets an element in the specified index or undefined if the index * is not present in the array * @param {number} index * @returns {Object / undefined} */ get: function (index) { return elements[index]; }, /** * Inserts an element at the end of the list * @param {Object} item * @chainable */ insert: function (item) { elements[size] = item; size += 1; return this; }, /** * Inserts an element in a specific position * @param {Object} item * @chainable */ insertAt: function (item, index) { elements.splice(index, 0, item); size = elements.length; return this; }, /** * Removes an item from the list * @param {Object} item * @return {boolean} */ remove: function (item) { index = this.indexOf(item); if (index === -1) { return false; } //swap(elements[index], elements[size-1]); size -= 1; elements.splice(index, 1); return true; }, /** * Gets the length of the list * @return {number} */ getSize: function () { return size; }, /** * Returns true if the list is empty * @returns {boolean} */ isEmpty: function () { return size === 0; }, /** * Returns the first occurrence of an element, if the element is not * contained in the list then returns -1 * @param {Object} item * @return {number} */ indexOf: function (item) { for (i = 0; i < size; i += 1) { if (item === elements[i]) { return i; } } return -1; }, /** * Returns the the first object of the list that has the * specified attribute with the specified value * if the object is not found it returns undefined * @param {string} attribute * @param {string} value * @return {Object / undefined} */ find: function (attribute, value) { var i, current; for (i = 0; i < elements.length; i += 1) { current = elements[i]; if (current[attribute] === value) { return current; } } return undefined; }, /** * Returns true if the list contains the item and false otherwise * @param {Object} item * @return {boolean} */ contains: function (item) { if (this.indexOf(item) !== -1) { return true; } return false; }, /** * Sorts the list using compFunction if possible, if no compFunction * is passed as an parameter then a default sorting method will be used. This default method will sort in * ascending order. * @param {Function} [compFunction] The criteria function used to find out the position for the elements in * the array list. This function will receive two parameters, each one will be an element from the array * list, the function will compare those elements and it must return: * * - 1, if the first element must be before the second element. * - -1, if the second element must be before the first element. * - 0, if the current situation doesn't met any of the two situations above. In this case both elements * can be evaluated as they had the same value. For example, in an array list of numbers, when you are * trying to apply a lineal sorting (ascending/descending) in a array list of numbers, if the array sorting * function finds two elements with the value 3 they should be evaluated returning 0, since both values are * the same. * * IMPORTANT NOTE: for a correct performance the sent parameter must return at least two of the values * listed above, if it doesn't the function can produce an infinite loop and thus an error. * @return {boolean} */ // sort : function (compFunction) { // var compFunction = compFunction || function(a, b) { // if(a < b) { // return 1; // } else if(a > b) { // return -1; // } else { // return 0; // } // }, swap = function (items, firstIndex, secondIndex){ // var temp = items[firstIndex]; // items[firstIndex] = items[secondIndex]; // items[secondIndex] = temp; // }, partition = function(items, left, right) { // var pivot = items[Math.floor((right + left) / 2)], // i = left, // j = right; // while (i <= j) { // while (compFunction(items[i], pivot) > 0) { // i++; // } // while (compFunction(items[j], pivot) < 0) { // j--; // } // if (i <= j) { // swap(items, i, j); // i++; // j--; // } // } // return i; // }, quickSort = function (items, left, right) { // var index; // if (items.length > 1) { // index = partition(items, left, right); // if (left < index - 1) { // quickSort(items, left, index - 1); // } // if (index < right) { // quickSort(items, index, right); // } // } // return items; // }; // // return quickSort(elements, 0, size - 1); // }, sort: function (compFunction) { var returnValue = false; if (compFunction) { elements.sort(compFunction); returnValue = true; } return returnValue; }, /** * Returns the list as an array * @return {Array} */ asArray: function () { return elements.slice(0); }, /** * Swaps the position of two elements * @chainable */ swap: function (index1, index2) { var aux; if (index1 < size && index1 >= 0 && index2 < size && index2 >= 0) { aux = elements[index1]; elements[index1] = elements[index2]; elements[index2] = aux; } return this; }, /** * Returns the first element of the list * @return {Object} */ getFirst: function () { return elements[0]; }, /** * Returns the last element of the list * @return {Object} */ getLast: function () { return elements[size - 1]; }, /** * Returns the last element of the list and deletes it from the list * @return {Object} */ popLast: function () { var lastElement; size -= 1; lastElement = elements[size]; elements.splice(size, 1); return lastElement; }, /** * Returns an array with the objects that determine the minimum size * the container should have * The array values are in this order TOP, RIGHT, BOTTOM AND LEFT * @return {Array} */ getDimensionLimit: function () { var result = [100000, -1, -1, 100000], objects = [undefined, undefined, undefined, undefined]; //number of pixels we want the inner shapes to be //apart from the border for (i = 0; i < size; i += 1) { if (result[0] > elements[i].y) { result[0] = elements[i].y; objects[0] = elements[i]; } if (result[1] < elements[i].x + elements[i].width) { result[1] = elements[i].x + elements[i].width; objects[1] = elements[i]; } if (result[2] < elements[i].y + elements[i].height) { result[2] = elements[i].y + elements[i].height; objects[2] = elements[i]; } if (result[3] > elements[i].x) { result[3] = elements[i].x; objects[3] = elements[i]; } } return result; }, /** * Clears the content of the arrayList * @chainable */ clear: function () { if (size !== 0) { elements = []; size = 0; } return this; }, /** * Sets the elements for the object. * @param {Array|null} items Array with the items to set. * @chainable */ set: function (items) { if (!(items === null || jQuery.isArray(items))) { throw new Error("set(): The parameter must be an array or null."); } elements = (items && items.slice(0)) || []; size = elements.length; return this; } }; }; PMUI.extendNamespace('PMUI.util.ArrayList', ArrayList); if (typeof exports !== "undefined") { module.exports = ArrayList; } }()); (function () { /** * @class PMUI.util.Style * Class that represent the style of a an object. * * // i.e * // Let's assume that 'shape' is a CustomShape * var style = new Style({ * cssClasses: [ * 'sprite-class', 'marker-class', ... * ], * cssProperties: { * border: 1px solid black, * background-color: grey, * ... * }, * belongsTo: shape * }) * * @constructor Creates a new instance of this class * @param {Object} options * @cfg {Array} [cssClasses=[]] the classes that `this.belongsTo` has * @cfg {Object} [cssProperties={}] the css properties that `this.belongsTo` has * @cfg {Object} [belongsTo=null] a pointer to the owner of this instance */ var Style = function (options) { /** * JSON Object used to map each of the css properties of the object, * this object has the same syntax as the object passed to jQuery.css() * cssProperties: { * background-color: [value], * border: [value], * ... * } * @property {Object} */ this.cssProperties = null; /** * Array of all the classes of this object * cssClasses = [ * 'class_1', * 'class_2', * ... * ] * @property {Array} */ this.cssClasses = null; /** * Pointer to the object to whom this style belongs to * @property {Object} */ this.belongsTo = null; Style.prototype.initObject.call(this, options); }; /** * The type of this class * @property {String} */ Style.prototype.type = "Style"; /** * Constant for the max z-index * @property {number} [MAX_ZINDEX=100] */ Style.MAX_ZINDEX = 100; /** * Instance initializer which uses options to extend the config options to * initialize the instance * @private * @param {Object} options */ Style.prototype.initObject = function (options) { var defaults = { cssClasses: [], cssProperties: {}, belongsTo: null }; jQuery.extend(true, defaults, options); this.cssClasses = defaults.cssClasses; this.cssProperties = defaults.cssProperties; this.belongsTo = defaults.belongsTo; }; /** * Applies cssProperties and cssClasses to `this.belongsTo` * @chainable */ Style.prototype.applyStyle = function () { var i, t, class_i; if (!this.belongsTo.html) { throw new Error("applyStyle(): can't apply style to an" + " object with no html."); } // apply the cssProperties jQuery(this.belongsTo.html).css(this.cssProperties); //adding default classes t = this.belongsTo.type.toLowerCase(); if (this.cssClasses.indexOf('pmui-' + t) === -1) { this.cssClasses.unshift('pmui-' + t); } if (this.cssClasses.indexOf('pmui') === -1) { this.cssClasses.unshift('pmui'); } // apply saved classes for (i = 0; i < this.cssClasses.length; i += 1) { class_i = this.cssClasses[i]; if (!$(this.belongsTo.html).hasClass(class_i)) { jQuery(this.belongsTo.html).addClass(class_i); } } return this; }; Style.prototype.unapplyStyle = function () { var t, property; if (!this.belongsTo.html) { throw new Error("unapplyStyle(): can't unapply style to an object with no html."); } t = this.belongsTo.type.toLowerCase(); jQuery(this.belongsTo.html).removeClass("pmui-" + t); for (property in this.cssProperties) { jQuery(this.belongsTo.html).css(property, ""); } }; /** * Extends the property `cssProperties` with a new object and also applies those new properties * @param {Object} properties * @chainable */ Style.prototype.addProperties = function (properties) { jQuery.extend(true, this.cssProperties, properties); jQuery(this.belongsTo && this.belongsTo.html).css(properties); return this; }; /** * Gets a property from `this.cssProperties` using jQuery or `window.getComputedStyle()` * @param {String} property * @return {String} */ Style.prototype.getProperty = function (property) { return this.cssProperties[property] || jQuery(this.belongsTo.html).css(property) || (this.belongsTo.html && window.getComputedStyle(this.belongsTo.html, null) .getProper