46082 lines
1.6 MiB
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 = {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"',
|
|
"'": '''
|
|
};
|
|
|
|
/** 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, & 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, & 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><script></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
|
|
* `&`, `<`, `>`, `"`, and `'` 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 & 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++ // & 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="""
|
|
, ATTRIB_VALUE_ENTITY_U : S++ // <foo bar="
|
|
, 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': ' ',
|
|
'\n\r': ' ',
|
|
'"': '"'
|
|
};
|
|
|
|
// 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 →',
|
|
/* Previous button label in tooltip box */
|
|
prevLabel: '← 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 = " ";
|
|
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">…</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+$/"};
|