Files
luos/workflow/public_html/lib/mafe/mafe.min.js
2025-04-06 22:54:52 +00:00

46082 lines
1.6 MiB

/**
* configure and extend classes and prototypes similar to inheritance in
* another languages. The method detects if we trying to extend a method of an object
* or a function inserted into a prototype.
* @param {String|Object} classObj contains the value of the class that we want to take an method for modifying
* @param {Sting} method the name of the function that we will be modified or overwritten
* @param {function} additionalFunc contains a function with the new code or the additional code
* for modified the original function.
*
* @return {[type]} [returns the value of the function modified, with the new functionality in this context.]
*/
var PMExtend = function (classObj, method, additionalFunc) {
var originalFunc;
if (classObj.prototype !== undefined) {
originalFunc = classObj.prototype[method];
if (originalFunc !== undefined && typeof originalFunc === 'function') {
return function () {
var returnVal = originalFunc.apply(this, arguments);
if (returnVal) {
returnVal = additionalFunc.apply(this, [returnVal].concat(arguments));
} else {
additionalFunc.apply(this, arguments);
}
return returnVal;
};
} else {
//You need to implement a catch on a higher level or at the plugin
throw new Error("Cannot extend method " + method + " in Class " + classObj.name);
}
} else {
originalFunc = classObj[method];
if (originalFunc !== undefined && typeof originalFunc === 'function') {
return function () {
var res;
res = originalFunc.apply(this, arguments);
res = additionalFunc.apply(this, [res].concat(arguments));
return res;
};
} else {
//You need to implement a catch on a higher level or at the plugin
throw new Error("Cannot extend method " + method + " in Class " + classObj.name);
}
}
};
/**
* @license
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modern -o ./dist/lodash.js`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
;(function() {
/** Used as a safe reference for `undefined` in pre ES5 environments */
var undefined;
/** Used to pool arrays and objects used internally */
var arrayPool = [],
objectPool = [];
/** Used to generate unique IDs */
var idCounter = 0;
/** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
var keyPrefix = +new Date + '';
/** Used as the size when optimizations are enabled for large arrays */
var largeArraySize = 75;
/** Used as the max size of the `arrayPool` and `objectPool` */
var maxPoolSize = 40;
/** Used to detect and test whitespace */
var whitespace = (
// whitespace
' \t\x0B\f\xA0\ufeff' +
// line terminators
'\n\r\u2028\u2029' +
// unicode category "Zs" space separators
'\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
);
/** Used to match empty string literals in compiled template source */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
/**
* Used to match ES6 template delimiters
* http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to match regexp flags from their coerced string values */
var reFlags = /\w*$/;
/** Used to detected named functions */
var reFuncName = /^\s*function[ \n\r\t]+\w/;
/** Used to match "interpolate" template delimiters */
var reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to match leading whitespace and zeros to be removed */
var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
/** Used to ensure capturing order of template delimiters */
var reNoMatch = /($^)/;
/** Used to detect functions containing a `this` reference */
var reThis = /\bthis\b/;
/** Used to match unescaped characters in compiled string literals */
var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
/** Used to assign default `context` object properties */
var contextProps = [
'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
'parseInt', 'setTimeout'
];
/** Used to make template sourceURLs easier to identify */
var templateCounter = 0;
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
boolClass = '[object Boolean]',
dateClass = '[object Date]',
funcClass = '[object Function]',
numberClass = '[object Number]',
objectClass = '[object Object]',
regexpClass = '[object RegExp]',
stringClass = '[object String]';
/** Used to identify object classifications that `_.clone` supports */
var cloneableClasses = {};
cloneableClasses[funcClass] = false;
cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
cloneableClasses[boolClass] = cloneableClasses[dateClass] =
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
/** Used as an internal `_.debounce` options object */
var debounceOptions = {
'leading': false,
'maxWait': 0,
'trailing': false
};
/** Used as the property descriptor for `__bindData__` */
var descriptor = {
'configurable': false,
'enumerable': false,
'value': null,
'writable': false
};
/** Used to determine if values are of the language type Object */
var objectTypes = {
'boolean': false,
'function': true,
'object': true,
'number': false,
'string': false,
'undefined': false
};
/** Used to escape characters for inclusion in compiled string literals */
var stringEscapes = {
'\\': '\\',
"'": "'",
'\n': 'n',
'\r': 'r',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
/** Used as a reference to the global object */
var root = (objectTypes[typeof window] && window) || this;
/** Detect free variable `exports` */
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
/** Detect free variable `module` */
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
/** Detect the popular CommonJS extension `module.exports` */
var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
/** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
var freeGlobal = objectTypes[typeof global] && global;
if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
root = freeGlobal;
}
/*--------------------------------------------------------------------------*/
/**
* The base implementation of `_.indexOf` without support for binary searches
* or `fromIndex` constraints.
*
* @private
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {number} Returns the index of the matched value or `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* An implementation of `_.contains` for cache objects that mimics the return
* signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
*
* @private
* @param {Object} cache The cache object to inspect.
* @param {*} value The value to search for.
* @returns {number} Returns `0` if `value` is found, else `-1`.
*/
function cacheIndexOf(cache, value) {
var type = typeof value;
cache = cache.cache;
if (type == 'boolean' || value == null) {
return cache[value] ? 0 : -1;
}
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value;
cache = (cache = cache[type]) && cache[key];
return type == 'object'
? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
: (cache ? 0 : -1);
}
/**
* Adds a given value to the corresponding cache object.
*
* @private
* @param {*} value The value to add to the cache.
*/
function cachePush(value) {
var cache = this.cache,
type = typeof value;
if (type == 'boolean' || value == null) {
cache[value] = true;
} else {
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value,
typeCache = cache[type] || (cache[type] = {});
if (type == 'object') {
(typeCache[key] || (typeCache[key] = [])).push(value);
} else {
typeCache[key] = true;
}
}
}
/**
* Used by `_.max` and `_.min` as the default callback when a given
* collection is a string value.
*
* @private
* @param {string} value The character to inspect.
* @returns {number} Returns the code unit of given character.
*/
function charAtCallback(value) {
return value.charCodeAt(0);
}
/**
* Used by `sortBy` to compare transformed `collection` elements, stable sorting
* them in ascending order.
*
* @private
* @param {Object} a The object to compare to `b`.
* @param {Object} b The object to compare to `a`.
* @returns {number} Returns the sort order indicator of `1` or `-1`.
*/
function compareAscending(a, b) {
var ac = a.criteria,
bc = b.criteria,
index = -1,
length = ac.length;
while (++index < length) {
var value = ac[index],
other = bc[index];
if (value !== other) {
if (value > other || typeof value == 'undefined') {
return 1;
}
if (value < other || typeof other == 'undefined') {
return -1;
}
}
}
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
// that causes it, under certain circumstances, to return the same value for
// `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
//
// This also ensures a stable sort in V8 and other engines.
// See http://code.google.com/p/v8/issues/detail?id=90
return a.index - b.index;
}
/**
* Creates a cache object to optimize linear searches of large arrays.
*
* @private
* @param {Array} [array=[]] The array to search.
* @returns {null|Object} Returns the cache object or `null` if caching should not be used.
*/
function createCache(array) {
var index = -1,
length = array.length,
first = array[0],
mid = array[(length / 2) | 0],
last = array[length - 1];
if (first && typeof first == 'object' &&
mid && typeof mid == 'object' && last && typeof last == 'object') {
return false;
}
var cache = getObject();
cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
var result = getObject();
result.array = array;
result.cache = cache;
result.push = cachePush;
while (++index < length) {
result.push(array[index]);
}
return result;
}
/**
* Used by `template` to escape characters for inclusion in compiled
* string literals.
*
* @private
* @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeStringChar(match) {
return '\\' + stringEscapes[match];
}
/**
* Gets an array from the array pool or creates a new one if the pool is empty.
*
* @private
* @returns {Array} The array from the pool.
*/
function getArray() {
return arrayPool.pop() || [];
}
/**
* Gets an object from the object pool or creates a new one if the pool is empty.
*
* @private
* @returns {Object} The object from the pool.
*/
function getObject() {
return objectPool.pop() || {
'array': null,
'cache': null,
'criteria': null,
'false': false,
'index': 0,
'null': false,
'number': null,
'object': null,
'push': null,
'string': null,
'true': false,
'undefined': false,
'value': null
};
}
/**
* Releases the given array back to the array pool.
*
* @private
* @param {Array} [array] The array to release.
*/
function releaseArray(array) {
array.length = 0;
if (arrayPool.length < maxPoolSize) {
arrayPool.push(array);
}
}
/**
* Releases the given object back to the object pool.
*
* @private
* @param {Object} [object] The object to release.
*/
function releaseObject(object) {
var cache = object.cache;
if (cache) {
releaseObject(cache);
}
object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
if (objectPool.length < maxPoolSize) {
objectPool.push(object);
}
}
/**
* Slices the `collection` from the `start` index up to, but not including,
* the `end` index.
*
* Note: This function is used instead of `Array#slice` to support node lists
* in IE < 9 and to ensure dense arrays are returned.
*
* @private
* @param {Array|Object|string} collection The collection to slice.
* @param {number} start The start index.
* @param {number} end The end index.
* @returns {Array} Returns the new array.
*/
function slice(array, start, end) {
start || (start = 0);
if (typeof end == 'undefined') {
end = array ? array.length : 0;
}
var index = -1,
length = end - start || 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = array[start + index];
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Create a new `lodash` function using the given context object.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} [context=root] The context object.
* @returns {Function} Returns the `lodash` function.
*/
function runInContext(context) {
// Avoid issues with some ES3 environments that attempt to use values, named
// after built-in constructors like `Object`, for the creation of literals.
// ES5 clears this up by stating that literals must use built-in constructors.
// See http://es5.github.io/#x11.1.5.
context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
/** Native constructor references */
var Array = context.Array,
Boolean = context.Boolean,
Date = context.Date,
Function = context.Function,
Math = context.Math,
Number = context.Number,
Object = context.Object,
RegExp = context.RegExp,
String = context.String,
TypeError = context.TypeError;
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to restore the original `_` reference in `noConflict` */
var oldDash = context._;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Used to detect if a method is native */
var reNative = RegExp('^' +
String(toString)
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/toString| for [^\]]+/g, '.*?') + '$'
);
/** Native method shortcuts */
var ceil = Math.ceil,
clearTimeout = context.clearTimeout,
floor = Math.floor,
fnToString = Function.prototype.toString,
getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
hasOwnProperty = objectProto.hasOwnProperty,
push = arrayRef.push,
setTimeout = context.setTimeout,
splice = arrayRef.splice,
unshift = arrayRef.unshift;
/** Used to set meta data on functions */
var defineProperty = (function() {
// IE 8 only accepts DOM elements
try {
var o = {},
func = isNative(func = Object.defineProperty) && func,
result = func(o, o, o) && func;
} catch(e) { }
return result;
}());
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
nativeIsFinite = context.isFinite,
nativeIsNaN = context.isNaN,
nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
nativeMax = Math.max,
nativeMin = Math.min,
nativeParseInt = context.parseInt,
nativeRandom = Math.random;
/** Used to lookup a built-in constructor by [[Class]] */
var ctorByClass = {};
ctorByClass[arrayClass] = Array;
ctorByClass[boolClass] = Boolean;
ctorByClass[dateClass] = Date;
ctorByClass[funcClass] = Function;
ctorByClass[objectClass] = Object;
ctorByClass[numberClass] = Number;
ctorByClass[regexpClass] = RegExp;
ctorByClass[stringClass] = String;
/*--------------------------------------------------------------------------*/
/**
* Creates a `lodash` object which wraps the given value to enable intuitive
* method chaining.
*
* In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
* and `unshift`
*
* Chaining is supported in custom builds as long as the `value` method is
* implicitly or explicitly included in the build.
*
* The chainable wrapper functions are:
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
* `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
* `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
* `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
* `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
* `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
* `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
* `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
* `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
* `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
* and `zip`
*
* The non-chainable wrapper functions are:
* `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
* `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
* `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
* `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
* `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
* `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
* `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
* `template`, `unescape`, `uniqueId`, and `value`
*
* The wrapper functions `first` and `last` return wrapped values when `n` is
* provided, otherwise they return unwrapped values.
*
* Explicit chaining can be enabled by using the `_.chain` method.
*
* @name _
* @constructor
* @category Chaining
* @param {*} value The value to wrap in a `lodash` instance.
* @returns {Object} Returns a `lodash` instance.
* @example
*
* var wrapped = _([1, 2, 3]);
*
* // returns an unwrapped value
* wrapped.reduce(function(sum, num) {
* return sum + num;
* });
* // => 6
*
* // returns a wrapped value
* var squares = wrapped.map(function(num) {
* return num * num;
* });
*
* _.isArray(squares);
* // => false
*
* _.isArray(squares.value());
* // => true
*/
function lodash(value) {
// don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
? value
: new lodashWrapper(value);
}
/**
* A fast path for creating `lodash` wrapper objects.
*
* @private
* @param {*} value The value to wrap in a `lodash` instance.
* @param {boolean} chainAll A flag to enable chaining for all methods
* @returns {Object} Returns a `lodash` instance.
*/
function lodashWrapper(value, chainAll) {
this.__chain__ = !!chainAll;
this.__wrapped__ = value;
}
// ensure `new lodashWrapper` is an instance of `lodash`
lodashWrapper.prototype = lodash.prototype;
/**
* An object used to flag environments features.
*
* @static
* @memberOf _
* @type Object
*/
var support = lodash.support = {};
/**
* Detect if functions can be decompiled by `Function#toString`
* (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
*
* @memberOf _.support
* @type boolean
*/
support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
/**
* Detect if `Function#name` is supported (all but IE).
*
* @memberOf _.support
* @type boolean
*/
support.funcNames = typeof Function.name == 'string';
/**
* By default, the template delimiters used by Lo-Dash are similar to those in
* embedded Ruby (ERB). Change the following template settings to use alternative
* delimiters.
*
* @static
* @memberOf _
* @type Object
*/
lodash.templateSettings = {
/**
* Used to detect `data` property values to be HTML-escaped.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'escape': /<%-([\s\S]+?)%>/g,
/**
* Used to detect code to be evaluated.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'evaluate': /<%([\s\S]+?)%>/g,
/**
* Used to detect `data` property values to inject.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'interpolate': reInterpolate,
/**
* Used to reference the data object in the template text.
*
* @memberOf _.templateSettings
* @type string
*/
'variable': '',
/**
* Used to import variables into the compiled template.
*
* @memberOf _.templateSettings
* @type Object
*/
'imports': {
/**
* A reference to the `lodash` function.
*
* @memberOf _.templateSettings.imports
* @type Function
*/
'_': lodash
}
};
/*--------------------------------------------------------------------------*/
/**
* The base implementation of `_.bind` that creates the bound function and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new bound function.
*/
function baseBind(bindData) {
var func = bindData[0],
partialArgs = bindData[2],
thisArg = bindData[4];
function bound() {
// `Function#bind` spec
// http://es5.github.io/#x15.3.4.5
if (partialArgs) {
// avoid `arguments` object deoptimizations by using `slice` instead
// of `Array.prototype.slice.call` and not assigning `arguments` to a
// variable as a ternary expression
var args = slice(partialArgs);
push.apply(args, arguments);
}
// mimic the constructor's `return` behavior
// http://es5.github.io/#x13.2.2
if (this instanceof bound) {
// ensure `new bound` is an instance of `func`
var thisBinding = baseCreate(func.prototype),
result = func.apply(thisBinding, args || arguments);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisArg, args || arguments);
}
setBindData(bound, bindData);
return bound;
}
/**
* The base implementation of `_.clone` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {*} value The value to clone.
* @param {boolean} [isDeep=false] Specify a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates clones with source counterparts.
* @returns {*} Returns the cloned value.
*/
function baseClone(value, isDeep, callback, stackA, stackB) {
if (callback) {
var result = callback(value);
if (typeof result != 'undefined') {
return result;
}
}
// inspect [[Class]]
var isObj = isObject(value);
if (isObj) {
var className = toString.call(value);
if (!cloneableClasses[className]) {
return value;
}
var ctor = ctorByClass[className];
switch (className) {
case boolClass:
case dateClass:
return new ctor(+value);
case numberClass:
case stringClass:
return new ctor(value);
case regexpClass:
result = ctor(value.source, reFlags.exec(value));
result.lastIndex = value.lastIndex;
return result;
}
} else {
return value;
}
var isArr = isArray(value);
if (isDeep) {
// check for circular references and return corresponding clone
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == value) {
return stackB[length];
}
}
result = isArr ? ctor(value.length) : {};
}
else {
result = isArr ? slice(value) : assign({}, value);
}
// add array properties assigned by `RegExp#exec`
if (isArr) {
if (hasOwnProperty.call(value, 'index')) {
result.index = value.index;
}
if (hasOwnProperty.call(value, 'input')) {
result.input = value.input;
}
}
// exit for shallow clone
if (!isDeep) {
return result;
}
// add the source value to the stack of traversed objects
// and associate it with its clone
stackA.push(value);
stackB.push(result);
// recursively populate clone (susceptible to call stack limits)
(isArr ? forEach : forOwn)(value, function(objValue, key) {
result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
});
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* The base implementation of `_.create` without support for assigning
* properties to the created object.
*
* @private
* @param {Object} prototype The object to inherit from.
* @returns {Object} Returns the new object.
*/
function baseCreate(prototype, properties) {
return isObject(prototype) ? nativeCreate(prototype) : {};
}
// fallback for browsers without `Object.create`
if (!nativeCreate) {
baseCreate = (function() {
function Object() {}
return function(prototype) {
if (isObject(prototype)) {
Object.prototype = prototype;
var result = new Object;
Object.prototype = null;
}
return result || context.Object();
};
}());
}
/**
* The base implementation of `_.createCallback` without support for creating
* "_.pluck" or "_.where" style callbacks.
*
* @private
* @param {*} [func=identity] The value to convert to a callback.
* @param {*} [thisArg] The `this` binding of the created callback.
* @param {number} [argCount] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
*/
function baseCreateCallback(func, thisArg, argCount) {
if (typeof func != 'function') {
return identity;
}
// exit early for no `thisArg` or already bound by `Function#bind`
if (typeof thisArg == 'undefined' || !('prototype' in func)) {
return func;
}
var bindData = func.__bindData__;
if (typeof bindData == 'undefined') {
if (support.funcNames) {
bindData = !func.name;
}
bindData = bindData || !support.funcDecomp;
if (!bindData) {
var source = fnToString.call(func);
if (!support.funcNames) {
bindData = !reFuncName.test(source);
}
if (!bindData) {
// checks if `func` references the `this` keyword and stores the result
bindData = reThis.test(source);
setBindData(func, bindData);
}
}
}
// exit early if there are no `this` references or `func` is bound
if (bindData === false || (bindData !== true && bindData[1] & 1)) {
return func;
}
switch (argCount) {
case 1: return function(value) {
return func.call(thisArg, value);
};
case 2: return function(a, b) {
return func.call(thisArg, a, b);
};
case 3: return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
}
return bind(func, thisArg);
}
/**
* The base implementation of `createWrapper` that creates the wrapper and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new function.
*/
function baseCreateWrapper(bindData) {
var func = bindData[0],
bitmask = bindData[1],
partialArgs = bindData[2],
partialRightArgs = bindData[3],
thisArg = bindData[4],
arity = bindData[5];
var isBind = bitmask & 1,
isBindKey = bitmask & 2,
isCurry = bitmask & 4,
isCurryBound = bitmask & 8,
key = func;
function bound() {
var thisBinding = isBind ? thisArg : this;
if (partialArgs) {
var args = slice(partialArgs);
push.apply(args, arguments);
}
if (partialRightArgs || isCurry) {
args || (args = slice(arguments));
if (partialRightArgs) {
push.apply(args, partialRightArgs);
}
if (isCurry && args.length < arity) {
bitmask |= 16 & ~32;
return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
}
}
args || (args = arguments);
if (isBindKey) {
func = thisBinding[key];
}
if (this instanceof bound) {
thisBinding = baseCreate(func.prototype);
var result = func.apply(thisBinding, args);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisBinding, args);
}
setBindData(bound, bindData);
return bound;
}
/**
* The base implementation of `_.difference` that accepts a single array
* of values to exclude.
*
* @private
* @param {Array} array The array to process.
* @param {Array} [values] The array of values to exclude.
* @returns {Array} Returns a new array of filtered values.
*/
function baseDifference(array, values) {
var index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
isLarge = length >= largeArraySize && indexOf === baseIndexOf,
result = [];
if (isLarge) {
var cache = createCache(values);
if (cache) {
indexOf = cacheIndexOf;
values = cache;
} else {
isLarge = false;
}
}
while (++index < length) {
var value = array[index];
if (indexOf(values, value) < 0) {
result.push(value);
}
}
if (isLarge) {
releaseObject(values);
}
return result;
}
/**
* The base implementation of `_.flatten` without support for callback
* shorthands or `thisArg` binding.
*
* @private
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
* @param {number} [fromIndex=0] The index to start from.
* @returns {Array} Returns a new flattened array.
*/
function baseFlatten(array, isShallow, isStrict, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value && typeof value == 'object' && typeof value.length == 'number'
&& (isArray(value) || isArguments(value))) {
// recursively flatten arrays (susceptible to call stack limits)
if (!isShallow) {
value = baseFlatten(value, isShallow, isStrict);
}
var valIndex = -1,
valLength = value.length,
resIndex = result.length;
result.length += valLength;
while (++valIndex < valLength) {
result[resIndex++] = value[valIndex];
}
} else if (!isStrict) {
result.push(value);
}
}
return result;
}
/**
* The base implementation of `_.isEqual`, without support for `thisArg` binding,
* that allows partial "_.where" style comparisons.
*
* @private
* @param {*} a The value to compare.
* @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
* @param {Array} [stackA=[]] Tracks traversed `a` objects.
* @param {Array} [stackB=[]] Tracks traversed `b` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
// used to indicate that when comparing objects, `a` has at least the properties of `b`
if (callback) {
var result = callback(a, b);
if (typeof result != 'undefined') {
return !!result;
}
}
// exit early for identical values
if (a === b) {
// treat `+0` vs. `-0` as not equal
return a !== 0 || (1 / a == 1 / b);
}
var type = typeof a,
otherType = typeof b;
// exit early for unlike primitive values
if (a === a &&
!(a && objectTypes[type]) &&
!(b && objectTypes[otherType])) {
return false;
}
// exit early for `null` and `undefined` avoiding ES3's Function#call behavior
// http://es5.github.io/#x15.3.4.4
if (a == null || b == null) {
return a === b;
}
// compare [[Class]] names
var className = toString.call(a),
otherClass = toString.call(b);
if (className == argsClass) {
className = objectClass;
}
if (otherClass == argsClass) {
otherClass = objectClass;
}
if (className != otherClass) {
return false;
}
switch (className) {
case boolClass:
case dateClass:
// coerce dates and booleans to numbers, dates to milliseconds and booleans
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal
return +a == +b;
case numberClass:
// treat `NaN` vs. `NaN` as equal
return (a != +a)
? b != +b
// but treat `+0` vs. `-0` as not equal
: (a == 0 ? (1 / a == 1 / b) : a == +b);
case regexpClass:
case stringClass:
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal
return a == String(b);
}
var isArr = className == arrayClass;
if (!isArr) {
// unwrap any `lodash` wrapped values
var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
bWrapped = hasOwnProperty.call(b, '__wrapped__');
if (aWrapped || bWrapped) {
return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
}
// exit for functions and DOM nodes
if (className != objectClass) {
return false;
}
// in older versions of Opera, `arguments` objects have `Array` constructors
var ctorA = a.constructor,
ctorB = b.constructor;
// non `Object` object instances with different constructors are not equal
if (ctorA != ctorB &&
!(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
('constructor' in a && 'constructor' in b)
) {
return false;
}
}
// assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1
// section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == a) {
return stackB[length] == b;
}
}
var size = 0;
result = true;
// add `a` and `b` to the stack of traversed objects
stackA.push(a);
stackB.push(b);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
// compare lengths to determine if a deep comparison is necessary
length = a.length;
size = b.length;
result = size == length;
if (result || isWhere) {
// deep compare the contents, ignoring non-numeric properties
while (size--) {
var index = length,
value = b[size];
if (isWhere) {
while (index--) {
if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
break;
}
}
} else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
break;
}
}
}
}
else {
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly
forIn(b, function(value, key, b) {
if (hasOwnProperty.call(b, key)) {
// count the number of properties.
size++;
// deep compare each property value.
return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
}
});
if (result && !isWhere) {
// ensure both objects have the same number of properties
forIn(a, function(value, key, a) {
if (hasOwnProperty.call(a, key)) {
// `size` will be `-1` if `a` has more properties than `b`
return (result = --size > -1);
}
});
}
}
stackA.pop();
stackB.pop();
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* The base implementation of `_.merge` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @param {Function} [callback] The function to customize merging properties.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates values with source counterparts.
*/
function baseMerge(object, source, callback, stackA, stackB) {
(isArray(source) ? forEach : forOwn)(source, function(source, key) {
var found,
isArr,
result = source,
value = object[key];
if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
// avoid merging previously merged cyclic sources
var stackLength = stackA.length;
while (stackLength--) {
if ((found = stackA[stackLength] == source)) {
value = stackB[stackLength];
break;
}
}
if (!found) {
var isShallow;
if (callback) {
result = callback(value, source);
if ((isShallow = typeof result != 'undefined')) {
value = result;
}
}
if (!isShallow) {
value = isArr
? (isArray(value) ? value : [])
: (isPlainObject(value) ? value : {});
}
// add `source` and associated `value` to the stack of traversed objects
stackA.push(source);
stackB.push(value);
// recursively merge objects and arrays (susceptible to call stack limits)
if (!isShallow) {
baseMerge(value, source, callback, stackA, stackB);
}
}
}
else {
if (callback) {
result = callback(value, source);
if (typeof result == 'undefined') {
result = source;
}
}
if (typeof result != 'undefined') {
value = result;
}
}
object[key] = value;
});
}
/**
* The base implementation of `_.random` without argument juggling or support
* for returning floating-point numbers.
*
* @private
* @param {number} min The minimum possible value.
* @param {number} max The maximum possible value.
* @returns {number} Returns a random number.
*/
function baseRandom(min, max) {
return min + floor(nativeRandom() * (max - min + 1));
}
/**
* The base implementation of `_.uniq` without support for callback shorthands
* or `thisArg` binding.
*
* @private
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function} [callback] The function called per iteration.
* @returns {Array} Returns a duplicate-value-free array.
*/
function baseUniq(array, isSorted, callback) {
var index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
result = [];
var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
seen = (callback || isLarge) ? getArray() : result;
if (isLarge) {
var cache = createCache(seen);
indexOf = cacheIndexOf;
seen = cache;
}
while (++index < length) {
var value = array[index],
computed = callback ? callback(value, index, array) : value;
if (isSorted
? !index || seen[seen.length - 1] !== computed
: indexOf(seen, computed) < 0
) {
if (callback || isLarge) {
seen.push(computed);
}
result.push(value);
}
}
if (isLarge) {
releaseArray(seen.array);
releaseObject(seen);
} else if (callback) {
releaseArray(seen);
}
return result;
}
/**
* Creates a function that aggregates a collection, creating an object composed
* of keys generated from the results of running each element of the collection
* through a callback. The given `setter` function sets the keys and values
* of the composed object.
*
* @private
* @param {Function} setter The setter function.
* @returns {Function} Returns the new aggregator function.
*/
function createAggregator(setter) {
return function(collection, callback, thisArg) {
var result = {};
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
setter(result, value, callback(value, index, collection), collection);
}
} else {
forOwn(collection, function(value, key, collection) {
setter(result, value, callback(value, key, collection), collection);
});
}
return result;
};
}
/**
* Creates a function that, when called, either curries or invokes `func`
* with an optional `this` binding and partially applied arguments.
*
* @private
* @param {Function|string} func The function or method name to reference.
* @param {number} bitmask The bitmask of method flags to compose.
* The bitmask may be composed of the following flags:
* 1 - `_.bind`
* 2 - `_.bindKey`
* 4 - `_.curry`
* 8 - `_.curry` (bound)
* 16 - `_.partial`
* 32 - `_.partialRight`
* @param {Array} [partialArgs] An array of arguments to prepend to those
* provided to the new function.
* @param {Array} [partialRightArgs] An array of arguments to append to those
* provided to the new function.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new function.
*/
function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
var isBind = bitmask & 1,
isBindKey = bitmask & 2,
isCurry = bitmask & 4,
isCurryBound = bitmask & 8,
isPartial = bitmask & 16,
isPartialRight = bitmask & 32;
if (!isBindKey && !isFunction(func)) {
throw new TypeError;
}
if (isPartial && !partialArgs.length) {
bitmask &= ~16;
isPartial = partialArgs = false;
}
if (isPartialRight && !partialRightArgs.length) {
bitmask &= ~32;
isPartialRight = partialRightArgs = false;
}
var bindData = func && func.__bindData__;
if (bindData && bindData !== true) {
// clone `bindData`
bindData = slice(bindData);
if (bindData[2]) {
bindData[2] = slice(bindData[2]);
}
if (bindData[3]) {
bindData[3] = slice(bindData[3]);
}
// set `thisBinding` is not previously bound
if (isBind && !(bindData[1] & 1)) {
bindData[4] = thisArg;
}
// set if previously bound but not currently (subsequent curried functions)
if (!isBind && bindData[1] & 1) {
bitmask |= 8;
}
// set curried arity if not yet set
if (isCurry && !(bindData[1] & 4)) {
bindData[5] = arity;
}
// append partial left arguments
if (isPartial) {
push.apply(bindData[2] || (bindData[2] = []), partialArgs);
}
// append partial right arguments
if (isPartialRight) {
unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
}
// merge flags
bindData[1] |= bitmask;
return createWrapper.apply(null, bindData);
}
// fast path for `_.bind`
var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
}
/**
* Used by `escape` to convert characters to HTML entities.
*
* @private
* @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeHtmlChar(match) {
return htmlEscapes[match];
}
/**
* Gets the appropriate "indexOf" function. If the `_.indexOf` method is
* customized, this method returns the custom method, otherwise it returns
* the `baseIndexOf` function.
*
* @private
* @returns {Function} Returns the "indexOf" function.
*/
function getIndexOf() {
var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
return result;
}
/**
* Checks if `value` is a native function.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
*/
function isNative(value) {
return typeof value == 'function' && reNative.test(value);
}
/**
* Sets `this` binding data on a given function.
*
* @private
* @param {Function} func The function to set data on.
* @param {Array} value The data array to set.
*/
var setBindData = !defineProperty ? noop : function(func, value) {
descriptor.value = value;
defineProperty(func, '__bindData__', descriptor);
};
/**
* A fallback implementation of `isPlainObject` which checks if a given value
* is an object created by the `Object` constructor, assuming objects created
* by the `Object` constructor have no inherited enumerable properties and that
* there are no `Object.prototype` extensions.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
*/
function shimIsPlainObject(value) {
var ctor,
result;
// avoid non Object objects, `arguments` objects, and DOM elements
if (!(value && toString.call(value) == objectClass) ||
(ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
return false;
}
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(value, key) {
result = key;
});
return typeof result == 'undefined' || hasOwnProperty.call(value, result);
}
/**
* Used by `unescape` to convert HTML entities to characters.
*
* @private
* @param {string} match The matched character to unescape.
* @returns {string} Returns the unescaped character.
*/
function unescapeHtmlChar(match) {
return htmlUnescapes[match];
}
/*--------------------------------------------------------------------------*/
/**
* Checks if `value` is an `arguments` object.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
* @example
*
* (function() { return _.isArguments(arguments); })(1, 2, 3);
* // => true
*
* _.isArguments([1, 2, 3]);
* // => false
*/
function isArguments(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == argsClass || false;
}
/**
* Checks if `value` is an array.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an array, else `false`.
* @example
*
* (function() { return _.isArray(arguments); })();
* // => false
*
* _.isArray([1, 2, 3]);
* // => true
*/
var isArray = nativeIsArray || function(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == arrayClass || false;
};
/**
* A fallback implementation of `Object.keys` which produces an array of the
* given object's own enumerable property names.
*
* @private
* @type Function
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
*/
var shimKeys = function(object) {
var index, iterable = object, result = [];
if (!iterable) return result;
if (!(objectTypes[typeof object])) return result;
for (index in iterable) {
if (hasOwnProperty.call(iterable, index)) {
result.push(index);
}
}
return result
};
/**
* Creates an array composed of the own enumerable property names of an object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
* @example
*
* _.keys({ 'one': 1, 'two': 2, 'three': 3 });
* // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
*/
var keys = !nativeKeys ? shimKeys : function(object) {
if (!isObject(object)) {
return [];
}
return nativeKeys(object);
};
/**
* Used to convert characters to HTML entities:
*
* Though the `>` character is escaped for symmetry, characters like `>` and `/`
* don't require escaping in HTML and have no special meaning unless they're part
* of a tag or an unquoted attribute value.
* http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
*/
var htmlEscapes = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
};
/** Used to convert HTML entities to characters */
var htmlUnescapes = invert(htmlEscapes);
/** Used to match HTML entities and HTML characters */
var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
/*--------------------------------------------------------------------------*/
/**
* Assigns own enumerable properties of source object(s) to the destination
* object. Subsequent sources will overwrite property assignments of previous
* sources. If a callback is provided it will be executed to produce the
* assigned values. The callback is bound to `thisArg` and invoked with two
* arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @type Function
* @alias extend
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize assigning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
* @example
*
* _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
* // => { 'name': 'fred', 'employer': 'slate' }
*
* var defaults = _.partialRight(_.assign, function(a, b) {
* return typeof a == 'undefined' ? b : a;
* });
*
* var object = { 'name': 'barney' };
* defaults(object, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
var assign = function(object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
callback = args[--argsLength];
}
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
}
}
}
return result
};
/**
* Creates a clone of `value`. If `isDeep` is `true` nested objects will also
* be cloned, otherwise they will be assigned by reference. If a callback
* is provided it will be executed to produce the cloned values. If the
* callback returns `undefined` cloning will be handled by the method instead.
* The callback is bound to `thisArg` and invoked with one argument; (value).
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to clone.
* @param {boolean} [isDeep=false] Specify a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the cloned value.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* var shallow = _.clone(characters);
* shallow[0] === characters[0];
* // => true
*
* var deep = _.clone(characters, true);
* deep[0] === characters[0];
* // => false
*
* _.mixin({
* 'clone': _.partialRight(_.clone, function(value) {
* return _.isElement(value) ? value.cloneNode(false) : undefined;
* })
* });
*
* var clone = _.clone(document.body);
* clone.childNodes.length;
* // => 0
*/
function clone(value, isDeep, callback, thisArg) {
// allows working with "Collections" methods without using their `index`
// and `collection` arguments for `isDeep` and `callback`
if (typeof isDeep != 'boolean' && isDeep != null) {
thisArg = callback;
callback = isDeep;
isDeep = false;
}
return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
}
/**
* Creates a deep clone of `value`. If a callback is provided it will be
* executed to produce the cloned values. If the callback returns `undefined`
* cloning will be handled by the method instead. The callback is bound to
* `thisArg` and invoked with one argument; (value).
*
* Note: This method is loosely based on the structured clone algorithm. Functions
* and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
* objects created by constructors other than `Object` are cloned to plain `Object` objects.
* See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the deep cloned value.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* var deep = _.cloneDeep(characters);
* deep[0] === characters[0];
* // => false
*
* var view = {
* 'label': 'docs',
* 'node': element
* };
*
* var clone = _.cloneDeep(view, function(value) {
* return _.isElement(value) ? value.cloneNode(true) : undefined;
* });
*
* clone.node == view.node;
* // => false
*/
function cloneDeep(value, callback, thisArg) {
return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
}
/**
* Creates an object that inherits from the given `prototype` object. If a
* `properties` object is provided its own enumerable properties are assigned
* to the created object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} prototype The object to inherit from.
* @param {Object} [properties] The properties to assign to the object.
* @returns {Object} Returns the new object.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* function Circle() {
* Shape.call(this);
* }
*
* Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
*
* var circle = new Circle;
* circle instanceof Circle;
* // => true
*
* circle instanceof Shape;
* // => true
*/
function create(prototype, properties) {
var result = baseCreate(prototype);
return properties ? assign(result, properties) : result;
}
/**
* Assigns own enumerable properties of source object(s) to the destination
* object for all destination properties that resolve to `undefined`. Once a
* property is set, additional defaults of the same property will be ignored.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param- {Object} [guard] Allows working with `_.reduce` without using its
* `key` and `object` arguments as sources.
* @returns {Object} Returns the destination object.
* @example
*
* var object = { 'name': 'barney' };
* _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
var defaults = function(object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
if (typeof result[index] == 'undefined') result[index] = iterable[index];
}
}
}
return result
};
/**
* This method is like `_.findIndex` except that it returns the key of the
* first element that passes the callback check, instead of the element itself.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per
* iteration. If a property name or object is provided it will be used to
* create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
* 'barney': { 'age': 36, 'blocked': false },
* 'fred': { 'age': 40, 'blocked': true },
* 'pebbles': { 'age': 1, 'blocked': false }
* };
*
* _.findKey(characters, function(chr) {
* return chr.age < 40;
* });
* // => 'barney' (property order is not guaranteed across environments)
*
* // using "_.where" callback shorthand
* _.findKey(characters, { 'age': 1 });
* // => 'pebbles'
*
* // using "_.pluck" callback shorthand
* _.findKey(characters, 'blocked');
* // => 'fred'
*/
function findKey(object, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
forOwn(object, function(value, key, object) {
if (callback(value, key, object)) {
result = key;
return false;
}
});
return result;
}
/**
* This method is like `_.findKey` except that it iterates over elements
* of a `collection` in the opposite order.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per
* iteration. If a property name or object is provided it will be used to
* create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
* 'barney': { 'age': 36, 'blocked': true },
* 'fred': { 'age': 40, 'blocked': false },
* 'pebbles': { 'age': 1, 'blocked': true }
* };
*
* _.findLastKey(characters, function(chr) {
* return chr.age < 40;
* });
* // => returns `pebbles`, assuming `_.findKey` returns `barney`
*
* // using "_.where" callback shorthand
* _.findLastKey(characters, { 'age': 40 });
* // => 'fred'
*
* // using "_.pluck" callback shorthand
* _.findLastKey(characters, 'blocked');
* // => 'pebbles'
*/
function findLastKey(object, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
forOwnRight(object, function(value, key, object) {
if (callback(value, key, object)) {
result = key;
return false;
}
});
return result;
}
/**
* Iterates over own and inherited enumerable properties of an object,
* executing the callback for each property. The callback is bound to `thisArg`
* and invoked with three arguments; (value, key, object). Callbacks may exit
* iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* Shape.prototype.move = function(x, y) {
* this.x += x;
* this.y += y;
* };
*
* _.forIn(new Shape, function(value, key) {
* console.log(key);
* });
* // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
*/
var forIn = function(collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
if (!iterable) return result;
if (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
for (index in iterable) {
if (callback(iterable[index], index, collection) === false) return result;
}
return result
};
/**
* This method is like `_.forIn` except that it iterates over elements
* of a `collection` in the opposite order.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* Shape.prototype.move = function(x, y) {
* this.x += x;
* this.y += y;
* };
*
* _.forInRight(new Shape, function(value, key) {
* console.log(key);
* });
* // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
*/
function forInRight(object, callback, thisArg) {
var pairs = [];
forIn(object, function(value, key) {
pairs.push(key, value);
});
var length = pairs.length;
callback = baseCreateCallback(callback, thisArg, 3);
while (length--) {
if (callback(pairs[length--], pairs[length], object) === false) {
break;
}
}
return object;
}
/**
* Iterates over own enumerable properties of an object, executing the callback
* for each property. The callback is bound to `thisArg` and invoked with three
* arguments; (value, key, object). Callbacks may exit iteration early by
* explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* console.log(key);
* });
* // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
*/
var forOwn = function(collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
if (!iterable) return result;
if (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
if (callback(iterable[index], index, collection) === false) return result;
}
return result
};
/**
* This method is like `_.forOwn` except that it iterates over elements
* of a `collection` in the opposite order.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* console.log(key);
* });
* // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
*/
function forOwnRight(object, callback, thisArg) {
var props = keys(object),
length = props.length;
callback = baseCreateCallback(callback, thisArg, 3);
while (length--) {
var key = props[length];
if (callback(object[key], key, object) === false) {
break;
}
}
return object;
}
/**
* Creates a sorted array of property names of all enumerable properties,
* own and inherited, of `object` that have function values.
*
* @static
* @memberOf _
* @alias methods
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names that have function values.
* @example
*
* _.functions(_);
* // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
*/
function functions(object) {
var result = [];
forIn(object, function(value, key) {
if (isFunction(value)) {
result.push(key);
}
});
return result.sort();
}
/**
* Checks if the specified property name exists as a direct property of `object`,
* instead of an inherited property.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @param {string} key The name of the property to check.
* @returns {boolean} Returns `true` if key is a direct property, else `false`.
* @example
*
* _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
* // => true
*/
function has(object, key) {
return object ? hasOwnProperty.call(object, key) : false;
}
/**
* Creates an object composed of the inverted keys and values of the given object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to invert.
* @returns {Object} Returns the created inverted object.
* @example
*
* _.invert({ 'first': 'fred', 'second': 'barney' });
* // => { 'fred': 'first', 'barney': 'second' }
*/
function invert(object) {
var index = -1,
props = keys(object),
length = props.length,
result = {};
while (++index < length) {
var key = props[index];
result[object[key]] = key;
}
return result;
}
/**
* Checks if `value` is a boolean value.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
* @example
*
* _.isBoolean(null);
* // => false
*/
function isBoolean(value) {
return value === true || value === false ||
value && typeof value == 'object' && toString.call(value) == boolClass || false;
}
/**
* Checks if `value` is a date.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a date, else `false`.
* @example
*
* _.isDate(new Date);
* // => true
*/
function isDate(value) {
return value && typeof value == 'object' && toString.call(value) == dateClass || false;
}
/**
* Checks if `value` is a DOM element.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
* @example
*
* _.isElement(document.body);
* // => true
*/
function isElement(value) {
return value && value.nodeType === 1 || false;
}
/**
* Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
* length of `0` and objects with no own enumerable properties are considered
* "empty".
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object|string} value The value to inspect.
* @returns {boolean} Returns `true` if the `value` is empty, else `false`.
* @example
*
* _.isEmpty([1, 2, 3]);
* // => false
*
* _.isEmpty({});
* // => true
*
* _.isEmpty('');
* // => true
*/
function isEmpty(value) {
var result = true;
if (!value) {
return result;
}
var className = toString.call(value),
length = value.length;
if ((className == arrayClass || className == stringClass || className == argsClass ) ||
(className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
return !length;
}
forOwn(value, function() {
return (result = false);
});
return result;
}
/**
* Performs a deep comparison between two values to determine if they are
* equivalent to each other. If a callback is provided it will be executed
* to compare values. If the callback returns `undefined` comparisons will
* be handled by the method instead. The callback is bound to `thisArg` and
* invoked with two arguments; (a, b).
*
* @static
* @memberOf _
* @category Objects
* @param {*} a The value to compare.
* @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* var object = { 'name': 'fred' };
* var copy = { 'name': 'fred' };
*
* object == copy;
* // => false
*
* _.isEqual(object, copy);
* // => true
*
* var words = ['hello', 'goodbye'];
* var otherWords = ['hi', 'goodbye'];
*
* _.isEqual(words, otherWords, function(a, b) {
* var reGreet = /^(?:hello|hi)$/i,
* aGreet = _.isString(a) && reGreet.test(a),
* bGreet = _.isString(b) && reGreet.test(b);
*
* return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
* });
* // => true
*/
function isEqual(a, b, callback, thisArg) {
return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
}
/**
* Checks if `value` is, or can be coerced to, a finite number.
*
* Note: This is not the same as native `isFinite` which will return true for
* booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is finite, else `false`.
* @example
*
* _.isFinite(-101);
* // => true
*
* _.isFinite('10');
* // => true
*
* _.isFinite(true);
* // => false
*
* _.isFinite('');
* // => false
*
* _.isFinite(Infinity);
* // => false
*/
function isFinite(value) {
return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
}
/**
* Checks if `value` is a function.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
* // => true
*/
function isFunction(value) {
return typeof value == 'function';
}
/**
* Checks if `value` is the language type of Object.
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(1);
* // => false
*/
function isObject(value) {
// check if the value is the ECMAScript language type of Object
// http://es5.github.io/#x8
// and avoid a V8 bug
// http://code.google.com/p/v8/issues/detail?id=2291
return !!(value && objectTypes[typeof value]);
}
/**
* Checks if `value` is `NaN`.
*
* Note: This is not the same as native `isNaN` which will return `true` for
* `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
* @example
*
* _.isNaN(NaN);
* // => true
*
* _.isNaN(new Number(NaN));
* // => true
*
* isNaN(undefined);
* // => true
*
* _.isNaN(undefined);
* // => false
*/
function isNaN(value) {
// `NaN` as a primitive is the only value that is not equal to itself
// (perform the [[Class]] check first to avoid errors with some host objects in IE)
return isNumber(value) && value != +value;
}
/**
* Checks if `value` is `null`.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
* @example
*
* _.isNull(null);
* // => true
*
* _.isNull(undefined);
* // => false
*/
function isNull(value) {
return value === null;
}
/**
* Checks if `value` is a number.
*
* Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a number, else `false`.
* @example
*
* _.isNumber(8.4 * 5);
* // => true
*/
function isNumber(value) {
return typeof value == 'number' ||
value && typeof value == 'object' && toString.call(value) == numberClass || false;
}
/**
* Checks if `value` is an object created by the `Object` constructor.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* _.isPlainObject(new Shape);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*/
var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
if (!(value && toString.call(value) == objectClass)) {
return false;
}
var valueOf = value.valueOf,
objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
return objProto
? (value == objProto || getPrototypeOf(value) == objProto)
: shimIsPlainObject(value);
};
/**
* Checks if `value` is a regular expression.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
* @example
*
* _.isRegExp(/fred/);
* // => true
*/
function isRegExp(value) {
return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
}
/**
* Checks if `value` is a string.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a string, else `false`.
* @example
*
* _.isString('fred');
* // => true
*/
function isString(value) {
return typeof value == 'string' ||
value && typeof value == 'object' && toString.call(value) == stringClass || false;
}
/**
* Checks if `value` is `undefined`.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
* @example
*
* _.isUndefined(void 0);
* // => true
*/
function isUndefined(value) {
return typeof value == 'undefined';
}
/**
* Creates an object with the same keys as `object` and values generated by
* running each own enumerable property of `object` through the callback.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new object with values of the results of each `callback` execution.
* @example
*
* _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
* // => { 'a': 3, 'b': 6, 'c': 9 }
*
* var characters = {
* 'fred': { 'name': 'fred', 'age': 40 },
* 'pebbles': { 'name': 'pebbles', 'age': 1 }
* };
*
* // using "_.pluck" callback shorthand
* _.mapValues(characters, 'age');
* // => { 'fred': 40, 'pebbles': 1 }
*/
function mapValues(object, callback, thisArg) {
var result = {};
callback = lodash.createCallback(callback, thisArg, 3);
forOwn(object, function(value, key, object) {
result[key] = callback(value, key, object);
});
return result;
}
/**
* Recursively merges own enumerable properties of the source object(s), that
* don't resolve to `undefined` into the destination object. Subsequent sources
* will overwrite property assignments of previous sources. If a callback is
* provided it will be executed to produce the merged values of the destination
* and source properties. If the callback returns `undefined` merging will
* be handled by the method instead. The callback is bound to `thisArg` and
* invoked with two arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize merging properties.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
* @example
*
* var names = {
* 'characters': [
* { 'name': 'barney' },
* { 'name': 'fred' }
* ]
* };
*
* var ages = {
* 'characters': [
* { 'age': 36 },
* { 'age': 40 }
* ]
* };
*
* _.merge(names, ages);
* // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
*
* var food = {
* 'fruits': ['apple'],
* 'vegetables': ['beet']
* };
*
* var otherFood = {
* 'fruits': ['banana'],
* 'vegetables': ['carrot']
* };
*
* _.merge(food, otherFood, function(a, b) {
* return _.isArray(a) ? a.concat(b) : undefined;
* });
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
*/
function merge(object) {
var args = arguments,
length = 2;
if (!isObject(object)) {
return object;
}
// allows working with `_.reduce` and `_.reduceRight` without using
// their `index` and `collection` arguments
if (typeof args[2] != 'number') {
length = args.length;
}
if (length > 3 && typeof args[length - 2] == 'function') {
var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
} else if (length > 2 && typeof args[length - 1] == 'function') {
callback = args[--length];
}
var sources = slice(arguments, 1, length),
index = -1,
stackA = getArray(),
stackB = getArray();
while (++index < length) {
baseMerge(object, sources[index], callback, stackA, stackB);
}
releaseArray(stackA);
releaseArray(stackB);
return object;
}
/**
* Creates a shallow clone of `object` excluding the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a callback is provided it will be executed for each
* property of `object` omitting the properties the callback returns truey
* for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|...string|string[]} [callback] The properties to omit or the
* function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object without the omitted properties.
* @example
*
* _.omit({ 'name': 'fred', 'age': 40 }, 'age');
* // => { 'name': 'fred' }
*
* _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
* return typeof value == 'number';
* });
* // => { 'name': 'fred' }
*/
function omit(object, callback, thisArg) {
var result = {};
if (typeof callback != 'function') {
var props = [];
forIn(object, function(value, key) {
props.push(key);
});
props = baseDifference(props, baseFlatten(arguments, true, false, 1));
var index = -1,
length = props.length;
while (++index < length) {
var key = props[index];
result[key] = object[key];
}
} else {
callback = lodash.createCallback(callback, thisArg, 3);
forIn(object, function(value, key, object) {
if (!callback(value, key, object)) {
result[key] = value;
}
});
}
return result;
}
/**
* Creates a two dimensional array of an object's key-value pairs,
* i.e. `[[key1, value1], [key2, value2]]`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns new array of key-value pairs.
* @example
*
* _.pairs({ 'barney': 36, 'fred': 40 });
* // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
*/
function pairs(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
var key = props[index];
result[index] = [key, object[key]];
}
return result;
}
/**
* Creates a shallow clone of `object` composed of the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a callback is provided it will be executed for each
* property of `object` picking the properties the callback returns truey
* for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|...string|string[]} [callback] The function called per
* iteration or property names to pick, specified as individual property
* names or arrays of property names.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object composed of the picked properties.
* @example
*
* _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
* // => { 'name': 'fred' }
*
* _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
* return key.charAt(0) != '_';
* });
* // => { 'name': 'fred' }
*/
function pick(object, callback, thisArg) {
var result = {};
if (typeof callback != 'function') {
var index = -1,
props = baseFlatten(arguments, true, false, 1),
length = isObject(object) ? props.length : 0;
while (++index < length) {
var key = props[index];
if (key in object) {
result[key] = object[key];
}
}
} else {
callback = lodash.createCallback(callback, thisArg, 3);
forIn(object, function(value, key, object) {
if (callback(value, key, object)) {
result[key] = value;
}
});
}
return result;
}
/**
* An alternative to `_.reduce` this method transforms `object` to a new
* `accumulator` object which is the result of running each of its own
* enumerable properties through a callback, with each callback execution
* potentially mutating the `accumulator` object. The callback is bound to
* `thisArg` and invoked with four arguments; (accumulator, value, key, object).
* Callbacks may exit iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] The custom accumulator value.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
* num *= num;
* if (num % 2) {
* return result.push(num) < 3;
* }
* });
* // => [1, 9, 25]
*
* var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* });
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function transform(object, callback, accumulator, thisArg) {
var isArr = isArray(object);
if (accumulator == null) {
if (isArr) {
accumulator = [];
} else {
var ctor = object && object.constructor,
proto = ctor && ctor.prototype;
accumulator = baseCreate(proto);
}
}
if (callback) {
callback = lodash.createCallback(callback, thisArg, 4);
(isArr ? forEach : forOwn)(object, function(value, index, object) {
return callback(accumulator, value, index, object);
});
}
return accumulator;
}
/**
* Creates an array composed of the own enumerable property values of `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property values.
* @example
*
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
* // => [1, 2, 3] (property order is not guaranteed across environments)
*/
function values(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
result[index] = object[props[index]];
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Creates an array of elements from the specified indexes, or keys, of the
* `collection`. Indexes may be specified as individual arguments or as arrays
* of indexes.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
* to retrieve, specified as individual indexes or arrays of indexes.
* @returns {Array} Returns a new array of elements corresponding to the
* provided indexes.
* @example
*
* _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
* // => ['a', 'c', 'e']
*
* _.at(['fred', 'barney', 'pebbles'], 0, 2);
* // => ['fred', 'pebbles']
*/
function at(collection) {
var args = arguments,
index = -1,
props = baseFlatten(args, true, false, 1),
length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
result = Array(length);
while(++index < length) {
result[index] = collection[props[index]];
}
return result;
}
/**
* Checks if a given value is present in a collection using strict equality
* for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
* offset from the end of the collection.
*
* @static
* @memberOf _
* @alias include
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {*} target The value to check for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {boolean} Returns `true` if the `target` element is found, else `false`.
* @example
*
* _.contains([1, 2, 3], 1);
* // => true
*
* _.contains([1, 2, 3], 1, 2);
* // => false
*
* _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
* // => true
*
* _.contains('pebbles', 'eb');
* // => true
*/
function contains(collection, target, fromIndex) {
var index = -1,
indexOf = getIndexOf(),
length = collection ? collection.length : 0,
result = false;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
if (isArray(collection)) {
result = indexOf(collection, target, fromIndex) > -1;
} else if (typeof length == 'number') {
result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
} else {
forOwn(collection, function(value) {
if (++index >= fromIndex) {
return !(result = value === target);
}
});
}
return result;
}
/**
* Creates an object composed of keys generated from the results of running
* each element of `collection` through the callback. The corresponding value
* of each key is the number of times the key was returned by the callback.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': 1, '6': 2 }
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': 1, '6': 2 }
*
* _.countBy(['one', 'two', 'three'], 'length');
* // => { '3': 2, '5': 1 }
*/
var countBy = createAggregator(function(result, value, key) {
(hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
});
/**
* Checks if the given callback returns truey value for **all** elements of
* a collection. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias all
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if all elements passed the callback check,
* else `false`.
* @example
*
* _.every([true, 1, null, 'yes']);
* // => false
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // using "_.pluck" callback shorthand
* _.every(characters, 'age');
* // => true
*
* // using "_.where" callback shorthand
* _.every(characters, { 'age': 36 });
* // => false
*/
function every(collection, callback, thisArg) {
var result = true;
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if (!(result = !!callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return (result = !!callback(value, index, collection));
});
}
return result;
}
/**
* Iterates over elements of a collection, returning an array of all elements
* the callback returns truey for. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias select
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that passed the callback check.
* @example
*
* var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [2, 4, 6]
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.filter(characters, 'blocked');
* // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*
* // using "_.where" callback shorthand
* _.filter(characters, { 'age': 36 });
* // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
*/
function filter(collection, callback, thisArg) {
var result = [];
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
result.push(value);
}
}
} else {
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result.push(value);
}
});
}
return result;
}
/**
* Iterates over elements of a collection, returning the first element that
* the callback returns truey for. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias detect, findWhere
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the found element, else `undefined`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true },
* { 'name': 'pebbles', 'age': 1, 'blocked': false }
* ];
*
* _.find(characters, function(chr) {
* return chr.age < 40;
* });
* // => { 'name': 'barney', 'age': 36, 'blocked': false }
*
* // using "_.where" callback shorthand
* _.find(characters, { 'age': 1 });
* // => { 'name': 'pebbles', 'age': 1, 'blocked': false }
*
* // using "_.pluck" callback shorthand
* _.find(characters, 'blocked');
* // => { 'name': 'fred', 'age': 40, 'blocked': true }
*/
function find(collection, callback, thisArg) {
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
return value;
}
}
} else {
var result;
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result = value;
return false;
}
});
return result;
}
}
/**
* This method is like `_.find` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the found element, else `undefined`.
* @example
*
* _.findLast([1, 2, 3, 4], function(num) {
* return num % 2 == 1;
* });
* // => 3
*/
function findLast(collection, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
forEachRight(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result = value;
return false;
}
});
return result;
}
/**
* Iterates over elements of a collection, executing the callback for each
* element. The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection). Callbacks may exit iteration early by
* explicitly returning `false`.
*
* Note: As with other "Collections" methods, objects with a `length` property
* are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
* may be used for object iteration.
*
* @static
* @memberOf _
* @alias each
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array|Object|string} Returns `collection`.
* @example
*
* _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
* // => logs each number and returns '1,2,3'
*
* _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
* // => logs each number and returns the object (property order is not guaranteed across environments)
*/
function forEach(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
if (typeof length == 'number') {
while (++index < length) {
if (callback(collection[index], index, collection) === false) {
break;
}
}
} else {
forOwn(collection, callback);
}
return collection;
}
/**
* This method is like `_.forEach` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @alias eachRight
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array|Object|string} Returns `collection`.
* @example
*
* _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
* // => logs each number from right to left and returns '3,2,1'
*/
function forEachRight(collection, callback, thisArg) {
var length = collection ? collection.length : 0;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
if (typeof length == 'number') {
while (length--) {
if (callback(collection[length], length, collection) === false) {
break;
}
}
} else {
var props = keys(collection);
length = props.length;
forOwn(collection, function(value, key, collection) {
key = props ? props[--length] : --length;
return callback(collection[key], key, collection);
});
}
return collection;
}
/**
* Creates an object composed of keys generated from the results of running
* each element of a collection through the callback. The corresponding value
* of each key is an array of the elements responsible for generating the key.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* // using "_.pluck" callback shorthand
* _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] }
*/
var groupBy = createAggregator(function(result, value, key) {
(hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
});
/**
* Creates an object composed of keys generated from the results of running
* each element of the collection through the given callback. The corresponding
* value of each key is the last element responsible for generating the key.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* var keys = [
* { 'dir': 'left', 'code': 97 },
* { 'dir': 'right', 'code': 100 }
* ];
*
* _.indexBy(keys, 'dir');
* // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
*
* _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*
* _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*/
var indexBy = createAggregator(function(result, value, key) {
result[key] = value;
});
/**
* Invokes the method named by `methodName` on each element in the `collection`
* returning an array of the results of each invoked method. Additional arguments
* will be provided to each invoked method. If `methodName` is a function it
* will be invoked for, and `this` bound to, each element in the `collection`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|string} methodName The name of the method to invoke or
* the function invoked per iteration.
* @param {...*} [arg] Arguments to invoke the method with.
* @returns {Array} Returns a new array of the results of each invoked method.
* @example
*
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
* // => [[1, 5, 7], [1, 2, 3]]
*
* _.invoke([123, 456], String.prototype.split, '');
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
function invoke(collection, methodName) {
var args = slice(arguments, 2),
index = -1,
isFunc = typeof methodName == 'function',
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
});
return result;
}
/**
* Creates an array of values by running each element in the collection
* through the callback. The callback is bound to `thisArg` and invoked with
* three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias collect
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of the results of each `callback` execution.
* @example
*
* _.map([1, 2, 3], function(num) { return num * 3; });
* // => [3, 6, 9]
*
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
* // => [3, 6, 9] (property order is not guaranteed across environments)
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // using "_.pluck" callback shorthand
* _.map(characters, 'name');
* // => ['barney', 'fred']
*/
function map(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
if (typeof length == 'number') {
var result = Array(length);
while (++index < length) {
result[index] = callback(collection[index], index, collection);
}
} else {
result = [];
forOwn(collection, function(value, key, collection) {
result[++index] = callback(value, key, collection);
});
}
return result;
}
/**
* Retrieves the maximum value of a collection. If the collection is empty or
* falsey `-Infinity` is returned. If a callback is provided it will be executed
* for each value in the collection to generate the criterion by which the value
* is ranked. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the maximum value.
* @example
*
* _.max([4, 2, 8, 6]);
* // => 8
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.max(characters, function(chr) { return chr.age; });
* // => { 'name': 'fred', 'age': 40 };
*
* // using "_.pluck" callback shorthand
* _.max(characters, 'age');
* // => { 'name': 'fred', 'age': 40 };
*/
function max(collection, callback, thisArg) {
var computed = -Infinity,
result = computed;
// allows working with functions like `_.map` without using
// their `index` argument as a callback
if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
callback = null;
}
if (callback == null && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value > result) {
result = value;
}
}
} else {
callback = (callback == null && isString(collection))
? charAtCallback
: lodash.createCallback(callback, thisArg, 3);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current > computed) {
computed = current;
result = value;
}
});
}
return result;
}
/**
* Retrieves the minimum value of a collection. If the collection is empty or
* falsey `Infinity` is returned. If a callback is provided it will be executed
* for each value in the collection to generate the criterion by which the value
* is ranked. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the minimum value.
* @example
*
* _.min([4, 2, 8, 6]);
* // => 2
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.min(characters, function(chr) { return chr.age; });
* // => { 'name': 'barney', 'age': 36 };
*
* // using "_.pluck" callback shorthand
* _.min(characters, 'age');
* // => { 'name': 'barney', 'age': 36 };
*/
function min(collection, callback, thisArg) {
var computed = Infinity,
result = computed;
// allows working with functions like `_.map` without using
// their `index` argument as a callback
if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
callback = null;
}
if (callback == null && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value < result) {
result = value;
}
}
} else {
callback = (callback == null && isString(collection))
? charAtCallback
: lodash.createCallback(callback, thisArg, 3);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current < computed) {
computed = current;
result = value;
}
});
}
return result;
}
/**
* Retrieves the value of a specified property from all elements in the collection.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {string} property The name of the property to pluck.
* @returns {Array} Returns a new array of property values.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.pluck(characters, 'name');
* // => ['barney', 'fred']
*/
var pluck = map;
/**
* Reduces a collection to a value which is the accumulated result of running
* each element in the collection through the callback, where each successive
* callback execution consumes the return value of the previous execution. If
* `accumulator` is not provided the first element of the collection will be
* used as the initial `accumulator` value. The callback is bound to `thisArg`
* and invoked with four arguments; (accumulator, value, index|key, collection).
*
* @static
* @memberOf _
* @alias foldl, inject
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] Initial value of the accumulator.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var sum = _.reduce([1, 2, 3], function(sum, num) {
* return sum + num;
* });
* // => 6
*
* var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* return result;
* }, {});
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function reduce(collection, callback, accumulator, thisArg) {
if (!collection) return accumulator;
var noaccum = arguments.length < 3;
callback = lodash.createCallback(callback, thisArg, 4);
var index = -1,
length = collection.length;
if (typeof length == 'number') {
if (noaccum) {
accumulator = collection[++index];
}
while (++index < length) {
accumulator = callback(accumulator, collection[index], index, collection);
}
} else {
forOwn(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
: callback(accumulator, value, index, collection)
});
}
return accumulator;
}
/**
* This method is like `_.reduce` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @alias foldr
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] Initial value of the accumulator.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var list = [[0, 1], [2, 3], [4, 5]];
* var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
* // => [4, 5, 2, 3, 0, 1]
*/
function reduceRight(collection, callback, accumulator, thisArg) {
var noaccum = arguments.length < 3;
callback = lodash.createCallback(callback, thisArg, 4);
forEachRight(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
: callback(accumulator, value, index, collection);
});
return accumulator;
}
/**
* The opposite of `_.filter` this method returns the elements of a
* collection that the callback does **not** return truey for.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that failed the callback check.
* @example
*
* var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [1, 3, 5]
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.reject(characters, 'blocked');
* // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
*
* // using "_.where" callback shorthand
* _.reject(characters, { 'age': 36 });
* // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*/
function reject(collection, callback, thisArg) {
callback = lodash.createCallback(callback, thisArg, 3);
return filter(collection, function(value, index, collection) {
return !callback(value, index, collection);
});
}
/**
* Retrieves a random element or `n` random elements from a collection.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to sample.
* @param {number} [n] The number of elements to sample.
* @param- {Object} [guard] Allows working with functions like `_.map`
* without using their `index` arguments as `n`.
* @returns {Array} Returns the random sample(s) of `collection`.
* @example
*
* _.sample([1, 2, 3, 4]);
* // => 2
*
* _.sample([1, 2, 3, 4], 2);
* // => [3, 1]
*/
function sample(collection, n, guard) {
if (collection && typeof collection.length != 'number') {
collection = values(collection);
}
if (n == null || guard) {
return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
}
var result = shuffle(collection);
result.length = nativeMin(nativeMax(0, n), result.length);
return result;
}
/**
* Creates an array of shuffled values, using a version of the Fisher-Yates
* shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to shuffle.
* @returns {Array} Returns a new shuffled collection.
* @example
*
* _.shuffle([1, 2, 3, 4, 5, 6]);
* // => [4, 1, 6, 3, 5, 2]
*/
function shuffle(collection) {
var index = -1,
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
var rand = baseRandom(0, ++index);
result[index] = result[rand];
result[rand] = value;
});
return result;
}
/**
* Gets the size of the `collection` by returning `collection.length` for arrays
* and array-like objects or the number of own enumerable properties for objects.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to inspect.
* @returns {number} Returns `collection.length` or number of own enumerable properties.
* @example
*
* _.size([1, 2]);
* // => 2
*
* _.size({ 'one': 1, 'two': 2, 'three': 3 });
* // => 3
*
* _.size('pebbles');
* // => 7
*/
function size(collection) {
var length = collection ? collection.length : 0;
return typeof length == 'number' ? length : keys(collection).length;
}
/**
* Checks if the callback returns a truey value for **any** element of a
* collection. The function returns as soon as it finds a passing value and
* does not iterate over the entire collection. The callback is bound to
* `thisArg` and invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias any
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if any element passed the callback check,
* else `false`.
* @example
*
* _.some([null, 0, 'yes', false], Boolean);
* // => true
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.some(characters, 'blocked');
* // => true
*
* // using "_.where" callback shorthand
* _.some(characters, { 'age': 1 });
* // => false
*/
function some(collection, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if ((result = callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return !(result = callback(value, index, collection));
});
}
return !!result;
}
/**
* Creates an array of elements, sorted in ascending order by the results of
* running each element in a collection through the callback. This method
* performs a stable sort, that is, it will preserve the original sort order
* of equal elements. The callback is bound to `thisArg` and invoked with
* three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an array of property names is provided for `callback` the collection
* will be sorted by each property value.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Array|Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of sorted elements.
* @example
*
* _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
* // => [3, 1, 2]
*
* _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
* // => [3, 1, 2]
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 },
* { 'name': 'barney', 'age': 26 },
* { 'name': 'fred', 'age': 30 }
* ];
*
* // using "_.pluck" callback shorthand
* _.map(_.sortBy(characters, 'age'), _.values);
* // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
*
* // sorting by multiple properties
* _.map(_.sortBy(characters, ['name', 'age']), _.values);
* // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
*/
function sortBy(collection, callback, thisArg) {
var index = -1,
isArr = isArray(callback),
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
if (!isArr) {
callback = lodash.createCallback(callback, thisArg, 3);
}
forEach(collection, function(value, key, collection) {
var object = result[++index] = getObject();
if (isArr) {
object.criteria = map(callback, function(key) { return value[key]; });
} else {
(object.criteria = getArray())[0] = callback(value, key, collection);
}
object.index = index;
object.value = value;
});
length = result.length;
result.sort(compareAscending);
while (length--) {
var object = result[length];
result[length] = object.value;
if (!isArr) {
releaseArray(object.criteria);
}
releaseObject(object);
}
return result;
}
/**
* Converts the `collection` to an array.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to convert.
* @returns {Array} Returns the new converted array.
* @example
*
* (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
* // => [2, 3, 4]
*/
function toArray(collection) {
if (collection && typeof collection.length == 'number') {
return slice(collection);
}
return values(collection);
}
/**
* Performs a deep comparison of each element in a `collection` to the given
* `properties` object, returning an array of all elements that have equivalent
* property values.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Object} props The object of property values to filter by.
* @returns {Array} Returns a new array of elements that have the given properties.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
* { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
* ];
*
* _.where(characters, { 'age': 36 });
* // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
*
* _.where(characters, { 'pets': ['dino'] });
* // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
*/
var where = filter;
/*--------------------------------------------------------------------------*/
/**
* Creates an array with all falsey values removed. The values `false`, `null`,
* `0`, `""`, `undefined`, and `NaN` are all falsey.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to compact.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.compact([0, 1, false, 2, '', 3]);
* // => [1, 2, 3]
*/
function compact(array) {
var index = -1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value) {
result.push(value);
}
}
return result;
}
/**
* Creates an array excluding all values of the provided arrays using strict
* equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to process.
* @param {...Array} [values] The arrays of values to exclude.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
* // => [1, 3, 4]
*/
function difference(array) {
return baseDifference(array, baseFlatten(arguments, true, true, 1));
}
/**
* This method is like `_.find` except that it returns the index of the first
* element that passes the callback check, instead of the element itself.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true },
* { 'name': 'pebbles', 'age': 1, 'blocked': false }
* ];
*
* _.findIndex(characters, function(chr) {
* return chr.age < 20;
* });
* // => 2
*
* // using "_.where" callback shorthand
* _.findIndex(characters, { 'age': 36 });
* // => 0
*
* // using "_.pluck" callback shorthand
* _.findIndex(characters, 'blocked');
* // => 1
*/
function findIndex(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length) {
if (callback(array[index], index, array)) {
return index;
}
}
return -1;
}
/**
* This method is like `_.findIndex` except that it iterates over elements
* of a `collection` from right to left.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': true },
* { 'name': 'fred', 'age': 40, 'blocked': false },
* { 'name': 'pebbles', 'age': 1, 'blocked': true }
* ];
*
* _.findLastIndex(characters, function(chr) {
* return chr.age > 30;
* });
* // => 1
*
* // using "_.where" callback shorthand
* _.findLastIndex(characters, { 'age': 36 });
* // => 0
*
* // using "_.pluck" callback shorthand
* _.findLastIndex(characters, 'blocked');
* // => 2
*/
function findLastIndex(array, callback, thisArg) {
var length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
while (length--) {
if (callback(array[length], length, array)) {
return length;
}
}
return -1;
}
/**
* Gets the first element or first `n` elements of an array. If a callback
* is provided elements at the beginning of the array are returned as long
* as the callback returns truey. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias head, take
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback] The function called
* per element or the number of elements to return. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the first element(s) of `array`.
* @example
*
* _.first([1, 2, 3]);
* // => 1
*
* _.first([1, 2, 3], 2);
* // => [1, 2]
*
* _.first([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [1, 2]
*
* var characters = [
* { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.first(characters, 'blocked');
* // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
*
* // using "_.where" callback shorthand
* _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
* // => ['barney', 'fred']
*/
function first(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = -1;
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array ? array[0] : undefined;
}
}
return slice(array, 0, nativeMin(nativeMax(0, n), length));
}
/**
* Flattens a nested array (the nesting can be to any depth). If `isShallow`
* is truey, the array will only be flattened a single level. If a callback
* is provided each element of the array is passed through the callback before
* flattening. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new flattened array.
* @example
*
* _.flatten([1, [2], [3, [[4]]]]);
* // => [1, 2, 3, 4];
*
* _.flatten([1, [2], [3, [[4]]]], true);
* // => [1, 2, 3, [[4]]];
*
* var characters = [
* { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
* { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
* ];
*
* // using "_.pluck" callback shorthand
* _.flatten(characters, 'pets');
* // => ['hoppy', 'baby puss', 'dino']
*/
function flatten(array, isShallow, callback, thisArg) {
// juggle arguments
if (typeof isShallow != 'boolean' && isShallow != null) {
thisArg = callback;
callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
isShallow = false;
}
if (callback != null) {
array = map(array, callback, thisArg);
}
return baseFlatten(array, isShallow);
}
/**
* Gets the index at which the first occurrence of `value` is found using
* strict equality for comparisons, i.e. `===`. If the array is already sorted
* providing `true` for `fromIndex` will run a faster binary search.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {boolean|number} [fromIndex=0] The index to search from or `true`
* to perform a binary search on a sorted array.
* @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2);
* // => 1
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 4
*
* _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
* // => 2
*/
function indexOf(array, value, fromIndex) {
if (typeof fromIndex == 'number') {
var length = array ? array.length : 0;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
} else if (fromIndex) {
var index = sortedIndex(array, value);
return array[index] === value ? index : -1;
}
return baseIndexOf(array, value, fromIndex);
}
/**
* Gets all but the last element or last `n` elements of an array. If a
* callback is provided elements at the end of the array are excluded from
* the result as long as the callback returns truey. The callback is bound
* to `thisArg` and invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.initial([1, 2, 3]);
* // => [1, 2]
*
* _.initial([1, 2, 3], 2);
* // => [1]
*
* _.initial([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [1]
*
* var characters = [
* { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.initial(characters, 'blocked');
* // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }]
*
* // using "_.where" callback shorthand
* _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
* // => ['barney', 'fred']
*/
function initial(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = lodash.createCallback(callback, thisArg, 3);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : callback || n;
}
return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
}
/**
* Creates an array of unique values present in all provided arrays using
* strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of shared values.
* @example
*
* _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
* // => [1, 2]
*/
function intersection() {
var args = [],
argsIndex = -1,
argsLength = arguments.length,
caches = getArray(),
indexOf = getIndexOf(),
trustIndexOf = indexOf === baseIndexOf,
seen = getArray();
while (++argsIndex < argsLength) {
var value = arguments[argsIndex];
if (isArray(value) || isArguments(value)) {
args.push(value);
caches.push(trustIndexOf && value.length >= largeArraySize &&
createCache(argsIndex ? args[argsIndex] : seen));
}
}
var array = args[0],
index = -1,
length = array ? array.length : 0,
result = [];
outer:
while (++index < length) {
var cache = caches[0];
value = array[index];
if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
argsIndex = argsLength;
(cache || seen).push(value);
while (--argsIndex) {
cache = caches[argsIndex];
if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
continue outer;
}
}
result.push(value);
}
}
while (argsLength--) {
cache = caches[argsLength];
if (cache) {
releaseObject(cache);
}
}
releaseArray(caches);
releaseArray(seen);
return result;
}
/**
* Gets the last element or last `n` elements of an array. If a callback is
* provided elements at the end of the array are returned as long as the
* callback returns truey. The callback is bound to `thisArg` and invoked
* with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback] The function called
* per element or the number of elements to return. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the last element(s) of `array`.
* @example
*
* _.last([1, 2, 3]);
* // => 3
*
* _.last([1, 2, 3], 2);
* // => [2, 3]
*
* _.last([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [2, 3]
*
* var characters = [
* { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.pluck(_.last(characters, 'blocked'), 'name');
* // => ['fred', 'pebbles']
*
* // using "_.where" callback shorthand
* _.last(characters, { 'employer': 'na' });
* // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
*/
function last(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = lodash.createCallback(callback, thisArg, 3);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array ? array[length - 1] : undefined;
}
}
return slice(array, nativeMax(0, length - n));
}
/**
* Gets the index at which the last occurrence of `value` is found using strict
* equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
* as the offset from the end of the collection.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
* // => 4
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 1
*/
function lastIndexOf(array, value, fromIndex) {
var index = array ? array.length : 0;
if (typeof fromIndex == 'number') {
index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
}
while (index--) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* Removes all provided values from the given array using strict equality for
* comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
* @param {...*} [value] The values to remove.
* @returns {Array} Returns `array`.
* @example
*
* var array = [1, 2, 3, 1, 2, 3];
* _.pull(array, 2, 3);
* console.log(array);
* // => [1, 1]
*/
function pull(array) {
var args = arguments,
argsIndex = 0,
argsLength = args.length,
length = array ? array.length : 0;
while (++argsIndex < argsLength) {
var index = -1,
value = args[argsIndex];
while (++index < length) {
if (array[index] === value) {
splice.call(array, index--, 1);
length--;
}
}
}
return array;
}
/**
* Creates an array of numbers (positive and/or negative) progressing from
* `start` up to but not including `end`. If `start` is less than `stop` a
* zero-length range is created unless a negative `step` is specified.
*
* @static
* @memberOf _
* @category Arrays
* @param {number} [start=0] The start of the range.
* @param {number} end The end of the range.
* @param {number} [step=1] The value to increment or decrement by.
* @returns {Array} Returns a new range array.
* @example
*
* _.range(4);
* // => [0, 1, 2, 3]
*
* _.range(1, 5);
* // => [1, 2, 3, 4]
*
* _.range(0, 20, 5);
* // => [0, 5, 10, 15]
*
* _.range(0, -4, -1);
* // => [0, -1, -2, -3]
*
* _.range(1, 4, 0);
* // => [1, 1, 1]
*
* _.range(0);
* // => []
*/
function range(start, end, step) {
start = +start || 0;
step = typeof step == 'number' ? step : (+step || 1);
if (end == null) {
end = start;
start = 0;
}
// use `Array(length)` so engines like Chakra and V8 avoid slower modes
// http://youtu.be/XAqIpGU8ZZk#t=17m25s
var index = -1,
length = nativeMax(0, ceil((end - start) / (step || 1))),
result = Array(length);
while (++index < length) {
result[index] = start;
start += step;
}
return result;
}
/**
* Removes all elements from an array that the callback returns truey for
* and returns an array of removed elements. The callback is bound to `thisArg`
* and invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of removed elements.
* @example
*
* var array = [1, 2, 3, 4, 5, 6];
* var evens = _.remove(array, function(num) { return num % 2 == 0; });
*
* console.log(array);
* // => [1, 3, 5]
*
* console.log(evens);
* // => [2, 4, 6]
*/
function remove(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0,
result = [];
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length) {
var value = array[index];
if (callback(value, index, array)) {
result.push(value);
splice.call(array, index--, 1);
length--;
}
}
return result;
}
/**
* The opposite of `_.initial` this method gets all but the first element or
* first `n` elements of an array. If a callback function is provided elements
* at the beginning of the array are excluded from the result as long as the
* callback returns truey. The callback is bound to `thisArg` and invoked
* with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias drop, tail
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.rest([1, 2, 3]);
* // => [2, 3]
*
* _.rest([1, 2, 3], 2);
* // => [3]
*
* _.rest([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [3]
*
* var characters = [
* { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.pluck(_.rest(characters, 'blocked'), 'name');
* // => ['fred', 'pebbles']
*
* // using "_.where" callback shorthand
* _.rest(characters, { 'employer': 'slate' });
* // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
*/
function rest(array, callback, thisArg) {
if (typeof callback != 'number' && callback != null) {
var n = 0,
index = -1,
length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
}
return slice(array, n);
}
/**
* Uses a binary search to determine the smallest index at which a value
* should be inserted into a given sorted array in order to maintain the sort
* order of the array. If a callback is provided it will be executed for
* `value` and each element of `array` to compute their sort ranking. The
* callback is bound to `thisArg` and invoked with one argument; (value).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to inspect.
* @param {*} value The value to evaluate.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* _.sortedIndex([20, 30, 50], 40);
* // => 2
*
* // using "_.pluck" callback shorthand
* _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
* // => 2
*
* var dict = {
* 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
* };
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return dict.wordToNumber[word];
* });
* // => 2
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return this.wordToNumber[word];
* }, dict);
* // => 2
*/
function sortedIndex(array, value, callback, thisArg) {
var low = 0,
high = array ? array.length : low;
// explicitly reference `identity` for better inlining in Firefox
callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
value = callback(value);
while (low < high) {
var mid = (low + high) >>> 1;
(callback(array[mid]) < value)
? low = mid + 1
: high = mid;
}
return low;
}
/**
* Creates an array of unique values, in order, of the provided arrays using
* strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of combined values.
* @example
*
* _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
* // => [1, 2, 3, 5, 4]
*/
function union() {
return baseUniq(baseFlatten(arguments, true, true));
}
/**
* Creates a duplicate-value-free version of an array using strict equality
* for comparisons, i.e. `===`. If the array is sorted, providing
* `true` for `isSorted` will use a faster algorithm. If a callback is provided
* each element of `array` is passed through the callback before uniqueness
* is computed. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias unique
* @category Arrays
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a duplicate-value-free array.
* @example
*
* _.uniq([1, 2, 1, 3, 1]);
* // => [1, 2, 3]
*
* _.uniq([1, 1, 2, 2, 3], true);
* // => [1, 2, 3]
*
* _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
* // => ['A', 'b', 'C']
*
* _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
* // => [1, 2.5, 3]
*
* // using "_.pluck" callback shorthand
* _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
function uniq(array, isSorted, callback, thisArg) {
// juggle arguments
if (typeof isSorted != 'boolean' && isSorted != null) {
thisArg = callback;
callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
isSorted = false;
}
if (callback != null) {
callback = lodash.createCallback(callback, thisArg, 3);
}
return baseUniq(array, isSorted, callback);
}
/**
* Creates an array excluding all provided values using strict equality for
* comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to filter.
* @param {...*} [value] The values to exclude.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
* // => [2, 3, 4]
*/
function without(array) {
return baseDifference(array, slice(arguments, 1));
}
/**
* Creates an array that is the symmetric difference of the provided arrays.
* See http://en.wikipedia.org/wiki/Symmetric_difference.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of values.
* @example
*
* _.xor([1, 2, 3], [5, 2, 1, 4]);
* // => [3, 5, 4]
*
* _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
* // => [1, 4, 5]
*/
function xor() {
var index = -1,
length = arguments.length;
while (++index < length) {
var array = arguments[index];
if (isArray(array) || isArguments(array)) {
var result = result
? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
: array;
}
}
return result || [];
}
/**
* Creates an array of grouped elements, the first of which contains the first
* elements of the given arrays, the second of which contains the second
* elements of the given arrays, and so on.
*
* @static
* @memberOf _
* @alias unzip
* @category Arrays
* @param {...Array} [array] Arrays to process.
* @returns {Array} Returns a new array of grouped elements.
* @example
*
* _.zip(['fred', 'barney'], [30, 40], [true, false]);
* // => [['fred', 30, true], ['barney', 40, false]]
*/
function zip() {
var array = arguments.length > 1 ? arguments : arguments[0],
index = -1,
length = array ? max(pluck(array, 'length')) : 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = pluck(array, index);
}
return result;
}
/**
* Creates an object composed from arrays of `keys` and `values`. Provide
* either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
* or two arrays, one of `keys` and one of corresponding `values`.
*
* @static
* @memberOf _
* @alias object
* @category Arrays
* @param {Array} keys The array of keys.
* @param {Array} [values=[]] The array of values.
* @returns {Object} Returns an object composed of the given keys and
* corresponding values.
* @example
*
* _.zipObject(['fred', 'barney'], [30, 40]);
* // => { 'fred': 30, 'barney': 40 }
*/
function zipObject(keys, values) {
var index = -1,
length = keys ? keys.length : 0,
result = {};
if (!values && length && !isArray(keys[0])) {
values = [];
}
while (++index < length) {
var key = keys[index];
if (values) {
result[key] = values[index];
} else if (key) {
result[key[0]] = key[1];
}
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Creates a function that executes `func`, with the `this` binding and
* arguments of the created function, only after being called `n` times.
*
* @static
* @memberOf _
* @category Functions
* @param {number} n The number of times the function must be called before
* `func` is executed.
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var saves = ['profile', 'settings'];
*
* var done = _.after(saves.length, function() {
* console.log('Done saving!');
* });
*
* _.forEach(saves, function(type) {
* asyncSave({ 'type': type, 'complete': done });
* });
* // => logs 'Done saving!', after all saves have completed
*/
function after(n, func) {
if (!isFunction(func)) {
throw new TypeError;
}
return function() {
if (--n < 1) {
return func.apply(this, arguments);
}
};
}
/**
* Creates a function that, when called, invokes `func` with the `this`
* binding of `thisArg` and prepends any additional `bind` arguments to those
* provided to the bound function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to bind.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var func = function(greeting) {
* return greeting + ' ' + this.name;
* };
*
* func = _.bind(func, { 'name': 'fred' }, 'hi');
* func();
* // => 'hi fred'
*/
function bind(func, thisArg) {
return arguments.length > 2
? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
: createWrapper(func, 1, null, null, thisArg);
}
/**
* Binds methods of an object to the object itself, overwriting the existing
* method. Method names may be specified as individual arguments or as arrays
* of method names. If no method names are provided all the function properties
* of `object` will be bound.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object to bind and assign the bound methods to.
* @param {...string} [methodName] The object method names to
* bind, specified as individual method names or arrays of method names.
* @returns {Object} Returns `object`.
* @example
*
* var view = {
* 'label': 'docs',
* 'onClick': function() { console.log('clicked ' + this.label); }
* };
*
* _.bindAll(view);
* jQuery('#docs').on('click', view.onClick);
* // => logs 'clicked docs', when the button is clicked
*/
function bindAll(object) {
var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
index = -1,
length = funcs.length;
while (++index < length) {
var key = funcs[index];
object[key] = createWrapper(object[key], 1, null, null, object);
}
return object;
}
/**
* Creates a function that, when called, invokes the method at `object[key]`
* and prepends any additional `bindKey` arguments to those provided to the bound
* function. This method differs from `_.bind` by allowing bound functions to
* reference methods that will be redefined or don't yet exist.
* See http://michaux.ca/articles/lazy-function-definition-pattern.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object the method belongs to.
* @param {string} key The key of the method.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var object = {
* 'name': 'fred',
* 'greet': function(greeting) {
* return greeting + ' ' + this.name;
* }
* };
*
* var func = _.bindKey(object, 'greet', 'hi');
* func();
* // => 'hi fred'
*
* object.greet = function(greeting) {
* return greeting + 'ya ' + this.name + '!';
* };
*
* func();
* // => 'hiya fred!'
*/
function bindKey(object, key) {
return arguments.length > 2
? createWrapper(key, 19, slice(arguments, 2), null, object)
: createWrapper(key, 3, null, null, object);
}
/**
* Creates a function that is the composition of the provided functions,
* where each function consumes the return value of the function that follows.
* For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
* Each function is executed with the `this` binding of the composed function.
*
* @static
* @memberOf _
* @category Functions
* @param {...Function} [func] Functions to compose.
* @returns {Function} Returns the new composed function.
* @example
*
* var realNameMap = {
* 'pebbles': 'penelope'
* };
*
* var format = function(name) {
* name = realNameMap[name.toLowerCase()] || name;
* return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
* };
*
* var greet = function(formatted) {
* return 'Hiya ' + formatted + '!';
* };
*
* var welcome = _.compose(greet, format);
* welcome('pebbles');
* // => 'Hiya Penelope!'
*/
function compose() {
var funcs = arguments,
length = funcs.length;
while (length--) {
if (!isFunction(funcs[length])) {
throw new TypeError;
}
}
return function() {
var args = arguments,
length = funcs.length;
while (length--) {
args = [funcs[length].apply(this, args)];
}
return args[0];
};
}
/**
* Creates a function which accepts one or more arguments of `func` that when
* invoked either executes `func` returning its result, if all `func` arguments
* have been provided, or returns a function that accepts one or more of the
* remaining `func` arguments, and so on. The arity of `func` can be specified
* if `func.length` is not sufficient.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to curry.
* @param {number} [arity=func.length] The arity of `func`.
* @returns {Function} Returns the new curried function.
* @example
*
* var curried = _.curry(function(a, b, c) {
* console.log(a + b + c);
* });
*
* curried(1)(2)(3);
* // => 6
*
* curried(1, 2)(3);
* // => 6
*
* curried(1, 2, 3);
* // => 6
*/
function curry(func, arity) {
arity = typeof arity == 'number' ? arity : (+arity || func.length);
return createWrapper(func, 4, null, null, null, arity);
}
/**
* Creates a function that will delay the execution of `func` until after
* `wait` milliseconds have elapsed since the last time it was invoked.
* Provide an options object to indicate that `func` should be invoked on
* the leading and/or trailing edge of the `wait` timeout. Subsequent calls
* to the debounced function will return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the debounced function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to debounce.
* @param {number} wait The number of milliseconds to delay.
* @param {Object} [options] The options object.
* @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
* @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
* @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* // avoid costly calculations while the window size is in flux
* var lazyLayout = _.debounce(calculateLayout, 150);
* jQuery(window).on('resize', lazyLayout);
*
* // execute `sendMail` when the click event is fired, debouncing subsequent calls
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* });
*
* // ensure `batchLog` is executed once after 1 second of debounced calls
* var source = new EventSource('/stream');
* source.addEventListener('message', _.debounce(batchLog, 250, {
* 'maxWait': 1000
* }, false);
*/
function debounce(func, wait, options) {
var args,
maxTimeoutId,
result,
stamp,
thisArg,
timeoutId,
trailingCall,
lastCalled = 0,
maxWait = false,
trailing = true;
if (!isFunction(func)) {
throw new TypeError;
}
wait = nativeMax(0, wait) || 0;
if (options === true) {
var leading = true;
trailing = false;
} else if (isObject(options)) {
leading = options.leading;
maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
trailing = 'trailing' in options ? options.trailing : trailing;
}
var delayed = function() {
var remaining = wait - (now() - stamp);
if (remaining <= 0) {
if (maxTimeoutId) {
clearTimeout(maxTimeoutId);
}
var isCalled = trailingCall;
maxTimeoutId = timeoutId = trailingCall = undefined;
if (isCalled) {
lastCalled = now();
result = func.apply(thisArg, args);
if (!timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
}
} else {
timeoutId = setTimeout(delayed, remaining);
}
};
var maxDelayed = function() {
if (timeoutId) {
clearTimeout(timeoutId);
}
maxTimeoutId = timeoutId = trailingCall = undefined;
if (trailing || (maxWait !== wait)) {
lastCalled = now();
result = func.apply(thisArg, args);
if (!timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
}
};
return function() {
args = arguments;
stamp = now();
thisArg = this;
trailingCall = trailing && (timeoutId || !leading);
if (maxWait === false) {
var leadingCall = leading && !timeoutId;
} else {
if (!maxTimeoutId && !leading) {
lastCalled = stamp;
}
var remaining = maxWait - (stamp - lastCalled),
isCalled = remaining <= 0;
if (isCalled) {
if (maxTimeoutId) {
maxTimeoutId = clearTimeout(maxTimeoutId);
}
lastCalled = stamp;
result = func.apply(thisArg, args);
}
else if (!maxTimeoutId) {
maxTimeoutId = setTimeout(maxDelayed, remaining);
}
}
if (isCalled && timeoutId) {
timeoutId = clearTimeout(timeoutId);
}
else if (!timeoutId && wait !== maxWait) {
timeoutId = setTimeout(delayed, wait);
}
if (leadingCall) {
isCalled = true;
result = func.apply(thisArg, args);
}
if (isCalled && !timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
return result;
};
}
/**
* Defers executing the `func` function until the current call stack has cleared.
* Additional arguments will be provided to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to defer.
* @param {...*} [arg] Arguments to invoke the function with.
* @returns {number} Returns the timer id.
* @example
*
* _.defer(function(text) { console.log(text); }, 'deferred');
* // logs 'deferred' after one or more milliseconds
*/
function defer(func) {
if (!isFunction(func)) {
throw new TypeError;
}
var args = slice(arguments, 1);
return setTimeout(function() { func.apply(undefined, args); }, 1);
}
/**
* Executes the `func` function after `wait` milliseconds. Additional arguments
* will be provided to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to delay.
* @param {number} wait The number of milliseconds to delay execution.
* @param {...*} [arg] Arguments to invoke the function with.
* @returns {number} Returns the timer id.
* @example
*
* _.delay(function(text) { console.log(text); }, 1000, 'later');
* // => logs 'later' after one second
*/
function delay(func, wait) {
if (!isFunction(func)) {
throw new TypeError;
}
var args = slice(arguments, 2);
return setTimeout(function() { func.apply(undefined, args); }, wait);
}
/**
* Creates a function that memoizes the result of `func`. If `resolver` is
* provided it will be used to determine the cache key for storing the result
* based on the arguments provided to the memoized function. By default, the
* first argument provided to the memoized function is used as the cache key.
* The `func` is executed with the `this` binding of the memoized function.
* The result cache is exposed as the `cache` property on the memoized function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to have its output memoized.
* @param {Function} [resolver] A function used to resolve the cache key.
* @returns {Function} Returns the new memoizing function.
* @example
*
* var fibonacci = _.memoize(function(n) {
* return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
* });
*
* fibonacci(9)
* // => 34
*
* var data = {
* 'fred': { 'name': 'fred', 'age': 40 },
* 'pebbles': { 'name': 'pebbles', 'age': 1 }
* };
*
* // modifying the result cache
* var get = _.memoize(function(name) { return data[name]; }, _.identity);
* get('pebbles');
* // => { 'name': 'pebbles', 'age': 1 }
*
* get.cache.pebbles.name = 'penelope';
* get('pebbles');
* // => { 'name': 'penelope', 'age': 1 }
*/
function memoize(func, resolver) {
if (!isFunction(func)) {
throw new TypeError;
}
var memoized = function() {
var cache = memoized.cache,
key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
return hasOwnProperty.call(cache, key)
? cache[key]
: (cache[key] = func.apply(this, arguments));
}
memoized.cache = {};
return memoized;
}
/**
* Creates a function that is restricted to execute `func` once. Repeat calls to
* the function will return the value of the first call. The `func` is executed
* with the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var initialize = _.once(createApplication);
* initialize();
* initialize();
* // `initialize` executes `createApplication` once
*/
function once(func) {
var ran,
result;
if (!isFunction(func)) {
throw new TypeError;
}
return function() {
if (ran) {
return result;
}
ran = true;
result = func.apply(this, arguments);
// clear the `func` variable so the function may be garbage collected
func = null;
return result;
};
}
/**
* Creates a function that, when called, invokes `func` with any additional
* `partial` arguments prepended to those provided to the new function. This
* method is similar to `_.bind` except it does **not** alter the `this` binding.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var greet = function(greeting, name) { return greeting + ' ' + name; };
* var hi = _.partial(greet, 'hi');
* hi('fred');
* // => 'hi fred'
*/
function partial(func) {
return createWrapper(func, 16, slice(arguments, 1));
}
/**
* This method is like `_.partial` except that `partial` arguments are
* appended to those provided to the new function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var defaultsDeep = _.partialRight(_.merge, _.defaults);
*
* var options = {
* 'variable': 'data',
* 'imports': { 'jq': $ }
* };
*
* defaultsDeep(options, _.templateSettings);
*
* options.variable
* // => 'data'
*
* options.imports
* // => { '_': _, 'jq': $ }
*/
function partialRight(func) {
return createWrapper(func, 32, null, slice(arguments, 1));
}
/**
* Creates a function that, when executed, will only call the `func` function
* at most once per every `wait` milliseconds. Provide an options object to
* indicate that `func` should be invoked on the leading and/or trailing edge
* of the `wait` timeout. Subsequent calls to the throttled function will
* return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the throttled function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to throttle.
* @param {number} wait The number of milliseconds to throttle executions to.
* @param {Object} [options] The options object.
* @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
* @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
* // avoid excessively updating the position while scrolling
* var throttled = _.throttle(updatePosition, 100);
* jQuery(window).on('scroll', throttled);
*
* // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
* jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
* 'trailing': false
* }));
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (!isFunction(func)) {
throw new TypeError;
}
if (options === false) {
leading = false;
} else if (isObject(options)) {
leading = 'leading' in options ? options.leading : leading;
trailing = 'trailing' in options ? options.trailing : trailing;
}
debounceOptions.leading = leading;
debounceOptions.maxWait = wait;
debounceOptions.trailing = trailing;
return debounce(func, wait, debounceOptions);
}
/**
* Creates a function that provides `value` to the wrapper function as its
* first argument. Additional arguments provided to the function are appended
* to those provided to the wrapper function. The wrapper is executed with
* the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {*} value The value to wrap.
* @param {Function} wrapper The wrapper function.
* @returns {Function} Returns the new function.
* @example
*
* var p = _.wrap(_.escape, function(func, text) {
* return '<p>' + func(text) + '</p>';
* });
*
* p('Fred, Wilma, & Pebbles');
* // => '<p>Fred, Wilma, &amp; Pebbles</p>'
*/
function wrap(value, wrapper) {
return createWrapper(wrapper, 16, [value]);
}
/*--------------------------------------------------------------------------*/
/**
* Creates a function that returns `value`.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} value The value to return from the new function.
* @returns {Function} Returns the new function.
* @example
*
* var object = { 'name': 'fred' };
* var getter = _.constant(object);
* getter() === object;
* // => true
*/
function constant(value) {
return function() {
return value;
};
}
/**
* Produces a callback bound to an optional `thisArg`. If `func` is a property
* name the created callback will return the property value for a given element.
* If `func` is an object the created callback will return `true` for elements
* that contain the equivalent object properties, otherwise it will return `false`.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} [func=identity] The value to convert to a callback.
* @param {*} [thisArg] The `this` binding of the created callback.
* @param {number} [argCount] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // wrap to create custom callback shorthands
* _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
* var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
* return !match ? func(callback, thisArg) : function(object) {
* return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
* };
* });
*
* _.filter(characters, 'age__gt38');
* // => [{ 'name': 'fred', 'age': 40 }]
*/
function createCallback(func, thisArg, argCount) {
var type = typeof func;
if (func == null || type == 'function') {
return baseCreateCallback(func, thisArg, argCount);
}
// handle "_.pluck" style callback shorthands
if (type != 'object') {
return property(func);
}
var props = keys(func),
key = props[0],
a = func[key];
// handle "_.where" style callback shorthands
if (props.length == 1 && a === a && !isObject(a)) {
// fast path the common case of providing an object with a single
// property containing a primitive value
return function(object) {
var b = object[key];
return a === b && (a !== 0 || (1 / a == 1 / b));
};
}
return function(object) {
var length = props.length,
result = false;
while (length--) {
if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
break;
}
}
return result;
};
}
/**
* Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
* corresponding HTML entities.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} string The string to escape.
* @returns {string} Returns the escaped string.
* @example
*
* _.escape('Fred, Wilma, & Pebbles');
* // => 'Fred, Wilma, &amp; Pebbles'
*/
function escape(string) {
return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
}
/**
* This method returns the first argument provided to it.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} value Any value.
* @returns {*} Returns `value`.
* @example
*
* var object = { 'name': 'fred' };
* _.identity(object) === object;
* // => true
*/
function identity(value) {
return value;
}
/**
* Adds function properties of a source object to the destination object.
* If `object` is a function methods will be added to its prototype as well.
*
* @static
* @memberOf _
* @category Utilities
* @param {Function|Object} [object=lodash] object The destination object.
* @param {Object} source The object of functions to add.
* @param {Object} [options] The options object.
* @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
* @example
*
* function capitalize(string) {
* return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
* }
*
* _.mixin({ 'capitalize': capitalize });
* _.capitalize('fred');
* // => 'Fred'
*
* _('fred').capitalize().value();
* // => 'Fred'
*
* _.mixin({ 'capitalize': capitalize }, { 'chain': false });
* _('fred').capitalize();
* // => 'Fred'
*/
function mixin(object, source, options) {
var chain = true,
methodNames = source && functions(source);
if (!source || (!options && !methodNames.length)) {
if (options == null) {
options = source;
}
ctor = lodashWrapper;
source = object;
object = lodash;
methodNames = functions(source);
}
if (options === false) {
chain = false;
} else if (isObject(options) && 'chain' in options) {
chain = options.chain;
}
var ctor = object,
isFunc = isFunction(ctor);
forEach(methodNames, function(methodName) {
var func = object[methodName] = source[methodName];
if (isFunc) {
ctor.prototype[methodName] = function() {
var chainAll = this.__chain__,
value = this.__wrapped__,
args = [value];
push.apply(args, arguments);
var result = func.apply(object, args);
if (chain || chainAll) {
if (value === result && isObject(result)) {
return this;
}
result = new ctor(result);
result.__chain__ = chainAll;
}
return result;
};
}
});
}
/**
* Reverts the '_' variable to its previous value and returns a reference to
* the `lodash` function.
*
* @static
* @memberOf _
* @category Utilities
* @returns {Function} Returns the `lodash` function.
* @example
*
* var lodash = _.noConflict();
*/
function noConflict() {
context._ = oldDash;
return this;
}
/**
* A no-operation function.
*
* @static
* @memberOf _
* @category Utilities
* @example
*
* var object = { 'name': 'fred' };
* _.noop(object) === undefined;
* // => true
*/
function noop() {
// no operation performed
}
/**
* Gets the number of milliseconds that have elapsed since the Unix epoch
* (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @category Utilities
* @example
*
* var stamp = _.now();
* _.defer(function() { console.log(_.now() - stamp); });
* // => logs the number of milliseconds it took for the deferred function to be called
*/
var now = isNative(now = Date.now) && now || function() {
return new Date().getTime();
};
/**
* Converts the given value into an integer of the specified radix.
* If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
* `value` is a hexadecimal, in which case a `radix` of `16` is used.
*
* Note: This method avoids differences in native ES3 and ES5 `parseInt`
* implementations. See http://es5.github.io/#E.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} value The value to parse.
* @param {number} [radix] The radix used to interpret the value to parse.
* @returns {number} Returns the new integer value.
* @example
*
* _.parseInt('08');
* // => 8
*/
var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
// Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
};
/**
* Creates a "_.pluck" style function, which returns the `key` value of a
* given object.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} key The name of the property to retrieve.
* @returns {Function} Returns the new function.
* @example
*
* var characters = [
* { 'name': 'fred', 'age': 40 },
* { 'name': 'barney', 'age': 36 }
* ];
*
* var getName = _.property('name');
*
* _.map(characters, getName);
* // => ['barney', 'fred']
*
* _.sortBy(characters, getName);
* // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }]
*/
function property(key) {
return function(object) {
return object[key];
};
}
/**
* Produces a random number between `min` and `max` (inclusive). If only one
* argument is provided a number between `0` and the given number will be
* returned. If `floating` is truey or either `min` or `max` are floats a
* floating-point number will be returned instead of an integer.
*
* @static
* @memberOf _
* @category Utilities
* @param {number} [min=0] The minimum possible value.
* @param {number} [max=1] The maximum possible value.
* @param {boolean} [floating=false] Specify returning a floating-point number.
* @returns {number} Returns a random number.
* @example
*
* _.random(0, 5);
* // => an integer between 0 and 5
*
* _.random(5);
* // => also an integer between 0 and 5
*
* _.random(5, true);
* // => a floating-point number between 0 and 5
*
* _.random(1.2, 5.2);
* // => a floating-point number between 1.2 and 5.2
*/
function random(min, max, floating) {
var noMin = min == null,
noMax = max == null;
if (floating == null) {
if (typeof min == 'boolean' && noMax) {
floating = min;
min = 1;
}
else if (!noMax && typeof max == 'boolean') {
floating = max;
noMax = true;
}
}
if (noMin && noMax) {
max = 1;
}
min = +min || 0;
if (noMax) {
max = min;
min = 0;
} else {
max = +max || 0;
}
if (floating || min % 1 || max % 1) {
var rand = nativeRandom();
return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
}
return baseRandom(min, max);
}
/**
* Resolves the value of property `key` on `object`. If `key` is a function
* it will be invoked with the `this` binding of `object` and its result returned,
* else the property value is returned. If `object` is falsey then `undefined`
* is returned.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} object The object to inspect.
* @param {string} key The name of the property to resolve.
* @returns {*} Returns the resolved value.
* @example
*
* var object = {
* 'cheese': 'crumpets',
* 'stuff': function() {
* return 'nonsense';
* }
* };
*
* _.result(object, 'cheese');
* // => 'crumpets'
*
* _.result(object, 'stuff');
* // => 'nonsense'
*/
function result(object, key) {
if (object) {
var value = object[key];
return isFunction(value) ? object[key]() : value;
}
}
/**
* A micro-templating method that handles arbitrary delimiters, preserves
* whitespace, and correctly escapes quotes within interpolated code.
*
* Note: In the development build, `_.template` utilizes sourceURLs for easier
* debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
*
* For more information on precompiling templates see:
* http://lodash.com/custom-builds
*
* For more information on Chrome extension sandboxes see:
* http://developer.chrome.com/stable/extensions/sandboxingEval.html
*
* @static
* @memberOf _
* @category Utilities
* @param {string} text The template text.
* @param {Object} data The data object used to populate the text.
* @param {Object} [options] The options object.
* @param {RegExp} [options.escape] The "escape" delimiter.
* @param {RegExp} [options.evaluate] The "evaluate" delimiter.
* @param {Object} [options.imports] An object to import into the template as local variables.
* @param {RegExp} [options.interpolate] The "interpolate" delimiter.
* @param {string} [sourceURL] The sourceURL of the template's compiled source.
* @param {string} [variable] The data object variable name.
* @returns {Function|string} Returns a compiled function when no `data` object
* is given, else it returns the interpolated text.
* @example
*
* // using the "interpolate" delimiter to create a compiled template
* var compiled = _.template('hello <%= name %>');
* compiled({ 'name': 'fred' });
* // => 'hello fred'
*
* // using the "escape" delimiter to escape HTML in data property values
* _.template('<b><%- value %></b>', { 'value': '<script>' });
* // => '<b>&lt;script&gt;</b>'
*
* // using the "evaluate" delimiter to generate HTML
* var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
* _.template(list, { 'people': ['fred', 'barney'] });
* // => '<li>fred</li><li>barney</li>'
*
* // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
* _.template('hello ${ name }', { 'name': 'pebbles' });
* // => 'hello pebbles'
*
* // using the internal `print` function in "evaluate" delimiters
* _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
* // => 'hello barney!'
*
* // using a custom template delimiters
* _.templateSettings = {
* 'interpolate': /{{([\s\S]+?)}}/g
* };
*
* _.template('hello {{ name }}!', { 'name': 'mustache' });
* // => 'hello mustache!'
*
* // using the `imports` option to import jQuery
* var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
* _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
* // => '<li>fred</li><li>barney</li>'
*
* // using the `sourceURL` option to specify a custom sourceURL for the template
* var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
* compiled(data);
* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
*
* // using the `variable` option to ensure a with-statement isn't used in the compiled template
* var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
* compiled.source;
* // => function(data) {
* var __t, __p = '', __e = _.escape;
* __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
* return __p;
* }
*
* // using the `source` property to inline compiled templates for meaningful
* // line numbers in error messages and a stack trace
* fs.writeFileSync(path.join(cwd, 'jst.js'), '\
* var JST = {\
* "main": ' + _.template(mainText).source + '\
* };\
* ');
*/
function template(text, data, options) {
// based on John Resig's `tmpl` implementation
// http://ejohn.org/blog/javascript-micro-templating/
// and Laura Doktorova's doT.js
// https://github.com/olado/doT
var settings = lodash.templateSettings;
text = String(text || '');
// avoid missing dependencies when `iteratorTemplate` is not defined
options = defaults({}, options, settings);
var imports = defaults({}, options.imports, settings.imports),
importsKeys = keys(imports),
importsValues = values(imports);
var isEvaluating,
index = 0,
interpolate = options.interpolate || reNoMatch,
source = "__p += '";
// compile the regexp to match each delimiter
var reDelimiters = RegExp(
(options.escape || reNoMatch).source + '|' +
interpolate.source + '|' +
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
(options.evaluate || reNoMatch).source + '|$'
, 'g');
text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
interpolateValue || (interpolateValue = esTemplateValue);
// escape characters that cannot be included in string literals
source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
// replace delimiters with snippets
if (escapeValue) {
source += "' +\n__e(" + escapeValue + ") +\n'";
}
if (evaluateValue) {
isEvaluating = true;
source += "';\n" + evaluateValue + ";\n__p += '";
}
if (interpolateValue) {
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
}
index = offset + match.length;
// the JS engine embedded in Adobe products requires returning the `match`
// string in order to produce the correct `offset` value
return match;
});
source += "';\n";
// if `variable` is not specified, wrap a with-statement around the generated
// code to add the data object to the top of the scope chain
var variable = options.variable,
hasVariable = variable;
if (!hasVariable) {
variable = 'obj';
source = 'with (' + variable + ') {\n' + source + '\n}\n';
}
// cleanup code by stripping empty strings
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
.replace(reEmptyStringMiddle, '$1')
.replace(reEmptyStringTrailing, '$1;');
// frame code as the function body
source = 'function(' + variable + ') {\n' +
(hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
"var __t, __p = '', __e = _.escape" +
(isEvaluating
? ', __j = Array.prototype.join;\n' +
"function print() { __p += __j.call(arguments, '') }\n"
: ';\n'
) +
source +
'return __p\n}';
// Use a sourceURL for easier debugging.
// http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
try {
var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
} catch(e) {
e.source = source;
throw e;
}
if (data) {
return result(data);
}
// provide the compiled function's source by its `toString` method, in
// supported environments, or the `source` property as a convenience for
// inlining compiled templates during the build process
result.source = source;
return result;
}
/**
* Executes the callback `n` times, returning an array of the results
* of each callback execution. The callback is bound to `thisArg` and invoked
* with one argument; (index).
*
* @static
* @memberOf _
* @category Utilities
* @param {number} n The number of times to execute the callback.
* @param {Function} callback The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns an array of the results of each `callback` execution.
* @example
*
* var diceRolls = _.times(3, _.partial(_.random, 1, 6));
* // => [3, 6, 4]
*
* _.times(3, function(n) { mage.castSpell(n); });
* // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
*
* _.times(3, function(n) { this.cast(n); }, mage);
* // => also calls `mage.castSpell(n)` three times
*/
function times(n, callback, thisArg) {
n = (n = +n) > -1 ? n : 0;
var index = -1,
result = Array(n);
callback = baseCreateCallback(callback, thisArg, 1);
while (++index < n) {
result[index] = callback(index);
}
return result;
}
/**
* The inverse of `_.escape` this method converts the HTML entities
* `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
* corresponding characters.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} string The string to unescape.
* @returns {string} Returns the unescaped string.
* @example
*
* _.unescape('Fred, Barney &amp; Pebbles');
* // => 'Fred, Barney & Pebbles'
*/
function unescape(string) {
return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
}
/**
* Generates a unique ID. If `prefix` is provided the ID will be appended to it.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} [prefix] The value to prefix the ID with.
* @returns {string} Returns the unique ID.
* @example
*
* _.uniqueId('contact_');
* // => 'contact_104'
*
* _.uniqueId();
* // => '105'
*/
function uniqueId(prefix) {
var id = ++idCounter;
return String(prefix == null ? '' : prefix) + id;
}
/*--------------------------------------------------------------------------*/
/**
* Creates a `lodash` object that wraps the given value with explicit
* method chaining enabled.
*
* @static
* @memberOf _
* @category Chaining
* @param {*} value The value to wrap.
* @returns {Object} Returns the wrapper object.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 },
* { 'name': 'pebbles', 'age': 1 }
* ];
*
* var youngest = _.chain(characters)
* .sortBy('age')
* .map(function(chr) { return chr.name + ' is ' + chr.age; })
* .first()
* .value();
* // => 'pebbles is 1'
*/
function chain(value) {
value = new lodashWrapper(value);
value.__chain__ = true;
return value;
}
/**
* Invokes `interceptor` with the `value` as the first argument and then
* returns `value`. The purpose of this method is to "tap into" a method
* chain in order to perform operations on intermediate results within
* the chain.
*
* @static
* @memberOf _
* @category Chaining
* @param {*} value The value to provide to `interceptor`.
* @param {Function} interceptor The function to invoke.
* @returns {*} Returns `value`.
* @example
*
* _([1, 2, 3, 4])
* .tap(function(array) { array.pop(); })
* .reverse()
* .value();
* // => [3, 2, 1]
*/
function tap(value, interceptor) {
interceptor(value);
return value;
}
/**
* Enables explicit method chaining on the wrapper object.
*
* @name chain
* @memberOf _
* @category Chaining
* @returns {*} Returns the wrapper object.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // without explicit chaining
* _(characters).first();
* // => { 'name': 'barney', 'age': 36 }
*
* // with explicit chaining
* _(characters).chain()
* .first()
* .pick('age')
* .value();
* // => { 'age': 36 }
*/
function wrapperChain() {
this.__chain__ = true;
return this;
}
/**
* Produces the `toString` result of the wrapped value.
*
* @name toString
* @memberOf _
* @category Chaining
* @returns {string} Returns the string result.
* @example
*
* _([1, 2, 3]).toString();
* // => '1,2,3'
*/
function wrapperToString() {
return String(this.__wrapped__);
}
/**
* Extracts the wrapped value.
*
* @name valueOf
* @memberOf _
* @alias value
* @category Chaining
* @returns {*} Returns the wrapped value.
* @example
*
* _([1, 2, 3]).valueOf();
* // => [1, 2, 3]
*/
function wrapperValueOf() {
return this.__wrapped__;
}
/*--------------------------------------------------------------------------*/
// add functions that return wrapped values when chaining
lodash.after = after;
lodash.assign = assign;
lodash.at = at;
lodash.bind = bind;
lodash.bindAll = bindAll;
lodash.bindKey = bindKey;
lodash.chain = chain;
lodash.compact = compact;
lodash.compose = compose;
lodash.constant = constant;
lodash.countBy = countBy;
lodash.create = create;
lodash.createCallback = createCallback;
lodash.curry = curry;
lodash.debounce = debounce;
lodash.defaults = defaults;
lodash.defer = defer;
lodash.delay = delay;
lodash.difference = difference;
lodash.filter = filter;
lodash.flatten = flatten;
lodash.forEach = forEach;
lodash.forEachRight = forEachRight;
lodash.forIn = forIn;
lodash.forInRight = forInRight;
lodash.forOwn = forOwn;
lodash.forOwnRight = forOwnRight;
lodash.functions = functions;
lodash.groupBy = groupBy;
lodash.indexBy = indexBy;
lodash.initial = initial;
lodash.intersection = intersection;
lodash.invert = invert;
lodash.invoke = invoke;
lodash.keys = keys;
lodash.map = map;
lodash.mapValues = mapValues;
lodash.max = max;
lodash.memoize = memoize;
lodash.merge = merge;
lodash.min = min;
lodash.omit = omit;
lodash.once = once;
lodash.pairs = pairs;
lodash.partial = partial;
lodash.partialRight = partialRight;
lodash.pick = pick;
lodash.pluck = pluck;
lodash.property = property;
lodash.pull = pull;
lodash.range = range;
lodash.reject = reject;
lodash.remove = remove;
lodash.rest = rest;
lodash.shuffle = shuffle;
lodash.sortBy = sortBy;
lodash.tap = tap;
lodash.throttle = throttle;
lodash.times = times;
lodash.toArray = toArray;
lodash.transform = transform;
lodash.union = union;
lodash.uniq = uniq;
lodash.values = values;
lodash.where = where;
lodash.without = without;
lodash.wrap = wrap;
lodash.xor = xor;
lodash.zip = zip;
lodash.zipObject = zipObject;
// add aliases
lodash.collect = map;
lodash.drop = rest;
lodash.each = forEach;
lodash.eachRight = forEachRight;
lodash.extend = assign;
lodash.methods = functions;
lodash.object = zipObject;
lodash.select = filter;
lodash.tail = rest;
lodash.unique = uniq;
lodash.unzip = zip;
// add functions to `lodash.prototype`
mixin(lodash);
/*--------------------------------------------------------------------------*/
// add functions that return unwrapped values when chaining
lodash.clone = clone;
lodash.cloneDeep = cloneDeep;
lodash.contains = contains;
lodash.escape = escape;
lodash.every = every;
lodash.find = find;
lodash.findIndex = findIndex;
lodash.findKey = findKey;
lodash.findLast = findLast;
lodash.findLastIndex = findLastIndex;
lodash.findLastKey = findLastKey;
lodash.has = has;
lodash.identity = identity;
lodash.indexOf = indexOf;
lodash.isArguments = isArguments;
lodash.isArray = isArray;
lodash.isBoolean = isBoolean;
lodash.isDate = isDate;
lodash.isElement = isElement;
lodash.isEmpty = isEmpty;
lodash.isEqual = isEqual;
lodash.isFinite = isFinite;
lodash.isFunction = isFunction;
lodash.isNaN = isNaN;
lodash.isNull = isNull;
lodash.isNumber = isNumber;
lodash.isObject = isObject;
lodash.isPlainObject = isPlainObject;
lodash.isRegExp = isRegExp;
lodash.isString = isString;
lodash.isUndefined = isUndefined;
lodash.lastIndexOf = lastIndexOf;
lodash.mixin = mixin;
lodash.noConflict = noConflict;
lodash.noop = noop;
lodash.now = now;
lodash.parseInt = parseInt;
lodash.random = random;
lodash.reduce = reduce;
lodash.reduceRight = reduceRight;
lodash.result = result;
lodash.runInContext = runInContext;
lodash.size = size;
lodash.some = some;
lodash.sortedIndex = sortedIndex;
lodash.template = template;
lodash.unescape = unescape;
lodash.uniqueId = uniqueId;
// add aliases
lodash.all = every;
lodash.any = some;
lodash.detect = find;
lodash.findWhere = find;
lodash.foldl = reduce;
lodash.foldr = reduceRight;
lodash.include = contains;
lodash.inject = reduce;
mixin(function() {
var source = {}
forOwn(lodash, function(func, methodName) {
if (!lodash.prototype[methodName]) {
source[methodName] = func;
}
});
return source;
}(), false);
/*--------------------------------------------------------------------------*/
// add functions capable of returning wrapped and unwrapped values when chaining
lodash.first = first;
lodash.last = last;
lodash.sample = sample;
// add aliases
lodash.take = first;
lodash.head = first;
forOwn(lodash, function(func, methodName) {
var callbackable = methodName !== 'sample';
if (!lodash.prototype[methodName]) {
lodash.prototype[methodName]= function(n, guard) {
var chainAll = this.__chain__,
result = func(this.__wrapped__, n, guard);
return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
? result
: new lodashWrapper(result, chainAll);
};
}
});
/*--------------------------------------------------------------------------*/
/**
* The semantic version number.
*
* @static
* @memberOf _
* @type string
*/
lodash.VERSION = '2.4.1';
// add "Chaining" functions to the wrapper
lodash.prototype.chain = wrapperChain;
lodash.prototype.toString = wrapperToString;
lodash.prototype.value = wrapperValueOf;
lodash.prototype.valueOf = wrapperValueOf;
// add `Array` functions that return unwrapped values
forEach(['join', 'pop', 'shift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
var chainAll = this.__chain__,
result = func.apply(this.__wrapped__, arguments);
return chainAll
? new lodashWrapper(result, chainAll)
: result;
};
});
// add `Array` functions that return the existing wrapped value
forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
func.apply(this.__wrapped__, arguments);
return this;
};
});
// add `Array` functions that return new wrapped values
forEach(['concat', 'slice', 'splice'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
};
});
return lodash;
}
/*--------------------------------------------------------------------------*/
// expose Lo-Dash
var _ = runInContext();
// some AMD build optimizers like r.js check for condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Expose Lo-Dash to the global object even when an AMD loader is present in
// case Lo-Dash is loaded with a RequireJS shim config.
// See http://requirejs.org/docs/api.html#config-shim
root._ = _;
// define as an anonymous module so, through path mapping, it can be
// referenced as the "underscore" module
define(function() {
return _;
});
}
// check for `exports` after `define` in case a build optimizer adds an `exports` object
else if (freeExports && freeModule) {
// in Node.js or RingoJS
if (moduleExports) {
(freeModule.exports = _)._ = _;
}
// in Narwhal or Rhino -require
else {
freeExports._ = _;
}
}
else {
// in a browser or Rhino
root._ = _;
}
}.call(this));
// wrapper for non-node envs
;(function (sax) {
sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
sax.SAXParser = SAXParser
sax.SAXStream = SAXStream
sax.createStream = createStream
// When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
// When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
// since that's the earliest that a buffer overrun could occur. This way, checks are
// as rare as required, but as often as necessary to ensure never crossing this bound.
// Furthermore, buffers are only tested at most once per write(), so passing a very
// large string into write() might have undesirable effects, but this is manageable by
// the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme
// edge case, result in creating at most one complete copy of the string passed in.
// Set to Infinity to have unlimited buffers.
sax.MAX_BUFFER_LENGTH = 64 * 1024
var buffers = [
"comment", "sgmlDecl", "textNode", "tagName", "doctype",
"procInstName", "procInstBody", "entity", "attribName",
"attribValue", "cdata", "script"
]
sax.EVENTS = // for discoverability.
[ "text"
, "processinginstruction"
, "sgmldeclaration"
, "doctype"
, "comment"
, "attribute"
, "opentag"
, "closetag"
, "opencdata"
, "cdata"
, "closecdata"
, "error"
, "end"
, "ready"
, "script"
, "opennamespace"
, "closenamespace"
]
function SAXParser (strict, opt) {
if (!(this instanceof SAXParser)) return new SAXParser(strict, opt)
var parser = this
clearBuffers(parser)
parser.q = parser.c = ""
parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
parser.opt = opt || {}
parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
parser.looseCase = parser.opt.lowercase ? "toLowerCase" : "toUpperCase"
parser.tags = []
parser.closed = parser.closedRoot = parser.sawRoot = false
parser.tag = parser.error = null
parser.strict = !!strict
parser.noscript = !!(strict || parser.opt.noscript)
parser.state = S.BEGIN
parser.ENTITIES = Object.create(sax.ENTITIES)
parser.attribList = []
// namespaces form a prototype chain.
// it always points at the current tag,
// which protos to its parent tag.
if (parser.opt.xmlns) parser.ns = Object.create(rootNS)
// mostly just for error reporting
parser.trackPosition = parser.opt.position !== false
if (parser.trackPosition) {
parser.position = parser.line = parser.column = 0
}
emit(parser, "onready")
}
if (!Object.create) Object.create = function (o) {
function f () { this.__proto__ = o }
f.prototype = o
return new f
}
if (!Object.getPrototypeOf) Object.getPrototypeOf = function (o) {
return o.__proto__
}
if (!Object.keys) Object.keys = function (o) {
var a = []
for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
return a
}
function checkBufferLength (parser) {
var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
, maxActual = 0
for (var i = 0, l = buffers.length; i < l; i ++) {
var len = parser[buffers[i]].length
if (len > maxAllowed) {
// Text/cdata nodes can get big, and since they're buffered,
// we can get here under normal conditions.
// Avoid issues by emitting the text node now,
// so at least it won't get any bigger.
switch (buffers[i]) {
case "textNode":
closeText(parser)
break
case "cdata":
emitNode(parser, "oncdata", parser.cdata)
parser.cdata = ""
break
case "script":
emitNode(parser, "onscript", parser.script)
parser.script = ""
break
default:
error(parser, "Max buffer length exceeded: "+buffers[i])
}
}
maxActual = Math.max(maxActual, len)
}
// schedule the next check for the earliest possible buffer overrun.
parser.bufferCheckPosition = (sax.MAX_BUFFER_LENGTH - maxActual)
+ parser.position
}
function clearBuffers (parser) {
for (var i = 0, l = buffers.length; i < l; i ++) {
parser[buffers[i]] = ""
}
}
function flushBuffers (parser) {
closeText(parser)
if (parser.cdata !== "") {
emitNode(parser, "oncdata", parser.cdata)
parser.cdata = ""
}
if (parser.script !== "") {
emitNode(parser, "onscript", parser.script)
parser.script = ""
}
}
SAXParser.prototype =
{ end: function () { end(this) }
, write: write
, resume: function () { this.error = null; return this }
, close: function () { return this.write(null) }
, flush: function () { flushBuffers(this) }
}
try {
var Stream = require("stream").Stream
} catch (ex) {
var Stream = function () {}
}
var streamWraps = sax.EVENTS.filter(function (ev) {
return ev !== "error" && ev !== "end"
})
function createStream (strict, opt) {
return new SAXStream(strict, opt)
}
function SAXStream (strict, opt) {
if (!(this instanceof SAXStream)) return new SAXStream(strict, opt)
Stream.apply(this)
this._parser = new SAXParser(strict, opt)
this.writable = true
this.readable = true
var me = this
this._parser.onend = function () {
me.emit("end")
}
this._parser.onerror = function (er) {
me.emit("error", er)
// if didn't throw, then means error was handled.
// go ahead and clear error, so we can write again.
me._parser.error = null
}
this._decoder = null;
streamWraps.forEach(function (ev) {
Object.defineProperty(me, "on" + ev, {
get: function () { return me._parser["on" + ev] },
set: function (h) {
if (!h) {
me.removeAllListeners(ev)
return me._parser["on"+ev] = h
}
me.on(ev, h)
},
enumerable: true,
configurable: false
})
})
}
SAXStream.prototype = Object.create(Stream.prototype,
{ constructor: { value: SAXStream } })
SAXStream.prototype.write = function (data) {
if (typeof Buffer === 'function' &&
typeof Buffer.isBuffer === 'function' &&
Buffer.isBuffer(data)) {
if (!this._decoder) {
var SD = require('string_decoder').StringDecoder
this._decoder = new SD('utf8')
}
data = this._decoder.write(data);
}
this._parser.write(data.toString())
this.emit("data", data)
return true
}
SAXStream.prototype.end = function (chunk) {
if (chunk && chunk.length) this.write(chunk)
this._parser.end()
return true
}
SAXStream.prototype.on = function (ev, handler) {
var me = this
if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) {
me._parser["on"+ev] = function () {
var args = arguments.length === 1 ? [arguments[0]]
: Array.apply(null, arguments)
args.splice(0, 0, ev)
me.emit.apply(me, args)
}
}
return Stream.prototype.on.call(me, ev, handler)
}
// character classes and tokens
var whitespace = "\r\n\t "
// this really needs to be replaced with character classes.
// XML allows all manner of ridiculous numbers and digits.
, number = "0124356789"
, letter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// (Letter | "_" | ":")
, quote = "'\""
, entity = number+letter+"#"
, attribEnd = whitespace + ">"
, CDATA = "[CDATA["
, DOCTYPE = "DOCTYPE"
, XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"
, XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/"
, rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }
// turn all the string character sets into character class objects.
whitespace = charClass(whitespace)
number = charClass(number)
letter = charClass(letter)
// http://www.w3.org/TR/REC-xml/#NT-NameStartChar
// This implementation works on strings, a single character at a time
// as such, it cannot ever support astral-plane characters (10000-EFFFF)
// without a significant breaking change to either this parser, or the
// JavaScript language. Implementation of an emoji-capable xml parser
// is left as an exercise for the reader.
var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040\.\d-]/
quote = charClass(quote)
entity = charClass(entity)
attribEnd = charClass(attribEnd)
function charClass (str) {
return str.split("").reduce(function (s, c) {
s[c] = true
return s
}, {})
}
function isRegExp (c) {
return Object.prototype.toString.call(c) === '[object RegExp]'
}
function is (charclass, c) {
return isRegExp(charclass) ? !!c.match(charclass) : charclass[c]
}
function not (charclass, c) {
return !is(charclass, c)
}
var S = 0
sax.STATE =
{ BEGIN : S++
, TEXT : S++ // general stuff
, TEXT_ENTITY : S++ // &amp and such.
, OPEN_WAKA : S++ // <
, SGML_DECL : S++ // <!BLARG
, SGML_DECL_QUOTED : S++ // <!BLARG foo "bar
, DOCTYPE : S++ // <!DOCTYPE
, DOCTYPE_QUOTED : S++ // <!DOCTYPE "//blah
, DOCTYPE_DTD : S++ // <!DOCTYPE "//blah" [ ...
, DOCTYPE_DTD_QUOTED : S++ // <!DOCTYPE "//blah" [ "foo
, COMMENT_STARTING : S++ // <!-
, COMMENT : S++ // <!--
, COMMENT_ENDING : S++ // <!-- blah -
, COMMENT_ENDED : S++ // <!-- blah --
, CDATA : S++ // <![CDATA[ something
, CDATA_ENDING : S++ // ]
, CDATA_ENDING_2 : S++ // ]]
, PROC_INST : S++ // <?hi
, PROC_INST_BODY : S++ // <?hi there
, PROC_INST_ENDING : S++ // <?hi "there" ?
, OPEN_TAG : S++ // <strong
, OPEN_TAG_SLASH : S++ // <strong /
, ATTRIB : S++ // <a
, ATTRIB_NAME : S++ // <a foo
, ATTRIB_NAME_SAW_WHITE : S++ // <a foo _
, ATTRIB_VALUE : S++ // <a foo=
, ATTRIB_VALUE_QUOTED : S++ // <a foo="bar
, ATTRIB_VALUE_CLOSED : S++ // <a foo="bar"
, ATTRIB_VALUE_UNQUOTED : S++ // <a foo=bar
, ATTRIB_VALUE_ENTITY_Q : S++ // <foo bar="&quot;"
, ATTRIB_VALUE_ENTITY_U : S++ // <foo bar=&quot;
, CLOSE_TAG : S++ // </a
, CLOSE_TAG_SAW_WHITE : S++ // </a >
, SCRIPT : S++ // <script> ...
, SCRIPT_ENDING : S++ // <script> ... <
}
sax.ENTITIES =
{ "amp" : "&"
, "gt" : ">"
, "lt" : "<"
, "quot" : "\""
, "apos" : "'"
, "AElig" : 198
, "Aacute" : 193
, "Acirc" : 194
, "Agrave" : 192
, "Aring" : 197
, "Atilde" : 195
, "Auml" : 196
, "Ccedil" : 199
, "ETH" : 208
, "Eacute" : 201
, "Ecirc" : 202
, "Egrave" : 200
, "Euml" : 203
, "Iacute" : 205
, "Icirc" : 206
, "Igrave" : 204
, "Iuml" : 207
, "Ntilde" : 209
, "Oacute" : 211
, "Ocirc" : 212
, "Ograve" : 210
, "Oslash" : 216
, "Otilde" : 213
, "Ouml" : 214
, "THORN" : 222
, "Uacute" : 218
, "Ucirc" : 219
, "Ugrave" : 217
, "Uuml" : 220
, "Yacute" : 221
, "aacute" : 225
, "acirc" : 226
, "aelig" : 230
, "agrave" : 224
, "aring" : 229
, "atilde" : 227
, "auml" : 228
, "ccedil" : 231
, "eacute" : 233
, "ecirc" : 234
, "egrave" : 232
, "eth" : 240
, "euml" : 235
, "iacute" : 237
, "icirc" : 238
, "igrave" : 236
, "iuml" : 239
, "ntilde" : 241
, "oacute" : 243
, "ocirc" : 244
, "ograve" : 242
, "oslash" : 248
, "otilde" : 245
, "ouml" : 246
, "szlig" : 223
, "thorn" : 254
, "uacute" : 250
, "ucirc" : 251
, "ugrave" : 249
, "uuml" : 252
, "yacute" : 253
, "yuml" : 255
, "copy" : 169
, "reg" : 174
, "nbsp" : 160
, "iexcl" : 161
, "cent" : 162
, "pound" : 163
, "curren" : 164
, "yen" : 165
, "brvbar" : 166
, "sect" : 167
, "uml" : 168
, "ordf" : 170
, "laquo" : 171
, "not" : 172
, "shy" : 173
, "macr" : 175
, "deg" : 176
, "plusmn" : 177
, "sup1" : 185
, "sup2" : 178
, "sup3" : 179
, "acute" : 180
, "micro" : 181
, "para" : 182
, "middot" : 183
, "cedil" : 184
, "ordm" : 186
, "raquo" : 187
, "frac14" : 188
, "frac12" : 189
, "frac34" : 190
, "iquest" : 191
, "times" : 215
, "divide" : 247
, "OElig" : 338
, "oelig" : 339
, "Scaron" : 352
, "scaron" : 353
, "Yuml" : 376
, "fnof" : 402
, "circ" : 710
, "tilde" : 732
, "Alpha" : 913
, "Beta" : 914
, "Gamma" : 915
, "Delta" : 916
, "Epsilon" : 917
, "Zeta" : 918
, "Eta" : 919
, "Theta" : 920
, "Iota" : 921
, "Kappa" : 922
, "Lambda" : 923
, "Mu" : 924
, "Nu" : 925
, "Xi" : 926
, "Omicron" : 927
, "Pi" : 928
, "Rho" : 929
, "Sigma" : 931
, "Tau" : 932
, "Upsilon" : 933
, "Phi" : 934
, "Chi" : 935
, "Psi" : 936
, "Omega" : 937
, "alpha" : 945
, "beta" : 946
, "gamma" : 947
, "delta" : 948
, "epsilon" : 949
, "zeta" : 950
, "eta" : 951
, "theta" : 952
, "iota" : 953
, "kappa" : 954
, "lambda" : 955
, "mu" : 956
, "nu" : 957
, "xi" : 958
, "omicron" : 959
, "pi" : 960
, "rho" : 961
, "sigmaf" : 962
, "sigma" : 963
, "tau" : 964
, "upsilon" : 965
, "phi" : 966
, "chi" : 967
, "psi" : 968
, "omega" : 969
, "thetasym" : 977
, "upsih" : 978
, "piv" : 982
, "ensp" : 8194
, "emsp" : 8195
, "thinsp" : 8201
, "zwnj" : 8204
, "zwj" : 8205
, "lrm" : 8206
, "rlm" : 8207
, "ndash" : 8211
, "mdash" : 8212
, "lsquo" : 8216
, "rsquo" : 8217
, "sbquo" : 8218
, "ldquo" : 8220
, "rdquo" : 8221
, "bdquo" : 8222
, "dagger" : 8224
, "Dagger" : 8225
, "bull" : 8226
, "hellip" : 8230
, "permil" : 8240
, "prime" : 8242
, "Prime" : 8243
, "lsaquo" : 8249
, "rsaquo" : 8250
, "oline" : 8254
, "frasl" : 8260
, "euro" : 8364
, "image" : 8465
, "weierp" : 8472
, "real" : 8476
, "trade" : 8482
, "alefsym" : 8501
, "larr" : 8592
, "uarr" : 8593
, "rarr" : 8594
, "darr" : 8595
, "harr" : 8596
, "crarr" : 8629
, "lArr" : 8656
, "uArr" : 8657
, "rArr" : 8658
, "dArr" : 8659
, "hArr" : 8660
, "forall" : 8704
, "part" : 8706
, "exist" : 8707
, "empty" : 8709
, "nabla" : 8711
, "isin" : 8712
, "notin" : 8713
, "ni" : 8715
, "prod" : 8719
, "sum" : 8721
, "minus" : 8722
, "lowast" : 8727
, "radic" : 8730
, "prop" : 8733
, "infin" : 8734
, "ang" : 8736
, "and" : 8743
, "or" : 8744
, "cap" : 8745
, "cup" : 8746
, "int" : 8747
, "there4" : 8756
, "sim" : 8764
, "cong" : 8773
, "asymp" : 8776
, "ne" : 8800
, "equiv" : 8801
, "le" : 8804
, "ge" : 8805
, "sub" : 8834
, "sup" : 8835
, "nsub" : 8836
, "sube" : 8838
, "supe" : 8839
, "oplus" : 8853
, "otimes" : 8855
, "perp" : 8869
, "sdot" : 8901
, "lceil" : 8968
, "rceil" : 8969
, "lfloor" : 8970
, "rfloor" : 8971
, "lang" : 9001
, "rang" : 9002
, "loz" : 9674
, "spades" : 9824
, "clubs" : 9827
, "hearts" : 9829
, "diams" : 9830
}
Object.keys(sax.ENTITIES).forEach(function (key) {
var e = sax.ENTITIES[key]
var s = typeof e === 'number' ? String.fromCharCode(e) : e
sax.ENTITIES[key] = s
})
for (var S in sax.STATE) sax.STATE[sax.STATE[S]] = S
// shorthand
S = sax.STATE
function emit (parser, event, data) {
parser[event] && parser[event](data)
}
function emitNode (parser, nodeType, data) {
if (parser.textNode) closeText(parser)
emit(parser, nodeType, data)
}
function closeText (parser) {
parser.textNode = textopts(parser.opt, parser.textNode)
if (parser.textNode) emit(parser, "ontext", parser.textNode)
parser.textNode = ""
}
function textopts (opt, text) {
if (opt.trim) text = text.trim()
if (opt.normalize) text = text.replace(/\s+/g, " ")
return text
}
function error (parser, er) {
closeText(parser)
if (parser.trackPosition) {
er += "\nLine: "+parser.line+
"\nColumn: "+parser.column+
"\nChar: "+parser.c
}
er = new Error(er)
parser.error = er
emit(parser, "onerror", er)
return parser
}
function end (parser) {
if (!parser.closedRoot) strictFail(parser, "Unclosed root tag")
if ((parser.state !== S.BEGIN) && (parser.state !== S.TEXT)) error(parser, "Unexpected end")
closeText(parser)
parser.c = ""
parser.closed = true
emit(parser, "onend")
SAXParser.call(parser, parser.strict, parser.opt)
return parser
}
function strictFail (parser, message) {
if (typeof parser !== 'object' || !(parser instanceof SAXParser))
throw new Error('bad call to strictFail');
if (parser.strict) error(parser, message)
}
function newTag (parser) {
if (!parser.strict) parser.tagName = parser.tagName[parser.looseCase]()
var parent = parser.tags[parser.tags.length - 1] || parser
, tag = parser.tag = { name : parser.tagName, attributes : {} }
// will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
if (parser.opt.xmlns) tag.ns = parent.ns
parser.attribList.length = 0
}
function qname (name, attribute) {
var i = name.indexOf(":")
, qualName = i < 0 ? [ "", name ] : name.split(":")
, prefix = qualName[0]
, local = qualName[1]
// <x "xmlns"="http://foo">
if (attribute && name === "xmlns") {
prefix = "xmlns"
local = ""
}
return { prefix: prefix, local: local }
}
function attrib (parser) {
if (!parser.strict) parser.attribName = parser.attribName[parser.looseCase]()
if (parser.attribList.indexOf(parser.attribName) !== -1 ||
parser.tag.attributes.hasOwnProperty(parser.attribName)) {
return parser.attribName = parser.attribValue = ""
}
if (parser.opt.xmlns) {
var qn = qname(parser.attribName, true)
, prefix = qn.prefix
, local = qn.local
if (prefix === "xmlns") {
// namespace binding attribute; push the binding into scope
if (local === "xml" && parser.attribValue !== XML_NAMESPACE) {
strictFail( parser
, "xml: prefix must be bound to " + XML_NAMESPACE + "\n"
+ "Actual: " + parser.attribValue )
} else if (local === "xmlns" && parser.attribValue !== XMLNS_NAMESPACE) {
strictFail( parser
, "xmlns: prefix must be bound to " + XMLNS_NAMESPACE + "\n"
+ "Actual: " + parser.attribValue )
} else {
var tag = parser.tag
, parent = parser.tags[parser.tags.length - 1] || parser
if (tag.ns === parent.ns) {
tag.ns = Object.create(parent.ns)
}
tag.ns[local] = parser.attribValue
}
}
// defer onattribute events until all attributes have been seen
// so any new bindings can take effect; preserve attribute order
// so deferred events can be emitted in document order
parser.attribList.push([parser.attribName, parser.attribValue])
} else {
// in non-xmlns mode, we can emit the event right away
parser.tag.attributes[parser.attribName] = parser.attribValue
emitNode( parser
, "onattribute"
, { name: parser.attribName
, value: parser.attribValue } )
}
parser.attribName = parser.attribValue = ""
}
function openTag (parser, selfClosing) {
if (parser.opt.xmlns) {
// emit namespace binding events
var tag = parser.tag
// add namespace info to tag
var qn = qname(parser.tagName)
tag.prefix = qn.prefix
tag.local = qn.local
tag.uri = tag.ns[qn.prefix] || ""
if (tag.prefix && !tag.uri) {
strictFail(parser, "Unbound namespace prefix: "
+ JSON.stringify(parser.tagName))
tag.uri = qn.prefix
}
var parent = parser.tags[parser.tags.length - 1] || parser
if (tag.ns && parent.ns !== tag.ns) {
Object.keys(tag.ns).forEach(function (p) {
emitNode( parser
, "onopennamespace"
, { prefix: p , uri: tag.ns[p] } )
})
}
// handle deferred onattribute events
// Note: do not apply default ns to attributes:
// http://www.w3.org/TR/REC-xml-names/#defaulting
for (var i = 0, l = parser.attribList.length; i < l; i ++) {
var nv = parser.attribList[i]
var name = nv[0]
, value = nv[1]
, qualName = qname(name, true)
, prefix = qualName.prefix
, local = qualName.local
, uri = prefix == "" ? "" : (tag.ns[prefix] || "")
, a = { name: name
, value: value
, prefix: prefix
, local: local
, uri: uri
}
// if there's any attributes with an undefined namespace,
// then fail on them now.
if (prefix && prefix != "xmlns" && !uri) {
strictFail(parser, "Unbound namespace prefix: "
+ JSON.stringify(prefix))
a.uri = prefix
}
parser.tag.attributes[name] = a
emitNode(parser, "onattribute", a)
}
parser.attribList.length = 0
}
parser.tag.isSelfClosing = !!selfClosing
// process the tag
parser.sawRoot = true
parser.tags.push(parser.tag)
emitNode(parser, "onopentag", parser.tag)
if (!selfClosing) {
// special case for <script> in non-strict mode.
if (!parser.noscript && parser.tagName.toLowerCase() === "script") {
parser.state = S.SCRIPT
} else {
parser.state = S.TEXT
}
parser.tag = null
parser.tagName = ""
}
parser.attribName = parser.attribValue = ""
parser.attribList.length = 0
}
function closeTag (parser) {
if (!parser.tagName) {
strictFail(parser, "Weird empty close tag.")
parser.textNode += "</>"
parser.state = S.TEXT
return
}
if (parser.script) {
if (parser.tagName !== "script") {
parser.script += "</" + parser.tagName + ">"
parser.tagName = ""
parser.state = S.SCRIPT
return
}
emitNode(parser, "onscript", parser.script)
parser.script = ""
}
// first make sure that the closing tag actually exists.
// <a><b></c></b></a> will close everything, otherwise.
var t = parser.tags.length
var tagName = parser.tagName
if (!parser.strict) tagName = tagName[parser.looseCase]()
var closeTo = tagName
while (t --) {
var close = parser.tags[t]
if (close.name !== closeTo) {
// fail the first time in strict mode
strictFail(parser, "Unexpected close tag")
} else break
}
// didn't find it. we already failed for strict, so just abort.
if (t < 0) {
strictFail(parser, "Unmatched closing tag: "+parser.tagName)
parser.textNode += "</" + parser.tagName + ">"
parser.state = S.TEXT
return
}
parser.tagName = tagName
var s = parser.tags.length
while (s --> t) {
var tag = parser.tag = parser.tags.pop()
parser.tagName = parser.tag.name
emitNode(parser, "onclosetag", parser.tagName)
var x = {}
for (var i in tag.ns) x[i] = tag.ns[i]
var parent = parser.tags[parser.tags.length - 1] || parser
if (parser.opt.xmlns && tag.ns !== parent.ns) {
// remove namespace bindings introduced by tag
Object.keys(tag.ns).forEach(function (p) {
var n = tag.ns[p]
emitNode(parser, "onclosenamespace", { prefix: p, uri: n })
})
}
}
if (t === 0) parser.closedRoot = true
parser.tagName = parser.attribValue = parser.attribName = ""
parser.attribList.length = 0
parser.state = S.TEXT
}
function parseEntity (parser) {
var entity = parser.entity
, entityLC = entity.toLowerCase()
, num
, numStr = ""
if (parser.ENTITIES[entity])
return parser.ENTITIES[entity]
if (parser.ENTITIES[entityLC])
return parser.ENTITIES[entityLC]
entity = entityLC
if (entity.charAt(0) === "#") {
if (entity.charAt(1) === "x") {
entity = entity.slice(2)
num = parseInt(entity, 16)
numStr = num.toString(16)
} else {
entity = entity.slice(1)
num = parseInt(entity, 10)
numStr = num.toString(10)
}
}
entity = entity.replace(/^0+/, "")
if (numStr.toLowerCase() !== entity) {
strictFail(parser, "Invalid character entity")
return "&"+parser.entity + ";"
}
return String.fromCodePoint(num)
}
function write (chunk) {
var parser = this
if (this.error) throw this.error
if (parser.closed) return error(parser,
"Cannot write after close. Assign an onready handler.")
if (chunk === null) return end(parser)
var i = 0, c = ""
while (parser.c = c = chunk.charAt(i++)) {
if (parser.trackPosition) {
parser.position ++
if (c === "\n") {
parser.line ++
parser.column = 0
} else parser.column ++
}
switch (parser.state) {
case S.BEGIN:
if (c === "<") {
parser.state = S.OPEN_WAKA
parser.startTagPosition = parser.position
} else if (not(whitespace,c)) {
// have to process this as a text node.
// weird, but happens.
strictFail(parser, "Non-whitespace before first tag.")
parser.textNode = c
parser.state = S.TEXT
}
continue
case S.TEXT:
if (parser.sawRoot && !parser.closedRoot) {
var starti = i-1
while (c && c!=="<" && c!=="&") {
c = chunk.charAt(i++)
if (c && parser.trackPosition) {
parser.position ++
if (c === "\n") {
parser.line ++
parser.column = 0
} else parser.column ++
}
}
parser.textNode += chunk.substring(starti, i-1)
}
if (c === "<") {
parser.state = S.OPEN_WAKA
parser.startTagPosition = parser.position
} else {
if (not(whitespace, c) && (!parser.sawRoot || parser.closedRoot))
strictFail(parser, "Text data outside of root node.")
if (c === "&") parser.state = S.TEXT_ENTITY
else parser.textNode += c
}
continue
case S.SCRIPT:
// only non-strict
if (c === "<") {
parser.state = S.SCRIPT_ENDING
} else parser.script += c
continue
case S.SCRIPT_ENDING:
if (c === "/") {
parser.state = S.CLOSE_TAG
} else {
parser.script += "<" + c
parser.state = S.SCRIPT
}
continue
case S.OPEN_WAKA:
// either a /, ?, !, or text is coming next.
if (c === "!") {
parser.state = S.SGML_DECL
parser.sgmlDecl = ""
} else if (is(whitespace, c)) {
// wait for it...
} else if (is(nameStart,c)) {
parser.state = S.OPEN_TAG
parser.tagName = c
} else if (c === "/") {
parser.state = S.CLOSE_TAG
parser.tagName = ""
} else if (c === "?") {
parser.state = S.PROC_INST
parser.procInstName = parser.procInstBody = ""
} else {
strictFail(parser, "Unencoded <")
// if there was some whitespace, then add that in.
if (parser.startTagPosition + 1 < parser.position) {
var pad = parser.position - parser.startTagPosition
c = new Array(pad).join(" ") + c
}
parser.textNode += "<" + c
parser.state = S.TEXT
}
continue
case S.SGML_DECL:
if ((parser.sgmlDecl+c).toUpperCase() === CDATA) {
emitNode(parser, "onopencdata")
parser.state = S.CDATA
parser.sgmlDecl = ""
parser.cdata = ""
} else if (parser.sgmlDecl+c === "--") {
parser.state = S.COMMENT
parser.comment = ""
parser.sgmlDecl = ""
} else if ((parser.sgmlDecl+c).toUpperCase() === DOCTYPE) {
parser.state = S.DOCTYPE
if (parser.doctype || parser.sawRoot) strictFail(parser,
"Inappropriately located doctype declaration")
parser.doctype = ""
parser.sgmlDecl = ""
} else if (c === ">") {
emitNode(parser, "onsgmldeclaration", parser.sgmlDecl)
parser.sgmlDecl = ""
parser.state = S.TEXT
} else if (is(quote, c)) {
parser.state = S.SGML_DECL_QUOTED
parser.sgmlDecl += c
} else parser.sgmlDecl += c
continue
case S.SGML_DECL_QUOTED:
if (c === parser.q) {
parser.state = S.SGML_DECL
parser.q = ""
}
parser.sgmlDecl += c
continue
case S.DOCTYPE:
if (c === ">") {
parser.state = S.TEXT
emitNode(parser, "ondoctype", parser.doctype)
parser.doctype = true // just remember that we saw it.
} else {
parser.doctype += c
if (c === "[") parser.state = S.DOCTYPE_DTD
else if (is(quote, c)) {
parser.state = S.DOCTYPE_QUOTED
parser.q = c
}
}
continue
case S.DOCTYPE_QUOTED:
parser.doctype += c
if (c === parser.q) {
parser.q = ""
parser.state = S.DOCTYPE
}
continue
case S.DOCTYPE_DTD:
parser.doctype += c
if (c === "]") parser.state = S.DOCTYPE
else if (is(quote,c)) {
parser.state = S.DOCTYPE_DTD_QUOTED
parser.q = c
}
continue
case S.DOCTYPE_DTD_QUOTED:
parser.doctype += c
if (c === parser.q) {
parser.state = S.DOCTYPE_DTD
parser.q = ""
}
continue
case S.COMMENT:
if (c === "-") parser.state = S.COMMENT_ENDING
else parser.comment += c
continue
case S.COMMENT_ENDING:
if (c === "-") {
parser.state = S.COMMENT_ENDED
parser.comment = textopts(parser.opt, parser.comment)
if (parser.comment) emitNode(parser, "oncomment", parser.comment)
parser.comment = ""
} else {
parser.comment += "-" + c
parser.state = S.COMMENT
}
continue
case S.COMMENT_ENDED:
if (c !== ">") {
strictFail(parser, "Malformed comment")
// allow <!-- blah -- bloo --> in non-strict mode,
// which is a comment of " blah -- bloo "
parser.comment += "--" + c
parser.state = S.COMMENT
} else parser.state = S.TEXT
continue
case S.CDATA:
if (c === "]") parser.state = S.CDATA_ENDING
else parser.cdata += c
continue
case S.CDATA_ENDING:
if (c === "]") parser.state = S.CDATA_ENDING_2
else {
parser.cdata += "]" + c
parser.state = S.CDATA
}
continue
case S.CDATA_ENDING_2:
if (c === ">") {
if (parser.cdata) emitNode(parser, "oncdata", parser.cdata)
emitNode(parser, "onclosecdata")
parser.cdata = ""
parser.state = S.TEXT
} else if (c === "]") {
parser.cdata += "]"
} else {
parser.cdata += "]]" + c
parser.state = S.CDATA
}
continue
case S.PROC_INST:
if (c === "?") parser.state = S.PROC_INST_ENDING
else if (is(whitespace, c)) parser.state = S.PROC_INST_BODY
else parser.procInstName += c
continue
case S.PROC_INST_BODY:
if (!parser.procInstBody && is(whitespace, c)) continue
else if (c === "?") parser.state = S.PROC_INST_ENDING
else parser.procInstBody += c
continue
case S.PROC_INST_ENDING:
if (c === ">") {
emitNode(parser, "onprocessinginstruction", {
name : parser.procInstName,
body : parser.procInstBody
})
parser.procInstName = parser.procInstBody = ""
parser.state = S.TEXT
} else {
parser.procInstBody += "?" + c
parser.state = S.PROC_INST_BODY
}
continue
case S.OPEN_TAG:
if (is(nameBody, c)) parser.tagName += c
else {
newTag(parser)
if (c === ">") openTag(parser)
else if (c === "/") parser.state = S.OPEN_TAG_SLASH
else {
if (not(whitespace, c)) strictFail(
parser, "Invalid character in tag name")
parser.state = S.ATTRIB
}
}
continue
case S.OPEN_TAG_SLASH:
if (c === ">") {
openTag(parser, true)
closeTag(parser)
} else {
strictFail(parser, "Forward-slash in opening tag not followed by >")
parser.state = S.ATTRIB
}
continue
case S.ATTRIB:
// haven't read the attribute name yet.
if (is(whitespace, c)) continue
else if (c === ">") openTag(parser)
else if (c === "/") parser.state = S.OPEN_TAG_SLASH
else if (is(nameStart, c)) {
parser.attribName = c
parser.attribValue = ""
parser.state = S.ATTRIB_NAME
} else strictFail(parser, "Invalid attribute name")
continue
case S.ATTRIB_NAME:
if (c === "=") parser.state = S.ATTRIB_VALUE
else if (c === ">") {
strictFail(parser, "Attribute without value")
parser.attribValue = parser.attribName
attrib(parser)
openTag(parser)
}
else if (is(whitespace, c)) parser.state = S.ATTRIB_NAME_SAW_WHITE
else if (is(nameBody, c)) parser.attribName += c
else strictFail(parser, "Invalid attribute name")
continue
case S.ATTRIB_NAME_SAW_WHITE:
if (c === "=") parser.state = S.ATTRIB_VALUE
else if (is(whitespace, c)) continue
else {
strictFail(parser, "Attribute without value")
parser.tag.attributes[parser.attribName] = ""
parser.attribValue = ""
emitNode(parser, "onattribute",
{ name : parser.attribName, value : "" })
parser.attribName = ""
if (c === ">") openTag(parser)
else if (is(nameStart, c)) {
parser.attribName = c
parser.state = S.ATTRIB_NAME
} else {
strictFail(parser, "Invalid attribute name")
parser.state = S.ATTRIB
}
}
continue
case S.ATTRIB_VALUE:
if (is(whitespace, c)) continue
else if (is(quote, c)) {
parser.q = c
parser.state = S.ATTRIB_VALUE_QUOTED
} else {
strictFail(parser, "Unquoted attribute value")
parser.state = S.ATTRIB_VALUE_UNQUOTED
parser.attribValue = c
}
continue
case S.ATTRIB_VALUE_QUOTED:
if (c !== parser.q) {
if (c === "&") parser.state = S.ATTRIB_VALUE_ENTITY_Q
else parser.attribValue += c
continue
}
attrib(parser)
parser.q = ""
parser.state = S.ATTRIB_VALUE_CLOSED
continue
case S.ATTRIB_VALUE_CLOSED:
if (is(whitespace, c)) {
parser.state = S.ATTRIB
} else if (c === ">") openTag(parser)
else if (c === "/") parser.state = S.OPEN_TAG_SLASH
else if (is(nameStart, c)) {
strictFail(parser, "No whitespace between attributes")
parser.attribName = c
parser.attribValue = ""
parser.state = S.ATTRIB_NAME
} else strictFail(parser, "Invalid attribute name")
continue
case S.ATTRIB_VALUE_UNQUOTED:
if (not(attribEnd,c)) {
if (c === "&") parser.state = S.ATTRIB_VALUE_ENTITY_U
else parser.attribValue += c
continue
}
attrib(parser)
if (c === ">") openTag(parser)
else parser.state = S.ATTRIB
continue
case S.CLOSE_TAG:
if (!parser.tagName) {
if (is(whitespace, c)) continue
else if (not(nameStart, c)) {
if (parser.script) {
parser.script += "</" + c
parser.state = S.SCRIPT
} else {
strictFail(parser, "Invalid tagname in closing tag.")
}
} else parser.tagName = c
}
else if (c === ">") closeTag(parser)
else if (is(nameBody, c)) parser.tagName += c
else if (parser.script) {
parser.script += "</" + parser.tagName
parser.tagName = ""
parser.state = S.SCRIPT
} else {
if (not(whitespace, c)) strictFail(parser,
"Invalid tagname in closing tag")
parser.state = S.CLOSE_TAG_SAW_WHITE
}
continue
case S.CLOSE_TAG_SAW_WHITE:
if (is(whitespace, c)) continue
if (c === ">") closeTag(parser)
else strictFail(parser, "Invalid characters in closing tag")
continue
case S.TEXT_ENTITY:
case S.ATTRIB_VALUE_ENTITY_Q:
case S.ATTRIB_VALUE_ENTITY_U:
switch(parser.state) {
case S.TEXT_ENTITY:
var returnState = S.TEXT, buffer = "textNode"
break
case S.ATTRIB_VALUE_ENTITY_Q:
var returnState = S.ATTRIB_VALUE_QUOTED, buffer = "attribValue"
break
case S.ATTRIB_VALUE_ENTITY_U:
var returnState = S.ATTRIB_VALUE_UNQUOTED, buffer = "attribValue"
break
}
if (c === ";") {
parser[buffer] += parseEntity(parser)
parser.entity = ""
parser.state = returnState
}
else if (is(entity, c)) parser.entity += c
else {
strictFail(parser, "Invalid character entity")
parser[buffer] += "&" + parser.entity + c
parser.entity = ""
parser.state = returnState
}
continue
default:
throw new Error(parser, "Unknown state: " + parser.state)
}
} // while
// cdata blocks can get very big under normal conditions. emit and move on.
// if (parser.state === S.CDATA && parser.cdata) {
// emitNode(parser, "oncdata", parser.cdata)
// parser.cdata = ""
// }
if (parser.position >= parser.bufferCheckPosition) checkBufferLength(parser)
return parser
}
/*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
if (!String.fromCodePoint) {
(function() {
var stringFromCharCode = String.fromCharCode;
var floor = Math.floor;
var fromCodePoint = function() {
var MAX_SIZE = 0x4000;
var codeUnits = [];
var highSurrogate;
var lowSurrogate;
var index = -1;
var length = arguments.length;
if (!length) {
return '';
}
var result = '';
while (++index < length) {
var codePoint = Number(arguments[index]);
if (
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
codePoint < 0 || // not a valid Unicode code point
codePoint > 0x10FFFF || // not a valid Unicode code point
floor(codePoint) != codePoint // not an integer
) {
throw RangeError('Invalid code point: ' + codePoint);
}
if (codePoint <= 0xFFFF) { // BMP code point
codeUnits.push(codePoint);
} else { // Astral code point; split in surrogate halves
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
codePoint -= 0x10000;
highSurrogate = (codePoint >> 10) + 0xD800;
lowSurrogate = (codePoint % 0x400) + 0xDC00;
codeUnits.push(highSurrogate, lowSurrogate);
}
if (index + 1 == length || codeUnits.length > MAX_SIZE) {
result += stringFromCharCode.apply(null, codeUnits);
codeUnits.length = 0;
}
}
return result;
};
if (Object.defineProperty) {
Object.defineProperty(String, 'fromCodePoint', {
'value': fromCodePoint,
'configurable': true,
'writable': true
});
} else {
String.fromCodePoint = fromCodePoint;
}
}());
}
})(typeof exports === "undefined" ? sax = {} : exports)
/**
* Tiny stack for browser or server
*
* @author Jason Mulligan <jason.mulligan@avoidwork.com>
* @copyright 2014 Jason Mulligan
* @license BSD-3 <https://raw.github.com/avoidwork/tiny-stack/master/LICENSE>
* @link http://avoidwork.github.io/tiny-stack
* @module tiny-stack
* @version 0.1.0
*/
;( function ( global ) {
"use strict";
/**
* TinyStack
*
* @constructor
*/
function TinyStack () {
this.data = [null];
this.top = 0;
}
/**
* Clears the stack
*
* @method clear
* @memberOf TinyStack
* @return {Object} {@link TinyStack}
*/
TinyStack.prototype.clear = function clear () {
this.data = [null];
this.top = 0;
return this;
};
/**
* Gets the size of the stack
*
* @method length
* @memberOf TinyStack
* @return {Number} Size of stack
*/
TinyStack.prototype.length = function length () {
return this.top;
};
/**
* Gets the item at the top of the stack
*
* @method peek
* @memberOf TinyStack
* @return {Mixed} Item at the top of the stack
*/
TinyStack.prototype.peek = function peek () {
return this.data[this.top];
};
/**
* Gets & removes the item at the top of the stack
*
* @method pop
* @memberOf TinyStack
* @return {Mixed} Item at the top of the stack
*/
TinyStack.prototype.pop = function pop () {
if ( this.top > 0 ) {
this.top--;
return this.data.pop();
}
else {
return undefined;
}
};
/**
* Pushes an item onto the stack
*
* @method push
* @memberOf TinyStack
* @return {Object} {@link TinyStack}
*/
TinyStack.prototype.push = function push ( arg ) {
this.data[++this.top] = arg;
return this;
};
/**
* TinyStack factory
*
* @method factory
* @return {Object} {@link TinyStack}
*/
function factory () {
return new TinyStack();
}
// Node, AMD & window supported
if ( typeof exports != "undefined" ) {
module.exports = factory;
}
else if ( typeof define == "function" ) {
define( function () {
return factory;
} );
}
else {
global.stack = factory;
}
} )( this );
'use strict';
function Base() { }
Base.prototype.get = function(name) {
return this.$model.properties.get(this, name);
};
Base.prototype.set = function(name, value) {
this.$model.properties.set(this, name, value);
};
//
//module.exports = Base;
var parseName = function(name, defaultPrefix) {
var parts = name.split(/:/),
localName, prefix;
// no prefix (i.e. only local name)
if (parts.length === 1) {
localName = name;
prefix = defaultPrefix;
} else
// prefix + local name
if (parts.length === 2) {
localName = parts[1];
prefix = parts[0];
} else {
throw new Error('expected <prefix:localName> or <localName>, got ' + name);
}
name = (prefix ? prefix + ':' : '') + localName;
return {
name: name,
prefix: prefix,
localName: localName
};
};
'use strict';
/**
* A utility that gets and sets properties of model elements.
*
* @param {Model} model
*/
function Properties(model) {
this.model = model;
}
//module.exports = Properties;
/**
* Sets a named property on the target element
*
* @param {Object} target
* @param {String} name
* @param {Object} value
*/
Properties.prototype.set = function(target, name, value) {
var property = this.model.getPropertyDescriptor(target, name);
if (!property) {
target.$attrs[name] = value;
} else {
Object.defineProperty(target, property.name, {
enumerable: !property.isReference,
writable: true,
value: value
});
}
};
/**
* Returns the named property of the given element
*
* @param {Object} target
* @param {String} name
*
* @return {Object}
*/
Properties.prototype.get = function(target, name) {
var property = this.model.getPropertyDescriptor(target, name);
if (!property) {
return target.$attrs[name];
}
var propertyName = property.name;
// check if access to collection property and lazily initialize it
if (!target[propertyName] && property.isMany) {
Object.defineProperty(target, propertyName, {
enumerable: !property.isReference,
writable: true,
value: []
});
}
return target[propertyName];
};
/**
* Define a property on the target element
*
* @param {Object} target
* @param {String} name
* @param {Object} options
*/
Properties.prototype.define = function(target, name, options) {
Object.defineProperty(target, name, options);
};
/**
* Define the descriptor for an element
*/
Properties.prototype.defineDescriptor = function(target, descriptor) {
this.define(target, '$descriptor', { value: descriptor });
};
/**
* Define the model for an element
*/
Properties.prototype.defineModel = function(target, model) {
this.define(target, '$model', { value: model });
};
'use strict';
//var _ = require('lodash');
//
//var Base = require('./base');
function Factory(model, properties) {
this.model = model;
this.properties = properties;
}
//module.exports = Factory;
Factory.prototype.createType = function(descriptor) {
var model = this.model;
var props = this.properties,
prototype = Object.create(Base.prototype);
// initialize default values
_.forEach(descriptor.properties, function(p) {
if (!p.isMany && p.default !== undefined) {
prototype[p.name] = p.default;
}
});
props.defineModel(prototype, model);
props.defineDescriptor(prototype, descriptor);
var name = descriptor.ns.name;
/**
* The new type constructor
*/
function ModdleElement(attrs) {
props.define(this, '$type', { value: name, enumerable: true });
props.define(this, '$attrs', { value: {} });
props.define(this, '$parent', { writable: true });
_.forEach(attrs, function(val, key) {
this.set(key, val);
}, this);
}
ModdleElement.prototype = prototype;
ModdleElement.hasType = prototype.$instanceOf = this.model.hasType;
// static links
props.defineModel(ModdleElement, model);
props.defineDescriptor(ModdleElement, descriptor);
return ModdleElement;
};
/**
* Built-in moddle types
*/
var BUILTINS = {
String: true,
Boolean: true,
Integer: true,
Real: true,
Element: true
};
/**
* Converters for built in types from string representations
*/
var TYPE_CONVERTERS = {
String: function(s) { return s; },
Boolean: function(s) { return s === 'true'; },
Integer: function(s) { return parseInt(s, 10); },
Real: function(s) { return parseFloat(s, 10); }
};
/**
* Convert a type to its real representation
*/
var coerceType = function(type, value) {
var converter = TYPE_CONVERTERS[type];
if (converter) {
return converter(value);
} else {
return value;
}
};
/**
* Return whether the given type is built-in
*/
var isBuiltIn = function(type) {
return !!BUILTINS[type];
};
/**
* Return whether the given type is simple
*/
var isSimple = function(type) {
return !!TYPE_CONVERTERS[type];
};
'use strict';
//var _ = require('lodash');
//
//var Types = require('./types');
// DescriptorBuilder = require('./descriptor-builder');
//
//var this.parseName = parseName;
function Registry(packages, properties, options) {
this.options = _.extend({ generateId: 'id' }, options || {});
this.packageMap = {};
this.typeMap = {};
this.packages = [];
this.properties = properties;
_.forEach(packages, this.registerPackage, this);
}
//module.exports = Registry;
Registry.prototype.getPackage = function(uriOrPrefix) {
return this.packageMap[uriOrPrefix];
};
Registry.prototype.getPackages = function() {
return this.packages;
};
Registry.prototype.registerPackage = function(pkg) {
// register types
_.forEach(pkg.types, function(descriptor) {
this.registerType(descriptor, pkg);
}, this);
this.packageMap[pkg.uri] = this.packageMap[pkg.prefix] = pkg;
this.packages.push(pkg);
};
/**
* Register a type from a specific package with us
*/
Registry.prototype.registerType = function(type, pkg) {
var ns = this.parseName(type.name, pkg.prefix),
name = ns.name,
propertiesByName = {};
// parse properties
_.forEach(type.properties, function(p) {
// namespace property names
var propertyNs = this.parseName(p.name, ns.prefix),
propertyName = propertyNs.name;
// namespace property types
if (!isBuiltIn( p.type)) {
p.type = this.parseName(p.type, propertyNs.prefix).name;
}
_.extend(p, {
ns: propertyNs,
name: propertyName
});
propertiesByName[propertyName] = p;
},this);
// update ns + name
_.extend(type, {
ns: ns,
name: name,
propertiesByName: propertiesByName
});
// link to package
this.definePackage(type, pkg);
// register
this.typeMap[name] = type;
};
/**
* Traverse the type hierarchy from bottom to top.
*/
Registry.prototype.mapTypes = function(nsName, iterator) {
var type = this.typeMap[nsName.name];
if (!type) {
throw new Error('unknown type <' + nsName.name + '>');
}
_.forEach(type.superClass, function(cls) {
var parentNs = this.parseName(cls, nsName.prefix);
this.mapTypes(parentNs, iterator);
}, this);
iterator(type);
};
/**
* Returns the effective descriptor for a type.
*
* @param {String} type the namespaced name (ns:localName) of the type
*
* @return {Descriptor} the resulting effective descriptor
*/
Registry.prototype.getEffectiveDescriptor = function(name) {
var options = this.options,
nsName = this.parseName(name);
var builder = new DescriptorBuilder(nsName);
this.mapTypes(nsName, function(type) {
builder.addTrait(type);
});
// check we have an id assigned
var id = this.options.generateId;
if (id && !builder.hasProperty(id)) {
builder.addIdProperty(id);
}
var descriptor = builder.build();
// define package link
this.definePackage(descriptor, descriptor.allTypes[descriptor.allTypes.length - 1].$pkg);
return descriptor;
};
Registry.prototype.definePackage = function(target, pkg) {
this.properties.define(target, '$pkg', { value: pkg });
};
Registry.prototype.parseName = function(name, defaultPrefix) {
var parts = name.split(/:/),
localName, prefix;
// no prefix (i.e. only local name)
if (parts.length === 1) {
localName = name;
prefix = defaultPrefix;
} else
// prefix + local name
if (parts.length === 2) {
localName = parts[1];
prefix = parts[0];
} else {
throw new Error('expected <prefix:localName> or <localName>, got ' + name);
}
name = (prefix ? prefix + ':' : '') + localName;
return {
name: name,
prefix: prefix,
localName: localName
};
};
'use strict';
//var _ = require('lodash');
//
//var parseNameNs = require('./ns').parseName;
function DescriptorBuilder(nameNs) {
this.ns = nameNs;
this.name = nameNs.name;
this.allTypes = [];
this.properties = [];
this.propertiesByName = {};
}
//module.exports = DescriptorBuilder;
DescriptorBuilder.prototype.build = function() {
return _.pick(this, [ 'ns', 'name', 'allTypes', 'properties', 'propertiesByName', 'bodyProperty' ]);
};
DescriptorBuilder.prototype.addProperty = function(p, idx) {
this.addNamedProperty(p, true);
var properties = this.properties;
if (idx !== undefined) {
properties.splice(idx, 0, p);
} else {
properties.push(p);
}
};
DescriptorBuilder.prototype.replaceProperty = function(oldProperty, newProperty) {
var oldNameNs = oldProperty.ns;
var props = this.properties,
propertiesByName = this.propertiesByName;
if (oldProperty.isBody) {
if (!newProperty.isBody) {
throw new Error(
'property <' + newProperty.ns.name + '> must be body property ' +
'to refine <' + oldProperty.ns.name + '>');
}
// TODO: Check compatibility
this.setBodyProperty(newProperty, false);
}
this.addNamedProperty(newProperty, true);
// replace old property at index with new one
var idx = props.indexOf(oldProperty);
if (idx === -1) {
throw new Error('property <' + oldNameNs.name + '> not found in property list');
}
props[idx] = newProperty;
// replace propertiesByName entry with new property
propertiesByName[oldNameNs.name] = propertiesByName[oldNameNs.localName] = newProperty;
};
DescriptorBuilder.prototype.redefineProperty = function(p) {
var nsPrefix = p.ns.prefix;
var parts = p.redefines.split('#');
var name = parseNameNs(parts[0], nsPrefix);
var attrName = parseNameNs(parts[1], name.prefix).name;
var redefinedProperty = this.propertiesByName[attrName];
if (!redefinedProperty) {
throw new Error('refined property <' + attrName + '> not found');
} else {
this.replaceProperty(redefinedProperty, p);
}
delete p.redefines;
};
DescriptorBuilder.prototype.addNamedProperty = function(p, validate) {
var ns = p.ns,
propsByName = this.propertiesByName;
if (validate) {
this.assertNotDefined(p, ns.name);
this.assertNotDefined(p, ns.localName);
}
propsByName[ns.name] = propsByName[ns.localName] = p;
};
DescriptorBuilder.prototype.removeNamedProperty = function(p) {
var ns = p.ns,
propsByName = this.propertiesByName;
delete propsByName[ns.name];
delete propsByName[ns.localName];
};
DescriptorBuilder.prototype.setBodyProperty = function(p, validate) {
if (validate && this.bodyProperty) {
throw new Error(
'body property defined multiple times ' +
'(<' + this.bodyProperty.ns.name + '>, <' + p.ns.name + '>)');
}
this.bodyProperty = p;
};
DescriptorBuilder.prototype.addIdProperty = function(name) {
var nameNs = parseNameNs(name, this.ns.prefix);
var p = {
name: nameNs.localName,
type: 'String',
isAttr: true,
ns: nameNs
};
// ensure that id is always the first attribute (if present)
this.addProperty(p, 0);
};
DescriptorBuilder.prototype.assertNotDefined = function(p, name) {
var propertyName = p.name,
definedProperty = this.propertiesByName[propertyName];
if (definedProperty) {
throw new Error(
'property <' + propertyName + '> already defined; ' +
'override of <' + definedProperty.definedBy.ns.name + '#' + definedProperty.ns.name + '> by ' +
'<' + p.definedBy.ns.name + '#' + p.ns.name + '> not allowed without redefines');
}
};
DescriptorBuilder.prototype.hasProperty = function(name) {
return this.propertiesByName[name];
};
DescriptorBuilder.prototype.addTrait = function(t) {
var allTypes = this.allTypes;
if (allTypes.indexOf(t) !== -1) {
return;
}
_.forEach(t.properties, function(p) {
// clone property to allow extensions
p = _.extend({}, p, {
name: p.ns.localName
});
Object.defineProperty(p, 'definedBy', {
value: t
});
// add redefine support
if (p.redefines) {
this.redefineProperty(p);
} else {
if (p.isBody) {
this.setBodyProperty(p);
}
this.addProperty(p);
}
}, this);
allTypes.push(t);
};
'use strict';
//var _ = require('lodash');
//
//var Types = require('./types'),
// Factory = require('./factory'),
// Registry = require('./registry'),
// Properties = require('./properties');
//
//var parseNameNs = require('./ns').parseName;
//// Moddle implementation /////////////////////////////////////////////////
/**
* @class Moddle
*
* A model that can be used to create elements of a specific type.
*
* @example
*
* var Moddle = require('moddle');
*
* var pkg = {
* name: 'mypackage',
* prefix: 'my',
* types: [
* { name: 'Root' }
* ]
* };
*
* var moddle = new Moddle([pkg]);
*
* @param {Array<Package>} packages the packages to contain
* @param {Object} options additional options to pass to the model
*/
function Moddle(packages, options) {
options = options || {};
this.properties = new Properties(this);
this.factory = new Factory(this, this.properties);
this.registry = new Registry(packages, this.properties, options);
this.typeCache = {};
}
//module.exports = Moddle;
/**
* Create an instance of the specified type.
*
* @method Moddle#create
*
* @example
*
* var foo = moddle.create('my:Foo');
* var bar = moddle.create('my:Bar', { id: 'BAR_1' });
*
* @param {String|Object} descriptor the type descriptor or name know to the model
* @param {Object} attrs a number of attributes to initialize the model instance with
* @return {Object} model instance
*/
Moddle.prototype.create = function(descriptor, attrs) {
var Type = this.getType(descriptor);
if (!Type) {
throw new Error('unknown type <' + descriptor + '>');
}
return new Type(attrs);
};
/**
* Returns the type representing a given descriptor
*
* @method Moddle#getType
*
* @example
*
* var Foo = moddle.getType('my:Foo');
* var foo = new Foo({ 'id' : 'FOO_1' });
*
* @param {String|Object} descriptor the type descriptor or name know to the model
* @return {Object} the type representing the descriptor
*/
Moddle.prototype.getType = function(descriptor) {
var cache = this.typeCache;
var name = _.isString(descriptor) ? descriptor : descriptor.ns.name;
var type = cache[name];
if (!type) {
descriptor = this.registry.getEffectiveDescriptor(name);
type = cache[descriptor.name] = this.factory.createType(descriptor);
}
return type;
};
/**
* Creates an any-element type to be used within model instances.
*
* This can be used to create custom elements that lie outside the meta-model.
* The created element contains all the meta-data required to serialize it
* as part of meta-model elements.
*
* @method Moddle#createAny
*
* @example
*
* var foo = moddle.createAny('vendor:Foo', 'http://vendor', {
* value: 'bar'
* });
*
* var container = moddle.create('my:Container', 'http://my', {
* any: [ foo ]
* });
*
* // go ahead and serialize the stuff
*
*
* @param {String} name the name of the element
* @param {String} nsUri the namespace uri of the element
* @param {Object} [properties] a map of properties to initialize the instance with
* @return {Object} the any type instance
*/
Moddle.prototype.createAny = function(name, nsUri, properties) {
var nameNs = parseNameNs(name);
var element = {
$type: name
};
var descriptor = {
name: name,
isGeneric: true,
ns: {
prefix: nameNs.prefix,
localName: nameNs.localName,
uri: nsUri
}
};
this.properties.defineDescriptor(element, descriptor);
this.properties.defineModel(element, this);
this.properties.define(element, '$parent', { enumerable: false, writable: true });
_.forEach(properties, function(a, key) {
if (_.isObject(a) && a.value !== undefined) {
element[a.name] = a.value;
} else {
element[key] = a;
}
});
return element;
};
/**
* Returns a registered package by uri or prefix
*
* @return {Object} the package
*/
Moddle.prototype.getPackage = function(uriOrPrefix) {
return this.registry.getPackage(uriOrPrefix);
};
/**
* Returns a snapshot of all known packages
*
* @return {Object} the package
*/
Moddle.prototype.getPackages = function() {
return this.registry.getPackages();
};
/**
* Returns the descriptor for an element
*/
Moddle.prototype.getElementDescriptor = function(element) {
return element.$descriptor;
};
/**
* Returns true if the given descriptor or instance
* represents the given type.
*
* May be applied to this, if element is omitted.
*/
Moddle.prototype.hasType = function(element, type) {
if (type === undefined) {
type = element;
element = this;
}
var descriptor = element.$model.getElementDescriptor(element);
return !!_.find(descriptor.allTypes, function(t) {
return t.name === type;
});
};
/**
* Returns the descriptor of an elements named property
*/
Moddle.prototype.getPropertyDescriptor = function(element, property) {
return this.getElementDescriptor(element).propertiesByName[property];
};
'use strict';
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function lower(string) {
return string.charAt(0).toLowerCase() + string.slice(1);
}
function hasLowerCaseAlias(pkg) {
return pkg.xml && pkg.xml.alias === 'lowerCase';
}
var aliasToName = function(alias, pkg) {
if (hasLowerCaseAlias(pkg)) {
return capitalize(alias);
} else {
return alias;
}
};
var nameToAlias = function(name, pkg) {
if (hasLowerCaseAlias(pkg)) {
return lower(name);
} else {
return name;
}
};
var DEFAULT_NS_MAP = {
'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
};
//
//module.exports.DEFAULT_NS_MAP = {
// 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
//};
'use strict';
//var sax = require('sax'),
// _ = require('lodash');
//
//var common = require('./common'),
// Types = require('moddle').types,
// Stack = require('tiny-stack'),
// parseNameNs = require('moddle').ns.parseName,
var parseNameNs = parseName;
var aliasToName = aliasToName;
function parseNodeAttributes(node) {
var nodeAttrs = node.attributes;
return _.reduce(nodeAttrs, function(result, v, k) {
var name, ns;
if (!v.local) {
name = v.prefix;
} else {
ns = parseNameNs(v.name, v.prefix);
name = ns.name;
}
result[name] = v.value;
return result;
}, {});
}
/**
* Normalizes namespaces for a node given an optional default namespace and a
* number of mappings from uris to default prefixes.
*
* @param {XmlNode} node
* @param {Model} model the model containing all registered namespaces
* @param {Uri} defaultNsUri
*/
function normalizeNamespaces(node, model, defaultNsUri) {
var uri, childUri, prefix;
uri = node.uri || defaultNsUri;
if (uri) {
var pkg = model.getPackage(uri);
if (pkg) {
prefix = pkg.prefix;
} else {
prefix = node.prefix;
}
node.prefix = prefix;
node.uri = uri;
}
_.forEach(node.attributes, function(attr) {
normalizeNamespaces(attr, model, null);
});
}
/**
* A parse context.
*
* @class
*
* @param {ElementHandler} parseRoot the root handler for parsing a document
*/
function Context(parseRoot) {
var elementsById = {};
var references = [];
var warnings = [];
this.addReference = function(reference) {
references.push(reference);
};
this.addElement = function(id, element) {
if (!id || !element) {
throw new Error('[xml-reader] id or ctx must not be null');
}
elementsById[id] = element;
};
this.addWarning = function (w) {
warnings.push(w);
};
this.warnings = warnings;
this.references = references;
this.elementsById = elementsById;
this.parseRoot = parseRoot;
}
function BaseHandler() {}
BaseHandler.prototype.handleEnd = function() {};
BaseHandler.prototype.handleText = function() {};
BaseHandler.prototype.handleNode = function() {};
function BodyHandler() {}
BodyHandler.prototype = new BaseHandler();
BodyHandler.prototype.handleText = function(text) {
this.body = (this.body || '') + text;
};
function ReferenceHandler(property, context) {
this.property = property;
this.context = context;
}
ReferenceHandler.prototype = new BodyHandler();
ReferenceHandler.prototype.handleNode = function(node) {
if (this.element) {
throw new Error('expected no sub nodes');
} else {
this.element = this.createReference(node);
}
return this;
};
ReferenceHandler.prototype.handleEnd = function() {
this.element.id = this.body;
};
ReferenceHandler.prototype.createReference = function() {
return {
property: this.property.ns.name,
id: ''
};
};
function ValueHandler(propertyDesc, element) {
this.element = element;
this.propertyDesc = propertyDesc;
}
ValueHandler.prototype = new BodyHandler();
ValueHandler.prototype.handleEnd = function() {
var value = this.body,
element = this.element,
propertyDesc = this.propertyDesc;
value = coerceType(propertyDesc.type, value);
if (propertyDesc.isMany) {
element.get(propertyDesc.name).push(value);
} else {
element.set(propertyDesc.name, value);
}
};
function BaseElementHandler() {}
BaseElementHandler.prototype = Object.create(BodyHandler.prototype);
BaseElementHandler.prototype.handleNode = function(node) {
var parser = this;
if (!this.element) {
this.element = this.createElement(node);
var id = this.element.id;
if (id) {
this.context.addElement(id, this.element);
}
} else {
parser = this.handleChild(node);
}
return parser;
};
/**
* @class XMLReader.ElementHandler
*
*/
function ElementHandler(model, type, context) {
this.model = model;
this.type = model.getType(type);
this.context = context;
}
ElementHandler.prototype = new BaseElementHandler();
ElementHandler.prototype.addReference = function(reference) {
this.context.addReference(reference);
};
ElementHandler.prototype.handleEnd = function() {
var value = this.body,
element = this.element,
descriptor = element.$descriptor,
bodyProperty = descriptor.bodyProperty;
if (bodyProperty && value !== undefined) {
value = coerceType(bodyProperty.type, value);
element.set(bodyProperty.name, value);
}
};
/**
* Create an instance of the model from the given node.
*
* @param {Element} node the xml node
*/
ElementHandler.prototype.createElement = function(node) {
var attributes = parseNodeAttributes(node),
Type = this.type,
descriptor = Type.$descriptor,
context = this.context,
instance = new Type({});
_.forEach(attributes, function(value, name) {
var prop = descriptor.propertiesByName[name];
if (prop && prop.isReference) {
context.addReference({
element: instance,
property: prop.ns.name,
id: value
});
} else {
if (prop) {
value = coerceType(prop.type, value);
}
instance.set(name, value);
}
});
return instance;
};
ElementHandler.prototype.getPropertyForElement = function(nameNs) {
if (_.isString(nameNs)) {
nameNs = parseNameNs(nameNs);
}
var type = this.type,
model = this.model,
descriptor = type.$descriptor;
var propertyName = nameNs.name;
var property = descriptor.propertiesByName[propertyName];
// search for properties by name first
if (property) {
return property;
}
var pkg = model.getPackage(nameNs.prefix);
if (pkg) {
var typeName = nameNs.prefix + ':' + aliasToName(nameNs.localName, descriptor.$pkg),
elementType = model.getType(typeName);
// search for collection members later
property = _.find(descriptor.properties, function(p) {
return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type);
});
if (property) {
return _.extend({}, property, { effectiveType: elementType.$descriptor.name });
}
} else {
// parse unknown element (maybe extension)
property = _.find(descriptor.properties, function(p) {
return !p.isReference && !p.isAttribute && p.type === 'Element';
});
if (property) {
return property;
}
}
throw new Error('unrecognized element <' + nameNs.name + '>');
};
ElementHandler.prototype.toString = function() {
return 'ElementDescriptor[' + this.type.$descriptor.name + ']';
};
ElementHandler.prototype.valueHandler = function(propertyDesc, element) {
return new ValueHandler(propertyDesc, element);
};
ElementHandler.prototype.referenceHandler = function(propertyDesc) {
return new ReferenceHandler(propertyDesc, this.context);
};
ElementHandler.prototype.handler = function(type) {
if (type === 'Element') {
return new GenericElementHandler(this.model, type, this.context);
} else {
return new ElementHandler(this.model, type, this.context);
}
};
/**
* Handle the child element parsing
*
* @param {Element} node the xml node
*/
ElementHandler.prototype.handleChild = function(node) {
var nameNs = parseNameNs(node.local, node.prefix);
var propertyDesc, type, element, childHandler;
propertyDesc = this.getPropertyForElement(nameNs);
element = this.element;
type = propertyDesc.effectiveType || propertyDesc.type;
if (isSimple(propertyDesc.type)) {
return this.valueHandler(propertyDesc, element);
}
if (propertyDesc.isReference) {
childHandler = this.referenceHandler(propertyDesc).handleNode(node);
} else {
childHandler = this.handler(type).handleNode(node);
}
var newElement = childHandler.element;
// child handles may decide to skip elements
// by not returning anything
if (newElement !== undefined) {
if (propertyDesc.isMany) {
element.get(propertyDesc.name).push(newElement);
} else {
element.set(propertyDesc.name, newElement);
}
if (propertyDesc.isReference) {
_.extend(newElement, {
element: element
});
this.context.addReference(newElement);
} else {
// establish child -> parent relationship
newElement.$parent = element;
}
}
return childHandler;
};
function GenericElementHandler(model, type, context) {
this.model = model;
this.context = context;
}
GenericElementHandler.prototype = Object.create(BaseElementHandler.prototype);
GenericElementHandler.prototype.createElement = function(node) {
var name = node.name,
prefix = node.prefix,
uri = node.ns[prefix],
attributes = node.attributes;
return this.model.createAny(name, uri, attributes);
};
GenericElementHandler.prototype.handleChild = function(node) {
var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node),
element = this.element;
var newElement = handler.element,
children;
if (newElement !== undefined) {
children = element.$children = element.$children || [];
children.push(newElement);
// establish child -> parent relationship
newElement.$parent = element;
}
return handler;
};
GenericElementHandler.prototype.handleText = function(text) {
this.body = this.body || '' + text;
};
GenericElementHandler.prototype.handleEnd = function() {
if (this.body) {
this.element.$body = this.body;
}
};
/**
* A reader for a meta-model
*
* @class XMLReader
*
* @param {Model} model used to read xml files
*/
function XMLReader(model) {
this.model = model;
}
XMLReader.prototype.fromXML = function(xml, rootHandler, done) {
var context = new Context(rootHandler);
var parser = sax.parser(true, { xmlns: true, trim: true });
var stackInstance = stack();
var model = this.model,
self = this;
rootHandler.context = context;
// push root handler
stackInstance.push(rootHandler);
function resolveReferences() {
var elementsById = context.elementsById;
var references = context.references;
var i, r;
for (i = 0; !!(r = references[i]); i++) {
var element = r.element;
var reference = elementsById[r.id];
var property = element.$descriptor.propertiesByName[r.property];
if (!reference) {
context.addWarning({
message: 'unresolved reference <' + r.id + '>',
element: r.element,
property: r.property,
value: r.id
});
}
if (property.isMany) {
var collection = element.get(property.name),
idx = collection.indexOf(r);
if (!reference) {
// remove unresolvable reference
collection.splice(idx, 1);
} else {
// update reference
collection[idx] = reference;
}
} else {
element.set(property.name, reference);
}
}
}
function handleClose(tagName) {
stackInstance.pop().handleEnd();
}
function handleOpen(node) {
var handler = stackInstance.peek();
normalizeNamespaces(node, model);
try {
stackInstance.push(handler.handleNode(node));
} catch (e) {
var line = this.line,
column = this.column;
throw new Error(
'unparsable content <' + node.name + '> detected\n\t' +
'line: ' + line + '\n\t' +
'column: ' + column + '\n\t' +
'nested error: ' + e.message);
}
}
function handleText(text) {
stackInstance.peek().handleText(text);
}
parser.onopentag = handleOpen;
parser.oncdata = parser.ontext = handleText;
parser.onclosetag = handleClose;
parser.onend = resolveReferences;
// deferred parse XML to make loading really ascnchronous
// this ensures the execution environment (node or browser)
// is kept responsive and that certain optimization strategies
// can kick in
_.defer(function() {
var error;
try {
parser.write(xml).close();
} catch (e) {
error = e;
}
done(error, error ? undefined : rootHandler.element, context);
});
};
XMLReader.prototype.handler = function(name) {
return new ElementHandler(this.model, name);
};
'use strict';
//var _ = require('lodash');
//var Types = require('moddle').types,
// common = require('./common'),
var parseNameNs = parseName;
var nameToAlias = nameToAlias;
var XML_PREAMBLE = '<?xml version="1.0" encoding="UTF-8"?>\n';
var CDATA_ESCAPE = /[<>"&]+/;
var DEFAULT_NS_MAP = DEFAULT_NS_MAP;
function nsName(ns) {
if (_.isString(ns)) {
return ns;
} else {
return (ns.prefix ? ns.prefix + ':' : '') + ns.localName;
}
}
function getElementNs(ns, descriptor) {
if (descriptor.isGeneric) {
return descriptor.name;
} else {
return _.extend({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns);
}
}
function getPropertyNs(ns, descriptor) {
return _.extend({ localName: descriptor.ns.localName }, ns);
}
function getSerializableProperties(element) {
var descriptor = element.$descriptor;
return _.filter(descriptor.properties, function(p) {
var name = p.name;
// do not serialize defaults
if (!element.hasOwnProperty(name)) {
return false;
}
var value = element[name];
// do not serialize default equals
if (value === p.default) {
return false;
}
return p.isMany ? value ? value.length : true : true;
});
}
/**
* Escape a string attribute to not contain any bad values (line breaks, '"', ...)
*
* @param {String} str the string to escape
* @return {String} the escaped string
*/
function escapeAttr(str) {
var escapeMap = {
'\n': '&#10;',
'\n\r': '&#10;',
'"': '&quot;'
};
// ensure we are handling strings here
str = _.isString(str) ? str : '' + str;
return str.replace(/(\n|\n\r|")/g, function(str) {
return escapeMap[str];
});
}
function filterAttributes(props) {
return _.filter(props, function(p) { return p.isAttr; });
}
function filterContained(props) {
return _.filter(props, function(p) { return !p.isAttr; });
}
function ReferenceSerializer(parent, ns) {
this.ns = ns;
}
ReferenceSerializer.prototype.build = function(element) {
this.element = element;
return this;
};
ReferenceSerializer.prototype.serializeTo = function(writer) {
writer
.appendIndent()
.append('<' + nsName(this.ns) + '>' + this.element.id + '</' + nsName(this.ns) + '>')
.appendNewLine();
};
function BodySerializer() {}
BodySerializer.prototype.serializeValue = BodySerializer.prototype.serializeTo = function(writer) {
var value = this.value,
escape = this.escape;
if (escape) {
writer.append('<![CDATA[');
}
writer.append(this.value);
if (escape) {
writer.append(']]>');
}
};
BodySerializer.prototype.build = function(prop, value) {
this.value = value;
if (prop.type === 'String' && CDATA_ESCAPE.test(value)) {
this.escape = true;
}
return this;
};
function ValueSerializer(ns) {
this.ns = ns;
}
ValueSerializer.prototype = new BodySerializer();
ValueSerializer.prototype.serializeTo = function(writer) {
writer
.appendIndent()
.append('<' + nsName(this.ns) + '>');
this.serializeValue(writer);
writer
.append( '</' + nsName(this.ns) + '>')
.appendNewLine();
};
function ElementSerializer(parent, ns) {
this.body = [];
this.attrs = [];
this.parent = parent;
this.ns = ns;
}
ElementSerializer.prototype.build = function(element) {
this.element = element;
var otherAttrs = this.parseNsAttributes(element);
if (!this.ns) {
this.ns = this.nsTagName(element.$descriptor);
}
if (element.$descriptor.isGeneric) {
this.parseGeneric(element);
} else {
var properties = getSerializableProperties(element);
this.parseAttributes(filterAttributes(properties));
this.parseContainments(filterContained(properties));
this.parseGenericAttributes(element, otherAttrs);
}
return this;
};
ElementSerializer.prototype.nsTagName = function(descriptor) {
var effectiveNs = this.logNamespaceUsed(descriptor.ns);
return getElementNs(effectiveNs, descriptor);
};
ElementSerializer.prototype.nsPropertyTagName = function(descriptor) {
var effectiveNs = this.logNamespaceUsed(descriptor.ns);
return getPropertyNs(effectiveNs, descriptor);
};
ElementSerializer.prototype.isLocalNs = function(ns) {
return ns.uri === this.ns.uri;
};
ElementSerializer.prototype.nsAttributeName = function(element) {
var ns;
if (_.isString(element)) {
ns = parseNameNs(element);
} else
if (element.ns) {
ns = element.ns;
}
var effectiveNs = this.logNamespaceUsed(ns);
// strip prefix if same namespace like parent
if (this.isLocalNs(effectiveNs)) {
return { localName: ns.localName };
} else {
return _.extend({ localName: ns.localName }, effectiveNs);
}
};
ElementSerializer.prototype.parseGeneric = function(element) {
var self = this,
body = this.body,
attrs = this.attrs;
_.forEach(element, function(val, key) {
if (key === '$body') {
body.push(new BodySerializer().build({ type: 'String' }, val));
} else
if (key === '$children') {
_.forEach(val, function(child) {
body.push(new ElementSerializer(self).build(child));
});
} else
if (key.indexOf('$') !== 0) {
attrs.push({ name: key, value: escapeAttr(val) });
}
});
};
/**
* Parse namespaces and return a list of left over generic attributes
*
* @param {Object} element
* @return {Array<Object>}
*/
ElementSerializer.prototype.parseNsAttributes = function(element) {
var self = this;
var genericAttrs = element.$attrs;
var attributes = [];
// parse namespace attributes first
// and log them. push non namespace attributes to a list
// and process them later
_.forEach(genericAttrs, function(value, name) {
var nameNs = parseNameNs(name);
if (nameNs.prefix === 'xmlns') {
self.logNamespace({ prefix: nameNs.localName, uri: value });
} else
if (!nameNs.prefix && nameNs.localName === 'xmlns') {
self.logNamespace({ uri: value });
} else {
attributes.push({ name: name, value: value });
}
});
return attributes;
};
ElementSerializer.prototype.parseGenericAttributes = function(element, attributes) {
var self = this;
_.forEach(attributes, function(attr) {
try {
self.addAttribute(self.nsAttributeName(attr.name), attr.value);
} catch (e) {
console.warn('[writer] missing namespace information for ', attr.name, '=', attr.value, 'on', element, e);
}
});
};
ElementSerializer.prototype.parseContainments = function(properties) {
var self = this,
body = this.body,
element = this.element,
typeDesc = element.$descriptor;
_.forEach(properties, function(p) {
var value = element.get(p.name),
isReference = p.isReference,
isMany = p.isMany;
var ns = self.nsPropertyTagName(p);
if (!isMany) {
value = [ value ];
}
if (p.isBody) {
body.push(new BodySerializer().build(p, value[0]));
} else
//if (Types.isSimple(p.type)) {
if (isSimple(p.type)) {
_.forEach(value, function(v) {
body.push(new ValueSerializer(ns).build(p, v));
});
} else
if (isReference) {
_.forEach(value, function(v) {
body.push(new ReferenceSerializer(self, ns).build(v));
});
} else {
// allow serialization via type
// rather than element name
var asType = p.serialize === 'xsi:type';
_.forEach(value, function(v) {
var serializer;
if (asType) {
serializer = new TypeSerializer(self, ns);
} else {
serializer = new ElementSerializer(self);
}
body.push(serializer.build(v));
});
}
});
};
ElementSerializer.prototype.getNamespaces = function() {
if (!this.parent) {
if (!this.namespaces) {
this.namespaces = {
prefixMap: {},
uriMap: {},
used: {}
};
}
} else {
this.namespaces = this.parent.getNamespaces();
}
return this.namespaces;
};
ElementSerializer.prototype.logNamespace = function(ns) {
var namespaces = this.getNamespaces();
var existing = namespaces.uriMap[ns.uri];
if (!existing) {
namespaces.uriMap[ns.uri] = ns;
}
namespaces.prefixMap[ns.prefix] = ns.uri;
return ns;
};
ElementSerializer.prototype.logNamespaceUsed = function(ns) {
var element = this.element,
model = element.$model,
namespaces = this.getNamespaces();
// ns may be
//
// * prefix only
// * prefix:uri
var prefix = ns.prefix;
var uri = ns.uri || DEFAULT_NS_MAP[prefix] ||
namespaces.prefixMap[prefix] || (model ? (model.getPackage(prefix) || {}).uri : null);
if (!uri) {
throw new Error('no namespace uri given for prefix <' + ns.prefix + '>');
}
ns = namespaces.uriMap[uri];
if (!ns) {
ns = this.logNamespace({ prefix: prefix, uri: uri });
}
if (!namespaces.used[ns.uri]) {
namespaces.used[ns.uri] = ns;
}
return ns;
};
ElementSerializer.prototype.parseAttributes = function(properties) {
var self = this,
element = this.element;
_.forEach(properties, function(p) {
self.logNamespaceUsed(p.ns);
var value = element.get(p.name);
if (p.isReference) {
value = value.id;
}
self.addAttribute(self.nsAttributeName(p), value);
});
};
ElementSerializer.prototype.addAttribute = function(name, value) {
var attrs = this.attrs;
if (_.isString(value)) {
value = escapeAttr(value);
}
attrs.push({ name: name, value: value });
};
ElementSerializer.prototype.serializeAttributes = function(writer) {
var element = this.element,
attrs = this.attrs,
root = !this.parent,
namespaces = this.namespaces;
function collectNsAttrs() {
return _.collect(namespaces.used, function(ns) {
var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : '');
return { name: name, value: ns.uri };
});
}
if (root) {
attrs = collectNsAttrs().concat(attrs);
}
_.forEach(attrs, function(a) {
writer
.append(' ')
.append(nsName(a.name)).append('="').append(a.value).append('"');
});
};
ElementSerializer.prototype.serializeTo = function(writer) {
var hasBody = this.body.length;
writer
.appendIndent()
.append('<' + nsName(this.ns));
this.serializeAttributes(writer);
writer
.append(hasBody ? '>' : ' />')
.appendNewLine();
writer.indent();
_.forEach(this.body, function(b) {
b.serializeTo(writer);
});
writer.unindent();
if (hasBody) {
writer
.appendIndent()
.append('</' + nsName(this.ns) + '>')
.appendNewLine();
}
};
/**
* A serializer for types that handles serialization of data types
*/
function TypeSerializer(parent, ns) {
ElementSerializer.call(this, parent, ns);
}
TypeSerializer.prototype = new ElementSerializer();
TypeSerializer.prototype.build = function(element) {
this.element = element;
this.typeNs = this.nsTagName(element.$descriptor);
return ElementSerializer.prototype.build.call(this, element);
};
TypeSerializer.prototype.isLocalNs = function(ns) {
return ns.uri === this.typeNs.uri;
};
function SavingWriter() {
this.value = '';
this.write = function(str) {
this.value += str;
};
}
function FormatingWriter(out, format) {
var indent = [''];
this.append = function(str) {
out.write(str);
return this;
};
this.appendNewLine = function() {
if (format) {
out.write('\n');
}
return this;
};
this.appendIndent = function() {
if (format) {
out.write(indent.join(' '));
}
return this;
};
this.indent = function() {
indent.push('');
return this;
};
this.unindent = function() {
indent.pop();
return this;
};
}
/**
* A writer for meta-model backed document trees
*
* @class XMLWriter
*/
function XMLWriter(options) {
options = _.extend({ format: false, preamble: true }, options || {});
function toXML(tree, writer) {
var internalWriter = writer || new SavingWriter();
var formatingWriter = new FormatingWriter(internalWriter, options.format);
if (options.preamble) {
formatingWriter.append(XML_PREAMBLE);
}
new ElementSerializer().build(tree).serializeTo(formatingWriter);
if (!writer) {
return internalWriter.value;
}
}
return {
toXML: toXML
};
}
//module.exports = XMLWriter;
'use strict';
//
//var _ = require('lodash');
//
//var Moddle = require('bpmn-moddle');
//ModdleXml = require('moddle-xml');
//
function createModel(packages) {
return new Moddle(packages);
}
/**
* A sub class of {@link Moddle} with support for import and export of BPMN 2.0 xml files.
*
* @class BpmnModdle
* @extends Moddle
*
* @param {Object|Array} packages to use for instantiating the model
* @param {Object} [options] additional options to pass over
*/
function BpmnModdle(packages, options) {
var packages = {
bpmn: {
"name": "BPMN20",
"uri": "http://www.omg.org/spec/BPMN/20100524/MODEL",
"associations": [],
"types": [
{
"name": "Interface",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "operations",
"type": "Operation",
"association": "A_operations_interface",
"isMany": true
},
{
"name": "implementationRef",
"type": "String",
"isAttr": true
}
]
},
{
"name": "Operation",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "inMessageRef",
"type": "Message",
"association": "A_inMessageRef_operation",
"isAttr": true,
"isReference": true
},
{
"name": "outMessageRef",
"type": "Message",
"association": "A_outMessageRef_operation",
"isAttr": true,
"isReference": true
},
{
"name": "errorRefs",
"type": "Error",
"association": "A_errorRefs_operation",
"isMany": true,
"isReference": true
},
{
"name": "implementationRef",
"type": "String",
"isAttr": true
}
]
},
{
"name": "EndPoint",
"superClass": [
"RootElement"
]
},
{
"name": "Auditing",
"superClass": [
"BaseElement"
]
},
{
"name": "GlobalTask",
"superClass": [
"CallableElement"
],
"properties": [
{
"name": "resources",
"type": "ResourceRole",
"association": "A_resources_globalTask",
"isMany": true
}
]
},
{
"name": "Monitoring",
"superClass": [
"BaseElement"
]
},
{
"name": "Performer",
"superClass": [
"ResourceRole"
]
},
{
"name": "Process",
"superClass": [
"FlowElementsContainer",
"CallableElement"
],
"properties": [
{
"name": "processType",
"type": "ProcessType",
"isAttr": true
},
{
"name": "isClosed",
"isAttr": true,
"type": "Boolean"
},
{
"name": "auditing",
"type": "Auditing",
"association": "A_auditing_process"
},
{
"name": "monitoring",
"type": "Monitoring",
"association": "A_monitoring_process"
},
{
"name": "properties",
"type": "Property",
"association": "A_properties_process",
"isMany": true
},
{
"name": "supports",
"type": "Process",
"association": "A_supports_process",
"isMany": true,
"isReference": true
},
{
"name": "definitionalCollaborationRef",
"type": "Collaboration",
"association": "A_definitionalCollaborationRef_process",
"isAttr": true,
"isReference": true
},
{
"name": "isExecutable",
"isAttr": true,
"type": "Boolean"
},
{
"name": "resources",
"type": "ResourceRole",
"association": "A_resources_process",
"isMany": true
},
{
"name": "artifacts",
"type": "Artifact",
"association": "A_artifacts_process",
"isMany": true
},
{
"name": "correlationSubscriptions",
"type": "CorrelationSubscription",
"association": "A_correlationSubscriptions_process",
"isMany": true
}
]
},
{
"name": "LaneSet",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "lanes",
"type": "Lane",
"association": "A_lanes_laneSet",
"isMany": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Lane",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "childLaneSet",
"type": "LaneSet",
"association": "A_childLaneSet_parentLane"
},
{
"name": "partitionElementRef",
"type": "BaseElement",
"association": "A_partitionElementRef_lane",
"isAttr": true,
"isReference": true
},
{
"name": "flowNodeRef",
"type": "FlowNode",
"association": "A_flowNodeRefs_lanes",
"isMany": true,
"isReference": true
},
{
"name": "partitionElement",
"type": "BaseElement",
"association": "A_partitionElement_lane"
}
]
},
{
"name": "GlobalManualTask",
"superClass": [
"GlobalTask"
]
},
{
"name": "ManualTask",
"superClass": [
"Task"
]
},
{
"name": "UserTask",
"superClass": [
"Task"
],
"properties": [
{
"name": "renderings",
"type": "Rendering",
"association": "A_renderings_usertask",
"isMany": true
},
{
"name": "implementation",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Rendering",
"superClass": [
"BaseElement"
]
},
{
"name": "HumanPerformer",
"superClass": [
"Performer"
]
},
{
"name": "PotentialOwner",
"superClass": [
"HumanPerformer"
]
},
{
"name": "GlobalUserTask",
"superClass": [
"GlobalTask"
],
"properties": [
{
"name": "implementation",
"isAttr": true,
"type": "String"
},
{
"name": "renderings",
"type": "Rendering",
"association": "A_renderings_globalUserTask",
"isMany": true
}
]
},
{
"name": "Gateway",
"isAbstract": true,
"superClass": [
"FlowNode"
],
"properties": [
{
"name": "gatewayDirection",
"type": "GatewayDirection",
"default": "Unspecified",
"isAttr": true
}
]
},
{
"name": "EventBasedGateway",
"superClass": [
"Gateway"
],
"properties": [
{
"name": "instantiate",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "eventGatewayType",
"type": "EventBasedGatewayType",
"isAttr": true,
"default": "Exclusive"
}
]
},
{
"name": "ComplexGateway",
"superClass": [
"Gateway"
],
"properties": [
{
"name": "activationCondition",
"type": "Expression",
"association": "A_activationCondition_complexGateway"
},
{
"name": "default",
"type": "SequenceFlow",
"association": "A_default_complexGateway",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ExclusiveGateway",
"superClass": [
"Gateway"
],
"properties": [
{
"name": "default",
"type": "SequenceFlow",
"association": "A_default_exclusiveGateway",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "InclusiveGateway",
"superClass": [
"Gateway"
],
"properties": [
{
"name": "default",
"type": "SequenceFlow",
"association": "A_default_inclusiveGateway",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ParallelGateway",
"superClass": [
"Gateway"
]
},
{
"name": "RootElement",
"isAbstract": true,
"superClass": [
"BaseElement"
]
},
{
"name": "Relationship",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "type",
"isAttr": true,
"type": "String"
},
{
"name": "direction",
"type": "RelationshipDirection",
"isAttr": true
},
{
"name": "sources",
"association": "A_sources_relationship",
"isMany": true,
"isReference": true,
"type": "Element"
},
{
"name": "targets",
"association": "A_targets_relationship",
"isMany": true,
"isReference": true,
"type": "Element"
}
]
},
{
"name": "BaseElement",
"isAbstract": true,
"properties": [
{
"name": "id",
"isAttr": true,
"type": "String"
},
{
"name": "extensionDefinitions",
"type": "ExtensionDefinition",
"association": "A_extensionDefinitions_baseElement",
"isMany": true,
"isReference": true
},
{
"name": "extensionElements",
"type": "ExtensionElements",
"association": "A_extensionElements_baseElement"
},
{
"name": "documentation",
"type": "Documentation",
"association": "A_documentation_baseElement",
"isMany": true
}
]
},
{
"name": "Extension",
"properties": [
{
"name": "mustUnderstand",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "definition",
"type": "ExtensionDefinition",
"association": "A_definition_extension"
}
]
},
{
"name": "ExtensionDefinition",
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "extensionAttributeDefinitions",
"type": "ExtensionAttributeDefinition",
"association": "A_extensionAttributeDefinitions_extensionDefinition",
"isMany": true
}
]
},
{
"name": "ExtensionAttributeDefinition",
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "type",
"isAttr": true,
"type": "String"
},
{
"name": "isReference",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "extensionDefinition",
"type": "ExtensionDefinition",
"association": "A_extensionAttributeDefinitions_extensionDefinition",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ExtensionElements",
"properties": [
{
"name": "valueRef",
"association": "A_valueRef_extensionElements",
"isAttr": true,
"isReference": true,
"type": "Element"
},
{
"name": "values",
"association": "A_value_extensionElements",
"type": "Element",
"isMany": true
},
{
"name": "extensionAttributeDefinition",
"type": "ExtensionAttributeDefinition",
"association": "A_extensionAttributeDefinition_extensionElements",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Documentation",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "text",
"type": "String",
"isBody": true
},
{
"name": "textFormat",
"default": "text/plain",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Event",
"isAbstract": true,
"superClass": [
"FlowNode",
"InteractionNode"
],
"properties": [
{
"name": "properties",
"type": "Property",
"association": "A_properties_event",
"isMany": true
}
]
},
{
"name": "IntermediateCatchEvent",
"superClass": [
"CatchEvent"
]
},
{
"name": "IntermediateThrowEvent",
"superClass": [
"ThrowEvent"
]
},
{
"name": "EndEvent",
"superClass": [
"ThrowEvent"
]
},
{
"name": "StartEvent",
"superClass": [
"CatchEvent"
],
"properties": [
{
"name": "isInterrupting",
"default": true,
"isAttr": true,
"type": "Boolean"
}
]
},
{
"name": "ThrowEvent",
"isAbstract": true,
"superClass": [
"Event"
],
"properties": [
{
"name": "inputSet",
"type": "InputSet",
"association": "A_inputSet_throwEvent"
},
{
"name": "eventDefinitionRefs",
"type": "EventDefinition",
"association": "A_eventDefinitionRefs_throwEvent",
"isMany": true,
"isReference": true
},
{
"name": "dataInputAssociation",
"type": "DataInputAssociation",
"association": "A_dataInputAssociation_throwEvent",
"isMany": true
},
{
"name": "dataInputs",
"type": "DataInput",
"association": "A_dataInputs_throwEvent",
"isMany": true
},
{
"name": "eventDefinitions",
"type": "EventDefinition",
"association": "A_eventDefinitions_throwEvent",
"isMany": true
}
]
},
{
"name": "CatchEvent",
"isAbstract": true,
"superClass": [
"Event"
],
"properties": [
{
"name": "parallelMultiple",
"isAttr": true,
"type": "Boolean",
"default": false
},
{
"name": "outputSet",
"type": "OutputSet",
"association": "A_outputSet_catchEvent"
},
{
"name": "eventDefinitionRefs",
"type": "EventDefinition",
"association": "A_eventDefinitionRefs_catchEvent",
"isMany": true,
"isReference": true
},
{
"name": "dataOutputAssociation",
"type": "DataOutputAssociation",
"association": "A_dataOutputAssociation_catchEvent",
"isMany": true
},
{
"name": "dataOutputs",
"type": "DataOutput",
"association": "A_dataOutputs_catchEvent",
"isMany": true
},
{
"name": "eventDefinitions",
"type": "EventDefinition",
"association": "A_eventDefinitions_catchEvent",
"isMany": true
}
]
},
{
"name": "BoundaryEvent",
"superClass": [
"CatchEvent"
],
"properties": [
{
"name": "cancelActivity",
"default": true,
"isAttr": true,
"type": "Boolean"
},
{
"name": "attachedToRef",
"type": "Activity",
"association": "A_boundaryEventRefs_attachedToRef",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "EventDefinition",
"isAbstract": true,
"superClass": [
"RootElement"
]
},
{
"name": "CancelEventDefinition",
"superClass": [
"EventDefinition"
]
},
{
"name": "ErrorEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "errorRef",
"type": "Error",
"association": "A_errorRef_errorEventDefinition",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "TerminateEventDefinition",
"superClass": [
"EventDefinition"
]
},
{
"name": "EscalationEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "escalationRef",
"type": "Escalation",
"association": "A_escalationRef_escalationEventDefinition",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Escalation",
"properties": [
{
"name": "structureRef",
"type": "ItemDefinition",
"association": "A_structureRef_escalation",
"isAttr": true,
"isReference": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "escalationCode",
"isAttr": true,
"type": "String"
}
],
"superClass": [
"RootElement"
]
},
{
"name": "CompensateEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "waitForCompletion",
"isAttr": true,
"type": "Boolean"
},
{
"name": "activityRef",
"type": "Activity",
"association": "A_activityRef_compensateEventDefinition",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "TimerEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "timeDate",
"type": "Expression",
"association": "A_timeDate_timerEventDefinition"
},
{
"name": "timeCycle",
"type": "Expression",
"association": "A_timeCycle_timerEventDefinition"
},
{
"name": "timeDuration",
"type": "Expression",
"association": "A_timeDuration_timerEventDefinition"
}
]
},
{
"name": "LinkEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "target",
"type": "LinkEventDefinition",
"association": "A_target_source",
"isAttr": true,
"isReference": true
},
{
"name": "source",
"type": "LinkEventDefinition",
"association": "A_target_source",
"isMany": true,
"isReference": true
}
]
},
{
"name": "MessageEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "messageRef",
"type": "Message",
"association": "A_messageRef_messageEventDefinition",
"isAttr": true,
"isReference": true
},
{
"name": "operationRef",
"type": "Operation",
"association": "A_operationRef_messageEventDefinition",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ConditionalEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "condition",
"type": "Expression",
"association": "A_condition_conditionalEventDefinition",
"serialize": "xsi:type"
}
]
},
{
"name": "SignalEventDefinition",
"superClass": [
"EventDefinition"
],
"properties": [
{
"name": "signalRef",
"type": "Signal",
"association": "A_signalRef_signalEventDefinition",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Signal",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "structureRef",
"type": "ItemDefinition",
"association": "A_structureRef_signal",
"isAttr": true,
"isReference": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ImplicitThrowEvent",
"superClass": [
"ThrowEvent"
]
},
{
"name": "DataState",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ItemAwareElement",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "itemSubjectRef",
"type": "ItemDefinition",
"association": "A_itemSubjectRef_itemAwareElement",
"isAttr": true,
"isReference": true
},
{
"name": "dataState",
"type": "DataState",
"association": "A_dataState_itemAwareElement"
}
]
},
{
"name": "DataAssociation",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "transformation",
"type": "FormalExpression",
"association": "A_transformation_dataAssociation"
},
{
"name": "assignment",
"type": "Assignment",
"association": "A_assignment_dataAssociation",
"isMany": true
},
{
"name": "sourceRef",
"type": "ItemAwareElement",
"association": "A_sourceRef_dataAssociation",
"isMany": true,
"isReference": true
},
{
"name": "targetRef",
"type": "ItemAwareElement",
"association": "A_targetRef_dataAssociation",
"isReference": true
}
]
},
{
"name": "DataInput",
"superClass": [
"ItemAwareElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "isCollection",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "inputSetRefs",
"type": "InputSet",
"association": "A_dataInputRefs_inputSetRefs",
"isVirtual": true,
"isMany": true,
"isReference": true
},
{
"name": "inputSetWithOptional",
"type": "InputSet",
"association": "A_optionalInputRefs_inputSetWithOptional",
"isVirtual": true,
"isMany": true,
"isReference": true
},
{
"name": "inputSetWithWhileExecuting",
"type": "InputSet",
"association": "A_whileExecutingInputRefs_inputSetWithWhileExecuting",
"isVirtual": true,
"isMany": true,
"isReference": true
}
]
},
{
"name": "DataOutput",
"superClass": [
"ItemAwareElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "isCollection",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "outputSetRefs",
"type": "OutputSet",
"association": "A_dataOutputRefs_outputSetRefs",
"isVirtual": true,
"isMany": true,
"isReference": true
},
{
"name": "outputSetWithOptional",
"type": "OutputSet",
"association": "A_outputSetWithOptional_optionalOutputRefs",
"isVirtual": true,
"isMany": true,
"isReference": true
},
{
"name": "outputSetWithWhileExecuting",
"type": "OutputSet",
"association": "A_outputSetWithWhileExecuting_whileExecutingOutputRefs",
"isVirtual": true,
"isMany": true,
"isReference": true
}
]
},
{
"name": "InputSet",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "dataInputRefs",
"type": "DataInput",
"association": "A_dataInputRefs_inputSetRefs",
"isMany": true,
"isReference": true
},
{
"name": "optionalInputRefs",
"type": "DataInput",
"association": "A_optionalInputRefs_inputSetWithOptional",
"isMany": true,
"isReference": true
},
{
"name": "whileExecutingInputRefs",
"type": "DataInput",
"association": "A_whileExecutingInputRefs_inputSetWithWhileExecuting",
"isMany": true,
"isReference": true
},
{
"name": "outputSetRefs",
"type": "OutputSet",
"association": "A_inputSetRefs_outputSetRefs",
"isMany": true,
"isReference": true
}
]
},
{
"name": "OutputSet",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "dataOutputRefs",
"type": "DataOutput",
"association": "A_dataOutputRefs_outputSetRefs",
"isMany": true,
"isReference": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "inputSetRefs",
"type": "InputSet",
"association": "A_inputSetRefs_outputSetRefs",
"isMany": true,
"isReference": true
},
{
"name": "optionalOutputRefs",
"type": "DataOutput",
"association": "A_outputSetWithOptional_optionalOutputRefs",
"isMany": true,
"isReference": true
},
{
"name": "whileExecutingOutputRefs",
"type": "DataOutput",
"association": "A_outputSetWithWhileExecuting_whileExecutingOutputRefs",
"isMany": true,
"isReference": true
}
]
},
{
"name": "Property",
"superClass": [
"ItemAwareElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "DataInputAssociation",
"superClass": [
"DataAssociation"
]
},
{
"name": "DataOutputAssociation",
"superClass": [
"DataAssociation"
]
},
{
"name": "InputOutputSpecification",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "inputSets",
"type": "InputSet",
"association": "A_inputSets_inputOutputSpecification",
"isMany": true
},
{
"name": "outputSets",
"type": "OutputSet",
"association": "A_outputSets_inputOutputSpecification",
"isMany": true
},
{
"name": "dataInputs",
"type": "DataInput",
"association": "A_dataInputs_inputOutputSpecification",
"isMany": true
},
{
"name": "dataOutputs",
"type": "DataOutput",
"association": "A_dataOutputs_inputOutputSpecification",
"isMany": true
}
]
},
{
"name": "DataObject",
"superClass": [
"FlowElement",
"ItemAwareElement"
],
"properties": [
{
"name": "isCollection",
"default": false,
"isAttr": true,
"type": "Boolean"
}
]
},
{
"name": "InputOutputBinding",
"properties": [
{
"name": "inputDataRef",
"type": "InputSet",
"association": "A_inputDataRef_inputOutputBinding",
"isAttr": true,
"isReference": true
},
{
"name": "outputDataRef",
"type": "OutputSet",
"association": "A_outputDataRef_inputOutputBinding",
"isAttr": true,
"isReference": true
},
{
"name": "operationRef",
"type": "Operation",
"association": "A_operationRef_ioBinding",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Assignment",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "from",
"type": "Expression",
"association": "A_from_assignment"
},
{
"name": "to",
"type": "Expression",
"association": "A_to_assignment"
}
]
},
{
"name": "DataStore",
"superClass": [
"RootElement",
"ItemAwareElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "capacity",
"isAttr": true,
"type": "Integer"
},
{
"name": "isUnlimited",
"default": true,
"isAttr": true,
"type": "Boolean"
}
]
},
{
"name": "DataStoreReference",
"superClass": [
"ItemAwareElement",
"FlowElement"
],
"properties": [
{
"name": "dataStoreRef",
"type": "DataStore",
"association": "A_dataStoreRef_dataStoreReference",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "DataObjectReference",
"superClass": [
"ItemAwareElement",
"FlowElement"
],
"properties": [
{
"name": "dataObjectRef",
"type": "DataObject",
"association": "A_dataObjectRef_dataObject",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ConversationLink",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "sourceRef",
"type": "InteractionNode",
"association": "A_sourceRef_outgoingConversationLinks",
"isAttr": true,
"isReference": true
},
{
"name": "targetRef",
"type": "InteractionNode",
"association": "A_targetRef_incomingConversationLinks",
"isAttr": true,
"isReference": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ConversationAssociation",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "innerConversationNodeRef",
"type": "ConversationNode",
"association": "A_innerConversationNodeRef_conversationAssociation",
"isAttr": true,
"isReference": true
},
{
"name": "outerConversationNodeRef",
"type": "ConversationNode",
"association": "A_outerConversationNodeRef_conversationAssociation",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "CallConversation",
"superClass": [
"ConversationNode"
],
"properties": [
{
"name": "calledCollaborationRef",
"type": "Collaboration",
"association": "A_calledCollaborationRef_callConversation",
"isAttr": true,
"isReference": true
},
{
"name": "participantAssociations",
"type": "ParticipantAssociation",
"association": "A_participantAssociations_callConversation",
"isMany": true
}
]
},
{
"name": "Conversation",
"superClass": [
"ConversationNode"
]
},
{
"name": "SubConversation",
"superClass": [
"ConversationNode"
],
"properties": [
{
"name": "conversationNodes",
"type": "ConversationNode",
"association": "A_conversationNodes_subConversation",
"isMany": true
}
]
},
{
"name": "ConversationNode",
"isAbstract": true,
"superClass": [
"InteractionNode",
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "participantRefs",
"type": "Participant",
"association": "A_participantRefs_conversationNode",
"isMany": true,
"isReference": true
},
{
"name": "messageFlowRefs",
"type": "MessageFlow",
"association": "A_messageFlowRefs_communication",
"isMany": true,
"isReference": true
},
{
"name": "correlationKeys",
"type": "CorrelationKey",
"association": "A_correlationKeys_conversationNode",
"isMany": true
}
]
},
{
"name": "GlobalConversation",
"superClass": [
"Collaboration"
]
},
{
"name": "PartnerEntity",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "participantRef",
"type": "Participant",
"association": "A_partnerEntityRef_participantRef",
"isMany": true,
"isReference": true
}
]
},
{
"name": "PartnerRole",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "participantRef",
"type": "Participant",
"association": "A_partnerRoleRef_participantRef",
"isMany": true,
"isReference": true
}
]
},
{
"name": "CorrelationProperty",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "correlationPropertyRetrievalExpression",
"type": "CorrelationPropertyRetrievalExpression",
"association": "A_correlationPropertyRetrievalExpression_correlationproperty",
"isMany": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "type",
"type": "ItemDefinition",
"association": "A_type_correlationProperty",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Error",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "structureRef",
"type": "ItemDefinition",
"association": "A_structureRef_error",
"isAttr": true,
"isReference": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "errorCode",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "CorrelationKey",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "correlationPropertyRef",
"type": "CorrelationProperty",
"association": "A_correlationPropertyRef_correlationKey",
"isMany": true,
"isReference": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Expression",
"superClass": [
"BaseElement"
]
},
{
"name": "FormalExpression",
"superClass": [
"Expression"
],
"properties": [
{
"name": "language",
"isAttr": true,
"type": "String"
},
{
"name": "body",
"type": "Element"
},
{
"name": "evaluatesToTypeRef",
"type": "ItemDefinition",
"association": "A_evaluatesToTypeRef_formalExpression",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Message",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "itemRef",
"type": "ItemDefinition",
"association": "A_itemRef_message",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ItemDefinition",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "itemKind",
"type": "ItemKind",
"isAttr": true
},
{
"name": "structureRef",
"type": "String",
"isAttr": true
},
{
"name": "isCollection",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "import",
"type": "Import",
"association": "A_import_itemDefinition",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "FlowElement",
"isAbstract": true,
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "auditing",
"type": "Auditing",
"association": "A_auditing_flowElement"
},
{
"name": "monitoring",
"type": "Monitoring",
"association": "A_monitoring_flowElement"
},
{
"name": "categoryValueRef",
"type": "CategoryValue",
"association": "A_categorizedFlowElements_categoryValueRef",
"isMany": true,
"isReference": true
}
]
},
{
"name": "SequenceFlow",
"superClass": [
"FlowElement"
],
"properties": [
{
"name": "isImmediate",
"isAttr": true,
"type": "Boolean"
},
{
"name": "conditionExpression",
"type": "Expression",
"association": "A_conditionExpression_sequenceFlow"
},
{
"name": "sourceRef",
"type": "FlowNode",
"association": "A_sourceRef_outgoing_flow",
"isAttr": true,
"isReference": true
},
{
"name": "targetRef",
"type": "FlowNode",
"association": "A_targetRef_incoming_flow",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "FlowElementsContainer",
"isAbstract": true,
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "laneSets",
"type": "LaneSet",
"association": "A_laneSets_flowElementsContainer",
"isMany": true
},
{
"name": "flowElements",
"type": "FlowElement",
"association": "A_flowElements_container",
"isMany": true
}
]
},
{
"name": "CallableElement",
"isAbstract": true,
"superClass": [
"RootElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "ioSpecification",
"type": "InputOutputSpecification",
"association": "A_ioSpecification_callableElement"
},
{
"name": "supportedInterfaceRefs",
"type": "Interface",
"association": "A_supportedInterfaceRefs_callableElements",
"isMany": true,
"isReference": true
},
{
"name": "ioBinding",
"type": "InputOutputBinding",
"association": "A_ioBinding_callableElement",
"isMany": true
}
]
},
{
"name": "FlowNode",
"isAbstract": true,
"superClass": [
"FlowElement"
],
"properties": [
{
"name": "incoming",
"type": "SequenceFlow",
"association": "A_targetRef_incoming_flow",
"isMany": true,
"isReference": true
},
{
"name": "outgoing",
"type": "SequenceFlow",
"association": "A_sourceRef_outgoing_flow",
"isMany": true,
"isReference": true
},
{
"name": "lanes",
"type": "Lane",
"association": "A_flowNodeRefs_lanes",
"isVirtual": true,
"isMany": true,
"isReference": true
}
]
},
{
"name": "CorrelationPropertyRetrievalExpression",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "messagePath",
"type": "FormalExpression",
"association": "A_messagePath_correlationset"
},
{
"name": "messageRef",
"type": "Message",
"association": "A_messageRef_correlationPropertyRetrievalExpression",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "CorrelationPropertyBinding",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "dataPath",
"type": "FormalExpression",
"association": "A_dataPath_correlationPropertyBinding"
},
{
"name": "correlationPropertyRef",
"type": "CorrelationProperty",
"association": "A_correlationPropertyRef_correlationPropertyBinding",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Resource",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "resourceParameters",
"type": "ResourceParameter",
"association": "A_resourceParameters_resource",
"isMany": true
}
]
},
{
"name": "ResourceParameter",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "isRequired",
"isAttr": true,
"type": "Boolean"
},
{
"name": "type",
"type": "ItemDefinition",
"association": "A_type_resourceParameter",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "CorrelationSubscription",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "correlationKeyRef",
"type": "CorrelationKey",
"association": "A_correlationKeyRef_correlationSubscription",
"isAttr": true,
"isReference": true
},
{
"name": "correlationPropertyBinding",
"type": "CorrelationPropertyBinding",
"association": "A_correlationPropertyBinding_correlationSubscription",
"isMany": true
}
]
},
{
"name": "MessageFlow",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "sourceRef",
"type": "InteractionNode",
"association": "A_sourceRef_messageFlow",
"isAttr": true,
"isReference": true
},
{
"name": "targetRef",
"type": "InteractionNode",
"association": "A_targetRef_messageFlow",
"isAttr": true,
"isReference": true
},
{
"name": "messageRef",
"type": "Message",
"association": "A_messageRef_messageFlow",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "MessageFlowAssociation",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "innerMessageFlowRef",
"type": "MessageFlow",
"association": "A_innerMessageFlowRef_messageFlowAssociation",
"isAttr": true,
"isReference": true
},
{
"name": "outerMessageFlowRef",
"type": "MessageFlow",
"association": "A_outerMessageFlowRef_messageFlowAssociation",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "InteractionNode",
"isAbstract": true,
"properties": [
{
"name": "incomingConversationLinks",
"type": "ConversationLink",
"association": "A_targetRef_incomingConversationLinks",
"isVirtual": true,
"isMany": true,
"isReference": true
},
{
"name": "outgoingConversationLinks",
"type": "ConversationLink",
"association": "A_sourceRef_outgoingConversationLinks",
"isVirtual": true,
"isMany": true,
"isReference": true
}
]
},
{
"name": "Participant",
"superClass": [
"InteractionNode",
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "interfaceRefs",
"type": "Interface",
"association": "A_interfaceRefs_participant",
"isMany": true,
"isReference": true
},
{
"name": "participantMultiplicity",
"type": "ParticipantMultiplicity",
"association": "A_participantMultiplicity_participant"
},
{
"name": "endPointRefs",
"type": "EndPoint",
"association": "A_endPointRefs_participant",
"isMany": true,
"isReference": true
},
{
"name": "processRef",
"type": "Process",
"association": "A_processRef_participant",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ParticipantAssociation",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "innerParticipantRef",
"type": "Participant",
"association": "A_innerParticipantRef_participantAssociation",
"isAttr": true,
"isReference": true
},
{
"name": "outerParticipantRef",
"type": "Participant",
"association": "A_outerParticipantRef_participantAssociation",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ParticipantMultiplicity",
"properties": [
{
"name": "minimum",
"default": 0,
"isAttr": true,
"type": "Integer"
},
{
"name": "maximum",
"default": 1,
"isAttr": true,
"type": "Integer"
}
]
},
{
"name": "Collaboration",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "isClosed",
"isAttr": true,
"type": "Boolean"
},
{
"name": "choreographyRef",
"type": "Choreography",
"association": "A_choreographyRef_collaboration",
"isMany": true,
"isReference": true
},
{
"name": "artifacts",
"type": "Artifact",
"association": "A_artifacts_collaboration",
"isMany": true
},
{
"name": "participantAssociations",
"type": "ParticipantAssociation",
"association": "A_participantAssociations_collaboration",
"isMany": true
},
{
"name": "messageFlowAssociations",
"type": "MessageFlowAssociation",
"association": "A_messageFlowAssociations_collaboration",
"isMany": true
},
{
"name": "conversationAssociations",
"type": "ConversationAssociation",
"association": "A_conversationAssociations_converstaionAssociations"
},
{
"name": "participants",
"type": "Participant",
"association": "A_participants_collaboration",
"isMany": true
},
{
"name": "messageFlows",
"type": "MessageFlow",
"association": "A_messageFlows_collaboration",
"isMany": true
},
{
"name": "correlationKeys",
"type": "CorrelationKey",
"association": "A_correlationKeys_collaboration",
"isMany": true
},
{
"name": "conversations",
"type": "ConversationNode",
"association": "A_conversations_collaboration",
"isMany": true
},
{
"name": "conversationLinks",
"type": "ConversationLink",
"association": "A_conversationLinks_collaboration",
"isMany": true
}
]
},
{
"name": "ChoreographyActivity",
"isAbstract": true,
"superClass": [
"FlowNode"
],
"properties": [
{
"name": "participantRefs",
"type": "Participant",
"association": "A_participantRefs_choreographyActivity",
"isMany": true,
"isReference": true
},
{
"name": "initiatingParticipantRef",
"type": "Participant",
"association": "A_initiatingParticipantRef_choreographyActivity",
"isAttr": true,
"isReference": true
},
{
"name": "correlationKeys",
"type": "CorrelationKey",
"association": "A_correlationKeys_choreographyActivity",
"isMany": true
},
{
"name": "loopType",
"type": "ChoreographyLoopType",
"default": "None",
"isAttr": true
}
]
},
{
"name": "CallChoreography",
"superClass": [
"ChoreographyActivity"
],
"properties": [
{
"name": "calledChoreographyRef",
"type": "Choreography",
"association": "A_calledChoreographyRef_callChoreographyActivity",
"isAttr": true,
"isReference": true
},
{
"name": "participantAssociations",
"type": "ParticipantAssociation",
"association": "A_participantAssociations_callChoreographyActivity",
"isMany": true
}
]
},
{
"name": "SubChoreography",
"superClass": [
"ChoreographyActivity",
"FlowElementsContainer"
],
"properties": [
{
"name": "artifacts",
"type": "Artifact",
"association": "A_artifacts_subChoreography",
"isMany": true
}
]
},
{
"name": "ChoreographyTask",
"superClass": [
"ChoreographyActivity"
],
"properties": [
{
"name": "messageFlowRef",
"type": "MessageFlow",
"association": "A_messageFlowRef_choreographyTask",
"isMany": true,
"isReference": true
}
]
},
{
"name": "Choreography",
"superClass": [
"FlowElementsContainer",
"Collaboration"
]
},
{
"name": "GlobalChoreographyTask",
"superClass": [
"Choreography"
],
"properties": [
{
"name": "initiatingParticipantRef",
"type": "Participant",
"association": "A_initiatingParticipantRef_globalChoreographyTask",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "TextAnnotation",
"superClass": [
"Artifact"
],
"properties": [
{
"name": "text",
"type": "String"
},
{
"name": "textFormat",
"default": "text/plain",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Group",
"superClass": [
"Artifact"
],
"properties": [
{
"name": "categoryValueRef",
"type": "CategoryValue",
"association": "A_categoryValueRef_categoryValueRef",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Association",
"superClass": [
"Artifact"
],
"properties": [
{
"name": "associationDirection",
"type": "AssociationDirection",
"isAttr": true
},
{
"name": "sourceRef",
"type": "BaseElement",
"association": "A_sourceRef_outgoing_association",
"isAttr": true,
"isReference": true
},
{
"name": "targetRef",
"type": "BaseElement",
"association": "A_targetRef_incoming_association",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "Category",
"superClass": [
"RootElement"
],
"properties": [
{
"name": "categoryValue",
"type": "CategoryValue",
"association": "A_categoryValue_category",
"isMany": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Artifact",
"isAbstract": true,
"superClass": [
"BaseElement"
]
},
{
"name": "CategoryValue",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "categorizedFlowElements",
"type": "FlowElement",
"association": "A_categorizedFlowElements_categoryValueRef",
"isVirtual": true,
"isMany": true,
"isReference": true
},
{
"name": "value",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Activity",
"isAbstract": true,
"superClass": [
"FlowNode"
],
"properties": [
{
"name": "isForCompensation",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "loopCharacteristics",
"type": "LoopCharacteristics",
"association": "A_loopCharacteristics_activity"
},
{
"name": "resources",
"type": "ResourceRole",
"association": "A_resources_activity",
"isMany": true
},
{
"name": "default",
"type": "SequenceFlow",
"association": "A_default_activity",
"isAttr": true,
"isReference": true
},
{
"name": "properties",
"type": "Property",
"association": "A_properties_activity",
"isMany": true
},
{
"name": "ioSpecification",
"type": "InputOutputSpecification",
"association": "A_ioSpecification_activity"
},
{
"name": "boundaryEventRefs",
"type": "BoundaryEvent",
"association": "A_boundaryEventRefs_attachedToRef",
"isMany": true,
"isReference": true
},
{
"name": "dataInputAssociations",
"type": "DataInputAssociation",
"association": "A_dataInputAssociations_activity",
"isMany": true
},
{
"name": "dataOutputAssociations",
"type": "DataOutputAssociation",
"association": "A_dataOutputAssociations_activity",
"isMany": true
},
{
"name": "startQuantity",
"default": 1,
"isAttr": true,
"type": "Integer"
},
{
"name": "completionQuantity",
"default": 1,
"isAttr": true,
"type": "Integer"
}
]
},
{
"name": "ServiceTask",
"superClass": [
"Task"
],
"properties": [
{
"name": "implementation",
"isAttr": true,
"type": "String"
},
{
"name": "operationRef",
"type": "Operation",
"association": "A_operationRef_serviceTask",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "SubProcess",
"superClass": [
"Activity",
"FlowElementsContainer"
],
"properties": [
{
"name": "triggeredByEvent",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "artifacts",
"type": "Artifact",
"association": "A_artifacts_subProcess",
"isMany": true
}
]
},
{
"name": "LoopCharacteristics",
"isAbstract": true,
"superClass": [
"BaseElement"
]
},
{
"name": "MultiInstanceLoopCharacteristics",
"superClass": [
"LoopCharacteristics"
],
"properties": [
{
"name": "isSequential",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "behavior",
"type": "MultiInstanceBehavior",
"default": "All",
"isAttr": true
},
{
"name": "loopCardinality",
"type": "Expression",
"association": "A_loopCardinality_multiInstanceLoopCharacteristics"
},
{
"name": "loopDataInputRef",
"type": "ItemAwareElement",
"association": "A_loopDataInputRef_multiInstanceLoopCharacteristics",
"isAttr": true,
"isReference": true
},
{
"name": "loopDataOutputRef",
"type": "ItemAwareElement",
"association": "A_loopDataOutputRef_multiInstanceLoopCharacteristics",
"isAttr": true,
"isReference": true
},
{
"name": "inputDataItem",
"type": "DataInput",
"association": "A_inputDataItem_multiInstanceLoopCharacteristics"
},
{
"name": "outputDataItem",
"type": "DataOutput",
"association": "A_outputDataItem_multiInstanceLoopCharacteristics"
},
{
"name": "completionCondition",
"type": "Expression",
"association": "A_completionCondition_multiInstanceLoopCharacteristics"
},
{
"name": "complexBehaviorDefinition",
"type": "ComplexBehaviorDefinition",
"association": "A_complexBehaviorDefinition_multiInstanceLoopCharacteristics",
"isMany": true
},
{
"name": "oneBehaviorEventRef",
"type": "EventDefinition",
"association": "A_oneBehaviorEventRef_multiInstanceLoopCharacteristics",
"isAttr": true,
"isReference": true
},
{
"name": "noneBehaviorEventRef",
"type": "EventDefinition",
"association": "A_noneBehaviorEventRef_multiInstanceLoopCharacteristics",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "StandardLoopCharacteristics",
"superClass": [
"LoopCharacteristics"
],
"properties": [
{
"name": "testBefore",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "loopCondition",
"type": "Expression",
"association": "A_loopCondition_standardLoopCharacteristics"
},
{
"name": "loopMaximum",
"type": "Expression",
"association": "A_loopMaximum_standardLoopCharacteristics"
}
]
},
{
"name": "CallActivity",
"superClass": [
"Activity"
],
"properties": [
{
"name": "calledElement",
"type": "String",
"association": "A_calledElementRef_callActivity",
"isAttr": true
}
]
},
{
"name": "Task",
"superClass": [
"Activity",
"InteractionNode"
]
},
{
"name": "SendTask",
"superClass": [
"Task"
],
"properties": [
{
"name": "implementation",
"isAttr": true,
"type": "String"
},
{
"name": "operationRef",
"type": "Operation",
"association": "A_operationRef_sendTask",
"isAttr": true,
"isReference": true
},
{
"name": "messageRef",
"type": "Message",
"association": "A_messageRef_sendTask",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ReceiveTask",
"superClass": [
"Task"
],
"properties": [
{
"name": "implementation",
"isAttr": true,
"type": "String"
},
{
"name": "instantiate",
"default": false,
"isAttr": true,
"type": "Boolean"
},
{
"name": "operationRef",
"type": "Operation",
"association": "A_operationRef_receiveTask",
"isAttr": true,
"isReference": true
},
{
"name": "messageRef",
"type": "Message",
"association": "A_messageRef_receiveTask",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ScriptTask",
"superClass": [
"Task"
],
"properties": [
{
"name": "scriptFormat",
"isAttr": true,
"type": "String"
},
{
"name": "script",
"type": "String"
}
]
},
{
"name": "BusinessRuleTask",
"superClass": [
"Task"
],
"properties": [
{
"name": "implementation",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "AdHocSubProcess",
"superClass": [
"SubProcess"
],
"properties": [
{
"name": "completionCondition",
"type": "Expression",
"association": "A_completionCondition_adHocSubProcess"
},
{
"name": "ordering",
"type": "AdHocOrdering",
"isAttr": true
},
{
"name": "cancelRemainingInstances",
"default": true,
"isAttr": true,
"type": "Boolean"
}
]
},
{
"name": "Transaction",
"superClass": [
"SubProcess"
],
"properties": [
{
"name": "protocol",
"isAttr": true,
"type": "String"
},
{
"name": "method",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "GlobalScriptTask",
"superClass": [
"GlobalTask"
],
"properties": [
{
"name": "scriptLanguage",
"isAttr": true,
"type": "String"
},
{
"name": "script",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "GlobalBusinessRuleTask",
"superClass": [
"GlobalTask"
],
"properties": [
{
"name": "implementation",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ComplexBehaviorDefinition",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "condition",
"type": "FormalExpression",
"association": "A_condition_complexBehaviorDefinition"
},
{
"name": "event",
"type": "ImplicitThrowEvent",
"association": "A_event_complexBehaviorDefinition"
}
]
},
{
"name": "ResourceRole",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "resourceRef",
"type": "Resource",
"association": "A_resourceRef_activityResource",
"isAttr": true,
"isReference": true
},
{
"name": "resourceParameterBindings",
"type": "ResourceParameterBinding",
"association": "A_resourceParameterBindings_activityResource",
"isMany": true
},
{
"name": "resourceAssignmentExpression",
"type": "ResourceAssignmentExpression",
"association": "A_resourceAssignmentExpression_activityResource"
},
{
"name": "name",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ResourceParameterBinding",
"properties": [
{
"name": "expression",
"type": "Expression",
"association": "A_expression_resourceParameterBinding"
},
{
"name": "parameterRef",
"type": "ResourceParameter",
"association": "A_parameterRef_resourceParameterBinding",
"isAttr": true,
"isReference": true
}
]
},
{
"name": "ResourceAssignmentExpression",
"properties": [
{
"name": "expression",
"type": "Expression",
"association": "A_expression_resourceAssignmentExpression"
}
]
},
{
"name": "Import",
"properties": [
{
"name": "importType",
"isAttr": true,
"type": "String"
},
{
"name": "location",
"isAttr": true,
"type": "String"
},
{
"name": "namespace",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Definitions",
"superClass": [
"BaseElement"
],
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "targetNamespace",
"isAttr": true,
"type": "String"
},
{
"name": "expressionLanguage",
"default": "http://www.w3.org/1999/XPath",
"isAttr": true,
"type": "String"
},
{
"name": "typeLanguage",
"default": "http://www.w3.org/2001/XMLSchema",
"isAttr": true,
"type": "String"
},
{
"name": "imports",
"type": "Import",
"association": "A_imports_definition",
"isMany": true
},
{
"name": "extensions",
"type": "Extension",
"association": "A_extensions_definitions",
"isMany": true
},
{
"name": "relationships",
"type": "Relationship",
"association": "A_relationships_definition",
"isMany": true
},
{
"name": "rootElements",
"type": "RootElement",
"association": "A_rootElements_definition",
"isMany": true
},
{
"name": "diagrams",
"association": "A_diagrams_definitions",
"isMany": true,
"type": "bpmndi:BPMNDiagram"
},
{
"name": "exporter",
"isAttr": true,
"type": "String"
},
{
"name": "exporterVersion",
"isAttr": true,
"type": "String"
}
]
}
],
"emumerations": [
{
"name": "ProcessType",
"literalValues": [
{
"name": "None"
},
{
"name": "Public"
},
{
"name": "Private"
}
]
},
{
"name": "GatewayDirection",
"literalValues": [
{
"name": "Unspecified"
},
{
"name": "Converging"
},
{
"name": "Diverging"
},
{
"name": "Mixed"
}
]
},
{
"name": "EventBasedGatewayType",
"literalValues": [
{
"name": "Parallel"
},
{
"name": "Exclusive"
}
]
},
{
"name": "RelationshipDirection",
"literalValues": [
{
"name": "None"
},
{
"name": "Forward"
},
{
"name": "Backward"
},
{
"name": "Both"
}
]
},
{
"name": "ItemKind",
"literalValues": [
{
"name": "Physical"
},
{
"name": "Information"
}
]
},
{
"name": "ChoreographyLoopType",
"literalValues": [
{
"name": "None"
},
{
"name": "Standard"
},
{
"name": "MultiInstanceSequential"
},
{
"name": "MultiInstanceParallel"
}
]
},
{
"name": "AssociationDirection",
"literalValues": [
{
"name": "None"
},
{
"name": "One"
},
{
"name": "Both"
}
]
},
{
"name": "MultiInstanceBehavior",
"literalValues": [
{
"name": "None"
},
{
"name": "One"
},
{
"name": "All"
},
{
"name": "Complex"
}
]
},
{
"name": "AdHocOrdering",
"literalValues": [
{
"name": "Parallel"
},
{
"name": "Sequential"
}
]
}
],
"prefix": "bpmn",
"xml": {
"alias": "lowerCase"
}
},
bpmndi: {
"name": "BPMNDI",
"uri": "http://www.omg.org/spec/BPMN/20100524/DI",
"types": [
{
"name": "BPMNDiagram",
"properties": [
{
"name": "plane",
"type": "BPMNPlane",
"association": "A_plane_diagram",
"redefines": "di:Diagram#rootElement"
},
{
"name": "labelStyle",
"type": "BPMNLabelStyle",
"association": "A_labelStyle_diagram",
"isMany": true
}
],
"superClass": [
"di:Diagram"
]
},
{
"name": "BPMNPlane",
"properties": [
{
"name": "bpmnElement",
"association": "A_bpmnElement_plane",
"isAttr": true,
"isReference": true,
"type": "bpmn:BaseElement",
"redefines": "di:DiagramElement#modelElement"
}
],
"superClass": [
"di:Plane"
]
},
{
"name": "BPMNShape",
"properties": [
{
"name": "bpmnElement",
"association": "A_bpmnElement_shape",
"isAttr": true,
"isReference": true,
"type": "bpmn:BaseElement",
"redefines": "di:DiagramElement#modelElement"
},
{
"name": "isHorizontal",
"isAttr": true,
"type": "Boolean"
},
{
"name": "isExpanded",
"isAttr": true,
"type": "Boolean"
},
{
"name": "isMarkerVisible",
"isAttr": true,
"type": "Boolean"
},
{
"name": "label",
"type": "BPMNLabel",
"association": "A_label_shape"
},
{
"name": "isMessageVisible",
"isAttr": true,
"type": "Boolean"
},
{
"name": "participantBandKind",
"type": "ParticipantBandKind",
"isAttr": true
},
{
"name": "choreographyActivityShape",
"type": "BPMNShape",
"association": "A_choreographyActivityShape_participantBandShape",
"isAttr": true,
"isReference": true
}
],
"superClass": [
"di:LabeledShape"
]
},
{
"name": "BPMNEdge",
"properties": [
{
"name": "label",
"type": "BPMNLabel",
"association": "A_label_edge"
},
{
"name": "bpmnElement",
"association": "A_bpmnElement_edge",
"isAttr": true,
"isReference": true,
"type": "bpmn:BaseElement",
"redefines": "di:DiagramElement#modelElement"
},
{
"name": "sourceElement",
"association": "A_sourceElement_sourceEdge",
"isAttr": true,
"isReference": true,
"type": "di:DiagramElement",
"redefines": "di:Edge#source"
},
{
"name": "targetElement",
"association": "A_targetElement_targetEdge",
"isAttr": true,
"isReference": true,
"type": "di:DiagramElement",
"redefines": "di:Edge#target"
},
{
"name": "messageVisibleKind",
"type": "MessageVisibleKind",
"isAttr": true,
"default": "initiating"
}
],
"superClass": [
"di:LabeledEdge"
]
},
{
"name": "BPMNLabel",
"properties": [
{
"name": "labelStyle",
"type": "BPMNLabelStyle",
"association": "A_labelStyle_label",
"isAttr": true,
"isReference": true,
"redefines": "di:DiagramElement#style"
}
],
"superClass": [
"di:Label"
]
},
{
"name": "BPMNLabelStyle",
"properties": [
{
"name": "font",
"type": "dc:Font"
}
],
"superClass": [
"di:Style"
]
}
],
"emumerations": [
{
"name": "ParticipantBandKind",
"literalValues": [
{
"name": "top_initiating"
},
{
"name": "middle_initiating"
},
{
"name": "bottom_initiating"
},
{
"name": "top_non_initiating"
},
{
"name": "middle_non_initiating"
},
{
"name": "bottom_non_initiating"
}
]
},
{
"name": "MessageVisibleKind",
"literalValues": [
{
"name": "initiating"
},
{
"name": "non_initiating"
}
]
}
],
"associations": [],
"prefix": "bpmndi"
},
dc: {
"name": "DC",
"uri": "http://www.omg.org/spec/DD/20100524/DC",
"types": [
{
"name": "Boolean"
},
{
"name": "Integer"
},
{
"name": "Real"
},
{
"name": "String"
},
{
"name": "Font",
"properties": [
{
"name": "name",
"type": "String",
"isAttr": true
},
{
"name": "size",
"type": "Real",
"isAttr": true
},
{
"name": "isBold",
"type": "Boolean",
"isAttr": true
},
{
"name": "isItalic",
"type": "Boolean",
"isAttr": true
},
{
"name": "isUnderline",
"type": "Boolean",
"isAttr": true
},
{
"name": "isStrikeThrough",
"type": "Boolean",
"isAttr": true
}
]
},
{
"name": "Point",
"properties": [
{
"name": "x",
"type": "Real",
"default": "0",
"isAttr": true
},
{
"name": "y",
"type": "Real",
"default": "0",
"isAttr": true
}
]
},
{
"name": "Bounds",
"properties": [
{
"name": "x",
"type": "Real",
"default": "0",
"isAttr": true
},
{
"name": "y",
"type": "Real",
"default": "0",
"isAttr": true
},
{
"name": "width",
"type": "Real",
"isAttr": true
},
{
"name": "height",
"type": "Real",
"isAttr": true
}
]
}
],
"prefix": "dc",
"associations": []
},
di: {
"name": "DI",
"uri": "http://www.omg.org/spec/DD/20100524/DI",
"types": [
{
"name": "DiagramElement",
"isAbstract": true,
"properties": [
{
"name": "owningDiagram",
"type": "Diagram",
"isReadOnly": true,
"association": "A_rootElement_owningDiagram",
"isVirtual": true,
"isReference": true
},
{
"name": "owningElement",
"type": "DiagramElement",
"isReadOnly": true,
"association": "A_ownedElement_owningElement",
"isVirtual": true,
"isReference": true
},
{
"name": "modelElement",
"isReadOnly": true,
"association": "A_modelElement_diagramElement",
"isVirtual": true,
"isReference": true,
"type": "Element"
},
{
"name": "style",
"type": "Style",
"isReadOnly": true,
"association": "A_style_diagramElement",
"isVirtual": true,
"isReference": true
},
{
"name": "ownedElement",
"type": "DiagramElement",
"isReadOnly": true,
"association": "A_ownedElement_owningElement",
"isVirtual": true,
"isMany": true
}
]
},
{
"name": "Node",
"isAbstract": true,
"superClass": [
"DiagramElement"
]
},
{
"name": "Edge",
"isAbstract": true,
"superClass": [
"DiagramElement"
],
"properties": [
{
"name": "source",
"type": "DiagramElement",
"isReadOnly": true,
"association": "A_source_sourceEdge",
"isVirtual": true,
"isReference": true
},
{
"name": "target",
"type": "DiagramElement",
"isReadOnly": true,
"association": "A_target_targetEdge",
"isVirtual": true,
"isReference": true
},
{
"name": "waypoint",
"isUnique": false,
"isMany": true,
"type": "dc:Point",
"serialize": "xsi:type"
}
]
},
{
"name": "Diagram",
"isAbstract": true,
"properties": [
{
"name": "rootElement",
"type": "DiagramElement",
"isReadOnly": true,
"association": "A_rootElement_owningDiagram",
"isVirtual": true
},
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "documentation",
"isAttr": true,
"type": "String"
},
{
"name": "resolution",
"isAttr": true,
"type": "Real"
},
{
"name": "ownedStyle",
"type": "Style",
"isReadOnly": true,
"association": "A_ownedStyle_owningDiagram",
"isVirtual": true,
"isMany": true
}
]
},
{
"name": "Shape",
"isAbstract": true,
"superClass": [
"Node"
],
"properties": [
{
"name": "bounds",
"type": "dc:Bounds"
}
]
},
{
"name": "Plane",
"isAbstract": true,
"superClass": [
"Node"
],
"properties": [
{
"name": "planeElement",
"type": "DiagramElement",
"subsettedProperty": "DiagramElement-ownedElement",
"association": "A_planeElement_plane",
"isMany": true
}
]
},
{
"name": "LabeledEdge",
"isAbstract": true,
"superClass": [
"Edge"
],
"properties": [
{
"name": "ownedLabel",
"type": "Label",
"isReadOnly": true,
"subsettedProperty": "DiagramElement-ownedElement",
"association": "A_ownedLabel_owningEdge",
"isVirtual": true,
"isMany": true
}
]
},
{
"name": "LabeledShape",
"isAbstract": true,
"superClass": [
"Shape"
],
"properties": [
{
"name": "ownedLabel",
"type": "Label",
"isReadOnly": true,
"subsettedProperty": "DiagramElement-ownedElement",
"association": "A_ownedLabel_owningShape",
"isVirtual": true,
"isMany": true
}
]
},
{
"name": "Label",
"isAbstract": true,
"superClass": [
"Node"
],
"properties": [
{
"name": "bounds",
"type": "dc:Bounds"
}
]
},
{
"name": "Style",
"isAbstract": true
}
],
"associations": [],
"prefix": "di"
}
};
Moddle.call(this, packages, options);
}
BpmnModdle.prototype = Object.create(Moddle.prototype);
//module.exports = BpmnModdle;
/**
* Instantiates a BPMN model tree from a given xml string.
*
* @param {String} xmlStr
* @param {String} [typeName] name of the root element, defaults to 'bpmn:Definitions'
* @param {Object} [options] options to pass to the underlying reader
* @param {Function} done callback that is invoked with (err, result, parseContext) once the import completes
*/
BpmnModdle.prototype.fromXML = function(xmlStr, typeName, options, done) {
if (!_.isString(typeName)) {
done = options;
options = typeName;
typeName = 'bpmn:Definitions';
}
if (_.isFunction(options)) {
done = options;
options = {};
}
var reader = new XMLReader(this, options);
var rootHandler = reader.handler(typeName);
reader.fromXML(xmlStr, rootHandler, done);
};
/**
* Serializes a BPMN 2.0 object tree to XML.
*
* @param {String} element the root element, typically an instance of `bpmn:Definitions`
* @param {Object} [options] to pass to the underlying writer
* @param {Function} done callback invoked with (err, xmlStr) once the import completes
*/
BpmnModdle.prototype.toXML = function(element, options, done) {
if (_.isFunction(options)) {
done = options;
options = {};
}
var writer = new XMLWriter(options);
try {
var result = writer.toXML(element);
done(null, result);
} catch (e) {
done(e);
}
};
/**
* Intro.js v1.0.0
* https://github.com/usablica/intro.js
* MIT licensed
*
* Copyright (C) 2013 usabli.ca - A weekend project by Afshin Mehrabani (@afshinmeh)
*/
(function (root, factory) {
if (typeof exports === 'object') {
// CommonJS
factory(exports);
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports'], factory);
} else {
// Browser globals
factory(root);
}
} (this, function (exports) {
//Default config/variables
var VERSION = '1.0.0';
/**
* IntroJs main class
*
* @class IntroJs
*/
function IntroJs(obj) {
this._targetElement = obj;
this._options = {
/* Next button label in tooltip box */
nextLabel: 'Next &rarr;',
/* Previous button label in tooltip box */
prevLabel: '&larr; Back',
/* Skip button label in tooltip box */
skipLabel: 'Skip',
/* Done button label in tooltip box */
doneLabel: 'Done',
/* Default tooltip box position */
tooltipPosition: 'bottom',
/* Next CSS class for tooltip boxes */
tooltipClass: '',
/* CSS class that is added to the helperLayer */
highlightClass: '',
/* Close introduction when pressing Escape button? */
exitOnEsc: true,
/* Close introduction when clicking on overlay layer? */
exitOnOverlayClick: true,
/* Show step numbers in introduction? */
showStepNumbers: true,
/* Let user use keyboard to navigate the tour? */
keyboardNavigation: true,
/* Show tour control buttons? */
showButtons: true,
/* Show tour bullets? */
showBullets: true,
/* Show tour progress? */
showProgress: false,
/* Scroll to highlighted element? */
scrollToElement: true,
/* Set the overlay opacity */
overlayOpacity: 0.8,
/* Precedence of positions, when auto is enabled */
positionPrecedence: ["bottom", "top", "right", "left"],
/* Disable an interaction with element? */
disableInteraction: false
};
}
/**
* Initiate a new introduction/guide from an element in the page
*
* @api private
* @method _introForElement
* @param {Object} targetElm
* @returns {Boolean} Success or not?
*/
function _introForElement(targetElm) {
var introItems = [],
self = this;
if (this._options.steps) {
//use steps passed programmatically
var allIntroSteps = [];
for (var i = 0, stepsLength = this._options.steps.length; i < stepsLength; i++) {
var currentItem = _cloneObject(this._options.steps[i]);
//set the step
currentItem.step = introItems.length + 1;
//use querySelector function only when developer used CSS selector
if (typeof(currentItem.element) === 'string') {
//grab the element with given selector from the page
currentItem.element = document.querySelector(currentItem.element);
}
//intro without element
if (typeof(currentItem.element) === 'undefined' || currentItem.element == null) {
var floatingElementQuery = document.querySelector(".introjsFloatingElement");
if (floatingElementQuery == null) {
floatingElementQuery = document.createElement('div');
floatingElementQuery.className = 'introjsFloatingElement';
document.body.appendChild(floatingElementQuery);
}
currentItem.element = floatingElementQuery;
currentItem.position = 'floating';
}
if (currentItem.element != null) {
introItems.push(currentItem);
}
}
} else {
//use steps from data-* annotations
var allIntroSteps = targetElm.querySelectorAll('*[data-intro]');
//if there's no element to intro
if (allIntroSteps.length < 1) {
return false;
}
//first add intro items with data-step
for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
var currentElement = allIntroSteps[i];
var step = parseInt(currentElement.getAttribute('data-step'), 10);
if (step > 0) {
introItems[step - 1] = {
element: currentElement,
intro: currentElement.getAttribute('data-intro'),
step: parseInt(currentElement.getAttribute('data-step'), 10),
tooltipClass: currentElement.getAttribute('data-tooltipClass'),
highlightClass: currentElement.getAttribute('data-highlightClass'),
position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
};
}
}
//next add intro items without data-step
//todo: we need a cleanup here, two loops are redundant
var nextStep = 0;
for (var i = 0, elmsLength = allIntroSteps.length; i < elmsLength; i++) {
var currentElement = allIntroSteps[i];
if (currentElement.getAttribute('data-step') == null) {
while (true) {
if (typeof introItems[nextStep] == 'undefined') {
break;
} else {
nextStep++;
}
}
introItems[nextStep] = {
element: currentElement,
intro: currentElement.getAttribute('data-intro'),
step: nextStep + 1,
tooltipClass: currentElement.getAttribute('data-tooltipClass'),
highlightClass: currentElement.getAttribute('data-highlightClass'),
position: currentElement.getAttribute('data-position') || this._options.tooltipPosition
};
}
}
}
//removing undefined/null elements
var tempIntroItems = [];
for (var z = 0; z < introItems.length; z++) {
introItems[z] && tempIntroItems.push(introItems[z]); // copy non-empty values to the end of the array
}
introItems = tempIntroItems;
//Ok, sort all items with given steps
introItems.sort(function (a, b) {
return a.step - b.step;
});
//set it to the introJs object
self._introItems = introItems;
//add overlay layer to the page
if(_addOverlayLayer.call(self, targetElm)) {
//then, start the show
_nextStep.call(self);
var skipButton = targetElm.querySelector('.introjs-skipbutton'),
nextStepButton = targetElm.querySelector('.introjs-nextbutton');
self._onKeyDown = function(e) {
if (e.keyCode === 27 && self._options.exitOnEsc == true) {
//escape key pressed, exit the intro
_exitIntro.call(self, targetElm);
//check if any callback is defined
if (self._introExitCallback != undefined) {
self._introExitCallback.call(self);
}
} else if(e.keyCode === 37) {
//left arrow
_previousStep.call(self);
} else if (e.keyCode === 39) {
//right arrow
_nextStep.call(self);
} else if (e.keyCode === 13) {
//srcElement === ie
var target = e.target || e.srcElement;
if (target && target.className.indexOf('introjs-prevbutton') > 0) {
//user hit enter while focusing on previous button
_previousStep.call(self);
} else if (target && target.className.indexOf('introjs-skipbutton') > 0) {
//user hit enter while focusing on skip button
_exitIntro.call(self, targetElm);
} else {
//default behavior for responding to enter
_nextStep.call(self);
}
//prevent default behaviour on hitting Enter, to prevent steps being skipped in some browsers
if(e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
};
self._onResize = function(e) {
_setHelperLayerPosition.call(self, document.querySelector('.introjs-helperLayer'));
_setHelperLayerPosition.call(self, document.querySelector('.introjs-tooltipReferenceLayer'));
};
if (window.addEventListener) {
if (this._options.keyboardNavigation) {
window.addEventListener('keydown', self._onKeyDown, true);
}
//for window resize
window.addEventListener('resize', self._onResize, true);
} else if (document.attachEvent) { //IE
if (this._options.keyboardNavigation) {
document.attachEvent('onkeydown', self._onKeyDown);
}
//for window resize
document.attachEvent('onresize', self._onResize);
}
}
return false;
}
/*
* makes a copy of the object
* @api private
* @method _cloneObject
*/
function _cloneObject(object) {
if (object == null || typeof (object) != 'object' || typeof (object.nodeType) != 'undefined') {
return object;
}
var temp = {};
for (var key in object) {
temp[key] = _cloneObject(object[key]);
}
return temp;
}
/**
* Go to specific step of introduction
*
* @api private
* @method _goToStep
*/
function _goToStep(step) {
//because steps starts with zero
this._currentStep = step - 2;
if (typeof (this._introItems) !== 'undefined') {
_nextStep.call(this);
}
}
/**
* Go to next step on intro
*
* @api private
* @method _nextStep
*/
function _nextStep() {
this._direction = 'forward';
if (typeof (this._currentStep) === 'undefined') {
this._currentStep = 0;
} else {
++this._currentStep;
}
if ((this._introItems.length) <= this._currentStep) {
//end of the intro
//check if any callback is defined
if (typeof (this._introCompleteCallback) === 'function') {
this._introCompleteCallback.call(this);
}
_exitIntro.call(this, this._targetElement);
return;
}
var nextStep = this._introItems[this._currentStep];
if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
this._introBeforeChangeCallback.call(this, nextStep.element);
}
_showElement.call(this, nextStep);
}
/**
* Go to previous step on intro
*
* @api private
* @method _nextStep
*/
function _previousStep() {
this._direction = 'backward';
if (this._currentStep === 0) {
return false;
}
var nextStep = this._introItems[--this._currentStep];
if (typeof (this._introBeforeChangeCallback) !== 'undefined') {
this._introBeforeChangeCallback.call(this, nextStep.element);
}
_showElement.call(this, nextStep);
}
/**
* Exit from intro
*
* @api private
* @method _exitIntro
* @param {Object} targetElement
*/
function _exitIntro(targetElement) {
//remove overlay layer from the page
var overlayLayer = targetElement.querySelector('.introjs-overlay');
//return if intro already completed or skipped
if (overlayLayer == null) {
return;
}
//for fade-out animation
overlayLayer.style.opacity = 0;
setTimeout(function () {
if (overlayLayer.parentNode) {
overlayLayer.parentNode.removeChild(overlayLayer);
}
}, 500);
//remove all helper layers
var helperLayer = targetElement.querySelector('.introjs-helperLayer');
if (helperLayer) {
helperLayer.parentNode.removeChild(helperLayer);
}
var referenceLayer = targetElement.querySelector('.introjs-tooltipReferenceLayer');
if (referenceLayer) {
referenceLayer.parentNode.removeChild(referenceLayer);
}
//remove disableInteractionLayer
var disableInteractionLayer = targetElement.querySelector('.introjs-disableInteraction');
if (disableInteractionLayer) {
disableInteractionLayer.parentNode.removeChild(disableInteractionLayer);
}
//remove intro floating element
var floatingElement = document.querySelector('.introjsFloatingElement');
if (floatingElement) {
floatingElement.parentNode.removeChild(floatingElement);
}
//remove `introjs-showElement` class from the element
var showElement = document.querySelector('.introjs-showElement');
if (showElement) {
showElement.className = showElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, ''); // This is a manual trim.
}
//remove `introjs-fixParent` class from the elements
var fixParents = document.querySelectorAll('.introjs-fixParent');
if (fixParents && fixParents.length > 0) {
for (var i = fixParents.length - 1; i >= 0; i--) {
fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
};
}
//clean listeners
if (window.removeEventListener) {
window.removeEventListener('keydown', this._onKeyDown, true);
} else if (document.detachEvent) { //IE
document.detachEvent('onkeydown', this._onKeyDown);
}
//set the step to zero
this._currentStep = undefined;
}
/**
* Render tooltip box in the page
*
* @api private
* @method _placeTooltip
* @param {Object} targetElement
* @param {Object} tooltipLayer
* @param {Object} arrowLayer
*/
function _placeTooltip(targetElement, tooltipLayer, arrowLayer, helperNumberLayer) {
var tooltipCssClass = '',
currentStepObj,
tooltipOffset,
targetElementOffset;
//reset the old style
tooltipLayer.style.top = null;
tooltipLayer.style.right = null;
tooltipLayer.style.bottom = null;
tooltipLayer.style.left = null;
tooltipLayer.style.marginLeft = null;
tooltipLayer.style.marginTop = null;
arrowLayer.style.display = 'inherit';
if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
helperNumberLayer.style.top = null;
helperNumberLayer.style.left = null;
}
//prevent error when `this._currentStep` is undefined
if (!this._introItems[this._currentStep]) return;
//if we have a custom css class for each step
currentStepObj = this._introItems[this._currentStep];
if (typeof (currentStepObj.tooltipClass) === 'string') {
tooltipCssClass = currentStepObj.tooltipClass;
} else {
tooltipCssClass = this._options.tooltipClass;
}
tooltipLayer.className = ('introjs-tooltip ' + tooltipCssClass).replace(/^\s+|\s+$/g, '');
//custom css class for tooltip boxes
var tooltipCssClass = this._options.tooltipClass;
currentTooltipPosition = this._introItems[this._currentStep].position;
if ((currentTooltipPosition == "auto" || this._options.tooltipPosition == "auto")) {
if (currentTooltipPosition != "floating") { // Floating is always valid, no point in calculating
currentTooltipPosition = _determineAutoPosition.call(this, targetElement, tooltipLayer, currentTooltipPosition)
}
}
var targetOffset = _getOffset(targetElement)
var tooltipHeight = _getOffset(tooltipLayer).height
var windowSize = _getWinSize()
switch (currentTooltipPosition) {
case 'top':
tooltipLayer.style.left = '15px';
tooltipLayer.style.top = '-' + (tooltipHeight + 10) + 'px';
arrowLayer.className = 'introjs-arrow bottom';
break;
case 'right':
tooltipLayer.style.left = (_getOffset(targetElement).width + 20) + 'px';
if (targetOffset.top + tooltipHeight > windowSize.height) {
// In this case, right would have fallen below the bottom of the screen.
// Modify so that the bottom of the tooltip connects with the target
arrowLayer.className = "introjs-arrow left-bottom";
tooltipLayer.style.top = "-" + (tooltipHeight - targetOffset.height - 20) + "px"
}
arrowLayer.className = 'introjs-arrow left';
break;
case 'left':
if (this._options.showStepNumbers == true) {
tooltipLayer.style.top = '15px';
}
if (targetOffset.top + tooltipHeight > windowSize.height) {
// In this case, left would have fallen below the bottom of the screen.
// Modify so that the bottom of the tooltip connects with the target
tooltipLayer.style.top = "-" + (tooltipHeight - targetOffset.height - 20) + "px"
arrowLayer.className = 'introjs-arrow right-bottom';
} else {
arrowLayer.className = 'introjs-arrow right';
}
tooltipLayer.style.right = (targetOffset.width + 20) + 'px';
break;
case 'floating':
arrowLayer.style.display = 'none';
//we have to adjust the top and left of layer manually for intro items without element
tooltipOffset = _getOffset(tooltipLayer);
tooltipLayer.style.left = '50%';
tooltipLayer.style.top = '50%';
tooltipLayer.style.marginLeft = '-' + (tooltipOffset.width / 2) + 'px';
tooltipLayer.style.marginTop = '-' + (tooltipOffset.height / 2) + 'px';
if (typeof(helperNumberLayer) != 'undefined' && helperNumberLayer != null) {
helperNumberLayer.style.left = '-' + ((tooltipOffset.width / 2) + 18) + 'px';
helperNumberLayer.style.top = '-' + ((tooltipOffset.height / 2) + 18) + 'px';
}
break;
case 'bottom-right-aligned':
arrowLayer.className = 'introjs-arrow top-right';
tooltipLayer.style.right = '0px';
tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
break;
case 'bottom-middle-aligned':
targetElementOffset = _getOffset(targetElement);
tooltipOffset = _getOffset(tooltipLayer);
arrowLayer.className = 'introjs-arrow top-middle';
tooltipLayer.style.left = (targetElementOffset.width / 2 - tooltipOffset.width / 2) + 'px';
tooltipLayer.style.bottom = '-' + (tooltipOffset.height + 10) + 'px';
break;
case 'bottom-left-aligned':
// Bottom-left-aligned is the same as the default bottom
case 'bottom':
// Bottom going to follow the default behavior
default:
tooltipLayer.style.bottom = '-' + (_getOffset(tooltipLayer).height + 10) + 'px';
tooltipLayer.style.left = (_getOffset(targetElement).width / 2 - _getOffset(tooltipLayer).width / 2) + 'px';
arrowLayer.className = 'introjs-arrow top';
break;
}
}
/**
* Determines the position of the tooltip based on the position precedence and availability
* of screen space.
*
* @param {Object} targetElement
* @param {Object} tooltipLayer
* @param {Object} desiredTooltipPosition
*
*/
function _determineAutoPosition(targetElement, tooltipLayer, desiredTooltipPosition) {
// Take a clone of position precedence. These will be the available
var possiblePositions = this._options.positionPrecedence.slice()
var windowSize = _getWinSize()
var tooltipHeight = _getOffset(tooltipLayer).height + 10
var tooltipWidth = _getOffset(tooltipLayer).width + 20
var targetOffset = _getOffset(targetElement)
// If we check all the possible areas, and there are no valid places for the tooltip, the element
// must take up most of the screen real estate. Show the tooltip floating in the middle of the screen.
var calculatedPosition = "floating"
// Check if the width of the tooltip + the starting point would spill off the right side of the screen
// If no, neither bottom or top are valid
if (targetOffset.left + tooltipWidth > windowSize.width || ((targetOffset.left + (targetOffset.width / 2)) - tooltipWidth) < 0) {
_removeEntry(possiblePositions, "bottom")
_removeEntry(possiblePositions, "top");
} else {
// Check for space below
if ((targetOffset.height + targetOffset.top + tooltipHeight) > windowSize.height) {
_removeEntry(possiblePositions, "bottom")
}
// Check for space above
if (targetOffset.top - tooltipHeight < 0) {
_removeEntry(possiblePositions, "top");
}
}
// Check for space to the right
if (targetOffset.width + targetOffset.left + tooltipWidth > windowSize.width) {
_removeEntry(possiblePositions, "right");
}
// Check for space to the left
if (targetOffset.left - tooltipWidth < 0) {
_removeEntry(possiblePositions, "left");
}
// At this point, our array only has positions that are valid. Pick the first one, as it remains in order
if (possiblePositions.length > 0) {
calculatedPosition = possiblePositions[0];
}
// If the requested position is in the list, replace our calculated choice with that
if (desiredTooltipPosition && desiredTooltipPosition != "auto") {
if (possiblePositions.indexOf(desiredTooltipPosition) > -1) {
calculatedPosition = desiredTooltipPosition
}
}
return calculatedPosition
}
/**
* Remove an entry from a string array if it's there, does nothing if it isn't there.
*
* @param {Array} stringArray
* @param {String} stringToRemove
*/
function _removeEntry(stringArray, stringToRemove) {
if (stringArray.indexOf(stringToRemove) > -1) {
stringArray.splice(stringArray.indexOf(stringToRemove), 1);
}
}
/**
* Update the position of the helper layer on the screen
*
* @api private
* @method _setHelperLayerPosition
* @param {Object} helperLayer
*/
function _setHelperLayerPosition(helperLayer) {
if (helperLayer) {
//prevent error when `this._currentStep` in undefined
if (!this._introItems[this._currentStep]) return;
var currentElement = this._introItems[this._currentStep],
elementPosition = _getOffset(currentElement.element),
widthHeightPadding = 10;
if (currentElement.position == 'floating') {
widthHeightPadding = 0;
}
//set new position to helper layer
helperLayer.setAttribute('style', 'width: ' + (elementPosition.width + widthHeightPadding) + 'px; ' +
'height:' + (elementPosition.height + widthHeightPadding) + 'px; ' +
'top:' + (elementPosition.top - 5) + 'px;' +
'left: ' + (elementPosition.left - 5) + 'px;');
}
}
/**
* Add disableinteraction layer and adjust the size and position of the layer
*
* @api private
* @method _disableInteraction
*/
function _disableInteraction () {
var disableInteractionLayer = document.querySelector('.introjs-disableInteraction');
if (disableInteractionLayer === null) {
disableInteractionLayer = document.createElement('div');
disableInteractionLayer.className = 'introjs-disableInteraction';
this._targetElement.appendChild(disableInteractionLayer);
}
_setHelperLayerPosition.call(this, disableInteractionLayer);
}
/**
* Show an element on the page
*
* @api private
* @method _showElement
* @param {Object} targetElement
*/
function _showElement(targetElement) {
if (typeof (this._introChangeCallback) !== 'undefined') {
this._introChangeCallback.call(this, targetElement.element);
}
var self = this,
oldHelperLayer = document.querySelector('.introjs-helperLayer'),
oldReferenceLayer = document.querySelector('.introjs-tooltipReferenceLayer'),
highlightClass = 'introjs-helperLayer',
elementPosition = _getOffset(targetElement.element);
//check for a current step highlight class
if (typeof (targetElement.highlightClass) === 'string') {
highlightClass += (' ' + targetElement.highlightClass);
}
//check for options highlight class
if (typeof (this._options.highlightClass) === 'string') {
highlightClass += (' ' + this._options.highlightClass);
}
if (oldHelperLayer != null) {
var oldHelperNumberLayer = oldReferenceLayer.querySelector('.introjs-helperNumberLayer'),
oldtooltipLayer = oldReferenceLayer.querySelector('.introjs-tooltiptext'),
oldArrowLayer = oldReferenceLayer.querySelector('.introjs-arrow'),
oldtooltipContainer = oldReferenceLayer.querySelector('.introjs-tooltip'),
skipTooltipButton = oldReferenceLayer.querySelector('.introjs-skipbutton'),
prevTooltipButton = oldReferenceLayer.querySelector('.introjs-prevbutton'),
nextTooltipButton = oldReferenceLayer.querySelector('.introjs-nextbutton');
//update or reset the helper highlight class
oldHelperLayer.className = highlightClass;
//hide the tooltip
oldtooltipContainer.style.opacity = 0;
oldtooltipContainer.style.display = "none";
if (oldHelperNumberLayer != null) {
var lastIntroItem = this._introItems[(targetElement.step - 2 >= 0 ? targetElement.step - 2 : 0)];
if (lastIntroItem != null && (this._direction == 'forward' && lastIntroItem.position == 'floating') || (this._direction == 'backward' && targetElement.position == 'floating')) {
oldHelperNumberLayer.style.opacity = 0;
}
}
//set new position to helper layer
_setHelperLayerPosition.call(self, oldHelperLayer);
_setHelperLayerPosition.call(self, oldReferenceLayer);
//remove `introjs-fixParent` class from the elements
var fixParents = document.querySelectorAll('.introjs-fixParent');
if (fixParents && fixParents.length > 0) {
for (var i = fixParents.length - 1; i >= 0; i--) {
fixParents[i].className = fixParents[i].className.replace(/introjs-fixParent/g, '').replace(/^\s+|\s+$/g, '');
};
}
//remove old classes
var oldShowElement = document.querySelector('.introjs-showElement');
oldShowElement.className = oldShowElement.className.replace(/introjs-[a-zA-Z]+/g, '').replace(/^\s+|\s+$/g, '');
//we should wait until the CSS3 transition is competed (it's 0.3 sec) to prevent incorrect `height` and `width` calculation
if (self._lastShowElementTimer) {
clearTimeout(self._lastShowElementTimer);
}
self._lastShowElementTimer = setTimeout(function() {
//set current step to the label
if (oldHelperNumberLayer != null) {
oldHelperNumberLayer.innerHTML = targetElement.step;
}
//set current tooltip text
oldtooltipLayer.innerHTML = targetElement.intro;
//set the tooltip position
oldtooltipContainer.style.display = "block";
_placeTooltip.call(self, targetElement.element, oldtooltipContainer, oldArrowLayer, oldHelperNumberLayer);
//change active bullet
oldReferenceLayer.querySelector('.introjs-bullets li > a.active').className = '';
oldReferenceLayer.querySelector('.introjs-bullets li > a[data-stepnumber="' + targetElement.step + '"]').className = 'active';
oldReferenceLayer.querySelector('.introjs-progress .introjs-progressbar').setAttribute('style', 'width:' + _getProgress.call(self) + '%;');
//show the tooltip
oldtooltipContainer.style.opacity = 1;
if (oldHelperNumberLayer) oldHelperNumberLayer.style.opacity = 1;
//reset button focus
if (nextTooltipButton.tabIndex === -1) {
//tabindex of -1 means we are at the end of the tour - focus on skip / done
skipTooltipButton.focus();
} else {
//still in the tour, focus on next
nextTooltipButton.focus();
}
}, 350);
} else {
var helperLayer = document.createElement('div'),
referenceLayer = document.createElement('div'),
arrowLayer = document.createElement('div'),
tooltipLayer = document.createElement('div'),
tooltipTextLayer = document.createElement('div'),
bulletsLayer = document.createElement('div'),
progressLayer = document.createElement('div'),
buttonsLayer = document.createElement('div');
helperLayer.className = highlightClass;
referenceLayer.className = 'introjs-tooltipReferenceLayer';
//set new position to helper layer
_setHelperLayerPosition.call(self, helperLayer);
_setHelperLayerPosition.call(self, referenceLayer);
//add helper layer to target element
this._targetElement.appendChild(helperLayer);
this._targetElement.appendChild(referenceLayer);
arrowLayer.className = 'introjs-arrow';
tooltipTextLayer.className = 'introjs-tooltiptext';
tooltipTextLayer.innerHTML = targetElement.intro;
bulletsLayer.className = 'introjs-bullets';
if (this._options.showBullets === false) {
bulletsLayer.style.display = 'none';
}
var ulContainer = document.createElement('ul');
for (var i = 0, stepsLength = this._introItems.length; i < stepsLength; i++) {
var innerLi = document.createElement('li');
var anchorLink = document.createElement('a');
anchorLink.onclick = function() {
self.goToStep(this.getAttribute('data-stepnumber'));
};
if (i === (targetElement.step-1)) anchorLink.className = 'active';
anchorLink.href = 'javascript:void(0);';
anchorLink.innerHTML = "&nbsp;";
anchorLink.setAttribute('data-stepnumber', this._introItems[i].step);
innerLi.appendChild(anchorLink);
ulContainer.appendChild(innerLi);
}
bulletsLayer.appendChild(ulContainer);
progressLayer.className = 'introjs-progress';
if (this._options.showProgress === false) {
progressLayer.style.display = 'none';
}
var progressBar = document.createElement('div');
progressBar.className = 'introjs-progressbar';
progressBar.setAttribute('style', 'width:' + _getProgress.call(this) + '%;');
progressLayer.appendChild(progressBar);
buttonsLayer.className = 'introjs-tooltipbuttons';
if (this._options.showButtons === false) {
buttonsLayer.style.display = 'none';
}
tooltipLayer.className = 'introjs-tooltip';
tooltipLayer.appendChild(tooltipTextLayer);
tooltipLayer.appendChild(bulletsLayer);
tooltipLayer.appendChild(progressLayer);
//add helper layer number
if (this._options.showStepNumbers == true) {
var helperNumberLayer = document.createElement('span');
helperNumberLayer.className = 'introjs-helperNumberLayer';
helperNumberLayer.innerHTML = targetElement.step;
referenceLayer.appendChild(helperNumberLayer);
}
tooltipLayer.appendChild(arrowLayer);
referenceLayer.appendChild(tooltipLayer);
//next button
var nextTooltipButton = document.createElement('a');
nextTooltipButton.onclick = function() {
if (self._introItems.length - 1 != self._currentStep) {
_nextStep.call(self);
}
};
nextTooltipButton.href = 'javascript:void(0);';
nextTooltipButton.innerHTML = this._options.nextLabel;
//previous button
var prevTooltipButton = document.createElement('a');
prevTooltipButton.onclick = function() {
if (self._currentStep != 0) {
_previousStep.call(self);
}
};
prevTooltipButton.href = 'javascript:void(0);';
prevTooltipButton.innerHTML = this._options.prevLabel;
//skip button
var skipTooltipButton = document.createElement('a');
skipTooltipButton.className = 'introjs-button introjs-skipbutton';
skipTooltipButton.href = 'javascript:void(0);';
skipTooltipButton.innerHTML = this._options.skipLabel;
skipTooltipButton.onclick = function() {
if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
self._introCompleteCallback.call(self);
}
if (self._introItems.length - 1 != self._currentStep && typeof (self._introExitCallback) === 'function') {
self._introExitCallback.call(self);
}
_exitIntro.call(self, self._targetElement);
};
buttonsLayer.appendChild(skipTooltipButton);
//in order to prevent displaying next/previous button always
if (this._introItems.length > 1) {
buttonsLayer.appendChild(prevTooltipButton);
buttonsLayer.appendChild(nextTooltipButton);
}
tooltipLayer.appendChild(buttonsLayer);
//set proper position
_placeTooltip.call(self, targetElement.element, tooltipLayer, arrowLayer, helperNumberLayer);
}
//disable interaction
if (this._options.disableInteraction === true) {
_disableInteraction.call(self);
}
prevTooltipButton.removeAttribute('tabIndex');
nextTooltipButton.removeAttribute('tabIndex');
if (this._currentStep == 0 && this._introItems.length > 1) {
prevTooltipButton.className = 'introjs-button introjs-prevbutton introjs-disabled';
prevTooltipButton.tabIndex = '-1';
nextTooltipButton.className = 'introjs-button introjs-nextbutton';
skipTooltipButton.innerHTML = this._options.skipLabel;
} else if (this._introItems.length - 1 == this._currentStep || this._introItems.length == 1) {
skipTooltipButton.innerHTML = this._options.doneLabel;
prevTooltipButton.className = 'introjs-button introjs-prevbutton';
nextTooltipButton.className = 'introjs-button introjs-nextbutton introjs-disabled';
nextTooltipButton.tabIndex = '-1';
} else {
prevTooltipButton.className = 'introjs-button introjs-prevbutton';
nextTooltipButton.className = 'introjs-button introjs-nextbutton';
skipTooltipButton.innerHTML = this._options.skipLabel;
}
//Set focus on "next" button, so that hitting Enter always moves you onto the next step
nextTooltipButton.focus();
//add target element position style
targetElement.element.className += ' introjs-showElement';
var currentElementPosition = _getPropValue(targetElement.element, 'position');
if (currentElementPosition !== 'absolute' &&
currentElementPosition !== 'relative') {
//change to new intro item
targetElement.element.className += ' introjs-relativePosition';
}
var parentElm = targetElement.element.parentNode;
while (parentElm != null) {
if (parentElm.tagName.toLowerCase() === 'body') break;
//fix The Stacking Contenxt problem.
//More detail: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
var zIndex = _getPropValue(parentElm, 'z-index');
var opacity = parseFloat(_getPropValue(parentElm, 'opacity'));
var transform = _getPropValue(parentElm, 'transform') || _getPropValue(parentElm, '-webkit-transform') || _getPropValue(parentElm, '-moz-transform') || _getPropValue(parentElm, '-ms-transform') || _getPropValue(parentElm, '-o-transform');
if (/[0-9]+/.test(zIndex) || opacity < 1 || transform !== 'none') {
parentElm.className += ' introjs-fixParent';
}
parentElm = parentElm.parentNode;
}
if (!_elementInViewport(targetElement.element) && this._options.scrollToElement === true) {
var rect = targetElement.element.getBoundingClientRect(),
winHeight = _getWinSize().height,
top = rect.bottom - (rect.bottom - rect.top),
bottom = rect.bottom - winHeight;
//Scroll up
if (top < 0 || targetElement.element.clientHeight > winHeight) {
window.scrollBy(0, top - 30); // 30px padding from edge to look nice
//Scroll down
} else {
window.scrollBy(0, bottom + 100); // 70px + 30px padding from edge to look nice
}
}
if (typeof (this._introAfterChangeCallback) !== 'undefined') {
this._introAfterChangeCallback.call(this, targetElement.element);
}
}
/**
* Get an element CSS property on the page
* Thanks to JavaScript Kit: http://www.javascriptkit.com/dhtmltutors/dhtmlcascade4.shtml
*
* @api private
* @method _getPropValue
* @param {Object} element
* @param {String} propName
* @returns Element's property value
*/
function _getPropValue (element, propName) {
var propValue = '';
if (element.currentStyle) { //IE
propValue = element.currentStyle[propName];
} else if (document.defaultView && document.defaultView.getComputedStyle) { //Others
propValue = document.defaultView.getComputedStyle(element, null).getPropertyValue(propName);
}
//Prevent exception in IE
if (propValue && propValue.toLowerCase) {
return propValue.toLowerCase();
} else {
return propValue;
}
}
/**
* Provides a cross-browser way to get the screen dimensions
* via: http://stackoverflow.com/questions/5864467/internet-explorer-innerheight
*
* @api private
* @method _getWinSize
* @returns {Object} width and height attributes
*/
function _getWinSize() {
if (window.innerWidth != undefined) {
return { width: window.innerWidth, height: window.innerHeight };
} else {
var D = document.documentElement;
return { width: D.clientWidth, height: D.clientHeight };
}
}
/**
* Add overlay layer to the page
* http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
*
* @api private
* @method _elementInViewport
* @param {Object} el
*/
function _elementInViewport(el) {
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
(rect.bottom+80) <= window.innerHeight && // add 80 to get the text right
rect.right <= window.innerWidth
);
}
/**
* Add overlay layer to the page
*
* @api private
* @method _addOverlayLayer
* @param {Object} targetElm
*/
function _addOverlayLayer(targetElm) {
var overlayLayer = document.createElement('div'),
styleText = '',
self = this;
//set css class name
overlayLayer.className = 'introjs-overlay';
//check if the target element is body, we should calculate the size of overlay layer in a better way
if (targetElm.tagName.toLowerCase() === 'body') {
styleText += 'top: 0;bottom: 0; left: 0;right: 0;position: fixed;';
overlayLayer.setAttribute('style', styleText);
} else {
//set overlay layer position
var elementPosition = _getOffset(targetElm);
if (elementPosition) {
styleText += 'width: ' + elementPosition.width + 'px; height:' + elementPosition.height + 'px; top:' + elementPosition.top + 'px;left: ' + elementPosition.left + 'px;';
overlayLayer.setAttribute('style', styleText);
}
}
targetElm.appendChild(overlayLayer);
overlayLayer.onclick = function() {
if (self._options.exitOnOverlayClick == true) {
_exitIntro.call(self, targetElm);
//check if any callback is defined
if (self._introExitCallback != undefined) {
self._introExitCallback.call(self);
}
}
};
setTimeout(function() {
styleText += 'opacity: ' + self._options.overlayOpacity.toString() + ';';
overlayLayer.setAttribute('style', styleText);
}, 10);
return true;
}
/**
* Get an element position on the page
* Thanks to `meouw`: http://stackoverflow.com/a/442474/375966
*
* @api private
* @method _getOffset
* @param {Object} element
* @returns Element's position info
*/
function _getOffset(element) {
var elementPosition = {};
//set width
elementPosition.width = element.offsetWidth;
//set height
elementPosition.height = element.offsetHeight;
//calculate element top and left
var _x = 0;
var _y = 0;
while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
_x += element.offsetLeft;
_y += element.offsetTop;
element = element.offsetParent;
}
//set top
elementPosition.top = _y;
//set left
elementPosition.left = _x;
return elementPosition;
}
/**
* Gets the current progress percentage
*
* @api private
* @method _getProgress
* @returns current progress percentage
*/
function _getProgress() {
// Steps are 0 indexed
var currentStep = parseInt((this._currentStep + 1), 10);
return ((currentStep / this._introItems.length) * 100);
}
/**
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
* via: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically
*
* @param obj1
* @param obj2
* @returns obj3 a new object based on obj1 and obj2
*/
function _mergeOptions(obj1,obj2) {
var obj3 = {};
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
return obj3;
}
var introJs = function (targetElm) {
if (typeof (targetElm) === 'object') {
//Ok, create a new instance
return new IntroJs(targetElm);
} else if (typeof (targetElm) === 'string') {
//select the target element with query selector
var targetElement = document.querySelector(targetElm);
if (targetElement) {
return new IntroJs(targetElement);
} else {
throw new Error('There is no element with given selector.');
}
} else {
return new IntroJs(document.body);
}
};
/**
* Current IntroJs version
*
* @property version
* @type String
*/
introJs.version = VERSION;
//Prototype
introJs.fn = IntroJs.prototype = {
clone: function () {
return new IntroJs(this);
},
setOption: function(option, value) {
this._options[option] = value;
return this;
},
setOptions: function(options) {
this._options = _mergeOptions(this._options, options);
return this;
},
start: function () {
_introForElement.call(this, this._targetElement);
return this;
},
goToStep: function(step) {
_goToStep.call(this, step);
return this;
},
nextStep: function() {
_nextStep.call(this);
return this;
},
previousStep: function() {
_previousStep.call(this);
return this;
},
exit: function() {
_exitIntro.call(this, this._targetElement);
return this;
},
refresh: function() {
_setHelperLayerPosition.call(this, document.querySelector('.introjs-helperLayer'));
_setHelperLayerPosition.call(this, document.querySelector('.introjs-tooltipReferenceLayer'));
return this;
},
onbeforechange: function(providedCallback) {
if (typeof (providedCallback) === 'function') {
this._introBeforeChangeCallback = providedCallback;
} else {
throw new Error('Provided callback for onbeforechange was not a function');
}
return this;
},
onchange: function(providedCallback) {
if (typeof (providedCallback) === 'function') {
this._introChangeCallback = providedCallback;
} else {
throw new Error('Provided callback for onchange was not a function.');
}
return this;
},
onafterchange: function(providedCallback) {
if (typeof (providedCallback) === 'function') {
this._introAfterChangeCallback = providedCallback;
} else {
throw new Error('Provided callback for onafterchange was not a function');
}
return this;
},
oncomplete: function(providedCallback) {
if (typeof (providedCallback) === 'function') {
this._introCompleteCallback = providedCallback;
} else {
throw new Error('Provided callback for oncomplete was not a function.');
}
return this;
},
onexit: function(providedCallback) {
if (typeof (providedCallback) === 'function') {
this._introExitCallback = providedCallback;
} else {
throw new Error('Provided callback for onexit was not a function.');
}
return this;
}
};
exports.introJs = introJs;
return introJs;
}));
/*! DataTables 1.10.7
* ©2008-2015 SpryMedia Ltd - datatables.net/license
*/
(function(Ea,Q,k){var P=function(h){function W(a){var b,c,e={};h.each(a,function(d){if((b=d.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=d.replace(b[0],b[2].toLowerCase()),e[c]=d,"o"===b[1]&&W(a[d])});a._hungarianMap=e}function H(a,b,c){a._hungarianMap||W(a);var e;h.each(b,function(d){e=a._hungarianMap[d];if(e!==k&&(c||b[e]===k))"o"===e.charAt(0)?(b[e]||(b[e]={}),h.extend(!0,b[e],b[d]),H(a[e],b[e],c)):b[e]=b[d]})}function P(a){var b=m.defaults.oLanguage,c=a.sZeroRecords;
!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&E(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&E(a,a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&db(a)}function eb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");
A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&H(m.models.oSearch,a[b])}function fb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;b&&!h.isArray(b)&&(a.aDataSort=[b])}function gb(a){var a=a.oBrowser,b=h("<div/>").css({position:"absolute",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",
top:1,left:1,width:100,overflow:"scroll"}).append(h('<div class="test"/>').css({width:"100%",height:10}))).appendTo("body"),c=b.find(".test");a.bScrollOversize=100===c[0].offsetWidth;a.bScrollbarLeft=1!==Math.round(c.offset().left);b.remove()}function hb(a,b,c,e,d,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;e!==d;)a.hasOwnProperty(e)&&(g=j?b(g,a[e],e,a):a[e],j=!0,e+=f);return g}function Fa(a,b){var c=m.defaults.column,e=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:Q.createElement("th"),sTitle:c.sTitle?
c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[e],mData:c.mData?c.mData:e,idx:e});a.aoColumns.push(c);c=a.aoPreSearchCols;c[e]=h.extend({},m.models.oSearch,c[e]);ka(a,e,h(b).data())}function ka(a,b,c){var b=a.aoColumns[b],e=a.oClasses,d=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=d.attr("width")||null;var f=(d.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(fb(c),H(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&
(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),h.extend(b,c),E(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),E(b,c,"aDataSort"));var g=b.mData,j=R(g),i=b.mRender?R(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b.fnGetData=function(a,b,c){var e=j(a,b,k,c);return i&&b?i(e,b,a,c):e};b.fnSetData=function(a,b,c){return S(g)(a,b,c)};"number"!==typeof g&&
(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,d.addClass(e.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=e.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=e.sSortableAsc,b.sSortingClassJUI=e.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=e.sSortableDesc,b.sSortingClassJUI=e.sSortJUIDescAllowed):(b.sSortingClass=e.sSortable,b.sSortingClassJUI=e.sSortJUI)}function X(a){if(!1!==a.oFeatures.bAutoWidth){var b=
a.aoColumns;Ga(a);for(var c=0,e=b.length;c<e;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&Y(a);w(a,null,"column-sizing",[a])}function la(a,b){var c=Z(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function $(a,b){var c=Z(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function aa(a){return Z(a,"bVisible").length}function Z(a,b){var c=[];h.map(a.aoColumns,function(a,d){a[b]&&c.push(d)});return c}function Ha(a){var b=a.aoColumns,c=a.aoData,e=m.ext.type.detect,d,
f,g,j,i,h,l,q,n;d=0;for(f=b.length;d<f;d++)if(l=b[d],n=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=e.length;g<j;g++){i=0;for(h=c.length;i<h;i++){n[i]===k&&(n[i]=x(a,i,d,"type"));q=e[g](n[i],a);if(!q&&g!==e.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function ib(a,b,c,e){var d,f,g,j,i,o,l=a.aoColumns;if(b)for(d=b.length-1;0<=d;d--){o=b[d];var q=o.targets!==k?o.targets:o.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<
g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Fa(a);e(q[f],o)}else if("number"===typeof q[f]&&0>q[f])e(l.length+q[f],o);else if("string"===typeof q[f]){j=0;for(i=l.length;j<i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&&e(j,o)}}if(c){d=0;for(a=c.length;d<a;d++)e(d,c[d])}}function K(a,b,c,e){var d=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data"});f._aData=b;a.aoData.push(f);for(var b=a.aoColumns,f=0,g=b.length;f<g;f++)c&&Ia(a,d,f,x(a,d,f)),b[f].sType=null;a.aiDisplayMaster.push(d);
(c||!a.oFeatures.bDeferRender)&&Ja(a,d,c,e);return d}function ma(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,d){c=na(a,d);return K(a,c.data,d,c.cells)})}function x(a,b,c,e){var d=a.iDraw,f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,c=f.fnGetData(g,e,{settings:a,row:b,col:c});if(c===k)return a.iDrawError!=d&&null===j&&(I(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b,4),a.iDrawError=d),j;if((c===g||null===c)&&
null!==j)c=j;else if("function"===typeof c)return c.call(g);return null===c&&"display"==e?"":c}function Ia(a,b,c,e){a.aoColumns[c].fnSetData(a.aoData[b]._aData,e,{settings:a,row:b,col:c})}function Ka(a){return h.map(a.match(/(\\.|[^\.])+/g),function(a){return a.replace(/\\./g,".")})}function R(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=R(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,
c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=Ka(f);for(var i=0,h=j.length;i<h;i++){f=j[i].match(ba);g=j[i].match(T);if(f){j[i]=j[i].replace(ba,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");i=0;for(h=a.length;i<h;i++)g.push(c(a[i],b,j));a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(T,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===
k)return k;a=a[j[i]]}}return a};return function(b,d){return c(b,d,a)}}return function(b){return b[a]}}function S(a){if(h.isPlainObject(a))return S(a._);if(null===a)return function(){};if("function"===typeof a)return function(b,e,d){a(b,"set",e,d)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,e,d){var d=Ka(d),f;f=d[d.length-1];for(var g,j,i=0,h=d.length-1;i<h;i++){g=d[i].match(ba);j=d[i].match(T);if(g){d[i]=d[i].replace(ba,"");a[d[i]]=[];
f=d.slice();f.splice(0,i+1);g=f.join(".");j=0;for(h=e.length;j<h;j++)f={},b(f,e[j],g),a[d[i]].push(f);return}j&&(d[i]=d[i].replace(T,""),a=a[d[i]](e));if(null===a[d[i]]||a[d[i]]===k)a[d[i]]={};a=a[d[i]]}if(f.match(T))a[f.replace(T,"")](e);else a[f.replace(ba,"")]=e};return function(c,e){return b(c,e,a)}}return function(b,e){b[a]=e}}function La(a){return D(a.aoData,"_aData")}function oa(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0}function pa(a,b,c){for(var e=-1,d=0,f=a.length;d<
f;d++)a[d]==b?e=d:a[d]>b&&a[d]--; -1!=e&&c===k&&a.splice(e,1)}function ca(a,b,c,e){var d=a.aoData[b],f,g=function(c,f){for(;c.childNodes.length;)c.removeChild(c.firstChild);c.innerHTML=x(a,b,f,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===d.src)d._aData=na(a,d,e,e===k?k:d._aData).data;else{var j=d.anCells;if(j)if(e!==k)g(j[e],e);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}d._aSortData=null;d._aFilterData=null;g=a.aoColumns;if(e!==k)g[e].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;
Ma(d)}}function na(a,b,c,e){var d=[],f=b.firstChild,g,j=0,i,o=a.aoColumns,l=a._rowReadObject,e=e||l?{}:[],q=function(a,b){if("string"===typeof a){var c=a.indexOf("@");-1!==c&&(c=a.substring(c+1),S(a)(e,b.getAttribute(c)))}},a=function(a){if(c===k||c===j)g=o[j],i=h.trim(a.innerHTML),g&&g._bAttrSrc?(S(g.mData._)(e,i),q(g.mData.sort,a),q(g.mData.type,a),q(g.mData.filter,a)):l?(g._setter||(g._setter=S(g.mData)),g._setter(e,i)):e[j]=i;j++};if(f)for(;f;){b=f.nodeName.toUpperCase();if("TD"==b||"TH"==b)a(f),
d.push(f);f=f.nextSibling}else{d=b.anCells;f=0;for(b=d.length;f<b;f++)a(d[f])}return{data:e,cells:d}}function Ja(a,b,c,e){var d=a.aoData[b],f=d._aData,g=[],j,i,h,l,q;if(null===d.nTr){j=c||Q.createElement("tr");d.nTr=j;d.anCells=g;j._DT_RowIndex=b;Ma(d);l=0;for(q=a.aoColumns.length;l<q;l++){h=a.aoColumns[l];i=c?e[l]:Q.createElement(h.sCellType);g.push(i);if(!c||h.mRender||h.mData!==l)i.innerHTML=x(a,b,l,"display");h.sClass&&(i.className+=" "+h.sClass);h.bVisible&&!c?j.appendChild(i):!h.bVisible&&c&&
i.parentNode.removeChild(i);h.fnCreatedCell&&h.fnCreatedCell.call(a.oInstance,i,x(a,b,l),f,b,l)}w(a,"aoRowCreatedCallback",null,[j,f,b])}d.nTr.setAttribute("role","row")}function Ma(a){var b=a.nTr,c=a._aData;if(b){c.DT_RowId&&(b.id=c.DT_RowId);if(c.DT_RowClass){var e=c.DT_RowClass.split(" ");a.__rowc=a.__rowc?Na(a.__rowc.concat(e)):e;h(b).removeClass(a.__rowc.join(" ")).addClass(c.DT_RowClass)}c.DT_RowAttr&&h(b).attr(c.DT_RowAttr);c.DT_RowData&&h(b).data(c.DT_RowData)}}function jb(a){var b,c,e,d,
f,g=a.nTHead,j=a.nTFoot,i=0===h("th, td",g).length,o=a.oClasses,l=a.aoColumns;i&&(d=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],e=h(f.nTh).addClass(f.sClass),i&&e.appendTo(d),a.oFeatures.bSort&&(e.addClass(f.sSortingClass),!1!==f.bSortable&&(e.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Oa(a,f.nTh,b))),f.sTitle!=e.html()&&e.html(f.sTitle),Pa(a,"header")(a,e,f,o);i&&da(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(o.sHeaderTH);
h(j).find(">tr>th, >tr>td").addClass(o.sFooterTH);if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ea(a,b,c){var e,d,f,g=[],j=[],i=a.aoColumns.length,o;if(b){c===k&&(c=!1);e=0;for(d=b.length;e<d;e++){g[e]=b[e].slice();g[e].nTr=b[e].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[e].splice(f,1);j.push([])}e=0;for(d=g.length;e<d;e++){if(a=g[e].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[e].length;f<b;f++)if(o=
i=1,j[e][f]===k){a.appendChild(g[e][f].cell);for(j[e][f]=1;g[e+i]!==k&&g[e][f].cell==g[e+i][f].cell;)j[e+i][f]=1,i++;for(;g[e][f+o]!==k&&g[e][f].cell==g[e][f+o].cell;){for(c=0;c<i;c++)j[e+c][f+o]=1;o++}h(g[e][f].cell).attr("rowspan",i).attr("colspan",o)}}}}function M(a){var b=w(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,e=a.asStripeClasses,d=e.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==B(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=
j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);var g=a._iDisplayStart,o=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!kb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:o;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ja(a,l);l=q.nTr;if(0!==d){var n=e[c%d];q._sRowStripe!=n&&(h(l).removeClass(q._sRowStripe).addClass(n),q._sRowStripe=n)}w(a,"aoRowCallback",null,[l,q._aData,c,j]);b.push(l);c++}}else c=f.sZeroRecords,
1==a.iDraw&&"ajax"==B(a)?c=f.sLoadingRecords:f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":d?e[0]:""}).append(h("<td />",{valign:"top",colSpan:aa(a),"class":a.oClasses.sRowEmpty}).html(c))[0];w(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],La(a),g,o,i]);w(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],La(a),g,o,i]);e=h(a.nTBody);e.children().detach();e.append(h(b));w(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=
!1}}function N(a,b){var c=a.oFeatures,e=c.bFilter;c.bSort&&lb(a);e?fa(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;M(a);a._drawHold=!1}function mb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),e=a.oFeatures,d=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=d[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,o,l,q,n=0;n<f.length;n++){g=
null;j=f[n];if("<"==j){i=h("<div/>")[0];o=f[n+1];if("'"==o||'"'==o){l="";for(q=2;f[n+q]!=o;)l+=f[n+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(o=l.split("."),i.id=o[0].substr(1,o[0].length-1),i.className=o[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;n+=q}d.append(i);d=h(i)}else if(">"==j)d=d.parent();else if("l"==j&&e.bPaginate&&e.bLengthChange)g=nb(a);else if("f"==j&&e.bFilter)g=ob(a);else if("r"==j&&e.bProcessing)g=pb(a);else if("t"==j)g=qb(a);else if("i"==
j&&e.bInfo)g=rb(a);else if("p"==j&&e.bPaginate)g=sb(a);else if(0!==m.ext.feature.length){i=m.ext.feature;q=0;for(o=i.length;q<o;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),d.append(g))}c.replaceWith(d)}function da(a,b){var c=h(b).children("tr"),e,d,f,g,j,i,o,l,q,n;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){e=c[f];for(d=e.firstChild;d;){if("TD"==d.nodeName.toUpperCase()||"TH"==d.nodeName.toUpperCase()){l=
1*d.getAttribute("colspan");q=1*d.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;o=g;n=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][o+j]={cell:d,unique:n},a[f+g].nTr=e}d=d.nextSibling}}}function qa(a,b,c){var e=[];c||(c=a.aoHeader,b&&(c=[],da(c,b)));for(var b=0,d=c.length;b<d;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!e[f]||!a.bSortCellsTop))e[f]=c[b][f].cell;return e}function ra(a,b,c){w(a,"aoServerParams","serverParams",[b]);
if(b&&h.isArray(b)){var e={},d=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(d);c?(c=c[0],e[c]||(e[c]=[]),e[c].push(b.value)):e[b.name]=b.value});b=e}var f,g=a.ajax,j=a.oInstance,i=function(b){w(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var o=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&o?o:h.extend(!0,b,o);delete g.data}o={data:b,success:function(b){var c=b.error||b.sError;c&&I(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,
c){var f=w(a,null,"xhr",[a,null,a.jqXHR]);-1===h.inArray(!0,f)&&("parsererror"==c?I(a,0,"Invalid JSON response",1):4===b.readyState&&I(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;w(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(o,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(o,g)),g.data=f)}function kb(a){return a.bAjaxDataGet?
(a.iDraw++,C(a,!0),ra(a,tb(a),function(b){ub(a,b)}),!1):!0}function tb(a){var b=a.aoColumns,c=b.length,e=a.oFeatures,d=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,o,l,q=U(a);g=a._iDisplayStart;i=!1!==e.bPaginate?a._iDisplayLength:-1;var n=function(a,b){j.push({name:a,value:b})};n("sEcho",a.iDraw);n("iColumns",c);n("sColumns",D(b,"sName").join(","));n("iDisplayStart",g);n("iDisplayLength",i);var k={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:d.sSearch,regex:d.bRegex}};for(g=
0;g<c;g++)o=b[g],l=f[g],i="function"==typeof o.mData?"function":o.mData,k.columns.push({data:i,name:o.sName,searchable:o.bSearchable,orderable:o.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),n("mDataProp_"+g,i),e.bFilter&&(n("sSearch_"+g,l.sSearch),n("bRegex_"+g,l.bRegex),n("bSearchable_"+g,o.bSearchable)),e.bSort&&n("bSortable_"+g,o.bSortable);e.bFilter&&(n("sSearch",d.sSearch),n("bRegex",d.bRegex));e.bSort&&(h.each(q,function(a,b){k.order.push({column:b.col,dir:b.dir});n("iSortCol_"+a,b.col);
n("sSortDir_"+a,b.dir)}),n("iSortingCols",q.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?j:k:b?j:k}function ub(a,b){var c=sa(a,b),e=b.sEcho!==k?b.sEcho:b.draw,d=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(e){if(1*e<a.iDraw)return;a.iDraw=1*e}oa(a);a._iRecordsTotal=parseInt(d,10);a._iRecordsDisplay=parseInt(f,10);e=0;for(d=c.length;e<d;e++)K(a,c[e]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;
M(a);a._bInitComplete||ta(a,b);a.bAjaxDataGet=!0;C(a,!1)}function sa(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?R(c)(b):b}function ob(a){var b=a.oClasses,c=a.sTableId,e=a.oLanguage,d=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=e.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),
f=function(){var b=!this.value?"":this.value;b!=d.sSearch&&(fa(a,{sSearch:b,bRegex:d.bRegex,bSmart:d.bSmart,bCaseInsensitive:d.bCaseInsensitive}),a._iDisplayStart=0,M(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===B(a)?400:0,i=h("input",b).val(d.sSearch).attr("placeholder",e.sSearchPlaceholder).bind("keyup.DT search.DT input.DT paste.DT cut.DT",g?ua(f,g):f).bind("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==
Q.activeElement&&i.val(d.sSearch)}catch(f){}});return b[0]}function fa(a,b,c){var e=a.oPreviousSearch,d=a.aoPreSearchCols,f=function(a){e.sSearch=a.sSearch;e.bRegex=a.bRegex;e.bSmart=a.bSmart;e.bCaseInsensitive=a.bCaseInsensitive};Ha(a);if("ssp"!=B(a)){vb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<d.length;b++)wb(a,d[b].sSearch,b,d[b].bEscapeRegex!==k?!d[b].bEscapeRegex:d[b].bRegex,d[b].bSmart,d[b].bCaseInsensitive);xb(a)}else f(b);a.bFiltered=
!0;w(a,null,"search",[a])}function xb(a){for(var b=m.ext.search,c=a.aiDisplay,e,d,f=0,g=b.length;f<g;f++){for(var j=[],i=0,h=c.length;i<h;i++)d=c[i],e=a.aoData[d],b[f](a,e._aFilterData,d,e._aData,i)&&j.push(d);c.length=0;c.push.apply(c,j)}}function wb(a,b,c,e,d,f){if(""!==b)for(var g=a.aiDisplay,e=Qa(b,e,d,f),d=g.length-1;0<=d;d--)b=a.aoData[g[d]]._aFilterData[c],e.test(b)||g.splice(d,1)}function vb(a,b,c,e,d,f){var e=Qa(b,e,d,f),d=a.oPreviousSearch.sSearch,f=a.aiDisplayMaster,g;0!==m.ext.search.length&&
(c=!0);g=yb(a);if(0>=b.length)a.aiDisplay=f.slice();else{if(g||c||d.length>b.length||0!==b.indexOf(d)||a.bSorted)a.aiDisplay=f.slice();b=a.aiDisplay;for(c=b.length-1;0<=c;c--)e.test(a.aoData[b[c]]._sFilterRow)||b.splice(c,1)}}function Qa(a,b,c,e){a=b?a:va(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,e?"i":"")}function va(a){return a.replace(Yb,"\\$1")}
function yb(a){var b=a.aoColumns,c,e,d,f,g,j,i,h,l=m.ext.type.search;c=!1;e=0;for(f=a.aoData.length;e<f;e++)if(h=a.aoData[e],!h._aFilterData){j=[];d=0;for(g=b.length;d<g;d++)c=b[d],c.bSearchable?(i=x(a,e,d,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(wa.innerHTML=i,i=Zb?wa.textContent:wa.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}
function zb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}function Ab(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function rb(a){var b=a.sTableId,c=a.aanFeatures.i,e=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Bb,sName:"information"}),e.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return e[0]}function Bb(a){var b=
a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,e=a._iDisplayStart+1,d=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Cb(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,e,d,f,g,j));h(b).html(j)}}function Cb(a,b){var c=a.fnFormatNumber,e=a._iDisplayStart+1,d=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===d;return b.replace(/_START_/g,c.call(a,e)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,
c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(e/d))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/d)))}function ga(a){var b,c,e=a.iInitDisplayStart,d=a.aoColumns,f;c=a.oFeatures;if(a.bInitialised){mb(a);jb(a);ea(a,a.aoHeader);ea(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Ga(a);b=0;for(c=d.length;b<c;b++)f=d[b],f.sWidth&&(f.nTh.style.width=s(f.sWidth));N(a);d=B(a);"ssp"!=d&&("ajax"==d?ra(a,[],function(c){var f=sa(a,c);for(b=0;b<f.length;b++)K(a,f[b]);
a.iInitDisplayStart=e;N(a);C(a,!1);ta(a,c)},a):(C(a,!1),ta(a)))}else setTimeout(function(){ga(a)},200)}function ta(a,b){a._bInitComplete=!0;b&&X(a);w(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);w(a,null,"length",[a,c])}function nb(a){for(var b=a.oClasses,c=a.sTableId,e=a.aLengthMenu,d=h.isArray(e[0]),f=d?e[0]:e,e=d?e[1]:e,d=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)d[0][g]=new Option(e[g],
f[g]);var i=h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",d[0].outerHTML));h("select",i).val(a._iDisplayLength).bind("change.DT",function(){Ra(a,h(this).val());M(a)});h(a.nTable).bind("length.dt.DT",function(b,c,f){a===c&&h("select",i).val(f)});return i[0]}function sb(a){var b=a.sPaginationType,c=m.ext.pager[b],e="function"===typeof c,d=function(a){M(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],
f=a.aanFeatures;e||c.fnInit(a,b,d);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(e){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),q,l=0;for(q=f.p.length;l<q;l++)Pa(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,d)},sName:"pagination"}));return b}function Ta(a,b,c){var e=a._iDisplayStart,d=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===d?e=0:"number"===typeof b?(e=b*d,e>f&&(e=0)):
"first"==b?e=0:"previous"==b?(e=0<=d?e-d:0,0>e&&(e=0)):"next"==b?e+d<f&&(e+=d):"last"==b?e=Math.floor((f-1)/d)*d:I(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==e;a._iDisplayStart=e;b&&(w(a,null,"page",[a]),c&&M(a));return b}function pb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");w(a,
null,"processing",[a,b])}function qb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var e=c.sX,d=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),o=h(b[0].cloneNode(!1)),l=b.children("tfoot");c.sX&&"100%"===b.attr("width")&&b.removeAttr("width");l.length||(l=null);c=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,
width:e?!e?null:s(e):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({overflow:"auto",height:!d?null:s(d),width:!e?null:s(e)}).append(b));l&&c.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:e?!e?null:s(e):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(o.removeAttr("id").css("margin-left",
0).append("bottom"===j?g:null).append(b.children("tfoot")))));var b=c.children(),q=b[0],f=b[1],n=l?b[2]:null;if(e)h(f).on("scroll.DT",function(){var a=this.scrollLeft;q.scrollLeft=a;l&&(n.scrollLeft=a)});a.nScrollHead=q;a.nScrollBody=f;a.nScrollFoot=n;a.aoDrawCallback.push({fn:Y,sName:"scrolling"});return c[0]}function Y(a){var b=a.oScroll,c=b.sX,e=b.sXInner,d=b.sY,f=b.iBarWidth,g=h(a.nScrollHead),j=g[0].style,i=g.children("div"),o=i[0].style,l=i.children("table"),i=a.nScrollBody,q=h(i),n=i.style,
k=h(a.nScrollFoot).children("div"),p=k.children("table"),m=h(a.nTHead),r=h(a.nTable),t=r[0],O=t.style,L=a.nTFoot?h(a.nTFoot):null,ha=a.oBrowser,w=ha.bScrollOversize,v,u,y,x,z,A=[],B=[],C=[],D,E=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};r.children("thead, tfoot").remove();z=m.clone().prependTo(r);v=m.find("tr");y=z.find("tr");z.find("th, td").removeAttr("tabindex");L&&(x=L.clone().prependTo(r),u=L.find("tr"),x=x.find("tr"));
c||(n.width="100%",g[0].style.width="100%");h.each(qa(a,z),function(b,c){D=la(a,b);c.style.width=a.aoColumns[D].sWidth});L&&G(function(a){a.style.width=""},x);b.bCollapse&&""!==d&&(n.height=q[0].offsetHeight+m[0].offsetHeight+"px");g=r.outerWidth();if(""===c){if(O.width="100%",w&&(r.find("tbody").height()>i.offsetHeight||"scroll"==q.css("overflow-y")))O.width=s(r.outerWidth()-f)}else""!==e?O.width=s(e):g==q.width()&&q.height()<r.height()?(O.width=s(g-f),r.outerWidth()>g-f&&(O.width=s(g))):O.width=
s(g);g=r.outerWidth();G(E,y);G(function(a){C.push(a.innerHTML);A.push(s(h(a).css("width")))},y);G(function(a,b){a.style.width=A[b]},v);h(y).height(0);L&&(G(E,x),G(function(a){B.push(s(h(a).css("width")))},x),G(function(a,b){a.style.width=B[b]},u),h(x).height(0));G(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+C[b]+"</div>";a.style.width=A[b]},y);L&&G(function(a,b){a.innerHTML="";a.style.width=B[b]},x);if(r.outerWidth()<g){u=i.scrollHeight>i.offsetHeight||
"scroll"==q.css("overflow-y")?g+f:g;if(w&&(i.scrollHeight>i.offsetHeight||"scroll"==q.css("overflow-y")))O.width=s(u-f);(""===c||""!==e)&&I(a,1,"Possible column misalignment",6)}else u="100%";n.width=s(u);j.width=s(u);L&&(a.nScrollFoot.style.width=s(u));!d&&w&&(n.height=s(t.offsetHeight+f));d&&b.bCollapse&&(n.height=s(d),b=c&&t.offsetWidth>i.offsetWidth?f:0,t.offsetHeight<i.offsetHeight&&(n.height=s(t.offsetHeight+b)));b=r.outerWidth();l[0].style.width=s(b);o.width=s(b);l=r.height()>i.clientHeight||
"scroll"==q.css("overflow-y");ha="padding"+(ha.bScrollbarLeft?"Left":"Right");o[ha]=l?f+"px":"0px";L&&(p[0].style.width=s(b),k[0].style.width=s(b),k[0].style[ha]=l?f+"px":"0px");q.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)i.scrollTop=0}function G(a,b,c){for(var e=0,d=0,f=b.length,g,j;d<f;){g=b[d].firstChild;for(j=c?c[d].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,e):a(g,e),e++),g=g.nextSibling,j=c?j.nextSibling:null;d++}}function Ga(a){var b=a.nTable,c=a.aoColumns,e=a.oScroll,d=e.sY,f=e.sX,
g=e.sXInner,j=c.length,e=Z(a,"bVisible"),i=h("th",a.nTHead),o=b.getAttribute("width"),l=b.parentNode,k=!1,n,m;(n=b.style.width)&&-1!==n.indexOf("%")&&(o=n);for(n=0;n<e.length;n++)m=c[e[n]],null!==m.sWidth&&(m.sWidth=Db(m.sWidthOrig,l),k=!0);if(!k&&!f&&!d&&j==aa(a)&&j==i.length)for(n=0;n<j;n++)c[n].sWidth=s(i.eq(n).width());else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var p=h("<tr/>").appendTo(j.find("tbody"));j.find("tfoot th, tfoot td").css("width",
"");i=qa(a,j.find("thead")[0]);for(n=0;n<e.length;n++)m=c[e[n]],i[n].style.width=null!==m.sWidthOrig&&""!==m.sWidthOrig?s(m.sWidthOrig):"";if(a.aoData.length)for(n=0;n<e.length;n++)k=e[n],m=c[k],h(Eb(a,k)).clone(!1).append(m.sContentPadding).appendTo(p);j.appendTo(l);f&&g?j.width(g):f?(j.css("width","auto"),j.width()<l.offsetWidth&&j.width(l.offsetWidth)):d?j.width(l.offsetWidth):o&&j.width(o);Fb(a,j[0]);if(f){for(n=g=0;n<e.length;n++)m=c[e[n]],d=h(i[n]).outerWidth(),g+=null===m.sWidthOrig?d:parseInt(m.sWidth,
10)+d-h(i[n]).width();j.width(s(g));b.style.width=s(g)}for(n=0;n<e.length;n++)if(m=c[e[n]],d=h(i[n]).width())m.sWidth=s(d);b.style.width=s(j.css("width"));j.remove()}o&&(b.style.width=s(o));if((o||f)&&!a._reszEvt)b=function(){h(Ea).bind("resize.DT-"+a.sInstance,ua(function(){X(a)}))},a.oBrowser.bScrollOversize?setTimeout(b,1E3):b(),a._reszEvt=!0}function ua(a,b){var c=b!==k?b:200,e,d;return function(){var b=this,g=+new Date,j=arguments;e&&g<e+c?(clearTimeout(d),d=setTimeout(function(){e=k;a.apply(b,
j)},c)):(e=g,a.apply(b,j))}}function Db(a,b){if(!a)return 0;var c=h("<div/>").css("width",s(a)).appendTo(b||Q.body),e=c[0].offsetWidth;c.remove();return e}function Fb(a,b){var c=a.oScroll;if(c.sX||c.sY)c=!c.sX?c.iBarWidth:0,b.style.width=s(h(b).outerWidth()-c)}function Eb(a,b){var c=Gb(a,b);if(0>c)return null;var e=a.aoData[c];return!e.nTr?h("<td/>").html(x(a,c,b,"display"))[0]:e.anCells[b]}function Gb(a,b){for(var c,e=-1,d=-1,f=0,g=a.aoData.length;f<g;f++)c=x(a,f,b,"display")+"",c=c.replace($b,""),
c.length>e&&(e=c.length,d=f);return d}function s(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function Hb(){var a=m.__scrollbarWidth;if(a===k){var b=h("<p/>").css({position:"absolute",top:0,left:0,width:"100%",height:150,padding:0,overflow:"scroll",visibility:"hidden"}).appendTo("body"),a=b[0].offsetWidth-b[0].clientWidth;m.__scrollbarWidth=a;b.remove()}return a}function U(a){var b,c,e=[],d=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var o=[];
f=function(a){a.length&&!h.isArray(a[0])?o.push(a):o.push.apply(o,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<o.length;a++){i=o[a][0];f=d[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=d[g].sType||"string",o[a]._idx===k&&(o[a]._idx=h.inArray(o[a][1],d[g].asSorting)),e.push({src:i,col:g,dir:o[a][1],index:o[a]._idx,type:j,formatter:m.ext.type.order[j+"-pre"]})}return e}function lb(a){var b,c,e=[],d=m.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;
Ha(a);h=U(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Ib(a,j.col);if("ssp"!=B(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)e[i[b]]=b;g===h.length?i.sort(function(a,b){var c,d,g,j,i=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g=0;g<i;g++)if(j=h[g],c=k[j.col],d=m[j.col],c=c<d?-1:c>d?1:0,0!==c)return"asc"===j.dir?c:-c;c=e[a];d=e[b];return c<d?-1:c>d?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,m=f[a]._aSortData,r=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=m[i.col],g=r[i.col],i=d[i.type+
"-"+i.dir]||d["string-"+i.dir],c=i(c,g),0!==c)return c;c=e[a];g=e[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Jb(a){for(var b,c,e=a.aoColumns,d=U(a),a=a.oLanguage.oAria,f=0,g=e.length;f<g;f++){c=e[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<d.length&&d[0].col==f?(i.setAttribute("aria-sort","asc"==d[0].dir?"ascending":"descending"),c=j[d[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",
b)}}function Ua(a,b,c,e){var d=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof d[0]&&(d=a.aaSorting=[d]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,D(d,"0")),-1!==c?(b=g(d[c],!0),null===b&&1===d.length&&(b=0),null===b?d.splice(c,1):(d[c][1]=f[b],d[c]._idx=b)):(d.push([b,f[0],0]),d[d.length-1]._idx=0)):d.length&&d[0][0]==b?(b=g(d[0]),d.length=1,d[0][1]=f[b],d[0]._idx=b):(d.length=0,d.push([b,f[0]]),d[0]._idx=
0);N(a);"function"==typeof e&&e(a)}function Oa(a,b,c,e){var d=a.aoColumns[c];Va(b,{},function(b){!1!==d.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Ua(a,c,b.shiftKey,e);"ssp"!==B(a)&&C(a,!1)},0)):Ua(a,c,b.shiftKey,e))})}function xa(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,e=U(a),d=a.oFeatures,f,g;if(d.bSort&&d.bSortClasses){d=0;for(f=b.length;d<f;d++)g=b[d].src,h(D(a.aoData,"anCells",g)).removeClass(c+(2>d?d+1:3));d=0;for(f=e.length;d<f;d++)g=e[d].src,h(D(a.aoData,"anCells",
g)).addClass(c+(2>d?d+1:3))}a.aLastSort=e}function Ib(a,b){var c=a.aoColumns[b],e=m.ext.order[c.sSortDataType],d;e&&(d=e.call(a.oInstance,a,b,$(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||e)f=e?d[j]:x(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function ya(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),
search:zb(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,e){return{visible:b.bVisible,search:zb(a.aoPreSearchCols[e])}})};w(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Kb(a){var b,c,e=a.aoColumns;if(a.oFeatures.bStateSave){var d=a.fnStateLoadCallback.call(a.oInstance,a);if(d&&d.time&&(b=w(a,"aoStateLoadParams","stateLoadParams",[a,d]),-1===h.inArray(!1,b)&&(b=a.iStateDuration,!(0<b&&d.time<+new Date-1E3*b)&&e.length===
d.columns.length))){a.oLoadedState=h.extend(!0,{},d);d.start!==k&&(a._iDisplayStart=d.start,a.iInitDisplayStart=d.start);d.length!==k&&(a._iDisplayLength=d.length);d.order!==k&&(a.aaSorting=[],h.each(d.order,function(b,c){a.aaSorting.push(c[0]>=e.length?[0,c[1]]:c)}));d.search!==k&&h.extend(a.oPreviousSearch,Ab(d.search));b=0;for(c=d.columns.length;b<c;b++){var f=d.columns[b];f.visible!==k&&(e[b].bVisible=f.visible);f.search!==k&&h.extend(a.aoPreSearchCols[b],Ab(f.search))}w(a,"aoStateLoaded","stateLoaded",
[a,d])}}}function za(a){var b=m.settings,a=h.inArray(a,D(b,"nTable"));return-1!==a?b[a]:null}function I(a,b,c,e){c="DataTables warning: "+(null!==a?"table id="+a.sTableId+" - ":"")+c;e&&(c+=". For more information about this error, please see http://datatables.net/tn/"+e);if(b)Ea.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,w(a,null,"error",[a,e,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,e,c)}}function E(a,b,c,e){h.isArray(c)?
h.each(c,function(c,f){h.isArray(f)?E(a,b,f[0],f[1]):E(a,b,f)}):(e===k&&(e=c),b[c]!==k&&(a[e]=b[c]))}function Lb(a,b,c){var e,d;for(d in b)b.hasOwnProperty(d)&&(e=b[d],h.isPlainObject(e)?(h.isPlainObject(a[d])||(a[d]={}),h.extend(!0,a[d],e)):a[d]=c&&"data"!==d&&"aaData"!==d&&h.isArray(e)?e.slice():e);return a}function Va(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).bind("selectstart.DT",function(){return!1})}function z(a,
b,c,e){c&&a[b].push({fn:c,sName:e})}function w(a,b,c,e){var d=[];b&&(d=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,e)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,e),d.push(b.result));return d}function Sa(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),e=a._iDisplayLength;b>=c&&(b=c-e);b-=b%e;if(-1===e||0>b)b=0;a._iDisplayStart=b}function Pa(a,b){var c=a.renderer,e=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?e[c[b]]||e._:"string"===typeof c?e[c]||e._:e._}function B(a){return a.oFeatures.bServerSide?
"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function Wa(a,b){var c=[],c=Mb.numbers_length,e=Math.floor(c/2);b<=c?c=V(0,b):a<=e?(c=V(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-e?c=V(b-(c-2),b):(c=V(a-e+2,a+e-1),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function db(a){h.each({num:function(b){return Aa(b,a)},"num-fmt":function(b){return Aa(b,a,Xa)},"html-num":function(b){return Aa(b,a,Ba)},"html-num-fmt":function(b){return Aa(b,a,Ba,Xa)}},function(b,
c){u.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(u.type.search[b+a]=u.type.search.html)})}function Nb(a){return function(){var b=[za(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this,b)}}var m,u,t,r,v,Ya={},Ob=/[\r\n]/g,Ba=/<.*?>/g,ac=/^[\w\+\-]/,bc=/[\w\+\-]$/,Yb=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Xa=/[',$\u00a3\u20ac\u00a5%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,J=function(a){return!a||!0===a||
"-"===a?!0:!1},Pb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Qb=function(a,b){Ya[b]||(Ya[b]=RegExp(va(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(Ya[b],"."):a},Za=function(a,b,c){var e="string"===typeof a;if(J(a))return!0;b&&e&&(a=Qb(a,b));c&&e&&(a=a.replace(Xa,""));return!isNaN(parseFloat(a))&&isFinite(a)},Rb=function(a,b,c){return J(a)?!0:!(J(a)||"string"===typeof a)?null:Za(a.replace(Ba,""),b,c)?!0:null},D=function(a,b,c){var e=[],d=0,f=a.length;
if(c!==k)for(;d<f;d++)a[d]&&a[d][b]&&e.push(a[d][b][c]);else for(;d<f;d++)a[d]&&e.push(a[d][b]);return e},ia=function(a,b,c,e){var d=[],f=0,g=b.length;if(e!==k)for(;f<g;f++)a[b[f]][c]&&d.push(a[b[f]][c][e]);else for(;f<g;f++)d.push(a[b[f]][c]);return d},V=function(a,b){var c=[],e;b===k?(b=0,e=a):(e=b,b=a);for(var d=b;d<e;d++)c.push(d);return c},Sb=function(a){for(var b=[],c=0,e=a.length;c<e;c++)a[c]&&b.push(a[c]);return b},Na=function(a){var b=[],c,e,d=a.length,f,g=0;e=0;a:for(;e<d;e++){c=a[e];for(f=
0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b},A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ba=/\[.*?\]$/,T=/\(\)$/,wa=h("<div>")[0],Zb=wa.textContent!==k,$b=/<.*?>/g;m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new t(za(this[u.iApiIndex])):new t(this)};this.fnAddData=function(a,b){var c=this.api(!0),e=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===
k||b)&&c.draw();return e.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],e=c.oScroll;a===k||a?b.draw(!1):(""!==e.sX||""!==e.sY)&&Y(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var e=this.api(!0),a=e.rows(a),d=a.settings()[0],h=d.aoData[a[0][0]];a.remove();b&&b.call(this,d,h);(c===k||c)&&e.draw();return h};
this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,e,d,h){d=this.api(!0);null===b||b===k?d.search(a,c,e,h):d.column(b).search(a,c,e,h);d.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var e=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==e||"th"==e?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};
this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===
k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return za(this[u.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,e,d){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(d===k||d)&&h.columns.adjust();(e===k||e)&&h.draw();return 0};this.fnVersionCheck=u.fnVersionCheck;var b=this,c=a===k,e=this.length;c&&(a={});this.oApi=this.internal=u.internal;for(var d in m.ext.internal)d&&
(this[d]=Nb(d));this.each(function(){var d={},d=1<e?Lb(d,a,!0):a,g=0,j,i=this.getAttribute("id"),o=!1,l=m.defaults,q=h(this);if("table"!=this.nodeName.toLowerCase())I(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{eb(l);fb(l.column);H(l,l,!0);H(l.column,l.column,!0);H(l,h.extend(d,q.data()));var n=m.settings,g=0;for(j=n.length;g<j;g++){var r=n[g];if(r.nTable==this||r.nTHead.parentNode==this||r.nTFoot&&r.nTFoot.parentNode==this){g=d.bRetrieve!==k?d.bRetrieve:l.bRetrieve;if(c||g)return r.oInstance;
if(d.bDestroy!==k?d.bDestroy:l.bDestroy){r.oInstance.fnDestroy();break}else{I(r,0,"Cannot reinitialise DataTable",3);return}}if(r.sTableId==this.id){n.splice(g,1);break}}if(null===i||""===i)this.id=i="DataTables_Table_"+m.ext._unique++;var p=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:i,sTableId:i});p.nTable=this;p.oApi=b.internal;p.oInit=d;n.push(p);p.oInstance=1===b.length?b:q.dataTable();eb(d);d.oLanguage&&P(d.oLanguage);d.aLengthMenu&&!d.iDisplayLength&&(d.iDisplayLength=
h.isArray(d.aLengthMenu[0])?d.aLengthMenu[0][0]:d.aLengthMenu[0]);d=Lb(h.extend(!0,{},l),d);E(p.oFeatures,d,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));E(p,d,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback",
"renderer","searchDelay",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);E(p.oScroll,d,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);E(p.oLanguage,d,"fnInfoCallback");z(p,"aoDrawCallback",d.fnDrawCallback,"user");z(p,"aoServerParams",d.fnServerParams,"user");z(p,"aoStateSaveParams",d.fnStateSaveParams,"user");z(p,"aoStateLoadParams",
d.fnStateLoadParams,"user");z(p,"aoStateLoaded",d.fnStateLoaded,"user");z(p,"aoRowCallback",d.fnRowCallback,"user");z(p,"aoRowCreatedCallback",d.fnCreatedRow,"user");z(p,"aoHeaderCallback",d.fnHeaderCallback,"user");z(p,"aoFooterCallback",d.fnFooterCallback,"user");z(p,"aoInitComplete",d.fnInitComplete,"user");z(p,"aoPreDrawCallback",d.fnPreDrawCallback,"user");i=p.oClasses;d.bJQueryUI?(h.extend(i,m.ext.oJUIClasses,d.oClasses),d.sDom===l.sDom&&"lfrtip"===l.sDom&&(p.sDom='<"H"lfr>t<"F"ip>'),p.renderer)?
h.isPlainObject(p.renderer)&&!p.renderer.header&&(p.renderer.header="jqueryui"):p.renderer="jqueryui":h.extend(i,m.ext.classes,d.oClasses);q.addClass(i.sTable);if(""!==p.oScroll.sX||""!==p.oScroll.sY)p.oScroll.iBarWidth=Hb();!0===p.oScroll.sX&&(p.oScroll.sX="100%");p.iInitDisplayStart===k&&(p.iInitDisplayStart=d.iDisplayStart,p._iDisplayStart=d.iDisplayStart);null!==d.iDeferLoading&&(p.bDeferLoading=!0,g=h.isArray(d.iDeferLoading),p._iRecordsDisplay=g?d.iDeferLoading[0]:d.iDeferLoading,p._iRecordsTotal=
g?d.iDeferLoading[1]:d.iDeferLoading);var t=p.oLanguage;h.extend(!0,t,d.oLanguage);""!==t.sUrl&&(h.ajax({dataType:"json",url:t.sUrl,success:function(a){P(a);H(l.oLanguage,a);h.extend(true,t,a);ga(p)},error:function(){ga(p)}}),o=!0);null===d.asStripeClasses&&(p.asStripeClasses=[i.sStripeOdd,i.sStripeEven]);var g=p.asStripeClasses,s=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(g,function(a){return s.hasClass(a)}))&&(h("tbody tr",this).removeClass(g.join(" ")),p.asDestroyStripes=g.slice());
n=[];g=this.getElementsByTagName("thead");0!==g.length&&(da(p.aoHeader,g[0]),n=qa(p));if(null===d.aoColumns){r=[];g=0;for(j=n.length;g<j;g++)r.push(null)}else r=d.aoColumns;g=0;for(j=r.length;g<j;g++)Fa(p,n?n[g]:null);ib(p,d.aoColumnDefs,r,function(a,b){ka(p,a,b)});if(s.length){var u=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h.each(na(p,s[0]).cells,function(a,b){var c=p.aoColumns[a];if(c.mData===a){var d=u(b,"sort")||u(b,"order"),e=u(b,"filter")||u(b,"search");if(d!==null||e!==
null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};ka(p,a)}}})}var v=p.oFeatures;d.bStateSave&&(v.bStateSave=!0,Kb(p,d),z(p,"aoDrawCallback",ya,"state_save"));if(d.aaSorting===k){n=p.aaSorting;g=0;for(j=n.length;g<j;g++)n[g][1]=p.aoColumns[g].asSorting[0]}xa(p);v.bSort&&z(p,"aoDrawCallback",function(){if(p.bSorted){var a=U(p),b={};h.each(a,function(a,c){b[c.src]=c.dir});w(p,null,"order",[p,a,b]);Jb(p)}});z(p,"aoDrawCallback",
function(){(p.bSorted||B(p)==="ssp"||v.bDeferRender)&&xa(p)},"sc");gb(p);g=q.children("caption").each(function(){this._captionSide=q.css("caption-side")});j=q.children("thead");0===j.length&&(j=h("<thead/>").appendTo(this));p.nTHead=j[0];j=q.children("tbody");0===j.length&&(j=h("<tbody/>").appendTo(this));p.nTBody=j[0];j=q.children("tfoot");if(0===j.length&&0<g.length&&(""!==p.oScroll.sX||""!==p.oScroll.sY))j=h("<tfoot/>").appendTo(this);0===j.length||0===j.children().length?q.addClass(i.sNoFooter):
0<j.length&&(p.nTFoot=j[0],da(p.aoFooter,p.nTFoot));if(d.aaData)for(g=0;g<d.aaData.length;g++)K(p,d.aaData[g]);else(p.bDeferLoading||"dom"==B(p))&&ma(p,h(p.nTBody).children("tr"));p.aiDisplay=p.aiDisplayMaster.slice();p.bInitialised=!0;!1===o&&ga(p)}});b=null;return this};var Tb=[],y=Array.prototype,cc=function(a){var b,c,e=m.settings,d=h.map(e,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,d),-1!==b?[e[b]]:
null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,d);return-1!==b?e[b]:null}).toArray()};t=function(a,b){if(!(this instanceof t))return new t(a,b);var c=[],e=function(a){(a=cc(a))&&c.push.apply(c,a)};if(h.isArray(a))for(var d=0,f=a.length;d<f;d++)e(a[d]);else e(a);this.context=Na(c);b&&this.push.apply(this,b.toArray?b.toArray():b);this.selector={rows:null,cols:null,opts:null};
t.extend(this,this,Tb)};m.Api=t;t.prototype={any:function(){return 0!==this.flatten().length},concat:y.concat,context:[],each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new t(b[a],this[a]):null},filter:function(a){var b=[];if(y.filter)b=y.filter.call(this,a,this);else for(var c=0,e=this.length;c<e;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new t(this.context,b)},flatten:function(){var a=[];
return new t(this.context,a.concat.apply(a,this.toArray()))},join:y.join,indexOf:y.indexOf||function(a,b){for(var c=b||0,e=this.length;c<e;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,e){var d=[],f,g,h,i,o,l=this.context,q,n,m=this.selector;"string"===typeof a&&(e=c,c=b,b=a,a=!1);g=0;for(h=l.length;g<h;g++){var p=new t(l[g]);if("table"===b)f=c.call(p,l[g],g),f!==k&&d.push(f);else if("columns"===b||"rows"===b)f=c.call(p,l[g],this[g],g),f!==k&&d.push(f);else if("column"===b||"column-rows"===
b||"row"===b||"cell"===b){n=this[g];"column-rows"===b&&(q=Ca(l[g],m.opts));i=0;for(o=n.length;i<o;i++)f=n[i],f="cell"===b?c.call(p,l[g],f.row,f.column,g,i):c.call(p,l[g],f,g,i,q),f!==k&&d.push(f)}}return d.length||e?(a=new t(l,a?d.concat.apply([],d):d),b=a.selector,b.rows=m.rows,b.cols=m.cols,b.opts=m.opts,a):this},lastIndexOf:y.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(y.map)b=y.map.call(this,a,this);else for(var c=
0,e=this.length;c<e;c++)b.push(a.call(this,this[c],c));return new t(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:y.pop,push:y.push,reduce:y.reduce||function(a,b){return hb(this,a,b,0,this.length,1)},reduceRight:y.reduceRight||function(a,b){return hb(this,a,b,this.length-1,-1,-1)},reverse:y.reverse,selector:null,shift:y.shift,sort:y.sort,splice:y.splice,toArray:function(){return y.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},
unique:function(){return new t(this.context,Na(this))},unshift:y.unshift};t.extend=function(a,b,c){if(c.length&&b&&(b instanceof t||b.__dt_wrapper)){var e,d,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);t.extend(d,d,c.methodExt);return d}};e=0;for(d=c.length;e<d;e++)f=c[e],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,t.extend(a,b[f.name],f.propExt)}};t.register=r=function(a,b){if(h.isArray(a))for(var c=0,e=a.length;c<
e;c++)t.register(a[c],b);else for(var d=a.split("."),f=Tb,g,j,c=0,e=d.length;c<e;c++){g=(j=-1!==d[c].indexOf("()"))?d[c].replace("()",""):d[c];var i;a:{i=0;for(var o=f.length;i<o;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===e-1?i.val=b:f=j?i.methodExt:i.propExt}};t.registerPlural=v=function(a,b,c){t.register(a,c);t.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof t?a.length?h.isArray(a[0])?new t(a.context,
a[0]):a[0]:k:a})};r("tables()",function(a){var b;if(a){b=t;var c=this.context;if("number"===typeof a)a=[c[a]];else var e=h.map(c,function(a){return a.nTable}),a=h(e).filter(a).map(function(){var a=h.inArray(this,e);return c[a]}).toArray();b=new b(a)}else b=this;return b});r("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new t(b[0]):a});v("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});v("tables().body()","table().body()",
function(){return this.iterator("table",function(a){return a.nTBody},1)});v("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});v("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});v("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});r("draw()",function(a){return this.iterator("table",function(b){N(b,
!1===a)})});r("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});r("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a._iDisplayLength,e=a.fnRecordsDisplay(),d=-1===c;return{page:d?0:Math.floor(b/c),pages:d?1:Math.ceil(e/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:e}});r("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:
k:this.iterator("table",function(b){Ra(b,a)})});var Ub=function(a,b,c){if(c){var e=new t(a);e.one("draw",function(){c(e.ajax.json())})}"ssp"==B(a)?N(a,b):(C(a,!0),ra(a,[],function(c){oa(a);for(var c=sa(a,c),e=0,g=c.length;e<g;e++)K(a,c[e]);N(a,b);C(a,!1)}))};r("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});r("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});r("ajax.reload()",function(a,b){return this.iterator("table",function(c){Ub(c,
!1===b,a)})});r("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});r("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});var $a=function(a,b,c,e,d){var f=[],g,j,i,o,l,q;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(o=b.length;i<o;i++){j=
b[i]&&b[i].split?b[i].split(","):[b[i]];l=0;for(q=j.length;l<q;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&f.push.apply(f,g)}a=u.selector[a];if(a.length){i=0;for(o=a.length;i<o;i++)f=a[i](e,d,f)}return f},ab=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",page:"all"},a)},bb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},
Ca=function(a,b){var c,e,d,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;e=b.order;d=b.page;if("ssp"==B(a))return"removed"===j?[]:V(0,c.length);if("current"==d){c=a._iDisplayStart;for(e=a.fnDisplayEnd();c<e;c++)f.push(g[c])}else if("current"==e||"applied"==e)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1===h.inArray(a,g)?a:null});else if("index"==e||"original"==e){c=0;for(e=a.aoData.length;c<e;c++)"none"==j?f.push(c):(d=h.inArray(c,g),(-1===d&&"removed"==j||0<=d&&
"applied"==j)&&f.push(c))}return f};r("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var d=b;return $a("row",a,function(a){var b=Pb(a);if(b!==null&&!d)return[b];var j=Ca(c,d);if(b!==null&&h.inArray(b,j)!==-1)return[b];if(!a)return j;if(typeof a==="function")return h.map(j,function(b){var d=c.aoData[b];return a(b,d._aData,d.nTr)?b:null});b=Sb(ia(c.aoData,j,"nTr"));return a.nodeName&&h.inArray(a,b)!==-1?[a._DT_RowIndex]:h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},
c,d)},1);c.selector.rows=a;c.selector.opts=b;return c});r("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||k},1)});r("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ia(a.aoData,b,"_aData")},1)});v("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var e=b.aoData[c];return"search"===a?e._aFilterData:e._aSortData},1)});v("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",
function(b,c){ca(b,c,a)})});v("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b},1)});v("rows().remove()","row().remove()",function(){var a=this;return this.iterator("row",function(b,c,e){var d=b.aoData;d.splice(c,1);for(var f=0,g=d.length;f<g;f++)null!==d[f].nTr&&(d[f].nTr._DT_RowIndex=f);h.inArray(c,b.aiDisplay);pa(b.aiDisplayMaster,c);pa(b.aiDisplay,c);pa(a[e],c,!1);Sa(b)})});r("rows.add()",function(a){var b=this.iterator("table",function(b){var c,
f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ma(b,c)[0]):h.push(K(b,c));return h},1),c=this.rows(-1);c.pop();c.push.apply(c,b.toArray());return c});r("row()",function(a,b){return bb(this.rows(a,b))});r("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=a;ca(b[0],this[0],"data");return this});r("row().node()",function(){var a=this.context;return a.length&&this.length?
a[0].aoData[this[0]].nTr||null:null});r("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?ma(b,a)[0]:K(b,a)});return this.row(b[0])});var cb=function(a,b){var c=a.context;c.length&&(c=c[0].aoData[b!==k?b:a[0]],c._details&&(c._details.remove(),c._detailsShow=k,c._details=k))},Vb=function(a,b){var c=a.context;if(c.length&&a.length){var e=c[0].aoData[a[0]];if(e._details){(e._detailsShow=b)?e._details.insertAfter(e.nTr):
e._details.detach();var d=c[0],f=new t(d),g=d.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<D(g,"_details").length&&(f.on("draw.dt.DT_details",function(a,b){d===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(d===b)for(var c,e=aa(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",e)}),f.on("destroy.dt.DT_details",
function(a,b){if(d===b)for(var c=0,e=g.length;c<e;c++)g[c]._details&&cb(f,c)}))}}};r("row().child()",function(a,b){var c=this.context;if(a===k)return c.length&&this.length?c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)cb(this);else if(c.length&&this.length){var e=c[0],c=c[0].aoData[this[0]],d=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?d.push(a):(c=h("<tr><td/></tr>").addClass(b),
h("td",c).addClass(b).html(a)[0].colSpan=aa(e),d.push(c[0]))};f(a,b);c._details&&c._details.remove();c._details=h(d);c._detailsShow&&c._details.insertAfter(c.nTr)}return this});r(["row().child.show()","row().child().show()"],function(){Vb(this,!0);return this});r(["row().child.hide()","row().child().hide()"],function(){Vb(this,!1);return this});r(["row().child.remove()","row().child().remove()"],function(){cb(this);return this});r("row().child.isShown()",function(){var a=this.context;return a.length&&
this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var dc=/^(.+):(name|visIdx|visible)$/,Wb=function(a,b,c,e,d){for(var c=[],e=0,f=d.length;e<f;e++)c.push(x(a,d[e],b));return c};r("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var d=a,f=b,g=c.aoColumns,j=D(g,"sName"),i=D(g,"nTh");return $a("column",d,function(a){var b=Pb(a);if(a==="")return V(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var d=Ca(c,
f);return h.map(g,function(b,f){return a(f,Wb(c,f,0,0,d),i[f])?f:null})}var k=typeof a==="string"?a.match(dc):"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[la(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null})}else return h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray()},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});v("columns().header()",
"column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});v("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});v("columns().data()","column().data()",function(){return this.iterator("column-rows",Wb,1)});v("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});v("columns().cache()","column().cache()",
function(a){return this.iterator("column-rows",function(b,c,e,d,f){return ia(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});v("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,e,d){return ia(a.aoData,d,"anCells",b)},1)});v("columns().visible()","column().visible()",function(a,b){return this.iterator("column",function(c,e){if(a===k)return c.aoColumns[e].bVisible;var d=c.aoColumns,f=d[e],g=c.aoData,j,i,m;if(a!==k&&f.bVisible!==a){if(a){var l=
h.inArray(!0,D(d,"bVisible"),e+1);j=0;for(i=g.length;j<i;j++)m=g[j].nTr,d=g[j].anCells,m&&m.insertBefore(d[e],d[l]||null)}else h(D(c.aoData,"anCells",e)).detach();f.bVisible=a;ea(c,c.aoHeader);ea(c,c.aoFooter);if(b===k||b)X(c),(c.oScroll.sX||c.oScroll.sY)&&Y(c);w(c,null,"column-visibility",[c,e,a]);ya(c)}})});v("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?$(b,c):c},1)});r("columns.adjust()",function(){return this.iterator("table",
function(a){X(a)},1)});r("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return la(c,b);if("fromData"===a||"toVisible"===a)return $(c,b)}});r("column()",function(a,b){return bb(this.columns(a,b))});r("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=ab(c),f=b.aoData,g=Ca(b,e),i=Sb(ia(f,g,"anCells")),
j=h([].concat.apply([],i)),l,m=b.aoColumns.length,o,r,t,s,u,v;return $a("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){o=[];r=0;for(t=g.length;r<t;r++){l=g[r];for(s=0;s<m;s++){u={row:l,column:s};if(c){v=b.aoData[l];a(u,x(b,l,s),v.anCells?v.anCells[s]:null)&&o.push(u)}else o.push(u)}}return o}return h.isPlainObject(a)?[a]:j.filter(a).map(function(a,b){l=b.parentNode._DT_RowIndex;return{row:l,column:h.inArray(b,f[l].anCells)}}).toArray()},b,e)});var e=this.columns(b,c),d=this.rows(a,
c),f,g,j,i,m,l=this.iterator("table",function(a,b){f=[];g=0;for(j=d[b].length;g<j;g++){i=0;for(m=e[b].length;i<m;i++)f.push({row:d[b][g],column:e[b][i]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});v("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b].anCells)?a[c]:k},1)});r("cells().data()",function(){return this.iterator("cell",function(a,b,c){return x(a,b,c)},1)});v("cells().cache()","cell().cache()",function(a){a=
"search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,e){return b.aoData[c][a][e]},1)});v("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,e){return x(b,c,e,a)},1)});v("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,column:c,columnVisible:$(a,c)}},1)});v("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,e){ca(b,c,a,e)})});r("cell()",
function(a,b,c){return bb(this.cells(a,b,c))});r("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?x(b[0],c[0].row,c[0].column):k;Ia(b[0],c[0].row,c[0].column,a);ca(b[0],c[0].row,"data",c[0].column);return this});r("order()",function(a,b){var c=this.context;if(a===k)return 0!==c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:h.isArray(a[0])||(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});
r("order.listener()",function(a,b,c){return this.iterator("table",function(e){Oa(e,a,b,c)})});r(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,e){var d=[];h.each(b[e],function(b,c){d.push([c,a])});c.aaSorting=d})});r("search()",function(a,b,c,e){var d=this.context;return a===k?0!==d.length?d[0].oPreviousSearch.sSearch:k:this.iterator("table",function(d){d.oFeatures.bFilter&&fa(d,h.extend({},d.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:
b,bSmart:null===c?!0:c,bCaseInsensitive:null===e?!0:e}),1)})});v("columns().search()","column().search()",function(a,b,c,e){return this.iterator("column",function(d,f){var g=d.aoPreSearchCols;if(a===k)return g[f].sSearch;d.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===e?!0:e}),fa(d,d.oPreviousSearch,1))})});r("state()",function(){return this.context.length?this.context[0].oSavedState:null});r("state.clear()",function(){return this.iterator("table",
function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});r("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});r("state.save()",function(){return this.iterator("table",function(a){ya(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,e,d=0,f=a.length;d<f;d++)if(c=parseInt(b[d],10)||0,e=parseInt(a[d],10)||0,c!==e)return c>e;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;h.each(m.settings,
function(a,d){var f=d.nScrollHead?h("table",d.nScrollHead)[0]:null,g=d.nScrollFoot?h("table",d.nScrollFoot)[0]:null;if(d.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){return h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable})};m.util={throttle:ua,escapeRegex:va};m.camelToHungarian=H;r("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,
b){r(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0].match(/\.dt\b/)||(a[0]+=".dt");var e=h(this.tables().nodes());e[b].apply(e,a);return this})});r("clear()",function(){return this.iterator("table",function(a){oa(a)})});r("settings()",function(){return new t(this.context,this.context)});r("init()",function(){var a=this.context;return a.length?a[0].oInit:null});r("data()",function(){return this.iterator("table",function(a){return D(a.aoData,"_aData")}).flatten()});r("destroy()",
function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,e=b.oClasses,d=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(d),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),q;b.bDestroying=!0;w(b,"aoDestroyCallback","destroy",[b]);a||(new t(b)).columns().visible(!0);k.unbind(".DT").find(":not(tbody *)").unbind(".DT");h(Ea).unbind(".DT-"+b.sInstance);d!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&d!=j.parentNode&&(i.children("tfoot").detach(),
i.append(j));i.detach();k.detach();b.aaSorting=[];b.aaSortingFixed=[];xa(b);h(l).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(e.sSortable+" "+e.sSortableAsc+" "+e.sSortableDesc+" "+e.sSortableNone);b.bJUI&&(h("th span."+e.sSortIcon+", td span."+e.sSortIcon,g).detach(),h("th, td",g).each(function(){var a=h("div."+e.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));!a&&c&&c.insertBefore(d,b.nTableReinsertBefore);f.children().detach();f.append(l);i.css("width",b.sDestroyWidth).removeClass(e.sTable);
(q=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%q])});c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){r(b+"s().every()",function(a){return this.iterator(b,function(e,d,f){a.call((new t(e))[b](d,f))})})});r("i18n()",function(a,b,c){var e=this.context[0],a=R(a)(e.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.7";m.settings=
[];m.models={};m.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",
sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,
fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,
fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},
sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,
sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null};W(m.defaults);m.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};W(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,
bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],
sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,
bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==B(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==B(this)?1*this._iRecordsDisplay:
this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,e=this.aiDisplay.length,d=this.oFeatures,f=d.bPaginate;return d.bServerSide?!1===f||-1===a?b+e:Math.min(b+a,this._iRecordsDisplay):!f||c>e||-1===a?e:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{}};m.ext=u={buttons:{},classes:{},errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},
header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(u,{afnFiltering:u.search,aTypes:u.type.detect,ofnSearch:u.type.search,oSort:u.type.order,afnSortData:u.order,aoFeatures:u.feature,oApi:u.internal,oStdClasses:u.classes,oPagination:u.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",
sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",
sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Da="",Da="",F=Da+"ui-state-default",ja=Da+"css_right ui-icon ui-icon-",Xb=Da+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(m.ext.oJUIClasses,
m.ext.classes,{sPageButton:"fg-button ui-button "+F,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:F+" sorting_asc",sSortDesc:F+" sorting_desc",sSortable:F+" sorting",sSortableAsc:F+" sorting_asc_disabled",sSortableDesc:F+" sorting_desc_disabled",sSortableNone:F+" sorting_disabled",sSortJUIAsc:ja+"triangle-1-n",sSortJUIDesc:ja+"triangle-1-s",sSortJUI:ja+"carat-2-n-s",
sSortJUIAscAllowed:ja+"carat-1-n",sSortJUIDescAllowed:ja+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+F,sScrollFoot:"dataTables_scrollFoot "+F,sHeaderTH:F,sFooterTH:F,sJUIHeader:Xb+" ui-corner-tl ui-corner-tr",sJUIFooter:Xb+" ui-corner-bl ui-corner-br"});var Mb=m.ext.pager;h.extend(Mb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},simple_numbers:function(a,b){return["previous",
Wa(a,b),"next"]},full_numbers:function(a,b){return["first","previous",Wa(a,b),"next","last"]},_numbers:Wa,numbers_length:7});h.extend(!0,m.ext.renderer,{pageButton:{_:function(a,b,c,e,d,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i,k,l=0,m=function(b,e){var n,r,t,s,u=function(b){Ta(a,b.data.action,true)};n=0;for(r=e.length;n<r;n++){s=e[n];if(h.isArray(s)){t=h("<"+(s.DT_el||"div")+"/>").appendTo(b);m(t,s)}else{k=i="";switch(s){case "ellipsis":b.append('<span class="ellipsis">&#x2026;</span>');break;
case "first":i=j.sFirst;k=s+(d>0?"":" "+g.sPageButtonDisabled);break;case "previous":i=j.sPrevious;k=s+(d>0?"":" "+g.sPageButtonDisabled);break;case "next":i=j.sNext;k=s+(d<f-1?"":" "+g.sPageButtonDisabled);break;case "last":i=j.sLast;k=s+(d<f-1?"":" "+g.sPageButtonDisabled);break;default:i=s+1;k=d===s?g.sPageButtonActive:""}if(i){t=h("<a>",{"class":g.sPageButton+" "+k,"aria-controls":a.sTableId,"data-dt-idx":l,tabindex:a.iTabIndex,id:c===0&&typeof s==="string"?a.sTableId+"_"+s:null}).html(i).appendTo(b);
Va(t,{action:s},u);l++}}}},n;try{n=h(Q.activeElement).data("dt-idx")}catch(r){}m(h(b).empty(),e);n&&h(b).find("[data-dt-idx="+n+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&(!ac.test(a)||!bc.test(a)))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||J(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;
return Rb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c,!0)?"html-num-fmt"+c:null},function(a){return J(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return J(a)?a:"string"===typeof a?a.replace(Ob," ").replace(Ba,""):""},string:function(a){return J(a)?a:"string"===typeof a?a.replace(Ob," "):a}});var Aa=function(a,b,c,e){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Qb(a,b));a.replace&&(c&&(a=a.replace(c,"")),
e&&(a=a.replace(e,"")));return 1*a};h.extend(u.type.order,{"date-pre":function(a){return Date.parse(a)||0},"html-pre":function(a){return J(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return J(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});db("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,e){h(a.nTable).on("order.dt.DT",function(d,
f,g,h){if(a===f){d=c.idx;b.removeClass(c.sSortingClass+" "+e.sSortAsc+" "+e.sSortDesc).addClass(h[d]=="asc"?e.sSortAsc:h[d]=="desc"?e.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,e){h("<div/>").addClass(e.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(e.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(d,f,g,h){if(a===f){d=c.idx;b.removeClass(e.sSortAsc+" "+e.sSortDesc).addClass(h[d]=="asc"?e.sSortAsc:h[d]=="desc"?e.sSortDesc:c.sSortingClass);
b.find("span."+e.sSortIcon).removeClass(e.sSortJUIAsc+" "+e.sSortJUIDesc+" "+e.sSortJUI+" "+e.sSortJUIAscAllowed+" "+e.sSortJUIDescAllowed).addClass(h[d]=="asc"?e.sSortJUIAsc:h[d]=="desc"?e.sSortJUIDesc:c.sSortingClassJUI)}})}}});m.render={number:function(a,b,c,e){return{display:function(d){if("number"!==typeof d&&"string"!==typeof d)return d;var f=0>d?"-":"",d=Math.abs(parseFloat(d)),g=parseInt(d,10),d=c?b+(d-g).toFixed(c).substring(2):"";return f+(e||"")+g.toString().replace(/\B(?=(\d{3})+(?!\d))/g,
a)+d}}}};h.extend(m.ext.internal,{_fnExternApiFunc:Nb,_fnBuildAjax:ra,_fnAjaxUpdate:kb,_fnAjaxParameters:tb,_fnAjaxUpdateDraw:ub,_fnAjaxDataSrc:sa,_fnAddColumn:Fa,_fnColumnOptions:ka,_fnAdjustColumnSizing:X,_fnVisibleToColumnIndex:la,_fnColumnIndexToVisible:$,_fnVisbleColumns:aa,_fnGetColumns:Z,_fnColumnTypes:Ha,_fnApplyColumnDefs:ib,_fnHungarianMap:W,_fnCamelToHungarian:H,_fnLanguageCompat:P,_fnBrowserDetect:gb,_fnAddData:K,_fnAddTr:ma,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:
null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:x,_fnSetCellData:Ia,_fnSplitObjNotation:Ka,_fnGetObjectDataFn:R,_fnSetObjectDataFn:S,_fnGetDataMaster:La,_fnClearTable:oa,_fnDeleteIndex:pa,_fnInvalidate:ca,_fnGetRowElements:na,_fnCreateTr:Ja,_fnBuildHead:jb,_fnDrawHead:ea,_fnDraw:M,_fnReDraw:N,_fnAddOptionsHtml:mb,_fnDetectHeader:da,_fnGetUniqueThs:qa,_fnFeatureHtmlFilter:ob,_fnFilterComplete:fa,_fnFilterCustom:xb,_fnFilterColumn:wb,_fnFilter:vb,_fnFilterCreateSearch:Qa,
_fnEscapeRegex:va,_fnFilterData:yb,_fnFeatureHtmlInfo:rb,_fnUpdateInfo:Bb,_fnInfoMacros:Cb,_fnInitialise:ga,_fnInitComplete:ta,_fnLengthChange:Ra,_fnFeatureHtmlLength:nb,_fnFeatureHtmlPaginate:sb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:pb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:qb,_fnScrollDraw:Y,_fnApplyToChildren:G,_fnCalculateColumnWidths:Ga,_fnThrottle:ua,_fnConvertToWidth:Db,_fnScrollingWidthAdjust:Fb,_fnGetWidestNode:Eb,_fnGetMaxLenString:Gb,_fnStringToCss:s,_fnScrollBarWidth:Hb,_fnSortFlatten:U,
_fnSort:lb,_fnSortAria:Jb,_fnSortListener:Ua,_fnSortAttachListener:Oa,_fnSortingClasses:xa,_fnSortData:Ib,_fnSaveState:ya,_fnLoadState:Kb,_fnSettingsFromNode:za,_fnLog:I,_fnMap:E,_fnBindAction:Va,_fnCallbackReg:z,_fnCallbackFire:w,_fnLengthOverflow:Sa,_fnRenderer:Pa,_fnDataSource:B,_fnRowAttributes:Ma,_fnCalculateEnd:function(){}});h.fn.dataTable=m;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]=
b});return h.fn.dataTable};"function"===typeof define&&define.amd?define("datatables",["jquery"],P):"object"===typeof exports?module.exports=P(require("jquery")):jQuery&&!jQuery.fn.dataTable&&P(jQuery)})(window,document);
var PMCommandReconnect = function (rec, opts) {
var CmdReconnect = function (port, settings) {
// We skip one level in the class hierarchy by calling to the constructor of superclass of the current class superclass
PMUI.command.CommandReconnect.superclass.call(this, port);
this.before = {
x: port.getX(),
y: port.getY(),
parent: port.getParent()
};
this.after = {
x: settings.x,
y: settings.y,
parent: settings.shape
};
};
CmdReconnect.prototype = new PMUI.command.CommandReconnect(rec);
CmdReconnect.prototype.execute = function () {
var connection = this.receiver.connection,
canvas = this.before.parent.canvas,
destElement,
srcElement;
this.receiver.setPosition(this.after.x, this.after.y)
.dragging = false;
PMUI.command.CommandReconnect.prototype.execute.call(this);
if (this.after.parent !== this.before.parent) {
canvas.regularShapes.insert(this.receiver);
}
srcElement = connection.getSrcPort().getParent();
destElement = connection.getDestPort().getParent();
srcElement.addOutgoingConnection(connection);
destElement.addIncomingConnection(connection);
};
CmdReconnect.prototype.undo = function () {
var connection,
destPort,
srcPort,
otherActivity;
PMUI.command.CommandReconnect.prototype.undo.call(this);
connection = this.receiver.connection;
destPort = connection.getDestPort();
srcPort = connection.getSrcPort();
if (this.after.parent !== this.before.parent) {
if (destPort === this.receiver) {
otherActivity = srcPort.getParent();
otherActivity.removeOutgoingConnection(connection);
otherActivity.addOutgoingConnection(connection);
this.after.parent.removeIncomingConnection(connection);
this.before.parent.addIncomingConnection(connection);
} else {
otherActivity = destPort.getParent();
otherActivity.removeIncomingConnection(connection);
otherActivity.addIncomingConnection(connection);
this.after.parent.removeOutgoingConnection(connection);
this.before.parent.addOutgoingConnection(connection);
}
}
};
return new CmdReconnect(rec, opts);
};
var PMSegmentDragBehavior = function (options) {
};
PMSegmentDragBehavior.prototype = new PMUI.behavior.ConnectionDragBehavior();
/**
* On drag handler, creates a connection segment from the shape to the current
* mouse position
* @param {PMUI.draw.CustomShape} customShape
* @return {Function}
*/
PMSegmentDragBehavior.prototype.onDrag = function (customShape) {
return function (e, ui) {
var canvas = customShape.getCanvas(),
endPoint = new PMUI.util.Point(),
realPoint = canvas.relativePoint(e);
if (canvas.connectionSegment) {
//remove the connection segment in order to create another one
$(canvas.connectionSegment.getHTML()).remove();
}
//Determine the point where the mouse currently is
endPoint.x = realPoint.x * customShape.canvas.zoomFactor;
endPoint.y = realPoint.y * customShape.canvas.zoomFactor;
//creates a new segment from where the helper was created to the
// currently mouse location
canvas.connectionSegment = new PMUI.draw.Segment({
startPoint: customShape.startConnectionPoint,
endPoint: endPoint,
parent: canvas,
color: new PMUI.util.Color(92, 156, 204),
zOrder: PMUI.util.Style.MAX_ZINDEX * 2
});
//We make the connection segment point to helper in order to get
// information when the drop occurs
canvas.connectionSegment.pointsTo = customShape;
//create HTML and paint
//canvas.connectionSegment.createHTML();
canvas.connectionSegment.paint();
};
};
var PMConnectHandler = function (options) {
PMUI.draw.Handler.call(this, options);
/**
* Category of this resize handler
* @type {"resizable"/"nonresizable"}
*/
this.category = null;
/**
* Denotes whether the resize handle is visible or not.
* @property boolean
*/
this.visible = false;
/**
* JSON used to create an instance of the class Style used when the object is resizable.
* @property {Object}
*/
this.resizableStyle = null;
/**
* JSON used to create an instance of the class Style used when the object is not resizable.
* @property {Object}
*/
this.nonResizableStyle = null;
this.relativeShape = null;
// set defaults
PMConnectHandler.prototype.init.call(this, options);
};
PMConnectHandler.prototype = new PMUI.draw.Handler();
/**
* The type of each instance of this class.
* @property {String}
*/
PMConnectHandler.prototype.type = "PMConnectHandler";
/**
* Instance initializer which uses options to extend the config options to initialize the instance
* @param {Object} options The object that contains the config
* @private
*/
PMConnectHandler.prototype.init = function (options) {
var defaults = {
width: 10,
height: 10,
parent: null,
orientation: null,
representation: null,
resizableStyle: {},
nonResizableStyle: {},
zOrder: 2
};
// extend recursively the defaultOptions with the given options
$.extend(true, defaults, options);
// add default zIndex to this handler
if (defaults.resizableStyle.cssProperties) {
defaults.resizableStyle.cssProperties.zIndex = defaults.zOrder;
}
if (defaults.nonResizableStyle.cssProperties) {
defaults.nonResizableStyle.cssProperties.zIndex = defaults.zOrder;
}
this.setParent(defaults.parent)
.setWidth(defaults.width)
.setHeight(defaults.height)
.setOrientation(defaults.orientation)
.setRepresentation(defaults.representation)
.setResizableStyle(defaults.resizableStyle)
.setNonResizableStyle(defaults.nonResizableStyle);
};
/**
* Sets the parent of this handler
* @param {PMUI.draw.Shape} newParent
* @chainable
*/
PMConnectHandler.prototype.setParent = function (newParent) {
this.parent = newParent;
return this;
};
/**
* Gets the parent of this handler.
* @return {PMUI.draw.Shape}
*/
PMConnectHandler.prototype.getParent = function () {
return this.parent;
};
/**
* Paints this resize handler by calling it's parent's `paint` and setting
* the visibility of this resize handler
* @chainable
*/
PMConnectHandler.prototype.paint = function () {
if (!this.html) {
throw new Error("paint(): This handler has no html");
}
// this line paints the representation (by default a rectangle)
PMUI.draw.Handler.prototype.paint.call(this);
this.setVisible(this.visible);
return this;
};
/**
* Sets the category of the resizeHandler (also adds the needed class to
* make the element resizable)
* @param newCategory
* @chainable
*/
PMConnectHandler.prototype.setCategory = function (newCategory) {
if (typeof newCategory === "string") {
this.category = newCategory;
}
this.style.addClasses([newCategory]);
return this;
};
/**
* Sets the resizable style of this shape by creating an instance of the class Style
* @param {Object} style
* @chainable
*/
PMConnectHandler.prototype.setResizableStyle = function (style) {
this.resizableStyle = new PMUI.util.Style({
belongsTo: this,
cssProperties: style.cssProperties,
cssClasses: style.cssClasses
});
return this;
};
/**
* Sets the non resizable style for this shape by creating an instance of the class Style
* @param {Object} style
* @chainable
*/
PMConnectHandler.prototype.setNonResizableStyle = function (style) {
this.nonResizableStyle = new PMUI.util.Style({
belongsTo: this,
cssProperties: style.cssProperties,
cssClasses: style.cssClasses
});
return this;
};
PMConnectHandler.prototype.attachListeners = function () {
var $handler = $('.dragConnectHandler');
$handler.mousedown(this.onMouseDown(this));
if (this.relativeShape) {
dragOptions = {
revert: true,
helper: "clone",
cursorAt: false,
revertDuration: 0,
grid: [1, 1],
start: this.onDragStart(this.relativeShape),
stop: this.onDragEnd(this.relativeShape),
drag: this.onDrag(this.relativeShape),
refreshPositions: true,
cursor: "pointer"
};
$(this.html).draggable(dragOptions);
}
return this;
};
PMConnectHandler.prototype.attachDrop = function () {
dropOptions = {
accept: '.dragConnectHandler, .pmui-oval',
hoverClass: "ui-state-hover",
drop: this.onDrop(this.relativeShape, this),
over: this.onDropOver(this.relativeShape, this)
};
$('.dropConnectHandler').droppable(dropOptions);
};
PMConnectHandler.prototype.onMouseDown = function (customShape) {
return function (e, ui) {
e.preventDefault();
e.stopPropagation();
}
};
PMConnectHandler.prototype.onMouseOver = function (customShape) {
return function (e, ui) {
e.preventDefault();
e.stopPropagation();
}
};
PMConnectHandler.prototype.onMouseOut = function (customShape) {
return function (e, ui) {
e.preventDefault();
e.stopPropagation();
PMUI.getActiveCanvas.isMouseOverHelper = false;
if (PMUI.getActiveCanvas.hightLightShape) {
PMUI.getActiveCanvas.hideDragConnectHandlers();
}
}
};
PMConnectHandler.prototype.onDragStart = function (customShape) {
return function (e, ui) {
if (!customShape.canvas.currentConnection) {
customShape.canvas.isDraggingConnectHandler = true;
var canvas = customShape.canvas,
currentLabel = canvas.currentLabel,
realPoint = canvas.relativePoint(e),
startPortX = e.pageX - customShape.getAbsoluteX(),
startPortY = e.pageY - customShape.getAbsoluteY();
// empty the current selection so that the segment created by the
// helper is always on top
customShape.canvas.emptyCurrentSelection();
if (currentLabel) {
currentLabel.loseFocus();
$(currentLabel.textField).focusout();
}
if (customShape.family !== "CustomShape") {
return false;
}
customShape.setOldX(customShape.getX());
customShape.setOldY(customShape.getY());
customShape.startConnectionPoint.x = customShape.canvas.zoomFactor * realPoint.x;
customShape.startConnectionPoint.y = customShape.canvas.zoomFactor * realPoint.y - canvas.getY();
} else {
customShape.canvas.currentConnection.disconnect();
}
return true;
};
};
PMConnectHandler.prototype.onDragEnd = function (customShape) {
return function (e, ui) {
if (customShape.canvas.connectionSegment) {
$(customShape.canvas.connectionSegment.getHTML()).remove();
customShape.canvas.currentConnection.connect()
.updateIncomingAndOutgoingConnections('create');
}
};
};
PMConnectHandler.prototype.onDrag = function (customShape) {
var sourceShape,
destinyShape,
startPoint;
return function (e, ui) {
var connections;
if (customShape.canvas.currentConnection) {
canvas = customShape.canvas;
endPoint = new PMUI.util.Point();
if (canvas.connectionSegment) {
$(canvas.connectionSegment.getHTML()).remove();
}
endPoint.x = e.pageX - canvas.getX() + canvas.getLeftScroll() - canvas.getAbsoluteX();
endPoint.y = e.pageY - canvas.getY() + canvas.getTopScroll() - canvas.getAbsoluteY();
//make connection segment
otherPort = customShape.connection.srcPort.getPoint(false)
.equals(customShape.getPoint(false)) ? customShape.connection.destPort :
customShape.connection.srcPort;
//remove related shapes
sourceShape = customShape.connection.srcPort.getParent();
destinyShape = customShape.connection.destPort.getParent();
connections = PMFlow.getConnections(sourceShape, destinyShape, false);
if (sourceShape && connections.length) {
// as we are invoking PMFlow.getConnections() with false as third parameter the result can have
// at most 1 element, that's why we use the index 0 in the arrays below.
sourceShape.removeOutgoingConnection(connections[0]);
destinyShape.removeIncomingConnection(connections[0]);
}
connections = PMFlow.getConnections(destinyShape, sourceShape, false);
if (destinyShape && connections.length) {
// as we are invoking PMFlow.getConnections() with false as third parameter the result can have
// at most 1 element, that's why we use the index 0 in the arrays below.
destinyShape.removeOutgoingConnection(connections[0]);
sourceShape.removeIncomingConnection(connections[0]);
}
startPoint = otherPort.getPoint(false);
startPoint.x = startPoint.x - canvas.getAbsoluteX();
startPoint.y = startPoint.y - canvas.getAbsoluteY();
canvas.connectionSegment = new PMUI.draw.Segment({
startPoint: startPoint,
endPoint: endPoint,
parent: canvas
});
canvas.connectionSegment.createHTML();
canvas.connectionSegment.paint();
} else {
customShape.canvas.isDraggingConnectHandler = true;
var canvas = customShape.getCanvas(),
endPoint = new PMUI.util.Point(),
realPoint = canvas.relativePoint(e);
if (canvas.connectionSegment) {
//remove the connection segment in order to create another one
$(canvas.connectionSegment.getHTML()).remove();
}
//Determine the point where the mouse currently is
endPoint.x = realPoint.x * customShape.canvas.zoomFactor - canvas.getX();
endPoint.y = realPoint.y * customShape.canvas.zoomFactor - canvas.getY();
//creates a new segment from where the helper was created to the
// currently mouse location
canvas.connectionSegment = new PMUI.draw.Segment({
startPoint: customShape.startConnectionPoint,
endPoint: endPoint,
parent: canvas,
zOrder: PMUI.util.Style.MAX_ZINDEX * 2
});
//We make the connection segment point to helper in order to get
// information when the drop occurs
canvas.connectionSegment.pointsTo = customShape;
//create HTML and paint
//canvas.connectionSegment.createHTML();
canvas.connectionSegment.paint();
}
};
};
PMConnectHandler.prototype.onClick = function (obj) {
return function (e, ui) {
alert('clicked');
};
};
/**
* Drag enter hook for this drop behavior, marks that a shape is over a
* droppable element
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMConnectHandler.prototype.onDropOver = function (shape, handler) {
return function (e, ui) {
};
};
/**
* Drag leave hook for this drop behavior, marks that a shape has left a
* droppable element
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMConnectHandler.prototype.onDropOut = function (shape, handler) {
return function (e, ui) {
shape.entered = false;
handler.style.addClasses(['pmConnnectHandler']);
};
};
/**
* On drop handler for this drop behavior, creates a connection between the
* droppable element and the dropped element, or move ports among those shapes
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMConnectHandler.prototype.onDrop = function (shape, handler) {
return function (e, ui) {
var connection,
sourceShape,
canvas = shape.getCanvas(),
id = ui.draggable.attr('id'),
targetShape,
originalType,
currLeft,
currTop,
startPoint,
sourcePort,
endPort,
endPortXCoord,
endPortYCoord,
port,
command,
validationResult;
if (!shape.canvas.currentConnection) {
shape.entered = false;
//if its the helper then we need to create two ports and draw a
// connection
//we get the points and the corresponding shapes involved
startPoint = shape.canvas.connectionSegment.startPoint;
sourceShape = shape.canvas.connectionSegment.pointsTo;
//determine the points where the helper was created
if (sourceShape.parent && sourceShape.parent.id === shape.id) {
return true;
}
validationResult = PMDesigner.connectValidator.isValid(sourceShape, shape);
if (!validationResult.result) {
//show invalid message
PMDesigner.msgFlash(validationResult.msg, document.body, 'info', 3000, 5);
return false;
}
sourceShape.setPosition(sourceShape.oldX, sourceShape.oldY);
startPoint.x -= sourceShape.absoluteX - shape.canvas.getAbsoluteX();
startPoint.y -= sourceShape.absoluteY - shape.canvas.getAbsoluteY();
//create the ports
sourcePort = new PMUI.draw.Port({
width: 10,
height: 10
});
endPort = new PMUI.draw.Port({
width: 10,
height: 10
});
//determine the position where the helper was dropped
endPortXCoord = ui.offset.left - shape.canvas.getX() -
shape.getAbsoluteX() + shape.canvas.getLeftScroll();
endPortYCoord = ui.offset.top - shape.canvas.getY() -
shape.getAbsoluteY() + shape.canvas.getTopScroll();
// add ports to the corresponding shapes
// addPort() determines the position of the ports
sourceShape.addPort(sourcePort, startPoint.x, startPoint.y);
shape.addPort(endPort, endPortXCoord, endPortYCoord,
false, sourcePort);
//add ports to the canvas array for regularShapes
//shape.canvas.regularShapes.insert(sourcePort).insert(endPort);
//create the connection
connection = new PMFlow({
srcPort: sourcePort,
destPort: endPort,
segmentColor: new PMUI.util.Color(0, 0, 0),
name: " ",
canvas: shape.canvas,
segmentStyle: shape.connectionType.segmentStyle,
flo_type: shape.connectionType.type
});
connection.setSrcDecorator(new PMUI.draw.ConnectionDecorator({
width: 11,
height: 11,
canvas: canvas,
decoratorPrefix: (typeof shape.connectionType.srcDecorator !== 'undefined'
&& shape.connectionType.srcDecorator !== null) ?
shape.connectionType.srcDecorator : "mafe-decorator",
decoratorType: "source",
parent: connection
}));
connection.setDestDecorator(new PMUI.draw.ConnectionDecorator({
width: 11,
height: 11,
canvas: canvas,
decoratorPrefix: (typeof shape.connectionType.destDecorator !== 'undefined'
&& shape.connectionType.destDecorator !== null) ?
shape.connectionType.destDecorator : "mafe-decorator",
decoratorType: "target",
parent: connection
}));
connection.canvas.commandStack.add(new PMUI.command.CommandConnect(connection));
//connect the two ports
connection.connect();
connection.setSegmentMoveHandlers();
//add the connection to the canvas, that means insert its html to
// the DOM and adding it to the connections array
canvas.addConnection(connection);
// Filling PMFlow fields
connection.setTargetShape(endPort.parent);
connection.setOriginShape(sourcePort.parent);
// now that the connection was drawn try to create the intersections
connection.checkAndCreateIntersectionsWithAll();
//attaching port listeners
sourcePort.attachListeners(sourcePort);
endPort.attachListeners(endPort);
// finally trigger createEvent
canvas.triggerCreateEvent(connection, []);
} else {
connection = shape.canvas.currentConnection;
if (shape.canvas.dragConnectHandlers.get(0).id === id) {
port = shape.canvas.dragConnectHandlers.get(0).relativeShape;
targetShape = shape.canvas.dragConnectHandlers.get(1).relativeShape.parent;
sourceShape = shape;
} else if (shape.canvas.dragConnectHandlers.get(1).id === id) {
port = shape.canvas.dragConnectHandlers.get(1).relativeShape;
sourceShape = shape.canvas.dragConnectHandlers.get(0).relativeShape.parent;
targetShape = shape;
} else {
port = null;
}
originalType = connection.flo_type;
validationResult = PMDesigner.connectValidator.isValid(sourceShape, targetShape, connection);
if (!validationResult.result) {
//show invalid message
PMDesigner.msgFlash(validationResult.msg, document.body, 'info', 3000, 5);
return false;
}
if (originalType !== 'DEFAULT' && originalType !== targetShape.connectionType.type) {
PMDesigner.msgFlash('Invalid connection type'.translate(), document.body, 'info', 3000, 5);
targetShape.connectionType.type = originalType;
return false;
}
command = new PMCommandReconnect(port, {
shape: shape,
x: ui.offset.left - shape.canvas.getX() - shape.getAbsoluteX() + shape.canvas.getLeftScroll(),
y: ui.offset.top - shape.canvas.getY() - shape.getAbsoluteY() + shape.canvas.getTopScroll()
});
canvas.commandStack.add(command);
command.execute();
canvas.currentConnection = connection;
canvas.triggerPortChangeEvent(port);
$(canvas.connectionSegment.getHTML()).remove();
canvas.connectionSegment = null;
connection.showPortsAndHandlers();
canvas.isDraggingConnectHandler = false;
canvas.hideDropConnectHandlers();
}
return false;
};
};
var PMShape = function (options) {
PMUI.draw.CustomShape.call(this, options);
this.extended = null;
this.extendedType = null;
this.relationship = null;
this.midPointArray = [];
this.htmlPorts = null;
this.hasConnectHandlers = false;
/**
* Stores the label object used to show into the canvas
* @type {Object}
* @private
*/
this.label = this.labels.get(0);
this.diffXMidPoint = [-1, -4, -1, 4];
this.diffYMidPoint = [4, -1, -4, -1];
this.focusLabel = false;
/**
* Array of markers added to this activity
* @type {Array}
*/
this.markersArray = new PMUI.util.ArrayList();
this.validatorMarker = null;
this.errors = new PMUI.util.ArrayList();
this.businessObject = {};
/**
* Connections going out from this element.
* @type {Array}
*/
this.outgoingConnections = null;
/**
* Connections going to this element.
* @type {Array}
*/
this.incomingConnections = null;
PMShape.prototype.init.call(this, options);
};
PMShape.prototype = new PMUI.draw.CustomShape();
PMShape.prototype.type = 'PMShape';
PMShape.prototype.pmConnectionDropBehavior = null;
PMShape.prototype.pmContainerDropBehavior = null;
PMShape.prototype.supportedArray = [];
PMShape.prototype.init = function (options) {
var defaults = {
extended: {},
relationship: {},
focusLabel: false
};
if (options) {
jQuery.extend(true, defaults, options);
this.outgoingConnections = new PMUI.util.ArrayList();
this.incomingConnections = new PMUI.util.ArrayList();
this.setExtended(defaults.extended)
.setExtendedType(defaults.extendedType)
.setRelationship(defaults.relationship)
.setIncomingConnections(defaults.incomingConnections)
.setOutgoingConnections(defaults.outgoingConnections);
if (defaults.markers) {
this.addMarkers(defaults.markers, this);
}
if (defaults.validatorMarker) {
this.addValidatorMarkers(defaults.validatorMarker, this);
}
if (defaults.corona) {
this.setCorona(defaults.corona, this.getEspecificType(defaults));
}
this.focusLabel = defaults.focusLabel;
}
};
/**
* Sets the label element
* @param {String} value
* @return {*}
*/
PMShape.prototype.setName = function (value) {
if (this.label) {
this.label.setMessage(value);
}
return this;
};
/**
* Returns the label text
* @return {String}
*/
PMShape.prototype.getName = function () {
var text = "";
if (this.label) {
text = this.label.getMessage();
}
return text;
};
PMShape.prototype.setExtendedType = function (type) {
this.extendedType = type;
return this;
};
PMShape.prototype.getDataObject = function () {
return {};
};
PMShape.prototype.setRelationship = function (relationship) {
this.relationship = relationship;
return this;
};
PMShape.prototype.addRelationship = function (object) {
if (typeof object === "object") {
jQuery.extend(true, this.relationship, object);
}
return this;
};
PMShape.prototype.setExtended = function (extended) {
var ext;
ext = (typeof extended === 'object') ? extended : {};
this.extended = ext;
return this;
};
PMShape.prototype.getExtendedObject = function () {
this.extended = {
extendedType: this.extendedType
};
return this.extended;
};
PMShape.prototype.getMarkers = function () {
return this.markersArray;
};
/**
* Factory method for drop behaviors.
* @param {String} type
* @param {Array} selectors An array in which each element is a valid JQuery selector to specify the accepted elements by
* the drop operation.
* @returns {*}
*/
PMShape.prototype.dropBehaviorFactory = function (type, selectors) {
if (type === 'pmconnection') {
if (!this.pmConnectionDropBehavior) {
this.pmConnectionDropBehavior = new PMConnectionDropBehavior(selectors);
}
return this.pmConnectionDropBehavior;
} else if (type === 'pmcontainer') {
if (!this.pmContainerDropBehavior) {
this.pmContainerDropBehavior = new PMContainerDropBehavior(selectors);
}
return this.pmContainerDropBehavior;
} else {
return PMUI.draw.CustomShape.prototype.dropBehaviorFactory.call(this, type, selectors);
}
};
PMShape.prototype.setDragBehavior = function (obj) {
var factory = new PMUI.behavior.BehaviorFactory({
products: {
"pmsegment": PMSegmentDragBehavior,
"customshapedrag": PMCustomShapeDragBehavior,
"regulardrag": PMUI.behavior.RegularDragBehavior,
"connectiondrag": PMUI.behavior.ConnectionDragBehavior,
"connection": PMUI.behavior.ConnectionDragBehavior,
"nodrag": PMUI.behavior.NoDragBehavior
},
defaultProduct: "nodrag"
});
this.drag = factory.make(obj);
if (this.html && this.drag) {
this.drag.attachDragBehavior(this);
}
if (this.canvas) {
this.canvas.hideDragConnectHandlers();
}
return this;
};
/**
* This function will attach all the listeners corresponding to the CustomShape
* @chainable
*/
PMShape.prototype.attachListeners = function () {
var that = this;
if (this.html === null) {
return this;
}
if (!this.canvas.readOnly) {
var $customShape = $(this.html).click(this.onClick(this));
$customShape.on("mousedown", this.onMouseDown(this));
$customShape.mouseup(this.onMouseUp(this));
$customShape.mouseover(this.onMouseOver(this));
$customShape.mouseout(this.onMouseOut(this));
$customShape.dblclick(this.onDblClick(this));
$customShape.on("contextmenu", function (e) {
e.preventDefault();
});
this.updateBehaviors();
} else {
if (this.canvas.hasClickEvent) {
var $customShape = $(this.html).click(function (e) {
if (that.hasClick) {
that.hasClick(e);
}
});
this.updateBehaviors();
}
}
return this;
};
PMShape.prototype.showConnectDropHelper = function (i, customShape) {
var connectHandler, x, y;
connectHandler = customShape.canvas.dropConnectHandlers.get(i);
connectHandler.setDimension(18 * customShape.canvas.getZoomFactor(), 18 * customShape.canvas.getZoomFactor());
x = customShape.getAbsoluteX() - customShape.canvas.getAbsoluteX() + customShape.xMidPoints[i] - connectHandler.width / 2 - 1;
y = customShape.getAbsoluteY() - customShape.canvas.getAbsoluteY() + customShape.yMidPoints[i] - connectHandler.height / 2 - 1;
if (customShape.parent.type !== 'PMCanvas') {
x += 3;
y += 2;
}
connectHandler.setPosition(x, y);
connectHandler.relativeShape = customShape;
connectHandler.attachDrop();
connectHandler.setVisible(true);
connectHandler.setZOrder(103);
};
/**
* Handler for the onmousedown event, changes the draggable properties
* according to the drag behavior that is being applied
* @param {PMUI.draw.CustomShape} CustomShape
* @returns {Function}
*/
PMShape.prototype.onMouseDown = function (customShape) {
return function (e, ui) {
var canvas = customShape.canvas;
if (customShape.getType() === 'PMPool' || customShape.getType() === 'PMLane') {
canvas.cancelConnect();
}
if (e.which === 3) {
$(canvas.html).trigger("rightclick", [e, customShape]);
} else {
canvas.hideDragConnectHandlers();
canvas.hideDropConnectHandlers();
customShape.dragType = 2;
if (customShape.dragType === customShape.DRAG) {
if (!(customShape.getType() === 'PMEvent' && customShape.getEventType() === 'BOUNDARY')) {
customShape.setDragBehavior("customshapedrag");
}
} else if (customShape.dragType === customShape.CONNECT) {
} else {
customShape.setDragBehavior("nodrag");
}
}
customShape.dragging = true;
e.stopPropagation();
};
};
/**
* @event mouseup
* Moused up callback fired when the user mouse ups on the `shape`
* @param {PMUI.draw.Shape} shape
*/
PMShape.prototype.onMouseUp = function (customShape) {
return function (e, ui) {
e.preventDefault();
if (customShape.canvas.canConnect
&& customShape.canvas.connectStartShape.getID() !== customShape.getID()
&& customShape.getType() !== 'PMPool'
&& customShape.getType() !== 'PMLane') {
customShape.canvas.connectProcedure(customShape, e);
}
if (customShape.canvas.canCreateShape
&& customShape.canvas.connectStartShape.getID() !== customShape.getID()
&& (customShape.getType() === 'PMPool' || customShape.getType() === 'PMLane')) {
customShape.canvas.manualCreateShape(customShape, e);
}
};
};
PMShape.prototype.showConnectDragHelpers = function (i, shape) {
var y, x, connectHandler;
connectHandler = shape.canvas.dragConnectHandlers.get(i);
connectHandler.setDimension(15 * shape.canvas.getZoomFactor(), 15 * shape.canvas.getZoomFactor());
x = shape.getAbsoluteX() - shape.canvas.getAbsoluteX() + shape.xMidPoints[i] - connectHandler.width / 2 - 1;
y = shape.getAbsoluteY() - shape.canvas.getAbsoluteY() + 1 + shape.yMidPoints[i] - connectHandler.height / 2 - 1;
if (shape.parent.type !== 'PMCanvas') {
x += 3;
y += 2;
}
connectHandler.setPosition(x, y);
connectHandler.setVisible(true);
connectHandler.relativeShape = shape;
connectHandler.attachListeners();
};
PMShape.prototype.showAllConnectDragHelpers = function () {
var shape = this, i, connectHandler;
if (shape.canvas.isDragging || shape.canvas.currentLabel || shape.entered || shape.canvas.isResizing || PMUI.isCtrl) {
shape.canvas.hideDragConnectHandlers();
return;
}
if (!shape.canvas.isDraggingConnectHandler && !shape.dragging && !shape.canvas.currentSelection.find('id', shape.id) && !shape.canvas.currentConnection && !shape.canvas.isMouseDown) {
if (shape.extendedType === "TEXT_ANNOTATION") {
shape.canvas.hideDragConnectHandlers();
shape.showConnectDragHelpers(3, shape);
for (i = 0; i < shape.canvas.dragConnectHandlers.getSize(); i += 1) {
connectHandler = shape.canvas.dragConnectHandlers.get(i);
connectHandler.relativeShape = shape;
shape.canvas.hightLightShape = shape;
connectHandler.attachListeners();
}
} else {
if (shape.extendedType !== "H_LABEL" && shape.extendedType !== "V_LABEL"
&& shape.extendedType !== "LANE" && shape.extendedType !== "POOL"
&& shape.extendedType !== "GROUP") {
shape.canvas.hideDragConnectHandlers();
shape.canvas.hightLightShape = shape;
for (i = 0; i < 4; i += 1) {
shape.showConnectDragHelpers(i, shape);
}
shape.canvas.emptyCurrentSelection();
}
}
}
};
PMShape.prototype.onClick = function (customShape) {
return function (e) {
var isCtrl = false,
canvas = customShape.canvas,
currentSelection = canvas.currentSelection,
currentLabel = canvas.currentLabel;
//hide all coronas
customShape.canvas.hideAllCoronas();
if (e.ctrlKey) {
isCtrl = true;
}
// hide the current connection if there was one
customShape.canvas.hideCurrentConnection();
if (e.which === 3) {
e.preventDefault();
// trigger right click
customShape.canvas.triggerRightClickEvent(customShape);
} else {
if (!customShape.wasDragged) {
// if the custom shape was not dragged (this var is set to true
// in custom_shape_drag_behavior >> onDragEnd)
if (isCtrl) {
if (currentSelection.contains(customShape)) {
// remove from the current selection
canvas.removeFromSelection(customShape);
} else {
// add to the current selection
canvas.addToSelection(customShape);
}
} else {
canvas.emptyCurrentSelection();
canvas.addToSelection(customShape);
if (!customShape.canvas.canConnect) {
if (customShape.canvas.currentLabel === null && customShape.corona) {
customShape.corona.show();
}
}
canvas.coronaShape = customShape;
}
}
if (!currentSelection.isEmpty()) {
canvas.triggerSelectEvent(currentSelection.asArray());
}
}
if (this.helper) {
$(this.helper.html).remove();
}
customShape.wasDragged = false;
e.stopPropagation();
};
};
PMShape.prototype.onDblClick = function (customShape) {
return function (e) {
customShape.canvas.hideAllFocusLabels();
customShape.label.getFocus();
e.preventDefault();
e.stopPropagation();
};
};
PMShape.prototype.onMouseOver = function (customShape) {
return function (e, ui) {
var layer,
canConnect = true;
if (customShape.canvas.canConnect
&& customShape.canvas.connectStartShape.getID() !== customShape.getID()
&& customShape.getType() !== 'PMPool'
&& customShape.getType() !== 'PMLane') {
//validate if can connect green, else is red
layer = customShape.getLayers().find('layerName', 'second-layer');
if (layer) {
layer.setVisible(true);
if (!PMDesigner.connectValidator.isValid(customShape.canvas.connectStartShape, customShape).result) {
canConnect = false;
}
layer.removeCSSClasses(['mafe-can-not-connect-layer', 'mafe-can-connect-layer']);
if (canConnect) {
layer.addCSSClasses(['mafe-can-connect-layer']);
} else {
layer.addCSSClasses(['mafe-can-not-connect-layer']);
}
}
}
e.preventDefault();
e.stopPropagation();
};
};
PMShape.prototype.onMouseOut = function (customShape) {
var that = this;
return function (e, ui) {
var layer;
customShape.dragging = false;
e.stopPropagation();
layer = customShape.getLayers().find('layerName', 'second-layer');
if (layer) {
layer.setVisible(false);
}
};
};
/**
* Overwrite the parent function to set the dimension
* @param {Number} x
* @param {Number} y
* @return {*}
*/
PMShape.prototype.setDimension = function (x, y) {
var factor = 1;
PMUI.draw.CustomShape.prototype.setDimension.call(this, x, y);
if (this.getType() === 'PMEvent' || this.getType() === 'PMGateway' || this.getType() === 'PMData') {
factor = 3;
}
if (this.label) {
//validation for vertical labels case pool and lanes
if (this.getType() === 'PMPool' || this.getType() === 'PMLane') {
this.label.updateDimension(false);
} else {
this.label.setDimension((this.zoomWidth * 0.9 * factor) / this.canvas.zoomFactor,
this.label.height);
this.label.setLabelPosition(this.label.location, this.label.diffX, this.label.diffY);
this.label.updateDimension(false);
}
}
if (this.getType() === 'PMPool') {
this.paint();
}
return this;
};
/**
* Creates a drag helper for drag and drop operations for the helper property
* in jquery ui draggable
* @returns {String} html
*/
PMShape.prototype.createDragHelper = function () {
var html = document.createElement("div");
html.style.width = 8 + "px";
html.style.height = 8 + "px";
html.style.borderRadius = "5px";
html.style.marginTop = "-5px";
html.style.marginLeft = "-5px";
html.style.backgroundColor = "rgb(92, 156, 204)";
html.style.zIndex = 2 * PMUI.draw.Shape.prototype.MAX_ZINDEX;
html.id = "drag-helper";
html.className = "drag-helper";
return html;
};
PMShape.prototype.getContextMenu = function () {
return {};
};
PMShape.prototype.getHTMLPorts = function () {
return this.htmlPorts;
};
PMShape.prototype.updatePropertiesHTMLPorts = function () {
var items = jQuery(this.htmlPorts).children(), k,
point = this.midPointArray;
for (k = 0; k < items.length; k += 1) {
items[k].style.left = point[k].x + "px";
items[k].style.top = point[k].y + "px";
}
return this;
};
/**
* Adds markers to the arrayMarker property
* @param {Array} markers
* @param {Object} parent
* @return {*}
*/
PMShape.prototype.addMarkers = function (markers, parent) {
var newMarker, i, factoryMarker;
if (jQuery.isArray(markers)) {
for (i = 0; i < markers.length; i += 1) {
factoryMarker = markers[i];
factoryMarker.parent = parent;
factoryMarker.canvas = parent.canvas;
newMarker = new PMMarker(factoryMarker);
this.markersArray.insert(newMarker);
}
}
return this;
};
/**
* Adds markers to the arrayMarker property
* @param {Array} markers
* @param {Object} parent
* @return {*}
*/
PMShape.prototype.addValidatorMarkers = function (marker, parent) {
marker.parent = parent;
marker.canvas = parent.canvas;
this.validatorMarker = new PMVAlidatorMarker(marker);
return this;
};
/**
* Adds a corona to shape
* @param corona
*/
PMShape.prototype.setCorona = function (options, type) {
var self = this,
objectCrown,
typeEspecific = "DEFAULT";
if (this.getType() !== "PMActivity") {
typeEspecific = type;
}
objectCrown = {
parent: self,
parentType: typeEspecific,
canvas: self.canvas
};
$.extend(true, objectCrown, options);
this.corona = new Corona(objectCrown);
return this;
};
PMShape.prototype.updateLabelsPosition = function () {
var i,
label;
for (i = 0; i < this.labels.getSize(); i += 1) {
label = this.labels.get(i);
label.setLabelPosition(label.location, label.diffX, label.diffY);
label.paint();
}
return this;
};
/**
* Paint the shape
*/
PMShape.prototype.paint = function () {
var m, marker, size, width;
PMUI.draw.CustomShape.prototype.paint.call(this);
size = this.markersArray.getSize();
for (m = 0; m < size; m += 1) {
marker = this.markersArray.get(m);
marker.paint();
}
if (this.validatorMarker) {
this.validatorMarker.paint();
}
if (this.corona) {
this.corona.paint();
this.corona.hide();
}
if (this.getType() === 'PMActivity') {
width = this.getWidth() - 20;
this.label.textField.style.width = width + 'px';
}
};
/**
* Extends fixZIndex from shape class
* @chainable
*/
PMShape.prototype.fixZIndex = function (shape, value) {
var i,
port;
PMUI.draw.CustomShape.prototype.fixZIndex.call(this, shape, value);
// force to z-order if container parent is the canvas
for (i = 0; i < shape.ports.getSize(); i += 1) {
port = shape.ports.get(i);
if (port.connection.getSrcPort().getParent().getParent().getType() === 'PMCanvas' &&
port.connection.getDestPort().getParent().getParent().getType() === 'PMCanvas') {
port.connection.setZOrder(1);
}
}
};
/**
* Extend applyZoom of CustomShape for apply Zoom into Markers
* @return {*}
*/
PMShape.prototype.applyZoom = function () {
var i, marker;
PMUI.draw.CustomShape.prototype.applyZoom.call(this);
for (i = 0; i < this.markersArray.getSize(); i += 1) {
marker = this.markersArray.get(i);
marker.applyZoom();
}
if (this.validatorMarker) {
this.validatorMarker.applyZoom();
}
return this;
};
/**
* Set flow as a default and update the other flows
* @param {String} destID
* @returns {AdamShape}
*/
PMShape.prototype.setDefaultFlow = function (floID) {
var i,
port,
connection;
for (i = 0; i < this.getPorts().getSize(); i += 1) {
port = this.getPorts().get(i);
connection = port.connection;
this.updateDefaultFlow(0);
if (connection.srcPort.parent.getID() === this.getID()) {
if (connection.getID() === floID) {
this.updateDefaultFlow(floID);
connection.setFlowCondition("");
connection.changeFlowType('default');
connection.setFlowType("DEFAULT");
} else if (connection.getFlowType() === 'DEFAULT') {
connection.changeFlowType('sequence');
connection.setFlowType("SEQUENCE");
}
}
}
return this;
};
PMShape.prototype.hideAllChilds = function () {
var i,
child,
j,
flow,
arrayFlow = {};
for (i = 0; i < this.getChildren().getSize(); i += 1) {
child = this.getChildren().get(i);
child.hideElement();
}
this.canvas.hideFlowRecursively(this);
};
PMShape.prototype.showAllChilds = function () {
var i, child;
for (i = 0; i < this.getChildren().getSize(); i += 1) {
child = this.getChildren().get(i);
child.showElement();
}
};
PMShape.prototype.hideElement = function () {
this.html.style.visibility = 'hidden';
return this;
};
PMShape.prototype.showElement = function () {
this.html.style.visibility = 'visible';
return this;
};
PMShape.prototype.getBpmnElementType = function () {
var map = {
'TASK': 'bpmn:Task',
'START': 'bpmn:StartEvent',
'END': 'bpmn:EndEvent',
'EXCLUSIVE': 'bpmn:ExclusiveGateway',
'INCLUSIVE': 'bpmn:InclusiveGateway',
'PARALLEL': 'bpmn:ParallelGateway',
'COMPLEX': 'bpmn:ComplexGateway',
'EVENTBASED': 'bpmn:EventBasedGateway',
'SUB_PROCESS': 'bpmn:SubProcess',
'INTERMEDIATE': 'bpmn:IntermediateCatchEvent',
'BOUNDARY': 'bpmn:BoundaryEvent',
'TEXT_ANNOTATION': 'bpmn:TextAnnotation',
'GROUP': 'bpmn:Group',
'PARTICIPANT': 'bpmn:Participant',
'POOL': 'bpmn:Participant',
'LANE': 'bpmn:Lane',
'DATASTORE': 'bpmn:DataStore'
};
if (this.evn_type === 'INTERMEDIATE' && this.evn_behavior === 'THROW') {
return 'bpmn:IntermediateThrowEvent';
} else {
return map[this.extendedType];
}
};
PMShape.prototype.createWithBpmn = function (bpmnElementType, name) {
var businessObject = {};
businessObject.elem = PMDesigner.bpmnFactory.create(bpmnElementType, {
id: 'el_' + this.id,
name: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : ""
});
if (!businessObject.di) {
if (this.type === 'PMParticipant' || this.type === 'PMPool' || this.type === 'PMLane') {
businessObject.di = PMDesigner.bpmnFactory.createDiShape(businessObject.elem, {}, {
id: 'di_' + businessObject.elem.id,
isHorizontal: true
});
} else {
businessObject.di = PMDesigner.bpmnFactory.createDiShape(businessObject.elem, {}, {
id: 'di_' + businessObject.elem.id
});
}
}
this[name] = businessObject;
};
PMShape.prototype.createHandlers = function (type, number, resizableStyle, nonResizableStyle) {
var i;
if (type === "Rectangle") {
//First determine how many ResizeHandlers we are to create
if (!number || (number !== 8 &&
number !== 4 && number !== 0)) {
number = 4;
}
//Then insert the corners first
for (i = 0; i < number && i < 4; i += 1) {
this.cornerResizeHandlers.insert(
new PMUI.draw.ResizeHandler({
parent: this,
zOrder: PMUI.util.Style.MAX_ZINDEX + 23,
representation: new PMUI.draw.Rectangle(),
orientation: this.cornersIdentifiers[i],
resizableStyle: resizableStyle,
nonResizableStyle: nonResizableStyle
})
);
}
//subtract 4 just added resize points to the total
number -= 4;
//add the rest to the mid list
for (i = 0; i < number; i += 1) {
this.midResizeHandlers.insert(
new PMUI.draw.ResizeHandler({
parent: this,
zOrder: PMUI.util.Style.MAX_ZINDEX + 23,
representation: new PMUI.draw.Rectangle(),
orientation: this.midPointIdentifiers[i],
resizableStyle: resizableStyle,
nonResizableStyle: nonResizableStyle
})
);
}
}
return this;
};
/**
* Recursive method to get correct parent busines object
* @param root
* @returns {PMPool}
*/
PMShape.prototype.getPoolParent = function (root) {
while (root.getType() !== 'PMPool') {
root = root.parent;
}
return root;
};
/**
*
* @param businessObject
* @param parentBusinessObject
*/
PMShape.prototype.updateShapeParent = function (businessObject, parentBusinessObject) {
var pool,
parentDi,
parentBusinessObjectAux = {};
parentDi = parentBusinessObject && parentBusinessObject.di;
//regular parent change
if (parentBusinessObject.elem &&
parentBusinessObject.elem.$type === 'bpmn:Lane') {
//text annotation Data store Data object into lane
if (!businessObject.elem.$lane && parentBusinessObject.elem) {
businessObject.elem.$lane = parentBusinessObject.elem;
}
if (businessObject.elem.$type !== 'bpmn:TextAnnotation'
&& businessObject.elem.$type !== 'bpmn:DataStoreReference'
&& businessObject.elem.$type !== 'bpmn:DataObjectReference') {
this.parent.updateLaneSetParent(businessObject, parentBusinessObject);
}
pool = this.getPoolParent(this.parent);
parentBusinessObjectAux = pool.businessObject;
parentDi = parentBusinessObjectAux && parentBusinessObjectAux.di;
this.updateSemanticParent(businessObject, parentBusinessObjectAux);
} else {
this.updateSemanticParent(businessObject, parentBusinessObject);
}
this.updateDiParent(businessObject.di, parentDi);
};
PMShape.prototype.updateSemanticParent = function (businessObject, newParent) {
var children;
if (businessObject.elem.$parent === newParent.elem) {
return;
}
if (businessObject.elem.$parent) {
// remove from old parent
children = businessObject.elem.$parent.get('flowElements');
CollectionRemove(children, businessObject.elem);
}
if (!newParent.elem) {
businessObject.elem.$parent = null;
} else {
// add to new parent
children = newParent.elem.get('flowElements');
children.push(businessObject.elem);
businessObject.elem.$parent = newParent.elem;
}
};
PMShape.prototype.updateDiParent = function (di, parentDi) {
var planeElements;
if (parentDi && !parentDi.$instanceOf('bpmndi:BPMNPlane')) {
parentDi = parentDi.$parent;
}
if (di.$parent === parentDi) {
return;
}
planeElements = (parentDi || di.$parent).get('planeElement');
if (parentDi) {
planeElements.push(di);
di.$parent = parentDi;
} else {
CollectionRemove(planeElements, di);
di.$parent = null;
}
};
PMShape.prototype.updateBounds = function (di) {
var bounds = this.type === 'label' ? this._getLabel(di).bounds : di.bounds,
x = this.getX(), y = this.getY(),
parent = this.parent;
while (parent.type !== 'PMCanvas') {
x = parent.getX() + x;
y = parent.getY() + y;
parent = parent.parent;
}
_.extend(bounds, {
x: x,
y: y,
width: this.width,
height: this.height
});
};
PMShape.prototype._getLabel = function (di) {
if (!di.label) {
di.label = PMDesigner.bpmnFactory.createDiLabel();
}
return di.label;
};
PMShape.prototype.createBpmn = function (type) {
if (!this.businessObject.elem && !(this instanceof PMUI.draw.MultipleSelectionContainer)) {
this.createWithBpmn(type, 'businessObject');
}
this.updateBounds(this.businessObject.di);
if (this.parent.getType() === 'PMCanvas' && !this.parent.businessObject.di) {
this.canvas.createBPMNDiagram();
}
if (this.parent.businessObject.elem) {
this.updateShapeParent(this.businessObject, this.parent.businessObject);
} else {
this.parent.createBusinesObject();
this.updateShapeParent(this.businessObject, this.parent.businessObject);
}
};
PMShape.prototype.removeBpmn = function () {
var parentShape = this.parent;
var businessObject = this.businessObject,
parentBusinessObject = parentShape && parentShape.businessObject.elem,
parentDi = parentBusinessObject && parentBusinessObject.di;
if (this.parent.businessObject.elem
&& this.parent.businessObject.elem.$type === 'bpmn:Lane') {
this.parent.updateLaneSetParent(businessObject, {elem: null});
} else if (this.parent.type === 'PMCanvas') {
this.parent.updateCanvasProcess();
}
this.updateSemanticParent(businessObject, {elem: null});
this.updateDiParent(businessObject.di);
};
PMShape.prototype.updateBpmn = function () {
this.updateBounds(this.businessObject.di);
if (!this.parent.businessObject.elem) {
this.parent.createBusinesObject();
}
this.updateShapeParent(this.businessObject, this.parent.businessObject);
};
PMShape.prototype.updateLaneSetParent = function (businessObject, newParent) {
if (businessObject.elem.$lane) {
children = businessObject.elem.$lane.get('flowNodeRef');
CollectionRemove(children, businessObject.elem);
}
if (!newParent.elem) {
} else {
// add to new parent
children = newParent.elem.get('flowNodeRef');
children.push(businessObject.elem);
businessObject.elem.$lane = newParent.elem;
}
};
PMShape.prototype.setBPPMName = function (name) {
if (this.businessObject && this.businessObject.elem) {
this.businessObject.elem.name = name;
}
if (this.participantObject && this.participantObject.elem) {
this.participantObject.elem.name = name;
}
};
PMShape.prototype.isSupported = function () {
return true;
};
/**
* Get the number total of Errors and Warnings.
* @returns {*}
*/
PMShape.prototype.getNumErrors = function () {
var numErrors = 0;
if (this.errors) {
numErrors = this.errors.getSize();
}
return numErrors;
};
/**
* Get Array of Errors.
* @returns {*|Array}
*/
PMShape.prototype.getArrayErrors = function () {
var arrayErrors = [];
if (this.errors) {
arrayErrors = this.errors.asArray();
}
return arrayErrors;
};
/**
* Add new Error to Array of Errors.
* @param error
*/
PMShape.prototype.addErrorLog = function (error) {
error.name = this.getName();
this.errors.insert(error);
error.id = this.getID();
PMDesigner.validTable.row.add([
null,
error.id,
error.severity,
error.name,
error.type,
error.description
]
).draw();
};
/**
* Validate the Number of Errors of type Warning.
* @param arrayErrors
* @returns {Boolean}
*/
PMShape.prototype.validateWarning = function (arrayErrors) {
var arrayLength,
sw = false,
i = 0;
if (_.isArray(arrayErrors)) {
sw = true;
arrayLength = arrayErrors.length;
while (arrayLength > 0) {
if (arrayErrors[i].severity !== "Warning") {
sw = false;
arrayLength = 0;
}
arrayLength -= 1;
i += 1;
}
}
return sw;
};
/**
* Set the severity Error (Error, Warning).
* @param typeString
*/
PMShape.prototype.setTypeErrors = function (typeString) {
var styleMarker;
if (this.validatorMarker.styleMarker) {
styleMarker = this.validatorMarker.styleMarker;
}
styleMarker.setTypeMarker(typeString);
};
/**
* Validate connections between shapes.
* @returns {boolean}
* @constructor
*/
PMShape.prototype.ValidateConnections = function () {
var ports = this.getPorts().asArray(),
connection,
segmentStyle,
i,
shapeSrc,
shapeDest,
isValid = true,
maxPorts = ports.length;
for (i = 0; i < maxPorts; i += 1) {
connection = ports[i].getConnection();
segmentStyle = connection.getSegmentStyle();
if (connection && segmentStyle === "regular") {
shapeSrc = connection.getSrcPort().getParent();
shapeDest = connection.getDestPort().getParent();
if (!this.ValidateContainer(shapeSrc.getParent(), shapeDest.getParent())) {
isValid = false;
}
}
}
return isValid;
};
/**
* Validate the container between two shapes.
* @param shapeSrc
* @param shapeDest
* @returns {boolean}
* @constructor
*/
PMShape.prototype.ValidateContainer = function (shapeSrc, shapeDest) {
var equLevel = true;
if (shapeSrc.getType() === shapeDest.getType()) {
switch (shapeSrc.getType()) {
case "PMPool":
equLevel = (shapeSrc.id !== shapeDest.id) ? false : true;
break;
case "PMLane":
equLevel = (this.getPoolParent(shapeSrc).id !== this.getPoolParent(shapeDest).id) ? false : true;
break;
default:
equLevel = true;
}
} else {
equLevel = false;
}
return equLevel;
};
PMShape.prototype.poolChildConnectionOnResize = function (resizing, root, delta, rootType) {
var i,
port,
child,
connection;
if (root) {
if (this.ports) {
for (i = 0; i < this.ports.getSize(); i += 1) {
port = this.ports.get(i);
connection = port.connection;
this.recalculatePortPosition(port);
connection.disconnect().connect();
if (!this.resizing) {
connection.setSegmentMoveHandlers();
connection.checkAndCreateIntersectionsWithAll();
}
}
}
} else {
if (this.ports) {
this.registerResizeConnection();
}
}
// children
for (i = 0; i < this.children.getSize(); i += 1) {
child = this.children.get(i);
child.setPosition(child.x, child.y);
child.poolChildConnectionOnResize(child.resizing, false, delta, rootType);
}
return this;
};
PMShape.prototype.registerResizeConnection = function () {
var i,
port,
connection;
for (i = 0; i < this.ports.getSize(); i += 1) {
port = this.ports.get(i);
port.setPosition(port.x, port.y);
connection = port.connection;
if (!this.canvas.refreshArray.contains(connection)) {
connection.canvas.refreshArray.insert(connection);
}
}
};
PMShape.prototype.fixConnectionsOnResize = function (resizing, root) {
var i,
port,
child,
connection,
zoomFactor = this.canvas.zoomFactor;
if (root) {
if (this.ports) {
// connections
for (i = 0; i < this.ports.getSize(); i += 1) {
port = this.ports.get(i);
connection = port.connection;
this.recalculatePortPosition(port);
connection.disconnect().connect();
if (!this.resizing) {
connection.setSegmentMoveHandlers();
connection.checkAndCreateIntersectionsWithAll();
}
}
}
} else {
if (this.ports) {
this.registerResizeConnection();
}
}
// children
for (i = 0; i < this.children.getSize(); i += 1) {
child = this.children.get(i);
child.setPosition(child.x, child.y);
child.fixConnectionsOnResize(child.resizing, false);
}
return this;
};
PMShape.prototype.refreshChildrenPositions = function (onCommand, delta) {
var i,
children = this.children,
child;
for (i = 0; i < children.getSize(); i += 1) {
child = children.get(i);
child.setPosition(child.getX(), child.getY());
child.refreshConnections(false, true);
if (onCommand) {
child.refreshAllMovedConnections(false, delta);
}
child.refreshChildrenPositions(onCommand, delta);
}
return this;
};
PMShape.prototype.refreshAllPoolConnections = function (inContainer, delta, rootType) {
var i,
connection,
max;
for (i = 0, max = this.canvas.refreshArray.getSize(); i < max; i += 1) {
connection = this.canvas.refreshArray.get(i);
connection.reconectSwitcher(delta, inContainer, rootType);
}
return this;
};
PMShape.prototype.laneRefreshConnections = function (inContainer, delta, rootType) {
var i,
connection,
max;
for (i = 0, max = this.canvas.refreshArray.getSize(); i < max; i += 1) {
connection = this.canvas.refreshArray.get(i);
connection.reconectSwitcher(delta, inContainer, rootType);
}
return this;
};
PMShape.prototype.refreshAllMovedConnections = function (inContainer, delta, rootType) {
var i,
connection,
ports = this.ports,
port,
max;
for (i = 0, max = ports.getSize(); i < max; i += 1) {
port = ports.get(i);
port.setPosition(port.x, port.y);
connection = port.connection;
if (!this.canvas.connToRefresh.contains(connection)) {
connection.canvas.connToRefresh.insert(connection);
}
}
return this;
};
PMShape.prototype.refreshChildConnections = function (inContainer, delta, rootType) {
var i,
connection,
max;
for (i = 0, max = this.canvas.refreshArray.getSize(); i < max; i += 1) {
connection = this.canvas.refreshArray.get(i);
connection.reconectSwitcher(delta, inContainer, rootType);
}
return this;
};
PMShape.prototype.refreshShape = function () {
PMUI.draw.Shape.prototype.refreshShape.call(this);
this.updatePortsOnZoom();
this.paint();
return this;
};
/**
* Sets the incoming connections for the element.
* @param elements{Array}
* @returns {PMShape}
*/
PMShape.prototype.setIncomingConnections = function(elements){
var i;
if (jQuery.isArray(elements)) {
this.incomingConnections.clear();
for (i = 0; i < elements.length; i += 1) {
this.addIncomingConnection(elements[i]);
}
}
return this;
};
/**
* Add an incoming connection.
* @param element{PMShape}
* @returns {PMShape}
*/
PMShape.prototype.addIncomingConnection = function(element){
this.incomingConnections.insert(element);
return this;
};
/**
* Remove an incoming connection.
* @param element{PMShape}
* @returns {PMShape}
*/
PMShape.prototype.removeIncomingConnection = function(element){
this.incomingConnections.remove(element);
return this;
};
/**
* Return the list of incoming connections.
* @param {...String} [types] Optional, returns only the connections of the specified types.
* @returns {Array}
*/
PMShape.prototype.getIncomingConnections = function(){
var validTypes = [],
i;
if (arguments.length) {
for (i = 0; i < arguments.length; i += 1) {
validTypes.push(arguments[i]);
}
return this.incomingConnections.asArray().filter(function (i) {
return validTypes.indexOf(i.flo_type) >= 0;
});
}
return this.incomingConnections.asArray().slice(0);
};
/**
* Returns the list of the elements connected to this element's incoming connections.
* @param {...String} [connection_types] The incoming elements whose connections are of this specified type, optional.
* @returns {Array|*|{applyDefaultStyles, childOptions, initChildLayout, destroyChildLayout, resizeChildLayout, resizeNestedLayout, resizeWhileDragging, resizeContentWhileDragging, triggerEventsWhileDragging, maskIframesOnResize, useStateCookie, [cookie.autoLoad], [cookie.autoSave], [cookie.keys], [cookie.name], [cookie.domain], [cookie.path], [cookie.expires], [cookie.secure], noRoomToOpenTip, togglerTip_open, togglerTip_closed, resizerTip, sliderTip}}
*/
PMShape.prototype.getIncomingElements = function () {
return this.getIncomingConnections.apply(this, arguments).map(function (i) {
return i.getSrcPort().getParent();
});
};
/**
* Sets all the outgoing connections for the element.
* @param elements{Array}
* @returns {PMShape}
*/
PMShape.prototype.setOutgoingConnections = function(elements){
var i;
if (jQuery.isArray(elements)) {
this.outgoingConnections.clear();
for (i = 0; i < elements.length; i += 1) {
this.addOutgoinConnections(elements[i]);
}
}
return this;
};
/**
* Add an outgoing connection to the element.
* @param element{PMShape}
* @returns {PMShape}
*/
PMShape.prototype.addOutgoingConnection = function(element){
this.outgoingConnections.insert(element);
return this;
};
/**
* Remove an outgoing connection to the element.
* @param element{PMShape}
* @returns {PMShape}
*/
PMShape.prototype.removeOutgoingConnection = function(element){
this.outgoingConnections.remove(element);
return this;
};
/**
* Return the list of outgoing connections.
* @param {...String} [types] Optional, returns only the connections of the specified types.
* @returns {Array}
*/
PMShape.prototype.getOutgoingConnections = function(){
var validTypes = [],
i;
if (arguments.length) {
for (i = 0; i < arguments.length; i += 1) {
validTypes.push(arguments[i]);
}
return this.outgoingConnections.asArray().filter(function (i) {
return validTypes.indexOf(i.flo_type) >= 0;
});
}
return this.outgoingConnections.asArray().slice(0);
};
/**
* Returns a list of the elements connected to the element's outgoing connections.
* @param {...String} [type] Optional, returns only the connections of the specified type.
* @returns {Array}
*/
PMShape.prototype.getOutgoingElements = function (type) {
return this.getOutgoingConnections.apply(this, arguments).map(function (i) {
return i.getDestPort().getParent();
});
};
/**
* Get Especific Type of the Shape or the object parameter
* @param object
* @returns {string}
*/
PMShape.prototype.getEspecificType = function (object) {
var especificType = "DEFAULT",
typeShape = this.getType(),
shape = this;
if (typeof object === "object" && !jQuery.isEmptyObject(object)) {
shape = object;
}
switch (typeShape) {
case "PMActivity":
especificType = shape.act_task_type;
break;
case "PMGateway":
especificType = shape.gat_type;
break;
case "PMEvent":
especificType = shape.evn_type + "_" + shape.evn_marker;
break;
case "PMArtifact":
especificType = shape.art_type;
break;
case "PMData":
especificType = shape.dat_type;
break;
}
return especificType;
};
/**
* @class PMFlow
* Handle the designer flows
*
* @constructor
* Create a new flow object
* @param {Object} options
*/
var PMFlow = function (options) {
PMUI.draw.Connection.call(this, options);
/**
* Unique Idenfier
* @type {String}
*/
this.flo_uid = null;
/**
* Defines the connecion/flow type
* @type {String}
*/
this.flo_type = null;
/**
* Defines the connection/flow name
* @type {String}
*/
this.flo_name = null;
/**
* Unique Identifier of the source shape
* @type {String}
*/
this.flo_element_origin = null;
/**
* Defines the type of shape for the source
* @type {String}
*/
this.flo_element_origin_type = null;
/**
* Unique Identifier of the target shape
* @type {String}
*/
this.flo_element_dest = null;
/**
* Defines the type of shape for the target
* @type {String}
*/
this.flo_element_dest_type = null;
/**
* Defines if the flow was followed inmediately
* @type {Boolean}
*/
this.flo_is_inmediate = null;
/**
* Defines the condition to follow the flow
* @type {String}
*/
this.flo_condition = null;
/**
* X1 Coordinate
* @type {Number}
*/
this.flo_x1 = null;
/**
* Y1 Coordinate
* @type {Number}
*/
this.flo_y1 = null;
/**
* X2 Coordinate
* @type {Number}
*/
this.flo_x2 = null;
/**
* Y2 Coordinate
* @type {Number}
*/
this.flo_y2 = null;
/**
* Array of segments that conform the connection
* @type {Array}
*/
this.flo_state = null;
this.label = null;
this.algorithm = 'manhattan';
PMFlow.prototype.init.call(this, options);
};
/**
* Return all the connections between two elements.
* @param {PMShape} sourceElement The source element from which an outgoing connection will be searched
* @param {PMShape} destElement The destination element the connection must income to.
* @param {Boolean} [ignoreDirection = false] If true, all connections between the two elements will be returned regardless the direction.
* @returns {Boolean}
*/
PMFlow.getConnections = function (sourceElement, destElement, ignoreDirection) {
var result;
result = sourceElement.getOutgoingConnections().filter(function (i) {
return i.getDestPort().getParent() === destElement;
});
if (ignoreDirection) {
result.concat(sourceElement.getIncomingConnections().filter(function (i) {
return i.getSrcPort().getParent === destElement;
}));
}
return result;
};
/**
* Check if there is any connection between two elements.
* @param {PMShape} sourceElement The source element from which an outgoing connection will be searched
* @param {PMShape} destElement The destination element the connection must income to.
* @param {Boolean} [ignoreDirection = false] If true, all connections between the two elements will be searched regardless the direction.
* @returns {Boolean}
*/
PMFlow.existsConnection = function (sourceElement, destElement, ignoreDirection) {
return PMFlow.getConnections(sourceElement, destElement, ignoreDirection).length > 0;
};
PMFlow.prototype = new PMUI.draw.Connection();
/**
* Defines the object type
* @type {String}
*/
PMFlow.prototype.type = "Connection"; //TODO Replace this type by PMFlow when jCore will be updated
/**
* Initialize the object with default values
* @param {Object} options
*/
PMFlow.prototype.init = function (options) {
var defaults = {
flo_type: 'SEQUENCE',
flo_is_inmediate: true,
flo_x1: 0,
flo_y1: 0,
flo_x2: 0,
flo_y2: 0,
name: ''
};
jQuery.extend(true, defaults, options);
this.setFlowType(defaults.flo_type)
.setFlowUid(defaults.flo_uid)
.setIsInmediate(defaults.flo_is_inmediate)
.setOriginPoint(defaults.flo_x1, defaults.flo_y1)
.setTargetPoint(defaults.flo_x2, defaults.flo_y2);
this.setFlowName(defaults.name || '');
this.setFlowOrigin(defaults.flo_element_origin || null, defaults.flo_element_origin_type || null);
this.setFlowTarget(defaults.flo_element_dest || null, defaults.flo_element_dest_type || null);
this.setFlowCondition(defaults.flo_condition || null);
this.setFlowState(defaults.flo_state || null);
};
/**
* Returns the flow's name
* @return {String}
*/
PMFlow.prototype.getName = function () {
return this.flo_name;
};
/**
* Sets the label element
* @param {String} value
* @return {*}
*/
PMFlow.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.flo_name = name;
this.setBPMName(name);
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
/**
* Returns the flow conditions
* @return {String}
*/
PMFlow.prototype.getFlowCondition = function () {
return this.flo_condition;
};
/**
* Defines the unique identiier property
* @param {String} value
* @return {*}
*/
PMFlow.prototype.setFlowUid = function (value) {
this.flo_uid = value;
return this;
};
/**
* Defines the connection type
* @param {String} type
* @return {*}
*/
PMFlow.prototype.setFlowType = function (type) {
this.flo_type = type;
return this;
};
/** Return Flow Type
*
* @returns {String}
*/
PMFlow.prototype.getFlowType = function () {
return this.flo_type;
};
/**
* Sets the inmediately behavior of the connection
* @param {Boolean} value
* @return {*}
*/
PMFlow.prototype.setIsInmediate = function (value) {
this.flo_is_inmediate = value;
return this;
};
/**
* Sets the origin point
* @param {Number} x
* @param {Number} y
* @return {*}
*/
PMFlow.prototype.setOriginPoint = function (x, y) {
this.flo_x1 = x;
this.flo_y1 = y;
return this;
};
/**
* Sets the target point
* @param {Number} x
* @param {Number} y
* @return {*}
*/
PMFlow.prototype.setTargetPoint = function (x, y) {
this.flo_x2 = x;
this.flo_y2 = y;
return this;
};
/**
* Sets the connection label
* @param {String} name
* @return {*}
*/
PMFlow.prototype.setFlowName = function (name) {
this.flo_name = name;
return this;
};
/**
* Set the shape origin using input data
* @param {String} code
* @param {String} type
* @return {*}
*/
PMFlow.prototype.setFlowOrigin = function (code, type) {
this.flo_element_origin = code;
this.flo_element_origin_type = type;
return this;
};
/**
* Set the shape target using input data
* @param {String} code
* @param {String} type
* @return {*}
*/
PMFlow.prototype.setFlowTarget = function (code, type) {
this.flo_element_dest = code;
this.flo_element_dest_type = type;
return this;
};
/**
* Sets the flow conditions
* @param value
* @return {*}
*/
PMFlow.prototype.setFlowCondition = function (value) {
this.flo_condition = value;
return this;
};
/**
* Sets the array of segments that conform the connection
* @param {Array} state
* @return {*}
*/
PMFlow.prototype.setFlowState = function (state) {
this.flo_state = state;
return this;
};
/**
* Sets the origin data from a Shape
* @param {PMShape} shape
* @return {*}
*/
PMFlow.prototype.setOriginShape = function (shape) {
var data;
if (shape instanceof PMShape) {
data = this.getNativeType(shape);
this.flo_element_origin = data.code;
this.flo_element_origin_type = data.type;
}
return this;
};
/**
* Sets the target data from a Shape
* @param {PMShape} shape
* @return {*}
*/
PMFlow.prototype.setTargetShape = function (shape) {
var data;
if (shape instanceof PMShape) {
data = this.getNativeType(shape);
this.flo_element_dest = data.code;
this.flo_element_dest_type = data.type;
}
return this;
};
/**
* Returns the clean object to be sent to the backend
* @return {Object}
*/
PMFlow.prototype.getDataObject = function () {
var typeMap = {
regular: 'SEQUENCE',
segmented: 'MESSAGE',
dotted: 'ASSOCIATION'
},
flo_x1 = 0,
flo_y1 = 0,
flo_x2 = 0,
flo_y2 = 0,
state = this.zoomPoints,
flowElementOrigin,
flowElementDest,
portsOrigin,
portOrigin,
portsDest,
portDest,
k, j,
bpmnMap = {
'PMActivity': 'bpmnActivity',
'PMEvent': 'bpmnEvent',
'PMGateway': 'bpmnGateway',
'PMArtifact': 'bpmnArtifact',
'PMData': 'bpmnData',
'PMParticipant': 'bpmnParticipant'
},
relatedObject;
//For get initial port and end port
flowElementOrigin = this.canvas.items.find("id", this.getSrcPort().parent.id);
relatedObject = flowElementOrigin.relatedObject;
this.evaluateRelatedObject(relatedObject);
if (!flowElementOrigin) {
throw new Error("Element not found!");
}
flowElementDest = this.canvas.items.find("id", this.getDestPort().parent.id);
if (!flowElementDest) {
throw new Error("Element not found!");
}
//Updating the positions, getting the last ports
portsOrigin = flowElementOrigin.relatedObject.getPorts().asArray();
for (k = 0; k < portsOrigin.length; k += 1) {
if (portsOrigin[k].connection) {
if (portsOrigin[k].connection.flo_uid === this.flo_uid) {
portOrigin = portsOrigin[k];
}
}
}
if (!portOrigin) {
portOrigin = {absoluteX: this.flo_x1, absoluteY: this.flo_y1};
}
portsDest = flowElementDest.relatedObject.getPorts().asArray();
for (j = 0; j < portsDest.length; j += 1) {
if (portsDest[j].connection) {
if (portsDest[j].connection.flo_uid === this.flo_uid) {
portDest = portsDest[j];
}
}
}
if (!portDest) {
portDest = {absoluteX: this.flo_x2, absoluteY: this.flo_y2};
}
//get origin and target points from state array
flo_x1 = state[0]['x'];
flo_y1 = state[0]['y'];
flo_x2 = state[state.length - 1]['x'];
flo_y2 = state[state.length - 1]['y'];
return {
flo_uid: this.flo_uid,
flo_type: this.flo_type,
flo_name: this.flo_name,
flo_element_origin: flowElementOrigin.id,
flo_element_origin_type: bpmnMap[flowElementOrigin.type],
flo_element_dest: flowElementDest.id,
flo_element_dest_type: bpmnMap[flowElementDest.type],
flo_is_inmediate: this.flo_is_inmediate,
flo_condition: this.flo_condition,
flo_state: state,
flo_x1: flo_x1,
flo_y1: flo_y1,
flo_x2: flo_x2,
flo_y2: flo_y2
};
};
/**
* evaluates the related object
* @param {relatedObject} shape
* @return {Object}
*/
PMFlow.prototype.evaluateRelatedObject = function (relatedObject) {
var type, gat_direction, extendedType;
if (relatedObject) {
type = relatedObject.getType();
if (type === 'PMGateway') {
gat_direction = relatedObject.gat_direction;
extendedType = relatedObject.extendedType;
if (extendedType === 'EXCLUSIVE' && gat_direction === 'CONVERGING') {
this.changeProperty("flo_condition", true);
}
}
}
return this;
};
/**
* Change the property values if there are
* @param {prop} property
* @param {value} value
* @return {Object}
*/
PMFlow.prototype.changeProperty = function (prop, value) {
if (prop !== undefined && prop !== null) {
this[prop] = value;
} else {
throw new Error("property not exist!");
}
return this;
};
/**
* Converts the type to be sent to backend
* @param {PMShape} shape
* @return {Object}
*/
PMFlow.prototype.getNativeType = function (shape) {
var type,
code;
switch (shape.getType()) {
case 'PMActivity':
type = "bpmnActivity";
code = shape.act_uid;
break;
case 'PMGateway':
type = "bpmnGateway";
code = shape.gat_uid;
break;
case 'PMEvent':
type = 'bpmnEvent';
code = shape.evn_uid;
break;
case 'PMArtifact':
type = "bpmnArtifact";
code = shape.art_uid;
break;
case 'PMData':
type = "bpmnData";
code = shape.dat_uid;
break;
case 'PMParticipant':
type = "bpmnParticipant";
code = shape.dat_uid;
break;
}
return {
"type": type,
"code": code
};
};
PMFlow.prototype.showMoveHandlers = function () {
PMUI.draw.Connection.prototype.showMoveHandlers.call(this);
this.canvas.updatedElement = [{
relatedObject: this
}];
$(this.html).trigger('selectelement');
return this;
};
/**
* Get Segment Width
* @returns {Number}
*/
PMFlow.prototype.getSegmentHeight = function (index) {
if (this.lineSegments.getSize()) {
return Math.abs(this.lineSegments.get(index).endPoint.y
- this.lineSegments.get(index).startPoint.y);
}
return 0;
};
/**
* Get Segment Width
* @returns {Number}
*/
PMFlow.prototype.getSegmentWidth = function (index) {
if (this.lineSegments.getSize()) {
return Math.abs(this.lineSegments.get(index).endPoint.x
- this.lineSegments.get(index).startPoint.x);
}
return 0;
};
/**
* Get Label Coordinates
* @returns {Point}
*/
PMFlow.prototype.getLabelCoordinates = function () {
var x, y, index = 0, diffX, diffY, i, max;
if (this.lineSegments.getSize()) {
max = (this.getSegmentWidth(0) > this.getSegmentHeight(0)) ?
this.getSegmentWidth(0) : this.getSegmentHeight(0);
for (i = 1; i < this.lineSegments.getSize(); i += 1) {
diffX = this.getSegmentWidth(i);
diffY = this.getSegmentHeight(i);
if (diffX > max + 1) {
max = diffX;
index = i;
} else if (diffY > max + 1) {
max = diffY;
index = i;
}
}
diffX = (this.lineSegments.get(index).endPoint.x
- this.lineSegments.get(index).startPoint.x) / 2;
diffY = (this.lineSegments.get(index).endPoint.y
- this.lineSegments.get(index).startPoint.y) / 2;
x = this.lineSegments.get(index).startPoint.x + diffX;
y = this.lineSegments.get(index).startPoint.y + diffY;
} else {
x = this.srcPort.getAbsoluteX();
y = this.srcPort.getAbsoluteY();
}
return new PMUI.util.Point(x, y);
};
/**
* Extended paint connection
* @param {Object} options Configuration options
* @chainable
*/
PMFlow.prototype.paint = function (options) {
PMUI.draw.Connection.prototype.paint.call(this, options);
// force to z-order if container parent is the canvas
if (this.getSrcPort().getParent().getParent().getType() === 'PMCanvas'
&& this.getDestPort().getParent().getParent().getType() === 'PMCanvas') {
this.setZOrder(1);
} else {
this.setZOrder(102);
}
};
/**
* Connects two PM Figures
* @returns {Connection}
*/
PMFlow.prototype.connect = function (options) {
var labelPoint;
PMUI.draw.Connection.prototype.connect.call(this, options);
labelPoint = this.getLabelCoordinates();
this.label = new PMUI.draw.Label({
message: this.getName(),
canvas: this.canvas,
parent: this,
position: {
location: "bottom",
diffX: labelPoint.getX() / this.canvas.zoomFactor,
diffY: labelPoint.getY() / this.canvas.zoomFactor + 10
}
});
this.html.appendChild(this.label.getHTML());
this.label.paint()
this.label.attachListeners();
this.label.setDimension(100, "auto");
this.label.setLabelPosition(this.label.location, this.label.diffX, this.label.diffY);
return this;
};
PMFlow.prototype.changeFlowType = function (type) {
var segmentStyle, destDecorator,
typeMap = {
'default': {
srcPrefix: 'mafe-default',
destPrefix: 'mafe-sequence'
},
'conditional': {
srcPrefix: 'mafe-decorator_conditional',
destPrefix: 'mafe-decorator_default'
},
'sequence': {
srcPrefix: 'mafe-sequence',
destPrefix: 'mafe-sequence'
}
}, srcDecorator;
if (type === 'association') {
segmentStyle = "dotted";
destDecorator = "con-none";
} else {
segmentStyle = "regular";
}
this.setSegmentStyle(segmentStyle);
this.originalSegmentStyle = segmentStyle;
if (type === 'association') {
if (srcDecorator && this.srcDecorator) {
this.srcDecorator
.setDecoratorPrefix(srcDecorator);
} else {
this.srcDecorator
.setDecoratorPrefix("mafe-decorator");
}
this.srcDecorator.paint();
} else {
this.srcDecorator.setDecoratorPrefix(typeMap[type].srcPrefix)
.setDecoratorType("source")
.paint();
this.destDecorator.setDecoratorPrefix(typeMap[type].destPrefix)
.setDecoratorType("target")
.paint();
this.disconnect()
.connect()
.setSegmentMoveHandlers()
.checkAndCreateIntersectionsWithAll();
return this;
}
if (destDecorator && this.srcDecorator) {
this.destDecorator
.setDecoratorPrefix(destDecorator);
} else {
this.destDecorator
.setDecoratorPrefix("mafe-decorator");
}
this.srcDecorator.paint();
this.disconnect();
this.connect();
return this;
};
PMFlow.prototype.saveAndDestroy = function () {
var otherConnection, sizeIntersection, bar;
sizeIntersection = this.intersectionWith.getSize();
PMUI.draw.Connection.prototype.saveAndDestroy.call(this);
bar = this.intersectionWith.asArray().slice();
bar.reverse();
for (i = 0; i < sizeIntersection; i += 1) {
otherConnection = bar[i];
otherConnection
.setSegmentColor(otherConnection.originalSegmentColor, false)
.setSegmentStyle(otherConnection.originalSegmentStyle, false)
.disconnect()
.connect();
otherConnection.setSegmentMoveHandlers();
otherConnection.checkAndCreateIntersectionsWithAll();
}
if (this.getFlowType() === 'DEFAULT') {
this.getSrcPort().getParent().updateDefaultFlow("");
}
this.updateIncomingAndOutgoingConnections("remove");
return;
};
PMFlow.prototype.showPortsAndHandlers = function () {
this.canvas.hideAllCoronas();
this.showMoveHandlers();
this.showPorts();
return this;
};
PMFlow.prototype.showPorts = function () {
var connectHandler,
connectHandler2,
portPoint,
handlerOriginalSize = 15,
handlerDimension = handlerOriginalSize * this.canvas.getZoomFactor();
this.canvas.hideDragConnectHandlers();
portPoint = this.srcPort.getPoint();
connectHandler = this.canvas.dragConnectHandlers.get(0);
connectHandler.setDimension(handlerDimension, handlerDimension);
connectHandler.setPosition(portPoint.x - Math.floor(handlerDimension / 2), portPoint.y - Math.floor(handlerDimension / 2));
connectHandler.setVisible(true);
connectHandler.relativeShape = this.srcPort;
connectHandler.attachListeners();
portPoint = this.destPort.getPoint();
connectHandler2 = this.canvas.dragConnectHandlers.get(1);
connectHandler2.setDimension(handlerDimension, handlerDimension);
connectHandler2.setPosition(portPoint.x - Math.floor(handlerDimension / 2), portPoint.y - Math.floor(handlerDimension / 2));
connectHandler2.setVisible(true);
connectHandler2.relativeShape = this.destPort;
connectHandler2.attachListeners();
return this;
};
PMFlow.prototype.hidePortsAndHandlers = function () {
this.hideMoveHandlers();
this.canvas.hideDragConnectHandlers();
return this
};
PMFlow.prototype.getBpmnElementType = function () {
var map = {
'SEQUENCE': 'bpmn:SequenceFlow',
'ASSOCIATION': 'bpmn:Association',
'MESSAGE': 'bpmn:MessageFlow'
};
var type = map[this.flo_type] || 'bpmn:SequenceFlow';
if (this.flo_type === 'DATAASSOCIATION') {
if (this.flo_element_origin_type === 'bpmnData') {
type = 'bpmn:DataInputAssociation';
} else {
type = 'bpmn:DataOutputAssociation';
}
}
return type;
};
PMFlow.prototype.createWithBpmn = function (bpmnElementType) {
var businessObject = PMDesigner.bpmnFactory.create(bpmnElementType, {
id: 'flo_' + this.id,
name: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : ""
});
businessObject.di = PMDesigner.bpmnFactory.createDiEdge(businessObject, [], {
id: businessObject.id + '_di'
});
this.businessObject = businessObject;
};
PMFlow.prototype.updateConnectionWaypoints = function () {
this.businessObject.di.set('waypoint', PMDesigner.bpmnFactory.createDiWaypoints(this.waypoints));
};
PMFlow.prototype.updateConnection = function (newSource, newTarget) {
var businessObject = this.businessObject,
children;
if (this.flo_type === 'DATAASSOCIATION') {
if (this.flo_element_origin_type === 'bpmnData') {
children = newTarget.elem.get('dataInputAssociations');
CollectionRemove(children, businessObject);
businessObject.sourceRef = [];
if (!children) {
newTarget.elem.dataInputAssociations = [];
newTarget.elem.dataInputAssociations.push(businessObject);
} else {
children.push(businessObject);
}
businessObject.sourceRef.push(newSource.elem);
} else {
children = newSource.elem.get('dataOutputAssociations');
CollectionRemove(children, businessObject);
businessObject.targetRef = [];
newSource.elem.get('dataOutputAssociations').push(businessObject);
businessObject.targetRef = newTarget.elem;
}
} else {
var inverseSet = businessObject.$instanceOf('bpmn:SequenceFlow');
if (businessObject.sourceRef !== newSource.elem) {
if (inverseSet) {
CollectionRemove(businessObject.sourceRef && businessObject.sourceRef.get('outgoing'), businessObject);
if (newSource.elem) {
newSource.elem.get('outgoing').push(businessObject);
}
}
businessObject.sourceRef = newSource.elem;
}
if (businessObject.targetRef !== newTarget.elem) {
if (inverseSet) {
CollectionRemove(businessObject.targetRef && businessObject.targetRef.get('incoming'), businessObject);
if (newTarget.elem) {
newTarget.elem.get('incoming').push(businessObject);
}
}
businessObject.targetRef = newTarget.elem;
}
}
businessObject.di.set('waypoint', PMDesigner.bpmnFactory.createDiWaypoints(this.points));
};
PMFlow.prototype.updateShapeParent = function (businessObject, parentBusinessObject) {
var parentBusinessObjectAux = {};
if (this.flo_type === 'MESSAGE') {
if (this.srcPort.parent.businessObject.elem
&& this.destPort.parent.businessObject.elem
&& this.srcPort.parent.businessObject.elem.$parent.id !== this.destPort.parent.businessObject.elem.$parent.id) {
parentBusinessObjectAux.elem = _.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"});
} else {
if (this.srcPort.parent.type === 'PMParticipant') {
parentBusinessObjectAux.elem = this.srcPort.parent && this.srcPort.parent.participantObject.elem.$parent;
} else if (this.srcPort.parent) {
parentBusinessObjectAux.elem = this.destPort.parent && this.destPort.parent.participantObject.elem.$parent;
}
}
}
if (parentBusinessObjectAux.elem) {
this.updateSemanticParent(businessObject, parentBusinessObjectAux);
} else {
this.updateSemanticParent(businessObject, parentBusinessObject);
}
this.updateDiParent(businessObject.di, parentBusinessObject.di);
};
PMFlow.prototype.updateSemanticParent = function (businessObject, newParent) {
var children;
if (businessObject.$parent === newParent.elem) {
return;
}
if (this.flo_type !== 'DATAASSOCIATION') {
if (this.flo_type === 'MESSAGE') {
//HERE MESSAGE FLOW SET TO COLLABORATIONS
if (businessObject.$parent) {
// remove from old parent
children = businessObject.$parent.get('messageFlows');
CollectionRemove(children, businessObject);
}
if (!newParent.elem) {
businessObject.$parent = null;
} else {
children = newParent.elem.get('messageFlows');
children.push(businessObject);
businessObject.$parent = newParent.elem;
}
} else {
if (businessObject.$parent) {
// remove from old parent
children = businessObject.$parent.get('flowElements');
CollectionRemove(children, businessObject);
}
if (!newParent.elem) {
businessObject.$parent = null;
} else {
// add to new parent
if (newParent.elem.$type === 'bpmn:Lane') {
children = newParent.elem.$parent.$parent.get('flowElements');
} else if (this.getSrcPort().getParent().getType() === 'PMEvent'
&& this.getSrcPort().getParent().getEventType() === 'BOUNDARY') {
children = newParent.elem.$parent.get('flowElements');
} else {
children = newParent.elem.get('flowElements');
}
children.push(businessObject);
businessObject.$parent = newParent.elem;
}
}
}
};
PMFlow.prototype.updateDiParent = function (di, parentDi) {
if (parentDi && !parentDi.$instanceOf('bpmndi:BPMNPlane')) {
parentDi = parentDi.$parent;
}
if (di.$parent === parentDi) {
return;
}
var planeElements = (parentDi || di.$parent).get('planeElement');
if (parentDi) {
planeElements.push(di);
di.$parent = parentDi;
} else {
CollectionRemove(planeElements, di);
}
};
PMFlow.prototype.createBpmn = function (bpmnElementType) {
var newSource, newTarget;
this.createWithBpmn(bpmnElementType);
this.updateShapeParent(this.businessObject, this.srcPort.parent.parent.businessObject);
newSource = this.srcPort.parent && this.srcPort.parent.businessObject;
newTarget = this.destPort.parent && this.destPort.parent.businessObject;
if (this.srcPort.parent.type == 'PMParticipant') {
newSource = this.srcPort.parent && this.srcPort.parent.participantObject;
}
if (this.destPort.parent.type == 'PMParticipant') {
newTarget = this.destPort.parent && this.destPort.parent.participantObject;
}
this.updateConnection(newSource, newTarget);
};
PMFlow.prototype.removeBpmn = function () {
var parentShape,
businessObject,
newSource,
newTarget,
children,
parentBusinessObject,
parentDi;
businessObject = this.businessObject;
this.updateSemanticParent(businessObject, {elem: null});
this.updateDiParent(businessObject.di);
if (this.flo_type !== 'DATAASSOCIATION') {
parentShape = this.parent;
parentBusinessObject = parentShape && parentShape.businessObject;
parentDi = parentBusinessObject && parentBusinessObject.di;
CollectionRemove(businessObject.sourceRef && businessObject.sourceRef.get('outgoing'), businessObject);
CollectionRemove(businessObject.targetRef && businessObject.targetRef.get('incoming'), businessObject);
} else {
newSource = this.srcPort.parent && this.srcPort.parent.businessObject.elem,
newTarget = this.destPort.parent && this.destPort.parent.businessObject.elem;
if (this.flo_element_origin_type === 'bpmnData') {
children = newTarget.get('dataInputAssociations');
CollectionRemove(children, businessObject);
} else {
children = newSource.get('dataOutputAssociations');
CollectionRemove(children, businessObject);
}
}
};
PMFlow.prototype.updateBpmn = function () {
var newSource = this.srcPort.parent && this.srcPort.parent.businessObject,
newTarget = this.destPort.parent && this.destPort.parent.businessObject;
this.updateConnection(newSource, newTarget);
};
PMFlow.prototype.setBPPMName = function (name) {
if (this.businessObject || this.participantObject) {
this.businessObject.name = name;
}
};
/**
* Sets flow name to export as bpmn xml standard
* @param name
*/
PMFlow.prototype.setBPMName = function (name) {
if (this.businessObject) {
this.businessObject.name = name;
}
};
PMFlow.prototype.reconectSwitcher = function (delta, inContainer, rootType) {
var srcElem,
destElem;
//get source and target element
srcElem = this.getSrcPort().parent;
destElem = this.getDestPort().parent;
//verify if is the same process
if (srcElem.businessObject.elem
&& destElem.businessObject.elem
&& srcElem.businessObject.elem.$parent.id === destElem.businessObject.elem.$parent.id) {
if (rootType && rootType === 'PMLane') {
this.reconnectManhattah(inContainer);
} else {
this.reconnectUser(delta, inContainer);
}
} else {
this.reconnectManhattah(inContainer);
}
this.setSegmentMoveHandlers();
this.checkAndCreateIntersectionsWithAll();
this.canvas.triggerUserStateChangeEvent(this);
};
/**
* updates the list of items related input and output
* @param action {String}, You can have two values, "remove" or "create"
* @returns {PMFlow}
*/
PMFlow.prototype.updateIncomingAndOutgoingConnections = function(action){
var source, destiny, sourceShape, destinyShape;
source = this.srcPort;
destiny = this.destPort;
sourceShape = source.parent;
destinyShape = destiny.parent;
if (sourceShape && destinyShape){
if (action === "remove"){
sourceShape.removeOutgoingConnection(this);
destinyShape.removeIncomingConnection(this);
} else if (action === "create"){
sourceShape.addOutgoingConnection(this);
destinyShape.addIncomingConnection(this);
}
}
return this;
};
/**
* @class PMConnectionDropBehavior
* Extends the functionality to handle creation of connections
*
* @constructor
* Creates a new instance of the object
*/
var PMConnectionDropBehavior = function (selectors) {
PMUI.behavior.ConnectionDropBehavior.call(this, selectors);
};
PMConnectionDropBehavior.prototype = new PMUI.behavior.ConnectionDropBehavior();
/**
* Defines the object type
* @type {String}
*/
PMConnectionDropBehavior.prototype.type = "PMConnectionDropBehavior";
/**
* Defines a Map of the basic Rules
* @type {Object}
*/
PMConnectionDropBehavior.prototype.basicRules = {
PMEvent: {
PMEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMActivity: {
connection: 'regular',
type: 'SEQUENCE'
}
},
PMActivity: {
PMActivity: {
connection: 'regular',
type: 'SEQUENCE'
},
PMArtifact: {
connection: 'dotted',
destDecorator: 'con_none',
type: 'ASSOCIATION'
},
PMIntermediateEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMEndEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMGateway: {
connection: 'regular',
type: 'SEQUENCE'
}
},
PMStartEvent: {
PMActivity: {
connection: 'regular',
type: 'SEQUENCE'
},
PMIntermediateEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMGateway: {
connection: 'regular',
type: 'SEQUENCE'
}
},
PMIntermediateEvent: {
PMActivity: {
connection: 'regular',
type: 'SEQUENCE'
},
PMIntermediateEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMEndEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMGateway: {
connection: 'regular',
type: 'SEQUENCE'
}
},
PMBoundaryEvent: {
PMActivity: {
connection: 'regular',
type: 'SEQUENCE'
},
PMIntermediateEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMEndEvent: {
connection: 'regular',
type: 'SEQUENCE'
},
PMGateway: {
connection: 'regular',
type: 'SEQUENCE'
}
},
PMGateway: {
PMActivity: {
connection: 'regular',
type: 'SEQUENCE'
},
PMIntermediateEvent: {
connection: 'regular',
type: 'SEQUENCE'
}
},
PMArtifact: {
PMActivity: {
connection: 'dotted',
destDecorator: 'con_none',
type: 'ASSOCIATION'
}
}
};
/**
* Defines a Map of the init Rules
* @type {Object}
*/
PMConnectionDropBehavior.prototype.initRules = {
PMCanvas: {
PMCanvas: {
name: 'PMCanvas to PMCanvas',
rules: PMConnectionDropBehavior.prototype.basicRules
}
},
PMActivity: {
PMCanvas: {
name: 'PMActivity to PMCanvas',
rules: PMConnectionDropBehavior.prototype.basicRules
}
}
};
/**
* Handle the hook functionality when a drop start
* @param shape
*/
PMConnectionDropBehavior.prototype.dropStartHook = function (shape, e, ui) {
shape.srcDecorator = null;
shape.destDecorator = null;
var draggableId = ui.draggable.attr("id"),
source = shape.canvas.customShapes.find('id', draggableId),
prop;
if (source) {
prop = this.validate(source, shape);
if (prop) {
shape.setConnectionType({
type: prop.type,
segmentStyle: prop.connection,
srcDecorator: prop.srcDecorator,
destDecorator: prop.destDecorator
});
} else {
// verif if port is changed
if (typeof source !== 'undefined') {
if (!(ui.helper && ui.helper.attr('id') === "drag-helper")) {
return false;
}
shape.setConnectionType('none');
}
}
}
return true;
};
/**
* Connection validations method
* return an object if is valid otherwise return false
* @param {Connection} source
* @param {Connection} target
*/
PMConnectionDropBehavior.prototype.validate = function (source, target) {
var sType,
tType,
rules,
initRules,
initRulesName,
BPMNAuxMap = {
PMEvent: {
'START': 'PMStartEvent',
'END': 'PMEndEvent',
'INTERMEDIATE': 'PMIntermediateEvent',
'BOUNDARY': 'PMBoundaryEvent'
},
bpmnArtifact: {
'TEXTANNOTATION': 'bpmnAnnotation'
}
};
if (source && target) {
if (source.getID() === target.getID()) {
return false;
}
if (this.initRules[source.getParent().getType()]
&& this.initRules[source.getParent().getType()][target.getParent().getType()]) {
initRules = this.initRules[source.getParent().getType()][target.getParent().getType()].rules;
initRulesName = this.initRules[source.getParent().getType()][target.getParent().getType()].name;
// get the types
sType = source.getType();
tType = target.getType();
//Custimize all PM events
if (sType === 'PMEvent') {
if (BPMNAuxMap[sType] && BPMNAuxMap[sType][source.getEventType()]) {
sType = BPMNAuxMap[sType][source.getEventType()];
}
}
if (tType === 'PMEvent') {
if (BPMNAuxMap[tType] && BPMNAuxMap[tType][target.getEventType()]) {
tType = BPMNAuxMap[tType][target.getEventType()];
}
}
if (initRules[sType] && initRules[sType][tType]) {
rules = initRules[sType][tType];
} else {
rules = false;
}
if (initRules) {
switch (initRulesName) {
case 'bpmnPool to bpmnPool':
if (source.getParent().getID() !== target.getParent().getID()) {
rules = false;
}
break;
case 'bpmnLane to bpmnLane':
if (source.getFirstPool(source.parent).getID()
!== target.getFirstPool(target.parent).getID()) {
if (this.extraRules[sType]
&& this.extraRules[sType][tType]) {
rules = this.extraRules[sType][tType];
} else {
rules = false;
}
}
break;
case 'bpmnActivity to bpmnLane':
if (this.basicRules[sType]
&& this.basicRules[sType][tType]) {
rules = this.basicRules[sType][tType];
} else {
rules = false;
}
break;
default:
break;
}
} else {
rules = false;
}
} else {
// get the types
sType = source.getType();
tType = target.getType();
//
if (sType === 'PMEvent') {
if (BPMNAuxMap[sType] && BPMNAuxMap[sType][source.getEventType()]) {
sType = BPMNAuxMap[sType][source.getEventType()];
}
}
if (tType === 'PMEvent') {
if (BPMNAuxMap[tType] && BPMNAuxMap[tType][target.getEventType()]) {
tType = BPMNAuxMap[tType][target.getEventType()];
}
}
if (this.advancedRules[sType] && this.advancedRules[sType][tType]) {
rules = this.advancedRules[sType][tType];
} else {
rules = false;
}
}
return rules;
}
};
PMConnectionDropBehavior.prototype.onDragEnter = function (customShape) {
return function (e, ui) {
var shapeRelative, i;
if (customShape.extendedType !== "PARTICIPANT") {
if (ui.helper && ui.helper.hasClass("dragConnectHandler")) {
shapeRelative = customShape.canvas.dragConnectHandlers.get(0).relativeShape;
if (shapeRelative.id !== customShape.id) {
for (i = 0; i < 4; i += 1) {
customShape.showConnectDropHelper(i, customShape);
}
}
}
} else {
shapeRelative = customShape.canvas.dragConnectHandlers.get(0).relativeShape;
if (shapeRelative && customShape && shapeRelative.id !== customShape.id) {
if (ui.helper && ui.helper.hasClass("dragConnectHandler")) {
for (i = 0; i < 10; i += 1) {
connectHandler = customShape.canvas.dropConnectHandlers.get(i);
connectHandler.setDimension(18 * customShape.canvas.getZoomFactor(), 18 * customShape.canvas.getZoomFactor());
connectHandler.setPosition(customShape.getZoomX() + i * customShape.getZoomWidth() / 10, customShape.getZoomY() - connectHandler.height / 2 - 1);
connectHandler.relativeShape = customShape;
connectHandler.attachDrop();
connectHandler.setVisible(true);
}
for (i = 0; i < 10; i += 1) {
connectHandler = customShape.canvas.dropConnectHandlers.get(i + 10);
connectHandler.setDimension(18 * customShape.canvas.getZoomFactor(), 18 * customShape.canvas.getZoomFactor());
connectHandler.setPosition(customShape.getZoomX() + i * customShape.getZoomWidth() / 10, customShape.getZoomY() + customShape.getZoomHeight() - connectHandler.height / 2 - 1);
connectHandler.relativeShape = customShape;
connectHandler.attachDrop();
connectHandler.setVisible(true);
}
}
}
}
}
};
/**
* Handle the functionality when a shape is dropped
* @param shape
*/
PMConnectionDropBehavior.prototype.onDrop = function (shape) {
var that = this;
return function (e, ui) {
var customShape,
id = ui.draggable.attr('id');
if (shape.getType() === "PMParticipant" && !(customShape = shape.canvas.shapeFactory(id))) {
if (customShape = shape.canvas.customShapes.find('id', id)) {
customShape.dropOnParticipant = true;
}
}
return false;
};
};
var PMCustomShapeDragBehavior = function () {
};
PMCustomShapeDragBehavior.prototype = new PMUI.behavior.CustomShapeDragBehavior();
/**
* Type of the instances
* @property {String}
*/
PMCustomShapeDragBehavior.prototype.type = "CustomShapeDragBehavior";
/**
* Attach the drag behavior and ui properties to the corresponding shape
* @param {PMUI.draw.CustomShape} customShape
*/
PMCustomShapeDragBehavior.prototype.attachDragBehavior = function (customShape) {
var dragOptions,
$customShape = $(customShape.getHTML());
dragOptions = {
revert: false,
helper: "none",
cursorAt: false,
revertDuration: 0,
disable: false,
grid: [1, 1],
start: this.onDragStart(customShape),
drag: this.onDrag(customShape, true),
stop: this.onDragEnd(customShape, true)
};
$customShape.draggable({ 'cursor': "move" });
$customShape.draggable(dragOptions);
};
/**
* On drag start handler, it uses the {@link PMUI.behavior.RegularDragBehavior}.onDragStart
* method to initialize the drag, but also initializes other properties
* @param {PMUI.draw.CustomShape} customShape
* @return {Function}
*/
PMCustomShapeDragBehavior.prototype.onDragStart = function (customShape) {
return function (e, ui) {
customShape.canvas.hideAllCoronas();
if (customShape.canvas.canConnect) {
if (customShape.canvas.connectStartShape.getID() !== customShape.getID()) {
customShape.canvas.connectProcedure(customShape, e);
}
customShape.canvas.cancelConnect();
return false;
}
if (customShape.canvas.currentSelection.asArray().length == 0) {
customShape.canvas.addToSelection(customShape);
}
PMUI.behavior.RegularDragBehavior.prototype.onDragStart.call(this,
customShape)(e, ui);
customShape.previousXDragPosition = customShape.getX();
customShape.previousYDragPosition = customShape.getY();
if (customShape.canvas.snapToGuide) {
//init snappers
customShape.canvas.startSnappers(e);
}
customShape.canvas.isDragging = true;
//to validate drag container
customShape.canvas.setLassoLimits();
};
};
/**
* Procedure executed while dragging, it takes care of multiple drag, moving
* connections, updating positions and children of the shapes being dragged
* @param {PMUI.draw.CustomShape} customShape shape being dragged
* @param {boolean} root return whether this is the shape where the drag started
* @param {number} childDiffX x distance needed for the non-root shapes to move
* @param {number} childDiffY y distance needed for the non-root shapes to move
* @param {Object} e jQuery object containing the properties when a drag event
* occur
* @param {Object} ui JQuery UI object containing the properties when a drag
* event occur
*/
PMCustomShapeDragBehavior.prototype.onDragProcedure = function (customShape, root, childDiffX, childDiffY, e, ui) {
var i,
j,
sibling,
diffX,
diffY,
port,
child,
connection,
shape1,
shape2,
canvas = customShape.canvas,
k,
uiOffset,
positionsX1 = [];
uiOffset = {};
uiOffset.x = ui.helper.position().left / canvas.zoomFactor;
uiOffset.y = ui.helper.position().top / canvas.zoomFactor;
uiOffset.diffX = customShape.x - uiOffset.x;
uiOffset.diffY = customShape.y - uiOffset.y;
// shapes
if (root) {
// Commented for problem on snappers
if (customShape.canvas.snapToGuide) {
customShape.canvas.processGuides(e, ui, customShape);
}
customShape.setPosition(uiOffset.x, uiOffset.y);
diffX = customShape.x - customShape.previousXDragPosition;
diffY = customShape.y - customShape.previousYDragPosition;
customShape.previousXDragPosition = customShape.x;
customShape.previousYDragPosition = customShape.y;
for (i = 0; i < customShape.canvas.currentSelection.getSize(); i += 1) {
sibling = customShape.canvas.currentSelection.get(i);
if (sibling.id !== customShape.id) {
sibling.setPosition(sibling.x + diffX, sibling.y + diffY);
}
}
} else {
customShape.setPosition(customShape.x, customShape.y);
}
// children
if (root) {
for (i = 0; i < customShape.canvas.currentSelection.getSize(); i += 1) {
sibling = customShape.canvas.currentSelection.get(i);
for (j = 0; j < sibling.children.getSize(); j += 1) {
child = sibling.children.get(j);
PMCustomShapeDragBehavior.prototype.onDragProcedure.call(this, child,
false, diffX, diffY, e, ui);
}
}
} else {
for (i = 0; i < customShape.children.getSize(); i += 1) {
child = customShape.children.get(i);
PMCustomShapeDragBehavior.prototype.onDragProcedure.call(this, child,
false, childDiffX, childDiffY, e, ui);
}
}
// connections
if (root) {
for (i = 0; i < customShape.canvas.currentSelection.getSize(); i += 1) {
sibling = customShape.canvas.currentSelection.get(i);
this.updateAndRepaintPositions({
customShape: customShape,
sibling: sibling,
diffX: diffX,
diffY: diffY
});
}
} else {
this.updateAndRepaintPositions({
customShape: customShape,
sibling: customShape,
diffX: childDiffX,
diffY: childDiffY
});
}
if (customShape) {
customShape.wasDragged = true;
}
};
/**
* Updates port position and repaint connections
* @param options
*/
PMCustomShapeDragBehavior.prototype.updateAndRepaintPositions = function (options) {
var j,
port,
connection,
customShape = options.customShape,
sibling = options.sibling;
// move the segments of this connections
for (j = 0; j < customShape.canvas.sharedConnections.getSize(); j += 1) {
connection = customShape.canvas.sharedConnections.get(j);
if (connection.srcPort.parent.getID() ===
sibling.getID()) {
// to avoid moving the connection twice
// (two times per shape), move it only if the shape
connection.move(options.diffX * customShape.canvas.zoomFactor,
options.diffY * customShape.canvas.zoomFactor);
}
}
for (j = 0; j < sibling.ports.getSize(); j += 1) {
//for each port update its absolute position and repaint its connection
port = sibling.ports.get(j);
connection = port.connection;
port.setPosition(port.x, port.y);
if (!customShape.canvas.sharedConnections.contains(connection)) {
connection
.setSegmentColor(PMUI.util.Color.GREY, false)
.setSegmentStyle("regular", false)// repaint: false
.disconnect()
.connect();
}
}
};
/**
* On drag handler, calls the drag procedure while the dragging is occurring,
* and also takes care of the snappers
* @param {PMUI.draw.CustomShape} customShape shape being dragged
* @param {boolean} root return whether this is the shape where the drag started
* @param {number} childDiffX x distance needed for the non-root shapes to move
* @param {number} childDiffY y distance needed for the non-root shapes to move
* @return {Function}
*/
PMCustomShapeDragBehavior.prototype.onDrag = function (customShape, root, childDiffX, childDiffY) {
var self = this;
return function (e, ui) {
self.onDragProcedure(customShape, root, childDiffX,
childDiffY, e, ui);
};
};
/**
* Procedure executed on drag end, it takes care of multiple drag, moving
* connections, updating positions and children of the shapes being dragged
* @param {PMUI.draw.CustomShape} customShape shape being dragged
* @param {boolean} root return whether this is the shape where the drag started
* @param {Object} e jQuery object containing the properties when a drag event
* occur
* @param {Object} ui JQuery UI object containing the properties when a drag
* event occur
*/
PMCustomShapeDragBehavior.prototype.dragEndProcedure = function (customShape, root, e, ui) {
var i,
j,
sibling,
port,
child,
connection,
shape1,
shape2,
canvas = customShape.canvas,
diffX = 0,
diffY = 0;
if (root) {
// the difference between this segment of code and the segment of code
// found in dragProcedure is that it's not needed to move the shapes
// anymore using differentials
customShape.wasDragged = false;
customShape.canvas.isDragging = false;
// validate lasso limits
if (canvas.lassoEnabled && canvas.lassoLimits.x.shape && canvas.lassoLimits.x.shape.getX() < 0) {
diffX -= canvas.lassoLimits.x.shape.getX();
}
if (canvas.lassoEnabled && canvas.lassoLimits.y.shape && canvas.lassoLimits.y.shape.getY() < 0) {
diffY -= canvas.lassoLimits.y.shape.getY();
}
for (i = 0; i < customShape.canvas.currentSelection.getSize();
i += 1) {
sibling = customShape.canvas.currentSelection.get(i);
// if dragging with lasso is rebasing the limit
if (diffX > 0 || diffY > 0) {
sibling.setPosition(sibling.getX() + diffX, sibling.getY() + diffY);
}
for (j = 0; j < sibling.children.getSize(); j += 1) {
child = sibling.children.get(j);
child.changedContainer = false;
PMUI.behavior.CustomShapeDragBehavior.prototype.dragEndProcedure.call(this,
child, false, e, ui);
}
}
} else {
for (i = 0; i < customShape.children.getSize(); i += 1) {
child = customShape.children.get(i);
PMUI.behavior.CustomShapeDragBehavior.prototype.dragEndProcedure.call(this,
child, false, e, ui);
}
}
// connections
if (root) {
for (i = 0; i < customShape.canvas.currentSelection.getSize();
i += 1) {
sibling = customShape.canvas.currentSelection.get(i);
for (j = 0; j < sibling.ports.getSize(); j += 1) {
// for each port update its absolute position and repaint
// its connection
port = sibling.ports.get(j);
connection = port.connection;
port.setPosition(port.x, port.y);
if (customShape.canvas.sharedConnections.
find('id', connection.getID())) {
// move the segments of this connections
if (connection.srcPort.parent.getID() ===
sibling.getID()) {
// to avoid moving the connection twice
// (two times per shape), move it only if the shape
// holds the sourcePort
connection.disconnect(true).connect({
algorithm: 'user',
points: connection.points,
dx: parseFloat($(connection.html).css('left')),
dy: parseFloat($(connection.html).css('top'))
});
connection.checkAndCreateIntersectionsWithAll();
connection.canvas.triggerUserStateChangeEvent(connection);
}
} else {
connection
.setSegmentColor(connection.originalSegmentColor, false)
.setSegmentStyle(connection.originalSegmentStyle, false)
.disconnect()
.connect();
connection.setSegmentMoveHandlers();
connection.checkAndCreateIntersectionsWithAll();
}
}
}
} else {
for (i = 0; i < customShape.ports.getSize(); i += 1) {
//for each port update its absolute position and repaint
//its connection
port = customShape.ports.get(i);
connection = port.connection;
shape1 = connection.srcPort.parent;
shape2 = connection.destPort.parent;
port.setPosition(port.x, port.y);
if (customShape.canvas.sharedConnections.
find('id', connection.getID())) {
// to avoid moving the connection twice
// (two times per shape), move it only if the shape
// holds the sourcePort
if (connection.srcPort.parent.getID() ===
customShape.getID()) {
connection.checkAndCreateIntersectionsWithAll();
}
} else {
connection
.setSegmentColor(connection.originalSegmentColor, false)
.setSegmentStyle(connection.originalSegmentStyle, false)
.disconnect()
.connect();
connection.setSegmentMoveHandlers();
connection.checkAndCreateIntersectionsWithAll();
}
}
}
};
/**
* On drag end handler, ot calls drag end procedure, removes the snappers and,
* fires the command move if necessary
* @param {PMUI.draw.CustomShape} customShape
* @return {Function}
*/
PMCustomShapeDragBehavior.prototype.onDragEnd = function (customShape) {
var command,
self = this;
return function (e, ui) {
// call to dragEnd procedure
self.dragEndProcedure(customShape, true, e, ui);
customShape.dragging = false;
// hide the snappers
customShape.canvas.verticalSnapper.hide();
customShape.canvas.horizontalSnapper.hide();
if (!customShape.changedContainer) {
if (customShape.parent.getType() === 'PMLane' && !customShape.dropOnParticipant) {
command = new PMCommandMoveInLane(customShape.canvas.currentSelection);
} else {
command = new PMUI.command.CommandMove(customShape.canvas.currentSelection);
}
command.execute();
customShape.canvas.commandStack.add(command);
customShape.dropOnParticipant = false;
}
customShape.changedContainer = false;
// decrease the zIndex of the oldParent of customShape
customShape.decreaseParentZIndex(customShape.oldParent);
// force to apply zoom, when move more than two figures
if (customShape.getCanvas().getCurrentSelection().getSize() > 1) {
customShape.getCanvas().applyZoom(customShape.getCanvas().getZoomPropertiesIndex() + 1);
}
customShape.getCanvas().emptyCurrentSelection();
};
};
var ToolbarPanel = function (options) {
this.tooltip = null;
ToolbarPanel.prototype.init.call(this, options);
};
ToolbarPanel.prototype = new PMUI.core.Panel();
ToolbarPanel.prototype.type = "ToolbarPanel";
ToolbarPanel.prototype.init = function (options) {
var defaults = {
fields: [],
tooltip: "",
width: "96%"
};
jQuery.extend(true, defaults, options);
PMUI.core.Panel.call(this, defaults);
this.fields = [];
this.setTooltip(defaults.tooltip);
this.setFields(defaults.fields);
};
ToolbarPanel.prototype.setTooltip = function (message) {
if (typeof message === "string") {
this.tooltip = message;
}
return this;
};
ToolbarPanel.prototype.setFields = function (fields) {
this.fields = fields;
return this;
};
/**
* Creates html structure for a button
* @param {*} button
*/
ToolbarPanel.prototype.createButtonHTML = function (button) {
var i,
li = PMUI.createHTMLElement("li"),
a = PMUI.createHTMLElement("a");
li.id = button.selector;
li.className = "mafe-toolbarpanel-btn";
a.title = "";
a.style.cursor = "move";
jQuery(a).tooltip({
content: button.tooltip,
tooltipClass: "mafe-action-tooltip",
position: {
my: "left top",
at: "left bottom",
collision: "flipfit"
}
});
for (i = 0; i < button.className.length; i += 1) {
jQuery(a).addClass(button.className[i]);
}
li.appendChild(a);
return li;
};
/**
* Creates html structure for a switch tongle component
* @param {*} element
* @returns {String}
*/
ToolbarPanel.prototype.createSwitchHTML = function (element) {
var li = PMUI.createHTMLElement("li"),
input = PMUI.createHTMLElement("input"),
label = PMUI.createHTMLElement("label"),
labelDescription = PMUI.createHTMLElement("label");
labelDescription.innerHTML = element.text || '';
labelDescription.className = "tgl-label";
input.type = "checkbox";
li.className = "mafe-toolbarpanel-switch";
input.type = "checkbox";
input.id = element.selector;
input.className = "tgl tgl-light";
input.checked = element.checked || false;
label.htmlFor = element.selector;
label.className = "tgl-btn";
input.addEventListener( 'change', function() {
if (element.checkHandler) {
if(this.checked) {
element.checkHandler(true);
} else {
element.checkHandler(false);
}
}
});
li.appendChild(labelDescription);
li.appendChild(input);
li.appendChild(label);
return li;
};
ToolbarPanel.prototype.createHTML = function () {
var that = this,
ul,
html;
PMUI.core.Panel.prototype.setElementTag.call(this, "ul");
PMUI.core.Panel.prototype.createHTML.call(this);
this.html.style.overflow = "visible";
jQuery.each(this.fields, function (i, button) {
if (button.type === "button") {
html = that.createButtonHTML(button);
} else if (button.type === "switch") {
html = that.createSwitchHTML(button);
}
that.html.appendChild(html);
button.html = html;
});
return this.html;
};
ToolbarPanel.prototype.activate = function () {
var that = this;
jQuery.each(this.fields, function (i, b) {
if (b.type === "button") {
jQuery(b.html).draggable({
opacity: 0.7,
helper: "clone",
cursor: "hand"
});
}
});
return this;
};
/**
* Enable the actions if the toolbar button has an action and is a button
* @chainable
*/
ToolbarPanel.prototype.enableActions = function () {
jQuery.each(this.fields, function (i, b) {
if (b.type === "button") {
if (b.actions) {
new PMAction(b.actions);
}
}
});
return this;
};
ToolbarPanel.prototype.getSelectors = function () {
var selectors = [],
that = this;
jQuery.each(this.fields, function (i, button) {
selectors.push("#" + button.selector);
});
return selectors;
};
var PMProject;
PMProject = function (options) {
this.diagrams = new PMUI.util.ArrayList();
this.keys = null;
this.waitingResponse = false;
this.identifiers = {};
this.isSave = false;
this.XMLSupported = true;
this.isClose = false;
this.userSettings = null;
this.definitions = null;
this.loadingProcess = false;
this.dirtyElements = [
{
laneset: {},
lanes: {},
activities: {},
events: {},
gateways: {},
flows: {},
artifacts: {},
lines: {},
data: {},
participants: {}
},
{
laneset: {},
lanes: {},
activities: {},
events: {},
gateways: {},
flows: {},
artifacts: {},
lines: {},
data: {},
participants: {}
}
];
PMProject.prototype.init.call(this, options);
};
PMProject.prototype.init = function (options) {
var defaults = {
projectId: "",
projectName: "",
description: "",
remoteProxy: null,
localProxy: null,
readOnly: false,
keys: {
access_token: null,
expires_in: null,
token_type: null,
scope: null,
refresh_token: null,
client_id: null,
client_secret: null
},
listeners: {
create: function () {
},
remove: function () {
},
update: function () {
},
success: function () {
},
failure: function () {
}
}
};
jQuery.extend(true, defaults, options);
this.setKeysClient(defaults.keys)
.setID(defaults.id)
.setTokens(defaults.keys)
.setListeners(defaults.listeners)
.setReadOnly(defaults.readOnly);
this.remoteProxy = new PMUI.proxy.RestProxy();
};
PMProject.prototype.setID = function (id) {
this.id = id;
return this;
};
PMProject.prototype.setProjectId = function (id) {
if (typeof id === "string") {
this.projectId = id;
}
return this;
};
PMProject.prototype.setXMLSupported = function (value) {
if (typeof value == "boolean")
this.XMLSupported = value;
return this;
};
/**
* Sets the readOnly Mode
* @param {PMProject} value
*/
PMProject.prototype.setReadOnly = function(value) {
if (typeof value === "boolean") this.readOnly = value;
return this;
};
PMProject.prototype.setProjectName = function (name) {
if (typeof name === "string") {
this.projectName = name;
jQuery(".navBar div").remove();
if ($(".navBar h2").length > 0) {
$(".navBar h2").text(name);
} else {
jQuery(".navBar").append("<h2>" + name + "</h2>");
}
}
return this;
};
/**
* Sets loading process
* @param settings
* @returns {PMProject}
*/
PMProject.prototype.setLoadingProcess = function(loading) {
if (typeof loading === "boolean") {
this.loadingProcess = loading;
}
return this;
};
/**
* Sets the user settings to the local property
* @param settings
* @returns {PMProject}
*/
PMProject.prototype.setUserSettings= function (settings) {
this.userSettings = settings;
return this;
};
PMProject.prototype.setDescription = function (description) {
this.description = description;
return this;
};
PMProject.prototype.setKeysClient = function (keys) {
if (typeof keys === "object") {
this.keys = keys;
}
return this;
};
PMProject.prototype.setListeners = function (listeners) {
if (typeof listeners === "object") {
this.listeners = listeners;
}
return this;
};
/**
* Sets the time interval used to save automatically
* @param {Number} interval Expressed in miliseconds
* @return {*}
*/
PMProject.prototype.setSaveInterval = function (interval) {
this.saveInterval = interval;
return this;
};
PMProject.prototype.getKeysClient = function () {
var keys = this.keys;
return {
access_token: keys.access_token,
expires_in: keys.expires_in,
token_type: keys.token_type,
scope: keys.scope,
refresh_token: keys.refresh_token,
client_id: keys.client_id,
client_secret: keys.client_secret
};
};
PMProject.prototype.buildCanvas = function (selectors, options) {
var canvas = new PMCanvas({
id: PMUI.generateUniqueId(),
project: PMDesigner.project,
top: 77,
width: 6000,
height: 6000,
style: {
cssProperties: {
overflow: "hidden"
}
},
drop: {
type: 'canvasdrop',
selectors: selectors
},
container: "pmcanvas",
readOnly: this.readOnly,
hasClickEvent: true,
copyAndPasteReferences: {
PMEvent: PMEvent,
PMGateway: PMGateway,
PMActivity: PMActivity,
PMArtifact: PMArtifact,
PMFlow: PMFlow
}
});
jQuery("#div-layout-canvas").append(canvas.getHTML());
canvas.toogleGridLine();
canvas.setShapeFactory(PMDesigner.shapeFactory);
canvas.attachListeners();
canvas.createConnectHandlers('', '');
var menuCanvas = PMDesigner.getMenuFactory("CANVAS");
canvas.setContextMenu(menuCanvas);
//enable gridLines
options.userSettings && options.userSettings.enabled_grid ?
canvas.enableGridLine(): canvas.disableGridLine();
PMDesigner.canvasList.addOption(
{
label: options.name,
value: canvas.getID()
});
this.diagrams.insert(canvas);
return canvas;
};
PMProject.prototype.getKeysClient = function () {
var keys = this.keys;
return {
access_token: keys.access_token,
expires_in: keys.expires_in,
token_type: keys.token_type,
scope: keys.scope,
refresh_token: keys.refresh_token,
client_id: keys.client_id,
client_secret: keys.client_secret
};
};
PMProject.prototype.load = function () {
var keys = this.getKeysClient(),
that = this;
$.ajax({
url: that.remoteProxy.url,
type: 'GET',
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + keys.access_token);
xhr.setRequestHeader("Accept-Language", LANG);
},
success: function (data, textStatus) {
that.dirty = false;
that.loadProject(data);
$(".loader").fadeOut("slow");
},
error: function (xhr, textStatus, errorThrown) {
$(".loader").fadeOut("slow");
that.listeners.failure(that, xhr, response);
}
});
return this;
};
PMProject.prototype.loadProject = function (project) {
var that = this,
i,
j,
diagram,
canvas,
sidebarCanvas = [];
if (project) {
this.setLoadingProcess(true);
this.setProjectId(project.prj_uid);
this.setProjectName(project.prj_name);
this.setDescription(project.prj_description);
this.setUserSettings(project.usr_setting_designer);
if (project.prj_bpmn_file_upload) {
that.importDiagram(project.prj_bpmn_file_upload);
} else {
for (i = 0; i < project.diagrams.length; i += 1) {
diagram = project.diagrams[i];
for (j = 0; j < PMDesigner.sidebar.length; j += 1) {
sidebarCanvas = sidebarCanvas.concat(PMDesigner.sidebar[j].getSelectors());
jQuery(".bpmn_shapes").append(PMDesigner.sidebar[j].getHTML());
}
//Remove Lane
sidebarCanvas.splice(15, 1);
//Remove Lasso and Validator
sidebarCanvas.splice(17, 2);
sidebarCanvas = sidebarCanvas.concat('.mafe-event-start');
sidebarCanvas = sidebarCanvas.concat('.mafe-event-intermediate');
sidebarCanvas = sidebarCanvas.concat('.mafe-event-end');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmactivity');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmgateway');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmdata');
sidebarCanvas = sidebarCanvas.concat('.mafe-artifact-annotation');
sidebarCanvas = sidebarCanvas.concat('.mafe-artifact-group');
sidebarCanvas = sidebarCanvas.concat('.mafe-pool');
sidebarCanvas = sidebarCanvas.concat('.mafe_participant');
canvas = PMDesigner.project.buildCanvas(sidebarCanvas, {
name: 'Main',
userSettings: this.userSettings
});
PMUI.setActiveCanvas(canvas);
jQuery("#p-center-layout").scroll(canvas.onScroll(canvas, jQuery("#p-center-layout")));
var xmlStr =
'<?xml version="1.0" encoding="UTF-8"?>' +
'<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" id="BPMNProcessmaker" targetNamespace="http://bpmn.io/schema/bpmn">' +
'</bpmn2:definitions>';
PMDesigner.moddle.fromXML(xmlStr, function (err, definitions) {
PMDesigner.businessObject = definitions;
canvas.buildDiagram(diagram);
if (!project.prj_update_date) {
canvas.setDefaultStartEvent();
PMDesigner.helper.startIntro();
}
that.setLoadingProcess(false);
that.loaded = true;
that.setSaveButtonDisabled();
PMDesigner.modeReadOnly();
PMDesigner.connectValidator.bpmnValidator();
});
}
}
}
};
/**
* Imports a Diagram if this is a valid .bpmn file
* @param data
*/
PMProject.prototype.importDiagram = function (data) {
PMDesigner.moddle.fromXML(data, function (err, definitions) {
if (err) {
PMDesigner.msgFlash('Import Error: '.translate() + err.message, document.body, 'error', 5000, 5);
} else {
PMDesigner.definitions = definitions;
var imp = new importBpmnDiagram(definitions);
if (PMDesigner.project.XMLSupported) {
PMDesigner.businessObject = definitions;
imp.completeImportFlows();
PMUI.getActiveCanvas().buildingDiagram = false;
PMDesigner.project.setDirty(true);
PMDesigner.project.save(false);
PMUI.getActiveCanvas().hideAllFocusLabels();
PMDesigner.project.setXMLSupported(true);
} else {
PMDesigner.msgFlash('The process definition that you are trying to import contains BPMN elements that are not supported in ProcessMaker. Please try with other process.'.translate(), document.body, 'error', 5000, 5);
}
}
});
}
/**
* Represents a flag if the project was saved or not
*/
PMProject.prototype.isDirty = function () {
return this.dirty;
};
/**
* Saves old bpmn project
* @param options
* @returns {PMProject}
*/
PMProject.prototype.save = function (options) {
var keys = this.getKeysClient(),
that = this;
if (!this.readOnly && this.isDirty()) {
that.isSave = true;
$.ajax({
url: that.remoteProxy.url,
type: "PUT",
contentType: "application/json",
data: JSON.stringify(that.getDirtyObject()),
beforeSend: function (xhr, settings) {
xhr.setRequestHeader("Authorization", "Bearer " + keys.access_token);
xhr.setRequestHeader("Accept-Language", LANG);
},
success: function (data, textStatus, xhr) {
that.listeners.success(that, textStatus, data);
that.isSave = false;
},
error: function (xhr, textStatus, errorThrown) {
if (xhr.status == 401 && typeof(xhr.responseJSON.error) != "undefined") {
//Refresh Token
$.ajax({
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/token",
type: "POST",
contentType: "application/json",
data: JSON.stringify(
{
grant_type: "refresh_token",
client_id: that.keys.client_id,
client_secret: that.keys.client_secret,
refresh_token: that.keys.refresh_token
}
),
success: function (data, textStatus, xhr) {
that.keys.access_token = xhr.responseJSON.access_token;
that.keys.expires_in = xhr.responseJSON.expires_in;
that.keys.token_type = xhr.responseJSON.token_type;
that.keys.scope = xhr.responseJSON.scope;
that.keys.refresh_token = xhr.responseJSON.refresh_token;
that.save(true);
},
error: function (xhr, textStatus, errorThrown) {
that.listeners.failure(that, textStatus, xhr);
that.isSave = false;
}
});
} else {
that.listeners.failure(that, textStatus, xhr);
that.isSave = false;
}
}
});
}
return this;
};
PMProject.prototype.saveClose = function (options) {
var keys = this.getKeysClient(),
that = this;
if (!this.readOnly && this.isDirty()) {
that.isSave = true;
$.ajax({
url: that.remoteProxy.url,
type: 'PUT',
data: JSON.stringify(that.getDirtyObject()),
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + keys.access_token);
xhr.setRequestHeader("Accept-Language", LANG);
},
success: function (data, textStatus) {
var message_window,
browser = PMDesigner.getBrowser();
url = parent.location.href;
that.listeners.success(that, textStatus, data);
that.isSave = false;
if ((navigator.userAgent.indexOf("MSIE") != -1) || (navigator.userAgent.indexOf("Trident") != -1)) {
window.close();
} else {
parent.location.href = url;
}
},
error: function (xhr, textStatus, errorThrown) {
that.listeners.failure(that, textStatus, xhr);
that.isSave = false;
}
});
}
return this;
};
PMProject.prototype.getDirtyObject = function () {
var that = this,
diaArray = [],
shape,
isGridEnabled = false,
diagram,
lastDiagram;
lastDiagram = this.diagrams.getSize() - 1;
diagram = this.diagrams.get(lastDiagram);
shape = this.getDataObject(diagram);
diaArray.push({
dia_uid: that.diagramId || PMUI.generateUniqueId(),
pro_uid: that.id,
laneset: shape.laneset,
lanes: shape.lanes,
activities: shape.activities,
events: shape.events,
gateways: shape.gateways,
flows: shape.flows,
artifacts: shape.artifacts,
data: shape.data,
participants: shape.participants
});
isGridEnabled = PMUI.getActiveCanvas().isGridLine && PMUI.getActiveCanvas().isGridLine? true: false;
return {
prj_uid: that.id,
prj_name: that.projectName,
prj_description: that.description,
usr_setting_designer: {enabled_grid : isGridEnabled},
diagrams: diaArray
};
};
PMProject.prototype.getDataObject = function (canvas) {
var object, i, elements, shapes;
elements = canvas.items.asArray();
shapes = {
activities: [],
gateways: [],
events: [],
flows: [],
artifacts: [],
laneset: [],
lanes: [],
data: [],
participants: [],
pools: []
};
if (canvas.items.getSize() > 0) {
for (i = 0; i < elements.length; i += 1) {
if (typeof elements[i].relatedObject.getDataObject() === "undefined") {
object = elements[i].relatedObject;
} else {
object = elements[i].relatedObject.getDataObject();
}
switch (elements[i].type) {
case "PMActivity":
shapes.activities.push(object);
break;
case "PMGateway":
shapes.gateways.push(object);
break;
case "PMEvent":
shapes.events.push(object);
break;
case "PMFlow":
case "Connection":
shapes.flows.push(object);
break;
case "PMArtifact":
shapes.artifacts.push(object);
break;
case "PMData":
shapes.data.push(object);
break;
case "PMParticipant":
shapes.participants.push(object);
break;
case "PMPool":
shapes.laneset.push(object);
break;
case "PMLane":
shapes.lanes.push(object);
break;
}
}
}
return shapes;
};
PMProject.prototype.setDirty = function (dirty) {
if (typeof dirty === "boolean") {
this.dirty = dirty;
}
return this;
};
PMProject.prototype.addElement = function (element) {
var object,
pk_name,
list,
i,
pasteElement,
elementUndo,
sh,
contDivergent = 0,
contConvergent = 0;
if (element.relatedElements.length > 0) {
for (i = element.relatedElements.length - 1; i >= 0; i -= 1) {
pasteElement = element.relatedElements[i];
list = this.getUpdateList(pasteElement.type);
if (list === undefined) {
return;
}
list[pasteElement.id] = object;
elementUndo = {
id: pasteElement.id,
relatedElements: [],
relatedObject: pasteElement,
type: pasteElement.type || pasteElement.extendedType
};
PMUI.getActiveCanvas().items.insert(elementUndo);
if (!(pasteElement instanceof PMUI.draw.MultipleSelectionContainer)
&& !(pasteElement instanceof PMLine)
&& !(pasteElement instanceof PMLabel)) {
pasteElement.createBpmn(pasteElement.getBpmnElementType());
}
}
} else {
switch (element.type) {
case "Connection":
pk_name = this.formatProperty(element.type, 'uid');
list = this.getUpdateList(element.type);
element.relatedObject[pk_name] = element.id;
if (typeof element.relatedObject.getDataObject === "undefined") {
object = element.relatedObject;
}
list[element.id] = object;
break;
default:
pk_name = this.formatProperty(element.type, 'uid');
list = this.getUpdateList(element.type);
element.relatedObject[pk_name] = element.id;
list[element.id] = object;
break;
}
PMUI.getActiveCanvas().items.insert(element);
var shape = element.relatedObject;
if (!(shape instanceof PMUI.draw.MultipleSelectionContainer)
&& !(shape instanceof PMLine)
&& !(shape instanceof PMLabel)) {
shape.createBpmn(shape.getBpmnElementType());
}
}
if (!this.loadingProcess) {
this.setDirty(true);
if(element.type === "Connection") {
PMDesigner.connectValidator.bpmnValidatorShape(element.relatedObject.destPort.parent);
PMDesigner.connectValidator.bpmnValidatorShape(element.relatedObject.srcPort.parent);
}
PMDesigner.connectValidator.bpmnValidatorShape(element.relatedObject);
//Call to Create callBack
this.listeners.create(this, element);
}
};
PMProject.prototype.updateElement = function (updateElement) {
var element,
i,
shape,
object,
list,
item;
for (i = 0; i < updateElement.length; i += 1) {
element = updateElement[i];
shape = element.relatedObject;
object = this.formatObject(element);
list = this.getUpdateList(element.type);
if (list[element.id]) {
jQuery.extend(true, list[element.id], object);
if (element.type === 'Connection') {
list[element.id].flo_state = object.flo_state;
item = PMUI.getActiveCanvas().items.find("id", element.id);
item.relatedObject.flo_state = object.flo_state;
}
} else {
list[element.id] = object;
}
if (shape) {
if (shape instanceof PMUI.draw.Port) {
shape.connection.updateBpmn();
} else {
if (!(shape instanceof PMUI.draw.MultipleSelectionContainer)
&& !(shape instanceof PMLine)
&& !(shape instanceof PMLabel)) {
shape.updateBpmn();
}
}
}
}
//run the process validator only when the project has been loaded
if (!this.loadingProcess) {
this.setDirty(true);
PMDesigner.connectValidator.bpmnValidateOnUpdate(updateElement);
//Call to Update callBack
this.listeners.update(this, updateElement);
}
};
PMProject.prototype.removeElement = function (updatedElements) {
var object,
dirtyEmptyCounter,
element,
i,
pk_name,
list,
emptyObject = {},
currentItem;
for (i = 0; i < updatedElements.length; i += 1) {
element = updatedElements[i];
currentItem = PMUI.getActiveCanvas().items.find("id", updatedElements[i].id);
PMUI.getActiveCanvas().items.remove(currentItem);
list = this.getUpdateList(element.type);
if (list) {
pk_name = this.formatProperty(element.type, 'uid');
if (list[element.id]) {
delete list[element.id];
} else {
pk_name = this.formatProperty(element.type, 'uid');
object = {};
object[pk_name] = element.id;
list[element.id] = object;
}
}
// to remove BpmnModdle in de exported xml
if (!(element instanceof PMUI.draw.MultipleSelectionContainer)
&& !(element instanceof PMLine)
&& !(element instanceof PMLabel)) {
element.removeBpmn();
if (element.atachedDiagram) {
this.removeAttachedDiagram(element);
}
}
}
if (!this.isWaitingResponse()) {
dirtyEmptyCounter = true;
dirtyEmptyCounter = dirtyEmptyCounter && (this.dirtyElements[0].activities === emptyObject);
dirtyEmptyCounter = dirtyEmptyCounter && (this.dirtyElements[0].gateways === emptyObject);
dirtyEmptyCounter = dirtyEmptyCounter && (this.dirtyElements[0].events === emptyObject);
dirtyEmptyCounter = dirtyEmptyCounter && (this.dirtyElements[0].artifacts === emptyObject);
dirtyEmptyCounter = dirtyEmptyCounter && (this.dirtyElements[0].flows === emptyObject);
if (dirtyEmptyCounter) {
this.setDirty(false);
}
}
this.setDirty(true);
//Call to Remove callBack
this.listeners.remove(this, updatedElements);
//validate bpmn rules on remove
for (i = 0; i < updatedElements.length; i += 1) {
if(updatedElements[i].type === "Connection") {
PMDesigner.connectValidator.bpmnValidatorShape(updatedElements[i].destPort.parent);
PMDesigner.connectValidator.bpmnValidatorShape(updatedElements[i].srcPort.parent);
}
}
};
PMProject.prototype.formatProperty = function (type, property) {
var prefixes = {
"PMActivity": "act",
"PMGateway": "gat",
"PMEvent": "evn",
"PMArtifact": "art",
"PMData": "dat",
"PMParticipant": "par",
"PMPool": "swl",
"PMLane": "lan"
},
map = {
x: "bou_x",
y: "bou_y",
width: "bou_width",
height: "bou_height"
},
out;
if (type === "PMFlow" || type === 'Connection') {
out = "flo_" + property;
} else if (map[property]) {
out = map[property];
} else {
out = prefixes[type] + '_' + property;
}
return out;
};
PMProject.prototype.getUpdateList = function (type) {
var listName = {
"PMActivity": "activities",
"PMGateway": "gateways",
"PMEvent": "events",
"PMFlow": "flows",
"PMArtifact": "artifacts",
"PMLabel": "artifacts",
"Connection": "flows",
"PMData": "data",
"PMParticipant": "participants",
"PMPool": "laneset",
"PMLane": "lanes"
},
dirtyArray;
dirtyArray = (this.isWaitingResponse()) ? 1 : 0;
return this.dirtyElements[dirtyArray][listName[type]];
};
/**
* Represents if the proxy is waiting any response from the server
*/
PMProject.prototype.isWaitingResponse = function () {
return this.waitingResponse;
};
PMProject.prototype.updateIdentifiers = function (response) {
var i, shape, that = this, connection, shapeCanvas;
if (typeof response === "object") {
for (i = 0; i < response.length; i += 1) {
shape = PMUI.getActiveCanvas().items.find("id", response[i].old_uid);
shapeCanvas = PMUI.getActiveCanvas().children.find("id", response[i].old_uid);
connection = PMUI.getActiveCanvas().connections.find("flo_uid", response[i].old_uid);
this.identifiers[response[i].old_uid] = response[i].new_uid;
if (shape) {
shape.id = response[i].new_uid;
shape.relatedObject.id = response[i].new_uid;
shape.relatedObject.html.id = response[i].new_uid;
switch (shape.type) {
case "Connection":
shape.relatedObject.flo_uid = response[i].new_uid;
break;
case "PMActivity":
shape.relatedObject.act_uid = response[i].new_uid;
break;
case "PMEvent":
shape.relatedObject.evn_uid = response[i].new_uid;
break;
case "PMGateway":
shape.relatedObject.gat_uid = response[i].new_uid;
break;
case "PMArtifact":
shape.relatedObject.art_uid = response[i].new_uid;
break;
case "PMData":
shape.relatedObject.dat_uid = response[i].new_uid;
break;
case "PMParticipant":
shape.relatedObject.par_uid = response[i].new_uid;
break;
case "PMPool":
shape.relatedObject.lns_uid = response[i].new_uid;
shape.relatedObject.participantObject.id = 'el_' + response[i].new_uid;
break;
case "PMLane":
shape.relatedObject.lan_uid = response[i].new_uid;
break;
}
}
if (shapeCanvas) {
shapeCanvas.id = response[i].new_uid;
}
if (connection) {
connection.flo_uid = response[i].new_uid;
connection.id = response[i].new_uid;
}
}
}
};
PMProject.prototype.formatObject = function (element) {
var i,
field,
formattedElement = {},
property;
formattedElement[this.formatProperty(element.type, 'uid')] = element.id;
if (element.adam) {
for (i = 0; i < element.fields.length; i += 1) {
field = element.fields[i];
formattedElement[field.field] = field.newVal;
}
} else if (element.fields) {
for (i = 0; i < element.fields.length; i += 1) {
field = element.fields[i];
property = this.formatProperty(element.type, field.field);
if (property === "element_uid") {
field.newVal = field.newVal.id;
}
formattedElement[property] = field.newVal;
}
}
return formattedElement;
};
PMProject.prototype.subProcessDiagram = function (element) {
var sidebarCanvas = [], opt = {name: element.act_name}, s, newCanvas, di;
PMUI.getActiveCanvas().getHTML().style.display = 'none';
if (!element.atachedDiagram) {
for (s = 0; s < PMDesigner.sidebar.length; s += 1) {
sidebarCanvas = sidebarCanvas.concat(PMDesigner.sidebar[s].getSelectors());
jQuery(".bpmn_shapes").append(PMDesigner.sidebar[s].getHTML());
}
sidebarCanvas.splice(17, 1);
sidebarCanvas.splice(5, 1);
sidebarCanvas = sidebarCanvas.concat('.pmui-pmevent');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmactivity');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmgateway');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmdata');
sidebarCanvas = sidebarCanvas.concat('.mafe-artifact-annotation');
sidebarCanvas = sidebarCanvas.concat('.mafe-artifact-group');
sidebarCanvas = sidebarCanvas.concat('.mafe-pool');
sidebarCanvas = sidebarCanvas.concat('.mafe_participant');
newCanvas = this.buildCanvas(sidebarCanvas, opt);
PMUI.setActiveCanvas(newCanvas);
jQuery("#p-center-layout").scroll(newCanvas.onScroll(newCanvas, jQuery("#p-center-layout")));
newCanvas.getHTML().style.display = 'inline';
element.atachedDiagram = newCanvas;
PMDesigner.canvasList.setValue(newCanvas.getID());
di = newCanvas.createBPMNDiagram();
newCanvas.businessObject = element.businessObject;
di.bpmnElement = element.businessObject; //update reference
newCanvas.businessObject.di = di;
} else {
newCanvas = element.atachedDiagram;
PMUI.setActiveCanvas(newCanvas);
newCanvas.getHTML().style.display = 'inline';
PMDesigner.canvasList.setValue(newCanvas.getID());
}
};
PMProject.prototype.removeAttachedDiagram = function (element) {
var canvas = element.atachedDiagram;
this.diagrams.remove(canvas);
if (canvas.html !== undefined) {
jQuery(canvas.html).remove();
canvas.html = null;
}
element.atachedDiagram = null;
PMDesigner.canvasList.removeOption(canvas.getID());
};
PMProject.prototype.setTokens = function (response) {
this.tokens = response;
return this;
};
PMProject.prototype.setSaveButtonDisabled = function () {
if (this.isDirty()) {
if (document.getElementsByClassName("mafe-save-process").length > 0) {
document.getElementsByClassName("mafe-save-process")[0].removeAttribute("style");
document.getElementsByClassName("mafe-save-process")[0].childNodes[0].style.color = "#FFF";
var mafebuttonMenu = document.getElementsByClassName("mafe-button-menu")[0];
mafebuttonMenu.style.backgroundColor = "#0C9778";
mafebuttonMenu.firstChild.src = "/lib/img/caret-down-w.png";
}
} else {
if (document.getElementsByClassName("mafe-save-process").length > 0) {
document.getElementsByClassName("mafe-save-process")[0].style.backgroundColor = "#e8e8e8";
document.getElementsByClassName("mafe-save-process")[0].style.color = "#000";
document.getElementsByClassName("mafe-save-process")[0].childNodes[0].style.color = "#000";
document.getElementsByClassName("mafe-save-process")[0].childNodes[0].text = "Save".translate();
var mafebuttonMenu = document.getElementsByClassName("mafe-button-menu")[0];
mafebuttonMenu.style.backgroundColor = "#e8e8e8";
mafebuttonMenu.firstChild.src = "/lib/img/caret-down.png";
}
}
};
/**
* @class Snapper
* Class snapper represents the helper shown while moving shapes.
* @extend JCoreObject
*
* @constructor Creates an instance of the class Snapper
* @param {Object} options Initialization options
* @cfg {Point} [orientation="horizontal"] The default orientation of this snapper
*/
var PMSnapper = function (options) {
PMUI.draw.Snapper.call(this, options);
/**
* Orientation of this snapper, it can be either "horizontal" or "vertical".
* @property {string} [orientation=null]
*/
this.orientation = null;
/**
* Data saved to define the positioning of this snapper in the canvas.
* @property {Array} [data=[]]
*/
this.data = [];
/**
* The visibility of this snapper.
* @property {boolean} [visible=false]
*/
this.visible = false;
PMSnapper.prototype.initObject.call(this, options);
};
PMSnapper.prototype = new PMUI.draw.Snapper();
/**
* The type of each instance of this class
* @property {String}
*/
PMSnapper.prototype.type = "Snapper";
/**
* Instance initializer which uses options to extend the config options to initialize the instance.
* @param {Object} options The object that contains the config
* @private
*/
PMSnapper.prototype.initObject = function (options) {
var defaults = {
orientation: "horizontal"
};
// extend recursively the defaultOptions with the given options
$.extend(true, defaults, options);
// call setters using the defaults object
this.setOrientation(defaults.orientation);
this.setDimension(defaults.width, defaults.height);
// create the html (it's hidden initially)
this.hide();
};
PMSnapper.prototype.getHTML = function () {
if (!this.html) {
this.createHTML();
}
return this.html;
};
/**
* Creates the HTML representation of the snapper.
* @returns {HTMLElement}
*/
PMSnapper.prototype.createHTML = function () {
if (!this.html) {
this.html = document.createElement("div");
this.style.applyStyle();
this.style.addProperties({
position: "absolute",
left: this.zoomX,
top: this.zoomY,
width: this.zoomWidth,
height: this.zoomHeight,
zIndex: this.zOrder
});
this.html.id = this.id;
this.canvas.html.appendChild(this.html);
this.setZOrder(99);
this.html.className = 'mafe-snapper';
if (this.getOrientation() === 'horizontal') {
this.html.id = 'guide-h';
this.html.style.borderTop = '1px dashed #55f';
this.html.style.width = '100%';
} else {
this.html.id = 'guide-v';
this.html.style.borderLeft = '1px dashed #55f';
this.html.style.height = '100%';
}
}
return this.html;
};
/**
* Hides the snapper.
* @chainable
*/
PMSnapper.prototype.hide = function () {
this.visible = false;
this.setVisible(this.visible);
return this;
};
/**
* Shows the snapper.
* @chainable
*/
PMSnapper.prototype.show = function () {
this.visible = true;
this.setVisible(this.visible);
return this;
};
/**
* Fills the data for the snapper (using customShapes and regularShapes).
* The data considered for each shape is:
*
* - Its absoluteX
* - Its absoluteY
* - Its absoluteX + width
* - Its absoluteY + height
*
* @chainable
*/
PMSnapper.prototype.createSnapData = function () {
var i,
index = 0,
shape,
border = 0;
// clear the data before populating it
this.data = [];
// populate the data array using the customShapes
for (i = 0; i < this.canvas.customShapes.getSize(); i += 1) {
shape = this.canvas.customShapes.get(i);
if (!this.canvas.currentSelection.find('id', shape.getID())) {
border = parseInt($(shape.getHTML()).css('borderTopWidth'), 10);
if (this.orientation === 'horizontal') {
this.data[index * 2] = shape.getAbsoluteY() - border;
this.data[index * 2 + 1] = shape.getAbsoluteY() + shape.getZoomHeight();
} else {
this.data[index * 2] = shape.getAbsoluteX() - border;
this.data[index * 2 + 1] = shape.getAbsoluteX() + shape.getZoomWidth();
}
index += 1;
}
}
// populate the data array using the regularShapes
for (i = 0; i < this.canvas.regularShapes.getSize(); i += 1) {
shape = this.canvas.regularShapes.get(i);
border = parseInt($(shape.getHTML()).css('borderTopWidth'), 10);
if (this.orientation === 'horizontal') {
this.data[index * 2] = shape.getAbsoluteY() - border;
this.data[index * 2 + 1] = shape.getAbsoluteY() +
shape.getZoomHeight();
} else {
this.data[index * 2] = shape.getAbsoluteX() - border;
this.data[index * 2 + 1] = shape.getAbsoluteX() +
shape.getZoomWidth();
}
index += 1;
}
return this;
};
/**
* Sorts the data using the builtin `sort()` function, so that there's an strictly increasing order.
* @chainable
*/
PMSnapper.prototype.sortData = function () {
this.data.sort(function (a, b) {
return a > b;
});
return this;
};
/**
* Performs a binary search for `value` in `this.data`, return true if `value` was found in the data.
* @param {number} value
* @return {boolean}
*/
PMSnapper.prototype.binarySearch = function (value) {
var low = 0,
up = this.data.length - 1,
mid;
while (low <= up) {
mid = parseInt((low + up) / 2, 10);
if (this.data[mid] === value) {
return value;
}
if (this.data[mid] > value) {
up = mid - 1;
} else {
low = mid + 1;
}
}
return false;
};
/**
* Attaches listeners to this snapper, currently it only has the
* mouseMove event which hides the snapper.
* @param {Snapper} snapper
* @chainable
*/
PMSnapper.prototype.attachListeners = function (snapper) {
var $snapper = $(snapper.html).mousemove(
function () {
snapper.hide();
}
);
return this;
};
/**
* Sets the orientation of this snapper.
* @param {string} orientation
* @chainable
*/
PMSnapper.prototype.setOrientation = function (orientation) {
if (orientation === "horizontal" || orientation === "vertical") {
this.orientation = orientation;
} else {
throw new Error("setOrientation(): parameter is not valid".translate());
}
return this;
};
/**
* Gets the orientation of this snapper.
* @return {string}
*/
PMSnapper.prototype.getOrientation = function () {
return this.orientation;
};
var PMCanvas = function (options) {
PMUI.draw.Canvas.call(this, options);
this.project = null;
this.items = null;
/**
* Minimum distance to "snap" to a guide
* @type {number}
*/
this.MIN_DISTANCE = 4;
/**
* Array which contains a list of all coordinates to snap
* @type {number}
*/
this.guides = [];
this.attachedListeners = null;
this.hasClickEvent = false;
this.isDragging = false;
this.isGridLine = true;
this.dragConnectHandlers = new PMUI.util.ArrayList();
this.dropConnectHandlers = new PMUI.util.ArrayList();
this.isDraggingConnectHandler = false;
this.businessObject = {};
this.isMouseOverHelper = false;
this.canConnect = false;
this.canCreateShape = false;
this.canCreateShapeType = null;
this.canCreateShapeClass = null;
this.shapeHelper = null;
this.coronaClick = false;
this.connectStartShape = null;
this.coronaShape = null;
this.lassoEnabled = false;
this.lassoLimits = null;
PMCanvas.prototype.init.call(this, options);
};
PMCanvas.prototype = new PMUI.draw.Canvas();
PMCanvas.prototype.type = "PMCanvas";
this.canvasContainerBehavior = null;
PMCanvas.prototype.init = function (options) {
var defaults = {
project: null,
snapToGuide: true,
enabledMenu: false,
hasClickEvent: false
};
jQuery.extend(true, defaults, options);
this.setProject(defaults.project)
.setEnabledMenu(defaults.enabledMenu)
.setHasClickEvent(defaults.hasClickEvent)
.setSnapToGuide(defaults.snapToGuide);
this.items = new PMUI.util.ArrayList();
this.attachedListeners = false;
};
PMCanvas.prototype.setHasClickEvent = function (value) {
this.hasClickEvent = value;
return this;
};
PMCanvas.prototype.setEnabledMenu = function (value) {
this.enabledMenu = value;
return this;
};
PMCanvas.prototype.setParent = function (parent) {
this.parent = parent;
return this;
};
PMCanvas.prototype.setProject = function (project) {
if (project instanceof PMProject) {
this.project = project;
}
return this;
};
PMCanvas.prototype.onCreateElementHandler = function (element) {
var id,
label,
menuElement,
shapeElement;
if (this.project) {
this.project.addElement(element);
if (!this.project.loadingProcess) {
if (element.relatedObject && (element.relatedObject.type === 'PMPool'
|| element.relatedObject.type === 'PMActivity')) {
element.relatedObject.canvas.emptyCurrentSelection();
element.relatedObject.canvas.addToSelection(element.relatedObject);
}
}
if (element.type === "Connection") {
return;
}
}
};
/**
* Factory of canvas behaviors. It uses lazy instantiation to create
* instances of the different container behaviors
* @param {String} type An string that specifies the container behavior we want
* an instance to have, it can be regular or nocontainer
* @return {ContainerBehavior}
*/
PMCanvas.prototype.containerBehaviorFactory = function (type) {
if (type === 'pmcanvas') {
if (!this.canvasContainerBehavior) {
this.canvasContainerBehavior = new CanvasContainerBehavior();
}
return this.canvasContainerBehavior;
} else {
return PMShape.prototype.containerBehaviorFactory.call(this, type);
}
};
PMCanvas.prototype.dropBehaviorFactory = function (type, selectors) {
if (type === 'canvasdrop') {
if (!this.pmConnectionDropBehavior) {
this.pmConnectionDropBehavior = new PMContainerDropBehavior(selectors);
}
return this.pmConnectionDropBehavior;
} else {
return PMUI.draw.CustomShape.prototype.dropBehaviorFactory.call(this, type, selectors);
}
};
PMCanvas.prototype.triggerTextChangeEvent = function (element, oldText, newText) {
var valid, reg, e, nText, mp, id;
if (element.parent.getType() === 'PMActivity' && !this.validateName(element, newText, oldText)) {
newText = oldText;
}
reg = /<[^\s]/g;
nText = newText.trim();
e = reg.test(nText);
if (e) {
nText = nText.replace(/</g, '< ');
}
this.updatedElement = [{
id: element.parent.id,
type: element.parent.type,
parent: element.parent,
fields: [{
field: "name",
oldVal: oldText,
newVal: nText
}]
}];
element.parent.setName(nText);
element.updateDimension();
element.parent.setBPPMName(nText);
if (element.parent.atachedDiagram) {
id = PMDesigner.canvasList.getID();
$('#' + id + ' option[value=' + element.parent.atachedDiagram.getID() + ']')
.text(nText);
}
jQuery(this.html).trigger("changeelement");
};
PMCanvas.prototype.triggerConnectionStateChangeEvent = function (connection) {
var points = [],
Point = PMUI.util.Point,
point,
i;
for (i = 0; i < connection.points.length; i += 1) {
point = connection.points[i];
points.push(new Point(point.x / this.zoomFactor, point.y / this.zoomFactor));
}
this.updatedElement = [{
id: connection.getID(),
type: connection.type,
fields: [
{
field: 'state',
oldVal: connection.getOldPoints(),
newVal: points
}
],
relatedObject: connection
}];
connection.algorithm = 'user';
$(this.html).trigger('changeelement');
this.hideDragConnectHandlers();
return this;
};
PMCanvas.prototype.triggerUserStateChangeEvent = function (connection) {
var points = [],
Point = PMUI.util.Point,
point,
i;
for (i = 0; i < connection.points.length; i += 1) {
point = connection.points[i];
points.push(new Point(point.x / this.zoomFactor, point.y / this.zoomFactor));
}
this.updatedElement = [{
id: connection.getID(),
type: connection.type,
fields: [
{
field: 'state',
oldVal: connection.getOldPoints(),
newVal: points
}
],
relatedObject: connection
}];
connection.algorithm = 'user';
return this;
};
PMCanvas.prototype.updateDimensionLabel = function (element) {
var width,
width = element.relatedObject.width;
newWidth = Math.max(width, this.zoomWidth);
element.relatedObject.label.setWidth(width);
return this;
};
PMCanvas.prototype.onChangeElementHandler = function (element) {
var textNode,
currentElement;
if (this.project && element.length > 0) {
try {
this.hideAllCoronas();
this.project.updateElement(element);
} catch (e) {
throw new Error("Error, There are problems updating the element".translate(), e);
}
}
};
PMCanvas.prototype.onRemoveElementHandler = function (elements) {
var i,
element,
shapeElement;
if (this.project) {
this.project.removeElement(elements);
try {
for (i = 0; i < elements.length; i += 1) {
if (elements[i].type === "Connection") {
element = elements[i];
element.updateIncomingAndOutgoingConnections("remove");
shapeElement = element.destPort.getParent();
if (shapeElement instanceof PMGateway) {
shapeElement.evaluateGatewayDirection();
}
shapeElement = element.srcPort.getParent();
if (shapeElement instanceof PMGateway) {
shapeElement.evaluateGatewayDirection();
}
PMDesigner.project.updateElement([]);
break;
}
}
} catch (e) {
throw new Error("Error, There are problems removing the element".translate(), e);
}
}
};
PMCanvas.prototype.onSelectElementHandler = function (element) {
PMUI.removeCurrentMenu();
if (element.length === 1) {
switch (element[0].type) {
case 'PMActivity':
case 'PMEvent':
case 'PMGateway':
break;
}
}
if (this.currentLabel != null) {
this.hideAllFocusedLabels();
}
this.isSelected = true;
return this;
};
PMCanvas.prototype.defineEvents = function () {
if (!this.readOnly) {
return PMUI.draw.Canvas.prototype.defineEvents.call(this);
}
};
PMCanvas.prototype.getContextMenu = function () {
return {};
};
PMCanvas.prototype.onRightClick = function () {
var that = this;
return function (a, b, c) {
};
};
/**
* Set guide Lines to canvas and create vertican and horizontal snappers
* @param {Boolean} snap new value to verify if canvas has enabled snappes
* @chainable
*/
PMCanvas.prototype.setSnapToGuide = function (snap) {
this.snapToGuide = snap;
// create snappers
this.horizontalSnapper = new PMSnapper({
orientation: 'horizontal',
canvas: this,
width: 4000,
height: 1
});
this.verticalSnapper = new PMSnapper({
orientation: 'vertical',
canvas: this,
width: 1,
height: 4000
});
return this;
};
/**
* Build the data of the snappers recreating the arrays,
* this method is called from {@link RegularDragBehavior#onDragStart} (it might
* be an overrided method `onDragStart` if the instance of {@link RegularDragBehavior} was changed).
* @chainable
*/
PMCanvas.prototype.startSnappers = function (event) {
var shape, i, parent;
this.horizontalSnapper.getHTML();
this.verticalSnapper.getHTML();
this.guides = [];
for (i = 0; i < this.customShapes.getSize(); i += 1) {
shape = this.customShapes.get(i);
if (!this.currentSelection.find('id', shape.getID())) {
this.computeGuidesForElement(shape);
}
}
return this;
};
PMCanvas.prototype.computeGuidesForElement = function (shape) {
var x = shape.getHTML().offsetLeft, y = shape.getHTML().offsetTop,
w, h;
w = shape.getZoomWidth() - 1;
h = shape.getZoomHeight() - 1;
this.guides.push(
{type: "h", x: x, y: y},
{type: "h", x: x, y: y + h},
{type: "v", x: x, y: y},
{type: "v", x: x + w, y: y}
);
return this;
};
/**
* Process the snappers according to this criteria and show and hide:
*
* - To show the vertical snapper
* - `shape.absoluteX` must equal a value in the data of `this.verticalSnapper`
* - `shape.absoluteX + shape.width` must equal a value in the data of `this.verticalSnapper`
*
* - To show the horizontal snapper
* - `shape.absoluteY` must equal a value in the data of `this.horizontalSnapper`
* - `shape.absoluteY + shape.height` must equal a value in the data of `this.horizontalSnapper`
*
* @param {Object} e
* @parem {Object} ui
* @param {Shape} customShape
* @chainable
*/
PMCanvas.prototype.processGuides = function (e, ui, customShape) {
// iterate all guides, remember the closest h and v guides
var guideV,
guideH,
distV = this.MIN_DISTANCE + 1,
distH = this.MIN_DISTANCE + 1,
offsetV,
offsetH,
mouseRelX,
mouseRelY,
pos,
w = customShape.getZoomWidth() - 1,
h = customShape.getZoomHeight() - 1,
d;
mouseRelY = e.originalEvent.pageY - ui.offset.top;
mouseRelX = e.originalEvent.pageX - ui.offset.left;
pos = {
top: e.originalEvent.pageY - customShape.canvas.getY() - mouseRelY
+ customShape.canvas.getTopScroll(),
left: e.originalEvent.pageX - customShape.canvas.getX() - mouseRelX
+ customShape.canvas.getLeftScroll()
};
$.each(this.guides, function (i, guide) {
if (guide.type === "h") {
d = Math.abs(pos.top - guide.y);
if (d < distH) {
distH = d;
guideH = guide;
offsetH = 0;
}
d = Math.abs(pos.top - guide.y + h);
if (d < distH) {
distH = d;
guideH = guide;
offsetH = h;
}
}
if (guide.type === "v") {
d = Math.abs(pos.left - guide.x);
if (d < distV) {
distV = d;
guideV = guide;
offsetV = 0;
}
d = Math.abs(pos.left - guide.x + w);
if (d < distV) {
distV = d;
guideV = guide;
offsetV = w;
}
}
});
if (distH <= this.MIN_DISTANCE) {
$("#guide-h").css("top", guideH.y - this.absoluteY).show();
if (customShape.parent.family !== 'Canvas') {
ui.position.top = guideH.y - offsetH - customShape.getParent().getAbsoluteY();
} else {
ui.position.top = guideH.y - offsetH;
}
} else {
$("#guide-h").hide();
}
if (distV <= this.MIN_DISTANCE) {
$("#guide-v").css("left", guideV.x - this.absoluteX).show();
if (customShape.parent.family !== 'Canvas') {
ui.position.left = guideV.x - offsetV - customShape.getParent().getAbsoluteX();
} else {
ui.position.left = guideV.x - offsetV;
}
} else {
$("#guide-v").hide();
}
return this;
};
/**
* Fires the {@link PMUI.draw.Canvas#event-changeelement} event, and elaborates the structure of the object that will
* be passed to the handlers, the structure contains the following fields (considering old values and new values):
*
* - x
* - y
* - parent (the shape that is parent of this shape)
* - state (of the connection)
*
* @param {PMUI.draw.Port} port The port updated
* @chainable
*/
PMCanvas.prototype.triggerPortChangeEvent = function (port) {
var direction = port.connection.srcPort.getID() === port.getID() ?
"src" : "dest",
map = {
src: {
x: "x1",
y: "y1",
parent: "element_origin",
type: 'element_origin_type'
},
dest: {
x: "x2",
y: "y2",
parent: "element_dest",
type: 'element_dest_type'
}
},
point,
state,
zomeedState = [],
i;
state = port.connection.getPoints();
for (i = 0; i < state.length; i += 1) {
point = port.connection.points[i];
zomeedState.push(new PMUI.util.Point(point.x / this.zoomFactor, point.y / this.zoomFactor));
}
point = direction === "src" ? zomeedState[0] : zomeedState[state.length - 1];
this.updatedElement = [{
id: port.connection.getID(),
type: port.connection.type,
fields: [
{
field: map[direction].x,
oldVal: point.x, // there's no old value
newVal: point.x
},
{
field: map[direction].y,
oldVal: point.y, // there's no old value
newVal: point.y
},
{
field: map[direction].parent,
oldVal: (port.getOldParent()) ? port.getOldParent().getID() : null,
newVal: port.getParent().getID()
},
{
field: map[direction].type,
oldVal: port.connection.getNativeType(port.getParent()).type,
newVal: port.connection.getNativeType(port.getParent()).type
},
{
field: "state",
oldVal: port.connection.getOldPoints(),
newVal: zomeedState
},
{
field: "condition",
oldVal: "",
newVal: port.connection.getFlowCondition()
}
],
relatedObject: port
}];
$(this.html).trigger('changeelement');
};
/**
* Attaches event listeners to this canvas, it also creates some custom triggers
* used to save the data (to send it to the database later).
*
* The events attached to this canvas are:
*
* - {@link PMUI.draw.Canvas#event-mousedown Mouse down event}
* - {@link PMUI.draw.Canvas#event-mousemove Mouse move event}
* - {@link PMUI.draw.Canvas#event-mouseup Mouse up event}
* - {@link PMUI.draw.Canvas#event-click Click event}
* - {@link PMUI.draw.Canvas#event-scroll Scroll event}
*
* The custom events are:
*
* - {@link PMUI.draw.Canvas#event-createelement Create element event}
* - {@link PMUI.draw.Canvas#event-removeelement Remove element event}
* - {@link PMUI.draw.Canvas#event-changeelement Change element event}
* - {@link PMUI.draw.Canvas#event-selectelement Select element event}
* - {@link PMUI.draw.Canvas#event-rightclick Right click event}
*
* This method also initializes jQueryUI's droppable plugin (instantiated as `this.dropBehavior`)
* @chainable
*/
PMCanvas.prototype.attachListeners = function () {
var $canvas,
$canvasContainer;
if (this.attachedListeners === false) {
$canvas = $(this.html);
if (!this.readOnly) {
$canvas.click(this.onClick(this)),
$canvasContainer = $canvas.parent();
$canvas.dblclick(this.onDblClick(this));
$canvas.mousedown(this.onMouseDown(this));
$canvasContainer.scroll(this.onScroll(this, $canvasContainer));
$canvas.mousemove(this.onMouseMove(this));
$canvas.mouseup(this.onMouseUp(this));
$canvas.on("rightclick", this.onRightClick(this));
}
$canvas.on("createelement", this.onCreateElement(this));
$canvas.on("removeelement", this.onRemoveElement(this));
$canvas.on("changeelement", this.onChangeElement(this));
$canvas.on("selectelement", this.onSelectElement(this));
$canvas.on("contextmenu", function (e) {
e.preventDefault();
});
this.updateBehaviors();
this.attachedListeners = true;
}
return this;
};
/**
* enpty current selection extended
* @returns {PMCanvas}
*/
PMCanvas.prototype.emptyCurrentSelection = function () {
this.hideAllCoronas();
PMUI.draw.Canvas.prototype.emptyCurrentSelection.call(this);
return this;
};
/**
* mouse move custom behavior
* @param canvas
* @returns {Function}
*/
PMCanvas.prototype.onMouseMove = function (canvas) {
return function (e, ui) {
if (canvas.lassoEnabled && canvas.isMouseDown && !canvas.rightClick) {
canvas.isMouseDownAndMove = true;
var x = e.pageX - canvas.getX() + canvas.getLeftScroll() - canvas.getAbsoluteX(),
y = e.pageY - canvas.getY() + canvas.getTopScroll() - canvas.getAbsoluteY(),
topLeftX,
topLeftY,
bottomRightX,
bottomRightY;
topLeftX = Math.min(x, canvas.multipleSelectionHelper.oldX);
topLeftY = Math.min(y, canvas.multipleSelectionHelper.oldY);
bottomRightX = Math.max(x, canvas.multipleSelectionHelper.oldX);
bottomRightY = Math.max(y, canvas.multipleSelectionHelper.oldY);
canvas.multipleSelectionHelper.setPosition(
topLeftX / canvas.zoomFactor,
topLeftY / canvas.zoomFactor
);
canvas.multipleSelectionHelper.setDimension(
(bottomRightX - topLeftX) / canvas.zoomFactor,
(bottomRightY - topLeftY) / canvas.zoomFactor
);
} else if (canvas.canConnect) {
canvas.connectHelper(e)
canvas.connectStartShape.corona.hide();
canvas.hideAllFocusedLabels();
} else if (canvas.canCreateShape) {
canvas.createShapeHelper(e);
}
};
};
/**
* on mouse up behavior
* @param canvas
* @returns {Function}
*/
PMCanvas.prototype.onMouseUp = function (canvas) {
return function (e, ui) {
var realPoint,
x,
y;
e.preventDefault();
if (canvas.canCreateShape) {
canvas.manualCreateShape(canvas, e);
canvas.canCreateShape = false;
return true;
}
if (canvas.isMouseDownAndMove) {
realPoint = canvas.relativePoint(e);
x = realPoint.x;
y = realPoint.y;
canvas.multipleSelectionHelper.setPosition(
Math.min(x, canvas.multipleSelectionHelper.zoomX) / canvas.zoomFactor,
Math.min(y, canvas.multipleSelectionHelper.zoomY) / canvas.zoomFactor
);
if (canvas.multipleSelectionHelper) {
canvas.multipleSelectionHelper.wrapElements();
canvas.IncreaseAllConnectionZIndex();
}
} else {
if (!canvas.multipleSelectionHelper.wasDragged) {
canvas.multipleSelectionHelper.reset().setVisible(false);
}
if (canvas.isMouseDown) {
canvas.onClickHandler(canvas, x, y);
}
}
canvas.isMouseDown = false;
canvas.isMouseDownAndMove = false;
canvas.rightClick = false;
//hide lasso tool
$('.mafe-toolbar-lasso').css('background-color', 'rgb(233, 233, 233)');
canvas.lassoEnabled = false;
};
};
/**
* Increacess z.Index to all connections
* @constructor
*/
PMCanvas.prototype.IncreaseAllConnectionZIndex = function () {
var i,
connection;
for (i = 0; i < this.sharedConnections.getSize(); i += 1) {
connection = this.sharedConnections.get(i);
connection.increaseZIndex();
}
};
PMCanvas.prototype.createShapeHelper = function (e) {
var realPoint = this.relativePoint(e);
if (this.shapeHelper) {
//remove the connection segment in order to create another one
$(this.shapeHelper.html).remove();
}
this.shapeHelper = new CreateShapeHelper({
x: realPoint.x * this.zoomFactor - this.getX(),
y: realPoint.y * this.zoomFactor - this.getY(),
parent: this,
zOrder: 999,
className: this.canCreateShapeClass
});
this.shapeHelper.paint();
};
PMCanvas.prototype.connectHelper = function (e) {
var endPoint = {},
realPoint,
diff;
if (this.canConnect) {
if (this.connectionSegment) {
//remove the connection segment in order to create another one
$(this.connectionSegment.getHTML()).remove();
}
//start point
this.startConnectionPoint = {
x: this.connectStartShape.getAbsoluteX() + this.connectStartShape.xMidPoints[1],
y: this.connectStartShape.getAbsoluteY() + this.connectStartShape.yMidPoints[1]
};
//Determine the point where the mouse currently is
realPoint = this.relativePoint(e);
endPoint.x = realPoint.x * this.zoomFactor - this.getX();
endPoint.y = realPoint.y * this.zoomFactor - this.getY();
endPoint.x += (endPoint.x - this.startConnectionPoint.x > 0) ? -5 : 5;
endPoint.y += (endPoint.y - this.startConnectionPoint.y > 0) ? -5 : 5;
//creates a new segment from where the helper was created to the
// currently mouse location
this.connectionSegment = new PMUI.draw.Segment({
startPoint: this.startConnectionPoint,
endPoint: endPoint,
parent: this,
zOrder: 9
});
this.connectionSegment.paint();
}
};
PMCanvas.prototype.connectProcedure = function (customShape, e) {
var endPoint,
tempPoint,
initPoint,
i,
endPort,
sourcePort,
distance = 99999999,
connection,
endPoint2,
validationResult;
if (customShape.canvas.connectionSegment) {
//remove the connection segment left
$(customShape.canvas.connectionSegment.getHTML()).remove();
}
customShape.canvas.canConnect = false;
$('body').css('cursor', 'default');
validationResult = PMDesigner.connectValidator.isValid(customShape.canvas.connectStartShape, customShape);
if (!validationResult.result) {
//show invalid message
PMDesigner.msgFlash(validationResult.msg, document.body, 'info', 3000, 5);
return false;
}
sourcePort = new PMUI.draw.Port({
width: 10,
height: 10
});
endPort = new PMUI.draw.Port({
width: 10,
height: 10
});
endPoint = new PMUI.util.Point(
e.pageX - customShape.canvas.getX() - customShape.getAbsoluteX() + customShape.canvas.getLeftScroll(),
e.pageY - customShape.canvas.getY() - customShape.getAbsoluteY() + customShape.canvas.getTopScroll()
);
endPoint2 = new PMUI.util.Point(
e.pageX - customShape.canvas.getX() + customShape.canvas.getLeftScroll(),
e.pageY - customShape.canvas.getY() + customShape.canvas.getTopScroll()
);
for (i = 0; i < customShape.canvas.connectStartShape.xMidPoints.length; i += 1) {
tempPoint = new PMUI.util.Point(
customShape.canvas.connectStartShape.getAbsoluteX() + customShape.canvas.connectStartShape.xMidPoints[i],
customShape.canvas.connectStartShape.getAbsoluteY() + customShape.canvas.connectStartShape.yMidPoints[i]
);
if (distance > tempPoint.getSquaredDistance(endPoint2)) {
distance = tempPoint.getSquaredDistance(endPoint2);
initPoint = new PMUI.util.Point(
customShape.canvas.connectStartShape.xMidPoints[i],
customShape.canvas.connectStartShape.yMidPoints[i]
)
}
}
customShape.canvas.connectStartShape.addPort(sourcePort, initPoint.x, initPoint.y);
customShape.addPort(endPort, endPoint.x, endPoint.y, false, sourcePort);
//add ports to the canvas array for regularShapes
//create the connection
connection = new PMFlow({
srcPort: sourcePort,
destPort: endPort,
segmentColor: new PMUI.util.Color(0, 0, 0),
name: " ",
canvas: customShape.canvas,
segmentStyle: customShape.connectionType.segmentStyle,
flo_type: customShape.connectionType.type
});
connection.setSrcDecorator(new PMUI.draw.ConnectionDecorator({
width: 11,
height: 11,
canvas: customShape.canvas,
decoratorPrefix: (typeof customShape.connectionType.srcDecorator !== 'undefined'
&& customShape.connectionType.srcDecorator !== null) ?
customShape.connectionType.srcDecorator : "mafe-decorator",
decoratorType: "source",
parent: connection
}));
connection.setDestDecorator(new PMUI.draw.ConnectionDecorator({
width: 11,
height: 11,
canvas: customShape.canvas,
decoratorPrefix: (typeof customShape.connectionType.destDecorator !== 'undefined'
&& customShape.connectionType.destDecorator !== null) ?
customShape.connectionType.destDecorator : "mafe-decorator",
decoratorType: "target",
parent: connection
}));
connection.canvas.commandStack.add(new PMUI.command.CommandConnect(connection));
//connect the two ports
connection.connect();
connection.setSegmentMoveHandlers();
//add the connection to the canvas, that means insert its html to
// the DOM and adding it to the connections array
customShape.canvas.addConnection(connection);
// Filling PMFlow fields
connection.setTargetShape(endPort.parent);
connection.setOriginShape(sourcePort.parent);
// now that the connection was drawn try to create the intersections
connection.checkAndCreateIntersectionsWithAll();
//attaching port listeners
sourcePort.attachListeners(sourcePort);
endPort.attachListeners(endPort);
// finally trigger createEvent
customShape.canvas.triggerCreateEvent(connection, []);
};
/**
* hides all corona shape
*/
PMCanvas.prototype.hideAllCoronas = function () {
var i,
shape;
for (i = 0; i < this.currentSelection.getSize(); i += 1) {
shape = this.currentSelection.get(i);
if (shape.corona) {
shape.corona.hide();
}
}
return this;
};
/**
* cancel connection action
*/
PMCanvas.prototype.cancelConnect = function () {
if (this.connectionSegment) {
$(this.connectionSegment.getHTML()).remove();
}
this.canConnect = false;
$('body').css('cursor', 'default');
};
/**
* doble click mouse behavior
* @param canvas
* @returns {Function}
*/
PMCanvas.prototype.onDblClick = function (canvas) {
return function (e, ui) {
var currentLabel = canvas.currentLabel, figure, realPoint, realPoint, oldConnection;
e.stopPropagation();
e.preventDefault();
realPoint = canvas.relativePoint(e);
realPoint.x = realPoint.x * canvas.zoomFactor - canvas.getX();
realPoint.y = realPoint.y * canvas.zoomFactor - canvas.getY();
figure = canvas.getBestConnecion(realPoint);
if (figure !== null) {
canvas.emptyCurrentSelection();
figure.label.getFocus();
}
};
};
PMCanvas.prototype.hideAllFocusedLabels = function () {
if (this.currentLabel != null)
this.currentLabel.loseFocus();
return true;
};
/**
* @event mousedown
* MouseDown Handler of the canvas. It does the following:
*
* - Trigger the {@link PMUI.draw.Canvas#event-rightclick Right Click event} if it detects a right click
* - Empties `canvas.currentSelection`
* - Hides `canvas.currentConnection` if there's one
* - Resets the position of `canvas.multipleSelectionContainer` making it visible and setting its
* `[x, y]` to the point where the user did mouse down in the `canvas`.
*
* @param {PMUI.draw.Canvas} canvas
*/
PMCanvas.prototype.onMouseDown = function (canvas) {
return function (e, ui) {
var x = e.pageX - canvas.getX() + canvas.getLeftScroll() - canvas.getAbsoluteX(),
y = e.pageY - canvas.getY() + canvas.getTopScroll() - canvas.getAbsoluteY();
if (canvas.canConnect) {
canvas.cancelConnect();
}
//hide corona
if (canvas.coronaShape) {
canvas.hideAllCoronas();
}
e.preventDefault();
if (e.which === 3) {
canvas.rightClick = true;
$(canvas.html).trigger("rightclick", [e, canvas]);
}
canvas.isMouseDown = true;
canvas.isMouseDownAndMove = false;
// do not create the rectangle selection if a segment handler
// is being dragged
if (canvas.draggingASegmentHandler) {
return;
}
// clear old selection
canvas.emptyCurrentSelection();
//verify lasso is enabled
if (canvas.lassoEnabled) {
// hide the currentConnection if there's one
canvas.hideCurrentConnection();
canvas.multipleSelectionHelper.reset();
canvas.multipleSelectionHelper.setPosition(x / canvas.zoomFactor,
y / canvas.zoomFactor);
canvas.multipleSelectionHelper.oldX = x;
canvas.multipleSelectionHelper.oldY = y;
canvas.multipleSelectionHelper.setVisible(true);
canvas.multipleSelectionHelper.changeOpacity(0.2);
}
};
};
PMCanvas.prototype.onClick = function (canvas) {
return function (e, ui) {
var currentLabel = canvas.currentLabel, figure, realPoint, realPoint, oldConnection;
if (currentLabel) {
currentLabel.loseFocus();
$(currentLabel.textField).focusout();
}
realPoint = canvas.relativePoint(e);
realPoint.x = realPoint.x * canvas.zoomFactor - canvas.getX();
realPoint.y = realPoint.y * canvas.zoomFactor - canvas.getY();
figure = canvas.getBestConnecion(realPoint);
canvas.hideDropConnectHandlers();
if (figure !== null && !canvas.isMouseDown) {
oldConnection = canvas.currentConnection;
canvas.emptyCurrentSelection();
if (oldConnection) {
oldConnection.hidePortsAndHandlers();
}
figure.showPortsAndHandlers();
canvas.currentConnection = figure;
}
};
};
PMCanvas.prototype.onMouseLeave = function (canvas) {
return function (e, ui) {
if (parseInt(e.screenX + 10, 10) >= parseInt(document.body.clientWidth, 10)) {
window.scrollBy(1, 0);
}
if (parseInt(e.screenY - 75, 10) >= parseInt(document.body.clientHeight, 10)) {
window.scrollBy(0, 1);
}
};
};
PMCanvas.prototype.manualCreateShape = function (parent, e) {
var customShape = this.shapeFactory(this.canCreateShapeType),
command,
endPoint = {},
realPoint = this.relativePoint(e);
endPoint.x = realPoint.x * this.zoomFactor - parent.getAbsoluteX();
endPoint.y = realPoint.y * this.zoomFactor - parent.getAbsoluteY();
endPoint.y -= this.getY();
parent.addElement(customShape, endPoint.x, endPoint.y, false);
this.updatedElement = customShape;
customShape.canvas.emptyCurrentSelection();
this.addToList(customShape);
customShape.showOrHideResizeHandlers(false);
if (customShape.getParent() instanceof PMLane) {
command = new PMCommandCreateInLane(customShape);
} else {
command = new PMUI.command.CommandCreate(customShape);
}
this.commandStack.add(command);
command.execute();
this.addToSelection(customShape);
customShape.corona.show();
e.pageY += customShape.getZoomHeight() / 2;
this.connectProcedure(customShape, e);
this.canCreateShape = false;
this.connectStartShape.corona.hide();
if (this.shapeHelper) {
//remove the connection segment in order to create another one
$(this.shapeHelper.html).remove();
}
if (customShape.getType() === 'PMGateway'
|| customShape.getType() === 'PMEvent') {
customShape.manualCreateMenu(e);
customShape.canvas.hideAllCoronas();
}
};
/**
* Parses `options` creating shapes and connections and placing them in this canvas.
* It does the following:
*
* - Creates each shape (in the same order as it is in the array `options.shapes`)
* - Creates each connection (in the same order as it is in the array `options.connections`)
* - Creates the an instance of {@link PMUI.command.CommandPaste} (if possible)
*
* @param {Object} options
* @param {Array} [options.shapes=[]] The config options of each shape to be placed in this canvas.
* @param {Array} [options.connections=[]] The config options of each connection to be placed in this canvas.
* @param {boolean} [options.uniqueID=false] If set to true, it'll assign a unique ID to each shape created.
* @param {boolean} [options.selectAfterFinish=false] If set to true, it'll add the shapes that are
* direct children of this canvas to `this.currentSelection` arrayList.
* @param {string} [options.prependMessage=""] The message to be prepended to each shape's label.
* @param {boolean} [options.createCommand=true] If set to true it'll create a command for each creation
* of a shape and connection (see {@link PMUI.command.CommandCreate},
{@link PMUI.command.CommandConnect}) and save them in
* a {@link PMUI.command.CommandPaste} (for undo-redo purposes).
* @param {number} [options.diffX=0] The number of pixels on the x-coordinate to move the shape on creation
* @param {number} [options.diffY=0] The number of pixels on the y-coordinate to move the shape on creation
* @chainable
*/
PMCanvas.prototype.parse = function (options) {
var defaults = {
shapes: [],
connections: [],
uniqueID: false,
selectAfterFinish: false,
prependMessage: "",
createCommand: true,
diffX: 0,
diffY: 0
},
i,
j,
id,
oldID,
shape,
points,
shapeOptions,
connection,
connectionOptions,
sourcePort,
sourcePortOptions,
sourceShape,
sourceBorder,
destPort,
destPortOptions,
destShape,
destBorder,
command,
diffX,
diffY,
stackCommandCreate = [],
stackCommandConnect = [],
canvasID = this.getID(),
mapOldId = {},
map = {};
$.extend(true, defaults, options);
// set the differentials (if the shapes are pasted in the canvas)
diffX = defaults.diffX;
diffY = defaults.diffY;
// map the canvas
map[canvasID] = this;
mapOldId[canvasID] = canvasID;
// empty the current selection and sharedConnections as a consequence
// (so that the copy is selected after)
if (defaults.selectAfterFinish) {
this.emptyCurrentSelection();
}
for (i = 0; i < defaults.shapes.length; i += 1) {
shapeOptions = {};
$.extend(true, shapeOptions, defaults.shapes[i]);
// set the canvas of <shape>
shapeOptions.canvas = this;
// create a map of the current id with a new id
oldID = shapeOptions.id;
// generate a unique id on user request
if (defaults.uniqueID) {
shapeOptions.id = PMUI.generateUniqueId();
}
mapOldId[oldID] = shapeOptions.id;
// change labels' messages (using prependMessage)
if (shapeOptions.labels) {
for (j = 0; j < shapeOptions.labels.length; j += 1) {
shapeOptions.labels[j].message = defaults.prependMessage +
shapeOptions.labels[j].message;
}
}
// create an instance of the shape based on its type
shape = this.shapeFactory(shapeOptions.extendedType, shapeOptions);
// map the instance with its id
map[shapeOptions.id] = shape;
// if the shapes don't have a valid parent then set the parent
// to be equal to the canvas
// TODO: ADD shapeOptions.topLeftOnCreation TO EACH SHAPE
if (!mapOldId[shapeOptions.parent]) {
this.addElement(shape,
shapeOptions.x + diffX, shapeOptions.y + diffY, true);
} else if (shapeOptions.parent !== canvasID) {
// get the parent of this shape
map[mapOldId[shapeOptions.parent]].addElement(shape, shapeOptions.x,
shapeOptions.y, true);
} else {
// move the shapes a little (so it can be seen that
// they were duplicated)
map[mapOldId[shapeOptions.parent]].addElement(shape,
shapeOptions.x + diffX, shapeOptions.y + diffY, true);
}
// perform some extra actions defined for each shape
shape.parseHook();
shape.attachListeners();
// execute command create but don't add it to the canvas.commandStack
command = new PMUI.command.CommandCreate(shape);
command.execute();
stackCommandCreate.push(command);
}
for (i = 0; i < defaults.connections.length; i += 1) {
connectionOptions = {};
$.extend(true, connectionOptions, defaults.connections[i]);
// state of the connection
points = connectionOptions.state || [];
// determine the shapes
sourcePortOptions = connectionOptions.srcPort;
sourceShape = map[mapOldId[sourcePortOptions.parent]];
sourceBorder = sourceShape.getBorderConsideringLayers();
destPortOptions = connectionOptions.destPort;
destShape = map[mapOldId[destPortOptions.parent]];
destBorder = destShape.getBorderConsideringLayers();
// populate points if points has no info (backwards compatibility,
// e.g. the flow state is null)
if (points.length === 0) {
points.push({
x: sourcePortOptions.x + sourceShape.getAbsoluteX(),
y: sourcePortOptions.y + sourceShape.getAbsoluteY()
});
points.push({
x: destPortOptions.x + destShape.getAbsoluteX(),
y: destPortOptions.y + destShape.getAbsoluteY()
});
}
//create the ports
sourcePort = new PMUI.draw.Port({
width: 8,
height: 8
});
destPort = new PMUI.draw.Port({
width: 8,
height: 8
});
// add the ports to the shapes
// LOGIC: points is an array of points relative to the canvas.
// CustomShape.addPort() requires that the point passed as an argument
// is respect to the shape, so transform the point's coordinates (also
// consider the border)
sourceShape.addPort(
sourcePort,
points[0].x + diffX + sourceBorder -
sourceShape.getAbsoluteX(),
points[0].y + diffX + sourceBorder -
sourceShape.getAbsoluteY()
);
destShape.addPort(
destPort,
points[points.length - 1].x + diffX + destBorder -
destShape.getAbsoluteX(),
points[points.length - 1].y + diffY + destBorder -
destShape.getAbsoluteY(),
false,
sourcePort
);
connection = this.connectionFactory(
connectionOptions.type,
{
srcPort: sourcePort,
destPort: destPort,
segmentColor: new PMUI.util.Color(92, 156, 204),
canvas: this,
segmentStyle: connectionOptions.segmentStyle
}
);
connection.id = connectionOptions.id || PMUI.generateUniqueId();
if (defaults.uniqueID) {
connection.id = PMUI.generateUniqueId();
}
//set its decorators
connection.setSrcDecorator(new PMUI.draw.ConnectionDecorator({
width: 1,
height: 1,
canvas: this,
decoratorPrefix: connectionOptions.srcDecoratorPrefix,
decoratorType: "source",
parent: connection
}));
connection.setDestDecorator(new PMUI.draw.ConnectionDecorator({
width: 1,
height: 1,
canvas: this,
decoratorPrefix: connectionOptions.destDecoratorPrefix,
decoratorType: "target",
parent: connection
}));
command = new PMUI.command.CommandConnect(connection);
stackCommandConnect.push(command);
// connect the two ports
if (points.length >= 3) {
connection.connect({
algorithm: 'user',
points: connectionOptions.state,
dx: defaults.diffX,
dy: defaults.diffY
});
} else {
connection.connect();
}
connection.setSegmentMoveHandlers();
// add the connection to the canvas, that means insert its html to
// the DOM and adding it to the connections array
this.addConnection(connection);
// now that the connection was drawn try to create the intersections
connection.checkAndCreateIntersectionsWithAll();
//attaching port listeners
sourcePort.attachListeners(sourcePort);
destPort.attachListeners(destPort);
this.triggerCreateEvent(connection, []);
}
// finally add to currentSelection each shape if possible (this method is
// down here because of the zIndex problem with connections)
if (defaults.selectAfterFinish) {
for (id in map) {
if (map.hasOwnProperty(id)) {
if (map[id].family !== 'Canvas') {
this.addToSelection(map[id]);
}
}
}
}
// create command if possible
if (defaults.createCommand) {
this.commandStack.add(new PMUI.command.CommandPaste(this, {
stackCommandCreate: stackCommandCreate,
stackCommandConnect: stackCommandConnect
}));
}
return this;
};
/**
* Fires the {@link PMUI.draw.Canvas#event-removeelement} event,
and elaborates the structure of the object that will
* be passed to the handlers.
* @param {PMUI.draw.CustomShape} shape The shape created
* @param {Array} relatedElements The array with the other elements created
* @chainable
*/
PMCanvas.prototype.triggerRemoveEvent = function (shape, relatedElements) {
if (relatedElements.length === 0) {
if (shape) {
relatedElements.push(shape);
}
}
this.updatedElement = {
id: (shape && shape.id) || null,
type: (shape && shape.type) || null,
relatedObject: shape,
relatedElements: relatedElements
};
this.canvas.hideDragConnectHandlers();
if (shape && shape.corona && shape.getType() !== 'Connection') {
shape.corona.hide();
}
if (shape && shape.validatorMarker) {
shape.validatorMarker.removeBoxMarker();
}
$(this.html).trigger('removeelement');
return this;
};
PMCanvas.prototype.createConnectHandlers = function (resizableStyle, nonResizableStyle) {
var i,
number = 20,
connectHandler;
//add the rest to the mid list
for (i = 0; i < number; i += 1) {
connectHandler = new PMConnectHandler({
parent: this,
zOrder: PMUI.util.Style.MAX_ZINDEX + 4,
representation: new PMUI.draw.Rectangle(),
resizableStyle: resizableStyle,
nonResizableStyle: nonResizableStyle
});
this.dragConnectHandlers.insert(
connectHandler
);
if (!this.html) {
return;
}
this.html.appendChild(connectHandler.getHTML());
connectHandler.setPosition(100, 100);
connectHandler.setCategory("dragConnectHandler");
connectHandler.attachListeners();
connectHandler.paint();
}
for (i = 0; i < number; i += 1) {
connectHandler = new PMConnectHandler({
parent: this,
zOrder: PMUI.util.Style.MAX_ZINDEX + 1,
representation: new PMUI.draw.Rectangle(),
resizableStyle: resizableStyle,
nonResizableStyle: nonResizableStyle
});
this.dropConnectHandlers.insert(
connectHandler
);
if (!this.html) {
return;
}
this.html.appendChild(connectHandler.getHTML());
connectHandler.setPosition(400, 100);
connectHandler.setCategory("dropConnectHandler");
connectHandler.attachListeners();
connectHandler.paint();
}
return this;
};
PMCanvas.prototype.hideDragConnectHandlers = function () {
var connectHandler,
i;
for (i = 0; i < this.dragConnectHandlers.getSize(); i += 1) {
connectHandler = this.dragConnectHandlers.get(i);
connectHandler.setVisible(false);
}
return this;
};
PMCanvas.prototype.hideDropConnectHandlers = function () {
var connectHandler,
i;
for (i = 0; i < this.dropConnectHandlers.getSize(); i += 1) {
connectHandler = this.dropConnectHandlers.get(i);
connectHandler.setVisible(false);
}
return this;
};
PMCanvas.prototype.applyZoom = function (scale) {
this.hideDragConnectHandlers();
this.hideDropConnectHandlers();
PMUI.draw.Canvas.prototype.applyZoom.call(this, scale);
return this;
};
PMCanvas.prototype.existThatName = function (element, name) {
var i,
shape,
result = false;
for (i = 0; i < this.customShapes.getSize(); i += 1) {
shape = this.customShapes.get(i);
if (shape.getID() !== element.getID() && shape.getName() === element.getName()) {
result = true;
break;
}
}
return result;
};
PMCanvas.prototype.validateName = function (element, newText, oldText) {
var result = true;
if ((typeof newText === "string") && (newText.trim() === "")) {
result = false;
PMDesigner.msgFlash("Task/sub-process name can't be empty".translate(), document.body, 'error', 3000, 5);
} else if (this.existThatName(element.parent, newText)) {
result = false;
PMDesigner.msgFlash('This name already exists.'.translate(), document.body, 'error', 3000, 5);
}
return result;
};
PMCanvas.prototype.addConnection = function (conn) {
var shapeElement;
PMUI.draw.Canvas.prototype.addConnection.call(this, conn);
if (conn.flo_state) {
conn.algorithm = 'user';
conn.disconnect(true).connect({
algorithm: 'user',
points: conn.flo_state
});
conn.setSegmentMoveHandlers();
}
conn.updateIncomingAndOutgoingConnections("create");
shapeElement = conn.destPort.getParent();
if (shapeElement instanceof PMGateway) {
shapeElement.evaluateGatewayDirection();
}
shapeElement = conn.srcPort.getParent();
if (shapeElement instanceof PMGateway) {
shapeElement.evaluateGatewayDirection();
}
};
/**
* This method hide all flows into a container (shape);
* @param {BPMNShape} shape
*/
PMCanvas.prototype.hideFlowRecursively = function (shape) {
var i,
child,
j,
flow;
for (i = 0; i < shape.getChildren().getSize(); i += 1) {
child = shape.getChildren().get(i);
for (j = 0; j < child.getPorts().getSize(); j += 1) {
flow = child.getPorts().get(j).connection;
flow.disconnect();
}
if (child.getChildren().getSize() > 0) {
this.hideFlowRecursively(child);
}
}
};
/**
* Remove all selected elements, it destroy the shapes and all references to them.
* @chainable
*/
PMCanvas.prototype.removeElements = function () {
var that = this,
dialogConfirm;
if (!that.canCreateShape && !that.isDragging) {
// Delete shape with a modal Dialog Confirm.
dialogConfirm = new FormDesigner.main.DialogConfirm(null, "warning", "Are you sure you want to delete this element?".translate());
dialogConfirm.onAccept = function () {
that.executeCommandDelete();
};
dialogConfirm.onClose = function () {
PMUI.isDelete = false;
return that;
};
}
return that;
};
/**
* Calls to Delete command and executes the action
* @param {PMCanvas} canvas
*/
PMCanvas.prototype.executeCommandDelete = function () {
// destroy the shapes (also destroy all the references to them)
var command = new PMCommandDelete(this);
this.commandStack.add(command);
command.execute();
return this;
};
PMCanvas.prototype.triggerTaskTypeChangeEvent = function (element) {
this.updatedElement = [{
id: element.id,
type: element.type,
fields: [
{
field: "act_task_type",
oldVal: '',
newVal: this.act_task_type
},
{
field: "act_task_type",
oldVal: '',
newVal: this.act_task_type
}
],
relatedObject: element
}];
$(this.html).trigger('changeelement');
return this;
};
PMCanvas.prototype.buildDiagram = function (diagram) {
var that = this;
this.buildingDiagram = true;
jQuery.each(diagram.laneset, function (index, val) {
laneset = diagram.laneset[index];
if (that.propertiesReview("laneset", laneset)) {
that.loadShape('POOL', laneset, true);
}
});
jQuery.each(diagram.lanes, function (index, val) {
lanes = diagram.lanes[index];
if (that.propertiesReview("lanes", lanes)) {
that.loadShape('LANE', lanes, true);
}
});
jQuery.each(diagram.activities, function (index, val) {
activities = diagram.activities[index];
if (that.propertiesReview("activities", activities)) {
that.loadShape(activities.act_type, activities, true);
}
});
jQuery.each(diagram.events, function (index, val) {
events = diagram.events[index];
if (that.propertiesReview("events", events)) {
that.loadShape(events.evn_type, events, true);
}
});
jQuery.each(diagram.gateways, function (index, val) {
gateways = diagram.gateways[index];
if (that.propertiesReview("gateways", gateways)) {
that.loadShape(gateways.gat_type, gateways, true);
}
});
jQuery.each(diagram.artifacts, function (index, val) {
artifacts = diagram.artifacts[index];
if (that.propertiesReview("artifacts", artifacts)) {
that.loadShape(artifacts.art_type, artifacts, true);
}
});
jQuery.each(diagram.data, function (index, val) {
data = diagram.data[index];
if (that.propertiesReview("data", data)) {
that.loadShape(data.dat_type, data, true);
}
});
jQuery.each(diagram.participants, function (index, val) {
participants = diagram.participants[index];
if (that.propertiesReview("participants", participants)) {
that.loadShape('PARTICIPANT', participants, true);
}
});
jQuery.each(diagram.flows, function (index, val) {
connections = diagram.flows[index];
if (that.propertiesReview("flows", connections)) {
that.loadFlow(connections, true);
}
});
this.buildingDiagram = false;
};
/**
* Adds a start event as a defaul init canvas
*/
PMCanvas.prototype.setDefaultStartEvent = function () {
var customShape = this.shapeFactory('START'),
command;
this.addElement(customShape, 100, 100, customShape.topLeftOnCreation);
this.updatedElement = customShape;
command = new PMUI.command.CommandCreate(customShape);
this.commandStack.add(command);
command.execute();
this.addToSelection(customShape);
customShape.corona.show();
};
PMCanvas.prototype.propertiesReview = function (type, currenShape) {
var passed = true, shape, i;
shape = {
laneset: [],
lanes: [],
activities: [
"act_uid",
"act_name",
"act_type"
],
events: [
"evn_uid",
"evn_name",
"evn_type"
],
gateways: [
"gat_uid",
"gat_name",
"gat_type"
],
flows: [
"flo_uid",
"flo_type",
"flo_element_dest",
"flo_element_origin",
"flo_x1",
"flo_x2",
"flo_y1",
"flo_y2"
],
artifacts: [],
startMessageEvent: [
"evn_uid",
"evn_name",
"evn_type"
],
startTimerEvent: [
"evn_uid",
"evn_name",
"evn_type"
]
};
if (shape[type]) {
for (i = 0; i < shape[type].length; i += 1) {
if (currenShape[shape[type][i]]) {
if (currenShape[shape[type][i]] === null && currenShape[shape[type][i]] === "") {
currenShape[shape[type][i]] = " ";
}
}
}
}
return true;
};
/**
* Loads the shape provided by the shape factory.
* @param type
* @param shape
* @param fireTrigger
* @param businessObject
*/
PMCanvas.prototype.loadShape = function (type, shape, fireTrigger, businessObject) {
var customShape,
command,
transformShape,
container;
transformShape = this.setShapeValues(type, shape);
customShape = this.shapeFactory(type, transformShape);
if (customShape) {
//to import .bpmn diagram
if (businessObject) {
customShape.businessObject = businessObject;
}
customShape.extendedType = type;
if (shape.bou_container === 'bpmnDiagram') {
this.addElement(customShape, parseInt(shape.bou_x, 10), parseInt(shape.bou_y, 10), true);
} else {
container = this.customShapes.find('id', shape.bou_element);
container.addElement(customShape, parseInt(shape.bou_x, 10), parseInt(shape.bou_y, 10), true);
}
this.updatedElement = customShape;
this.addToList(customShape);
customShape.showOrHideResizeHandlers(false);
if (fireTrigger) {
this.triggerCreateEvent(customShape, []);
}
}
};
PMCanvas.prototype.setShapeValues = function (type, options) {
var newShape;
switch (type) {
case "TASK":
case "SUB_PROCESS":
options.width = parseInt(options.bou_width, 10);
options.height = parseInt(options.bou_height, 10);
options.id = options.act_uid;
options.labels = [
{
message: options.act_name
}
];
break;
case "START":
case "END":
case "INTERMEDIATE":
case "BOUNDARY":
options.id = options.evn_uid;
options.labels = [
{
message: options.evn_name
}
];
break;
case "TEXT_ANNOTATION":
case "GROUP":
options.width = parseInt(options.bou_width, 10);
options.height = parseInt(options.bou_height, 10);
options.id = options.art_uid;
options.labels = [
{
message: options.art_name
}
];
break;
case "COMPLEX":
case "EXCLUSIVE":
case "PARALLEL":
case "INCLUSIVE":
case "EVENTBASED":
options.id = options.gat_uid;
options.labels = [
{
message: options.gat_name
}
];
break;
case "DATAOBJECT":
case "DATASTORE":
case "DATAINPUT":
case "DATAOUTPUT":
options.id = options.dat_uid;
options.labels = [
{
message: options.dat_name
}
];
break;
case "PARTICIPANT":
options.id = options.par_uid;
options.width = parseInt(options.bou_width, 10);
options.height = parseInt(options.bou_height, 10);
options.labels = [
{
message: options.par_name
}
];
break;
case "POOL":
options.id = options.lns_uid;
options.width = parseInt(options.bou_width, 10);
options.height = parseInt(options.bou_height, 10);
options.labels = [
{
message: options.lns_name
}
];
break;
case "LANE":
options.id = options.lan_uid;
options.relPosition = parseInt(options.bou_rel_position, 10);
options.width = parseInt(options.bou_width, 10);
options.height = parseInt(options.bou_height, 10);
options.labels = [
{
message: options.lan_name
}
];
break;
}
return options;
};
PMCanvas.prototype.loadFlow = function (conn, trigger) {
var sourceObj,
targetObj,
startPoint,
endPoint,
sourcePort,
targetPort,
connection,
segmentMap = {
'SEQUENCE': 'regular',
'MESSAGE': 'segmented',
'DATAASSOCIATION': 'dotted',
'ASSOCIATION': 'dotted',
'DEFAULT': 'regular',
'CONDITIONAL': 'regular'
},
srcDecorator = {
'SEQUENCE': 'mafe-decorator',
'MESSAGE': 'mafe-message',
'DATAASSOCIATION': 'mafe-association',
'ASSOCIATION': 'mafe-decorator',
'DEFAULT': 'mafe-default',
'CONDITIONAL': 'mafe-decorator_conditional'
},
destDecorator = {
'SEQUENCE': 'mafe-sequence',
'MESSAGE': 'mafe-message',
'DATAASSOCIATION': 'mafe-association',
'ASSOCIATION': 'mafe-decorator_association',
'DEFAULT': 'mafe-sequence',
'CONDITIONAL': 'mafe-sequence'
},
positionSourceX,
positionSourceY,
positionTargetX,
positionTargetY;
sourceObj = this.getElementByUid(conn.flo_element_origin);
targetObj = this.getElementByUid(conn.flo_element_dest);
if (typeof sourceObj === "object" && typeof targetObj === "object") {
startPoint = new PMUI.util.Point(conn.flo_x1, conn.flo_y1);
endPoint = new PMUI.util.Point(conn.flo_x2, conn.flo_y2);
sourcePort = new PMUI.draw.Port({
width: 10,
height: 10
});
targetPort = new PMUI.draw.Port({
width: 10,
height: 10
});
positionSourceX = startPoint.x - sourceObj.absoluteX + this.canvas.absoluteX;
positionSourceY = startPoint.y - sourceObj.absoluteY + this.canvas.absoluteY;
positionTargetX = endPoint.x - targetObj.absoluteX + this.canvas.absoluteX;
positionTargetY = endPoint.y - targetObj.absoluteY + this.canvas.absoluteY;
sourceObj.addPort(sourcePort, positionSourceX, positionSourceY);
targetObj.addPort(targetPort, positionTargetX, positionTargetY, false, sourcePort);
if (!conn.flo_name) {
conn.flo_name = ' ';
}
connection = new PMFlow({
id: conn.flo_uid,
srcPort: sourcePort,
destPort: targetPort,
canvas: this.canvas,
segmentStyle: segmentMap[conn.flo_type],
segmentColor: new PMUI.util.Color(0, 0, 0),
flo_type: conn.flo_type,
name: conn.flo_name,
flo_condition: conn.flo_condition,
flo_state: conn.flo_state,
flo_uid: (conn.flo_uid) ? conn.flo_uid : null
});
connection.setSrcDecorator(new PMUI.draw.ConnectionDecorator({
decoratorPrefix: srcDecorator[conn.flo_type],
decoratorType: "source",
style: {
cssClasses: []
},
width: 11,
height: 11,
canvas: this.canvas,
parent: connection
}));
connection.setDestDecorator(new PMUI.draw.ConnectionDecorator({
decoratorPrefix: destDecorator[conn.flo_type],
decoratorType: "target",
style: {
cssClasses: []
},
width: 11,
height: 11,
canvas: this.canvas,
parent: connection
}));
connection.setSegmentMoveHandlers();
//add the connection to the canvas, that means insert its html to
// the DOM and adding it to the connections array
this.addConnection(connection);
// Filling mafeFlow fields
connection.setTargetShape(targetPort.parent);
connection.setOriginShape(sourcePort.parent);
// now that the connection was drawn try to create the intersections
connection.checkAndCreateIntersectionsWithAll();
//attaching port listeners
sourcePort.attachListeners(sourcePort);
targetPort.attachListeners(targetPort);
this.updatedElement = connection;
if (trigger) {
this.triggerCreateEvent(connection, []);
}
} else {
throw new Error("No elements found to connect.".translate());
}
};
PMCanvas.prototype.getElementByUid = function (uid) {
var element;
element = this.items.find('id', uid);
if (!element) {
element = this.getCustomShapes().find('id', uid);
}
return element.relatedObject;
};
PMCanvas.prototype.createBPMNDiagram = function () {
var bpmnDia = PMDesigner.moddle.create('bpmndi:BPMNDiagram', {id: 'dia_' + PMUI.generateUniqueId()});
var bpmnPlane = PMDesigner.moddle.create('bpmndi:BPMNPlane', {
'bpmnElement': this.businessObject.elem,
id: 'plane_' + PMUI.generateUniqueId()
});
bpmnDia.plane = bpmnPlane;
this.businessObject.diagram = bpmnDia;
PMDesigner.businessObject.get('diagrams').push(bpmnDia);
this.businessObject.di = bpmnPlane;
};
PMCanvas.prototype.createBusinesObject = function (createProcess) {
this.businessObject.elem = {};
var bpmnProcess = PMDesigner.moddle.create('bpmn:Process', {id: 'pmui-' + PMUI.generateUniqueId()});
PMDesigner.businessObject.get('rootElements').push(bpmnProcess);
this.businessObject.elem = bpmnProcess;
if (this.businessObject.di
&& (typeof this.businessObject.di.bpmnElement === 'undefined'
|| !this.businessObject.di.bpmnElement)) {
this.businessObject.di.bpmnElement = this.businessObject.elem;
}
};
PMCanvas.prototype.updateCanvasProcess = function () {
var process,
children;
if (this.businessObject.elem && (_.findWhere(PMDesigner.businessObject.get('rootElements'), {
$type: "bpmn:Process",
id: this.businessObject.elem.id
}))) {
process = _.findWhere(PMDesigner.businessObject.get('rootElements'), {
$type: "bpmn:Process",
id: this.businessObject.elem.id
});
if (process.flowElements.length === 1) {
children = PMDesigner.businessObject.get('rootElements');
CollectionRemove(children, process);
this.businessObject.elem = null;
}
if (this.businessObject.di && this.businessObject.di.planeElement.length <= 1) {
this.removeBPMNDiagram();
}
}
};
PMCanvas.prototype.removeBPMNDiagram = function () {
var dia,
children;
dia = _.findWhere(PMDesigner.businessObject.get('diagrams'), {
$type: "bpmndi:BPMNDiagram",
id: this.businessObject.diagram.id
});
children = PMDesigner.businessObject.get('diagrams');
CollectionRemove(children, dia);
this.businessObject.di = null;
};
PMCanvas.prototype.toogleGridLine = function () {
if (this.isGridLine === true) {
this.disableGridLine();
} else {
this.enableGridLine();
}
//force to update the designer
PMDesigner.project.updateElement([]);
return this.isGridLine;
};
/**
* Disable grid lines, removing the class pmui-pmcanvas
* @returns {PMCanvas}
*/
PMCanvas.prototype.disableGridLine = function () {
this.html.classList.remove("pmui-pmcanvas");
this.isGridLine = false;
return this;
};
/**
* Enable grid lines, adding the class pmui-pmcanvas
* @returns {PMCanvas}
*/
PMCanvas.prototype.enableGridLine = function () {
this.html.classList.add("pmui-pmcanvas");
this.isGridLine = true;
return this;
};
/**
* Return GridLine boolean property
* @returns {PMCanvas}
*/
PMCanvas.prototype.getGridLine = function () {
return this.isGridLine;
};
/**
* Override method "fixSnapData" of PUI.draw.Canvas
*/
PMCanvas.prototype.fixSnapData = function () {
//TODO complete fixSnapData function
};
/**
* Sets and calculate the limits to work with the lasso tool.
* calculate this.lassoLimits to validate if the selected shapes can be dragged surpasses the limits of the canvas.
* @returns {PMCanvas}
*/
PMCanvas.prototype.setLassoLimits = function () {
var minXObj = {
"limit": 99999,
"shape": null
},
minYObj = {
"limit": 99999,
"shape": null
},
shape,
i;
for (i = 0; i < this.currentSelection.getSize(); i += 1) {
shape = this.currentSelection.get(i);
if (shape.getX() < minXObj.limit) {
minXObj = {
"limit": shape.getX(),
"shape": shape
}
}
if (shape.getY() < minYObj.limit) {
minYObj = {
"limit": shape.getY(),
"shape": shape
}
}
}
this.lassoLimits = {
"x": minXObj,
"y": minYObj
};
return this;
};
/**
* @class PMEvent
* @param {Object} options
*/
var PMEvent = function (options) {
PMShape.call(this, options);
/**
* Defines the alphanumeric unique code
* @type {String}
*/
this.evn_uid = null;
/**
* Defines the name
* @type {String}
*/
this.evn_name = null;
/**
* Defines the event type
* @type {String}
*/
this.evn_type = null;
/**
* Defines the event marker supported
* @type {String}
*/
this.evn_marker = null;
/**
* Defines id the event interrups or not the execution
* @type {Boolean}
*/
this.evn_is_interrupting = true;
/**
* Defines the activity attachec when the event is a boundary element
* @type {String}
*/
this.evn_attached_to = null;
/**
* Defines if the event can cancel the activity attached to
* @type {Boolean}
*/
this.evn_cancel_activity = false;
/**
* Define the activity related when event is playing as transactional event
* @type {String}
*/
this.evn_activity_ref = null;
/**
* Defines if the event needs to wait for completation status
* @type {Boolean}
*/
this.evn_wait_for_completion = false;
/**
* Defines the error name when event is playing like an error event
* @type {String}
*/
this.evn_error_name = null;
/**
* Defines the error code when event is playing like an error event
* @type {String}
*/
this.evn_error_code = null;
/**
* Defines the escalation name when event is playing like
* an escalation event
* @type {String}
*/
this.evn_escalation_name = null;
/**
* Defines the escalation name when event is playing like
* an escalation event
* @type {String}
*/
this.evn_escalation_code = null;
/**
* Defines the condition on the event
* @type {String}
*/
this.evn_condition = null;
/**
* Defines the message association
* @type {String}
*/
this.evn_message = null;
/**
* Defines the operation tom be executed when event is used like
* a transactional event
* @type {String}
*/
this.evn_operation_name = null;
/**
* XXXX
* @type {String}
*/
this.evn_operation_implementation_ref = null;
/**
* Defines the date to be executed a timer event
* @type {String}
*/
this.evn_time_date = null;
/**
* Defines the time cycle to be executed a timer event
* @type {String}
*/
this.evn_time_cycle = null;
/**
* Defines the duration of the timer event
* @type {String}
*/
this.evn_time_duration = null;
/**
* Define the behavior of the event. Valid values are: CATCH, THROW
* @type {String}
*/
this.evn_behavior = null;
/**
* Defines the order of the boundary event when is attached to an activity
* @type {Number}
*/
this.numberRelativeToActivity = 0;
this.businessObject = {};
PMEvent.prototype.init.call(this, options);
};
PMEvent.prototype = new PMShape();
/**
* Defines the object type
* @type {String}
*/
PMEvent.prototype.type = 'PMEvent';
/**
* Initialize the object with default values
* @param {Object} options
*/
PMEvent.prototype.mapBpmnType = {
'START': {
'MESSAGECATCH': 'bpmn:MessageEventDefinition',
'TIMER': 'bpmn:TimerEventDefinition',
'CONDITIONAL': 'bpmn:ConditionalEventDefinition',
'SIGNALCATCH': 'bpmn:SignalEventDefinition'
},
'INTERMEDIATE': {
'MESSAGETHROW': 'bpmn:MessageEventDefinition',
'EMAIL': 'bpmn:MessageEventDefinition',
'MESSAGECATCH': 'bpmn:MessageEventDefinition',
'TIMER': 'bpmn:TimerEventDefinition',
'CONDITIONAL': 'bpmn:ConditionalEventDefinition',
'LINKCATCH': 'bpmn:LinkEventDefinition',
'SIGNALCATCH': 'bpmn:SignalEventDefinition',
'LINKTHROW': 'bpmn:LinkEventDefinition',
'COMPENSATIONTHROW': 'bpmn:CompensateEventDefinition',
'SIGNALTHROW': 'bpmn:SignalEventDefinition'
},
'BOUNDARY': {
'MESSAGETHROW': 'bpmn:MessageEventDefinition',
'MESSAGECATCH': 'bpmn:MessageEventDefinition',
'TIMER': 'bpmn:TimerEventDefinition',
'CONDITIONAL': 'bpmn:ConditionalEventDefinition',
'LINKCATCH': 'bpmn:LinkEventDefinition',
'SIGNALCATCH': 'bpmn:SignalEventDefinition',
'LINKTHROW': 'bpmn:LinkEventDefinition',
'COMPENSATIONTHROW': 'bpmn:CompensateEventDefinition',
'SIGNALTHROW': 'bpmn:SignalEventDefinition',
'ERRORCATCH': 'bpmn:ErrorEventDefinition'
},
'END': {
'MESSAGETHROW': 'bpmn:MessageEventDefinition',
'EMAIL': 'bpmn:MessageEventDefinition',
'SIGNALTHROW': 'bpmn:SignalEventDefinition',
'ERRORTHROW': 'bpmn:ErrorEventDefinition',
'CANCELHROW': 'bpmn:EscalationEventDefinition',
'COMPENSATIONTHROW': 'bpmn:CompensateEventDefinition',
'TERMINATETHROW': 'bpmn:TerminateEventDefinition',
'CANCELTHROW': 'bpmn:CancelEventDefinition'
}
};
PMEvent.prototype.supportedList = {
'START': {
'EMPTY': true,
'MESSAGECATCH': true,
'TIMER': true,
'CONDITIONAL': true,
'SIGNALCATCH': true
},
'INTERMEDIATE': {
'MESSAGETHROW': true,
'MESSAGECATCH': true,
'TIMER': true,
'CONDITIONAL': true,
'SIGNALCATCH': true,
'SIGNALTHROW': true,
'EMAIL': true
},
'BOUNDARY': {
'MESSAGETHROW': false,
'MESSAGECATCH': false,
'TIMER': false,
'CONDITIONAL': false,
'LINKCATCH': false,
'SIGNALCATCH': false,
'LINKTHROW': false,
'COMPENSATIONTHROW': false,
'SIGNALTHROW': false,
'ERRORCATCH': false
},
'END': {
'EMPTY': true,
'MESSAGETHROW': true,
'SIGNALTHROW': true,
'ERRORTHROW': true,
'CANCELHROW': false,
'COMPENSATIONTHROW': false,
'TERMINATETHROW': true,
'CANCELTHROW': false,
'EMAIL': true
}
};
PMEvent.prototype.init = function (options) {
var defaults = {
evn_uid: '',
evn_is_interrupting: true,
evn_message: '',
evn_name: '',
evn_marker: 'EMPTY',
evn_type: 'START',
evn_behavior: 'CATCH'
};
jQuery.extend(true, defaults, options);
this.setEventUid(defaults.evn_uid)
.setEventType(defaults.evn_type)
.setEventMarker(defaults.evn_marker)
.setEventMessage(defaults.evn_message)
.setBehavior(defaults.evn_behavior)
.setCondition(defaults.evn_condition)
.setAttachedTo(defaults.evn_attached_to)
.setIsInterrupting(defaults.evn_is_interrupting);
if (defaults.evn_name) {
this.setName(defaults.evn_name);
}
this.setOnBeforeContextMenu(this.beforeContextMenu);
};
/**
* Sets the label element
* @param {String} value
* @return {*}
*/
PMEvent.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.evn_name = name;
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
PMEvent.prototype.getDataObject = function () {
var container,
element_id,
name = this.getName();
switch (this.parent.type) {
case 'PMCanvas':
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
case 'PMPool':
container = 'bpmnPool';
element_id = this.parent.id;
break;
case 'PMLane':
container = 'bpmnLane';
element_id = this.parent.id;
break;
case 'PMActivity':
container = 'bpmnActivity';
element_id = this.parent.id;
break;
default:
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
}
return {
evn_uid: this.id,
evn_name: name,
evn_type: this.evn_type,
evn_marker: this.evn_marker,
evn_is_interrupting: this.evn_is_interrupting,
evn_attached_to: this.evn_attached_to,
evn_cancel_activity: this.evn_cancel_activity,
evn_activity_ref: this.evn_activity_ref,
evn_wait_for_completion: this.evn_wait_for_completion,
evn_error_name: this.evn_error_name,
evn_error_code: this.evn_error_code,
evn_escalation_name: this.evn_escalation_name,
evn_escalation_code: this.evn_escalation_code,
evn_condition: this.evn_condition,
evn_message: this.evn_message,
evn_operation_name: this.evn_operation_name,
evn_operation_implementation_ref: this.evn_operation_implementation_ref,
evn_time_date: this.evn_time_date,
evn_time_cycle: this.evn_time_cycle,
evn_time_duration: this.evn_time_duration,
evn_behavior: this.evn_behavior,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: container,
bou_element: element_id,
_extended: this.getExtendedObject()
};
};
/**
* Sets the event uid property
* @param {String} id
* @return {*}
*/
PMEvent.prototype.setEventUid = function (id) {
this.evn_uid = id;
return this;
};
/**
* Sets the event type property
* @param {String} type
* @return {*}
*/
PMEvent.prototype.setEventType = function (type) {
type = type.toLowerCase();
var defaultTypes = {
start: 'START',
end: 'END',
intermediate: 'INTERMEDIATE',
boundary: 'BOUNDARY'
};
if (defaultTypes[type]) {
this.evn_type = defaultTypes[type];
}
return this;
};
/**
* Sets the event marker property
* @param {String} marker
* @return {*}
*/
PMEvent.prototype.setEventMarker = function (marker) {
this.evn_marker = marker;
return this;
};
/**
* Sets if the event interrups the execution or not
* @param {Boolean} value
* @return {*}
*/
PMEvent.prototype.setIsInterrupting = function (value) {
if (typeof value === "boolean") {
this.evn_is_interrupting = value;
}
return this;
};
/**
* Sets the event behavior property
* @param {String} behavior
* @return {*}
*/
PMEvent.prototype.setBehavior = function (behavior) {
behavior = behavior.toLowerCase();
var defaultBehaviors = {
"catch": 'CATCH',
"throw": 'THROW'
};
if (defaultBehaviors[behavior]) {
this.evn_behavior = defaultBehaviors[behavior];
}
return this;
};
/**
* Sets the activity id where the event is attached to
* @param {String} value
* @param {Boolean} [cancel]
* @return {*}
*/
PMEvent.prototype.setAttachedTo = function (value, cancel) {
if (typeof cancel !== 'undefined') {
if (typeof cancel === "boolean") {
this.evn_cancel_activity = cancel;
}
} else {
this.evn_cancel_activity = this.evn_cancel_activity || false;
}
this.evn_attached_to = value;
return this;
};
/**
* Destroy a event
* @returns {PMEvent}
*/
PMEvent.prototype.destroy = function () {
if (this.getType() === 'PMEvent' && this.getEventType() === 'BOUNDARY') {
if (this.parent.boundaryPlaces && this.numberRelativeToActivity !== null) {
this.parent.boundaryPlaces
.get(this.numberRelativeToActivity)
.available = true;
this.parent.boundaryArray.remove(this);
}
}
return this;
};
/**
* Sets the event message
* @param {String} msg
* @return {*}
*/
PMEvent.prototype.setEventMessage = function (msg) {
this.evn_message = msg;
return this;
};
/**
* Sets the event condition property
* @param {String} value
* @return {*}
*/
PMEvent.prototype.setCondition = function (value) {
this.evn_condition = value;
return this;
};
/**
* Set the compensation properties
* @param {String} activity
* @param {Boolean} wait
* @return {*}
*/
PMEvent.prototype.setCompensationActivity = function (activity, wait) {
if (typeof wait !== 'undefined') {
if (typeof wait === "boolean") {
this.evn_wait_for_completion = wait;
}
} else {
this.evn_wait_for_completion = this.evn_wait_for_completion || false;
}
this.evn_activity_ref = activity;
return this;
};
/**
* Sets the error properties
* @param {String} name Error Name
* @param {String} code Error Code
* @return {*}
*/
PMEvent.prototype.setEventError = function (name, code) {
this.evn_error_name = name;
this.evn_error_code = code;
return this;
};
/**
* Sets the escalation properties
* @param {String} name Escalation Name
* @param {String} code Escalation Code
* @return {*}
*/
PMEvent.prototype.setEventEscalation = function (name, code) {
this.evn_escalation_name = name;
this.evn_escalation_code = code;
return this;
};
/**
* Sets the event operation properties
* @param {String} name
* @param {String} implementation
* @return {*}
*/
PMEvent.prototype.setEventOperation = function (name, implementation) {
this.evn_operation_name = name;
this.evn_operation_implementation_ref = implementation;
return this;
};
/**
* Sets the event timer properties
* @param {String} date
* @param {String} cycle
* @param {String} duration
* @return {*}
*/
PMEvent.prototype.setEventTimer = function (date, cycle, duration) {
this.evn_time_date = date;
this.evn_time_cycle = cycle;
this.evn_time_duration = duration;
return this;
};
/**
* Sets te default_flow property
* @param value
* @return {*}
*/
PMEvent.prototype.setDefaultFlow = function (value) {
PMShape.prototype.setDefaultFlow.call(this, value);
this.evn_default_flow = value;
return this;
};
/**
* Attach the event to an activity
* @return {*}
*/
PMEvent.prototype.attachToActivity = function () {
var numBou = this.parent.getAvailableBoundaryPlace();
if (numBou !== false) {
this.parent.setBoundary(this, numBou);
this.setAttachedTo(this.parent.getID());
this.setNumber(numBou);
} else {
this.destroy();
this.saveAndDestroy();
}
return this;
};
/**
* Sets the number/order of the current event when is attached to an activity
* @param {Number} num
* @return {*}
*/
PMEvent.prototype.setNumber = function (num) {
this.numberRelativeToActivity = num;
return this;
};
PMEvent.prototype.getEventType = function () {
return this.evn_type;
};
PMEvent.prototype.getEventMarker = function () {
return this.evn_marker;
};
PMEvent.prototype.getEventMessage = function () {
return this.evn_message;
};
/**
* Validates if an even has an message connection
* @returns {boolean}
*/
PMEvent.prototype.isAllowed = function () {
var result = true,
i,
connection;
for (i = 0; i < this.getPorts().getSize(); i += 1) {
connection = this.getPorts().get(i).connection;
if (connection.flo_type === 'MESSAGE') {
result = false;
break;
}
}
return result;
};
/**
* Change an event marker
* @return {Object}
*/
PMEvent.prototype.changeMarkerTo = function (type, message) {
var command,
msg;
if (this.isAllowed()) {
command = new CommandChangeEventMarker(this, type);
this.canvas.commandStack.add(command);
command.execute();
} else {
msg = 'Invalid operation: Delete message flow before converting it to '.translate();
PMDesigner.msgFlash(msg + message + ' Event'.translate(), document.body, 'error', 3000, 5);
}
return this;
};
PMEvent.prototype.manualCreateMenu = function (e) {
var endMarker = null;
switch (this.getEventType()) {
case 'END':
endMarker = {
text: "End Event Type".translate(),
icon: "mafe-menu-properties-action",
id: "result",
items: [
{
id: "endempty",
text: "Empty".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('EMPTY');
PMDesigner.project.updateElement([]);
},
disabled: true
},
{
id: "endemail",
text: "Email Message".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('EMAIL');
PMDesigner.project.updateElement([]);
}
},
{
id: "endmessagethrow",
text: "Message".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('MESSAGETHROW');
PMDesigner.project.updateElement([]);
}
},
{
id: "enderrorthrow",
text: "Error".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('ERRORTHROW');
PMDesigner.project.updateElement([]);
}
},
{
id: "endsignalthrow",
text: "Signal".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('SIGNALTHROW');
PMDesigner.project.updateElement([]);
}
},
{
id: "endterminatethrow",
text: "Terminate".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('TERMINATETHROW');
PMDesigner.project.updateElement([]);
}
}
]
};
break;
case 'INTERMEDIATE':
endMarker = intermediateThrowMarker = {
text: "Intermediate Event Type".translate(),
icon: "mafe-menu-properties-action",
id: "result",
items: [
{
id: "intermediateemail",
text: "Email Message".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('EMAIL');
PMDesigner.project.updateElement([]);
},
disabled: true
},
{
id: "intermediatemessagethrow",
text: "Send Message".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('MESSAGETHROW');
PMDesigner.project.updateElement([]);
}
},
{
id: "intermediatesignalthrow",
text: "Signal".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeMarkerTo('SIGNALTHROW');
PMDesigner.project.updateElement([]);
}
}
]
};
break;
}
if (endMarker) {
var tempMenu = new PMUI.menu.Menu(endMarker);
tempMenu.setTargetElement(this);
tempMenu.show(e.pageX, e.pageY + this.getZoomHeight() / 2 + 4);
}
};
PMEvent.prototype.beforeContextMenu = function () {
var items, i,
menuItem,
hasMarker = false;
this.canvas.hideAllCoronas();
if (this.canvas.readOnly) {
return;
}
switch (this.getEventType()) {
case 'END':
items = this.menu.items.find('id', 'result').childMenu.items;
break;
case 'INTERMEDIATE':
case 'START':
if (this.evn_behavior === 'CATCH') {
items = this.menu.items.find('id', 'trigger').childMenu.items;
} else {
items = this.menu.items.find('id', 'result').childMenu.items;
}
break;
default:
items = new PMUI.util.ArrayList();
break;
}
for (i = 0; i < items.getSize(); i += 1) {
menuItem = items.get(i);
if (menuItem.id === this.getEventType().toLowerCase() +
this.getEventMarker().toLowerCase()) {
menuItem.disable();
hasMarker = true;
} else {
menuItem.enable();
}
}
};
/**
* Stringifies the PMEvent object
* @return {Object}
*/
PMEvent.prototype.stringify = function () {
var inheritedJSON = PMShape.prototype.stringify.call(this),
thisJSON = {
evn_marker: this.getEventMarker(),
evn_message: this.getEventMessage(),
evn_condition: this.evn_condition,
evn_attached_to: this.evn_attached_to,
evn_is_interrupting: this.evn_is_interrupting,
evn_behavior: this.evn_behavior
};
jQuery.extend(true, inheritedJSON, thisJSON);
return inheritedJSON;
};
PMEvent.prototype.createBpmn = function (type) {
if (!this.businessObject.elem && !(this instanceof PMUI.draw.MultipleSelectionContainer)) {
this.createWithBpmn(type, 'businessObject');
}
this.updateBounds(this.businessObject.di);
if (this.parent.getType() === 'PMCanvas' && !this.parent.businessObject.di) {
this.canvas.createBPMNDiagram();
}
if (this.parent.businessObject.elem) {
if (this.getEventType() === 'BOUNDARY') {
if (this.parent.parent.getType() === 'PMLane') {
this.updateShapeParent(this.businessObject, this.parent.parent.businessObject);
} else if (this.parent.parent.getType() === 'PMPool') {
this.updateShapeParent(this.businessObject, this.parent.parent.businessObject);
}
} else {
this.updateShapeParent(this.businessObject, this.parent.businessObject);
}
} else {
this.parent.createBusinesObject();
this.updateShapeParent(this.businessObject, this.parent.businessObject);
}
};
PMEvent.prototype.updateBpmn = function () {
this.updateBounds(this.businessObject.di);
if (!this.parent.businessObject.elem) {
this.parent.createBusinesObject();
}
if (this.getEventType() === 'BOUNDARY') {
this.updateShapeParent(this.businessObject, this.parent.parent.businessObject);
} else {
this.updateShapeParent(this.businessObject, this.parent.businessObject);
}
};
/**
* create bpmn object and attach to businessObject event
*/
PMEvent.prototype.createWithBpmn = function (bpmnElementType) {
PMShape.prototype.createWithBpmn.call(this, bpmnElementType, 'businessObject');
this.businessObject.elem.eventDefinitions = [];
if (this.getEventType() === 'BOUNDARY') {
this.businessObject.elem.attachedToRef = this.parent.businessObject.elem;
}
this.createEventDefinition();
};
PMEvent.prototype.createEventDefinition = function () {
var def, type;
if (this.getEventMarker() !== 'EMPTY'
&& this.getEventMarker() !== 'MULTIPLECATCH'
&& this.getEventMarker() !== 'PARALLELCATCH') {
type = this.mapBpmnType[this.getEventType()][this.getEventMarker()];
def = PMDesigner.bpmnFactory.create(type, {id: 'def_' + PMUI.generateUniqueId()});
this.businessObject.elem.eventDefinitions.push(def);
}
};
PMEvent.prototype.updateBpmEventMarker = function (newBpmnType) {
this.businessObject.elem.eventDefinitions = [];
this.createEventDefinition();
};
PMEvent.prototype.isSupported = function () {
var isSupported = false;
if (this.supportedList[this.evn_type][this.getEventMarker()] == true) {
isSupported = true;
}
return isSupported;
};
/**
* PMEvent Properties
*/
PMEvent.prototype.eventProperties = function () {
var typeEventMarker = this.getEventType() + "_" + this.getEventMarker(),
windowMessage,
that = this;
switch (typeEventMarker) {
case "START_TIMER":
case "INTERMEDIATE_TIMER":
PMDesigner.timerEventProperties(that);
break;
case "INTERMEDIATE_EMAIL":
case "END_EMAIL":
PMDesigner.emailEventProperties(that);
break;
case "START_MESSAGECATCH":
case "INTERMEDIATE_MESSAGETHROW":
case "INTERMEDIATE_MESSAGECATCH":
case "END_MESSAGETHROW":
windowMessage = new MessageEventDefinition(that);
break;
}
};
/**
* @class PMActivity
* @param {Object} options
*/
var PMActivity = function (options) {
PMShape.call(this, options);
/**
* Activity Alphanumeric unique identifier
* @type {String}
*/
this.act_uid = null;
/**
* Activity name
* @type {String}
*/
this.act_name = null;
/**
* Activity Type
* @type {String}
*/
this.act_type = null;
/**
* Define if the task is for compensation (BPMN)
* @type {Boolean}
*/
this.act_is_for_compensation = null;
/**
* Define the quantity needed to start the activity
* @type {Number}
*/
this.act_start_quantity = null;
/**
* Define the quantity needed to complete the activity
* @type {Number}
*/
this.act_completion_quantity = null;
/**
* Define the task type.
* @type {String}
*/
this.act_task_type = null;
/**
* Define the task loop type.
* @type {String}
*/
this.act_loop_type = null;
/**
* Define the activity implementation
* @type {String}
*/
this.act_implementation = null;
/**
* Define the instatiation status
* @type {Boolean}
*/
this.act_instantiate = null;
/**
* Define the script type supported
* @type {String}
*/
this.act_script_type = null;
/**
* Define the script
* @type {String}
*/
this.act_script = null;
/**
* Defines the loop type accepted
* @type {String}
*/
this.act_loop_type = null;
/**
* Define if the test to complete the loop would be executed before o later
* @type {Boolean}
*/
this.act_test_before = null;
/**
* Defines the maximum value of loops allowed
* @type {Number}
*/
this.act_loop_maximum = null;
/**
* Defines the loop condition
* @type {String}
*/
this.act_loop_condition = null;
/**
* Defines the loop cardinality
* @type {String}
*/
this.act_loop_cardinality = null;
/**
* Defines the loop behavior
* @type {String}
*/
this.act_loop_behavior = null;
/**
* Define if the activity has an adhoc behavior
* @type {Boolean}
*/
this.act_is_adhoc = null;
/**
* Defines if the activity is collapsed
* @type {Boolean}
*/
this.act_is_collapsed = null;
/**
* Defines the condition needed to complete the activity
* @type {String}
*/
this.act_completion_condition = null;
/**
* Define the order to be executed when exists several task in parallel mode
* @type {Number}
*/
this.act_ordering = null;
/**
* Defines if into a loop all instances would be cancelled
* @type {Boolean}
*/
this.act_cancel_remaining_instances = null;
/**
* Defines the protocol used for the transaction activities
* @type {String}
*/
this.act_protocol = null;
/**
* Define the method to be used when activity consume/execute a web service
* @type {String}
*/
this.act_method = null;
/**
* Define the scope of the activity
* @type {Boolean}
*/
this.act_is_global = null;
/**
* Define the referer to another object (Process, Participant or Another Activity)
* @type {String}
*/
this.act_referer = null;
/**
* Defines the default flow when activity is related to two or more flows
* @type {String}
*/
this.act_default_flow = null;
/**
* Defines the diagram related when activity plays as subprocess
* @type {String}
*/
this.act_master_diagram = null;
/**
* Array of Boundary places created to receive boundary events
* @type {Array}
*/
this.boundaryPlaces = new PMUI.util.ArrayList();
/**
* Array of Boundary events attached to this activity
* @type {Array}
*/
this.boundaryArray = new PMUI.util.ArrayList();
this.isValidDropArea = true;
PMActivity.prototype.init.call(this, options);
};
/**
* Point the prototype to the PMShape Object
* @type {PMShape}
*/
PMActivity.prototype = new PMShape();
/**
* Defines the object type
* @type {String}
*/
PMActivity.prototype.type = 'PMActivity';
/**
* Points to container behavior object
* @type {Object}
*/
PMActivity.prototype.activityContainerBehavior = null;
/**
* Points to the resize behavior object
* @type {Object}
*/
PMActivity.prototype.activityResizeBehavior = null;
PMActivity.prototype.mapBpmnType = {
'EMPTY': 'bpmn:Task',
'SENDTASK': 'bpmn:SendTask',
'RECEIVETASK': 'bpmn:ReceiveTask',
'USERTASK': 'bpmn:UserTask',
'SERVICETASK': 'bpmn:ServiceTask',
'SCRIPTTASK': 'bpmn:ScriptTask',
'MANUALTASK': 'bpmn:ManualTask',
'BUSINESSRULE': 'bpmn:BusinessRuleTask'
};
PMActivity.prototype.supportedArray = [
'EMPTY',
'COLLAPSED',
'SENDTASK',
'RECEIVETASK',
'USERTASK',
'SERVICETASK',
'SCRIPTTASK',
'MANUALTASK',
'BUSINESSRULE'
];
PMActivity.prototype.supportedLoopArray = [
'EMPTY',
'NONE',
'LOOP',
'PARALLEL',
'SEQUENTIAL'
];
PMActivity.prototype.mapLoopTypes = {
'LOOP': 'bpmn:StandardLoopCharacteristics',
'PARALLEL': 'bpmn:MultiInstanceLoopCharacteristics',
'SEQUENTIAL': 'bpmn:MultiInstanceLoopCharacteristics'
};
/**
* Initialize object with default values
* @param options
*/
PMActivity.prototype.init = function (options) {
var defaults = {
act_type: 'TASK',
act_name: 'Task',
act_loop_type: 'NONE',
act_is_for_compensation: false,
act_task_type: 'EMPTY',
act_is_collapsed: false,
act_is_global: false,
act_loop_cardinality: 0,
act_loop_maximum: 0,
act_start_quantity: 1,
act_is_adhoc: false,
act_cancel_remaining_instances: true,
act_instantiate: false,
act_completion_quantity: 0,
act_implementation: '',
act_script: '',
act_script_type: '',
act_default_flow: 0,
minHeight: 50,
minWidth: 100,
maxHeight: 500,
maxWidth: 600
};
jQuery.extend(true, defaults, options);
this.setActivityUid(defaults.act_uid)
.setActName(defaults.act_name)
.setActivityType(defaults.act_type)
.setLoopType(defaults.act_loop_type)
.setIsForCompensation(defaults.act_is_for_compensation)
.setTaskType(defaults.act_task_type)
.setIsCollapsed(defaults.act_is_collapsed)
.setIsGlobal(defaults.act_is_global)
.setLoopCardinality(defaults.act_loop_cardinality)
.setLoopMaximun(defaults.act_loop_maximum)
.setStartQuantity(defaults.act_start_quantity)
.setIsAdhoc(defaults.act_is_adhoc)
.setCancelRemainingInstances(defaults.act_cancel_remaining_instances)
.setInstantiate(defaults.act_instantiate)
.setImplementation(defaults.act_implementation)
.setCompletionQuantity(defaults.act_completion_quantity)
.setScript(defaults.act_script)
.setScriptType(defaults.act_script_type)
.setDefaultFlow(defaults.act_default_flow)
.setMinHeight(defaults.minHeight)
.setMinWidth(defaults.minWidth)
.setMaxHeight(defaults.maxHeight)
.setMaxWidth(defaults.maxWidth);
this.setOnBeforeContextMenu(this.beforeContextMenu);
};
/**
* Sets the label element
* @param {String} value
* @return {*}
*/
PMActivity.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.act_name = name;
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
/**
* Returns the activity type property
* @return {String}
*/
PMActivity.prototype.getActivityType = function () {
return this.act_type;
};
/**
* Returns the is for compensation property
* @return {Boolean}
*/
PMActivity.prototype.getIsForCompensation = function () {
return this.act_is_for_compensation;
};
/**
* Returns if the activity cancel remaining instances when is cancelled
* @return {Boolean}
*/
PMActivity.prototype.getCancelRemainingInstances = function () {
return this.act_cancel_remaining_instances;
};
/**
* Returns the quantity needed to complete an activity
* @return {Number}
*/
PMActivity.prototype.getCompletionQuantity = function () {
return this.act_completion_quantity;
};
/**
* Set is the activity is global (scope)
* @param {Boolean} value
* @return {*}
*/
PMActivity.prototype.getIsGlobal = function () {
return this.act_is_global;
};
/**
* Returns the start quantity needed to start an activity
* @return {Number}
*/
PMActivity.prototype.getStartQuantity = function () {
return this.act_start_quantity;
};
/**
* Returns if the instance is active
* @return {Boolean}
*/
PMActivity.prototype.getInstantiate = function () {
return this.act_instantiate;
};
/**
* Returns the implementation property
* @return {String}
*/
PMActivity.prototype.getImplementation = function () {
return this.act_implementation;
};
/**
* Return the Script property
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.getScript = function () {
return this.act_script;
};
/**
* Return the Script Type property
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.getScriptType = function () {
return this.act_script_type;
};
/**
* Return the minimun height of an activity
* @return {*}
*/
PMActivity.prototype.getMinHeight = function () {
return this.minHeight;
};
/**
* Return the minimun width of an activity
* @return {*}
*/
PMActivity.prototype.getMinWidth = function () {
return this.minWidth;
};
/**
* Return the maximun height of an activity
* @return {*}
*/
PMActivity.prototype.getMaxHeight = function () {
return this.maxHeight;
};
/**
* Return the maximun width of an activity
* @return {*}
*/
PMActivity.prototype.getMaxWidth = function () {
return this.maxWidth;
};
/**
* Sets the act_uid property
* @param {String} value
* @return {*}
*/
PMActivity.prototype.setActivityUid = function (value) {
this.act_uid = value;
return this;
};
/**
* Sets the activity type property
* @param {String} type
* @return {*}
*/
PMActivity.prototype.setActivityType = function (type) {
this.act_type = type;
return this;
};
/**
* Sets the implementation property
* @param {String} type
* @return {*}
*/
PMActivity.prototype.setImplementation = function (type) {
this.act_implementation = type;
return this;
};
/**
* Set the loop type property
* @param {String} type
* @return {*}
*/
PMActivity.prototype.setLoopType = function (type) {
this.act_loop_type = type;
return this;
};
/**
* Sets the collapsed property
* @param {Boolean} value
* @return {*}
*/
PMActivity.prototype.setIsCollapsed = function (value) {
if (typeof value === "boolean") {
this.act_is_collapsed = value;
}
return this;
};
/**
* Sets the is for compensation property
* @param {Boolean} value
* @return {*}
*/
PMActivity.prototype.setIsForCompensation = function (value) {
if (typeof value === "boolean") {
this.act_is_for_compensation = value;
}
return this;
};
/**
* Sets the activity task type
* @param {String} type
* @return {*}
*/
PMActivity.prototype.setTaskType = function (type) {
this.act_task_type = type;
return this;
};
/**
* Sets the activity task type
* @param {String} type
* @return {*}
*/
PMActivity.prototype.setLoopType = function (type) {
this.act_loop_type = type;
return this;
};
/**
* Set is the activity is global (scope)
* @param {Boolean} value
* @return {*}
*/
PMActivity.prototype.setIsGlobal = function (value) {
if (typeof value === "boolean") {
this.act_is_global = value;
}
return this;
};
/**
* Set the loop cardinality of the activity
* @param {String} value
* @return {*}
*/
PMActivity.prototype.setLoopCardinality = function (value) {
this.act_loop_cardinality = value;
return this;
};
/**
* Sets the loop maximun value
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setLoopMaximun = function (value) {
this.act_loop_maximum = value;
return this;
};
/**
* Sets the start quantity needed to start an activity
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setStartQuantity = function (value) {
this.act_start_quantity = value;
return this;
};
/**
* Sets if the activity has an adhoc behavior
* @param {Boolean} value
* @return {*}
*/
PMActivity.prototype.setIsAdhoc = function (value) {
if (typeof value === "boolean") {
this.act_is_adhoc = value;
}
return this;
};
/**
* Sets if the activity cancel remaining instances when is cancelled
* @param {Boolean} value
* @return {*}
*/
PMActivity.prototype.setCancelRemainingInstances = function (value) {
if (typeof value === "boolean") {
this.act_cancel_remaining_instances = value;
}
return this;
};
/**
* Sets if the instance is active
* @param {Boolean} value
* @return {*}
*/
PMActivity.prototype.setInstantiate = function (value) {
if (typeof value === "boolean") {
this.act_instantiate = value;
}
return this;
};
/**
* Sets the quantity needed to complete an activity
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setCompletionQuantity = function (value) {
this.act_completion_quantity = value;
return this;
};
/**
* Sets the Script property
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setScript = function (value) {
this.act_script = value;
return this;
};
/**
* Sets the Script Type property
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setScriptType = function (value) {
this.act_script_type = value;
return this;
};
/**
* Sets te default_flow property
* @param value
* @return {*}
*/
PMActivity.prototype.setDefaultFlow = function (value) {
if (this.html) {
PMShape.prototype.setDefaultFlow.call(this, value);
this.canvas.triggerCommandAdam(this, ['act_default_flow'], [this.act_default_flow], [value]);
}
this.act_default_flow = value;
return this;
};
/**
* Sets the minimun height
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setMinHeight = function (value) {
this.minHeight = value;
return this;
};
/**
* Sets the minimun with
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setMinWidth = function (value) {
this.minWidth = value;
return this;
};
/**
* Sets the maximun height
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setMaxHeight = function (value) {
this.maxHeight = value;
return this;
};
/**
* Sets the maximun with
* @param {Number} value
* @return {*}
*/
PMActivity.prototype.setMaxWidth = function (value) {
this.maxWidth = value;
return this;
};
PMActivity.prototype.setActType = function (type) {
this.act_type = type;
return this;
};
PMActivity.prototype.setActName = function (name) {
this.act_name = name;
return this;
};
/**
* Factory of activity behaviors. It uses lazy instantiation to create
* instances of the different container behaviors
* @param {String} type An string that specifies the container behavior we want
* an instance to have, it can be regular or nocontainer
* @return {ContainerBehavior}
*/
PMActivity.prototype.containerBehaviorFactory = function (type) {
if (type === 'activity') {
if (!this.activityContainerBehavior) {
this.activityContainerBehavior = new ActivityContainerBehavior();
}
return this.activityContainerBehavior;
} else {
return PMShape.prototype.containerBehaviorFactory.call(this, type);
}
};
PMActivity.prototype.dropBehaviorFactory = function (type, selectors) {
if (type === 'pmconnection') {
if (!this.pmConnectionDropBehavior) {
this.pmConnectionDropBehavior = new PMConnectionDropBehavior(selectors);
}
return this.pmConnectionDropBehavior;
} else if (type === 'pmcontainer') {
if (!this.pmContainerDropBehavior) {
this.pmContainerDropBehavior = new PMContainerDropBehavior(selectors);
}
return this.pmContainerDropBehavior;
} else if (type === 'pmactivitydrop') {
if (!this.pmContainerDropBehavior) {
this.pmContainerDropBehavior = new PMActivityDropBehavior(selectors);
}
return this.pmContainerDropBehavior;
} else {
return PMUI.draw.CustomShape.prototype.dropBehaviorFactory.call(this, type, selectors);
}
};
PMActivity.prototype.getDataObject = function () {
var name = this.getName(),
container,
element_id;
switch (this.parent.type) {
case 'PMCanvas':
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
case 'PMPool':
container = 'bpmnPool';
element_id = this.parent.id;
break;
case 'PMLane':
container = 'bpmnLane';
element_id = this.parent.id;
break;
default:
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
}
return {
act_uid: this.id,
act_name: name,
act_type: this.act_type,
act_task_type: this.act_task_type,
act_loop_type: this.act_loop_type,
act_is_for_compensation: this.act_is_for_compensation,
act_start_quantity: this.act_start_quantity,
act_completion_quantity: this.act_completion_quantity,
act_implementation: this.act_implementation,
act_instantiate: this.act_instantiate,
act_script_type: this.act_script_type,
act_script: this.act_script,
act_loop_type: this.act_loop_type,
act_test_before: this.act_test_before,
act_loop_maximum: this.act_loop_maximum,
act_loop_condition: this.act_loop_condition,
act_loop_cardinality: this.act_loop_cardinality,
act_loop_behavior: this.act_loop_behavior,
act_is_adhoc: this.act_is_adhoc,
act_is_collapsed: this.act_is_collapsed,
act_completion_condition: this.act_completion_condition,
act_ordering: this.act_ordering,
act_cancel_remaining_instances: this.act_cancel_remaining_instances,
act_protocol: this.act_protocol,
act_method: this.act_method,
act_is_global: this.act_is_global,
act_referer: this.act_referer,
act_default_flow: this.act_default_flow,
act_master_diagram: this.act_master_diagram,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: container,
bou_element: element_id,
_extended: this.getExtendedObject()
};
};
/**
* Create/Initialize the boundary places array
* @return {*}
*/
PMActivity.prototype.makeBoundaryPlaces = function () {
var bouX,
bouY,
factor = 3,
space,
number = 0,
shape = this.boundaryArray.getFirst(),
numBottom = 0,
numLeft = 0,
numTop = 0,
numRight = 0;
//BOTTON
bouY = shape.parent.getHeight() - shape.getHeight() / 2;
bouX = shape.parent.getWidth() - (numBottom + 1) * (shape.getWidth() + factor);
while (bouX + shape.getWidth() / 2 > 0) {
space = {};
space.x = bouX;
space.y = bouY;
space.available = true;
space.number = number;
space.location = 'BOTTOM';
shape.parent.boundaryPlaces.insert(space);
number += 1;
numBottom += 1;
bouX = shape.parent.getWidth() - (numBottom + 1) * (shape.getWidth() + factor);
}
//LEFT
bouY = shape.parent.getHeight() - (numLeft + 1) * (shape.getHeight() + factor);
bouX = -shape.getHeight() / 2;
while (bouY + shape.getHeight() / 2 > 0) {
space = {};
space.x = bouX;
space.y = bouY;
space.available = true;
space.number = number;
space.location = 'LEFT';
shape.parent.boundaryPlaces.insert(space);
number += 1;
numLeft += 1;
bouY = shape.parent.getHeight() - (numLeft + 1) * (shape.getHeight() + factor);
}
//TOP
bouY = -shape.getWidth() / 2;
bouX = numTop * (shape.getWidth() + factor);
while (bouX + shape.getWidth() / 2 < shape.parent.getWidth()) {
space = {};
space.x = bouX;
space.y = bouY;
space.available = true;
space.number = number;
space.location = 'TOP';
shape.parent.boundaryPlaces.insert(space);
number += 1;
numTop += 1;
bouX = numTop * (shape.getWidth() + factor);
}
//RIGHT
bouY = numRight * (shape.getHeight() + factor);
bouX = shape.parent.getWidth() - shape.getWidth() / 2;
while (bouY + shape.getHeight() / 2 < shape.parent.getHeight()) {
space = {};
space.x = bouX;
space.y = bouY;
space.available = true;
space.number = number;
space.location = 'RIGHT';
shape.parent.boundaryPlaces.insert(space);
number += 1;
numRight += 1;
bouY = numRight * (shape.getHeight() + factor);
}
return this;
};
/**
* Sets the boundary element to a selected boundary place
* @param {PMEvent} shape
* @param {Number} number
* @return {*}
*/
PMActivity.prototype.setBoundary = function (shape, number) {
var bouPlace = this.boundaryPlaces.get(number);
bouPlace.available = false;
shape.setPosition(bouPlace.x, bouPlace.y);
return this;
};
/**
* Returns the current place available to attach boundary events.
* Retuns false if there's not place available
* @return {Number/Boolean}
*/
PMActivity.prototype.getAvailableBoundaryPlace = function () {
var place = 0,
bouPlace,
sw = true,
i;
for (i = 0; i < this.boundaryPlaces.getSize(); i += 1) {
bouPlace = this.boundaryPlaces.get(i);
if (bouPlace.available && sw) {
place = bouPlace.number;
sw = false;
}
}
if (sw) {
place = false;
}
return place;
};
/**
* Update Boundary Places Array
* @return {*}
*/
PMActivity.prototype.updateBoundaryPlaces = function () {
var i,
aux,
k = 0;
aux = new PMUI.util.ArrayList();
for (i = 0; i < this.boundaryPlaces.getSize(); i += 1) {
aux.insert(this.boundaryPlaces.get(i));
}
this.boundaryPlaces.clear();
this.makeBoundaryPlaces();
for (i = 0; i < this.boundaryPlaces.getSize(); i += 1) {
if (k < aux.getSize()) {
this.boundaryPlaces.get(i).available = aux.get(k).available;
k += 1;
}
}
return this;
};
/**
* Returns the number of boundary events attached to this activity
* @return {Number}
*/
PMActivity.prototype.getNumberOfBoundaries = function () {
var child,
i,
bouNum = 0;
for (i = 0; i < this.getChildren().getSize(); i += 1) {
child = this.getChildren().get(i);
if (child.getType() === 'PMEvent' && child.evn_type === 'BOUNDARY') {
bouNum = bouNum + 1;
}
}
return bouNum;
};
/**
* Updates boundary positions when exists a change into the boundary array
* @param {Boolean} createIntersections
*/
PMActivity.prototype.updateBoundaryPositions = function (createIntersections) {
var child,
port,
i,
j;
if (this.getNumberOfBoundaries() > 0) {
this.updateBoundaryPlaces();
for (i = 0; i < this.getChildren().getSize(); i += 1) {
child = this.getChildren().get(i);
if (child.getType() === 'PMEvent'
&& child.evn_type === 'BOUNDARY') {
child.setPosition(this.boundaryPlaces.get(child.numberRelativeToActivity).x,
this.boundaryPlaces.get(child.numberRelativeToActivity).y
);
for (j = 0; j < child.ports.getSize(); j += 1) {
port = child.ports.get(j);
port.setPosition(port.x, port.y);
port.connection.disconnect().connect();
if (createIntersections) {
port.connection.setSegmentMoveHandlers();
port.connection.checkAndCreateIntersectionsWithAll();
}
}
}
}
}
};
PMActivity.prototype.getActivityType = function () {
return this.act_type;
};
PMActivity.prototype.getContextMenu = function () {
};
PMActivity.prototype.getTaskType = function () {
return this.act_task_type;
};
PMActivity.prototype.getLoopType = function () {
return this.act_loop_type;
};
PMActivity.prototype.updateDefaultFlow = function (destID) {
this.act_default_flow = destID;
return this;
};
PMActivity.prototype.updateTaskType = function (newType) {
return this;
};
PMActivity.prototype.updateScriptType = function (newType) {
return this;
};
PMActivity.prototype.changeColor = function (newTheme) {
switch (newTheme) {
case 'red':
newClass = 'mafe-activity-task-' + newTheme;
break;
case 'green':
newClass = 'mafe-activity-task-' + newTheme;
break;
case 'orange':
newClass = 'mafe-activity-task-' + newTheme;
break;
case 'silver':
newClass = 'mafe-activity-task-' + newTheme;
break;
default:
newClass = 'mafe-activity-task';
break;
}
var firstLayer = this.getLayers().asArray()[0];
//remove custom clasess
firstLayer.style.removeClasses(['mafe-activity-task', 'mafe-activity-task-red', 'mafe-activity-task-green', 'mafe-activity-task-orange', 'mafe-activity-task-silver']);
//add the new class
firstLayer.style.addClasses([newClass]);
return this;
};
PMActivity.prototype.setResizeBehavior = function (behavior) {
var factory = new PMUI.behavior.BehaviorFactory({
products: {
"regularresize": PMUI.behavior.RegularResizeBehavior,
"Resize": PMUI.behavior.RegularResizeBehavior,
"yes": PMUI.behavior.RegularResizeBehavior,
"resize": PMUI.behavior.RegularResizeBehavior,
"noresize": PMUI.behavior.NoResizeBehavior,
"NoResize": PMUI.behavior.NoResizeBehavior,
"no": PMUI.behavior.NoResizeBehavior,
"activityResize": PMActivityResizeBehavior
},
defaultProduct: "noresize"
});
this.resizeBehavior = factory.make(behavior);
if (this.html) {
this.resize.init(this);
}
return this;
};
/**
* Change task type
* @param {String} type
* @returns {*}
*/
PMActivity.prototype.switchTaskType = function (type) {
var marker = this.markersArray.get(0),
lowerType = type.toLowerCase();
marker.removeAllClasses();
marker.setMarkerZoomClasses([
"mafe-" + lowerType + "-marker-10",
"mafe-" + lowerType + "-marker-15",
"mafe-" + lowerType + "-marker-21",
"mafe-" + lowerType + "-marker-26",
"mafe-" + lowerType + "-marker-31"
]);
marker.paint(true);
this.setTaskType(type);
this.paint();
this.updateBpmnTaskType(this.mapBpmnType[this.getTaskType()]);
PMDesigner.connectValidator.bpmnValidator();
return this;
};
/**
* Change subprocess type
* @param {String} type
* @returns {*}
*/
PMActivity.prototype.switchSubProcessType = function (type) {
var marker = this.markersArray.get(0),
lowerType = type.toLowerCase();
marker.removeAllClasses();
marker.setMarkerZoomClasses([
"mafe-" + lowerType + "-marker-10",
"mafe-" + lowerType + "-marker-15",
"mafe-" + lowerType + "-marker-21",
"mafe-" + lowerType + "-marker-26",
"mafe-" + lowerType + "-marker-31"
]);
marker.paint(true);
this.setTaskType(type);
this.paint();
return this;
};
PMActivity.prototype.executeLoopType = function (type) {
var marker = this.markersArray.get(1),
lowerType = type.toLowerCase();
marker.removeAllClasses();
marker.setMarkerZoomClasses([
"mafe-" + lowerType + "-marker-10",
"mafe-" + lowerType + "-marker-15",
"mafe-" + lowerType + "-marker-21",
"mafe-" + lowerType + "-marker-26",
"mafe-" + lowerType + "-marker-31"
]);
marker.paint(true);
this.setLoopType(type);
this.paint();
this.updateBpmnTaskType(this.mapBpmnType[this.getTaskType()], this.getLoopType());
PMDesigner.connectValidator.bpmnValidator();
return this;
};
/**
* this method admin thw activity loop types
* @param type
* @param shape
*/
PMActivity.prototype.switchLoopType = function (type) {
var data = {
act_uid: this.getID()
},
self = this,
url = '/project/' + PMDesigner.project.id + '/activity/validate-active-cases';
PMDesigner.restApi.execute({
data: JSON.stringify(data),
method: "update",
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + url,
success: function (data, textStatus, xhr) {
if (data.result) {
self.executeLoopType(type);
} else {
PMDesigner.msgFlash(data.message, document.body, 'error', 3000, 5);
}
},
error: function (xhr, textStatus, errorThrown) {
PMDesigner.msgFlash('There are problems updating the Loop Marker'.translate(), document.body, 'error', 3000, 5);
}
});
};
PMActivity.prototype.beforeContextMenu = function () {
var items, i,
menuItem,
hasMarker = false;
this.canvas.hideAllCoronas();
if (this.canvas.readOnly) {
return;
}
if (this.getActivityType() === 'TASK') {
items = this.menu.items.find('id', 'taskType').childMenu.items;
for (i = 0; i < items.getSize(); i += 1) {
menuItem = items.get(i);
if (menuItem.id === this.getTaskType().toLowerCase()) {
menuItem.disable();
hasMarker = true;
} else {
menuItem.enable();
}
}
items = this.menu.items.find('id', 'loopType').childMenu.items;
for (i = 0; i < items.getSize(); i += 1) {
menuItem = items.get(i);
if (menuItem.id === this.getLoopType().toLowerCase()) {
menuItem.disable();
hasMarker = true;
} else {
menuItem.enable();
}
}
}
};
/**
* updates XML task type tag, removes the current tag and create a new updated
* @param newBpmnType
* @param loopType
*/
PMActivity.prototype.updateBpmnTaskType = function (newBpmnType, loopType) {
var tempID = this.businessObject.elem.id,
outgoing,
incoming;
outgoing = (this.businessObject.elem && this.businessObject.elem.outgoing) ?
this.businessObject.elem.outgoing : null;
incoming = (this.businessObject.elem && this.businessObject.elem.incoming) ?
this.businessObject.elem.incoming : null;
this.removeBpmn();
this.businessObject.elem = null;
this.createBpmn(newBpmnType);
this.businessObject.elem.id = tempID;
this.businessObject.elem.incoming = (incoming) ? incoming : null;
this.businessObject.elem.outgoing = (outgoing) ? outgoing : null;
if (loopType && typeof loopType !== 'undefined' && loopType !== 'EMPTY') {
this.createLoopCharacteristics(this.businessObject.elem, loopType);
}
};
PMActivity.prototype.getBpmnElementType = function () {
if (this.extendedType === 'SUB_PROCESS') {
return 'bpmn:SubProcess';
} else {
return this.mapBpmnType[this.getTaskType()];
}
};
PMActivity.prototype.isSupported = function () {
var isSupported = false;
if (this.supportedArray.indexOf(this.getTaskType()) !== -1) {
isSupported = true;
if (this.getTaskType() != "COLLAPSED") {
if (this.supportedLoopArray.indexOf(this.getLoopType()) !== -1) {
isSupported = true;
} else {
isSupported = false;
}
}
}
return isSupported;
};
/**
* Creates XML Loop task tag to export.
* @param element
* @param loopType
*/
PMActivity.prototype.createLoopCharacteristics = function (element, loopType) {
var loopTypeA,
loopChar = {
isSequential: false,
behavior: 'All'
};
loopTypeA = this.mapLoopTypes[loopType];
element['loopCharacteristics'] = PMDesigner.bpmnFactory.create(loopTypeA, loopChar);
if (loopType == "SEQUENTIAL") {
element['loopCharacteristics'].set('isSequential', true);
} else {
element['loopCharacteristics'].set('isSequential', false);
}
};
PMActivity.prototype.createBpmn = function (type) {
if (!this.businessObject.elem && !(this instanceof PMUI.draw.MultipleSelectionContainer)) {
this.createWithBpmn(type, 'businessObject');
}
this.updateBounds(this.businessObject.di);
if (this.parent.getType() === 'PMCanvas' && !this.parent.businessObject.di) {
this.canvas.createBPMNDiagram();
}
//LOOP characteristics
if (this.act_loop_type && this.act_loop_type !== "EMPTY") {
this.createLoopCharacteristics(this.businessObject.elem, this.act_loop_type);
}
if (this.parent.businessObject.elem) {
this.updateShapeParent(this.businessObject, this.parent.businessObject);
} else {
//Here create busines object to new process
this.parent.createBusinesObject();
this.updateShapeParent(this.businessObject, this.parent.businessObject);
}
};
/**
* @class PMGateway
* @param {Object} options
*/
var PMGateway = function (options) {
PMShape.call(this, options);
/**
* Gateway id
* @type {String}
*/
this.gat_uid = null;
/**
* Gateway name
* @type {String}
*/
this.gat_name = null;
/**
* Gateway type, accept only: 'exclusive' and 'parallel' values
* @type {String}
*/
this.gat_type = null;
/**
* Gateway Direction, accept only 'unspecified', 'converging', 'diverging',
* 'mixed'
* @type {String}
*/
this.gat_direction = null;
/**
* Instantiate property
* @type {String}
*/
this.gat_instantiate = null;
/**
* Event Gatewat Type property
* @type {String}
*/
this.gat_event_gateway_type = null;
/**
* Activation Count property
* @type {Number}
*/
this.gat_activation_count = null;
/**
* WaitingForStart property
* @type {Boolean}
*/
this.gat_waiting_for_start = null;
/**
* Default Flow property
* @type {null}
*/
this.gat_default_flow = null;
this.defaltFlowMenuItem = null;
this.businessObject = {};
PMGateway.prototype.init.call(this, options);
};
PMGateway.prototype = new PMShape();
/**
* Defines the object type
* @type {String}
*/
PMGateway.prototype.type = 'PMGateway';
/**
* Get data about object
*
*/
PMGateway.prototype.mapBpmnType = {
'EXCLUSIVE': 'bpmn:ExclusiveGateway',
'INCLUSIVE': 'bpmn:InclusiveGateway',
'PARALLEL': 'bpmn:ParallelGateway',
'COMPLEX': 'bpmn:ComplexGateway',
'EVENTBASED': 'bpmn:EventBasedGateway'
};
PMGateway.prototype.supportedArray = [
'EXCLUSIVE',
'INCLUSIVE',
'PARALLEL'
];
PMGateway.prototype.getDataObject = function () {
var name = this.getName(),
container,
element_id;
switch (this.parent.type) {
case 'PMCanvas':
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
case 'PMPool':
container = 'bpmnPool';
element_id = this.parent.id;
break;
case 'PMLane':
container = 'bpmnLane';
element_id = this.parent.id;
break;
default:
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
}
return {
gat_uid: this.getID(),
gat_name: name,
gat_type: this.gat_type,
gat_direction: this.gat_direction,
gat_instantiate: this.gat_instantiate,
gat_event_gateway_type: this.gat_event_gateway_type,
gat_activation_count: this.gat_activation_count,
gat_waiting_for_start: this.gat_waiting_for_start,
gat_default_flow: this.gat_default_flow,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: container,
bou_element: element_id,
_extended: this.getExtendedObject()
};
};
/**
* Initialize the PMGateway object
* @param options
*/
PMGateway.prototype.init = function (options) {
var defaults = {
gat_direction: 'DIVERGING',
gat_instantiate: false,
gat_event_gateway_type: 'NONE',
gat_activation_count: 0,
gat_waiting_for_start: true,
gat_type: 'COMPLEX',
gat_name: "Gateway",
gat_default_flow: 0
};
jQuery.extend(true, defaults, options);
this.setGatewayUid(defaults.gat_uid)
.setGatewayType(defaults.gat_type)
.setDirection(defaults.gat_direction)
.setInstantiate(defaults.gat_instantiate)
.setEventGatewayType(defaults.gat_event_gateway_type)
.setActivationCount(defaults.gat_activation_count)
.setWaitingForStart(defaults.gat_waiting_for_start)
.setDefaultFlow(defaults.gat_default_flow);
if (defaults.gat_name) {
this.setName(defaults.gat_name);
}
this.setOnBeforeContextMenu(this.beforeContextMenu);
};
/**
* Sets the Gateway ID
* @param id
* @return {*}
*/
PMGateway.prototype.setGatewayUid = function (id) {
this.gat_uid = id;
return this;
};
/**
* Sets the label element
* @param {String} value
* @return {*}
*/
PMGateway.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.gat_name = name;
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
/**
* Sets the gateway type
* @param type
* @return {*}
*/
PMGateway.prototype.setGatewayType = function (type) {
type = type.toUpperCase();
var defaultTypes = {
COMPLEX: 'COMPLEX',
EXCLUSIVE: 'EXCLUSIVE',
PARALLEL: 'PARALLEL',
INCLUSIVE: 'INCLUSIVE',
EVENTBASED: 'EVENTBASED',
EXCLUSIVEEVENTBASED: 'EXCLUSIVEEVENTBASED',
PARALLELEVENTBASED: 'PARALLELEVENTBASED'
};
if (defaultTypes[type]) {
this.gat_type = defaultTypes[type];
}
return this;
};
/**
* Sets the Gateway direction
* @param direction
* @return {*}
*/
PMGateway.prototype.setDirection = function (direction) {
if (typeof direction !== 'undefined') {
direction = direction.toLowerCase();
var defaultDir = {
unspecified: 'UNSPECIFIED',
diverging: 'DIVERGING',
converging: 'CONVERGING',
mixed: 'MIXED'
};
if (defaultDir[direction]) {
this.gat_direction = defaultDir[direction];
}
}
return this;
};
/**
* Sets the instantiate property
* @param value
* @return {*}
*/
PMGateway.prototype.setInstantiate = function (value) {
this.gat_instantiate = value;
return this;
};
/**
* Sets the event_gateway_type property
* @param value
* @return {*}
*/
PMGateway.prototype.setEventGatewayType = function (value) {
this.gat_event_gateway_type = value;
return this;
};
/**
* Sets the activation_count property
* @param value
* @return {*}
*/
PMGateway.prototype.setActivationCount = function (value) {
this.gat_activation_count = value;
return this;
};
/**
* Sets the waiting_for_start property
* @param value
* @return {*}
*/
PMGateway.prototype.setWaitingForStart = function (value) {
this.gat_waiting_for_start = value;
return this;
};
/**
* Sets te default_flow property
* @param value
* @return {*}
*/
PMGateway.prototype.setDefaultFlow = function (value) {
if (this.html) {
PMShape.prototype.setDefaultFlow.call(this, value);
}
this.gat_default_flow = value;
return this;
};
PMGateway.prototype.getGatewayType = function () {
return this.gat_type;
};
PMGateway.prototype.createConfigureAction = function () {
};
PMGateway.prototype.cleanFlowConditions = function () {
var i, port, connection, oldValues;
for (i = 0; i < this.getPorts().getSize(); i += 1) {
port = this.getPorts().get(i);
connection = port.connection;
if (connection.srcPort.parent.getID() === this.getID()) {
oldValues = {
condition: connection.getFlowCondition(),
type: connection.getFlowType()
};
connection.setFlowCondition('');
connection.canvas
.triggerFlowConditionChangeEvent(connection, oldValues);
}
}
};
PMGateway.prototype.updateGatewayType = function (newType) {
};
PMGateway.prototype.updateDirection = function (newDirection) {
};
PMGateway.prototype.updateDefaultFlow = function (destID) {
};
PMGateway.prototype.changeTypeTo = function (type) {
var command = new CommandChangeGatewayType(this, type);
this.canvas.commandStack.add(command);
command.execute();
return this;
};
/**
* Sets te default_flow property
* @param value
* @return {*}
*/
PMGateway.prototype.setDefaultFlow = function (value) {
if (this.html) {
PMShape.prototype.setDefaultFlow.call(this, value);
}
this.gat_default_flow = value;
return this;
};
PMGateway.prototype.manualCreateMenu = function (e) {
var tempMenu = new PMUI.menu.Menu({
text: "Gateway Type".translate(),
icon: "mafe-menu-properties-action",
id: "gatewaytype",
items: [
{
id: "gatewayexclusive",
text: "Exclusive (XOR) Gateway".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeTypeTo('EXCLUSIVE');
PMDesigner.project.updateElement([]);
},
disabled: true
},
{
id: "gatewayparallel",
text: "Parallel (AND) Gateway".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeTypeTo('PARALLEL');
PMDesigner.project.updateElement([]);
}
},
{
id: "gatewayinclusive",
text: "Inclusive (OR) Gateway".translate(),
onClick: function (menuOption) {
var targetElement = menuOption
.getMenuTargetElement();
targetElement.changeTypeTo('INCLUSIVE');
PMDesigner.project.updateElement([]);
}
}
]
});
tempMenu.setTargetElement(this);
tempMenu.show(e.pageX, e.pageY + this.getZoomHeight() / 2 + 4);
};
PMGateway.prototype.beforeContextMenu = function () {
var i,
port,
connection,
shape,
defaultflowItems = [],
items,
name,
target,
menuItem,
hasMarker;
this.canvas.hideAllCoronas();
if (this.canvas.readOnly) {
return;
}
items = this.menu.items.find('id', 'gatewaytype').childMenu.items;
for (i = 0; i < items.getSize(); i += 1) {
menuItem = items.get(i);
if (menuItem.id === 'gateway' +
this.getGatewayType().toLowerCase()) {
menuItem.disable();
hasMarker = true;
} else {
menuItem.enable();
}
}
defaultflowItems.push({
text: 'None'.translate(),
id: 'emptyFlow',
disabled: (0 === parseInt(this.gat_default_flow)) ? true : false,
onClick: function (menuOption) {
target = menuOption.getMenuTargetElement();
var cmd = new CommandDefaultFlow(target, 0);
cmd.execute();
target.canvas.commandStack.add(cmd);
}
});
for (i = 0; i < this.getPorts().getSize(); i += 1) {
port = this.getPorts().get(i);
connection = port.connection;
if (connection.srcPort.parent.getID() === this.getID()) {
shape = connection.destPort.parent;
switch (shape.getType()) {
case 'PMActivity':
name = (shape.getName() !== '') ? shape.getName() : 'Task'
.translate();
break;
case 'PMEvent':
name = (shape.getName() !== '') ? shape.getName() : 'Event'
.translate();
break;
case 'PMGateway':
name = (shape.getName() !== '') ? shape.getName() : 'Gateway'
.translate();
break;
}
defaultflowItems.push(
{
text: name,
id: connection.getID(),
disabled: (connection.getID() === this.gat_default_flow),
onClick: function (menuOption) {
target = menuOption.getMenuTargetElement();
//target.setDefaultFlow(menuOption.id);
var cmd = new CommandDefaultFlow(target, menuOption.id);
cmd.execute();
target.canvas.commandStack.add(cmd);
}
});
}
}
if (this.defaltFlowMenuItem) {
this.menu.removeItem('defaultflowMenu');
}
if ((defaultflowItems.length > 0) && (this.gat_type !== "PARALLEL")) {
this.defaltFlowMenuItem = {
id: 'defaultflowMenu',
text: "Default Flow".translate(),
items: defaultflowItems
};
var last = this.menu.items.getLast();
this.menu.addItem(this.defaltFlowMenuItem);
this.menu.addItem(last);
}
};
PMGateway.prototype.updateBpmGatewayType = function (newBpmnType) {
var outgoing,
incoming;
outgoing = ( this.businessObject.elem && this.businessObject.elem.outgoing) ?
this.businessObject.elem.outgoing : null;
incoming = ( this.businessObject.elem && this.businessObject.elem.incoming) ?
this.businessObject.elem.incoming : null;
this.removeBpmn();
this.businessObject.elem = null;
this.createBpmn(newBpmnType);
this.businessObject.elem.incoming = (incoming) ? incoming : null;
this.businessObject.elem.outgoing = (outgoing) ? outgoing : null;
};
PMGateway.prototype.isSupported = function () {
var isSupported = false;
if (this.supportedArray.indexOf(this.getGatewayType()) !== -1) {
isSupported = true;
}
return isSupported;
};
/**
* Evaluates the gateway address, according to the amount of input and output connections, by default use Diverging.
* Converging multiples inputs and only an output.
* Diverging an input and an output.
* Diverging multiples inputs output and multiples outputs.
* @returns {PMGateway}
*/
PMGateway.prototype.evaluateGatewayDirection = function () {
var incomings = this.getIncomingConnections('SEQUENCE', 'DEFAULT') || [],
outgoings = this.getOutgoingConnections('SEQUENCE', 'DEFAULT') || [],
direction;
if (incomings.length > 1 && outgoings.length === 1) {
direction = "CONVERGING";
} else {
direction = "DIVERGING";
}
this.setDirection(direction);
return this;
};
/**
* @inheritdoc
**/
PMGateway.prototype.setIncomingConnections = function() {
PMShape.prototype.setIncomingConnections.apply(this, arguments);
return this.evaluateGatewayDirection();
};
/**
* @inheritdoc
**/
PMGateway.prototype.addIncomingConnection = function() {
PMShape.prototype.addIncomingConnection.apply(this, arguments);
return this.evaluateGatewayDirection();
};
/**
* @inheritdoc
**/
PMGateway.prototype.removeIncomingConnection = function() {
PMShape.prototype.removeIncomingConnection.apply(this, arguments);
return this.evaluateGatewayDirection();
};
/**
* @inheritdoc
**/
PMGateway.prototype.setOutgoingConnections = function() {
PMShape.prototype.setOutgoingConnections.apply(this, arguments);
return this.evaluateGatewayDirection();
};
/**
* @inheritdoc
**/
PMGateway.prototype.addOutgoingConnection = function() {
PMShape.prototype.addOutgoingConnection.apply(this, arguments);
return this.evaluateGatewayDirection();
};
/**
* @inheritdoc
**/
PMGateway.prototype.removeOutgoingConnection = function() {
PMShape.prototype.removeOutgoingConnection.apply(this, arguments);
return this.evaluateGatewayDirection();
};
var PMLine = function (options) {
PMUI.draw.RegularShape.call(this, options);
/**
* Defines the type artifact
* @type {String}
*/
this.art_type = null;
/**
* Defines the unique identifier
* @type {String}
*/
this.art_uid = null;
this.art_orientation = null;
this.label = null;
this.box = null;
this.extended = null;
this.extendedType = null;
this.relationship = null;
PMLine.prototype.init.call(this, options);
};
/**
* Constant that represents that a drag behavior for moving the shape should be
* used
* @property {Number}
*/
PMLine.prototype = new PMUI.draw.RegularShape();
PMLine.prototype.type = "PMArtifact";
PMLine.prototype.family = "RegularShape";
PMLine.prototype.init = function (options) {
var defaults = {
art_orientation: "vertical",
label: "",
art_type: 'PMArtifact',
art_name: "",
art_uid: PMUI.generateUniqueId()
};
jQuery.extend(true, defaults, options);
this.setOrientation(defaults.art_orientation)
.setLabel(defaults.label)
.setArtifactUid(defaults.art_uid)
.setArtifactType(defaults.art_type)
.setName(defaults.art_name);
};
PMLine.prototype.setOrientation = function (orientation) {
var availableOpt, option;
orientation = orientation.toLowerCase();
availableOpt = {
"vertical": "vertical",
"horizontal": "horizontal"
};
option = (availableOpt[orientation]) ? orientation : "vertical";
this.art_orientation = option;
this.style.addClasses(["mafe-line-" + this.art_orientation]);
return this;
};
PMLine.prototype.setLabel = function (label) {
return this;
};
/**
* Sets the label element
* @param {String} value
* @return {*}
*/
PMLine.prototype.setName = function (value) {
if (this.label) {
this.label.setMessage(value);
}
return this;
};
/**
* Returns the label text
* @return {String}
*/
PMLine.prototype.getName = function () {
var text = "";
if (this.label) {
text = this.label.getMessage();
}
return text;
};
PMLine.prototype.setExtendedType = function (type) {
this.extendedType = type;
return this;
};
PMLine.prototype.setRelationship = function (relationship) {
this.relationship = relationship;
return this;
};
PMLine.prototype.addRelationship = function (object) {
if (typeof object === "object") {
jQuery.extend(true, this.relationship, object);
}
return this;
};
PMLine.prototype.setExtended = function (extended) {
var ext;
ext = (typeof extended === 'object') ? extended : {};
this.extended = ext;
return this;
};
/**
* Sets the artifact type property
* @param {String} type
* @return {*}
*/
PMLine.prototype.setArtifactType = function (type) {
this.art_type = type;
return this;
};
/**
* Sets the artifact unique identifier
* @param {String} value
* @return {*}
*/
PMLine.prototype.setArtifactUid = function (value) {
this.art_uid = value;
return this;
};
PMLine.prototype.getExtendedObject = function () {
this.extended = {
extendedType: this.extendedType
};
return this.extended;
};
/**
* Returns the clean object to be sent to the backend
* @return {Object}
*/
PMLine.prototype.getDataObject = function () {
var name = this.getName();
return {
art_uid: this.art_uid,
art_name: name,
art_type: this.art_type,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: 'bpmnDiagram',
_extended: this.getExtendedObject()
};
};
PMLine.prototype.getArtifactType = function () {
return this.art_type;
};
/**
* @event mousedown
* Moused down callback fired when the user mouse downs on the `shape`
* @param {PMUI.draw.Shape} shape
*/
PMLine.prototype.onMouseDown = function (shape) {
return function (e, ui) {
e.stopPropagation();
};
};
PMLine.prototype.createHTML = function () {
var width = this.width || 20000,
height = this.height || 20000;
PMUI.draw.RegularShape.prototype.createHTML.call(this);
this.style.removeAllProperties();
this.style.addProperties({
position: "absolute",
cursor: "move"
});
if (this.art_orientation === "vertical") {
this.height = height;
this.width = 5;
this.style.addProperties({
width: "5px",
height: height + "px",
top: -parseInt(height / 3, 10)
});
} else {
this.width = width;
this.height = 5;
this.style.addProperties({
width: width + "px",
height: "5px",
left: -parseInt(width / 3, 10)
});
}
return this.html;
};
var CustomLayer = function (options) {
PMUI.draw.Layer.call(this, options);
this.tooltip = null;
this.listeners = {
click: function () {
}
};
CustomLayer.prototype.init.call(this, options);
};
CustomLayer.prototype = new PMUI.draw.Layer();
CustomLayer.prototype.type = "customLayer";
CustomLayer.prototype.init = function (options) {
var defaults = {
tooltip: "",
listeners: {
click: function (event, layer, shape) {
}
}
};
jQuery.extend(true, defaults, options);
this.setTooltipMessage(defaults.tooltip)
.setListeners(defaults.listeners);
};
CustomLayer.prototype.setTooltipMessage = function (message) {
if (typeof message === "string") {
this.tooltip = message;
}
if (this.html) {
jQuery(this.html).attr("title", "");
jQuery(this.html).tooltip({content: this.tooltip, tooltipClass: "mafe-action-tooltip"});
}
return this;
};
CustomLayer.prototype.setListeners = function (events) {
if (typeof events === "object") {
this.listeners.click = events.click;
}
return this;
};
CustomLayer.prototype.createHTML = function (modifying) {
this.setProperties();
PMUI.draw.Layer.prototype.createHTML.call(this, modifying);
this.setTooltipMessage();
this.defineEvents();
return this.html;
};
CustomLayer.prototype.defineEvents = function () {
var that = this;
jQuery(that.html).on("click", function (event) {
that.listeners.click(event, that, that.parent);
event.stopPropagation();
});
};
/**
* @class PMArtifact
* Handle BPMN Annotations
*
*
* @constructor
* Creates a new instance of the class
* @param {Object} options
*/
var PMArtifact = function (options) {
PMShape.call(this, options);
/**
* Defines the type artifact
* @type {String}
*/
this.art_type = null;
/**
* Defines the unique identifier
* @type {String}
*/
this.art_uid = null;
PMArtifact.prototype.initObject.call(this, options);
};
PMArtifact.prototype = new PMShape();
/**
* Defines the object type
* @type {String}
*/
PMArtifact.prototype.type = "PMArtifact";
PMArtifact.prototype.PMArtifactResizeBehavior = null;
/**
* Initialize the object with the default values
* @param {Object} options
*/
PMArtifact.prototype.initObject = function (options) {
var defaults = {
art_type: 'TEXT_ANNOTATION',
art_name: ""
};
jQuery.extend(true, defaults, options);
this.setArtifactUid(defaults.art_uid);
this.setArtifactType(defaults.art_type);
this.setName(defaults.art_name);
};
/**
* Sets the artifact type property
* @param {String} type
* @return {*}
*/
PMArtifact.prototype.setArtifactType = function (type) {
this.art_type = type;
return this;
};
/**
* Sets the artifact unique identifier
* @param {String} value
* @return {*}
*/
PMArtifact.prototype.setArtifactUid = function (value) {
this.art_uid = value;
return this;
};
/**
* Returns the clean object to be sent to the backend
* @return {Object}
*/
PMArtifact.prototype.getDataObject = function () {
var name = this.getName(),
container,
element_id;
switch (this.parent.type) {
case 'PMCanvas':
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
case 'PMPool':
container = 'bpmnPool';
element_id = this.parent.id;
break;
case 'PMLane':
container = 'bpmnLane';
element_id = this.parent.id;
break;
case 'PMActivity':
container = 'bpmnActivity';
element_id = this.parent.id;
break;
default:
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
}
return {
art_uid: this.id,
art_name: name,
art_type: this.art_type,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: container,
bou_element: element_id,
_extended: this.getExtendedObject()
};
};
PMArtifact.prototype.getArtifactType = function () {
return this.art_type;
};
PMArtifact.prototype.updateHTML = function () {
var height, width;
height = this.height;
width = this.width;
PMShape.prototype.updateHTML.call(this);
this.setDimension(width, height);
return this;
};
/**
* Extends the paint method to draw text annotation lines
*/
PMArtifact.prototype.paint = function () {
if (this.getArtifactType() === 'GROUP') {
PMShape.prototype.paint.call(this);
} else {
if (!this.graphics || this.graphics === null) {
this.graphics = new JSGraphics(this.id);
} else {
this.graphics.clear();
}
this.graphics.setStroke(1);
this.graphics.drawLine(0, 0, 0, this.getZoomHeight());
this.graphics.drawLine(0, 0, Math.round(this.getZoomWidth() * 0.25), 0);
this.graphics.drawLine(0, this.getZoomHeight(), Math.round(this.getZoomWidth() * 0.25), this.getZoomHeight());
this.graphics.paint();
for (i = 0; i < this.labels.getSize(); i += 1) {
label = this.labels.get(i);
label.paint();
}
if (this.corona) {
this.corona.paint();
this.corona.hide();
}
}
};
PMArtifact.prototype.setResizeBehavior = function (behavior) {
var factory = new PMUI.behavior.BehaviorFactory({
products: {
"regularresize": PMUI.behavior.RegularResizeBehavior,
"Resize": PMUI.behavior.RegularResizeBehavior,
"yes": PMUI.behavior.RegularResizeBehavior,
"resize": PMUI.behavior.RegularResizeBehavior,
"noresize": PMUI.behavior.NoResizeBehavior,
"NoResize": PMUI.behavior.NoResizeBehavior,
"no": PMUI.behavior.NoResizeBehavior,
"annotationResize": PMArtifactResizeBehavior
},
defaultProduct: "noresize"
});
this.resizeBehavior = factory.make(behavior);
if (this.html) {
this.resize.init(this);
}
return this;
};
PMArtifact.prototype.createWithBpmn = function () {
var businessObject = {};
var bpmnElementType = this.getBpmnElementType();
businessObject.elem = PMDesigner.bpmnFactory.create(bpmnElementType, {
id: this.id,
text: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : ""
});
if (!businessObject.di) {
if (this.type === 'Connection') {
businessObject.di = PMDesigner.bpmnFactory.createDiEdge(businessObject.elem, [], {
id: businessObject.id + '_di'
});
} else {
businessObject.di = PMDesigner.bpmnFactory.createDiShape(businessObject.elem, {}, {
id: businessObject.id + '_di'
});
}
}
this.businessObject = businessObject;
};
/**
* Return an incremental name based of the type of the shape
* @param {Object} pmCanvas The current canvas
*/
var IncrementNameCanvas = function (pmCanvas) {
var random,
elementsName = {
TASK: "Task".translate(),
SUB_PROCESS: "Sub-process".translate(),
START: "Start Event".translate(),
START_MESSAGE: "Start Message Event".translate(),
START_TIMER: "Start Timer Event".translate(),
END: "End Event".translate(),
END_MESSAGE: "End Message Event".translate(),
SELECTION: "Selection".translate(),
EVALUATION: "Evaluation".translate(),
PARALLEL: "Parallel Gateway".translate(),
INCLUSIVE: "Inclusive Gateway".translate(),
EXCLUSIVE: "Exclusive Gateway".translate(),
PARALLEL_EVALUATION: "Parallel by Evaluation".translate(),
PARALLEL_JOIN: "Parallel Join".translate(),
TEXT_ANNOTATION: "Annotation".translate(),
VERTICAL_LINE: "Vertical line".translate(),
HORIZONTAL_LINE: "Horizontal line".translate(),
H_LABEL: "Horizontal Text".translate(),
V_LABEL: "Vertical Text".translate(),
DATASTORE: "Data Store".translate(),
DATAOBJECT: "Data Object".translate(),
PARTICIPANT: "Black Box Pool".translate(),
POOL: "Pool".translate(),
INTERMEDIATE_SENDMESSAGE: "Intermediate Send Message Event".translate(),
INTERMEDIATE_RECEIVEMESSAGE: "Intermediate Receive Message Event".translate(),
LANE: "Lane".translate(),
GROUP: "Group".translate(),
BOUNDARY_EVENT: ' ',
END_EMAIL: "End Email Event".translate(),
INTERMEDIATE_EMAIL: "Intermediate Email Event".translate()
},
random = false;
return {
id: Math.random(),
get: function (type) {
var i,
j,
k = pmCanvas.getCustomShapes().getSize(),
exists,
index = 1;
for (i = 0; i < k; i += 1) {
exists = false;
for (j = 0; j < k; j += 1) {
if (pmCanvas.getCustomShapes().get(j).getName() === elementsName[type] + " " + (i + 1)) {
exists = true;
break;
}
}
if (!exists) {
break;
}
}
return elementsName[type] + " " + (i + 1);
}
};
};
/**
* It is required overwriting the method, since there custom functionality
* that should not affect the core of PMUI.
*/
PMUI.ui.Window.prototype.open = function () {
var the_window, that = this;
if (this.isOpen) {
return this;
}
the_window = this.getHTML();
if (this.modal) {
this.modalObject.appendChild(the_window);
document.body.appendChild(this.modalObject);
jQuery(the_window).draggable({
handle: $(this.header),
containment: '#' + this.modalObject.id,
scroll: false});
if (!$.stackModal) {
$.stackModal = [];
}
$.stackModal.push(the_window);
$(the_window).on("keydown", function (event) {
if (event.keyCode !== $.ui.keyCode.TAB) {
return;
}
var tabbables = $(':tabbable', this),
first = tabbables.filter(':first'),
last = tabbables.filter(':last');
if (event.target === last[0] && !event.shiftKey) {
if (first && first.focus) {
first.focus(1);
}
return false;
} else if (event.target === first[0] && event.shiftKey) {
if (last && last.focus) {
last.focus(1);
}
return false;
}
if (event.which === PMDesigner.keyCodeF5) {
this.blur();
event.preventDefault();
window.location.reload(true);
}
});
} else {
document.body.appendChild(the_window);
jQuery(this.getHTML()).draggable();
}
if (typeof this.onOpen === 'function') {
this.onOpen(this);
}
this.isOpen = true;
this.updateDimensionsAndPosition();
this.setVisible(true);
this.defineEvents();
if (document.body && this.modal) {
document.body.style.overflow = "hidden"
}
$(the_window).find("*").on("keydown", function (e) {
if (e.which === PMDesigner.keyCodeF5) {
this.blur();
e.preventDefault();
window.location.reload(true);
}
});
return this;
};
/**
* It is required overwriting the method, since there custom functionality
* that should not affect the core of PMUI.
*/
PMUI.ui.Window.prototype.close = function () {
jQuery(this.modalObject).detach();
jQuery(this.html).detach();
jQuery(this.closeButton).detach();
if (typeof this.onClose === 'function') {
this.onClose(this);
}
this.isOpen = false;
if (document.body && this.modal) {
document.body.style.overflow = "auto";
}
if ($.stackModal) {
$.stackModal.pop();
var the_window = $.stackModal[$.stackModal.length - 1];
}
return this;
};
var autoResizeScreen = function () {
var myWidth = 0, myHeight = 0;
if (typeof(window.innerWidth) === 'number') {
myWidth = window.innerWidth;
myHeight = window.innerHeight;
} else if (document.documentElement &&
(document.documentElement.clientWidth || document.documentElement.clientHeight)) {
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else if (document.body &&
(document.body.clientWidth || document.body.clientHeight)) {
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
return myWidth;
};
var showUID = function (id) {
var messageWindow = new PMUI.ui.MessageWindow({
width: 490,
bodyHeight: 'auto',
id: 'showMessageWindowUID',
windowMessageType: 'info',
message: id,
footerItems: [
{
text: 'Ok'.translate(),
handler: function () {
messageWindow.close();
},
buttonType: "success"
}
]
});
messageWindow.setTitle("ID".translate());
messageWindow.open();
messageWindow.showFooter();
$(messageWindow.dom.icon).removeClass();
};
var applyStyleWindowForm = function (win) {
$(win.body).removeClass("pmui-background");
win.footer.html.style.textAlign = 'right';
(function searchForm(items) {
var i;
for (i = 0; i < items.length; i += 1) {
if (items[i].footer && items[i].footer.setVisible) {
$(win.body).addClass("pmui-background");
items[i].footer.setVisible(false);
}
searchForm(items[i].getItems ? items[i].getItems() :
(items[i].getPanel ? items[i].getPanel().getItems() : []));
}
}(win.getItems()));
};
var QuickMessageWindow = function (html, message) {
if (html === undefined) {
return;
}
QuickMessageWindow.prototype.show.call(this, html, message);
};
QuickMessageWindow.prototype.show = function (html, message) {
var that = this,
factorX = 25,
factorY = 20;
if ($('#tooltipmessagecustom')[0]) {
$('#tooltipmessagecustom').css({
'top': $(html).offset().top + factorY,
'left': $(html).offset().left + factorX
});
$('#tooltipmessagecustombody').html(message);
} else {
var button = $('<div id="header"></div>')
.append($("<a style='font-size: 14px'></a>")
.html('X')
.on('click', function () {
$('#tooltipmessagecustom').remove();
}));
$('body').append($('<div></div>')
.append(button)
.append($('<div></div>')
.attr('id', 'tooltipmessagecustombody')
.css({'float': 'left'})
.html(message))
.addClass('pmui pmui-pmtooltipmessage')
.attr('id', 'tooltipmessagecustom')
.css({
'box-sizing': 'border-box', 'position': 'absolute',
'z-index': '100', 'font-size': '10',
'top': $(html).offset().top + factorY,
'left': $(html).offset().left + factorX
})).on('mousedown', function (evt) {
that.closeEvent(evt);
}).on('click', function (evt) {
that.closeEvent(evt);
}).on('mouseup', function (evt) {
that.closeEvent(evt);
});
$(window).scroll(function () {
that.close();
});
}
};
QuickMessageWindow.prototype.close = function () {
$('#tooltipmessagecustom').remove();
};
QuickMessageWindow.prototype.closeEvent = function (evt) {
var element = evt.target || evt.srcElement;
if ($('#tooltipmessagecustom')[0] && element !== $('#tooltipmessagecustom')[0] && element !== $('#tooltipmessagecustom')[0].children[1]) {
$('#tooltipmessagecustom').remove();
}
};
var ButtonFormPanel = function (options) {
options.labelVisible = false;
this.onclick = options.onclick;
this.parameter = options.parameter;
PMUI.field.TextField.call(this, options);
ButtonFormPanel.prototype.init.call(this, options);
};
ButtonFormPanel.prototype = new PMUI.field.TextField();
ButtonFormPanel.prototype.init = function (options) {
var defaults = {};
jQuery.extend(true, defaults, options);
};
ButtonFormPanel.prototype.createHTML = function () {
var that = this, button;
PMUI.field.TextField.prototype.createHTML.call(this);
button = new PMUI.ui.Button({
id: this.id,
text: this.getLabel(),
handler: function () {
that.onclick(that);
}
});
this.dom.controlContainer.appendChild(button.getHTML());
this.dom.controlContainer.getElementsByTagName('input')[0].style.display = 'none';
button.defineEvents();
this.button = button;
return this.html;
};
var LabelFormPanel = function (options) {
PMUI.field.TextField.call(this, options);
LabelFormPanel.prototype.init.call(this, options);
};
LabelFormPanel.prototype = new PMUI.field.TextField();
LabelFormPanel.prototype.init = function (options) {
var defaults = {};
jQuery.extend(true, defaults, options);
};
LabelFormPanel.prototype.createHTML = function () {
PMUI.field.TextField.prototype.createHTML.call(this);
this.dom.controlContainer.getElementsByTagName('input')[0].style.display = 'none';
return this.html;
};
var messagePageGrid = function (currentPage, pageSize, numberItems, criteria, filter) {
var msg;
if (numberItems === 0) {
return '';
}
msg = 'Page'.translate() + ' ' + (currentPage + 1) + ' ' + 'of'.translate() + ' ' + Math.ceil(numberItems / pageSize);
return msg;
};
/*
* Function: validateKeysField
* valid characteres for file name:
* http://support.microsoft.com/kb/177506/es
*
* (A-z)letter
* (0-9)number
* ^ Accent circumflex (caret)
* & Ampersand
* ' Apostrophe (single quotation mark)
* @ At sign
* { Brace left
* } Brace right
* [ Bracket opening
* ] Bracket closing
* , Comma
* $ Dollar sign
* = Equal sign
* ! Exclamation point
* - Hyphen
* # Number sign
* ( Parenthesis opening
* ) Parenthesis closing
* % Percent
* . Period
* + Plus
* ~ Tilde
* _ Underscore
*
* Example: only backspace, number and letter.
* validateKeysField(objectHtmlInput, ['isbackspace', 'isnumber', 'isletter']);
*
* Aditional support:
* : Colon
*
*/
var validateKeysField = function (object, validates) {
object.onkeypress = function (e) {
var key = document.all ? e.keyCode : e.which,
isbackspace = key === 8,
isnumber = key > 47 && key < 58,
isletter = (key > 96 && key < 123) || (key > 64 && key < 91),
isaccentcircumflex = key === 94,
isampersand = key === 41,
isapostrophe = key === 145,
isatsign = key === 64,
isbraceleft = key === 123,
isbraceright = key === 125,
isbracketopening = key === 91,
isbracketclosing = key === 93,
iscomma = key === 130,
isdollarsign = key === 36,
isequalsign = key === 61,
isexclamationpoint = key === 33,
ishyphen = key === 45,
isnumbersign = key === 35,
isparenthesisopening = key === 40,
isparenthesisclosing = key === 41,
ispercent = key === 37,
isperiod = key === 46,
isplus = key === 43,
istilde = key === 126,
isunderscore = key === 95,
iscolon = key === 58,
sw = eval(validates[0]);
if (key === 0) {
return true;
}
sw = eval(validates[0]);
for (var i = 1; i < validates.length; i++) {
sw = sw || eval(validates[i]);
}
return sw;
};
};
var applyStyleTreePanel = function (treePanel, fontStyle) {
if (fontStyle !== false) {
$(treePanel.getHTML()).find('a').css('font-weight', 'bold');
$(treePanel.getHTML()).find('a').css('color', 'black');
$(treePanel.getHTML()).find('ul li ul li>a').css('font-weight', 'normal');
$(treePanel.getHTML()).find('ul li ul li>a').css('color', 'black');
}
};
/*
* Convert time format HH:MM:SS to decimal value.
*/
var timeToDecimal = function (value) {
var s = value.toString().replace(/\s/g, '').split(':'), hour, min, sec;
hour = parseInt(s[0]) || 0;
min = parseInt(s[1]) || 1;
sec = parseInt(s[2]) || 1;
return (hour + min / 60 + sec / 3600);
};
/*
* Convert decimal to time format HH:MM:SS.
*/
var decimalToTime = function (value, second) {
var num = typeof value === 'number' ? value : 1, hour, min, sec;
hour = parseInt(num);
num = num - parseInt(num);
num = num.toFixed(13);
num = num * 60;
min = parseInt(num);
num = num - parseInt(num);
num = num.toFixed(13);
num = num * 60;
sec = parseInt(num);
hour = hour.toString().length === 1 ? '0' + hour : hour;
min = min.toString().length === 1 ? '0' + min : min;
sec = sec.toString().length === 1 ? '0' + sec : sec;
return second === true ? hour + ':' + min + ':' + sec : hour + ':' + min;
};
var Mafe = {};
/**
*
* @param {type} settings
* @returns {undefined}
*/
Mafe.Window = function (settings) {
this.views = [];
PMUI.ui.Window.call(this, settings);
Mafe.Window.prototype.init.call(this, settings);
};
Mafe.Window.prototype = new PMUI.ui.Window();
Mafe.Window.prototype.init = function (settings) {
this.setHeight(DEFAULT_WINDOW_HEIGHT);
this.setWidth(DEFAULT_WINDOW_WIDTH);
this.hideFooter();
this.setButtonPanelPosition('bottom');
};
Mafe.Window.prototype.createHTML = function () {
PMUI.ui.Window.prototype.createHTML.call(this);
this.footer.html.style.textAlign = 'right';
return this.html;
};
Mafe.Window.prototype.resetView = function () {
var items;
this.hideFooter();
items = this.items.asArray();
for (var i = 0; i < items.length; i++) {
if (items[i].setVisible) {
items[i].setVisible(false);
}
if (items[i].reset) {
items[i].reset();
}
}
};
Mafe.Window.prototype.setButtons = function (buttons) {
this.clearFooterItems();
this.setFooterItems(buttons);
this.showFooter();
};
/**
*
* @param {type} settings
* @returns {undefined}
*/
Mafe.Grid = function (settings) {
var defaults = {
pageSize: 10,
width: '96%',
filterPlaceholder: 'Search ...'.translate(),
emptyMessage: 'No records found'.translate(),
nextLabel: 'Next'.translate(),
previousLabel: 'Previous'.translate(),
style: {cssClasses: ['mafe-gridPanel']},
customStatusBar: function (currentPage, pageSize, numberItems, criteria, filter) {
return messagePageGrid(currentPage, pageSize, numberItems, criteria, filter);
}
};
jQuery.extend(true, defaults, settings);
PMUI.grid.GridPanel.call(this, defaults);
Mafe.Grid.prototype.init.call(this, defaults);
};
Mafe.Grid.prototype = new PMUI.grid.GridPanel();
Mafe.Grid.prototype.init = function (settings) {
var defaults = {};
jQuery.extend(true, defaults, settings);
};
Mafe.Grid.prototype.createHTML = function () {
PMUI.grid.GridPanel.prototype.createHTML.call(this);
$(this.html).find('.pmui-textcontrol').css({'margin-top': '5px', width: '250px'});
return this.html;
};
/**
*
* @param {type} settings
* @returns {undefined}
*/
Mafe.Form = function (settings) {
var defaults;
this.onYesConfirmCancellation = new Function();
defaults = {
width: DEFAULT_WINDOW_WIDTH - 3,
height: 'auto'
};
jQuery.extend(true, defaults, settings);
PMUI.form.Form.call(this, defaults);
Mafe.Form.prototype.init.call(this);
};
Mafe.Form.prototype = new PMUI.form.Form();
Mafe.Form.prototype.init = function (settings) {
var defaults = {};
jQuery.extend(true, defaults, settings);
};
Mafe.Form.prototype.getConfirmCancellationToLoseChanges = function () {
return this.confirmCancellationToLoseChanges;
};
Mafe.Form.prototype.loseChanges = function (options) {
var that = this, confirmCancellation;
if (that.isDirty()) {
confirmCancellation = new Mafe.ConfirmCancellation(options);
confirmCancellation.onYes = function () {
that.onYesConfirmCancellation();
};
} else {
that.onYesConfirmCancellation();
}
};
Mafe.ConfirmDeletion = function () {
var that = this, defaults;
that.onDelete = new Function();
that.onCancel = new Function();
defaults = {
id: 'idConfirmDeletion',
width: 490,
bodyHeight: 'auto',
windowMessageType: 'warning',
message: 'Do you want to delete this Element?'.translate(),
footerItems: [{
id: 'idCancelConfirmDeletion',
text: 'No'.translate(),
visible: true,
handler: function () {
that.onCancel();
that.close();
},
buttonType: "error"
}, {
id: 'idDeleteConfirmDeletion',
text: 'Yes'.translate(),
visible: true,
handler: function () {
that.onDelete();
that.close();
},
buttonType: "success"
}
]
};
PMUI.ui.MessageWindow.call(this, defaults);
Mafe.ConfirmDeletion.prototype.init.call(this);
};
Mafe.ConfirmDeletion.prototype = new PMUI.ui.MessageWindow();
Mafe.ConfirmDeletion.prototype.init = function () {
this.open();
this.showFooter();
};
/**
*
* @returns {undefined}
*/
Mafe.ConfirmCancellation = function (options) {
var that = this, defaults;
that.onYes = new Function();
that.onNo = new Function();
defaults = {
id: 'idConfirmCancellation',
title: options["title"] || 'Confirm'.translate(),
width: 490,
bodyHeight: 'auto',
windowMessageType: 'warning',
message: 'Are you sure you want to discard your changes?'.translate(),
footerItems: [
{
id: 'idCancelConfirmCancellation',
text: 'No'.translate(),
visible: true,
handler: function () {
that.onNo();
that.close();
},
buttonType: "error"
}, {
id: 'idDeleteConfirmCancellation',
text: 'Yes'.translate(),
visible: true,
handler: function () {
that.onYes();
that.close();
},
buttonType: "success"
}
]
};
PMUI.ui.MessageWindow.call(this, defaults);
Mafe.ConfirmCancellation.prototype.init.call(this);
};
Mafe.ConfirmCancellation.prototype = new PMUI.ui.MessageWindow();
Mafe.ConfirmCancellation.prototype.init = function () {
this.open();
this.showFooter();
};
/**
*
* @param {type} settings
* @returns {undefined}
*/
Mafe.Tree = function (settings) {
var defaults;
if (settings && settings.width) {
this._width = settings.width;
} else {
this._width = 210;
}
defaults = {
id: 'idMafeTree',
filterable: true,
filterPlaceholder: 'Search ...'.translate(),
emptyMessage: 'No records found'.translate(),
autoBind: true,
nodeDefaultSettings: {
autoBind: true,
collapsed: false,
labelDataBind: 'labelDataBind',
itemsDataBind: 'itemsDataBind',
childrenDefaultSettings: {
labelDataBind: 'labelDataBind',
autoBind: true
}
}
};
jQuery.extend(true, defaults, settings);
PMUI.panel.TreePanel.call(this, defaults);
Mafe.Tree.prototype.init.call(this, defaults);
};
Mafe.Tree.prototype = new PMUI.panel.TreePanel();
Mafe.Tree.prototype.init = function (defaults) {
var that = this;
that.style.addProperties({overflow: 'auto'});
};
Mafe.Tree.prototype.createHTML = function () {
PMUI.panel.TreePanel.prototype.createHTML.call(this);
this.setWidth(this._width);
return this.html;
};
/**
*
* @param {type} settings
* @returns {undefined}
*/
Mafe.Accordion = function (settings) {
var defaults;
if (settings && settings.width) {
this._width = settings.width;
}
defaults = {
id: 'idAccordion',
hiddenTitle: true,
heightItem: 'auto',
title: '',
multipleSelection: true,
listeners: {
select: function (accordionItem, event) {
}
}
};
jQuery.extend(true, defaults, settings);
PMUI.panel.AccordionPanel.call(this, defaults);
Mafe.Accordion.prototype.init.call(this);
};
Mafe.Accordion.prototype = new PMUI.panel.AccordionPanel();
Mafe.Accordion.prototype.init = function () {
var that = this;
that.style.addProperties({'vertical-align': 'top'});
};
Mafe.Accordion.prototype.createHTML = function () {
PMUI.panel.AccordionPanel.prototype.createHTML.call(this);
this.setWidth(this._width);
return this.html;
};
/**
* Failsafe remove an element from a collection
*
* @param {Array<Object>} [collection]
* @param {Object} [element]
*
* @return {Object} the element that got removed or undefined
*/
var CollectionRemove = function (collection, element) {
var idx;
if (!collection || !element) {
return;
}
idx = collection.indexOf(element);
if (idx === -1) {
return;
}
collection.splice(idx, 1);
return element;
};
function setEncoded(link, name, data) {
var encodedData = encodeURIComponent(data);
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(new Blob([data], {type: "application/octet-stream"}), name);
} else {
if (data) {
link.addClass('active').attr({
'href': 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData,
'download': name
});
} else {
link.removeClass('active');
}
}
}
function convertDatetimeToIso8601(datetime) {
var separate, date, time, timeDifference, signed, hours, minutes;
separate = datetime.split(' ');
date = separate[0].split('-');
time = (separate[1] || '00:00:00').split(':');
date = new Date(date[0] || 0, (date[1] || 1) - 1, date[2] || 0, time[0] || 0, time[1] || 0, time[2] || 0);
timeDifference = date.getTimezoneOffset();
signed = '+';
if (timeDifference > 0) {
signed = '-';
}
timeDifference = Math.abs(timeDifference);
hours = Math.floor(timeDifference / 60).toString();
minutes = Math.floor(timeDifference % 60).toString();
return datetime.replace(/\s/g, 'T') + signed +
('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2);
}
/**
* FullScreen class
*/
var FullScreen = function (options) {
this.element = null;
this.onReadyScreen = null;
this.onCancelScreen = null;
this.fullscreemed = false;
this.fireEvent = false;
FullScreen.prototype.init.call(this, options);
};
/**
* [init description]
* @param {Object} options Config options
*/
FullScreen.prototype.init = function (options) {
var defaults = {
element: document.documentElement,
onReadyScreen: function () {
},
onCancelScreen: function () {
}
};
jQuery.extend(true, defaults, options);
this.element = defaults.element;
this.action = null;
this.onReadyScreen = defaults.onReadyScreen;
this.onCancelScreen = defaults.onCancelScreen;
this.attachListeners();
};
FullScreen.prototype.cancel = function () {
var requestMethod, fnCancelScreen, wscript, el;
if (parent.document.documentElement === document.documentElement) {
el = document;
} else {
el = parent.document;
}
requestMethod = el.cancelFullScreen ||
el.webkitCancelFullScreen ||
el.mozCancelFullScreen ||
el.exitFullscreen;
if (requestMethod) {
requestMethod.call(el);
try {
fnCancelScreen = this.onCancelScreen;
fnCancelScreen(el);
} catch (e) {
throw new Error(e);
}
} else if (typeof window.ActiveXObject !== "undefined") { // Older IE.
wscript = new ActiveXObject("WScript.Shell");
if (wscript !== null) {
wscript.SendKeys("{F11}");
}
}
};
FullScreen.prototype.applyZoom = function () {
var requestMethod, wscript, fnReadyScreen, el = this.element;
requestMethod = el.requestFullScreen ||
el.webkitRequestFullScreen ||
el.mozRequestFullScreen ||
el.msRequestFullScreen;
if (requestMethod) {
requestMethod.call(el);
try {
fnReadyScreen = this.onReadyScreen;
fnReadyScreen(el);
} catch (e) {
throw new Error(e);
}
} else if (typeof window.ActiveXObject !== "undefined") {
wscript = new ActiveXObject("WScript.Shell");
if (wscript !== null) {
wscript.SendKeys("{F11}");
}
}
return false
};
FullScreen.prototype.toggle = function (action) {
var el,
isInFullScreen;
this.action = action;
if (parent.document.documentElement === document.documentElement) {
el = document;
} else {
el = parent.document;
}
isInFullScreen = (el.fullScreenElement && el.fullScreenElement !== null) || (el.mozFullScreen || el.webkitIsFullScreen);
if (isInFullScreen) {
action.setTooltip('Full Screen'.translate());
this.cancel();
} else {
this.applyZoom();
this.fullscreemed = true;
action.setTooltip('Exit full screen'.translate());
}
return false;
};
FullScreen.prototype.attachListeners = function () {
var el, self = this;
if (parent.document.documentElement === document.documentElement) {
el = document;
} else {
el = parent.document;
}
el.addEventListener("fullscreenchange", function () {
self.fireFullScreen();
}, false);
el.addEventListener("mozfullscreenchange", function () {
self.fireFullScreen();
//to fix: in firefox the tooltip is always visible
if (self.action) {
self.action.setTooltip('Full Screen'.translate());
$(self.action.selector).tooltip("close");
}
}, false);
el.addEventListener("webkitfullscreenchange", function (e, a) {
self.fireFullScreen();
}, false);
el.addEventListener("msfullscreenchange", function () {
self.fireFullScreen();
}, false);
};
FullScreen.prototype.fireFullScreen = function () {
if (this.fullscreemed && this.fireEvent) {
this.fireEvent = false;
} else {
this.fireEvent = true;
}
return true;
};
var PMIframe = function (settings) {
PMUI.core.Element.call(this, settings);
this.src = null;
this.name = null;
this.scrolling = null;
this.frameborder = null;
this.errorMessage = null;
this.data = null;
PMIframe.prototype.init.call(this, settings);
};
PMIframe.prototype = new PMUI.core.Element();
PMIframe.prototype.type = "PMPMIframe";
PMIframe.prototype.family = 'PMPMIframe';
PMIframe.prototype.init = function (settings) {
var defaults = {
src: "",
name: "",
width: 770,
height: 305,
scrolling: 'no',
frameborder: "0"
};
jQuery.extend(true, defaults, settings);
this.setSrc(defaults.src)
.setName(defaults.name)
.setWidth(defaults.width)
.setHeight(defaults.height)
.setScrolling(defaults.scrolling)
.setFrameborder(defaults.frameborder);
};
PMIframe.prototype.setSrc = function (src) {
this.src = src;
return this;
};
PMIframe.prototype.setName = function (name) {
this.name = name;
return this;
};
PMIframe.prototype.setScrolling = function (scrolling) {
this.scrolling = scrolling;
return this;
};
PMIframe.prototype.setFrameborder = function (frameborder) {
this.frameborder = frameborder;
return this;
};
PMIframe.prototype.createHTML = function () {
var input;
if (this.html) {
return this.html;
}
input = PMUI.createHTMLElement("iframe");
input.className = "PMIframeWin";
input.id = this.id;
input.name = "PMIframeWindow";
input.src = this.src;
input.frameBorder = this.frameborder;
this.html = input;
this.applyStyle();
return this.html;
};
var PMTiny = function (options) {
PMUI.control.HTMLControl.call(this, options);
this.theme = null;
this.plugins = null;
this.mode = null;
this.editorSelector = null;
this.widthTiny = null;
this.heightTiny = null;
this.directionality = null;
this.verifyHtml = null;
this.themeAdvancedButtons1 = null;
this.themeAdvancedButtons2 = null;
this.popupCss = null;
this.skin = null;
this.skinVariant = null;
this.processID = null;
this.domainURL = null;
this.baseURL = null;
this.contentCss = null;
this.themeAdvancedFonts = null;
PMTiny.prototype.init.call(this, options);
};
PMTiny.prototype = new PMUI.control.HTMLControl();
PMTiny.prototype.type = "PMTiny";
PMTiny.prototype.family = 'PMCodeMirrorControl';
PMTiny.prototype.init = function (options) {
var defaults = {
theme: "advanced",
plugins: "advhr,advimage,advlink,advlist,autolink,autoresize,contextmenu,directionality,emotions,example,example_dependency,fullpage,fullscreen,iespell,inlinepopups,insertdatetime,layer,legacyoutput,lists,media,nonbreaking,noneditable,pagebreak,paste,preview,print,save,searchreplace,style,tabfocus,table,template,visualblocks,visualchars,wordcount,xhtmlxtras,pmSimpleUploader,pmVariablePicker,pmGrids,style",
mode: "specific_textareas",
editorSelector: "tmceEditor",
widthTiny: DEFAULT_WINDOW_WIDTH - 60,
heightTiny: DEFAULT_WINDOW_HEIGHT - 100,
directionality: 'ltr',
verifyHtml: false,
themeAdvancedButtons1: "pmSimpleUploader,|,pmVariablePicker,|,pmGrids,|,bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,fontselect,fontsizeselect,|,cut,copy,paste,|,bullist,numlist,|,outdent,indent,blockquote",
themeAdvancedButtons2: "tablecontrols,|,undo,redo,|,link,unlink,image,|,forecolor,backcolor,styleprops,|,hr,removeformat,visualaid,|,sub,sup,|,ltr,rtl,|,code",
popupCss: "/js/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/dialog.css",
skin: "o2k7",
skinVariant: "silver",
processID: null,
domainURL: "/sys" + WORKSPACE + "/" + LANG + "/" + SKIN + "/",
baseURL: "/js/tinymce/jscripts/tiny_mce",
contentCss: "",
themeAdvancedFonts: "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats;"
};
jQuery.extend(true, defaults, options);
this.setTheme(defaults.theme)
.setPlugins(defaults.plugins)
.setMode(defaults.mode)
.setEditorSelector(defaults.editorSelector)
.setDirectionality(defaults.directionality)
.setVerifyHtml(defaults.verifyHtml)
.setThemeAdvancedButtons1(defaults.themeAdvancedButtons1)
.setThemeAdvancedButtons2(defaults.themeAdvancedButtons2)
.setPopupCss(defaults.popupCss)
.setSkin(defaults.skin)
.setSkinVariant(defaults.skinVariant)
.setProcessID(defaults.processID)
.setDomainURL(defaults.domainURL)
.setBaseURL(defaults.baseURL)
.setHeightTiny(defaults.heightTiny)
.setWidthTiny(defaults.widthTiny)
.setContentCss(defaults.contentCss)
.setThemeAdvancedFonts(defaults.themeAdvancedFonts);
};
PMTiny.prototype.setTheme = function (theme) {
this.theme = theme;
return this;
};
PMTiny.prototype.setPlugins = function (plugins) {
this.plugins = plugins;
return this;
};
PMTiny.prototype.setMode = function (mode) {
this.mode = mode;
return this;
};
PMTiny.prototype.setEditorSelector = function (editorSelector) {
this.editorSelector = editorSelector;
return this;
};
PMTiny.prototype.setDirectionality = function (directionality) {
this.directionality = directionality;
return this;
};
PMTiny.prototype.setVerifyHtml = function (verifyHtml) {
this.verifyHtml = verifyHtml;
return this;
};
PMTiny.prototype.setThemeAdvancedButtons1 = function (themeAdvancedButtons1) {
this.themeAdvancedButtons1 = themeAdvancedButtons1;
return this;
};
PMTiny.prototype.setThemeAdvancedButtons2 = function (themeAdvancedButtons2) {
this.themeAdvancedButtons2 = themeAdvancedButtons2;
return this;
};
PMTiny.prototype.setPopupCss = function (popupCss) {
this.popupCss = popupCss;
return this;
};
PMTiny.prototype.setSkin = function (skin) {
this.skin = skin;
return this;
};
PMTiny.prototype.setSkinVariant = function (skinVariant) {
this.skinVariant = skinVariant;
return this;
};
PMTiny.prototype.setProcessID = function (processID) {
this.processID = processID;
return this;
};
PMTiny.prototype.setDomainURL = function (domainURL) {
this.domainURL = domainURL;
return this;
};
PMTiny.prototype.setBaseURL = function (baseURL) {
this.baseURL = baseURL;
return this;
};
PMTiny.prototype.setWidthTiny = function (widthTiny) {
this.widthTiny = widthTiny;
return this;
};
PMTiny.prototype.setHeightTiny = function (heightTiny) {
this.heightTiny = heightTiny;
return this;
};
/**
* Set CSS used in the content editor
*
* @param string contentCss
* @returns {PMTiny}
*/
PMTiny.prototype.setContentCss = function (contentCss) {
this.contentCss = contentCss;
return this;
};
/**
* Set fonts list for the advanced theme
*
* @param string themeAdvancedFonts
* @returns {PMTiny}
*/
PMTiny.prototype.setThemeAdvancedFonts = function (themeAdvancedFonts) {
this.themeAdvancedFonts = themeAdvancedFonts;
return this;
};
PMTiny.prototype.setParameterTiny = function () {
var that = this, domainURL;
tinyMCE.baseURL = this.baseURL;
domainURL = this.domainURL;
tinyMCE.init({
theme: this.theme,
plugins: this.plugins,
mode: this.mode,
editor_selector: this.editorSelector,
width: this.widthTiny,
height: this.heightTiny,
directionality: this.directionality,
verify_html: this.verifyHtml,
theme_advanced_buttons1: this.themeAdvancedButtons1,
theme_advanced_buttons2: this.themeAdvancedButtons2,
popup_css: this.popupCss,
skin: this.skin,
skin_variant: this.skinVariant,
relative_urls: false,
remove_script_host: false,
convert_urls: this.convert_urls,
content_css: this.contentCss,
theme_advanced_fonts: this.themeAdvancedFonts,
oninit: function () {
tinyMCE.activeEditor.processID = PMDesigner.project.id;
tinyMCE.activeEditor.domainURL = domainURL;
//added the tinyeditor reference to the PMUI control
that.controlEditor = tinyMCE.activeEditor;
tinyMCE.execCommand('mceFocus', false, 'tinyeditor');
},
onchange_callback: function (inst) {
that.onChangeHandler();
if (inst.isDirty()) {
inst.save();
}
return true;
},
handle_event_callback: function (e) {
if (this.isDirty()) {
this.save();
}
return true;
}
});
};
PMTiny.prototype.createHTML = function () {
var input;
if (this.html) {
return this.html;
}
input = PMUI.createHTMLElement("textArea");
input.className = "tmceEditor";
input.id = "tinyeditor";
input.name = "tinyeditor";
input.width = this.width;
input.height = this.height;
this.html = input;
return this.html;
};
PMTiny.prototype.setValueTiny = function (value) {
if (this.html) {
if (this.html.id) {
$('#' + this.html.id + '_ifr').height('100%');
}
if (this.controlEditor) {
this.controlEditor.setContent(value);
}
}
return this;
};
PMTiny.prototype.getValue = function (value) {
if (this.html) {
if (this.controlEditor) {
return this.controlEditor.getContent(value);
}
}
return '';
};
PMTiny.prototype.setVisible = function (visible) {
visible = !!visible;
this.visible = visible;
if (this.html) {
if (this.html.id) {
if (visible) {
$('#' + this.html.id + '_tbl').css("display", "block");
} else {
$('#' + this.html.id + '_tbl').css("display", "none");
}
}
}
return this;
};
var PMTinyField = function (settings) {
PMUI.form.Field.call(this, settings);
PMTinyField.prototype.init.call(this, settings);
};
PMTinyField.prototype = new PMUI.form.Field();
PMTinyField.prototype.type = "PMTinyField";
PMTinyField.prototype.family = 'PMTinyField';
PMTinyField.prototype.init = function (settings) {
var defaults = {
theme: "advanced",
plugins: "advhr,advimage,advlink,advlist,autolink,autoresize,contextmenu,directionality,emotions,example,example_dependency,fullpage,fullscreen,iespell,inlinepopups,insertdatetime,layer,legacyoutput,lists,media,nonbreaking,noneditable,pagebreak,paste,preview,print,save,searchreplace,style,tabfocus,table,template,visualblocks,visualchars,wordcount,xhtmlxtras,pmSimpleUploader,pmVariablePicker,pmGrids,style",
mode: "specific_textareas",
editorSelector: "tmceEditor",
widthTiny: DEFAULT_WINDOW_WIDTH - 60,
heightTiny: DEFAULT_WINDOW_HEIGHT - 100,
directionality: 'rtl',
verifyHtml: false,
themeAdvancedButtons1: "pmSimpleUploader,|,pmVariablePicker,|,pmGrids,|,bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,|,fontselect,fontsizeselect,|,cut,copy,paste,|,bullist,numlist,|,outdent,indent,blockquote",
themeAdvancedButtons2: "tablecontrols,|,undo,redo,|,link,unlink,image,|,forecolor,backcolor,styleprops,|,hr,removeformat,visualaid,|,sub,sup,|,ltr,rtl,|,code",
popupCss: "/js/tinymce/jscripts/tiny_mce/themes/advanced/skins/default/dialog.css",
skin: "o2k7",
skinVariant: "silver",
processID: null,
domainURL: "/sys" + WORKSPACE + "/" + LANG + "/" + SKIN + "/",
baseURL: "/js/tinymce/jscripts/tiny_mce",
contentCss: "",
themeAdvancedFonts: "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats;"
};
jQuery.extend(true, defaults, settings);
this.setTheme(defaults.theme)
.setPlugins(defaults.plugins)
.setMode(defaults.mode)
.setEditorSelector(defaults.editorSelector)
.setDirectionality(defaults.directionality)
.setVerifyHtml(defaults.verifyHtml)
.setThemeAdvancedButtons1(defaults.themeAdvancedButtons1)
.setThemeAdvancedButtons2(defaults.themeAdvancedButtons2)
.setPopupCss(defaults.popupCss)
.setSkin(defaults.skin)
.setSkinVariant(defaults.skinVariant)
.setProcessID(defaults.processID)
.setDomainURL(defaults.domainURL)
.setBaseURL(defaults.baseURL)
.setHeightTiny(defaults.heightTiny)
.setWidthTiny(defaults.widthTiny)
.setContentCss(defaults.contentCss)
.setThemeAdvancedFonts(defaults.themeAdvancedFonts)
.hideLabel(true);
};
PMTinyField.prototype.setTheme = function (theme) {
this.controls[0].setTheme(theme);
return this;
};
PMTinyField.prototype.setPlugins = function (plugins) {
this.controls[0].setPlugins(plugins);
return this;
};
PMTinyField.prototype.setMode = function (mode) {
this.controls[0].setMode(mode);
return this;
};
PMTinyField.prototype.setEditorSelector = function (editorSelector) {
this.controls[0].setEditorSelector(editorSelector);
return this;
};
PMTinyField.prototype.setDirectionality = function (directionality) {
this.controls[0].setDirectionality(directionality);
return this;
};
PMTinyField.prototype.setVerifyHtml = function (verifyHtml) {
this.controls[0].setVerifyHtml(verifyHtml);
return this;
};
PMTinyField.prototype.setThemeAdvancedButtons1 = function (themeAdvancedButtons1) {
this.controls[0].setThemeAdvancedButtons1(themeAdvancedButtons1);
return this;
};
PMTinyField.prototype.setThemeAdvancedButtons2 = function (themeAdvancedButtons2) {
this.controls[0].setThemeAdvancedButtons2(themeAdvancedButtons2);
return this;
};
PMTinyField.prototype.setPopupCss = function (popupCss) {
this.controls[0].setPopupCss(popupCss);
return this;
};
PMTinyField.prototype.setSkin = function (skin) {
this.skin = skin;
this.controls[0].setSkin(skin);
return this;
};
PMTinyField.prototype.setSkinVariant = function (skinVariant) {
this.controls[0].setSkinVariant(skinVariant);
return this;
};
PMTinyField.prototype.setProcessID = function (processID) {
this.controls[0].setProcessID(processID);
return this;
};
PMTinyField.prototype.setDomainURL = function (domainURL) {
this.controls[0].setDomainURL(domainURL);
return this;
};
PMTinyField.prototype.setBaseURL = function (baseURL) {
this.controls[0].setBaseURL(baseURL);
return this;
};
PMTinyField.prototype.setWidthTiny = function (widthTiny) {
this.controls[0].setWidthTiny(widthTiny);
return this;
};
PMTinyField.prototype.setHeightTiny = function (heightTiny) {
this.controls[0].setHeightTiny(heightTiny);
return this;
};
/**
* Set CSS used in the content editor
*
* @param string contentCss
* @returns {PMTinyField}
*/
PMTinyField.prototype.setContentCss = function (contentCss) {
this.controls[0].setContentCss(contentCss);
return this;
};
/**
* Set fonts list for the advanced theme
*
* @param string themeAdvancedFonts
* @returns {PMTinyField}
*/
PMTinyField.prototype.setThemeAdvancedFonts = function (themeAdvancedFonts) {
this.controls[0].setThemeAdvancedFonts(themeAdvancedFonts);
return this;
};
PMTinyField.prototype.hideLabel = function (value) {
jQuery(this.dom.labelTextContainer).hide();
this.labelVisible = !value;
return this;
}
PMTinyField.prototype.setParameterTiny = function () {
this.controls[0].setParameterTiny();
return this;
}
PMTinyField.prototype.setValueTiny = function (value) {
this.controls[0].setValueTiny(value);
return this;
}
PMTinyField.prototype.setControls = function () {
if (this.controls.length) {
return this;
}
this.controls.push(new PMTiny());
return this;
};
var PMRestClient = function (options) {
this.endpoint = null;
this.typeRequest = null;
this.data = null;
this.functionSuccess = null;
this.functionFailure = null;
this.functionComplete = null;
this.apiVersion = null;
this.restProxy = null;
this.pmProcess = null;
this.messageError = null;
this.messageSuccess = null;
this.flashContainer = null;
this.flashDuration = null;
this.flashSeverity = null;
this.multipart = false;
this.needStringify = null;
this.hostName = HTTP_SERVER_HOSTNAME;
PMRestClient.prototype.init.call(this, options);
};
PMRestClient.prototype.type = "PMRestClient";
PMRestClient.prototype.init = function (options) {
var defaults = {
endpoint: '',
typeRequest: 'get',
data: null,
functionSuccess: function (resp, data) {
},
functionFailure: function (resp, data) {
},
functionComplete: function (resp, data) {
},
apiVersion: '1.0',
restProxy: '',
processID: '',
messageError: false,
messageSuccess: false,
flashContainer: document.body,
flashDuration: 3000,
flashSeverity: 'success',
multipart: false,
needStringify: true
}
jQuery.extend(true, defaults, options);
this.setProcessID()
.setApiVersion(defaults.apiVersion)
.setEndpoint(defaults.endpoint)
.setTypeRequest(defaults.typeRequest)
.setData(defaults.data)
.setFunctionSuccess(defaults.functionSuccess)
.setFunctionFailure(defaults.functionFailure)
.setFunctionComplete(defaults.functionComplete)
.setMessageSuccess(defaults.messageSuccess)
.setMessageError(defaults.messageError)
.setFlashContainer(defaults.flashContainer)
.setFlashDuration(defaults.flashDuration)
.setFlashSeverity(defaults.flashSeverity)
.setMultipart(defaults.multipart)
.setNeedStringify(defaults.needStringify);
};
PMRestClient.prototype.setProcessID = function () {
this.processID = PMDesigner.project.id;
return this;
};
PMRestClient.prototype.setEndpoint = function (endpoint) {
this.endpoint = "/api/" + this.apiVersion + "/" + WORKSPACE + "/project/" + this.processID + "/" + endpoint;
return this;
};
PMRestClient.prototype.setBaseEndPoint = function (endpoint) {
this.endpoint = "/api/" + this.apiVersion + "/" + WORKSPACE + "/" + endpoint;
return this;
};
PMRestClient.prototype.setTypeRequest = function (typeRequest) {
this.typeRequest = typeRequest;
return this;
};
PMRestClient.prototype.setData = function (data) {
this.data = data;
return this;
};
PMRestClient.prototype.setFunctionSuccess = function (functionSuccess) {
this.functionSuccess = functionSuccess;
return this;
};
PMRestClient.prototype.setFunctionComplete = function (functionComplete) {
this.functionComplete = functionComplete;
return this;
};
PMRestClient.prototype.setFunctionFailure = function (functionFailure) {
this.functionFailure = functionFailure;
return this;
};
PMRestClient.prototype.setMessageSuccess = function (messageSuccess) {
this.messageSuccess = (messageSuccess) ? messageSuccess : false;
return this;
};
PMRestClient.prototype.setMessageError = function (messageError) {
this.messageError = (messageError) ? messageError : false;
return this;
};
PMRestClient.prototype.setApiVersion = function (apiVersion) {
this.apiVersion = apiVersion;
return this;
};
PMRestClient.prototype.setRestProxy = function () {
this.restProxy = new PMUI.proxy.RestProxy();
return this;
};
PMRestClient.prototype.setToken = function () {
var keys;
if (this.pmProcess === '' || this.pmProcess === null) {
this.setProcessID();
}
if (this.restProxy === '' || this.restProxy === null) {
this.setRestProxy();
}
keys = PMDesigner.project.getKeysClient();
this.restProxy.setDataType("json");
this.restProxy.setAuthorizationType('oauth2', PMDesigner.project.tokens);
if (this.multipart) {
this.enableMultipart();
}
return this;
};
/**
* Enables Multipart header
* @returns {PMRestClient}
*/
PMRestClient.prototype.enableMultipart = function () {
this.restProxy.rc.setHeader('X-Requested-With', 'MULTIPART');
return this;
};
PMRestClient.prototype.setFlashContainer = function (flashContainer) {
this.flashContainer = flashContainer;
return this;
};
PMRestClient.prototype.setFlashDuration = function (flashDuration) {
this.flashDuration = flashDuration;
return this;
};
PMRestClient.prototype.setFlashSeverity = function (flashSeverity) {
this.flashSeverity = flashSeverity;
return this;
};
PMRestClient.prototype.setMultipart = function (multipart) {
this.multipart = multipart;
return this;
};
PMRestClient.prototype.setNeedStringify = function (value) {
this.needStringify = value;
return this;
};
PMRestClient.prototype.setHeader = function (name, value) {
if (this.restProxy === '' || this.restProxy === null) {
this.setRestProxy();
}
this.restProxy.rc.setHeader(name, value);
return this;
};
/**
* Validates Multipart responses
* @param response
*/
PMRestClient.prototype.validateMesssage = function (response) {
var HTTP_SUCCESS = ["200", "201", "202", "204", "207"],
showMessage = false,
messageMultipart = [],
i,
that = this;
for (i = 0; i < response.length; i += 1) {
if (HTTP_SUCCESS.indexOf(String(response[i].status)) !== -1) {
if (that.messageSuccess[i] !== null) {
showMessage = true;
messageMultipart.push(that.messageSuccess[i]);
}
} else {
if (that.messageError[i] !== null) {
showMessage = true;
messageMultipart.push(that.messageError[i]);
that.setFlashSeverity('error');
}
}
}
};
/**
* Executes extended Rest Client
*
*/
PMRestClient.prototype.executeRestClient = function () {
if (this.restProxy === '' || this.restProxy === null) {
this.setRestProxy();
}
this.setToken();
this.restProxy.rc.setHeader("Accept-Language", LANG);
switch (this.typeRequest) {
case 'get':
this.get();
break;
case 'post':
this.post();
break;
case 'put':
this.put();
break;
case 'update':
this.update();
break;
case 'remove':
this.remove();
break;
}
};
/**
* Get method
*/
PMRestClient.prototype.get = function () {
var that = this;
this.restProxy.get({
url: this.hostName + this.endpoint,
authorizationOAuth: true,
data: this.data,
success: function (xhr, response) {
if (that.multipart) {
that.validateMesssage(response);
}
if (that.messageSuccess) {
PMDesigner.msgFlash(
that.messageSuccess,
that.flashContainer,
that.flashSeverity,
that.flashDuration
);
}
that.functionSuccess(xhr, response);
},
failure: function (xhr, response) {
that.failureResponse(that, xhr, response);
},
complete: function (xhr, response) {
that.functionComplete(xhr, response);
}
});
};
/**
* Post method
*/
PMRestClient.prototype.post = function () {
var that = this;
this.restProxy.post({
url: this.hostName + this.endpoint,
authorizationOAuth: true,
data: this.data,
success: function (xhr, response) {
if (that.multipart) {
that.validateMesssage(response);
}
if (that.messageSuccess) {
PMDesigner.msgFlash(
that.messageSuccess,
that.flashContainer,
that.flashSeverity,
that.flashDuration
);
}
that.functionSuccess(xhr, response);
},
failure: function (xhr, response) {
that.failureResponse(that, xhr, response);
},
complete: function (xhr, response) {
that.functionComplete(xhr, response);
}
});
};
/**
* Put Method
*/
PMRestClient.prototype.put = function () {
var that = this;
this.restProxy.put({
url: this.hostName + this.endpoint,
authorizationOAuth: true,
data: this.data,
success: function (xhr, response) {
if (that.multipart) {
that.validateMesssage(response);
}
if (that.messageSuccess) {
PMDesigner.msgFlash(
that.messageSuccess,
that.flashContainer,
that.flashSeverity,
that.flashDuration
);
}
that.functionSuccess(xhr, response);
},
failure: function (xhr, response) {
that.failureResponse(that, xhr, response);
},
complete: function (xhr, response) {
that.functionComplete(xhr, response);
}
});
};
/**
* Delete method
*/
PMRestClient.prototype.remove = function () {
var that = this;
this.restProxy.remove({
url: this.hostName + this.endpoint,
authorizationOAuth: true,
data: this.data,
success: function (xhr, response) {
if (that.multipart) {
that.validateMesssage(response);
}
if (that.messageSuccess) {
PMDesigner.msgFlash(
that.messageSuccess,
that.flashContainer,
that.flashSeverity,
that.flashDuration
);
}
that.functionSuccess(xhr, response);
},
failure: function (xhr, response) {
that.failureResponse(that, xhr, response);
},
complete: function (xhr, response) {
that.functionComplete(xhr, response);
}
});
};
/**
* Update Method
*/
PMRestClient.prototype.update = function () {
var that = this;
this.restProxy.update({
url: this.hostName + this.endpoint,
authorizationOAuth: true,
data: this.data,
success: function (xhr, response) {
if (that.multipart) {
that.validateMesssage(response);
}
if (that.messageSuccess) {
PMDesigner.msgFlash(
that.messageSuccess,
that.flashContainer,
that.flashSeverity,
that.flashDuration
);
}
that.functionSuccess(xhr, response);
},
failure: function (xhr, response) {
that.failureResponse(that, xhr, response);
},
complete: function (xhr, response) {
that.functionComplete(xhr, response);
}
});
};
/**
* Failure response manager
* @param root
* @param xhr
* @param response
*/
PMRestClient.prototype.failureResponse = function (root, xhr, response) {
if (xhr.status === 401 && typeof(response.error) != "undefined") {
root.refreshAccesToken(root);
return;
} else {
if (xhr.status === 400) {
root.functionFailure(xhr, response);
return;
}
if (root.messageError) {
PMDesigner.msgWinError(root.messageError);
}
}
root.functionFailure(xhr, response);
};
/**
* Gets new token using the refresh token key
* @param root
*/
PMRestClient.prototype.refreshAccesToken = function (root) {
var newRestClient = new PMUI.proxy.RestProxy();
newRestClient.post({
url: this.hostName + "/api/" + root.apiVersion + "/" + WORKSPACE + "/token",
data: {
grant_type: "refresh_token",
client_id: PMDesigner.project.tokens.client_id,
client_secret: PMDesigner.project.tokens.client_secret,
refresh_token: PMDesigner.project.tokens.refresh_token
},
success: function (xhr, response) {
PMDesigner.project.tokens.access_token = response.access_token;
PMDesigner.project.tokens.expires_in = response.expires_in;
PMDesigner.project.tokens.token_type = response.token_type;
PMDesigner.project.tokens.scope = response.scope;
PMDesigner.project.tokens.refresh_token = response.refresh_token;
root.executeRestClient();
},
failure: function (xhr, response) {
PMDesigner.msgWinError('An error occurred while retrieving the access token'.translate());
}
});
};
var PMCodeMirror = function (settings) {
PMUI.control.TextAreaControl.call(this, settings);
this.lineNumbers = null;
this.matchBrackets = null;
this.mode = null;
this.indentUnit = null;
this.indentWithTabs = null;
this.enterMode = null;
this.tabMode = null;
this.lineWrapping = null;
this.showCursorWhenSelecting = null;
this.autofocus = null;
this.height = null;
this.dom = {};
this.cm = null;
PMCodeMirror.prototype.init.call(this, settings);
};
PMCodeMirror.prototype = new PMUI.control.TextAreaControl();
PMCodeMirror.prototype.type = "PMCodeMirrorControl";
PMCodeMirror.prototype.family = 'PMCodeMirrorControl';
PMCodeMirror.prototype.init = function (settings) {
var defaults = {
lineNumbers: true,
matchBrackets: true,
mode: "application/x-httpd-php-open",
indentUnit: 4,
indentWithTabs: true,
enterMode: "keep",
tabMode: "shift",
lineWrapping: true,
showCursorWhenSelecting: true,
autofocus: "on",
height: 120
};
jQuery.extend(true, defaults, settings);
this.setLineNumbers(defaults.lineNumbers)
.setMatchBrackets(defaults.matchBrackets)
.setMode(defaults.mode)
.setIndentUnit(defaults.indentUnit)
.setIndentWithTabs(defaults.indentWithTabs)
.setEnterMode(defaults.enterMode)
.setTabMode(defaults.tabMode)
.setLineWrapping(defaults.lineWrapping)
.setShowCursorWhenSelecting(defaults.showCursorWhenSelecting)
.setAutofocus(defaults.autofocus)
.setHeight(defaults.height);
};
PMCodeMirror.prototype.setHeight = function (height) {
this.height = height;
return this;
};
PMCodeMirror.prototype.setLineNumbers = function (lineNumbers) {
this.lineNumbers = lineNumbers;
return this;
};
PMCodeMirror.prototype.setMatchBrackets = function (matchBrackets) {
this.matchBrackets = matchBrackets;
return this;
};
PMCodeMirror.prototype.setMode = function (mode) {
this.mode = mode;
return this;
};
PMCodeMirror.prototype.setIndentUnit = function (indentUnit) {
this.indentUnit = indentUnit;
return this;
};
PMCodeMirror.prototype.setIndentWithTabs = function (indentWithTabs) {
this.indentWithTabs = indentWithTabs;
return this;
};
PMCodeMirror.prototype.setEnterMode = function (enterMode) {
this.enterMode = enterMode;
return this;
};
PMCodeMirror.prototype.setTabMode = function (tabMode) {
this.tabMode = tabMode;
return this;
};
PMCodeMirror.prototype.setLineWrapping = function (lineWrapping) {
this.lineWrapping = lineWrapping;
return this;
};
PMCodeMirror.prototype.setShowCursorWhenSelecting = function (showCursorWhenSelecting) {
this.showCursorWhenSelecting = showCursorWhenSelecting;
return this;
};
PMCodeMirror.prototype.setAutofocus = function (autofocus) {
this.autofocus = autofocus;
return this;
};
PMCodeMirror.prototype.setParameterCodeMirror = function () {
if (!this.html) {
return this;
}
this.cm = CodeMirror.fromTextArea(
this.dom.textArea,
{
height: this.height,
lineNumbers: this.lineNumbers,
matchBrackets: this.matchBrackets,
mode: this.mode,
indentUnit: this.indentUnit,
indentWithTabs: this.indentWithTabs,
enterMode: this.enterMode,
tabMode: this.tabMode,
lineWrapping: this.lineWrapping,
showCursorWhenSelecting: this.showCursorWhenSelecting,
autofocus: this.autofocus,
extraKeys: {"Ctrl-Space": "autocomplete"}
}
);
return this;
};
PMCodeMirror.prototype.getValueFromRawElement = function () {
return (this.cm && this.cm.getValue()) || "";
};
PMCodeMirror.prototype.defineEvents = function () {
var that = this;
if (!this.eventsDefined) {
if (this.cm) {
this.cm.on("change", function () {
that.onChangeHandler();
});
}
}
return this;
};
PMCodeMirror.prototype.createHTML = function () {
var containerCode;
if (this.html) {
return this.html;
}
PMUI.control.TextAreaControl.prototype.createHTML.call(this);
containerCode = PMUI.createHTMLElement("div");
containerCode.appendChild(this.html);
this.dom.textArea = this.html;
this.html = containerCode;
this.applyStyle();
this.setParameterCodeMirror();
return this.html;
};
var PMCodeMirrorField = function (settings) {
PMUI.form.Field.call(this, settings);
PMCodeMirrorField.prototype.init.call(this, settings);
};
PMCodeMirrorField.prototype = new PMUI.form.Field();
PMCodeMirrorField.prototype.type = "PMCodeMirrorField";
PMCodeMirrorField.prototype.family = 'PMCodeMirrorField';
PMCodeMirrorField.prototype.init = function (settings) {
var defaults = {
lineNumbers: true,
matchBrackets: true,
mode: "application/x-httpd-php-open",
indentUnit: 4,
indentWithTabs: true,
enterMode: "keep",
tabMode: "shift",
lineWrapping: true,
showCursorWhenSelecting: true,
autofocus: "on"
};
jQuery.extend(true, defaults, settings);
this.setLineNumbers(defaults.lineNumbers)
.setMatchBrackets(defaults.matchBrackets)
.setMode(defaults.mode)
.setIndentUnit(defaults.indentUnit)
.setIndentWithTabs(defaults.indentWithTabs)
.setEnterMode(defaults.enterMode)
.setTabMode(defaults.tabMode)
.setLineWrapping(defaults.lineWrapping)
.setShowCursorWhenSelecting(defaults.showCursorWhenSelecting)
.setAutofocus(defaults.autofocus);
};
PMCodeMirrorField.prototype.setLineNumbers = function (lineNumbers) {
this.controls[0].setLineNumbers(lineNumbers);
return this;
};
PMCodeMirrorField.prototype.setMatchBrackets = function (matchBrackets) {
this.controls[0].setMatchBrackets(matchBrackets);
return this;
};
PMCodeMirrorField.prototype.setMode = function (mode) {
this.controls[0].setMode(mode);
return this;
};
PMCodeMirrorField.prototype.setIndentUnit = function (indentUnit) {
this.controls[0].setIndentUnit(indentUnit);
return this;
};
PMCodeMirrorField.prototype.setIndentWithTabs = function (indentWithTabs) {
this.controls[0].setIndentWithTabs(indentWithTabs);
return this;
};
PMCodeMirrorField.prototype.setEnterMode = function (enterMode) {
this.controls[0].setEnterMode(enterMode);
return this;
};
PMCodeMirrorField.prototype.setTabMode = function (tabMode) {
this.controls[0].setTabMode(tabMode);
return this;
};
PMCodeMirrorField.prototype.setLineWrapping = function (lineWrapping) {
this.controls[0].setLineWrapping(lineWrapping);
return this;
};
PMCodeMirrorField.prototype.setShowCursorWhenSelecting = function (showCursorWhenSelecting) {
this.controls[0].setShowCursorWhenSelecting(showCursorWhenSelecting);
return this;
};
PMCodeMirrorField.prototype.setAutofocus = function (autofocus) {
this.controls[0].setAutofocus(autofocus);
return this;
};
PMCodeMirrorField.prototype.setControls = function () {
if (this.controls.length) {
return this;
}
this.controls.push(new PMCodeMirror());
return this;
};
var CriteriaField = function (options) {
this.renderType = (options && options.renderType) || "text";
PMUI.field.TextField.call(this, options);
this.process = null;
this.workspace = null;
this.buttonHTML = null;
this.rows = options.rows;
this.options = options;
CriteriaField.prototype.init.call(this, options);
};
CriteriaField.prototype = new PMUI.field.TextField();
CriteriaField.prototype.setProcess = function (process) {
this.process = process;
return this;
};
CriteriaField.prototype.setWorkspace = function (workspace) {
this.workspace = workspace;
return this;
};
CriteriaField.prototype.init = function (options) {
var defaults = {
process: PMDesigner.project.projectId,
workspace: WORKSPACE
};
jQuery.extend(true, defaults, options);
this.setProcess(defaults.process)
.setWorkspace(defaults.workspace);
};
CriteriaField.prototype.createVariablePicker = function () {
var vp = new VariablePicker({
relatedField: this,
processId: this.process
});
return vp;
};
CriteriaField.prototype.setControls = function () {
if (this.controls.length) {
return this;
}
if (this.renderType === 'text') {
this.controls.push(new PMUI.control.TextControl());
} else {
this.controls.push(new PMUI.control.TextAreaControl({style: {cssProperties: {resize: 'vertical'}}}));
}
return this;
};
/**
* Update the property disable
* @param {boolean} value
*/
CriteriaField.prototype.updateDisabled = function (value) {
this.setDisabled(value);
this.buttonHTML.setDisabled(value);
};
CriteriaField.prototype.createCallBack = function () {
var that = this,
newValue,
init = 0,
index = 0;
return {
success: function (variable) {
var prevText,
lastText,
htmlControl = that.controls[index].html;
init = htmlControl.selectionStart;
prevText = htmlControl.value.substr(index, init);
lastText = htmlControl.value.substr(htmlControl.selectionEnd, htmlControl.value.length);
newValue = prevText + variable + lastText;
that.setValue(newValue);
that.isValid();
htmlControl.selectionEnd = init + variable.length;
}
};
};
CriteriaField.prototype.createHTML = function () {
var button, that = this, variablePicker;
PMUI.field.TextField.prototype.createHTML.call(this);
button = new PMUI.ui.Button({
id: 'buttonCriteriaField',
text: '@@',
handler: function () {
if (that.process != "") {
variablePicker = that.createVariablePicker();
variablePicker.open(that.createCallBack());
} else {
return;
}
},
style: {
cssProperties: {
background: '#1E91D1',
fontSize: 18,
padding: '5px',
borderRadius: '4px',
verticalAlign: 'top'
}
}
});
this.buttonHTML = button;
$(this.helper.html).before(button.getHTML());
this.buttonHTML.style.addProperties({"margin-left": "10px"});
this.buttonHTML.html.tabIndex = -1;
if (typeof this.options.disabled === 'boolean') {
this.buttonHTML.setDisabled(this.options.disabled);
}
if (this.rows != null)
this.controls[0].setHeight(this.rows);
button.defineEvents();
return this.html;
};
// Overwrite original init function for FormItemFactory
PMUI.form.FormItemFactory.prototype.init = function () {
var defaults = {
products: {
"criteria": CriteriaField,
"field": PMUI.form.Field,
"panel": PMUI.form.FormPanel,
"text": PMUI.field.TextField,
"password": PMUI.field.PasswordField,
"dropdown": PMUI.field.DropDownListField,
"radio": PMUI.field.RadioButtonGroupField,
"checkbox": PMUI.field.CheckBoxGroupField,
"textarea": PMUI.field.TextAreaField,
"datetime": PMUI.field.DateTimeField,
"optionsSelector": PMUI.field.OptionsSelectorField,
"buttonField": PMUI.field.ButtonField,
"annotation": PMUI.field.TextAnnotationField
},
defaultProduct: "panel"
};
this.setProducts(defaults.products)
.setDefaultProduct(defaults.defaultProduct);
};
var SwitchField = function (options) {
this.renderType = (options && options.renderType) || "text";
PMUI.field.CheckBoxGroupField.call(this, options);
this.process = null;
this.workspace = null;
this.rows = options.rows;
this.options = options;
SwitchField.prototype.init.call(this, options);
};
SwitchField.prototype = new PMUI.field.CheckBoxGroupField();
SwitchField.prototype.setProcess = function (process) {
this.process = process;
return this;
};
SwitchField.prototype.setWorkspace = function (workspace) {
this.workspace = workspace;
return this;
};
SwitchField.prototype.init = function (options) {
var defaults = {
process: PMDesigner.project.projectId,
workspace: WORKSPACE
};
jQuery.extend(true, defaults, options);
this.setProcess(defaults.process)
.setWorkspace(defaults.workspace);
};
SwitchField.prototype.createCallBack = function () {
var that = this,
newValue,
init = 0,
index = 0;
return {
success: function (variable) {
var prevText,
lastText,
htmlControl = that.controls[index].html;
init = htmlControl.selectionStart;
prevText = htmlControl.value.substr(index, init);
lastText = htmlControl.value.substr(htmlControl.selectionEnd, htmlControl.value.length);
newValue = prevText + variable + lastText;
that.setValue(newValue);
that.isValid();
htmlControl.selectionEnd = init + variable.length;
}
};
};
SwitchField.prototype.setPlaceholder = function (placeholder) {}
SwitchField.prototype.setMaxLength = function (placeholder) {}
SwitchField.prototype.setReadOnly = function (placeholder) {}
SwitchField.prototype.createHTML = function () {
PMUI.field.CheckBoxGroupField.prototype.createHTML.call(this);
this.setSwitchStyle();
return this.html;
};
/**
* Set style type switch to checkbox
*/
SwitchField.prototype.setSwitchStyle = function () {
var table,
span,
label;
if (this.html) {
table = this.html.getElementsByTagName("table")[0];
table.setAttribute('style', 'padding: 0px; border:0px');
table.setAttribute('class', '');
span = table.getElementsByTagName("span")[0];
span.setAttribute('class', 'slider round');
label = table.getElementsByTagName("label")[0];
label.setAttribute('class', 'switch');
}
};
// Overwrite original init function for FormItemFactory
PMUI.form.FormItemFactory.prototype.init = function () {
var defaults = {
products: {
"criteria": CriteriaField,
"switch": SwitchField,
"field": PMUI.form.Field,
"panel": PMUI.form.FormPanel,
"text": PMUI.field.TextField,
"password": PMUI.field.PasswordField,
"dropdown": PMUI.field.DropDownListField,
"radio": PMUI.field.RadioButtonGroupField,
"checkbox": PMUI.field.CheckBoxGroupField,
"textarea": PMUI.field.TextAreaField,
"datetime": PMUI.field.DateTimeField,
"optionsSelector": PMUI.field.OptionsSelectorField,
"buttonField": PMUI.field.ButtonField,
"annotation": PMUI.field.TextAnnotationField
},
defaultProduct: "panel"
};
this.setProducts(defaults.products)
.setDefaultProduct(defaults.defaultProduct);
};
var PMTooltipMessage = function (options) {
PMUI.ui.Window.call(this, options);
this.container = null;
this.message = options.message;
PMTooltipMessage.prototype.init.call(this, options);
};
PMTooltipMessage.prototype = new PMUI.ui.Window();
PMTooltipMessage.prototype.type = "PMTooltipMessage";
PMTooltipMessage.prototype.createHTML = function () {
if (this.html) {
return this.html;
}
PMUI.ui.Window.prototype.createHTML.call(this);
this.closeButton.style.removeAllClasses();
this.closeButton.setText("x");
this.closeButton.style.addClasses(['mafe-tooltip-close']);
this.header.appendChild(this.closeButton.getHTML());
this.container = PMUI.createHTMLElement('div');
this.container.innerHTML = this.message;
this.body.appendChild(this.container);
return this.html;
};
PMTooltipMessage.prototype.open = function (x, y) {
PMUI.ui.Window.prototype.open.call(this);
this.setVisible(false);
this.setX(x);
this.setY(y);
this.header.className = "mafe-tooltip-header";
this.body.className = "mafe-tooltip-body";
this.style.addClasses(['mafe-tooltip']);
this.setTitle("");
$("#" + this.id).show("drop", "fast");
this.closeButton.defineEvents();
};
PMTooltipMessage.prototype.setMessage = function (message) {
this.message = message;
if (this.html)
this.container.innerHTML = message;
};
var VariablePicker = function (options) {
this.relatedField = null;
this.processId = null;
this.workspace = null;
this.window = null;
this.currentVariable = null;
this.pageSize = 10;
VariablePicker.prototype.init.call(this, options);
};
VariablePicker.prototype.type = 'VariablePicker';
VariablePicker.prototype.family = 'VariablePicker';
VariablePicker.prototype.init = function (options) {
var defaults = {
relatedField: null,
processId: PMDesigner.project.projectId,
workspace: WORKSPACE
};
jQuery.extend(true, defaults, options);
this.setRelatedField(defaults.relatedField)
.setProcessId(defaults.processId)
.setWorkspace(defaults.workspace);
};
VariablePicker.prototype.setRelatedField = function (field) {
if (field instanceof PMUI.form.Field) {
this.relatedField = field;
}
return this;
};
VariablePicker.prototype.setProcessId = function (process) {
this.processId = process;
return this;
};
VariablePicker.prototype.setWorkspace = function (workspace) {
this.workspace = workspace;
return this;
};
VariablePicker.prototype.getURL = function () {
var url = '/api/1.0/' + this.workspace + '/project/' + this.processId + '/variables';
return url;
};
VariablePicker.prototype.open = function (callback) {
var w, rc, fieldC, dataGrid, panel, textField, that = this;
button = new PMUI.ui.Button({
id: 'insertVariable',
text: 'Insert Variable'.translate(),
handler: function () {
if (callback && callback.success && typeof callback.success === 'function') {
that.currentVariable = fieldC.getValue() + that.currentVariable;
callback.success.call(that, that.currentVariable);
}
that.returnFocus();
that.close();
},
disabled: true
});
textField = new PMUI.field.TextField({
id: 'textFieldSearch',
label: '',
placeholder: 'Text to Search'.translate()
});
w = new PMUI.ui.Window({
id: 'processVariables',
title: 'Process Variables'.translate(),
width: 480,
height: 475,
closable: true,
modal: true,
buttons: [
button
],
buttonsPosition: 'center'
});
fieldC = new PMUI.field.DropDownListField({
id: 'prefixDropDownListField',
label: 'Prefix'.translate(),
helper: '@@ string, @# float, @% integer, @= original type, @& object.'.translate(),
options: [
{
id: 'prefixDropDownListField1',
label: '@@',
value: '@@'
},
{
id: 'prefixDropDownListField2',
label: '@#',
value: '@#'
},
{
id: 'prefixDropDownListField3',
label: '@%',
value: '@%'
},
{
id: 'prefixDropDownListField6',
label: '@=',
value: '@='
},
{
id: 'prefixDropDownListField7',
label: '@&',
value: '@&'
}
],
onChange: function (newValue, oldValue) {
}
});
textField = new PMUI.field.TextField({
id: 'textFieldSearch',
label: '',
placeholder: 'Text to search'.translate(),
width: 150
});
dataGrid = new PMUI.grid.GridPanel({
id: 'gridPanel',
selectable: true,
pageSize: this.pageSize,
nextLabel: 'Next'.translate(),
previousLabel: 'Previous'.translate(),
tableContainerHeight: 280,
customStatusBar: function (currentPage, pageSize, numberItems, criteria, filter) {
return messagePageGrid(currentPage, pageSize, numberItems, criteria, filter);
},
columns: [
{
id: 'gridPanelVariable',
title: 'Variable'.translate(),
columnData: 'var_name',
width: 150,
sortable: true,
alignmentCell: 'left'
},
{
id: 'gridPanelLabel',
title: 'Type'.translate(),
columnData: 'var_label',
width: 230,
sortable: false,
alignmentCell: 'left'
}
],
onRowClick: function (row, data) {
button.enable();
that.currentVariable = data.var_name;
}
});
panelFilter = new PMUI.core.Panel({
id: 'panelFilter',
layout: 'hbox',
items: [fieldC, textField]
});
panel = new PMUI.core.Panel({
id: 'paneldataGrid',
layout: 'vbox',
items: [panelFilter, dataGrid]
});
rc = new PMRestClient({
typeRequest: 'get',
functionSuccess: function (xhr, response) {
that.window = w;
dataGrid.setDataItems(response);
w.open();
w.showFooter();
w.addItem(panel);
panelFilter.setWidth(430);
fieldC.setControlsWidth(70);
textField.controls[0].onKeyUp = function () {
dataGrid.filter(textField.controls[0].html.value);
};
dataGrid.dom.toolbar.style.display = 'none';
$(dataGrid.dom.footer).css("margin-top", "0px");
$(dataGrid.dom.footer).css("position", "static");
$(dataGrid.dom.footer).css("padding-left", "10px");
$(dataGrid.dom.footer).css("padding-right", "10px");
textField.dom.labelTextContainer.innerHTML = '';
textField.dom.labelTextContainer.style.marginTop = 5;
fieldC.dom.labelTextContainer.style.paddingLeft = 20;
panel.style.addProperties({'padding-left': 20});
fieldC.dom.labelTextContainer.style.width = 60;
textField.dom.labelTextContainer.style.display = 'none';
textField.controls[0].setWidth(200);
$(dataGrid.html).find(".pmui-gridpanel-footer").css("position", "static");
$(dataGrid.html).find(".pmui-gridpanel-footer").css("margin-top", "0px");
}
});
rc.setBaseEndPoint('projects/' + this.processId + '/variables').executeRestClient();
};
VariablePicker.prototype.close = function () {
if (this.window) {
this.window.close();
this.window = null;
}
};
/**
* Set focus to Input of the Variable Picker
*/
VariablePicker.prototype.returnFocus = function () {
var that = this;
if (that.relatedField && that.relatedField.html) {
jQuery(that.relatedField.html).find(":input").focus();
}
};
var PMAction = function (options) {
this.name = null;
this.action = null;
this.selector = null;
this.tooltip = null;
this.execute = null;
this.label = null;
this.before = null;
this.after = null;
this.handler = null;
this.eventsDefined = false;
PMAction.prototype.init.call(this, options);
};
PMAction.prototype.type = "action";
PMAction.prototype.events = [
"click", "click"
];
PMAction.prototype.init = function (options) {
var defaults = {
action: "click",
selector: "",
tooltip: "",
execute: false,
label: {
selector: "",
text: "",
value: ""
},
before: function (event) {
event.preventDefault();
PMUI.removeCurrentMenu();
},
after: function (event) {
event.stopPropagation();
},
handler: function (event) {
}
};
jQuery.extend(true, defaults, options);
this.setAction(defaults.action)
.setSelector(defaults.selector)
.setExecute(defaults.execute)
.setLabel(defaults.label)
.setBefore(defaults.before)
.setAfter(defaults.after)
.setHandler(defaults.handler)
.setText(defaults.label.text)
.setValue(defaults.label.value)
.setTooltip(defaults.tooltip)
.addEventListener();
};
PMAction.prototype.setAction = function (action) {
this.action = action;
return this;
};
PMAction.prototype.setSelector = function (selector) {
this.selector = selector;
return this;
};
PMAction.prototype.setExecute = function (option) {
this.execute = option;
return this;
};
PMAction.prototype.setLabel = function (label) {
this.label = label;
if (!label.selector) {
this.label.selector = this.selector;
}
return this;
};
PMAction.prototype.setBefore = function (action) {
this.before = action;
return this;
};
PMAction.prototype.setAfter = function (action) {
this.after = action;
return this;
};
PMAction.prototype.setHandler = function (action) {
this.handler = action;
return this;
};
PMAction.prototype.setText = function (text) {
if (typeof text === "string" && text.length > 0) {
this.label.text = text;
jQuery(this.label.selector).text(this.label.text);
}
return this;
};
PMAction.prototype.setValue = function (value) {
if (typeof value === "string" && value.length > 0) {
this.label.value = value;
jQuery(this.label.selector).val(this.label.value);
}
return this;
};
PMAction.prototype.setTooltip = function (message) {
var that = this;
if (typeof message === "string") {
this.tooltip = message;
jQuery(this.selector).attr("title", "");
jQuery(this.selector).tooltip({ content: that.tooltip, tooltipClass: "mafe-action-tooltip" });
}
return this;
};
PMAction.prototype.addEventListener = function () {
var that = this;
if (this.execute === true && this.eventsDefined === false) {
jQuery(this.selector).on(this.action, function (event) {
try {
that.before(event);
} catch (e) {
throw new Error('Before action '.translate() + e.message);
}
try {
that.handler(event);
} catch (e) {
throw new Error('Handler '.translate() + e.message);
}
try {
that.after(event);
} catch (e) {
throw new Error('After action '.translate() + e.message);
}
});
if (this.label.text !== "") {
jQuery(this.label.selector).text(this.label.text);
}
this.eventsDefined = true;
}
return this;
};
PMAction.prototype.defineEvents = function () {
this.setExecute(true);
this.addEventListener();
};
var PMSeparatorLine = function (settings) {
PMUI.control.HTMLControl.call(this, settings);
this.width = null;
this.height = null;
this.color = null;
this.marginLeft = null;
PMSeparatorLine.prototype.init.call(this, settings);
};
PMSeparatorLine.prototype = new PMUI.control.HTMLControl();
PMSeparatorLine.prototype.type = "PMSeparatorLine";
PMSeparatorLine.prototype.family = 'PMSeparatorLine';
PMSeparatorLine.prototype.init = function (settings) {
var defaults = {
width: "90%",
height: '3px',
color: "#C0C0C0",
marginLeft: "0%"
};
jQuery.extend(true, defaults, settings);
this.setWidth(defaults.width);
this.setColor(defaults.color);
this.setHeight(defaults.height);
this.setMarginLeft(defaults.marginLeft);
};
PMSeparatorLine.prototype.setHeight = function (height) {
this.height = height;
if (this.html) {
this.html.style.height = this.height;
}
return this;
};
PMSeparatorLine.prototype.setWidth = function (width) {
this.width = width;
if (this.html) {
this.html.style.width = this.width;
}
return this;
};
PMSeparatorLine.prototype.setColor = function (color) {
this.color = color;
if (this.html) {
this.html.style.background = this.color;
}
return this;
};
PMSeparatorLine.prototype.setMarginLeft = function (marginLeft) {
this.marginLeft = marginLeft;
if (this.html) {
this.html.style.marginLeft = this.marginLeft;
}
return this;
};
PMSeparatorLine.prototype.createHTML = function () {
var input;
if (this.html) {
return this.html;
}
input = PMUI.createHTMLElement("hr");
input.className = "PMSeparatorLine";
input.id = this.id;
input.name = "PMSeparatorLine";
this.html = input;
this.setColor(this.color);
this.setMarginLeft(this.marginLeft);
this.applyStyle();
return this.html;
};
var PMSeparatorLineField = function (settings) {
PMUI.form.Field.call(this, settings);
PMSeparatorLineField.prototype.init.call(this, settings);
};
PMSeparatorLineField.prototype = new PMUI.form.Field();
PMSeparatorLineField.prototype.type = "PMSeparatorLineField";
PMSeparatorLineField.prototype.family = 'PMSeparatorLineField';
PMSeparatorLineField.prototype.init = function (settings) {
var defaults = {
controlHeight: 1,
controlColor: "#CDCDCD",
widthControl: "90%",
marginLeft: "5%"
};
jQuery.extend(true, defaults, settings);
this.setControlHeight(defaults.controlHeight)
.setControlColor(defaults.controlColor)
.setMarginLeft(defaults.marginLeft);
};
PMSeparatorLineField.prototype.setControlHeight = function (size) {
this.controls[0].setHeight(size);
return this;
};
PMSeparatorLineField.prototype.setControlColor = function (color) {
this.controls[0].setColor(color);
return this;
};
PMSeparatorLineField.prototype.setMarginLeft = function (marginLeft) {
this.controls[0].setMarginLeft(marginLeft);
return this;
};
PMSeparatorLineField.prototype.setControls = function () {
if (this.controls.length) {
return this;
}
this.controls.push(new PMSeparatorLine());
return this;
};
PMSeparatorLineField.prototype.getValue = function () {
return null;
};
PMSeparatorLineField.prototype.createHTML = function () {
PMUI.form.Field.prototype.createHTML.call(this);
this.hideLabel();
this.setLabelWidth('0%');
return this.html;
};
var PMLabelField = function (settings) {
PMUI.form.Field.call(this, settings);
PMLabelField.prototype.init.call(this, settings);
};
PMLabelField.prototype = new PMUI.form.Field();
PMLabelField.prototype.type = "PMLabelField";
PMLabelField.prototype.family = 'PMLabelField';
PMLabelField.prototype.init = function (settings) {
var defaults = {
text: "Mafe Label0",
textMode: "plain"
};
jQuery.extend(true, defaults, settings);
this.setText(defaults.text);
this.setTextMode(defaults.textMode);
};
PMLabelField.prototype.setText = function (text) {
this.controls[0].setText(text);
return this;
};
PMLabelField.prototype.setTextMode = function (textMode) {
this.controls[0].setTextMode(textMode);
return this;
};
PMLabelField.prototype.setControls = function () {
if (this.controls.length) {
return this;
}
this.controls.push(new PMLabelControl());
return this;
};
PMLabelField.prototype.getValue = function () {
return null;
};
PMLabelField.prototype.createHTML = function () {
PMUI.form.Field.prototype.createHTML.call(this);
this.hideLabel();
this.setLabelWidth('0%');
return this.html;
};
var PMLabelControl = function (settings) {
PMUI.control.Control.call(this, settings);
this.label = null;
PMLabelControl.prototype.init.call(this, settings);
};
PMLabelControl.prototype = new PMUI.control.Control();
PMLabelControl.prototype.type = "PMLabelControl";
PMLabelControl.prototype.family = 'PMLabelControl';
PMLabelControl.prototype.init = function (settings) {
this.label = new PMUI.ui.TextLabel();
};
PMLabelControl.prototype.setText = function (text) {
if (this.label) {
this.label.setText(text);
}
return this;
};
PMLabelControl.prototype.setTextMode = function (textMode) {
if (this.label) {
this.label.setTextMode(textMode);
}
return this;
};
PMLabelControl.prototype.createHTML = function () {
PMUI.control.Control.prototype.createHTML.call(this);
this.html = this.label.getHTML();
this.setPositionMode('relative');
return this.html;
};
/*global jCore*/
var PMArtifactResizeBehavior = function () {
};
PMArtifactResizeBehavior.prototype = new PMUI.behavior.RegularResizeBehavior();
PMArtifactResizeBehavior.prototype.type = "PMArtifactResizeBehavior";
/**
* Sets a shape's container to a given container
* @param container
* @param shape
*/
PMArtifactResizeBehavior.prototype.onResizeStart = function (shape) {
return PMUI.behavior.RegularResizeBehavior
.prototype.onResizeStart.call(this, shape);
};
/**
* Removes shape from its current container
* @param shape
*/
PMArtifactResizeBehavior.prototype.onResize = function (shape) {
return function (e, ui) {
PMUI.behavior.RegularResizeBehavior
.prototype.onResize.call(this, shape)(e, ui);
if (shape.graphics) {
shape.paint();
}
};
};
var ConnectValidator = function () {
};
ConnectValidator.prototype.type = "ConnectValidator";
ConnectValidator.prototype.initRules = {
'START': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'STARTMESSAGECATCH': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'INTERMEDIATE': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'INTERMEDIATEEMAIL': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'INTERMEDIATEMESSAGETHROW': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'INTERMEDIATEMESSAGECATCH': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'END': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'ENDEMAIL': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'ENDMESSAGETHROW': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'TASK': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'SUB_PROCESS': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'GATEWAY': {
'START': 'sequencialRules',
'INTERMEDIATE': 'sequencialRules',
'INTERMEDIATEEMAIL': 'sequencialRules',
'INTERMEDIATEMESSAGETHROW': 'sequencialRules',
'INTERMEDIATEMESSAGECATCH': 'sequencialRules',
'TASK': 'sequencialRules',
'SUB_PROCESS': 'sequencialRules',
'GATEWAY': 'sequencialRules',
'END': 'sequencialRules',
'ENDEMAIL': 'sequencialRules',
'ENDMESSAGETHROW': 'sequencialRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'DATA': {
'START': 'associationRules',
'INTERMEDIATE': 'associationRules',
'INTERMEDIATEEMAIL': 'associationRules',
'INTERMEDIATEMESSAGETHROW': 'associationRules',
'INTERMEDIATEMESSAGECATCH': 'associationRules',
'TASK': 'associationRules',
'SUB_PROCESS': 'associationRules',
'GATEWAY': 'associationRules',
'END': 'associationRules',
'DATA': 'associationRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules'
},
'PARTICIPANT': {
'START': 'messageRules',
'STARTMESSAGECATCH': 'messageRules',
'TASK': 'messageRules',
'SUB_PROCESS': 'messageRules',
'GATEWAY': 'messageRules',
'END': 'messageRules',
'ENDEMAIL': 'messageRules',
'ENDMESSAGETHROW': 'messageRules',
'DATA': 'messageRules',
'PARTICIPANT': 'messageRules',
'TEXT_ANNOTATION': 'annotationRules',
'INTERMEDIATEMESSAGECATCH': 'messageRules'
},
'TEXT_ANNOTATION': {
'START': 'annotationRules',
'INTERMEDIATE': 'annotationRules',
'INTERMEDIATEEMAIL': 'annotationRules',
'INTERMEDIATEMESSAGETHROW': 'annotationRules',
'INTERMEDIATEMESSAGECATCH': 'annotationRules',
'TASK': 'annotationRules',
'SUB_PROCESS': 'annotationRules',
'GATEWAY': 'annotationRules',
'END': 'annotationRules',
'ENDEMAIL': 'annotationRules',
'ENDMESSAGETHROW': 'annotationRules',
'DATA': 'annotationRules',
'PARTICIPANT': 'annotationRules',
'TEXT_ANNOTATION': 'annotationRules'
}
};
ConnectValidator.prototype.sequencialRules = {
'START': {
'START': false,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': false,
'END': false
},
'STARTMESSAGECATCH': {
'START': false,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': false,
'END': false
},
'INTERMEDIATE': {
'START': false,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': true,
'END': true,
'ENDEMAIL': true,
'ENDMESSAGETHROW': true
},
'INTERMEDIATEEMAIL': {
'START': false,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': true,
'END': true,
'ENDEMAIL': true,
'ENDMESSAGETHROW': true
},
'INTERMEDIATEMESSAGETHROW': {
'START': false,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': true,
'END': true,
'ENDEMAIL': true,
'ENDMESSAGETHROW': true
},
'INTERMEDIATEMESSAGECATCH': {
'START': false,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': true,
'END': true,
'ENDEMAIL': true,
'ENDMESSAGETHROW': true
},
'END': {
'START': false,
'TASK': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'END': false,
'INTERMEDIATE': false,
'INTERMEDIATEEMAIL': false,
'INTERMEDIATEMESSAGETHROW': false,
'INTERMEDIATEMESSAGECATCH': false
},
'ENDEMAIL': {
'START': false,
'TASK': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'END': false,
'INTERMEDIATE': false,
'INTERMEDIATEEMAIL': false,
'INTERMEDIATEMESSAGETHROW': false,
'INTERMEDIATEMESSAGECATCH': false
},
'ENDMESSAGETHROW': {
'START': false,
'TASK': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'END': false,
'INTERMEDIATE': false,
'INTERMEDIATEEMAIL': false,
'INTERMEDIATEMESSAGETHROW': false,
'INTERMEDIATEMESSAGECATCH': false
},
'TASK': {
'START': false,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': true,
'END': true,
'ENDEMAIL': true,
'ENDMESSAGETHROW': true,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true
},
'SUB_PROCESS': {
'START': false,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': true,
'END': true,
'ENDEMAIL': true,
'ENDMESSAGETHROW': true,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true
},
'GATEWAY': {
'START': false,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': true,
'END': true,
'ENDEMAIL': true,
'ENDMESSAGETHROW': true,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true
},
'DATAOBJECT': {
'TASK': true,
'INTERMEDIATE': true,
'INTERMEDIATEEMAIL': true,
'INTERMEDIATEMESSAGETHROW': true,
'INTERMEDIATEMESSAGECATCH': true
}
};
ConnectValidator.prototype.messageRules = {
'PARTICIPANT': {
'PARTICIPANT': true,
'TASK': true,
'SUBPROCESS': true,
'START': false,
'STARTMESSAGECATCH': true,
'END': false,
'INTERMEDIATE': true,
'INTERMEDIATEMESSAGECATCH': true,
'GATEWAY': false
},
'START': {
'PARTICIPANT': false
},
'STARTMESSAGECATCH': {
'PARTICIPANT': false
},
'INTERMEDIATE': {
'PARTICIPANT': false
},
'INTERMEDIATEMESSAGETHROW': {
'PARTICIPANT': true
},
'INTERMEDIATEMESSAGECATCH': {
'PARTICIPANT': false
},
'INTERMEDIATEEMAIL': {
'PARTICIPANT': true
},
'TASK': {
'PARTICIPANT': true
},
'SUB_PROCESS': {
'PARTICIPANT': true
},
'END': {
'PARTICIPANT': false
},
'GATEWAY': {
'PARTICIPANT': false
},
'DATA': {
'PARTICIPANT': false
},
'ENDMESSAGETHROW': {
'PARTICIPANT': true
},
'ENDEMAIL': {
'PARTICIPANT': true
}
};
ConnectValidator.prototype.associationRules = {
'PARTICIPANT': {
'TASK': false,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'DATA': false,
'END': false,
'PARTICIPANT': false
},
'START': {
'TASK': false,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'DATA': false,
'END': false,
'PARTICIPANT': false
},
'INTERMEDIATE': {
'TASK': false,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'DATA': false,
'END': false,
'PARTICIPANT': false
},
'END': {
'TASK': false,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'DATA': false,
'END': false,
'PARTICIPANT': false
},
'TASK': {
'TASK': false,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'DATA': true,
'END': false,
'PARTICIPANT': false
},
'SUB_PROCESS': {
'TASK': false,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'DATA': true,
'END': false,
'PARTICIPANT': false
},
'GATEWAY': {
'TASK': false,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': false,
'GATEWAY': false,
'DATAOBJECT': false,
'END': false
},
'DATA': {
'TASK': true,
'START': false,
'INTERMEDIATE': false,
'SUB_PROCESS': true,
'GATEWAY': false,
'DATA': false,
'END': false,
'PARTICIPANT': false
}
};
ConnectValidator.prototype.proMessageRules = {
'TASK': {
'START': false,
'INTERMEDIATE': false,
'TASK': true,
'SUB_PROCESS': true,
'GATEWAY': false,
'END': false
}
};
ConnectValidator.prototype.isValid = function (sourceShape, targetShape, connection) {
var result = {
result: false,
msg: 'Invalid Connections'.translate()
},
connectionConf,
rules,
i,
parentSource;
//type of shapes
if (this.getTypeToValidate(sourceShape) && this.getTypeToValidate(targetShape)) {
result.msg = 'Invalid Connection';
//validate if there is an current connection between same elements
if ((!connection || (connection.getSrcPort().getParent() !== sourceShape || connection.getDestPort() !== targetShape)) && PMFlow.existsConnection(sourceShape, targetShape, false)) {
return {
result: false,
msg: 'There is already a connection between these elements'.translate()
};
}
//validate loop connections
if (sourceShape.getID() === targetShape.getID()) {
return result;
}
if (sourceShape.participantObject) {
parentSource = sourceShape.participantObject.elem.$parent.id;
} else {
if (sourceShape.businessObject.elem.$type !== "bpmn:BoundaryEvent") {
parentSource = sourceShape.businessObject.elem.$parent.id;
} else {
parentSource = sourceShape.businessObject.elem.attachedToRef.$parent.id;
}
}
//verify if elenents are into the same process
if (sourceShape.businessObject.elem
&& targetShape.businessObject.elem
&& targetShape.businessObject.elem.$parent
&& parentSource !== targetShape.businessObject.elem.$parent.id) {
switch (sourceShape.type) {
case 'PMActivity':
result.conf = {
type: 'MESSAGE',
segmentStyle: 'segmented',
destDecorator: 'mafe-message',
srcDecorator: 'mafe-message'
};
if (targetShape.type === 'PMActivity') {
result.result = true;
result.invalid = true;
} else if (targetShape.type === 'PMEvent' && targetShape.evn_marker === 'MESSAGECATCH') {
result.result = true;
} else if (targetShape.type === 'PMData') {
result.result = true;
result.conf = {
type: 'DATAASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-association'
};
} else if (targetShape.type === 'PMArtifact') {
result.result = true;
result.conf = {
type: 'ASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-default'
};
}
break;
case 'PMEvent':
result.conf = {
type: 'MESSAGE',
segmentStyle: 'segmented',
destDecorator: 'mafe-message',
srcDecorator: 'mafe-message'
};
if (sourceShape.type === 'PMEvent'
&& (sourceShape.evn_marker === 'MESSAGETHROW')) {
if (targetShape.type === 'PMActivity') {
result.result = true;
} else if (targetShape.type === 'PMEvent' && targetShape.evn_marker === 'MESSAGECATCH') {
result.result = true;
}
} else if (targetShape.type === 'PMArtifact') {
result.result = true;
result.conf = {
type: 'ASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-default'
};
}
break;
case 'PMGateway':
if (targetShape.type === 'PMArtifact') {
result.result = true;
result.conf = {
type: 'ASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-default'
};
}
break;
case 'PMData':
if (targetShape.type === 'PMActivity') {
result.result = true;
result.conf = {
type: 'DATAASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-association'
};
} else if (targetShape.type === 'PMArtifact') {
result.result = true;
result.conf = {
type: 'ASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-default'
};
}
break;
case 'PMArtifact':
result.result = true;
result.conf = {
type: 'ASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-default'
};
break;
}
if (result.result) {
// validate that the sourceShape allow the outgoing connection
if ((!connection || (connection.getSrcPort().getParent() !== sourceShape)) && !this.canAcceptOutgoingConnection(sourceShape, result.conf.type)) {
return {
result: false,
msg: 'The source shape can not have more than one outgoing connection'.translate()
};
}
}
if (result.result) {
result.result = true;
targetShape.setConnectionType(result.conf);
}
} else {
if (this.initRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)]) {
rules = this.initRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)];
switch (rules) {
case 'sequencialRules':
if (this.sequencialRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)]) {
result.result = this.sequencialRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)];
}
connectionConf = {
type: 'SEQUENCE',
segmentStyle: 'regular',
destDecorator: 'mafe-sequence'
};
break;
case 'messageRules':
if (this.messageRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)]) {
result.result = this.messageRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)];
if (result.result) {
if (sourceShape.extendedType === 'START' && sourceShape.evn_marker === "MESSAGE") {
result.result = false;
result.msg = 'Start Event must not have any outgoing Message Flows'.translate();
}
}
}
connectionConf = {
type: 'MESSAGE',
segmentStyle: 'segmented',
destDecorator: 'mafe-message',
srcDecorator: 'mafe-message'
};
break;
case 'annotationRules':
result.result = true;
connectionConf = {
type: 'ASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-default'
};
break;
case 'associationRules':
if (this.associationRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)]) {
result.result = this.associationRules[this.getTypeToValidate(sourceShape)][this.getTypeToValidate(targetShape)];
}
connectionConf = {
type: 'DATAASSOCIATION',
segmentStyle: 'dotted',
destDecorator: 'mafe-association'
};
break;
}
if (result.result) {
// validate that the sourceShape allow the outgoing connection
if ((!connection || (connection.getSrcPort().getParent() !== sourceShape)) && !this.canAcceptOutgoingConnection(sourceShape, connectionConf.type)) {
return {
result: false,
msg: 'The source shape can not have more than one outgoing connection'.translate()
};
}
}
targetShape.setConnectionType(connectionConf);
}
}
}
return result;
};
ConnectValidator.prototype.getTypeToValidate = function (shape) {
var type;
switch (shape.extendedType) {
case 'START':
if (shape.getEventMarker() === 'MESSAGECATCH') {
type = shape.extendedType + shape.getEventMarker();
} else {
type = shape.extendedType;
}
break;
case 'END':
if (shape.getEventMarker() === 'EMAIL'
|| shape.getEventMarker() === 'MESSAGETHROW') {
type = shape.extendedType + shape.getEventMarker();
} else {
type = shape.extendedType;
}
break;
case 'INTERMEDIATE':
if (shape.getEventMarker() === 'EMAIL'
|| shape.getEventMarker() === 'MESSAGETHROW'
|| shape.getEventMarker() === 'MESSAGECATCH') {
type = shape.extendedType + shape.getEventMarker();
} else {
type = shape.extendedType;
}
break;
case 'TASK':
case 'SUB_PROCESS':
case 'PARTICIPANT':
case 'TEXT_ANNOTATION':
type = shape.extendedType;
break;
case 'EXCLUSIVE':
case 'PARALLEL':
case 'INCLUSIVE':
case 'COMPLEX':
type = 'GATEWAY';
break;
case 'DATAOBJECT':
case 'DATASTORE':
case 'DATAINPUT':
case 'DATAOUTPUT':
type = 'DATA';
break;
case 'GROUP':
type = 'GROUP';
break;
case 'POOL':
type = 'POOL';
break;
case 'LANE':
type = 'LANE';
break;
default:
type = 'TASK';
break;
}
return type;
};
ConnectValidator.prototype.styleErrorMap = new PMUI.util.ArrayList();
ConnectValidator.prototype.hasNotMap = new PMUI.util.ArrayList();
/**
* Validate All Shapes.
* @returns {ConnectValidator}
*/
ConnectValidator.prototype.bpmnValidator = function () {
var canvas,
shape,
i;
canvas = PMUI.getActiveCanvas();
PMDesigner.validTable.clear().draw();
for (i = 0; i < canvas.customShapes.getSize(); i += 1) {
shape = canvas.customShapes.get(i);
this.bpmnValidatorShape(shape);
}
return this;
};
/**
* Validate un update a bpmn element
* @param {*} updatedElement
*/
ConnectValidator.prototype.bpmnValidateOnUpdate = function (updatedElement) {
for (i = 0; i < updatedElement.length; i += 1) {
if(updatedElement[i].type === "Connection") {
if (updatedElement[i].relatedObject.type === "Port") {
this.bpmnValidatorShape(updatedElement[i].relatedObject.parent);
this.bpmnValidatorShape(updatedElement[i].relatedObject.oldParent);
} else {
this.bpmnValidatorShape(updatedElement[i].relatedObject.destPort.parent);
this.bpmnValidatorShape(updatedElement[i].relatedObject.srcPort.parent);
}
}
}
return this;
};
/**
* Validate Shape
* @param shape
* @returns {ConnectValidator}
*/
ConnectValidator.prototype.bpmnValidatorShape = function (shape) {
if (shape && shape.validatorMarker) {
this.bpmnFlowValidator(shape);
shape.validatorMarker.hide();
if (shape.getNumErrors() > 0 && shape.validatorMarker) {
if (shape.validateWarning(shape.getArrayErrors())) {
shape.setTypeErrors("warning");
} else {
shape.setTypeErrors("error");
}
shape.validatorMarker.show();
}
}
return this;
};
/**
* Call to Sequence flow Validator
* @param shape
* @returns {ConnectValidator}
*/
ConnectValidator.prototype.bpmnFlowValidator = function (shape) {
this.sequenceFlowValidator(shape);
return this;
};
/**
* Check the type bpmn Shape and get rules of validation
* @param shape
*/
ConnectValidator.prototype.sequenceFlowValidator = function (shape) {
var ref = shape.businessObject.elem,
criteria,
errorCandidates,
i,
error = {},
type,
max;
shape.errors.clear();
if (shape.getType() === 'PMParticipant') {
ref = shape.participantObject.elem;
}
switch (ref.$type) {
case 'bpmn:Task':
case 'bpmn:SendTask':
case 'bpmn:ReceiveTask':
case 'bpmn:ServiceTask':
case 'bpmn:UserTask':
case 'bpmn:ScriptTask':
case 'bpmn:ManualTask':
case 'bpmn:BusinessRuleTask':
type = 'bpmnActivity';
break;
case 'bpmn:SubProcess':
type = 'bpmnSubProcess';
break;
case 'bpmn:IntermediateThrowEvent':
case 'bpmn:IntermediateCatchEvent':
type = 'bpmnIntermediateEvent';
break;
case 'bpmn:ExclusiveGateway':
case 'bpmn:ParallelGateway':
case 'bpmn:InclusiveGateway':
type = 'bpmnGateway';
break;
case 'bpmn:DataObjectReference':
type = 'bpmnDataObject';
break;
case 'bpmn:DataStoreReference':
type = 'bpmnDataStore';
break;
default:
type = ref.$type;
break;
}
if (PMDesigner.modelRules.getStatus()) {
errorCandidates = PMDesigner.modelRules.getCollectionType(type);
}
if (errorCandidates) {
for (i = 0, max = errorCandidates.getSize(); i < max; i += 1) {
error = errorCandidates.get(i);
criteria = error.getCriteria();
if (criteria && typeof criteria === "function") {
criteria(shape, _.extend({}, error));
}
}
}
};
/**
* Verify if the supplied element can accept one outgoing connection more.
* @param {PMShape} shape
* @returns {boolean}
*/
ConnectValidator.prototype.canAcceptOutgoingConnection = function (shape, connectionType) {
if (!(shape instanceof PMGateway) && connectionType === 'SEQUENCE') {
return !shape.getOutgoingConnections(connectionType).length;
}
return true;
};
/**
* Validate if PMActivity/PMEvent onDrop is correct
* @param {PMUI.draw.Shape} shape
* @param {PMUI.draw.Shape} customShape
* @returns {boolean}
*/
ConnectValidator.prototype.onDropMovementIsAllowed = function (shape, customShape) {
var result = true,
i,
connection,
ports,
len,
sourceShape,
targetShape,
elemShape,
flowType,
oldParent = customShape.getOldParent().getParent();
if (shape.getID() !== customShape.getParent().getID()) {
ports = customShape.getPorts();
len = ports.getSize();
for (i = 0; i < len; i += 1) {
//Get sourceShape and targetShape (PMevent/PMactivity)
connection = ports.get(i).getConnection();
sourceShape = connection.getSrcPort().getParent();
targetShape = connection.getDestPort().getParent();
elemShape = shape.businessObject.elem;
elemShape = (elemShape && elemShape.$parent && elemShape.$parent.$parent) ? elemShape : false;
flowType = (connection.getFlowType() === 'MESSAGE') ? true : false;
if (flowType &&
(sourceShape.getParent().getID() === shape.getID()
|| targetShape.getParent().getID() === shape.getID())) {
result = false;
break;
} else if (elemShape && flowType &&
(elemShape.$parent.$parent.id === sourceShape.businessObject.elem.$parent.id ||
elemShape.$parent.$parent.id === targetShape.businessObject.elem.$parent.id)) {
result = (oldParent) ? (oldParent.getID() !== shape.getParent().getID()) ? false : true : false;
break;
}
}
}
return result;
};
var CommandChangeGatewayType = function (receiver, options) {
PMUI.command.Command.call(this, receiver);
this.before = null;
this.after = null;
CommandChangeGatewayType.prototype.initObject.call(this, options);
};
PMUI.inheritFrom('PMUI.command.Command', CommandChangeGatewayType);
/**
* Type of the instances of this class
* @property {String}
*/
CommandChangeGatewayType.prototype.type = "CommandChangeGatewayType";
/**
* Initializes the command parameters
* @param {PMUI.draw.Core} receiver The object that will perform the action
*/
CommandChangeGatewayType.prototype.initObject = function (options) {
var parsedClass = options;
this.layer = this.receiver.getLayers().get(0);
this.before = {
zoomSprite: this.layer.zoomSprites,
type: this.receiver.extendedType,
defaultFlow: this.receiver.canvas.items.find('id', this.receiver.gat_default_flow) ?
this.receiver.canvas.items.find('id', this.receiver.gat_default_flow).relatedObject : null
};
this.after = {
zoomSprite: [
'mafe-gateway-' + parsedClass.toLowerCase() + '-20',
'mafe-gateway-' + parsedClass.toLowerCase() + '-30',
'mafe-gateway-' + parsedClass.toLowerCase() + '-41',
'mafe-gateway-' + parsedClass.toLowerCase() + '-51',
'mafe-gateway-' + parsedClass.toLowerCase() + '-61'
],
type: options
};
};
/**
* Executes the command, changes the position of the element, and if necessary
* updates the position of its children, and refreshes all connections
*/
CommandChangeGatewayType.prototype.execute = function () {
var menuShape;
this.layer.setZoomSprites(this.after.zoomSprite);
this.receiver.setGatewayType(this.after.type);
this.receiver.extendedType = this.after.type;
this.receiver
.updateBpmGatewayType(this.receiver.mapBpmnType[this.after.type]);
PMDesigner.project.updateElement([]);
this.receiver.paint();
if (this.after.type === 'PARALLEL' && this.before.defaultFlow) {
this.receiver.gat_default_flow = null;
this.before.defaultFlow.changeFlowType('sequence');
this.before.defaultFlow.setFlowType("SEQUENCE");
}
menuShape = PMDesigner.getMenuFactory(this.after.type);
this.receiver.setContextMenu(menuShape);
};
/**
* Returns to the state before the command was executed
*/
CommandChangeGatewayType.prototype.undo = function () {
this.layer.setZoomSprites(this.before.zoomSprite);
this.receiver.setGatewayType(this.before.type);
this.receiver.extendedType = this.before.type;
this.receiver
.updateBpmGatewayType(this.receiver.mapBpmnType[this.before.type]);
PMDesigner.project.setDirty(true);
$(this.receiver.html).trigger('changeelement');
this.receiver.paint();
menuShape = PMDesigner.getMenuFactory(this.before.type);
this.receiver.setContextMenu(menuShape);
if (this.after.type === 'PARALLEL' && this.before.defaultFlow) {
this.receiver.gat_default_flow = this.before.defaultFlow.getID();
this.before.defaultFlow.setFlowCondition("");
this.before.defaultFlow.changeFlowType('default');
this.before.defaultFlow.setFlowType("DEFAULT");
}
};
/**
* Executes the command again after an undo action has been done
*/
CommandChangeGatewayType.prototype.redo = function () {
this.execute();
};
var CommandDefaultFlow = function (receiver, options) {
PMUI.command.Command.call(this, receiver);
this.before = null;
this.after = null;
CommandDefaultFlow.prototype.initObject.call(this, options);
};
PMUI.inheritFrom('PMUI.command.Command', CommandDefaultFlow);
/**
* Type of the instances of this class
* @property {String}
*/
CommandChangeGatewayType.prototype.type = "CommandDefaultFlow";
/**
* Initializes the command parameters
* @param {PMUI.draw.Core} receiver The object that will perform the action
*/
CommandDefaultFlow.prototype.initObject = function (options) {
this.before = {
id: this.receiver.gat_default_flow
};
this.after = {
id: options
};
};
/**
* Executes the command, changes the position of the element, and if necessary
* updates the position of its children, and refreshes all connections
*/
CommandDefaultFlow.prototype.execute = function () {
this.receiver.setDefaultFlow(this.after.id);
PMDesigner.project.setDirty(true);
};
/**
* Returns to the state before the command was executed
*/
CommandDefaultFlow.prototype.undo = function () {
this.receiver.setDefaultFlow(this.before.id);
};
/**
* Executes the command again after an undo action has been done
*/
CommandDefaultFlow.prototype.redo = function () {
this.execute();
};
/**
* @class PMArtifact
* Handle BPMN Annotations
*
*
* @constructor
* Creates a new instance of the class
* @param {Object} options
*/
var PMLabel = function (options) {
PMShape.call(this, options);
/**
* Defines the type artifact
* @type {String}
*/
this.art_type = null;
/**
* Defines the unique identifier
* @type {String}
*/
this.art_uid = null;
PMArtifact.prototype.initObject.call(this, options);
};
PMLabel.prototype = new PMShape();
/**
* Defines the object type
* @type {String}
*/
PMLabel.prototype.type = "PMArtifact";
PMLabel.prototype.PMArtifactResizeBehavior = null;
/**
* Initialize the object with the default values
* @param {Object} options
*/
PMArtifact.prototype.initObject = function (options) {
var defaults = {
art_type: 'PMArtifact',
art_name: ""
};
jQuery.extend(true, defaults, options);
this.setArtifactUid(defaults.art_uid);
this.setArtifactType(defaults.art_type);
this.setName(defaults.art_name);
};
/**
* Sets the artifact type property
* @param {String} type
* @return {*}
*/
PMLabel.prototype.setArtifactType = function (type) {
this.art_type = type;
return this;
};
/**
* Sets the artifact unique identifier
* @param {String} value
* @return {*}
*/
PMLabel.prototype.setArtifactUid = function (value) {
this.art_uid = value;
return this;
};
/**
* Returns the clean object to be sent to the backend
* @return {Object}
*/
PMLabel.prototype.getDataObject = function () {
var name = this.getName();
return {
art_uid: this.id,
art_name: name,
art_type: this.art_type,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: 'bpmnDiagram',
_extended: this.getExtendedObject()
};
};
PMLabel.prototype.getArtifactType = function () {
return this.art_type;
};
PMLabel.prototype.createLayer = function (options) {
var layer;
options.parent = this;
layer = new CustomLayer(options);
this.addLayer(layer);
return layer;
};
PMArtifact.prototype.updateHTML = function () {
var height, width;
height = this.height;
width = this.width;
PMShape.prototype.updateHTML.call(this);
this.setDimension(width, height);
return this;
};
/*global jCore, $ */
/**
* @class AdamMarker
* Handle Activity Markers
*
* @constructor
* Creates a new instance of the class
* @param {Object} options
*/
var PMMarker = function (options) {
PMUI.draw.Shape.call(this, options);
/**
* Defines the positions of the markers
* @type {Array}
* @private
*/
this.positions = ['left+2 top+2', 'center top+5', 'right top',
'left+5 bottom-1', 'center bottom-2', 'right-5 bottom-1'];
/**
* Defines the offset of the markers
* @type {Array}
* @private
*/
this.offset = ['5 5', '0 5', '0 5', '5 -1', '0 -1', '-5 -1'];
/**
* Define the marker type property
* @type {null}
*/
this.markerType = null;
PMMarker.prototype.initObject.call(this, options);
};
PMMarker.prototype = new PMUI.draw.Shape();
/**
* Defines the object type
* @type {String}
*/
PMMarker.prototype.type = 'PMMarker';
/**
* Initialize the object with the default values
* @param {Object} options
*/
PMMarker.prototype.initObject = function (options) {
var defaults = {
canvas: null,
parent: null,
position: 0,
width: 21,
height: 21,
markerZoomClasses: [],
markerType: null
};
$.extend(true, defaults, options);
this.setParent(defaults.parent)
.setPosition(defaults.position)
.setHeight(defaults.height)
.setWidth(defaults.width)
.setMarkerZoomClasses(defaults.markerZoomClasses)
.setMarkerType(defaults.markerType);
};
/**
* Applies zoom to the Marker
* @return {*}
*/
PMMarker.prototype.applyZoom = function () {
var newSprite;
this.removeAllClasses();
this.setProperties();
newSprite = this.markerZoomClasses[this.parent.canvas.zoomPropertiesIndex];
this.html.className = newSprite;
this.currentZoomClass = newSprite;
return this;
};
/**
* Create the HTML for the marker
* @return {*}
*/
PMMarker.prototype.createHTML = function () {
PMUI.draw.Shape.prototype.createHTML.call(this);
this.html.id = this.id;
this.setProperties();
this.html.className = this.markerZoomClasses[
this.parent.canvas.getZoomPropertiesIndex()
];
this.currentZoomClass = this.html.className;
this.parent.html.appendChild(this.html);
return this.html;
};
/**
* Updates the painting of the marker
* @param update
*/
PMMarker.prototype.paint = function (update) {
if (this.getHTML() === null || update) {
this.createHTML();
}
$(this.html).position({
of: $(this.parent.html),
my: this.positions[this.position],
at: this.positions[this.position],
collision: 'none'
});
};
/**
* Sets the marker type property
* @param {String} newType
* @return {*}
*/
PMMarker.prototype.setMarkerType = function (newType) {
this.markerType = newType;
return this;
};
/**
* Sets the position of the marker
* @param {Number} newPosition
* @return {*}
*/
PMMarker.prototype.setPosition = function (newPosition) {
if (newPosition !== null && typeof newPosition === 'number') {
this.position = newPosition;
}
return this;
};
/**
* Sets the parent of the marker
* @param {AdamActivity} newParent
* @return {*}
*/
PMMarker.prototype.setParent = function (newParent) {
this.parent = newParent;
return this;
};
/**
* Sets the elements class
* @param eClass
* @return {*}
*/
PMMarker.prototype.setEClass = function (eClass) {
this.currentZoomClass = eClass;
return this;
};
/**
* Sets the array of zoom classes
* @param {Object} classes
* @return {*}
*/
PMMarker.prototype.setMarkerZoomClasses = function (classes) {
this.markerZoomClasses = classes;
return this;
};
/**
* Sets the marker HTML properties
* @return {*}
*/
PMMarker.prototype.setProperties = function () {
this.html.style.width = this.width * this.parent.getCanvas().getZoomFactor() + 'px';
this.html.style.height = this.height * this.parent.getCanvas().getZoomFactor() + 'px';
return this;
};
/**
* Remove all classes of HTML
* @return {*}
*/
PMMarker.prototype.removeAllClasses = function () {
this.html.className = '';
return this;
};
/*global jCore*/
var PMActivityResizeBehavior = function () {
};
PMActivityResizeBehavior.prototype = new PMUI.behavior.RegularResizeBehavior();
PMActivityResizeBehavior.prototype.type = "PMActivityResizeBehavior";
/**
* Sets a shape's container to a given container
* @param container
* @param shape
*/
PMActivityResizeBehavior.prototype.onResizeStart = function (shape) {
return PMUI.behavior.RegularResizeBehavior
.prototype.onResizeStart.call(this, shape);
};
/**
* Removes shape from its current container
* @param shape
*/
PMActivityResizeBehavior.prototype.onResize = function (shape) {
return function (e, ui) {
PMUI.behavior.RegularResizeBehavior
.prototype.onResize.call(this, shape)(e, ui);
shape.paint();
shape.updateBoundaryPositions(false);
};
};
PMActivityResizeBehavior.prototype.onResizeEnd = function (shape) {
return function (e, ui) {
var i,
label,
command,
margin = 10;
shape.resizing = false;
shape.canvas.isResizing = false;
// last resize
PMUI.behavior.RegularResizeBehavior.prototype.onResize.call(this, shape)(e, ui);
// show the handlers again
shape.showOrHideResizeHandlers(true);
// update the dimensions of the parent if possible (a shape might
// have been resized out of the dimensions of its parent)
shape.parent.updateDimensions(margin);
if (shape.ports) {
shape.firePortsChange();
}
// TESTING COMMANDS
command = new PMCommandResize(shape);
shape.canvas.commandStack.add(command);
command.execute();
for (i = 0; i < shape.labels.getSize(); i += 1) {
label = shape.labels.get(i);
label.setLabelPosition(label.location, label.diffX, label.diffY);
}
return true;
};
};
/**
* @class PMGateway
* @param {Object} options
*/
var PMData = function (options) {
PMShape.call(this, options);
this.dat_name = '';
this.dat_type = 'DATAOBJECT';
this.dat_is_collection = false;
this.dat_is_global = false;
this.dat_object_ref = '';
this.dat_is_unlimited = false;
this.dat_capacity = 0;
this.businessObject = {};
PMData.prototype.init.call(this, options);
};
PMData.prototype = new PMShape();
/**
* Defines the object type
* @type {String}
*/
PMData.prototype.type = 'PMData';
PMData.prototype.mapBpmnType = {
'DATAOBJECT': 'bpmn:DataObject',
'DATAINPUT': 'bpmn:DataInput',
'DATAOUTPUT': 'bpmn:DataOutput'
};
PMData.prototype.getDataObject = function () {
var name = this.getName(),
container,
element_id;
switch (this.parent.type) {
case 'PMCanvas':
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
case 'PMPool':
container = 'bpmnPool';
element_id = this.parent.id;
break;
case 'PMLane':
container = 'bpmnLane';
element_id = this.parent.id;
break;
default:
container = 'bpmnDiagram';
element_id = this.canvas.id;
break;
}
return {
dat_uid: this.dat_uid,
dat_name: name,
dat_type: this.dat_type,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: container,
bou_element: element_id,
_extended: this.getExtendedObject()
};
};
/**
* Initialize the PMData object
* @param options
*/
PMData.prototype.init = function (options) {
var defaults = {
dat_name: '',
dat_type: '',
dat_is_collection: false,
dat_is_global: false,
dat_object_ref: '',
dat_is_unlimited: false,
dat_capacity: 0
};
jQuery.extend(true, defaults, options);
this.setDataUid(defaults.dat_uid)
.setDataType(defaults.dat_type);
if (defaults.dat_name) {
this.setName(defaults.dat_name);
}
this.setOnBeforeContextMenu(this.beforeContextMenu);
};
/**
* Gets BPMNShape type
* @returns {string}
*/
PMData.prototype.getDataType = function () {
return this.dat_type;
};
/**
* Gets Data Name
* @returns {string}
*/
PMData.prototype.getDataName = function () {
return this.dat_name;
};
/**
* Gets Data Capasity
* @returns {*}
*/
PMData.prototype.getCapacity = function () {
return this.dat_capacity;
};
/**
* Gets Data global value
* @returns {boolean}
*/
PMData.prototype.getIsGlobal = function () {
return this.dat_is_global;
};
/**
* Gets Data Unlimited value
* @returns {boolean}
*/
PMData.prototype.getUnlimited = function () {
return this.dat_is_unlimited;
};
/**
* Gets Data collection status
* @returns {boolean}
*/
PMData.prototype.getDataCollection = function () {
return this.dat_is_collection;
};
/**
* Gets Data type
* @returns {string}
*/
PMData.prototype.getDataType = function () {
return this.dat_type;
};
/**
* Sets the act_uid property
* @param {String} value
* @return {*}
*/
PMData.prototype.setDataUid = function (value) {
this.dat_uid = value;
return this;
};
/**
* Sets Data name
* @param {string} newName
* @chainable
*/
PMData.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.act_name = name;
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
/**
* Sets BPMNData type
* @param {string} newType
* @chainable
*/
PMData.prototype.setDataType = function (newType) {
if (!newType || typeof newType === 'undefined') {
return;
}
this.dat_type = newType;
return this;
};
/**
* Sets Data global mode
* @param {boolean} isGlobal
* @returns {*}
*/
PMData.prototype.setIsGlobal = function (isGlobal) {
if (typeof isGlobal !== 'undefined') {
this.dat_is_global = isGlobal;
}
return this;
};
/**
* Sets Data capasity
* @param {string} capacity
* @returns {*}
*/
PMData.prototype.setCapacity = function (capacity) {
if (typeof capacity === 'undefined')
return;
this.dat_capacity = capacity;
return this;
};
/**
* Setd data unlimited mode
* @param {boolean} unlimited
* @returns {*}
*/
PMData.prototype.setIsUnlimited = function (unlimited) {
if (typeof unlimited === 'undefined')
return;
this.dat_is_unlimited = unlimited;
return this;
};
/**
* Sets Data collection mode
* @param {boolean} collection
* @returns {*}
*/
PMData.prototype.setIsCollection = function (collection) {
if (typeof collection === 'undefined')
return;
this.dat_is_collection = collection;
return this;
};
/**
* Change data type
* @param {String} type
* @returns {*}
*/
PMData.prototype.switchDataType = function (type) {
var marker = this.markersArray.get(0),
lowerType = type.toLowerCase();
marker.removeAllClasses();
marker.setMarkerZoomClasses([
"mafe-" + lowerType + "-marker-10",
"mafe-" + lowerType + "-marker-15",
"mafe-" + lowerType + "-marker-21",
"mafe-" + lowerType + "-marker-26",
"mafe-" + lowerType + "-marker-31"
]);
marker.paint(true);
this.setDataType(type);
this.updateBpmnDataType(this.mapBpmnType[this.getDataType()], type);
PMDesigner.project.updateElement([]);
return this;
};
PMData.prototype.updateBpmnDataType = function (newBpmnType, dataType) {
this.verifyDataIOEspecification();
this.removeBpmn();
this.businessObject.elem = null;
this.createBpmn(newBpmnType, dataType);
};
PMData.prototype.createWithBpmn = function (bpmnElementType, name) {
var businessObject = {};
if (this.extendedType === 'DATASTORE') {
var ds = PMDesigner.bpmnFactory.create('bpmn:DataStore', {
id: this.id,
name: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : "",
});
PMDesigner.businessObject.get('rootElements').push(ds);
businessObject.elem = PMDesigner.bpmnFactory.create('bpmn:DataStoreReference', {
id: this.id + '_ref',
name: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : "",
dataStoreRef: ds
});
businessObject.elem.dsRef = ds;
} else {
if (bpmnElementType == 'bpmn:DataObject' || bpmnElementType === undefined) {
var dObj = PMDesigner.bpmnFactory.create('bpmn:DataObject', {
id: this.id,
name: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : "",
});
businessObject.elem = PMDesigner.bpmnFactory.create('bpmn:DataObjectReference', {
id: this.id + '_ref',
name: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : "",
dataObjectRef: dObj
});
// validate if container is a lane because data store is always into process tag
if (this.parent.getType() === 'PMLane') {
this.updateSemanticParent({elem: dObj}, this.parent.parent.businessObject);
} else {
this.updateSemanticParent({elem: dObj}, this.parent.businessObject);
}
businessObject.elem.doRef = dObj;
}
if (bpmnElementType == 'bpmn:DataInput' || bpmnElementType == 'bpmn:DataOutput') {
businessObject = this.createDataIOBusinessObject(bpmnElementType);
}
}
if (!businessObject.di) {
businessObject.di = PMDesigner.bpmnFactory.createDiShape(businessObject.elem, {}, {
id: businessObject.elem.id + '_di'
});
}
this[name] = businessObject;
};
PMData.prototype.beforeContextMenu = function () {
var items, i,
menuItem,
hasMarker = false;
this.canvas.hideAllCoronas();
if (this.canvas.readOnly) {
return;
}
if (this.getDataType() === 'DATAOBJECT' || this.getDataType() === 'DATAOUTPUT' || this.getDataType() === 'DATAINPUT') {
items = this.menu.items.find('id', 'dataType').childMenu.items;
for (i = 0; i < items.getSize(); i += 1) {
menuItem = items.get(i);
if (menuItem.id === this.getDataType().toLowerCase()) {
menuItem.disable();
hasMarker = true;
} else {
menuItem.enable();
}
}
}
};
PMData.prototype.getDataType = function () {
return this.dat_type;
};
PMData.prototype.createDataIOEspecification = function (element) {
var ioEspecification = PMDesigner.bpmnFactory.create('bpmn:InputOutputSpecification', {
id: this.id + '_ioEspecification',
name: (this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : "") + '_ioEspecification'
});
ioEspecification['dataInputs'] = [];
this.parent.businessObject.elem['ioSpecification'] = ioEspecification;
};
PMData.prototype.verifyDataIOEspecification = function () {
if (!this.parent.businessObject.elem || !this.parent.businessObject.elem.get('ioSpecification')) {
this.createDataIOEspecification(this.parent.businessObject);
}
};
PMData.prototype.createDataBusinessObject = function () {
return this;
};
PMData.prototype.createDataIOBusinessObject = function (bpmnElementType) {
var dObj = PMDesigner.bpmnFactory.create(bpmnElementType, {
id: this.id,
name: this.getName() ? PMDesigner.escapeXMLCharacters(this.getName()) : ""
});
this.parent.businessObject.elem['ioSpecification'].dataInputs.push(dObj);
return {elem: dObj};
};
var PMParticipant = function (options) {
PMShape.call(this, options);
/**
*
* @type {String}
*/
this.name = '';
/**
*
* @type {String}
*/
this.proUid = '';
/**
*
* @type {String}
*/
this.childLaneset = '';
/**
*
* @type {Number}
*/
this.numParticipants = 0;
this.graphic = null;
this.headLineCoord = 40;
this.orientation = 'HORIZONTAL';
PMParticipant.prototype.initObject.call(this, options);
};
PMParticipant.prototype = new PMShape();
PMParticipant.prototype.type = 'PMParticipant';
PMParticipant.prototype.participantResizeBehavior = null;
PMParticipant.prototype.getDataObject = function () {
var name = this.getName();
return {
par_uid: this.getID(),
par_name: name,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: 'bpmnDiagram',
_extended: this.getExtendedObject()
};
};
PMParticipant.prototype.initObject = function (options) {
var defaultOptions = {
name: 'Participant',
numParticipants: 0,
orientation: 'HORIZONTAL'
};
$.extend(true, defaultOptions, options);
this.setName(defaultOptions.par_name)
.setNumparticipants(defaultOptions.numParticipants)
.setOrientation(defaultOptions.orientation);
};
PMParticipant.prototype.createHTML = function () {
PMShape.prototype.createHTML.call(this);
this.style.addClasses(['mafe_participant']);
return this.html;
};
PMParticipant.prototype.decreaseZIndex = function () {
this.fixZIndex(this, 1);
return this;
};
PMParticipant.prototype.onUpdateLabel = function () {
var label = this.getLabels().get(0);
label.text.style["text-overflow"] = "ellipsis";
label.text.style["overflow"] = "hidden";
label.text.style["white-space"] = "nowrap";
label.text.style["margin-left"] = "2%";
label.text.setAttribute("title", label.getMessage());
return this;
};
PMParticipant.prototype.paint = function () {
var zoomFactor = this.canvas.zoomFactor;
if (typeof this.graphic === 'undefined' || this.graphic === null) {
this.graphic = new JSGraphics(this.id);
} else {
this.graphic.clear();
}
if (this.validatorMarker) {
this.validatorMarker.paint();
this.validatorMarker.hide();
}
this.graphic.setColor('#3b4753');
this.graphic.setStroke(2);
if (this.orientation === 'VERTICAL') {
this.graphic.drawLine(0, this.headLineCoord * zoomFactor, this.zoomWidth,
this.headLineCoord * zoomFactor);
this.getLabels().get(0).setOrientation('horizontal');
this.getLabels().get(0).setLabelPosition('top');
} else {
this.graphic.drawLine(this.headLineCoord * zoomFactor, 0,
this.headLineCoord * zoomFactor,
this.zoomHeight - 5);
this.getLabels().get(0).setOrientation('vertical');
this.getLabels().get(0).setLabelPosition('center-left', 20, 0);
}
this.onUpdateLabel();
this.graphic.paint();
if (this.corona) {
this.corona.paint();
this.corona.hide();
}
};
/**
* Change pool orientation dinamically
* @param {String} orientation
* @returns {BPMNPool}
*/
PMParticipant.prototype.changeOrientation = function (orientation) {
var command = new BPMNCommandUpdateOrientation(this, {
before: this.getOrientation(),
after: orientation.toUpperCase()
});
command.execute();
this.getCanvas().commandStack.add(command);
return this;
};
/**
* Set participant name
* @param {String} name
* @returns {BPMNLane}
*/
PMParticipant.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.par_name = name;
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
/**
* Set participant name
* @param {String} name
* @returns {BPMNLane}
*/
PMParticipant.prototype.setType = function (newType) {
this.type = newType;
return this;
};
/**
* Set process uid asociated to participant
* @param {String} uid
* @returns {BPMNLane}
*/
PMParticipant.prototype.setProUid = function (uid) {
this.proUid = uid;
return this;
};
/**
* Set number of participants
* @param {Number} uid
* @returns {BPMNLane}
*/
PMParticipant.prototype.setNumparticipants = function (numParticipants) {
this.numParticipants = numParticipants;
return this;
};
/**
* Set pool orientation
* @param {String} orientation
* @returns {BPMNLane}
*/
PMParticipant.prototype.setOrientation = function (orientation) {
this.orientation = orientation;
return this;
};
/**
* Get the participant name
* @returns {String}
*/
PMParticipant.prototype.getName = function () {
return this.par_name;
};
/**
* Get the participant process uid
* @returns {String}
*/
PMParticipant.prototype.getProUid = function () {
return this.proUid;
};
/**
* Get the number of participants
* @returns {Number}
*/
PMParticipant.prototype.getNumParticipants = function () {
return this.numParticipants;
};
/**
* Get the type
* @returns {Number}
*/
PMParticipant.prototype.getType = function () {
return this.type;
};
/**
* Get orientation
* @returns {Number}
*/
PMParticipant.prototype.getOrientation = function () {
return this.orientation;
};
PMParticipant.prototype.setResizeBehavior = function (behavior) {
var factory = new PMUI.behavior.BehaviorFactory({
products: {
"regularresize": PMUI.behavior.RegularResizeBehavior,
"Resize": PMUI.behavior.RegularResizeBehavior,
"yes": PMUI.behavior.RegularResizeBehavior,
"resize": PMUI.behavior.RegularResizeBehavior,
"noresize": PMUI.behavior.NoResizeBehavior,
"NoResize": PMUI.behavior.NoResizeBehavior,
"no": PMUI.behavior.NoResizeBehavior,
"participantResize": PMParticipantResizeBehavior
},
defaultProduct: "noresize"
});
this.resizeBehavior = factory.make(behavior);
if (this.html) {
this.resize.init(this);
}
return this;
};
PMParticipant.prototype.createBpmn = function (type) {
var bpmnCollaboration;
if (!this.parent.businessObject.di) {
this.parent.createBPMNDiagram();
}
if (!(_.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"}))) {
bpmnCollaboration = PMDesigner.moddle.create('bpmn:Collaboration', {id: 'pmui-' + PMUI.generateUniqueId()});
PMDesigner.businessObject.get('rootElements').push(bpmnCollaboration);
this.parent.businessObject.di.bpmnElement = bpmnCollaboration;
bpmnCollaboration.participants = [];
bpmnCollaboration.messageFlows = [];
} else {
bpmnCollaboration = _.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"});
}
if (!this.businessObject.elem) {
this.createWithBpmn(type, 'participantObject');
this.updateBounds(this.participantObject.di);
this.updateSemanticParent(this.participantObject, {elem: bpmnCollaboration});
this.updateDiParent(this.participantObject.di, this.parent.businessObject.di);
}
};
PMParticipant.prototype.updateSemanticParent = function (businessObject, newParent) {
var children;
if (businessObject.elem.$parent === newParent.elem) {
return;
}
if (businessObject.elem.$parent) {
children = businessObject.elem.$parent.get('participants');
CollectionRemove(children, businessObject.elem);
}
if (!newParent.elem) {
businessObject.elem.$parent = null;
} else {
children = newParent.elem.get('participants');
children.push(businessObject.elem);
businessObject.elem.$parent = newParent.elem;
}
};
PMParticipant.prototype.updateDiParent = function (di, parentDi) {
PMShape.prototype.updateDiParent.call(this, di, parentDi);
};
/**
* create busines object to moodle bpmn export
*/
PMParticipant.prototype.createBusinesObject = function () {
var participant = _.findWhere(this.participantObject.elem.$parent.get('participants'),
{id: this.participantObject.elem.id}),
bpmnProcess = PMDesigner.moddle.create('bpmn:Process',
{id: 'pmui-' + PMUI.generateUniqueId()});
PMDesigner.businessObject.get('rootElements').push(bpmnProcess);
this.businessObject.elem = bpmnProcess;
this.businessObject.di = this.canvas.businessObject.di;
participant.processRef = bpmnProcess;
};
PMParticipant.prototype.removeBpmn = function () {
var coll, children, pros;
if ((_.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"}))) {
coll = _.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"});
if (coll.participants.length === 1) {
children = PMDesigner.businessObject.get('rootElements');
CollectionRemove(children, coll);
//PMDesigner.businessObject.get
if (this.parent.businessObject.di) {
this.parent.businessObject.di.bpmnElement = this.parent.businessObject;
}
}
}
if (this.businessObject.elem && (_.findWhere(PMDesigner.businessObject.get('rootElements'), {
$type: "bpmn:Process",
id: this.businessObject.elem.id
}))) {
pros = _.findWhere(PMDesigner.businessObject.get('rootElements'), {
$type: "bpmn:Process",
id: this.businessObject.elem.id
});
children = PMDesigner.businessObject.get('rootElements');
CollectionRemove(children, pros);
this.businessObject.elem = null;
}
this.updateSemanticParent(this.participantObject, {elem: null});
this.updateDiParent(this.participantObject.di);
if (this.businessObject.di
&& this.businessObject.di.planeElement.length == 0) {
this.parent.removeBPMNDiagram();
}
};
PMParticipant.prototype.updateBpmn = function () {
this.updateBounds(this.participantObject.di);
};
/*global jCore*/
var PMParticipantResizeBehavior = function () {
};
PMParticipantResizeBehavior.prototype = new PMUI.behavior.RegularResizeBehavior();
PMParticipantResizeBehavior.prototype.type = "PMParticipantResizeBehavior";
/**
* Sets a shape's container to a given container
* @param container
* @param shape
*/
PMParticipantResizeBehavior.prototype.onResizeStart = function (shape) {
return PMUI.behavior.RegularResizeBehavior
.prototype.onResizeStart.call(this, shape);
};
/**
* Removes shape from its current container
* @param shape
*/
PMParticipantResizeBehavior.prototype.onResize = function (shape) {
return function (e, ui) {
PMUI.behavior.RegularResizeBehavior
.prototype.onResize.call(this, shape)(e, ui);
if (shape.graphic) {
shape.paint();
}
};
};
var PMPoolResizeBehavior = function () {
this.oldHeight = null;
this.isTop = false;
};
PMPoolResizeBehavior.prototype = new PMUI.behavior.RegularResizeBehavior();
PMPoolResizeBehavior.prototype.type = "PMPoolResizeBehavior";
PMPoolResizeBehavior.prototype.init = function (shape) {
PMUI.behavior.RegularResizeBehavior
.prototype.init.call(this, shape);
$shape = $(shape.getHTML());
$shape.resizable();
$shape.resizable('option', 'minWidth', 200 * shape.canvas.getZoomFactor());
$shape.resizable('option', 'minHeight', 30 * shape.canvas.getZoomFactor());
};
/**
* Sets a shape's container to a given container
* @param container
* @param shape
*/
PMPoolResizeBehavior.prototype.onResizeStart = function (shape) {
return function (e, ui) {
PMUI.behavior.RegularResizeBehavior
.prototype.onResizeStart.call(this, shape)(e, ui);
//shape.hideAllChilds();
shape.hasMinimun = false;
if (shape.bpmnLanes.getSize() > 0) {
this.lastLaneHeight = shape.bpmnLanes.getLast().getHeight();
this.firstLaneHeight = shape.bpmnLanes.getFirst().getHeight();
}
};
};
/**
* Removes shape from its current container
* @param shape
*/
PMPoolResizeBehavior.prototype.onResize = function (shape) {
return function (e, ui) {
var i,
port,
diffH,
newWidth,
lane,
top = true,
newY,
canvas = shape.canvas;
shape.setPosition(ui.position.left / canvas.zoomFactor,
ui.position.top / canvas.zoomFactor);
shape.setDimension(ui.size.width / canvas.zoomFactor,
ui.size.height / canvas.zoomFactor);
if (shape.graphic) {
shape.paint();
}
//to resize last lane
diffH = (ui.size.height / canvas.zoomFactor) - (ui.originalSize.height / canvas.zoomFactor);
newWidth = shape.getWidth() - shape.headLineCoord - 1.2;
if (shape.bpmnLanes.getSize() > 0) {
if (ui.originalPosition.top === ui.position.top) {
this.isTop = false;
shape.setMinimunsResize();
lane = shape.bpmnLanes.getLast();
lane.setDimension(newWidth, this.lastLaneHeight + diffH);
for (i = 0; i < shape.bpmnLanes.getSize() - 1; i += 1) {
lane = shape.bpmnLanes.get(i);
lane.setDimension(newWidth, lane.getHeight());
}
} else {
this.isTop = true;
shape.setMinimunsResize(true);
lane = shape.bpmnLanes.getFirst();
lane.setDimension(newWidth, this.firstLaneHeight + diffH);
newY = this.firstLaneHeight + diffH;
for (i = 1; i < shape.bpmnLanes.getSize(); i += 1) {
lane = shape.bpmnLanes.get(i);
lane.setPosition(lane.getX(), newY);
lane.setDimension(newWidth, lane.getHeight());
newY += lane.getHeight();
}
}
}
};
};
/**
* Adds a shape to a given container
* @param container
* @param shape
*/
PMPoolResizeBehavior.prototype.onResizeEnd = function (shape) {
return function (e, ui) {
var i,
size,
label,
delta;
shape.resizing = false;
shape.canvas.isResizing = false;
// last resize
PMUI.behavior.RegularResizeBehavior.prototype.onResize.call(this, shape)(e, ui);
// show the handlers again
shape.showOrHideResizeHandlers(true);
// update the dimensions of the parent if possible (a shape might
// have been resized out of the dimensions of its parent)
shape.updateBpmnOnResize();
for (i = 0, size = shape.labels.getSize(); i < size; i += 1) {
label = shape.labels.get(i);
label.setLabelPosition(label.location, label.diffX, label.diffY);
}
delta = {
dx: shape.x - shape.oldX,
dy: shape.y - shape.oldY
};
options = {
isTop: this.isTop,
beforeHeightsOpt: {
lastLaneHeight: this.lastLaneHeight,
firstLaneHeight: this.firstLaneHeight
},
delta: delta
};
var command = new PMCommandPoolResize(shape, options);
shape.getCanvas().commandStack.add(command);
shape.canvas.refreshArray.clear();
shape.poolChildConnectionOnResize(true, true);
shape.refreshAllPoolConnections(false, delta);
//force to activate save button
PMDesigner.project.updateElement([]);
};
};
/**
* Updates the minimum height and maximum height of the JQqueryUI's resizable plugin.
* @param {PMUI.draw.Shape} shape
* @chainable
*/
PMPoolResizeBehavior.prototype.updateResizeMinimums = function (shape) {
var minW,
minH,
children = shape.getChildren(),
limits = children.getDimensionLimit(),
margin = 15,
$shape = $(shape.getHTML());
if (children.getSize() > 0) {
minW = (limits[1] + margin) * shape.canvas.getZoomFactor();
minH = (limits[2] + margin) * shape.canvas.getZoomFactor();
} else {
minW = 300 * shape.canvas.getZoomFactor();
minH = 30 * shape.canvas.getZoomFactor();
}
// update jQueryUI's minWidth and minHeight
$shape.resizable();
$shape.resizable('option', 'minWidth', minW);
$shape.resizable('option', 'minHeight', minH);
return this;
};
/**
* @class PMPoolDropBehavior
* The {@link PMUI.behavior.DropBehavior DropBehavior} for PMPool class.
* @extend PMUI.behavior.DropBehavior
* @param {Object} [options] css selectors that the drop behavior
* will accept
* @constructor
*/
var PMPoolDropBehavior = function (options) {
PMUI.behavior.DropBehavior.call(this, options);
};
PMPoolDropBehavior.prototype = new PMUI.behavior.DropBehavior();
PMPoolDropBehavior.prototype.constructor = PMPoolDropBehavior;
/**
* Type for the instance
* @property {string}
*/
PMPoolDropBehavior.prototype.type = 'PMPoolDropBehavior';
/**
* @inheritDoc
*/
PMPoolDropBehavior.prototype.onDrop = function (shape) {
return function (e, ui) {
var canvas = shape.getCanvas(),
id = ui.draggable.attr('id'),
shapesAdded = [],
selection,
position,
droppedShape,
command;
if (canvas.readOnly) {
return false;
}
droppedShape = canvas.shapeFactory(id);
if (!droppedShape) {
droppedShape = canvas.customShapes.find("id", id);
if (!droppedShape || !shape.dropBehavior.dropHook(shape, droppedShape, e, ui)) {
PMDesigner.msgFlash('Invalid operation.'.translate(), document.body, 'error', 5000, 5);
droppedShape.setPosition(droppedShape.getOldX(), droppedShape.getOldY());
return false;
}
if (droppedShape.parent.id !== shape.id) {
selection = canvas.currentSelection;
selection.asArray().forEach(function (item) {
var coordinates = PMUI.getPointRelativeToPage(item);
coordinates = PMUI.pageCoordinatesToShapeCoordinates(shape, null,
coordinates.x, coordinates.y, droppedShape);
shapesAdded.push({
shape: item,
container: shape,
x: coordinates.x,
y: coordinates.y,
topLeft: false
});
});
if (shape.getType() === 'PMLane') {
command = new PMCommandSwitchToLaneContainer(shapesAdded);
} else {
command = new PMUI.command.CommandSwitchContainer(shapesAdded);
}
command.execute();
canvas.commandStack.add(command);
canvas.multipleDrop = true;
}
canvas.hideAllFocusLabels();
shape.updateDimensions(10);
canvas.updatedElement = null;
droppedShape.ports.asArray().forEach(function (item) {
var connectionx = item.connection,
result = PMDesigner.connectValidator.isValid(
connectionx.getSrcPort().parent,
connectionx.getDestPort().parent,
connectionx);
if (result.conf && result.conf.segmentStyle !== connectionx.originalSegmentStyle) {
PMDesigner.msgFlash('Invalid flow between elements. Please delete the flow and reconnect the elements.'.translate(), document.body, 'error', 5000, 5);
}
});
return;
}
if (droppedShape instanceof PMLane && _.find(shape.children.asArray(), function (i) { return !(i instanceof PMLane); })) {
return PMDesigner.msgFlash('The lane can be dropped only over an empty pool. Please empty the pool before dropping a lane.'.translate(), document.body, 'error', 3000, 5);
}
position = PMUI.pageCoordinatesToShapeCoordinates(shape, e, null, null, droppedShape);
command = new PMCommandCreateLane({
pool: shape,
lane: droppedShape,
x: position.getX(),
y: position.getY()
});
if (command) {
canvas.hideAllCoronas();
canvas.updatedElement = shape;
canvas.commandStack.add(command);
command.execute();
canvas.hideAllFocusLabels();
if (droppedShape.label && droppedShape.focusLabel) {
droppedShape.label.getFocus();
}
}
};
};
/**
* Hook if PMEvent onDrop is correct
* @param {PMUI.draw.Shape} shape
* @param {PMUI.draw.Shape} customShape
* @param {Object} e jQuery object that contains the properties on the
* drop event
* @param {Object} ui jQuery object that contains the properties on the
* drop event
* @returns {boolean}
*/
PMPoolDropBehavior.prototype.dropHook = function (shape, customShape, e, ui) {
var result = true,
shapesTypes = ['PMEvent', 'PMActivity'];
if ((shapesTypes.indexOf(customShape.getType()) > -1) &&
!PMDesigner.connectValidator.onDropMovementIsAllowed(shape, customShape)) {
result = false;
}
return result;
};
var PMPool = function (options) {
PMShape.call(this, options);
/**
*
* @type {String}
*/
this.name = '';
/**
*
* @type {String}
*/
this.proUid = '';
/**
*
* @type {String}
*/
this.proType = '';
/**
*
* @type {Boolean}
*/
this.executable = false;
/**
*
* @type {Boolean}
*/
this.closed = false;
/**
*
* @type {String}
*/
this.parentLane = null;
/**
*
* @type {Number}
*/
this.relPosition = 0;
/**
*
* @type {Boolean}
*/
this.sizeIdentical = false;
/**
*
* @type {Number}
*/
this.participants = 0;
this.graphic = null;
this.headLineCoord = 40;
this.orientation = 'HORIZONTAL';
this.participantObject = null;
this.hasMinimun = false;
this.zoomPoolArray = [1, 5, 1, 2, 1];
/**
* Private property which indicates if a shape was just created inside the pool.
* @type {boolean}
*/
this.shapeJustCreated = false;
this.bpmnLanes = new PMUI.util.ArrayList();
PMPool.prototype.initObject.call(this, options);
};
PMPool.prototype = new PMShape();
PMPool.prototype.type = 'PMPool';
PMPool.prototype.poolContainerBehavior = null;
PMPool.prototype.poolResizeBehavior = null;
PMPool.prototype.getDataObject = function () {
var name = this.getName();
return {
lns_uid: this.getID(),
lns_name: name,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_container: 'bpmnDiagram',
_extended: this.getExtendedObject()
};
};
/**
* Object init method (internal)
* @param {Object} options
*/
PMPool.prototype.initObject = function (options) {
var defaultOptions = {
lns_name: 'Pool',
proUid: '',
proType: '',
executable: false,
closed: false,
parentLane: '',
relPosition: 0,
sizeIdentical: false,
participants: 0,
orientation: 'HORIZONTAL',
resizing: false,
parentLane: null,
identicalSize: false
};
$.extend(true, defaultOptions, options);
this.setName(defaultOptions.lns_name)
.setProUid(defaultOptions.proUid)
.setProType(defaultOptions.proType)
.setExecutable(defaultOptions.executable)
.setClosed(defaultOptions.closed)
.setParentLane(defaultOptions.parentLane)
.setRelPosition(defaultOptions.relPosition)
.setSizeIdentical(defaultOptions.sizeIdentical)
.setOrientation(defaultOptions.orientation)
.setParentLane(defaultOptions.parentLane)
.setIdenticalSize(defaultOptions.identicalSize);
};
/**
* Creates the HTML representation of the layer
* @returns {HTMLElement}
*/
PMPool.prototype.createHTML = function () {
PMShape.prototype.createHTML.call(this);
return this.html;
};
PMPool.prototype.decreaseZIndex = function () {
this.fixZIndex(this, 3);
return this;
};
PMPool.prototype.applyZoom = function () {
PMShape.prototype.applyZoom.call(this);
this.updateDimensions(10);
};
PMPool.prototype.onUpdateLabel = function () {
var label = this.getLabels().get(0);
label.text.style["text-overflow"] = "ellipsis";
label.text.style["overflow"] = "hidden";
label.text.style["white-space"] = "nowrap";
label.text.style["margin-left"] = "2%";
label.text.setAttribute("title", label.getMessage());
return this;
};
/**
* Paints the corresponding Pool, in this case adds the
* corresponding css classes and margins
* @chainable
*/
PMPool.prototype.paint = function () {
var zoomFactor = this.canvas.zoomFactor,
label = this.getLabels().get(0);
if (typeof this.graphic === 'undefined' || this.graphic === null) {
this.graphic = new JSGraphics(this.id);
} else {
this.graphic.clear();
}
this.graphic.setColor('#3b4753'); //change color
this.graphic.setStroke(2);
if (this.orientation === 'VERTICAL') {
this.graphic.drawLine(0, this.headLineCoord * zoomFactor,
this.zoomWidth, this.headLineCoord * zoomFactor);
label.setOrientation('horizontal');
label.setLabelPosition('top');
} else {
this.graphic.drawLine(this.headLineCoord * zoomFactor, 0,
this.headLineCoord * zoomFactor, this.zoomHeight - 5);
}
this.onUpdateLabel();
this.graphic.paint();
if (this.corona) {
this.corona.paint();
this.corona.hide();
}
};
/**
* Factory of pool behaviors. It uses lazy instantiation to create
* instances of the different container behaviors
* @param {String} type An string that specifies the container behavior we want
* an instance to have, it can be regular or nocontainer
* @return {ContainerBehavior}
*/
PMPool.prototype.containerBehaviorFactory = function (type) {
if (type === 'pool') {
if (!this.poolContainerBehavior) {
this.poolContainerBehavior = new PoolContainerBehavior();
}
return this.poolContainerBehavior;
} else {
return PMShape.prototype.containerBehaviorFactory.call(this, type);
}
};
/**
* Handler for the onmousedown event, changes the draggable properties
* according to the drag behavior that is being applied
* @param {CustomShape} CustomShape
* @returns {Function}
* TODO Implement Mouse Down handler
*/
PMPool.prototype.onMouseDown = function (shape) {
if (shape.getParentLane()) {
return function (e, ui) {
e.stopPropagation();
};
} else {
return PMShape.prototype.onMouseDown.call(this, shape);
}
};
PMPool.prototype.setResizeBehavior = function (behavior) {
var factory = new PMUI.behavior.BehaviorFactory({
products: {
"regularresize": PMUI.behavior.RegularResizeBehavior,
"Resize": PMUI.behavior.RegularResizeBehavior,
"yes": PMUI.behavior.RegularResizeBehavior,
"resize": PMUI.behavior.RegularResizeBehavior,
"noresize": PMUI.behavior.NoResizeBehavior,
"NoResize": PMUI.behavior.NoResizeBehavior,
"no": PMUI.behavior.NoResizeBehavior,
"poolResize": PMPoolResizeBehavior
},
defaultProduct: "noresize"
});
this.resizeBehavior = factory.make(behavior);
if (this.html) {
this.resize.init(this);
}
return this;
};
/**
* Add a lane and refactor all lane positions and dimensions
* @param {BPMNLane} newLane
* @returns {PMPool}
*/
PMPool.prototype.addLane = function (newLane) {
this.bpmnLanes.insert(newLane);
newLane.setRelPosition(this.bpmnLanes.getSize());
newLane.setParentPool(this.getID());
return this;
};
/**
* remove a lane and refactor all lane positions and dimensions
* @param {BPMNLane} lane
* @chainable
*/
PMPool.prototype.removeLane = function (lane) {
this.bpmnLanes.remove(lane);
return this;
};
/**
* Get number of lanes into a pool
* @return {Number}
*/
PMPool.prototype.getAllChildLanesNum = function (num) {
var i, lane, childPool;
for (i = 0; i < this.bpmnLanes.getSize(); i += 1) {
lane = this.bpmnLanes.get(i);
childPool = this.canvas.customShapes.find('id', lane.getChildPool());
if (childPool) {
num += childPool.getAllChildLanesNum(0);
} else {
num += 1;
}
}
return num;
};
/**
* Destroy a pool and update lane parentLane property if is a child pool
* @chainable
*/
PMPool.prototype.destroy = function () {
var parentLane = this.canvas.customShapes.find('id', this.getParentLane());
if (parentLane) {
this.parent.labels.get(0).setVisible(true);
parentLane.childPool = null;
}
return this;
};
/**
* Comparison function for ordering layers according to priority
* @param {BPMNLane} lane1
* @param {BPMNLane} lane2
* @returns {boolean}
*/
PMPool.prototype.comparisonFunction = function (lane1, lane2) {
return lane1.relPosition > lane2.relPosition;
};
/**
* Refactor recursively all lane position an dimensions
* because lanes has a particular behavior
* @chainable
*/
PMPool.prototype.setLanePositionAndDimension = function (lane) {
var numLanes,
oldX,
oldY,
newx,
newy,
oldWidth,
oldHeight,
newWidth,
newHeight,
oldRelPosition,
lane,
i,
label,
numLanes2,
newHeight2,
newWidth2,
childPool;
numLanes = this.bpmnLanes.getSize();
newx = (this.orientation === 'HORIZONTAL') ? this.headLineCoord : -1;
newy = (this.orientation === 'HORIZONTAL') ? 0 : this.headLineCoord;
//new lane width to update
newWidth = (this.orientation === 'HORIZONTAL') ?
this.getWidth() - this.headLineCoord - 2 : this.getWidth() / numLanes;
//new lane height to update
newHeight = (this.orientation === 'HORIZONTAL') ?
(this.getHeight() - 1) / numLanes : this.getHeight() - this.headLineCoord;
// FOR IDENTICAL OPTION
numLanes2 = this.getAllChildLanesNum(0);
newWidth2 = (this.orientation === 'HORIZONTAL') ?
this.getWidth() - this.headLineCoord - 2 : this.getWidth() / numLanes2;
newHeight2 = (this.orientation === 'HORIZONTAL') ?
this.getHeight() / numLanes2 : this.getHeight() - this.headLineCoord;
if (numLanes > 1) {
lane.style.addProperties({
'border-top': '2px solid #3b4753'
});
lane.setDimension(newWidth, lane.getHeight());
lane.setPosition(newx, newy + this.getHeight());
lane.setRelPosition(numLanes);
//TODO: We need remove this method to implement Vertical direction POOL
this.setDimension(this.getWidth(), this.getHeight() + lane.getHeight());
this.label.updateDimension(false);
this.paint();
} else {
lane.style.removeProperties(['border-top', 'border-left']);
lane.setDimension(newWidth, this.getHeight());
lane.setPosition(newx, newy);
lane.setRelPosition(numLanes);
}
lane.label.updateDimension(false);
this.label.updateDimension(false);
lane.paint();
lane.updateBounds(lane.businessObject.di);
this.updateBounds(this.participantObject.di);
return this;
};
/**
* Updates all child lanes when a lane has been removed
* @param lane
* @returns {PMPool}
*/
PMPool.prototype.updateOnRemoveLane = function (lane) {
var i, diffH = 0, nextLane, tempLane = lane, tempX = lane.getX(), tempY = lane.getY(), newY = 0;
for (i = lane.getRelPosition() - 1; i < this.bpmnLanes.getSize(); i += 1) {
nextLane = this.bpmnLanes.get(i);
if (i === 0) {
nextLane.style.removeProperties(['border-top', 'border-left']);
}
if (i > 0) {
newY = this.getNewPositionY(i);
}
nextLane.setPosition(lane.getX(), newY);
nextLane.setRelPosition(nextLane.getRelPosition() - 1);
nextLane.paint();
}
if (this.bpmnLanes.getSize() > 0) {
this.setDimension(this.getWidth(), this.getHeight() - lane.getHeight());
this.paint();
}
return this;
};
/**
+ * Get the new position in Y axis for a lane
+ * @param index
+ * @returns {integer}
+ */
PMPool.prototype.getNewPositionY = function (index) {
var i,
nextLane,
newY = 0;
for (i = 0; i < index; i += 1) {
nextLane = this.bpmnLanes.get(i);
newY += this.bpmnLanes.get(i).getHeight();
}
return newY;
};
/**
* Updates all bpmn child lanes when resize event has been finished
*/
PMPool.prototype.updateBpmnOnResize = function () {
var lane,
i;
this.updateBpmn();
for (i = 0; i < this.bpmnLanes.getSize(); i += 1) {
lane = this.bpmnLanes.get(i);
lane.updateBpmn();
}
};
PMPool.prototype.setMinimunsResize = function (top) {
var $shape = $(this.getHTML()),
lane,
i,
j,
shape,
limits,
margin = 15,
laneChildrens = new PMUI.util.ArrayList(),
minH,
hdiff,
laneHeightMin = 0,
minW = 200;
if (!this.hasMinimun) {
if (top) {
lane = this.bpmnLanes.getFirst();
minH = this.getHeight() - lane.getHeight() + (30 * this.canvas.getZoomFactor());
for (i = this.bpmnLanes.getSize() - 1; i >= 0; i -= 1) {
lane = this.bpmnLanes.get(i);
for (j = 0; j < lane.getChildren().getSize(); j += 1) {
shape = lane.getChildren().get(j);
laneChildrens.insert(
{
x: shape.x,
y: shape.y + laneHeightMin,
width: shape.width,
height: shape.height
}
);
}
laneHeightMin += lane.height;
}
} else {
lane = this.bpmnLanes.getLast();
minH = lane.getY() + (30 * this.canvas.getZoomFactor());
for (i = 0; i < this.bpmnLanes.getSize(); i += 1) {
lane = this.bpmnLanes.get(i);
for (j = 0; j < lane.getChildren().getSize(); j += 1) {
shape = lane.getChildren().get(j);
laneChildrens.insert(
{
x: shape.x,
y: shape.y + laneHeightMin,
width: shape.width,
height: shape.height
}
);
}
laneHeightMin += lane.height;
}
}
if (laneChildrens.getSize() > 0) {
laneChildrens.insert(
{
x: 0,
y: 0,
width: 0,
height: minH
}
);
limits = laneChildrens.getDimensionLimit();
minW = (limits[1] + margin + this.headLineCoord) * this.canvas.getZoomFactor();
minH = (limits[2] + margin) * this.canvas.getZoomFactor();
}
$shape.resizable('option', 'minWidth', minW);
$shape.resizable('option', 'minHeight', minH);
this.hasMinimun = true;
}
};
/**
* Updates all child lanes connections when resize event has been finished
*/
PMPool.prototype.updateConnectionsChildrens = function () {
var i,
j,
shapeLane,
shape = this;
for (i = 0; i < shape.children.asArray().length; i++) {
if (shape.children.asArray()[i].type == "PMLane") {
shapeLane = shape.children.asArray()[i];
for (j = 0; j < shapeLane.children.asArray().length; j++) {
shapeLane.children.asArray()[i].refreshConnections(false, true);
}
} else {
shape.children.asArray()[i].refreshConnections(false, true);
}
}
};
/**
* Updates dimesions and positions to pool lane childs
*/
PMPool.prototype.updateAllLaneDimension = function(avoidWeight) {
var newWidth = 0,
lane,
newY = 0,
i,
parentHeight = 0,
laneOldY,
containerWidth,
delta;
for (i = 0; i < this.bpmnLanes.getSize(); i += 1) {
lane = this.bpmnLanes.get(i);
if (lane.getWidth() > newWidth) {
newWidth = lane.getWidth();
}
laneOldY = lane.y;
lane.setDimension(newWidth, lane.getHeight());
lane.setRelPosition(i + 1);
if (i > 0) {
newY += this.bpmnLanes.get(i - 1).getHeight();
lane.setPosition(lane.getX(), newY);
lane.style.addProperties({
'border-top': '2px solid #3b4753'
});
} else {
lane.style.removeProperties(['border-top', 'border-left']);
}
parentHeight += lane.getHeight();
lane.paint();
lane.updateBounds(lane.businessObject.di);
//updating connections into a lane
lane.canvas.refreshArray.clear();
delta = {
dx: 0,
dy: lane.y - laneOldY
};
if (delta.dx > 0 || delta.dy >0){
lane.fixConnectionsOnResize(lane.resizing, true);
lane.laneRefreshConnections(delta);
}
}
newWidth = newWidth && !avoidWeight ? newWidth + this.headLineCoord + 2.1: this.getWidth();
this.setDimension(newWidth, parentHeight);
this.paint();
this.updateBounds(this.participantObject.di);
};
/**
* to multiple pool support
* @returns {*}
*/
PMPool.prototype.getMasterPool = function () {
if (this.parent.family !== 'Canvas') {
return this.parent.parent.getMasterPool();
} else {
return this;
}
};
/**
* Set pool name
* @param {String} name
* @returns {PMPool}
*/
PMPool.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.lns_name = name;
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
/**
* Set pool type
* @param {String} name
* @returns {PMPool}
*/
PMPool.prototype.setType = function (newType) {
this.type = newType;
return this;
};
/**
* Set proUid attached to pool
* @param {String} uid
* @returns {PMPool}
*/
PMPool.prototype.setProUid = function (uid) {
this.proUid = uid;
return this;
};
/**
* Set pool type
* @param {String} proType
* @returns {PMPool}
*/
PMPool.prototype.setProType = function (proType) {
this.proType = proType;
return this;
};
/**
* Set executable mode to pool
* @param {Boolean} executable
* @returns {PMPool}
*/
PMPool.prototype.setExecutable = function (executable) {
this.executable = executable;
return this;
};
/**
* Set closed mode to pool
* @param {Boolean} closed
* @returns {PMPool}
*/
PMPool.prototype.setClosed = function (closed) {
this.closed = closed;
return this;
};
/**
* Set pool orientation
* @param {String} orientation
* @returns {PMPool}
*/
PMPool.prototype.setOrientation = function (orientation) {
this.orientation = orientation;
return this;
};
/**
* Set pool resizing mode
* @param {String} orientation
* @returns {PMPool}
*/
PMPool.prototype.setResizing = function (resizing) {
this.resizing = resizing;
return this;
};
/**
* Set parent Lane UID to pool
* @param {String} parentLane
* @returns {PMPool}
*/
PMPool.prototype.setParentLane = function (parentLane) {
this.parentLane = parentLane;
return this;
};
/**
* Set pool rel position
* @param {Number} relPosition
* @returns {PMPool}
*/
PMPool.prototype.setRelPosition = function (relPosition) {
this.relPosition = relPosition;
return this;
};
/**
* Set size identical mode if we want identical size of pool childs
* @param {Number} relPosition
* @returns {PMPool}
*/
PMPool.prototype.setSizeIdentical = function (sizeIdentical) {
this.sizeIdentical = sizeIdentical;
return this;
};
/**
* Set number of participants into a pool
* @param {Number} num
* @returns {PMPool}
*/
PMPool.prototype.setParticipants = function (num) {
this.participants = num;
return this;
};
/**
* Set identical Size to a pool
* @param {Boolean} val
* @returns {PMPool}
*/
PMPool.prototype.setIdenticalSize = function (val) {
this.identicalSize = val;
return this;
};
/**
* Get the pool name
* @returns {String}
*/
PMPool.prototype.getName = function () {
return this.lns_name;
};
/**
* Get the pool type
* @returns {String}
*/
PMPool.prototype.getType = function () {
return this.type;
};
/**
* Get the process uid attached to pool
* @returns {String}
*/
PMPool.prototype.getProUid = function () {
return this.proUid;
};
/**
* Get the process uid attached to pool
* @returns {String}
*/
PMPool.getProcessType = function () {
return this.proType;
};
/**
* Get a boolean value if the pool is in executable mode
* @returns {Boolean}
*/
PMPool.isExecutable = function () {
return this.executable;
};
/**
* Get a boolean value if the pool is closed
* @returns {Boolean}
*/
PMPool.prototype.isClosed = function () {
return this.closed;
};
/**
* Get the pool orientation
* @returns {Sring}
*/
PMPool.prototype.getOrientation = function () {
return this.orientation;
};
/**
* Get the pool resizing mode
* @returns {String}
*/
PMPool.prototype.getResizing = function () {
return this.resizing;
};
/**
* Get the relative position of the pool
* @returns {Number}
*/
PMPool.prototype.getRelPosition = function () {
return this.relPosition;
};
/**
* Get a boolean value if pool have identical size
* @returns {Boolean}
*/
PMPool.prototype.isSizeIdentical = function () {
return this.sizeIdentical;
};
/**
* Get a parent lane
* @returns {BPMNLane}
*/
PMPool.prototype.getParentLane = function () {
return this.parentLane;
};
/**
* Get a number of participants asociate to pool
* @returns {Boolean}
*/
PMPool.prototype.getParticipants = function () {
return this.participants;
};
/**
* Get a identical size value
* @returns {Boolean}
*/
PMPool.prototype.getIdenticalSize = function () {
return this.identicalSize;
};
/**
* Updates the dimensions and position of this shape (note: 'this' is a shape)
* @param {Number} margin the margin for this element to consider towards the
* shapes near its borders
* @chainable
*/
PMPool.prototype.updateDimensions = function (margin) {
// update its size (if an child grew out of the shape)
// only if it's not the canvas
if (this.family !== 'Canvas') {
this.updateSize(margin);
this.refreshConnections();
this.resizeBehavior.updateResizeMinimums(this);
this.updateDimensions.call(this.parent, margin);
}
return this;
};
/**
* Updates the dimensions and position of this pool relative to lane childs (note: 'this' is a shape)
* @chainable
*/
PMPool.prototype.updateDimensionsWithLanes = function (margin) {
// update its size (if an child grew out of the shape)
// only if it's not the canvas
var lane,
i,
j,
limits,
minW,
minH,
childrens,
margin = 15,
shape,
$shape = $(this.getHTML()),
laneHeightMin = 0,
laneHeightSum = 0,
lastLane,
laneChildrens = new PMUI.util.ArrayList();
for (i = 0; i < this.bpmnLanes.getSize(); i += 1) {
lane = this.bpmnLanes.get(i);
childrens = lane.getChildren();
for (j = 0; j < childrens.getSize(); j += 1) {
shape = childrens.get(j);
if (i < this.bpmnLanes.getSize() - 1) {
laneHeightSum += shape.parent.height;
} else {
laneHeightSum = 0;
}
laneChildrens.insert(
{
x: shape.x,
y: shape.y + laneHeightMin,
width: shape.width,
height: shape.height
}
);
}
laneHeightMin += lane.height;
}
if (laneChildrens.getSize() > 0) {
limits = laneChildrens.getDimensionLimit();
minW = (limits[1] + margin + this.headLineCoord) * this.canvas.getZoomFactor();
minH = (limits[2] + margin) * this.canvas.getZoomFactor();
} else {
minW = 300 * this.canvas.getZoomFactor();
lastLane = this.bpmnLanes.get(this.bpmnLanes.getSize() - 2);
if (lastLane) {
minH = lastLane.getY() + lastLane.getHeight() + (30 * this.canvas.getZoomFactor());
}
}
$shape.resizable();
$shape.resizable('option', 'minWidth', minW);
$shape.resizable('option', 'minHeight', minH);
return this;
};
PMPool.prototype.stringify = function () {
var inheritedJSON = PMShape.prototype.stringify.call(this),
thisJSON = {
name: this.getName(),
proUid: this.getProUid(),
proType: this.proType,
executable: this.executable,
closed: this.isClosed(),
parentLane: this.parentLane,
relPosition: this.getRelPosition(),
sizeIdentical: this.isSizeIdentical(),
participants: this.getParticipants(),
orientation: this.getOrientation(),
parentLane: this.getParentLane()
};
$.extend(true, inheritedJSON, thisJSON);
return inheritedJSON;
};
/**
* Creates bussines model to export to standard bpmn file
* @param type xml tag to export bpmn file
*/
PMPool.prototype.createBpmn = function (type) {
var bpmnCollaboration;
if (!this.parent.businessObject.di) {
this.parent.createBPMNDiagram();
}
if (!(_.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"}))) {
bpmnCollaboration = PMDesigner.moddle.create('bpmn:Collaboration', {id: 'pmui-' + PMUI.generateUniqueId()});
PMDesigner.businessObject.get('rootElements').unshift(bpmnCollaboration);
this.parent.businessObject.di.bpmnElement = bpmnCollaboration;
bpmnCollaboration.participants = [];
} else {
bpmnCollaboration = _.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"});
}
if (!this.businessObject.elem) {
this.createWithBpmn(type, 'participantObject');
this.updateBounds(this.participantObject.di);
this.updateSemanticParent(this.participantObject, {elem: bpmnCollaboration});
this.updateDiParent(this.participantObject.di, this.parent.businessObject.di);
}
};
/**
* update participant parent .bpmn file
* @param businessObject
* @param newParent
*/
PMPool.prototype.updateSemanticParent = function (businessObject, newParent) {
var children;
if (businessObject.elem.$parent && businessObject.elem.$parent === newParent.elem) {
return;
}
if (businessObject.elem.$parent) {
// remove from old parent
children = businessObject.elem.$parent.get('participants');
CollectionRemove(children, businessObject.elem);
}
if (!newParent.elem) {
businessObject.elem.$parent = null;
} else {
// add to new parent
children = newParent.elem.get('participants');
children.push(businessObject.elem);
businessObject.elem.$parent = newParent.elem;
}
};
PMPool.prototype.updateDiParent = function (di, parentDi) {
PMShape.prototype.updateDiParent.call(this, di, parentDi);
};
/**
* Overwrite the parent function to set the dimension
* @param {Number} x
* @param {Number} y
* @return {*}
*/
PMPool.prototype.setDimension = function (x, y) {
var factorArray = [10.5, 5, 1.1, 2, 1], //factors used to fix browsers round problems
zoomFactor = this.getCanvas().getZoomFactor(),
i,
lanesCount = this.bpmnLanes.getSize(),
lane,
containerWidth = x - this.headLineCoord - (factorArray[this.getCanvas().zoomPropertiesIndex] * zoomFactor);
PMUI.draw.CustomShape.prototype.setDimension.call(this, x, y);
if (this.label) {
//validation for vertical labels case pool and lanes
this.label.updateDimension(false);
}
for (i = 0; i < lanesCount; i += 1) {
lane = this.bpmnLanes.get(i);
lane.setDimension(containerWidth, lane.getHeight());
}
this.paint();
return this;
};
/**
* create busines object to moodle bpmn export
*/
PMPool.prototype.createBusinesObject = function () {
var participant = _.findWhere(this.participantObject.elem.$parent.get('participants'),
{id: this.participantObject.elem.id}),
bpmnProcess = PMDesigner.moddle.create('bpmn:Process',
{id: 'pmui-' + PMUI.generateUniqueId()});
PMDesigner.businessObject.get('rootElements').push(bpmnProcess);
this.businessObject.elem = bpmnProcess;
this.businessObject.di = this.canvas.businessObject.di;
participant.processRef = bpmnProcess;
};
/**
* @inheritDoc
*/
PMPool.prototype.dropBehaviorFactory = function (type, selectors) {
if (type === 'pmcontainer') {
this.pmConnectionDropBehavior = this.pmConnectionDropBehavior || new PMPoolDropBehavior(selectors);
return this.pmConnectionDropBehavior;
}
return PMShape.prototype.dropBehaviorFactory.apply(this, arguments);
};
PMPool.prototype.removeBpmn = function () {
var coll, children, pros;
if ((_.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"}))) {
coll = _.findWhere(PMDesigner.businessObject.get('rootElements'), {$type: "bpmn:Collaboration"});
if (coll.participants.length === 1) {
children = PMDesigner.businessObject.get('rootElements');
CollectionRemove(children, coll);
//PMDesigner.businessObject.get
if (this.parent.businessObject.di) {
this.parent.businessObject.di.bpmnElement = this.parent.businessObject;
}
}
}
if (this.businessObject.elem && (_.findWhere(PMDesigner.businessObject.get('rootElements'), {
$type: "bpmn:Process",
id: this.businessObject.elem.id
}))) {
pros = _.findWhere(PMDesigner.businessObject.get('rootElements'), {
$type: "bpmn:Process",
id: this.businessObject.elem.id
});
children = PMDesigner.businessObject.get('rootElements');
CollectionRemove(children, pros);
this.businessObject.elem = null;
}
this.updateSemanticParent(this.participantObject, {elem: null});
this.updateDiParent(this.participantObject.di);
if (this.businessObject.di
&& this.businessObject.di.planeElement
&& this.businessObject.di.planeElement.length === 0) {
this.parent.removeBPMNDiagram();
}
};
PMPool.prototype.updateBpmn = function () {
this.updateBounds(this.participantObject.di);
};
/**
* @inheritdoc
*/
PMPool.prototype.onMouseUp = function (customShape) {
var that = this;
return function (e, ui) {
if (customShape.canvas.canCreateShape && customShape.canvas.connectStartShape.getID() !== customShape.getID()) {
that.shapeJustCreated = true;
}
(PMShape.prototype.onMouseUp.call(that, customShape))(e, ui);
};
};
/**
* @inheritdoc
*/
PMPool.prototype.onClick = function (customShape) {
var that = this;
return function (e) {
if (that.shapeJustCreated) {
customShape.canvas.hideAllCoronas();
} else {
(PMShape.prototype.onClick.call(that, customShape))(e);
}
that.shapeJustCreated = false;
if (this.helper) {
$(this.helper.html).remove();
}
customShape.wasDragged = false;
e.stopPropagation();
};
};
var PMLane = function (options) {
PMShape.call(this, options);
/**
*
* @type {String}
*/
this.name = '';
/**
*
* @type {String}
*/
this.proUid = '';
/**
*
* @type {String}
*/
this.childLaneset = '';
/**
*
* @type {Number}
*/
this.relPosition = 0;
this.parentPool = null;
this.childPool = null;
/**
* Private property which indicates if a shape was just created inside the lane.
* @type {boolean}
*/
this.shapeJustCreated = false;
PMLane.prototype.initObject.call(this, options);
};
PMLane.prototype = new PMShape();
PMLane.prototype.type = 'PMLane';
PMLane.prototype.laneContainerBehavior = null;
PMLane.prototype.getDataObject = function () {
var name = this.getName();
return {
lan_uid: this.id,
lns_uid: this.parent.id,
lan_name: name,
bou_x: this.x,
bou_y: this.y,
bou_width: this.width,
bou_height: this.height,
bou_rel_position: this.getRelPosition(),
element_id: this.parent.id,
bou_container: 'bpmnPool',
lan_parent_pool: this.parentPool,
_extended: this.getExtendedObject()
};
};
PMLane.prototype.initObject = function (options) {
var defaultOptions = {
lan_name: 'Lane',
proUid: null,
childLaneset: null,
relPosition: 0,
childPool: null,
orientation: 'HORIZONTAL'
};
$.extend(true, defaultOptions, options);
this.setName(defaultOptions.lan_name)
.setProUid(defaultOptions.proUid)
.setRelPosition(defaultOptions.relPosition)
.setChildPool(defaultOptions.childPool)
.setOrientation(defaultOptions.orientation);
};
PMLane.prototype.paint = function () {
if (this.parent.orientation === 'VERTICAL') {
this.getLabels().get(0).setOrientation('horizontal');
this.getLabels().get(0).setLabelPosition('top');
} else {
this.getLabels().get(0).setOrientation('vertical');
this.getLabels().get(0).setLabelPosition('center-left', 20, 0);
}
if (this.childPool) {
this.getLabels().get(0).setVisible(false);
}
this.getLabels().get(0).setZOrder(1);
if (this.corona) {
this.corona.paint();
this.corona.hide();
}
};
/**
* Factory of pool behaviors. It uses lazy instantiation to create
* instances of the different container behaviors
* @param {String} type An string that specifies the container behavior we want
* an instance to have, it can be regular or nocontainer
* @return {ContainerBehavior}
*/
PMLane.prototype.containerBehaviorFactory = function (type) {
if (type === 'lane') {
if (!this.laneContainerBehavior) {
this.laneContainerBehavior = new LaneContainerBehavior();
}
return this.laneContainerBehavior;
} else {
return PMShape.prototype.containerBehaviorFactory.call(this, type);
}
};
PMLane.prototype.setResizeBehavior = function (behavior) {
var factory = new PMUI.behavior.BehaviorFactory({
products: {
"regularresize": PMUI.behavior.RegularResizeBehavior,
"Resize": PMUI.behavior.RegularResizeBehavior,
"yes": PMUI.behavior.RegularResizeBehavior,
"resize": PMUI.behavior.RegularResizeBehavior,
"noresize": PMUI.behavior.NoResizeBehavior,
"NoResize": PMUI.behavior.NoResizeBehavior,
"no": PMUI.behavior.NoResizeBehavior,
"laneResize": PMLaneResizeBehavior
},
defaultProduct: "noresize"
});
this.resizeBehavior = factory.make(behavior);
if (this.html) {
this.resize.init(this);
}
return this;
};
/**
* Convert a lane to Pool
*/
PMLane.prototype.transformToPool = function () {
var customShape = new BPMNPool({
width: this.getWidth() - 1,
height: this.getHeight() - 1,
"canvas": this.canvas,
"connectAtMiddlePoints": false,
container: 'pool',
topLeft: true,
drop: {
type: 'bpmnconnectioncontainer',
selectors: ["#BPMNLane",
"#BPMNActivity", "#BPMNSubProcess", "#BPMNStartEvent",
"#BPMNEndEvent", "#BPMNIntermediateEvent", "#BPMNGateway",
"#BPMNDataObject", "#BPMNDataStore", "#BPMNGroup",
"#BPMNAnnotation", ".bpmn_droppable", ".custom_shape"],
overwrite: true
},
drag: 'noDrag',
resizeBehavior: "no",
resizeHandlers: {
type: "Rectangle",
total: 4,
resizableStyle: {
cssProperties: {
'background-color': "rgb(0, 255, 0)",
'border': '1px solid black'
}
},
nonResizableStyle: {
cssProperties: {
'background-color': "white",
'border': '1px solid black'
}
}
},
"style": {
cssClasses: []
},
layers: [
{
layerName: "first-layer",
priority: 2,
visible: true,
style: {
cssProperties: {}
}
}
],
labels: [
{
message: this.getMessage(),
width: 50,
height: 10,
orientation: 'vertical',
position: {
location: 'center-left',
diffX: 20,
diffY: 0
},
updateParent: false
}
],
orientation: this.parent.getOrientation(),
name: this.getName(),
parentLane: this.getID()
});
this.labels.get(0).setVisible(false);
this.setChildPool(customShape.getID());
this.addElement(customShape, 1, 0, true);
customShape.labels.get(0).setVisible(true);
this.canvas.triggerSinglePropertyChangeEvent(this, 'childPool', this.getChildPool(), customShape.getID());
customShape.attachListeners();
this.canvas.updatedElement = customShape;
var command = new jCore.CommandCreate(customShape);
this.canvas.commandStack.add(command);
command.execute();
};
PMLane.prototype.createHTML = function () {
PMShape.prototype.createHTML.call(this);
if (this.getRelPosition() > 1) {
this.style.addProperties({
'border-top': '2px solid #3b4753'
});
}
return this.html;
};
PMLane.prototype.attachListeners = function () {
var $lane = $(this.html);
if (!this.html) {
return this;
}
PMShape.prototype.attachListeners.call(this);
};
PMLane.prototype.onMouseDown = function (shape) {
return function (e, ui) {
if (shape.getType() === 'PMPool' || shape.getType() === 'PMLane') {
shape.canvas.cancelConnect();
}
PMUI.draw.CustomShape.prototype.onMouseDown.call(this, shape)(e, ui);
shape.setDragBehavior('nodrag');
};
};
PMLane.prototype.destroy = function () {
var parentPool = this.canvas.customShapes.find('id', this.parent.getID());
if (parentPool) {
parentPool.removeLane(this);
parentPool.updateOnRemoveLane(this);
}
return this;
};
PMLane.prototype.setChildPool = function (pPool) {
this.childPool = pPool;
return this;
};
PMLane.prototype.setParentPool = function (pPool) {
this.parentPool = pPool;
return this;
};
/**
* Set lane name
* @param {String} name
* @returns {BPMNLane}
*/
PMLane.prototype.setName = function (name) {
if (typeof name !== 'undefined') {
this.lan_name = name;
if (this.label) {
this.label.setMessage(name);
}
}
return this;
};
/**
* Set lane type
* @param {String} newType
* @returns {BPMNLane}
*/
PMLane.prototype.setType = function (newType) {
this.type = newType;
return this;
};
/**
* Set process uid asociated to lane
* @param {String} uid
* @returns {BPMNLane}
*/
PMLane.prototype.setProUid = function (uid) {
this.proUid = uid;
return this;
};
/**
* Set the relative position of lane
* @param {Number} relPosition
* @returns {BPMNLane}
*/
PMLane.prototype.setRelPosition = function (relPosition) {
this.relPosition = relPosition;
return this;
};
PMLane.prototype.setOrientation = function (orientation) {
this.orientation = orientation;
return this;
};
/**
* Set ChildLaneset to lane
* @param {BPMNPool} childLane
* @returns {BPMNLane}
*/
PMLane.prototype.setChildLaneset = function (childLane) {
this.childLaneset = childLane;
return this;
};
/**
* Get the lane name
* @returns {String}
*/
PMLane.prototype.getName = function () {
return this.lan_name;
};
PMLane.prototype.getType = function () {
return this.type;
};
/**
* Get pro uid asociated to lane
* @returns {String}
*/
PMLane.prototype.getProUid = function () {
return this.proUid;
};
/**
* Get the relative position of lane
* @returns {Number}
*/
PMLane.prototype.getRelPosition = function () {
return this.relPosition;
};
PMLane.prototype.getOrientation = function () {
return this.orientation;
};
/**
* Get ChildLaneSet
* @returns {BPMNPool}
*/
PMLane.prototype.getChildLaneset = function () {
return this.childLaneset;
};
PMLane.prototype.getChildPool = function () {
return this.childPool;
};
PMLane.prototype.applyZoom = function () {
PMShape.prototype.applyZoom.call(this);
this.updateDimensions();
};
PMLane.prototype.updateDimensions = function (margin) {
var minW,
minH,
children = this.getChildren(),
limits = children.getDimensionLimit(),
margin = 30,
$shape = $(this.getHTML());
minW = (limits[1] + margin) * this.canvas.getZoomFactor();
minH = (limits[2] + margin) * this.canvas.getZoomFactor();
// update jQueryUI's minWidth and minHeight
$shape.resizable();
$shape.resizable('option', 'minWidth', minW);
$shape.resizable('option', 'minHeight', minH);
return this;
};
/**
* That method shows or hides lane resize behaviors
* @param visible
* @returns {PMLane}
*/
PMLane.prototype.showOrHideResizeHandlers = function (visible) {
var i;
if (!visible) {
visible = false;
}
for (i = 0; i < this.cornerResizeHandlers.getSize(); i += 1) {
this.cornerResizeHandlers.get(i).setVisible(false);
}
for (i = 0; i < this.midResizeHandlers.getSize(); i += 1) {
if (i === 2) {
this.midResizeHandlers.get(i).setVisible(visible);
} else {
this.midResizeHandlers.get(i).setVisible(false);
}
}
return this;
};
PMLane.prototype.updateAllRelatedDimensions = function (avoidWeight) {
this.parent.updateAllLaneDimension(avoidWeight);
this.parent.paint();
return this;
};
PMLane.prototype.stringify = function () {
var inheritedJSON = PMShape.prototype.stringify.call(this),
thisJSON = {
name: this.getName(),
proUid: this.getProUid(),
relPosition: this.getRelPosition(),
childPool: this.getChildPool()
};
$.extend(true, inheritedJSON, thisJSON);
return inheritedJSON;
};
PMLane.prototype.createBpmn = function (type) {
var bpmnLaneset;
if (!this.parent.businessObject.elem) {
this.parent.createBusinesObject();
}
bpmnLaneset = this.createLaneset();
this.createWithBpmn('bpmn:Lane', 'businessObject');
this.updateBounds(this.businessObject.di);
this.updateSemanticParent(this.businessObject, { elem: bpmnLaneset });
this.updateDiParent(this.businessObject.di, this.parent.parent.businessObject.di);
};
PMLane.prototype.createLaneset = function () {
var bpmnLaneset;
if (!(_.findWhere(this.parent.businessObject.elem.get('flowElements'), {$type: "bpmn:LaneSet"}))) {
bpmnLaneset = PMDesigner.moddle.create('bpmn:LaneSet');
bpmnLaneset.$parent = this.parent.businessObject.elem;
this.parent.businessObject.elem.get('flowElements').push(bpmnLaneset);
} else {
bpmnLaneset = _.findWhere(this.parent.businessObject.elem.get('flowElements'), {$type: "bpmn:LaneSet"});
}
return bpmnLaneset;
};
PMLane.prototype.updateSemanticParent = function (businessObject, newParent) {
var children;
if (businessObject.elem.$parent === newParent.elem) {
return;
}
if (businessObject.elem.$parent) {
// remove from old parent
children = businessObject.elem.$parent.get('lanes');
CollectionRemove(children, businessObject.elem);
}
if (!newParent.elem) {
businessObject.elem.$parent = null;
} else {
// add to new parent
children = newParent.elem.get('lanes');
children.push(businessObject.elem);
businessObject.elem.$parent = newParent.elem;
}
};
PMLane.prototype.removeBpmn = function () {
var bpmnLaneset;
this.parent.updateBounds(this.parent.participantObject.di);
PMShape.prototype.removeBpmn.call(this);
if ((_.findWhere(this.parent.businessObject.elem.get('flowElements'), {$type: "bpmn:LaneSet"}))) {
bpmnLaneset = _.findWhere(this.parent.businessObject.elem.get('flowElements'), {$type: "bpmn:LaneSet"});
if (bpmnLaneset.lanes < 1) {
CollectionRemove(this.parent.businessObject.elem.get('flowElements'), bpmnLaneset);
}
}
};
PMLane.prototype.updateBpmn = function () {
this.updateBounds(this.businessObject.di);
};
PMLane.prototype.laneRefreshConnections = function (delta) {
var i,
max,
srcElem,
destElem,
connection,
delta;
for (i = 0, max = this.canvas.refreshArray.getSize(); i < max; i += 1) {
connection = this.canvas.refreshArray.get(i);
srcElem = connection.getSrcPort().parent;
destElem = connection.getDestPort().parent;
if (this.isConnetionIntoLane(srcElem)
&& this.isConnetionIntoLane(destElem)) {
connection.reconnectUser(delta, false);
connection.setSegmentMoveHandlers();
connection.checkAndCreateIntersectionsWithAll();
this.canvas.triggerUserStateChangeEvent(connection);
} else {
connection.reconnectManhattah();
connection.setSegmentMoveHandlers();
connection.checkAndCreateIntersectionsWithAll();
this.canvas.triggerConnectionStateChangeEvent(connection);
}
}
};
PMLane.prototype.isConnetionIntoLane = function (shape) {
var i,
max,
child;
for (i = 0, max = this.children.getSize(); i < max; i += 1) {
child = this.children.get(i);
if (shape.getID() === child.getID()) {
return true;
}
}
return false;
};
/**
* @inheritdoc
*/
PMLane.prototype.onMouseUp = function (customShape) {
var that = this;
return function (e, ui) {
if (customShape.canvas.canCreateShape && customShape.canvas.connectStartShape.getID() !== customShape.getID()) {
that.shapeJustCreated = true;
}
(PMShape.prototype.onMouseUp.call(that, customShape))(e, ui);
};
};
/**
* @inheritdoc
*/
PMLane.prototype.onClick = function (customShape) {
var that = this;
return function (e) {
if (that.shapeJustCreated) {
customShape.canvas.hideAllCoronas();
} else {
(PMShape.prototype.onClick.call(that, customShape))(e);
}
that.shapeJustCreated = false;
if (this.helper) {
$(this.helper.html).remove();
}
customShape.wasDragged = false;
e.stopPropagation();
};
};
/**
* Command create: command created when a lane is created (from the toolbar)
* @class BPMNCommandCreateLane
* @constructor
*/
var PMCommandCreateLane = function (settngs) {
PMUI.command.Command.call(this, settngs);
};
PMCommandCreateLane.prototype = new PMUI.command.Command({});
/**
* Type of command of this object
* @type {String}
*/
PMCommandCreateLane.prototype.type = 'PMCommandCreateLane';
/**
* Executes the command
*/
PMCommandCreateLane.prototype.execute = function () {
var pool = this.receiver.pool,
lane = this.receiver.lane;
pool.addElement(lane, this.receiver.x, this.receiver.y, lane.topLeftOnCreation);
lane.showOrHideResizeHandlers(false);
lane.canvas.triggerCreateEvent(lane, []);
if (lane instanceof PMLane) {
pool.setLanePositionAndDimension(lane);
}
};
/**
* Inverse executes the command a.k.a. undo
*/
PMCommandCreateLane.prototype.undo = function () {
var pool = this.receiver.pool,
lane = this.receiver.lane;
pool.removeElement(lane);
};
/**
* Re-executes the command.
* @returns {BPMNCommandCreateLane}
*/
PMCommandCreateLane.prototype.redo = function () {
this.execute();
return this;
};
var PMCommandAddToLane = function (receiver, childObject, coordinates) {
PMCommandAddToLane.superclass.call(this, receiver);
this._boundExceed = {};
PMCommandAddToLane.prototype.initObject.call(this, receiver, childObject, coordinates);
};
PMUI.inheritFrom('PMUI.command.Command', PMCommandAddToLane);
PMCommandAddToLane.prototype.type = 'PMCommandAddToLane';
PMCommandAddToLane.prototype.initObject = function (receiver, childObject, coordinates) {
this.childObject = childObject;
this._boundExceed = {
x: childObject.getWidth() - (receiver.getWidth() - coordinates.x),
y: childObject.getHeight() - (receiver.getHeight() - coordinates.y)
};
this.before = {
laneWidth: this.receiver.getWidth(),
laneHeight: this.receiver.getHeight()
};
this.after = {
childX: this.childObject.getX(),
childY: this.childObject.getY()
};
};
PMCommandAddToLane.prototype.execute = function () {
if (this._boundExceed.x > 0 || this._boundExceed.y > 0) {
this.receiver.setDimension(
this.receiver.width + (this._boundExceed.x >= 0 ? this._boundExceed.x : 0),
this.receiver.height + (this._boundExceed.y >= 0 ? this._boundExceed.y : 0)
);
this.receiver.updateAllRelatedDimensions();
}
if (!this.receiver.getChildren().contains(this.childObject)) {
this.receiver.getChildren().insert(this.childObject);
}
this.after.laneWidth = this.receiver.getWidth();
this.after.laneHeight = this.receiver.getHeight();
this.receiver.html.appendChild(this.childObject.getHTML());
this.childObject.canvas.addToList(this.childObject);
this.childObject.showOrHideResizeHandlers(false);
this.childObject.canvas.triggerCreateEvent(this.childObject, []);
return this;
};
PMCommandAddToLane.prototype.undo = function () {
this.receiver.getChildren().remove(this.childObject);
if (this.after.laneWidth !== this.before.laneWidth || this.after.laneHeight !== this.before.laneHeight) {
this.receiver.setDimension(this.before.laneWidth, this.before.laneHeight);
this.receiver.updateAllRelatedDimensions();
}
this.childObject.saveAndDestroy();
this.childObject.canvas.triggerRemoveEvent(this.childObject, []);
return this;
};
PMCommandAddToLane.prototype.redo = function () {
this.execute();
return this;
};
/**
* @class PMUI.behavior.ContainerDropBehavior
* Encapsulates the drop behavior of a container
* @extends PMUI.behavior.DropBehavior
*
* @constructor
* Creates a new instance of the class
* @param {Array} [selectors=[]] css selectors that this drop behavior will
* accept
*/
var PMContainerDropBehavior = function (selectors) {
PMUI.behavior.DropBehavior.call(this, selectors);
};
PMContainerDropBehavior.prototype = new PMUI.behavior.DropBehavior();
/**
* Type of the instances
* @property {String}
*/
PMContainerDropBehavior.prototype.type = "PMContainerDropBehavior";
/**
* Default selectors for this drop behavior
* @property {String}
*/
PMContainerDropBehavior.prototype.defaultSelector = "";
/**
* On drop handler for this drop behavior, creates shapes when dropped from the
* toolbar, or move shapes among containers
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMContainerDropBehavior.prototype.onDrop = function (shape) {
return function (e, ui) {
var customShape = null,
canvas = shape.getCanvas(),
selection,
sibling,
i,
command,
coordinates,
id,
shapesAdded = [];
if (canvas.readOnly) {
return false;
}
shape.entered = false;
if (ui.helper && ui.helper.attr('id') === "drag-helper") {
return false;
}
id = ui.draggable.attr('id');
customShape = canvas.shapeFactory(id);
if (customShape === null) {
customShape = canvas.customShapes.find('id', id);
if (!customShape || !shape.dropBehavior.dropHook(shape, customShape, e, ui)) {
PMDesigner.msgFlash('Invalid operation.'.translate(), document.body, 'error', 5000, 5);
customShape.setPosition(customShape.getOldX(), customShape.getOldY());
return false;
}
if (customShape.getParent().getType() === 'PMLane'
&& shape.getType() === 'PMPool'
&& shape.bpmnLanes.getSize() > 0) {
PMDesigner.msgFlash('Invalid operation.'.translate(), document.body, 'error', 5000, 5);
customShape.setPosition(customShape.getOldX(), customShape.getOldY());
return false;
}
if (!(customShape.parent &&
customShape.parent.id === shape.id)) {
selection = canvas.currentSelection;
for (i = 0; i < selection.getSize(); i += 1) {
sibling = selection.get(i);
coordinates = PMUI.getPointRelativeToPage(sibling);
coordinates = PMUI.pageCoordinatesToShapeCoordinates(shape, null,
coordinates.x, coordinates.y, customShape);
shapesAdded.push({
shape: sibling,
container: shape,
x: coordinates.x,
y: coordinates.y,
topLeft: false
});
}
if (shape.getType() === 'PMLane') {
command = new PMCommandSwitchToLaneContainer(shapesAdded);
} else {
command = new PMUI.command.CommandSwitchContainer(shapesAdded);
}
command.execute();
canvas.commandStack.add(command);
canvas.multipleDrop = true;
}
canvas.hideAllFocusLabels();
shape.updateDimensions(10);
canvas.updatedElement = null;
var portx,
connectionx,
result;
for (var i = 0; i < customShape.ports.asArray().length; i += 1) {
portx = customShape.ports.asArray()[i];
connectionx = portx.connection;
result = PMDesigner.connectValidator.isValid(connectionx.getSrcPort().parent, connectionx.getDestPort().parent, connectionx);
if (result.conf && result.conf.segmentStyle !== connectionx.originalSegmentStyle) {
PMDesigner.msgFlash('Invalid flow between elements. Please delete the flow and reconnect the elements.'.translate(), document.body, 'error', 5000, 5);
}
}
} else {
coordinates = PMUI.pageCoordinatesToShapeCoordinates(shape, e, null, null, customShape);
var result = shape.addElement(customShape, coordinates.x, coordinates.y,
customShape.topLeftOnCreation);
if (shape.containerBehavior.addElementLane !== true) {
//since it is a new element in the designer, we triggered the
//custom on create element event
canvas.hideAllCoronas();
canvas.updatedElement = customShape;
if (shape.getType() == 'PMLane') {
command = new PMCommandAddToLane(shape, customShape, coordinates);
} else if (customShape.getType() === 'PMLane') {
command = new PMCommandCreateLane(customShape);
} else {
// create the command for this new shape
command = new PMUI.command.CommandCreate(customShape);
}
canvas.commandStack.add(command);
command.execute();
canvas.hideAllFocusLabels();
if (customShape.label && customShape.focusLabel) {
customShape.label.getFocus();
}
}
canvas.hideAllFocusLabels();
if (customShape.label && customShape.focusLabel) {
customShape.label.getFocus();
}
}
};
};
PMContainerDropBehavior.prototype.setSelectors = function (selectors, overwrite) {
PMUI.behavior.DropBehavior.prototype
.setSelectors.call(this, selectors, overwrite);
this.selectors.push(".port");
return this;
};
/**
* Hook if PMEvent onDrop is correct
* @param {PMUI.draw.Shape} shape
* @param {PMUI.draw.Shape} customShape
* @param {Object} e jQuery object that contains the properties on the
* drop event
* @param {Object} ui jQuery object that contains the properties on the
* drop event
* @returns {boolean}
*/
PMContainerDropBehavior.prototype.dropHook = function (shape, customShape, e, ui) {
var result = true,
shapesTypes = ['PMEvent', 'PMActivity'];
if ((shapesTypes.indexOf(customShape.getType()) > -1) &&
!PMDesigner.connectValidator.onDropMovementIsAllowed(shape, customShape)) {
result = false;
}
return result;
};
var PoolContainerBehavior = function () {
this.addElementLane = false;
};
PoolContainerBehavior.prototype = new PMUI.behavior.RegularContainerBehavior();
PoolContainerBehavior.prototype.type = "PoolContainerBehavior";
PoolContainerBehavior.prototype.addToContainer = function (container,
shape, x, y,
topLeftCorner) {
var shapeLeft = 0,
shapeTop = 0,
shapeWidth,
shapeHeight,
canvas,
topLeftFactor = (topLeftCorner === true) ? 0 : 1;
this.addElementLane = false;
if (shape.type === 'PMLane') {
if (container.type === "Canvas") {
canvas = container;
} else {
canvas = container.canvas;
}
// have not lanes childrens
if (container.children.getSize() !== container.bpmnLanes.getSize()) {
PMDesigner.msgFlash('The lane can be dropped only over an empty pool. Please empty the pool before dropping a lane.'.translate(), document.body, 'error', 3000, 5);
this.addElementLane = true;
} else {
shapeWidth = container.getWidth() - container.headLineCoord;
shapeHeight = container.getHeight();
shapeLeft += x - (shapeWidth / 2) * topLeftFactor;
shapeTop += y - (shapeHeight / 2) * topLeftFactor;
shapeLeft /= canvas.zoomFactor;
shapeTop /= canvas.zoomFactor;
shape.setParent(container);
container.getChildren().insert(shape);
this.addShape(container, shape, shapeLeft, shapeTop);
container.addLane(shape);
shape.fixZIndex(shape, 0);
// fix resize minWidth and minHeight and also fix the dimension
// of this shape (if a child made it grow)
//container.resizeBehavior.updateResizeMinimums(container);
// adds the shape to either the customShape arrayList or the regularShapes
// arrayList if possible
canvas.addToList(shape);
}
} else {
if (PMUI.draw.Geometry.pointInRectangle(new PMUI.util.Point(x, y),
new PMUI.util.Point(container.headLineCoord, 0),
new PMUI.util.Point(container.getZoomWidth(),
container.getZoomHeight())
)) {
if (container.getChildren().find('type', 'PMLane')) {
this.addToCanvas(container, shape);
} else {
PMUI.behavior.RegularContainerBehavior.prototype.addToContainer.call(this, container,
shape, x, y, topLeftCorner);
shape.absoluteX += 2;
shape.absoluteY += 2;
}
} else {
this.addToCanvas(container, shape);
}
}
if (!this.addElementLane) {
shape.canvas.triggerCreateEvent(shape, []);
}
};
/**
* @inheritDoc
*/
PoolContainerBehavior.prototype.removeFromContainer = function (shape) {
var pool = shape.getParent();
pool.getChildren().remove(shape);
if (pool.isResizable()) {
pool.resizeBehavior.updateResizeMinimums(shape.parent);
}
if (shape instanceof PMLane) {
pool.removeLane(shape);
pool.updateOnRemoveLane(shape);
}
shape.saveAndDestroy();
shape.canvas.triggerRemoveEvent(shape, []);
shape.setParent(null);
return this;
};
/**
* Force to add a shape to canvas
* @param container
* @param shape
*/
PoolContainerBehavior.prototype.addToCanvas = function (container, shape) {
shape.setParent(container.canvas);
container.canvas.getChildren().insert(shape);
this.addShape(container.canvas, shape, shape.getOldX(), shape.getOldY());
shape.fixZIndex(shape, 0);
// adds the shape to either the customShape arrayList or the regularShapes
// arrayList if possible
container.canvas.addToList(shape);
};
PoolContainerBehavior.prototype.addShape = function (container, shape, x, y) {
shape.setPosition(x, y);
if (shape instanceof PMArtifact && shape.art_type === 'GROUP') {
$(container.getHTML()).prepend(shape.getHTML());
} else {
container.getHTML().appendChild(shape.getHTML());
}
shape.updateHTML();
shape.paint();
shape.applyBehaviors();
shape.attachListeners();
return this;
};
/**
* Command resize: command resize when a poll is resized (mazimized or minimized)
* @class BPMNCommandPoolResize
* @constructor
*/
var PMCommandPoolResize = function (receiver, options) {
this.isTop = options.isTop;
this.beforeHeightsOpt = options.beforeHeightsOpt;
this.delta = options.delta;
if (receiver.bpmnLanes.getSize() > 0) {
this.afterHeightsOpt = {
lastLaneHeight: receiver.bpmnLanes.getLast().getHeight(),
firstLaneHeight: receiver.bpmnLanes.getFirst().getHeight()
};
}
PMUI.command.CommandResize.call(this, receiver);
};
/**
* Type of command of this object
* @type {String}
*/
PMUI.inheritFrom('PMUI.command.CommandResize', PMCommandPoolResize);
PMCommandPoolResize.prototype.type = 'PMCommandPoolResize';
/**
* Executes the command
*/
PMCommandPoolResize.prototype.execute = function () {
var i,
pool = this.receiver,
lane,
newY,
newWidth,
delta;
PMUI.command.CommandResize.prototype.execute.call(this);
if (pool.bpmnLanes.getSize() > 0) {
newWidth = pool.getWidth() - pool.headLineCoord - 1.2;
if (this.isTop) {
lane = pool.bpmnLanes.getFirst();
lane.setDimension(newWidth, this.afterHeightsOpt.firstLaneHeight);
newY = this.afterHeightsOpt.firstLaneHeight;
for (i = 1; i < pool.bpmnLanes.getSize(); i += 1) {
lane = pool.bpmnLanes.get(i);
lane.setPosition(lane.getX(), newY);
lane.setDimension(newWidth, lane.getHeight());
newY += lane.getHeight();
}
} else {
pool.setMinimunsResize();
lane = pool.bpmnLanes.getLast();
lane.setDimension(newWidth, this.afterHeightsOpt.lastLaneHeight);
for (i = 0; i < pool.bpmnLanes.getSize() - 1; i += 1) {
lane = pool.bpmnLanes.get(i);
lane.setDimension(newWidth, lane.getHeight());
}
}
}
pool.canvas.refreshArray.clear();
delta = {
dx: this.delta.dx,
dy: this.delta.dy
};
pool.poolChildConnectionOnResize(true, true);
pool.refreshAllPoolConnections(false, delta);
};
/**
* Inverse executes the command a.k.a. undo
*/
PMCommandPoolResize.prototype.undo = function () {
var i,
pool = this.receiver,
lane,
newWidth,
newY,
delta;
this.receiver.oldHeight = this.receiver.getHeight();
PMUI.command.CommandResize.prototype.undo.call(this);
if (this.receiver.graphic) {
this.receiver.paint();
}
if (pool.bpmnLanes.getSize() > 0) {
newWidth = pool.getWidth() - pool.headLineCoord - 1.2;
if (this.isTop) {
lane = pool.bpmnLanes.getFirst();
lane.setDimension(newWidth, this.beforeHeightsOpt.firstLaneHeight);
newY = this.beforeHeightsOpt.firstLaneHeight;
for (i = 1; i < pool.bpmnLanes.getSize(); i += 1) {
lane = pool.bpmnLanes.get(i);
lane.setPosition(lane.getX(), newY);
lane.setDimension(newWidth, lane.getHeight());
newY += lane.getHeight();
}
} else {
lane = pool.bpmnLanes.getLast();
lane.setDimension(newWidth, this.beforeHeightsOpt.lastLaneHeight);
for (i = 0; i < pool.bpmnLanes.getSize() - 1; i += 1) {
lane = pool.bpmnLanes.get(i);
lane.setDimension(newWidth, lane.getHeight());
}
}
}
pool.canvas.refreshArray.clear();
delta = {
dx: this.delta.dx * -1,
dy: this.delta.dy * -1
};
pool.poolChildConnectionOnResize(true, true);
pool.refreshAllPoolConnections(false, delta);
};
/**
* Executes the command a.k.a redo
*/
PMCommandPoolResize.prototype.redo = function () {
this.execute();
};
/*global jCore*/
var PMLaneResizeBehavior = function () {
};
PMLaneResizeBehavior.prototype = new PMUI.behavior.RegularResizeBehavior();
PMLaneResizeBehavior.prototype.type = "PMLaneResizeBehavior";
PMLaneResizeBehavior.prototype.init = function (shape) {
PMUI.behavior.RegularResizeBehavior
.prototype.init.call(this, shape);
$shape = $(shape.getHTML());
$shape.resizable();
$shape.resizable('option', 'minHeight', 30 * shape.canvas.getZoomFactor());
};
/**
* Sets a shape's container to a given container
* @param container
* @param shape
*/
PMLaneResizeBehavior.prototype.onResizeStart = function (shape) {
return PMUI.behavior.RegularResizeBehavior
.prototype.onResizeStart.call(this, shape);
};
/**
* Removes shape from its current container
* @param shape
*/
PMLaneResizeBehavior.prototype.onResize = function (shape) {
return function (e, ui) {
PMUI.behavior.RegularResizeBehavior
.prototype.onResize.call(this, shape)(e, ui);
};
};
PMLaneResizeBehavior.prototype.onResizeEnd = function (shape) {
return function (e, ui) {
var i,
j,
label,
command;
shape.resizing = false;
shape.canvas.isResizing = false;
// last resize
PMUI.behavior.RegularResizeBehavior.prototype.onResize.call(this, shape)(e, ui);
// show the handlers again
shape.showOrHideResizeHandlers(true);
for (i = 0; i < shape.labels.getSize(); i += 1) {
label = shape.labels.get(i);
label.setLabelPosition(label.location, label.diffX, label.diffY);
}
// TESTING COMMANDS
command = new PMCommandLaneResize(shape);
command.execute();
shape.canvas.commandStack.add(command);
shape.parent.updateDimensionsWithLanes();
return true;
};
};
var LaneContainerBehavior = function () {
};
LaneContainerBehavior.prototype = new PMUI.behavior.RegularContainerBehavior();
LaneContainerBehavior.prototype.type = "LaneContainerBehavior";
/**
* @inheritDoc
*/
LaneContainerBehavior.prototype.addToContainer = function (container, shape, x, y, topLeftCorner) {
PMUI.behavior.RegularContainerBehavior.prototype.addToContainer.call(this, container, shape, x, y, topLeftCorner);
shape.getCanvas().triggerCreateEvent(shape, []);
};
LaneContainerBehavior.prototype.addShape = function (container, shape, x, y) {
shape.setPosition(x, y);
//insert the shape HTML to the DOM
if (shape instanceof PMArtifact && shape.art_type === 'GROUP') {
$(container.getHTML()).prepend(shape.getHTML());
} else {
container.getHTML().appendChild(shape.getHTML());
}
shape.updateHTML();
shape.paint();
shape.applyBehaviors();
shape.attachListeners();
return this;
};
/**
* @inheritDoc
*/
LaneContainerBehavior.prototype.removeFromContainer = function (shape) {
shape.getCanvas().triggerRemoveEvent(shape, []);
PMUI.behavior.RegularContainerBehavior.prototype.removeFromContainer.call(this, shape);
};
/**
* @class CommandDelete
* Class CommandDelete determines the actions executed when some shapes are deleted (redo) and the actions
* executed when they're recreated (undo).
*
* Instances of this class are created in {@link Canvas#removeElements}.
* @extends Command
*
* @constructor Creates an instance of the class CommandDelete
* @param {Object} receiver The object that will execute the command
*/
PMCommandDelete = function (receiver) {
PMUI.command.Command.call(this, receiver);
/**
* A stack of commandsConnect
* @property {Array}
*/
this.stackCommandConnect = [];
/**
* ArrayList that represents the selection that was active before deleting the elements
* @property {ArrayList}
*/
this.currentSelection = new PMUI.util.ArrayList();
/**
* Reference to the current connection in the canvas
* @property {Connection}
*/
this.currentConnection = null;
/**
* List of all the elements related to the commands
* @property {Array}
*/
this.relatedElements = [];
this.beforeRelPositions = [];
this.tempLanes = new PMUI.util.ArrayList();
PMCommandDelete.prototype.initObject.call(this, receiver);
};
PMUI.inheritFrom('PMUI.command.Command', PMCommandDelete);
/**
* Type of command
* @property {String}
*/
PMCommandDelete.prototype.type = "PMCommandDelete";
/**
* Instance initializer which uses options to extend the config options to initialize the instance
* @param {Object} receiver The object that will execute the command
* @private
*/
PMCommandDelete.prototype.initObject = function (receiver) {
var i,
shape;
// move the current selection to this.currentSelection array
for (i = 0; i < receiver.getCurrentSelection().getSize() > 0; i += 1) {
shape = receiver.getCurrentSelection().get(i);
this.currentSelection.insert(shape);
}
// save the currentConnection of the canvas if possible
if (receiver.currentConnection) {
this.currentConnection = receiver.currentConnection;
}
};
/**
* Saves and destroys connections and shapes
* @private
* @param {Object} shape
* @param {boolean} root True if `shape` is a root element in the tree
* @param {boolean} [fillArray] If set to true it'll fill `this.relatedElements` with the objects erased
* @return {boolean}
*/
PMCommandDelete.prototype.saveAndDestroy = function (shape, root, fillArray) {
var i,
child,
parent,
children = null,
connection,
length,
canvas = shape.canvas;
if (shape.hasOwnProperty("children")) {
children = shape.children;
}
// special function to be called as an afterwards
// BIG NOTE: doesn't have to delete html
if (shape.destroy) {
shape.destroy();
}
length = children.getSize();
for (i = 0; i < length; i += 1) {
child = children.get(i);
this.saveAndDestroy(child, false, fillArray);
}
while (shape.ports && shape.ports.getSize() > 0) {
connection = shape.ports.getFirst().connection;
if (fillArray) {
this.relatedElements.push(connection);
}
this.stackCommandConnect.push(
new PMUI.command.CommandConnect(connection)
);
connection.saveAndDestroy();
}
// remove from the children array of its parent
if (root) {
parent = shape.parent;
parent.getChildren().remove(shape);
if (parent.isResizable()) {
parent.resizeBehavior.updateResizeMinimums(shape.parent);
}
if (parent.getType() === 'PMLane') {
parent.updateDimensions();
}
// remove from the currentSelection and from either the customShapes
// arrayList or the regularShapes arrayList
// remove the html only from the root
if (shape.corona) {
shape.corona.hide();
}
shape.html = $(shape.html).detach()[0];
if (shape.getType() === 'PMLane') {
this.beforeRelPositions[shape.getID()] = shape.getRelPosition();
shape.parent.bpmnLanes.remove(shape);
}
}
if (fillArray) {
this.relatedElements.push(shape);
}
// remove from the currentSelection and from either the customShapes
// arrayList or the regularShapes arrayList
canvas.removeFromList(shape);
return true;
};
/**
* Executes the command
*
* @chainable
*/
PMCommandDelete.prototype.execute = function () {
var shape,
i,
canvas = this.receiver,
currentConnection,
fillArray = false,
mainShape = null,
data,
url = '/project/' + PMDesigner.project.id + '/activity/validate-active-cases';
if (this.relatedElements.length === 0) {
fillArray = true;
}
canvas.emptyCurrentSelection();
// copy from this.currentConnection
if (this.currentSelection.getSize() === 1) {
shape = this.currentSelection.get(0);
if (shape.getType() === 'PMActivity') {
data = {
act_uid: shape.getID(),
case_type: 'assigned'
};
PMDesigner.restApi.execute({
data: JSON.stringify(data),
method: "update",
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + url,
async: false,
success: function (data, textStatus, xhr) {
if (data.result) {
canvas.addToSelection(shape);
} else {
shape.corona.hide();
PMDesigner.msgFlash(data.message, document.body, 'error', 3000, 5);
}
},
error: function (xhr, textStatus, errorThrown) {
PMDesigner.msgFlash('There are problems removing task'.translate(), document.body, 'error', 3000, 5);
}
});
} else {
canvas.addToSelection(shape);
}
} else if (this.currentSelection.getSize() !== 0) {
PMDesigner.msgFlash('Invalid operation, please delete elements individually'.translate(), document.body, 'error', 3000, 5);
}
if (canvas.currentSelection.getSize() === 1) {
mainShape = shape;
}
// remove the elements in the canvas current selection
if (shape && shape.getType() === 'PMPool') {
for (i = 0; i < shape.bpmnLanes.getSize(); i += 1) {
this.tempLanes.insert(shape.bpmnLanes.get(i));
}
}
while (canvas.getCurrentSelection().getSize() > 0) {
shape = canvas.getCurrentSelection().getFirst();
this.saveAndDestroy(shape, true, fillArray);
}
if (shape && shape.getType() === 'PMLane') {
for (i = 0; i < shape.parent.bpmnLanes.getSize(); i += 1) {
shape.parent.bpmnLanes.get(i)
.refreshChildrenPositions(true)
.refreshConnections(false, false);
}
}
// destroy the currentConnection
canvas.currentConnection = this.currentConnection;
currentConnection = canvas.currentConnection;
if (currentConnection) {
// add to relatedElements just in the case when only a connection is
// selected and deleted
this.relatedElements.push(currentConnection);
this.stackCommandConnect.push(
new PMUI.command.CommandConnect(currentConnection)
);
currentConnection.saveAndDestroy();
currentConnection = null;
mainShape = currentConnection;
}
canvas.triggerRemoveEvent(mainShape, this.relatedElements);
return this;
};
/**
* Inverse executes the command a.k.a. undo
*
* @chainable
*/
PMCommandDelete.prototype.undo = function () {
// undo recreates the shapes
var i,
shape,
mainShape = this.currentSelection.getFirst() || this.currentConnection,
size,
haveLanes = false,
shapeBefore,
j,
element,
length;
this.currentSelection.sort(function (lane1, lane2) {
return lane1.relPosition > lane2.relPosition;
});
length = this.currentSelection.getSize();
for (i = 0; i < length; i += 1) {
shape = this.currentSelection.get(i);
shapeBefore = null;
// add to the canvas array of regularShapes and customShapes
shape.canvas.addToList(shape);
shape.getChildren().asArray().forEach(function (e) {
shape.canvas.addToList(e);
});
// add to the children of the parent
shape.parent.getChildren().insert(shape);
shape.showOrHideResizeHandlers(false);
if (shape.getType() !== 'PMLane') {
shape.parent.html.appendChild(shape.getHTML());
} else {
shapeBefore = shape.parent.bpmnLanes
.get(this.beforeRelPositions[shape.getID()] - 1);
if (shapeBefore) {
shape.parent.html
.insertBefore(shape.getHTML(), shapeBefore.getHTML());
} else {
shape.parent.html.appendChild(shape.getHTML());
}
size = shape.parent.bpmnLanes.getSize();
for (j = this.beforeRelPositions[shape.getID()] - 1; j < size; j += 1) {
element = shape.parent.bpmnLanes.get(j);
element.setRelPosition(j + 2);
}
shape.setRelPosition(this.beforeRelPositions[shape.getID()]);
shape.parent.bpmnLanes.insert(shape);
shape.parent.bpmnLanes.bubbleSort(shape.parent.comparisonFunction);
shape.parent.updateAllLaneDimension();
}
if (shape.getType() === 'PMPool') {
for (i = 0; i < this.tempLanes.getSize(); i += 1) {
shape.bpmnLanes.insert(this.tempLanes.get(i));
}
if (shape.bpmnLanes.getSize() > 0) {
shape.updateAllLaneDimension();
}
}
if(shape.corona){
shape.corona.hide();
}
}
// reconnect using the stack of commandConnect
for (i = this.stackCommandConnect.length - 1; i >= 0; i -= 1) {
this.stackCommandConnect[i].buildConnection();
}
this.receiver.triggerCreateEvent(mainShape, this.relatedElements);
if (haveLanes) {
for (i = 0; i < mainShape.parent.bpmnLanes.getSize(); i += 1) {
mainShape.parent.bpmnLanes.get(i)
.refreshChildrenPositions(true)
.refreshConnections(false);
}
}
return this;
};
/**
* Executes the command (a.k.a redo)
* @chainable
*/
PMCommandDelete.prototype.redo = function () {
this.execute();
return this;
};
var PMCommandResize = function (receiver) {
PMCommandResize.superclass.call(this, receiver);
this._boundExceed = null;
this._parent;
PMCommandResize.prototype.initObject.call(this, receiver);
};
PMUI.inheritFrom('PMUI.command.CommandResize', PMCommandResize);
PMCommandResize.prototype.type = 'PMCommandResize';
PMCommandResize.prototype.initObject = function (receiver) {
this._parent = this.receiver.getParent();
if (this._parent.getType() === 'PMLane') {
this.before.parentWidth = this.after.parentWidth = this._parent.getWidth();
this.before.parentHeight = this.after.parentHeight = this._parent.getHeight();
if (this._boundExceed === null) {
this._boundExceed = {
x: this.receiver.getWidth() - (this._parent.getWidth() - this.receiver.getX()),
y: this.receiver.getHeight() - (this._parent.getHeight() - this.receiver.getY())
};
}
if (this._boundExceed.x > 0) {
this.after.parentWidth = this.before.parentWidth + this._boundExceed.x;
}
if (this._boundExceed.y > 0) {
this.after.parentHeight = this.before.parentHeight + this._boundExceed.y;
}
}
};
PMCommandResize.prototype.execute = function () {
PMCommandResize.superclass.prototype.execute.call(this);
if (this._boundExceed !== null && (this._boundExceed.x > 0 || this._boundExceed.y > 0)) {
this._parent.setDimension(
this.after.parentWidth,
this.after.parentHeight
);
this._parent.updateAllRelatedDimensions();
}
return this;
};
PMCommandResize.prototype.undo = function () {
PMCommandResize.superclass.prototype.undo.call(this);
if (this._boundExceed !== null && (this._boundExceed.x > 0 || this._boundExceed.y > 0)) {
this._parent.setDimension(
this.before.parentWidth,
this.before.parentHeight
);
this._parent.updateAllRelatedDimensions();
}
return this;
};
/**
* Command resize: command resize when a poll is resized (mazimized or minimized)
* @class BPMNCommandPoolResize
* @constructor
*/
var PMCommandLaneResize = function (receiver) {
PMUI.command.CommandResize.call(this, receiver);
};
/**
* Type of command of this object
* @type {String}
*/
PMUI.inheritFrom('PMUI.command.CommandResize', PMCommandLaneResize);
PMCommandLaneResize.prototype.type = 'PMCommandLaneResize';
/**
* Executes the command
*/
PMCommandLaneResize.prototype.execute = function () {
PMUI.command.CommandResize.prototype.execute.call(this);
this.receiver.updateAllRelatedDimensions(true);
};
/**
* Inverse executes the command a.k.a. undo
*/
PMCommandLaneResize.prototype.undo = function () {
this.receiver.oldWidth = this.receiver.getWidth();
this.receiver.oldHeight = this.receiver.getHeight();
PMUI.command.CommandResize.prototype.undo.call(this);
this.receiver.updateAllRelatedDimensions(true);
};
/**
* Executes the command a.k.a redo
*/
PMCommandLaneResize.prototype.redo = function () {
this.execute();
};
var PMCommandMoveInLane = function (receiver) {
PMCommandMoveInLane.superclass.call(this, receiver);
this._parentLane = null;
this._boundExceed = {
x: 0,
y: 0
};
PMCommandMoveInLane.prototype.initObject.call(this, receiver);
};
PMUI.inheritFrom('PMUI.command.CommandMove', PMCommandMoveInLane);
PMCommandMoveInLane.prototype.type = 'PMCommandMoveInLane';
PMCommandMoveInLane.prototype.initObject = function (receiver) {
var i,
size = this.receiver.getSize(),
shape,
boundExceed,
laneWidth,
laneHeight;
if (this.receiver.getSize() > 0) {
this._parentLane = receiver.get(0).getParent();
}
laneWidth = this._parentLane.getWidth();
laneHeight = this._parentLane.getHeight();
this.before.laneWidth = laneWidth;
this.before.laneHeight = laneHeight;
for (i = 0; i < size; i += 1) {
shape = this.receiver.get(i);
boundExceed = {
x: shape.getWidth() - (laneWidth - shape.getX()),
y: shape.getHeight() - (laneHeight - shape.getY())
};
if (boundExceed.x > 0 || boundExceed.y > 0) {
if (this._boundExceed.x < boundExceed.x) {
this._boundExceed.x = boundExceed.x;
}
if (this._boundExceed.y < boundExceed.y) {
this._boundExceed.y = boundExceed.y;
}
}
}
this.after.laneWidth = laneWidth + this._boundExceed.x;
this.after.laneHeight = laneHeight + this._boundExceed.y;
};
PMCommandMoveInLane.prototype.execute = function () {
var res = PMCommandMoveInLane.superclass.prototype.execute.call(this);
this._parentLane.setDimension(
this.after.laneWidth,
this.after.laneHeight
);
this._parentLane.updateAllRelatedDimensions(false);
return res;
};
PMCommandMoveInLane.prototype.undo = function () {
var res = PMCommandMoveInLane.superclass.prototype.undo.call(this);
this._parentLane.setDimension(
this.before.laneWidth,
this.before.laneHeight
);
this._parentLane.updateAllRelatedDimensions();
return res;
};
var CommandChangeEventMarker = function (receiver, options) {
PMUI.command.Command.call(this, receiver);
this.before = null;
this.after = null;
CommandChangeEventMarker.prototype.initObject.call(this, options);
};
PMUI.inheritFrom('PMUI.command.Command', CommandChangeEventMarker);
/**
* Type of the instances of this class
* @property {String}
*/
CommandChangeEventMarker.prototype.type = "CommandChangeEventMarker";
/**
* Initializes the command parameters
* @param {PMUI.draw.Core} receiver The object that will perform the action
*/
CommandChangeEventMarker.prototype.initObject = function (options) {
var parsedClass = options;
this.layer = this.receiver.getLayers().get(0);
this.before = {
zoomSprite: this.layer.zoomSprites,
marker: this.receiver.evn_marker
};
this.after = {
zoomSprite: [
'mafe-event-' + this.receiver.getEventType().toLowerCase() + '-' +
parsedClass.toLowerCase() + '-16',
'mafe-event-' + this.receiver.getEventType().toLowerCase() + '-' +
parsedClass.toLowerCase() + '-24',
'mafe-event-' + this.receiver.getEventType().toLowerCase() + '-' +
parsedClass.toLowerCase() + '-33',
'mafe-event-' + this.receiver.getEventType().toLowerCase() + '-' +
parsedClass.toLowerCase() + '-41',
'mafe-event-' + this.receiver.getEventType().toLowerCase() + '-' +
parsedClass.toLowerCase() + '-49'
],
marker: options
};
};
/**
* Executes the command, changes the position of the element, and if necessary
* updates the position of its children, and refreshes all connections
*/
CommandChangeEventMarker.prototype.execute = function () {
var menuShape;
this.layer.setZoomSprites(this.after.zoomSprite);
this.receiver.setEventMarker(this.after.marker);
this.receiver
.updateBpmEventMarker(this.receiver.getBpmnElementType());
PMDesigner.project.updateElement([]);
menuShape = PMDesigner.getMenuFactory(this.receiver.getEventType());
this.receiver.setContextMenu(menuShape);
this.receiver.paint();
};
/**
* Returns to the state before the command was executed
*/
CommandChangeEventMarker.prototype.undo = function () {
var menuShape;
this.layer.setZoomSprites(this.before.zoomSprite);
this.receiver.setEventMarker(this.before.marker);
this.receiver
.updateBpmEventMarker(this.receiver.getBpmnElementType());
this.receiver.extendedType = this.before.marker;
PMDesigner.project.setDirty(true);
$(this.receiver.html).trigger('changeelement');
menuShape = PMDesigner.getMenuFactory(this.receiver.getEventType());
this.receiver.setContextMenu(menuShape);
this.receiver.paint();
};
/**
* Executes the command again after an undo action has been done
*/
CommandChangeEventMarker.prototype.redo = function () {
this.execute();
};
var PMCommandSwitchToLaneContainer = function (receiver) {
PMCommandSwitchToLaneContainer.superclass.call(this, receiver);
this._parentLane = null;
this._boundExceed = {
x: 0,
y: 0
};
PMCommandSwitchToLaneContainer.prototype.initObject.call(this, receiver);
};
PMUI.inheritFrom("PMUI.command.CommandSwitchContainer", PMCommandSwitchToLaneContainer);
PMCommandSwitchToLaneContainer.prototype.type = 'PMCommandSwitchToLaneContainer';
PMCommandSwitchToLaneContainer.prototype.initObject = function (receiver) {
this._parentLane = this.after.shapes[0].parent;
};
PMCommandSwitchToLaneContainer.prototype.execute = function () {
var i, shape, boundExceed, laneWidth, laneHeight;
PMCommandSwitchToLaneContainer.superclass.prototype.execute.call(this);
if (this.before.laneWidth === undefined ||this.before.laneHeight === undefined) {
laneWidth = this._parentLane.getWidth();
laneHeight = this._parentLane.getHeight();
this.before.laneWidth = laneWidth;
this.before.laneHeight = laneHeight;
for (i = 0; i < this.relatedShapes.length; i += 1) {
shape = this.relatedShapes[i];
boundExceed = {
x: shape.getWidth() - (laneWidth - shape.getX()),
y: shape.getHeight() - (laneHeight - shape.getY())
};
if (boundExceed.x > 0 || boundExceed.y > 0) {
if (this._boundExceed.x < boundExceed.x) {
this._boundExceed.x = boundExceed.x;
}
if (this._boundExceed.y < boundExceed.y) {
this._boundExceed.y = boundExceed.y;
}
}
}
this.after.laneWidth = laneWidth + this._boundExceed.x;
this.after.laneHeight = laneHeight + this._boundExceed.y;
}
this._parentLane.setDimension(
this.after.laneWidth,
this.after.laneHeight
);
this._parentLane.updateAllRelatedDimensions();
return this;
};
PMCommandSwitchToLaneContainer.prototype.undo = function () {
PMCommandSwitchToLaneContainer.superclass.prototype.undo.call(this);
this._parentLane.setDimension(
this.before.laneWidth,
this.before.laneHeight
);
this._parentLane.updateAllRelatedDimensions();
return this;
};
var PMCommandCreateInLane = function (receiver) {
PMCommandCreateInLane.superclass.call(this, receiver);
this._parentLane = null;
this._boundExceed = {};
PMCommandCreateInLane.prototype.initObject.call(this, receiver);
};
PMUI.inheritFrom('PMUI.command.CommandCreate', PMCommandCreateInLane);
PMCommandCreateInLane.prototype.type = 'PMCommandCreateInLane';
PMCommandCreateInLane.prototype.initObject = function (receiver) {
this._parentLane = receiver.getParent();
if (!(this._parentLane instanceof PMLane)) {
throw new Error('initObject(): The container element must be a PMLane instance.');
}
this._boundExceed = {
x: receiver.getWidth() - (this._parentLane.getWidth() - receiver.getX()),
y: receiver.getHeight() - (this._parentLane.getHeight() - receiver.getY())
};
this.before.laneWidth = this._parentLane.getWidth();
this.before.laneHeight = this._parentLane.getHeight();
this.after.laneWidth = this.before.laneWidth + (this._boundExceed.x > 0 ? this._boundExceed.x : 0);
this.after.laneHeight = this.before.laneHeight + (this._boundExceed.y > 0 ? this._boundExceed.y : 0);
};
PMCommandCreateInLane.prototype.execute = function () {
PMCommandCreateInLane.superclass.prototype.execute.call(this);
if (this._boundExceed.x > 0 || this._boundExceed.y > 0) {
this._parentLane.setDimension(
this.after.laneWidth,
this.after.laneHeight
);
this._parentLane.updateAllRelatedDimensions();
}
return this;
};
PMCommandCreateInLane.prototype.undo = function () {
PMCommandCreateInLane.superclass.prototype.undo.call(this);
if (this._boundExceed.x > 0 || this._boundExceed.y > 0) {
this._parentLane.setDimension(
this.before.laneWidth,
this.before.laneHeight
);
this._parentLane.updateAllRelatedDimensions();
}
return this;
};
var CanvasContainerBehavior = function () {
};
CanvasContainerBehavior.prototype = new PMUI.behavior.RegularContainerBehavior();
CanvasContainerBehavior.prototype.type = "CanvasContainerBehavior";
/**
* Adds a shape to a given container given its coordinates
* @param {PMUI.draw.BehavioralElement} container container using this behavior
* @param {PMUI.draw.Shape} shape shape to be added
* @param {number} x x coordinate where the shape will be added
* @param {number} y y coordinate where the shape will be added
* @param {boolean} topLeftCorner Determines whether the x and y coordinates
* will be considered from the top left corner or from the center
*/
CanvasContainerBehavior.prototype.addToContainer = function (container, shape, x, y, topLeftCorner) {
var shapeLeft = 0,
shapeTop = 0,
shapeWidth,
shapeHeight,
canvas,
topLeftFactor = (topLeftCorner === true) ? 0 : 1;
if (container.family === "Canvas") {
canvas = container;
} else {
canvas = container.canvas;
}
shapeWidth = shape.getZoomWidth();
shapeHeight = shape.getZoomHeight();
shapeLeft += x - (shapeWidth / 2) * topLeftFactor;
shapeTop += y - (shapeHeight / 2) * topLeftFactor;
shapeLeft /= canvas.zoomFactor;
shapeTop /= canvas.zoomFactor;
shape.setParent(container);
container.getChildren().insert(shape);
this.addShape(container, shape, shapeLeft, shapeTop);
// fix the zIndex of this shape and it's children
if (shape.getType() === 'PMPool' || shape.getType() === 'PMParticipant') {
shape.fixZIndex(shape, 3);
} else {
shape.fixZIndex(shape, 2);
}
// fix resize minWidth and minHeight and also fix the dimension
// of this shape (if a child made it grow)
container.updateDimensions(10);
// adds the shape to either the customShape arrayList or the regularShapes
// arrayList if possible
canvas.addToList(shape);
canvas.triggerCreateEvent(shape, []);
};
CanvasContainerBehavior.prototype.addShape = function (container, shape, x, y) {
shape.setPosition(x, y);
//insert the shape HTML to the DOM
if (shape instanceof PMArtifact && shape.art_type === 'GROUP') {
$(container.getHTML()).prepend(shape.getHTML());
} else {
container.getHTML().appendChild(shape.getHTML());
}
shape.updateHTML();
shape.paint();
shape.applyBehaviors();
shape.attachListeners();
return this;
};
/**
* Removes shape from its current container
* @param {PMUI.draw.Shape} shape shape to be removed
* @template
* @protected
*/
CanvasContainerBehavior.prototype.removeFromContainer = function (shape) {
var canvas = shape.getCanvas();
canvas.triggerRemoveEvent(shape, []);
PMUI.behavior.RegularContainerBehavior.prototype.removeFromContainer.call(this, shape);
};
/**
* @class ActivityContainerBehavior
* Encapsulates the behavior of a regular container
* @extends PMUI.behavior.RegularContainerBehavior
*
* @constructor
* Creates a new instance of the class
*/
var ActivityContainerBehavior = function () {
};
ActivityContainerBehavior.prototype = new PMUI.behavior.RegularContainerBehavior();
/**
* Type of the instances
* @property {String}
*/
ActivityContainerBehavior.prototype.type = "ActivityContainerBehavior";
/**
* Adds a shape to a given container given its coordinates
* @param {PMUI.draw.BehavioralElement} container container using this behavior
* @param {PMUI.draw.Shape} shape shape to be added
* @param {number} x x coordinate where the shape will be added
* @param {number} y y coordinate where the shape will be added
* @param {boolean} topLeftCorner Determines whether the x and y coordinates
* will be considered from the top left corner or from the center
*/
ActivityContainerBehavior.prototype.addToContainer = function (container, shape, x, y, topLeftCorner) {
var shapeLeft = 0,
shapeTop = 0,
shapeWidth,
shapeHeight,
canvas,
topLeftFactor = (topLeftCorner === true) ? 0 : 1;
if (container.family === "Canvas") {
canvas = container;
} else {
canvas = container.canvas;
}
shapeWidth = shape.getZoomWidth();
shapeHeight = shape.getZoomHeight();
shapeLeft += x - (shapeWidth / 2) * topLeftFactor;
shapeTop += y - (shapeHeight / 2) * topLeftFactor;
shapeLeft /= canvas.zoomFactor;
shapeTop /= canvas.zoomFactor;
shape.setParent(container);
container.getChildren().insert(shape);
this.addShape(container, shape, shapeLeft, shapeTop);
// fix the zIndex of this shape and it's children
shape.fixZIndex(shape, 1);
canvas.addToList(shape);
if (shape.getType() === 'PMEvent' && shape.getEventType() === 'BOUNDARY') {
container.boundaryArray.insert(shape);
if (container.boundaryPlaces.isEmpty()) {
container.makeBoundaryPlaces();
}
shape.attachToActivity();
} else {
// fix resize minWidth and minHeight and also fix the dimension
// of this shape (if a child made it grow)
container.updateDimensions(10);
}
};
/**
* @class PMUI.behavior.ContainerDropBehavior
* Encapsulates the drop behavior of a container
* @extends PMUI.behavior.DropBehavior
*
* @constructor
* Creates a new instance of the class
* @param {Array} [selectors=[]] css selectors that this drop behavior will
* accept
*/
var PMActivityDropBehavior = function (selectors) {
PMUI.behavior.DropBehavior.call(this, selectors);
};
PMActivityDropBehavior.prototype = new PMUI.behavior.DropBehavior();
/**
* Type of the instances
* @property {String}
*/
PMActivityDropBehavior.prototype.type = "PMActivityDropBehavior";
/**
* Default selectors for this drop behavior
* @property {String}
*/
PMActivityDropBehavior.prototype.defaultSelector = ".custom_shape";
/**
* On drop handler for this drop behavior, creates shapes when dropped from the
* toolbar, or move shapes among containers
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMActivityDropBehavior.prototype.onDrop = function (shape) {
return function (e, ui) {
var customShape = null,
canvas = shape.getCanvas(),
selection,
sibling,
i,
command,
coordinates,
id,
shapesAdded = [],
containerBehavior = shape.containerBehavior;
if (canvas.readOnly) {
return false;
}
shape.layers.getFirst().removeCSSClasses(['dropableClass']);
if (!shape.isValidDropArea) {
return false;
}
shape.entered = false;
if (ui.helper && ui.helper.attr('id') === "drag-helper") {
return false;
}
id = ui.draggable.attr('id');
customShape = canvas.shapeFactory(id);
if (customShape === null) {
customShape = canvas.customShapes.find('id', id);
if (!customShape || !shape.dropBehavior.dropHook(shape, e, ui)) {
return false;
}
if (!(customShape.parent &&
customShape.parent.id === shape.id)) {
selection = canvas.currentSelection;
for (i = 0; i < selection.getSize(); i += 1) {
sibling = selection.get(i);
coordinates = PMUI.getPointRelativeToPage(sibling);
coordinates = PMUI.pageCoordinatesToShapeCoordinates(shape, null,
coordinates.x, coordinates.y, customShape);
shapesAdded.push({
shape: sibling,
container: shape,
x: coordinates.x,
y: coordinates.y,
topLeft: false
});
}
command = new PMUI.command.CommandSwitchContainer(shapesAdded);
command.execute();
canvas.commandStack.add(command);
canvas.multipleDrop = true;
}
shape.setBoundary(customShape, customShape.numberRelativeToActivity);
// fix resize minWidth and minHeight and also fix the dimension
// of this shape (if a child made it grow)
canvas.hideAllFocusLabels();
canvas.updatedElement = null;
} else {
coordinates = PMUI.pageCoordinatesToShapeCoordinates(shape, e, null, null, customShape);
if (PMUI.validCoordinatedToCreate(shape, e, customShape)) {
shape.addElement(customShape, coordinates.x, coordinates.y,
customShape.topLeftOnCreation);
//since it is a new element in the designer, we triggered the
//custom on create element event
canvas.updatedElement = customShape;
if (customShape.getType() === 'PMLane') {
command = new PMCommandCreateLane(customShape);
canvas.commandStack.add(command);
command.execute();
} else {
// create the command for this new shape
command = new PMUI.command.CommandCreate(customShape);
canvas.commandStack.add(command);
command.execute();
}
canvas.hideAllFocusLabels();
}
}
};
};
PMActivityDropBehavior.prototype.setSelectors = function (selectors, overwrite) {
PMUI.behavior.DropBehavior.prototype
.setSelectors.call(this, selectors, overwrite);
this.selectors.push(".port");
return this;
};
PMActivityDropBehavior.prototype.onDragEnter = function (customShape) {
return function (e, ui) {
var shapeRelative, i;
if (customShape.extendedType !== "PARTICIPANT") {
if (ui.helper && ui.helper.hasClass("dragConnectHandler")) {
if (customShape.extendedType !== "TEXT_ANNOTATION") {
shapeRelative = customShape.canvas.dragConnectHandlers.get(0).relativeShape;
if (shapeRelative.id !== customShape.id) {
for (i = 0; i < 4; i += 1) {
customShape.showConnectDropHelper(i, customShape);
}
}
} else {
if (customShape.extendedType !== "H_LABEL" && customShape.extendedType !== "V_LABEL") {
shapeRelative = customShape.canvas.dragConnectHandlers.get(3).relativeShape;
if (shapeRelative.id !== customShape.id) {
customShape.canvas.hideDropConnectHandlers();
customShape.showConnectDropHelper(3, customShape);
}
}
}
} else {
customShape.layers.getFirst().addCSSClasses(['dropableClass']);
return false;
}
} else {
shapeRelative = customShape.canvas.dragConnectHandlers.get(0).relativeShape;
if (shapeRelative.id !== customShape.id) {
if (ui.helper && ui.helper.hasClass("dragConnectHandler")) {
for (i = 0; i < 10; i += 1) {
connectHandler = customShape.canvas.dropConnectHandlers.get(i);
connectHandler.setDimension(18 * customShape.canvas.getZoomFactor(), 18 * customShape.canvas.getZoomFactor());
connectHandler.setPosition(customShape.getZoomX() + i * customShape.getZoomWidth() / 10, customShape.getZoomY() - connectHandler.height / 2 - 1);
connectHandler.relativeShape = customShape;
connectHandler.attachDrop();
connectHandler.setVisible(true);
}
for (i = 0; i < 10; i += 1) {
connectHandler = customShape.canvas.dropConnectHandlers.get(i + 10);
connectHandler.setDimension(18 * customShape.canvas.getZoomFactor(), 18 * customShape.canvas.getZoomFactor());
connectHandler.setPosition(customShape.getZoomX() + i * customShape.getZoomWidth() / 10, customShape.getZoomY() + customShape.getZoomHeight() - connectHandler.height / 2 - 1);
connectHandler.relativeShape = customShape;
connectHandler.attachDrop();
connectHandler.setVisible(true);
}
}
}
}
}
};
PMActivityDropBehavior.prototype.onDragLeave = function (shape) {
return function (e, ui) {
shape.layers.getFirst().removeCSSClasses(['dropableClass']);
};
};
'use strict';
/**
* An empty collection stub. Use {@link RefsCollection.extend} to extend a
* collection with ref semantics.
*
* @classdesc A change and inverse-reference aware collection with set semantics.
*
* @class RefsCollection
*/
function RefsCollection() { }
/**
* Extends a collection with {@link Refs} aware methods
*
* @memberof RefsCollection
* @static
*
* @param {Array<Object>} collection
* @param {Refs} refs instance
* @param {Object} property represented by the collection
* @param {Object} target object the collection is attached to
*
* @return {RefsCollection<Object>} the extended array
*/
function extend(collection, refs, property, target) {
var inverseProperty = property.inverse;
/**
* Removes the given element from the array and returns it.
*
* @method RefsCollection#remove
*
* @param {Object} element the element to remove
*/
collection.remove = function(element) {
var idx = this.indexOf(element);
if (idx !== -1) {
this.splice(idx, 1);
// unset inverse
refs.unset(element, inverseProperty, target);
}
return element;
};
/**
* Returns true if the collection contains the given element
*
* @method RefsCollection#contains
*
* @param {Object} element the element to check for
*/
collection.contains = function(element) {
return this.indexOf(element) !== -1;
};
/**
* Adds an element to the array, unless it exists already (set semantics).
*
* @method RefsCollection#add
*
* @param {Object} element the element to add
*/
collection.add = function(element) {
if (!this.contains(element)) {
this.push(element);
// set inverse
refs.set(element, inverseProperty, target);
}
};
return collection;
}
//module.exports.extend = extend;
'use strict';
//var Collection = require('./collection');
function hasOwnProperty(e, property) {
return Object.prototype.hasOwnProperty.call(e, property.name || property);
}
function defineCollectionProperty(ref, property, target) {
Object.defineProperty(target, property.name, {
enumerable: property.enumerable,
value: Collection.extend(target[property.name] || [], ref, property, target)
});
}
function defineProperty(ref, property, target) {
var inverseProperty = property.inverse;
var _value = target[property.name];
if(!target[property.name]){
Object.defineProperty(target, property.name, {
enumerable: property.enumerable,
get: function() {
return _value;
},
set: function(value) {
// return if we already performed all changes
if (value === _value) {
return;
}
var old = _value;
// temporary set null
_value = null;
if (old) {
ref.unset(old, inverseProperty, target);
}
// set new value
_value = value;
// set inverse value
ref.set(_value, inverseProperty, target);
}
});
};
}
/**
* Creates a new references object defining two inversly related
* attribute descriptors a and b.
*
* <p>
* When bound to an object using {@link Refs#bind} the references
* get activated and ensure that add and remove operations are applied
* reversely, too.
* </p>
*
* <p>
* For attributes represented as collections {@link Refs} provides the
* {@link RefsCollection#add}, {@link RefsCollection#remove} and {@link RefsCollection#contains} extensions
* that must be used to properly hook into the inverse change mechanism.
* </p>
*
* @class Refs
*
* @classdesc A bi-directional reference between two attributes.
*
* @param {Refs.AttributeDescriptor} a property descriptor
* @param {Refs.AttributeDescriptor} b property descriptor
*
* @example
*
* var refs = Refs({ name: 'wheels', collection: true, enumerable: true }, { name: 'car' });
*
* var car = { name: 'toyota' };
* var wheels = [{ pos: 'front-left' }, { pos: 'front-right' }];
*
* refs.bind(car, 'wheels');
*
* car.wheels // []
* car.wheels.add(wheels[0]);
* car.wheels.add(wheels[1]);
*
* car.wheels // [{ pos: 'front-left' }, { pos: 'front-right' }]
*
* wheels[0].car // { name: 'toyota' };
* car.wheels.remove(wheels[0]);
*
* wheels[0].car // undefined
*/
function Refs(a, b) {
if (!(this instanceof Refs)) {
return new Refs(a, b);
}
// link
a.inverse = b;
b.inverse = a;
this.props = {};
this.props[a.name] = a;
this.props[b.name] = b;
}
/**
* Binds one side of a bi-directional reference to a
* target object.
*
* @memberOf Refs
*
* @param {Object} target
* @param {String} property
*/
Refs.prototype.bind = function(target, property) {
if (typeof property === 'string') {
if (!this.props[property]) {
throw new Error('no property <' + property + '> in ref');
}
property = this.props[property];
}
if (property.collection) {
defineCollectionProperty(this, property, target);
} else {
defineProperty(this, property, target);
}
};
Refs.prototype.ensureBound = function(target, property) {
if (!hasOwnProperty(target, property)) {
this.bind(target, property);
}
};
Refs.prototype.unset = function(target, property, value) {
if (target) {
this.ensureBound(target, property);
if (property.collection) {
target[property.name].remove(value);
} else {
target[property.name] = undefined;
}
}
};
Refs.prototype.set = function(target, property, value) {
if (target) {
this.ensureBound(target, property);
if (property.collection) {
target[property.name].add(value);
} else {
target[property.name] = value;
}
}
};
//
//module.exports = Refs;
/**
* An attribute descriptor to be used specify an attribute in a {@link Refs} instance
*
* @typedef {Object} Refs.AttributeDescriptor
* @property {String} name
* @property {boolean} [collection=false]
* @property {boolean} [enumerable=false]
*/
'use strict';
//
var diRefs = new Refs({ name: 'bpmnElement', enumerable: true }, { name: 'di' });
function BpmnTreeWalker(handler) {
// list of containers already walked
var handledProcesses = [];
// list of elements to handle deferred to ensure
// prerequisites are drawn
var deferred = [];
///// Helpers /////////////////////////////////
function contextual(fn, ctx) {
return function(e) {
fn(e, ctx);
};
}
function is(element, type) {
return element.$instanceOf(type);
}
function visit(element, ctx) {
var gfx = element.gfx;
// avoid multiple rendering of elements
if (gfx) {
throw new Error('already rendered <' + element.id + '>');
}
// call handler
return handler.element(element, ctx);
}
function visitRoot(element, diagram) {
return handler.root(element, diagram);
}
function visitIfDi(element, ctx) {
try {
if (element.di) {
return visit(element, ctx);
}
} catch (e) {
logError(e.message, { element: element, error: e });
}
}
function logError(message, context) {
handler.error(message, context);
}
////// DI handling ////////////////////////////
function registerDi(di) {
var bpmnElement = di.bpmnElement;
if (bpmnElement) {
diRefs.bind(bpmnElement, 'di');
bpmnElement.di = di;
} else {
logError('no bpmnElement for <' + di.$type + '#' + di.id + '>', { element: di });
}
}
function handleDiagram(diagram) {
handlePlane(diagram.plane);
}
function handlePlane(plane) {
registerDi(plane);
_.forEach(plane.planeElement, handlePlaneElement);
}
function handlePlaneElement(planeElement) {
registerDi(planeElement);
}
////// Semantic handling //////////////////////
function handleDefinitions(definitions, diagram) {
// make sure we walk the correct bpmnElement
var diagrams = definitions.diagrams, i, rootElement, participant;
if (diagram && diagrams.indexOf(diagram) === -1) {
throw new Error('diagram not part of bpmn:Definitions');
}
if (!diagram && diagrams && diagrams.length) {
diagram = diagrams[0];
}
// no diagram -> nothing to import
if (!diagram) {
return;
}
// load DI from selected diagram only
handleDiagram(diagram);
var plane = diagram.plane,
rootElement = plane.bpmnElement;
if (!rootElement) {
throw new Error('no rootElement referenced in BPMNPlane <' + diagram.plane.id + '>');
}
var ctx = visitRoot(rootElement, plane);
if (is(rootElement, 'bpmn:Process')) {
handleProcess(rootElement, ctx);
rootElement.visited = true;
} else if (is(rootElement, 'bpmn:Collaboration')) {
handleCollaboration(rootElement, ctx);
// force drawing of everything not yet drawn that is part of the target DI
handleUnhandledProcesses(definitions.rootElements, ctx);
for (i = 0; i < rootElement.participants.length; i += 1) {
participant = rootElement.participants[i];
if(participant.processRef) {
participant.processRef.visited = true;
}
}
} else {
throw new Error('unsupported root element for bpmndi:Diagram <' + rootElement.$type + '>');
}
// handle all deferred elements
handleDeferred(deferred);
for (i = 0; i < definitions.rootElements.length; i += 1) {
rootElement = definitions.rootElements[i];
if (rootElement.$type !== 'bpmn:Collaboration' && !rootElement.visited) {
//plane
//var ctx = visitRoot(rootElement, plane);
if (is(rootElement, 'bpmn:Process')) {
handleProcess(rootElement, ctx);
} else if(rootElement.$type !== 'bpmn:DataStore'){
throw new Error('unsupported root element for bpmndi:Diagram <' + rootElement.$type + '>');
}
handleDeferred(deferred);
}
}
}
function handleDeferred(deferred) {
_.forEach(deferred, function(d) { d(); });
}
function handleProcess(process, context) {
handleFlowElementsContainer(process, context);
handleIoSpecification(process.ioSpecification, context);
handleArtifacts(process.artifacts, context);
// log process handled
handledProcesses.push(process);
}
function handleUnhandledProcesses(rootElements) {
// walk through all processes that have not yet been drawn and draw them
// if they contain lanes with DI information.
// we do this to pass the free-floating lane test cases in the MIWG test suite
var processes = _.filter(rootElements, function(e) {
return is(e, 'bpmn:Process') && e.laneSets && handledProcesses.indexOf(e) === -1;
});
processes.forEach(contextual(handleProcess));
}
function handleMessageFlow(messageFlow, context) {
visitIfDi(messageFlow, context);
}
function handleMessageFlows(messageFlows, context) {
if (messageFlows) {
_.forEach(messageFlows, contextual(handleMessageFlow, context));
}
}
function handleDataAssociation(association, context) {
visitIfDi(association, context);
}
function handleDataInput(dataInput, context) {
visitIfDi(dataInput, context);
}
function handleDataOutput(dataOutput, context) {
visitIfDi(dataOutput, context);
}
function handleArtifact(artifact, context) {
// bpmn:TextAnnotation
// bpmn:Group
// bpmn:Association
visitIfDi(artifact, context);
}
function handleArtifacts(artifacts, context) {
_.forEach(artifacts, contextual(handleArtifact, context));
}
function handleIoSpecification(ioSpecification, context) {
if (!ioSpecification) {
return;
}
_.forEach(ioSpecification.dataInputs, contextual(handleDataInput, context));
_.forEach(ioSpecification.dataOutputs, contextual(handleDataOutput, context));
}
function handleSubProcess(subProcess, context) {
handleFlowElementsContainer(subProcess, context);
handleArtifacts(subProcess.artifacts, context);
}
function handleFlowNode(flowNode, context) {
var childCtx = visitIfDi(flowNode, context);
if (is(flowNode, 'bpmn:SubProcess')) {
handleSubProcess(flowNode, childCtx || context);
}
}
function handleSequenceFlow(sequenceFlow, context) {
visitIfDi(sequenceFlow, context);
}
function handleDataElement(dataObject, context) {
visitIfDi(dataObject, context);
}
function handleBoundaryEvent(dataObject, context) {
visitIfDi(dataObject, context);
}
function handleLane(lane, context) {
var newContext = visitIfDi(lane, context);
if (lane.childLaneSet) {
handleLaneSet(lane.childLaneSet, newContext || context);
} else {
var filterList = _.filter(lane.flowNodeRef, function(e) {
return e.$type !== 'bpmn:BoundaryEvent';
});
handleFlowElements(filterList, newContext || context);
}
}
function handleLaneSet(laneSet, context) {
_.forEach(laneSet.lanes, contextual(handleLane, context));
}
function handleLaneSets(laneSets, context) {
_.forEach(laneSets, contextual(handleLaneSet, context));
}
function handleFlowElementsContainer(container, context) {
if (container.laneSets) {
handleLaneSets(container.laneSets, context);
handleNonFlowNodes(container.flowElements);
} else {
handleFlowElements(container.flowElements, context);
}
}
function handleNonFlowNodes(flowElements, context) {
_.forEach(flowElements, function(e) {
if (is(e, 'bpmn:SequenceFlow')) {
deferred.push(function() {
handleSequenceFlow(e, context);
});
} else if (is(e, 'bpmn:BoundaryEvent')) {
deferred.unshift(function() {
handleBoundaryEvent(e, context);
});
} else if (is(e, 'bpmn:DataObject')) {
// SKIP (assume correct referencing via DataObjectReference)
} else if (is(e, 'bpmn:DataStoreReference')) {
handleDataElement(e, context);
} else if (is(e, 'bpmn:DataObjectReference')) {
handleDataElement(e, context);
}
});
}
function handleFlowElements(flowElements, context) {
_.forEach(flowElements, function(e) {
if (is(e, 'bpmn:SequenceFlow')) {
deferred.push(function() {
handleSequenceFlow(e, context);
});
} else if (is(e, 'bpmn:BoundaryEvent')) {
deferred.unshift(function() {
handleBoundaryEvent(e, context);
});
} else if (is(e, 'bpmn:FlowNode')) {
handleFlowNode(e, context);
if (is(e, 'bpmn:Activity')) {
handleIoSpecification(e.ioSpecification, context);
// defer handling of associations
deferred.push(function() {
_.forEach(e.dataInputAssociations, contextual(handleDataAssociation, context));
_.forEach(e.dataOutputAssociations, contextual(handleDataAssociation, context));
});
}
} else if (is(e, 'bpmn:DataObject')) {
// SKIP (assume correct referencing via DataObjectReference)
} else if (is(e, 'bpmn:DataStoreReference')) {
handleDataElement(e, context);
} else if (is(e, 'bpmn:DataObjectReference')) {
handleDataElement(e, context);
} else {
logError(
'unrecognized flowElement <' + e.$type + '> in context ' + (context ? context.id : null),
{ element: e, context: context });
}
});
}
function handleParticipant(participant, context) {
var newCtx = visitIfDi(participant, context);
var process = participant.processRef;
if (process) {
handleProcess(process, newCtx || context);
}
}
function handleCollaboration(collaboration) {
_.forEach(collaboration.participants, contextual(handleParticipant));
handleArtifacts(collaboration.artifacts);
handleMessageFlows(collaboration.messageFlows);
}
///// API ////////////////////////////////
return {
handleDefinitions: handleDefinitions
};
}
//module.exports = BpmnTreeWalker;
//var BpmnTreeWalker = require('./BpmnTreeWalker');
/**
* Import the definitions into a diagram.
*
* Errors and warnings are reported through the specified callback.
*
* @param {Diagram} diagram
* @param {ModdleElement} definitions
* @param {Function} done the callback, invoked with (err, [ warning ]) once the import is done
*/
var importBpmnDiagram = function (definitions) {
var error;
this.participants = [];
this.lanes = [];
this.laneRelPosition = 0;
this.flowsArray = new PMUI.util.ArrayList();
this.headerHeight = 0;
this.eventMarkerMap = {
'CATCH': {
'bpmn:MessageEventDefinition': 'MESSAGECATCH',
'bpmn:TimerEventDefinition': 'TIMER',
'bpmn:ConditionalEventDefinition': 'CONDITIONAL',
'bpmn:LinkEventDefinition': 'LINKCATCH',
'bpmn:SignalEventDefinition': 'SIGNALCATCH',
'bpmn:ErrorEventDefinition': 'ERRORCATCH',
'bpmn:CompensateEventDefinition': 'COMPENSATIONTHROW'
},
'THROW': {
'bpmn:MessageEventDefinition': 'MESSAGETHROW',
'bpmn:TimerEventDefinition': 'TIMER',
'bpmn:ConditionalEventDefinition': 'CONDITIONAL',
'bpmn:CompensateEventDefinition': 'COMPENSATIONTHROW',
'bpmn:SignalEventDefinition': 'SIGNALTHROW',
'bpmn:ErrorEventDefinition': 'ERRORTHROW',
'bpmn:TerminateEventDefinition':'TERMINATETHROW'
}
};
this.taskType = {
'bpmn:Task': 'EMPTY',
'bpmn:SendTask': 'SENDTASK',
'bpmn:ReceiveTask': 'RECEIVETASK',
'bpmn:UserTask': 'USERTASK',
'bpmn:ServiceTask': 'SERVICETASK',
'bpmn:ScriptTask': 'SCRIPTTASK',
'bpmn:ManualTask': 'MANUALTASK',
'bpmn:BusinessRuleTask': 'BUSINESSRULE'
};
this.loopType = {
'bpmn:StandardLoopCharacteristics': 'LOOP',
'bpmn:MultiInstanceLoopCharacteristics':'PARALLEL'
};
this.dataObjectType = {
'bpmn:DataInput': 'datainput',
'bpmn:DataOutput':'dataoutput',
'bpmn:DataObject':'dataobject'
};
//eventBus.fire('import.start');
try {
PMDesigner.businessObject = definitions;
this.checkXML(definitions);
if(PMDesigner.project.XMLSupported){
diRefs = null;
diRefs = new Refs({ name: 'bpmnElement', enumerable: true }, { name: 'di' });
this.parse(definitions);
}
} catch (e) {
error = e;
PMDesigner.project.setXMLSupported(false);
}
};
importBpmnDiagram.prototype.parse = function (definitions) {
var self = this, sidebarCanvas = [], i, visitor;
visitor = {
root: function(element) {
var businessObject = {},
canvas,
project;
if (element.$type === 'bpmn:Collaboration') {
// TODO IF THERE IS COLLABORATIONS
return self.addParticipant(element);
} else {
businessObject.elem = element;
businessObject.di = element.di;
for (i = 0; i < PMDesigner.sidebar.length; i += 1) {
sidebarCanvas = sidebarCanvas.concat(PMDesigner.sidebar[i].getSelectors());
jQuery(".bpmn_shapes").append(PMDesigner.sidebar[i].getHTML());
}
sidebarCanvas.splice(15, 1); //to remove lane selector
//Remove Lasso and Validator
sidebarCanvas.splice(17, 2);
// sidebarCanvas = sidebarCanvas + ',.mafe-event-start';
sidebarCanvas = sidebarCanvas.concat('.pmui-pmevent');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmactivity');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmgateway');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmdata');
sidebarCanvas = sidebarCanvas.concat('.mafe-artifact-annotation');
canvas = PMDesigner.project.buildCanvas(sidebarCanvas, {name: element.$parent.name});
PMUI.setActiveCanvas(canvas);
project = PMUI.getActiveCanvas().project;
project && project.userSettings && project.userSettings.enabled_grid
? canvas.enableGridLine() : canvas.disableGridLine();
jQuery("#p-center-layout").scroll(canvas.onScroll(canvas, jQuery("#p-center-layout")));
PMDesigner.canvasList.setValue(canvas.getID());
element.id = canvas.getID();
canvas.businessObject = businessObject;
}
},
element: function(element, parentShape) {
return self.addElement(element, parentShape);
},
error: function(message, context) {
//warnings.push({ message: message, context: context });
}
};
var walker = new BpmnTreeWalker(visitor);
// import
walker.handleDefinitions(definitions);
};
importBpmnDiagram.prototype.checkXML = function (definitions) {
var self = this,
visitor,
walker;
visitor = {
root: function(element) {
},
element: function(element, parentShape) {
return (self.checkElement(element, parentShape));
},
error: function(message, context) {
console.log('add error');
}
};
var walker = new BpmnTreeWalker(visitor);
// import
walker.handleDefinitions(definitions);
};
/**
* Adds bpmn participants, that arrives from a .bpmn file as a collaboration node
* @param element
* @returns {importBpmnDiagram}
*/
importBpmnDiagram.prototype.addParticipant = function (collaboration) {
var i,
j,
participants,
participant,
sidebarCanvas = [],
canvas,
rootElements,
element,
tempIndex = -1,
isParticipant,
project;
participants = collaboration.participants;
for (j = 0; j < PMDesigner.sidebar.length; j += 1) {
sidebarCanvas = sidebarCanvas.concat(PMDesigner.sidebar[j].getSelectors());
jQuery(".bpmn_shapes").append(PMDesigner.sidebar[j].getHTML());
}
sidebarCanvas.splice(15, 1); //to remove lane selector
//Remove Lasso and Validator
sidebarCanvas.splice(17, 2);
sidebarCanvas = sidebarCanvas.concat('.pmui-pmevent');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmactivity');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmgateway');
sidebarCanvas = sidebarCanvas.concat('.pmui-pmdata');
sidebarCanvas = sidebarCanvas.concat('.mafe-artifact-annotation');
canvas = PMDesigner.project.buildCanvas(sidebarCanvas, {name: collaboration.$parent.name});
PMUI.setActiveCanvas(canvas);
project = PMUI.getActiveCanvas().project;
project && project.userSettings && project.userSettings.enabled_grid
? canvas.enableGridLine() : canvas.disableGridLine();
PMDesigner.canvasList.setValue(canvas.getID());
jQuery("#p-center-layout").scroll(canvas.onScroll(canvas, jQuery("#p-center-layout")));
rootElements = PMDesigner.definitions.rootElements;
for (i = 0; i < participants.length; i += 1) {
participant = participants[i];
isParticipant = true;
for (j = 0; j < rootElements.length; j += 1) {
element = rootElements[j];
if (element.$type === 'bpmn:Process' && participant.processRef && participant.processRef.id !== element.id) {
tempIndex = j;
isParticipant = false;
break;
}
}
if( typeof participant.processRef !== 'undefined') {
this.participants.push(participant);
canvas.businessObject.elem = participant.processRef;
}
if (canvas.businessObject && participant.$parent.di) {
canvas.businessObject.di = participant.$parent.di;
}
canvas.buildingDiagram = true;
}
if (tempIndex > 0 ) {
canvas.businessObject.elem = rootElements[tempIndex];
}
return this;
};
importBpmnDiagram.prototype.getLoopCharacteristics = function (element) {
var loopType;
if(element.loopCharacteristics){
loopType = this.loopType[element.loopCharacteristics.$type] === undefined ? "EMPTY": this.loopType[element.loopCharacteristics.$type];
if(element.loopCharacteristics.isSequential){
loopType = "SEQUENTIAL";
}
}
return loopType;
};
importBpmnDiagram.prototype.getOwnProperties = function (element) {
var ownProp = false,
parent,
taskType,
loopType,
marker,
behavior,
type,
typeMap = {
'bpmn:Lane': 'LANE',
'bpmn:Participant': 'POOL',
'bpmn:StartEvent': 'START',
'bpmn:EndEvent': 'END',
'bpmn:BoundaryEvent': 'BOUNDARY',
'bpmn:Task': 'TASK',
'bpmn:SendTask': 'TASK',
'bpmn:ReceiveTask': 'TASK',
'bpmn:UserTask': 'TASK',
'bpmn:ServiceTask': 'TASK',
'bpmn:ScriptTask': 'TASK',
'bpmn:ManualTask': 'TASK',
'bpmn:CallActivity': 'TASK',
'bpmn:BusinessRuleTask': 'TASK',
'bpmn:SubProcess': 'SUB_PROCESS',
'bpmn:ExclusiveGateway': 'EXCLUSIVE',
'bpmn:ParallelGateway': 'PARALLEL',
'bpmn:InclusiveGateway': 'INCLUSIVE',
//'bpmn:EventBasedGateway': 'EVENTBASED',
'bpmn:IntermediateCatchEvent': 'INTERMEDIATE',
'bpmn:IntermediateThrowEvent': 'INTERMEDIATE',
'bpmn:TextAnnotation': 'TEXT_ANNOTATION',
'bpmn:DataStoreReference': 'DATASTORE',
'bpmn:DataObjectReference': 'DATAOBJECT',
'bpmn:Group': 'GROUP',
'bpmn:DataInput': 'DATAINPUT',
'bpmn:DataOutput': 'DATAOUTPUT'
};
type = typeMap[element.$type];
switch (type) {
case 'START':
if (element.eventDefinitions && element.eventDefinitions[0]) {
marker = this.eventMarkerMap['CATCH'][element.eventDefinitions[0].$type];
}
ownProp = {
'evn_name': element.name,
'evn_marker': marker ? marker : 'EMPTY'
};
break;
case 'END':
if (element.eventDefinitions && element.eventDefinitions[0]) {
marker = this.eventMarkerMap['THROW'][element.eventDefinitions[0].$type];
}
ownProp = {
'evn_name': element.name,
'evn_marker': marker ? marker : 'EMPTY'
};
break;
case 'INTERMEDIATE':
behavior = (element.$type === 'bpmn:IntermediateCatchEvent') ? 'CATCH' : 'THROW';
if (element.eventDefinitions && element.eventDefinitions[0]) {
marker = this.eventMarkerMap[behavior][element.eventDefinitions[0].$type];
}
//marker = this.eventMarkerMap[behavior][element.eventDefinitions[0].$type];
ownProp = {
'evn_behavior': behavior,
'evn_marker': marker ? marker : 'MESSAGECATCH',
'evn_name': element.name
};
break;
case 'BOUNDARY':
if (element.eventDefinitions && element.eventDefinitions[0]) {
marker = this.eventMarkerMap['CATCH'][element.eventDefinitions[0].$type];
}
if(typeof marker !== "undefined" && this.validateElementsForDesigner(element.$type,marker)){
ownProp = {
'evn_behavior': behavior,
'evn_marker': marker ? marker : 'EMPTY',
'evn_name': element.name,
'bou_container': 'bpmnActivity',
'bou_element': element.attachedToRef.id
};
}else{
type = undefined;
}
break;
case 'SUB_PROCESS':
ownProp = {
'act_name': element.name,
'act_type': 'SUB_PROCESS'
};
break;
case 'TASK':
taskType = this.taskType[element.$type];
loopType = this.getLoopCharacteristics(element);
ownProp = {
'act_name': element.name,
'act_task_type': taskType,
'act_loop_type' : loopType
};
break;
case 'EXCLUSIVE':
ownProp = {
'gat_uid': 'pmui-' + PMUI.generateUniqueId(),
'gat_name': element.name,
'gat_type': 'EXCLUSIVE'
};
break;
case 'PARALLEL':
ownProp = {
'gat_uid': 'pmui-' + PMUI.generateUniqueId(),
'gat_name': element.name,
'gat_type': 'PARALLEL'
};
break;
case 'INCLUSIVE':
ownProp = {
'gat_uid': 'pmui-' + PMUI.generateUniqueId(),
'gat_name': element.name,
'gat_type': 'INCLUSIVE'
};
break;
case 'EVENTBASED':
ownProp = {
'gat_uid': 'pmui-' + PMUI.generateUniqueId(),
'gat_name': element.name,
'gat_type': 'EVENTBASED'
};
break;
case 'POOL':
ownProp = {
'par_uid': 'pmui-' + PMUI.generateUniqueId(),
'par_name': element.name
};
if (typeof element.processRef === 'undefined') {
type = 'PARTICIPANT';
}
break;
case 'LANE':
this.lanes.push(element);
parent = this.getParentData(element);
this.laneRelPosition += 1;
ownProp = {
'lan_uid': 'pmui-' + PMUI.generateUniqueId(),
'lan_name': element.name ? element.name : ' ',
'bou_container': 'bpmnPool',
'bou_element': parent.parentUid,
'bou_rel_position': this.laneRelPosition,
'bou_x': 40,
'bou_y': element.di.bounds.y - parent.y
};
break;
case 'GROUP':
case 'TEXT_ANNOTATION':
ownProp = {
'art_uid': 'pmui-' + PMUI.generateUniqueId(),
'art_name': element.text
};
break;
case 'DATASTORE':
case 'DATAOBJECT':
ownProp = {
'dat_uid': 'pmui-' + PMUI.generateUniqueId(),
'dat_name': element.name,
'dat_object_type':this.dataObjectType[element.$type]?this.dataObjectType[element.$type]:'dataobject'
};
break;
case 'DATAINPUT':
ownProp = {
'dat_uid': 'pmui-' + PMUI.generateUniqueId(),
'dat_name': element.name,
'dat_object_type':this.dataObjectType[element.$type]?this.dataObjectType[element.$type]:'dataobject'
};
break;
case 'DATAOUTPUT':
ownProp = {
'dat_uid': 'pmui-' + PMUI.generateUniqueId(),
'dat_name': element.name,
'dat_object_type':this.dataObjectType[element.$type]?this.dataObjectType[element.$type]:'dataobject'
};
break;
}
return {'properties': ownProp, 'type': type};
};
importBpmnDiagram.prototype.checkElement = function (element) {
var validation,
type,
marker,
loop,
parameters;
parameters = {
'bpmn:StartEvent':{
"parallelMultiple":false
}
};
loopTypes= {
'bpmn:StandardLoopCharacteristics':true,
'bpmn:MultiInstanceLoopCharacteristics':true,
'empty':true
};
validation ={
'bpmn:Lane': true,
'bpmn:ChoreographyTask':true,
'bpmn:Participant': true,
'bpmn:Task': true,
'bpmn:SendTask': true,
'bpmn:ReceiveTask': true,
'bpmn:UserTask': true,
'bpmn:ServiceTask': true,
'bpmn:ScriptTask': true,
'bpmn:ManualTask': true,
'bpmn:CallActivity': false,
'bpmn:BusinessRuleTask': true,
'bpmn:SubProcess': true,
'bpmn:AdHocSubProcess':false,
'bpmn:Transaction':false,
'bpmn:ExclusiveGateway': true,
'bpmn:ParallelGateway': true,
'bpmn:InclusiveGateway': true,
'bpmn:EventBasedGateway': false,
//'bpmn:IntermediateCatchEvent': 'INTERMEDIATE',
//'bpmn:IntermediateThrowEvent': 'INTERMEDIATE',
'bpmn:TextAnnotation': true,
'bpmn:DataStoreReference': true,
'bpmn:DataObjectReference': true,
'bpmn:DataInput': true,
'bpmn:DataOutput': true,
'bpmn:Group': true,
'bpmn:SequenceFlow': true,
'bpmn:Association': true,
'bpmn:DataOutputAssociation': true,
'bpmn:DataInputAssociation': true,
'bpmn:MessageFlow': true,
'bpmn:StartEvent':{
'bpmn:MessageEventDefinition': true,
'bpmn:TimerEventDefinition': true,
'bpmn:ConditionalEventDefinition': true,
'bpmn:CompensateEventDefinition': false,
'bpmn:SignalEventDefinition': true,
'bpmn:ErrorEventDefinition': false,
'bpmn:TerminateEventDefinition':false,
'bpmn:MultipleEventDefinition':false,
'bpmn:EscalationEventDefinition':false,
'empty':true
},
'bpmn:EndEvent':{
'bpmn:MessageEventDefinition': true,
'bpmn:TimerEventDefinition': false,
'bpmn:ConditionalEventDefinition': false,
'bpmn:CompensateEventDefinition': false,
'bpmn:SignalEventDefinition': true,
'bpmn:ErrorEventDefinition': true,
'bpmn:TerminateEventDefinition':true,
'bpmn:MultipleEventDefinition':false,
'bpmn:EscalationEventDefinition':false,
'bpmn:CancelEventDefinition':false,
'empty':true
},
'bpmn:IntermediateCatchEvent':{
'bpmn:MessageEventDefinition': true,
'bpmn:TimerEventDefinition': true,
'bpmn:ConditionalEventDefinition': true,
'bpmn:CompensateEventDefinition': false,
'bpmn:SignalEventDefinition': true,
'bpmn:ErrorEventDefinition': false,
'bpmn:TerminateEventDefinition':false,
'bpmn:MultipleEventDefinition':false,
'bpmn:EscalationEventDefinition':false,
'bpmn:LinkEventDefinition':false,
'empty':false
},
'bpmn:IntermediateThrowEvent':{
'bpmn:MessageEventDefinition': true,
'bpmn:TimerEventDefinition': false,
'bpmn:ConditionalEventDefinition': false,
'bpmn:CompensateEventDefinition': false,
'bpmn:SignalEventDefinition': true,
'bpmn:ErrorEventDefinition': false,
'bpmn:TerminateEventDefinition':false,
'bpmn:MultipleEventDefinition':false,
'bpmn:EscalationEventDefinition':false,
'bpmn:LinkEventDefinition':false,
'empty':false
},
'bpmn:BoundaryEvent':{
'bpmn:MessageEventDefinition': false, //true
'bpmn:TimerEventDefinition': false, //true
'bpmn:ConditionalEventDefinition': false, //true
'bpmn:CompensateEventDefinition': false,
'bpmn:SignalEventDefinition': false, //true
'bpmn:ErrorEventDefinition': false, //true
'bpmn:TerminateEventDefinition':false,
'bpmn:MultipleEventDefinition':false,
'bpmn:EscalationEventDefinition':false,
'bpmn:LinkEventDefinition':false,
'empty':false
},
};
type = element.$type;
//for events
if (element.eventDefinitions && element.eventDefinitions[0]) {
marker = element.eventDefinitions[0].$type;
}else{
if(element.$type == 'bpmn:StartEvent' || element.$type == 'bpmn:IntermediateThrowEvent' || element.$type == 'bpmn:IntermediateCatchEvent' || element.$type == 'bpmn:BoundaryEvent')
marker = "empty";
}
//for subprocess
if (element.loopCharacteristics) {
if(!loopTypes[element.loopCharacteristics.$type]){
marker = "unresolved";
}
}
if(marker !== undefined){
if(this.checkParametersOfElement(element)){
if(!validation[type][marker]){
PMDesigner.project.setXMLSupported(false);
}
}else{
PMDesigner.project.setXMLSupported(false);
}
}else{
if(this.checkParametersOfElement(element)){
if(!validation[type]){
PMDesigner.project.setXMLSupported(false);
}
}else{
PMDesigner.project.setXMLSupported(false);
}
}
};
importBpmnDiagram.prototype.checkParametersOfElement= function (element) {
if(element.$type == 'bpmn:StartEvent'){
if(element.isInterrupting == false){
return false;
}
if(element.parallelMultiple == true){
return false;
}
}
if(element.$type == 'bpmn:IntermediateThrowEvent' || element.$type == 'bpmn:IntermediateCatchEvent'){
if(element.isInterrupting == false){
return false;
}
}
if(element.$type == 'bpmn:IntermediateThrowEvent' || element.$type == 'bpmn:IntermediateCatchEvent'){
if(element.isInterrupting == false){
return false;
}
}
if(element.$type == 'bpmn:DataObjectReference'){
if(element.dataObjectRef.isCollection == true){
return false;
}
}
if(element.$type == 'bpmn:DataInput'){
if(element.isCollection == true){
return false;
}
}
if(element.$type == 'bpmn:DataOutput'){
if(element.isCollection == true){
return false;
}
}
return true;
};
/**
* gets parent data
* @param element
* @param parentShape
*/
importBpmnDiagram.prototype.getParentData = function (element) {
var i,
participant,
uid,
canvas = PMUI.getActiveCanvas(),
pool,
currentProcess = element.$parent.$parent;
for (i = 0; i < this.participants.length; i += 1) {
participant = this.participants[i];
if (participant.processRef.id === currentProcess.id) {
uid = participant.id;
break;
}
}
pool = canvas.customShapes.find('id', uid);
return {parentUid: uid, container: pool.extendedType, y: pool.y};
};
importBpmnDiagram.prototype.getContainerShape = function (element) {
var i,
j,
participant,
uid = null,
canvas = PMUI.getActiveCanvas(),
container = null,
refs,
currentProcess = element.$parent;
if (element.$type !== 'bpmn:TextAnnotation'
&& element.$type !== 'bpmn:DataStoreReference') {
for (i = 0; i < this.lanes.length; i += 1) {
refs = this.lanes[i].get('flowNodeRef');
for (j = 0; j < refs.length; j += 1) {
if (refs[j].id === element.id) {
uid = this.lanes[i].id;
break;
}
}
}
if (!uid) {
while (currentProcess.$parent.$parent) {
currentProcess = currentProcess.$parent;
}
for (i = 0; i < this.participants.length; i += 1) {
participant = this.participants[i];
if (typeof participant.processRef !== 'undefined'
&& participant.processRef.id === currentProcess.id) {
uid = participant.id;
break;
}
}
}
container = canvas.customShapes.find('id', uid);
} else {
container = this.getAuxContainer(element);
}
return container;
};
importBpmnDiagram.prototype.getAuxContainer = function (element) {
var container = null,
uid = null,
i,
x,
y,
x1,
y1,
x2,
y2,
participant,
canvas = PMUI.getActiveCanvas();
for (i = 0; i < this.participants.length; i += 1) {
participant = this.participants[i];
//console.log(participant);
x = element.di.bounds.x;
y = element.di.bounds.y;
x1 = participant.di.bounds.x;
x2 = participant.di.bounds.x + participant.di.bounds.width;
y1 = participant.di.bounds.y;
y2 = participant.di.bounds.y + participant.di.bounds.height;
if(x < x2 && x > x1 && y < y2 && y > y1) {
uid = participant.id;
break;
}
}
if (uid) {
container = canvas.customShapes.find('id', uid);
}
return container;
};
/**
* import bpmn elements
* @param element
* @param parentShape
*/
importBpmnDiagram.prototype.addElement = function (element) {
var canvas = PMUI.getActiveCanvas(),
shape,
x,
y,
businessObject = {
elem: element,
di: element.di
},
bounds = element.di.bounds,
container,
bouElement = null,
bouType = "bpmnDiagram",
conectionMap = {
'bpmn:SequenceFlow': 'SEQUENCE',
'bpmn:Association': 'ASSOCIATION',
'bpmn:DataOutputAssociation': 'DATAASSOCIATION',
'bpmn:DataInputAssociation': 'DATAASSOCIATION',
'bpmn:MessageFlow': 'MESSAGE'
},
ownProp;
//if (PMDesigner.businessObject.id
// && PMDesigner.businessObject.id !== 'BPMNProcessmaker'
// && bounds) {
// //bounds.y += this.headerHeight; // to consider header
//}
ownProp = this.getOwnProperties(element);
if (ownProp.properties) {
container = this.getContainerShape(element);
x = bounds.x;
y = bounds.y;
// validate for camunda modeler datastore
if (container) {
bouElement = container.id;
bouType = container.type;
while (container.getType() !== 'PMCanvas') {
x = x - container.getX();
y = y - container.getY();
container = container.parent;
}
}
shape = {
'bou_container': bouType,
'bou_element': bouElement,
'bou_height': bounds.height,
'bou_width': bounds.width,
'bou_x': x,
'bou_y': y
};
$.extend(true, shape, ownProp.properties);
if (element.$type === 'bpmn:Participant') {
if (typeof element.processRef !== 'undefined') {
this.laneRelPosition = 0;
element.processRef.id = 'pmui-' + PMUI.generateUniqueId();
businessObject.elem = element.processRef;
}
}
canvas.loadShape(ownProp.type, shape, false, businessObject);
if (element.$type === 'bpmn:Participant') {
canvas.updatedElement.participantObject = element;
}
element.id = canvas.updatedElement.id;
}
if (conectionMap[element.$type] && !this.flowsArray.find('id', element.id)) {
//here save a connection element because some elements not has ascending order
this.flowsArray.insert(element);
}
};
/**
* That method must complete all shape connections
*/
importBpmnDiagram.prototype.completeImportFlows = function () {
var i,
conn,
state,
dest,
origin,
canvas = PMUI.getActiveCanvas(),
conectionMap = {
'bpmn:SequenceFlow': 'SEQUENCE',
'bpmn:Association': 'ASSOCIATION',
'bpmn:DataOutputAssociation': 'DATAASSOCIATION',
'bpmn:DataInputAssociation': 'DATAASSOCIATION',
'bpmn:MessageFlow': 'MESSAGE'
},
element,
flowArraySize = this.flowsArray.getSize();
for (i = 0; i < flowArraySize; i += 1) {
element = this.flowsArray.get(i);
if (element.$type === 'bpmn:DataInputAssociation') {
//dest = element.targetRef ? element.targetRef.id : element.$parent.id;
dest = element.$parent.id;
origin = element.sourceRef ? element.sourceRef[0].id : element.$parent.id;
} else if (element.$type === 'bpmn:DataOutputAssociation') {
dest = element.targetRef ? element.targetRef.id : element.$parent.id;
origin = element.$parent.id;
}else {
dest = element.targetRef ? element.targetRef.id : element.$parent.id;
origin = element.sourceRef ? element.sourceRef.id : element.$parent.id;
}
state = this.getState(element);
conn = {
flo_uid: 'pmui-' + PMUI.generateUniqueId(),
flo_condition: null,
flo_element_dest: dest,
flo_element_origin: origin,
flo_is_inmediate: "1",
flo_name: element.name || null,
flo_state: state,
flo_type: conectionMap[element.$type],
flo_x1: state[0].x,
flo_y1: state[0].y,
flo_x2: state[state.length - 1].x,
flo_y2: state[state.length - 1].y
};
canvas.loadFlow(conn, false);
canvas.updatedElement = {
id : (canvas.updatedElement && canvas.updatedElement.id) || null,
type : (canvas.updatedElement && canvas.updatedElement.type) || null,
relatedObject : canvas.updatedElement,
relatedElements: []
};
canvas.items.insert(canvas.updatedElement);
element.id = canvas.updatedElement.id;
canvas.updatedElement.relatedObject.businessObject = element;
}
};
/**
* geting all states in xml file
* @param element
*/
importBpmnDiagram.prototype.getState = function (element) {
var state = [],
waypoint = element.di.waypoint,
i;
for (i = 0; i < waypoint.length; i += 1) {
//if (PMDesigner.businessObject.id && PMDesigner.businessObject.id !== 'BPMNProcessmaker') {
// //waypoint[i].y += 80; //to consider header
//}
state.push({x: waypoint[i].x - 1, y: waypoint[i].y});
}
return state;
};
/**
* geting all states in xml file
* @param element
*/
importBpmnDiagram.prototype.validateElementsForDesigner = function (mapType, marker) {
var resp = true,
validation;
validation ={
'bpmn:EndEvent':{
'MESSAGETHROW':true,
'TIMER':false,
'SCALATIONTHROW':false,
'COMPENSATIONTHROW':false,
'SIGNALTHROW':true,
'ERRORTHROW':true,
'TERMINATETHROW':true,
'MULTIPLETHROW':false,
},
'bpmn:IntermediateCatchEvent':{
'MESSAGECATCH': true,
'TIMER': true,
'CONDITIONAL':true,
'LINKCATCH':false,
'SIGNALCATCH':true,
'COMPENSATIONTHROW':false,
'MULTIPLECATCH':false,
'PARALLELCATCH':false
},
'bpmn:IntermediateThrowEvent':{
'MESSAGETHROW':true,
'SIGNALTHROW':true,
'SCALATIONTHROW':false,
'COMPENSATIONTHROW':false,
'LINKTHROW':false
},
'bpmn:BoundaryEvent':{
'MESSAGECATCH': true,
'TIMER': true,
'CONDITIONAL':true,
'LINKCATCH':false,
'SIGNALCATCH':true,
'COMPENSATIONTHROW':false,
'MULTIPLECATCH':false,
'PARALLELCATCH':false,
'ERRORTHROW':true
}
};
if(validation[mapType]){
if(typeof validation[mapType][marker] !== "undefined"){
return validation[mapType][marker];
}
}
return resp;
};
//'use strict';
//
//var _ = require('lodash');
function BpmnFactory(moddle) {
this._model = moddle;
}
BpmnFactory.$inject = [ 'moddle' ];
BpmnFactory.prototype._needsId = function(element) {
return element.$instanceOf('bpmn:RootElement') ||
element.$instanceOf('bpmn:FlowElement') ||
element.$instanceOf('bpmn:Artifact') ||
element.$instanceOf('bpmndi:BPMNShape') ||
element.$instanceOf('bpmndi:BPMNEdge') ||
element.$instanceOf('bpmndi:BPMNDiagram') ||
element.$instanceOf('bpmndi:BPMNPlane');
};
//BpmnFactory.prototype._ensureId = function(element) {
// if (!element.id && this._needsId(element)) {
// //element.id = this._model.ids.next(element);
// element.id = this._model.ids.next(element);
// }
//};
BpmnFactory.prototype.create = function(type, attrs) {
var element = this._model.create(type, attrs || {});
element.id = attrs.id;
//this._ensureId(element);
return element;
};
BpmnFactory.prototype.createDiLabel = function() {
return this.create('bpmndi:BPMNLabel', {
bounds: this.createDiBounds()
});
};
BpmnFactory.prototype.createDiShape = function(semantic, bounds, attrs) {
return this.create('bpmndi:BPMNShape', _.extend({
bpmnElement: semantic,
bounds: this.createDiBounds(bounds)
}, attrs));
};
BpmnFactory.prototype.createDiBounds = function(bounds) {
return this.create('dc:Bounds', bounds);
};
BpmnFactory.prototype.createDiWaypoints = function(waypoints) {
return _.map(waypoints, function(pos) {
return this.createDiWaypoint(pos);
}, this);
};
BpmnFactory.prototype.createDiWaypoint = function(point) {
return this.create('dc:Point', _.pick(point, [ 'x', 'y' ]));
};
BpmnFactory.prototype.createDiEdge = function(semantic, waypoints, attrs) {
return this.create('bpmndi:BPMNEdge', _.extend({
bpmnElement: semantic
}, attrs));
};
//module.exports = BpmnFactory;
var getData2PMUI = function (form) {
if (form) {
var input, field, data2 = {};
for (var i = 0; i < $(form).find(".pmui-field").length; i += 1) {
input = null;
field = null;
field = PMUI.getPMUIObject($(form).find(".pmui-field")[i]);
var value = null;
switch (field.type) {
case "TextField":
value = field.controls[0].html.value;
break;
case "TextAreaField":
value = field.controls[0].html.value;
break;
case "DropDownListField":
value = field.controls[0].html.value;
break;
case "radio":
var dataChekbox = [];
for (var j = 0; j < $(field.html).find("input").length; j += 1) {
if ($(field.html).find("input")[j].selected) {
value = $(field.html).find("input")[j].value;
}
}
break;
case "CheckBoxGroupField":
var dataChekbox = [];
for (var j = 0; j < $(field.html).find("input").length; j += 1) {
if ($(field.html).find("input")[j].checked) {
dataChekbox.push($(field.html).find("input")[j].value);
}
}
value = JSON.stringify(dataChekbox);
break;
case "datetime":
value = field.controls[0].html.value;
break;
case "PasswordField":
value = field.controls[0].html.value;
break;
case "PMCodeMirrorField":
value = field.controls[0].value;
break;
}
data2[field.getName()] = value;
}
}
return data2;
};
var SuggestField = function (settings) {
this.id = settings["id"] || "";
this.label = settings["label"] || null;
this.placeholder = settings["placeholder"] || null;
this.type = "suggest";
this.value = settings["value"] || "";
this.form = settings["form"] || null;
this.required = settings["required"] || null;
this.disabled = settings["disabled"] || false;
this.maxLength = settings["maxLength"] || null;
this.mode = settings["mode"] || "edit";
this.options = settings["options"] || [];
this.containerList = null;
this.width = settings.width || "auto";
this.messageRequired = null;
this.messageRequiredExtended = null;
this.searchLoad = null;
this.helper = settings.helper || null;
this.html = null;
this.responseAjax;
this.data = null;
this.separatingText = settings.separatingText || null;
this.setDynamicLoad(settings.dynamicLoad);
this.dom = {};
this.dom.fieldRequired = null
};
/**
* Disables the field. Notice that when a field is disabled it is not validated and it is not returned when its
* form's getData() method is invoked.
* @chainable
*/
SuggestField.prototype.disable = function () {
this.disabled = true;
this.inputField.prop('disabled', true);
return this;
};
/**
* Enables the field. Notice that when a field is disabled it is not validated and it is not returned when its
* form's getData() method is invoked.
* @chainable
*/
SuggestField.prototype.enable = function () {
this.disabled = false;
this.inputField[0].disabled = false;
return this;
};
SuggestField.prototype.hideRequired = function (){
this.dom.fieldRequired.style.display = 'none';
return this;
};
/**
* Disables the field. Notice that when a field is disabled it is not validated and it is not returned when its
* form's getData() method is invoked.
* @chainable
*/
SuggestField.prototype.disable = function () {
this.disabled = true;
this.inputField[0].disabled = true;
return this;
};
SuggestField.prototype.showRequired = function (){
this.dom.fieldRequired.style.display = 'inline-block';
return this;
};
/**
* Sets if the fields is required or not.
* @param {Boolean} required
* @chainable
*/
SuggestField.prototype.setRequired = function (required) {
this.required = !!required;
if (this.dom.fieldRequired) {
if (this.required) {
this.showRequired();
} else {
this.hideRequired();
}
}
return this;
};
SuggestField.prototype.setDynamicLoad = function (dynamicLoad) {
this.dynamicLoad = !!dynamicLoad ? dynamicLoad : false;
if (this.dynamicLoad.hasOwnProperty("keys")) {
this.setKeys(this.dynamicLoad["keys"]);
}
return this;
};
SuggestField.prototype.setKeys = function (keys) {
var endPoints = [];
this.keys = keys || {};
return this;
};
SuggestField.prototype.createHTML = function () {
this.containerLabel;
this.tooltip;
this.containerLabel = $(document.createElement("div"));
this.containerLabel.css({
width: "23.5%",
display: "inline-block",
float: "left",
"text-align": "left",
"margin-right": "5px",
padding: "6px 30px 6px 10px",
"box-sizing": "border-box",
"color": "rgb(45, 62, 80)",
"font-size": "14px"
});
this.tooltip = $(document.createElement("span"));
this.tooltip[0].className = "pmui-icon pmui-icon-help";
this.tooltip.css({
"vertical-align": "middle",
"right": "52px",
top: "0px",
width: "18px",
height: "18px",
position: "relative",
"z-index": "auto",
"float": "right"
});
this.requiredTag = $(document.createElement("span"));
this.colonTag = $(document.createElement("span"));
this.inputField = $(document.createElement("input"));
if (this.disabled) {
this.disable();
}
this.inputLabel = $(document.createElement("label"));
this.inputLabel[0].textContent = this.label || "unlabel :";
this.requiredTag[0].textContent = "*";
this.requiredTag.css({
color: "red"
});
this.colonTag[0].textContent = ":";
this.containerLabel[0].appendChild(this.inputLabel[0]);
if (this.required) {
this.containerLabel[0].appendChild(this.requiredTag[0]);
this.dom.fieldRequired = this.requiredTag[0];
}
this.containerLabel[0].appendChild(this.colonTag[0]);
this.html = $(document.createElement("div"));
this.html.attr("id", this.id);
this.html.addClass("suggest-field");
this.html.addClass("suggest-field pmui-field");
this.html.append(this.containerLabel[0]);
this.html.append(this.inputField);
if (this.helper) {
this.tooltip[0].setAttribute("title", this.helper);
this.tooltip.tooltip();
this.html.append(this.tooltip);
}
this.inputField[0].placeholder = this.placeholder.translate();
$(this.inputLabel).css({
display: "inline-block",
float: "left"
});
this.containerList = $(document.createElement("ul"));
this.setStyle();
this.atachListener();
this.html.find("input").after(this.containerList);
if (this.dynamicLoad) {
this.searchLoad = $(PMUI.createHTMLElement("span"));
this.searchLoad.addClass("pmui-gridpanel-searchload");
this.searchLoad.css({
"margin-left": "-23px",
"margin-top": "5px"
});
this.html.append(this.searchLoad);
}
return this.html[0];
};
SuggestField.prototype.atachListener = function () {
var value = "", that = this, itemLabel;
this.html.find("input").keyup(function (e) {
value = this.value;
if (value) {
that.hideMessageRequired();
that.hideMessageRequiredExtended();
that.containerList.css({
top: $(e.target).position().top + 18,
"margin-left": $(e.target).position().left - 10
});
that.containerList.show();
if (!that.dynamicLoad) {
that.makeOptions(this.value, 10);
} else {
that.containerList.empty();
that.executeAjax(this.value);
}
} else {
that.containerList.hide();
}
});
$("body").click(function (e) {
that.containerList.hide();
});
return this;
};
SuggestField.prototype.makeOptions = function (val, maxItems) {
var elements = this.options, i, count = 0, that = this, items = [];
this.containerList.empty().css({
"max-width": this.html.find("input").outerWidth()
});
if (!this.dynamicLoad) {
$.grep(elements, function (data, index) {
itemLabel = data.label;
if ((itemLabel.toLowerCase().indexOf(val.toLowerCase()) !== -1) && count < maxItems) {
items.push(data);
}
});
}
this.createItems(items);
return this;
};
SuggestField.prototype.executeAjax = function (criteria) {
var responseAjax, that = this, options = [], endpoints = [], restClient;
this.searchLoad.addClass("load");
for (var i = 0; i < this.keys.endpoints.length; i += 1) {
url = this.keys.endpoints[i]["url"] + "?filter=" + (criteria ? criteria : "") + "&start=0&limit=10";
method = this.keys.endpoints[i]["method"];
endpoints.push({
url: url,
method: method
});
}
restClient = new PMRestClient({
typeRequest: 'post',
multipart: true,
data: {
calls: endpoints
},
functionSuccess: function (xhr, response) {
var responseAjax = [], dataItem, i;
for (i = 0; i < response.length; i += 1) {
if (that.separatingText) {
responseAjax.push(that.separatingText[i]);
}
responseAjax = responseAjax.concat(response[i].response);
}
data = responseAjax;
for (i = 0; i < data.length; i += 1) {
if (typeof data[i] === "object") {
for (var j = 0; j < that.dynamicLoad["data"].length; j += 1) {
if (data[i][that.dynamicLoad["data"][j]["key"]]) {
var showLabel = " ";
for (var k = 0; k < that.dynamicLoad["data"][j]["label"].length; k += 1) {
if (data[i].hasOwnProperty(that.dynamicLoad["data"][j]["label"][k])) {
showLabel = showLabel + data[i][that.dynamicLoad["data"][j]["label"][k]] + " ";
} else {
showLabel = showLabel + that.dynamicLoad["data"][j]["label"][k] + " ";
}
}
dataItem = {
label: showLabel,
value: data[i][that.dynamicLoad["data"][j]["key"]],
data: data[i]
}
options.push(dataItem);
}
}
} else {
dataItem = {
label: data[i],
value: null,
data: null
}
options.push(dataItem);
}
}
that.options = options;
that.createItems(that.options, that.options.length);
that.searchLoad.removeClass("load");
return responseAjax;
}
});
restClient.setBaseEndPoint('');
restClient.executeRestClient();
return this;
};
SuggestField.prototype.createItems = function (items) {
var that = this, i, li, span;
this.containerList.empty();
for (i = 0; i < items.length; i += 1) {
li = document.createElement("li");
li.className = "list-suggest-item";
span = document.createElement("span");
$(span).css({
width: "auto",
display: "block",
paddingLeft: "10px",
paddingTop: "2px",
paddingBottom: "2px",
paddingRight: "2px",
height: "100%"
});
span.innerHTML = items[i].label;
span.setAttribute("data-value", items[i].value);
$(span).data({data: items[i]["data"]});
li.appendChild(span);
if (items[i].value) {
$(li).css({
position: "relative",
display: "block",
"background-color": "#fff",
border: "1px solid #ddd",
"box-sizing": "border-box",
"height": "auto",
"line-height": "20px",
"width": this.inputField.outerWidth()
});
li.onclick = this.onclickItem();
} else {
$(li).css({
position: "relative",
display: "block",
"background-color": "#3397e1",
"color": "white",
"border": "1px solid #ddd",
"box-sizing": "border-box",
"height": "auto",
"line-height": "20px",
"width": this.inputField.outerWidth(),
"text-align": "center",
"cursor": "default",
"text-transform": "uppercase",
"font-weight": "bold"
}).addClass("single-label");
}
this.containerList.append(li);
if (this.containerList.children.length > 4) {
this.containerList.css("height", "200px");
} else {
this.containerList.css("height", "auto");
}
}
this.containerList.show();
return this;
};
SuggestField.prototype.onclickItem = function () {
var that = this;
return function (e) {
var item, text;
item = e.currentTarget;
text = item.textContent;
that.html.find("input").val(text);
that.value = $(item).find("span").data().value;
that.data = $(item).find("span").data().data;
that.containerList.hide();
}
};
SuggestField.prototype.setStyle = function () {
this.html.find("input").css({
left: "0px",
top: "0px",
width: this.width,
height: "30px",
position: "relative",
"z-index": "auto",
"box-sizing": "border-box",
"padding": "2px 10px 2px 10px"
});
this.containerList.css({
position: "absolute",
"z-index": "3",
"border-radius": "5px",
"height": "auto",
"box-shadow": "2px 10px 29px #818181",
cursor: "pointer",
overflow: "scroll",
"padding-right": "0",
"margin-bottom": "20px",
"padding-left": "0",
"max-height": "200px",
"display": "none"
});
return this;
};
SuggestField.prototype.get = function (prototype) {
if (this[prototype]) {
return this[prototype];
} else {
return null;
}
};
SuggestField.prototype.set = function (prototype, value) {
this[prototype] = value;
return this;
};
SuggestField.prototype.showMessageRequired = function () {
if (this.messageRequired == null) {
var messageRequired = $('<span class="pmui-field-message" style="display: block; margin-left: 24%;"><span class="pmui pmui-textlabel" style="left: 0px; top: 0px; width:auto; height: auto; position: relative; z-index: auto;">' + "This field is required.".translate() + '</span></span>');
this.messageRequired = messageRequired;
this.html.find('ul').after(messageRequired);
}
else {
this.messageRequired.show();
}
};
/**
* Prepare the message for the required suggested field
*/
SuggestField.prototype.showMessageRequiredExtended = function () {
if (this.messageRequiredExtended === null) {
var messageRequiredExtended = $('<span class="pmui-field-message" style="display: block; margin-left: 35.2%;"><span class="pmui pmui-textlabel" style="left: 0px; top: 0px; width:auto; height: auto; position: relative; z-index: auto;">' + "This field is required.".translate() + '</span></span>');
this.messageRequiredExtended = messageRequiredExtended;
this.html.find('ul').after(messageRequiredExtended);
} else {
this.messageRequiredExtended.show();
}
this.html.find("input").css({ border: "1px solid white", "border-radius": "2px", outline: "1px solid #ecc3c2" });
};
SuggestField.prototype.hideMessageRequired = function () {
if (this.messageRequired != null) {
this.messageRequired.hide();
}
};
/**
* Hide the message required extended when it is no longer needed
*/
SuggestField.prototype.hideMessageRequiredExtended = function () {
if (this.messageRequiredExtended != null) {
this.messageRequiredExtended.hide();
}
};
SuggestField.prototype.isValid = function () {
if (this.required && this.html.find("input").val() === "") {
return false
}
return true;
};
/**
* Set the style for the input field
*
* @param {string} border
* @param {string} borderRadius
* @param {string} color
* @param {string} outline
*/
SuggestField.prototype.repaint = function (border, borderRadius, color, outline) {
var that = this;
that.html.find("input").css({
border: border,
"border-radius": borderRadius,
color: color,
outline: outline
});
};
var CreateShapeHelper = function (options) {
this.html = null;
CreateShapeHelper.prototype.initObject.call(this, options);
};
CreateShapeHelper.prototype.initObject = function (options) {
var defaults = {
parent: null,
x: 0,
y: 0,
zOrder: 7,
className: ''
};
$.extend(true, defaults, options);
this.setParent(defaults.parent);
this.setPosition(defaults.x, defaults.y);
this.setZOrder(defaults.zOrder);
this.setClasName(defaults.className);
};
CreateShapeHelper.prototype.setClasName = function (name) {
this.className = name;
return this;
};
CreateShapeHelper.prototype.setZOrder = function (zOrder) {
this.zOrder = zOrder;
return this;
};
CreateShapeHelper.prototype.setParent = function (parent) {
this.parent = parent;
return this;
};
CreateShapeHelper.prototype.setPosition = function (x, y) {
this.x = x + 2;
this.y = y + 2;
return this;
};
CreateShapeHelper.prototype.createHTML = function () {
this.html = document.createElement('div');
this.html.id = 'CreateShapeHelper';
this.html.className = this.className;
this.html.style.position = "absolute";
this.html.style.left = this.x + "px";
this.html.style.top = this.y + "px";
this.html.style.height = "30px";
this.html.style.width = "30px";
this.html.style.zIndex = this.zOrder;
return this.html;
};
CreateShapeHelper.prototype.paint = function () {
if (this.html === null) {
this.parent.html.appendChild(this.createHTML());
}
return this;
};
/**
* @class AdamMarker
* Handle Activity Markers
*
* @constructor
* Creates a new instance of the class
* @param {Object} options
*/
var PMVAlidatorMarker = function (options) {
PMMarker.call(this, options);
PMVAlidatorMarker.prototype.initObject.call(this, options);
};
PMVAlidatorMarker.prototype = new PMMarker();
/**
* Defines the object type
* @type {String}
*/
PMVAlidatorMarker.prototype.type = 'PMVAlidatorMarker';
/**
* Initialize the object with the default values
* @param {Object} options
*/
PMVAlidatorMarker.prototype.initObject = function (options) {
var defaults = {
errors: {}
};
$.extend(true, defaults, options);
this.setErrors(defaults.errors);
};
PMVAlidatorMarker.prototype.createHTML = function () {
PMMarker.prototype.createHTML.call(this);
this.html.className = 'PMVAlidatorMarker';
return this.html;
};
PMVAlidatorMarker.prototype.paint = function () {
PMMarker.prototype.paint.call(this);
if (this.styleMarker) {
this.styleMarker.paint();
}
};
PMVAlidatorMarker.prototype.applyZoom = function () {
this.setProperties();
if (this.styleMarker) {
this.styleMarker.applyZoom();
}
return this;
};
PMVAlidatorMarker.prototype.setErrors = function (errors) {
this.errors = errors;
this.errors.style.parent = this;
this.styleMarker = new MarkerItem(this.errors.style);
return this;
};
PMVAlidatorMarker.prototype.show = function () {
if (this.html) {
this.html.style.visibility = 'visible';
}
return this;
};
PMVAlidatorMarker.prototype.hide = function () {
if (this.html) {
this.html.style.visibility = 'hidden';
}
return this;
};
PMVAlidatorMarker.prototype.removeBoxMarker = function () {
if (this.styleMarker) {
this.styleMarker.removeErrorBox();
}
return this;
};
var MarkerItem = function (options) {
PMUI.draw.Shape.call(this, options);
this.markerZoomClassesError = [];
this.markerZoomClassesWarning = [];
this.infoDiv = null;
this.typeMarker = "error";
MarkerItem.prototype.initObject.call(this, options);
};
MarkerItem.prototype = new PMUI.draw.Shape();
MarkerItem.prototype.type = 'MarkerItem';
MarkerItem.prototype.initObject = function (options) {
var defaults = {
width: 14,
height: 14
};
$.extend(true, defaults, options);
this.setParent(defaults.parent)
.setHeight(defaults.height)
.setWidth(defaults.width)
.setMarkerZoomClassesError(defaults.markerZoomClassesError)
.setMarkerZoomClassesWarning(defaults.markerZoomClassesWarning);
};
MarkerItem.prototype.setParent = function (newParent) {
this.parent = newParent;
return this;
};
/**
* Set style icons type Error
* @param classes
* @returns {MarkerItem}
*/
MarkerItem.prototype.setMarkerZoomClassesError = function (classes) {
this.markerZoomClassesError = classes;
return this;
};
/**
* Set style icons type Warning
* @param classes
* @returns {MarkerItem}
*/
MarkerItem.prototype.setMarkerZoomClassesWarning = function (classes) {
this.markerZoomClassesWarning = classes;
return this;
};
/**
* Set the type of Error (error, warning)
* @param type
* @returns {MarkerItem}
*/
MarkerItem.prototype.setTypeMarker = function (type) {
this.typeMarker = type;
if (this.html) {
switch (this.getTypeMarker()) {
case 'warning':
this.html.className = this.markerZoomClassesWarning[this.parent.canvas.getZoomPropertiesIndex()];
break;
default:
this.html.className = this.markerZoomClassesError[this.parent.canvas.getZoomPropertiesIndex()];
}
}
return this;
};
/**
* Get the type error marker.
* @returns {string|*}
*/
MarkerItem.prototype.getTypeMarker = function () {
return this.typeMarker;
};
/**
* Apply zoom styles.
* @returns {MarkerItem}
*/
MarkerItem.prototype.applyZoom = function () {
var newSprite;
this.removeAllClasses();
this.setProperties();
switch (this.getTypeMarker()) {
case 'warning':
newSprite = this.markerZoomClassesWarning[this.parent.canvas.getZoomPropertiesIndex()];
break;
default:
newSprite = this.markerZoomClassesError[this.parent.canvas.getZoomPropertiesIndex()];
}
if (this.html) {
this.html.className = newSprite;
}
this.currentZoomClass = newSprite;
return this;
};
/**
* Create DIV message of errors and events(show and hide).
* @returns {*}
*/
MarkerItem.prototype.createHTML = function () {
var that = this;
PMUI.draw.Shape.prototype.createHTML.call(this);
this.html.id = this.id;
this.setProperties();
this.currentZoomClass = this.html.className;
this.parent.html.appendChild(this.html);
$(this.html).mouseenter(function () {
return that.showErrorBox();
});
$(this.html).mouseout(function () {
return that.removeErrorBox();
});
return this.html;
};
/**
* Create HTML.
*/
MarkerItem.prototype.paint = function () {
if (this.getHTML() === null) {
this.createHTML();
}
};
/**
* Show event to make hover.
* @param item
* @returns {Function}
*/
MarkerItem.prototype.showErrorBox = function () {
var self = this,
i,
h,
error,
shape,
shapeValidator,
leftPixels = 7,
left,
right,
widthContainer,
widthWindow,
freeSpace,
missingSpace,
boxErrors,
numErrorsShape = 0;
// Get parent Item Marker
if (self.getParent()) {
shapeValidator = self.getParent();
if (shapeValidator.getParent()) {
shape = shapeValidator.getParent();
}
}
// Show List Errors
if (shape) {
if ($('.arrow_box')) {
$('.arrow_box').remove();
}
numErrorsShape = shape.getNumErrors();
if (numErrorsShape > 0) {
// Crete Box Container
self.infoDiv = document.createElement("div");
h = document.createElement("ul");
// Add Errors list
for (i = 0; i < numErrorsShape; i += 1) {
error = shape.errors.get(i);
$(h).append('<li>' + error.description + '</li>');
}
self.infoDiv.appendChild(h);
// Add class style arrow_box
self.infoDiv.className = 'arrow_box';
// Set Position of the container of errors
self.infoDiv.style.left = shape.getAbsoluteX() + shape.getZoomWidth() + leftPixels + "px";
self.infoDiv.style.top = shape.getAbsoluteY() + shape.canvas.getY() + "px";
// Add the Container Errors to Body
document.body.appendChild(self.infoDiv);
// Reposition Container of Errors
boxErrors = $('.arrow_box')[0];
if (boxErrors) {
right = boxErrors.getBoundingClientRect().right;
left = boxErrors.getBoundingClientRect().left;
widthContainer = right - left;
widthWindow = $(window).width();
freeSpace = widthWindow - left;
if (freeSpace > 0 && widthContainer > 0) {
missingSpace = freeSpace - widthContainer;
if (missingSpace < 0) {
boxErrors.style.minWidth = freeSpace + "px";
}
}
}
}
}
};
/**
* Remove Error Box
*/
MarkerItem.prototype.removeErrorBox = function () {
var self = this;
if (self.infoDiv) {
$(self.infoDiv).remove();
}
};
/**
* Set Properties MarkerItem
* @returns {MarkerItem}
*/
MarkerItem.prototype.setProperties = function () {
if (this.html) {
this.html.style.position = 'relative';
this.html.style.width = this.width * PMUI.getActiveCanvas().getZoomFactor() + 'px';
this.html.style.height = this.height * PMUI.getActiveCanvas().getZoomFactor() + 'px';
}
return this;
};
/**
* Remove All Clasess MarkerItem
* @returns {MarkerItem}
*/
MarkerItem.prototype.removeAllClasses = function () {
if (this.html) {
this.html.className = '';
}
return this;
};
/**
* RestApi cliento to consume designer end points
* V 0.0.1
* @type {{}|RestApi}
*/
//create the RestApi variable if one does not exist already
var RestApi = RestApi || {};
RestApi = (function () {
var _api;
var _methodsMap = {
"read": "GET",
"update": "PUT",
"create": "POST",
"delete": "DELETE"
};
var _methods = ["read", "update", "create", "delete"];
function RestClient(params) {
var keys = params.keys,
defaults,
serverUrl = (params && params.serverUrl) || "/rest/v10";
//console.log('init RestClient instance');
//TODO restClient
return {
execute: function (params) {
defaults = {
url: HTTP_SERVER_HOSTNAME + "/rest/v10",
method: "GET",
contentType: "application/json",
data: '',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + keys.access_token);
},
success: function () {
},
error: function () {
}
};
_.extend(defaults, params);
defaults.url = defaults.url;
defaults.method = _methodsMap[defaults.method];
defaults.data = defaults.data;
defaults.success = defaults.success;
defaults.error = defaults.error;
$.ajax(defaults);
}
};
};
return {
/**
* Gets an instance of rest api
* @param params
* @returns {PMDesigner.RestApi}
*/
getRestApi: function (params) {
return _api || this.createRestApi(params);
},
/**
* creates a rest api instance
* @param params
* @returns {*}
*/
createRestApi: function (params) {
_api = new RestClient(params);
return _api;
}
};
})();
var FormDesigner = {};
FormDesigner.version = '0.1';
FormDesigner.DEPRECATION_LINK = 'http://wiki.processmaker.com/Deprecated_Features';
FormDesigner.DEPRECATION_TEXT = 'Control Deprecated. Refer to '.translate() + '<a href="'
+ FormDesigner.DEPRECATION_LINK + '" target="_blank">' + FormDesigner.DEPRECATION_LINK + '</a>.';
FormDesigner.extendNamespace = function (path, newClass) {
var current,
pathArray,
extension,
i;
if (arguments.length !== 2) {
throw new Error("FormDesigner.extendNamespace(): method needs 2 arguments");
}
pathArray = path.split('.');
if (pathArray[0] === 'FormDesigner') {
pathArray = pathArray.slice(1);
}
current = FormDesigner;
// 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;
};
FormDesigner.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;
};
FormDesigner.getNextNumber = function (string, type, field, max) {
var a,
i;
if (max === undefined) {
max = 0;
}
for (i in string) {
if (typeof string[i] === "object")
max = FormDesigner.getNextNumber(string[i], type, field, max);
if (typeof string[i] === "string" && string[i] === type && string[field]) {
a = parseInt(string[field].replace(/^\D+/g, ''));
if (a >= max)
max = a;
}
}
return max;
};
FormDesigner.getNextNumberVar = function (jsonData, properties, callback) {
PMDesigner.restApi.execute({
method: "read",
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id + "/process-variables",
success: function (data, textStatus, xhr) {
var i,
num,
max,
nextVar = FormDesigner.getNextNumber(jsonData, properties.type.value, "variable");
max = nextVar;
for (i = 0; i < data.length; i += 1) {
if (data[i].var_name.indexOf(properties.type.value) >= 0 && data[i].var_name) {
num = parseInt(data[i].var_name.replace(/^\D+/g, ''));
if (num >= max) {
max = num;
}
}
}
nextVar = max + 1;
nextVar = nextVar.toString();
nextVar = FormDesigner.leftPad(nextVar, 3, "0");
nextVar = properties.type.value + "Var" + nextVar;
callback(nextVar);
},
error: function (xhr, textStatus, errorThrown) {
}
});
};
FormDesigner.leftPad = function (string, length, fill) {
if (string && typeof string === "string") {
while (string.length < length) {
string = fill + string;
}
}
return string;
};
(function () {
var FormItem = function (options) {
this.render = options.type;
this.variable = options.variable;
this.parent = options.parentObject;
this.onSelect = new Function();
this.onSetProperty = new Function();
if (options.onSelect) {
this.onSelect = options.onSelect;
}
this.onRemove = new Function();
this.disabled = false;
FormItem.prototype.init.call(this);
};
FormItem.prototype.init = function () {
var that = this,
html,
label = "";
switch (this.render) {
case FormDesigner.main.TypesControl.text:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-text'><input type='text' style='width:100%;box-sizing:border-box;'/><div>";
break;
case FormDesigner.main.TypesControl.textarea:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-textarea'><textarea style='width:100%;box-sizing:border-box;height:18px;resize:vertical;padding:0px;'></textarea></div>";
break;
case FormDesigner.main.TypesControl.dropdown:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-dropdown'><select style='width:100%;box-sizing:border-box;'></select></div>";
break;
case FormDesigner.main.TypesControl.checkbox:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-checkbox'><input type='checkbox' value=''></div>";
break;
case FormDesigner.main.TypesControl.checkgroup:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-checkgroup'></div>";
break;
case FormDesigner.main.TypesControl.radio:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-radio'></div>";
break;
case FormDesigner.main.TypesControl.datetime:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-datetime'><span class='fd-gridForm-grid-suggest-placeholder'></span><img src='" + $.imgUrl + "fd-calendar.png' style='float:right;'></img></div>";
break;
case FormDesigner.main.TypesControl.suggest:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-suggest'><span class='fd-gridForm-grid-suggest-placeholder'></span><img src='" + $.imgUrl + "fd-ui-list-box.png' style='float:right;'></img></div>";
break;
case FormDesigner.main.TypesControl.hidden:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-hidden'><img src='" + $.imgUrl + "fd-ui-text-field-hidden.png' style='float:right;'></img></div>";
break;
case FormDesigner.main.TypesControl.title:
html = "<div class='fd-gridForm-grid-title'><span style='white-space:nowrap;'></span></div>";
break;
case FormDesigner.main.TypesControl.subtitle:
html = "<div class='fd-gridForm-grid-subtitle'><span style='white-space:nowrap;'></span></div>";
break;
case FormDesigner.main.TypesControl.annotation:
html = "<div class='fd-gridForm-grid-annotation'><span style='white-space:nowrap;'></span></div>";
break;
case FormDesigner.main.TypesControl.link:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-link'><span style='color:blue;text-decoration:underline;'></span></div>";
break;
case FormDesigner.main.TypesControl.image:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-image'><img src='" + $.imgUrl + "fd-image.png'></img></div>";
break;
case FormDesigner.main.TypesControl.file:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-file'><button>Select file</button><span>No file was selected</span></div>";
break;
case FormDesigner.main.TypesControl.multipleFile:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-file'><button>Select file</button><span>No file was selected</span></div>";
break;
case FormDesigner.main.TypesControl.submit:
html = "<button class='fd-gridForm-grid-submit'></button>";
break;
case FormDesigner.main.TypesControl.button:
html = "<button class='fd-gridForm-grid-button'></button>";
break;
case FormDesigner.main.TypesControl.panel:
html = "<div class='fd-gridForm-grid-panel'>" + "Panel: ".translate() + "<span class='fd-gridForm-grid-panel-placeholder'></span></div>";
break;
case FormDesigner.main.TypesControl.msgPanel:
html = "<div class='fd-gridForm-grid-msgpanel'>" + "The specified subform could not be found in the process.".translate() + "<span class='fd-gridForm-grid-panel-placeholder'></span></div>";
break;
case FormDesigner.main.TypesControl.geomap:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-geomap'><img src='" + $.imgUrl + "fd-map.png'></img></div>";
break;
case FormDesigner.main.TypesControl.qrcode:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-qrcode'><img src='" + $.imgUrl + "fd-qr-code.png'></img></div>";
break;
case FormDesigner.main.TypesControl.signature:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-signature'><img src='" + $.imgUrl + "fd-text_signature.png'></img></div>";
break;
case FormDesigner.main.TypesControl.imagem:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-imagem'><img src='" + $.imgUrl + "fd-image-instagram.png'></img></div>";
break;
case FormDesigner.main.TypesControl.audiom:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-audiom'><img src='" + $.imgUrl + "fd-audio-card.png'></img></div>";
break;
case FormDesigner.main.TypesControl.videom:
label = "<span class='fd-gridForm-field-label'></span>";
html = "<div class='fd-gridForm-grid-videom'><img src='" + $.imgUrl + "fd-video.png'></img></div>";
break;
}
if (label !== "")
label = label + "<span class='fd-gridForm-grid-contentRequired'>*</span>";
this.html = $("<div class='grid-item-field' tabindex='-1'>" + label + html + "</div>");
this.html.data("objectInstance", this);
this.html.on("click", function (e) {
this.focus();
e.stopPropagation();
$.designerSelectElement(this, function () {
if (that.disabled === true) {
return false;
}
that.onRemove();
});
that.onSelect(that.properties, that);
});
this.properties = new FormDesigner.main.Properties(this.render, this.html, that);
this.properties.onClick = function (property) {
var a,
b,
fields,
dialogCreateVariable,
dialog;
if (property === "formula") {
fields = that.parent.getFieldObjects([
FormDesigner.main.TypesControl.text
]);
a = new FormDesigner.main.DialogFormula(null, fields);
a.onSave = function () {
that.properties.set(property, a.editor.getValue());
};
a.editor.setValue(that.properties.get()[property].value);
}
if (property === "variable") {
dialogCreateVariable = new FormDesigner.main.DialogCreateVariable(null, that.render, [], that.properties.get()[property].value);
dialogCreateVariable.onSave = function (variable) {
that.setVariable(variable);
};
dialogCreateVariable.onSelect = function (variable) {
dialogCreateVariable.dialog.dialog("close");
that.setVariable(variable);
};
FormDesigner.getNextNumberVar(that.getData(), that.properties, function (nextVar) {
dialogCreateVariable.setVarName(nextVar);
});
}
if (property === "inputDocument") {
dialog = new FormDesigner.main.DialogInputDocument(null);
dialog.onClick = function (option) {
dialog.dialog.dialog("close").remove();
that.setInputDocument({
size: {
value: option.inp_doc_max_filesize,
disabled: true
},
sizeUnity: {
value: option.inp_doc_max_filesize_unit,
disabled: true
},
extensions: {
value: option.inp_doc_type_file,
disabled: true
},
enableVersioning: {
value: (option.inp_doc_versioning) ? true : false,
disabled: true
},
inp_doc_uid: {
value: option.inp_doc_uid,
disabled: true
},
inputDocument: {
value: option.inp_doc_title,
disabled: false
}
});
};
return false;
}
if (property === "dbConnectionLabel") {
a = new FormDesigner.main.DialogDBConnection(null);
a.onClick = function (option) {
a.dialog.dialog("close").remove();
b = that.properties.set(property, option.label);
b.node.textContent = option.label;
that.properties.set("dbConnection", option.value);
};
}
if (property === "sql") {
a = new FormDesigner.main.DialogSql(null);
a.onSave = function () {
b = that.properties.set(property, a.editor.getValue());
b.node.textContent = a.editor.getValue();
};
a.editor.setValue(that.properties.get()[property].value);
}
if (property === "options") {
a = new FormDesigner.main.DialogOptions(null, that.properties.get()[property].value);
a.onApply = function () {
b = that.properties.set(property, a.getOptions());
b.node.textContent = JSON.stringify(a.getOptions());
};
if (that.properties.dataType.value === "boolean") {
a.setOptionsBoolean();
}
}
if (property === "validate") {
a = new FormDesigner.main.DialogRegularExpression(null, that.properties["dataType"].value);
a.onClick = function (regex) {
a.dialog.dialog("close").remove();
b = that.properties.set("validate", regex.value);
if (b.node)
b.node.value = regex.value;
};
}
if (property === "content") {
var a = new FormDesigner.main.DialogContent();
a.onSave = function () {
that.properties.set(property, a.editor.getValue());
};
a.editor.setValue(that.properties.get()[property].value);
}
if (property === "dataVariable") {
a = new FormDesigner.main.DialogVariable(null, FormDesigner.main.TypesControl.checkgroup);
a.onClick = function (variable) {
a.dialog.dialog("close").remove();
b = that.properties.set("dataVariable", "@@" + variable.var_name);
if (b.node)
b.node.value = variable.var_name;
};
a.load();
}
};
this.properties.onSet = function (prop, value) {
var oValue, oLabel;
that.onSetProperty(prop, value, that);
if (prop === "id") {
that.html.find(".fd-gridForm-grid-panel-placeholder").text(value);
}
if (prop === "label") {
that.html.find(".fd-gridForm-field-label").text(value);
that.html.find(".fd-gridForm-grid-title").find("span").text(value);
that.html.find(".fd-gridForm-grid-subtitle").find("span").text(value);
that.html.find(".fd-gridForm-grid-annotation").find("span").text(value);
that.html.find(".fd-gridForm-grid-submit").text(value);
that.html.find(".fd-gridForm-grid-button").text(value);
}
if (prop === "value") {
that.html.find(".fd-gridForm-grid-link").find("span").text(value);
}
if (prop === "required") {
if (value)
that.html.find(".fd-gridForm-grid-contentRequired").show();
else
that.html.find(".fd-gridForm-grid-contentRequired").hide();
}
if (prop === "options") {
that.html.find(".fd-gridForm-grid-dropdown").find("select").empty();
that.html.find(".fd-gridForm-grid-checkgroup").empty();
that.html.find(".fd-gridForm-grid-radio").empty();
for (var i = 0; i < value.length; i++) {
oValue = $('<div />').text(value[i].value).html();
oLabel = $('<div />').text(value[i].label).html();
that.html.find(".fd-gridForm-grid-dropdown").find("select").append("<option value='" + oValue + "'>" + oLabel + "</option>");
that.html.find(".fd-gridForm-grid-checkgroup").append("<label><input type='checkbox' value='" + oValue + "'><span>" + oLabel + "</span></label>");
that.html.find(".fd-gridForm-grid-radio").append("<label><input type='radio' value='" + oValue + "'><span>" + oLabel + "</span></label>");
}
}
if (prop === "placeholder") {
that.html.find(".fd-gridForm-grid-text").find("input").attr("placeholder", value);
that.html.find(".fd-gridForm-grid-textarea").find("textarea").attr("placeholder", value);
that.html.find(".fd-gridForm-grid-suggest-placeholder").text(value);
}
};
this.properties.onClickClearButton = function (property) {
var b, prop;
if (property === "variable" && that.properties[property].value !== "") {
var a = new FormDesigner.main.DialogConfirmClearVariable();
a.onAccept = function () {
var label = that.properties.label.value;
that.parent.setNextLabel(that.properties);
that.properties.id.node.value = that.properties.id.value;
b = that.properties.set("variable", "");
b.node.textContent = "...";
b = that.properties.set("dataType", "");
b.node.textContent = "";
b = that.properties.set("label", label);
if (b.node)
b.node.value = label;
b = that.properties.set("dbConnectionLabel", "PM Database");
if (b.node)
b.node.textContent = "PM Database";
b = that.properties.set("dbConnection", "workflow");
b = that.properties.set("sql", "");
if (b.node)
b.node.textContent = "...";
b = that.properties.set("options", JSON.parse("[]"));
if (b.node)
b.node.textContent = "[]";
that.properties.size.disabled = false;
b = that.properties.set("size", "1024");
if (b.node) {
b.node.value = "1024";
}
that.properties.sizeUnity.disabled = false;
b = that.properties.set("sizeUnity", "KB");
if (b.node) {
b.node.value = "KB";
}
that.properties.extensions.disabled = false;
b = that.properties.set("extensions", "*");
if (b.node) {
b.node.value = "*";
}
that.properties.set("inp_doc_uid", "");
};
}
if (property === "minDate" || property === "maxDate" || property === "defaultDate") {
b = that.properties.set(property, "");
if (b.node)
b.node.value = "";
}
if (property === "inputDocument") {
that.setInputDocument({
size: {
value: 0,
disabled: false
},
sizeUnity: {
value: 'MB',
disabled: false
},
extensions: {
value: '*',
disabled: false
},
enableVersioning: {
value: false,
disabled: true
},
inp_doc_uid: {
value: '',
disabled: true
},
inputDocument: {
value: '...',
disabled: false
}
});
}
};
this.createDeprecatedIcon();
};
FormItem.prototype.getData = function () {
var data = {}, property, prop = this.properties.get();
for (property in prop) {
data[property] = prop[property].value;
}
if (this.variable) {
data["var_name"] = this.variable["var_name"];
}
return data;
};
FormItem.prototype.setDisabled = function (disabled) {
this.disabled = disabled;
this.properties.setDisabled(disabled);
};
FormItem.prototype.setVariable = function (variable) {
var that = this,
b,
label;
that.variable = variable;
label = this.defaultLabel(variable);
that.properties.set("label", label);
that.properties.set("var_uid", variable.var_uid);
b = that.properties.set("variable", variable.var_name);
if (b.node) {
that.properties.label.node.value = label;
}
if (b.node)
b.node.textContent = variable.var_name;
b = that.properties.set("dataType", variable.var_field_type);
if (b.node)
b.node.textContent = variable.var_field_type;
b = that.properties.set("id", variable.var_name);
if (b.node)
b.node.value = variable.var_name;
b = that.properties.set("name", variable.var_name);
if (b.node)
b.node.value = variable.var_name;
b = that.properties.set("dbConnectionLabel", variable.var_dbconnection_label);
if (b.node)
b.node.textContent = variable.var_dbconnection_label;
that.properties.set("dbConnection", variable.var_dbconnection);
b = that.properties.set("sql", variable.var_sql);
if (b.node)
b.node.textContent = variable.var_sql === "" ? "..." : variable.var_sql;
b = that.properties.set("options", JSON.parse(variable.var_accepted_values));
if (b.node)
b.node.textContent = variable.var_accepted_values;
if (typeof variable.inp_doc_uid === "string" && variable.inp_doc_uid.length > 0) {
$.ajax({
async: false,
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id + "/input-document/" + variable.inp_doc_uid,
method: "GET",
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + PMDesigner.project.keys.access_token);
},
success: function (data) {
that.properties.size.disabled = true;
b = that.properties.set("size", data.inp_doc_max_filesize);
if (b.node) {
b.node.value = data.inp_doc_max_filesize;
}
that.properties.sizeUnity.disabled = true;
b = that.properties.set("sizeUnity", data.inp_doc_max_filesize_unit);
if (b.node) {
b.node.value = data.inp_doc_max_filesize_unit;
}
b = that.properties.set("enableVersioning", data.inp_doc_versioning === 1);
if (b.node) {
b.node.enableVersioning = data.inp_doc_versioning === 1;
}
that.properties.extensions.disabled = true;
b = that.properties.set("extensions", data.inp_doc_type_file);
if (b.node) {
b.node.value = data.inp_doc_type_file;
}
that.properties.set("inp_doc_uid", data.inp_doc_uid);
}
});
}
};
/**
* Set inputDocument properties to a field
* @param params
*/
FormItem.prototype.setInputDocument = function (params) {
var property,
key;
for (key in params) {
property = this.properties.set(key, params[key].value);
switch (key) {
case 'inp_doc_uid':
break;
case 'inputDocument':
if (property.node) {
property.node.textContent = params[key].value;
property.value = (params[key].value === '...') ? '' : params[key].value;
}
break;
case 'enableVersioning':
if (property.node) {
property.node.textContent = (params[key].value) ? 'Yes' : 'No';
}
default:
if (property.node) {
property.node.value = params[key].value;
property.node.disabled = params[key].disabled;
}
break;
}
}
};
/**
* Create deprecation icon.
*/
FormItem.prototype.createDeprecatedIcon = function () {
this.deprecatedIcon = $("<div class='mafe-deprecated-control'></div>");
this.deprecatedIcon.attr('title', "");
this.deprecatedIcon.hide();
this.deprecatedIcon.tooltip({
content: FormDesigner.DEPRECATION_TEXT,
close: function (event, ui) {
ui.tooltip.hover(function () {
$(this).stop(true).fadeTo(400, 1);
}, function () {
$(this).fadeOut("400", function () {
$(this).remove();
});
});
}
});
this.html.prepend(this.deprecatedIcon);
};
/**
* Enable or disable deprecated icon.
* @param {boolean} status
*/
FormItem.prototype.deprecated = function (status) {
if (status === true) {
this.deprecatedIcon.show();
} else {
this.deprecatedIcon.hide();
}
};
/**
* Get a default label from a variable
* @param {object} variable
* @returns {string}
*/
FormItem.prototype.defaultLabel = function (variable) {
var name = variable.var_name,
stringAux,
flagUpper = true,
i = 1;
name = name.replace(/_/g, " ");
if (name === name.toUpperCase()) {
name = name.toLowerCase();
}
stringAux = name.charAt(0).toUpperCase();
while (i < name.length) {
if (name.charAt(i) !== " ") {
if (name.charAt(i) !== name.charAt(i).toUpperCase()) {
stringAux += name.charAt(i);
flagUpper = true;
} else {
if (flagUpper) {
stringAux += " " + name.charAt(i);
} else {
stringAux += name.charAt(i).toLowerCase();
}
flagUpper = false;
}
} else {
i += 1;
stringAux += " " + name.charAt(i).toUpperCase();
}
i += 1;
}
return stringAux;
};
FormDesigner.extendNamespace('FormDesigner.main.FormItem', FormItem);
}());
(function () {
var AreaButtons = function () {
AreaButtons.prototype.init.call(this);
};
AreaButtons.prototype.init = function () {
this.save = $("<div class='fd-designer-button' title='" + "Save".translate() + "'><img src='" + $.imgUrl + "fd-save.png' style='width:24px;height:24px;'/></div>");
$.hoverToolbarButtons(this.save, "fd-save.png", "fd-savew.png");
this.export_ = $("<div class='fd-designer-button' title='" + "Export".translate() + "'><img src='" + $.imgUrl + "fd-export.png' style='width:24px;height:24px;'/></div>");
$.hoverToolbarButtons(this.export_, "fd-export.png", "fd-exportw.png");
this.import_ = $("<div class='fd-designer-button' title='" + "Import".translate() + "'><img src='" + $.imgUrl + "fd-import.png' style='width:24px;height:24px;'/></div>");
$.hoverToolbarButtons(this.import_, "fd-import.png", "fd-importw.png");
this.preview = $("<div class='fd-designer-button' title='" + "Preview".translate() + "'><img src='" + $.imgUrl + "fd-preview.png' style='width:24px;height:24px;'/></div>");
$.hoverToolbarButtons(this.preview, "fd-preview.png", "fd-previeww.png");
this.clear = $("<div class='fd-designer-button' title='" + "Clear".translate() + "'><img src='" + $.imgUrl + "fd-clear.png' style='width:24px;height:24px;'/></div>");
$.hoverToolbarButtons(this.clear, "fd-clear.png", "fd-clearw.png");
this.language = $("<div class='fd-designer-button' title='" + "Language".translate() + "'><img src='" + $.imgUrl + "fd-language.png' style='width:24px;height:24px;'/></div>");
$.hoverToolbarButtons(this.language, "fd-language.png", "fd-languagew.png");
this.close = $("<div class='fd-designer-button' title='" + "Close".translate() + "'><img src='" + $.imgUrl + "fd-close.png' style='width:24px;height:24px;'/></div>");
$.hoverToolbarButtons(this.close, "fd-close.png", "fd-closew.png");
this.body = $("<div style='position:absolute;right:0px;background-color:#3397e1;'></div>");
this.body.append(this.save);
this.body.append(this.export_);
this.body.append(this.import_);
this.body.append(this.preview);
this.body.append(this.clear);
this.body.append(this.language);
this.body.append(this.close);
};
FormDesigner.extendNamespace('FormDesigner.main.AreaButtons', AreaButtons);
}());
(function () {
var AreaToolBox = function () {
AreaToolBox.prototype.init.call(this);
};
AreaToolBox.prototype.init = function () {
var that = this;
this.accordion = $("<div></div>");
this.accordion.accordion({
heightStyle: "content",
collapsible: true,
icons: false,
event: "mousedown"
});
this.body = this.accordion;
};
AreaToolBox.prototype.addItem = function (title, item) {
var name = $("<h3 class='fd-accordion-title' style='margin:0px;'>" + title + "</h3>");
var body = $("<div style='padding:0px;border:none;border-radius:0px;'></div>");
body.append(item.body);
this.accordion.append(name);
this.accordion.append(body);
this.accordion.accordion("refresh");
};
FormDesigner.extendNamespace('FormDesigner.main.AreaToolBox', AreaToolBox);
}());
(function () {
var Properties = function (type, ele, owner) {
this.onGet = new Function();
this.onSet = new Function();
this.onClick = new Function();
this.onClickClearButton = new Function();
this.ele = ele;
this.owner = owner;
this.pf = [];
Properties.prototype.init.call(this, type);
};
Properties.prototype.init = function (type) {
this.type = {label: "type".translate(), value: type, type: "label"};
this.id = {
label: "id".translate(),
value: "",
type: "text",
on: "change",
regExp: new RegExp(__env.pmVariable.regEx.substr(1, __env.pmVariable.regEx.length - 2)),
regExpInv: new RegExp(__env.pmVariable.regEx.substr(1, __env.pmVariable.regEx.length - 2), "gi"),
required: true
};
this.name = {label: "name".translate(), value: "", type: "hidden", labelButton: "...", required: true};
this.description = {label: "description".translate(), value: "", type: "textarea"};
this.placeholder = {label: "placeholder".translate(), value: "", type: "textarea"};
this.colSpan = {
label: "col-span".translate(),
value: "12",
type: "text",
on: "change",
helpButton: "Colspan is used to define the size and number of columns of a selected row. Twelve columns can be defined as maximum. ".translate() + "The column sizes are defined with integer numbers separated by spaces. Any combination of column sizes can be defined but all the columns sizes should add 12. <br>".translate() + "ex:<br>two columns of different sizes: 8 4<br>two columns of the same size: 6 6<br>Three columns of the same size: 4 4 4<br>Three columns of different sizes: 2 8 2<br><br>" + "For a better design we recommend using values above 3.<br>If you need more info please visit <a target='_blank' href='http://getbootstrap.com/css/'>Bootstrap grid system</a>.".translate()
};
this.label = {label: "label".translate(), value: "", type: "text"};
this.tabIndex = {
label: "tab index".translate(),
value: "",
type: "text"
};
this.href = {label: "href".translate(), value: "http://www.processmaker.com/", type: "textarea"};
this.hint = {label: "hint".translate(), value: "", type: "textarea"};
this.ariaLabel = {label: "aria label".translate(), value: "", type: "textarea"};
this.ariaLabelVisible = {label: "aria label visible".translate(), value: true, type: "checkbox"};
this.src = {label: "src".translate(), value: "", type: "text"};
this.shape = {
label: "shape".translate(), value: "", type: "select", items: [
{value: "thumbnail", label: "thumbnail".translate()},
{value: "rounded", label: "rounded".translate()},
{value: "circle", label: "circle".translate()}
]
};
this.alternateText = {label: "alternate text".translate(), value: "", type: "textarea"};
this.comment = {label: "comment".translate(), value: "", type: "text"};
this.required = {label: "required".translate(), value: false, type: "checkbox"};
this.dnd = {label: "drag & drop".translate(), value: false, type: "hidden"};
this.extensions = {label: "file extensions".translate(), value: "*", type: "text"};
this.galleryEnabled = {label: "Enable gallery".translate(), value: true, type: "checkbox"};
this.availableOffline = {label: "Available offline".translate(), value: false, type: "checkbox"};
this.cameraEnabled = {label: "Enable camera".translate(), value: true, type: "checkbox"};
this.size = {label: "max file size".translate(), value: 1024, type: "text"};
this.sizeUnity = {
label: "size unit".translate(), value: "KB", type: "select", items: [
{value: "KB", label: "KB".translate()},
{value: "MB", label: "MB".translate()}
]
};
this.maxFileNumber = {
label: "Max file number".translate(),
value: "0",
type: "text",
regExpNumber: /^\d*$/,
regExpString: /^[@][@%=]+[a-zA-Z\_]{1}\w+$/
};
this.enableVersioning = {
label: "versioning".translate(),
value: false,
type: "label"
};
this.columns = {label: "columns".translate(), value: [], type: "hidden"};
this.data = {label: "data".translate(), value: [], type: "hidden"};
this.dataType = {label: "variable data type".translate(), value: "", type: "label"};
this.value = {label: "value".translate(), value: "", type: "text"};
this.defaultValue = {
label: "default value".translate(),
value: "",
type: "text",
helpButton: "Allows setting a default value manually<br>or variables permitted using prefixes @@, @=, @#".translate()
};
this.textTransform = {
label: "text transform to".translate(), value: "none", type: "select", items: [
{value: "none", label: "none".translate()},
{value: "lower", label: "lowercase".translate()},
{value: "upper", label: "UPPERCASE".translate()},
{value: "capitalizePhrase", label: "Capitalize phrase".translate()},
{value: "titleCase", label: "Title Case".translate()}
]
};
this.validate = {
label: "validate".translate(),
value: "",
type: "textareabutton",
labelButton: "help".translate(),
placeholder: "Use a pattern (to be used in a search).".translate()
};
this.validateMessage = {
label: "validation error message".translate(),
value: "",
type: "textarea",
placeholder: "Error message".translate()
};
this.requiredFieldErrorMessage = {
label: "required field error message".translate(),
value: "",
type: "textarea",
placeholder: "Required field error message".translate()
};
this.maxLength = {label: "max length".translate(), value: 1000, type: "text", regExp: /^[0-9]+$/};
this.formula = {label: "formula".translate(), value: "", type: "button", labelButton: "edit...".translate()};
this.mode = {
label: "display mode".translate(), value: "parent", type: "select", items: [
{value: "parent", label: "parent".translate()},
{value: "edit", label: "edit".translate()},
{value: "view", label: "view".translate()},
{value: "disabled", label: "disabled".translate()}
], helpButton: "" +
"Select the mode of the control:<br>".translate() +
"<ul style='margin:2px 2px 2px -25px;'>".translate() +
"<li>Parent: Inherit the mode from parent.</li>".translate() +
"<li>Edit: Allow user to change the control's value.</li>".translate() +
"<li>View: Allow user to only view the control's value.</li>".translate() +
"<li>Disabled: Control is greyed out, but still displays its value.</li>".translate() +
"</ul>"
};
this.variable = {
label: "variable".translate(),
value: "",
type: "labelbutton",
labelButton: "...",
clearButton: "clear".translate()
};
this.inputDocument = {
label: "Input Document".translate(),
value: "",
type: "labelbutton",
labelButton: "...",
clearButton: "clear".translate()
};
this.var_uid = {label: "var_uid".translate(), value: "", type: "hidden"};
this.protectedValue = {label: "protected value".translate(), value: false, type: "checkbox"};
this.delay = {label: "Delay".translate(), value: 0, type: "text", regExp: /^[0-9]+$/};
this.resultsLimit = {
label: "Results Limit".translate(),
value: 10,
type: "text",
regExpNumber: /^\d*[0-9]\d*$/,
regExpString: /^[@][@%=]+[a-zA-Z\_]{1}\w+$/
};
this.forceSelection = {label: "force selection".translate(), value: false, type: "checkbox"};
this.alt = {label: "title (mouseover)".translate(), value: "", type: "text"};
this.multiple = {label: "multiple".translate(), value: false, type: "hidden"};
this.script = {label: "javascript".translate(), value: "", type: "button", labelButton: "edit...".translate()};
this.layout = {
label: "layout".translate(), value: "responsive", type: "select", items: [
{value: "responsive", label: "responsive".translate()},
{value: "static", label: "static".translate()}
]
};
this.pageSize = {
label: "page size".translate(), value: "0", type: "select", items: [
{value: "0", label: "none".translate()},
{value: "5", label: "5"},
{value: "10", label: "10"},
{value: "20", label: "20"},
{value: "50", label: "50"},
{value: "100", label: "100"},
{value: "200", label: "200"}
]
};
this.addRow = {label: "add row".translate(), value: true, type: "checkbox"};
this.deleteRow = {label: "delete row".translate(), value: true, type: "checkbox"};
this.columnWidth = {label: "column width".translate(), value: "10", type: "text", helpButton: ""};
this.operation = {
label: "function".translate(), value: "", type: "select",
items: [
{value: "", label: "none".translate()},
{value: "sum", label: "sum".translate()},
{value: "avg", label: "average".translate()}
]
};
this.datasource = {
label: "datasource".translate(), value: "database", type: "select",
items: [
{value: "database", label: "database".translate()},
{value: "dataVariable", label: "array variable".translate()}
]
};
this.dbConnectionLabel = {
label: "DB Connection".translate(),
value: "PM Database",
type: "labelbutton",
labelButton: "..."
};
this.dbConnection = {label: "", value: "workflow", type: "hidden"};
this.sql = {label: "sql".translate(), value: "", type: "labelbutton", labelButton: "..."};
this.memoryCache = {label: "Memory cache".translate(), value: false, type: "checkbox"};
this.dataVariable = {
label: "data variable".translate(),
value: "",
type: "hidden",
labelButton: "@@",
placeholder: "@@myData".translate()
};
this.options = {label: "options".translate(), value: [], type: "labelbutton", labelButton: "..."};
this.language = {
label: "language".translate(), value: "en", type: "select", items: [
{value: "en", label: "English".translate()}
]
};
this.content = {label: "content".translate(), value: "", type: "button", labelButton: "edit...".translate()};
this.border = {label: "border".translate(), value: "1px", type: "text"};
this.externalLibs = {label: "external libs".translate(), value: "", type: "textarea"};
this.gridStore = {label: "grid store".translate(), value: false, type: "checkbox"};
this.rows = {label: "rows".translate(), value: "5", type: "text", regExp: /^[0-9]+$/};
this.inp_doc_uid = {label: "", value: "", type: "hidden"};
this.printable = {label: "print dynaform".translate(), value: false, type: "hidden"};
this.format = {
label: "format".translate(),
value: "YYYY-MM-DD",
type: "text",
helpButton: "Default: false".translate() +
"<p>See <a href='http://momentjs.com/docs/#/displaying/format/' target='_blank'>http://momentjs.com/docs/#/displaying/format/</a> ".translate() + "for valid datetime formats. If only the date is included in the format then the time picker will not be displayed.</p>".translate() +
"Examples:".translate() +
"<ul style='margin:2px 2px 2px -25px;'>" +
"<li>dddd, MMMM Do YYYY, h:mm:ss a >> \"Sunday, February 14th 2010, 3:25:50 pm\"</li>".translate() +
"<li>ddd, hA >> \"Sun, 3PM\"</li>".translate() +
"<li>YYYY MM DD >> \"Valid date\"</li>".translate() +
"</ul>" +
"<table border='1' style='border-collapse:collapse;'><tbody>" + "<tr><th></th><th>Token</th><th>Output</th></tr><tr><td><b>Month</b></td><td>M</td><td>1 2 ... 11 12</td></tr>".translate() + "<tr><td></td><td>Mo</td><td>1st 2nd ... 11th 12th</td></tr><tr><td></td><td>MM</td><td>01 02 ... 11 12</td></tr>".translate() + "<tr><td></td><td>MMM</td><td>Jan Feb ... Nov Dec</td></tr><tr><td></td><td>MMMM</td><td>January February ... November December</td></tr>".translate() + "<tr><td><b>Quarter</b></td><td>Q</td><td>1 2 3 4</td></tr><tr><td><b>Day of Month</b></td><td>D</td><td>1 2 ... 30 31</td></tr>".translate() + "<tr><td></td><td>Do</td><td>1st 2nd ... 30th 31st</td></tr><tr><td></td><td>DD</td><td>01 02 ... 30 31</td></tr>".translate() + "<tr><td><b>Day of Year</b></td><td>DDD</td><td>1 2 ... 364 365</td></tr><tr><td></td><td>DDDo</td><td>1st 2nd ... 364th 365th</td></tr>".translate() + "<tr><td></td><td>DDDD</td><td>001 002 ... 364 365</td></tr><tr><td><b>Day of Week</b></td><td>d</td><td>0 1 ... 5 6</td></tr>".translate() + "<tr><td></td><td>do</td><td>0th 1st ... 5th 6th</td></tr><tr><td></td><td>dd</td><td>Su Mo ... Fr Sa</td></tr>".translate() + "<tr><td></td><td>ddd</td><td>Sun Mon ... Fri Sat</td></tr><tr><td></td><td>dddd</td><td>Sunday Monday ... Friday Saturday</td></tr>".translate() + "<tr><td><b>Day of Week (Locale)</b></td><td>e</td><td>0 1 ... 5 6</td></tr><tr><td><b>Day of Week (ISO)</b></td><td>E</td><td>1 2 ... 6 7</td></tr>".translate() + "<tr><td><b>Week of Year</b></td><td>w</td><td>1 2 ... 52 53</td></tr><tr><td></td><td>wo</td><td>1st 2nd ... 52nd 53rd</td></tr>".translate() + "<tr><td></td><td>ww</td><td>01 02 ... 52 53</td></tr><tr><td><b>Week of Year (ISO)</b></td><td>W</td><td>1 2 ... 52 53</td></tr>".translate() + "<tr><td></td><td>Wo</td><td>1st 2nd ... 52nd 53rd</td></tr><tr><td></td><td>WW</td><td>01 02 ... 52 53</td></tr>".translate() + "<tr><td><b>Year</b></td><td>YY</td><td>70 71 ... 29 30</td></tr><tr><td></td><td>YYYY</td><td>1970 1971 ... 2029 2030</td></tr>".translate() + "<tr><td><b>Week Year</b></td><td>gg</td><td>70 71 ... 29 30</td></tr><tr><td></td><td>gggg</td><td>1970 1971 ... 2029 2030</td></tr>".translate() + "<tr><td><b>Week Year (ISO)</b></td><td>GG</td><td>70 71 ... 29 30</td></tr><tr><td></td><td>GGGG</td><td>1970 1971 ... 2029 2030</td></tr>".translate() + "<tr><td><b>AM/PM</b></td><td>A</td><td>AM PM</td></tr><tr><td></td><td>a</td><td>am pm</td></tr>".translate() + "<tr><td><b>Hour</b></td><td>H</td><td>0 1 ... 22 23</td></tr><tr><td></td><td>HH</td><td>00 01 ... 22 23</td></tr>".translate() + "<tr><td></td><td>h</td><td>1 2 ... 11 12</td></tr><tr><td></td><td>hh</td><td>01 02 ... 11 12</td></tr>".translate() + "<tr><td><b>Minute</b></td><td>m</td><td>0 1 ... 58 59</td></tr><tr><td></td><td>mm</td><td>00 01 ... 58 59</td></tr>".translate() + "<tr><td><b>Second</b></td><td>s</td><td>0 1 ... 58 59</td></tr><tr><td></td><td>ss</td><td>00 01 ... 58 59</td></tr>".translate() + "<tr><td><b>Fractional Second</b></td><td>S</td><td>0 1 ... 8 9</td></tr><tr><td></td><td>SS</td><td>0 1 ... 98 99</td></tr>".translate() + "<tr><td></td><td>SSS</td><td>0 1 ... 998 999</td></tr><tr><td><b>Timezone</b></td><td>z or zz</td><td>EST CST ... MST PST<br><b>Note:</b> as of <b>1.6.0</b>, the z/zz format tokens have been deprecated. ".translate() + "<a href=\"https://github.com/moment/moment/issues/162\">Read more about it here.</a></td></tr>".translate() + "<tr><td></td><td>Z</td><td>-07:00 -06:00 ... +06:00 +07:00</td></tr><tr><td></td><td>ZZ</td><td>-0700 -0600 ... +0600 +0700</td></tr>".translate() + "<tr><td><b>Unix Timestamp</b></td><td>X</td><td>1360013296</td></tr><tr><td><b>Unix Millisecond Timestamp</b></td><td>x</td><td>1360013296123</td></tr></tbody></table>".translate(),
helpButtonCss: "fd-tooltip-date-format"
};
this.dayViewHeaderFormat = {label: "day view header format".translate(), value: "MMMM YYYY", type: "hidden"};
this.extraFormats = {label: "extra formats".translate(), value: false, type: "hidden"};
this.stepping = {label: "stepping".translate(), value: 1, type: "hidden"};
this.minDate = {
label: "min date".translate(),
value: "",
type: "datepicker",
helpButton: "Allows date selection after this date<br>(in YYYY-MM-DD HH:MM:SS format)<br>Variables permitted @@, @=<br>(must use the same date format for dependencies)".translate(),
clearButton: "clear".translate(),
regExp: /^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])$|^(@@|@#|@%|@=|@\?|@\$)[a-zA-Z]+[0-9a-zA-Z_]*$|^$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3])$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])$/
};
this.maxDate = {
label: "max date".translate(),
value: "",
type: "datepicker",
helpButton: "Allows date selection before this date<br>(in YYYY-MM-DD HH:MM:SS format)<br>Variables permitted @@, @=<br>(must use the same date format for dependencies)".translate(),
clearButton: "clear".translate(),
regExp: /^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])$|^(@@|@#|@%|@=|@\?|@\$)[a-zA-Z]+[0-9a-zA-Z_]*$|^$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3])$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])$/
};
this.useCurrent = {
label: "initial selection date".translate(),
value: "false",
type: "select",
items: [
{
value: "false",
label: "false".translate()
},
{
value: "true",
label: "true".translate()
},
{
value: "year",
label: "year".translate()
},
{
value: "month",
label: "month".translate()
},
{
value: "day",
label: "day".translate()
},
{
value: "hour",
label: "hour".translate()
},
{
value: "minute",
label: "minute".translate()
}
],
helpButton: "Default: false<br>On show, will set the picker to:<br>".translate() + "false: No default selection <br>true: current date<br>year: the first day of the current year<br>month: the first day of the month<br>day: the current day<br>hour: the current hour without minutes<br>minute: the current minute".translate()
};
this.collapse = {label: "collapse".translate(), value: true, type: "hidden"};
this.locale = {
label: "locale".translate(),
value: "",
type: "hidden",
accepts: "string, moment.local('locale')".translate()
};
this.defaultDate = {
label: "default date".translate(),
value: "",
type: "datepicker",
helpButton: "Set the date picker to this date by default<br>(in YYYY-MM-DD HH:MM:SS format)<br>Variables permitted @@, @=<br>(must use the same date format for dependencies)".translate(),
clearButton: "clear".translate(),
regExp: /^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])$|^(@@|@#|@%|@=|@\?|@\$)[a-zA-Z]+[0-9a-zA-Z_]*$|^$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3])$|^[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])\s(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])$/
};
this.disabledDates = {
label: "disabled dates".translate(),
value: false,
type: "hidden",
accepts: "array of [date, moment, string]".translate()
};
this.enabledDates = {
label: "enabled dates".translate(),
value: false,
type: "hidden",
accepts: "array of [date, moment, string]".translate()
};
this.icons = {
label: "icons".translate(), value: {
time: 'glyphicon glyphicon-time',
date: 'glyphicon glyphicon-calendar',
up: 'glyphicon glyphicon-chevron-up',
down: 'glyphicon glyphicon-chevron-down',
previous: 'glyphicon glyphicon-chevron-left',
next: 'glyphicon glyphicon-chevron-right',
today: 'glyphicon glyphicon-screenshot',
clear: 'glyphicon glyphicon-trash'
}, type: "hidden", accepts: "object with all or some of the parameters above".translate()
};
this.useStrict = {label: "useStrict".translate(), value: false, type: "hidden"};
this.sideBySide = {label: "side by side".translate(), value: false, type: "hidden"};
this.daysOfWeekDisabled = {
label: "days of week disabled".translate(),
value: false,
type: "hidden",
accepts: "array of numbers from 0-6".translate()
};
this.calendarWeeks = {label: "calendar weeks".translate(), value: false, type: "hidden"};
this.viewMode = {
label: "datepicker view mode".translate(),
value: "days",
type: "select",
items: [
{value: "days", label: "days".translate()},
{value: "months", label: "months".translate()},
{value: "years", label: "years".translate()}
],
helpButton: "Select dates by days, months or years by default when the date picker is initially shown.<br>".translate() + "Note: To remove days, months or years from the date picker, use a format which does not have those elements. For example a format of \"MM/YYY\" will not allow the user to select days.".translate()
};
this.toolbarPlacement = {
label: "toolbar placement".translate(),
value: "default",
type: "hidden",
accepts: "'default', 'top', 'bottom'".translate()
};
this.showTodayButton = {label: "show today button".translate(), value: false, type: "hidden"};
this.showClear = {
label: "show clear button".translate(),
value: "false",
type: "select",
items: [
{value: "false", label: "hide".translate()},
{value: "true", label: "show".translate()}
],
helpButton: "Default: false<br>Show the \"Clear\" button in the icon toolbar.<br>".translate() + "Clicking the \"Clear\" button will set the calendar to null.".translate()
};
this.widgetPositioning = {
label: "widget positioning".translate(),
value: {
horizontal: 'auto',
vertical: 'auto'
},
type: "hidden",
accepts: "object with the all or one of the parameters above; horizontal: 'auto', 'left', 'right' or vertical: 'auto', 'top', 'bottom'".translate()
};
this.widgetParent = {
label: "widget parent".translate(),
value: null,
type: "hidden",
accepts: "string or jQuery object".translate()
};
this.keepOpen = {label: "keep open".translate(), value: false, type: "hidden"};
this.fixedLocation = {label: "Fixed location".translate(), value: false, type: "checkbox"};
//custom properties
if (this.owner instanceof FormDesigner.main.GridItem) {
this.variable.type = "hidden";
this.dataType.type = "hidden";
}
if (type === FormDesigner.main.TypesControl.form) {
this.pf = ["type", "variable", "var_uid", "dataType", "id", "name", "description", "mode", "script",
"language", "externalLibs", "printable"];
this.id.type = "label";
this.id.required = false;
this.name.type = "text";
this.name.on = "change";
this.name.regExp = !/^\s+|\s+$/g;
this.language.type = "hidden";
this.variable.type = "hidden";
this.dataType.type = "hidden";
}
if (type === FormDesigner.main.TypesControl.title) {
this.pf = ["type", "id", "label", "ariaLabel"];
this.name.type = "text";
this.label.type = "textarea";
}
if (type === FormDesigner.main.TypesControl.subtitle) {
this.pf = ["type", "id", "label", "ariaLabel"];
this.name.type = "text";
this.label.type = "textarea";
}
if (type === FormDesigner.main.TypesControl.link) {
this.pf = ["type", "id", "name", "label", "tabIndex", "value", "href", "hint", "ariaLabel"];
this.name.type = "text";
this.label.type = "text";
this.value.label = "display text".translate();
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.image) {
this.pf = ["type", "id", "name", "label", "tabIndex", "hint", "ariaLabel", "src", "shape", "alternateText", "comment", "alt"];
this.name.type = "text";
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.file) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex", "hint", "ariaLabel", "ariaLabel",
"required", "requiredFieldErrorMessage", "dnd", "extensions", "size", "sizeUnity", "mode", "multiple",
"inp_doc_uid"];
this.name.type = "text";
this.label.type = "text";
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.multipleFile) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex", "ariaLabel",
"inputDocument", "required", "requiredFieldErrorMessage", "dnd", "extensions", "size", "sizeUnity",
"maxFileNumber", "enableVersioning", "mode", "multiple", "inp_doc_uid"];
this.name.type = "hidden";
this.label.type = "text";
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.submit) {
this.pf = ["type", "id", "name", "label", "tabIndex", "ariaLabel"];
this.name.type = "text";
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.button) {
this.pf = ["type", "id", "name", "label", "tabIndex", "ariaLabel"];
this.name.type = "text";
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.grid) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "hint",
"required", "requiredFieldErrorMessage", "columns", "data", "mode", "layout", "pageSize", "addRow",
"deleteRow"];
this.label.label = "title".translate();
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.subform) {
this.pf = ["type", "id", "name", "description", "mode"];
}
if (type === FormDesigner.main.TypesControl.text) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"defaultValue", "placeholder", "hint", "ariaLabel", "required", "requiredFieldErrorMessage", "textTransform",
"validate", "validateMessage", "maxLength", "formula", "mode", "operation", "dbConnection",
"dbConnectionLabel", "sql", "memoryCache"];
if (this.owner instanceof FormDesigner.main.FormItem) {
this.operation.type = "hidden";
}
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.textarea) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"defaultValue", "placeholder", "hint", "ariaLabel", "required", "requiredFieldErrorMessage", "validate",
"validateMessage", "mode", "dbConnection", "dbConnectionLabel", "sql", "memoryCache", "rows"];
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.dropdown) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"defaultValue", "placeholder", "hint", "ariaLabel", "required", "requiredFieldErrorMessage", "mode", "datasource",
"dbConnection", "dbConnectionLabel", "sql", "memoryCache", "dataVariable", "options"];
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.checkbox) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"defaultValue", "hint", "ariaLabel", "ariaLabelVisible", "required", "requiredFieldErrorMessage", "mode", "options"];
this.defaultValue.type = "checkbox";
this.defaultValue.helpButton = "";
if (this.owner instanceof FormDesigner.main.FormItem) {
this.options.type = "hidden";
}
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.options.type = "hidden";
this.dbConnectionLabel.type = "hidden";
this.dbConnection.type = "hidden";
this.sql.type = "hidden";
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
this.ariaLabelVisible.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.checkgroup) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"defaultValue", "hint", "ariaLabel", "ariaLabelVisible", "required", "requiredFieldErrorMessage", "mode", "datasource", "dbConnection",
"dbConnectionLabel", "sql", "memoryCache", "dataVariable", "options"];
}
if (type === FormDesigner.main.TypesControl.radio) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"defaultValue", "hint", "ariaLabel", "ariaLabel", "ariaLabelVisible", "required", "requiredFieldErrorMessage", "mode", "datasource", "dbConnection",
"dbConnectionLabel", "sql", "memoryCache", "dataVariable", "options"];
}
if (type === FormDesigner.main.TypesControl.datetime) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"placeholder", "hint", "ariaLabel", "required", "requiredFieldErrorMessage", "mode", "format", "dayViewHeaderFormat",
"extraFormats", "stepping", "minDate", "maxDate", "useCurrent", "collapse", "locale", "defaultDate",
"disabledDates", "enabledDates", "icons", "useStrict", "sideBySide", "daysOfWeekDisabled",
"calendarWeeks", "viewMode", "toolbarPlacement", "showTodayButton", "showClear", "widgetPositioning",
"widgetParent", "keepOpen"];
this.type.helpButton = "Date/time picker widget based on twitter bootstrap <br>" +
"<a href='http://eonasdan.github.io/bootstrap-datetimepicker/' target='_blank'>" +
"http://eonasdan.github.io/bootstrap-datetimepicker/</a>".translate();
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.suggest) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "label", "tabIndex",
"defaultValue", "placeholder", "hint", "ariaLabel", "required", "requiredFieldErrorMessage", "mode", "datasource",
"dbConnection", "dbConnectionLabel", "sql", "memoryCache", "dataVariable", "options", "delay", "resultsLimit",
"forceSelection"];
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
this.tabIndex.type = "hidden";
this.ariaLabel.type = "hidden";
}
}
if (type === FormDesigner.main.TypesControl.annotation) {
this.pf = ["type", "id", "label", "ariaLabel"];
this.name.type = "text";
this.label.label = "text".translate();
this.label.type = "textarea";
}
if (type === FormDesigner.main.TypesControl.hidden) {
this.pf = ["type", "variable", "var_uid", "dataType", "protectedValue", "id", "name", "defaultValue",
"dbConnection", "dbConnectionLabel", "sql"];
}
if (type === FormDesigner.main.TypesControl.panel) {
this.pf = ["type", "id", "content", "border"];
}
if (type === FormDesigner.main.TypesControl.msgPanel) {
this.pf = ["type"];
}
if (type === FormDesigner.main.TypesControl.geomap) {
this.pf = ["type", "variable", "var_uid", "protectedValue", "id", "name", "label", "hint", "fixedLocation"];
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.qrcode) {
this.pf = ["type", "variable", "var_uid", "protectedValue", "id", "name", "label", "hint"];
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.signature) {
this.pf = ["type", "id", "name", "label", "hint"];
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.imagem) {
this.pf = ["type", "id", "name", "label", "inputDocument", "hint", "required", "requiredFieldErrorMessage",
"cameraEnabled", "galleryEnabled", "availableOffline", "inp_doc_uid", "mode"];
this.label.type = "text";
if (this.owner instanceof FormDesigner.main.GridItem) {
this.pf.push("columnWidth");
}
}
if (type === FormDesigner.main.TypesControl.audiom) {
this.pf = ["type", "id", "name", "label", "inputDocument", "hint", "required", "requiredFieldErrorMessage",
"inp_doc_uid", "mode"];
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.videom) {
this.pf = ["type", "id", "name", "label", "inputDocument", "hint", "required", "requiredFieldErrorMessage",
"inp_doc_uid", "mode"];
this.label.type = "text";
}
if (type === FormDesigner.main.TypesControl.cell) {
this.pf = ["type", "colSpan"];
}
};
Properties.prototype.set = function (prop, value) {
var that = this;
if (this[prop] === undefined)
return;
this[prop].oldestValue = this[prop].oldValue;
this[prop].oldValue = this[prop].value;
this[prop].value = value;
that.onSet(prop, value);
return this[prop];
};
Properties.prototype.get = function () {
var a = {}, s;
for (var i = 0; i < this.pf.length; i++) {
a[this.pf[i]] = this[this.pf[i]];
}
//stack invalid properties
for (var i in a) {
s = a[i].value;
if (a[i].disabled === false && a[i].regExp && a[i].regExp.test(s) === false) {
$.globalInvalidProperties.push("- Property '" + i + "' in the '" + a.type.value + "' type is invalid.");
break;
}
}
//end stack invalid properties
this.onGet(a);
return a;
};
Properties.prototype.setNode = function (prop, node) {
this[prop].node = node;
};
Properties.prototype.setDisabled = function (disabled) {
var dt = this.get();
for (var i in dt) {
dt[i].disabled = disabled;
}
};
FormDesigner.extendNamespace('FormDesigner.main.Properties', Properties);
}());
(function () {
$.imgUrl = "/lib/img/";
$.icons = $("<div style='position:absolute;margin:0px;top:1px;right:1px;background:white;'>" +
"<img src='" + $.imgUrl + "fd-move2.png' style='width:16px;height:16px;margin-right:2px;cursor:move;' class='formdesigner-move-row'>" +
"<img src='" + $.imgUrl + "fd-close.png' style='width:16px;height:16px;margin-right:0px;cursor:pointer;' class='formdesigner-close-row'>" +
"</div>");
$.elicons = $("<div style='position:absolute;top:1px;margin:0px;right:1px;background:white;width:16px;height:16px;'>" +
"<img src='" + $.imgUrl + "fd-close.png' style='width:16px;height:16px;margin-right:0px;cursor:pointer;' class='formdesigner-close-row'>" +
"</div>");
$.isOpenValidator = false;
$.fmold = null;
$.fmoldparent = null;
$.fmoldborder = null;
$.fmborder = "1px dashed black";
$.designerSelectElement = function (el, fn, fn2) {
$.icons.hide();
$.elicons.hide();
if ($.fmold !== null) {
if ($.fmold.tagName === "TD") {
var tr = $.fmoldparent;
for (var i = 0; i < tr.childNodes.length; i++) {
td = tr.childNodes[i];
td.style.border = $.fmoldborder;
}
} else {
$.fmold.style.border = $.fmoldborder;
}
}
if (el.tagName === "TD") {
$.fmoldborder = el.style.border;
var tr = el.parentNode, td;
for (var i = 0; i < tr.childNodes.length; i++) {
td = tr.childNodes[i];
if (i === 0) {
td.style.borderLeft = $.fmborder;
}
td.style.borderTop = $.fmborder;
td.style.borderBottom = $.fmborder;
}
td = tr.childNodes[i - 1];
td.style.borderRight = $.fmborder;
$.fmold = el;
$.fmoldparent = el.parentNode;
//icons
$(tr.childNodes[tr.childNodes.length - 1].childNodes[0]).append($.icons);
$.icons.show();
$.icons.find(".formdesigner-close-row")[0].onclick = function (e) {
e.stopPropagation();
if (fn2 && fn2() === false) {
return;
}
$(tr).remove();
if (fn) {
fn(tr);
}
};
} else {
$.fmoldborder = el.style.border;
el.style.border = $.fmborder;
$.fmold = el;
//icons
$(el).append($.elicons);
$.elicons.show();
$.elicons.find(".formdesigner-close-row")[0].onclick = function (e) {
if ($.elicons.parent().parent()[0] && $.elicons.parent().parent()[0].tagName === "TD") {
$.elicons.parent().parent().addClass("itemVariables");
$.elicons.parent().parent().addClass("itemControls");
$.elicons.parent().parent().addClass("cellDragDrop");
}
e.stopPropagation();
if (fn && fn() === false) {
return;
}
$(el).remove();
};
}
};
$.globalInvalidProperties = [];
$.changeAllValue = function (string, prop, oldValue, newValue) {
for (var i in string) {
if (typeof string[i] === "object") {
string[i] = $.changeAllValue(string[i], prop, oldValue, newValue);
}
if (typeof string[i] === "string" && i === prop && string[i] === oldValue) {
string[i] = newValue;
}
}
return string;
};
$.countValue = function (string, prop, value, withTrim) {
var n = 0, a, b;
for (var i in string) {
if (typeof string[i] === "object")
n = n + $.countValue(string[i], prop, value, withTrim);
if (typeof string[i] === "string" && i === prop) {
a = string[i];
b = value;
if (withTrim === true) {
a = a.trim();
b = b.trim();
}
if (a === b) {
n = n + 1;
}
}
}
return n;
};
$.getProp = function (string, prop) {
var a = [], b;
for (var i in string) {
if (typeof string[i] === "object") {
b = $.getProp(string[i], prop);
for (var j = 0; j < b.length; j++) {
a.push(b[j]);
}
}
if (typeof string[i] === "string" && i === prop) {
a.push(string[i]);
}
}
return a;
};
$.setAllPropForType = function (string, prop, value, types) {
for (var i in string) {
if (typeof string[i] === "object") {
string[i] = $.setAllPropForType(string[i], prop, value, types);
}
if (typeof string[i] === "string" && i === prop && string["type"] && types.indexOf(string["type"]) >= 0) {
string[i] = value;
}
}
return string;
};
$.hoverToolbarButtons = function (a, img1, img2) {
a.on("mouseout", function () {
a.find("img")[0].src = "" + $.imgUrl + img1;
});
a.on("mouseover", function () {
a.find("img")[0].src = "" + $.imgUrl + img2;
});
};
$.rPadDT = function (str) {
str = str.toString();
return str.length < 2 ? $.rPadDT("0" + str) : str;
};
/**
* Function: validkeys
* Note: valid characteres for file name in http://support.microsoft.com/kb/177506/es
*
* (A-z)letter
* (0-9)number
* ^ Accent circumflex (caret)
* & Ampersand
* ' Apostrophe (single quotation mark)
* @ At sign
* { Brace left
* } Brace right
* [ Bracket opening
* ] Bracket closing
* , Comma
* $ Dollar sign
* = Equal sign
* ! Exclamation point
* - Hyphen
* # Number sign
* ( Parenthesis opening
* ) Parenthesis closing
* % Percent
* . Period
* + Plus
* ~ Tilde
* _ Underscore
*
* Example: only backspace, number and letter.
* $.validkeys(objectHtmlInput, ['isbackspace', 'isnumber', 'isletter']);
*
* Aditional support:
* : Colon
*
* @param {type} object
* @param {type} validates
* @returns {undefined}
*/
$.validkeys = function (object, validates) {
object.onkeypress = function (e) {
var key = document.all ? e.keyCode : e.which;
if (key === 0)
return true;
var isbackspace = key === 8;
var isnumber = key > 47 && key < 58;
var isletter = (key > 96 && key < 123) || (key > 64 && key < 91);
var isaccentcircumflex = key === 94;
var isampersand = key === 41;
var isapostrophe = key === 145;
var isatsign = key === 64;
var isbraceleft = key === 123;
var isbraceright = key === 125;
var isbracketopening = key === 91;
var isbracketclosing = key === 93;
var iscomma = key === 130;
var isdollarsign = key === 36;
var isequalsign = key === 61;
var isexclamationpoint = key === 33;
var ishyphen = key === 45;
var isnumbersign = key === 35;
var isparenthesisopening = key === 40;
var isparenthesisclosing = key === 41;
var ispercent = key === 37;
var isperiod = key === 46;
var isplus = key === 43;
var istilde = key === 126;
var isunderscore = key === 95;
var iscolon = key === 58;
var sw = eval(validates[0]);
for (var i = 1; i < validates.length; i++) {
sw = sw || eval(validates[i]);
}
return sw;
};
};
$.validDataTypeAndControlType = function (dataType, controlType, fn) {
if (controlType === FormDesigner.main.TypesControl.text && (dataType === "string" || dataType === "integer" || dataType === "float")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.textarea && (dataType === "string" || dataType === "integer" || dataType === "float")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.dropdown && (dataType === "string" || dataType === "integer" || dataType === "float")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.checkbox && (dataType === "boolean")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.checkgroup && (dataType === "array")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.radio && (dataType === "string" || dataType === "integer" || dataType === "float" || dataType === "boolean")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.datetime && (dataType === "datetime")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.suggest && (dataType === "string" || dataType === "integer" || dataType === "float")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.hidden && (dataType === "string" || dataType === "integer" || dataType === "float" || dataType === "boolean" || dataType === "datetime")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.grid && (dataType === "grid")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.file && (dataType === "file")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.multipleFile && (dataType === "multiplefile")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.geomap && (dataType === "string")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.qrcode && (dataType === "string")) {
fn();
}
if (controlType === FormDesigner.main.TypesControl.form && (dataType === "grid")) {
fn();
}
};
$.recovered = {data: [], date: ""};
var Designer = function (dynaform) {
this.onHide = new Function();
this.onSave = new Function();
this.dynaform = dynaform;
this.form1 = null;
this._auxForm = null;
//this.form2 = null;
Designer.prototype.init.call(this);
};
Designer.prototype.init = function () {
var that = this,
listControls,
listMobileControls,
listProperties;
this.loadDynaforms();
this.container = $("<div style='position:absolute;top:0;right:0;bottom:0;left:0;z-index:100;'></div>");
this.center = $("<div class='ui-layout-center'></div>");
this.north = $("<div class='ui-layout-north fd-toolbar-designer' style='overflow:hidden;background-color:#3397e1;padding:0px;'></div>");
this.west = $("<div class='ui-layout-west' style='padding:0px;overflow-y:scroll;'></div>");
this.west.on("scroll", function () {
$(document).trigger("pm.fd.scroll");
});
this.container.append(this.center);
this.container.append(this.north);
this.container.append(this.west);
$("body").append(this.container);
var layout = this.container.layout({
north: {
enableCursorHotkey: false,
resizable: false,
spacing_open: 0,
closable: false,
size: 35
},
west: {
enableCursorHotkey: false,
resizable: true,
spacing_open: 1,
spacing_closed: 1,
size: 233
}
});
$(".ui-layout-toggler-west-open").css({"overflow": "visible"}).parent().css({"overflow": "visible"});
$(".ui-layout-toggler-west-open").append("<img id='toggleWest' src='" + $.imgUrl + "fd-toggle.png' style='position:absolute;left:-6px;'/>");
this.center[0].style.width = "";//todo
//new objects
listControls = new FormDesigner.main.ListControls();
listMobileControls = new FormDesigner.main.ListMobileControls();
listProperties = new FormDesigner.main.ListProperties();
this.form1 = new FormDesigner.main.Form();
this.title = $("<div style='float:left;font-family:Montserrat,sans-serif;font-size:20px;color:white;margin:5px;white-space:nowrap;'>Titulo</div>");
this.areaButtons = new FormDesigner.main.AreaButtons();
this.areaToolBox = new FormDesigner.main.AreaToolBox();
this.areaToolBox.addItem("Web controls".translate(), listControls);
if (window.distribution === "1")
this.areaToolBox.addItem("Mobile controls".translate(), listMobileControls);
this.areaToolBox.addItem("Properties".translate(), listProperties);
this.areaTabs = new FormDesigner.main.TabsForm();
this.areaTabs.addItem("Master", this.form1);
this.north.append(this.title);
this.north.append(this.areaButtons.body);
this.west.append(this.areaToolBox.body);
this.center.append(this.areaTabs.body);
//events
var confirmRecovery = false;
this.areaButtons.save[0].onclick = function () {
//save lost dynaforms
if ($.recovered.data.length > 0) {
if (confirmRecovery === false) {
var a = new FormDesigner.main.DialogConfirm(null, "warning", "The form was recovered from a previous version {0}. Possible missing controls are going to be recreated.".translate([$.recovered.date]));
a.onAccept = function () {
confirmRecovery = true;
that.areaButtons.save[0].onclick();
};
a.onCancel = function () {
};
return false;
}
confirmRecovery = false;
var calls = [];
for (var i = 0; i < $.recovered.data.length; i++) {
calls.push({url: "dynaform", method: "POST", data: $.recovered.data[i]});
}
calls.push({url: "dynaforms", method: "GET"});
$.ajax({
async: false,
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id + "/",
data: JSON.stringify({calls: calls}),
method: "POST",
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader('X-Requested-With', 'MULTIPART');
xhr.setRequestHeader("Authorization", "Bearer " + PMDesigner.project.keys.access_token);
},
success: function (responses) {
//synchronize id
var json = that.getData();
for (var i = 0; i < responses.length - 1; i++) {
if (responses[i].status === 201) {
json = $.changeAllValue(json, "id", $.recovered.data[i].dyn_uid_old, responses[i].response.dyn_uid)
}
}
$.recovered.data = [];
//update list dynaforms
if (responses[responses.length - 1].status === 200) {
$.remoteDynaforms = responses[responses.length - 1].response;
}
//update form
var form = that.form1.getData();
var dynaform = {
dyn_content: JSON.stringify(json),
dyn_description: form.description,
dyn_title: form.name,
dyn_type: "xmlform",
dyn_uid: form.id,
dyn_version: 2
};
that.form1.setData(dynaform);
},
error: function (responses) {
}
});
}
//validations
var data = that.getData();
var a = $.getProp(data, "variable");
for (var i = 0; i < a.length; i++) {
if (a[i] !== "" && $.countValue(data, "variable", a[i], true) > 1) {
var b = new FormDesigner.main.DialogInvalid(null, a[i], "duplicated");
b.onAccept = function () {
b.dialog.dialog("close");
};
return false;
}
}
a = $.getProp(data, "id");
for (var i = 0; i < a.length; i++) {
if (a[i] !== "" && $.countValue(data, "id", a[i], true) > 1) {
var b = new FormDesigner.main.DialogInvalid(null, a[i], "duplicated");
b.onAccept = function () {
b.dialog.dialog("close");
};
return false;
}
}
if ($.globalInvalidProperties.length > 0) {
new FormDesigner.main.DialogInvalidProperties();
return false;
}
//save
that.dynaform.dyn_title = data.name;
that.dynaform.dyn_description = data.description;
that.dynaform.dyn_content = JSON.stringify(data);
var restClient = new PMRestClient({
endpoint: 'dynaform/' + that.dynaform.dyn_uid,
typeRequest: 'update',
data: that.dynaform,
functionSuccess: function (xhr, response) {
that.form1.setDirty();
that.onSave();
},
functionFailure: function (xhr, response) {
PMDesigner.msgWinError(response.error.message);
},
messageError: 'There are problems creating the DynaForm, please try again.'.translate(),
messageSuccess: 'DynaForm saved successfully'.translate(),
flashContainer: ''
});
restClient.executeRestClient();
return false;
};
this.areaButtons.export_[0].onclick = function () {
var jsondata = that.getData(),
i,
variables,
size= (typeof jsondata['items'] !== 'undefined') ? jsondata['items'].length : 0; // validation for undefined issues
for (i = 0; i < size; i += 1) {
variables = jsondata['items'][i]['variables'];
variables.forEach(function(v){ delete v.create });
};
var name = (that.form1.properties.name.value ? that.form1.properties.name.value : 'untitle') + '.json';
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(new Blob([JSON.stringify(jsondata)], {'type': 'application/octet-stream'}), name);
return false;
}
var a = document.createElement('a');
document.body.appendChild(a);
a.href = window.URL.createObjectURL(new Blob([JSON.stringify(jsondata)], {'type': 'application/octet-stream'}));
a.download = name;
a.click();
document.body.removeChild(a);
delete a;
return false;
};
this.areaButtons.import_[0].onclick = function () {
var actionImport = function () {
var form = that._getAuxForm();
var input = document.createElement("input");
input.type = "file";
form.appendChild(input);
form.style.display = "none";
document.body.appendChild(form);
input.onchange = function () {
var file = input.files[0];
if (file.name.indexOf(".json") < 0) {
new FormDesigner.main.DialogInvalidFile(null, file.name);
return;
}
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (e) {
listProperties.clear();
var dynaform = that.form1.getData();
that.form1.setData({
dyn_content: e.target.result,
dyn_description: dynaform.description,
dyn_title: dynaform.name,
dyn_type: "xmlform",
dyn_uid: dynaform.id,
dyn_version: 2
});
//patch to clear _items because is duplicating the items
that.form1._items.clear();
that.form1.synchronizeVariables();
};
reader.onerror = function (evt) {
};
//IE8 implementation
//var filePath = f:\oo.txt;
//var fso = new ActiveXObject("Scripting.FileSystemObject");
//var textStream = fso.OpenTextFile(filePath);
//var fileData = file.ReadAll();
};
input.click();
};
if (that.form1.getData().items.length > 0) {
var a = new FormDesigner.main.DialogConfirmImport();
a.onAccept = actionImport;
} else {
actionImport();
}
return false;
};
this.areaButtons.preview[0].onclick = function () {
that.onSave = function () {
$(that.container).hide();
var preview = new FormDesigner.main.Preview(this.dynaform.dyn_uid, this.dynaform.dyn_title, PMDesigner.project.id);
preview.show();
preview.setData();
preview.onClose = function () {
that.show();
};
that.onSave = new Function();
};
that.areaButtons.save[0].onclick();
return false;
};
this.areaButtons.clear[0].onclick = function () {
if (that.form1.getData().items.length > 0) {
var a = new FormDesigner.main.DialogConfirmClear();
a.onAccept = function () {
that.form1.clear();
that.form1.clearItemsDeprecated();
if (!that.form1.checkForDeprecatedControls()) {
that.form1.hideDeprecationMessage();
}
listProperties.clear();
};
}
return false;
};
this.areaButtons.language[0].onclick = function () {
that.onSave = function () {
var a = new FormDesigner.main.DialogLanguage(null, that.dynaform.dyn_uid);
a.onLoad = function (response) {
that.form1.setLanguages();
};
that.onSave = new Function();
};
that.areaButtons.save[0].onclick();
return false;
};
this.areaButtons.close[0].onclick = function () {
if (that.form1.isDirty()) {
var a = new FormDesigner.main.DialogConfirmClose();
a.onAccept = function () {
that.hide();
};
} else {
that.hide();
}
return false;
};
this.form1.onSelect = function (properties) {
listProperties.body.find('input').focus();
listProperties.clear();
listProperties.load(properties);
that.areaToolBox.accordion.accordion("option", "active", (window.distribution === "1") ? 2 : 1);
//initial form only
if (that.form1 === properties.owner && properties.type.value === FormDesigner.main.TypesControl.form) {
$.elicons.hide();
}
};
this.form1.onRemove = function () {
return false;
};
this.form1.onRemoveItem = function (formItem) {
if (formItem) {
if (arguments.length > 1) {
formItem.parent._items.remove(formItem);
}
that.form1._items.remove(formItem);
}
if (!that.form1.checkForDeprecatedControls()) {
that.form1.hideDeprecationMessage();
}
listProperties.clear();
};
this.form1.onRemoveCell = function () {
listProperties.clear();
};
this.form1.onDrawControl = function (properties) {
if (properties) {
that.form1.setNextLabel(properties);
}
if (properties && properties.get().variable && properties.get().variable.type === "labelbutton") {
that.form1.setNextVar(properties);
}
};
this.form1.onDrawDroppedItem = function (render, target) {
var i,
controls = listControls.controls.concat(listMobileControls.controls);
if (Array.isArray(controls)) {
for (i = 0; i < controls.length; i++) {
if (controls[i].render === render &&
controls[i].deprecated === true) {
if (typeof target.deprecated === "function") {
target.deprecated(true);
if (arguments.length > 2) {
target.parent._items.insert(target);
// TODO forced way if a form has three levels, Will not work with fourth levels
if (target.parent.parent.parent) {
target.parent.parent._items.insert(target);
}
}
that.form1._items.insert(target);
}
that.form1.showDeprecationMessage();
}
}
}
};
this.form1.onSetProperty = function (prop, value, target) {
var dialogMessage,
object,
oldValue,
required,
duplicated,
regExp,
type,
existRegExp,
messageDialog,
messageMaxFile = 'Invalid Configuration: the "Max File number" value should be integer.'.translate(),
showMessage = false,
dateLimit,
regExp,
validateValue;
switch (prop) {
case "name":
if (target.properties[prop].node && target instanceof FormDesigner.main.Form) {
if (target === that.form1) {
that.title.text(value).attr("title", value);
}
if (value === "" || !value.replace(/\s/g, '').length) {
dialogMessage = new FormDesigner.main.DialogInvalid(null, prop, "required");
dialogMessage.onClose = function () {
oldValue = target.properties[prop].oldValue;
object = target.properties.set(prop, oldValue);
if (object.node) {
object.node.value = oldValue;
}
};
dialogMessage.onAccept = function () {
dialogMessage.dialog.dialog("close");
};
}
}
break;
case "id":
if (target.properties[prop].node) {
if ($.isOpenValidator === false) {
required = value === "";
duplicated = $.countValue(that.getData(), prop, value, true) > 1;
regExp = target.properties[prop].regExp && target.properties[prop].regExp.test(target.properties[prop].value) === false;
type = required ? "required" : duplicated ? "duplicated" : regExp ? "invalid" : "";
if (type !== "") {
dialogMessage = new FormDesigner.main.DialogInvalid(null, prop, type);
dialogMessage.onClose = function () {
existRegExp = target.properties[prop].regExp && target.properties[prop].regExpInv;
oldValue = target.properties[prop].oldValue;
if (existRegExp && target.properties[prop].regExp.test(oldValue) === false) {
oldValue = oldValue.replace(target.properties[prop].regExpInv, "");
}
object = target.properties.set(prop, oldValue);
if (object.node) {
object.node.value = oldValue;
}
};
dialogMessage.onAccept = function () {
dialogMessage.dialog.dialog("close");
};
}
}
if (target instanceof FormDesigner.main.GridItem) {
target.properties["name"].value = value;
}
}
break;
case "maxLength":
if (target.properties[prop].node) {
if (value === "") {
dialogMessage = new FormDesigner.main.DialogInvalid(null, prop, "required");
dialogMessage.onClose = function () {
oldValue = target.properties[prop].oldValue;
object = target.properties.set(prop, oldValue);
if (object.node) {
object.node.value = oldValue;
}
};
dialogMessage.onAccept = function () {
dialogMessage.dialog.dialog("close");
};
}
}
break;
case "variable":
if (target.properties[prop].node && value !== "" && $.countValue(that.getData(), prop, value) > 1) {
$.isOpenValidator = true;
dialogMessage = new FormDesigner.main.DialogInvalid(null, prop, "duplicated");
dialogMessage.onClose = function () {
$.isOpenValidator = false;
oldValue = target.properties[prop].oldValue;
object = target.properties.set(prop, oldValue);
if (object.node) {
object.node.textContent = oldValue === "" ? "..." : oldValue;
}
oldValue = target.properties["dataType"].oldValue;
object = target.properties.set("dataType", oldValue);
if (object.node) {
object.node.textContent = oldValue;
}
oldValue = target.properties["name"].oldValue;
target.properties.set("name", oldValue);
oldValue = target.properties["dbConnectionLabel"].oldValue;
object = target.properties.set("dbConnectionLabel", oldValue);
if (object.node) {
object.node.textContent = oldValue;
}
oldValue = target.properties["dbConnection"].oldValue;
target.properties.set("dbConnection", oldValue);
oldValue = target.properties["sql"].oldValue;
object = target.properties.set("sql", oldValue);
if (object.node) {
object.node.textContent = oldValue === "" ? "..." : oldValue;
}
oldValue = target.properties["options"].oldValue;
object = target.properties.set("options", oldValue);
if (object.node) {
object.node.textContent = JSON.stringify(oldValue);
}
oldValue = target.properties["id"].oldValue;
object = target.properties.set("id", oldValue);
if (object.node) {
object.node.value = oldValue;
}
};
dialogMessage.onAccept = function () {
dialogMessage.dialog.dialog("close");
};
}
if (target.properties.type.value === FormDesigner.main.TypesControl.checkbox) {
target.properties.options.type = value === "" ? "hidden" : "labelbutton";
if (target.properties[prop].node) {
listProperties.clear();
listProperties.load(target.properties);
}
}
break;
case "gridStore":
if (target.properties.type.value === FormDesigner.main.TypesControl.form) {
if (target.properties.gridStore.value === false) {
target.properties.variable.value = "";
target.properties.dataType.value = "";
target.properties.protectedValue.value = false;
}
target.properties.variable.type = target.properties.gridStore.value ? "labelbutton" : "hidden";
target.properties.dataType.type = target.properties.gridStore.value ? "label" : "hidden";
target.properties.protectedValue.type = target.properties.gridStore.value ? "checkbox" : "hidden";
if (target.properties[prop].node) {
listProperties.clear();
listProperties.load(target.properties);
}
}
break;
case "datasource":
if (value === "database") {
target.properties.dbConnectionLabel.type = "labelbutton";
target.properties.sql.type = "labelbutton";
target.properties.dataVariable.type = "hidden";
}
if (value === "dataVariable") {
target.properties.dbConnectionLabel.type = "hidden";
target.properties.sql.type = "hidden";
target.properties.dataVariable.type = "textbutton";
}
if (target.properties[prop].node) {
target.properties.dbConnectionLabel.value = "PM Database";
target.properties.dbConnection.value = "workflow";
target.properties.sql.value = "";
target.properties.dataVariable.value = "";
listProperties.clear();
listProperties.load(target.properties);
}
break;
case "inp_doc_uid":
if (target.properties.type.value === FormDesigner.main.TypesControl.file) {
if (target.properties.inp_doc_uid.value !== "") {
target.properties.size.disabled = true;
target.properties.sizeUnity.disabled = true;
target.properties.extensions.disabled = true;
}
if (target.properties.variable.node) {
listProperties.clear();
listProperties.load(target.properties);
}
}
break;
case "useRelative":
if (target.properties.type.value === FormDesigner.main.TypesControl.datetime) {
target.properties.minDate.disabled = value;
target.properties.maxDate.disabled = value;
target.properties.relativeMinDate.disabled = !value;
target.properties.relativeMaxDate.disabled = !value;
if (target.properties[prop].node) {
listProperties.clear();
listProperties.load(target.properties);
}
}
break;
case "defaultDate":
if (target.properties.type.value === FormDesigner.main.TypesControl.datetime) {
if (target.properties[prop].node) {
if (target.properties.type.value === FormDesigner.main.TypesControl.datetime) {
if (value === "today") {
target.properties.defaultDate.disabledTodayOption = true;
listProperties.clear();
listProperties.load(target.properties);
} else if (value === "") {
target.properties.defaultDate.disabledTodayOption = false;
listProperties.clear();
listProperties.load(target.properties);
} else {
dateLimit = that.thereIsDefaultDateLimit(
target.properties.minDate.value,
target.properties.maxDate.value,
target.properties.defaultDate.value
);
if (dateLimit) {
dialogMessage = new FormDesigner.main.DialogMessage(null, "success", "Default date is out of range.".translate());
dialogMessage.onClose = function () {
target.properties.set("defaultDate", dateLimit);
target.properties.defaultDate.node.value = dateLimit;
};
}
}
}
}
}
break;
case "maxDate":
if (target.properties[prop].node) {
if (target.properties.type.value === FormDesigner.main.TypesControl.datetime) {
dateLimit = that.thereIsMaxDateLimit(
target.properties.minDate.value,
target.properties.maxDate.value,
target.properties.defaultDate.value
);
if (dateLimit) {
dialogMessage = new FormDesigner.main.DialogMessage(null, "success", "Max date must be greater than the min and default date".translate());
dialogMessage.onClose = function () {
target.properties.set("maxDate", dateLimit);
target.properties.maxDate.node.value = dateLimit;
};
}
}
}
break;
case "minDate":
if (target.properties[prop].node) {
if (target.properties.type.value === FormDesigner.main.TypesControl.datetime) {
dateLimit = that.thereIsMinDateLimit(
target.properties.minDate.value,
target.properties.maxDate.value,
target.properties.defaultDate.value
);
if (dateLimit) {
dialogMessage = new FormDesigner.main.DialogMessage(null, "success", "Min date must be lesser than the max and default date.".translate());
dialogMessage.onClose = function () {
target.properties.set("minDate", dateLimit);
target.properties.minDate.node.value = dateLimit;
};
}
}
}
break;
case "required":
if (target.properties["requiredFieldErrorMessage"].node) {
target.properties.requiredFieldErrorMessage.node.disabled = !value;
}
break;
case "resultsLimit":
validateValue = !isNaN(parseInt(value)) ? target.properties[prop].regExpNumber.test(value) :
target.properties[prop].regExpString.test(value);
if (!validateValue) {
messageDialog = 'The value provided for the Results limit property of the field "'.translate() + target.properties.id.value + '" is invalid'.translate();
dialogMessage = new FormDesigner.main.DialogMessage(null, 'success', messageDialog);
dialogMessage.onClose = function () {
oldValue = target.properties[prop].oldValue;
object = target.properties.set(prop, oldValue);
if (object.node) {
object.node.value = oldValue;
}
};
dialogMessage.onAccept = function () {
dialogMessage.dialog.dialog("close");
};
} else {
target.properties[prop].value = value;
}
break;
case "size":
case "sizeUnity":
//the "maxFileSizeInformation" variable, comes from backend.
that.validateMaxFileSize(
target,
maxFileSizeInformation,
function (target, message) {
var dialogMessage,
value,
oldValue;
value = target.properties[prop].value;
oldValue = target.properties[prop].oldValue;
if (target.properties[prop].node && value !== oldValue) {
dialogMessage = new FormDesigner.main.DialogMessage(null, "alert", message);
dialogMessage.onClose = function () {
that.setMinimalFileSize(target, maxFileSizeInformation);
};
}
}
);
break;
case "tabIndex":
regExp = /^-{0,1}\d+$/;
validateValue = (!isNaN(parseInt(value)) && Number.isInteger(parseInt(value)) && regExp.test(value)) || value === "";
if (this.dirty === null && !validateValue) { // First Time set tab index
validateValue = true;
value = "";
}
if (!validateValue) {
messageDialog = 'The value provided for the tab index property of the field "{0}" is invalid'.translate([target.properties.id.value]);
dialogMessage = new FormDesigner.main.DialogInvalid(null, prop, "invalid");
dialogMessage.onClose = function () {
oldValue = target.properties[prop].oldValue;
if(!(!isNaN(parseInt(oldValue)) && Number.isInteger(parseInt(oldValue)) && regExp.test(oldValue)) || oldValue === ""){
oldValue = "";
}
object = target.properties.set(prop, oldValue);
if (object.node) {
object.node.value = oldValue;
}
};
dialogMessage.onAccept = function () {
dialogMessage.dialog.dialog("close");
};
} else {
target.properties[prop].value = value;
}
break;
case "maxFileNumber":
if (!target.properties[prop].regExpNumber.test(value)) {
showMessage = (target.variable && target.variable.var_field_type === "grid") || target instanceof FormDesigner.main.GridItem? true : !target.properties[prop].regExpString.test(value);
}
if (showMessage || value === '') {
dialogMessage = new FormDesigner.main.DialogMessage(null, "warning", messageMaxFile);
dialogMessage.onClose = function () {
oldValue = target.properties[prop].oldValue;
object = target.properties.set(prop, oldValue);
if (object.node) {
object.node.value = oldValue;
}
};
}
break;
}
};
this.form1.onSynchronizeVariables = function (variables) {
var msg = "";
var json = that.getData();
for (var i = 0; i < variables.length; i++) {
if (variables[i].create === undefined || variables[i].var_name !== variables[i].var_name_old) {
msg = msg + "+ '" + variables[i].var_name + "'<br>";
}
json = $.changeAllValue(json, "variable", variables[i].var_name_old, variables[i].var_name);
json = $.changeAllValue(json, "id", variables[i].var_name_old, variables[i].var_name);
json = $.changeAllValue(json, "name", variables[i].var_name_old, variables[i].var_name);
json = $.changeAllValue(json, "var_name", variables[i].var_name_old, variables[i].var_name);
json = $.changeAllValue(json, "var_uid", variables[i].var_uid_old, variables[i].var_uid);
json = $.changeAllValue(json, "prj_uid", variables[i].prj_uid_old, variables[i].prj_uid);
}
listProperties.clear();
var dynaform = that.form1.getData();
that.form1.setData({
dyn_content: JSON.stringify(json),
dyn_description: dynaform.description,
dyn_title: dynaform.name,
dyn_type: "xmlform",
dyn_uid: dynaform.id,
dyn_version: 2
});
if (msg !== "") {
new FormDesigner.main.DialogChangedVariables(null, msg);
}
};
this.form1.properties.language.type = "select";
this.form1.properties.mode.value = "edit";
this.form1.properties.mode.items = [
{value: "edit", label: "edit".translate()},
{value: "view", label: "view".translate()},
{value: "disabled", label: "disabled".translate()}
];
this.form1.properties.mode.helpButton = "";
this.form1.properties.gridStore.type = "hidden";
this.form1.properties.printable.type = "checkbox";
this.form1.properties.protectedValue.type = "hidden";
this.form1.setData(this.dynaform);
this.form1.setDirty();
that.title.text(this.dynaform.dyn_title).attr("title", this.dynaform.dyn_title).tooltip({
tooltipClass: "fd-tooltip",
position: {my: "left top+1"}
});
$(document).on("pm.fd.show", that.onShowHandler.bind(this, listControls, listMobileControls));
};
Designer.prototype._getAuxForm = function () {
var form;
if (!this._auxForm) {
form = document.createElement('form');
this._auxForm = form;
}
return this._auxForm;
};
Designer.prototype._disposeAuxForm = function () {
var form = this._auxForm;
if (form) {
form.parentNode.removeChild(form);
}
this._auxForm = null;
};
Designer.prototype.show = function () {
var a = document.body.childNodes;
for (var i = 0; i < a.length; i++)
$(a[i]).hide();
$(this.container).show();
$(document).trigger("pm.fd.show");
};
Designer.prototype.hide = function () {
var a = document.body.childNodes;
for (var i = 0; i < a.length; i++)
$(a[i]).show();
$(this.container).remove();
this._disposeAuxForm();
$(".loader").hide();
this.onHide();
};
Designer.prototype.getForms = function () {
return this.form1;
};
Designer.prototype.getData = function () {
$.globalInvalidProperties = [];
var data = {};
data["name"] = this.form1.properties.name.value;
data["description"] = this.form1.properties.description.value;
data["items"] = [];
data["items"].push(this.form1.getData());
return data;
};
Designer.prototype.loadDynaforms = function () {
var isSeen = 1;
$.ajax({
async: false,
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id
+ "/dynaforms?seen=" + isSeen,
method: "GET",
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + PMDesigner.project.keys.access_token);
},
success: function (data) {
$.remoteDynaforms = data;
}
});
};
/**
* Validate the date
* @param date
*
*/
Designer.prototype.parseDate = function (stringDate) {
var parts;
if (typeof stringDate !== "undefined" && stringDate !== null) {
parts = stringDate.split("-");
// new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
return new Date(parts[0], parts[1] - 1, parts[2]); // Note: months are 0-based
}
return null;
};
/**
* Verifies if a date is valid
* @param date
* @returns {boolean}
*/
Designer.prototype.isValidDate = function (date) {
return date instanceof Date && !isNaN(date);
};
/**
* Search if there is a limit lower than minDate property.
* @param minDateString
* @param maxDateString
* @param defaultDateString
* @returns {Object}
*/
Designer.prototype.thereIsMinDateLimit = function (minDateString, maxDateString, defaultDateString) {
var minDate = this.parseDate(minDateString),
maxDate = this.parseDate(maxDateString),
defaultDate = this.parseDate(defaultDateString),
result = null;
if (this.isValidDate(minDate)) {
if (this.isValidDate(defaultDate)) {
if (minDate > defaultDate) {
result = defaultDateString;
}
}
if (!result && this.isValidDate(maxDate)) {
if (minDate > maxDate) {
result = maxDateString;
}
}
}
return result;
};
/**
* Search if there is a limit highest than maxDate property.
* @param minDateString
* @param maxDateString
* @param defaultDateString
* @returns {Object}
*/
Designer.prototype.thereIsMaxDateLimit = function (minDateString, maxDateString, defaultDateString) {
var minDate = this.parseDate(minDateString),
maxDate = this.parseDate(maxDateString),
defaultDate = this.parseDate(defaultDateString),
result = null;
if (this.isValidDate(maxDate)) {
if (this.isValidDate(defaultDate)) {
if (maxDate < defaultDate) {
result = defaultDateString;
}
}
if (!result && this.isValidDate(minDate)) {
if (maxDate < minDate) {
result = minDateString;
}
}
}
return result;
};
/**
* Search if defaultDate property is in range of min date and max date.
* @param minDateString
* @param maxDateString
* @param defaultDateString
* @returns {Object}
*/
Designer.prototype.thereIsDefaultDateLimit = function (minDateString, maxDateString, defaultDateString) {
var minDate = this.parseDate(minDateString),
maxDate = this.parseDate(maxDateString),
defaultDate = this.parseDate(defaultDateString),
result = null;
if (this.isValidDate(defaultDate)) {
if (this.isValidDate(minDate)) {
if (defaultDate < minDate) {
result = minDateString;
}
}
if (!result && this.isValidDate(maxDate)) {
if (defaultDate > maxDate) {
result = maxDateString;
}
}
}
return result;
};
/**
* Handler for on show trigger.
* @param {array} listControls
* @param {array} listMobileControls
*/
Designer.prototype.onShowHandler = function (listControls, listMobileControls) {
var i,
popOver,
controls = listControls.controls.concat(listMobileControls.controls);
if (Array.isArray(controls)) {
for (i = 0; i < controls.length; i += 1) {
if (controls[i].deprecated === true) {
popOver = controls[i].target.getPopOver();
$(document).on('pm.fd.scroll', popOver.hide.bind(popOver));
if (!PMDYNAFORM_FIRST_TIME) {
popOver.show();
}
}
}
}
PMDYNAFORM_FIRST_TIME = true;
};
/**
* Validate Max File Size, if the value exceeds the allowed limit, an alert message
* is displayed.
*
* @param object target
* @param object maxFileSizeInformation
* @param function callback
*/
Designer.prototype.validateMaxFileSize = function (target, maxFileSizeInformation, callback) {
var isTypeValid,
message;
if (target.properties === null) {
return;
}
isTypeValid = target.properties.type.value === FormDesigner.main.TypesControl.file ||
target.properties.type.value === FormDesigner.main.TypesControl.multipleFile;
if (!isTypeValid) {
return;
}
if (this.isValidMaxFileSizeFromProperties(maxFileSizeInformation, target.properties) === false) {
message = "The maximum value of this field is ".translate() + maxFileSizeInformation.uploadMaxFileSize;
callback(target, message);
}
};
/**
* Returns true if the value of Max files Size, satisfies the configuration of
* the php ini directives, false otherwise.
*
* @param {object} maxFileSizeInformation
* @param {object} properties
* @returns {Boolean}
*/
Designer.prototype.isValidMaxFileSizeFromProperties = function (maxFileSizeInformation, properties) {
var value,
unit,
items,
i;
value = parseInt(properties.size.value, 10);
unit = properties.sizeUnity.value;
items = properties.sizeUnity.items;
if (Array.isArray(items)) {
for (i = 0; i < items.length; i += 1) {
if (unit === items[i].value) {
value = value * Math.pow(1024, i + 1);
}
}
}
if (maxFileSizeInformation.uploadMaxFileSizeBytes < value) {
return false;
}
return true;
};
/**
* Set Minimal File Size.
*
* @param object target
* @param object maxFileSizeInformation
*/
Designer.prototype.setMinimalFileSize = function (target, maxFileSizeInformation) {
var size,
sizeValue,
sizeUnity,
sizeUnityValue;
sizeValue = maxFileSizeInformation.uploadMaxFileSizeMBytes;
size = target.properties.set("size", sizeValue);
if (size && size.node) {
size.node.value = sizeValue;
}
sizeUnityValue = maxFileSizeInformation.uploadMaxFileSizeUnit;
sizeUnity = target.properties.set("sizeUnity", sizeUnityValue);
if (sizeUnity.node) {
sizeUnity.node.value = sizeUnityValue;
}
};
FormDesigner.extendNamespace('FormDesigner.main.Designer', Designer);
}());
(function () {
var DialogDynaforms = function (appendTo, uidParentDynaform) {
this.onClose = new Function();
this.onSelectItem = new Function();
this.uidParentDynaform = uidParentDynaform;
DialogDynaforms.prototype.init.call(this, appendTo);
};
DialogDynaforms.prototype.init = function (appendTo) {
var that = this;
this.dialog = $("<div title='" + "Select a Control".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.body = $("<div style='border:1px solid #bbb;'></div>");
this.dialog.append("<p>Please select the control you want to use with your variable.</p>".translate());
this.dialog.append(this.body);
this.load();
};
DialogDynaforms.prototype.load = function () {
var that = this;
this.body.find(">div").remove();
(new PMRestClient({
endpoint: 'dynaforms',
typeRequest: 'get',
functionSuccess: function (xhr, response) {
for (var i = 0; i < response.length; i++) {
if (response[i].dyn_uid !== that.uidParentDynaform) {//todo
that.addItem(response[i]);
}
}
},
messageError: 'There are problems getting the list of DynaForms, please try again.'.translate()
})).executeRestClient();
};
DialogDynaforms.prototype.addItem = function (dynaform) {
var that = this;
var item = $(
"<div class='fd-list' style='width:auto;cursor:pointer;'>" +
"<div style='display:inline-block;background-size:contain;background-image:url(" + $.imgUrl + "fd-application-form.png);width:16px;height:16px;vertical-align:middle;'></div>" +
"<div style='display:inline-block;margin-left:10px;'>" + dynaform.dyn_title + "</div>" +
"</div>");
this.body.append(item);
item.attr("render", "subform");
item.attr("dynaform", JSON.stringify(dynaform));
item.on("click", function (event) {
that.onSelectItem(event, item);
that.dialog.dialog("close").remove();
});
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogDynaforms', DialogDynaforms);
}());
(function () {
var DialogTypeControl = function (appendTo) {
this.onClose = new Function();
this.onSelectItem = new Function();
DialogTypeControl.prototype.init.call(this, appendTo);
};
DialogTypeControl.prototype.init = function (appendTo) {
var that = this;
this.dialog = $("<div title='" + "Select a Control".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.body = $("<div style='border:1px solid #bbb;'></div>");
this.dialog.append("<p>" + "Please select the control you want to use with your variable.".translate() + "<p>");
this.dialog.append(this.body);
};
DialogTypeControl.prototype.load = function (variable) {
var controls = [{
url: "" + $.imgUrl + "fd-ui-text-field.png",
label: "textfield".translate(),
render: FormDesigner.main.TypesControl.text
}, {
url: "" + $.imgUrl + "fd-ui-text-area.png",
label: "textarea".translate(),
render: FormDesigner.main.TypesControl.textarea
}, {
url: "" + $.imgUrl + "fd-ui-combo-box.png",
label: "dropdown".translate(),
render: FormDesigner.main.TypesControl.dropdown
}, {
url: "" + $.imgUrl + "fd-ui-check-boxes-list.png",
label: "checkbox".translate(),
render: FormDesigner.main.TypesControl.checkbox
}, {
url: "" + $.imgUrl + "fd-ui-radio-buttons-list.png",
label: "radio".translate(),
render: FormDesigner.main.TypesControl.radio
}, {
url: "" + $.imgUrl + "fd-calendar.png",
label: 'datetime',
render: FormDesigner.main.TypesControl.datetime
}, {
url: "" + $.imgUrl + "fd-ui-list-box.png",
label: "suggest".translate(),
render: FormDesigner.main.TypesControl.suggest
}, {
url: "" + $.imgUrl + "fd-ui-text-field-hidden.png",
label: "hidden".translate(),
render: FormDesigner.main.TypesControl.hidden
}
];
this.body.find(">div").remove();
for (var i = 0; i < controls.length; i++) {
if (variable.var_field_type === "string" && (controls[i].label === "textfield" || controls[i].label === "textarea" || controls[i].label === "dropdown" || controls[i].label === "checkbox" || controls[i].label === "radio" || controls[i].label === "suggest" || controls[i].label === "hidden")) {
this.addItem(controls[i]);
}
if (variable.var_field_type === "integer" && (controls[i].label === "textfield" || controls[i].label === "dropdown" || controls[i].label === "checkbox" || controls[i].label === "radio" || controls[i].label === "suggest" || controls[i].label === "hidden")) {
this.addItem(controls[i]);
}
if (variable.var_field_type === "float" && (controls[i].label === "textfield" || controls[i].label === "dropdown" || controls[i].label === "checkbox" || controls[i].label === "radio" || controls[i].label === "suggest" || controls[i].label === "hidden")) {
this.addItem(controls[i]);
}
if (variable.var_field_type === "boolean" && (controls[i].label === "dropdown" || controls[i].label === "radio" || controls[i].label === "hidden" || controls[i].label === "checkbox")) {
this.addItem(controls[i]);
}
if (variable.var_field_type === "datetime" && (controls[i].label === "datetime" || controls[i].label === "datetime" || controls[i].label === "suggest" || controls[i].label === "hidden")) {
this.addItem(controls[i]);
}
}
};
DialogTypeControl.prototype.addItem = function (control) {
var that = this;
var item = $(
"<div class='fd-list' style='width:auto;height:16px;position:relative;cursor:pointer;'>" +
"<div style='display:inline-block;vertical-align:middle;'><img src=" + control.url + "></img></div>" +
"<div style='display:inline-block;margin-left:10px;'>" + control.label + "</div>" +
"</div>");
this.body.append(item);
item.attr("render", control.render);
item.on("click", function (event) {
that.onSelectItem(event, item);
that.dialog.dialog("close").remove();
});
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogTypeControl', DialogTypeControl);
}());
(function () {
/**
* Represents an item in the list of controls.
*
* @param {object} control
* @returns {NoticeL#1.Notice}
* @constructor
*/
var Notice = function () {
Notice.prototype.init.call(this);
};
/**
* Initialize the class.
*/
Notice.prototype.init = function () {
var element;
this.message = $("<div></div>");
element = $("<div class='mafe-alert'></div>");
element.append('<button class="button-close"><span class="fa fa-times"></span></button>')
.append(this.message)
.on('click', '.button-close', function () {
element.fadeOut();
});
element.hide();
this.body = element;
};
/**
* Show message.
* @param {type} message
*/
Notice.prototype.show = function (message) {
this.message.empty();
this.message.append(message);
this.body.show();
};
/**
* Close message.
*/
Notice.prototype.close = function () {
this.body.fadeOut();
};
FormDesigner.extendNamespace('FormDesigner.main.Notice', Notice);
}());
(function () {
var Form = function (parent) {
this.id = PMUI.generateUniqueId();
this.onRemove = new Function();
this.onRemoveItem = new Function();
this.onRemoveCell = new Function();
this.onSelect = new Function();
this.onDrawControl = new Function();
this.onSetProperty = new Function();
this.onSynchronizeVariables = new Function();
this.onDrawDroppedItem = new Function();
this.sourceNode = null;
this.targetNode = null;
this.parent = parent;
this.stopValidateRows = false;
this.variable = null;
this.dirty = null;
this.subformSupport = true;
this.disabled = false;
this.recovery = false;
this.checkColspan = true;
this.typesControlSupported = [
FormDesigner.main.TypesControl.title,
FormDesigner.main.TypesControl.subtitle,
FormDesigner.main.TypesControl.label,
FormDesigner.main.TypesControl.link,
FormDesigner.main.TypesControl.image,
FormDesigner.main.TypesControl.file,
FormDesigner.main.TypesControl.multipleFile,
FormDesigner.main.TypesControl.submit,
FormDesigner.main.TypesControl.button,
FormDesigner.main.TypesControl.text,
FormDesigner.main.TypesControl.textarea,
FormDesigner.main.TypesControl.dropdown,
FormDesigner.main.TypesControl.checkbox,
FormDesigner.main.TypesControl.checkgroup,
FormDesigner.main.TypesControl.radio,
FormDesigner.main.TypesControl.datetime,
FormDesigner.main.TypesControl.suggest,
FormDesigner.main.TypesControl.hidden,
FormDesigner.main.TypesControl.annotation,
FormDesigner.main.TypesControl.geomap,
FormDesigner.main.TypesControl.qrcode,
FormDesigner.main.TypesControl.signature,
FormDesigner.main.TypesControl.imagem,
FormDesigner.main.TypesControl.audiom,
FormDesigner.main.TypesControl.videom,
FormDesigner.main.TypesControl.panel,
FormDesigner.main.TypesControl.msgPanel
];
this._items = new PMUI.util.ArrayList();
Form.prototype.init.call(this);
};
Form.prototype.init = function () {
var that = this;
this.thead = $("<thead><tr><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th><th></th></tr></thead>");
this.tbody = $("<tbody class='itemsVariablesControls'></tbody>");
this.tbody.sortable({
placeholder: "fd-gridForm-placeholder",
handle: ".formdesigner-move-row",
stop: function (event, ui) {
if (ui.item.attr("variable"))
that.variable = JSON.parse(ui.item.attr("variable"));
if (ui.item.attr("render")) {
var c = that.addCell();
that.targetNode = c;
c.data("createdRow", true);
ui.item.replaceWith(that.addRow().append(c));
var properties = that.drawDroppedItem(ui.item.attr("render"));
that.onDrawControl(properties);
}
that.validateDragDrop();
that.validateRows();
}
}).droppable({
drop: function (event, ui) {
}
});
this.table = $("<table style='width:100%;'></table>");
this.table.append(this.thead);
this.table.append(this.tbody);
this.body = $("<div id='" + this.id + "' class=\"pm-mafe-form\" style='background:#F6F5F3;margin:6px;padding:10px;border-radius:5px;border:1px solid #DADADA;position:relative;'></div>");
this.body.append(this.table);
this.body.on("click", function (e) {
e.stopPropagation();
$.designerSelectElement(this, that.onRemove);
that.onSelect(that.properties);
});
this.body.data("objectInstance", this);
this.properties = new FormDesigner.main.Properties(FormDesigner.main.TypesControl.form, this.body, that);
this.properties.onClick = function (property) {
var a, b;
if (property === "script") {
a = new FormDesigner.main.DialogScript();
a.onSave = function () {
that.properties.set(property, {
type: "js",
code: a.editor.getValue()
});
};
if (typeof that.properties.get()[property].value === "object") {
a.editor.setValue(that.properties.get()[property].value.code);
}
}
if (property === "variable") {
a = new FormDesigner.main.DialogCreateVariable(null, FormDesigner.main.TypesControl.form, [], that.properties.get()[property].value);
a.onSave = function (variable) {
that.setVariable(variable);
};
a.onSelect = function (variable) {
a.dialog.dialog("close");
that.setVariable(variable);
};
}
};
this.properties.onClickClearButton = function (property) {
var a, b;
if (property === "variable" && that.properties[property].value !== "") {
a = new FormDesigner.main.DialogConfirmClearVariable();
a.onAccept = function () {
b = that.properties.set("variable", "");
b.node.textContent = "...";
b = that.properties.set("dataType", "");
b.node.textContent = "";
b = that.properties.set("protectedValue", false);
b.node.checked = false;
};
}
};
this.properties.onSet = function (prop, value) {
that.onSetProperty(prop, value, that);
};
this.clear();
this.notice = new FormDesigner.main.Notice();
this.notice.body.insertBefore(this.table);
};
Form.prototype.addRow = function () {
var row = $("<tr style='padding:5px;'></tr>");
this.tbody.append(row);
return row;
};
Form.prototype.addCell = function () {
var that = this,
cell,
properties;
cell = $("<td style='height:56px;background:white;position:relative;vertical-align:top;border:1px dotted gray;' class='itemVariables itemControls cellDragDrop colspan-12' colspan='12'></td>");
cell[0].disabled = false;
cell[0].setDisabled = function (disabled) {
cell[0].disabled = disabled;
cell.data("properties").setDisabled(disabled);
};
cell.sortable({
placeholder: "fd-gridForm-placeholder",
connectWith: ".cellDragDrop",
items: '>*:not(.containerCellDragDrop)',
receive: function (event, ui) {
that.sourceNode = ui.sender;
that.targetNode = $(this);
},
stop: function (event, ui) {
if (ui.item.attr("variable"))
that.variable = JSON.parse(ui.item.attr("variable"));
that.targetNode = that.targetNode ? $(ui.item[0].parentNode) : that.targetNode;
if (ui.item.attr("render")) {
$(ui.item).remove();
var properties = that.drawDroppedItem(ui.item.attr("render"));
that.onDrawControl(properties);
}
that.validateDragDrop();
that.validateRows();
}
}).droppable({
drop: function (event, ui) {
}
});
properties = new FormDesigner.main.Properties(FormDesigner.main.TypesControl.cell, cell, cell[0]);
properties.onSet = function (prop, value) {
if (prop === "colSpan" && properties[prop].node) {
//calculate colspan
value = $.trim(value);
var dt = value.split(" "), s = 0, ss = "", i, r, col;
for (i = 0; i < dt.length; i++) {
col = parseInt(dt[i], 10);
if (s + col <= 12 && col !== 0 && col > 0) {
s = s + col;
ss = ss + col + " ";
}
}
if (s < 12) {
r = 12 - s;
s = s + r;
ss = ss + r;
}
ss = $.trim(ss);
//validation
if (that.checkColspan === true && cell.parent().children().length > ss.split(" ").length) {
var a = new FormDesigner.main.DialogConfirm(null, "warning", "The colspan change is going to remove columns and content fields. Do you want to continue?".translate());
a.onAccept = function () {
that.checkColspan = false;
properties.set(prop, ss);
that.checkColspan = true;
};
a.onClose = function () {
that.checkColspan = false;
var oldValue = properties[prop].oldValue;
properties.set(prop, oldValue);
properties[prop].node.value = oldValue;
that.checkColspan = true;
};
return;
}
//update value in properties and input
properties[prop].node.value = ss;
properties[prop].value = ss;
//complete cells
var row = cell.parent();
dt = ss.split(" ");
if (row.children().length < dt.length) {
for (i = 0; i < dt.length; i++) {
if (i < row.children().length) {
} else {
row.append(that.addCell());
}
row.children()[i].style.width = (dt[i] * 100 / 12) + "%";//todo colspan
row.children()[i].colSpan = dt[i];
}
}
if (row.children().length >= dt.length) {
for (i = 0; i < dt.length; i++) {
row.children()[i].style.width = (dt[i] * 100 / 12) + "%";//todo colspan
row.children()[i].colSpan = dt[i];
}
while (row.children().length > i) {
$(row.children()[i]).remove();
}
}
//update icons
$.designerSelectElement(row.children()[0]);
//update all cells to new value
row.children().each(function (i, e) {
var a = $(e).data("properties").onSet;
$(e).data("properties").onSet = new Function();
$(e).data("properties").set(prop, ss);
$(e).data("properties").onSet = a;
});
//update colspan class for resize media query
row.children().each(function (i, e) {
for (var i = 1; i <= 12; i++) {
$(e).removeClass("colspan-" + i);
}
$(e).addClass("colspan-" + e.colSpan);
});
}
};
cell.data("properties", properties);
cell.on("click", function (e) {
e.stopPropagation();
$.designerSelectElement(this, function (row) {
var itemsToRemove;
that.validateRows();
that.validateDragDrop();
that.onRemoveCell();
itemsToRemove = that._items.asArray().filter(function (i) {
return row.innerHTML.indexOf(i.html.parent().parent().get(0).innerHTML) !== -1;
});
itemsToRemove.forEach(function (item) {
that._items.remove(item);
});
if (!that.checkForDeprecatedControls()) {
that.hideDeprecationMessage();
}
}, function () {
if (that.disabled === true) {
return false;
}
});
that.onSelect(properties);
});
cell.append("<div class='containerCellDragDrop' style='float:right;'></div>");
return cell;
};
Form.prototype.drawDroppedItem = function (render, data) {
var that = this,
properties = null,
target = null;
switch (render) {
case that.inTypesControl(render):
var formItem = new FormDesigner.main.FormItem({
parentObject: that,
type: render,
variable: that.variable,
onSelect: function (properties) {
that.onSelect(properties);
}
});
formItem.onRemove = function () {
that.onRemoveItem(this);
};
formItem.onSetProperty = function (prop, value, target) {
that.onSetProperty(prop, value, target);
};
that.targetNode.append(formItem.html);
properties = formItem.properties;
target = formItem;
break;
case FormDesigner.main.TypesControl.grid:
var grid = new FormDesigner.main.Grid(that);
grid.onRemove = function () {
this.clearItemsDeprecated();
that.onRemoveItem();
};
grid.onRemoveItem = function (gridItem) {
that.onRemoveItem(gridItem, "grid");
};
grid.onSelect = function (properties) {
that.onSelect(properties);
};
grid.onVariableDrawDroppedItem = function (variable) {
if (that.isVariableUsed(variable.var_uid)) {
new FormDesigner.main.DialogInformation();
return false;
}
};
grid.onDrawControl = function (properties) {
that.onDrawControl(properties);
};
grid.onDrawDroppedItem = function (render, target) {
that.onDrawDroppedItem(render, target, "grid");
};
grid.onSetProperty = function (prop, value, target) {
that.onSetProperty(prop, value, target);
};
that.targetNode.append(grid.body);
properties = grid.properties;
target = grid;
break;
case FormDesigner.main.TypesControl.form:
var form = new FormDesigner.main.Form(that);
form.onRemove = function () {
form.clearItemsDeprecated();
that.onRemoveItem();
};
form.onRemoveItem = function () {
that.onRemoveItem();
};
form.onRemoveCell = function () {
that.onRemoveItem();
};
form.onSelect = function (properties) {
that.onSelect(properties);
};
form.onDrawControl = function (properties) {
that.onDrawControl(properties);
};
form.onDrawDroppedItem = function (render, target) {
that.onDrawDroppedItem(render, target, "form");
};
form.onSetProperty = function (prop, value, target) {
that.onSetProperty(prop, value, target);
};
form.setData(data);
form.setDisabled(true);
form.properties.gridStore.disabled = false;
form.properties.variable.disabled = false;
form.properties.mode.disabled = false;
form.properties.protectedValue.disabled = false;
form.body[0].style.margin = "20px 6px 6px 6px";
that.targetNode.append(form.body);
that.validateDragDrop();
that.validateRows();
that.variable = null;
properties = form.properties;
target = form;
break;
case FormDesigner.main.TypesControl.variable:
if (that.isVariableUsed(that.variable.var_uid)) {
var dialogInformation = new FormDesigner.main.DialogInformation();
dialogInformation.onAccept = function () {
if (that.targetNode.data("createdRow") === true) {
that.targetNode.parent().remove();
}
};
return;
}
that.stopValidateRows = true;
var dialogTypeControl = new FormDesigner.main.DialogTypeControl();
dialogTypeControl.load(that.variable);
dialogTypeControl.onSelectItem = function (event, item) {
that.drawDroppedItem(item.attr("render"));
that.validateDragDrop();
that.validateRows();
that.variable = null;
};
dialogTypeControl.onClose = function () {
that.validateDragDrop();
that.validateRows();
that.variable = null;
};
target = dialogTypeControl;
break;
case FormDesigner.main.TypesControl.subform:
if (that.subformSupport === false) {
new FormDesigner.main.DialogUnsupported();
return;
}
that.stopValidateRows = true;
var dialogDynaforms = new FormDesigner.main.DialogDynaforms(null, that.properties.id.value);
dialogDynaforms.onSelectItem = function (event, item) {
var prop,
subDynaform;
subDynaform = JSON.parse(item.attr("dynaform"));
//todo validation form with subform
var sf, sfi, sfj, jsp;
jsp = JSON.parse(subDynaform.dyn_content);
if (jsp.items.length > 0) {
sf = jsp.items[0];
for (sfi = 0; sfi < sf.items.length; sfi++) {
for (sfj = 0; sfj < sf.items[sfi].length; sfj++) {
if (sf.items[sfi][sfj].type === FormDesigner.main.TypesControl.form) {
new FormDesigner.main.DialogUnsupported();
return;
}
}
}
}
prop = that.drawDroppedItem(FormDesigner.main.TypesControl.form, subDynaform);
prop.owner.subformSupport = false;
};
dialogDynaforms.onClose = function () {
that.validateDragDrop();
that.validateRows();
that.variable = null;
};
target = dialogDynaforms;
break;
}
that.onDrawDroppedItem(render, target);
return properties;
};
Form.prototype.validateDragDrop = function () {
this.tbody.find("td").each(function (i, ele) {
if (ele.childNodes.length >= 2) {
$(ele).removeClass("itemVariables");
$(ele).removeClass("itemControls");
$(ele).removeClass("cellDragDrop");
} else {
$(ele).addClass("itemVariables");
$(ele).addClass("itemControls");
$(ele).addClass("cellDragDrop");
}
});
};
Form.prototype.validateRows = function () {
var that = this, row, sw, cell, length;
if (that.stopValidateRows === true) {
that.stopValidateRows = false;
return;
}
length = this.tbody.find(">tr").length;
for (var i = 1; i < length; i++) {
sw = true;
row = this.tbody.find(">tr").last();
cell = row.find(">td");
if (cell.length === 1) {
cell.each(function (i, ele) {
if (ele.childNodes.length >= 2) {
sw = false;
}
});
if (sw) {
row.remove();
}
}
}
this.tbody.find(">tr").last().find(">td").each(function (i, ele) {
if (ele.childNodes.length >= 2) {
that.addRow().append(that.addCell());
return false;
}
});
if (this.tbody.find(">tr").length === 0) {
that.addRow().append(that.addCell());
}
};
/**
* Init controls supported
* @param val
* @return {*}
*/
Form.prototype.inTypesControl = function (val) {
if ($.inArray(val, this.typesControlSupported) > -1) {
return val;
}
return null;
};
Form.prototype.getData = function () {
var data, fieldObject, rows, i, j, k, itemsrow, itemsTable, dataCell, flag, propertiesForm, property, cells,
variables;
data = {};
itemsTable = [];
variables = [];
propertiesForm = this.properties.get();
for (property in propertiesForm) {
data[property] = propertiesForm[property].value;
}
rows = this.tbody[0].childNodes;
for (i = 0; i < rows.length; i++) {
itemsrow = [];
flag = false;
cells = rows[i].childNodes;
for (j = 0; j < cells.length; j++) {
dataCell = {};
if (cells[j].children.length > 1) {
fieldObject = $(cells[j].children[1]).data("objectInstance");
if (fieldObject) {
dataCell = fieldObject.getData();
//get variable
if (fieldObject.variable) {
for (k = 0; k < variables.length; k++) {
if (variables[k] && variables[k].var_uid === fieldObject.variable.var_uid) {
break;
}
}
if (k === variables.length && fieldObject.variable !== null) {
variables.push(fieldObject.variable);
}
}
//get variable in columns
if (dataCell.columns) {
var sb = fieldObject.getVariables();
for (var sbi = 0; sbi < sb.length; sbi++) {
for (k = 0; k < variables.length; k++) {
if (sb[sbi] && variables[k] && variables[k].var_uid === sb[sbi].var_uid) {
break;
}
}
if (k === variables.length && sb[sbi] !== null) {
variables.push(sb[sbi]);
}
}
}
}
flag = true;
}
dataCell["colSpan"] = cells[j].colSpan;
itemsrow.push(dataCell);
}
if (flag) {
itemsTable.push(itemsrow);
}
}
data["items"] = itemsTable;
data["variables"] = variables;
return data;
};
Form.prototype.setData = function (dynaform) {
if (dynaform === undefined) {
return;
}
if (dynaform.dyn_content === undefined || dynaform.dyn_content === "" || dynaform.dyn_content === "{}") {
dynaform.dyn_content = JSON.stringify({
"name": dynaform.dyn_title,
"description": dynaform.dyn_description,
"items": []
});
}
this.tbody.find(">tr").remove();
var that = this, i, j, k, l, content, forms, form, rows, cells, row, properties, variables, propertiesColumns;
content = JSON.parse(dynaform.dyn_content);
that.properties.set("id", dynaform.dyn_uid);
that.properties.set("name", dynaform.dyn_title);
that.properties.set("description", dynaform.dyn_description);
that.properties.set("mode", "edit");
that.properties.set("script", "");
that.properties.set("language", "en");
that.properties.set("externalLibs", "");
that.properties.set("gridStore", false);
that.properties.set("variable", "");
that.properties.set("dataType", "");
that.properties.set("printable", false);
that.properties.set("protectedValue", false);
forms = content.items;
for (i = 0; i < forms.length; i++) {
form = forms[i];
form = that.compatibilityType(form);
that.properties.set("id", dynaform.dyn_uid);
that.properties.set("name", dynaform.dyn_title);
that.properties.set("description", dynaform.dyn_description);
that.properties.set("mode", form.mode);
that.properties.set("script", form.script);
that.properties.set("language", form.language);
that.properties.set("externalLibs", form.externalLibs);
that.properties.set("gridStore", form.gridStore ? form.gridStore : false);//compatibility with older forms
that.properties.set("variable", form.variable ? form.variable : "");//compatibility with older forms
that.properties.set("dataType", form.dataType ? form.dataType : "");//compatibility with older forms
that.properties.set("printable", form.printable ? form.printable : false);//compatibility with older forms
that.properties.set("protectedValue", form.protectedValue ? form.protectedValue : false);//compatibility with older forms
variables = form.variables;
rows = form.items;
for (j = 0; j < rows.length; j++) {
cells = rows[j];
if (cells.length > 0)
row = that.addRow();
var cs = "";
for (k = 0; k < cells.length; k++) {
cs = cs + cells[k].colSpan + " ";
}
cs = cs.trim();
for (k = 0; k < cells.length; k++) {
//get variable
if (cells[k].var_uid) {
for (l = 0; l < variables.length; l++) {
if (variables[l] && cells[k].var_uid === variables[l].var_uid) {
that.variable = variables[l];
break;
}
}
}
that.targetNode = that.addCell();
that.targetNode[0].colSpan = cells[k].colSpan;
that.targetNode[0].style.width = (cells[k].colSpan * 100 / 12) + "%";//todo colspan
that.targetNode.removeClass("colspan-12");
that.targetNode.addClass("colspan-" + cells[k].colSpan);
that.targetNode.data("properties").set("colSpan", cs);
row.append(that.targetNode);
//load elements & properties
if (cells[k].type !== FormDesigner.main.TypesControl.form) {
properties = that.drawDroppedItem(cells[k].type);
if (properties) {
for (var pro in cells[k]) {
properties.set(pro, cells[k][pro]);
//load columns if element is grid
if (pro === "columns") {
var grid = properties.ele.data("objectInstance");
if (grid) {
grid.targetNode = grid.body;
var columns = properties[pro].value;
for (var ic = 0; ic < columns.length; ic++) {
//get variable for column
if (columns[ic].var_uid) {
for (l = 0; l < variables.length; l++) {
if (variables[l] && columns[ic].var_uid === variables[l].var_uid) {
grid.variable = variables[l];
break;
}
}
}
propertiesColumns = grid.drawDroppedItem(columns[ic].type);
if (propertiesColumns) {
for (var proc in columns[ic]) {
propertiesColumns.set(proc, columns[ic][proc]);
}
}
grid.variable = null;
}
}
}
}
}
that.variable = null;
}
//load form element
if (cells[k].type === FormDesigner.main.TypesControl.form) {
//get local dynaform
var subFormType = cells[k].type;
var subDynaform = {
dyn_content: JSON.stringify({
name: cells[k].name,
description: cells[k].description,
items: [
cells[k]
]
}),
dyn_description: cells[k].description,
dyn_title: cells[k].name,
dyn_type: "xmlform",
dyn_uid: cells[k].id,
dyn_version: 2
};
//get remote dynaform
var sw = false;
for (var i = 0; i < $.remoteDynaforms.length; i++) {
if ($.remoteDynaforms[i].dyn_uid === subDynaform.dyn_uid) {
subDynaform = $.remoteDynaforms[i];
sw = true;
//set subform data from owner form
var sd = JSON.parse(subDynaform.dyn_content);
sd.items[0].gridStore = cells[k].gridStore;
sd.items[0].variable = cells[k].variable;
sd.items[0].dataType = cells[k].dataType;
sd.items[0].mode = cells[k].mode;
sd.items[0].protectedValue = cells[k].protectedValue;
subDynaform.dyn_content = JSON.stringify(sd);
break;
}
}
if (sw === false && that.recovery === true) {
subDynaform.dyn_uid_old = subDynaform.dyn_uid;
var newName = subDynaform.dyn_title + " - " + dynaform.history_date;
for (var i = 0; i < $.remoteDynaforms.length; i++) {
if (newName === $.remoteDynaforms[i].dyn_title) {
newName = newName + "-copy";
i - 1;
}
}
subDynaform.dyn_title = newName;
$.recovered.date = dynaform.history_date;
$.recovered.data.push(subDynaform);
}
if (sw === false && that.recovery === false) {
subFormType = FormDesigner.main.TypesControl.msgPanel;
subDynaform = null;
}
that.stopValidateRows = true;
that.drawDroppedItem(subFormType, subDynaform);
that.variable = null;
}
}
}
}
that.validateDragDrop();
that.validateRows();
that.setLanguages();
};
Form.prototype.clear = function () {
this.tbody.find(">tr").remove();
this.addRow().append(this.addCell());
};
Form.prototype.getFieldObjects = function (filter) {
var i, j, a, rows, cells, fieldObject;
a = [];
rows = this.tbody[0].childNodes;
for (i = 0; i < rows.length; i++) {
cells = rows[i].childNodes;
for (j = 0; j < cells.length; j++) {
if (cells[j].children.length > 1) {
fieldObject = $(cells[j].children[1]).data("objectInstance");
if (fieldObject && filter.indexOf(fieldObject.properties.type.value) > -1)
a.push(fieldObject);
}
}
}
return a;
};
Form.prototype.isDirty = function () {
return this.dirty !== JSON.stringify(this.getData());
};
Form.prototype.setDirty = function () {
this.dirty = JSON.stringify(this.getData());
};
Form.prototype.isVariableUsed = function (var_uid) {
var that = this;
var variable = that.getData();
for (var i = 0; i < variable.variables.length; i++) {
if (variable.variables[i] && variable.variables[i].var_uid === var_uid) {
return true;
}
}
return false;
};
Form.prototype.setLanguages = function () {
var that = this;
(new PMRestClient({
endpoint: "dynaform/" + that.properties.id.value + "/list-language",
typeRequest: "get",
functionSuccess: function (xhr, response) {
var i, a = that.properties.language.items[0];
that.properties.language.items = [];
that.properties.language.items.push(a)
for (i = 0; i < response.length; i++) {
that.properties.language.items.push({
value: response[i]["Lang"],
label: response[i]["X-Poedit-Language"] + " (" + response[i]["Lang"] + ")"
});
}
if (that.properties.language.node !== undefined) {
$(that.properties.language.node).empty();
for (i = 0; i < that.properties.language.items.length; i++) {
$(that.properties.language.node).append("<option value='" + that.properties.language.items[i].value + "'>" + that.properties.language.items[i].label + "</option>");
}
$(that.properties.language.node).val("en");
$(that.properties.language.node).each(function (i, e) {
if (that.properties.language.value === e.value) {
$(that.properties.language.node).val(e.value);
}
});
}
}
})).executeRestClient();
};
Form.prototype.compatibilityType = function (form) {
var j, k;
for (j = 0; j < form.items.length; j++) {
for (k = 0; k < form.items[j].length; k++) {
if (form.items[j][k].type === "form") {
form.items[j][k] = this.compatibilityType(form.items[j][k]);
}
if (form.items[j][k].type === "annotation") {
form.items[j][k].type = "label";
}
}
}
return form;
};
Form.prototype.setDisabled = function (disabled) {
this.disabled = disabled;
var obj;
if (disabled) {
this.tbody.sortable("disable");
this.tbody.find("td").sortable("disable");
} else {
this.tbody.sortable("enable");
this.tbody.find("td").sortable("enable");
}
this.tbody.find("td").each(function (i, cell) {
cell.setDisabled(disabled);
obj = $(cell.children[1]).data("objectInstance");
if (obj && obj.setDisabled) {
obj.setDisabled(disabled);
}
});
this.tbody.find("td").css({
"background-color": disabled ? "#F6F5F3" : "white"
});
this.tbody.find(".grid-item-field").css({
"background-color": disabled ? "#F6F5F3" : "white"
});
this.properties.setDisabled(disabled);
};
Form.prototype.synchronizeVariables = function () {
var that = this, calls = [];
$.ajax({
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id + "/process-variables",
method: "GET",
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + PMDesigner.project.keys.access_token);
},
success: function (data) {
var variables = that.getData().variables,
i,
j,
changeName;
for (i = 0; i < variables.length; i++) {
variables[i].var_accepted_values = that._getVarAcceptedValues(variables[i]);
variables[i].var_uid_old = variables[i].var_uid;
variables[i].var_name_old = variables[i].var_name;
variables[i].prj_uid_old = variables[i].prj_uid;
changeName = true;
for (j = 0; j < data.length; j++) {
data[j].var_accepted_values = that._getVarAcceptedValues(data[j]);
if (changeName && that._compareVariable(variables[i], data[j])) {
variables[i].var_uid = data[j].var_uid;
variables[i].prj_uid = data[j].prj_uid;
variables[i].create = false;
} else {
if (variables[i].var_name === data[j].var_name) {
variables[i].var_name = variables[i].var_name + "_1";
j = -1;
changeName = false;
}
}
}
}
for (i = 0; i < variables.length; i++) {
if (variables[i].create === undefined) {
calls.push({
url: "process-variable", method: "POST", data: variables[i]
});
}
}
if (calls.length > 0) {
$.ajax({
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id + "/",
data: JSON.stringify({calls: calls}),
method: "POST",
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader('X-Requested-With', 'MULTIPART');
xhr.setRequestHeader("Authorization", "Bearer " + PMDesigner.project.keys.access_token);
},
success: function (responses) {
for (var i = 0; i < responses.length; i++) {
if (responses[i].status === 201) {
for (var j = 0; j < variables.length; j++) {
if (responses[i].response.var_name === variables[j].var_name) {
variables[j].var_uid = responses[i].response.var_uid;
variables[j].prj_uid = responses[i].response.prj_uid;
}
}
}
}
that.onSynchronizeVariables(variables);
},
error: function (responses) {
for (var i = 0; i < responses.length; i++) {
if (responses[i].status === 201) {
for (var j = 0; j < variables.length; j++) {
if (responses[i].response.var_name === variables[j].var_name) {
variables[j].var_uid = responses[i].response.var_uid;
variables[j].prj_uid = responses[i].response.prj_uid;
}
}
}
}
that.onSynchronizeVariables(variables);
}
});
} else {
that.onSynchronizeVariables(variables);
}
}
});
};
/**
* Gets the AcceptedValues values of a variable
* @param variable
* @returns {*|Array}
* @private
*/
Form.prototype._getVarAcceptedValues = function (variable) {
var acceptedValues = variable.var_accepted_values;
try {
//In previous versions it was a string (acceptedValues)
if (typeof acceptedValues === 'string') {
acceptedValues = JSON.parse(acceptedValues);
}
} catch (e) {
throw new Error('Accepted Values is an empty string '.translate() + e.message);
}
return acceptedValues;
};
/**
* Compare the variable if it exists
* @param importedVariable
* @param currentVariable
* @returns {boolean}
* @private
*/
Form.prototype._compareVariable = function (importedVariable, currentVariable) {
//Four properties of the variable are compared (name, fieldType, sql and acceptedValues)
return (
importedVariable.var_name === currentVariable.var_name &&
importedVariable.var_field_type === currentVariable.var_field_type &&
importedVariable.var_sql === currentVariable.var_sql &&
JSON.stringify(importedVariable.var_accepted_values) === JSON.stringify(currentVariable.var_accepted_values)
);
};
Form.prototype.setVariable = function (variable) {
var that = this, b;
that.properties.set("var_uid", variable.var_uid);
b = that.properties.set("variable", variable.var_name);
if (b.node)
b.node.textContent = variable.var_name;
b = that.properties.set("dataType", variable.var_field_type);
if (b.node)
b.node.textContent = variable.var_field_type;
};
Form.prototype.setNextLabel = function (properties) {
var nextLabel,
that = this;
nextLabel = FormDesigner.getNextNumber(that.getData(), properties.type.value, "id") + 1;
nextLabel = nextLabel.toString();
while (nextLabel.length < 10) {
nextLabel = "0" + nextLabel;
}
nextLabel = properties.type.value + nextLabel;
properties.set("id", nextLabel.replace(/\s/g, ""));
properties.set("name", nextLabel.replace(/\s/g, ""));
nextLabel = FormDesigner.getNextNumber(that.getData(), properties.type.value, "label") + 1;
nextLabel = properties.type.value + '_' + nextLabel;
properties.set("label", nextLabel);
};
Form.prototype.setNextVar = function (properties) {
var that = this,
nextVar = "",
dialogCreateVariable;
nextVar = properties.type.value + "Var" + nextVar;
dialogCreateVariable = new FormDesigner.main.DialogCreateVariable(null, properties.type.value, [], null);
dialogCreateVariable.setVarName(nextVar);
dialogCreateVariable.onSave = function (variable) {
if (properties.owner.setVariable) {
properties.owner.setVariable(variable);
}
};
dialogCreateVariable.onSelect = function (variable) {
if ($.countValue(that.getData(), "variable", variable.var_name) > 0) {
$.isOpenValidator = true;
var di = new FormDesigner.main.DialogInvalid(null, "variable", "duplicated");
di.onClose = function () {
$.isOpenValidator = false;
};
di.onAccept = function () {
di.dialog.dialog("close");
};
return;
}
if (properties.owner.setVariable) {
properties.owner.setVariable(variable);
}
dialogCreateVariable.dialog.dialog("close");
};
FormDesigner.getNextNumberVar(that.getData(), properties, function (nextVar) {
dialogCreateVariable.setVarName(nextVar);
});
};
/**
* Creates the alert message to notify about deprecated controls being used in current form.
* @private
*/
Form.prototype.showDeprecationMessage = function () {
var message = '<strong>' + 'Warning!'.translate() + '</strong>'
+ ('<span class="sr-only">Error:</span>' + ' '
+ 'This form contains deprecated controls marked with the'.translate() + ' '
+ '<span class="fa fa-exclamation-circle" style="color:red;" aria-hidden="true"></span> ' + 'icon.'.translate() + ' '
+ 'Those controls will no longer be supported and probably will not be available in future versions.'.translate() + ' '
+ 'Please refer to the following link to get more information:').translate()
+ '<br/><a href="' + FormDesigner.DEPRECATION_LINK + '" target="_blank">' + FormDesigner.DEPRECATION_LINK + '</a>';
this.notice.show(message);
};
/**
* Hide the alert message about deprecated controls.
*/
Form.prototype.hideDeprecationMessage = function () {
this.notice.close();
};
/**
* Verify if we have deprecated controls in the form.
* @return {boolean}
*/
Form.prototype.checkForDeprecatedControls = function () {
return this._items.asArray().length > 0;
};
/**
* Clear list of deprecated control in the Form.
*/
Form.prototype.clearItemsDeprecated = function () {
var itemsForm = this._items.asArray(),
i;
for (i = 0; i < itemsForm.length; i+= 1) {
if (this.parent) {
this.parent._items.remove(itemsForm[i])
}
}
this._items.clear();
};
FormDesigner.extendNamespace('FormDesigner.main.Form', Form);
}());
(function () {
/**
* Represents an item in the list of controls.
*
* @param {object} control
* @returns {ListItemL#1.ListItem}
* @constructor
*/
var ListItem = function (control) {
this.control = control;
ListItem.prototype.init.call(this);
};
/**
* Initialize the class.
*/
ListItem.prototype.init = function () {
this.deprecatedControlClassName = 'mafe-deprecated-control';
this.body = $(
"<div class='fd-list-responsive'>" +
"<div style=''><img src='" + this.control.url + "'></img></div>" +
"<div style=''>" + this.control.label + "</div>" +
"<div class='" + this.deprecatedControlClassName + "'>" +
"</div>");
this.body.attr("render", this.control.render);
this.body.draggable({
appendTo: document.body,
revert: "invalid",
helper: "clone",
cursor: "move",
zIndex: 1000,
connectToSortable: ".itemControls,.itemsVariablesControls"
});
this.deprecated(this.control.deprecated);
this.createPopOver();
};
/**
* Enable or disable deprecated icon.
* @param {boolean} status
*/
ListItem.prototype.deprecated = function (status) {
var element = this.body.find("." + this.deprecatedControlClassName);
if (status === true) {
element.show();
} else {
element.hide();
}
};
/**
* Create FormDesigner.main.PMPopOver element.
*/
ListItem.prototype.createPopOver = function () {
var content = $('<div><div class="mafe-deprecated-title">' + 'Warning!'.translate() + '</div><p>'
+ this.control.deprecationMessage + ' For additional information:'.translate() + '</p><p><a href="'
+ FormDesigner.DEPRECATION_LINK + '" target="_blank">' + FormDesigner.DEPRECATION_LINK
+ '</a></p><button type="button" class="deprecated-ok-btn">' + 'Got it'.translate() + '</button></div>');
this.pmPopOver = new FormDesigner.main.PMPopOver({
body: content,
targetElement: this.body.find("." + this.deprecatedControlClassName),
placement: "right",
class: "deprecated"
});
content.find('button').data('parentBody', this.pmPopOver);
content.on('click', 'button', function () {
$(this).data('parentBody').hide();
});
};
/**
* Get FormDesigner.main.PMPopOver instance.
* @returns {FormDesigner.main.PMPopOver}
*/
ListItem.prototype.getPopOver = function () {
return this.pmPopOver;
};
FormDesigner.extendNamespace('FormDesigner.main.ListItem', ListItem);
}());
(function () {
var ListControls = function () {
ListControls.prototype.init.call(this);
};
/**
* Initialize controls.
*/
ListControls.prototype.init = function () {
this.body = $("<div style='background:#262932;overflow:hidden;padding:4px;'></div>");
this.controls = [
{
url: "" + $.imgUrl + "fd-text.png",
label: "textbox".translate(),
render: FormDesigner.main.TypesControl.text
}, {
url: "" + $.imgUrl + "fd-textarea.png",
label: "textarea".translate(),
render: FormDesigner.main.TypesControl.textarea
}, {
url: "" + $.imgUrl + "fd-dropdown.png",
label: "dropdown".translate(),
render: FormDesigner.main.TypesControl.dropdown
}, {
url: "" + $.imgUrl + "fd-checkbox.png",
label: "checkbox".translate(),
render: FormDesigner.main.TypesControl.checkbox
}, {
url: "" + $.imgUrl + "fd-checkgroup.png",
label: "checkgroup".translate(),
render: FormDesigner.main.TypesControl.checkgroup
}, {
url: "" + $.imgUrl + "fd-radio.png",
label: "radio".translate(),
render: FormDesigner.main.TypesControl.radio
}, {
url: "" + $.imgUrl + "fd-datetime.png",
label: "datetime".translate(),
render: FormDesigner.main.TypesControl.datetime
}, {
url: "" + $.imgUrl + "fd-suggest.png",
label: "suggest".translate(),
render: FormDesigner.main.TypesControl.suggest
}, {
url: "" + $.imgUrl + "fd-hidden.png",
label: "hidden".translate(),
render: FormDesigner.main.TypesControl.hidden
}, {
url: "" + $.imgUrl + "fd-h1.png",
label: "title".translate(),
render: FormDesigner.main.TypesControl.title
}, {
url: "" + $.imgUrl + "fd-h2.png",
label: "subtitle".translate(),
render: FormDesigner.main.TypesControl.subtitle
}, {
url: "" + $.imgUrl + "fd-label.png",
label: "label".translate(),
render: FormDesigner.main.TypesControl.annotation
}, {
url: "" + $.imgUrl + "fd-link.png",
label: "link".translate(),
render: FormDesigner.main.TypesControl.link
}, {
url: "" + $.imgUrl + "fd-image2.png",
label: "image".translate(),
render: FormDesigner.main.TypesControl.image
}, {
url: "" + $.imgUrl + "fd-file.png",
label: "file".translate(),
render: FormDesigner.main.TypesControl.file,
deprecated: true,
deprecationMessage: "This control is being deprecated. Please use FileUpload instead."
}, {
url: "" + $.imgUrl + "fd-file-upload.png",
label: "fileupload".translate(),
render: FormDesigner.main.TypesControl.multipleFile
}, {
url: "" + $.imgUrl + "fd-submit.png",
label: "submit".translate(),
render: FormDesigner.main.TypesControl.submit
}, {
url: "" + $.imgUrl + "fd-button.png",
label: "button".translate(),
render: FormDesigner.main.TypesControl.button
}, {
url: "" + $.imgUrl + "fd-grid.png",
label: "grid".translate(),
render: FormDesigner.main.TypesControl.grid
}, {
url: "" + $.imgUrl + "fd-panel32.png",
label: "panel".translate(),
render: FormDesigner.main.TypesControl.panel
}, {
url: "" + $.imgUrl + "fd-subform.png",
label: "subform".translate(),
render: FormDesigner.main.TypesControl.subform
}
];
this.load();
};
ListControls.prototype.load = function () {
var i;
for (i = 0; i < this.controls.length; i += 1) {
this.controls[i].target = this.addItem(this.controls[i]);
}
};
ListControls.prototype.addItem = function (control) {
var item;
item = new FormDesigner.main.ListItem(control);
this.body.append(item.body);
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.ListControls', ListControls);
}());
(function () {
var ListMobileControls = function () {
ListMobileControls.prototype.init.call(this);
};
/**
* Initialize mobile controls.
*/
ListMobileControls.prototype.init = function () {
this.body = $("<div style='background:#262932;overflow:hidden;padding:4px;'></div>");
this.controls = [
{
url: "" + $.imgUrl + "fd-geomap-mobile.png",
label: "geomap".translate(),
render: FormDesigner.main.TypesControl.geomap
}, {
url: "" + $.imgUrl + "fd-qrcode-mobile.png",
label: "qr code".translate(),
render: FormDesigner.main.TypesControl.qrcode
}, {
url: "" + $.imgUrl + "fd-signature-mobile.png",
label: "signature".translate(),
render: FormDesigner.main.TypesControl.signature
}, {
url: "" + $.imgUrl + "fd-image2.png",
label: "image".translate(),
render: FormDesigner.main.TypesControl.imagem
}, {
url: "" + $.imgUrl + "fd-audio-mobile.png",
label: "audio".translate(),
render: FormDesigner.main.TypesControl.audiom
}, {
url: "" + $.imgUrl + "fd-video-mobile.png",
label: "video".translate(),
render: FormDesigner.main.TypesControl.videom
}
];
this.load();
};
/**
* Load mobile controls.
*/
ListMobileControls.prototype.load = function () {
var i;
for (i = 0; i < this.controls.length; i += 1) {
this.controls[i].target = this.addItem(this.controls[i]);
}
};
/**
* Add mobile control.
* @param control
* @return {PMUI.item.ListItem|ListItemL#1.ListItem}
*/
ListMobileControls.prototype.addItem = function (control) {
var item;
item = new FormDesigner.main.ListItem(control);
this.body.append(item.body);
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.ListMobileControls', ListMobileControls);
}());
(function () {
var ListProperties = function () {
ListProperties.prototype.init.call(this);
};
ListProperties.prototype.init = function () {
this.tbody = $("<tbody class='fd-tbody'></tbody>");
this.table = $(
"<table class='fd-table' style='width:100%;'>" +
"<thead>" +
"<th class='fd-table-th' style='min-width:30px;width:50px;max-width:100px;'><span>" + "Property".translate() + "</span></th>" +
"<th class='fd-table-th' style='width:auto;'><span>" + "Value".translate() + "</span>" +
"</th>" +
"</thead>" +
"</table>");
this.table.append(this.tbody);
this.body = $("<div></div>");
this.body.append(this.table);
this.cache = {};
};
ListProperties.prototype.addItem = function (propertiesGot, property, properties) {
var input,
i,
minDate = '',
maxDate = '',
defaultDate = '',
dialogMessage = '',
width = "width:100%;border:1px solid gray;box-sizing:border-box;",
id = FormDesigner.generateUniqueId(),
that = this;
switch (propertiesGot[property].type) {
case "label":
//improvement changes in value
var a = propertiesGot[property].value;
if (property === "type" && a === "cell") {
a = "row";
}
input = $("<div style='position:relative;width:100%;overflow:hidden;height:16px;'><span style='position:absolute;-webkit-user-select:text;-moz-user-select:text;user-select:text;'>" + a + "</span></div>");
properties.setNode(property, input[0]);
break;
case "text":
input = $("<input type='text' style='" + width + "' id='" + id + "'>").val(propertiesGot[property].value);
input.on(propertiesGot[property].on ? propertiesGot[property].on : "change", function () {
properties.set(property, this.value);
});
input.attr("placeholder", propertiesGot[property].placeholder ? propertiesGot[property].placeholder : "");
properties.setNode(property, input[0]);
break;
case "textarea":
input = $("<textarea style='" + width + "resize: vertical;' id='" + id + "'></textarea>").val(propertiesGot[property].value);
input.on("keyup", function () {
properties.set(property, this.value);
});
input.attr("placeholder", propertiesGot[property].placeholder ? propertiesGot[property].placeholder : "");
properties.setNode(property, input[0]);
break;
case "select":
input = $("<select style='" + width + "' id='" + id + "'></select>");
for (i = 0; i < propertiesGot[property].items.length; i++)
input.append("<option value='" + propertiesGot[property].items[i].value + "'>" + propertiesGot[property].items[i].label + "</option>");
input.val(propertiesGot[property].value);
input.on("change", function () {
properties.set(property, this.value);
});
properties.setNode(property, input[0]);
break;
case "checkbox":
input = $("<input type='checkbox' id='" + id + "'>");
input.prop("checked", propertiesGot[property].value);
input.on("change", function () {
properties.set(property, this.checked);
});
properties.setNode(property, input[0]);
break;
case "button":
input = $("<input type='button' value='" + propertiesGot[property].labelButton + "' id='" + id + "'>");
input.on("click", function () {
properties.onClick(property, this);
});
properties.setNode(property, input[0]);
break;
case "labelbutton":
var a = propertiesGot[property].value;
if (typeof a === "object")
a = JSON.stringify(a);
if (a === "")
a = propertiesGot[property].labelButton;
input = $("<div style='position:relative;width:100%;overflow:hidden;height:16px;'><span style='position:absolute;-webkit-user-select:text;-moz-user-select:text;user-select:text;text-decoration:underline;cursor:pointer;white-space:nowrap;'></span></div>");
input.find("span").text(a).on("click", function (e) {
e.stopPropagation();
if ($(e.target).data("disabled") === true)
return;
properties.onClick(property, input.find("span")[0]);
});
properties.setNode(property, input.find("span")[0]);
break;
case "textbutton":
input = $("<input type='text' style='" + width + "' id='" + id + "'><input type='button' value='" + propertiesGot[property].labelButton + "'>");
$(input[0]).val(propertiesGot[property].value);
$(input[0]).on("keyup", function () {
properties.set(property, this.value);
});
$(input[0]).attr("placeholder", propertiesGot[property].placeholder ? propertiesGot[property].placeholder : "");
$(input[1]).on("click", function () {
properties.onClick(property, this);
});
properties.setNode(property, input[0]);
break;
case "textareabutton":
input = $("<textarea style='" + width + "resize:vertical;height:50px;' id='" + id + "'></textarea><input type='button' value='" + propertiesGot[property].labelButton + "'>");
$(input[0]).val(propertiesGot[property].value);
$(input[0]).on("keyup", function () {
properties.set(property, this.value);
});
$(input[0]).attr("placeholder", propertiesGot[property].placeholder ? propertiesGot[property].placeholder : "");
$(input[1]).on("click", function () {
properties.onClick(property, this);
});
properties.setNode(property, input[0]);
break;
case "datepicker":
input = $("<input type='text' style='" + width + "' id='" + id + "'/>").val(propertiesGot[property].value);
input.on(propertiesGot[property].on ? propertiesGot[property].on : "change", function () {
properties.set(property, this.value);
});
input.attr("placeholder", propertiesGot[property].placeholder ? propertiesGot[property].placeholder : "");
properties.setNode(property, input[0]);
break;
case "textselect":
input = $("<input type='text' style='" + width.replace("100%", "50%") + "' id='" + id + "'/><select style='" + width.replace("100%", "50%") + "'></select>");
$(input[0]).val(propertiesGot[property].value.text);
$(input[0]).on("keyup", function () {
properties.set(property, { text: this.value, select: $(input[1]).val() });
});
$(input[0]).attr("placeholder", propertiesGot[property].placeholder ? propertiesGot[property].placeholder : "");
for (i = 0; i < propertiesGot[property].items.length; i++)
$(input[1]).append("<option value='" + propertiesGot[property].items[i].value + "'>" + propertiesGot[property].items[i].label + "</option>");
$(input[1]).val(propertiesGot[property].value.select);
$(input[1]).on("change", function () {
properties.set(property, { text: $(input[0]).val(), select: this.value });
});
properties.setNode(property, { text: $(input[0]).val(), select: $(input[1]).val() });
break;
}
if (propertiesGot[property].type !== "hidden") {
var cellName = $("<td class='fd-table-td'><label for=" + id + ">" + propertiesGot[property].label + "</label></td>");
var cellValue = $("<td class='fd-table-td' style='position:relative;'></td>").append(input);
var row = $("<tr id='" + property + "'></tr>");
row.append(cellName);
row.append(cellValue);
this.tbody.append(row);
if (propertiesGot[property].required === true) {
cellName.append("<span style='color:red;float:right;'>*</span>");
}
var n = 0;
if (propertiesGot[property].helpButton) {
var button = $("<img src='" + $.imgUrl + "fd-help.png' style='cursor:pointer;position:absolute;top:0;right:" + n + ";'>");
button[0].title = propertiesGot[property].helpButton.translate();
button.tooltip({
tooltipClass: propertiesGot[property].helpButtonCss ? propertiesGot[property].helpButtonCss : null,
position: { my: "left+15 center", at: "right center" },
content: function () {
return $(this).prop('title');
},
close: function (event, ui) {
ui.tooltip.hover(function () {
$(this).stop(true).fadeTo(400, 1);
}, function () {
$(this).fadeOut("400", function () {
$(this).remove();
});
});
}
});
cellValue.append(button);
n = n + 16;
cellValue[0].style.paddingRight = n + "px";
}
if (propertiesGot[property].clearButton) {
var button = $("<img src='" + $.imgUrl + "fd-remove.png' style='cursor:pointer;position:absolute;top:0;right:" + n + "px;' title='" + propertiesGot[property].clearButton + "'>");
button.on("click", function (e) {
e.stopPropagation();
if ($(e.target).data("disabled") === true)
return;
properties.onClickClearButton(property);
});
cellValue.append(button);
n = n + 16;
cellValue[0].style.paddingRight = n + "px";
}
if (propertiesGot[property].type === "datepicker") {
button = $("<img src='" + $.imgUrl + "fd-calendar.png' style='cursor:pointer;position:absolute;top:0;right:" + n + "px;' title='" + "datepicker".translate() + "'>");
button.on("click", function (e) {
e.stopPropagation();
if ($(e.target).data("disabled") === true) {
return;
}
if ($(e.target).data("disabledTodayOption") === true) {
return;
}
// init jQyery datepicker
that.datepicker = that.dateComponentFactory(cellValue, {
minDate: minDate,
maxDate: maxDate,
onSelect: function (dateText, inst) {
properties.set(property, dateText, cellValue.find("input[type='text']")[0]);
},
onClose: function (dateText, inst) {
that.datepicker.datepicker("destroy");
$("#ui-datepicker-div").remove();
},
beforeShow: function () {
var params = null;
switch (property) {
case "maxDate":
params = {
minDate: that.getDateByParam(cellValue, "minDate")
}
break;
case "minDate":
params = {
maxDate: that.getDateByParam(cellValue, "maxDate")
}
break;
case "defaultDate":
params = {
maxDate: that.getDateByParam(cellValue, "maxDate"),
minDate: that.getDateByParam(cellValue, "minDate")
}
break;
}
return params;
}
});
cellValue.find(".ui-datepicker-trigger").hide();
});
cellValue.append(button);
n = n + 16;
cellValue[0].style.paddingRight = n + "px";
// init jQuery autocomplete
this.autoCopleteFactory(cellValue, "datetime");
}
if (propertiesGot[property].type === "datepicker" && propertiesGot[property].todayOption) {
cellValue.append("<span style='text-decoration:underline;'><input type='checkbox'/>" + propertiesGot[property].todayOption + "</span>");
var sw = propertiesGot[property].value === "today";
var checkboxToday = cellValue.find("input[type='checkbox']");
checkboxToday.prop("checked", sw);
checkboxToday.on("change", function () {
properties.set(property, this.checked ? "today" : "", cellValue.find("input[type='text']")[0]);
});
}
}
var disabled = propertiesGot[property].disabled === true;
var scope = this.tbody.find("#" + property);
scope.find("input").prop("disabled", disabled);
scope.find("textarea").prop("disabled", disabled);
scope.find("select").prop("disabled", disabled);
scope.find("button").prop("disabled", disabled);
scope.find("span,img").each(function (i, e) {
$(e).data("disabled", disabled);
});
if (!propertiesGot[property].disabled && property === "requiredFieldErrorMessage") {
scope.find("textarea").prop("disabled", !propertiesGot["required"].value);
}
if (!propertiesGot[property].disabled && propertiesGot.type.value === 'multipleFile' &&
(property === 'extensions' || property === 'size' || property === 'sizeUnity')) {
propertiesGot[property].node.disabled = propertiesGot['inputDocument'].value;
}
if (property === 'enableVersioning') {
propertiesGot[property].node.textContent = (propertiesGot[property].value) ? 'Yes' : 'No';
}
if (cellValue && propertiesGot[property].disabledTodayOption !== undefined) {
cellValue.find("input[type='text']").prop("disabled", propertiesGot[property].disabledTodayOption);
scope.find("span,img").each(function (i, e) {
$(e).data("disabledTodayOption", propertiesGot[property].disabledTodayOption);
});
}
if (property === "defaultValue") {
// init jQuery autocomplete
var dataTypeMap = {
text: "string",
textarea: "string",
dropdown: "string",
checkbox: "boolean",
checkgroup: "array",
radio: "string",
suggest: "string",
hidden: "string"
};
this.autoCopleteFactory(cellValue, dataTypeMap[propertiesGot["type"].value] || "string");
}
};
ListProperties.prototype.autoCopleteFactory = function (cellValue, type) {
var that = this;
// implement autocomple widget
cellValue.find("input[type='text']").autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term,
cachekey = type + "-" + request.term,
regExg = /[@][@#=]+[a-zA-Z]?/;
// To validate prefix @@ @# @=
if (!regExg.test(term)) {
return;
}
cellValue.find("input[type='text']").datepicker('hide');
$("#ui-datepicker-div").remove();
if (cachekey in that.cache) {
response(that.cache[cachekey]);
return;
}
// add a new rule to validate
term = term.substring(1) !== "@" ? term[0] + encodeURIComponent(term.substring(1)) : term;
$.ajax({
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id + "/process-variables/" + type + "/paged/?search=" + term,
processData: false,
success: function (json) {
that.cache[cachekey] = json;
response(json);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.error(errorThrown);
},
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + PMDesigner.project.keys.access_token);
}
});
}
});
};
ListProperties.prototype.load = function (properties) {
var that = this, property;
var propertiesGot = properties.get();
for (property in propertiesGot) {
that.addItem(propertiesGot, property, properties);
}
};
ListProperties.prototype.clear = function () {
this.tbody.find("tr").remove();
};
/**
* Creates the date picker component.
* @param control the form control to set de datepicker.
* @param options dynamic params to set the properties.
* @returns {*}
*/
ListProperties.prototype.dateComponentFactory = function (control, options) {
var defaults = {
showOtherMonths: true,
selectOtherMonths: true,
dateFormat: "yy-mm-dd",
changeMonth: true,
changeYear: true,
yearRange: "-100:+100",
minDate: '',
maxDate: '',
onSelect: function () { },
onClose: function () { },
beforeShow: function () { }
},
datePicker;
$.extend(true, defaults, options);
// append the date picker to the control component
datePicker = control
.find("input[type='text']")
.datepicker({
buttonImage: $.imgUrl + "fd-calendar.png",
buttonImageOnly: true,
constrainInput: false,
buttonText: "Select date",
showOn: "button",
showOtherMonths: defaults.showOtherMonths,
selectOtherMonths: defaults.selectOtherMonths,
dateFormat: defaults.dateFormat,
changeMonth: defaults.changeMonth,
changeYear: defaults.changeYear,
yearRange: defaults.yearRange,
minDate: defaults.minDate,
maxDate: defaults.maxDate,
onSelect: defaults.onSelect,
onClose: defaults.onClose,
beforeShow: defaults.beforeShow
}).next(".ui-datepicker-trigger").addClass("datetime-gadget-class");
datePicker.datepicker("show");
return datePicker;
};
/**
* Gets the date according to the passed param
*/
ListProperties.prototype.getDateByParam = function (control, param) {
var varRegex = /\@(?:([\@\%\#\?\$\=\&Qq\!])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*(?:[\\\\][\w\W])?)*)\))((?:\s*\[['"]?\w+['"]?\])+|\-\>([a-zA-Z\_]\w*))?/,
value = '';
if (control && param) {
value = $(control.parent().parent()[0].rows[param])
.find("input")
.val();
if (!varRegex.test(value)) {
return value;
} else {
return '';
}
} else {
return '';
}
};
FormDesigner.extendNamespace('FormDesigner.main.ListProperties', ListProperties);
}());
(function () {
var TabsForm = function () {
TabsForm.prototype.init.call(this);
};
TabsForm.prototype.init = function () {
this.count = -1;
this.body = $("<div style='border:none;padding:0px;'></div>");
this.head = $("<ul style='border:none;background:white;padding:0px;border-bottom: 1px solid #DADADA;border-radius:0px;'></ul>");
this.body.append(this.head);
this.body.tabs({
heightStyle: "content",
active: 0
});
};
TabsForm.prototype.addItem = function (name, gridForm) {
this.count = this.count + 1;
var head = $("<li style='background:white;border-left:1px solid #DADADA;border-top:1px solid #DADADA;border-right:1px solid #DADADA;'><a href='#tabs-" + this.count + "'>" + name + "</a></li>");
var body = $("<div id='tabs-" + this.count + "' style='padding:0px;'></div>");
body.append(gridForm.body);
this.head.append(head);
this.body.append(body);
this.body.tabs("destroy");
this.body.tabs({
heightStyle: "content",
active: this.count
});
if (this.body.find(".ui-tabs-panel").length === 1)
this.head.hide();
else
this.head.show();
return {head: head, body: body};
};
FormDesigner.extendNamespace('FormDesigner.main.TabsForm', TabsForm);
}());
(function () {
var TypesControl = {
title: "title",
subtitle: "subtitle",
label: "label", //deprecated
link: "link",
image: "image",
file: "file",
multipleFile: "multipleFile",
submit: "submit",
button: "button",
grid: "grid",
subform: "subform",
variable: "variable", //only variable
text: "text",
textarea: "textarea",
dropdown: "dropdown",
checkbox: "checkbox",
checkgroup: "checkgroup",
radio: "radio",
datetime: "datetime",
suggest: "suggest",
hidden: "hidden",
form: "form",
cell: "cell",
annotation: "label", //todo
geomap: "location",
qrcode: "scannerCode",
signature: "signature",
imagem: "imageMobile",
audiom: "audioMobile",
videom: "videoMobile",
panel: "panel",
msgPanel: "msgPanel"
};
FormDesigner.extendNamespace('FormDesigner.main.TypesControl', TypesControl);
}());
(function () {
var DialogStyle = function (dialog, type) {
var bo = dialog[0].parentNode;
bo.style.border = '1px solid rgba(0, 0, 0, 0.4)';
bo.style.borderRadius = '0px';
bo.style.padding = '0px';
var b = bo.previousSibling.style;
b.background = 'transparent';
b.backgroundColor = 'rgba(0, 0, 0, 0.4)';
b.opacity = '1';
var titleBar = bo.firstChild;
titleBar.style.border = 'none';
titleBar.style.borderRadius = '0px';
titleBar.style.background = '#3397e1';
titleBar.style.color = 'white';
titleBar.style.height = '25px';
titleBar.style.fontSize = '16px';
titleBar.style.fontFamily = 'SourceSansPro';
titleBar.style.fontWeight = 'normal';
titleBar.firstChild.style.marginTop = '5px';
titleBar.firstChild.style.textAlign = 'center';
var button = titleBar.firstChild.nextSibling;
button.style.background = '#3397e1';
button.style.border = 'none';
button.style.marginRight = '4px';
button.style.width = "18px";
button.style.height = "18px";
button.title = "close".translate();
var icon = button.firstChild;
icon.style.backgroundImage = 'url(' + $.imgUrl + 'fd-close.png)';
icon.style.margin = "0px";
icon.style.backgroundPosition = "0px 0px";
icon.style.left = "-3px";
icon.style.top = "-3px";
icon.style.width = "24px";
icon.style.height = "24px";
icon.parentNode.onmouseover = function () {
icon.style.backgroundImage = 'url(' + $.imgUrl + 'fd-closew.png)';
};
icon.parentNode.onmouseout = function () {
icon.style.backgroundImage = 'url(' + $.imgUrl + 'fd-close.png)';
};
icon.nextSibling.style.padding = "0px";
dialog.removeClass("ui-state-focus");
dialog.removeClass("ui-state-hover");
if (type === "alert") {
//red
titleBar.style.background = "#e84c3d";
button.style.background = "#e84c3d";
}
if (type === "warning") {
//yellow
titleBar.style.background = "#edb60b";
button.style.background = "#edb60b";
}
if (type === "success") {
//green
}
};
FormDesigner.extendNamespace('FormDesigner.main.DialogStyle', DialogStyle);
}());
(function () {
var Grid = function (parent) {
this.onSelect = new Function();
this.onRemove = new Function();
this.onRemoveItem = new Function();
this.onSetProperty = new Function();
this.onVariableDrawDroppedItem = new Function();
this.onDrawControl = new Function();
this.onDrawDroppedItem = new Function();
this.parent = parent;
this.properties = null;
this.variable = parent.variable;
this.disabled = false;
this.typesControlSupported = [
FormDesigner.main.TypesControl.link,
FormDesigner.main.TypesControl.file,
FormDesigner.main.TypesControl.multipleFile,
FormDesigner.main.TypesControl.text,
FormDesigner.main.TypesControl.textarea,
FormDesigner.main.TypesControl.dropdown,
FormDesigner.main.TypesControl.checkbox,
FormDesigner.main.TypesControl.datetime,
FormDesigner.main.TypesControl.suggest,
FormDesigner.main.TypesControl.hidden
];
Grid.prototype.init.call(this);
this._items = new PMUI.util.ArrayList();
};
Grid.prototype.init = function () {
var that = this;
this.body = $("" +
"<div class='itemVariables itemControls gridCellDragDrop fd-gridForm-grid' style='position:relative;font-size:11px;'>" +
"<div class='fd-gridForm-grid-griditem-gridtitle'></div>" +
"<div class='fd-gridForm-grid-griditem-gridplaceholder'>" + "Grid: drag & drop controls.<br>Supports: textbox, textarea, dropdown, checkbox, datetime, suggest, hidden, link, multiplefile.".translate() + "</div>" +
"</div>");
this.body.sortable({
placeholder: "fd-gridForm-grid-placeholder",
connectWith: ".gridCellDragDrop",
items: ">*:not(.fd-gridForm-grid-griditem-gridtitle):not(.fd-gridForm-grid-griditem-gridplaceholder)",
receive: function (event, ui) {
that.sourceNode = ui.sender;
that.targetNode = $(this);
},
stop: function (event, ui) {
if (ui.item.attr("variable"))
that.variable = JSON.parse(ui.item.attr("variable"));
that.targetNode = that.targetNode ? $(ui.item[0].parentNode) : that.targetNode;
if (ui.item.attr("render")) {
$(ui.item).remove();
var properties = that.drawDroppedItem(ui.item.attr("render"));
that.onDrawControl(properties);
}
}
});
this.body.on("click", function (e) {
e.stopPropagation();
$.designerSelectElement(this, function () {
if (that.disabled === true) {
return false;
}
that.onRemove();
});
that.onSelect(that.properties);
});
this.body.data("objectInstance", this);
this.properties = new FormDesigner.main.Properties(FormDesigner.main.TypesControl.grid, this.body, that);
this.properties.onSet = function (prop, value) {
that.onSetProperty(prop, value, that);
if (prop === "label") {
that.body.find(".fd-gridForm-grid-griditem-gridtitle").text(value);
}
};
this.properties.onClick = function (property) {
var dialogCreateVariable;
if (property === "variable") {
dialogCreateVariable = new FormDesigner.main.DialogCreateVariable(null, FormDesigner.main.TypesControl.grid, [], that.properties.get()[property].value);
dialogCreateVariable.onSave = function (variable) {
that.setVariable(variable);
};
dialogCreateVariable.onSelect = function (variable) {
dialogCreateVariable.dialog.dialog("close");
that.setVariable(variable);
};
FormDesigner.getNextNumberVar(that.getData(), that.properties, function (nextVar) {
dialogCreateVariable.setVarName(nextVar);
});
}
};
this.properties.onClickClearButton = function (property) {
var b;
if (property === "variable" && that.properties[property].value !== "") {
var a = new FormDesigner.main.DialogConfirmClearVariable();
a.onAccept = function () {
var label = that.properties.label.value;
that.parent.setNextLabel(that.properties);
that.properties.id.node.value = that.properties.id.value;
b = that.properties.set("variable", "");
b.node.textContent = "...";
b = that.properties.set("dataType", "");
b.node.textContent = "";
b = that.properties.set("label", label);
b.node.value = label;
b = that.properties.set("protectedValue", false);
b.node.checked = false;
};
}
};
};
Grid.prototype.drawDroppedItem = function (render) {
var that = this,
properties = null,
target = null;
switch (render) {
case FormDesigner.main.TypesControl.variable:
if (that.onVariableDrawDroppedItem(that.variable) === false)
return;
if (that.isVariableUsed(that.variable.var_uid)) {
var dialogInformation = new FormDesigner.main.DialogInformation();
dialogInformation.onAccept = function () {
};
return;
}
var dialogTypeControl = new FormDesigner.main.DialogTypeControl();
dialogTypeControl.load(that.variable);
dialogTypeControl.onSelectItem = function (event, item) {
that.drawDroppedItem(item.attr("render"));
that.variable = null;
};
dialogTypeControl.onClose = function () {
that.variable = null;
};
target = dialogTypeControl;
break;
case that.inTypesControl(render):
var gridItem = new FormDesigner.main.GridItem(render, that.variable, that);
gridItem.onSelect = function (properties) {
that.onSelect(properties);
};
gridItem.onRemove = function () {
that.onRemoveItem(this);
};
gridItem.onSetProperty = function (prop, value, target) {
that.onSetProperty(prop, value, target);
};
that.targetNode.append(gridItem.html);
properties = gridItem.properties;
target = gridItem;
break;
}
that.onDrawDroppedItem(render, target);
return properties;
};
Grid.prototype.inTypesControl = function (val) {
if ($.inArray(val, this.typesControlSupported) > -1) {
return val;
}
new FormDesigner.main.DialogUnsupported();//todo
return null;
};
Grid.prototype.getData = function () {
var columns = [], obj;
this.body.find(">div").each(function (i, ele) {
obj = $(ele).data("objectInstance");
if (obj) {
columns.push(obj.getData());
}
});
var prop = {};
var a = this.properties.get();
for (var b in a) {
prop[b] = a[b].value;
}
prop["columns"] = columns;
prop["title"] = prop.label;
return prop;
};
Grid.prototype.getVariables = function () {
var obj, variables = [], variable, i;
this.body.find(">div").each(function (ie, ele) {
obj = $(ele).data("objectInstance");
if (obj) {
variable = $(ele).data("objectInstance").variable;
for (i = 0; i < variables.length; i++) {
if (variable && variables[i] && variables[i].var_uid === variable.var_uid) {
break;
}
}
if (i === variables.length) {
variables.push(variable);
}
}
});
return variables;
};
Grid.prototype.isVariableUsed = function (var_uid) {
var that = this;
var variables = that.getVariables();
for (var i = 0; i < variables.length; i++) {
if (variables[i] && variables[i].var_uid === var_uid) {
return true;
}
}
return false;
};
Grid.prototype.getFieldObjects = function (filter) {
var a = [], obj;
this.body.find(">div").each(function (i, ele) {
obj = $(ele).data("objectInstance");
if (obj && filter.indexOf(obj.properties.type.value) > -1)
a.push(obj);
});
return a;
};
Grid.prototype.setDisabled = function (disabled) {
this.disabled = disabled;
var obj;
if (disabled) {
this.body.sortable("disable");
} else {
this.body.sortable("enable");
}
this.body.find(">div").each(function (i, ele) {
obj = $(ele).data("objectInstance");
if (obj && obj.setDisabled) {
obj.setDisabled(disabled);
}
});
this.properties.setDisabled(disabled);
};
Grid.prototype.setVariable = function (variable) {
var that = this, b;
that.variable = variable;
that.properties.set("var_uid", variable.var_uid);
b = that.properties.set("variable", variable.var_name);
if (b.node)
b.node.textContent = variable.var_name;
b = that.properties.set("dataType", variable.var_field_type);
if (b.node)
b.node.textContent = variable.var_field_type;
b = that.properties.set("id", variable.var_name);
if (b.node)
b.node.value = variable.var_name;
that.properties.set("name", variable.var_name);
};
/**
* Verify if in the grid exist a deprecated control.
* @return {number}
*/
Grid.prototype.checkForDeprecatedControls = function () {
return this._items.asArray().length;
};
/**
* Clear list of deprecated control in the grid.
*/
Grid.prototype.clearItemsDeprecated = function () {
var itemsGrid = this._items.asArray(),
i;
for (i = 0; i < itemsGrid.length; i+= 1) {
this.parent._items.remove(itemsGrid[i])
}
this._items.clear();
};
FormDesigner.extendNamespace('FormDesigner.main.Grid', Grid);
}());
(function () {
var GridItem = function (render, variable, parent) {
this.onSelect = new Function();
this.onRemove = new Function();
this.onSetProperty = new Function();
this.render = render;
this.variable = variable;
this.parent = parent;
this.disabled = false;
GridItem.prototype.init.call(this);
};
GridItem.prototype.init = function () {
var that = this,
html;
switch (this.render) {
case FormDesigner.main.TypesControl.text:
html = "<input type='text' value='' class='fd-gridForm-grid-text-column'>";
break;
case FormDesigner.main.TypesControl.textarea:
html = "<textarea class='fd-gridForm-grid-textarea-column' style='resize:none;'></textarea>";
break;
case FormDesigner.main.TypesControl.dropdown:
html = "<select class='fd-gridForm-grid-text-column' style='box-sizing:border-box;width:100%;'></select>";
break;
case FormDesigner.main.TypesControl.checkbox:
html = "<input type='checkbox'>";
break;
case FormDesigner.main.TypesControl.checkgroup:
html = "<input type='checkbox'>";
break;
case FormDesigner.main.TypesControl.radio:
html = "<input type='radio'>";
break;
case FormDesigner.main.TypesControl.datetime:
html = "<div style='height:18px;border:1px solid #c0c0c0;box-sizing:border-box;width:100%;background-color:white;'><span class='fd-gridForm-grid-suggest-placeholder'></span><img src='" + $.imgUrl + "fd-calendar.png' style='float:right;'/></div>";
break;
case FormDesigner.main.TypesControl.suggest:
html = "<div style='height:18px;border:1px solid #c0c0c0;box-sizing:border-box;width:100%;background-color:white;'><span class='fd-gridForm-grid-suggest-placeholder'></span><img src='" + $.imgUrl + "fd-ui-list-box.png' style='float:right;'/></div>";
break;
case FormDesigner.main.TypesControl.hidden:
html = "<div style='height:18px;border:1px dashed #c0c0c0;box-sizing:border-box;width:100%;background-color:white;'><img src='" + $.imgUrl + "fd-ui-text-field-hidden.png' style='float:right;'/></div>";
break;
case FormDesigner.main.TypesControl.title:
html = "<span>...</span>";
break;
case FormDesigner.main.TypesControl.subtitle:
html = "<span>...</span>";
break;
case FormDesigner.main.TypesControl.annotation:
html = "<span>...</span>";
break;
case FormDesigner.main.TypesControl.link:
html = "<span class='fd-gridForm-grid-link-column'></span>";
break;
case FormDesigner.main.TypesControl.image:
html = "<img src='" + $.imgUrl + "fd-image.png'/>";
break;
case FormDesigner.main.TypesControl.file:
html = "<button>Select file</button><span>No file was selected</span>";
case FormDesigner.main.TypesControl.multipleFile:
html = "<button>Select file</button><span>No file was selected</span>";
break;
case FormDesigner.main.TypesControl.submit:
html = "<input type='button' value='button'>";
break;
case FormDesigner.main.TypesControl.button:
html = "<input type='button' value='button'>";
break;
}
this.html = $(
"<div class=\"pm-mafe-grid-item\" pm-mafe-grid-item-type=\"" + this.render + "\" style='position:relative;background:white;'>" +
"<div style='font-weight:bold;margin-bottom:2px;text-align:center;background:#2d3e50;color:white;padding:5px;height:12px;'>" +
" <span class='fd-gridForm-grid-griditem-columnLabel'></span><span class='fd-gridForm-grid-griditem-columnRequired'>*</span>" +
"</div>" +
"<div class='fd-gridForm-grid-griditem-columnType' style='padding:2px;background:#eaebed;height:31px;'></div>" +
"</div>");
this.html.find(".fd-gridForm-grid-griditem-columnType").append(html);
this.html.data("objectInstance", this);
this.html.on("click", function (e) {
e.stopPropagation();
$.designerSelectElement(this, function () {
if (that.disabled === true) {
return false;
}
that.onRemove();
});
that.onSelect(that.properties, that);
});
this.properties = new FormDesigner.main.Properties(this.render, this.html, that);
this.properties.onClick = function (property) {
var a, b, fields, dialog;
if (property === "formula") {
fields = that.parent.getFieldObjects([
FormDesigner.main.TypesControl.text
]);
a = new FormDesigner.main.DialogFormula(null, fields);
a.onSave = function () {
that.properties.set(property, a.editor.getValue());
};
a.editor.setValue(that.properties.get()[property].value);
}
if (property === "dbConnectionLabel") {
a = new FormDesigner.main.DialogDBConnection(null);
a.onClick = function (option) {
a.dialog.dialog("close").remove();
b = that.properties.set(property, option.label);
b.node.textContent = option.label;
that.properties.set("dbConnection", option.value);
};
}
if (property === "inputDocument") {
dialog = new FormDesigner.main.DialogInputDocument(null);
dialog.onClick = function (option) {
dialog.dialog.dialog("close").remove();
that.setInputDocument({
size: {
value: option.inp_doc_max_filesize,
disabled: true
},
sizeUnity: {
value: option.inp_doc_max_filesize_unit,
disabled: true
},
extensions: {
value: option.inp_doc_type_file,
disabled: true
},
enableVersioning: {
value: (option.inp_doc_versioning) ? true : false,
disabled: true
},
inp_doc_uid: {
value: option.inp_doc_uid,
disabled: true
},
inputDocument: {
value: option.inp_doc_title,
disabled: false
}
});
};
return false;
}
if (property === "sql") {
a = new FormDesigner.main.DialogSql(null);
a.onSave = function () {
b = that.properties.set(property, a.editor.getValue());
b.node.textContent = a.editor.getValue();
};
a.editor.setValue(that.properties.get()[property].value);
}
if (property === "options") {
a = new FormDesigner.main.DialogOptions(null, that.properties.get()[property].value);
a.onApply = function () {
b = that.properties.set(property, a.getOptions());
b.node.textContent = JSON.stringify(a.getOptions());
};
if (that.properties.dataType.value === "boolean") {
a.setOptionsBoolean();
}
}
if (property === "validate") {
a = new FormDesigner.main.DialogRegularExpression(null, that.properties["dataType"].value);
a.onClick = function (regex) {
a.dialog.dialog("close").remove();
b = that.properties.set("validate", regex.value);
b.node.value = regex.value;
};
}
if (property === "dataVariable") {
a = new FormDesigner.main.DialogVariable(null, FormDesigner.main.TypesControl.checkgroup);
a.onClick = function (variable) {
a.dialog.dialog("close").remove();
b = that.properties.set("dataVariable", "@@" + variable.var_name);
if (b.node)
b.node.value = variable.var_name;
};
a.load();
}
};
this.properties.onSet = function (prop, value) {
that.onSetProperty(prop, value, that);
if (prop === "label") {
that.html.find(".fd-gridForm-grid-griditem-columnLabel").text(value);
}
if (prop === "value") {
that.html.find(".fd-gridForm-grid-link-column").text(value);
}
if (prop === "required") {
if (value)
that.html.find(".fd-gridForm-grid-griditem-columnRequired").show();
else
that.html.find(".fd-gridForm-grid-griditem-columnRequired").hide();
}
if (prop === "options") {
that.html.find(".fd-gridForm-grid-text-column").empty();
for (var i = 0; i < value.length; i++) {
that.html.find(".fd-gridForm-grid-text-column").append("<option value='" + value[i].value + "'>" + value[i].label + "</option>");
}
}
if (prop === "placeholder") {
that.html.find(".fd-gridForm-grid-text-column").attr("placeholder", value);
that.html.find(".fd-gridForm-grid-textarea-column").attr("placeholder", value);
that.html.find(".fd-gridForm-grid-suggest-placeholder").text(value);
}
};
this.properties.onGet = function (properties) {
if (that.parent.properties.get().layout.value === "form") {
that.properties.columnWidth.type = "hidden";
that.properties.columnWidth.helpButton = "";
}
if (that.parent.properties.get().layout.value === "responsive") {
that.properties.columnWidth.type = "text";
that.properties.columnWidth.helpButton = "Percentage value.";
}
if (that.parent.properties.get().layout.value === "static") {
that.properties.columnWidth.type = "text";
that.properties.columnWidth.helpButton = "Pixel value.";
}
};
// This section reset properties in clearbutton in grids
this.properties.onClickClearButton = function (property) {
if (property === "inputDocument") {
that.setInputDocument({
size: {
value: 0,
disabled: false
},
sizeUnity: {
value: 'MB',
disabled: false
},
extensions: {
value: '*',
disabled: false
},
enableVersioning: {
value: false,
disabled: true
},
inp_doc_uid: {
value: '',
disabled: true
},
inputDocument: {
value: '...',
disabled: false
}
});
}
};
this.createDeprecatedIcon();
};
GridItem.prototype.getData = function () {
var prop = {};
var a = this.properties.get();
for (var b in a) {
prop[b] = a[b].value;
}
prop["width"] = 100;//todo
prop["title"] = prop.label;
if (this.variable) {
prop["var_name"] = this.variable.var_name;
}
return prop;
};
GridItem.prototype.setDisabled = function (disabled) {
this.disabled = disabled;
this.properties.setDisabled(disabled);
};
/**
* Set properties for input document
* @param params
*/
GridItem.prototype.setInputDocument = function (params) {
var property,
key;
for (key in params) {
property = this.properties.set(key, params[key].value);
switch (key) {
case 'inp_doc_uid':
break;
case 'inputDocument':
if (property.node) {
property.node.textContent = params[key].value;
property.value = (params[key].value === '...') ? '' : params[key].value;
}
break;
case 'enableVersioning':
if (property.node) {
property.node.textContent = (params[key].value) ? 'Yes' : 'No';
}
default:
if (property.node) {
property.node.value = params[key].value;
property.node.disabled = params[key].disabled;
}
break;
}
}
};
/**
* Create deprecation icon.
*/
GridItem.prototype.createDeprecatedIcon = function () {
this.deprecatedIcon = $("<div class='mafe-deprecated-control'></div>");
this.deprecatedIcon.attr('title', "");
this.deprecatedIcon.hide();
this.deprecatedIcon.tooltip({
content: FormDesigner.DEPRECATION_TEXT,
close: function (event, ui) {
ui.tooltip.hover(function () {
$(this).stop(true).fadeTo(400, 1);
}, function () {
$(this).fadeOut("400", function () {
$(this).remove();
});
});
}
});
this.html.find('.fd-gridForm-grid-griditem-columnLabel').parent().prepend(this.deprecatedIcon);
};
/**
* Enable or disable deprecated icon.
* @param {boolean} status
*/
GridItem.prototype.deprecated = function (status) {
if (status === true) {
this.deprecatedIcon.show();
} else {
this.deprecatedIcon.hide();
}
};
FormDesigner.extendNamespace('FormDesigner.main.GridItem', GridItem);
}());
(function () {
var Preview = function (dyn_uid, dyn_title, prj_uid, iframeOptions) {
this.dyn_uid = dyn_uid;
this.dyn_title = dyn_title;
this.prj_uid = prj_uid;
this.onClose = new Function();
Preview.prototype.init.call(this, iframeOptions);
};
Preview.prototype.init = function (iframeOptions) {
var that = this,
defaultIframeOptions = {
id: 'pm-dynaform-preview-iframe',
name: 'pm-dynaform-preview-iframe'
};
jQuery.extend(true, defaultIframeOptions, iframeOptions);
this.srcPreview = 'cases/pmDynaform?dyn_uid=' + this.dyn_uid + "&prj_uid=" + this.prj_uid;
this.desktop = $("<div class='fd-designer-button' title='" + "Desktop".translate() + "'><img src='" + $.imgUrl + "fd-desktop.png' style='width:24px;height:24px;'/></div>");
this.desktop.on("click", function () {
that.iframe.css('width', '100%');
return false;
});
$.hoverToolbarButtons(this.desktop, "fd-desktop.png", "fd-desktopw.png");
this.tablet = $("<div class='fd-designer-button' title='" + "Tablet".translate() + "'><img src='" + $.imgUrl + "fd-tablet.png' style='width:24px;height:24px;'/></div>");
this.tablet.on("click", function () {
that.iframe.css('width', '800px');
return false;
});
$.hoverToolbarButtons(this.tablet, "fd-tablet.png", "fd-tabletw.png");
this.smartphone = $("<div class='fd-designer-button' title='" + "Smartphone".translate() + "'><img src='" + $.imgUrl + "fd-mobile_phone.png' style='width:24px;height:24px;'/></div>");
this.smartphone.on("click", function () {
that.iframe.css('width', '400px');
return false;
});
$.hoverToolbarButtons(this.smartphone, "fd-mobile_phone.png", "fd-mobile_phonew.png");
this.back = $("<div class='fd-designer-button' title='" + "Close".translate() + "'><img src='" + $.imgUrl + "fd-close.png' style='width:24px;height:24px;'/></div>");
this.back.on("click", function () {
that.close();
return false;
});
$.hoverToolbarButtons(this.back, "fd-close.png", "fd-closew.png");
this.title = $("<div style='float:left;font-family:Montserrat,sans-serif;font-size:20px;color:white;margin:5px;white-space:nowrap;'></div>");
this.title.text(this.dyn_title).attr("title", this.dyn_title).tooltip({
tooltipClass: "fd-tooltip",
position: {my: "left top+1"}
});
this.buttons = $("<div style='position:absolute;right:0px;background-color:#3397e1;'>");
this.buttons.append(this.desktop);
this.buttons.append(this.tablet);
this.buttons.append(this.smartphone);
this.buttons.append(this.back);
this.toolbar = $("<div class='fd-toolbar-preview' style='overflow:hidden;width:100%;height:33px;background-color:#3397e1;margin-bottom:15px;border:1px solid #2979b8;'></div>");
this.toolbar.append(this.title);
this.toolbar.append(this.buttons);
this.iframe = $("<iframe></iframe>");
this.iframe.attr("id", defaultIframeOptions.id);
this.iframe.attr("name", defaultIframeOptions.name);
this.iframe.css("border", "none");
this.iframe.css("width", "100%");
this.iframe.css("height", "100%");
this.body = $("<div style='z-index:100;position:absolute;top:0;right:0;bottom:35px;left:0;'></div>");
this.body.append(this.toolbar);
this.body.append(this.iframe);
};
Preview.prototype.show = function () {
jQuery('body').append(this.body);
this.body.show();
};
Preview.prototype.close = function () {
this.onClose();
this.body.remove();
};
Preview.prototype.setData = function () {
var that = this;
that.iframe[0].src = this.srcPreview;
that.iframe[0].onload = function () {
var pm = this.contentWindow.window;
if (pm && pm.PMDynaform) {
pm.dynaform = new pm.PMDynaform.core.Project({
data: this.contentWindow.window.jsonData,
keys: {
server: HTTP_SERVER_HOSTNAME,
projectId: PMDesigner.project.id,
workspace: WORKSPACE
},
token: {
accessToken: PMDesigner.project.keys.access_token
},
isPreview: true,
isRTL: this.contentWindow ? this.contentWindow.window.isRTL : false
});
$(this.contentWindow.document).find('form').submit(function (e) {
e.preventDefault();
return false;
});
if (pm.PMDynaform.view && pm.PMDynaform.view.ModalProgressBar) {
pm.PMDynaform.view.ModalProgressBar.prototype.render = function () {
return this;
};
}
}
};
};
FormDesigner.extendNamespace('FormDesigner.main.Preview', Preview);
}());
(function () {
var DialogConfirmClose = function (appendTo) {
this.onAccept = new Function();
DialogConfirmClose.prototype.init.call(this, appendTo);
};
DialogConfirmClose.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "No".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Confirm".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Do you want to close? All your changes will be lost if you close it.".translate() +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogConfirmClose', DialogConfirmClose);
}());
(function () {
var DialogInvalidProperties = function (appendTo) {
this.onAccept = new Function();
DialogInvalidProperties.prototype.init.call(this, appendTo);
};
DialogInvalidProperties.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Ok".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Errors".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: true,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "alert");
var msg = "";
var dt = $.globalInvalidProperties;
for (var i = 0; i < dt.length; i++) {
msg = msg + dt[i] + "<br> ";
}
msg = msg.replace(/[,\s]+$/, "");
this.dialog.append("<div style='font-size:14px;margin:20px;height:60px;overflow-y:auto;'>" +
"Properties invalid elements:<br><br>".translate() + msg +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogInvalidProperties', DialogInvalidProperties);
}());
(function () {
var DialogConfirmImport = function (appendTo) {
this.onAccept = new Function();
DialogConfirmImport.prototype.init.call(this, appendTo);
};
DialogConfirmImport.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "No".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Confirm".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Do you want to import? All your changes will be lost if you import it.".translate() +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogConfirmImport', DialogConfirmImport);
}());
(function () {
var DialogConfirmClear = function (appendTo) {
this.onAccept = new Function();
DialogConfirmClear.prototype.init.call(this, appendTo);
};
DialogConfirmClear.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "No".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Confirm".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Do you want to clear? All your changes will be lost if you clear it.".translate() +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogConfirmClear', DialogConfirmClear);
}());
(function () {
var DialogInformation = function (appendTo) {
this.onAccept = new Function();
DialogInformation.prototype.init.call(this, appendTo);
};
DialogInformation.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Information".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"The variable is being used.".translate() +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogInformation', DialogInformation);
}());
(function () {
var DialogScript = function (appendTo) {
this.onSave = new Function();
this.onClose = new Function();
DialogScript.prototype.init.call(this, appendTo);
};
DialogScript.prototype.init = function (appendTo) {
var that = this;
this.save = $("<a href='#' class='fd-button fd-button-success'>" + "Save".translate() + "</a>");
this.save.on("click", function () {
that.onSave();
that.dialog.dialog("close").remove();
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "Cancel".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close").remove();
return false;
});
this.buttons = $("<div class='fd-button-panel'><div style='float:right'></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.save);
$.ui.keyCode.TAB = null;//focus button prevents dialog with CodeMirror tab
this.dialog = $("<div title='" + "Javascript".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 940,
height: 500,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
$.ui.keyCode.TAB = 9;
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.textarea = $("<textarea></textarea>");
this.body = $("<div style='border:1px solid #bbb;'></div>");
this.body.append(this.textarea);
this.dialog.append(this.body);
this.dialog.append("<p>" + "Press".translate() + " <strong>ctrl-space</strong> " + "to activate autocompletion".translate() + ".</p>");
this.dialog.append(this.buttons);
this.editor = CodeMirror.fromTextArea(this.textarea[0], {
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
mode: "application/javascript",
viewportMargin: Infinity,
className: "CodeMirror-hints-custom-mafe"
});
this.editor.setSize(910, 350);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogScript', DialogScript);
}());
(function () {
var DialogFormula = function (appendTo, fields) {
this.onSave = new Function();
this.onClose = new Function();
this.fields = fields;
DialogFormula.prototype.init.call(this, appendTo);
};
DialogFormula.prototype.init = function (appendTo) {
var that = this;
this.save = $("<a href='#' class='fd-button fd-button-success'>" + "Save".translate() + "</a>");
this.save.on("click", function () {
that.onSave();
that.dialog.dialog("close").remove();
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "Cancel".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close").remove();
return false;
});
this.buttons = $("<div class='fd-button-panel'><div style='float:right'></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.save);
$.ui.keyCode.TAB = null;//focus button prevents dialog with CodeMirror tab
this.dialog = $("<div title='" + "Formula".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 940,
height: 500,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
$.ui.keyCode.TAB = 9;
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.textarea = $("<textarea></textarea>");
this.body = $("<div style='border:1px solid #bbb;'></div>");
this.body.append(this.textarea);
this.dialog.append(this.body);
this.dialog.append("<p>" + "Press".translate() + " <strong>ctrl-space</strong> " + "to activate autocompletion".translate() + ".</p>");
this.dialog.append(this.buttons);
this.editor = CodeMirror.fromTextArea(this.textarea[0], {
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
mode: "application/javascript",
viewportMargin: Infinity,
className: "CodeMirror-hints-custom-mafe"
});
this.editor.setSize(910, 350);
//add elements for codemirror autocomplete
CodeMirror.hint.javascript = function (cm) {
var inner = {from: cm.getCursor(), to: cm.getCursor(), list: []};
for (var i = 0; i < that.fields.length; i++) {
if (that.fields[i].var_name) {
inner.list.push(that.fields[i].var_name);
}
}
var others = [
"parseInt()",
"parseFloat()",
".concat()",
".toString()",
".toUpperCase()",
".toLowerCase()",
".indexOf()",
".substring()",
".lastIndexOf()",
".split()"
];
for (var i = 0; i < others.length; i++) {
inner.list.push(others[i]);
}
return inner;
};
};
FormDesigner.extendNamespace('FormDesigner.main.DialogFormula', DialogFormula);
}());
(function () {
var DialogInvalidFile = function (appendTo, msg) {
this.onAccept = new Function();
this.msg = msg;
DialogInvalidFile.prototype.init.call(this, appendTo);
};
DialogInvalidFile.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-success'>" + "Ok".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Errors".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "alert");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Invalid file: ".translate() + that.msg + ". " +
"Please upload a file with a valid extension (.json)".translate() + "." +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogInvalidFile', DialogInvalidFile);
}());
(function () {
var DialogVariable = function (appendTo, render) {
this.render = render;
this.onClose = new Function();
this.onLoad = new Function();
this.onClick = new Function();
DialogVariable.prototype.init.call(this, appendTo);
};
DialogVariable.prototype.init = function (appendTo) {
var that = this;
this.dialog = $("<div title='" + "Variable".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.search = $("<div style='padding-bottom:10px;'><span style='vertical-align:top;'>" + "Search".translate() + " : </span><input type='text'/><img src='" + $.imgUrl + "fd-refresh.png' style='margin-top:-4px;vertical-align:middle;cursor: pointer;' title='" + "refresh".translate() + "'></div>");
this.search.find("input").on("keyup", function () {
var input = this;
that.body.find(">div").each(function (i, e) {
var sw = false;
$(e).find(">div").each(function (i, e) {
sw = sw || $(e).text().toLowerCase().indexOf(input.value.toLowerCase()) > -1;
});
if (sw)
$(e).show();
else
$(e).hide();
});
});
this.search.find("img").on("click", function () {
that.load();
});
this.body = $("<div style='overflow-x:hidden;border:1px solid #bbb;height:305px;'></div>");
this.dialog.append(this.search);
this.dialog.append(this.body);
};
DialogVariable.prototype.load = function () {
var that = this;
this.body.find(">div").remove();
var restProxy = new PMRestClient({
endpoint: 'process-variables',
typeRequest: 'get',
functionSuccess: function (xhr, response) {
response.sort(function (a, b) {
if (a.var_name < b.var_name)
return -1;
if (a.var_name > b.var_name)
return 1;
return 0;
});
for (var i = 0; i < response.length; i++) {
$.validDataTypeAndControlType(response[i].var_field_type, that.render, function () {
that.addItem(response[i]);
});
}
that.onLoad(response);
}
});
restProxy.executeRestClient();
};
DialogVariable.prototype.addItem = function (variable) {
var that = this;
var item = $("<div class='fd-list' style='cursor:pointer;'>" +
"<div style='width:auto;display:inline-block;margin:1px;color:rgb(238, 113, 15);'>[" + variable.var_field_type + "]</div>" +
"<div style='width:auto;display:inline-block;color:rgb(33, 54, 109);'>" + variable.var_name + "</div>" +
"</div>");
item.on("click", function () {
that.onClick(variable);
});
this.body.append(item);
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogVariable', DialogVariable);
}());
(function () {
var DialogDBConnection = function (appendTo) {
this.onClose = new Function();
this.onLoad = new Function();
this.onClick = new Function();
DialogDBConnection.prototype.init.call(this, appendTo);
};
DialogDBConnection.prototype.init = function (appendTo) {
var that = this;
this.dialog = $("<div title='" + "Database Connection".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.search = $("<p>" + "Search".translate() + " : <input type='text'/><img src='" + $.imgUrl + "fd-refresh.png' style='margin-top:-4px;vertical-align:middle;cursor: pointer;' title='" + "refresh".translate() + "'></p>");
this.search.find(">input").on("keyup", function () {
var input = this;
that.body.find(">div").each(function (i, e) {
var sw = false;
$(e).find(">div").each(function (i, e) {
sw = sw || $(e).text().toLowerCase().indexOf(input.value.toLowerCase()) > -1;
});
if (sw)
$(e).show();
else
$(e).hide();
});
});
this.search.find("img").on("click", function () {
that.load();
});
this.body = $("<div style='overflow-x:hidden;border:1px solid #bbb;height:305px;'></div>");
this.dialog.append(this.search);
this.dialog.append(this.body);
this.load();
};
DialogDBConnection.prototype.load = function () {
var that = this;
this.body.find(">div").remove();
that.addItem({label: "PM Database", value: "workflow"});
var restProxy = new PMRestClient({
endpoint: "database-connections",
typeRequest: "get",
functionSuccess: function (xhr, response) {
for (var i = 0; i < response.length; i++) {
if (response[i].dbs_connection_type === "TNS") {
that.addItem({
label: "[" + response[i].dbs_tns + "] " + response[i].dbs_type + " : " + response[i].dbs_database_description,
value: response[i].dbs_uid
});
} else {
that.addItem({
label: "[" + response[i].dbs_server + ":" + response[i].dbs_port + "] " + response[i].dbs_type + ": " + response[i].dbs_database_name + response[i].dbs_database_description,
value: response[i].dbs_uid
});
}
}
that.onLoad(response);
}
});
restProxy.executeRestClient();
};
DialogDBConnection.prototype.addItem = function (variable) {
var that = this;
var item = $("<div class='fd-list' style='cursor:pointer;'>" +
"<div style='width:auto;display:inline-block;color:rgb(33, 54, 109);'>" + variable.label + "</div>" +
"</div>");
item.on("click", function () {
that.onClick(variable);
});
this.body.append(item);
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogDBConnection', DialogDBConnection);
}());
(function () {
var DialogSql = function (appendTo) {
this.onSave = new Function();
this.onClose = new Function();
DialogSql.prototype.init.call(this, appendTo);
};
DialogSql.prototype.init = function (appendTo) {
var that = this;
this.save = $("<a href='#' class='fd-button fd-button-success'>" + "Save".translate() + "</a>");
this.save.on("click", function () {
that.onSave();
that.dialog.dialog("close").remove();
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "Cancel".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close").remove();
return false;
});
this.buttons = $("<div class='fd-button-panel'><div style='float:right'></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.save);
$.ui.keyCode.TAB = null;//focus button prevents dialog with CodeMirror tab
this.dialog = $("<div title='" + "SQL Editor".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 940,
height: 500,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
$.ui.keyCode.TAB = 9;
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.textarea = $("<textarea></textarea>");
this.body = $("<div style='border:1px solid #bbb;'></div>");
this.body.append(this.textarea);
this.dialog.append(this.body);
this.dialog.append("<p>" + "Press".translate() + " <strong>ctrl-space</strong> " + "to activate autocompletion".translate() + ".</p>");
this.dialog.append(this.buttons);
this.editor = CodeMirror.fromTextArea(this.textarea[0], {
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
mode: "text/x-sql",
viewportMargin: Infinity,
className: "CodeMirror-hints-custom-mafe"
});
this.editor.setSize(910, 350);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogSql', DialogSql);
}());
(function () {
var DialogOptions = function (appendTo, options) {
this.onApply = new Function();
this.onClose = new Function();
this.appendTo = appendTo;
this.options = options;
DialogOptions.prototype.init.call(this);
};
DialogOptions.prototype.init = function () {
var that = this;
this.save = $("<a href='#' class='fd-button fd-button-success'>" + "Apply".translate() + "</a>");
this.save.on("click", function () {
if (!that.isValid()) {
return false;
}
that.onApply();
that.dialog.dialog("close").remove();
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "Cancel".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close").remove();
return false;
});
this.buttons = $("<div class='fd-button-panel'><div style='float:right'></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.save);
this.edit = $("<input type='text' style='width:100%;height:100%;box-sizing:border-box;'/>");
this.add = $("<a href='#' class='fd-button fd-button-create' style='float:right;padding:7px 10px 7px 35px;margin-bottom:5px;'>" + "Create".translate() + "</a>");
this.add.on("click", function () {
var row = that.addItem("", "");
var cells = row.find(".fd-table-td-edit");
that.setInputEdit($(cells[0]));
return false;
});
this.add.on("keydown", function (e) {
var row = that.table.find("tr");
if (row.length > 0 && e.keyCode === 9 && !e.shiftKey) {
that.setInputEdit($($(row[1]).find(".fd-table-td-edit")[0]));
return false;
}
});
this.tbody = $("<tbody class='fd-tbody'></tbody>");
this.tbody.sortable({
placeholder: "fd-drag-drop-placeholder",
handle: ".fd-drag-drop",
stop: function (event, ui) {
},
start: function (event, ui) {
ui.placeholder.html("<td class='fd-drag-drop-placeholder' colspan='6'></td>")
}
}).droppable({
drop: function (event, ui) {
}
});
this.table = $(
"<table class='fd-table' style='width:100%;border:1px solid #bbb;'>" +
"<thead>" +
"<th class='fd-table-th' style='height:21px;width:16px;font-size:14px;'>" + "Key".translate() + "</th>" +
"<th class='fd-table-th' style='height:21px;width:auto;font-size:14px;'>" + "Label".translate() + "</th>" +
"<th class='fd-table-th' style='height:21px;width:40px;font-size:14px;'></th>" +
"</thead>" +
"</table>");
this.table.append(this.tbody);
this.msgError = $("<div style='color:red;'></div>");
this.dialog = $("<div title='" + "Options".translate() + "'></div>");
this.dialog.dialog({
appendTo: this.appendTo ? this.appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.dialog.append("<p>" + "Please add option and click in cell for editing the cell value".translate() + ".</p>");
this.dialog.append(this.add);
this.dialog.append($("<div style='overflow-y:auto;height:210px;width:100%;'></div>").append(this.table));
this.dialog.append(this.msgError);
this.dialog.append(this.buttons);
this.load();
};
DialogOptions.prototype.load = function () {
for (var i = 0; i < this.options.length; i++)
this.addItem(this.options[i].value, this.options[i].label);
};
DialogOptions.prototype.addItem = function (value, label) {
var that = this, cell;
var del = $("<td class='fd-table-td' style='text-align:center;height:27px;'>" +
"<a href='#' class='fd-button fd-button-no' style='margin:0px 5px 0px 5px;font-family:SourceSansPro,Arial,Tahoma,Verdana;font-size:14px;padding: 5px 5px;'>" + "Delete".translate() + "</a>" +
"<img class='fd-drag-drop' src='" + $.imgUrl + "fd-dragdrop.png' title='" + "up & down".translate() + "'/>" +
"</td>");
del.find(".fd-button").on("click", function () {
var a = new FormDesigner.main.DialogConfirmDeleteOption();
a.onAccept = function () {
del.parent().remove();
};
return false;
});
del.find(".fd-button").on("keydown", function (e) {
var ri = $(this).parent().parent()[0].rowIndex + 1;
if (e.keyCode === 9 && !e.shiftKey && that.table.find("tr").length > ri) {
that.setInputEdit($($(that.table.find("tr")[ri]).find(".fd-table-td-edit")[0]));
return false;
}
if (e.keyCode === 9 && e.shiftKey) {
var row = $(this).parent().parent();
that.setInputEdit($($(row).find(".fd-table-td-edit")[1]));
return false;
}
});
var row = $("<tr style='height:20px;'></tr>");
cell = $("<td class='fd-table-td fd-table-td-edit' style='padding:0px 2px 0px 1px;'></td>").text(value);
row.append(cell);
cell = $("<td class='fd-table-td fd-table-td-edit' style='padding:0px 2px 0px 1px;'></td>").text(label);
row.append(cell);
row.append(del);
row.find(".fd-table-td-edit").on("click", function (e) {
e.stopPropagation();
that.setInputEdit($(e.target));
return false;
});
this.tbody.append(row);
return row;
};
DialogOptions.prototype.getOptions = function () {
var a = [];
if (this.edit.parent()[0] && this.edit.parent()[0].nodeName === "TD") {
this.edit.parent().text(this.edit.val().trim());
this.edit.remove();
}
var aux = "";
this.tbody.find(".fd-table-td-edit").each(function (i, e) {
if (i % 2 === 1) {
a.push({
value: aux,
label: $(e).text()
});
}
aux = $(e).text();
});
return a;
};
DialogOptions.prototype.isValid = function () {
this.tbody.find(".fd-table-td-edit").removeClass("fd-table-td-error");
var options = this.getOptions();
for (var i = 0; i < options.length; i++) {
for (var j = 0; j < options.length; j++) {
if (i !== j && options[j].value === options[i].value) {
this.msgError.text("Duplicate value for key".translate() + ".");
$(this.tbody.find("tr")[j]).find(".fd-table-td-edit").addClass("fd-table-td-error");
return false;
}
if (options[j].label === "") {
this.msgError.text("The label is empty".translate() + ".");
$(this.tbody.find("tr")[j]).find(".fd-table-td-edit").addClass("fd-table-td-error");
return false;
}
}
}
this.msgError.text("");
return true;
};
DialogOptions.prototype.setOptionsBoolean = function () {
this.tbody.find("tr").each(function (i, e) {
$(e).find(".fd-table-td-edit").each(function (i, cell) {
if (0 === i)
$(cell).off();
});
$(e).find(".fd-button").hide();
$(e).find(".fd-drag-drop").hide();
});
this.add.hide();
};
DialogOptions.prototype.setInputEdit = function (cell) {
var that = this;
if (that.edit.parent()[0] && that.edit.parent()[0].nodeName === "TD") {
that.edit.parent().text(that.edit.val().trim());
}
that.edit.val(cell.text());
cell.text("");
cell.append(that.edit);
setTimeout(function () {
that.edit.focus();
}, 50);
that.edit.on("click", function (e) {
e.stopPropagation();
return false;
});
that.edit.on("keydown", function (e) {
var cell = that.edit.parent();
var ci = cell[0].cellIndex;
if (e.keyCode === 9 && ci === 0 && !e.shiftKey) {
that.setInputEdit(cell.next());
return false;
}
if (e.keyCode === 9 && ci === 1 && e.shiftKey) {
that.setInputEdit(cell.prev());
return false;
}
});
};
FormDesigner.extendNamespace('FormDesigner.main.DialogOptions', DialogOptions);
}());
(function () {
var DialogLanguage = function (appendTo, dyn_uid) {
this.onClose = new Function();
this.onLoad = new Function();
this.dyn_uid = dyn_uid;
DialogLanguage.prototype.init.call(this, appendTo);
};
DialogLanguage.prototype.init = function (appendTo) {
var that = this;
this.dialog = $("<div title='" + "Languages".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.uploadFile = $("<form style='margin-top:11px;float:right;'>" +
"<input type='file' name='LANGUAGE' class='fd-gridform-language-upload'/>" +
"</form>");
this.uploadFile.find(".fd-gridform-language-upload").on("change", function (e) {
var win = window, fd = new FormData(), xhr, val = 'LANGUAGE';
fd.append(val, e.target.files[0]);
if (win.XMLHttpRequest)
xhr = new XMLHttpRequest();
else if (win.ActiveXObject)
xhr = new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('POST', '/api/1.0/' + WORKSPACE + '/project/' + PMDesigner.project.id + '/dynaform/' + that.dyn_uid + '/upload-language', true);
xhr.setRequestHeader('Authorization', 'Bearer ' + PMDesigner.project.keys.access_token);
xhr.onload = function () {
if (this.status === 200) {
that.uploadFile[0].reset();
that.load();
} else {
that.uploadFile[0].reset();
}
};
xhr.send(fd);
});
this.search = $("<p>" + "Search".translate() + " : <input type='text'/><img src='" + $.imgUrl + "fd-refresh.png' style='margin-top:-4px;vertical-align:middle;cursor: pointer;' title='" + "refresh".translate() + "'></p>");
this.search.find(">input").on("keyup", function () {
var input = this;
that.body.find(">div").each(function (i, e) {
var sw = false;
$(e).find(">div").each(function (i, e) {
sw = sw || $(e).text().toLowerCase().indexOf(input.value.toLowerCase()) > -1;
});
if (sw)
$(e).show();
else
$(e).hide();
});
});
this.search.find("img").on("click", function () {
that.load();
});
this.body = $("<div style='overflow-x:hidden;border:1px solid #bbb;height:305px;'></div>");
this.dialog.append(this.uploadFile);
this.dialog.append(this.search);
this.dialog.append(this.body);
this.load();
};
DialogLanguage.prototype.load = function () {
var that = this;
this.body.find(">div").remove();
var restProxy = new PMRestClient({
endpoint: "dynaform/" + this.dyn_uid + "/list-language",
typeRequest: "get",
functionSuccess: function (xhr, response) {
//default lang
var item = that.addItem({
label: "English [processmaker.en.po]",
value: "en"
});
item.find(".fd-button").hide();
//lang
for (var i = 0; i < response.length; i++) {
that.addItem({
label: response[i]["X-Poedit-Language"] + " [" + response[i]["File-Name"] + "]",
value: response[i].Lang
});
}
that.onLoad(response);
}
});
restProxy.executeRestClient();
};
DialogLanguage.prototype.addItem = function (variable) {
var that = this;
var item = $("<div class='fd-list' style='cursor:pointer;height:27px;'>" +
"<div style='width:410px;display:inline-block;color:rgb(33, 54, 109);'>" + variable.label + "</div>" +
"<div style='width:auto;display:inline-block;color:rgb(33, 54, 109);'>" +
"<a href='#' class='fd-button fd-button-no' style='margin:0px 5px 0px 5px;font-family:SourceSansPro,Arial,Tahoma,Verdana;font-size:14px;padding:5px 5px;'>" + "Delete".translate() + "</a>" +
"</div>" +
"</div>");
item.find(".fd-button").on("click", function (e) {
e.stopPropagation();
var a = new FormDesigner.main.DialogConfirmDeleteLang();
a.onAccept = function () {
var restProxy = new PMRestClient({
endpoint: "dynaform/" + that.dyn_uid + "/delete-language/" + variable.value,
typeRequest: "post",
functionSuccess: function (xhr, response) {
that.load();
}
});
restProxy.executeRestClient();
}
return false;
});
item.on("click", function (e) {
e.stopPropagation();
var restProxy = new PMRestClient({
endpoint: "dynaform/" + that.dyn_uid + "/download-language/" + variable.value,
typeRequest: "get",
functionSuccess: function (xhr, response) {
var name = "processmaker." + response.lang + ".po";
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(new Blob([response.labels], {'type': 'application/octet-stream'}), name);
return false;
}
var a = document.createElement('a');
document.body.appendChild(a);
a.href = window.URL.createObjectURL(new Blob([response.labels], {'type': 'application/octet-stream'}));
a.download = name;
a.click();
document.body.removeChild(a);
}
});
restProxy.executeRestClient();
return false;
});
this.body.append(item);
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogLanguage', DialogLanguage);
}());
(function () {
var DialogConfirmDeleteLang = function (appendTo) {
this.onAccept = new Function();
DialogConfirmDeleteLang.prototype.init.call(this, appendTo);
};
DialogConfirmDeleteLang.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "No".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Confirm".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Do you want to delete this lang?".translate() + "." +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogConfirmDeleteLang', DialogConfirmDeleteLang);
}());
(function () {
var DialogConfirmDeleteOption = function (appendTo) {
this.onAccept = new Function();
DialogConfirmDeleteOption.prototype.init.call(this, appendTo);
};
DialogConfirmDeleteOption.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "No".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Confirm".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Do you want to delete this option?".translate() + "." +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogConfirmDeleteOption', DialogConfirmDeleteOption);
}());
(function () {
var DialogInvalid = function (appendTo, property, type, config) {
this.property = property;
this.type = type;
this.config = config || null;
this.onAccept = new Function();
this.onClose = new Function();
DialogInvalid.prototype.init.call(this, appendTo);
};
DialogInvalid.prototype.init = function (appendTo) {
var that = this,
configDialog = this.getErrorMessage(this.type, this.property, this.config);
this.accept = $("<a href='#' class='fd-button fd-button-success'>" + "Ok".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + configDialog.title + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.onClose();
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "alert");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
configDialog.message +
"</div>");
this.dialog.append(this.buttons);
this.accept.focus();
};
/**
* Get error message
* @param type
* @param property
* @param config
* @returns {Object}
*/
DialogInvalid.prototype.getErrorMessage = function (type, property, config) {
var conf = {};
conf.title = (config) ? this.config.title.translate() : 'Errors'.translate();
switch (type) {
case 'required':
conf.message = "The ".translate() + property + " is required.".translate();
break;
case 'invalid':
conf.message = "The ".translate() + property + " is invalid.".translate();
break;
case 'duplicated':
conf.message = "The ".translate() + property + " is duplicated.".translate();
break;
case 'custom':
conf.message = (config) ? config.msg.translate() : '';
break;
}
return conf;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogInvalid', DialogInvalid);
}());
(function () {
var DialogRegularExpression = function (appendTo, dataType) {
this.dataType = dataType;
this.onClose = new Function();
this.onClick = new Function();
DialogRegularExpression.prototype.init.call(this, appendTo);
};
DialogRegularExpression.prototype.init = function (appendTo) {
var that = this;
this.dialog = $("<div title='" + "Regular Expression".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.body = $("<div style='overflow-x:hidden;border:1px solid #bbb;height:265px;'></div>");
this.dialog.append("<span>" +
"Enter a regular expression which is a search pattern which matches the text entered in the field. ".translate() +
"To learn more about regular expressions, see the <a href=\"http://wiki.processmaker.com/3.0/Text_and_Textarea_Controls#Validate\" target=\"_blank\">wiki</a>.<br><br>".translate() +
"Examples:<br>".translate() +
"</span>");
this.dialog.append(this.body);
this.load();
};
DialogRegularExpression.prototype.load = function () {
var that = this, data;
data = [{
dataType: "integer", name: "An integer".translate(), value: "^[-+]?[0-9]+$"
}, {
dataType: "float", name: "An integer or decimal number".translate(), value: "[-+]?[0-9]+\\.[0-9]+$"
}, {
dataType: "string", name: "An email address".translate(), value: "^\\w+(\\.\\w+)*@(\\w+\\.)+\\w{2,4}$"
}
];
this.body.find(">div").remove();
for (var i = 0; i < data.length; i++) {
if (that.dataType === data[i].dataType || that.dataType === "") {
that.addItem(data[i]);
}
}
};
DialogRegularExpression.prototype.addItem = function (regex) {
var that = this;
var item = $("<div class='fd-list' style='cursor:pointer;'>" +
"<div style='width:150px;display:inline-block;margin:1px;color:rgb(238, 113, 15);'>" + regex.name + "</div>" +
"<div style='width:auto;display:inline-block;color:rgb(33, 54, 109);'>" + regex.value + "</div>" +
"</div>");
item.on("click", function () {
that.onClick(regex);
});
this.body.append(item);
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogRegularExpression', DialogRegularExpression);
}());
(function () {
var DialogConfirmClearVariable = function (appendTo) {
this.onAccept = new Function();
DialogConfirmClearVariable.prototype.init.call(this, appendTo);
};
DialogConfirmClearVariable.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "No".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Confirm".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Do you want to clear this variable? The following properties are reset: Variable, Data Type, DB Connection, SQL and Options.".translate() +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogConfirmClearVariable', DialogConfirmClearVariable);
}());
(function () {
var DialogContent = function (appendTo) {
this.onSave = new Function();
this.onClose = new Function();
DialogContent.prototype.init.call(this, appendTo);
};
DialogContent.prototype.init = function (appendTo) {
var that = this;
this.save = $("<a href='#' class='fd-button fd-button-success'>" + "Save".translate() + "</a>");
this.save.on("click", function () {
that.onSave();
that.dialog.dialog("close").remove();
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "Cancel".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close").remove();
return false;
});
this.buttons = $("<div class='fd-button-panel'><div style='float:right'></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.save);
$.ui.keyCode.TAB = null;//focus button prevents dialog with CodeMirror tab
this.dialog = $("<div title='" + "Content".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 940,
height: 500,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
$.ui.keyCode.TAB = 9;
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.textarea = $("<textarea></textarea>");
this.body = $("<div style='border:1px solid #bbb;'></div>");
this.body.append(this.textarea);
this.dialog.append(this.body);
this.dialog.append("<p>" + "Press".translate() + " <strong>ctrl-space</strong> " + "to activate autocompletion".translate() + ".</p>");
this.dialog.append(this.buttons);
this.editor = CodeMirror.fromTextArea(this.textarea[0], {
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
mode: "text/html",
viewportMargin: Infinity,
className: "CodeMirror-hints-custom-mafe"
});
this.editor.setSize(910, 350);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogContent', DialogContent);
}());
(function () {
var DialogUnsupported = function (appendTo) {
this.onAccept = new Function();
DialogUnsupported.prototype.init.call(this, appendTo);
};
DialogUnsupported.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Ok".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Information".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: true,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "success");
var msg = "";
var dt = $.globalInvalidProperties;
for (var i = 0; i < dt.length; i++) {
msg = msg + dt[i] + "<br> ";
}
msg = msg.replace(/[,\s]+$/, "");
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
"Unsupported element.".translate() +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogUnsupported', DialogUnsupported);
}());
(function () {
var DialogChangedVariables = function (appendTo, message) {
this.onAccept = new Function();
this.message = message;
DialogChangedVariables.prototype.init.call(this, appendTo);
};
DialogChangedVariables.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Ok".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "New variables created".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 200,
resizable: true,
close: function (event, ui) {
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, "warning");
this.message = this.message.replace(/[,\s]+$/, "");
this.dialog.append("<div style='font-size:14px;margin:20px;height:85px;overflow-y:auto;'>" +
"The imported dynaform includes new variables and existing variables that require changes.".translate() + " " +
"The changed variables have been added with the suffix “_1”.".translate() + " " +
"Please take note of the changes to update your process logic.".translate() + " " +
"The following variables have been created:<br>".translate() + this.message +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogChangedVariables', DialogChangedVariables);
}());
(function () {
var DialogCreateVariable = function (appendTo, type, options, var_name) {
this.onSave = new Function();
this.onSelect = new Function();
this.onClose = new Function();
this.appendTo = appendTo;
this.type = type;
this.options = options;
this.var_name = var_name;
DialogCreateVariable.prototype.init.call(this);
};
DialogCreateVariable.prototype.init = function () {
var that = this;
this.var_dbconnection = "workflow";
this.var_sql = "";
this.var_accepted_values = that.options;
this.inp_doc_uid = "";
this.add = $("<a href='#' class='fd-button fd-button-create' style='padding:7px 10px 7px 35px;margin-bottom:5px;position:absolute;right:10px;top:10px;'>" + "Variables".translate() + "</a>");
this.add.on("click", function () {
that.dialog.dialog("close");
var pmvariables = new PMVariables();
pmvariables.onWindowClose = function (variable) {
if (variable !== null && variable.var_name_old === that.var_name) {
that.onSave(variable);
}
};
pmvariables.load();
return false;
});
this.buttonSave = $("<a href='#' class='fd-button fd-button-success'>" + "Save".translate() + "</a>");
this.buttonSave.on("click", function () {
that.save();
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "Cancel".translate() + "</a>");
this.cancel.on("click", function () {
that.dialog.dialog("close").remove();
return false;
});
this.buttons = $("<div class='fd-button-panel'><div style='float:right'></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.buttonSave);
this.optionSelect = $(
" <div style='padding:10px;'>" +
" <label>" +
" <input type='radio' id='optionCreate' name='optionCreateSelect' checked/>" +
" <span style='width:110px;display:inline-block;vertical-align:super;'>" + "Create variable".translate() + "</span>" +
" </label>" +
" <label>" +
" <input type='radio' id='optionSelect' name='optionCreateSelect'/>" +
" <span style='width:110px;display:inline-block;vertical-align:super;'>" + "Select variable".translate() + "</span>" +
" </label>" +
" </div>");
this.optionSelect.find("#optionCreate").on("click", function () {
that.buttonSave.show();
that.content.show();
that.selectVariable.dialog.hide();
that.dialog.css({height: heightCreate});
});
this.optionSelect.find("#optionSelect").on("click", function () {
that.buttonSave.hide();
that.content.hide();
that.selectVariable.dialog.show();
that.selectVariable.load();
that.dialog.css({height: 452});
});
this.selectVariable = new FormDesigner.main.DialogVariable(null, this.type);
this.selectVariable.onClick = function (variable) {
that.onSelect(variable);
};
this.selectVariable.dialog.dialog("destroy");
this.selectVariable.dialog.hide();
this.content = $(
"<div>" +
" <div style='padding:10px;'>" +
" <label><span style='width:110px;display:inline-block;vertical-align:top;'>" + "Variable Name:".translate() + "</span>" +
" <input type='text' name='var_name' id='var_name' style='width:200px;'/>" +
" </label>" +
" </div>" +
" <div style='padding:0px 10px 10px 10px;'>" +
" <a title='" + "Settings".translate() + "' style='cursor:pointer;margin-bottom:5px;text-decoration:underline;' id='buttonSettings'>" + "Settings".translate() + "</a>" +
" </div>" +
" <div id='settings' style='padding: 0px 10px 10px;'>" +
" <label style='display:block;margin-bottom:5px;'>" +
" <span style='width:110px;display:inline-block;vertical-align:top;'>" + "Type:".translate() + "</span>" +
" <select id='var_field_type' style='width:auto;'></select>" +
" </label>" +
" <label style='display:block;margin-bottom:5px;' id='var_dbconnection'>" +
" <span style='width:110px;display:inline-block;vertical-align:top;'>" + "Database Connection:".translate() + "</span>" +
" <div style='overflow:hidden;width:250px;display:inline-block;'><a style='cursor:pointer;white-space:nowrap;text-decoration:underline;' id='buttonDbConnection'>PM Database</a></div>" +
" </label>" +
" <label style='display:block;margin-bottom:5px;' id='var_sql'>" +
" <span style='width:110px;display:inline-block;vertical-align:top;'>" + "Sql:".translate() + "</span>" +
" <div style='overflow:hidden;width:250px;display:inline-block;'><a style='cursor:pointer;white-space:nowrap;text-decoration:underline;' id='buttonSql'>...</a></div>" +
" </label>" +
" <label style='display:block;margin-bottom:5px;' id='var_accepted_values'>" +
" <span style='width:110px;display:inline-block;vertical-align:top;'>" + "Options:".translate() + "</span>" +
" <div style='overflow:hidden;width:250px;display:inline-block;'><a style='cursor:pointer;white-space:nowrap;text-decoration:underline;' id='buttonOptions'>[]</a></div>" +
" </label>" +
" <label style='display:block;margin-bottom:5px;' id='inp_doc_uid'>" +
" <span style='width:110px;display:inline-block;vertical-align:top;'>" + "Input Document<span style='color:red;'>*</span>:".translate() + "</span>" +
" <div style='overflow:hidden;width:250px;display:inline-block;'><a style='cursor:pointer;white-space:nowrap;text-decoration:underline;' id='buttonInputDocument'>...</a></div>" +
" </label>" +
" </div>" +
"</div>"
);
this.content.find("#settings").css({display: "none"});
var show = true;
var heightCreate = 180;
this.content.find("#buttonSettings").on("click", function () {
if (show) {
heightCreate = 260;
that.dialog.css({height: heightCreate});
that.content.find("#settings").css({display: "block"});
show = false;
} else {
heightCreate = 165;
that.dialog.css({height: heightCreate});
that.content.find("#settings").css({display: "none"});
show = true;
}
return false;
});
var a;
this.content.find("#buttonDbConnection").on("click", function () {
a = new FormDesigner.main.DialogDBConnection(null);
a.onClick = function (option) {
a.dialog.dialog("close").remove();
that.var_dbconnection = option.value;
that.content.find("#buttonDbConnection").text(option.label);
};
return false;
});
this.content.find("#buttonSql").on("click", function () {
a = new FormDesigner.main.DialogSql(null);
a.onSave = function () {
that.var_sql = a.editor.getValue();
that.content.find("#buttonSql").text(a.editor.getValue());
};
a.editor.setValue(that.var_sql);
return false;
});
this.content.find("#buttonOptions").on("click", function () {
a = new FormDesigner.main.DialogOptions(null, that.var_accepted_values);
a.onApply = function () {
that.var_accepted_values = a.getOptions();
that.content.find("#buttonOptions").text(JSON.stringify(a.getOptions()));
};
if (that.content.find("#var_field_type").val() === "boolean") {
a.setOptionsBoolean();
}
return false;
});
this.content.find("#buttonInputDocument").on("click", function () {
a = new FormDesigner.main.DialogInputDocument(null);
a.onClick = function (option) {
a.dialog.dialog("close").remove();
that.inp_doc_uid = option.value;
that.content.find("#buttonInputDocument").text(option.label);
};
return false;
});
this.dialog = $("<div title='" + "Create/Select Variable".translate() + "'></div>");
this.dialog.dialog({
appendTo: this.appendTo ? this.appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 195,
resizable: false,
position: { my: "center top+50", at: "center top", of: window },
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
this.dialog.append(this.optionSelect);
this.dialog.append(this.content);
this.dialog.append(this.selectVariable.dialog);
this.dialog.append(this.buttons);
this.dialog.append(this.add);
FormDesigner.main.DialogStyle(this.dialog);
$.validkeys(that.content.find("#var_name")[0], ['isbackspace', 'isnumber', 'isletter', 'isunderscore']);
that.content.find("#var_name").focus();
//data
that.content.find("#var_field_type").on("change", function () {
that.setFieldsVisibility(this.value);
});
var types = [{
value: "string", label: "String"
}, {
value: "integer", label: "Integer"
}, {
value: "float", label: "Float"
}, {
value: "boolean", label: "Boolean"
}, {
value: "datetime", label: "Datetime"
}, {
value: "grid", label: "Grid"
}, {
value: "array", label: "Array"
}, {
value: "file", label: "File"
}, {
value: "multiplefile", label: "Multiple File"
}
];
that.content.find("#var_field_type").empty();
for (var i = 0; i < types.length; i++) {
$.validDataTypeAndControlType(types[i].value, that.type, function () {
that.addItem(types[i]);
});
}
that.setFieldsVisibility(that.content.find("#var_field_type").val());
};
DialogCreateVariable.prototype.save = function () {
var that = this;
if (!that.isValid()) {
var a = new FormDesigner.main.DialogMessage(null, "alert", "A valid variable starts with a letter or underscore, followed by any number of letters, numbers, or underscores.".translate());
a.onClose = function () {
};
a.onAccept = function () {
};
return false;
}
if (!that.isValidInputDocument()) {
var a = new FormDesigner.main.DialogMessage(null, "alert", "The input document is required, please select the value.".translate());
a.onClose = function () {
};
a.onAccept = function () {
};
return false;
}
$.ajax({
url: HTTP_SERVER_HOSTNAME + "/api/1.0/" + WORKSPACE + "/project/" + PMDesigner.project.id + "/process-variable",
data: JSON.stringify({
var_name: that.content.find("#var_name").val(),
var_field_type: that.content.find("#var_field_type").val(),
var_dbconnection: that.var_dbconnection,
var_sql: that.var_sql,
var_label: that.content.find("#var_field_type").val(),
var_default: "",
var_accepted_values: that.var_accepted_values,
var_field_size: 10,
inp_doc_uid: that.inp_doc_uid
}),
method: "POST",
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + PMDesigner.project.keys.access_token);
},
success: function (variable) {
that.dialog.dialog("close").remove();
that.onSave(variable);
},
error: function (responses) {
var msg;
try {
msg = JSON.parse(responses.responseText).error.message;
} catch (e) {
msg = "Error";
}
var a = new FormDesigner.main.DialogMessage(null, "alert", msg);
a.onClose = function () {
};
a.onAccept = function () {
};
}
});
};
DialogCreateVariable.prototype.isValid = function () {
return /^[a-zA-Z_\x7f-\xff]+[a-zA-Z0-9_\x7f-\xff]*$/.test(this.content.find("#var_name").val());
};
DialogCreateVariable.prototype.isValidInputDocument = function () {
if (this.content.find("#var_field_type").val() === "file" || this.content.find("#var_field_type").val() === "multipleFile") {
return this.inp_doc_uid !== "";
}
return true;
};
DialogCreateVariable.prototype.setVarName = function (var_name) {
this.content.find("#var_name").val(var_name);
};
DialogCreateVariable.prototype.addItem = function (type) {
var that = this;
that.content.find("#var_field_type").append("<option value='" + type.value + "'>" + type.label + "</option>");
};
DialogCreateVariable.prototype.setFieldsVisibility = function (type) {
var that = this;
that.content.find("#var_dbconnection").show();
that.content.find("#var_sql").show();
that.content.find("#var_accepted_values").show();
that.content.find("#inp_doc_uid").hide();
if (type === "boolean") {
that.content.find("#var_dbconnection").hide();
that.content.find("#var_sql").hide();
that.var_accepted_values = [{value: "1", label: "true"}, {value: "0", label: "false"}];
that.content.find("#buttonOptions").text(JSON.stringify(that.var_accepted_values));
}
if (type === "datetime" || type === "grid" || type === "file" || type === "multiplefile") {
that.content.find("#var_dbconnection").hide();
that.content.find("#var_sql").hide();
that.content.find("#var_accepted_values").hide();
}
if (type === "file") {
that.content.find("#inp_doc_uid").show();
}
};
FormDesigner.extendNamespace('FormDesigner.main.DialogCreateVariable', DialogCreateVariable);
}());
(function () {
var DialogMessage = function (appendTo, type, message) {
this.type = type;
this.message = message;
this.onAccept = new Function();
this.onClose = new Function();
DialogMessage.prototype.init.call(this, appendTo);
};
DialogMessage.prototype.init = function (appendTo) {
var that = this,
title;
this.accept = $("<a href='#' class='fd-button fd-button-success'>" + "Ok".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.accept);
title = that.type === "success"? "Information" : "Errors";
this.dialog = $("<div title='" + title.translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.onClose();
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog, this.type);
this.dialog.append("<div style='font-size:14px;margin:20px;text-align:center'>" +
this.message +
"</div>");
this.dialog.append(this.buttons);
this.accept.focus();
};
FormDesigner.extendNamespace('FormDesigner.main.DialogMessage', DialogMessage);
}());
(function () {
var DialogConfirm = function (appendTo, type, message) {
this.type = type;
this.message = message;
this.onAccept = new Function();
this.onCancel = new Function();
this.onClose = new Function();
DialogConfirm.prototype.init.call(this, appendTo);
};
DialogConfirm.prototype.init = function (appendTo) {
var that = this;
this.accept = $("<a href='#' class='fd-button fd-button-yes'>" + "Yes".translate() + "</a>");
this.accept.on("click", function () {
that.onAccept();
that.dialog.dialog("close");
return false;
});
this.cancel = $("<a href='#' class='fd-button fd-button-no'>" + "No".translate() + "</a>");
this.cancel.on("click", function () {
that.onCancel();
that.dialog.dialog("close");
return false;
});
this.buttons = $("<div class='fd-button-panel'><div></div></div>");
this.buttons.find("div:nth-child(1)").append(this.cancel);
this.buttons.find("div:nth-child(1)").append(this.accept);
this.dialog = $("<div title='" + "Confirm".translate() + "'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 470,
height: 170,
resizable: false,
close: function (event, ui) {
that.dialog.remove();
that.onClose();
}
});
FormDesigner.main.DialogStyle(this.dialog, this.type);
this.dialog.append("<div style='font-size:14px;margin:20px;'>" +
this.message +
"</div>");
this.dialog.append(this.buttons);
};
FormDesigner.extendNamespace('FormDesigner.main.DialogConfirm', DialogConfirm);
}());
(function () {
var DialogInputDocument = function (appendTo) {
this.onClose = new Function();
this.onLoad = new Function();
this.onClick = new Function();
DialogInputDocument.prototype.init.call(this, appendTo);
};
DialogInputDocument.prototype.init = function (appendTo) {
var that = this;
this.dialog = $("<div title='" + "Input Documents".translate() + "' style='padding:10px;'></div>");
this.dialog.dialog({
appendTo: appendTo ? appendTo : document.body,
modal: true,
autoOpen: true,
width: 500,
height: 400,
resizable: false,
close: function (event, ui) {
that.onClose(event, ui);
that.dialog.remove();
}
});
FormDesigner.main.DialogStyle(this.dialog);
this.search = $("<p>" + "Search".translate() + " : <input type='text'/><img src='" + $.imgUrl + "fd-refresh.png' style='margin-top:-4px;vertical-align:middle;cursor: pointer;' title='" + "refresh".translate() + "'></p>");
this.search.find(">input").on("keyup", function () {
var input = this;
that.body.find(">div").each(function (i, e) {
var sw = false;
$(e).find(">div").each(function (i, e) {
sw = sw || $(e).text().toLowerCase().indexOf(input.value.toLowerCase()) > -1;
});
if (sw)
$(e).show();
else
$(e).hide();
});
});
this.search.find("img").on("click", function () {
that.load();
});
this.body = $("<div style='overflow-x:hidden;border:1px solid #bbb;height:305px;'></div>");
this.dialog.append(this.search);
this.dialog.append(this.body);
this.load();
};
DialogInputDocument.prototype.load = function () {
var that = this;
this.body.find(">div").remove();
var restProxy = new PMRestClient({
endpoint: "input-documents",
typeRequest: "get",
functionSuccess: function (xhr, response) {
var resp;
for (var i = 0; i < response.length; i++) {
resp = response[i];
resp["label"] = response[i].inp_doc_title;
resp["value"] = response[i].inp_doc_uid;
that.addItem(resp);
}
that.onLoad(response);
}
});
restProxy.executeRestClient();
};
DialogInputDocument.prototype.addItem = function (variable) {
var that = this;
var item = $("<div class='fd-list' style='cursor:pointer;'>" +
"<div style='width:auto;display:inline-block;color:rgb(33, 54, 109);'>" + variable.label + "</div>" +
"</div>");
item.on("click", function () {
that.onClick(variable);
});
this.body.append(item);
return item;
};
FormDesigner.extendNamespace('FormDesigner.main.DialogInputDocument', DialogInputDocument);
}());
(function () {
/**
* PopOver for PM Dynaform's designer.
* @param {Object} settings An object containing the config options for the new PopOver.
* @cfg {String|JQuery Object| Element} body The content for the PopOver, it casn be an HTML string, a JQuery Object
* or an Element.
* @cfg {String} [class=""] The class name for the popover, useful for applying custom styles through a css class.
* @cfg {String} [placement=PMPopOver.PLACEMENT.RIGHT] A string that determines the placement of the popover related
* to its target element. Please Use one of the keys defined under PMPopOver.PLACEMENT.
*
* @constructor
*/
var PMPopOver = function (settings) {
this._body = null;
this._targetElement = null;
this._dom = {};
this._class = null;
this._placement = null;
this._visible = false;
PMPopOver.prototype._init.call(this, settings);
};
/**
* All the possible values for placement config option.
* @type {{TOP: string, RIGHT: string, BOTTOM: string, LEFT: string}}
*/
PMPopOver.PLACEMENT = {
TOP: 'top',
RIGHT: 'right',
BOTTOM: 'bottom',
LEFT: 'left'
};
/**
* Initialize the class
* @param settings
* @private
*/
PMPopOver.prototype._init = function (settings) {
settings = $.extend({
body: "",
class: "",
placement: PMPopOver.PLACEMENT.RIGHT
}, settings);
this._placement = settings.placement;
this._class = settings.class;
this.setBody(settings.body)
.setTargetElement(settings.targetElement);
};
/**
* Sets the element the PopOver belongs to.
* @param targetElement
* @chainable
*/
PMPopOver.prototype.setTargetElement = function (targetElement) {
if (!targetElement) {
throw new Error('setTargetElement(): Invalid parameter.');
}
this._clickHandler = this._clickHandler || this.toggleVisible.bind(this);
if (this._targetElement) {
$(this._targetElement).off("click", this._clickHandler);
}
this._targetElement = targetElement;
$(this._targetElement).on("click", this._clickHandler);
return this;
};
/**
* Sets the PopOver body.
* @param body
* @chainable
*/
PMPopOver.prototype.setBody = function (body) {
if (!(body instanceof Element || body instanceof jQuery || typeof body === 'string')) {
throw new Error("setBody(): The parameter must be a DOM Element, jQuery element or a string.");
}
this._body = body;
if (this._dom.content) {
$(this._dom.content).empty().append(body);
}
return this;
};
/**
* Returns the position of the PopOver target element.
* @returns {Object}
* @private
*/
PMPopOver.prototype._getTargetPosition = function () {
var $element = this._targetElement instanceof jQuery ? this._targetElement : $(this._targetElement),
element = this._targetElement instanceof jQuery ? this._targetElement.get(0) : this._targetElement;
return $.extend(element.getBoundingClientRect ? element.getBoundingClientRect() : {
width: element.offsetWidth,
height: element.offsetHeight
}, $element.offset());
};
/**
* Returns the final position for the popover.
* @returns {{top: *, left: *}}
* @private
*/
PMPopOver.prototype._getPosition = function () {
var targetPosition = this._getTargetPosition(),
arrowOffset = 10,
html = this.getHTML(),
htmlWidth,
htmlHeight,
placement,
top,
left;
document.body.appendChild(html);
html.style.display = 'block';
htmlWidth = html.offsetWidth;
htmlHeight = html.offsetHeight;
placement = this._placement;
switch (placement) {
case PMPopOver.PLACEMENT.TOP:
top = targetPosition.top - htmlHeight - arrowOffset;
left = targetPosition.left + (targetPosition.width / 2) - (htmlWidth / 2);
break;
case PMPopOver.PLACEMENT.RIGHT:
top = targetPosition.top + (targetPosition.height / 2) - (htmlHeight / 2);
left = targetPosition.left + targetPosition.width + arrowOffset;
break;
case PMPopOver.PLACEMENT.BOTTOM:
top = targetPosition.top + targetPosition.height + arrowOffset;
left = targetPosition.left + (targetPosition.width / 2) - (htmlWidth / 2);
break;
case PMPopOver.PLACEMENT.LEFT:
top = targetPosition.top + (targetPosition.height / 2) - (htmlHeight / 2);
left = targetPosition.left - htmlWidth - arrowOffset;
break;
default:
throw new Error('_getPosition(): Invalid placement parameter.');
}
return {
top: top,
left: left
};
};
/**
* Displays the PopOver.
* @chainable
* @return {body}
*/
PMPopOver.prototype.show = function () {
var position = this._getPosition();
$(this._html).removeClass("top right bottom left").addClass(this._placement).addClass("in");
this._html.style.top = position.top + 'px';
this._html.style.left = position.left + 'px';
this._visible = true;
return this;
};
/**
* Hides the PopOver.
* @chainable
* @return {body}
*/
PMPopOver.prototype.hide = function () {
if (this._html) {
$(this._html).fadeOut(150, "linear", function () {
this.style.display = 'none';
$(this).removeClass('in');
});
}
this._visible = false;
return this;
};
/**
* Toggles the PopOver visibility.
* @chainable
*/
PMPopOver.prototype.toggleVisible = function () {
return this._visible ? this.hide() : this.show();
};
/**
* Creates the PopOver HTML.
* @chainable
* @return {body}
* @private
*/
PMPopOver.prototype._createHTML = function () {
var container,
arrow,
content;
if (this._html) {
return this;
}
container = document.createElement('div');
arrow = document.createElement('div');
content = document.createElement('div');
container.className = "mafe-popover fade " + this._class;
arrow.className = "arrow";
content.className = "mafe-popover-content";
container.appendChild(arrow);
container.appendChild(content);
this._dom.container = container;
this._dom.arrow = arrow;
this._dom.content = content;
this._html = container;
this.setBody(this._body);
this._html.addEventListener("mousedown", function (e) {
e.stopPropagation();
});
document.addEventListener("mousedown", this.hide.bind(this), false);
return this;
};
/**
* Returns the PopOver HTML.
* @returns {Element}
*/
PMPopOver.prototype.getHTML = function () {
if (!this._html) {
this._createHTML();
}
return this._html;
};
FormDesigner.extendNamespace('FormDesigner.main.PMPopOver', PMPopOver);
})();
/**
* @class ItemRule
* @param object
* @constructor
*/
var ItemRule = function (object) {
/**
* Code of the Rule
* @type {String}
*/
this.code = null;
/**
* Type Shape
* @type {String}
*/
this.type = null;
/**
* Category of the Rule (BPMN | ENGINE)
* @type {String}
*/
this.category = null;
/**
* Type of alert (Error | Warning)
* @type {String}
*/
this.severity = null;
/**
* Description rule
* @type {String}
*/
this.description = null;
/**
* Criteria of validation
* @type {Function}
*/
this.criteria = null;
this.init(object);
};
/**
* Inicialize ItemRules.
* @param object
*/
ItemRule.prototype.init = function (object) {
if (typeof object === "object") {
this.setCode(object.code);
this.setTypeElement(object.type);
this.setCategory("BPMN");
this.setSeverity(object.severity);
this.setDescription(object.description);
this.setCriteria(object.criteria);
}
};
/**
* Get code rule
* @returns {String}
*/
ItemRule.prototype.getCode = function () {
return this.code;
};
/**
* Get type rule
* @returns {String}
*/
ItemRule.prototype.getTypeElement = function () {
return this.type;
};
/**
* Get category
* @returns {String}
*/
ItemRule.prototype.getCategory = function () {
return this.category;
};
/**
* Get severity
* @returns {String}
*/
ItemRule.prototype.getSeverity = function () {
return this.severity;
};
/**
* Get description
* @returns {String}
*/
ItemRule.prototype.getDescription = function () {
return this.description;
};
/**
* Get criteria
* @returns {function}
*/
ItemRule.prototype.getCriteria = function () {
return this.criteria;
};
/**
* Validate code
* @param codeRule {String}
* @returns {Boolean}
*/
ItemRule.prototype.isCodeRule = function (codeRule) {
var isCode = false;
if (codeRule === this.code) {
isCode = true;
}
return isCode;
};
/**
* Set code
* @param code
* @returns {ItemRule}
*/
ItemRule.prototype.setCode = function (code) {
if (code && typeof code === "string") {
this.code = code;
}
return this;
};
/**
* Set type element
* @param typeElement {String}
* @returns {ItemRule}
*/
ItemRule.prototype.setTypeElement = function (typeElement) {
if (typeElement && typeof typeElement === "string") {
this.type = typeElement;
}
return this;
};
/**
* Set type element
* @param typeElement {String}
* @returns {ItemRule}
*/
ItemRule.prototype.setCategory = function (category) {
if (category && typeof category === "string") {
this.category = category;
}
return this;
};
/**
* Set severity
* @param severity {String}
* @returns {ItemRule}
*/
ItemRule.prototype.setSeverity = function (severity) {
if (severity && typeof severity === "string") {
this.severity = severity;
}
return this;
};
/**
* Set description
* @param description {String}
* @returns {ItemRule}
*/
ItemRule.prototype.setDescription = function (description) {
if (description && typeof description === "string") {
this.description = description;
}
return this;
};
/**
* Set criteria
* @param criteria {Function}
* @returns {ItemRule}
*/
ItemRule.prototype.setCriteria = function (criteria) {
if (criteria && typeof criteria === "function") {
this.criteria = criteria;
}
return this;
};
/**
* @class CollectionRules
* @param collectionRules
* @constructor
*/
var CollectionRules = function (collectionRules) {
/**
* Type Shape
* @type {String}
*/
this.typeShape = null;
/**
* Array of Rules
* @type {Rules}
*/
this.rules = new PMUI.util.ArrayList();
this.init(collectionRules);
};
/**
* Inicialize CollectionRules
* @param collectionRules
*/
CollectionRules.prototype.init = function (collectionRules) {
if (typeof collectionRules === "object") {
this.setTypeShape(collectionRules.typeShape);
this.loadRules(collectionRules.rules);
}
};
/**
* Get type shape
* @returns {String}
*/
CollectionRules.prototype.getTypeShape = function () {
return this.typeShape;
};
/**
* Validate type shape
* @param typeShape
* @returns {Boolean}
*/
CollectionRules.prototype.isTypeShape = function (typeShape) {
var isType = false;
if (typeShape === this.getTypeShape()) {
isType = true;
}
return isType;
};
/**
* Get Array Rules
* @returns {Array Rules}
*/
CollectionRules.prototype.getRules = function () {
return this.rules;
};
/**
* Get Item Rule
* @returns {ItemRule}
*/
CollectionRules.prototype.getItemRule = function (codeRule) {
var itemRule,
itemsRules;
if (codeRule) {
itemsRules = this.getRules();
itemRule = itemsRules.find("code", codeRule);
}
return itemRule;
};
/**
* Set type shape
* @param typeShape
* @returns {CollectionRules}
*/
CollectionRules.prototype.setTypeShape = function (typeShape) {
this.typeShape = (typeShape && typeof typeShape === "string") ? typeShape : this.typeShape;
return this;
};
/**
* Set array rules
* @param arrRules
* @returns {CollectionRules}
*/
CollectionRules.prototype.setRules = function (arrRules) {
if (arrRules && Array.isArray(arrRules)) {
this.rules = arrRules;
}
return this;
};
/**
* Load rules array
* @param arrRules
* @returns {CollectionRules}
*/
CollectionRules.prototype.loadRules = function (arrRules) {
var itemRule,
i,
max;
if (arrRules && Array.isArray(arrRules) && arrRules.length > 0) {
max = arrRules.length;
for (i = 0; i < max; i += 1) {
itemRule = new ItemRule(arrRules[i]);
this.rules.insert(itemRule);
}
}
return this;
};
/**
* Add new ItemRule object
* @param itemRule {Object}
*/
CollectionRules.prototype.addItemRule = function (itemRule) {
if (itemRule && typeof itemRule === "object") {
this.rules.insert(itemRule);
}
return this;
};
/**
* Remove ItemRule object
* @param itemRule
* @returns {CollectionRules}
*/
CollectionRules.prototype.removeItemRule = function (itemRule) {
if (itemRule && typeof itemRule === "object") {
this.rules.remove(itemRule);
}
return this;
};
/**
* @class ModelRules
* @param object
* @constructor
*/
var ModelRules = function (object, status) {
/**
* Status Rules
* @type {Boolean}
*/
this.enable = true;
/**
* Items collection
* @type {PMUI.util.ArrayList}
*/
this.itemsCollection = new PMUI.util.ArrayList();
this.init(object, status);
};
/**
* Inicialize Model Rules
* @param object
*/
ModelRules.prototype.init = function (object, status) {
var prop;
this.setStatus(status);
if (object && typeof object === "object") {
for (prop in object) {
this.enable
this.loadCollection(prop, object[prop]);
}
}
};
/**
* Load Collection Rules
* @param type
* @param arrRules
* @returns {ModelRules}
*/
ModelRules.prototype.loadCollection = function (type, arrRules) {
var collectionObject;
if (type && arrRules) {
if (typeof type === "string" && Array.isArray(arrRules)) {
collectionObject = new CollectionRules({
'typeShape': type,
'rules': arrRules
});
this.itemsCollection.insert(collectionObject);
}
}
return this;
};
/**
* Get the status of the enable property (true | false)
* @returns {Boolean}
*/
ModelRules.prototype.getStatus = function () {
return this.enable;
};
/**
* Get Items Collection Arralist
* @returns {PMUI.util.ArrayList}
*/
ModelRules.prototype.getItemsCollection = function () {
return this.itemsCollection;
};
/**
* Set the status of the enable property
* @param status
* @returns {ModelRules}
*/
ModelRules.prototype.setStatus = function (status) {
this.enable = (typeof status === "boolean") ? status : this.enable;
return this;
};
/**
* Get Collection Rules for type Bpmn Element
* Example:
* PMDesigner.modelRules.getCollectionType('bpmnActivity');
* @param type {String}
* @returns CollectionRules {PMUI.util.ArrayList}
*/
ModelRules.prototype.getCollectionType = function (type) {
var collection,
i,
itemCollection,
max;
if (type && typeof type === "string") {
max = this.itemsCollection.getSize();
for (i = 0; i < max; i += 1) {
itemCollection = this.itemsCollection.get(i);
if (itemCollection.isTypeShape(type)) {
collection = itemCollection.getRules();
break;
}
}
}
return collection;
};
/**
* Add Item Rule
* Example:
* PMDesigner.modelRules.addItemRuleToCollection('bpmnActivity', {
* code: '123456',
* description: 'This is a Message of Error'.translate(),
* type: 'bpmnActivity',
* severity: 'Warning', {'Warning | Error'}
* criteria: function (shape, error) {
* //Validation Rule
* shape.addErrorLog(error);
* }
* });
* @param type {String}
* @param item {Object}
* @returns {ModelRules}
*/
ModelRules.prototype.addItemRuleToCollection = function (type, item) {
var itemCollection,
itemRule,
max,
index = 0;
if (type && item) {
max = this.itemsCollection.getSize();
while (index < max) {
itemCollection = this.itemsCollection.get(index);
if (itemCollection.isTypeShape(type)) {
itemRule = new ItemRule(item);
itemCollection.addItemRule(itemRule);
index = max;
}
index += 1;
}
}
return this;
};
/**
* Remove Item Rule
* Example:
* PMDesigner.modelRules.removeItemRuleFromCollection('123465');
* @param code {String}
* @returns {ModelRules}
*/
ModelRules.prototype.removeItemRuleFromCollection = function (code) {
var itemCollection,
itemRule,
max,
index = 0;
if (code && typeof code === "string") {
max = this.itemsCollection.getSize();
while (index < max) {
itemCollection = this.itemsCollection.get(index);
itemRule = itemCollection.getItemRule(code);
if (itemRule) {
itemCollection.removeItemRule(itemRule);
index = max;
}
index += 1;
}
}
return this;
};
/**
* Add Collection Rules
* Example:
* PMDesigner.modelRules.addItemRuleToCollection('bpmnActivity'
* [
* {Object ItemRule},
* {Object ItemRule},
* {Object ItemRule}
* ]
* );
* @param typeShape {String}
* @param collectionRules {Array}
* @returns {ModelRules}
*/
ModelRules.prototype.addCollectionRules = function (typeShape, arrayRules) {
var max,
i;
if (type && arrayRules && Array.isArray(arrayRules)) {
max = arrayRules.length;
for (i = 0; i < max; i += 1) {
this.addItemRuleToCollection(typeShape, arrayRules[i]);
}
}
return this;
};
/**
* Crown Class
* @param options
* @constructor
*/
var Corona = function (options) {
/**
* Call Shape Contructor
*/
PMUI.draw.Shape.call(this, options);
/**
* Define parent crown
* @type {shape}
*/
this.parent = null;
/**
* Define Type Especific of the parent
* @type {null}
*/
this.parentType = null;
/**
* Define number rows
* @type {number}
*/
this.rows = 1;
/**
* Define number cols
* @type {number}
*/
this.cols = 1;
/**
* Define Items of the Crown
* @type {PMUI.util.ArrayList}
*/
this.itemsCrown = new PMUI.util.ArrayList();
/**
* Event OnMouseOut
* @type {null}
*/
this.eventOnMouseOut = null;
this.init(options);
};
/**
* Define New Object Shape
* @type {PMUI.draw.Shape}
*/
Corona.prototype = new PMUI.draw.Shape();
/**
* Defines the object type
* @type {String}
*/
Corona.prototype.type = 'Crown';
/**
* Inicializate Crown
* @param options
* @returns {Crown}
*/
Corona.prototype.init = function (options) {
var config;
if (typeof options === "object" && !jQuery.isEmptyObject(options)) {
this.setParent(options.parent);
this.setParentType(options.parentType);
config = this.getConfigItems(options.parentType);
if (config) {
this.populateItemsCrown(config);
this.setRows(config.rows);
this.setCols(config.cols);
}
}
return this;
};
/**
* Get Parent Crown
* @returns {shape|PMUI.draw.Shape|*}
*/
Corona.prototype.getParent = function () {
return this.parent;
};
/**
* Get Parent Type
* @returns {null|string|*}
*/
Corona.prototype.getParentType = function () {
return this.parentType;
};
/**
* Get Rows
* @returns {number}
*/
Corona.prototype.getRows = function () {
return this.rows;
};
/**
* Get Cols
* @returns {number}
*/
Corona.prototype.getCols = function () {
return this.cols;
};
/**
* Get Items Crown
* @returns {PMUI.util.ArrayList|*}
*/
Corona.prototype.getItemsCrown = function () {
return this.itemsCrown;
};
/**
* Set Parent Crown
* @param parent
* @returns {Corona}
*/
Corona.prototype.setParent = function (parent) {
if (typeof parent === "object" && !jQuery.isEmptyObject(parent)) {
this.parent = parent;
}
return this;
};
/**
* Set Parent Type
* @param parentType
* @returns {Corona}
*/
Corona.prototype.setParentType = function (parentType) {
if (parentType && typeof parentType === "string") {
this.parentType = parentType;
}
return this;
};
/**
* Set Number Rows
* @param rows
* @returns {Crown}
*/
Corona.prototype.setRows = function (rows) {
if (rows && rows > 0) {
this.rows = rows;
}
return this;
};
/**
* Set Number Cols
* @param cols
* @returns {Crown}
*/
Corona.prototype.setCols = function (cols) {
if (cols && cols > 0) {
this.cols = cols;
}
return this;
};
/**
* Resize crown
* @returns {Corona}
*/
Corona.prototype.adjustSize = function () {
var width,
height,
itemFirst,
margin = 4;
itemFirst = this.getItemsCrown().get(0);
width = (itemFirst.getWidth() + margin) * this.getCols();
height = (itemFirst.getHeight() + margin) * this.getRows();
if (this.html) {
this.html.style.width = width + "px";
this.html.style.height = height + 'px';
this.updatePosition();
}
return this;
};
/**
* Changes position
* @returns {Corona}
*/
Corona.prototype.updatePosition = function () {
jQuery(this.html).position({
of: jQuery(this.parent.html),
my: "left top",
at: "right top",
collision: 'none'
});
return this;
};
/**
* Get config Items Crown
* @param especificType
* @returns {*}
*/
Corona.prototype.getConfigItems = function (especificType) {
var configDefault = PMDesigner.configCrown,
typeShape = this.getParent().getType(),
configCrown = configDefault[typeShape][especificType];
return configCrown;
};
/**
* Populate Crown from previous configuration
* @param config
* @returns {Corona}
*/
Corona.prototype.populateItemsCrown = function (config) {
var order = (config && config.order) || [],
itemsDefault = PMDesigner.modelCrown.getItemsDefault(),
itemCrownDefault,
itemCrown,
max,
i;
if (order && Array.isArray(order) && order.length > 0) {
max = order.length;
for (i = 0; i < max; i += 1) {
itemCrownDefault = itemsDefault.find("id", order[i]);
itemCrownDefault.parent = this;
itemCrownDefault.canvas = this.canvas;
itemCrown = new ItemCrown(itemCrownDefault);
this.itemsCrown.insert(itemCrown);
}
}
return this;
};
Corona.prototype.isCreatedItems = function () {
var isCreated = false;
if (this.countChildrens() === this.getItemsCrown().getSize()) {
isCreated = true;
}
return isCreated
};
/**
* Paint Crown
* @returns {Corona}
*/
Corona.prototype.paint = function () {
if (!this.html) {
this.createHTML();
}
return this;
};
/**
* Create HTML
* @returns {Corona}
*/
Corona.prototype.createHTML = function () {
var htmlParent = this.getCanvas().html,
htmlCrown,
htmlRow,
itemCrown,
itemsAux = this.getItemsCrown().asArray(),
cont = 0,
i;
this.html = null;
htmlCrown = this.createHtmlCrown();
while (itemsAux.length > 0) {
if (this.getRows() > cont) {
htmlRow = this.createHtmlRow(cont);
for (i = 0; i < this.getCols(); i += 1) {
if (itemsAux.length > 0) {
itemCrown = itemsAux.shift();
itemCrown = itemCrown.createHtmlItem();
itemCrown = itemCrown.attachListeners();
htmlRow.appendChild(itemCrown.html);
} else {
break;
}
}
htmlCrown.appendChild(htmlRow);
cont += 1;
}
}
htmlParent.appendChild(htmlCrown);
this.html = htmlCrown;
this.adjustSize();
return this;
};
/**
* Create Html Crown
* @returns {*}
*/
Corona.prototype.createHtmlCrown = function () {
var htmlCrown = null,
classCrown = "crown-container";
PMUI.draw.Shape.prototype.createHTML.call(this);
htmlCrown = this.html;
if (htmlCrown) {
htmlCrown.className = classCrown;
}
return htmlCrown;
};
/**
* Create Html Row
* @param index
* @returns {HTMLElement|*}
*/
Corona.prototype.createHtmlRow = function (index) {
var htmlRow = null,
classRow = "row";
htmlRow = PMUI.createHTMLElement("div");
htmlRow.className = classRow + " " + classRow + "-" + index;
return htmlRow;
};
/**
* Show Crown
* @returns {Corona}
*/
Corona.prototype.show = function () {
if (this.isDirtyParentType()) {
this.updateCrown();
}
if (!this.html) {
this.createHTML();
} else {
jQuery(this.html).show();
this.updatePosition();
this.setZOrder(this.getParent().getZOrder() + 1 || 1);
}
return this;
};
/**
* Hide Crown
* @returns {Corona}
*/
Corona.prototype.hide = function () {
if (this && this.html) {
jQuery(this.html).hide();
}
return this;
};
/**
* Destroy Crown Content
* @returns {Corona}
*/
Corona.prototype.destroy = function () {
if (this && this.html) {
jQuery(this.html).empty();
jQuery(this.html).remove();
this.html = null;
}
this.getItemsCrown().clear();
return this;
};
/**
* Update Crown when the config changes
* @returns {Corona}
*/
Corona.prototype.updateCrown = function () {
var config,
especificType = this.getParent().getEspecificType();
this.destroy();
this.setParentType(especificType);
config = this.getConfigItems(especificType);
this.populateItemsCrown(config);
this.setRows(config.rows);
this.setCols(config.cols);
return this;
};
/**
* Validate if the shape type change
* @returns {boolean}
*/
Corona.prototype.isDirtyParentType = function () {
var isDirty = false;
if (this.getParent().getType() !== "PMActivity" && this.getParentType() !== this.getParent().getEspecificType()) {
isDirty = true;
}
return isDirty;
};
/**
* Item Crown Class
* @param options
* @constructor
*/
var ItemCrown = function (options) {
/**
* Call Shape Constructor
*/
PMUI.draw.Shape.call(this, options);
/**
* Define Id ItemCrown
* @type {null}
*/
this.id = null;
/**
* Parent Item Crown
* @type {null}
*/
this.parent = null;
/**
* Name Item Crown
* @type {string}
*/
this.name = null;
/**
* Class Name Item Crown
* @type {string}
*/
this.className = null;
/**
* Width of the Item Crown
* @type {number}
*/
this.width = 22;
/**
* Height of the Item Crown
* @type {number}
*/
this.height = 22;
/**
* Event OnClick
* @type {null}
*/
this.eventOnClick = null;
/**
* Event OnMouseDown
* @type {null}
*/
this.eventOnMouseDown = null;
/**
* Event OnMouseUp
* @type {null}
*/
this.eventOnMouseUp = null;
/**
* Event OnMouseMove
* @type {null}
*/
this.eventOnMouseMove = null;
/**
* Event OnMouseOut
* @type {null}
*/
this.eventOnMouseOut = null;
this.init(options);
};
/**
* Define new Object Shape
* @type {PMUI.draw.Shape}
*/
ItemCrown.prototype = new PMUI.draw.Shape();
/**
* Defines the object type
* @type {String}
*/
ItemCrown.prototype.type = 'ItemCrown';
/**
* Inicialize Item Crown
* @param options
* @returns {ItemCrown}
*/
ItemCrown.prototype.init = function (options) {
if (typeof options === "object") {
this.setId(options.id);
this.setParent(options.parent);
this.setName(options.name);
this.setClassName(options.className);
this.setEventOnClick(options.eventOnClick);
this.setEventOnMouseDown(options.eventOnMouseDown);
this.setEventOnMouseUp(options.eventOnMouseUp);
this.setEventOnMouseMove(options.eventOnMouseMove);
this.setEventOnMouseOut(options.eventOnMouseOut);
}
return this;
};
/**
* Get Id Item Crown
* @returns {null}
*/
ItemCrown.prototype.getId = function () {
return this.id;
};
/**
* Get parent Item Crown
* @returns {null}
*/
ItemCrown.prototype.getParent = function () {
return this.parent;
};
/**
* Get Name
* @returns {null|string|*}
*/
ItemCrown.prototype.getName = function () {
return this.name;
};
/**
* Get Class Name Style
* @returns {null|*}
*/
ItemCrown.prototype.getClassName = function () {
return this.className;
};
/**
* Get Width
* @returns {number|*}
*/
ItemCrown.prototype.getWidth = function () {
return this.width;
};
/**
* Get Height
* @returns {number|*}
*/
ItemCrown.prototype.getHeight = function () {
return this.height;
};
/**
* Get Function EventOnclick
* @returns {null|*}
*/
ItemCrown.prototype.getEventOnClick = function () {
return this.eventOnClick;
};
/**
* Get Function EventOnMouseDown
* @returns {null|*}
*/
ItemCrown.prototype.getEventOnMouseDown = function () {
return this.eventOnMouseDown;
};
/**
* Set Id ItemCrown
* @param id
* @returns {ItemCrown}
*/
ItemCrown.prototype.setId = function (id) {
if (id && typeof id === "string") {
this.id = id;
}
return this;
};
/**
* Set Parent ItemCrown
* @param parent
* @returns {ItemCrown}
*/
ItemCrown.prototype.setParent = function (parent) {
if (typeof parent === "object" && !jQuery.isEmptyObject(parent)) {
this.parent = parent;
}
return this;
};
/**
* Set Name
* @param name
* @returns {ItemCrown}
*/
ItemCrown.prototype.setName = function (name) {
if (name && typeof name === "string") {
this.name = name;
}
return this;
};
/**
* Set ClassName Style
* @param className
* @returns {ItemCrown}
*/
ItemCrown.prototype.setClassName = function (className) {
if (className && typeof className === "string") {
this.className = className
}
return this;
};
/**
* Set Width
* @param width
* @returns {ItemCrown}
*/
ItemCrown.prototype.setWidth = function (width) {
if (width) {
this.width = width;
}
return this;
};
/**
* Set Height
* @param height
* @returns {ItemCrown}
*/
ItemCrown.prototype.setHeight = function (height) {
if (height) {
this.height = height;
}
return this;
};
/**
* Set Function EventOnClick
* @param func
* @returns {ItemCrown}
*/
ItemCrown.prototype.setEventOnClick = function (func) {
if (func && typeof func === "function") {
this.eventOnClick = func;
}
return this;
};
/**
* Set Function EventOnMouseDown
* @param func
* @returns {ItemCrown}
*/
ItemCrown.prototype.setEventOnMouseDown = function (func) {
if (func && typeof func === "function") {
this.eventOnMouseDown = func;
}
return this;
};
/**
* Set Function EventOnMouseUp
* @param func
* @returns {ItemCrown}
*/
ItemCrown.prototype.setEventOnMouseUp = function (func) {
if (func && typeof func === "function") {
this.eventOnMouseUp = func;
}
return this;
};
/**
* Set Function EventOnMouseMove
* @param func
* @returns {ItemCrown}
*/
ItemCrown.prototype.setEventOnMouseMove = function (func) {
if (func && typeof func === "function") {
this.eventOnMouseMove = func;
}
return this;
};
/**
* Set Function EventOnMouseOut
* @param func
* @returns {ItemCrown}
*/
ItemCrown.prototype.setEventOnMouseOut = function (func) {
if (func && typeof func === "function") {
this.eventOnMouseOut = func;
}
return this;
};
/**
* Create HTML Item Crown
* @returns {*}
*/
ItemCrown.prototype.createHtmlItem = function () {
var htmlItemCrown,
classItemCrown = "item-crown",
positionDefault = 'relative';
PMUI.draw.Shape.prototype.createHTML.call(this);
htmlItemCrown = this.html;
htmlItemCrown.className = this.getClassName() + " " + classItemCrown;
htmlItemCrown.title = this.getName();
htmlItemCrown.style.position = positionDefault;
htmlItemCrown.style.width = this.getWidth() + "px";
htmlItemCrown.style.height = this.getHeight() + "px";
this.html = htmlItemCrown;
return this;
};
/**
* Listeners
* @returns {ItemCrown}
*/
ItemCrown.prototype.attachListeners = function () {
var htmlItemCrown;
htmlItemCrown = this.html;
if (htmlItemCrown) {
jQuery(htmlItemCrown).click(this.onClick());
jQuery(htmlItemCrown).mousedown(this.onMouseDown());
jQuery(htmlItemCrown).mouseup(this.onMouseUp());
jQuery(htmlItemCrown).mousemove(this.onMouseMove());
jQuery(htmlItemCrown).mouseout(this.onMouseOut());
}
this.html = htmlItemCrown;
return this;
};
/**
* OnClick Event
* @returns {Function}
*/
ItemCrown.prototype.onClick = function () {
var that = this;
return function (e) {
e.stopPropagation();
e.preventDefault();
if (that.eventOnClick) {
that.eventOnClick(that);
}
};
};
/**
* OnMouseDown Event
* @returns {Function}
*/
ItemCrown.prototype.onMouseDown = function () {
var that = this;
return function (e) {
e.stopPropagation();
e.preventDefault();
if (that.eventOnMouseDown) {
that.eventOnMouseDown(that);
}
};
};
/**
* OnMouseUp Event
* @returns {Function}
*/
ItemCrown.prototype.onMouseUp = function () {
var that = this;
return function (e) {
e.stopPropagation();
e.preventDefault();
if (that.eventOnMouseUp) {
that.eventOnMouseUp(that);
}
};
};
/**
* OnMouseMove Event
* @returns {Function}
*/
ItemCrown.prototype.onMouseMove = function () {
var that = this;
return function (e) {
e.stopPropagation();
e.preventDefault();
if (that.eventOnMouseMove) {
that.eventOnMouseMove(that);
}
};
};
/**
* OnMouseOut Event
* @returns {Function}
*/
ItemCrown.prototype.onMouseOut = function () {
var that = this;
return function (e) {
e.stopPropagation();
e.preventDefault();
if (that.eventOnMouseOut) {
that.eventOnMouseOut(that);
}
};
};
/**
* Class ModelCrown
* @param options
* @constructor
*/
var ModelCrown = function (options) {
this.itemsDefault = PMUI.util.ArrayList();
this.init(options);
};
/**
* Initialize ModelCrown
* @param options
*/
ModelCrown.prototype.init = function (options) {
if (typeof options === "object" && Object.keys(options).length > 0) {
this.setItemsDefault(options.items);
}
return this;
};
/**
* Get Items ModelCrown
* @returns {*|Array}
*/
ModelCrown.prototype.getItemsDefault = function () {
return this.itemsDefault;
};
/**
* Set Items ModelCrown
* @param items {Array of the Objects}
* @returns {ModelCrown}
*/
ModelCrown.prototype.setItemsDefault = function (items) {
var itemCrown,
max,
i;
if (items && Array.isArray(items) && items.length > 0) {
max = items.length;
for (i = 0; i < max; i += 1) {
this.itemsDefault.insert(items[i]);
}
}
return this;
};
/**
* Add New Item Crown
* Example:
* PMDesigner.modelCrown.addItemToCrown({
* id: "example-id",
* name: "exmaple-name".translate(),
* className: "name-class-css",
* eventOnClick: function(item) {
* --Your code goes here
* },
* eventOnMouseDown: function(item) {
* --Your code goes here
* }
* });
*
* @param itemObject {Object}
* @returns {ModelCrown}
*/
ModelCrown.prototype.addItemToCrown = function (itemObject) {
if (typeof itemObject === "object" && Object.keys(itemObject).length > 0) {
this.itemsDefault.insert(itemObject);
}
return this;
};
/**
* Remove ItemCrown
* Example:
* PMDesigner.modelCrown.removeItemFromCrown(idItem);
*
* @param idItem {string}
* @returns {ModelCrown}
*/
ModelCrown.prototype.removeItemFromCrown = function (idItem) {
var itemCrown;
if (idItem && typeof idItem === "string") {
itemCrown = this.itemsDefault.find("id", idItem);
if (itemCrown) {
this.itemsDefault.remove(itemCrown);
}
}
return this;
};
var __env = __env || {};__env.USER_GUEST = {"uid":"00000000000000000000000000000002","firstname":"Guest","lastname":"Guest","username":"guest"}; __env.pmVariable = {"regEx":"/^[a-zA-Z\\_]{1}\\w+$/"};