How to use ensureUnlocked method in Appium Android Driver

Best JavaScript code snippet using appium-android-driver

ctx.core.js

Source:ctx.core.js Github

copy

Full Screen

1/**2 * @module Ctx framework Core classes and methods3 * @file ctx/ctx.core.js4 * @description5 * This module implements core classes and functions used to define **Contextor** language:6 * * Object descriptor,7 * * Technical and functional events,8 * * Context management,9 * * Registry management,10 * * ...11 * \\12 * // :!: __Caution:__ this page is auto-generated from source code and should not be modified from wiki application.//13 * @author SAP Intelligent RPA R&D team14 * 15 */16/**17 * @ignore18 * Global legacy variables, used when porting V2 language projects to V3 language19 * Do not use in general case !20 */21var _Work0_ = '';22var _Work1_ = '';23var _Work2_ = '';24var _Work3_ = '';25var _Work4_ = '';26var _Work5_ = '';27var _Work6_ = '';28var _Work7_ = '';29var _Work8_ = '';30var _Work9_ = '';31/**32 * @ignore33 * @global _DEBUG flag: can be overidded at compile time34 * @define {boolean} */35var _DEBUG = false;36// add 'String.prototype...' function if nedded37if (!String.prototype.toCamel) {38 String.prototype.toCamel = function(){39 return this.replace(/([-_ ][a-z])/g, function($1){return $1.toUpperCase().replace(/[-_ ]/,'');});40 };41}42if (!String.prototype.trim) {43 String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); };44}45if (!String.prototype.ltrim) {46 String.prototype.ltrim = function(){ return this.replace(/^\s+/,''); };47}48if (!String.prototype.rtrim) {49 String.prototype.rtrim = function(){ return this.replace(/\s+$/,''); };50}51if (!String.prototype.startsWith) {52 String.prototype.startsWith = function(prefix) { return (this.indexOf(prefix) == 0); };53}54if (!String.prototype.endsWith) {55 String.prototype.endsWith = function(suffix) { return (this.indexOf(suffix, this.length - suffix.length) !== -1); };56}57if (!String.prototype.format) {58 String.prototype.format = function() {59 var args = arguments;60 return this.replace(/{(\d+)}/g, function(match, number) {61 return typeof args[number] != 'undefined'62 ? args[number]63 : match64 ;65 });66 };67}68// add 'Object.keys' function if nedded69if (typeof Object.keys !== 'function') {70 // JScript in IE8 and below mistakenly skips over built-in properties.71 // https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute72 var hasDontEnumBug = !({toString: true}).propertyIsEnumerable('toString');73 var getKeys = function(object) {74 var type = typeof object;75 if (type != 'object' && type != 'function' || object === null) {76 throw new TypeError('Object.keys called on non-object');77 }78 var keys = [];79 for (var key in object) {80 if (Object.prototype.hasOwnProperty.call(object, key)) {81 keys.push(key);82 }83 }84 return keys;85 }86 if (hasDontEnumBug) {87 var dontEnumProperties = [88 'toString',89 'toLocaleString',90 'valueOf',91 'hasOwnProperty',92 'isPrototypeOf',93 'prototypeIsEnumerable',94 'constructor'95 ];96 Object.keys = function(object) {97 var keys = getKeys(object);98 for (var ii = 0, il = dontEnumProperties.length; ii < il; ii++) {99 var property = dontEnumProperties[ii];100 if (object.hasOwnProperty(property)) {101 keys.push(property);102 }103 }104 return keys;105 };106 } else {107 Object.keys = getKeys;108 }109}110if (typeof Object.create !== 'function') {111 Object.create = function (o) {112 /** @constructor */113 function F() { return undefined; }114 F.prototype = o;115 return new F();116 };117}118// **********************************119// *** Polyfill methods for Array ***120// **********************************121// add 'Array.isArray' function if nedded122if (!Array.isArray) {123 Array.isArray = function(arg) {124 return Object.prototype.toString.call(arg) === '[object Array]';125 };126}127/**128 * Contextor Framework129 * @class ctx130 * @constructor131 * @path ctx132 */133var ctx = ( function () {134 /** 135 * @ignore136 * Framework global version137 * @const138 * @type {string}139 */140 var _coreVersion = "2.0.7.54";141 // verbs saved anyway142 var _forceSave = {143 'ctx.log': true144 };145 var _autoStartKey = "HKCU\\Software\\SAP\\Intelligent RPA\\Settings\\DisableAutoStart";146 var _confirmStartKey = "HKCU\\Software\\SAP\\Intelligent RPA\\Settings\\ConfirmStart";147 var _restartingKey = "HKCU\\Software\\SAP\\Intelligent RPA\\Settings\\Restarting";148 var _runningKey = "HKCU\\Software\\SAP\\Intelligent RPA\\Settings\\Running";149 var _serviceStartKey = "HKCU\\Software\\SAP\\Intelligent RPA\\Settings\\ServiceStart";150 var _cmdLineNameKey = "HKCU\\Software\\SAP\\Intelligent RPA\\Settings\\CmdLineName";151 var _cmdLineKey = "HKCU\\Software\\SAP\\Intelligent RPA\\Settings\\CmdLine";152 //var _configFolderPersonal = "%localappdata%\\SAP\\Intelligent RPA\\config\\";153 //var _configFolderCommon = "%programdata%\\SAP\\Intelligent RPA\\config\\"154 //var _configFile = "config.xml";155 /** @type {Array} */ var _projectList = [];156 /** @type {number} */ var _currentProjectIndex = -1;157 // read options from the command line158 var _updateOptions = function() {159 // read options from the command line160 ctx.noNotify = true;161 var node = ctx.context.getCtx('//GLOBAL/WkMng_Info/OptionFiles');162 if (node && node.childNodes) {163 for (var i = 0; i < node.childNodes.length; i ++) {164 var text = node.childNodes[i].text;165 if (text) {166 var pos = text.indexOf('=');167 if (pos > 0) {168 var key = text.substring(0, pos).trim();169 var val = text.substring(pos + 1).trim();170 if (key !== '') {171 // overload or add option172 if (ctx.index(ctx.options, key) !== undefined) {173 var type = typeof(ctx.index(ctx.options, key));174 if (type == 'boolean')175 val = (val == 'true' ? true : false);176 else if (type == 'number')177 val = parseInt(val, 10);178 } else {179 if (val == 'true') val = true;180 else if (val == 'false') val = false;181 else if (!isNaN(parseInt(val, 10))) val = parseInt(val, 10);182 }183 ctx.index(ctx.options, key, val);184 }185 } else {186 // non formatted option (<key>=>value>) : store it 'as is'187 ctx.options.optionFiles.push(text);188 }189 }190 }191 }192 }193 // read options from the option file194 var _updateOptionFile = function () {195 var text = '';196 try {197 var file = ctx.options.path.bin + "\\ctx.options.json";198 text = ctx.fso.file.read(file);199 if (text) {200 var obj = ctx.json.parse(text);201 var groups = ['all'];202 var groups2;203 if (obj['machines']) {204 groups2 = obj['machines'][ctx.options.computerName];205 if (groups2 && Array.isArray(groups2)) {206 groups = groups.concat(groups2);207 }208 }209 if (obj['logins']) {210 groups2 = obj['logins'][ctx.options.userName];211 if (groups2 && Array.isArray(groups2)) {212 groups = groups.concat(groups2);213 }214 }215 ctx.each(groups, function(id, group) {216 var options = obj.options[group];217 if ('object' === typeof(options)) {218 ctx.set(options, ctx.options);219 }220 });221 }222 } catch (ex) {}223 }224 //var _htmlDoc = null;225 var _timerObj = {};226 var _timerIndex = 0;227 var self =228 /** @lends ctx */229 {230 /** any event const value231 * @ignore232 * @const233 * @path ctx.anyEvent234 * @property {string} */ anyEvent: '_Any_',235 /** class type236 * @ignore237 * @const238 * @path ctx.ctxType239 * @property {string} */ ctxType: 'ctx',240 /** root object241 * @ignore242 * @path ctx.root243 * @property {Object} */ root: null,244 /** available projects245 * @ignore246 * @path ctx.availableProjects247 * @property {Array} */ availableProjects: [],248 /** restart mode249 * @ignore250 * @path ctx.restartAgent251 * @property {boolean} */ restartAgent: false,252 /** restart mode253 * @ignore254 * @path ctx.shutdownOnIdle255 * @property {boolean} */ shutdownOnIdle: false,256 /** map of event handlers257 * @ignore258 * @path ctx.subscriptions259 * @property {Object} subscriptions */ subscriptions: {},260 /** map of pending events261 * @ignore262 * @path ctx.pendingEvents263 * @property {Array} pendingEvents */ pendingEvents: [],264 /** Application array265 * @ignore266 * @path ctx.app267 * @description268 * Contains the list of declared applications269 *270 * __Ex.:__271<code javascript>272// enumerate applications273for (var id in ctx.app) {274 var app = ctx.app[id];275 ctx.log(app.name);276}277</code>278 * @property {Object<string, ctx.application>} */ app : {},279 /** Application data array280 * @ignore281 * @path ctx.data282 * @description283 * ctx.data.284 * Appli1285 * [0] --> contains ctx.app.Appli1[0].data286 * [3584] --> contains ctx.app.Appli1[3584].data287 * Appli2288 * [0] --> contains ctx.app.Appli2[0].data289 * [2587] --> contains ctx.app.Appli2[2587].data290 * [3798] --> contains ctx.app.Appli2[3789].data291 *292 * @ignore [internal usage]293 * Contains the list of data container for declared application instances294 * @property {Array<ctx.dataClass>} */ data : [],295 /** map of 'Action' functions depending on nature296 * @ignore297 * @path ctx.actionFunction298 * @property {Object} */ actionFunction : {},299 /** map of 'ActionApp' functions depending on nature300 * @ignore301 * @path ctx.actionAppFunction302 * @property {Object} */ actionAppFunction : {},303 /** custom types declared for items304 * @ignore305 * @path ctx.customTypes306 * @property {Object} */ customTypes : {},307 /** disable notifications (single)308 * @ignore309 * @path ctx.noNotify310 * @property {boolean} */ noNotify : false,311 /** disable notifications312 * @ignore313 * @path ctx.lockNoNotify314 * @property {boolean} */ lockNoNotify : false,315 /** hide trace parameters316 * @ignore317 * @path ctx.anonymous318 * @property {boolean} */ anonymous : false,319 /** custom types declared for pages320 * @ignore321 * @path ctx.pageCustomTypes322 * @property {Object} */ pageCustomTypes : {},323 /** Map of pending functions324 * @ignore325 * @path ctx.pendingFunctions326 * @property {Array<function()>} */ pendingFunctions : [],327// /** Map of pending scenarios328// * @ignore329// * @path ctx.pendingScenarios330// * @property {Array<ctx.scenarioClass>} */ pendingScenarios : [],331//332// /** Map of pending promises333// * @ignore334// * @path ctx.pendingPromises335// * @property {Array<ctx.promiseClass>} */ pendingPromises : [],336 /** Object index337 * @ignore338 * @path ctx.objectIndex339 * @property {number} */ objectIndex : 0,340 /** Counter array341 * @ignore342 * @path ctx.counters343 * @property {Object} */ counters : {344 /** Action counter list345 * @ignore346 * @path ctx.counters.actions347 * @property {Object} */ actions: {},348 /** Running scenario counter list349 * @ignore350 * @path ctx.counters.scenarios351 * @property {Object} */ scenarios: {}352 },353 /**354 * @ignore355 * @type {string} */ _traceDate : '',356 /**357 * @ignore358 * @type {WScriptShell} */ _shell : null,359 /**360 * @ignore361 * @type {ScriptingFileSystemObject} */ _fso : null,362 /**363 * Current application364 * @path ctx.currentAppli365 * @property {ctx.application} currentAppli */ currentAppli : null,366 /** Current event367 * @path ctx.currentEvent368 * @property {ctx.event} currentEvent */ currentEvent : null,369 /** Current promise370 * @ignore371 * @path ctx.currentPromise372 * @property {ctx.promiseClass} currentPromise */ currentPromise : null,373 /**374 * Current page375 * @path ctx.currentPage376 * @property {ctx.page} currentPage */ currentPage : null,377 /** Current running scenario378 * @ignore379 * @path ctx.currentScenario380 * @property {ctx.scenarioClass} currentScenario */ currentScenario : null,381 /** Current running step382 * @ignore383 * @path ctx.currentStep384 * @property {ctx.stepClass} currentStep */ currentStep : null,385 /** Current subscription386 * @ignore387 * @path ctx.currentSubscription388 * @property {Object} currentSubscription */ currentSubscription : null,389 /** Current parentId390 * @ignore391 * @path ctx.currentParentId392 * @property {number} currentParentId */ currentParentId : 0,393 /** Current timer reason394 * @ignore395 * @path ctx.currentTimerReason396 * @property {string} currentTimerReason */ currentTimerReason : '',397 /** Engine activity : variable is false by default, is set to true after event GLOBAL:START is received398 * @ignore399 * @path ctx.engineStarted400 * @property {boolean} engineStarted */ engineStarted : false,401 /** Events triggered402 * @ignore403 * @path ctx.eventTriggered404 * @property {boolean} eventTriggered */ eventTriggered : false,405 /** Engine is stopping (GLOBAL END was received)406 * @ignore407 * @path ctx.engineStopInProgress408 * @property {boolean} */ engineStopInProgress : false,409 /** Project sub features410 * @ignore411 * @path ctx.features412 * @property {Object} */ features : {},413 /** Last received event414 * @ignore415 * @path ctx.lastEvent416 * @property {ctx.event} lastEvent */ lastEvent : null,417 /**418 * Adds an application or process.419 * @description420 * __Ex.:__421<code javascript>422var GLOBAL = ctx.addApplication( 'GLOBAL' );423var LinkedIn = ctx.addApplication( 'LinkedIn', {"nature":"WEB3","path":"www.linkedin.com/"} );424</code>425 * @method addApplication426 * @path ctx.addApplication427 * @ignore428 * @param {string} name429 * @param {Object} [obj]430 * @return {ctx.application} Created application431 */432 addApplication : function (name, obj) {433 return (ctx.app[name] = new ctx.application(name, obj));434 },435 /**436 * Adds a pending function437 * @description438 * __Ex.:__439<code javascript>440</code>441 * @method addPendingFunction442 * @path ctx.addPendingFunction443 * @ignore444 * @param {function()} callback445 */446 addPendingFunction : function (callback) {447 if (ctx.currentEvent && ctx.currentEvent.parent) {448 // add function in the pending list, it will be called at the end of event treatment449 ctx.pendingFunctions.push(callback);450 } else {451 // no event is being treated (typically, endStep() called from a timer function) : call immediately452 callback();453 }454 },455 /**456 * clears old trace folders and archives457 * @description458 * __Ex.:__459<code javascript>460ctx.clearTraceFolder();461</code>462 * @method clearTraceFolder463 * @ignore internal use464 * @path ctx.clearTraceFolder465 * @return {boolean} result466 */467 clearTraceFolder : function () {468 var res = true;469 try {470 // archive should be something like files '<computer>.<user>.2015-10-30T14.45.23Z.889.zip' or folders '<computer>.<user>.2015-10-30T14.45.23Z.889'471 var targets = { };472 ctx.noNotify = true;473 targets.files = ctx.fso.folder.getFileCollection(ctx.options.path.log, true),474 ctx.noNotify = true;475 targets.folders = ctx.fso.folder.getFolderCollection(ctx.options.path.log, true)476 var prefix = ctx.options.computerName + '.' + ctx.options.userName + '.';477 var pos, pos2;478 var sDate;479 var oldFileArray = []; // archives to be deleted480 var fileArray = [];481 ctx.each(targets, function(id, target) {482 ctx.each(target, function(index, item) {483 var filename = item.Name;484 pos = filename.indexOf(prefix);485 if (pos >= 0) {486 // date = '2015-10-30T...'487 sDate = filename.substr(prefix.length + pos, 10);488 var todayDate = new Date();489 var y = parseInt(sDate.substr(0, 4), 10);490 var m = (parseInt(sDate.substr(5, 2), 10) - 1);491 var d = parseInt(sDate.substr(8, 2), 10);492 if ((y > 2000) && (d > 0)) {493 var fileDate = new Date(y, m, d);494 var diffDate = todayDate - fileDate;495 var nbDays = Math.floor(diffDate / (1000 * 60 * 60 * 24));496 if (nbDays <= ctx.options.traceArchive.maxDuration) {497 fileArray.push(filename);498 } else {499 oldFileArray.push(filename);500 }501 }502 }503 });504 });505 //list of recent files:506 // - sort by ascendant date507 // - move the first entries (oldest) to oldFileArray, (only keep the last 'maxCount' archives)508 fileArray.sort();509 var nbToDelete = fileArray.length - ctx.options.traceArchive.maxCount;510 if (nbToDelete > 0) {511 for (var i = 0; i < nbToDelete ; i ++) {512 var filename = fileArray.shift();513 oldFileArray.push(filename);514 }515 }516 //delete obsolete files and folders517 while (oldFileArray.length > 0) {518 var entry = ctx.options.path.log + '\\' + oldFileArray.shift();519 ctx.noNotify = true;520 if (entry.endsWith('.zip') ) {521 ctx.fso.file.remove(entry);522 } else {523 ctx.fso.folder.remove(entry);524 }525 }526 } catch (ex) {}527 return res;528 },529 /**530 * Compares two version numbers (one can be Interactive version)531 * @description532 * __Ex.:__533<code javascript>534if (ctx.compareVersion('3.0.6.5') < 0)535{536 // Interactive version is inferior to '3.0.6.5'537}538</code>539 * @advanced540 * @method compareVersion541 * @path ctx.compareVersion542 * @param {string} version version to be compared543 * @param {string} [reference] reference version for comparison (if omitted, the Interactive version 'ctx.options.productVersion' is used)544 * @param { function(e.error, string, Object) } [callback] optional callback to be called if comparison < 0545 * @param { Object } [obj] optional object as parameter for the callback546 * @return {number} result : -2 (failure), -1 (version > reference), 0 (equal), 1 (reference > version)547 */548 compareVersion : function (version, reference, callback, obj) {549 reference = reference || ctx.options.productVersion;550 var res = 0; // version = reference551 if (typeof version + typeof reference !== 'stringstring') {552 res = -2;553 } else {554 var a = reference.split('.');555 var b = version.split('.');556 var i = 0;557 var len = Math.max(a.length, b.length);558 for (; i < len; i++) {559 if ((a[i] && !b[i] && parseInt(a[i], 10) > 0) || (parseInt(a[i], 10) > parseInt(b[i], 10))) {560 res = 1; // reference > version561 break;562 } else if ((b[i] && !a[i] && parseInt(b[i], 10) > 0) || (parseInt(a[i], 10) < parseInt(b[i], 10))) {563 res = -1; // version > reference564 break;565 }566 }567 }568 if ((res < 0) && callback && ('function' === typeof callback)) {569 if (obj === undefined) obj = null;570 callback(e.error.NotImplemented, "Requires min. version: " + version, obj);571 }572 return res;573 },574 /**575 * Emulates DOM 'window' and 'document' objects in a non-Web javascript engine576 * @ignore577 * @method emulateBrowser578 * @path ctx.emulateBrowser579 * @return {boolean} result success state580 */581 emulateBrowser : function () {582 try {583 if (typeof window === 'undefined') {584 // disable cookie security warning which can lock htmlfile (following KB4088775)585 var val = ctx.registry.get('Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1A10', e.registry.root.CurrentUser);586 if (val != 0) {587 ctx.registry.set('Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1A10', 0, e.registry.root.CurrentUser, e.registry.type.Number);588 }589 try {590 if ('undefined' === typeof setTimeout) {591 // event for timer notifications592 GLOBAL.addEvent({ evCtxtTimer: '' }); 593 GLOBAL.events.evCtxtTimer.internal = true;594 GLOBAL.events.evCtxtTimer.on(function (ev) {595 if (ev && ev.data) {596 var timerIndex = parseInt(ev.data, 10);597 var callback = _timerObj[timerIndex];598 if (callback && ('function' === typeof callback)) {599 delete _timerObj[timerIndex];600 callback();601 }602 }603 });604 /**605 * @param {Function|string} callback606 * @param {number} [delay]607 * @param {...*} [var_args]608 * @ignore609 * @see https://developer.mozilla.org/en/DOM/window.setTimeout610 */611 setTimeout = function(callback, delay, var_args) {612 // workaround following KB4088775 : reallocate htmlfile at each call613 _timerIndex ++;614 _timerObj[_timerIndex] = callback;615 GLOBAL.notify(GLOBAL.events.evCtxtTimer, _timerIndex, delay);616 return _timerIndex;617 };618 /*setTimeout = function(callback, delay, var_args) {619 // workaround following KB4088775 : reallocate htmlfile at each call620 var timer = {621 doc: new ActiveXObject("htmlfile"),622 id: 0623 };624 _timerIndex ++;625 _timerObj[_timerIndex] = timer;626 timer.id = timer.doc.parentWindow.setTimeout( function(timerIndex) { return function() {627 var timer = _timerObj[timerIndex];628 if (timer) {629 delete _timerObj[timerIndex];630 if (callback && ('function' === typeof callback))631 callback();632 } else {633 ctx.log('setTimeout: unknown id ' + _timerIndex, e.logIconType.Warning)634 }635 }; }(_timerIndex), delay, var_args);636 return _timerIndex;637 };*/638 clearTimeout = function(index) {639 // workaround following KB4088775 : reallocate htmlfile at each call640 var callback = _timerObj[index];641 if (callback) {642 delete _timerObj[index];643 }644 return index;645 };646 /*clearTimeout = function(obj) {647 // workaround following KB4088775 : reallocate htmlfile at each call648 var timer = _timerObj[obj];649 if (timer) {650 delete _timerObj[obj];651 return id;652 }653 };*/654 /**655 * @param {Function|string} callback656 * @param {number} [delay]657 * @ignore658 * @see https://developer.mozilla.org/en/DOM/window.setTimeout659 */660 setInterval = function(callback, delay) {661 // workaround following KB4088775 : reallocate htmlfile at each call662 var timer = {663 doc: new ActiveXObject("htmlfile"),664 id: 0665 };666 _timerIndex ++;667 _timerObj[_timerIndex] = timer;668 timer.id = timer.doc.parentWindow.setInterval( function() {669 if (callback && ('function' === typeof callback))670 callback();671 }, delay);672 return _timerIndex;673 };674 clearInterval = function(obj) {675 // workaround following KB4088775 : reallocate htmlfile at each call676 var timer = _timerObj[obj];677 if (timer) {678 var id = timer.doc.parentWindow.clearInterval(timer.id);679 delete _timerObj[obj];680 return id;681 }682 };683 }684 alert = function(message) {685 var htmlDoc = new ActiveXObject("htmlfile"); // workaround following KB4088775 : reallocate htmlfile at each call686 return htmlDoc.parentWindow.alert(message)687 };688 } catch (ex) {689 alert = function(message) { return ctx.log(message) };690 }691 }692 } catch (ex) {693 return false;694 }695 return true;696 },697 /**698 * Gets a defined applicaton or process object by its name699 * @advanced700 * @description701 * __Ex.:__702<code javascript>703var app = ctx.getApplication('LinkedIn');704</code>705 * @method getApplication706 * @path ctx.getApplication707 * @param {string} name application name708 * @return {ctx.application} Application object709 */710 getApplication : function (name) {711 return (ctx.app[name]);712 },713 /**714 * Retrieves the object descriptor from a string selector715 * @description716 * Object selector, should be : ''[appliName[(appliInst)]]:[pageName[(pageInst)]]:[item[(itemInst)][index]]:''717 * * if 'appliName' is omitted, current appli is used718 * * if 'appliInst' is omitted, current appli instance is used719 *720 * __Ex.:__721<code javascript>722 - var desc = ctx.getDescriptor("MyAppli:pMain:btSearch");723 - var desc = ctx.getDescriptor(".pMain.btSearch");724 - var desc = ctx.getDescriptor("..btSearch");725 - var desc = ctx.getDescriptor("MyAppli(5145).pMain.btSearch");726 - var desc = ctx.getDescriptor("MyAppli.pMain(1002).btSearch");727 - var desc = ctx.getDescriptor("MyAppli.pMain.rowResult[0]"); // first value in occursed item728 - var desc = ctx.getDescriptor("MyAppli.pMain.tabResult[iRow][iCol]"); // cell (iRom, iCol) in an array729</code>730 * @method getDescriptor731 * @path ctx.getDescriptor732 * @ignore733 * @param {string|ctx.descriptor} [selector] string selector734 * @param {ctx.descriptor} [desc] Optional source descriptor object (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])735 * @return {ctx.descriptor} Object descriptor (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])736 */737 getDescriptor : function (selector, desc) {738 if ((typeof selector === 'undefined') || (selector === '')) {739 selector = '.'; // implicit selector : [current appli:current page]740 }741 var tSelector = selector.split('.');742 var val;743 var offset = 0;744 if (desc) {745 if (desc.appliName !== '')746 offset--;747 if (desc.pageName !== '')748 offset--;749 } else {750 desc = new ctx.descriptor();751 }752 var nb = tSelector.length;753 if (typeof tSelector[offset] !== 'undefined') {754 if (tSelector[offset] !== '') {755 //rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),756 val = tSelector[offset]; //.match('/^*\(/g');757 desc.appliName = val;758 if (ctx.currentEvent && desc.appliName == ctx.currentEvent.appliName && ctx.app[ctx.currentEvent.appliName] && ctx.app[ctx.currentEvent.appliName][ctx.currentEvent.appliInst])759 desc.appliInst = ctx.currentEvent.appliInst;760 } else if (ctx.currentEvent && ctx.app[ctx.currentEvent.appliName] && ctx.app[ctx.currentEvent.appliName][ctx.currentEvent.appliInst]) {761 desc.appliName = ctx.currentEvent.appliName;762 desc.appliInst = ctx.currentEvent.appliInst;763 }764 }765 if (typeof tSelector[offset + 1] !== 'undefined') {766 if (tSelector[offset + 1] !== '') {767 val = tSelector[offset + 1]; //.match('/^*\(/g');768 desc.pageName = val;769 if (ctx.currentEvent && desc.pageName == ctx.currentEvent.pageName)770 desc.pageInst = ctx.currentEvent.pageInst;771 } else if (ctx.currentEvent) {772 desc.pageName = ctx.currentEvent.pageName;773 desc.pageInst = ctx.currentEvent.pageInst;774 }775 }776 if (typeof tSelector[offset + 2] !== 'undefined') {777 if (tSelector[offset + 2] !== '') {778 val = tSelector[offset + 2]; //.match('/^*\(/g');779 desc.itemName = val;780 } else {781 desc.itemName = ctx.currentEvent.itemName;782 }783 desc.itemFullName = desc.itemName;784 for (var i = 0; i < desc.index.length; i++) {785 desc.itemFullName = desc.itemFullName + '[' + desc.index[i] + ']';786 }787 }788 return desc;789 },790 /**791 * Returns Javascript engine version.792 * @description793 * __Ex.:__794<code javascript>795var obj = ctx.getEngineVersion();796// obj = {797// scriptEngine: 'JScript',798// majorVersion: '5',799// minorVersion: '8',800// buildVersion: '16428' }801</code>802 * @method getEngineVersion803 * @path ctx.getEngineVersion804 * @return {Object} Object containing version values (see ex. below)805 */806 getEngineVersion : function () {807 var obj = {};808 try {809 obj.scriptEngine = Host.ScriptEngine();810 obj.majorVersion = Host.ScriptEngineMajorVersion();811 obj.minorVersion = Host.ScriptEngineMinorVersion();812 obj.buildVersion = Host.ScriptEngineBuildVersion();813 } catch(ex) {}814 ctx.notifyAction('ctx.getEngineVersion', obj);815 return obj;816 },817 /**818 * Returns whether agent is in trial mode.819 * @description 820 * @method getTrialMode821 * @path ctx.getTrialMode822 * @return {boolean} true if agent is in trial mode, false otherwise823 */824 getTrialMode : function () {825 ctx.notifyAction('ctx.getTrialMode');826 var res= false;827 try {828 res = ctx.wkMng.GetTrialMode() === 1 ? true : false;829 } catch(ex) {} 830 return res;831},832 /**833 * Returns enumerated key from a value.834 * @description835 * __Ex.:__836<code javascript>837var key = ctx.getEnumKey(e.socket.status, 2); // key equals 'open'838</code>839 * @method getEnumKey840 * @path ctx.getEnumKey841 * @param {Object} enumeration enumerated object842 * @param {*} value value to be searched843 * @return {string} enumerated key (empty string if not found) 844 */845 getEnumKey : function (enumeration, value) {846 var key = '';847 ctx.each(enumeration, function(id, val) {848 if (value == val) {849 key = id;850 return false;851 }852 });853 return key;854 },855// /**856// * Retrieves the object descriptor from the current page or application857// * @ignore858// * @method getObjectDescriptor859// * @path ctx.getObjectDescriptor860// * @param {ctx.descriptor} [desc] Optional source descriptor object (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])861// * @return {ctx.descriptor} Object descriptor (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])862// */863// getObjectDescriptor : function (desc) {864// // global descriptor : return default appli / page865// if (!desc)866// desc = new ctx.descriptor();867//// if (ctx.currentPage)868//// desc = ctx.currentPage.getObjectDescriptor(desc);869//// else if (ctx.currentAppli)870//// desc = ctx.currentAppli.getObjectDescriptor(desc);871//// if (desc.appliName == '') {872//// // default host process, in case no ctx.currentEvent is defined (usual if action launched using 'Test code' or 'Page tester')873//// desc = GLOBAL.getObjectDescriptor(desc);874//// }875// return desc;876// },877 /** Returns a formatted XML command from a command name and an object containing parameters878 * @description879 * __Ex.:__880<code javascript>881ex. : 'MESSBOX', {PageName: 'pVersion', Type: e.messbox.type.HTMLView, Template: 'Warning', Title: "Contextor - Version", ...}882returns : "<MESSBOX PageName='pVersion' Type='HTMLView' Template='Warning'><_Value>...</_Value></MESSBOX>"883</code>884 * Description885 * @method getXMLSyntax886 * @path ctx.getXMLSyntax887 * @ignore888 * @param {string} command command name ('MESSBOX', 'SETVALUE', 'LOGMESS', ...)889 * @param {Object} [object] command parameters890 * @param {string} [subcommand] optional subcommand as a string891 * @return {string} formatted string892 */893 getXMLSyntax : function (command, object, subcommand) {894 var str = '<' + command,895 val, att;896 // add standard attributes897 for (att in object) {898 if ((typeof object[att] !== 'undefined') && (object[att] != null)) {899 val = String(object[att]);900 if ((typeof val !== 'undefined') && !((val.indexOf('<') != -1) || (val.indexOf('>') != -1) || (val.indexOf('"') != -1) || (val.indexOf('&') != -1)))901 str = str + " " + att + "=\"" + object[att] + "\"";902 }903 }904 str = str + '>';905 // add CData attributes906 for (att in object) {907 if ((typeof object[att] !== 'undefined') && (object[att] != null)) {908 val = String(object[att]);909 if (val && (val !== '') && ((val.indexOf('<') != -1) || (val.indexOf('>') != -1) || (val.indexOf('"') != -1) || (val.indexOf('&') != -1))) {910 var bCData = (val.indexOf('<![CDATA[') == -1);911 str = str + "<_" + att + ">";912 if (bCData)913 str = str + "<![CDATA[";914 str = str + object[att];915 if (bCData)916 str = str + "]]>";917 str = str + "</_" + att + ">";918 }919 }920 }921 if (subcommand)922 str = str + subcommand;923 str = str + '</' + command + '>';924 return str;925 },926 /**927 * Gets or sets the debug mode928 * @description929 * __Ex.:__930<code javascript>931// add a test menu in systray in debug mode only932if (ctx.isDebug()) {933systray.addMenu(...);934}935</code>936 * @method isDebug937 * @deprecated Rather use ctx.options.isDebug938 * @path ctx.isDebug939 * @param {boolean} [value] boolean value to set the debug mode940 * @return {boolean} result true: debug mode | false: release mode941 */942 isDebug : function (value) {943 if (typeof value !== 'undefined')944 ctx.options.isDebug = (value ? true : false);945 return ctx.options.isDebug;946 },947 /**948 * Tests if an object is empty949 * @description950 * __Ex.:__951<code javascript>952// add a test menu in systray in debug mode only953if (ctx.isEmpty(obj)) { ... }954</code>955 * @method isEmpty956 * @path ctx.isEmpty957 * @param {Object} obj object to be tested958 * @return {boolean} result true: empty | false: not empty959 */960 isEmpty : function(obj) {961 for(var i in obj) { return false; } return true;962 },963 /**964 * Returns if project is launched in Studio or standalone mode965 * @description966 * __Ex.:__967<code javascript>968if (ctx.isStudioUsed()) { ... }969</code>970 * @method isStudioUsed971 * @path ctx.isStudioUsed972 * @return {boolean} result true: Studio mode | false: standalone mode973 */974 isStudioUsed : function() {975 return ctx.options.trace.frameworkNotify;976 },977 /**978 * Function used to transcode a source object to a destination object979 * @description980 * __Ex.:__981<code javascript>982var source = {983 Title: 'Inception',984 Released: '16 Jul 2010',985 Director: 'Christopher Nolan',986 Plot: 'A thief, who steals corporate secrets through ...'987};988var dest = {};989ctx.map(source, dest, {990 Title: title,991 Released: date,992 Director: director,993 Plot: details,994})995// --> dest = {996// title: 'Inception',997// datez: '16 Jul 2010',998// director: 'Christopher Nolan',999// details: 'A thief, who steals corporate secrets through ...'1000//};1001</code>1002 * @method map1003 * @path ctx.map1004 * @param {*} source source object1005 * @param {Object} dest destination object1006 * @param {Object} mapping transcoding object1007 * @return {Object} destination object1008 */1009 map : function (source, dest, mapping) {1010 dest = dest || {};1011 if ((typeof source !== 'object') || (typeof dest !== 'object') || (typeof mapping !== 'object')) {1012 throw new Error(e.error.InvalidArgument, "ctx.map : source, dest and mapping should be objects.");1013 }1014 ctx.each(mapping, function(id, value) {1015 if ((source[id] !== undefined) && (source[id] !== null)) dest[value] = source[id];1016 });1017 ctx.notifyAction('ctx.map');1018 return dest;1019 },1020 /**1021 * Function used to trace function calls1022 * @description1023 * __Ex.:__1024<code javascript>1025ctx.notifyAction('excel.file.open');1026</code>1027 * @method notifyAction1028 * @path ctx.notifyAction1029 * @ignore1030 * @param {string} name action name1031 * @param {*} [res] function result1032 * @param {ctx.descriptor} [desc] object descriptor (application, page, item) (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])1033 * @param {string} [verb] connector language verb1034 * @param {Object} [params] function parameters1035 * @param {*} [attributes] optional extra attributes1036 * @suppress {es5Strict } warning 'arguments.callee'1037 */1038 notifyAction : function (name, res, desc, verb, params, attributes) {1039 if (ctx.noNotify || ctx.lockNoNotify) {1040 ctx.noNotify = false;1041 return;1042 }1043 1044 // PLO - fix SAPMLIPA-11527 ctx.log generates an exception when loaded in the Intellisense engine1045 if (!ctx.engineStarted) return ;1046 1047 var forceSave = _forceSave[name];1048 if (ctx.options.trace.autoRecordingStarted || ctx.options.trace.frameworkNotify || ctx.options.trace.recording || forceSave) {1049 if (ctx.anonymous) {1050 params = null;1051 ctx.anonymous = false;1052 } else {1053 //var params3 = Array.prototype.slice.call(arguments);1054 params = params || (arguments.callee.caller.arguments ? Array.prototype.slice.call(arguments.callee.caller.arguments) : null);1055 }1056 var shortParams = ctx.ctxShort(params);1057// var toto = params.length;1058// var titi = shortParams.length;1059// var txt = '';1060// for (var id in shortParams) {1061// if (txt != '') {1062// txt += ', ';1063// }1064// if (typeof shortParams[id] === 'undefined') {1065// txt += 'undefined';1066// } else if (typeof shortParams[id] === 'string') {1067// txt += ctx.serialize(shortParams[id], true, false);1068// } else if (shortParams[id] instanceof ctx.event) {1069// /** @type {ctx.event} */ var ev = shortParams[id];1070// txt += ev.serialize(false, false);1071// } else {1072// txt += ctx.serialize(shortParams[id], false, false);1073// }1074// }1075 var obj = {1076 ts: ctx.getTime(),1077 ctx:'Action',1078 action: name,1079 params: ((ctx.options.anonymous || ctx.anonymous) ? null : shortParams),1080 result: ((ctx.options.anonymous || ctx.anonymous) ? null : res),1081 verb: verb1082 };1083 ctx.anonymous = false;1084 if (ctx.currentParentId > 0) {1085 obj.parentId = ctx.currentParentId;1086 }1087 if (desc) {1088 if (desc.appliName) {1089 obj.appliName = desc.appliName;1090 obj.appliInst = desc.appliInst;1091 }1092 if (desc.pageName) {1093 obj.pageName = desc.pageName;1094 obj.pageInst = desc.pageInst;1095 }1096 if (desc.itemName) {1097 obj.itemName = desc.itemFullName;1098 if (desc.itemInst > 0) { obj.itemInst = desc.itemInst; }1099 if (desc.itemOccurs > 0) { obj.itemOccurs = desc.itemOccurs; }1100 }1101 }1102 try {1103 if (attributes && ('object' === typeof attributes)) {1104 var shortAttributes = ctx.ctxShort(attributes);1105 for (var id in shortAttributes) {1106 obj[id] = shortAttributes[id];1107 }1108 }1109 } catch (ex) { }1110 ctx.notifyDebug(obj, forceSave);1111 }1112 if (name) {1113 if (ctx.counters.actions[name]) ctx.counters.actions[name] ++; else ctx.counters.actions[name] = 1;1114 }1115 },1116 /**1117 * Sends a debug string to Studio Debugger1118 * @description1119 * __Ex.:__1120<code javascript>1121var obj = {1122 ctx: 'State',1123 name: name,1124 ...1125};1126ctx.notifyDebug(obj);1127</code>1128 * @method notifyDebug1129 * @ignore1130 * @path ctx.notifyDebug1131 * @param {Object} obj1132 * @param {boolean} [forceSave] if true, trace is saved in any case1133 * @param {boolean} [fileOnly] if true, trace in file and not in Debug flow1134 */1135 notifyDebug : function (obj, forceSave, fileOnly) {1136 if (forceSave || ctx.options.trace.autoRecordingStarted || ctx.options.trace.frameworkNotify || ctx.options.trace.recording) {1137 // add timestamp1138 if (!obj.ts)1139 obj.ts = ctx.getTime();1140 var txt = ctx.serialize(obj, false, false, undefined, true);1141 // *** send notifications to Studio Debugger ***1142 if (ctx.options.trace.frameworkNotify && (typeof Host !== 'undefined') && (Host.Debug) && (!fileOnly)) {1143 Host.Debug.write(txt);1144 }1145 // *** local serialization in a trace file ***1146 if (ctx.engineStarted && (forceSave || ctx.options.trace.autoRecordingStarted || ctx.options.trace.recording) && ctx.options.traceFolder) {1147 //if (forceSave || ctx.options.trace.recording)1148 if (forceSave)1149 ctx.wkMng.CtxtWriteFile(ctx.options.path.log + '\\' + ctx.options.traceFolder + '\\traces.pscl', txt + '\n', true);1150 //if (ctx.options.trace.autoRecordingStarted && (!ctx.options.trace.recording))1151 if (ctx.options.trace.autoRecordingStarted || ctx.options.trace.recording)1152 ctx.wkMng.CtxtWriteFile(ctx.options.path.log + '\\' + ctx.options.traceFolderRecording + '\\traces.pscl', txt + '\n', true);1153 }1154 if (ctx.options.trace.alternativeTraceFile)1155 ctx.wkMng.CtxtWriteFile(ctx.options.trace.alternativeTraceFile, txt + '\n', true);1156 }1157 },1158 /**1159 * Function used to trace error1160 * @description1161 * __Ex.:__1162 * <code javascript>1163 * ctx.notifyError(data);1164 * </code>1165 * @method notifyError1166 * @path ctx.notifyError1167 * @ignore1168 * @param {*} data data1169 * @param {string} label label1170 */1171 notifyError : function (data, label) {1172 ctx.log(data, e.logIconType.Error, label);1173 },1174 /**1175 * Sends an event to Studio Debugger1176 * @description1177 * __Ex.:__1178<code javascript>1179var obj = {1180 ctx: 'State',1181 name: name,1182 ...1183};1184ctx.notifyEvent(obj);1185</code>1186 * @method notifyEvent1187 * @ignore1188 * @path ctx.notifyEvent1189 * @param {ctx.event} ev1190 * @param {boolean} [fileOnly] if true, trace in file and not in Debug flow1191 */1192 notifyEvent : function (ev, fileOnly) {1193 var obj = {1194 ts: ctx.getTime(),1195 ctx: 'Event',1196 event: ev.name,1197 appliName: ev.appliName,1198 appliInst: ev.appliInst1199 };1200 if (ev.pageName) {1201 obj.pageName = ev.pageName;1202 obj.pageInst = ev.pageInst;1203 }1204 if (ev.itemName) {1205 obj.itemName = ev.itemName;1206 obj.itemInst = ev.itemInst;1207 if (ev.itemIndex) { obj.itemIndex = ev.itemIndex; }1208 }1209 if (ev.reqAppliName) {1210 obj.reqAppliName = ev.reqAppliName;1211 obj.reqAppliInst = ev.reqAppliInst;1212 }1213 if (ev.reqEventName) { obj.reqEventName = ev.reqEventName; }1214 if (ev.reqItemName) { obj.reqItemName = ev.reqItemName; }1215 if (ev.data) { obj.data = ev.data; }1216 // add screenshot capture1217 if (ctx.options.trace.screenshotTraces && ((ev.name == e.event.page.LOAD) || (ev.name == e.event.page.ACTIVATE))) {1218 var traceFolder = ((ctx.options.trace.autoRecordingStarted || ctx.options.trace.recording) ? ctx.options.traceFolderRecording : ctx.options.traceFolder)1219 if (ev.page && ev.page.hwnd) {1220 var file = ctx.getTimestamp(null, true) + '.png';1221 ctx.noNotify = true;1222 ctx.screenshot( {1223 File: ctx.options.path.log + '\\' + traceFolder + "\\" + file,1224 HWND: ev.page.hwnd1225 } );1226 obj.screenshot = {1227 file: file,1228 folder: traceFolder,1229 hwnd: ev.page.hwnd1230 };1231 }1232 }1233 ctx.notifyDebug(obj, false, fileOnly);1234 },1235 /**1236 * Function used to trace informations.1237 * @description1238 * __Ex.:__1239 * <code javascript> ctx.notifyInfo( 'desktop', data );</code>1240 * @method notifyInfo1241 * @path ctx.notifyInfo1242 * @param {*} data Data1243 * @param {string} name Label associated with data1244 * @param {string} [filename] Filename in which traces are recorded (if omitted, use the default trace files)1245 */1246 notifyInfo : function (data, name, filename) {1247 ctx.log(data, e.logIconType.Data, name);1248 },1249 /**1250 * @ignore1251 * Sends a 'State' event to Studio Debugger1252 * @method notifyState1253 * @path ctx.notifyState1254 * @param {string} type1255 * @param {string} name1256 * @param {number} id1257 * @param {string} action1258 * @param {*} [data]1259 * @param {string} [parentName]1260 * @param {number} [parentId]1261 * @param {ctx.application} [parentAppli]1262 */1263 notifyState : function (type, name, id, action, data, parentName, parentId, parentAppli) {1264 if (ctx.options.trace.autoRecordingStarted || ctx.options.trace.frameworkNotify || ctx.options.trace.recording) {1265 var obj = {1266 ts: ctx.getTime(),1267 ctx: 'State',1268 type: type,1269 name: name,1270 id: id,1271 action: action1272 };1273 if (parentAppli && parentAppli.name) {1274 obj.appliName = parentAppli.name;1275 if (parentAppli.instance > 0) obj.appliInst = parentAppli.instance;1276 }1277 if (parentName) {1278 obj.parentName = parentName;1279 }1280 if (parentId) {1281 obj.parentId = parentId;1282 }1283 if (data) {1284 obj.data = data;1285 }1286 ctx.notifyDebug(obj);1287 }1288 },1289onEnginePrestart : function () {1290 if ('undefined' !== typeof Host) {1291 ctx.root = Host;1292 }1293 ctx.engineStarted = true;1294 // Browser emulation1295 ctx.emulateBrowser();1296 // Standard paths1297 ctx.options.path.log = ctx.context.get('//WkMng_Info/CurrentDir');1298 ctx.options.path.local = ctx.context.get('//WkMng_Info/CurrentURL');1299 ctx.options.path.bin = ctx.options.path.local;1300 ctx.options.path.resources = ctx.options.path.bin;1301 ctx.options.path.exec = ctx.context.get('//WkMng_Info/ConteXtorDir');1302 ctx.options.path.server = ctx.context.get('//WkMng_Info/ServerURL');1303 /** @deprecated use ctx.options.path.log instead of ctx.options.currentDir1304 * @ignore1305 * @path ctx.options.currentDir */ ctx.options.currentDir = ctx.options.path.log;1306 /** @deprecated use ctx.options.path.bin instead of ctx.options.currentURL1307 * @ignore1308 * @path ctx.options.currentURL */ ctx.options.currentURL = ctx.options.path.bin;1309 /** @deprecated use ctx.options.path.exec instead of ctx.options.execDir1310 * @ignore1311 * @path ctx.options.execDir */ ctx.options.execDir = ctx.options.path.exec;1312 /** @deprecated use ctx.options.path.resources instead of ctx.options.resourceURL1313 * @ignore1314 * @path ctx.options.resourceURL */ ctx.options.resourceURL = ctx.options.path.resources;1315 /** @deprecated use ctx.options.path.server instead of ctx.options.serverURL1316 * @ignore1317 * @path ctx.options.serverURL */ ctx.options.serverURL = ctx.options.path.server;1318 // machine and user infos1319 ctx.options.computerName = ctx.context.get('//WkMng_Info/ComputerName');1320 ctx.options.userName = ctx.context.get('//WkMng_Info/UserCode');1321 ctx.options.fullUserName = ctx.context.get('//WkMng_Info/FullUserCode');1322 ctx.options.canonicalName = ctx.context.get('//WkMng_Info/CanonicalName');1323 ctx.options.displayName = ctx.context.get("//GLOBAL/WkMng_Info/DisplayName");1324 ctx.options.fullyQualifiedDN = ctx.context.get("//GLOBAL/WkMng_Info/FullyQualifiedDN");1325 // product version (get version from WkMng component)1326 ctx.updateProductVersion();1327 // no redondancy with variables in Context: PrjVersion, PrjName, ...1328 ctx.options.projectVersion = ctx.context.get('//GLOBAL/PrjVersion');1329 ctx.options.projectClient = ctx.context.get('//GLOBAL/PrjClient');1330 ctx.options.projectName = ctx.context.get('//GLOBAL/PrjName');1331 ctx.options.projectDate = ctx.context.get('//GLOBAL/PrjDate');1332 ctx.options.projectLabel = ctx.context.get('//GLOBAL/PrjLabel');1333 ctx.options.projectComment = ctx.context.get('//GLOBAL/PrjComment');1334 try {1335 ctx.options.projectUid = ctx.context.getNode('//PROCESS[@Name="GLOBAL"]').getAttribute('CtxtId');1336 } catch (ex) { }1337 1338 ctx.options.frameworkVersion = ctx.version(); // SDK version1339 ctx.options.JScriptVersion = ctx.getEngineVersion(); // JS Engine version1340 // *** Traces levels ***1341 var traceLevel = ctx.context.get('//WkMng_Param/WkMng_TraceLevel');1342 // *** WkMng trace levels (not modifiable, just for display) ***1343 ctx.options.trace.errors = ((traceLevel & 1) ? true : false);1344 ctx.options.trace.events = ((traceLevel & 2) ? true : false);1345 ctx.options.trace.actions = ((traceLevel & 4) ? true : false);1346 ctx.options.trace.actionsFull = ((traceLevel & 8) ? true : false);1347 ctx.options.trace.context = ((traceLevel & 16) ? true : false);1348 ctx.options.trace.extendPilots = ((traceLevel & 32) ? true : false);1349 ctx.options.trace.objects = ((traceLevel & 64) ? true : false);1350 ctx.options.trace.windowsEvents = ((traceLevel & 128) ? true : false);1351 ctx.options.trace.messageBoxes = ((traceLevel & 256) ? true : false);1352 ctx.options.trace.debuggerV2 = ((traceLevel & 512) ? true : false);1353 ctx.options.trace.advanced = ((traceLevel & 1024) ? true : false);1354 // *** ctx framework trace levels ***1355 // Studio debug channel1356 ctx.options.trace.frameworkNotify = ((traceLevel & 2048) ? true : false);1357 // trace recording1358 ctx.options.trace.recording = ctx.options.trace.frameworkTraces = ((traceLevel & 4096) ? true : false);1359 ctx.options.trace.screenshotTraces = ((traceLevel & 8192) ? true : false);1360 // read options from the command line1361 _updateOptions();1362 // read options from the options file1363 //_updateOptionFile();1364 if (ctx.options.trace["frameworkTraces"])1365 ctx.options.trace.recording = true; // for compatibility1366 // test menu display1367 ctx.options.isDebug = (ctx.options.trace.debuggerV2 || ctx.options.trace.frameworkNotify);1368 // for compatibility, save data in GLOBAL.data1369 /** @deprecated use ctx.options.path.log instead of GLOBAL.data.currentDir1370 * @ignore1371 * @path GLOBAL.data.currentDir */ GLOBAL.data.currentDir = ctx.options.path.log;1372 /** @deprecated use ctx.options.path.bin instead of GLOBAL.data.currentURL1373 * @ignore1374 * @path GLOBAL.data.currentURL */ GLOBAL.data.currentURL = ctx.options.path.bin;1375 /** @deprecated use ctx.options.path.exec instead of GLOBAL.data.execDir1376 * @ignore1377 * @path GLOBAL.data.execDir */ GLOBAL.data.execDir = ctx.options.path.exec;1378 /** @deprecated use GLOBAL.data.path.resources instead of GLOBAL.data.execDir1379 * @ignore1380 * @path GLOBAL.data.resourceURL */ GLOBAL.data.resourceURL = ctx.options.path.resources;1381 /** @deprecated use ctx.options.path.server instead of GLOBAL.data.serverURL1382 * @ignore1383 * @path GLOBAL.data.serverURL */ GLOBAL.data.serverURL = ctx.options.path.server;1384 ctx.noNotify = true;1385 //ctx.wait(function(ev) {1386 ctx.switchOrShutdown(true, false);1387 //}, 100);1388 return false;1389},1390/** callback called at engine startup : initializes some dynamic variables1391* @method onEngineStart1392* @path ctx.onEngineStart1393* @return {boolean}1394* @ignore1395*/1396onEngineStart : function () {1397 ctx.eventTriggered = true;1398 // check libraries1399 if (ctx.popup === undefined) { ctx.log('ctx.popup library should be included', e.logIconType.Error) ; }1400 if (ctx.fso === undefined) { ctx.log('ctx.fso library should be included', e.logIconType.Error) ; }1401 if (ctx.wmi === undefined) { ctx.log('ctx.wmi library should be included', e.logIconType.Error) ; }1402 if (ctx.wscript === undefined) { ctx.log('ctx.wscript library should be included', e.logIconType.Error) ; }1403 if (ctx.diagnostic === undefined) { ctx.log('ctx.diagnostic library should be included', e.logIconType.Error) ; }1404 var args;1405 while ((args = ctx.pendingEvents.shift()) != undefined) {1406 ctx.onEvent.apply(ctx, args);1407 }1408 ctx.lockNoNotify = true;1409 // *** Licence informations ***1410 //ctx.options.licence = _readLicence("Interactive");1411 //ctx.options.studioLicence = _readLicence("Studio");1412// clear old trace folders1413 ctx.clearTraceFolder();1414 // create a new trace folder1415 ctx.reinitTraceFolder(false, true);1416 if (ctx.options.trace.recording && ctx.diagnostic) {1417 ctx.diagnostic.enableRecording(true, false, true);1418 }1419 // create local job folder1420 var jobFolder = ctx.options.path.log + "\\jobs";1421 if (!ctx.fso.folder.exist(jobFolder)) {1422 ctx.fso.folder.create(jobFolder);1423 }1424 setInterval(function() {1425 // check every tem minutes if day changed : if true, reinitialize trace folder1426 var today = ctx.getTimestamp(null, true).substring(0, 10);1427 var currentDay = ctx.options.traceTimestamp.substring(0, 10);1428 if (today != currentDay) {1429 ctx.reinitTraceFolder(false, true);1430 }1431 // Collect garbage1432 CollectGarbage();1433 }, 600000);1434 // By default using a timeout of 5 minutes. If we have a breakpoint, the timeout is not set1435 ctx.setExecutionTimeout();1436 1437 ctx.lockNoNotify = false;1438 return true;1439},1440 /** callback called at engine stop1441 * @method onEngineStop1442 * @path ctx.onEngineStop1443 * @ignore1444 */1445 onEngineStop : function () {1446 ctx.setExecutionTimeout(0);1447 ctx.engineStarted = false;1448 ctx.eventTriggered = false;1449 CollectGarbage();1450 },1451 /** Sets or resets execution timeout \1452 * @method setExecutionTimeout1453 * @path ctx.setExecutionTimeout1454 * @param {number} [timeout] new timeout in ms. It omitted, 'ctx.options.executionTimeout' is used. if < 10000 ms, timeout is reset1455 */1456 setExecutionTimeout : function (timeout) {1457 if (timeout === undefined) {1458 timeout = ctx.options.executionTimeout;1459 } else if (timeout < 10000) {1460 // reset deadlock protection1461 timeout = 0xffffffff;1462 }1463 if (ctxHost && ('undefined' !== typeof ctxHost.SetTimeoutValue)) {1464 ctxHost.SetTimeoutValue( timeout );1465 1466 var vbscriptCode = 'ctxHost.SetTimeoutValue(' + timeout + ')';1467 ctx.execVBS(vbscriptCode);1468 }1469 },1470 /**1471 * creates / reinits trace folder and triggers archiving1472 * @description1473 * __Ex.:__1474<code javascript>1475ctx.reinitTraceFolder(false, true);1476</code>1477 * @method reinitTraceFolder1478 * @ignore internal use1479 * @path ctx.reinitTraceFolder1480 * @param {boolean} [copyArchive] copy or send archive1481 * @param {boolean} [createNew] create a new trace folder1482 * @param {boolean} [recording] create a folder for auto or manual recording1483 * @param {boolean} [deleteOld] delete folder for auto recording1484 * @param {string} [prefix] optional prefix1485 * @return {string} new trace folder path1486 */1487 reinitTraceFolder : function (copyArchive, createNew, recording, deleteOld, prefix) {1488 try {1489 var traceFolder = (recording ? ctx.options.traceFolderRecording : ctx.options.traceFolder)1490 var oldTraceFolder = traceFolder; // reset trace folder1491 prefix = prefix || (recording ? e.trace.type.Record : e.trace.type.Log);1492 if (createNew) {1493 // create a new trace folder1494 ctx._fso = ctx._fso || new ActiveXObject("Scripting.FileSystemObject");1495 var ts = ctx.getTimestamp(null, true);1496 if (!recording) { ctx.options.traceTimestamp = ts; }1497 traceFolder = prefix + '.' + ctx.options.computerName + '.' + ctx.options.userName + '.' + ts;1498 if(recording)1499 ctx.options.traceFolderRecording = traceFolder;1500 else1501 ctx.options.traceFolder = traceFolder;1502 if (!ctx._fso.FolderExists(ctx.options.path.log + '\\' + traceFolder)) {1503 ctx._fso.CreateFolder(ctx.options.path.log + '\\' + traceFolder);1504 }1505 // notify Studio with the folder name for LOGS1506 if (!recording) {1507 GLOBAL.notify(GLOBAL.events.evUpdateLogFolder, ctx.options.path.log + '\\' + traceFolder);1508 }1509 if (typeof ctx.onStartTraceCallback === 'function') {1510 ctx.onStartTraceCallback(ctx.options.path.log + '\\' + traceFolder);1511 }1512 } else {1513 if(recording)1514 ctx.options.traceFolderRecording = '';1515 else1516 ctx.options.traceFolder = '';1517 }1518 // archive previous folder1519 if (oldTraceFolder) {1520 if (deleteOld) {1521 if (ctx._fso.FolderExists(ctx.options.path.log + '\\' + oldTraceFolder)) {1522 ctx._fso.DeleteFolder(ctx.options.path.log + '\\' + oldTraceFolder);1523 }1524 } else {1525 if (typeof ctx.onStopTraceCallback === 'function') {1526 ctx.onStopTraceCallback(ctx.options.path.log + '\\' + oldTraceFolder, copyArchive);1527 }1528 }1529 }1530 } catch (ex) {}1531 return traceFolder;1532 },1533 /** Calculates a color as a RGB value1534 * @description1535 * __Ex.:__1536<code javascript>1537var color = ctx.rgb(0xff, 0, 0); // 'red color'1538</code>1539 * @method rgb1540 * @path ctx.rgb1541 * @param {number} r red color (0 to 0xff)1542 * @param {number} g green color (0 to 0xff)1543 * @param {number} b blue color (0 to 0xff)1544 * @return {number} RGB value1545 */1546 rgb : function (r, g, b) {1547 return r + g * 0x100 + b * 0x10000;1548 },1549 /** 1550 * @ignore1551 * Function called to update product versions.1552 * @method updateProductVersion1553 * @path ctx.updateProductVersion1554 */1555 updateProductVersion : function() {1556 ctx.options.productVersions = {};1557 var node = ctx.context.getCtx('//GLOBAL/WkMng_Info/Components');1558 if (node && node.childNodes) {1559 for (var i = 0; i < node.childNodes.length; i ++) {1560 var component = node.childNodes[i].tagName;1561 var version = node.childNodes[i].childNodes[1].text || node.childNodes[i].childNodes[0].text; // product version, or file version1562 ctx.options.productVersions[component] = version;1563 }1564 }1565 ctx.options.productVersion = ctx.options.productVersions['XsWrkMng2'];1566 },1567 /**1568 * Generates a GUID string.1569 * @description1570 * __Ex.:__1571<code javascript>1572var uuid = ctx.uuid( ); // uuid = af8a8416-6e18-a307-bd9c-f2c947bbb3aa1573</code>1574 * Adapted from Slavik Meltser (slavik@meltser.info). See [[http://slavik.meltser.info/?p=142]]1575 * @method uuid1576 * @path ctx.uuid1577 * @returns {string} The generated GUID.1578 */1579 uuid : function () {1580 /**1581 * Generates a GUID sub-string.1582 * @method _p81583 * @ignore1584 * @param {boolean} [s] true: -xxxx-xxxx, false: xxxxxxxx1585 * @returns {string} sub-string1586 */1587 function _p8(s) {1588 var p = (Math.random().toString(16)+"000000000").substr(2,8);1589 return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ;1590 }1591 return _p8() + _p8(true) + _p8(true) + _p8();1592 },1593 /**1594 * Returns the ctx framework version.1595 * @description1596 * __Ex.:__1597<code javascript>1598var vers = ctx.version(); // '3.0.1'1599</code>1600 * @method version1601 * @path ctx.version1602 * @return {string} Framework global version1603 */1604 version : function () {1605 ctx.notifyAction('ctx.version', _coreVersion);1606 return _coreVersion;1607 },1608 restartOnProject : function(packageUid, packageVersionUid) {1609 if (ctx.compareVersion('1.0.5.0') < 0) {1610 // Agent < 1.0.5 1611 // Write packageVersionUid in registry1612 // Restart agent1613 ctx.registry.set('Software\\SAP\\Intelligent RPA\\Desktop Agent\\CurrentProject', packageVersionUid, e.registry.root.CurrentUser);1614 ctx.shutdownAgent(true, true);1615 }1616 else {1617 // Agent >= 1.0.51618 // New restart method : call workmanager1619 ctx.wkMng.SwitchProject(packageUid, packageVersionUid);1620 }1621 },1622 1623 /**1624 * Handles Agent shutdown (with or without restart).1625 * @method shutdownAgent1626 * @path ctx.shutdownAgent1627 * @param {boolean} [restart] if true, shutdwon then restart1628 * @param {boolean} [waitIdle] if true, waits until there is no running scenario1629 * @param {string} [message] popup message (if omitted, no popup displayed)1630 * @param {string} [title] popup title1631 */1632 shutdownAgent : function(restart, waitIdle, message, title) {1633 var _shutdownAgent = function(restart, waitIdle) {1634 if (ctx.isStudioUsed()) {1635 ctx.restartAgent = false; // no restart in Studio mode1636 } else {1637 ctx.restartAgent = restart;1638 }1639 if (waitIdle && !ctx.isEmpty(ctx.runningScenarios.map)) {1640 ctx.shutdownOnIdle = true;1641 if (typeof ctx.galaxyAPI !== 'undefined') {1642 ctx.galaxyAPI.setBusy(true, function(code, label) { });1643 }1644 } else {1645 ctx.registry.set(_runningKey, '');1646 if (ctx.restartAgent) {1647 ctx.registry.set(_restartingKey, '1');1648 }1649 GLOBAL.notify(GLOBAL.events.PRESTOPCTX);1650 }1651 }1652 if (!(ctx.popups['pCtxtShutdown'] && (ctx.popups['pCtxtShutdown'] instanceof ctx.popupClass))) {1653 // standard Shutdown/Restart/Update popup declaration1654 ctx.popup({ pCtxtShutdown: {1655 template: e.popup.template.YesNo,1656 title: GLOBAL.labels.stopPopup.title,1657 CX: 500,1658 CY: 200,1659 message: '<br/><b>' + GLOBAL.labels.stopPopup.label + '</b><br/>', 1660 icon: e.popup.icon64.hello1661 }});1662 }1663 if (message && ctx.options.shutdownConfirmation && (ctx.popups['pCtxtShutdown'] instanceof ctx.popupClass)) {1664 ctx.popups["pCtxtShutdown"].open({1665 title: title,1666 message: '<br/><b>' + message + '</b><br/>'1667 }).waitResult(function(res) {1668 if (res == e.item.id.Yes) {1669 _shutdownAgent(restart, waitIdle);1670 }1671 });1672 } else {1673 _shutdownAgent(restart, waitIdle);1674 }1675 },1676 /**1677 * Handles Agent shutdown (with or without restart).1678 * @method shutdownContextor1679 * @deprecated use ctx.shutdownAgent instead1680 * @ignore1681 * @path ctx.shutdownContextor1682 * @param {boolean} [restart] if true, shutdwon then restart1683 * @param {boolean} [waitIdle] if true, waits until there is no running scenario1684 * @param {string} [message] popup message (if omitted, no popup displayed)1685 * @param {string} [title] popup title1686 */1687 shutdownContextor : function(restart, waitIdle, message, title) {1688 return ctx.shutdownAgent(restart, waitIdle, message, title);1689 },1690 /**1691 * Handles Contextor shutdown (with or without restart)1692 * @method switchOrShutdown1693 * @path ctx.switchOrShutdown1694 * @param {boolean} [onStart] if true, function is called at startup1695 * @param {boolean} [onUpdate] if true, function is called for update of current project(s)1696 * @return {boolean} false if no change required1697 */1698 switchOrShutdown : function(onStart, onUpdate) {1699 ctx.lockNoNotify = true;1700 var autoStart = (ctx.registry.get(_autoStartKey) == '1' ? false : true);1701 var confirmStart = (ctx.registry.get(_confirmStartKey) == '1' ? true : false);1702 var restarting = (ctx.registry.get(_restartingKey) == '1' ? true : false);1703 var running = (ctx.registry.get(_runningKey) == '1' ? true : false);1704 var serviceStart = (ctx.registry.get(_serviceStartKey) == '1' ? true : false);1705 ctx.registry.set(_runningKey, '1');1706 ctx.registry.set(_restartingKey, '');1707 ctx.registry.set(_serviceStartKey, '');1708 var projectList = ctx.availableProjects;1709 ctx.lockNoNotify = false;1710 // called at statup1711 if (onStart) {1712 if (!(autoStart || serviceStart || restarting || ctx.isStudioUsed())) {1713 // auto start disabled, launch at session logon --> shutdown1714 ctx.shutdownAgent(false, false);1715 return true;1716 }1717 //if ((!confirmStart) || restarting || running || ctx.options.unattended) {1718 if ((!confirmStart) || restarting || running || ctx.options.unattended || ctx.isStudioUsed()) {1719 // direct launch (no choice popup)1720 ctx.onEngineStart();1721 return false;1722 }1723 } else {1724 if (onUpdate && (!ctx.isStudioUsed()) && (ctx.options.unattended || (!confirmStart))) {1725 // restart on first project1726 //var project = projectList[0];1727 // GDLV : ignoring the project to start on1728 1729// if ((project) &&1730// ((project.name && ctx.options.projectName && (project.name != ctx.options.projectName)) ||1731// (project.date && ctx.options.projectDate && (project.date != ctx.options.projectDate)) ||1732// (project.version && ctx.options.projectVersion && (project.version != ctx.options.projectVersion)))) {1733// var cmdLineName = project.schedule;1734// var cmdLine = project.args;1735// if (cmdLine && cmdLineName) {1736// ctx.log("Switching to project : " + cmdLineName);1737// ctx.registry.set(_cmdLineKey, cmdLine);1738// ctx.registry.set(_cmdLineNameKey, cmdLineName);1739// }1740 ctx.shutdownAgent(true, true);1741 return true;1742// }1743// return false;1744 }1745 }1746 var current = 0;1747 var options = {};1748 if (projectList.length > 0) {1749 ctx.each(projectList, function(id, project) {1750 var label = project['configurationName'] + ' - ' + project.name + ' - '+ project.version;1751 options[id] = label;1752 if (project.current) {1753 current = id;1754 }1755 });1756 } else {1757 options[0] = ctx.options.projectLabel || ctx.options.projectName + ' ' + ctx.options.projectVersion;1758 }1759 var form = {1760 group : []1761 }1762 if (projectList.length > 0) {1763 form.group.push({1764 width : 12,1765 label : {1766 type : e.item.type.label,1767 value : " "1768 }1769 });1770 form.group.push({1771 width : 12,1772 project : {1773 type: e.item.type.select,1774 options: options,1775 value: current1776 }1777 });1778 }1779 var buttons;1780 var escape = '';1781 var disabled = ctx.isStudioUsed() && (!ctx.options.galaxyAPI.enableStudioRestart);1782 if (onStart) {1783 buttons = {1784 start: {1785 label: GLOBAL.labels.buttons.start,1786 icon: e.item.icon.refresh,1787 disabled: disabled,1788 submit : true,1789 type: e.item.style.Orange1790 },1791 shutdown: {1792 label: GLOBAL.labels.buttons.stop,1793 icon: e.item.icon.stop,1794 submit : true,1795 type: e.item.style.Red1796 }1797 }1798 escape = 'shutdown';1799 } else {1800 buttons = {1801 restart: {1802 label: GLOBAL.labels.buttons.restart,1803 icon: e.item.icon.refresh,1804 disabled: disabled,1805 submit : true,1806 type: e.item.style.Orange1807 },1808 shutdown: {1809 label: GLOBAL.labels.buttons.stop,1810 icon: e.item.icon.stop,1811 submit : true,1812 type: e.item.style.Red1813 },1814 close: {1815 label: GLOBAL.labels.buttons.close,1816 icon: e.item.icon.ok,1817 submit : true,1818 type: e.item.style.Blue1819 }1820 }1821 escape = 'close';1822 }1823 if (onUpdate && ctx.isStudioUsed()) {1824 return false;1825 }1826 ctx.popup('pCtxtSwitchShutdown').open({1827 template: e.popup.template.NoButton,1828 canClose: false,1829 //IEHost: true,1830 size : "small",1831 X: e.popup.position.Center,1832 Y: e.popup.position.Center,1833 CX: 600,1834 CY: 300,1835 title: GLOBAL.labels.popup.defaultTitle,1836 form: form,1837 escape: escape,1838 buttons: buttons1839 }).waitResult(function(res) {1840 // save current values1841 //ctx.registry.set(_autoStartKey, (res.autoStart ? "" : "1"));1842 //ctx.registry.set(_confirmStartKey, (res.confirmStart ? "1" : ""));1843 var project = projectList[res.project];1844 if(project)1845 ctx.registry.set('Software\\SAP\\Intelligent RPA\\Desktop Agent\\CurrentProject', project.packageVersionUid, e.registry.root.CurrentUser, e.registry.type.String);1846 if (res.button == 'restart') {1847 if ((res.project != current) && project) {1848 //var cmdLineName = project.schedule;1849 //var cmdLine = project.args;1850 //if (cmdLine && cmdLineName) {1851 // ctx.log("Switching to project : " + cmdLineName);1852 // ctx.registry.set(_cmdLineKey, cmdLine);1853 // ctx.registry.set(_cmdLineNameKey, cmdLineName);1854 //}1855 } else if (onStart) {1856 ctx.onEngineStart();1857 }1858 ctx.shutdownAgent(true, true);1859 } else if (res.button == 'shutdown') {1860 ctx.shutdownAgent(false, true);1861 }1862 });1863 return false;1864 }1865 };1866 return self;1867})();1868/**1869 * Generic iterator function, used to iterate inside objects or arrays1870 * @description1871 * __Ex.:__1872<code javascript>1873 ctx.each( [ 'val1', 'val2', 'val3' ], function( value, index ) {1874 // called successively with [index=0, value='val1'], [index=1, value='val2'], [index=2, value='val3']1875 } );1876 ctx.each( { name:'Ford', firstname:'John' }, function( value, index ) {1877 // called successively with [index='name', value='Ford'], [index='firstname', value='John']1878 } );1879</code>1880* @method each1881* @path ctx.each1882* @param {*} obj Object to be enumerated1883* @param {function(string,*)} func Function to be called for each enumeration. First argument is the key, second argument is the value.1884*/1885ctx.each = function (obj, func) {1886 var itemCount = 0;1887 var en;1888 var res;1889 var hasEnumerator = (('undefined' === typeof(Enumerator)) ? false : true);1890 if (obj) {1891 if (Object.prototype.toString.call(obj) === '[object Array]') {1892 // It's an array, loop through it1893 for (var i = 0; i < obj.length; i++) {1894 res = func(String(i), obj[i]);1895 if (res === false) break;1896 }1897 } else if (hasEnumerator && (obj instanceof Enumerator)) {1898 // It's an Enumerator1899 en = obj;1900 } else if (obj instanceof Object) {1901 // It's a JS object1902 for (var x in obj) {1903 if (typeof obj[x] !== 'function') {1904 res = func(x, obj[x]);1905 if (res === false) break;1906 }1907 }1908 } else if (hasEnumerator) {1909 // It's not a JS object, probably ActiveX or native object: make it an Enumerator1910 en = new Enumerator(obj);1911 }1912 if (en) {1913 en.moveFirst();1914 while (en.atEnd() === false) {1915 res = func(String(itemCount), en.item());1916 if (res === false) break;1917 en.moveNext();1918 itemCount++;1919 }1920 }1921 }1922};1923 /**1924 * @ignore1925 * @typedef {{1926 * valid: boolean,1927 * index: (number|undefined),1928 * count: number,1929 * key: (string|undefined),1930 * value: (*|undefined)1931 * }}1932 */1933 ctx.iteratorParams = {1934 valid: false,1935 index: -1,1936 count: 0,1937 key: '',1938 value: undefined1939 };1940/**1941 * @ignore1942 * Class used to iterate inside objects or arrays1943 * @deprecated use ctx.array instead of ctx.iterator1944 * @class ctx.iterator1945 * @path ctx.iterator1946 * @param {*} [obj] object to be enumerated1947 */1948ctx.iterator = function (obj) {1949 /** @type {number} */ var _index = -1;1950 /** @type {number} */ var _count = 0;1951 /** @type {Array<string>} */ var _keys = [];1952 /** @type {Object} */ var _data = {};1953 var self = {1954 /**1955 * @ignore1956 * Returns the count of elements1957 * @method count1958 * @path ctx.iterator.count1959 * @return {number}1960 * @description1961 * __Ex.:__1962<code javascript>1963var jobs = ctx.iterator([1964 { search: 'Interstellar' },1965 { search: 'Pulp Fiction' },1966 ...1967]);1968var count = jobs.count();1969</code>1970 */1971 count: function() {1972 return _count;1973 },1974 /**1975 * @ignore1976 * Returns the current element1977 * @method current1978 * @path ctx.iterator.current1979 * @param {number} [index] iteration index. If omitted, get current index. If mentioned, set the current index and returns iteration1980 * @return {ctx.iteratorParams}1981 * @description1982 * __Ex.:__1983<code javascript>1984var jobs = ctx.iterator([1985 { search: 'Interstellar' },1986 { search: 'Pulp Fiction' },1987 ...1988]);1989var it = jobs.current();1990// it = {1991// valid: true,1992// index: 0,1993// count: 5,1994// key: 0,1995// value: { search: 'Interstellar' }1996// }1997</code>1998 */1999 current: function(index) {2000 if (index !== undefined) {2001 if (index >= _count) {2002 _index = _count;2003 } else if (index < 0) {2004 _index = -1;2005 } else {2006 _index = index;2007 }2008 }2009 if ((_index >= _count) || (_index < 0))2010 return { valid: false, index: _index, count: _count, key: undefined, value: undefined}2011 else2012 return { valid: true, index: _index, count: _count, key: _keys[_index], value: _data[_keys[_index]]}2013 },2014 /**2015 * @ignore2016 * Returns if the current element is valid2017 * @method currentValid2018 * @path ctx.iterator.currentValid2019 * @return {*}2020 * @description2021 * __Ex.:__2022<code javascript>2023var jobs = ctx.iterator(...);2024if (jobs.currentValid()) { ... }2025</code>2026 */2027 currentValid: function() {2028 return ( ((_index < _count) && (_index >= 0)) ? true : false );2029 },2030 /**2031 * @ignore2032 * Returns the value of the current element2033 * @method currentValue2034 * @path ctx.iterator.currentValue2035 * @return {*}2036 * @description2037 * __Ex.:__2038<code javascript>2039var jobs = ctx.iterator(...);2040var val = jobs.currentValid();2041</code>2042 */2043 currentValue: function(index) {2044 return ( ((_index < _count) && (_index >= 0)) ? _data[_keys[_index]] : undefined );2045 },2046 /**2047 * @ignore2048 * Returns the value of a random element2049 * @method getRandomValue2050 * @path ctx.iterator.getRandomValue2051 * @return {*}2052 * @description2053 * __Ex.:__2054<code javascript>2055var jobs = ctx.iterator(...);2056var val = jobs.getRandomValue();2057</code>2058 */2059 getRandomValue: function() {2060 var index = Math.floor ( Math.random () * _count );2061 var it = self.current(index);2062 //ctx.log(index + " / " + _count, e.logIconType.Info, it);2063 return it.value;2064 },2065 /**2066 * @ignore2067 * Sets the iterator index to the beginning2068 * @method begin2069 * @path ctx.iterator.begin2070 * @return {*}2071 * @description2072 * __Ex.:__2073<code javascript>2074var jobs = ctx.iterator(...);2075jobs.begin();2076</code>2077 */2078 begin: function() {2079 return self.current(-1);2080 },2081 /**2082 * @ignore2083 * Sets the iterator index to the end2084 * @method end2085 * @path ctx.iterator.end2086 * @return {*}2087 * @description2088 * __Ex.:__2089<code javascript>2090var jobs = ctx.iterator(...);2091jobs.end();2092</code>2093 */2094 end: function() {2095 return self.current(_count);2096 },2097 /**2098 * @ignore2099 * Sets the iterator index to the next element2100 * @method next2101 * @path ctx.iterator.next2102 * @return {ctx.iteratorParams}2103 * @description2104 * __Ex.:__2105<code javascript>2106var jobs = ctx.iterator(...);2107jobs.next();2108</code>2109 */2110 next: function() {2111 if (_index < _count) _index ++;2112 return self.current();2113 },2114 /**2115 * @ignore2116 * Removes and returns the last element in the iterator2117 * @method pop2118 * @path ctx.iterator.pop2119 * @return {Object} deleted object2120 * @description2121 * __Ex.:__2122<code javascript>2123var jobs = ctx.iterator(...);2124var it = jobs.pop();2125</code>2126 */2127 pop: function() {2128 var obj = null;2129 if (_count > 0) {2130 _count --;2131 obj = _data[_count];2132 delete _data[_count];2133 _keys.pop();2134 if (_index > _count) _index = _count;2135 }2136 return obj;2137 },2138 /**2139 * @ignore2140 * Sets the iterator index to the previous element2141 * @method previous2142 * @path ctx.iterator.previous2143 * @return {ctx.iteratorParams}2144 * @description2145 * __Ex.:__2146<code javascript>2147var jobs = ctx.iterator(...);2148var it = jobs.previous();2149</code>2150 */2151 previous: function() {2152 if (_index >= 0) _index --;2153 return self.current();2154 },2155 /**2156 * @ignore2157 * Adds an element to the iterator2158 * @method push2159 * @path ctx.iterator.push2160 * @param {*} [value]2161 * @return {number} new index2162 * @description2163 * __Ex.:__2164<code javascript>2165var jobs = ctx.iterator(...);2166var val = 'my value'2167jobs.push(val);2168</code>2169 */2170 push: function(value) {2171 if (value === undefined) value = null;2172 _data[_count] = value;2173 _keys.push(String(_count));2174 _count ++;2175 return _count;2176 },2177 /**2178 * @ignore2179 * Sets the iterator with a new oject (or to an empty iterator if object is omitted)2180 * @method set2181 * @path ctx.iterator.set2182 * @param {*} [obj] object to reinitialize the iterator2183 * @return {boolean}2184 * @description2185 * __Ex.:__2186<code javascript>2187var jobs = ctx.iterator(...);2188jobs.set([2189 'value 1',2190 'value 2',2191 'value 3'2192]);2193</code>2194 */2195 set: function(obj) {2196 var res = false;2197 _data = {};2198 _index = -1;2199 _count = 0;2200 _keys = [];2201 if (obj && ('object' === typeof obj)) {2202 ctx.each(obj, function(id, value) {2203 _data[id] = value;2204 _keys.push(id);2205 });2206 _count = _keys.length;2207 }2208 res = (_count > 0);2209 return res;2210 },2211 /**2212 * @ignore2213 * Resizes the iterator with a new size2214 * @method resize2215 * @path ctx.iterator.resize2216 * @param {number} size2217 * @param {*} [defval] default value2218 * @return {boolean}2219 * @description2220 * __Ex.:__2221<code javascript>2222var jobs = ctx.iterator(...);2223jobs.resize(10);2224</code>2225 */2226 resize: function (size, defval) {2227 var delta = _count - size;2228 while (delta > 0) { self.pop(); delta--; }2229 while (delta < 0) { self.push(defval); delta++; }2230 return true;2231 }2232 }2233 self.set(obj);2234 return self;2235};2236/**2237* Merges a value or set of values in the data object2238* @description2239* __Ex.:__2240* <code javascript>2241* GLOBAL.data.set( { name:'Ford', firstname:'John' } ); // adds 'name' and 'firstname' attributes in GLOBAL.data2242* </code>2243* @method set2244* @path ctx.set2245* @param {*} data object or string containing data to be set2246* @param {Object} target object (or application) to be modified2247* @param {string} [path] target path or object2248* @param {e.data.format} [format] data format type (see [[:lib:common:ctx.enum#enumeration_edataformat|e.data.format]])2249* @param {e.data.initType} [initType] data initialisation type (see [[:lib:common:ctx.enum#enumeration_edatainitType|e.data.initType]])2250* @param {e.data.pathType} [pathType] data path type (default is 'e.data.pathType.XPath')\\ (see [[:lib:common:ctx.enum#enumeration_edatapathType|e.data.pathType]])2251* @param {boolean} [locked] if 'true', no new attribute can be added2252* @param {number} [level] max recursive level2253* @param {boolean} [isShort] if 'true', serialize a sort description2254* @return {*} destination object after modification2255*/2256ctx.set = function (data, target, path, format, initType, pathType, locked, level, isShort) {2257 /**2258 * Merges an object in a given object2259 * __Note:__ this function is inspired from **jQuery.extend()** ([[https://api.jquery.com/jquery.extend/]])2260 * @ignore2261 * @method _set2262 * @param {*} data object or string containing data to be set2263 * @param {Object} target object (or application) to be modified2264 * @param {number} [level] max recursive level2265 * @param {boolean} [locked] if 'true', no new attribute can be added2266 * @param {boolean} [isShort] if 'true', serialize a sort description2267 * @return {Object} destination object after modification2268 */2269 var _set = function (data, target, level, locked, isShort) {2270 var copyIsArray;2271 if (level === undefined) level = 10;2272 if (data) {2273 var properties;2274 if (isShort && ('function' === typeof data.ctxShort)) {2275 properties = data.ctxShort();2276 }2277 level--;2278 if (properties) {2279 ctx.each(properties, function(index, property) {2280 if (!(locked && ('undefined' === typeof target[property])))2281 target[property] = data[property];2282 });2283 } else {2284 var targetArray = Array.isArray(target);2285 ctx.each(data, function(id, value) {2286 // anti loop2287 if ( value === target[id]) {2288 return true;2289 }2290 if (targetArray) {2291 target.push(value);2292 return true;2293 }2294 if (locked && ('undefined' === typeof target[id])) {2295 return true;2296 }2297 if ( value && ((copyIsArray = Array.isArray( value)) || (typeof value === "object"))) {2298 if ((typeof target[id] !== "object" && typeof target[id] !== "function")) {2299 if (copyIsArray) {2300 copyIsArray = false;2301 if (!(target[id] && Array.isArray(target[id])))2302 target[id] = [];2303 } else {2304 if (!(target[id] && (typeof target[id] === "object")))2305 target[id] = {};2306 }2307 }2308 if (level > 1) {2309 _set(value, target[id], level, locked, isShort);2310 }2311 } else {2312 if (value !== undefined) {2313 target[id] = value;2314 }2315 }2316 });2317 }2318 }2319 return target;2320 }2321 var parentAppli = null;2322 var targetObject = null;2323 var res;2324 var sPath = path || '';2325 if (target && target.data) {2326 parentAppli = target;2327 targetObject = target.data;2328 } else {2329 targetObject = target;2330 }2331 if (typeof targetObject !== 'object') {2332 throw new Error(e.error.InvalidArgument, 'ctx.set: target should be an object');2333 }2334 if (sPath) {2335 switch (pathType) {2336 case e.data.pathType.JsonPath :2337 throw new Error(e.error.NotImplemented, 'ctx.set: \'JsonPath\' type is not implemented');2338 break;2339 case e.data.pathType.SQLPath :2340 throw new Error(e.error.NotImplemented, 'ctx.set: \'SQLPath\' type is not implemented');2341 break;2342 case e.data.pathType.XPath :2343 default :2344 if (typeof format == 'undefined') {2345 if (typeof data === 'string')2346 format = e.data.format.text;2347 else if (typeof data === 'object')2348 format = e.data.format.js;2349 }2350 var obj = {}; // data to be inserted2351 /** @type {string} */ var sData = '';2352 if (format == e.data.format.js) {2353 if (typeof data !== 'object') {2354 throw new Error(e.error.InvalidArgument, 'ctx.set: input should be an object');2355 }2356 obj = data;2357 } else {2358 if (typeof data === 'object') {2359 throw new Error(e.error.InvalidArgument, 'ctx.set: input should be a simple type: string, number, ...');2360 }2361 sData = String(data);2362 }2363 if (parentAppli) {2364 if (sPath.startsWith('/'))2365 {2366 // absolute XPath in the global data object2367 targetObject = ctx.data;2368 }2369 }2370 var bCreate = true; // force creation if node does not exist2371 var bRemove = false;2372 switch (initType) {2373 case e.data.initType.DEL:2374 bRemove = true;2375 break;2376 case e.data.initType.ADD:2377 throw new Error(e.error.NotImplemented, 'ctx.set: e.data.initType.ADD type is not implemented');2378 break;2379 case e.data.initType.CREATE:2380 // only create the node if it does not exist2381 if (ctx.exist(targetObject, sPath, pathType))2382 return targetObject;2383 break;2384 case e.data.initType.CRINIT:2385 default:2386 break;2387 }2388 switch (format) {2389 // *** source is a context node ***2390 case e.data.format.ctx:2391 case 'CTX':2392 if (sData) {2393 if (sData.indexOf('/') != 0)2394 {2395 // use a data template2396 if (parentAppli && parentAppli.dataTemplates && parentAppli.dataTemplates[sData]) {2397 obj = parentAppli.dataTemplates[sData];2398 if (!obj)2399 throw new Error(e.error.InvalidArgument, 'ctx.set: unkown data template : \'' + sData + '\'');2400 } else {2401 throw new Error(e.error.InvalidArgument, 'ctx.set: invalid data template : \'' + sData + '\'');2402 }2403 }2404 else2405 {2406 obj = ctx.json.searchXPath(targetObject, sData);2407 }2408 }2409 res = ctx.json.searchXPath(targetObject, sPath, obj, bCreate, bRemove);2410 return res;2411 break;2412 // *** source is an external XML or JSON file ***2413 case e.data.format.xmlURL:2414 case e.data.format.jsonURL:2415 case 'URL':2416 if (sData) {2417 ctx.ajax.call({2418 url: sData,2419 async: false,2420 contentType: (format == e.data.format.jsonURL ? e.ajax.content.json : e.ajax.content.xml ),2421 success: function(res, status, xhr) {2422 try {2423 if (format == e.data.format.jsonURL) {2424 // res contains a string with XML data2425 obj = ctx.json.parse(res);2426 res = ctx.json.searchXPath(targetObject, sPath, obj, bCreate, bRemove);2427 return res;2428 } else {2429 // res contains a string with XML data2430 obj = ctx.xml.xml2object(res);2431 res = ctx.json.searchXPath(targetObject, sPath, obj, bCreate, bRemove);2432 return res;2433 }2434 } catch (ex) {2435 throw new Error(e.error.InvalidArgument, 'ctx.set: invalid data file : \'' + sData + '\'');2436 }2437 },2438 error: function(xhr, status, statusText) {2439 throw new Error(e.error.InvalidArgument, 'ctx.set: file could not be loaded : \'' + sData + '\'');2440 }2441 });2442 }2443 break;2444 // *** source is a JSON string ***2445 case e.data.format.json:2446 if (sData) {2447 try {2448 obj = ctx.json.parse(sData);2449 res = ctx.json.searchXPath(targetObject, sPath, obj, bCreate, bRemove);2450 return res;2451 } catch (ex) {2452 throw new Error(e.error.InvalidArgument, 'ctx.set: input should be a JSON string');2453 }2454 }2455 break;2456 // *** source is an XML string ***2457 case e.data.format.xml:2458 case 'XML':2459 if (sData) {2460 try {2461 obj = ctx.xml.xml2object(sData);2462 res = ctx.json.searchXPath(targetObject, sPath, obj, bCreate, bRemove);2463 return res;2464 } catch (ex) {2465 throw new Error(e.error.InvalidArgument, 'ctx.set: input should be an XML string');2466 }2467 }2468 break;2469 // *** source is a JS object or raw text ***2470 case e.data.format.js:2471 case e.data.format.text:2472 default:2473 obj = data;2474 res = ctx.json.searchXPath(targetObject, sPath, obj, bCreate, bRemove);2475 return res;2476 break;2477 }2478 break;2479 }2480 } else {2481 // *** standard 'set' mode ***2482 if (typeof data === 'object') {2483 if (Array.isArray(data)) {2484 if (!(target && Array.isArray(target))) {2485 target = [];2486 } else if (!(target && (typeof target === 'object'))) {2487 target = {};2488 }2489 }2490 targetObject = _set(data, targetObject, level, locked, isShort);2491 } else {2492 /** @type {*} */var tObj = targetObject;2493 tObj = data;2494 }2495 }2496 return targetObject;2497}2498//ctx.fn = ctx.prototype = {2499// constructor: ctx2500//};2501///**2502// * Module extension function2503// * __Note:__ this function is directly inspired from **jQuery.extend()** ([[https://api.jquery.com/jquery.extend/]])2504// * @ignore2505// * @method extend2506// * @path ctx.extend2507// * @param {...*} args2508// * @return {Object} target2509// */2510//ctx.extend = function (args) {2511////ctx.extend = ctx.fn.extend = function (args) {2512// var options, name, src, copy, copyIsArray, clone,2513// target = arguments[0] || {},2514// i = 1,2515// length = arguments.length,2516// deep = false;2517// // Handle a deep copy situation2518// if (typeof target === "boolean") {2519// deep = target;2520// target = arguments[1] || {};2521// // skip the boolean and the target2522// i = 2;2523// }2524// // Handle case when target is a string or something (possible in deep copy)2525// if (typeof target !== "object" && typeof target !== "function") {2526// target = {};2527// }2528// // extend ctx itself if only one argument is passed2529// if (length === i) {2530// target = this;2531// --i;2532// }2533// for (i = 0; i < length; i++) {2534// // Only deal with non-null/undefined values2535// if ((options = arguments[i]) !== null) {2536// // Extend the base object2537// for (name in options) {2538// src = target[name];2539// copy = options[name];2540// // Prevent never-ending loop2541// if (target === copy) {2542// continue;2543// }2544// // Recurse if we're merging plain objects or arrays2545// if (deep && copy && ((typeof copy === "object") || (copyIsArray = Array.isArray(copy)))) {2546// if (copyIsArray) {2547// copyIsArray = false;2548// clone = src && Array.isArray(src) ? src : [];2549// } else {2550// clone = src && (typeof src === "object") ? src : {};2551// }2552// // Never move original objects, clone them2553// target[name] = ctx.extend(deep, clone, copy);2554// // Don't bring in undefined values2555// } else if (typeof copy !== 'undefined') {2556// target[name] = copy;2557// }2558// }2559// }2560// }2561// // Return the modified object2562// return target;2563//};2564/**2565* Emulated WkMng object, only for testing in a Web browser2566* @path ctx.ICtxWkMng2567* @class ctx.ICtxWkMng2568* @ignore2569* @constructor2570*/2571ctx.ICtxWkMng = function () {2572 this.WkMgTrtEvent = function (AppliName, Event, ObjectName, ControlName, Data, lIdInstanceAppli, lIdInstanceObjet, lIdInstanceItem, pdispOiApp, ReqPrjName, reqAppliName, reqEventName, reqItemName, lReqIdInstanceAppli) { return ""; }2573 this.WkMgTrtEvent2 = function (AppliName, Event, ObjectName, ControlName, lControlIndex, Data, lIdInstanceAppli, lIdInstanceObjet, lIdInstanceItem, pdispOiApp, ReqPrjName, reqAppliName, reqEventName, reqItemName, lReqIdInstanceAppli) { return ""; }2574 this.WkMgLog = function (Message, lType) { return ""; }2575 this.WkMgLogErrSys = function (Message, ler, lerr) { return ""; }2576 this.WkMgSelSingleNode = function (queryString) { return ""; }2577 this.WkMgNotify = function (CtxName, AppliName, Event, ObjetName, ControlName, lControlIndex, Data, lIdInstanceAppli, lIdInstanceObjet, lIdInstanceItem, pdispOiApp) { return ""; }2578 this.CtxtAction = function (Action, AppliName, PageName, Item, lItemIndex, DataIn, lIdAppliInst, lIdPageInst, lIdItemInst) {2579 ctx.log("CtxtAction: " + Action + '|' + AppliName + '(' + lIdAppliInst + ').' + PageName + '(' + lIdPageInst + ')' + (Item !== '' ? '.' + Item + (lIdItemInst ? '(' + lIdItemInst + ')' : '') + (lItemIndex ? '[' + lItemIndex + ']' : '') : '') + '|' + DataIn);2580 return "";2581 }2582 this.CtxtActionApp = function (Action, AppliName, PageName, P1, P2, P3, P4, P5, lIdAppliInst, lIdPageInst, lIdItemInst) {2583 ctx.log("CtxtActionApp: " + Action + '|' + AppliName + '(' + lIdAppliInst + ').' + PageName + '(' + lIdPageInst + ')|' + P1 + '|' + P2 + '|' + P3 + '|' + P4 + '|' + P5 + '|' + lIdItemInst);2584 return "";2585 }2586 this.CtxtVerbExec = function (Command, AppliName, PageName, lIdAppliInst, lIdPageInst) {2587 ctx.log("CtxtVerbExec: " + Command + '|' + AppliName + '(' + lIdAppliInst + ').' + PageName + '(' + lIdPageInst + ')');2588 return "";2589 }2590 2591 this.CtxtLogTick = function () { return ""; }2592 this.CtxtLogTime = function (vChrono, Mess) { return ""; }2593 this.CtxtWriteFile = function (File, Text, vbEnd) { return ""; }2594 this.CtxtCreateObj = function (Object) { return ""; }2595 /**2596 * Description2597 * @ignore2598 * @method CtxtGetVal2599 * @path ctx.ICtxWkMng2600 * @param {string} variable2601 * @param {string} nodeCtx2602 * @param {string} idApp2603 * @param {Object} [pResult]2604 * @return {string} result2605 */2606 this.CtxtGetVal = function (variable, nodeCtx, idApp, pResult) { return ""; }2607 /**2608 * Description2609 * @ignore2610 * @method CtxtSetVal2611 * @param {string} variable2612 * @param {string} value2613 * @param {string} nodeCtx2614 * @param {string} idApp2615 * @param {Object} [pResult]2616 * @return {string} result2617 */2618 this.CtxtSetVal = function (variable, value, nodeCtx, idApp, pResult) { return ""; }2619 /**2620 * Description2621 * @ignore2622 * @method CtxtGetCtx2623 * @param {string} variable2624 * @param {string} nodeCtx2625 * @param {string} idApp2626 * @param {Object} [pResult]2627 * @return {string} result2628 */2629 this.CtxtGetCtx = function (variable, nodeCtx, idApp, pResult) { return ""; }2630 /**2631 * Description2632 * @ignore2633 * @method CtxtSetCtx2634 * @param {string} ctxt2635 * @param {string} iAction2636 * @param {string} model2637 * @param {string} iModel2638 * @param {string} nodeCtx2639 * @param {string} idApp2640 * @param {Object} [pResult]2641 * @return {string} result2642 */2643 this.CtxtSetCtx = function (ctxt, iAction, model, iModel, nodeCtx, idApp, pResult) { return ""; }2644 /**2645 * Description2646 * @ignore2647 * @method CtxtDelCtx2648 * @param {string} variable2649 * @param {string} nodeCtx2650 * @param {string} idApp2651 * @param {Object} [pResult]2652 * @return {string} result2653 */2654 this.CtxtDelCtx = function (variable, nodeCtx, idApp, pResult) { return ""; }2655 /**2656 * Description2657 * @ignore2658 * @method CtxtAddBloc2659 * @param {string} ctxt2660 * @param {string} model2661 * @param {string} iModel2662 * @param {string} [nodeCtx]2663 * @param {string} [idApp]2664 * @param {Object} [pResult]2665 * @return {string} result2666 */2667 this.CtxtAddBloc = function (ctxt, model, iModel, nodeCtx, idApp, pResult) { return ""; }2668 /**2669 * Description2670 * @ignore2671 * @method WkMgGetPscNode2672 * @param {string} pilote2673 * @param {Object} [pResult]2674 * @return {string} result2675 */2676 this.WkMgGetPscNode = function (pilote, pResult) { return ""; }2677 /**2678 * Description2679 * @ignore2680 * @method WkMgMessErr2681 * @param {string} pilot2682 * @param {string} func2683 * @param {string} code2684 * @param {string} error2685 * @param {Object} lMess2686 * @return {string} result2687 */2688 this.WkMgMessErr = function (pilot, func, code, error, lMess) { return ""; }2689 /**2690 * Description2691 * @ignore2692 * @method CryptProtect2693 * @param {string} input2694 * @param {string} [password]2695 * @return {string} result2696 */2697 this.CryptProtect = function (input, password) { return ""; }2698 /**2699 * Description2700 * @ignore2701 * @method CryptUnprotect2702 * @param {string} input2703 * @param {string} [password]2704 * @return {string} result2705 */2706 this.CryptUnprotect = function (input, password) { return ""; }2707 this.CryptEncryptStringToFile = function (inputString, outputFile, password) { return ""; }2708 this.CryptDecryptFileToString = function (inputFile, password) { return ""; }2709 this.CryptEncryptFileToFile = function (inputFile, outputFile, password) { return ""; }2710 this.CryptDecryptFileToFile = function (inputFile, outputFile, password) { return ""; }2711 this.CryptEncryptMessage = function (input, store, certificate) { return ""; }2712 this.CryptDecryptMessage = function (input, store, certificate) { return ""; }2713 this.CryptSignMessage = function (input) { return ""; }2714 this.CryptVerifyMessage = function (input) { return ""; }2715 this.SendTxtMsgToSocket = function (txt) { return ""; }2716 };2717/**2718 * The wkMng object :2719 * - if executed in Contextor engine, set it to a WkMng object2720 * - if executed in a test Web page, set it to a dummy emulation object2721 * @ignore2722 * @method wkMng2723 * @path ctx.wkMng2724 * @return {ctx.ICtxWkMng}2725 */2726ctx.wkMng = (2727/** @suppress {checkTypes} */2728function()2729{2730 // real (Interactive engine) or emulated (IE browser) object2731 /** @type {ctx.ICtxWkMng} */2732 var _wkMng = null;2733 if (!_wkMng) {2734 if (typeof Contextor !== 'undefined') {2735 _wkMng = Contextor;2736 } else if (typeof ctx.ICtxWkMng !== 'undefined') {2737 _wkMng = new ctx.ICtxWkMng();2738 }2739 }2740 return _wkMng;2741})();2742/**2743* Object describing an object position and size (X, Y, CX, CY, ...)2744* @class ctx.position2745* @path ctx.position2746* @param {number} [x] object left position (relative to screen)2747* @param {number} [y] object top position (relative to screen)2748* @param {number} [cx] object width2749* @param {number} [cy] object height2750* @param {number} [x2] object left position (relative to parent window)2751* @param {number} [y2] object top position (relative to parent window)2752* @param {number} [hwnd] handle of the parent window2753* @constructor2754*/2755ctx.position = function (x, y, cx, cy, x2, y2, hwnd) {2756 /** class type2757 * @ignore2758 * @const2759 * @path ctx.position.ctxType2760 * @property {string} */ this.ctxType = 'ctx.position';2761 /** object left position (relative to screen)2762 * @path ctx.position.x2763 * @property {number} */ this.x = x || 0;2764 /** object top position (relative to screen)2765 * @path ctx.position.y2766 * @property {number} */ this.y = y || 0;2767 /** object width2768 * @path ctx.position.cx2769 * @property {number} */ this.cx = cx || 0;2770 /** object height2771 * @path ctx.position.cy2772 * @property {number} */ this.cy = cy || 0;2773 /** object left position (relative to parent window)2774 * @path ctx.position.x22775 * @property {number} */ this.x2 = x2 || 0;2776 /** object top position (relative to parent window)2777 * @path ctx.position.y22778 * @property {number} */ this.y2 = y2 || 0;2779 /** handle of the parent window2780 * @path ctx.position.hwnd2781 * @property {number} */ this.hwnd = hwnd || 0;2782};2783/**2784* Object describing an object (application, page, item), with given names and instances2785* @class ctx.descriptor2786* @advanced2787* @path ctx.descriptor2788* @constructor2789*/2790ctx.descriptor = function () {2791 /** class type2792 * @ignore2793 * @const2794 * @path ctx.descriptor.ctxType2795 * @property {string} */ this.ctxType = 'ctx.descriptor';2796 /** application or process object2797 * @path ctx.descriptor.appli2798 * @property {ctx.application} */ this.appli = null;2799 /** application or process instance2800 * @path ctx.descriptor.appliInst2801 * @property {number} */ this.appliInst = -1;2802 /** application or process name2803 * @path ctx.descriptor.appliName2804 * @property {string} */ this.appliName = "";2805 /** object name2806 * @path ctx.descriptor.name2807 * @property {string} */ this.name = "";2808 /** occurence list for multi-dimension items2809 * @path ctx.descriptor.index2810 * @property {Array<string>} */ this.index = [];2811 /** item object2812 * @path ctx.descriptor.item2813 * @property {ctx.item} */ this.item = null;2814 /** item full name (including occurences or prefix)2815 * @path ctx.descriptor.itemFullName2816 * @property {string} */ this.itemFullName = ""; // item name including occurences (item[...][...])2817 /** item instance2818 * @path ctx.descriptor.itemInst2819 * @property {number} */ this.itemInst = 0;2820 /** item name2821 * @path ctx.descriptor.itemName2822 * @property {string} */ this.itemName = "";2823 /** item occurence level2824 * @path ctx.descriptor.itemOccurs2825 * @property {number} */ this.itemOccurs = 0;2826 /** object nature2827 * @path ctx.descriptor.nature2828 * @property {string} */ this.nature = "";2829 /** page object2830 * @path ctx.descriptor.page2831 * @property {ctx.page} */ this.page = null;2832 /** page instance2833 * @path ctx.descriptor.pageInst2834 * @property {number} */ this.pageInst = -1;2835 /** page name2836 * @path ctx.descriptor.pageName2837 * @property {string} */ this.pageName = "";2838 /** object type : application, page, item, ...2839 * @path ctx.descriptor.type2840 * @property {string} */ this.type = "";2841 /** [Internal usage]2842 * Returns the short description for serialization2843 * @ignore2844 * @method ctxShort2845 * @path ctx.descriptor.ctxShort2846 */2847 this.ctxShort = function() {2848 return ['ctxType', 'type', 'name', 'appliName', 'appliInst', 'pageName', 'pageInst', 'itemName', 'itemInst', 'itemOccurs', 'index'];2849 }2850};2851 /** Map of ctx.dataManager templates2852 * @path ctx.dataManagers2853 * @class ctx.dataManagers2854 * @type {Object}2855 */2856 ctx.dataManagers = {2857 /** Instanciates and initializes a dataManager object2858 * @description2859 * __Ex.:__2860<code javascript>2861MyAppli.on({ evCRMELIGetData: function(ev) {2862// create a dataManager, unserialized from the received event2863var data = ctx.dataManagers.create(ev.data);2864...2865}});2866</code>2867 * @method create2868 * @path ctx.dataManagers.create2869 * @param {*} data object with initialized values2870 * @return {Object|ctx.dataClass} data object2871 */2872 create : function (data) {2873 var obj;2874 if (data && data.ctxName) {2875 var id = data.ctxName;2876 var tId = id.split('.');2877 var root = ctx.dataManagers;2878 while (tId.length > 1) {2879 var category = tId.shift();2880 if (root[category]) {2881 root = root[category];2882 }2883 }2884 id = tId.shift();2885 if (root[id] && (typeof root[id].create === 'function')) {2886 obj = root[id].create(data, true);2887 }2888 }2889 if (!obj) {2890 var name = '';2891 if (data instanceof ctx.dataClass) { name = data.ctxName; }2892 throw new Error(e.error.InvalidArgument, 'ctx.dataManagers.create: unknown data model: ' + name);2893 }2894 return obj;2895 }2896 };2897 /**2898 * Class used to manage data objects2899 *2900 * __Ex.:__2901<code javascript>2902ctx.dataManager({ticket : {2903 id: '',2904 priority: '',2905 description: '',2906 assigned: '',2907 ...2908}});2909</code>2910 * @description2911 * @class ctx.dataManager2912 * @path ctx.dataManager2913 * @constructor2914 * @param {ctx.dataClass|Object|string} [obj] object for initialization2915 * @param {boolean} [locked] if 'true', no attribute can be added after initialization2916 * @suppress {checkTypes}2917 * @return {ctx.dataClass} dataManager object2918 */2919 ctx.dataManager = function (obj, locked) {2920 var dataManager = null;2921 if (obj instanceof ctx.dataClass) {2922 dataManager = obj.create();2923 } else if (obj && (typeof (obj) === 'object')) {2924 ctx.each(obj, function(id, value) {2925 var name = id;2926 var tId = id.split('.');2927 var root = ctx.dataManagers;2928 while (tId.length > 1) {2929 var category = tId.shift();2930 if (!root[category]) { root[category] = {}; }2931 root = root[category];2932 }2933 id = tId.shift();2934 if (!root[id]) {2935 if (typeof (value) === 'object') {2936 root[id] = new ctx.dataClass(value, name, locked); // create new2937 dataManager = root[id];2938 }2939 } else {2940 dataManager = root[id].create();2941 }2942 });2943 } else if (typeof (obj) === 'string') {2944 var id = obj;2945 var name = id;2946 var tId = id.split('.');2947 var root = ctx.dataManagers;2948 while (tId.length > 1) {2949 var category = tId.shift();2950 if (!root[category]) { root[category] = {}; }2951 root = root[category];2952 }2953 id = tId.shift();2954 if (!root[name]) {2955 root[id] = new ctx.dataClass({}, name, false); // create new2956 dataManager = root[id];2957 } else {2958 dataManager = root[name].create();2959 }2960 } else {2961 //var name = 'dataManager_' + ctx.uuid();2962 dataManager = new ctx.dataClass({}, '', false); // create a new empty dataManager2963 }2964 return dataManager;2965 };2966/**2967 * Class to store free data in objects2968 * @class ctx.dataClass2969 * @path ctx.dataClass2970 * @advanced2971 * @constructor2972 * @param {ctx.dataClass|Object} [obj] optional object or dataManager for initialization2973 * @param {string} [name] class name (if omited, a unique name is generated)2974 * @param {boolean} [locked] if 'true', no attribute can be added after initialization2975 */2976 ctx.dataClass = function (obj, name, locked) {2977 if (!(this instanceof ctx.dataClass))2978 return new ctx.dataClass(obj, name, locked); // in case 'new' was not used2979 var self = this;2980 /** class type2981 * @ignore2982 * @const2983 * @path ctx.dataClass.ctxType2984 * @property {string} */ self.ctxType = 'ctx.dataClass';2985 /** class name2986 * @ignore2987 * @path ctx.dataClass.ctxName2988 * @property {string} */ self.ctxName = name || (obj && obj.ctxName);2989 // model2990 var _model = obj;2991 // locked state2992 var _locked = locked || false;2993 /**2994 * Completes an existing object with attributes of the data manager2995 * @description2996 * __Ex.:__2997 * <code javascript>2998 * obj = contactData.create(obj);2999 * </code>3000 * @method complete3001 * @path ctx.dataClass.complete3002 * @param {Object} obj initialization data3003 * @return {Object} returned object3004 */3005 self.complete = function (obj) {3006 if (obj && (typeof obj === 'object')) {3007 ctx.each(self, function(id, value) {3008 if (typeof obj[id] === 'undefined') {3009 obj[id] = value;3010 }3011 });3012 }3013 return obj;3014 }3015 /**3016 * Creates an instance of the data manager object3017 * @description3018 * __Ex.:__3019 * <code javascript>3020 * var contact = contactData.create();3021 * </code>3022 * @method create3023 * @path ctx.dataClass.create3024 * @param {*|ctx.dataClass} [obj] optional initialization data3025 * @param {boolean} [checkModel] if true, check the model of initialization data3026 * @return {ctx.dataClass|null} returned object (or null if not a compatible model)3027 */3028 self.create = function (obj, checkModel) {3029 var data = null;3030 if ((!checkModel) || (obj && (obj.ctxName == self.ctxName))){3031 data = new ctx.dataClass(self);3032 if (obj && (typeof obj === 'object')) {3033 data.set(obj);3034 }3035 }3036 return data;3037 }3038 /**3039 * Tests if a value or set of values exists in the data object3040 * @description3041 * __Ex.:__3042 * <code javascript>3043 * if (ScnApp.data.exist("//Data_Popup1", e.data.pathType.XPath)) { ... }3044 * </code>3045 * @method exist3046 * @path ctx.dataClass.exist3047 * @param {string} [path] path3048 * @param {e.data.pathType} [pathType] data path type (see [[:lib:common:ctx.enum#enumeration_edatapathtype|e.data.pathType]]) (default is 'e.data.pathType.XPath')3049 * @return {boolean} returned object or value3050 */3051 self.exist = function (path, pathType) {3052 var parentAppli = null;3053 if ((self.appliName) && (self.appliInst !== undefined) && ctx.app[self.appliName]) {3054 if (self.appliInst == -1)3055 parentAppli = ctx.app[self.appliName];3056 else3057 parentAppli = ctx.app[self.appliName][self.appliInst];3058 }3059 /** @type {ctx.descriptor} */ var desc = (parentAppli && parentAppli.getObjectDescriptor ? parentAppli.getObjectDescriptor() : ctx.getDescriptor());3060 if (desc && desc.appli) {3061 parentAppli = desc.appli;3062 }3063 return ctx.exist(parentAppli, path, pathType);3064 }3065 /**3066 * Deletes a node in the data object3067 * @description3068 * __Ex.:__3069 * <code javascript>3070 * GLOBAL.data.set( { name:'Ford', firstname:'John' } ); // adds 'name' and 'firstname' attributes in GLOBAL.data3071 * </code>3072 * @method del3073 * @path ctx.dataClass.del3074 * @param {string} [path] target path or object3075 * @param {e.data.pathType} [pathType] data path type (see [[:lib:common:ctx.enum#enumeration_edatapathtype|e.data.pathType]]) (default is 'e.data.pathType.XPath')3076 * @return {*} modified object3077 */3078 self.del = function (path, pathType) {3079 return self.set('', path, e.data.format.ctx, e.data.initType.DEL, pathType);3080 }3081 /**3082 * Returns a value or set of values in the data object3083 * @description3084 * __Ex.:__3085 * <code javascript>3086 * var val = ScnApp.data.get("//Data_Popup1", e.data.pathType.XPath);3087 * </code>3088 * @method get3089 * @path ctx.dataClass.get3090 * @param {string} [path] path3091 * @param {e.data.pathType} [pathType] data path type (see [[:lib:common:ctx.enum#enumeration_edatapathtype|e.data.pathType]]) (default is 'e.data.pathType.XPath')3092 * @param {e.data.format} [format] output data format (see [[:lib:common:ctx.enum#enumeration_edataformat|e.data.format]])3093 * @return {*} returned object or value3094 */3095 self.get = function (path, pathType, format) {3096 var parentAppli = null;3097 if ((self.appliName) && (self.appliInst !== undefined) && ctx.app[self.appliName]) {3098 if (self.appliInst == -1)3099 parentAppli = ctx.app[self.appliName];3100 else3101 parentAppli = ctx.app[self.appliName][self.appliInst];3102 }3103 /** @type {ctx.descriptor} */ var desc = (parentAppli && parentAppli.getObjectDescriptor ? parentAppli.getObjectDescriptor() : ctx.getDescriptor());3104 if (desc && desc.appli) {3105 parentAppli = desc.appli;3106 }3107 return ctx.get(parentAppli, path, pathType, format);3108 }3109 /**3110 * Resets a set of values in the data object3111 * @description3112 * __Ex.:__3113 * <code javascript>3114 * var contact = ctx.dataManagers.myApplication.contact.create();3115 * // contact :3116 * // FirstName = '';3117 * // LastName = '';3118 * // Mobile = '';3119 * // Address = '';3120 * contact.FirstName = 'John';3121 * contact.LastName = 'Smith';3122 * ...3123 * contact.reset( );3124 * </code>3125 * @method reset3126 * @path ctx.dataClass.reset3127 * @return {*} modified object3128 */3129 self.reset = function () {3130 return self.set(_model || {});3131 }3132 /**3133 * Merges a value or set of values in the data object3134 * @description3135 * __Ex.:__3136 * <code javascript>3137 * GLOBAL.data.set( { name:'Ford', firstname:'John' } ); // adds 'name' and 'firstname' attributes in GLOBAL.data3138 * </code>3139 * @method set3140 * @path ctx.dataClass.set3141 * @param {*} data object or string containing data to be set3142 * @param {string} [path] target path or object3143 * @param {e.data.format} [format] data format type (see [[:lib:common:ctx.enum#enumeration_edataformat|e.data.format]])3144 * @param {e.data.initType} [initType] data initialisation type (see [[:lib:common:ctx.enum#enumeration_edatainittype|e.data.initType]])3145 * @param {e.data.pathType} [pathType] data path type (see [[:lib:common:ctx.enum#enumeration_edatapathtype|e.data.pathType]]) (default is 'e.data.pathType.XPath')3146 * @param {boolean} [locked] if 'true', no attribute can be added after initialization3147 * @return {*} modified object3148 */3149 self.set = function (data, path, format, initType, pathType, locked) {3150 var parentAppli = null;3151 if ((self.appliName) && (self.appliInst !== undefined) && ctx.app[self.appliName]) {3152 if (ctx.app[self.appliName].isProcess || (self.appliInst == -1))3153 parentAppli = ctx.app[self.appliName];3154 else3155 parentAppli = ctx.app[self.appliName][self.appliInst];3156 }3157 /** @type {ctx.descriptor} */ var desc = (parentAppli && parentAppli.getObjectDescriptor ? parentAppli.getObjectDescriptor() : ctx.getDescriptor());3158 if (desc && desc.appli) {3159 parentAppli = desc.appli;3160 }3161 var res = ctx.set(data, parentAppli || self, path, format, initType, pathType, locked || _locked);3162 return res;3163 }3164 if (obj) {3165 self.set(obj, '', undefined, undefined, undefined, _locked);3166 if (locked === undefined) _locked = true; // if there is an initialization object, prevent adding further attributes by default3167 }3168 //self._info.ts = ctx.getTimestamp(); // creation timestamp3169 return self;3170 };3171ctx.construct = function (constructor, args) {3172 /** @constructor */3173 function F() {3174 return constructor.apply(this, args);3175 }3176 F.prototype = constructor.prototype;3177 return new F();3178}3179/**3180* Class used to manage array objects3181* @description3182* __Ex.:__3183<code javascript>3184var array = ctx.array([...]);3185</code>3186* @class ctx.array3187* @path ctx.array3188* @param {...*} var_args3189* @return {ctx.arrayClass} array object3190*/3191ctx.array = function (var_args) {3192 return ctx.construct(ctx.arrayClass, arguments);3193 //return new ctx.arrayClass(arguments);3194};3195/** create an Array object3196* @class ctx.array3197* @path ctx.arrayClass3198* @constructor3199* @advanced3200* @param {...*} var_args3201*/3202ctx.arrayClass = function(var_args) {3203 /*if (!(this instanceof ctx.arrayClass)) {3204 return ctx.construct(ctx.array, arguments);3205 }*/3206 var arr = [ ];3207 var _callbacks = {};3208 var _singleCallbacks = {};3209 var _checkCallbacks = function() {3210 if (_callbacks[arr.index] && ('function' === typeof _callbacks[arr.index])) {3211 _callbacks[arr.index](arr.index);3212 if (_singleCallbacks[arr.index]) {3213 delete _callbacks[arr.index];3214 delete _singleCallbacks[arr.index];3215 }3216 }3217 }3218 /** class type3219 * @ignore3220 * @const3221 * @path ctx.arrayClass.ctxType3222 * @property {string} */3223 arr.ctxType = 'ctx.array';3224 /** class type3225 * @ignore3226 * @const3227 * @path ctx.arrayClass.ctxArray3228 * @property {boolean} */3229 arr.ctxArray = true;3230 /**3231 * @type {number}3232 */3233 arr.index = 0;3234 /**3235 * Clears array content3236 * @method clear3237 * @path ctx.arrayClass.clear3238 * @description3239 * __Ex.:__3240 <code javascript>3241 var jobs = ctx.array([3242 { search: 'Interstellar' },3243 { search: 'Pulp Fiction' },3244 ...3245 ]);3246 ...3247 jobs.clear();3248 </code>3249 */3250 arr.clear = function() {3251 arr = ctx.array();3252 return arr;3253 }3254 /**3255 * Returns the current element3256 * @method item3257 * @path ctx.arrayClass.item3258 * @param {number} [index] iteration index. If omitted, get current index. If mentioned, set the current index and returns iteration3259 * @description3260 * __Ex.:__3261 <code javascript>3262 var jobs = ctx.array([3263 { search: 'Interstellar' },3264 { search: 'Pulp Fiction' },3265 ...3266 ]);3267 var it = jobs.item();3268 </code>3269 */3270 arr.item = function(index) {3271 if ((index !== undefined) && (index < arr.length) && (index >= 0) && (arr.index != index)) {3272 arr.index = index;3273 _checkCallbacks();3274 }3275 if ((arr.index < arr.length) && (arr.index >= 0))3276 return arr[arr.index];3277 else3278 return undefined;3279 }3280// arr.last = function() {3281// return arr[arr.length - 1];3282// };3283 /**3284 * Sets the array index to the first element, and returns it. If empty, returns 'undefined'3285 * @method moveFirst3286 * @path ctx.arrayClass.moveFirst3287 * @return {*}3288 * @description3289 * __Ex.:__3290 <code javascript>3291 var jobs = ctx.array(...);3292 jobs.end();3293 </code>3294 */3295 arr.moveFirst = function() {3296 return arr.item((arr.length > 0 ? 0 : -1));3297 }3298 /**3299 * Sets the array index to the last element, and returns it. If empty, returns 'undefined'3300 * @method moveLast3301 * @path ctx.arrayClass.moveEnd3302 * @return {*}3303 * @description3304 * __Ex.:__3305 <code javascript>3306 var jobs = ctx.array(...);3307 jobs.end();3308 </code>3309 */3310 arr.moveLast = function() {3311 return arr.item(arr.length - 1);3312 }3313 /**3314 * Sets the array index to the next element, and returns it. If end is reached, returns 'undefined'3315 * @method moveNext3316 * @path ctx.arrayClass.moveNext3317 * @return {*}3318 * @description3319 * __Ex.:__3320 <code javascript>3321 var jobs = ctx.array(...);3322 jobs.moveNext();3323 </code>3324 */3325 arr.moveNext = function() {3326 if (arr.index < arr.length) {3327 arr.index ++;3328 _checkCallbacks();3329 return arr.item();3330 } else {3331 return undefined;3332 }3333 }3334 /**3335 * Sets the array index to the previous element, and returns it. If beginning is reached, returns 'undefined'3336 * @method previous3337 * @path ctx.arrayClass.previous3338 * @return {*}3339 * @description3340 * __Ex.:__3341 <code javascript>3342 var jobs = ctx.array(...);3343 var job = jobs.previous();3344 </code>3345 */3346 arr.movePrevious = function() {3347 if (arr.index >= 0) {3348 arr.index --;3349 _checkCallbacks();3350 return arr.item();3351 } else {3352 return undefined;3353 }3354 }3355 /**3356 * Sets the array index to the next element, and returns it. If end is reached, returns 'undefined'3357 * @method next3358 * @path ctx.arrayClass.atEnd3359 * @description3360 * __Ex.:__3361 <code javascript>3362 var jobs = ctx.array(...);3363 if (jobs.atEnd()) {3364 ...3365 }3366 </code>3367 */3368 arr.atEnd = function() {3369 return ((arr.index < 0) || (arr.index >= arr.length));3370 }3371 /**3372 * Returns the value of a random element3373 * @method random3374 * @path ctx.arrayClass.random3375 * @return {*}3376 * @description3377 * __Ex.:__3378 <code javascript>3379 var jobs = ctx.array(...);3380 var val = jobs.random();3381 </code>3382 */3383 arr.random = function() {3384 if (arr.length > 0) {3385 var index = Math.floor ( Math.random () * arr.length );3386 return arr[index];3387 } else3388 return undefined;3389 }3390 /**3391 * increments the counter3392 * @description3393 * __Ex.:__3394<code javascript>3395var counter = ctx.counter().onValue(0, function() {3396 sc.endStep();3397});3398...3399counter.increment();3400...3401counter.decrement(); // the callback is called3402</code>3403 * @method increment3404 * @path ctx.arrayClass.increment3405 * @return {*}3406 */3407 arr.increment = function () {3408 arr.index ++;3409 if (arr.index >= arr.length) {3410 arr.length = arr.index + 1;3411 }3412 _checkCallbacks();3413 return arr.item();3414 }3415 /**3416 * decrements the counter3417 * @description3418 * __Ex.:__3419<code javascript>3420var counter = ctx.counter().onValue(0, function() {3421 sc.endStep();3422});3423...3424counter.increment();3425...3426counter.decrement(); // the callback is called3427</code>3428 * @method decrement3429 * @path ctx.counterClass.decrement3430 * @return {*}3431 */3432 arr.decrement = function () {3433 return arr.movePrevious();3434 }3435 /**3436 * decrements the counter3437 * @description3438 * __Ex.:__3439<code javascript>3440var counter = ctx.array().onValue(0, function() {3441 sc.endStep();3442});3443...3444counter.check(); // the callback is called if current value is '0'3445</code>3446 * @method check3447 * @path ctx.arrayClass.check3448 */3449 arr.check = function () {3450 _checkCallbacks();3451 }3452 /**3453 * adds a callback to be called on a given value3454 * @description3455 * __Ex.:__3456<code javascript>3457var counter = ctx.array().on(0, function() {3458 sc.endStep();3459});3460</code>3461 * @method on3462 * @path ctx.arrayClass.on3463 * @param {number} value value to trigger the callback3464 * @param {function(number)} [callback] callback (if omitted, the existing callback is removed)3465 * @param {boolean} [single] is true, the callback is called once3466 */3467 arr.on = function (value, callback, single) {3468 if (callback && ('function' === typeof callback)) {3469 _callbacks[value] = callback;3470 _singleCallbacks[value] = (single ? true : false);3471 } else {3472 if (_callbacks[value]) delete _callbacks[value];3473 if (_singleCallbacks[value]) delete _singleCallbacks[value];3474 }3475 }3476 /**3477 * sets current counter value3478 * @method setValue3479 * @path ctx.arrayClass.setValue3480 * @param {number} value new index value3481 */3482 arr.setIndex = function (value) {3483 if ((value !== undefined) && ('number' === typeof(value)) && (arr.index != value)) {3484 arr.index = value;3485 if (arr.index >= arr.length) {3486 arr.length = arr.index + 1;3487 }3488 _checkCallbacks();3489 }3490 }3491 var args = arguments;3492 if ((args.length == 1) && (Array.isArray(args[0])))3493 args = args[0];// Array wrapper3494 if (args.length > 0)3495 arr.push.apply(arr, args);3496 return arr;3497};3498/**3499* Class used to manage counter objects3500* @class ctx.counter3501* @path ctx.counter3502* @param {number} [initValue] initial value (0 by default)3503* @return {ctx.counterClass} counter object3504*/3505ctx.counter = function (initValue) {3506 var counter = new ctx.counterClass(initValue);3507 return counter;3508};3509/**3510* Class used to implement asynchronous counters3511* @class ctx.counterClass3512* @path ctx.counterClass3513* @constructor3514* @param {number} [initValue] initial value (0 by default)3515*/3516ctx.counterClass = function (initValue) {3517 /** @type {number}*/ var _value = 0;3518 if ((initValue !== undefined) && ('number' === typeof(initValue))) _value = initValue;3519 var _callbacks = {};3520 var _singleCallbacks = {};3521 var _checkCallbacks = function() {3522 if (_callbacks[_value] && ('function' === typeof _callbacks[_value])) {3523 _callbacks[_value]();3524 if (_singleCallbacks[_value]) {3525 delete _callbacks[_value];3526 delete _singleCallbacks[_value];3527 }3528 }3529 }3530 /** class type3531 * @ignore3532 * @const3533 * @path ctx.counterClass.ctxType3534 * @property {string} */ this.ctxType = 'ctx.counterClass';3535 /**3536 * decrements the counter3537 * @description3538 * __Ex.:__3539<code javascript>3540var counter = ctx.counter().onValue(0, function() {3541 sc.endStep();3542});3543...3544counter.checkValue(); // the callback is called if current value is '0'3545</code>3546 * @method checkValue3547 * @path ctx.counterClass.checkValue3548 * @return {ctx.counterClass}3549 */3550 this.checkValue = function () {3551 _checkCallbacks();3552 return this;3553 }3554 /**3555 * decrements the counter3556 * @description3557 * __Ex.:__3558<code javascript>3559var counter = ctx.counter().onValue(0, function() {3560 sc.endStep();3561});3562...3563counter.increment();3564...3565counter.decrement(); // the callback is called3566</code>3567 * @method decrement3568 * @path ctx.counterClass.decrement3569 * @return {number}3570 */3571 this.decrement = function () {3572 _value --;3573 _checkCallbacks();3574 return _value;3575 }3576 /**3577 * gets the current counter value3578 * @description3579 * __Ex.:__3580<code javascript>3581counter.decrement();3582...3583if (counter.getValue() <= 0) { ... }3584</code>3585 * @method getValue3586 * @path ctx.counterClass.getValue3587 * @return {number}3588 */3589 this.getValue = function () {3590 return _value;3591 }3592 /**3593 * increments the counter3594 * @description3595 * __Ex.:__3596<code javascript>3597var counter = ctx.counter().onValue(0, function() {3598 sc.endStep();3599});3600...3601counter.increment();3602...3603counter.decrement(); // the callback is called3604</code>3605 * @method increment3606 * @path ctx.counterClass.increment3607 * @return {number}3608 */3609 this.increment = function () {3610 _value ++;3611 _checkCallbacks();3612 return _value;3613 }3614 /**3615 * adds a callback to be called on a given value3616 * @description3617 * __Ex.:__3618<code javascript>3619var counter = new ctx.counter().onValue(0, function() {3620 sc.endStep();3621});3622</code>3623 * @method onValue3624 * @path ctx.counterClass.onValue3625 * @param {number} value value to trigger the callback3626 * @param {function()} [callback] callback (if omitted, the existing callback is removed)3627 * @param {boolean} [single] is true, the callback is called once3628 * @return {ctx.counterClass}3629 */3630 this.onValue = function (value, callback, single) {3631 if (callback && ('function' === typeof callback)) {3632 _callbacks[value] = callback;3633 _singleCallbacks[value] = (single ? true : false);3634 } else {3635 if (_callbacks[value]) delete _callbacks[value];3636 if (_singleCallbacks[value]) delete _singleCallbacks[value];3637 }3638 return this;3639 }3640 /**3641 * sets current counter value3642 * @description3643 * __Ex.:__3644<code javascript>3645var counter = new ctx.counter().onValue(0, function() {3646 sc.endStep();3647});3648</code>3649 * @method setValue3650 * @path ctx.counterClass.setValue3651 * @param {number} value new counter value3652 * @return {ctx.counterClass}3653 */3654 this.setValue = function (value) {3655 if ((value !== undefined) && ('number' === typeof(value))) {3656 _value = value;3657 _checkCallbacks();3658 }3659 return this;3660 }3661};3662/**3663* Class used to implement technical or functional events3664* @class ctx.event3665* @path ctx.event3666* @constructor3667* @advanced3668* @param {string|Object} [nameOrObj] event name or initialization parameters3669* @param {ctx.application|ctx.page|ctx.item|ctx.popupItem} [parent] parent object3670* @param {Object|ctx.dataClass} [dataClass] data model object3671* @param {boolean} [technical] if true, technical object3672*/3673ctx.event = function (nameOrObj, parent, dataClass, technical) {3674 var _event = this;3675 /** class type3676 * @ignore3677 * @const3678 * @path ctx.event.ctxType3679 * @property {string} */ this.ctxType = 'ctx.event';3680 /** parent application or process object3681 * @path ctx.event.appli3682 * @property {ctx.application} */ this.appli = (parent ? parent.appli : null);3683 /** application or process instance3684 * @path ctx.event.appliInst3685 * @property {number} */ this.appliInst = (parent && parent.appli ? parent.appli.instance : -1);3686 /** application or process name3687 * @path ctx.event.appliName3688 * @property {string} */ this.appliName = (parent && parent.appli ? parent.appli.name : '');3689 /** optional data stored in event3690 * @path ctx.event.data3691 * @property {*|ctx.dataClass} */ this.data = null;3692 /** data format3693 * @path ctx.event.format3694 * @property {e.data.format} */ this.format = e.data.format.none;3695 /** internal event (not displayed in debugger)3696 * @path ctx.event.internal3697 * @property {boolean} */ this.internal = false;3698 /** item index3699 * @path ctx.event.itemIndex3700 * @property {number} */ this.itemIndex = (parent && parent.item ? parent.item.index : 0);3701 /** item instance3702 * @path ctx.event.itemInst3703 * @property {number} */ this.itemInst = (parent && parent.item ? parent.item.instance : 0);3704 /** item name3705 * @path ctx.event.itemName3706 * @property {string} */ this.itemName = (parent && parent.item ? parent.item.name : '');3707 /** item occurence level3708 * @path ctx.event.itemOccurs3709 * @property {number} */ this.itemOccurs = (parent && parent.item ? parent.item.occurs : 0);3710 /** Event name3711 * @path ctx.event.name3712 * @property {string} */ this.name = '';3713 /** instance count3714 * @path ctx.event.nbInst3715 * @property {number} */ this.nbInst = 0;3716 /** parent page object3717 * @path ctx.event.page3718 * @property {ctx.page} */ this.page = (parent ? parent.page : null);3719 /** page instance3720 * @path ctx.event.pageInst3721 * @property {number} */ this.pageInst = (parent && parent.page ? parent.page.instance : -1);3722 /** page name3723 * @path ctx.event.pageName3724 * @property {string} */ this.pageName = (parent && parent.page ? parent.page.name : '');3725 /** parent object associated with event (application, page, item)3726 * @path ctx.event.parent3727 * @property {ctx.application|ctx.page|ctx.item|undefined} */ this.parent = parent;3728 /** source application or process instance3729 * @path ctx.event.reqAppliInst3730 * @property {number} */ this.reqAppliInst = 0;3731 /** source application or process name3732 * @path ctx.event.reqAppliName3733 * @property {string} */ this.reqAppliName = '';3734 /** source event name3735 * @path ctx.event.reqEventName3736 * @property {string} */ this.reqEventName = '';3737 /** source item name3738 * @path ctx.event.reqItemName3739 * @property {string} */ this.reqItemName = '';3740 /** technical vs functionnal event3741 * @path ctx.event.technical3742 * @property {boolean} */ this.technical = technical;3743 /**3744 * Clears event content3745 * @description3746 * __Ex.:__3747<code javascript>3748ev.clear();3749</code>3750 * @method clear3751 * @path ctx.event.clear3752 */3753 this.clear = function () {3754 this.name = '';3755 this.parent = null;3756 this.appli = null;3757 this.page = null;3758 this.appliName = '';3759 this.pageName = '';3760 this.itemName = '';3761 this.appliInst = -1;3762 this.pageInst = -1;3763 this.itemInst = 0;3764 this.itemIndex = -1;3765 this.itemOccurs = 0;3766 this.nbInst = 0;3767 ((this.data && this.data.reset) ? this.data.reset() : this.data = {} );3768 this.reqAppliName = '';3769 this.reqAppliInst = 0;3770 this.reqEventName = '';3771 this.reqItemName = '';3772 }3773 /**3774 * Returns a copy of the event3775 * @description3776 * __Ex.:__3777<code javascript>3778var ev2 = ev.copy();3779</code>3780 * @method copy3781 * @path ctx.event.copy3782 * @suppress {checkTypes}3783 * @return {ctx.event} copied event3784 */3785 this.copy = function () {3786 var ev = new ctx.event(this.name);3787 ctx.each(this, function(id, value) {3788 if ((id == 'data') && (typeof value === 'object')) {3789 if (typeof ev.data.set === 'function') {3790 ev.data.set(value);3791 } else {3792 ctx.set(value, ev.data);3793 }3794 } else {3795 ev[id] = value;3796 }3797 });3798 return ev;3799 }3800 /**3801 * Creates a new instance of an event3802 * @description3803 * __Ex.:__3804<code javascript>3805var ev2 = MyApply.events.ev.create();3806</code>3807 * @method create3808 * @path ctx.event.create3809 * @param {Object|ctx.dataClass} [obj] optional initialization data3810 * @return {ctx.event} created event3811 */3812 this.create = function (obj) {3813 var ev = this.copy();3814 if (obj ) {3815 if (this.data.create) {3816 ev.data = this.data.create(obj);3817 } else {3818 ev.data = obj;3819 }3820 }3821 return ev;3822 }3823 /** @method init3824 * @param {Object} [obj]3825 * @path ctx.event.init3826 * @return {ctx.event} */3827 this.init = function(obj) {3828 if (obj && ('object' === typeof obj)) {3829 ctx.each(obj, function(id, value) {3830 if ((_event[id] !== undefined) && (value !== undefined)) {3831 _event[id] = value;3832 }3833 });3834 }3835 var ev = _event;3836 if ((!ev.appli) && ctx.app[ev.appliName]) {3837 ev.appli = ctx.app[ev.appliName][ev.appliInst] || ctx.app[ev.appliName];3838 }3839 if ((!ev.page) && ev.pageName && ev.appli && ev.appli[ev.pageName]) {3840 ev.page = ev.appli[ev.pageName][ev.pageInst] || ev.appli[ev.pageName];3841 }3842 ev.parent = (ev.page ? ev.page : ev.appli);3843 return _event;3844 }3845 if (dataClass instanceof ctx.dataClass) {3846 this.data = ctx.dataManager(dataClass);3847 } else if (dataClass && (typeof (dataClass) === 'object')) {3848 var obj = {};3849 obj[_event.name] = dataClass;3850 this.data = ctx.dataManager(obj);3851 } else {3852 //this.data = ctx.dataManager(name);3853 this.data = {};3854 }3855 if (nameOrObj) {3856 if ('object' === typeof nameOrObj) {3857 _event.init(nameOrObj);3858 } else if ('string' === typeof nameOrObj) {3859 _event.name = nameOrObj;3860 }3861 }3862 /** [Internal usage]3863 * Returns the short description for serialization3864 * @ignore3865 * @method ctxShort3866 * @path ctx.event.ctxShort3867 */3868 this.ctxShort = function() {3869 return ['ctxType', 'name', 'appliName', 'appliInst', 'pageName', 'pageInst', 'itemName', 'itemInst', 'itemIndex', 'itemOccurs', 'nbInst', 'data', 'reqAppliName', 'reqAppliInst', 'reqEventName', 'reqItemName'];3870 }3871 /**3872 * Gets an alias of the event, like <appliName[appliInst].pageName[pageInst].itemName:name>3873 * @method getAlias3874 * @path ctx.event.getAlias3875 * @return {string} result3876 */3877 this.getAlias = function () {3878 var res = this.appliName + '[' + this.appliInst + ']';3879 if (this.pageName) {3880 res = res + '.' + this.pageName + '[' + this.pageInst + ']';3881 }3882 if (this.itemName) {3883 res = res + '.' + this.itemName;3884 }3885 res = res + ':' + this.name;3886 return res;3887 }3888 /**3889 * Gets an alias of the event source, like <reqAppliName[reqAppliInst].reqPageName[reqPageInst].reqItemName:name>3890 * @method getAliasReq3891 * @path ctx.event.getAliasReq3892 * @return {string} result3893 */3894 this.getAliasReq = function () {3895 var res = this.reqAppliName + '[' + this.reqAppliInst + ']';3896 if (this.reqItemName) {3897 res = res + '.' + this.reqItemName;3898 }3899 res = res + ':' + (this.reqEventName || this.name);3900 return res;3901 }3902 /**3903 * Retrieves the object descriptor from the given event3904 * @method getObjectDescriptor3905 * @path ctx.event.getObjectDescriptor3906 * @ignore3907 * @param {ctx.descriptor} [desc] Optional source descriptor object3908 * @return {ctx.descriptor} Object descriptor3909 */3910 this.getObjectDescriptor = function (desc) {3911 if (!desc)3912 desc = new ctx.descriptor();3913 if (this.parent)3914 desc = this.parent.getObjectDescriptor(desc);3915 if (this.name) { desc.name = this.name; }3916 if (this.type) { desc.type = this.type; }3917 if (this.appli) { desc.appli = this.appli; }3918 if (this.page) { desc.page = this.page; }3919 if (this.appliName) { desc.appliName = this.appliName; }3920 if (this.pageName) { desc.pageName = this.pageName; }3921 if (this.itemName) { desc.itemName = this.itemName; }3922 if (this.appliInst >= 0) { desc.appliInst = this.appliInst; }3923 if (this.pageInst >= 0) { desc.pageInst = this.pageInst; }3924 if (this.itemInst >= 0) { desc.itemInst = this.itemInst; }3925 if (this.itemIndex >= 0) { desc.itemIndex = this.itemIndex; }3926 if (this.itemOccurs) { desc.itemOccurs = this.itemOccurs; }3927 if (this.index) { desc.index = this.index; }3928 return desc;3929 };3930 /**3931 * Sends an event to a target application or page3932 * @description3933 * __Ex.:__3934<code javascript>3935// sends a functional event 'evLogin' with data and a 5 s delay3936var obj = { name: 'Smith', firstname: 'John' };3937ev.notify(MyAppli.events.evLogin, obj, 5000);3938</code>3939 * @method notify3940 * @path ctx.event.notify3941 * @param {ctx.event} event event object to be notified3942 * @param {*} [data] event data3943 * @param {number|string} [timer] timer value (ms)3944 * @param {string} [appliInst] appli instance3945 * @param {string} [method] optional method name : 'Send' for a synchronous call3946 * @param {string} [itemName] item name3947 * @return returns result3948 */3949 this.notify = function (event, data, timer, appliInst, method, itemName) {3950 if (this.appli && (typeof this.appli.notify === 'function')) {3951 var reqEvent = this;3952 return this.appli.notify(event, data, timer, appliInst, method, itemName, reqEvent);3953 }3954 return '';3955 };3956 /**3957 * Sets a permanent or single handler to listen to a given event3958 * @description3959 * __Ex.:__3960<code javascript>3961LinkedIn.events.START.on(function(ev) {...});3962</code>3963 * @method on3964 * @path ctx.event.on3965 * @param {function(ctx.event)} func callback to be called on event reception3966 * @param {boolean|function()} [immediateCondition] if defined, function to be called immediately : if it returns a 'true' result, the 'func' callback is executed3967 * @param {Object} [context] context object to be called with the callback3968 * @param {boolean} [single] if 'true', sets a single listening on the event (otherwise, a permanent listening)3969 * @param {number} [delay] optional delay to wait before calling the callback (default is 0)3970 * @param {boolean} [noStepReset] if 'true', and handler is set in a step, it is not reset on step exit3971 * @return {Object} an object to be provided to 'ctx.off()' to disable listening3972 */3973 this.on = function (func, immediateCondition, context, single, delay, noStepReset) {3974 return ctx.on(this, func, immediateCondition, context, single, delay, noStepReset);3975 };3976 /**3977 * Sets a single handler to listen to a given event3978 * @description3979 * __Ex.:__3980<code javascript>3981LinkedIn.events.START.once(function(ev) {...});3982</code>3983 * @method once3984 * @path ctx.event.once3985 * @param {function(ctx.event)} func callback to be called on event reception3986 * @param {boolean|function()} [immediateCondition] if defined, function to be called immediately : if it returns a 'true' result, the 'func' callback is executed3987 * @param {Object} [context] context object to be called with the callback3988 * @param {number} [delay] optional delay to wait before calling the callback (default is 0)3989 * @param {boolean} [noStepReset] if 'true', and handler is set in a step, it is not reset on step exit3990 * @return {Object} an object to be provided to 'ctx.off()' to disable listening3991 */3992 this.once = function (func, immediateCondition, context, delay, noStepReset) {3993 return ctx.on(this, func, immediateCondition, context, true, delay, noStepReset);3994 };3995 /**3996 * Sends an event back to the source application or page3997 * @description3998 * __Ex.:__3999<code javascript>4000// *** source application ***4001// send a functional event to 'MyAppli' application4002var obj = { name: 'Smith', firstname: 'John' };4003MyAppli.notify(MyAppli.events.evSetId, obj);4004});4005// *** destination application ***4006// handles the event on 'MyAppli' application4007MyAppli.on({evSetId: function(ev) {4008// handle input data4009var data = ev.data;4010... = data.name;4011...4012// add output data4013data.result = ...4014// send answer to the source application4015ev.reply();4016}});4017// *** source application ***4018// handles the answer event on 'MyAppli' application4019MyAppli.on({evSetId: function(ev) {4020// handle answer here...4021var data = ev.data;4022... = data.result;4023}});4024</code>4025 * @method reply4026 * @path ctx.event.reply4027 * @param {Object} [data] optional data values4028 * @param {ctx.event} [newEvent] optional event to send to4029 * @return {string} result value4030 */4031 this.reply = function (data, newEvent) {4032 var desc = this.getObjectDescriptor();4033 if (data) {4034 if (typeof this.data !== 'object') {4035 this.data = new ctx.dataClass();4036 }4037 ctx.set(data, this.data);4038 }4039 var reqEvent = (newEvent && newEvent.name ? newEvent.name : (this.reqEventName ? this.reqEventName : this.name ));4040 var reqAppliName = (newEvent && newEvent.appliName ? newEvent.appliName : (this.reqAppliName ? this.reqAppliName : this.appliName ));4041 var reqAppliInst = (newEvent && newEvent.reqAppliInst >= 0 ? newEvent.reqAppliInst : (this.reqAppliInst >= 0 ? this.reqAppliInst : this.appliInst ));4042 // anti-loop checking4043 if ((reqEvent == this.name) && (reqAppliName == this.appliName) && ((this.reqAppliInst == -1) || (this.reqAppliInst == this.appliInst))) {4044 return '';4045 }4046 var strData = ctx.serialize(this.data, false, true);4047 return ctx.verbExec(desc, 'reply', 'NOTIFY', {4048 Event: reqEvent,4049 Appli: reqAppliName,4050 InstanceAppli: ((reqAppliInst == -1) ? undefined : reqAppliInst),4051 Data: strData,4052 EventResp: this.name4053 });4054 }4055 /**4056 * Serializes an event content4057 * @description4058 * __Ex.:__4059<code javascript>4060var txt = ev.serialize();4061</code>4062 * @method serialize4063 * @path ctx.event.serialize4064 * @param {boolean} [doEscape] if 'true', escapes all control characters ("\b" -> "\\b", "\"" -> "\\\"", "\\" -> "\\\\", ...)4065 * @param {boolean} [addPrefix] if 'true' and 'data' is an object, adds a prefix to automate unserialisation4066 * @return {string} serialized value4067 */4068 this.serialize = function (doEscape, addPrefix) {4069 //var ev = ctx.clone(this);4070 // make a shallow copy of the event, remove objects with circular references4071 var ev = {};4072 for (var id in this) {4073 if (!((id == 'parent') || (id == 'appli') || (id == 'page')))4074 ev[id] = this[id];4075 }4076 return ctx.serialize(this, doEscape, addPrefix);4077 };4078 /**4079 * Merges an object in the given event4080 * @description4081 * __Ex.:__4082<code javascript>4083ev.set(obj);4084</code>4085 * @method set4086 * @path ctx.event.set4087 * @param {Object} obj object to be merged4088 */4089 this.set = function (obj) {4090 return ctx.set(obj, this);4091 }4092 /**4093 * Sets a 'SETPENDING' action4094 * @description4095 * __Ex.:__4096<code javascript>4097MyHllApiAppli.on({ evLogin: function(ev) {4098if (MyHllApiAppli.nbInst == 1) {4099 // only virtual instance exists : connect session to create a real instance4100 MyHllApiAppli.PAGELOAD.connectPS(MyHllApiAppli.data.session);4101 MyHllApiAppli.data.isHllConnected = true;4102 ev.setpending();4103} else {4104 // *** real instance ***4105 // start scenario4106 MyHllApiAppli.scenarios.scLogin.start();4107}4108}});4109</code>4110 * @method setpending4111 * @path ctx.event.setpending4112 * @return {string} action result4113 */4114 this.setpending = function () {4115 var desc = this.getObjectDescriptor();4116 return ctx.verbExec(desc, 'setpending', 'SETPENDING', {4117 Event : this.name,4118 Data : ctx.serialize(this.data, false, true),4119 Item : this.itemName,4120 ReqAppli : this.reqAppliName,4121 ReqIdInstanceAppli : this.reqAppliInst,4122 EventResp : this.reqEventName,4123 ItemResp : this.reqItemName4124 });4125 }4126};4127/**4128* Class used to manage promise objects4129* @class ctx.promise4130* @path ctx.promise4131* @ignore4132* @param {function(*)} resolver function4133* @param {String} [label] optional string for labeling the promise.4134* @return {ctx.promiseClass} promise object4135*/4136ctx.promise = function (resolver, label) {4137 return new ctx.promiseClass(resolver); // create new4138};4139/**4140* Class used to implement promise objects4141* @class ctx.promiseClass4142* @path ctx.promiseClass4143* @constructor4144* @advanced4145* @param {function(*)} resolver function4146* @param {String} [label] optional string for labeling the promise.4147*/4148ctx.promiseClass = function (resolver, label) {4149 var _promise = this;4150 var _id = ctx.objectIndex ++;4151 var _label = label;4152 var _state = undefined; // FULFILLED || REJECTED ||4153 var _result = undefined;4154 var _subscribers = [];4155 var _catch = null;4156 _subscribers.push( {4157 done: resolver,4158 fail: undefined,4159 label: label4160 } );4161 /**4162 *4163 * @description4164 * __Ex.:__4165<code javascript>4166</code>4167 * @method all4168 * @path ctx.promiseClass.all4169 * @ignore4170 * @param {Array<ctx.promiseClass>} entries array of promises4171 * @param {String} [label] optional string for labeling the promise.4172 * @return {ctx.promiseClass} promise object4173 */4174 this.all = function (entries, label) {4175 //return new Enumerator(this, entries, true /* abort on reject */, label).promise;4176 return _promise;4177 }4178 /**4179 *4180 * @description4181 * __Ex.:__4182<code javascript>4183</code>4184 * @method catch4185 * @path ctx.promiseClass.catch4186 * @advanced4187 * @param {function(*)|undefined} onRejection rejection function4188 * @param {String} [label] optional string for labeling the promise.4189 * @return {ctx.promiseClass} promise object4190 */4191 this['catch'] = function (onRejection, label) {4192 return _promise.then(undefined, onRejection, label);4193// _catch = func;4194// return this;4195 }4196 /**4197 *4198 * @description4199 * __Ex.:__4200<code javascript>4201</code>4202 * @method finally4203 * @path ctx.promiseClass.finally4204 * @advanced4205 * @param {function(*)} callback callback function4206 * @param {String} [label] optional string for labeling the promise.4207 * @return {ctx.promiseClass} promise object4208 */4209 this['finally'] = function (callback, label) {4210 var constructor = _promise.constructor;4211 return _promise.then(function(value) {4212 var lastEvent = ((ctx.currentEvent && ctx.currentEvent.parent) ? ctx.currentEvent : ctx.lastEvent);4213 return constructor.resolve(callback(lastEvent)).then(function(){4214 return value;4215 });4216 }, function(reason) {4217 var lastEvent = ((ctx.currentEvent && ctx.currentEvent.parent) ? ctx.currentEvent : ctx.lastEvent);4218 return constructor.resolve(callback(lastEvent)).then(function(){4219 throw reason;4220 });4221 }, label);4222 }4223 /**4224 *4225 * @description4226 * __Ex.:__4227<code javascript>4228</code>4229 * @method reject4230 * @path ctx.promiseClass.reject4231 * @advanced4232 * @static4233 * @param {*} reason value that the returned promise will be rejected with.4234 * @param {String} [label] optional string for identifying the returned promise.4235 * @return {ctx.promiseClass} promise object4236 */4237 this.reject = function (reason, label) {4238 return _promise;4239 }4240 /**4241 *4242 * @description4243 * __Ex.:__4244<code javascript>4245</code>4246 * @method resolve4247 * @path ctx.promiseClass.resolve4248 * @advanced4249 * @param {*} value result value4250 * @return {ctx.promiseClass} promise object4251 */4252 this.resolve = function (value) {4253 var obj = _subscribers.shift();4254 if (obj && obj.done) {4255 var oldPromise = ctx.currentPromise;4256 var lastEvent = ((ctx.currentEvent && ctx.currentEvent.parent) ? ctx.currentEvent : ctx.lastEvent);4257 ctx.currentPromise = _promise;4258 var context;4259 if (this != _promise) { context = this; }4260 if ((!context) && ctx.currentSubscription) { context = ctx.currentSubscription.context; }4261 if ((!context) && lastEvent) {4262 if (lastEvent.page) {4263 context = lastEvent.page;4264 } else if (lastEvent.appli) {4265 context = lastEvent.appli;4266 }4267 }4268 obj.done.apply(context, [value])4269 ctx.currentPromise = oldPromise;4270 }4271 return _promise;4272 }4273 /**4274 *4275 * @description4276 * __Ex.:__4277<code javascript>4278</code>4279 * @method then4280 * @path ctx.promiseClass.then4281 * @advanced4282 * @param {function(*)|undefined} onFulfillment fulfill function4283 * @param {function(*)} [onRejection] reject function4284 * @param {String} [label] optional string for labeling the promise4285 * @return {ctx.promiseClass} promise object4286 */4287 this.then = function (onFulfillment, onRejection, label) {4288 _subscribers.push( {4289 done: onFulfillment,4290 fail: onRejection,4291 label: label4292 } );4293 return _promise;4294 }4295 // differed start4296 ctx.pendingFunctions.push(function () {4297 var lastEvent = ((ctx.currentEvent && ctx.currentEvent.parent) ? ctx.currentEvent : ctx.lastEvent);4298 _promise.resolve(lastEvent);4299 });4300 return _promise;4301}4302/**4303 * @ignore4304 * Mapper library4305 * @class ctx.mapper4306 * @path ctx.mapper4307 * @constructor4308 **/4309ctx.mapper = (function () {4310 /**4311 * This class is derived from 'object-mapper' code \\4312 * The MIT License (MIT)4313 * Copyright (c) 2012 Daniel L. VerWeire4314 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:4315 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.4316 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.4317 * @see https://github.com/wankdanker/node-object-mapper4318 * @ignore4319 */4320 var self =4321 /** @lends ctx.mapper */4322 {4323 /**4324 * @ignore4325 * Map a object to another using the passed map4326 * @path ctx.mapper.map4327 * @method map4328 * @param {*} fromObject source object4329 * @param {Object} toObject destination object, or array of properties to map (if 'propertyMap' is omitted)4330 * @param {Object} [propertyMap] array of properties to map4331 * @return {*}4332 */4333 map: function(fromObject, toObject, propertyMap) {4334 var propertyKeys;4335 var tObj = toObject || {};4336 var propMap = propertyMap;4337 if (typeof propMap === 'undefined') {4338 propMap = tObj;4339 tObj = undefined;4340 }4341 propMap = propMap || {};4342 propertyKeys = Object.keys(propMap);4343 return _map(fromObject, tObj, propMap, propertyKeys);4344 },4345 /**4346 * @ignore4347 * Gets a value with the key in the passed object4348 * @path ctx.mapper.get4349 * @method get4350 * @param {Object} fromObject source object4351 * @param {Object} fromKey source key4352 * @return {*}4353 */4354 get : function (fromObject, fromKey) {4355 var regDot = /\./g4356 , regFinishArray = /.+(\[\])/g4357 , keys4358 , key4359 , result4360 , lastValue4361 ;4362 keys = fromKey.split(regDot);4363 key = keys.splice(0, 1);4364 lastValue = fromKey.match(regFinishArray);4365 if(lastValue != null && lastValue[0] === fromKey){4366 fromKey = fromKey.slice(0,-2);4367 }else{4368 lastValue = null;4369 }4370 result = _getValue(fromObject, key[0], keys);4371 if (Array.isArray(result) && !lastValue) {4372 if (result.length) {4373 result = result.reduce(function (a, b) {4374 if (Array.isArray(a) && Array.isArray(b)) {4375 return a.concat(b);4376 } else if (Array.isArray(a)) {4377 a.push(b);4378 return a;4379 } else {4380 return [a, b];4381 }4382 });4383 }4384 if (!Array.isArray(result)) {4385 result = [result];4386 }4387 }4388 return result;4389 },4390 /**4391 * @ignore4392 * Sets a value withing the key in the passed object4393 * @path ctx.mapper.set4394 * @method set4395 * @param {Object} baseObject4396 * @param {Object} destinationKey4397 * @param {*} fromValue4398 * @return {*|Object}4399 */4400 set: function (baseObject, destinationKey, fromValue) {4401 var regDot = /\./g4402 , keys4403 , key4404 ;4405 keys = destinationKey.split(regDot);4406 key = keys.splice(0, 1);4407 return _setValue(baseObject, key[0], keys, fromValue);4408 }4409 };4410 /**4411 * Gets the value of key within passed object, considering if there is a array or object4412 * @param fromObject4413 * @param key4414 * @param keys4415 * @returns {*}4416 * @ignore4417 * @private4418 */4419 function _getValue(fromObject, key, keys) {4420 var regArray = /(\[\]|\[(.*)\])$/g4421 , match4422 , arrayIndex4423 , isValueArray = false4424 , result4425 ;4426 if (!fromObject) {4427 return;4428 }4429 match = regArray.exec(key);4430 if (match) {4431 key = key.replace(regArray, '');4432 isValueArray = (key !== '');4433 arrayIndex = match[2];4434 }4435 if (keys.length === 0) {4436 if (isValueArray) {4437 if (typeof arrayIndex === 'undefined') {4438 result = fromObject[key];4439 } else {4440 result = fromObject[key][arrayIndex];4441 }4442 } else if (Array.isArray(fromObject)) {4443 if (key === '') {4444 if (typeof arrayIndex === 'undefined') {4445 result = fromObject;4446 } else {4447 result = fromObject[arrayIndex];4448 }4449 } else {4450 result = fromObject.map(function (item) {4451 return item[key];4452 })4453 }4454 } else {4455 result = fromObject[key];4456 }4457 } else {4458 if (isValueArray) {4459 if (Array.isArray(fromObject[key])) {4460 if (typeof arrayIndex === 'undefined') {4461 result = fromObject[key].map(function (item) {4462 return _getValue(item, keys[0], keys.slice(1));4463 });4464 } else {4465 result = _getValue(fromObject[key][arrayIndex], keys[0], keys.slice(1));4466 }4467 } else {4468 if (typeof arrayIndex === 'undefined') {4469 result = _getValue(fromObject[key], keys[0], keys.slice(1));4470 } else {4471 result = _getValue(fromObject[key][arrayIndex], keys[0], keys.slice(1));4472 }4473 }4474 } else if (Array.isArray(fromObject)) {4475 if (key === '') {4476 if (typeof arrayIndex === 'undefined') {4477 result = _getValue(fromObject, keys[0], keys.slice(1));4478 } else {4479 result = _getValue(fromObject[arrayIndex], keys[0], keys.slice(1));4480 }4481 } else {4482 result = fromObject.map(function (item) {4483 result = _getValue(item, keys[0], keys.slice(1));4484 })4485 }4486 if (typeof arrayIndex === 'undefined') {4487 result = fromObject.map(function (item) {4488 return _getValue(item, keys[0], keys.slice(1));4489 });4490 } else {4491 result = _getValue(fromObject[arrayIndex], keys[0], keys.slice(1));4492 }4493 } else {4494 result = _getValue(fromObject[key], keys[0], keys.slice(1));4495 }4496 }4497 return result;4498 }4499 //module.exports = SetKeyValue;4500 /**4501 * Set the value within the passed object, considering if is a array or object set4502 * @param destinationObject4503 * @param key4504 * @param keys4505 * @param fromValue4506 * @return {*}4507 * @private4508 * @ignore4509 */4510 function _setValue(destinationObject, key, keys, fromValue) {4511 var regArray = /(\[\]|\[(.*)\])$/g4512 , regAppendArray = /(\[\]|\[(.*)\]\+)$/g4513 , regCanBeNull = /(\?)$/g4514 , match4515 , appendToArray4516 , canBeNull4517 , arrayIndex = 04518 , valueIndex4519 , isPropertyArray = false4520 , isValueArray = false4521 , value4522 ;4523 canBeNull = regCanBeNull.test(key);4524 if(canBeNull){4525 key = key.replace(regCanBeNull, '');4526 }4527 match = regArray.exec(key);4528 appendToArray = regAppendArray.exec(key);4529 if (match) {4530 isPropertyArray = true;4531 key = key.replace(regArray, '');4532 isValueArray = (key !== '');4533 }4534 if (appendToArray) {4535 match = appendToArray;4536 isPropertyArray = true;4537 isValueArray = (key !== '');4538 key = key.replace(regAppendArray, '');4539 }4540 if (_isEmpty(destinationObject)) {4541 if (isPropertyArray) {4542 arrayIndex = match[2] || 0;4543 if (isValueArray) {4544 destinationObject = {};4545 destinationObject[key] = [];4546 } else {4547 destinationObject = [];4548 }4549 } else {4550 destinationObject = {};4551 }4552 } else {4553 if (isPropertyArray) {4554 arrayIndex = match[2] || 0;4555 }4556 }4557 if (keys.length === 0) {4558 if(!canBeNull && (fromValue === null || fromValue === undefined)){4559 return destinationObject;4560 }4561 if (isValueArray) {4562 if (Array.isArray(destinationObject[key]) === false) {4563 destinationObject[key] = [];4564 }4565 if(appendToArray){4566 destinationObject[key].push(fromValue);4567 } else{4568 destinationObject[key][arrayIndex] = fromValue;4569 }4570 } else if (Array.isArray(destinationObject)) {4571 destinationObject[arrayIndex] = fromValue;4572 } else {4573 destinationObject[key] = fromValue;4574 }4575 } else {4576 if (isValueArray) {4577 if (Array.isArray(destinationObject[key]) === false) {4578 destinationObject[key] = [];4579 }4580 if (Array.isArray(fromValue) && _isNextArrayProperty(keys) === false) {4581 for (valueIndex = 0; valueIndex < fromValue.length; valueIndex++) {4582 value = fromValue[valueIndex];4583 destinationObject[key][arrayIndex + valueIndex] = _setValue(destinationObject[key][arrayIndex + valueIndex], keys[0], keys.slice(1), value);4584 }4585 } else {4586 destinationObject[key][arrayIndex] = _setValue(destinationObject[key][arrayIndex], keys[0], keys.slice(1), fromValue);4587 }4588 } else if (Array.isArray(destinationObject)) {4589 if (Array.isArray(fromValue)) {4590 for (valueIndex = 0; valueIndex < fromValue.length; valueIndex++) {4591 value = fromValue[valueIndex];4592 destinationObject[arrayIndex + valueIndex] = _setValue(destinationObject[arrayIndex + valueIndex], keys[0], keys.slice(1), value);4593 }4594 } else {4595 destinationObject[arrayIndex] = _setValue(destinationObject[arrayIndex], keys[0], keys.slice(1), fromValue);4596 }4597 } else {4598 destinationObject[key] = _setValue(destinationObject[key], keys[0], keys.slice(1), fromValue);4599 }4600 }4601 return destinationObject;4602 }4603 /**4604 * Check if next key is a array lookup4605 * @param keys4606 * @returns {boolean}4607 * @private4608 * @ignore4609 */4610 function _isNextArrayProperty(keys) {4611 var regArray = /(\[\]|\[(.*)\])$/g4612 ;4613 return regArray.test(keys[0]);4614 }4615 /**4616 * Check if passed object is empty, checking for object and array types4617 * @param object4618 * @returns {boolean}4619 * @private4620 * @ignore4621 */4622 function _isEmpty(object) {4623 var empty = false;4624 if (typeof object === 'undefined' || object === null) {4625 empty = true;4626 } else if (_isEmptyObject(object)) {4627 empty = true;4628 } else if (_isEmptyArray(object)) {4629 empty = true;4630 }4631 return empty;4632 }4633 /**4634 * Check if passed object is empty4635 * @param object4636 * @returns {boolean}4637 * @private4638 * @ignore4639 */4640 function _isEmptyObject(object) {4641 return typeof object === 'object'4642 && Array.isArray(object) === false4643 && Object.keys(object).length === 04644 ;4645 }4646 /**4647 * Check if passed array is empty or with empty values only4648 * @param object4649 * @returns {boolean}4650 * @private4651 * @ignore4652 */4653 function _isEmptyArray(object) {4654 return Array.isArray(object)4655 && (object.length === 04656 || object.join('').length === 0)4657 ;4658 }4659 /**4660 * Function that handle each key from map4661 * @param fromObject4662 * @param toObject4663 * @param propertyMap4664 * @param propertyKeys4665 * @returns {*}4666 * @private4667 * @ignore4668 */4669 function _map(fromObject, toObject, propertyMap, propertyKeys) {4670 var fromKey4671 , toKey4672 ;4673 if (propertyKeys.length) {4674 fromKey = propertyKeys.splice(0, 1)[0];4675 if (propertyMap.hasOwnProperty(fromKey)) {4676 toKey = propertyMap[fromKey];4677 toObject = _mapKey(fromObject, fromKey, toObject, toKey);4678 } else {4679 toObject = null;4680 }4681 return _map(fromObject, toObject, propertyMap, propertyKeys);4682 } else {4683 return toObject;4684 }4685 }4686 /**4687 * Function that calls get and set key values4688 * @param fromObject4689 * @param fromKey4690 * @param toObject4691 * @param toKey4692 * @private4693 * @ignore4694 */4695 function _mapKey(fromObject, fromKey, toObject, toKey) {4696 var fromValue = {};4697 var restToKeys4698 , _default = {}4699 , transform4700 ;4701 if (Array.isArray(toKey) && toKey.length) {4702 toKey = toKey.slice();4703 restToKeys = toKey.splice(1);4704 toKey = toKey[0];4705 }4706 if (toKey instanceof Object && Object.getPrototypeOf(toKey) === Object.prototype) {4707 _default = toKey['default'] || {};4708 transform = toKey.transform;4709 toKey = toKey.key;4710 }4711 if (Array.isArray(toKey)) {4712 transform = toKey[1];4713 _default = toKey[2] || {};4714 toKey = toKey[0];4715 }4716 if (typeof _default === 'function') {4717 _default = _default(fromObject, fromKey, toObject, toKey);4718 }4719 fromValue = self.get(fromObject, fromKey);4720 if (typeof fromValue === 'undefined' || fromValue === null) {4721 fromValue = _default;4722 }4723 if (typeof fromValue !== 'undefined' && typeof transform === 'function') {4724 fromValue = transform(fromValue, fromObject, toObject, fromKey, toKey);4725 }4726 if (typeof fromValue === 'undefined' || typeof toKey === 'undefined') {4727 return toObject;4728 }4729 fromValue = fromValue || {};4730 toObject = self.set(toObject, toKey, fromValue);4731 if (Array.isArray(restToKeys) && restToKeys.length) {4732 toObject = _mapKey(fromObject, fromKey, toObject, restToKeys);4733 }4734 return toObject;4735 }4736 return self;4737})();4738 /** [internal use]4739 * Amplify Core 1.1.24740 *4741 * Copyright 2011 - 2013 appendTo LLC. (http://appendto.com/team)4742 * Dual licensed under the MIT or GPL licenses.4743 * http://appendto.com/open-source-licenses4744 *4745 * http://amplifyjs.com4746 * @ignore4747 * @class ctx.amplify4748 * @path ctx.amplify4749 * @throws {Error}4750 * @constructor4751 */4752 ctx.amplify = (function () {4753 var self =4754 /** @lends ctx.amplify */4755 {4756 /** [internal use]4757 * Publishes a subscribed event4758 * @ignore4759 * @method publish4760 * @path ctx.amplify.publish4761 * @param {string} topic4762 * @param {ctx.event} event4763 * @return {number} the number of subscriptions for this event4764 */4765 publish : function (topic, event) {4766 if (typeof topic !== "string") {4767 throw new Error(e.error.InvalidArgument, "You must provide a valid topic to publish.");4768 }4769 var args = [],4770 topicSubscriptions,4771 sub,4772 length,4773 i = 0,4774 nbSubs = 0,4775 ret;4776 var subs = ctx.subscriptions;4777 if (!ctx.subscriptions[topic]) {4778 return 0;4779 }4780 topicSubscriptions = ctx.subscriptions[topic].slice();4781 //var bAllSubsAreSingle = true;4782 for (length = topicSubscriptions.length; i < length; i++) {4783 sub = topicSubscriptions[i];4784 var oldSub = ctx.currentSubscription;4785 ctx.currentSubscription = sub;4786 //args = slice.call(arguments, 1);4787 // copy current event as first argument for the callback4788 args.push(event.copy());4789 // add optional arguments for the callback4790 if (sub.argument)4791 args.push(sub.argument);4792 var context = sub.context;4793 if (!context) {4794 if (event.page) {4795 context = event.page;4796 } else if (event.appli) {4797 context = event.appli;4798 }4799 }4800 if (sub.active) {4801 ctx.currentStep = sub.step;4802 ctx.notifyState((sub.single ? 'once' : 'on'), topic, sub.id, 'run', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : ''));4803 if (sub.single) {4804 // trigger a single time : disable subscription4805 sub.active = false4806 //this.unsubscribe(topic, sub.context, sub.callback, true);4807 }4808 // ctx.subscriptions[topic].splice(i, 1);4809 //} else {4810 // bAllSubsAreSingle = false;4811 //}4812 // 25092015 experimental !! : make systematic asynchronous calls --> cancelled4813 //sub.delay = sub.delay || 1;4814 if (sub.delay) {4815 // call after delay4816 var timerIndex = ctx.objectIndex++;4817 // Name the timer for debugging4818 var strTimeoutName = 'delay(' + sub.delay + ')' ;4819 ctx.notifyState('once', strTimeoutName, timerIndex, 'set', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : ''));4820 var timerId = setTimeout(function(sub, context, args) { return function() {4821 ctx.notifyState('once', strTimeoutName, timerIndex, 'run', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : ''));4822 sub.timerId = 0;4823 var oldSub = ctx.currentSubscription;4824 var oldParentId = ctx.currentParentId;4825 ctx.currentSubscription = sub;4826 if (sub.step && sub.step.callFunction)4827 {4828 var oldStep = ctx.currentStep;4829 ctx.currentStep = sub.step;4830 ctx.currentParentId = sub.id;4831 // call the function in the context of the step4832 ret = sub.step.callFunction(sub.callback, context, args);4833 ctx.currentStep = oldStep;4834 } else {4835 // call without step context4836 ret = sub.callback.apply(context, args);4837 }4838 ctx.currentSubscription = oldSub;4839 ctx.currentParentId = oldParentId;4840 ctx.notifyState('once', strTimeoutName, timerIndex, 'reset', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : ''));4841 }; }(sub, context, args), sub.delay);4842 if (sub.step)4843 {4844 sub.step.timers[timerIndex] = timerId;4845 } else {4846 sub.timerId = timerId;4847 }4848 } else {4849 // call immediatly4850 var oldParentId = ctx.currentParentId;4851 ctx.currentParentId = sub.id;4852 if (sub.step && sub.step.callFunction)4853 {4854 // call the function in the context of the step4855 ret = sub.step.callFunction(sub.callback, context, args);4856 } else {4857 // call without step context4858 ret = sub.callback.apply(context, args);4859 }4860 ctx.currentParentId = oldParentId;4861 }4862 }4863 if (sub.single) {4864 // trigger a single time : remove subscription4865 this.unsubscribe(topic, sub.context, sub.callback);4866 //ctx.notifyState((sub.single ? 'once' : 'on'), topic, sub.id, 'reset', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : ''));4867 } else {4868 // permanent triggering : put it in 'set' state (if still active)4869 if (sub.active) {4870 ctx.notifyState('on', topic, sub.id, 'set', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : ''));4871 }4872 }4873 //ctx.currentStep = null;4874 ctx.currentSubscription = oldSub;4875 if (ret === false) {4876 break; // cancel loop4877 }4878 nbSubs ++;4879 }4880 return nbSubs;4881 },4882 /** [internal use]4883 * Registers a new event subscription4884 * @ignore4885 * @method subscribe4886 * @path ctx.amplify.subscribe4887 * @throws {Error}4888 * @param {string} topic4889 * @param {Object|function(ctx.event)} context or callback4890 * @param {function(ctx.event)|Object|string|number} [callback] callback or priority4891 * @param {number|string} [priority]4892 * @param {*} [argument]4893 * @param {boolean} [single]4894 * @param {ctx.stepClass} [step]4895 * @param {number} [delay] optional delay to wait before calling the callback (default is 0)4896 * @return {*} func4897 */4898 subscribe : function (topic, context, callback, priority, argument, single, step, delay) {4899 if (typeof topic !== "string") {4900 throw new Error(e.error.InvalidArgument, "You must provide a valid topic to create a subscription.");4901 }4902 if (arguments.length === 3 && typeof callback === "number") {4903 priority = callback;4904 callback = context;4905 context = null;4906 } else if (arguments.length === 2) {4907 callback = context;4908 context = null;4909 }4910 priority = priority || 10;4911 var topicIndex = 0,4912 topics = topic.split(/\s/),4913 topicLength = topics.length,4914 added;4915 for (; topicIndex < topicLength; topicIndex++) {4916 topic = topics[topicIndex];4917 added = false;4918 if (!ctx.subscriptions[topic]) {4919 ctx.subscriptions[topic] = [];4920 }4921 var i = ctx.subscriptions[topic].length - 1,4922 sub,4923 subscriptionInfo = {4924 name : topic,4925 id : ctx.objectIndex++,4926 active : true,4927 callback : callback,4928 context : context,4929 priority : priority,4930 single : single,4931 argument : argument,4932 step : step,4933 timerId : 0,4934 delay : delay4935 };4936 for (; i >= 0; i--) {4937 sub = ctx.subscriptions[topic][i];4938 if ((sub.callback.toString() === subscriptionInfo.callback.toString()) && (sub.context == subscriptionInfo.context) && (((sub.step && subscriptionInfo.step) ? (sub.step.id == subscriptionInfo.step.id) : true)))4939 {4940 // don't add several times the same topic/callback/context/step4941 added = true;4942 break;4943 }4944 if (sub.priority <= priority) {4945 ctx.subscriptions[topic].splice(i + 1, 0, subscriptionInfo);4946 added = true;4947 break;4948 }4949 }4950 if (!added) {4951 ctx.subscriptions[topic].unshift(subscriptionInfo);4952 ctx.notifyState((single ? 'once' : 'on'), topic, subscriptionInfo.id, 'set', '', (step ? step.name : ''), (step ? step.id : ''));4953 }4954 }4955 return callback;4956 },4957 /** [internal use]4958 * Unregisters an existing event subscription4959 * @method unsubscribe4960 * @path ctx.amplify.unsubscribe4961 * @throws {Error}4962 * @ignore4963 * @param {string} topic4964 * @param {Object|function(ctx.event)} context context or callback4965 * @param {function(ctx.event)|Object} [callback]4966 * @param {boolean} [noNotify]4967 * @return {boolean} result true | false4968 */4969 unsubscribe : function (topic, context, callback, noNotify) {4970 if (typeof topic !== "string") {4971 throw new Error(e.error.InvalidArgument, "You must provide a valid topic to remove a subscription.");4972 }4973 if (arguments.length === 2) {4974 callback = context;4975 context = null;4976 }4977 if (!ctx.subscriptions[topic]) {4978 return false;4979 }4980 var length = ctx.subscriptions[topic].length;4981 for (var i = 0; i < length; i++) {4982 var sub = ctx.subscriptions[topic][i];4983 if (sub.callback === callback) {4984 if (!context || sub.context === context) {4985 // Adjust counter and length for removed item4986 if (sub.timerId) { clearTimeout(sub.timerId); sub.timerId = 0; }4987 sub.active = false;4988 ctx.subscriptions[topic].splice(i, 1);4989 i--;4990 length--;4991 if (!noNotify) { ctx.notifyState((sub.single ? 'once' : 'on'), topic, sub.id, 'reset', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : '')); }4992 }4993 }4994 }4995 if (ctx.subscriptions[topic].length === 0 ) {4996 delete ctx.subscriptions[topic];4997 }4998 return true;4999 },5000 /** [internal use]5001 * Unregisters all existing event subscriptions relative to a given step5002 * @method unsubscribeStep5003 * @path ctx.amplify.unsubscribeStep5004 * @ignore5005 * @param {ctx.stepClass} step step to unregister5006 * @return {boolean} result true | false5007 */5008 unsubscribeStep : function (step) {5009 if (!step) {5010 return false;5011 }5012 // clear the active timers launched inside the step5013 for (var index in step.timers) {5014 if (step.timers[index]) {5015 clearTimeout(step.timers[index]);5016 delete step.timers[index];5017 ctx.notifyState('once', 'timer' + index, parseInt(index, 10), 'reset', '', (step ? step.name : ''), (step ? step.id : -1));5018 }5019 }5020 for (var topic in ctx.subscriptions) {5021 var length = ctx.subscriptions[topic].length;5022 for (var i = 0; i < length; i++) {5023 var sub = ctx.subscriptions[topic][i];5024 if (sub && (sub.step === step)) {5025 // Adjust counter and length for removed item5026 if (sub.timerId) {5027 clearTimeout(sub.timerId);5028 sub.timerId = 0;5029 }5030 sub.active = false;5031 ctx.subscriptions[topic].splice(i, 1);5032 i--;5033 length--;5034 ctx.notifyState((sub.single ? 'once' : 'on'), topic, sub.id, 'reset', '', (sub.step ? sub.step.name : ''), (sub.step ? sub.step.id : ''));5035 }5036 }5037 if (ctx.subscriptions[topic].length === 0 ) {5038 delete ctx.subscriptions[topic];5039 }5040 };5041 return true;5042 }5043 }5044 return self;5045 }());5046/** Project options and settings\\5047*5048* ''ctx.options'' contains the options for the SDK : a set of data pre-filled by Interactive at startup: versions, project, user, machine, ...5049* @path ctx.options5050* @class ctx.options5051*/5052ctx.options = {5053 /** Anonymous mode (hides parameters in traces for confidentiality)5054 * @property {boolean} anonymous5055 * @path ctx.options.anonymous */ anonymous : false,5056 /** Auto-test mode5057 * @property {boolean} autoTest5058 * @path ctx.options.autoTest */ autoTest : false,5059 /** Break on exception5060 * @property {boolean} breakException5061 * @path ctx.options.breakException */ breakException : false,5062 /** User canonical name5063 * @property {string} canonicalName5064 * @readonly5065 * @path ctx.options.canonicalName */ canonicalName : '',5066 /** Machine name5067 * @property {string} computerName5068 * @readonly5069 * @path ctx.options.computerName */ computerName : '',5070 /** Demo mode enabled/disabled5071 * @property {boolean} demoMode5072 * @path ctx.options.demoMode */ demoMode: false,5073 /** timer duration (ms) for demo mode5074 * @property {number} demoTimer5075 * @path ctx.options.demoTimer */ demoTimer: 0,5076 /** User display name5077 * @property {string} displayName5078 * @readonly5079 * @path ctx.options.displayName */ displayName : '',5080 /** Project environment (development, qualification, production, ...)5081 * @path ctx.options.env5082 * @property {string} env */ env : e.env.prod,5083 /** Javascript antiloop mechanism (ms): minimum value is 10 000 ms, default is 300 000 ms (5 min)5084 * @property {boolean} executionTimeout5085 * @path ctx.options.executionTimeout */ executionTimeout: 300000,5086 /** Language framework version5087 * @property {string} frameworkVersion5088 * @readonly5089 * @path ctx.options.frameworkVersion */ frameworkVersion: '',5090 /** User full login (including dommain)5091 * @property {string} fullUserName5092 * @readonly5093 * @path ctx.options.fullUserName */ fullUserName : '',5094 /** User qualified domain name5095 * @property {string} fullyQualifiedDN5096 * @readonly5097 * @path ctx.options.fullyQualifiedDN */ fullyQualifiedDN : '',5098 /** highlight color5099 * @property {number} highlightColor5100 * @path ctx.options.highlightColor */ highlightColor: ctx.rgb(0xff, 0, 0), // red5101 /** Debug mode enabled5102 * @path ctx.options.isDebug5103 * @property {boolean} isDebug */ isDebug : false,5104 licence: {5105 /** Licence identifier5106 * @property {string} licence.id5107 * @readonly5108 * @path ctx.options.licence.id */ id: '',5109 /** Licence name5110 * @property {string} licence.name5111 * @readonly5112 * @path ctx.options.licence.name */ name: '',5113 /** Licence serial number5114 * @property {string} licence.id5115 * @readonly5116 * @path ctx.options.licence.serial */ serial: ''5117 },5118 studioLicence: {5119 /** Licence identifier5120 * @property {string} licence.id5121 * @readonly5122 * @path ctx.options.studioLicence.id */ id: '',5123 /** Licence name5124 * @property {string} licence.name5125 * @readonly5126 * @path ctx.options.studioLicence.name */ name: '',5127 /** Licence serial number5128 * @property {string} licence.id5129 * @readonly5130 * @path ctx.options.studioLicence.serial */ serial: ''5131 },5132 path: {5133 /** Folder containing Interactive binaries5134 * @property {string} path.exec5135 * @readonly5136 * @path ctx.options.path.exec */ exec: '',5137 /** Folder containing project files (alias for 'ctx.options.path.local')5138 * @property {string} path.bin5139 * @readonly5140 * @ignore5141 * @path ctx.options.path.bin */ bin: '',5142 /** Folder containing project files5143 * @property {string} path.local5144 * @readonly5145 * @path ctx.options.path.local */ local: '',5146 /** Folder containing log and work files5147 * @property {string} path.log5148 * @readonly5149 * @path ctx.options.path.log */ log: '',5150 /** Folder containing resource files (bitmaps, ...)5151 * @property {string} path.resources5152 * @readonly5153 * @path ctx.options.path.resources */ resources: '',5154 /** Folder containing server project files5155 * @property {string} path.server5156 * @readonly5157 * @path ctx.options.path.server */ server: ''5158 },5159 /** JScript engine version5160 * @property {Object} JScriptVersion5161 * @readonly5162 * @path ctx.options.JScriptVersion */ JScriptVersion: '',5163 /** options from command line5164 * @property {Object} optionFiles5165 * @readonly5166 * @path ctx.options.optionFiles */ optionFiles: [],5167 /** Product version5168 * @property {string} productVersion5169 * @readonly5170 * @path ctx.options.productVersion */ productVersion : '',5171 /** Array of component versions5172 * @property {Object} productVersions5173 * @readonly5174 * @path ctx.options.productVersions */ productVersions: [],5175 /** Server version5176 * @property {string} serverVersion5177 * @readonly5178 * @path ctx.options.serverVersion */ serverVersion : '',5179 /** Client name5180 * @property {string} projectClient5181 * @readonly5182 * @path ctx.options.projectClient */ projectClient : '',5183 /** Project free comment5184 * @property {string} projectComment5185 * @readonly5186 * @path ctx.options.projectComment */ projectComment : '',5187 /** Project date5188 * @property {string} projectDate5189 * @readonly5190 * @path ctx.options.projectDate */ projectDate : '',5191 /** Project icon5192 * @property {string} projectIcon5193 * @path ctx.options.projectIcon */ projectIcon : '',5194 /** Project description5195 * @property {string} projectLabel5196 * @readonly5197 * @path ctx.options.projectLabel */ projectLabel : '',5198 /** Project name5199 * @property {string} projectName5200 * @readonly5201 * @path ctx.options.projectName */ projectName : '',5202 /** Project Uid5203 * @property {string} projectUid5204 * @readonly5205 * @path ctx.options.projectUid */ projectUid : '',5206 /** Project version5207 * @property {string} projectVersion5208 * @readonly5209 * @path ctx.options.projectVersion */ projectVersion : '',5210 /** settings container5211 * @path ctx.options.settings5212 * @property {ctx.dataClass} settings */ settings : null,5213 /** simulation mode5214 * @property {boolean} simulationMode5215 * @path ctx.options.simulationMode */ simulationMode: false,5216 /** shutdown confirmation5217 * @property {boolean} shutdownConfirmation5218 * @path ctx.options.shutdownConfirmation */ shutdownConfirmation: true,5219 /** Scenario timeouts disabled (for debugging purpose)5220 * @path ctx.options.timeoutDisabled5221 * @property {boolean} timeoutDisabled */ timeoutDisabled : false,5222 /** Unattended mode : remove all confirmation popups5223 * @path ctx.options.unattended5224 * @property {boolean} unattended */ unattended : false,5225 /** Display a confirmation popup before restarting Contextor5226 * @path ctx.options.restartConfirmation5227 * @property {boolean} restartConfirmation */ restartConfirmation : false,5228 /** Start Contextor Interactive when opening session5229 * @path ctx.options.startAtLogon5230 * @property {boolean} startAtLogon */ startAtLogon : undefined,5231 /** Display a confirmation popup before restarting Contextor5232 * @ignore (deprecated)5233 * @path ctx.options.updateConfirmation5234 * @property {boolean} updateConfirmation */ updateConfirmation : false,5235 trace : {5236 /** activate low level traces for actions5237 * @path ctx.options.trace.actions5238 * @advanced5239 * @property {boolean} trace.actions */ actions : false,5240 /** activate low level traces for actions (verbose)5241 * @path ctx.options.trace.actionsFull5242 * @advanced5243 * @property {boolean} trace.actionsFull */ actionsFull : false,5244 /** activate advanced low level traces5245 * @path ctx.options.trace.advanced5246 * @advanced5247 * @property {boolean} trace.advanced */ advanced : false,5248 /**5249 * @path ctx.options.trace.alternativeTraceFile5250 * @ignore5251 * @property {string} trace.alternativeTraceFile */ alternativeTraceFile : '',5252 /** enable auto-recording5253 * @path ctx.options.trace.autoRecording5254 * @property {boolean} trace.autoRecording */ autoRecording : false,5255 /** result for auto-recording5256 * @path ctx.options.trace.autoRecordingCode5257 * @ignore5258 * @property {e.error} trace.autoRecordingCode */ autoRecordingCode : e.error.OK,5259 /** auto-recording status5260 * @path ctx.options.trace.autoRecordingStarted5261 * @ignore5262 * @property {boolean} trace.autoRecordingStarted */ autoRecordingStarted : false,5263 /** activate low level traces for context5264 * @path ctx.options.trace.context5265 * @property {boolean} trace.context */ context : false,5266 /** display the Debugger v2 (old version)5267 * @path ctx.options.trace.debuggerV25268 * @property {boolean} trace.debuggerV2 */ debuggerV2 : false,5269 /** activate low level traces for errors5270 * @path ctx.options.trace.errors5271 * @property {boolean} trace.errors */ errors : false,5272 /** activate low level traces for events5273 * @path ctx.options.trace.events5274 * @property {boolean} trace.events */ events : false,5275 /** activate low level traces for extended connectors5276 * @path ctx.options.trace.extendPilots5277 * @property {boolean} trace.extendPilots */ extendPilots : false,5278 /** activate framework traces notifications to the Studio5279 * @path ctx.options.trace.frameworkNotify5280 * @ignore5281 * @property {boolean} trace.frameworkNotify */ frameworkNotify : false,5282 /** activate framework traces to generate trace files (.PSCL)5283 * @path ctx.options.trace.frameworkTraces5284 * @ignore5285 * @deprecated Rather use ctx.options.trace.recording5286 * @property {boolean} trace.frameworkTraces */ frameworkTraces : false,5287 /** activate framework traces to generate trace files (.PSCL)5288 * @path ctx.options.trace.recording5289 * @property {boolean} trace.recording */ recording : false,5290 /** activate low level traces for message boxes5291 * @path ctx.options.trace.messageBoxes5292 * @property {boolean} trace.messageBoxes */ messageBoxes : false,5293 /** activate low level traces for pages5294 * @path ctx.options.trace.objects5295 * @property {boolean} trace.objects */ objects : false,5296 /** activate screenshot generation with traces5297 * @path ctx.options.trace.screenshotTraces5298 * @property {boolean} trace.screenshotTraces */ screenshotTraces : false,5299 /** activate low level traces for Windows5300 * @path ctx.options.trace.windowsEvents5301 * @property {boolean} trace.windowsEvents */ windowsEvents : false5302 },5303 traceArchive: {5304 /** max archive duration (number of days)5305 * @property {boolean} traceArchive.maxDuration5306 * @path ctx.options.traceArchive.maxDuration */ maxDuration: 5, // 5 days max5307 /** max archive count (number of folder or ZIP files)5308 * @property {boolean} traceArchive.maxCount5309 * @path ctx.options.traceArchive.maxCount */ maxCount: 10 // 10 archives max5310 },5311 /** Folder containing traces5312 * @property {string} traceFolder5313 * @path ctx.options.traceFolder */ traceFolder : '',5314 /** Folder containing traces for recording5315 * @property {string} traceFolder5316 * @path ctx.options.traceFolder */ traceFolderRecording : '',5317 /** Trace level (global trace level for the framework)5318 * @property {e.trace.level} traceLevel5319 * @path ctx.options.traceLevel */ traceLevel: e.trace.level.None,5320 /** Timestamp of the trace folder creation5321 * @property {string} traceTimestamp5322 * @path ctx.options.traceTimestamp */ traceTimestamp : '',5323 /** User login5324 * @property {string} userName5325 * @path ctx.options.userName */ userName : '',5326 /**5327 * Reads an option5328 * @method read5329 * @path ctx.options.read5330 * @param {string} module to be updated (part of 'ctx.options')5331 * @param {string} option to be updated (part of 'ctx.options[module]')5332 * @return {*} read value5333 */5334 read: function (module, option) {5335 ctx.notifyAction('ctx.options.read');5336 var node = (module ? ctx.options[module] : ctx.options);5337 if (node) {5338 // read in registry5339 if ('string' === typeof module) module = module.replace(/[.]/g, '\\'); else module = '';5340 var root = ctx.registry.getRoot(module, option);5341 var value = ctx.registry.get(root);5342 if ((node[option] !== undefined) && (value !== undefined)) {5343 node[option] = value;5344 }5345 return node[option];5346 }5347 },5348 /**5349 * Updates an option5350 * @method save5351 * @path ctx.options.save5352 * @param {string} module to be updated (part of 'ctx.options')5353 * @param {string} option to be updated (part of 'ctx.options[module]')5354 * @param {*} [state] self test mode status : true|false|undefined (if undefined, status is toggled)5355 * @return {boolean} true if value was changed5356 */5357 save: function (module, option, state) {5358 ctx.notifyAction('ctx.options.save');5359 var node = (module ? ctx.options[module] : ctx.options);5360 if (node) {5361 var value = node[option];5362 if ((typeof value === 'boolean') && (state === undefined)) {5363 node[option] = !node[option];5364 } else {5365 node[option] = state;5366 }5367 if (node[option] !== value) {5368 // save in registry5369 if ('string' === typeof module) module = module.replace(/[.]/g, '\\'); else module = '';5370 var root = ctx.registry.getRoot(module, option);5371 ctx.registry.set(root, node[option]);5372 return true;5373 }5374 }5375 return false;5376 }5377};5378/**5379* __Ex.:__5380*5381<code javascript>5382ctx.options :5383{5384 // pre-defined data5385 currentURL: "D:\\Projects\\Tools\\samplesV3\\demoLanguageV3\\bin",5386 currentDir: "D:\\Projects\\Tools\\samplesV3\\demoLanguageV3\\log",5387 serverURL: "D:\\Projects\\Tools\\samplesV3\\demoLanguageV3\\server",5388 resourceURL: "D:\\Projects\\Tools\\samplesV3\\demoLanguageV3\\bin",5389 execDir: "C:\\Program Files (x86)\\SAP\...",5390 frameworkVersion: "3.0.17",5391 productVersion: "3.0.5.3",5392 projectVersion: "1.12",5393 projectClient: "R and D",5394 projectName: "demoLanguageV3",5395 projectDate: "26/05/2015",5396 projectLabel: "Language v3 Demo",5397 projectComment: "Provides a set of demonstration cases based on language v3",5398 traces {5399 ...5400 }5401 ...5402}5403</code>5404*5405*/5406/**5407 * Module for resource management5408 * @class ctx.resources5409 * @path ctx.resources5410 * @constructor5411 */5412ctx.resources = (function() {5413 //var _dom = undefined;5414 var _map = [];5415 var _dom = undefined;5416 var self =5417 /** @lends ctx.resources */5418 {5419 /**5420 * Clears the content of the clipboard5421 * @description5422 * __Ex.:__5423<code javascript>5424ctx.resources.clear();5425</code>5426 * @method clear5427 * @ignore5428 * @path ctx.resources.clear5429 */5430 clear : function(type) {5431 for (var id in self.data) {5432 }5433 },5434 /**5435 * Loads an Html file, replaces image files with base 64 string5436 * @description5437 * __Ex.:__5438<code javascript>5439</code>5440 * @method loadHtml5441 * @path ctx.resources.loadHtml5442 * @param {string} filePath Html file to be loaded5443 * @return {string} file content5444 */5445 loadHtml: function(filePath) {5446 var filename = filePath;5447 if (filename && (!ctx.fso.isPathAbsolute(filename))) {5448 if ((!filename.startsWith('/')) && (!filename.startsWith('\\')))5449 filename = '\\' + filename;5450 filename = ctx.options.path.resources + filename;5451 }5452 var htmlCode = ctx.fso.file.read(filename);5453 htmlCode = htmlCode.replace(/[\n\t\r]/gi, '');5454 var rootPath = filename.substring(0, Math.max(filename.lastIndexOf("/"), filename.lastIndexOf("\\")));5455 var posEnd = -1;5456 var posBeg = -1;5457 var loop = true;5458 var image = '';5459 var code;5460 while (loop) {5461 image = '';5462 posEnd = htmlCode.indexOf('.png"', posEnd); // todo : manage all image types, manage ' and "5463 if (posEnd > 0) {5464 posBeg = htmlCode.lastIndexOf('"', posEnd);5465 if (posBeg > 0) {5466 image = htmlCode.substring(posBeg + 1, posEnd + 4);5467 image = self.loadImageAsBase64(image, rootPath);5468 code = htmlCode;5469 htmlCode = code.substring(0, posBeg + 1) + image + code.substring(posEnd + 3);5470 posEnd += 5;5471 }5472 } else {5473 loop = false;5474 }5475 }5476 return htmlCode;5477 },5478 /**5479 * Loads an image file and converts it to a base 64 string5480 * @description5481 * __Ex.:__5482<code javascript>5483var icon = loadImageAsBase64("bmp\\theIcon.png", ctx.options.path.resources);5484</code>5485 * @method loadImageAsBase645486 * @path ctx.resources.loadImageAsBase645487 * @param {string} filePath image filename5488 * @param {string} [rootPath] optional root path (if filePath is a relative path)5489 * @return {string} image as a base 64 string5490 */5491 loadImageAsBase64: function (filePath, rootPath) {5492 var filename = filePath;5493 if (filePath && (!ctx.fso.isPathAbsolute(filePath))) {5494 if ((!filename.startsWith('/')) && (!filename.startsWith('\\')))5495 filename = '\\' + filename;5496 rootPath = rootPath || ctx.options.path.resources;5497 filename = rootPath + filename;5498 }5499 try {5500 var bytes = ctx.fso.file.read(filename, e.file.encoding.Binary);5501 //_dom = _dom || new ActiveXObject('Microsoft.XMLDOM');5502 var _dom = new ActiveXObject('Microsoft.XMLDOM');5503 var elem = _dom.createElement('tmpCtxt');5504 elem.dataType = e.ajax.content.base64;5505 elem.nodeTypedValue = bytes;5506 var res = 'data:image/png;base64,' + elem.text.replace(/[^A-Z\d+=\/]/gi, '');5507 return res;5508 } catch (ex) {5509 ctx.log('ctx.resources.loadImageAsBase64: could not load \'' + filePath + '\'', e.logIconType.Warning);5510 }5511 return filePath;5512 }5513 };5514 return self;5515})();5516 /**5517 * Function used to implement page and item actions5518 * @description5519 * __Ex.:__5520 * <code javascript>5521 * return ctx.action(desc, 'set', 'SETVALUE', 'John');5522 * </code>5523 * @method action5524 * @path ctx.action5525 * @throws {Error}5526 * @ignore5527 * @param {ctx.descriptor} desc object descriptor (application, page, item) (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])5528 * @param {string} name action name5529 * @param {string} language framework language verb5530 * @param {string|number|Object} [data] parameter(s) associated with the object5531 * @param {string} [prefix] optional prefix used to qualify action5532 * @param {string} [minVersion] minimum engine version required for the action5533 * @return {string} result value5534 * @suppress {es5Strict } warning 'arguments.callee'5535 */5536 ctx.action = function (desc, language, name, data, prefix, minVersion) {5537 var res = '';5538 var params = undefined;5539 if (ctx.engineStarted) {5540 data = ctx.serialize(data, false, false);5541 prefix = prefix || '';5542 var itemName = (prefix ? prefix + desc.itemFullName : desc.itemFullName) || '';5543 try {5544 params = (arguments.callee.caller.arguments ? Array.prototype.slice.call(arguments.callee.caller.arguments) : undefined);5545 try {5546 if (ctx.options.demoTimer > 0) {5547 if (desc.item && desc.item.highlight) {5548 // demo mode : highlight item with a synchronous tempo5549 desc.item.highlight(ctx.options.demoTimer, true, false);5550 } else if (desc.page && desc.page.highlight) {5551 // demo mode : highlight page with a synchronous tempo5552 desc.page.highlight(ctx.options.demoTimer, true, false);5553 }5554 }5555 } catch (ex) { }5556 if (minVersion && ctx.compareVersion(minVersion) < 0) {5557 ctx.notifyAction(language, res, desc, name, params);5558 ctx.log(desc.appliName + '.' + desc.pageName + (itemName ? ('.' + itemName) : '') + '.' + language + ': requires minimum version ' + minVersion, e.logIconType.Warning);5559 return res;5560 }5561 if (desc.appliInst < 0) {5562 ctx.log(desc.appliName + '.' + desc.pageName + (itemName ? ('.' + itemName) : '') + '.' + language + ': there is no running instance', e.logIconType.Warning);5563 }5564 if (ctx.actionFunction[desc.nature])5565 res = ctx.actionFunction[desc.nature](name, desc.appliName, desc.pageName, itemName, 0, data, desc.appliInst, desc.pageInst, desc.itemInst);5566 else5567 res = ctx.wkMng.CtxtAction(name, desc.appliName, desc.pageName, itemName, 0, data, desc.appliInst, desc.pageInst, desc.itemInst);5568 ctx.notifyAction(language, res, desc, name, params);5569 if ((!language) || (!name)) {5570 throw new Error(e.error.Fail, "ctx.action : action undefined" );5571 }5572 } catch (ex) {5573 ctx.notifyAction(language, res, desc, name, params);5574 throw new Error(e.error.Fail, desc.appliName + '.' + desc.pageName + (itemName ? ('.' + itemName) : '') + '.' + language + ': ' + ex.message );5575 }5576 }5577 return res;5578 };5579 /**5580 * Function used to implement page and item actions5581 * @description5582 * __Ex.:__5583<code javascript>5584return ctx.actionApp(desc, 'SETTEXT', 'The title');5585</code>5586 * @method actionApp5587 * @ignore5588 * @path ctx.actionApp5589 * @param {ctx.descriptor} desc object descriptor (application, page, item) (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])5590 * @param {string} language framework language verb5591 * @param {string} name action name5592 * @param {string|number|Object} [P1] parameter 15593 * @param {string|number|Object} [P2] parameter 25594 * @param {string|number|Object} [P3] parameter 35595 * @param {string|number|Object} [P4] parameter 45596 * @param {string|number|Object} [P5] parameter 55597 * @param {string} [minVersion] minimum engine version required for the action5598 * @return {string} result value5599 * @suppress {es5Strict } warning 'arguments.callee'5600 */5601 ctx.actionApp = function (desc, language, name, P1, P2, P3, P4, P5, minVersion) {5602 var res = '';5603 var params = '';5604 if (ctx.engineStarted) {5605 /** @type {string} */ var sP1 = ctx.serialize(P1, false, false);5606 /** @type {string} */ var sP2 = ctx.serialize(P2, false, false);5607 /** @type {string} */ var sP3 = ctx.serialize(P3, false, false);5608 /** @type {string} */ var sP4 = ctx.serialize(P4, false, false);5609 /** @type {string} */ var sP5 = ctx.serialize(P5, false, false);5610 try {5611 params = (arguments.callee.caller.arguments ? Array.prototype.slice.call(arguments.callee.caller.arguments) : undefined);5612 try {5613 if ((ctx.options.demoTimer > 0) && (name != 'GETRECT')) {5614 if (desc.item && desc.item.highlight) {5615 // demo mode : highlight item with a synchronous tempo5616 desc.item.highlight(ctx.options.demoTimer, true, false);5617 } else if (desc.page && desc.page.highlight) {5618 // demo mode : highlight page with a synchronous tempo5619 desc.page.highlight(ctx.options.demoTimer, true, false);5620 }5621 }5622 } catch (ex) { }5623 if (minVersion && ctx.compareVersion(minVersion) < 0) {5624 ctx.notifyAction(language, res, desc, name, params);5625 ctx.log(desc.appliName + '.' + desc.pageName + '.' + language + ': requires minimum version ' + minVersion, e.logIconType.Warning);5626 return res;5627 }5628 if (desc.appliInst < 0) {5629 ctx.log(desc.appliName + '.' + desc.pageName + '.' + language + ': there is no running instance', e.logIconType.Warning);5630 }5631 if (ctx.actionAppFunction[desc.nature])5632 res = ctx.actionAppFunction[desc.nature](name, desc.appliName, desc.pageName, sP1, sP2, sP3, sP4, sP5, desc.appliInst, desc.pageInst, desc.itemInst);5633 else5634 res = ctx.wkMng.CtxtActionApp(name, desc.appliName, desc.pageName, sP1, sP2, sP3, sP4, sP5, desc.appliInst, desc.pageInst, desc.itemInst);5635 if ((!language) || (!name)) {5636 throw new Error(e.error.Fail, "ctx.actionApp : action undefined" );5637 } else {5638 ctx.notifyAction(language, res, desc, name, params);5639 }5640 } catch (ex) {5641 ctx.notifyAction(language, res, desc, name, params);5642 throw new Error(e.error.Fail, desc.appliName + '.' + desc.pageName + '.' + language + ': '+ ex.message );5643 }5644 }5645 return res;5646 };5647 /**5648 * Function used to implement global actions5649 * @description5650 * __Ex.:__5651<code javascript>5652return ctx.verbExec(desc, 'regHotKey', 'REGHOTKEY', {5653 Value: shortcut,5654 Proc: event.appliName,5655 Event: event.name5656});5657</code>5658 * @method verbExec5659 * @path ctx.verbExec5660 * @throws {Error}5661 * @ignore5662 * @param {ctx.descriptor} desc object descriptor (application, page, item) (see [[lib:ctx:ctx.core#class_ctxdescriptor|ctx.descriptor]])5663 * @param {string} name action name5664 * @param {string} language framework language verb5665 * @param {Object} [params] parameters5666 * @param {string} [subcommand]5667 * @param {boolean} [pageReset] if true, reset page name and instance (false by default)5668 * @param {string} [minVersion] minimum engine version required for the action5669 * @return {string} result value5670 * @suppress {es5Strict } warning 'arguments.callee'5671 */5672 ctx.verbExec = function (desc, language, name, params, subcommand, pageReset, minVersion) {5673 desc = desc || ctx.getDescriptor();5674 var res = '';5675 var params2 = '';5676 if (ctx.engineStarted) {5677 try {5678 params2 = (arguments.callee.caller.arguments ? Array.prototype.slice.call(arguments.callee.caller.arguments) : undefined);5679 if ((!language) || (!name)) {5680 throw new Error(e.error.Fail, "ctx.verbExec : action undefined" );5681 }5682 var noAppli = false;5683 if (!desc.appliName) {5684 noAppli = true;5685 GLOBAL.getObjectDescriptor(desc);5686 }5687 if (minVersion && ctx.compareVersion(minVersion) < 0) {5688 ctx.notifyAction(language, res, desc, name, params2);5689 ctx.log('ctx.verbExec \'' + language + '\' : requires minimum version ' + minVersion, e.logIconType.Warning);5690 return res;5691 }5692 var cmd = ctx.getXMLSyntax(name, params, subcommand);5693 if (pageReset) {5694 // reset page name before calling 'verbExec' (for instance, 'EXIST' is not a 'page' verb, but an 'application' verb)5695 desc.pageName = '';5696 desc.pageInst = -1;5697 }5698 if (desc.appliInst < 0) {5699 ctx.log('ctx.verbExec \'' + language + '\' : there is no running instance ', e.logIconType.Warning);5700 }5701 res = ctx.wkMng.CtxtVerbExec(cmd, desc.appliName, desc.pageName, desc.appliInst, desc.pageInst);5702 if(noAppli) {5703 desc.appliName = 'ctx';5704 desc.appliInst = -1;5705 }5706 ctx.notifyAction(language, res, desc, name, params2);5707 } catch (ex) {5708 ctx.notifyAction(language, res, desc, name, params2);5709 throw new Error(e.error.Fail, 'ctx.verbExec \'' + language + '\' : ' + ex.name + ' ' + ex.message );5710 }5711 }5712 return res;5713 };5714ctx.execMethod = function (desc, method, params) {5715 var param ='';5716 var args = Array.prototype.slice.call(arguments);5717 for (var i=2; i<args.length; ++i) {5718 var a = args[i];5719 if (i > 2) param +='|';5720 param += typeof a ==="string" ? a.replace("^", "^^").replace("|", "^|") : a;5721 }5722 return ctx.actionApp(desc, 'execMethod', 'EXECMETHOD', method, desc.itemFullName, param, "", "");5723}5724ctx.onScriptTimeOut = function(appliName, pageName, itemName, itemIndex, event, data, appliInst, pageInst, itemInst, reqAppliName, reqEventName, reqItemName, reqAppliInst) {5725 ctx.log('Execution timeout in event: ' + appliName + '.' + pageName + (itemName ? '.' + itemName : '') + ':' + event, e.logIconType.Error);5726};5727// ******************************5728// *** Event handler callback ***5729// ******************************5730/**5731* Main entry callback to dispatch events from WkMng5732* @method onEvent5733* @path ctx.onEvent5734* @ignore5735* @param {string} appliName application or process name5736* @param {string} pageName page name5737* @param {string} itemName item name5738* @param {number} itemIndex item index5739* @param {string} event event name5740* @param {*} data5741* @param {number} appliInst application or process instance5742* @param {number} pageInst page instance5743* @param {number} itemInst item instance5744* @param {string} reqAppliName source application or process name5745* @param {string} reqEventName source event name5746* @param {string} reqItemName source item name5747* @param {number} reqAppliInst source application or process instance5748* @return {boolean} result5749*/5750ctx.onEvent = function (appliName, pageName, itemName, itemIndex, event, data, appliInst, pageInst, itemInst, reqAppliName, reqEventName, reqItemName, reqAppliInst) {5751 var res = false;5752 if ((!appliName) && (!event))5753 return true; // test at startup to detect framework5754 if (event == '_BREAK_EXCEPTION_') {5755 ctx.options.breakException = (data == 'Y' ? true : false);5756 return true;5757 }5758 if ((event == 'VERSION') || (event == '_VERSION_')) {5759 ctx.updateProductVersion();5760 return true;5761 }5762 // before GLOBAL:START or after GLOBAL:END, don't manage events5763 if (!ctx.engineStarted) {5764 if ((appliName == GLOBAL.name) && (event == e.event.application.START)) {5765 ctx.onEnginePrestart();5766 }5767 }5768 if (!ctx.eventTriggered) {5769 // differ GLOBAL START and INIT5770 if ((appliName == GLOBAL.name)) {5771 ctx.pendingEvents.push([appliName, pageName, itemName, itemIndex, event, data, appliInst, pageInst, itemInst, reqAppliName, reqEventName, reqItemName, reqAppliInst]);5772 return true;5773 }5774 }5775 // correct Expbar2 events which are un-coherent. Ex. : event='EXPBAR2', Page='', Item='evVersion'5776 if (pageName === '' && itemName !== '') {5777 pageName = event;5778 event = itemName;5779 itemName = '';5780 }5781 if (itemName) {5782 // for occursed item, itemName can be formatted as item[index] : extract name and index5783 var posBeg = itemName.indexOf('[');5784 if (posBeg > 0)5785 {5786 var posEnd = itemName.indexOf(']', posBeg);5787 if (posEnd > 0)5788 {5789 itemIndex = parseInt(itemName.substring(posBeg + 1, posEnd), 10);5790 itemName = itemName.substring(0, posBeg);5791 }5792 }5793 }5794 var bRemovePage = false;5795 var bUndefinedPage = false;5796 var bRemoveApp = false;5797 // build real application or page instances when receiving 'START', 'END', 'LOAD', 'UNLOAD'5798 switch (event) {5799 case e.event.application.START:5800 {5801 if (ctx.app[appliName]) {5802 ctx.app[appliName].cloneApplication(appliInst)5803 }5804 break;5805 }5806 case e.event.application.END:5807 {5808 if (ctx.app[appliName] && ctx.app[appliName][appliInst]) {5809 bRemoveApp = true;5810 }5811 break;5812 }5813 case e.event.page.LOAD:5814 {5815 // undeclared page management (eg. : '_Undefined_' for HLLAPI or WEB)5816 if (!ctx.app[appliName][pageName]) {5817 bUndefinedPage = true;5818 ctx.app[appliName].addPage(pageName);5819 }5820 // instantiate 'real' instances5821 //ctx.app[appliName][pageName].clonePage(ctx.app[appliName], pageInst);5822 ctx.app[appliName][pageName].clonePage(ctx.app[appliName][appliInst], -1);5823 ctx.app[appliName][pageName].clonePage(ctx.app[appliName][appliInst], pageInst);5824 break;5825 }5826 case e.event.page.UNLOAD:5827 {5828 bRemovePage = true;5829 break;5830 }5831 }5832 var ev = new ctx.event(event);5833 if ((event.startsWith('$')) || (event.startsWith('_'))) { ev.internal = true; }5834 // set current page for this application5835 // set current page and application for the event5836 ev.page = ev.appli = null;5837 var previousCurrentPage = ctx.app[appliName].currentPage;5838 var previousCurrentInstPage = (ctx.app[appliName][appliInst] ? ctx.app[appliName][appliInst].currentPage : null);5839 if (appliName !== '' && pageName !== '' && ctx.app[appliName]) {5840 ctx.app[appliName].currentPage = null;5841 if (ctx.app[appliName][appliInst]) { ctx.app[appliName][appliInst].currentPage = null; }5842 }5843 if ((appliName !== '') && ctx.app[appliName]) {5844 ev.appli = ctx.app[appliName][appliInst];5845 }5846 if ((appliName !== '') && (pageName !== '') && ctx.app[appliName] && ctx.app[appliName][appliInst] && ctx.app[appliName][appliInst][pageName]) {5847 ev.page = ctx.app[appliName][appliInst][pageName][pageInst];5848 if (bUndefinedPage && (previousCurrentInstPage || previousCurrentPage)) {5849 // undefined page received : keep the previously defined current page5850 ctx.app[appliName][appliInst].currentPage = previousCurrentInstPage;5851 ctx.app[appliName].currentPage = previousCurrentPage;5852 } else if (!bRemovePage) {5853 ctx.app[appliName][appliInst].currentPage = ev.page;5854 ctx.app[appliName].currentPage = ev.page;5855 }5856 }5857 ev.appliName = appliName;5858 ev.appliInst = appliInst;5859 ev.pageName = pageName;5860 ev.pageInst = pageInst;5861 ev.itemName = itemName;5862 ev.itemInst = itemInst;5863 ev.itemIndex = itemIndex;5864 ev.index = []; // [index]5865 ev.nbInst = (ctx.app[appliName] ? ctx.app[appliName].nbInst : 0);5866 ev.name = event;5867 if ('string' === typeof data)5868 ev.data = ctx.unserialize(data);5869 else5870 ev.data = data;5871 if (ev.data && ev.data.ctxName) {5872 ev.data = ctx.dataManagers.create(ev.data); // create a ctx.dataManager object5873 }5874 ev.reqAppliName = reqAppliName;5875 ev.reqAppliInst = reqAppliInst;5876 ev.reqEventName = reqEventName;5877 ev.reqItemName = reqItemName;5878 ev.parent = (ev.page ? ev.page : ev.appli);5879 if (ctx.app[appliName] && ctx.app[appliName].events[event] && ctx.app[appliName].events[event].internal) {5880 ev.internal = true;5881 } else if (ctx.app[appliName] && ctx.app[appliName][pageName] && ctx.app[appliName][pageName].events[event] && ctx.app[appliName][pageName].events[event].internal) {5882 ev.internal = true;5883 }5884 if (!ev.internal) {5885 if (ev.appli)5886 ctx.currentAppli = ev.appli;5887 if (ev.page)5888 ctx.currentPage = ev.page;5889 ctx.currentEvent = ev;5890 }5891 if (event == '_ERROR')5892 {5893 var sav = ctx.options.trace.frameworkNotify ;5894 ctx.options.trace.frameworkNotify = true ;5895 ctx.notifyError(data, 'Error');5896 ctx.options.trace.frameworkNotify = sav ;5897 }5898 if (ev.page && ev.page.onLoad && (event == e.event.page.LOAD)) {5899 // memorize page hWnd, useful for screenshot for example5900 ev.page.onLoad(ev);5901 }5902 if ((ctx.options.trace.autoRecordingStarted || ctx.options.trace.frameworkNotify || ctx.options.trace.recording) && (!ev.internal)) {5903 ctx.notifyEvent(ev);5904 }5905 // if ctx.breakException = true : call event callback without catching exceptions5906 if (ctx.options.breakException) {5907 res = ctx.onEvent2(ev);5908 } else {5909 try {5910 res = ctx.onEvent2(ev);5911 } catch (ex) {5912 ctx.log(ex, e.logIconType.Error, ex.message );5913 return false;5914 }5915 }5916 // if 'UNLOAD' event received, clean up the page instances5917 if (bRemovePage) {5918 var pg;5919 if (ctx.app[appliName]) {5920 ctx.app[appliName].removePage(appliInst, pageName, pageInst);5921 }5922 }5923 // if 'END' event received, clean up the application instances5924 if (bRemoveApp) {5925 if (ctx.app[appliName] && ctx.app[appliName][appliInst]) {5926 ctx.app[appliName].removeApplicationInstance(appliInst);5927 if (ctx.app[appliName].defaultInst == appliInst) {5928 ctx.app[appliName].defaultInst = -1; // the default instance is closed5929 }5930 }5931 }5932 // if there are pending callbacks, call them at the end of treatment5933 var func = null;5934 while ((func= ctx.pendingFunctions.shift()) != null) {5935 func.apply();5936 }5937 // keep a copy of last received event5938 ctx.lastEvent = ev.copy()5939 // reset current event on exit5940 ev.clear();5941 // clear legacy variables5942 _Work0_ = '';5943 _Work1_ = '';5944 _Work2_ = '';5945 _Work3_ = '';5946 _Work4_ = '';5947 _Work5_ = '';5948 _Work6_ = '';5949 _Work7_ = '';5950 _Work8_ = '';5951 _Work9_ = '';5952 // *** engine stopped ***5953 if ((appliName == GLOBAL.name) && (event == e.event.application.END)) {5954 ctx.onEngineStop();5955 }5956 return res;5957}5958/**5959 * Sub entry callback to dispatch events from WkMng (without try/catch management)5960 * @method onEvent25961 * @path ctx.onEvent25962 * @ignore5963 * @param {ctx.event} ev event object5964 * @return {boolean} result5965 */5966ctx.onEvent2 = function (ev) {5967 var evName = ev.appliName;5968 if (ev.appliName != 'GLOBAL') {5969 // publish event for 'GLOBAL'5970 if ((ctx.app['GLOBAL'].events[ev.name] !== undefined) && (!ctx.app['GLOBAL'].events[ev.name].technical)) {5971 ctx.amplify.publish('GLOBAL' + ":" + ev.name, ev);5972 }5973 if (ctx.app['GLOBAL'].events[ctx.anyEvent] !== undefined) {5974 ctx.amplify.publish('GLOBAL' + ":" + ctx.anyEvent, ev);5975 }5976 }5977 // publish event for 'appli' (if it is declared)5978 if (ctx.app[ev.appliName].events) {5979 if (ctx.app[ev.appliName].events[ev.name] !== undefined) {5980 ctx.amplify.publish(evName + ":" + ev.name, ev);5981 }5982 if (ctx.app[ev.appliName].events[ctx.anyEvent] !== undefined) {5983 ctx.amplify.publish(evName + ":" + ctx.anyEvent, ev);5984 }5985 }5986 if (ev.pageName) {5987 // publish event for 'appli.page'5988 evName += "." + ev.pageName;5989 if (ctx.app[ev.appliName].pages[ev.pageName] && ctx.app[ev.appliName].pages[ev.pageName].events) {5990 if (ctx.app[ev.appliName].pages[ev.pageName].events[ev.name] !== undefined)5991 ctx.amplify.publish(evName + ":" + ev.name, ev);5992 if (ctx.app[ev.appliName].pages[ev.pageName].events[ctx.anyEvent] !== undefined)5993 ctx.amplify.publish(evName + ":" + ctx.anyEvent, ev);5994 }5995 }5996 if (ev.itemName) {5997 evName += "." + ev.itemName;5998 // publish event for 'appli.page.item'5999 if (ctx.app[ev.appliName].pages[ev.pageName] && ctx.app[ev.appliName].pages[ev.pageName].items[ev.itemName] && ctx.app[ev.appliName].pages[ev.pageName].items[ev.itemName].events) {6000 if (ctx.app[ev.appliName].pages[ev.pageName].items[ev.itemName].events[ev.name] !== undefined) {6001 ctx.amplify.publish(evName + ":" + ev.name, ev);6002 }6003 if (ctx.app[ev.appliName].pages[ev.pageName].items[ev.itemName].events[ctx.anyEvent] !== undefined) {6004 ctx.amplify.publish(evName + ":" + ctx.anyEvent, ev);6005 }6006 }6007 if (ev.pageName && ev.pageName.startsWith('_')) {6008 var pageName = ev.pageName.substring(1);6009 if (ctx.app[ev.appliName].popups[pageName] && ctx.app[ev.appliName].popups[pageName].items[ev.itemName] && ctx.app[ev.appliName].popups[pageName].items[ev.itemName].events) {6010 //evName = ev.appliName + "." + pageName + "." + ev.itemName;6011 if (ctx.app[ev.appliName].popups[pageName].items[ev.itemName].events[ev.name] !== undefined) {6012 ctx.amplify.publish(evName + ":" + ev.name, ev);6013 }6014 if (ctx.app[ev.appliName].popups[pageName].items[ev.itemName].events[ctx.anyEvent] !== undefined) {6015 ctx.amplify.publish(evName + ":" + ctx.anyEvent, ev);6016 }6017 }6018 }6019 }6020 return true;6021};6022/** [Internal usage]6023* Returns the short description for serialization6024* @ignore6025* @method ctxShort6026* @path ctx.ctxShort6027* @param {*} obj6028* @return {*} result6029*/6030ctx.ctxShort = function(obj) {6031 var res;6032 if (Array.isArray(obj))6033 res = [];6034 else6035 res = {};6036 return ctx.set(obj, res, undefined, undefined, undefined, undefined, undefined, 6, true);6037}6038/**6039* Evaluates a JavaScript expression, returns a serialized object6040* @description6041* __Ex.:__6042<code javascript>6043var txt = ctx.eval( "MyAppli.start();" );6044</code>6045* @ignore6046* @method eval6047* @path ctx.eval6048* @param {string} expression JavaScript expression to be evaluated6049* @param {boolean} [serialize] if true or omitted, the result is serialized in JSON6050* @return {*} evaluation result (serializedi in JSON if result is an object )6051*/6052ctx.eval = function ( expression, serialize ) {6053 try {6054 var res = eval ( expression );6055 if ((typeof res === 'object') && (serialize !== false)) {6056 res = ctx.serialize(res, false, false, '\t', true);6057 }6058 return res;6059 }6060 catch(exc) {6061 // "!Error: " prefix to identify errors on Debugger side6062 return "!Error: " + exc.description;6063 }6064}6065/** Overload the evaluation fonction6066* @path CtxtCompute6067* @ignore6068*/6069CtxtCompute = ctx.eval;6070/** Add an alias on the event callback to interface with WkMng6071* @ignore6072* @path onCtxEvent6073*/6074var onCtxEvent = ctx.onEvent;6075/** Add an alias on the event callback for script tiemout notifications6076* @ignore6077* @path OnScriptTimeOut6078*/6079var OnScriptTimeOut = ctx.onScriptTimeOut;6080var lockTimer;6081 6082var lockStatus = {6083 // lockstatus 6084 lockstatusUnknown: 0,6085 lockstatusLocked: 1,6086 lockstatusUnlocked: 2,6087 lockstatusLockedButCannotUnlock: 36088};6089var getStatus = function(value) { 6090 switch (value) {6091 case 0: return lockStatus.lockstatusUnknown;6092 case 1: return lockStatus.lockstatusLocked;6093 case 2: return lockStatus.lockstatusUnlocked;6094 case 3: return lockStatus.lockstatusLockedButCannotUnlock;6095 default: return lockStatus.lockstatusUnlocked;6096 }6097};6098var setLockTimer = function () { 6099 if (lockTimer)6100 {6101 clearTimeout(lockTimer);6102 lockTimer = undefined;6103 }6104 lockTimer = setTimeout( function () {6105 ctx.wkMng.PreventScreenLock(false);6106 ctx.wkMng.LockWorkStation();6107 lockTimer = null;6108 }, 10000);6109}6110ctx.workstation = { };6111ctx.workstation.ensureUnlocked = function () {6112 var coreValue = ctx.wkMng.WorkStationLockStatus();6113 switch ( getStatus(coreValue) ) {6114 case lockStatus.lockstatusLockedButCannotUnlock:6115 ctx.wkMng.PreventScreenLock(false);6116 throw ctx.error.Error('Can\'t unlock');6117 case lockStatus.lockstatusLocked: 6118 ctx.wkMng.UnLockWorkStation();6119 for (var i = 0; i < 10; ++i) {6120 if (getStatus(ctx.wkMng.WorkStationLockStatus()) === lockStatus.lockstatusUnlocked) {6121 setLockTimer();6122 break;6123 }6124 ctx.sleep(250);6125 //await ctx.core.waitTime(250); // need to modify keystroke and mouseclick to async functions to be able to call await ensureUnlocked 6126 }6127 break;6128 case lockStatus.lockstatusUnlocked: 6129 if (lockTimer)6130 setLockTimer();6131 break;6132 default:6133 break;6134 }...

