UNPKG

processmaker-builder

Version:

The gulp task runner for ProcessMaker building

1,494 lines (1,398 loc) 1.72 MB
/** * @class PMUI * Base class PMUI * @singleton */ var PMUI.util.PMUI = {}; PMUI.version = '0.1.1'; PMUI.isCtrl = false; PMUI.isShift = false; PMUI.activeCanvas = null; PMUI.currentContextMenu = null; $(document).keydown(function (e) { if (PMUI.activeCanvas) { 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(); PMUI.activeCanvas.moveElements(PMUI.activeCanvas, 'LEFT'); } break; case 38: // Top if (!PMUI.activeCanvas.currentLabel) { e.preventDefault(); PMUI.activeCanvas.moveElements(PMUI.activeCanvas, 'TOP'); } break; case 39: // Right if (!PMUI.activeCanvas.currentLabel) { e.preventDefault(); PMUI.activeCanvas.moveElements(PMUI.activeCanvas, 'RIGHT'); } break; case 40: // Bottom if (!PMUI.activeCanvas.currentLabel) { e.preventDefault(); 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; 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]) { //console.log("PMUI.extendNamespace(): Warning! overriding the class '" + pathArray.join('.') + "'"); } 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.point.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++) { 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; 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"); } }; 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); }, /** * 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 () { if (!this.belongsTo.html) { throw new Error("applyStyle(): can't apply style to an" + " object with no html."); } var i, t, class_i; // 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 i, 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) .getPropertyValue(property)) || ""; }; /** * Returns all the style's css properties set explicitly. * @return {Object} An object literal with the properties. */ Style.prototype.getProperties = function() { return this.cssProperties; }; /** * Removes ´properties´ from the ´this.cssProperties´, also disables those properties from * the HTMLElement * @param {Array} properties An array in which each element is th name of the cssProperty to be removed. * @chainable */ Style.prototype.removeProperties = function (properties) { var property, i; for (i = 0; i < properties.length; i += 1) { property = properties[i]; if (this.cssProperties.hasOwnProperty(property)) { // JS Code Convention jQuery(this.belongsTo.html).css(property, ""); // reset inline style delete this.cssProperties[property]; } } return this; }; /** * Removes all properties from the object. * @chainable */ Style.prototype.removeAllProperties = function() { var key; if(this.belongsTo) { for(key in this.cssProperties) { jQuery(this.belongsTo.html).css(key, ""); } } this.cssProperties = {}; return this; }; /** * Adds new classes to ´this.cssClasses´ array * @param {Array} cssClasses * @chainable */ Style.prototype.addClasses = function (cssClasses) { var i, cssClass; if (cssClasses && cssClasses instanceof Array) { for (i = 0; i < cssClasses.length; i += 1) { cssClass = cssClasses[i]; if (typeof cssClass === "string") { if (this.cssClasses.indexOf(cssClass) === -1) { this.cssClasses.push(cssClass); jQuery(this.belongsTo && this.belongsTo.html).addClass(cssClass); } } else { throw new Error("addClasses(): array element is not of type string"); } } } else { throw new Error("addClasses(): parameter must be of type Array"); } return this; }; /** * Removes classes from ´this.cssClasses´ array, also removes those classes from * the HTMLElement * @param {Array} cssClasses * @chainable */ Style.prototype.removeClasses = function (cssClasses) { var i, index, cssClass; if (cssClasses && cssClasses instanceof Array) { for (i = 0; i < cssClasses.length; i += 1) { cssClass = cssClasses[i]; if (typeof cssClass === "string") { index = this.cssClasses.indexOf(cssClass); if (index !== -1) { jQuery(this.belongsTo.html).removeClass(this.cssClasses[index]); this.cssClasses.splice(index, 1); } } else { throw new Error("removeClasses(): array element is not of " + "type string"); } } } else { throw new Error("removeClasses(): parameter must be of type Array"); } return this; }; /** * Removes all the classes from ´this.cssClasses´ array * @param {Array} cssClasses * @chainable */ Style.prototype.removeAllClasses = function () { while(this.cssClasses.length) { jQuery(this.belongsTo && this.belongsTo.html).removeClass(this.cssClasses.pop()); } return this; }; /** * Checks if the class is a class stored in ´this.cssClasses´ * @param cssClass * @return {boolean} */ Style.prototype.containsClass = function (cssClass) { return this.cssClasses.indexOf(cssClass) !== -1; }; /** * Returns an array with all the classes of ´this.belongsTo´ * @return {Array} */ Style.prototype.getClasses = function () { return this.cssClasses.slice(0); }; /** * Clears all the css properties and classes. * @chainable */ Style.prototype.clear = function() { return this.removeAllClasses().removeAllProperties(); } /** * Serializes this instance * @return {Object} * @return {Array} return.cssClasses */ Style.prototype.stringify = function () { return { cssClasses: this.cssClasses // cssProperties: this.cssProperties }; }; // Declarations created to instantiate in NodeJS environment if (typeof exports !== "undefined") { module.exports = Style; } PMUI.extendNamespace('PMUI.util.Style', Style); }()); (function () { /** * @class PMUI.util.Factory * This class encapsulate the way to construct object using the product definition inside * * @constructor * This method creates a new instance of this object * @param {Object} settings Constructor setiings */ var Factory = function (settings) { /** * Defines the products can be make by the factory * @type {Object} */ this.products = null; /** * Defines the default product to make * @type {String} */ this.defaultProduct = null; Factory.prototype.init.call(this, settings); }; /** * Defines the object type * @type {String} */ Factory.prototype.type = "Factory"; /** * Defines the object family * @type {String} */ Factory.prototype.family = "Factory"; /** * Initializes the object with the default values * @param {Object} options Contructor options */ Factory.prototype.init = function (options) { var defaults; if (!options) { options = {}; } defaults = { defaultProduct: options.defaultProduct || "element", products: options.products || {"element": PMUI.core.Element} }; this.setDefaultProduct(defaults.defaultProduct) .setProducts(defaults.products); }; /** * Sets the default product property * @param {String} def Default value */ Factory.prototype.setDefaultProduct = function (def) { this.defaultProduct = def; return this; }; /** * Sets the product object * @param {Object} products Products object */ Factory.prototype.setProducts = function (products) { this.products = products; return this; }; /** * Removes a product from the factory. * @param {String|Object} product The product to be removed, it can be: * * - a string: the product referenced with that pmType will be removed from factory. * - a object: the constructor, all the products with that constructor will be removed. * @return {[type]} [description] */ Factory.prototype.removeProduct = function(product) { var key, products = this.products; if(typeof product === 'string') { delete products[product]; } else { for(key in p