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  }120  columnVisibility(attr, state) {121    if (arguments.length === 1) {122      // getter123      return this._columnManager.visibility.get(attr);...

Full Screen