Full Screen

Full Screen

local_data_table.js

Source:local_data_table.js Github

copy

Full Screen

...46 return this.config.columnTypes;47 }48 // apply filtering49 filter(...args) {50 this._lockManager.ensureUnlocked("filter");51 this.dataTable.fnFilter(...args);52 }53 // change pagination54 page(...args) {55 this._lockManager.ensureUnlocked("page");56 return this.dataTable.fnPageChange(...args);57 }58 // sort specific columns59 sort(...args) {60 this._lockManager.ensureUnlocked("sort");61 return this.dataTable.fnSort(...args);62 }63 selectedModels() {64 this._lockManager.ensureUnlocked("bulk");65 return this.selectionManager.models();66 }67 render() {68 this.$el.html(this.template);69 this._dataTableCreate();70 this._initBulkHandling();71 this._enableRowHighlight();72 this.paginate && this._initPaginationHandling();73 this._triggerChangeSelection();74 this.urlPagination && this._setupPaginationHistory();75 this.trigger("render");76 this._afterRender();77 return this;78 }79 renderColumn(id) {80 const config = this._columnManager.columnConfigForId(id);81 if (!config) {82 throw new Error("column not found");83 }84 this.cache.each(row => {85 row.renderColumnByConfig(config);86 });87 }88 selectAllVisible(state) {89 this._lockManager.ensureUnlocked("bulk");90 this.bulkCheckbox.prop("checked", state);91 _.each(this._visibleRowsOnCurrentPage(), function(row) {92 this._setRowSelectedState(row.model, row, state);93 }, this);94 this._triggerChangeSelection({ selectAllVisible: state });95 }96 selectAllMatching() {97 this._lockManager.ensureUnlocked("bulk");98 if (!this.paginate) throw new Error("#selectAllMatching can only be used with paginated tables");99 _.each(this._allMatchingModels(), function(model) {100 this._setRowSelectedState(model, this.cache.get(model), true);101 }, this);102 this._triggerChangeSelection();103 }104 matchingCount() {105 this._lockManager.ensureUnlocked("bulk");106 return this.dataTable.fnSettings().aiDisplay.length;107 }108 totalRecordsCount() {109 this._lockManager.ensureUnlocked("bulk");110 return this.dataTable.fnSettings().fnRecordsTotal();111 }112 pageLimit() {113 return this.dataTable.fnSettings()._iDisplayLength;114 }115 columnRequired(state, id) {116 if (!state && this._columnManager.columnConfigForId(id).required) {117 throw new Error("can not disable visibility when column is required");118 }119 }