Best Python code snippet using localstack_python
ConfigLoader.js
Source:ConfigLoader.js  
1///////////////////////////////////////////////////////////////////////////2// Copyright © 2014 - 2017 Esri. All Rights Reserved.3//4// Licensed under the Apache License Version 2.0 (the "License");5// you may not use this file except in compliance with the License.6// You may obtain a copy of the License at7//8//    http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing, software11// distributed under the License is distributed on an "AS IS" BASIS,12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13// See the License for the specific language governing permissions and14// limitations under the License.15///////////////////////////////////////////////////////////////////////////1617define([18  'dojo/_base/declare',19  'dojo/_base/lang',20  'dojo/_base/array',21  'dojo/_base/html',22  'dojo/_base/config',23  'dojo/cookie',24  'dojo/Deferred',25  'dojo/promise/all',26  'dojo/request/xhr',27  './utils',28  './WidgetManager',29  './shared/utils',30  './tokenUtils',31  './portalUtils',32  './appConfigResourceUtils',33  './portalUrlUtils',34  './AppStateManager',35  'esri/IdentityManager',36  'esri/config',37  'esri/urlUtils',38  'esri/arcgis/utils'39],40function (declare, lang, array, html, dojoConfig, cookie,41  Deferred, all, xhr, jimuUtils, WidgetManager, sharedUtils, tokenUtils,42  portalUtils, appConfigResourceUtils, portalUrlUtils, AppStateManager, IdentityManager, esriConfig, esriUrlUtils,43  arcgisUtils) {44  var instance = null, clazz;4546  clazz = declare(null, {47    urlParams: null,48    appConfig: null,49    rawAppConfig: null,50    configFile: null,51    _configLoaded: false,52    portalSelf: null,5354    constructor: function (urlParams, options) {55      this._removeHash(urlParams);56      this.urlParams = urlParams || {};57      this.widgetManager = WidgetManager.getInstance();58      lang.mixin(this, options);59    },6061    /****************************************************62    * The app accept the following URL parameters:63    * ?config=<abc-config.json>, this is a config file url64    * ?id=<123>, the id is WAB app id, which is created from portal.65          URL has this parameter means open WAB app from portal.66    * ?appid=<123>, the appid is portal/AGOL app id, which is created from portal/AGOL template.67          The template is created from WAB's app.68          When URL has this parameter, we'll check whether the app is launched69          in portal/AGOL, or not in portal/AGOL.70          > IF in portal, we'll use the appid to get portal/AGOL template id and app data,71          then get WAB app id, then get WAB app config, then merge config;72          > IF NOT in portal, we'll use the appid to get app data, then merge the data73          to WAB app config.74        How to check whether the app is in portal?75          When try to load config file, if URL has no config or id parameter, we'll load76          <app>/config.json file. If the app is in XT, the portalUrl in config.json is not empty.77          If the app is in portal/AGOL, the app is stemapp indeed, which portalUrl is empty.78          So, if portal url is empty, we consider the app is in portal. However, the exception is79          launch stemapp directly. The solution is the XT builder will write "wab_portalurl" cookie80          for stemapp. So, if we find this cookie, we know the app is not in portal.81    * ?itemid=<itemid>, this webmap item will override the itemid in app config82    * ?mode=<config|preview>, this is for internal using purpose83    * ?URL parameters that affect map extent84    ********************************************************/85    loadConfig: function () {86      console.time('Load Config');87      return this._tryLoadConfig().then(lang.hitch(this, function(appConfig) {88        var err = this.checkConfig(appConfig);89        if (err) {90          throw Error(err);91        }92        this.rawAppConfig = lang.clone(appConfig);93        AppStateManager.getInstance().setRawAppConfig(this.rawAppConfig);94        appConfig = this._upgradeAppConfig(appConfig);95        this._processAfterTryLoad(appConfig);96        this.appConfig = appConfig;9798        if(this.urlParams.id){99          return this.loadWidgetsManifest(appConfig).then(lang.hitch(this, function() {100            return this.loadAndUpgradeAllWidgetsConfig(appConfig);101          })).then(lang.hitch(this, function(appConfig) {102            return this.insertAppIdtoResourceUrlofAppConfig(appConfig, this.urlParams.id);103          })).then(lang.hitch(this, function() {104            this._configLoaded = true;105            this._setDocumentTitle(appConfig);106107            this._readAndSetSharedTheme(appConfig);108            return this.getAppConfig();109          }));110        }else{111          tokenUtils.setPortalUrl(appConfig.portalUrl);112          arcgisUtils.arcgisUrl = portalUrlUtils.getBaseItemUrl(appConfig.portalUrl);113          return this._proesssWebTierAndSignin(appConfig).then(lang.hitch(this, function() {114            if(this.urlParams.appid){115              //url has appid parameter means open app as an app created from AGOL template116              if(!window.appInfo.isRunInPortal){117                return this._processNotInPortalAppProtocol(appConfig).118                then(lang.hitch(this, function(appConfig){119                  return this._getAppDataAddTemplateDataFromTemplateAppId120                  (appConfig.portalUrl, this.urlParams.appid).121                  then(lang.hitch(this, function(result){122                    if(result.appData.appConfig){123                      appConfig = result.appData.appConfig;124                    }125                    appConfig._appData = result.appData;126                    appConfig.templateConfig = result.templateData;127                    appConfig.isTemplateApp = true;128                    return appConfig;129                  }));130                }));131              }else{132                return this._getAppConfigFromTemplateAppId(appConfig.portalUrl,133                this.urlParams.appid).then(lang.hitch(this, function(appConfig){134                  this._tryUpdateAppConfigByLocationUrl(appConfig);135                  return this._processInPortalAppProtocol(appConfig);136                }));137              }138            }else{139              return this._processNotInPortalAppProtocol(appConfig);140            }141          })).then(lang.hitch(this, function(appConfig) {142            this._processAfterTryLoad(appConfig);143            this.appConfig = appConfig;144            if(appConfig.map.itemId){145              return appConfig;146            }else{147              var webmapDef;148              if(appConfig.map["3D"]) {149                webmapDef = portalUtils.getDefaultWebScene(appConfig.portalUrl);150              } else {151                webmapDef = portalUtils.getDefaultWebMap(appConfig.portalUrl);152              }153154              return webmapDef.then(function(itemId){155                appConfig.map.itemId = itemId;156                return appConfig;157              });158            }159          })).then(lang.hitch(this, function(appConfig) {160            return this.loadWidgetsManifest(appConfig);161          })).then(lang.hitch(this, function(appConfig) {162            //if it's an AGOL template app, the appConfig will have one property:_appData163            //if it's an WAB template app, the appConfig will have one property:isTemplateApp164            if(appConfig._appData){165              if(appConfig._appData.values && appConfig._appData.values.webmap){166                return portalUtils.getPortal(appConfig.portalUrl)167                .getItemById(appConfig._appData.values.webmap)168                .then(lang.hitch(this, function(webmapInfo){169                  return jimuUtils.template170                    .mergeTemplateAppConfigToAppConfig(appConfig, appConfig._appData, webmapInfo);171                }));172              }else{173                return jimuUtils.template174                    .mergeTemplateAppConfigToAppConfig(appConfig, appConfig._appData);175              }176            }else {177              return appConfig;178            }179          })).then(lang.hitch(this, function(appConfig) {180            return this.loadAndUpgradeAllWidgetsConfig(appConfig);181          })).then(lang.hitch(this, function(appConfig) {182            if(appConfig._wabAppId){//for AGOL template183              return this.processResourceInAppConfigForConfigLoader(appConfig, this.urlParams);184            }else if(appConfig.appItemId && window.JSON.stringify(appConfig).indexOf('${itemId}') > -1){185              //for app download from portal/agol and deployed standalone186              return this.insertAppIdtoResourceUrlofAppConfig(appConfig, appConfig.appItemId);187            }else{188              return appConfig;189            }190          })).then(lang.hitch(this, function(appConfig) {191            this.appConfig = appConfig;192            this._configLoaded = true;193            this._setDocumentTitle(appConfig);194            this._readAndSetSharedTheme(appConfig);195            return this.getAppConfig();196          }));197        }198      }), lang.hitch(this, function(err){199        this.showError(err);200        //we still return a rejected deferred201        var def = new Deferred();202        def.reject(err);203        return def;204      }));205    },206    processResourceInAppConfigForConfigLoader:function(appConfig, urlParams){207      var portalUrl = appConfig.portalUrl;208      //statement:The original app is app1, the template based app is app2209      var app1Id = appConfig.appItemId;210      var app2Id = urlParams.appid;211      var deferred = new Deferred();212      var cloneAppConfig = lang.clone(appConfig);213      //1.Traverse appConfig of app1, get all the resources URL, replace its ${itemId} with app2Id214      this.insertAppIdtoResourceUrlofAppConfig(cloneAppConfig, app2Id).then(function(){215216        //2.if in builder env, continue to handle resource of app1 and app2217        if(urlParams.mode === 'config'){218          //3.get all resource url from app1, if app1's resource is not empty, continue219          var app1Resources = this.getResourceUrlsOfAppConfig(appConfig).result;220          if(app1Resources.length !== 0){221            portalUtils.getItemResources(portalUrl, app2Id).then(function(app2Resources){222              //4.If the app2's resource is empty, this is the first time to open app2,so223              //copy all app1's resources to the app2224              if(app2Resources.length === 0){225                app1Resources = app1Resources.map(function(item){226                  return {227                      resUrl:item228                    };229                });230                return appConfigResourceUtils.AddResourcesToItemForAppSave(portalUrl,231                  app1Resources, app1Id, app2Id).then(function(){232                  deferred.resolve(cloneAppConfig);233                },function(error){234                  console.warn('Add resource to template based app error:' + error.message || error);235                  deferred.resolve(cloneAppConfig);236                });237              }else{238                deferred.resolve(cloneAppConfig);239              }240            },function(error){241              console.warn('Get resource of template based item error:' + error.message || error);242              deferred.resolve(cloneAppConfig);243            });244          }else{245            deferred.resolve(cloneAppConfig);246          }247        }else{248          deferred.resolve(cloneAppConfig);249        }250      }.bind(this),function(error){251        console.warn('Insert appId to resource url of appConfig error:' + error.message || error);252        deferred.resolve(cloneAppConfig);253      });254      return deferred;255    },256    getResourceUrlsOfAppConfig: function(appConfig) {257      function isResources(value) {258        return /^https?:\/\/(.)+\/sharing\/rest\/content\/items/.test(value);259      }260      //callback:func, switch resources to  b64 string(import app to xt)261      function getResourceUrl(pendingObj) {262        return pendingObj.value;263      }264265      var cb = {266        test: isResources,267        func: lang.hitch(this, getResourceUrl)268      };269270      return jimuUtils.processItemResourceOfAppConfig(appConfig, cb);271    },272    insertAppIdtoResourceUrlofAppConfig: function(appConfig, appId) {273      //Traverse appConfig, get all the resources URL, replace its ${itemId} and token274      var portalUrl = appConfig.portalUrl;275      var self = this;276277      function _updateAppConfigWithNewValue(updatingObj, newValue){278        var obj = updatingObj.obj;279        var key = updatingObj.key;280        if(typeof updatingObj.i === 'number'){281          obj[key][updatingObj.i] = newValue;282        } else {283          obj[key] = newValue;284        }285      }286      //callback:test, is a resource url or not287      function isResources(value){288        return /^https?:\/\/(.)+\/sharing\/rest\/content\/items/.test(value);289      }290      //callback:func, process the resource291      function updateItemIdAndTokenOfResources(args, pendingObj) {292        var retUrl = self.processItemIdAndTokenOfResources(pendingObj.value, args);293        _updateAppConfigWithNewValue(pendingObj, retUrl);294        return true;295      }296      return portalUtils.getPortal(portalUrl).getItemById(appId).then(lang.hitch(this, function(appItemInfo) {297        var appInfo = {298          appId: appId,299          isPublic: appItemInfo.access === 'public',300          portalUrl: portalUrl301        };302        var cb = {303          test:isResources,304          func: lang.hitch(this, updateItemIdAndTokenOfResources, appInfo)305        };306        var result = jimuUtils.processItemResourceOfAppConfig(appConfig, cb);307        return result.appConfig;308      }));309    },310    processItemIdAndTokenOfResources:function(resUrl, appInfo){311      //replace resUrl's ${itemId} and token312      if (resUrl.indexOf('${itemId}') > 0) {313        resUrl = resUrl.replace('${itemId}', appInfo.appId);314      }315      if (/(\?|\&)token=.+/.test(resUrl)) {316        resUrl = resUrl.replace(/(\?|\&)token=.+/, '');317      }318      if (!appInfo.isPublic) {319        var credential = tokenUtils.getPortalCredential(appInfo.portalUrl);320        if (credential) {321          resUrl += '?token=' + credential.token;322        }323      }324      return resUrl;325    },326    _setDocumentTitle: function(appConfig) {327      if(!window.isBuilder) {328        //launch329        if (appConfig && appConfig.title) {330          document.title = jimuUtils.stripHTML(appConfig.title);331        }332      }333      //startup\Plugin.js change doc.title when in config mode.334    },335336    getAppConfig: function(){337      var c = lang.clone(this.appConfig);338      c.getConfigElementById = function(id){339        return jimuUtils.getConfigElementById(this, id);340      };341342      c.getConfigElementsByName = function(name){343        return jimuUtils.getConfigElementsByName(this, name);344      };345346      c.visitElement = function(cb){347        jimuUtils.visitElement(this, cb);348      };349350      this._addAuthorizedCrossOriginDomains(this.portalSelf, c);351352      return c;353    },354355    _addAuthorizedCrossOriginDomains: function(portalSelf, appConfig){356      // we read withCredentials domains(mostly web-tier) and put them into corsEnabledServers357      // tokenUtils.addAuthorizedCrossOriginDomains will ignore duplicated values358      if(portalSelf && portalSelf.authorizedCrossOriginDomains){359        tokenUtils.addAuthorizedCrossOriginDomains(portalSelf.authorizedCrossOriginDomains);360      }361      if(appConfig && appConfig.authorizedCrossOriginDomains){362        tokenUtils.addAuthorizedCrossOriginDomains(appConfig.authorizedCrossOriginDomains);363      }364    },365366    checkConfig: function(){367      return false;368    },369370    processProxy: function(appConfig){371      esriConfig.defaults.io.alwaysUseProxy = appConfig.httpProxy &&372      appConfig.httpProxy.useProxy && appConfig.httpProxy.alwaysUseProxy;373      esriConfig.defaults.io.proxyUrl = "";374      esriConfig.defaults.io.proxyRules = [];375376      if (appConfig.httpProxy && appConfig.httpProxy.useProxy && appConfig.httpProxy.url) {377        esriConfig.defaults.io.proxyUrl = appConfig.httpProxy.url;378      }379      if (appConfig.httpProxy && appConfig.httpProxy.useProxy && appConfig.httpProxy.rules) {380        array.forEach(appConfig.httpProxy.rules, function(rule) {381          esriUrlUtils.addProxyRule(rule);382        });383      }384    },385386    addNeedValues: function(appConfig){387      this._processNoUriWidgets(appConfig);388      this._processEmptyGroups(appConfig);389      this._addElementId(appConfig);390391      //do't know why repreated id is generated sometimes, so fix here.392      this._fixRepeatedId(appConfig);393    },394395    showError: function(err){396      if(err && err.message){397        html.create('div', {398          'class': 'app-error',399          innerHTML: jimuUtils.sanitizeHTML(err.message)400        }, document.body);401      }402    },403404    _tryLoadConfig: function() {405      if(this.urlParams.id === 'stemapp'){406        this.urlParams.config = window.appInfo.appPath + 'config.json';407        delete this.urlParams.id;408      }409      if(this.urlParams.config) {410        this.configFile = this.urlParams.config;411        return xhr(this.configFile, {412          handleAs: 'json',413          headers: {414            "X-Requested-With": null415          }416        }).then(lang.hitch(this, function(appConfig){417          tokenUtils.setPortalUrl(appConfig.portalUrl);418          if(appConfig.portalUrl){419            window.portalUrl = appConfig.portalUrl;420          }421422          if(this.urlParams.token){423            return tokenUtils.registerToken(this.urlParams.token).then(function(){424              return appConfig;425            });426          }else{427            return appConfig;428          }429        }));430      }else if(this.urlParams.id){431        //app is hosted in portal432        window.appInfo.isRunInPortal = true;433        var portalUrl = portalUrlUtils.getPortalUrlFromLocation();434        var def = new Deferred();435        tokenUtils.setPortalUrl(portalUrl);436        window.portalUrl = portalUrl;437        arcgisUtils.arcgisUrl = portalUrlUtils.getBaseItemUrl(portalUrl);438439        var tokenDef;440        if(this.urlParams.token){441          tokenDef = tokenUtils.registerToken(this.urlParams.token);442        }else{443          tokenDef = new Deferred();444          tokenDef.resolve();445        }446447        tokenDef.then(lang.hitch(this, function(){448          //we don't process webtier in portal because portal has processed.449          var portal = portalUtils.getPortal(portalUrl);450          portal.loadSelfInfo().then(lang.hitch(this, function(portalSelf){451            this.portalSelf = portalSelf;452            //if the portal uses web-tier authorization, we can get allSSL info here453            if(portalSelf.allSSL && window.location.protocol === "http:"){454              console.log("redirect from http to https");455              window.location.href = portalUrlUtils.setHttpsProtocol(window.location.href);456              def.reject();457              return;458            }459            this._processSignIn(portalUrl).then(lang.hitch(this, function(){460              //integrated in portal, open as a WAB app461              this._getAppConfigFromAppId(portalUrl, this.urlParams.id)462              .then(lang.hitch(this, function(appConfig){463                this._tryUpdateAppConfigByLocationUrl(appConfig);464                return this._processInPortalAppProtocol(appConfig);465              })).then(function(appConfig){466                def.resolve(appConfig);467              }, function(err){468                def.reject(err);469              });470            }));471          }));472        }), lang.hitch(this, function(err){473          this.showError(err);474        }));475        return def;476      } else{477        this.configFile = "config.json";478        return xhr(this.configFile, {handleAs: 'json'}).then(lang.hitch(this, function(appConfig){479          tokenUtils.setPortalUrl(appConfig.portalUrl);480          if(appConfig.portalUrl){481            window.portalUrl = appConfig.portalUrl;482          }483          if(this.urlParams.token){484            return tokenUtils.registerToken(this.urlParams.token).then(function(){485              return appConfig;486            });487          }else{488            return appConfig;489          }490        }));491      }492    },493494    _upgradeAppConfig: function(appConfig){495      var appVersion = window.wabVersion;496      var configVersion = appConfig.wabVersion;497      var newConfig;498499      //save wabVersion in app config json here500      appConfig.configWabVersion = appConfig.wabVersion;501502      if(appVersion === configVersion){503        return appConfig;504      }505      var configVersionIndex = this.versionManager.getVersionIndex(configVersion);506      var appVersionIndex = this.versionManager.getVersionIndex(appVersion);507      if(configVersionIndex > appVersionIndex){508        throw Error('Bad version number, ' + configVersion);509      }else{510        newConfig = this.versionManager.upgrade(appConfig, configVersion, appVersion);511        newConfig.wabVersion = appVersion;512        return newConfig;513      }514    },515516    loadAndUpgradeAllWidgetsConfig: function(appConfig){517      var def = new Deferred(), defs = [];518519      sharedUtils.visitElement(appConfig, lang.hitch(this, function(e){520        if(!e.uri){521          return;522        }523        var upgradeDef = this.widgetManager.tryLoadWidgetConfig(e);524        defs.push(upgradeDef);525      }));526      all(defs).then(lang.hitch(this, function(){527        def.resolve(appConfig);528      }), function(err){529        def.reject(err);530      });531      return def;532    },533534    _processAfterTryLoad: function(appConfig){535      this._setPortalUrl(appConfig);536      this._tryUpdateAppConfigByLocationUrl(appConfig);537      this._processUrlParams(appConfig);538539      this.addNeedValues(appConfig);540      this.processProxy(appConfig);541542      IdentityManager.tokenValidity = 60 * 24 * 7;//token is valid in 7 days543      return appConfig;544    },545546    _readAndSetSharedTheme: function(appConfig){547      if(!appConfig.theme.sharedTheme){548        appConfig.theme.sharedTheme = {549          useHeader: false,550          useLogo: false551        };552        if(this.portalSelf.portalProperties && this.portalSelf.portalProperties.sharedTheme){553          appConfig.theme.sharedTheme.isPortalSupport = true;554        }else{555          appConfig.theme.sharedTheme.isPortalSupport = false;556        }557      }558559      if(appConfig.theme.sharedTheme.useHeader){560        if(appConfig.theme.sharedTheme.isPortalSupport && this.portalSelf.portalProperties){561          appConfig.theme.customStyles = {562            mainBackgroundColor: this.portalSelf.portalProperties.sharedTheme.header.background563          };564          appConfig.titleColor = this.portalSelf.portalProperties.sharedTheme.header.text;565        }else{566          console.error('Portal does not support sharedTheme.');567        }568      }569570      if(appConfig.theme.sharedTheme.useLogo){571        if(appConfig.theme.sharedTheme.isPortalSupport && this.portalSelf.portalProperties){572          if(this.portalSelf.portalProperties.sharedTheme.logo.small){573            appConfig.logo = this.portalSelf.portalProperties.sharedTheme.logo.small;574          }else{575            appConfig.logo = 'images/app-logo.png';576          }577578          if(!appConfig.logoLink && this.portalSelf.portalProperties.sharedTheme.logo.link){579            appConfig.logoLink = this.portalSelf.portalProperties.sharedTheme.logo.link;580          }581        }else{582          console.error('Portal does not support sharedTheme, use default logo.');583          appConfig.logo = 'images/app-logo.png';584        }585      }586    },587588    _tryUpdateAppConfigByLocationUrl: function(appConfig){589      if(this.urlParams.config &&590        this.urlParams.config.indexOf('arcgis.com/sharing/rest/content/items/') > -1){591592        //for load config from arcgis.com, for back compatibility test.593        return;594      }595596      //app is hosted in portal597      //we process protalUrl specially because user in a group owned by two orgs should598      //open the app correctly if the app is shared to this kind of group.599      //so we need to keep main protalUrl consistent with portalUrl browser location.600      var portalUrlFromLocation = portalUrlUtils.getPortalUrlFromLocation();601      var processedPortalUrl = portalUrlUtils.getStandardPortalUrl(portalUrlFromLocation);602603      if(portalUrlUtils.isOnline(processedPortalUrl)){604        processedPortalUrl = portalUrlUtils.updateUrlProtocolByOtherUrl(processedPortalUrl,605                                                                        appConfig.portalUrl);606        if(appConfig.map.portalUrl){607          if(portalUrlUtils.isSamePortalUrl(appConfig.portalUrl, appConfig.map.portalUrl)){608            appConfig.map.portalUrl = processedPortalUrl;609          }610        }611        appConfig.portalUrl = processedPortalUrl;612613        //update proxy url614        if(appConfig.httpProxy && appConfig.httpProxy.url){615          appConfig.httpProxy.url = portalUrlUtils.getPortalProxyUrl(processedPortalUrl);616        }617      }618    },619620    _processWidgetJsons: function(appConfig){621      sharedUtils.visitElement(appConfig, function(e, info){622        if(info.isWidget && e.uri){623          jimuUtils.widgetJson.processWidgetJson(e);624        }625      });626    },627628    _processNoUriWidgets: function(appConfig){629      var i = 0;630      sharedUtils.visitElement(appConfig, function(e, info){631        if(info.isWidget && !e.uri){632          i ++;633          e.placeholderIndex = i;634        }635      });636    },637638    _processEmptyGroups: function(appConfig){639      var i = 0;640      if(!appConfig.widgetOnScreen.groups){641        return;642      }643      array.forEach(appConfig.widgetOnScreen.groups, function(g){644        if(!g.widgets || g.widgets && g.widgets.length === 0){645          i ++;646          g.placeholderIndex = i;647        }648      });649    },650651    _addElementId: function (appConfig){652      var maxId = 0, i;653654      sharedUtils.visitElement(appConfig, function(e){655        if(!e.id){656          return;657        }658        //fix element id659        e.id = e.id.replace(/\//g, '_');660661        var li = e.id.lastIndexOf('_');662        if(li > -1){663          i = e.id.substr(li + 1);664          maxId = Math.max(maxId, i);665        }666      });667668      sharedUtils.visitElement(appConfig, function(e){669        if(!e.id){670          maxId ++;671          if(e.itemId){672            e.id = e.itemId + '_' + maxId;673          }else if(e.uri){674            e.id = e.uri.replace(/\//g, '_') + '_' + maxId;675          }else{676            e.id = ''  + '_' + maxId;677          }678        }679      });680    },681682    _setPortalUrl: function(appConfig){683      if(appConfig.portalUrl){684        //we can judge the app is running in portal or not now.685        //we should consider this case: the app is running in arcgis.com and the app is shared to686        //an cross-org group and the member of another org of this group is opening this app.687        //In this case, appConfig.portalUrl is different with portalUrlByLocation, but the app is688        //running in portal(arcgis.com).689        var portalUrlByLocation = portalUrlUtils.getPortalUrlFromLocation();690        var isOnline = portalUrlUtils.isOnline(portalUrlByLocation);691        if(!portalUrlUtils.isSamePortalUrl(appConfig.portalUrl, portalUrlByLocation) && !isOnline){692          //app is deployed outside of portal693          window.appInfo.isRunInPortal = false;694        }695        return;696      }697      //if there is no portalUrl in appConfig, try to check whether the app698      //is launched from XT version builder699      if(window.isXT && cookie('wab_portalurl')){700        appConfig.portalUrl = cookie('wab_portalurl');701        return;702      }703704      //if not launched from XT builder and has no portalUrl is set,705      //let's assume it's hosted in portal, use the browser location706      window.appInfo.isRunInPortal = true;707      appConfig.portalUrl = portalUrlUtils.getPortalUrlFromLocation();708      return;709    },710711    _changePortalUrlProtocol: function(appConfig, protocol){712      //if browser uses https protocol, portalUrl should also use https713      appConfig.portalUrl = portalUrlUtils.setProtocol(appConfig.portalUrl, protocol);714715      if(appConfig.map.portalUrl){716        appConfig.map.portalUrl = portalUrlUtils.setProtocol(appConfig.map.portalUrl, protocol);717      }718719      if(appConfig.httpProxy){720        var httpProxyUrl = appConfig.httpProxy.url;721722        appConfig.httpProxy.url = portalUrlUtils.setProtocol(httpProxyUrl, protocol);723724        if(appConfig.httpProxy && appConfig.httpProxy.rules){725          array.forEach(appConfig.httpProxy.rules, lang.hitch(this, function(rule){726            rule.proxyUrl = portalUrlUtils.setProtocol(rule.proxyUrl, protocol);727          }));728        }729      }730    },731732    _processInPortalAppProtocol: function(appConfig){733      var def = new Deferred();734      var portalUrl = appConfig.portalUrl;735      var portal = portalUtils.getPortal(portalUrl);736737      //for hosted app, we need to check allSSL property738      var handleAllSSL = lang.hitch(this, function(allSSL){739        if(window.location.protocol === 'https:'){740          this._changePortalUrlProtocol(appConfig, 'https');741        }else{742          if(allSSL){743            //keep the protocol of browser honor allSSL property744            console.log("redirect from http to https");745            window.location.href = portalUrlUtils.setHttpsProtocol(window.location.href);746            def.reject();747            return;748          }else{749            this._changePortalUrlProtocol(appConfig, 'http');750          }751        }752        this._checkLocale();753        def.resolve(appConfig);754      });755756      //we have called checkSignInStatus in _processSignIn before come here757      portal.loadSelfInfo().then(lang.hitch(this, function(portalSelf){758        this.portalSelf = portalSelf;759        //we need to check anonymous property for orgnization first,760        if(portalSelf.access === 'private'){761          //we do not force user to sign in,762          //we just check protocol of portalUrl in appConfig as allSSL763          var isPortalHttps = appConfig.portalUrl.toLowerCase().indexOf('https://') === 0;764          handleAllSSL(isPortalHttps);765        }766        else{767          //Allow anonymous access to portal.768          handleAllSSL(portalSelf.allSSL);769        }770      }), lang.hitch(this, function(err){771        def.reject(err);772      }));773      return def;774    },775776    _processNotInPortalAppProtocol: function(appConfig){777      var def = new Deferred();778      if(appConfig.portalUrl){779        var portal = portalUtils.getPortal(appConfig.portalUrl);780        portal.loadSelfInfo().then(lang.hitch(this, function(portalSelf){781          this.portalSelf = portalSelf;782          var isBrowserHttps = window.location.protocol === 'https:';783          var allSSL = !!portalSelf.allSSL;784          if(allSSL || isBrowserHttps){785            this._changePortalUrlProtocol(appConfig, 'https');786          }787788          var isPortalHttps = appConfig.portalUrl.toLowerCase().indexOf('https://') === 0;789          if(isPortalHttps && !isBrowserHttps){790            //for app in configWindow and previewWindow, we should not refresh url because there is791            //a DOMException if protocol of iframe is not same as protocol of builder window792            //such as:Blocked a frame with origin "https://***" from accessing a cross-origin frame.793            if(!tokenUtils.isInConfigOrPreviewWindow()){794              //if portal uses https protocol, the browser must use https too795              console.log("redirect from http to https");796              window.location.href = portalUrlUtils.setHttpsProtocol(window.location.href);797              def.reject();798              return;799            }800          }801          def.resolve(appConfig);802        }), lang.hitch(this, function(err){803          def.reject(err);804        }));805      }806      else{807        def.resolve(appConfig);808      }809      return def;810    },811812    //this function will be not called if app is in portal.813    _proesssWebTierAndSignin: function(appConfig){814      var def = new Deferred();815      var isWebTier = false;816      var portalUrl = appConfig.portalUrl;817      this._processWebTier(appConfig).then(lang.hitch(this, function(webTier){818        isWebTier = webTier;819        var portal = portalUtils.getPortal(portalUrl);820        return portal.loadSelfInfo();821      })).then(lang.hitch(this, function(portalSelf) {822        this.portalSelf = portalSelf;823        return this._processSignIn(portalUrl, isWebTier);824      })).then(lang.hitch(this, function() {825        def.resolve();826      }), function(err){827        def.reject(err);828      });829      return def;830    },831832    _processWebTier: function(appConfig){833      var def = new Deferred();834      var portalUrl = appConfig.portalUrl;835      if(appConfig.isWebTier){836        //If appConfig.isWebTier is true, we should assume the portal uses web-tier authentication837        //no matter what value tokenUtils.isWebTierPortal returns, because the portal maybe838        //disable auto account registration. #4202839        tokenUtils.addAuthorizedCrossOriginDomains([portalUrl]);840        //Although it is recommended to enable ssl for IWA/PKI portal by Esri,841        //there is no force on the client. They still can use http for IWA/PKI.842        //It is not correnct to assume web-tier authorization only works with https.843        tokenUtils.isWebTierPortal(portalUrl).then(lang.hitch(this, function() {844          var credential = tokenUtils.getPortalCredential(portalUrl);845          //if portal uses web-tier but the user doesn't have an account in this portal,846          //credential will be null847          if(credential && credential.ssl){848            //if credential.ssl, it means that the portal is allSSL enabled849            if(window.location.protocol === 'http:' && !tokenUtils.isInConfigOrPreviewWindow()){850              console.log("redirect from http to https");851              window.location.href = portalUrlUtils.setHttpsProtocol(window.location.href);852              return;853            }854          }855          //resolve appConfig.isWebTier, not the resoponse of tokenUtils.isWebTierPortal856          def.resolve(appConfig.isWebTier);857        }), lang.hitch(this, function(err) {858          def.reject(err);859        }));860      }else{861        def.resolve(false);862      }863      return def;864    },865866    _processSignIn: function(portalUrl, isWebTier){867      var def = new Deferred();868      var portal = portalUtils.getPortal(portalUrl);869      var sharingUrl = portalUrlUtils.getSharingUrl(portalUrl);870      var defSignIn;871872      if(window.appInfo.isRunInPortal){873        //we don't register oauth info for app run in portal.874        defSignIn = IdentityManager.checkSignInStatus(sharingUrl);875        defSignIn.promise.always(lang.hitch(this, function(){876          def.resolve();877        }));878      }else{879        if (!tokenUtils.isInBuilderWindow() && !tokenUtils.isInConfigOrPreviewWindow() &&880          this.portalSelf.supportsOAuth && this.rawAppConfig && this.rawAppConfig.appId && !isWebTier) {881          tokenUtils.registerOAuthInfo(portalUrl, this.rawAppConfig.appId);882        }883        //we call checkSignInStatus here because this is the first place where we can get portal url884        defSignIn = IdentityManager.checkSignInStatus(sharingUrl);885        defSignIn.promise.always(lang.hitch(this, function(){886          tokenUtils.xtGetCredentialFromCookie(portalUrl);887          //call portal self again because the first call is not sign in,888          //this call maybe have signed in.889          portal.loadSelfInfo().then(lang.hitch(this, function(portalSelf) {890            this.portalSelf = portalSelf;891            this._checkLocale();892            def.resolve();893          }));894        }));895      }896      return def;897    },898899    _checkLocale: function(){900      if(tokenUtils.isInConfigOrPreviewWindow()){901        //in builder, app will use wab_locale902        return;903      }904905      var appLocale = this.portalSelf.user && this.portalSelf.user.culture ||906          dojoConfig.locale;907908      appLocale = appLocale.toLowerCase();909910      if(!this.urlParams.locale && jimuUtils.isLocaleChanged(dojoConfig.locale, appLocale)){911        cookie('wab_app_locale', appLocale);912        window.location.reload();913      }914    },915916    _getAppConfigFromTemplateAppId: function(portalUrl, appId){917      var portal = portalUtils.getPortal(portalUrl);918      //the appid means: the app created by AGOL template.919      return this._getWabAppIdAndDataFromTemplateAppId(portalUrl, appId).920      then(lang.hitch(this, function(response){921        var wabAppId = response.appId;922        var appData = response.appData;923924        return all([this._getAppConfigFromAppId(portalUrl, wabAppId),925          portal.getItemData(appData.source)]).then(lang.hitch(this, function(results){926          var appConfig;927          if(appData.appConfig){//appConfig is stored in template app928            appConfig = appData.appConfig;929            delete appData.appConfig;930          }else{//appConfig is in template931            appConfig = results[0];932          }933934          appConfig = this._upgradeAppConfig(appConfig);935936          var templateConfig = results[1];937938          appConfig._appData = appData;939          appConfig._wabAppId = wabAppId;940          appConfig.templateConfig = templateConfig;941          appConfig.isTemplateApp = true;942          return appConfig;943        }));944      }));945    },946947    _getAppDataAddTemplateDataFromTemplateAppId: function(portalUrl, appId){948      //the appid means: the app created by AGOL template.949      var portal = portalUtils.getPortal(portalUrl);950      return portal.getItemData(appId).then(function(appData){951        //appData.source means template id952        return portal.getItemData(appData.source).then(function(templateData){953          return {954            appData: appData,955            templateData: templateData956          };957        });958      });959    },960961    _getWabAppIdAndDataFromTemplateAppId: function(portalUrl, appId){962      //the appid means: the app created by AGOL template.963      var def = new Deferred();964      var portal = portalUtils.getPortal(portalUrl);965      portal.getItemData(appId).then(lang.hitch(this, function(appData) {966        //appData.source means template id967        portal.getItemById(appData.source).then(lang.hitch(this, function(item) {968          var urlObject = esriUrlUtils.urlToObject(item.url);969          def.resolve({970            appId: urlObject.query.id,971            appData: appData972          });973        }));974      }), function(err){975        def.reject(err);976      });977      return def;978    },979980    _getAppConfigFromAppId: function(portalUrl, appId){981      //the appid means: the app created by app builder.982      return portalUtils.getPortal(portalUrl).getItemData(appId);983    },984985    _removeHash: function(urlParams){986      for(var p in urlParams){987        if(urlParams[p]){988          urlParams[p] = urlParams[p].replace('#', '');989        }990      }991    },992993    loadWidgetsManifest: function(config){994      var defs = [], def = new Deferred();995      if(config._buildInfo && config._buildInfo.widgetManifestsMerged){996        this._loadMergedWidgetManifests().then(lang.hitch(this, function(manifests){997          sharedUtils.visitElement(config, lang.hitch(this, function(e){998            if(!e.widgets && (e.uri || e.itemId)){999              if(e.uri && manifests[e.uri]){1000                this._addNeedValuesForManifest(manifests[e.uri], e.uri);1001                jimuUtils.widgetJson.addManifest2WidgetJson(e, manifests[e.uri]);1002              }else{1003                defs.push(loadWidgetManifest(this.widgetManager, e, config.portalUrl));1004              }1005            }1006          }));1007          all(defs).then(function(){1008            def.resolve(config);1009          });1010        }));1011      }else{1012        sharedUtils.visitElement(config, lang.hitch(this, function(e){1013          if(!e.widgets && (e.uri || e.itemId)){1014            defs.push(loadWidgetManifest(this.widgetManager, e, config.portalUrl));1015          }1016        }));1017        all(defs).then(function(){1018          def.resolve(config);1019        });1020      }10211022      function loadWidgetManifest(widgetManager, e, portalUrl){1023        function _doLoadWidgetManifest(e){1024          return widgetManager.loadWidgetManifest(e).then(function(manifest){1025            return manifest;1026          }, function(err){1027            console.log('Widget failed to load, it is removed.', e.name);10281029            if(err.stack){1030              console.error(err.stack);1031            }else{1032              //TODO err.code === 400, err.code === 4031033              console.log(err);1034            }1035            deleteUnloadedWidgets(config, e);1036          });1037        }10381039        if(e.itemId){1040          return portalUtils.getPortal(portalUrl).getItemById(e.itemId).then(function(item){1041            if(isWidgetUsable(item.url)){1042              e.uri = jimuUtils.widgetJson.getUriFromItem(item);1043              return _doLoadWidgetManifest(e);1044            }else{1045              console.log('Widget is not useable, it is removed.', e.name);1046              deleteUnloadedWidgets(config, e);1047            }1048          }, function(err){1049            console.log('Widget is not loaded, it is removed.', e.name, err);1050            deleteUnloadedWidgets(config, e);1051          });1052        }else{1053          return _doLoadWidgetManifest(e);1054        }1055      }10561057      function isWidgetUsable(/*widgetUrl*/){1058        // if(jimuUtils.isEsriDomain(widgetUrl)){1059        //   return true;1060        // }10611062        // var credential = tokenUtils.getPortalCredential(config.portalUrl);1063        // if(!credential){1064        //   return false;1065        // }10661067        // //if user has signed in, because we use the config.portalUrl to get credential, so the user MUST be in this org.1068        // return true;10691070        //this is for portal only. in portal, as long as user can access the item, use can use the widget.1071        //so return true here.1072        //When online support custom widget, we'll review this code. 201709071073        return true;1074      }10751076      function deleteUnloadedWidgets(config, e){1077        //if has e, delete a specific widget1078        //if has no e, delete all unloaded widget1079        deleteInSection('widgetOnScreen');1080        deleteInSection('widgetPool');10811082        function deleteInSection(section){1083          if(config[section] && config[section].widgets){1084            config[section].widgets = config[section].widgets.filter(function(w){1085              if(e){1086                return w.id !== e.id;1087              }else{1088                if(w.uri && !w.manifest){1089                  console.error('Widget is removed because it is not loaded successfully.', w.uri);1090                }1091                return w.manifest;1092              }1093            });1094          }1095          if(config[section] && config[section].groups){1096            config[section].groups.forEach(function(g){1097              if(g.widgets){1098                g.widgets = g.widgets.filter(function(w){1099                  if(e){1100                    return w.id !== e.id;1101                  }else{1102                    if(w.uri && !w.manifest){1103                      console.error('Widget is removed because it is not loaded successfully.', w.uri);1104                    }1105                    return w.manifest;1106                  }1107                });1108              }1109            });1110          }1111        }1112      }11131114      setTimeout(function(){1115        //delete problem widgets to avoid one widget crash app1116        if(!def.isResolved()){1117          deleteUnloadedWidgets(config);1118          def.resolve(config);1119        }1120      }, 60 * 1000);1121      return def;1122    },11231124    _addNeedValuesForManifest: function(manifest, uri){1125      lang.mixin(manifest, jimuUtils.getUriInfo(uri));11261127      jimuUtils.manifest.addManifestProperies(manifest);1128      jimuUtils.manifest.processManifestLabel(manifest, dojoConfig.locale);1129    },11301131    _loadMergedWidgetManifests: function(){1132      var file = window.appInfo.appPath + 'widgets/widgets-manifest.json';1133      return xhr(file, {1134        handleAs: 'json'1135      });1136    },11371138    _fixRepeatedId: function(appConfig){1139      var id = [];1140      sharedUtils.visitElement(appConfig, function(e){1141        if(id.indexOf(e.id) >= 0){1142          e.id += '_';1143        }1144        id.push(e.id);1145      });1146    },11471148    //we use URL parameters for the first loading.1149    //After loaded, if user changes app config through builder,1150    //we'll use the configuration in builder.1151    _processUrlParams: function(appConfig){1152      var urlWebmap = this.urlParams.itemid || this.urlParams.webmap;1153      if(urlWebmap && appConfig.map.itemId !== urlWebmap){1154        if(appConfig.map.mapOptions){1155          jimuUtils.deleteMapOptions(appConfig.map.mapOptions);1156        }1157        appConfig.map.itemId = urlWebmap;1158      }1159      if(this.urlParams.mode){1160        appConfig.mode = this.urlParams.mode;1161      }1162      if(!appConfig.map.mapOptions){1163        appConfig.map.mapOptions = {};1164      }11651166      if(this.urlParams.scale){1167        appConfig.map.mapOptions.scale = this.urlParams.scale;1168      }1169      if(this.urlParams.level || this.urlParams.zoom){1170        appConfig.map.mapOptions.zoom = this.urlParams.level || this.urlParams.zoom;1171      }1172    }1173  });11741175  clazz.getInstance = function (urlParams, options) {1176    if(instance === null) {1177      instance = new clazz(urlParams, options);1178    }else{1179      instance.urlParams = urlParams;1180      instance.options = options;1181    }1182    return instance;1183  };11841185  return clazz;
...pnp-ww.js
Source:pnp-ww.js  
1'use strict';2// ===============3// Widget Wrangler4// ===============5//6// This is a light-weight JavaScript library that loads "widgets" written in MV* style libraries such7// as AngularJS. It manages loading JS libraries efficiently and without conflict when they are used8// by multiple independent widgets on a page.9//10// Widget Wrangler does not depend on any other Javascript libraries11//12var ww = window.ww || function () {13    var ww = {14        version: "1.0.0",       // Library verison number15        // *** SCRIPT MANAGEMENT ***16        // Each script library that's needed is tracked via a script object with the following properties:17        //  index - index into the scriptLibraries[] array for this script18        //  scriptSrc - source URL for the script19        //  status - set to "Loading" or "Complete"20        scriptLibraries: [],     // Array of scripts that have been loaded or in process of loading.21        22        // loadScript(scriptSrc)23        //  This function gets called whenever a script needs to be loaded. It handles the possibility24        //  that it has already been loaded, is in the progress of loading, or has never been loaded25        //  at all, and notifies the appScriptLoaded when loading is complete.26        loadScript: function loadScript(scriptSrc) {27            var scriptLoading = {};         // Object found in - or to be added to - the scriptLibraries array28            // Check if script is already queued29            for (var i = 0; i < ww.scriptLibraries.length; i++) {30                if (ww.scriptLibraries[i].scriptSrc === scriptSrc) {31                    scriptLoading = ww.scriptLibraries[i];32                    break;33                }34            }35            // If script was not already queued, add it to the queue and start loading it36            if (Object.getOwnPropertyNames(scriptLoading).length < 1) {37                // First add it to the scriptLibraries array38                var newScript = {39                    index: ww.scriptLibraries.length,40                    scriptSrc: scriptSrc,41                    status: "Loading"42                };43                ww.scriptLibraries.push(newScript);44                scriptLoading = ww.scriptLibraries[ww.scriptLibraries.length - 1];45                // Now tell the browser to load the script46                var head = document.getElementsByTagName('head')[0];47                var script = document.createElement('script');48                script.type = 'text/javascript';49                if (script.readyState) {50                    script.onreadystatechange = function () {51                        if (this.readyState == 'complete') ww.scriptLoaded(newScript.index);52                    };53                }54                script.onload = function() {55                    ww.scriptLoaded(newScript.index);56                };57                script.onerror = function() {58                    newScript.status = "Error";59                    ww.scriptError(newScript.index);60                };61                script.src = scriptSrc;62                head.appendChild(script);63            }64            return scriptLoading;65        },66        // scriptLoaded(index)67        //  This function is called when a script has finished loading68        scriptLoaded: function scriptLoaded(index) {69            if (ww.scriptLibraries[index].status !== "Error") {70                // Mark the script as complete71                ww.scriptLibraries[index].status = "Complete";72                // Look through apps for any that are waiting for a script to load, and call73                // their appScriptLoaded with the index of the script that has completed74                for (var i = 0; i < ww.apps.length; i++) {75                    if (ww.apps[i].appStatus === "Waiting") {76                        ww.apps[i].appScriptLoaded(index);77                    }78                }79            }80        },81        // scriptError(index)82        //  This function handles script loading errors83        scriptError: function scriptError(index) {84            // Look through apps for any that are waiting for a script to load, and call85            // their appScriptError with the index of the script that has errored86            for (var i = 0; i < ww.apps.length; i++) {87                if (ww.apps[i].appStatus === "Waiting") {88                    ww.apps[i].appScriptError(index);89                }90            }91        },92        // *** APP MANAGEMENT ***93        // Each instance of WW on a page, along with its parent HTML element, is considered an "app" and94        // is tracked using an appObj object.95        apps: [],       // Array of all known apps on this page96        // appObj - prototype for an object that represents an app.97        appObj: function appObj() {98            var obj = {99                appId: "",                // Unique string identifier for this app100                appName: "",              // App name (also the Angular controller name)101                appType: "",              // App type (set to "Angular" or "Self")102                appBind: null,            // App binding function for "Self" app103                appElement: {},           // DOM element to bind to104                appStatus: "Not Started", // App Status is "Not Started", "Waiting", "Complete" or "Error"105                appScripts: [],           // Array of appScriptObj objects for script this app requires106                appExecPriority: 0,       // The app's current executing priorty.107                appMaxPriority: 0,        // The app's highest priority.108                // startLoading()109                //   This function initializes the apps scripts at priority 0 to be loaded.110                startLoading: function startLoading() {111                    this.appMaxPriority = this.appScripts[this.appScripts.length-1].priority;112                    for (var i = 0; i < this.appScripts.length; i++) {113                        if (this.appScripts[i].priority === 0) {114                            this.appStatus = "Waiting";115                            var newScript = ww.loadScript(this.appScripts[i].src);116                            this.appScripts[i].status = newScript.status;117                            this.appScripts[i].index = newScript.index;118                            if (newScript.status === "Complete") {119                                //If script is already loaded, notify appScriptLoaded for this app.120                                this.appScriptLoaded(newScript.index);121                            } else if (newScript.status === "Error") {122                                //If script is already loaded, but in error, call appScriptError for this app.123                                this.appScriptError(newScript.index);124                            }125                        }126                    }127                },128                // appScriptLoaded(index)129                //  This function is called whenever an app needs to be notified that a script has loaded.130                //  index is an index into the appScripts array131                appScriptLoaded: function appScriptLoaded(index) {132                    var i = 0,133                        appLoaded = false,134                        priorityComplete = false,135                        completedScript = null;136                    // First, try to find the appScript corresponding to the script that finished loading137                    for (i = 0; i < this.appScripts.length; i++) {138                        if (this.appScripts[i].index === index) {139                            completedScript = this.appScripts[i];140                        }141                    }142                    if (completedScript !== null) {143                        // If here, we found the appScript. Mark it complete.  Could be a script that this app hasn't loaded yet.144                        completedScript.status = "Complete";145                        if (completedScript.priority === this.appExecPriority) {146                            // Check if all the scripts we were waiting for are done. If so, we can infer that147                            // we've finished loading all scripts at this priority and should either start loading148                            // the next priority of scripts or bootstrap the app.149                            priorityComplete = true;150                            for (i = 0; i < this.appScripts.length; i++) {151                                if (this.appScripts[i].priority === this.appExecPriority && this.appScripts[i].status !== "Complete")152                                    priorityComplete = false;153                            }154                            if (priorityComplete) {155                                appLoaded = true;156                                while (appLoaded && this.appExecPriority <= this.appMaxPriority) {157                                    appLoaded = true;158                                    // Look for additional scripts at the next priority and, if found, start them if they're not already complete.159                                    this.appExecPriority++;160                                    for (i = 0; i < this.appScripts.length; i++) {161                                        if (this.appScripts[i].priority === this.appExecPriority && this.appScripts[i].status !== "Complete") {162                                            var newScript = ww.loadScript(this.appScripts[i].src);163                                            this.appScripts[i].status = newScript.status;164                                            this.appScripts[i].index = newScript.index;165                                            if (newScript.status !== "Complete") {166                                                appLoaded = false;167                                            }168                                            if (newScript.status === "Error") {169                                                //If script is already loaded, but in error, call appScriptError for this app.170                                                this.appScriptError(newScript.index);171                                            }172                                        }173                                    }174                                }175                            }176                            if (appLoaded) {177                                // If here, all the scripts needed by the app are loaded.178                                this.appStatus = "Complete";179                                // Bootstrap the Angular controller180                                if (this.appType === "angular") {181                                    try {182                                        window.angular.bootstrap(this.appElement, [this.appName]);183                                        console.log(this.appName + "(" + this.appId + ")" + " loading complete.");184                                    } catch (e) {185                                        console.log("Error bootstrapping application: " + this.appName + "(" + this.appId + ")");186                                        console.log(e);187                                    }188                                //Self Binding Application189                                } else if (this.appBind.length > 0) {190                                    //Deal with namespaces or nesting of function.191                                    var fnElements = this.appBind.split(".");192                                    var bindFn = window;193                                    for (i = 0; i < fnElements.length; i++) {194                                        bindFn = bindFn[fnElements[i]];195                                    }196                                    if (typeof bindFn === 'function') {197                                        bindFn(this.appElement);198                                        console.log(this.appName + "(" + this.appId + ")" + " with function: " + this.appBind + " loading complete.");199                                    } else {200                                        console.log("Error bootstrapping application: " + this.appName + "(" + this.appId + ") with function: " + this.appBind);201                                    }202                                }203                            }204                        }205                    }206                },207                // appScriptError(index)208                //  This script handles checking if a script the app depends on has errored.209                appScriptError: function appScriptError(index) {210                    // Try to find the appScript corresponding to the script that finished loading211                    for (var i = 0; i < this.appScripts.length; i++) {212                        if (this.appScripts[i].index === index) {213                            this.appStatus = "Error";214                            console.log(this.appName + "(" + this.appId + ")" + " failed to load script: " + this.appScripts[i].src);215                        }216                    }217                }218            };219            return obj;220        },221        // appScriptObj222        //  Prototype for an object that represents a script needed by an app223        appScriptObj: function appScriptObj() {224            var obj = {225                index: -1,                  // Index in the scriptLibraries array226                src: "",                    // Source URL227                priority: 0,                // Priority where all priority 0 scripts are loaded first, then priority 1, etc.228                status: "NotLoaded",        // Status is "NotLoaded", "Loading" or "Complete"               229            };230            return obj;231        }232    };233    return ww;234}();235(function () {236    // *** In-line execution begins here ***237    // We will bind to the parent of this script block, so find it now while the DOM is still loading238    // ie. before doing any async calls to load scripts! Right now, it will be the last, deepest child in the tree.239    try {240        var APP_TYPES = ["angular"];241        var validAppType = true;242        var element = document.documentElement; // This will hold the <script> tag's DOM element243        while (element.childNodes.length && element.lastChild.nodeType === 1) {244            element = element.lastChild;245        }246        var elementToBind = element.parentNode; // This is the parent of the script tag247        // Get the path of the script source so we can handle relative script URL's248        var scriptPath = element.src;249        scriptPath = scriptPath.substring(0, scriptPath.lastIndexOf('/') + 1);250        // Get the app parameters from the <script> element251        var appName = element.getAttribute("ww-appName");252        var appType = element.getAttribute("ww-appType");253        if (appType === null) { appType = ""; }254        if (appType.length > 0) {255            appType = appType.toLowerCase();256            validAppType = (APP_TYPES.indexOf(appType) > -1);257        }258        var appBind = element.getAttribute("ww-appBind");259        if (appBind === null) { appBind = ""; }260        var appScripts = null;261        try {262            appScripts = JSON.parse(element.getAttribute("ww-appScripts"));263        } catch (e) {264            console.log("Error parsing ww-appScripts tag: " + e);265        }266        if (appScripts !== null && appName.length > 0 && (appType.length > 0 || appBind.length > 0) && validAppType) {267            // Create the app object268            var newApp = new ww.appObj();269            newApp.appId = appName + ww.apps.length;270            newApp.appName = appName;271            newApp.appType = appType;272            newApp.appBind = appBind;273            newApp.appElement = elementToBind;274            // Add an appScript object for each script the app requires 275            for (var i = 0; i < appScripts.length; i++) {276                var newScript = new ww.appScriptObj();277                if (appScripts[i].src.substring(0, 2) === "~/") {278                    appScripts[i].src = appScripts[i].src.replace("~/", scriptPath);279                }280                newScript.src = appScripts[i].src;281                newScript.priority = appScripts[i].priority || 0;282                newApp.appScripts.push(newScript);283            }284            // Add the app to the apps collection and start loading285            ww.apps.push(newApp);286            newApp.startLoading();287        } else {288            console.log("Unable to load app: " + appName + ".  Error in script tag.");289        }290    } catch (e) {291        console.log(e);292    }...ProjectState.js
Source:ProjectState.js  
1import ProjectContext from "./ProjectContext";2import {useState, useCallback} from "react";3const ProjectState = (props) => {4    const host = process.env.REACT_APP_SERVER_URL;5    const savedProjects = localStorage.getItem("projects");6    const [projects, setProjects] = useState(  savedProjects ? JSON.parse(savedProjects) : [])7    const [alert,setAlert] = useState({error:false,message:""});8    const newAlert = (error,message)=>{9        setAlert({error,message});10    }11    const [isLoading, setIsLoading] = useState(true);12    const getProjectById = (id) => {13        return projects.find((project) => { return project._id === id})14        // return await fetchSingleProjectById(id);15    }16    // const fetchSingleProjectById = async (id)=>{17    //     try {18    //         const response = await fetch(19    //             `${host}/api/projects/getProject/${id}`,20    //             {21    //                 method: 'GET',22    //                 headers: {23    //                     'Content-Type': 'application/json'24    //                 }25    //             }26    //         )27    //28    //         const result = await response.json();29    //         console.log(result);30    //31    //         if(result.success){32    //             return result.project;33    //         } else {34    //             console.log(result);35    //             return null;36    //         }37    //     }catch (e){38    //         console.log(e.message);39    //     }40    // }41    const fetchProjects = useCallback(async ()=> {42        try {43            setIsLoading(true);44            const response = await fetch(45                `${host}/api/projects/getAllProjects`,46                {47                    method: 'GET',48                    headers: {49                        'Content-Type': 'application/json'50                    }51                }52            )53            const result = await response.json();54            // console.log(result);55            if(result.success){56                setProjects(result.projects);57                localStorage.setItem("projects",JSON.stringify(result.projects))58            } else {59                console.log(result);60            }61            setIsLoading(false);62        }catch (e){63            console.log(e.message);64            setIsLoading(false);65        }66    },[host])67    const setPros = (projs)=>{68        setProjects(projs);69    }70    return (71        <ProjectContext.Provider value = {{projects,getProjectById,fetchProjects,setPros,isLoading,alert,newAlert}}>72            {props.children}73        </ProjectContext.Provider>74    )75}76export default ProjectState;77/**78 * {79            "_id": "616ecce83683100e860",80            "name": "Meme's Magic",81            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",82            "description": "Hello world appHello world appHello world appHello world appHello world appHello world appHello world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app \n world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app ",83            "technologies": [84                "Android",85                "Kotlin",86                "Hello",87                "Hi",88                "done",89            ],90            "photos": [91                {92                    "photoUrl": "https://akshaymoorthy.com/img/social/social_signup.png",93                    "description": "Sign up Screen",94                    "_id": "616ecce84d0c36865100e861"95                },96                {97                    "photoUrl": "https://akshaymoorthy.com/img/social/social_otp.png",98                    "description": "Otp Screen",99                    "_id": "616ecce84d0c36865100e861"100                },101                {102                    "photoUrl": "https://akshaymoorthy.com/img/social/social_signup.png",103                    "description": "Again SignUp Page",104                    "_id": "616ecce84d0c36865100e861"105                },106                {107                    "photoUrl": "https://akshaymoorthy.com/img/social/social_otp.png",108                    "description": "Otp Screen",109                    "_id": "616ecce84d0c36865100e861"110                }111            ],112            "__v": 0113        },114 {115            "_id": "616ecce836sdfsf83100e860",116            "name": "Meme's Magic",117            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",118            "description": "Hello world app",119            "technologies": [120                "Android",121                "Kotlin"122            ],123            "photos": [124                {125                    "photoUrl": "this is photourl",126                    "description": "Descriptionva",127                    "_id": "616ecce84d0c36865100e861"128                }129            ],130            "__v": 0131        },132 {133            "_id": "616ecce83683100ewerwer860",134            "name": "Meme's Magic",135            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",136            "description": "Hello world app",137            "technologies": [138                "Android",139                "Kotlin"140            ],141            "photos": [142                {143                    "photoUrl": "this is photourl",144                    "description": "Descriptionva",145                    "_id": "616ecce84d0c36865100e861"146                }147            ],148            "__v": 0149        },150 {151            "_id": "616ecce8xcvxvc3683100e860",152            "name": "Meme's Magic",153            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",154            "description": "Hello world app",155            "technologies": [156                "Android",157                "Kotlin"158            ],159            "photos": [160                {161                    "photoUrl": "this is photourl",162                    "description": "Descriptionva",163                    "_id": "616ecce84d0c36865100e861"164                }165            ],166            "__v": 0167        },168 {169            "_id": "616ecce83683100e860",170            "name": "Meme's Magic",171            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",172            "description": "Hello world appHello world appHello world appHello world appHello world appHello world appHello world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app \n world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app world appHello world appHello world appHello world app ",173            "technologies": [174                "Android",175                "Kotlin",176                "Hello",177                "Hi",178                "done",179            ],180            "photos": [181                {182                    "photoUrl": "https://akshaymoorthy.com/img/social/social_signup.png",183                    "description": "Sign up Screen",184                    "_id": "616ecce84d0c36865100e861"185                },186                {187                    "photoUrl": "https://akshaymoorthy.com/img/social/social_otp.png",188                    "description": "Otp Screen",189                    "_id": "616ecce84d0c36865100e861"190                },191                {192                    "photoUrl": "https://akshaymoorthy.com/img/social/social_signup.png",193                    "description": "Again SignUp Page",194                    "_id": "616ecce84d0c36865100e861"195                },196                {197                    "photoUrl": "https://akshaymoorthy.com/img/social/social_otp.png",198                    "description": "Otp Screen",199                    "_id": "616ecce84d0c36865100e861"200                }201            ],202            "__v": 0203        },204 {205            "_id": "616ecce836sdfsf83100e860",206            "name": "Meme's Magic",207            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",208            "description": "Hello world app",209            "technologies": [210                "Android",211                "Kotlin"212            ],213            "photos": [214                {215                    "photoUrl": "this is photourl",216                    "description": "Descriptionva",217                    "_id": "616ecce84d0c36865100e861"218                }219            ],220            "__v": 0221        },222 {223            "_id": "616ecce83683100ewerwer860",224            "name": "Meme's Magic",225            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",226            "description": "Hello world app",227            "technologies": [228                "Android",229                "Kotlin"230            ],231            "photos": [232                {233                    "photoUrl": "this is photourl",234                    "description": "Descriptionva",235                    "_id": "616ecce84d0c36865100e861"236                }237            ],238            "__v": 0239        },240 {241            "_id": "616ecce8xcvxvc3683100e860",242            "name": "Meme's Magic",243            "logo": "https://cdn.vox-cdn.com/thumbor/PSLYCBn2BjUj8Zdbf4BD6SMus-0=/0x0:1800x1179/920x613/filters:focal(676x269:964x557):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/66741310/3zlqxf_copy.0.jpg",244            "description": "Hello world app",245            "technologies": [246                "Android",247                "Kotlin"248            ],249            "photos": [250                {251                    "photoUrl": "this is photourl",252                    "description": "Descriptionva",253                    "_id": "616ecce84d0c36865100e861"254                }255            ],256            "__v": 0257        },...class_app_resources.js
Source:class_app_resources.js  
1var class_app_resources =2[3    [ "PanelPosition", "class_app_resources.html#a5dc3e7e1440c5220b3b9d335d93dbc20", [4      [ "Absolute", "class_app_resources.html#a5dc3e7e1440c5220b3b9d335d93dbc20a4b416446a4e9361cbd46fb295db6ce2e", null ],5      [ "Center", "class_app_resources.html#a5dc3e7e1440c5220b3b9d335d93dbc20aaa79b7c40b072fdcab65bfa11d732389", null ],6      [ "Mouse", "class_app_resources.html#a5dc3e7e1440c5220b3b9d335d93dbc20a3f366d19b692520f76c2e34d5dc45ef5", null ],7      [ "Horizontal", "class_app_resources.html#a5dc3e7e1440c5220b3b9d335d93dbc20a7d5f78c516bedc0a066182a6fd606b8b", null ],8      [ "Vertical", "class_app_resources.html#a5dc3e7e1440c5220b3b9d335d93dbc20a2434cd8c1a594a4cdaa250f86639c600", null ],9      [ "Cascad", "class_app_resources.html#a5dc3e7e1440c5220b3b9d335d93dbc20a3ba0605601cc5bfa69483648aa563cd9", null ]10    ] ],11    [ "AppResources", "class_app_resources.html#a04c4e9bf8909883ff3f050a3fc083615", null ],12    [ "~AppResources", "class_app_resources.html#ab8be6056cfdd56131dfe2e754b92a3f4", null ],13    [ "colChg", "class_app_resources.html#a2523db3c52420ca58653ee28ac383935", null ],14    [ "doPanelPosition", "class_app_resources.html#a79daacc9e6b6dfc2cbaa6fdb9929c018", null ],15    [ "fntChg", "class_app_resources.html#a688b391a946c46e2b2c6203aac1ac559", null ],16    [ "getButBkg", "class_app_resources.html#adbd32901dfb3efc785cbc456f663e860", null ],17    [ "getButLabFnt", "class_app_resources.html#a72c171c32a9e465229cc75558890f00e", null ],18    [ "getButTrtLabFnt", "class_app_resources.html#a30ac8bc4637aa62b6e3ed2818d969222", null ],19    [ "getCalFldBkg", "class_app_resources.html#ab8e57f0d0b58c3f71bcdf24b3518a070", null ],20    [ "getConFldBkg", "class_app_resources.html#a2479f3cab2baa59b7cc493a580e85e8d", null ],21    [ "getFldBkg", "class_app_resources.html#a41447587ee9faa7978ea54c02c2cc260", null ],22    [ "getFldDtaFnt", "class_app_resources.html#ac7d00954872e0ac466888c43f4d22e95", null ],23    [ "getFldLabFnt", "class_app_resources.html#a78402b8fcbc29364095711f493586a13", null ],24    [ "getFldObjCol", "class_app_resources.html#a7faa9b925ce2de11d12ff625178a769f", null ],25    [ "getForeground", "class_app_resources.html#a031379b52ae18abf415d9259e3deb9a9", null ],26    [ "getMenubarBackground", "class_app_resources.html#a5723e83d88e2381c25ea437a20b57898", null ],27    [ "getMessageBackground", "class_app_resources.html#af2d7d8be62f983e5a5580673b67a247e", null ],28    [ "getMnuBarFnt", "class_app_resources.html#a2668b905dc43ba0c3c300739f902c20c", null ],29    [ "getMtxBkg", "class_app_resources.html#aa060edd65c66cf0d11ab4a838e239b60", null ],30    [ "getMtxDtaFnt", "class_app_resources.html#a196375a49f9985675da749ddb4ac680e", null ],31    [ "getMtxTitFnt", "class_app_resources.html#a8da96ffb633bf18a68e69a7d49303678", null ],32    [ "getObjCol", "class_app_resources.html#a0c3d40ca787ea8ac9411884af8a69251", null ],33    [ "getOblFldBkg", "class_app_resources.html#a17d9e01f68c59ab324d3538622fb5ee1", null ],34    [ "getOptionmenuBackground", "class_app_resources.html#a7b9dee8d6d4b9b80ef5f389b2e91222d", null ],35    [ "getPanelPosition", "class_app_resources.html#a7e17c2883edc110d06df2bad4389d191", null ],36    [ "getScrFnt", "class_app_resources.html#a61bf28302dc30415f481683cf89b58b5", null ],37    [ "getScrollinglistBackground", "class_app_resources.html#a55ab7db0a6af1695d70e10f6c0d5201d", null ],38    [ "getStaBarFnt", "class_app_resources.html#ad16a9d14a245452dc5a502b837338599", null ],39    [ "getUntLabFnt", "class_app_resources.html#a697785840e0dfc8eca70f75d1d947d23", null ],40    [ "getViewBackground", "class_app_resources.html#ab45065da360dba337a7c19b2ef0a8ca1", null ],41    [ "getViwCrtDtaFnt", "class_app_resources.html#ada11693957dafd69bb4b65abd19e1ad8", null ],42    [ "getWinTitFnt", "class_app_resources.html#a2317182c996538438bab06238c78e0b3", null ],43    [ "getXPanelPosition", "class_app_resources.html#aa8094e8ca901548e108ec3b406674f5b", null ],44    [ "getYPanelPosition", "class_app_resources.html#a6ea48eef68a38baeb798aa68ba478c70", null ],45    [ "iniCol", "class_app_resources.html#a7f27906e2492ed85dbd908567900ebf5", null ],46    [ "iniColFrmBd", "class_app_resources.html#a8a090ffa8b44b888756a975722bfb2d1", null ],47    [ "iniFntFrmBd", "class_app_resources.html#a7057b61f4c0a8eec1bd4104e92ca907b", null ],48    [ "init", "class_app_resources.html#a02fd73d861ef2e4aabb38c0c9ff82947", null ],49    [ "initColors", "class_app_resources.html#a9f21b1233c13274ef0be8f4741ec84ad", null ],50    [ "initColors", "class_app_resources.html#a6eb835898e53e0c247e29bb83b6228ba", null ],51    [ "initColors", "class_app_resources.html#a944ca07505cc2d60aead513f4fd337bc", null ],52    [ "initFonts", "class_app_resources.html#afe6b3bcff9aad1c980a043c3a056ad75", null ],53    [ "initFonts", "class_app_resources.html#aeb213dd662edf84bf36867617b0d4e5a", null ],54    [ "initPosition", "class_app_resources.html#ac7c5b859ac0291b71de9abbd27d8b520", null ],55    [ "initPositionFromBd", "class_app_resources.html#ad98003e89400101f277b03eec7ed2503", null ],56    [ "initResources", "class_app_resources.html#af0a58090c6c364385e3b2cb9af895401", null ],57    [ "notifyResourcesChanged", "class_app_resources.html#af80b8008ef3627fc6ab122a70a18c7f7", null ],58    [ "setBdColor", "class_app_resources.html#a08d5725461197e0b261be420a46bca3f", null ],59    [ "setBdFnt", "class_app_resources.html#abd419064183d78c291d69c3208d5433c", null ],60    [ "setBdFnt", "class_app_resources.html#a60abec129798149603c1c32e8bf3db05", null ],61    [ "setButtonBackground", "class_app_resources.html#a3e62c1c3e07fa69bf2e1f868d39c7fef", null ],62    [ "setCalFldBkg", "class_app_resources.html#a77f39d7863c9b8fdf8660b385377a881", null ],63    [ "setConFldBkg", "class_app_resources.html#ae76da2ace7b7035b39864caab7b305b7", null ],64    [ "setEntryfieldBackground", "class_app_resources.html#a4d280b83c9f04ccf3fb79172cfc821c2", null ],65    [ "setForeground", "class_app_resources.html#a955fa67a96bd1fe11d5056e53ef3878e", null ],66    [ "setMatrixBackground", "class_app_resources.html#ac4351f6bc312e971362db823479767cf", null ],67    [ "setMenubarBackground", "class_app_resources.html#a400d2e0449fbfb24689e7a990258310f", null ],68    [ "setMessageBackground", "class_app_resources.html#a4bf1084d1c5c856f4a1b175954ed4dc1", null ],69    [ "setOblFldBkg", "class_app_resources.html#adbadc9e4f2015cbb51d6d29fc45e23ae", null ],70    [ "setOptionmenuBackground", "class_app_resources.html#ad8d83b9cb0220c151d859264a623eec5", null ],71    [ "setPanelPosition", "class_app_resources.html#a67962e5310393c2fdf33649fe9462c55", null ],72    [ "setScrollinglistBackground", "class_app_resources.html#a0160c69b2555e93877139aaceb352757", null ],73    [ "setViewBackground", "class_app_resources.html#aea364313561803c6d38df22f1d522b11", null ],74    [ "update", "class_app_resources.html#ad6ab13ba59fdab1387676c44d922aa4b", null ],75    [ "update", "class_app_resources.html#a466a6016284df373a18305c8487b3acf", null ],76    [ "_butBkg", "class_app_resources.html#a8bba49957d4192a53ed0feede43a410a", null ],77    [ "_butLabFnt", "class_app_resources.html#a57eb8beb16218716f31bde7418107afd", null ],78    [ "_butTrtLabFnt", "class_app_resources.html#a621253a7e3b723396d7b56448ddaf247", null ],79    [ "_calFldBkg", "class_app_resources.html#a2948d858ca8c7714c577665ff20a75c3", null ],80    [ "_conFldBkg", "class_app_resources.html#a8fffb7a7d60899d27ed29e09ee0d1c17", null ],81    [ "_Display", "class_app_resources.html#ad0dd7149f27e0452b7252c2daf8058dd", null ],82    [ "_fldBkg", "class_app_resources.html#afe6a14ad98fb20c8a9166c51c1ee0939", null ],83    [ "_fldDtaFnt", "class_app_resources.html#aa175ae2e63e439bb929a2163a71de443", null ],84    [ "_fldLabFnt", "class_app_resources.html#a6629edba080de994704182ff26ccdbb1", null ],85    [ "_mnuBarBkg", "class_app_resources.html#a95b6c61fe07d7a4ef7088dced840ef5d", null ],86    [ "_mnuBarFnt", "class_app_resources.html#a8a3703096122f51be5e5daf5e619599e", null ],87    [ "_mtxBkg", "class_app_resources.html#a085e7d0ee9aac0348fe46e79247d7924", null ],88    [ "_mtxDtaFnt", "class_app_resources.html#ab2a8414b27d74bb347d11dd1f5e4d498", null ],89    [ "_mtxTitFnt", "class_app_resources.html#a53c654746b4ddcc4bc7d9f22a211a356", null ],90    [ "_oblFldBkg", "class_app_resources.html#abd0fe11e7624def0808087dee3baf355", null ],91    [ "_optMnuBkg", "class_app_resources.html#a8f60cb78dd9ecffafd550fe4d4964611", null ],92    [ "_panelPosition", "class_app_resources.html#a8c37230cae161391a743820455a88afa", null ],93    [ "_scrBkg", "class_app_resources.html#a11da5dbf711c79988c7d4df44aa91301", null ],94    [ "_scrFnt", "class_app_resources.html#aa18d899b3067c355ef8c08caaf268cfa", null ],95    [ "_staBarBkg", "class_app_resources.html#ab7e7c5e6c37f8a4706f547b6a30ac064", null ],96    [ "_staBarFnt", "class_app_resources.html#a2aec2928b1037e13588b3a27b1d52456", null ],97    [ "_txtFrg", "class_app_resources.html#a13e5fd90f679cb4ec949a0e54180b8cc", null ],98    [ "_untLabFnt", "class_app_resources.html#aeb2de7ab42f75836f706425f52b687d2", null ],99    [ "_viwCrtDta", "class_app_resources.html#a6f2e1fc0dddc3056016a77050cb68d2b", null ],100    [ "_winBkg", "class_app_resources.html#aae44ba4d3eabc06e83f3b866788de2bf", null ],101    [ "_winTitFnt", "class_app_resources.html#a9e25e79f2af5ae5f794d5542cdefe30e", null ],102    [ "_xCurrentPanelPosition", "class_app_resources.html#ae795c09b6f12254dbb216eada9d6750c", null ],103    [ "_xPanelPosition", "class_app_resources.html#a481b171e5cfbf10f46f4057f3655dd7b", null ],104    [ "_yCurrentPanelPosition", "class_app_resources.html#abfc864ab37fb2ed9fde42db870bcf6e0", null ],105    [ "_yPanelPosition", "class_app_resources.html#ad8e9cb1494da167d1b5a2bcc7928f328", null ]...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
