processmaker-builder
Version:
The gulp task runner for ProcessMaker building
1,494 lines (1,391 loc) • 1.77 MB
JavaScript
/**
* @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, '&');
s = s.replace(/\"/g, '"');
s = s.replace(/</g, '<');
s = s.replace(/>/g, '>');
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