From bcd493e429b02e2d9340c6be6d363ae8829e2fb3 Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Mon, 16 Jan 2017 14:39:35 -0600 Subject: [PATCH 01/13] implement an 'init' and 'startup' method in mixins and utilize deferreds for async ops --- viewer/js/viewer/_ConfigMixin.js | 25 ++++++++-------------- viewer/js/viewer/_ControllerBase.js | 32 +++++++++++++++++++++-------- viewer/js/viewer/_LayoutMixin.js | 15 ++++++++++++++ viewer/js/viewer/_MapMixin.js | 23 ++++++++++++++++----- viewer/js/viewer/_WebMapMixin.js | 15 ++++++++++---- viewer/js/viewer/_WidgetsMixin.js | 23 +++++++++++++++++---- 6 files changed, 95 insertions(+), 38 deletions(-) diff --git a/viewer/js/viewer/_ConfigMixin.js b/viewer/js/viewer/_ConfigMixin.js index 430a22f8f..afbe4abe4 100644 --- a/viewer/js/viewer/_ConfigMixin.js +++ b/viewer/js/viewer/_ConfigMixin.js @@ -9,6 +9,13 @@ define([ ) { return declare(null, { + startup: function () { + this.inherited(arguments); + this.initConfigAsync().then( + lang.hitch(this, 'initConfigSuccess'), + lang.hitch(this, 'initConfigError') + ); + }, initConfigAsync: function () { var returnDeferred = new Deferred(); @@ -30,10 +37,6 @@ define([ initConfigSuccess: function (config) { this.config = config; - - // in _WidgetsMixin - this.createWidgets(['loading']); - if (config.isDebug) { window.app = this; //dev only } @@ -44,17 +47,7 @@ define([ defaultMode: config.defaultMapClickMode }; - // in _LayoutMixin - this.initLayout(); - - // in _WidgetsMixin - this.createWidgets(['layout']); - - // in _MapMixin - this.initMapAsync().then( - lang.hitch(this, 'initMapComplete'), - lang.hitch(this, 'initMapError') - ); + this.configDeferred.resolve(config); }, initConfigError: function (err) { @@ -64,4 +57,4 @@ define([ }); } }); -}); \ No newline at end of file +}); diff --git a/viewer/js/viewer/_ControllerBase.js b/viewer/js/viewer/_ControllerBase.js index 3863c9ff2..c524fb828 100644 --- a/viewer/js/viewer/_ControllerBase.js +++ b/viewer/js/viewer/_ControllerBase.js @@ -1,21 +1,35 @@ /*eslint no-console: 0*/ define([ 'dojo/_base/declare', - 'dojo/_base/lang' + 'dojo/_base/lang', + 'dojo/Deferred' ], function ( declare, - lang + lang, + Deferred ) { return declare(null, { + init: function () { + + // create a set of deferreds that can be resolved by mixins + // other mixins can also create deferreds in their relevent constructors + this.configDeferred = new Deferred(); - startup: function () { this.inherited(arguments); + }, - // in _ConfigMixin - this.initConfigAsync().then( - lang.hitch(this, 'initConfigSuccess'), - lang.hitch(this, 'initConfigError') - ); + startup: function () { + this.init(); + this.mapDeferred.then(function () { + console.log(' map deferred'); + }); + this.configDeferred.then(function () { + console.log(' config deferred'); + }); + this.layoutDeferred.then(function () { + console.log(' layout deferred'); + }); + this.inherited(arguments); }, //centralized error handler @@ -54,4 +68,4 @@ define([ return dest; } }); -}); \ No newline at end of file +}); diff --git a/viewer/js/viewer/_LayoutMixin.js b/viewer/js/viewer/_LayoutMixin.js index 7560e78e9..f4de2c880 100644 --- a/viewer/js/viewer/_LayoutMixin.js +++ b/viewer/js/viewer/_LayoutMixin.js @@ -11,6 +11,8 @@ define([ 'dojo/dom-class', 'dojo/dom-geometry', 'dojo/sniff', + 'dojo/Deferred', + 'dojo/promise/all', 'put-selector', @@ -33,6 +35,8 @@ define([ domClass, domGeom, has, + Deferred, + promiseAll, put, @@ -61,6 +65,14 @@ define([ } }, collapseButtons: {}, + init: function () { + this.inherited(arguments); + this.layoutDeferred = new Deferred(); + }, + startup: function () { + this.inherited(arguments); + promiseAll([this.configDeferred]).then(lang.hitch(this, 'initLayout')); + }, initLayout: function () { this.config.layout = this.config.layout || {}; @@ -69,6 +81,9 @@ define([ this.addTitles(); this.detectTouchDevices(); this.initPanes(); + + // resolve the layout deferred + this.layoutDeferred.resolve(); }, // add topics for subscribing and publishing diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index 48ebcc95c..492bfd877 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -5,6 +5,7 @@ define([ 'dojo/dom', 'dojo/_base/array', 'dojo/Deferred', + 'dojo/promise/all', 'esri/map', @@ -17,12 +18,23 @@ define([ dom, array, Deferred, + promiseAll, Map ) { return declare(null, { + init: function () { + this.inherited(arguments); + this.mapDeferred = new Deferred(); + }, + + startup: function () { + this.inherited(arguments); + promiseAll([this.configDeferred, this.layoutDeferred]).then(lang.hitch(this, 'initMapAsync')); + }, + initMapAsync: function () { var returnDeferred = new Deferred(); var returnWarnings = []; @@ -39,7 +51,7 @@ define([ if (this.config.webMapId) { if (this._initWebMap) { - mapDeferred = this._initWebMap(this.config.webMapId, container, this.config.webMapOptions); + // mapDeferred = this._initWebMap(this.config.webMapId, container, this.config.webMapOptions); } else { returnWarnings.push('The "_WebMapMixin" Controller Mixin is required to use a webmap'); mapDeferred.resolve(returnWarnings); @@ -195,7 +207,7 @@ define([ if (this.map) { // in _WidgetsMixin - this.createWidgets(['map', 'layer']); + // this.createWidgets(['map', 'layer']); this.map.on('resize', function (evt) { var pnt = evt.target.extent.getCenter(); @@ -205,10 +217,11 @@ define([ }); // in _LayoutsMixin - this.createPanes(); + // this.createPanes(); // in _WidgetsMixin - this.createWidgets(); + // this.createWidgets(); + this.mapDeferred.resolve(this.map); } }, @@ -234,4 +247,4 @@ define([ } } }); -}); \ No newline at end of file +}); diff --git a/viewer/js/viewer/_WebMapMixin.js b/viewer/js/viewer/_WebMapMixin.js index b24e4d0d4..a637c4094 100644 --- a/viewer/js/viewer/_WebMapMixin.js +++ b/viewer/js/viewer/_WebMapMixin.js @@ -2,6 +2,7 @@ define([ 'dojo/_base/declare', 'dojo/_base/lang', 'dojo/_base/array', + 'dojo/promise/all', 'esri/arcgis/utils', 'esri/units', @@ -12,6 +13,7 @@ define([ declare, lang, array, + promiseAll, arcgisUtils, units, @@ -19,14 +21,19 @@ define([ i18n ) { return declare(null, { + startup: function () { + this.inherited(arguments); + promiseAll([this.configDeferred, this.mapDeferred]).then(lang.hitch(this, '_initWebMap')); + }, - _initWebMap: function (webMapId, container, webMapOptions) { - webMapOptions = webMapOptions || {}; + _initWebMap: function () { + var webMapOptions = this.config.webMapOptions || {}; if (!webMapOptions.mapOptions && this.config.mapOptions) { webMapOptions.mapOptions = this.config.mapOptions; } + var container = dom.byId(this.config.layout.map) || 'mapCenter'; - var mapDeferred = arcgisUtils.createMap(webMapId, container, webMapOptions); + var mapDeferred = arcgisUtils.createMap(this.config.webMapId, container, webMapOptions); mapDeferred.then(lang.hitch(this, function (response) { this.webMap = { clickEventHandle: response.clickEventHandle, @@ -227,4 +234,4 @@ define([ } } }); -}); \ No newline at end of file +}); diff --git a/viewer/js/viewer/_WidgetsMixin.js b/viewer/js/viewer/_WidgetsMixin.js index 76bf85de1..0dacdc1da 100644 --- a/viewer/js/viewer/_WidgetsMixin.js +++ b/viewer/js/viewer/_WidgetsMixin.js @@ -34,6 +34,21 @@ define([ widgets: {}, widgetTypes: ['titlePane', 'contentPane', 'floating', 'domNode', 'invisible', 'map', 'layer', 'layout', 'loading'], + init: function () { + this.inherited(arguments); + this.configDeferred.then(lang.hitch(this, 'createWidgets', ['loading'])); + }, + startup: function () { + this.inherited(arguments); + this.configDeferred.then(lang.hitch(this, function () { + if (this.mapDeferred) { + this.mapDeferred.then(lang.hitch(this, 'createWidgets', ['map', 'layer'])); + } + if (this.layoutDeferred) { + this.layoutDeferred.then(lang.hitch(this, 'createWidgets', ['titlePane', 'contentPane', 'floating', 'domNode', 'invisible', 'layout'])); + } + })); + }, createWidgets: function (widgetTypes) { var widgets = [], @@ -45,7 +60,7 @@ define([ var widget = lang.clone(this.config.widgets[key]); widget.widgetKey = widget.widgetKey || widget.id || key; if (widget.include && (!this.widgets[widget.widgetKey]) && (array.indexOf(widgetTypes, widget.type) >= 0)) { - widget.position = (typeof (widget.position) !== 'undefined') ? widget.position : 10000; + widget.position = (typeof(widget.position) !== 'undefined') ? widget.position : 10000; if ((widget.type === 'titlePane' || widget.type === 'contentPane') && !widget.placeAt) { widget.placeAt = 'left'; } @@ -122,7 +137,7 @@ define([ } // 2 ways to use require to accommodate widgets that may have an optional separate configuration file - if (typeof (widgetConfig.options) === 'string') { + if (typeof(widgetConfig.options) === 'string') { require([widgetConfig.options, widgetConfig.path], lang.hitch(this, 'createWidget', widgetConfig)); } else { require([widgetConfig.path], lang.hitch(this, 'createWidget', widgetConfig, widgetConfig.options)); @@ -220,7 +235,7 @@ define([ options.id = parentId; } var placeAt = widgetConfig.placeAt; - if (typeof (placeAt) === 'string') { + if (typeof(placeAt) === 'string') { placeAt = this.panes[placeAt]; } if (!placeAt) { @@ -261,7 +276,7 @@ define([ var placeAt = widgetConfig.placeAt; if (!placeAt) { placeAt = this.panes.left; - } else if (typeof (placeAt) === 'string') { + } else if (typeof(placeAt) === 'string') { placeAt = this.panes[placeAt]; } if (placeAt) { From 7cb59c3be8e1b12983c7dbc78b2af397925b8605 Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Wed, 18 Jan 2017 22:13:48 -0600 Subject: [PATCH 02/13] async loading of loadConfig and preStartup methods --- viewer/js/config/app.js | 13 ++--- viewer/js/config/viewer.js | 12 ++++- viewer/js/viewer/_ConfigMixin.js | 43 +++++++++++++--- viewer/js/viewer/_ControllerBase.js | 78 +++++++++++++++++++++-------- viewer/js/viewer/_LayoutMixin.js | 18 +++---- viewer/js/viewer/_MapMixin.js | 28 +++-------- viewer/js/viewer/_WebMapMixin.js | 4 +- viewer/js/viewer/_WidgetsMixin.js | 62 +++++++++++++++++------ 8 files changed, 176 insertions(+), 82 deletions(-) diff --git a/viewer/js/config/app.js b/viewer/js/config/app.js index dc36e5e1c..15bbaca98 100644 --- a/viewer/js/config/app.js +++ b/viewer/js/config/app.js @@ -49,15 +49,16 @@ //_MyCustomMixin ) { - var controller = new (declare([ - _ControllerBase, - _ConfigMixin, + var App = declare([ _LayoutMixin, _MapMixin, _WidgetsMixin, - _WebMapMixin - ]))(); - controller.startup(); + _WebMapMixin, + _ConfigMixin, + _ControllerBase + ]); + var app = new App(); + app.startup(); }); })(); diff --git a/viewer/js/config/viewer.js b/viewer/js/config/viewer.js index 1ea172b9f..d1f45deeb 100644 --- a/viewer/js/config/viewer.js +++ b/viewer/js/config/viewer.js @@ -78,7 +78,7 @@ define([ sliderStyle: 'small' }, - //webMapId: 'ef9c7fbda731474d98647bebb4b33c20', // High Cost Mortgage + webMapId: '880a967872114b44a63c207df10e0a75', // High Cost Mortgage // webMapOptions: {}, // panes: { @@ -273,6 +273,16 @@ define([ }], // set include:true to load. For titlePane type set position the the desired order in the sidebar widgets: { + // a widget that loads and runs before the app + // loader: { + // type: 'loading', + // path: 'dijit/_WidgetBase', + // options: { + // constructor: function () { + // alert('Preload!'); + // } + // } + // }, growler: { include: true, id: 'growler', diff --git a/viewer/js/viewer/_ConfigMixin.js b/viewer/js/viewer/_ConfigMixin.js index afbe4abe4..10a7929fe 100644 --- a/viewer/js/viewer/_ConfigMixin.js +++ b/viewer/js/viewer/_ConfigMixin.js @@ -9,12 +9,41 @@ define([ ) { return declare(null, { - startup: function () { - this.inherited(arguments); - this.initConfigAsync().then( - lang.hitch(this, 'initConfigSuccess'), - lang.hitch(this, 'initConfigError') - ); + loadConfig: function (wait) { + + // this will be used to make any inherited methods 'wait' + var waitDeferred; + + if (wait) { + waitDeferred = new Deferred(); + + // if we need to wait for a previous deferred + // wait for it, + wait.then(lang.hitch(this, function () { + + // load the config + this.initConfigAsync().then(lang.hitch(this, function () { + + // do some stuff + this.initConfigSuccess(arguments); + + // resolve + waitDeferred.resolve(); + }), + lang.hitch(this, 'initConfigError') + ); + + })); + } else { + + waitDeferred = this.initConfigAsync(); + waitDeferred.then( + lang.hitch(this, 'initConfigSuccess'), + lang.hitch(this, 'initConfigError') + ); + } + // call any inherited methods or return a deferred + return this.inherited(arguments, [waitDeferred]) || waitDeferred; }, initConfigAsync: function () { @@ -46,8 +75,6 @@ define([ current: config.defaultMapClickMode, defaultMode: config.defaultMapClickMode }; - - this.configDeferred.resolve(config); }, initConfigError: function (err) { diff --git a/viewer/js/viewer/_ControllerBase.js b/viewer/js/viewer/_ControllerBase.js index c524fb828..f9727882f 100644 --- a/viewer/js/viewer/_ControllerBase.js +++ b/viewer/js/viewer/_ControllerBase.js @@ -4,38 +4,74 @@ define([ 'dojo/_base/lang', 'dojo/Deferred' ], function ( - declare, - lang, - Deferred + declare, lang, Deferred ) { return declare(null, { - init: function () { + /** + * A method run before anything else, can be inherited by mixins to + * load and process the config sync or async + * @return {undefined | Deferred} If the operation is async it should return + * a deferred, otherwise it should return the value of `this.inherited(arguments)` + */ + loadConfig: function () { + return this.inherited(arguments); + }, + /** + * A method run after the config is loaded but before startup is called + * on mixins + * @return {undefined | Deferred} If the operation is async it should return + * a deferred, otherwise it should return the value of `this.inherited(arguments)` + */ + preStartup: function () { + return this.inherited(arguments); + }, + /** + * executes an array of asynchronous methods synchronously + * @param {Array} methods The array of functions to execute + * @param {Deferred} deferred A deferred created inside the method and resolved once all methods are complete + * @return {Deferred} A deferred resolved once all methods are executed + */ + executeSync: function (methods, deferred) { + deferred = deferred || new Deferred(); + + // if our list is empty, resolve the deferred and quit + if (!methods || !methods.length) { + deferred.resolve(); + return deferred; + } - // create a set of deferreds that can be resolved by mixins - // other mixins can also create deferreds in their relevent constructors - this.configDeferred = new Deferred(); + // execute and remove the method from the list + var result = lang.hitch(this, methods.splice(0, 1)[0])(); - this.inherited(arguments); - }, + // execute our next function once this one completes + if (result) { + result.then(lang.hitch(this, 'executeSync', methods, deferred)); + } else { + this.executeSync(methods, deferred); + } + return deferred; + }, startup: function () { - this.init(); - this.mapDeferred.then(function () { - console.log(' map deferred'); - }); - this.configDeferred.then(function () { - console.log(' config deferred'); - }); - this.layoutDeferred.then(function () { - console.log(' layout deferred'); - }); - this.inherited(arguments); + + var inherited = this.getInherited(arguments); + this.executeSync([ + this.loadConfig, + this.preStartup + ]).then(lang.hitch(this, function () { + console.log(this); + + // start up the mixin chain + inherited.apply(this); + })); + + }, //centralized error handler handleError: function (options) { if (this.config.isDebug) { - if (typeof (console) === 'object') { + if (typeof(console) === 'object') { for (var option in options) { if (options.hasOwnProperty(option)) { console.log(option, options[option]); diff --git a/viewer/js/viewer/_LayoutMixin.js b/viewer/js/viewer/_LayoutMixin.js index f4de2c880..0b1657a16 100644 --- a/viewer/js/viewer/_LayoutMixin.js +++ b/viewer/js/viewer/_LayoutMixin.js @@ -65,16 +65,12 @@ define([ } }, collapseButtons: {}, - init: function () { - this.inherited(arguments); + preStartup: function () { this.layoutDeferred = new Deferred(); - }, - startup: function () { - this.inherited(arguments); - promiseAll([this.configDeferred]).then(lang.hitch(this, 'initLayout')); + return this.inherited(arguments); }, - initLayout: function () { + startup: function () { this.config.layout = this.config.layout || {}; this.addTopics(); @@ -84,6 +80,7 @@ define([ // resolve the layout deferred this.layoutDeferred.resolve(); + this.inherited(arguments); }, // add topics for subscribing and publishing @@ -186,7 +183,7 @@ define([ panes[key] = lang.mixin(this.defaultPanes[key], panes[key]); } } - // where to place the buttons + // where to place the buttons // either the center map pane or the outer pane? this.collapseButtonsPane = this.config.collapseButtonsPane || 'outer'; @@ -266,7 +263,10 @@ define([ } if (!suppressEvent) { - topic.publish('viewer/onTogglePane', {pane: id, show: show}); + topic.publish('viewer/onTogglePane', { + pane: id, + show: show + }); } } } diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index 492bfd877..1c0eeab15 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -25,14 +25,14 @@ define([ return declare(null, { - init: function () { - this.inherited(arguments); + preStartup: function () { this.mapDeferred = new Deferred(); + return this.inherited(arguments); }, startup: function () { this.inherited(arguments); - promiseAll([this.configDeferred, this.layoutDeferred]).then(lang.hitch(this, 'initMapAsync')); + this.layoutDeferred.then(lang.hitch(this, 'initMapAsync')); }, initMapAsync: function () { @@ -42,6 +42,7 @@ define([ this._createMap(returnWarnings).then( lang.hitch(this, '_createMapResult', returnDeferred, returnWarnings) ); + returnDeferred.then(lang.hitch(this, 'initMapComplete')); return returnDeferred; }, @@ -49,17 +50,8 @@ define([ var mapDeferred = new Deferred(), container = dom.byId(this.config.layout.map) || 'mapCenter'; - if (this.config.webMapId) { - if (this._initWebMap) { - // mapDeferred = this._initWebMap(this.config.webMapId, container, this.config.webMapOptions); - } else { - returnWarnings.push('The "_WebMapMixin" Controller Mixin is required to use a webmap'); - mapDeferred.resolve(returnWarnings); - } - } else { - this.map = new Map(container, this.config.mapOptions); - mapDeferred.resolve(returnWarnings); - } + this.map = new Map(container, this.config.mapOptions); + mapDeferred.resolve(returnWarnings); return mapDeferred; }, @@ -206,8 +198,6 @@ define([ } if (this.map) { - // in _WidgetsMixin - // this.createWidgets(['map', 'layer']); this.map.on('resize', function (evt) { var pnt = evt.target.extent.getCenter(); @@ -216,11 +206,7 @@ define([ }, 100); }); - // in _LayoutsMixin - // this.createPanes(); - - // in _WidgetsMixin - // this.createWidgets(); + // resolve the map deferred this.mapDeferred.resolve(this.map); } diff --git a/viewer/js/viewer/_WebMapMixin.js b/viewer/js/viewer/_WebMapMixin.js index a637c4094..9bd9ad373 100644 --- a/viewer/js/viewer/_WebMapMixin.js +++ b/viewer/js/viewer/_WebMapMixin.js @@ -3,6 +3,7 @@ define([ 'dojo/_base/lang', 'dojo/_base/array', 'dojo/promise/all', + 'dojo/dom', 'esri/arcgis/utils', 'esri/units', @@ -14,6 +15,7 @@ define([ lang, array, promiseAll, + dom, arcgisUtils, units, @@ -23,7 +25,7 @@ define([ return declare(null, { startup: function () { this.inherited(arguments); - promiseAll([this.configDeferred, this.mapDeferred]).then(lang.hitch(this, '_initWebMap')); + this.mapDeferred.then(lang.hitch(this, '_initWebMap')); }, _initWebMap: function () { diff --git a/viewer/js/viewer/_WidgetsMixin.js b/viewer/js/viewer/_WidgetsMixin.js index 0dacdc1da..75c6fdfd1 100644 --- a/viewer/js/viewer/_WidgetsMixin.js +++ b/viewer/js/viewer/_WidgetsMixin.js @@ -2,6 +2,8 @@ define([ 'dojo/_base/declare', 'dojo/_base/array', 'dojo/_base/lang', + 'dojo/promise/all', + 'dojo/Deferred', 'put-selector', @@ -15,6 +17,8 @@ define([ declare, array, lang, + promiseAll, + Deferred, put, @@ -34,20 +38,36 @@ define([ widgets: {}, widgetTypes: ['titlePane', 'contentPane', 'floating', 'domNode', 'invisible', 'map', 'layer', 'layout', 'loading'], - init: function () { - this.inherited(arguments); - this.configDeferred.then(lang.hitch(this, 'createWidgets', ['loading'])); + preStartup: function (wait) { + + var waitDeferred; + if (wait) { + waitDeferred = new Deferred(); + + wait.then(lang.hitch(this, function () { + // load loading widgets + promiseAll(this.createWidgets(['loading'])).then(waitDeferred.resolve); + })); + } else { + var deferreds = this.createWidgets(['loading']); + if (deferreds.length) { + waitDeferred = promiseAll(deferreds); + } + } + + return this.inherited(arguments) || waitDeferred; }, startup: function () { this.inherited(arguments); - this.configDeferred.then(lang.hitch(this, function () { - if (this.mapDeferred) { - this.mapDeferred.then(lang.hitch(this, 'createWidgets', ['map', 'layer'])); - } - if (this.layoutDeferred) { - this.layoutDeferred.then(lang.hitch(this, 'createWidgets', ['titlePane', 'contentPane', 'floating', 'domNode', 'invisible', 'layout'])); - } - })); + if (this.mapDeferred) { + this.mapDeferred.then(lang.hitch(this, 'createWidgets', ['map', 'layer'])); + } + if (this.layoutDeferred) { + promiseAll([this.mapDeferred, this.layoutDeferred]) + .then(lang.hitch(this, + 'createWidgets', ['titlePane', 'contentPane', 'floating', 'domNode', 'invisible', 'layout'] + )); + } }, createWidgets: function (widgetTypes) { @@ -97,10 +117,14 @@ define([ paneWidgets.sort(function (a, b) { return a.position - b.position; }); - + var deferreds = []; array.forEach(paneWidgets, function (paneWidget, i) { - this.widgetLoader(paneWidget, i); + var def = this.widgetLoader(paneWidget, i); + if (def) { + deferreds.push(def); + } }, this); + return deferreds; }, widgetLoader: function (widgetConfig, position) { @@ -137,11 +161,19 @@ define([ } // 2 ways to use require to accommodate widgets that may have an optional separate configuration file + var deferred = new Deferred(); if (typeof(widgetConfig.options) === 'string') { - require([widgetConfig.options, widgetConfig.path], lang.hitch(this, 'createWidget', widgetConfig)); + require([widgetConfig.options, widgetConfig.path], lang.hitch(this, function (options, WidgetClass) { + deferred.resolve(); + this.createWidget(widgetConfig, options, WidgetClass); + })); } else { - require([widgetConfig.path], lang.hitch(this, 'createWidget', widgetConfig, widgetConfig.options)); + require([widgetConfig.path], lang.hitch(this, function (WidgetClass) { + deferred.resolve(); + this.createWidget(widgetConfig, widgetConfig.options, WidgetClass); + })); } + return deferred; }, createWidget: function (widgetConfig, options, WidgetClass) { From 6f319d719f8e35554a59bbea050ac18d3a8ad844 Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Thu, 19 Jan 2017 19:31:02 -0600 Subject: [PATCH 03/13] use createMap method to allow mixins to modify map before resolving deferred --- viewer/js/viewer/_MapMixin.js | 18 +++++++++++++++--- viewer/js/viewer/_WebMapMixin.js | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index 1c0eeab15..b69ca1c5a 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -39,19 +39,31 @@ define([ var returnDeferred = new Deferred(); var returnWarnings = []; - this._createMap(returnWarnings).then( + this.createMap(returnWarnings).then( lang.hitch(this, '_createMapResult', returnDeferred, returnWarnings) ); returnDeferred.then(lang.hitch(this, 'initMapComplete')); return returnDeferred; }, - _createMap: function (returnWarnings) { + createMap: function (returnWarnings) { + var returnWarnings = []; var mapDeferred = new Deferred(), container = dom.byId(this.config.layout.map) || 'mapCenter'; this.map = new Map(container, this.config.mapOptions); - mapDeferred.resolve(returnWarnings); + + // let some other mixins modify or add map items async + var wait = this.inherited(arguments); + if (wait) { + wait.then(function (warnings) { + // are warnings passed? + // returnWarnings.push(warnings); + mapDeferred.resolve(returnWarnings); + }); + } else { + mapDeferred.resolve(returnWarnings); + } return mapDeferred; }, diff --git a/viewer/js/viewer/_WebMapMixin.js b/viewer/js/viewer/_WebMapMixin.js index 9bd9ad373..2731135b8 100644 --- a/viewer/js/viewer/_WebMapMixin.js +++ b/viewer/js/viewer/_WebMapMixin.js @@ -25,10 +25,10 @@ define([ return declare(null, { startup: function () { this.inherited(arguments); - this.mapDeferred.then(lang.hitch(this, '_initWebMap')); + // this.mapDeferred.then(lang.hitch(this, '_initWebMap')); }, - _initWebMap: function () { + createMap: function () { var webMapOptions = this.config.webMapOptions || {}; if (!webMapOptions.mapOptions && this.config.mapOptions) { webMapOptions.mapOptions = this.config.mapOptions; From 76ef0dbe8f4d3b08447de14c751fa6c9cfe11773 Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Thu, 19 Jan 2017 19:46:18 -0600 Subject: [PATCH 04/13] override createMap method if mixin returns a deferred - as a result, order is not important with map/webmap mixins --- viewer/js/config/app.js | 2 +- viewer/js/viewer/_MapMixin.js | 10 +++++++++- viewer/js/viewer/_WebMapMixin.js | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/viewer/js/config/app.js b/viewer/js/config/app.js index 15bbaca98..8db0d0fa6 100644 --- a/viewer/js/config/app.js +++ b/viewer/js/config/app.js @@ -51,10 +51,10 @@ ) { var App = declare([ _LayoutMixin, - _MapMixin, _WidgetsMixin, _WebMapMixin, + _MapMixin, _ConfigMixin, _ControllerBase ]); diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index b69ca1c5a..e161a759f 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -47,6 +47,14 @@ define([ }, createMap: function (returnWarnings) { + + // mixins override the default createMap method and return a deferred + var result = this.inherited(arguments); + if (result) { + return result; + } + + // otherwise we can create the map var returnWarnings = []; var mapDeferred = new Deferred(), container = dom.byId(this.config.layout.map) || 'mapCenter'; @@ -54,7 +62,7 @@ define([ this.map = new Map(container, this.config.mapOptions); // let some other mixins modify or add map items async - var wait = this.inherited(arguments); + wait = this.inherited(arguments) || wait; if (wait) { wait.then(function (warnings) { // are warnings passed? diff --git a/viewer/js/viewer/_WebMapMixin.js b/viewer/js/viewer/_WebMapMixin.js index 2731135b8..bdfbf3a14 100644 --- a/viewer/js/viewer/_WebMapMixin.js +++ b/viewer/js/viewer/_WebMapMixin.js @@ -29,6 +29,7 @@ define([ }, createMap: function () { + console.log('web map mixin'); var webMapOptions = this.config.webMapOptions || {}; if (!webMapOptions.mapOptions && this.config.mapOptions) { webMapOptions.mapOptions = this.config.mapOptions; From 705ecb6277f899b8ce5f046d08271ef5d70e87d1 Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Thu, 19 Jan 2017 19:48:04 -0600 Subject: [PATCH 05/13] remove console.log --- viewer/js/viewer/_WebMapMixin.js | 1 - 1 file changed, 1 deletion(-) diff --git a/viewer/js/viewer/_WebMapMixin.js b/viewer/js/viewer/_WebMapMixin.js index bdfbf3a14..2731135b8 100644 --- a/viewer/js/viewer/_WebMapMixin.js +++ b/viewer/js/viewer/_WebMapMixin.js @@ -29,7 +29,6 @@ define([ }, createMap: function () { - console.log('web map mixin'); var webMapOptions = this.config.webMapOptions || {}; if (!webMapOptions.mapOptions && this.config.mapOptions) { webMapOptions.mapOptions = this.config.mapOptions; From 44caebffc929ee579c5f1cd1d99089e825d6308f Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Thu, 19 Jan 2017 20:06:38 -0600 Subject: [PATCH 06/13] add documentation and fix typo --- viewer/js/config/app.js | 16 ++++++++++++++-- viewer/js/viewer/_MapMixin.js | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/viewer/js/config/app.js b/viewer/js/config/app.js index 8db0d0fa6..fcf63aefe 100644 --- a/viewer/js/config/app.js +++ b/viewer/js/config/app.js @@ -50,12 +50,24 @@ ) { var App = declare([ + + // add custom mixins here...note order may be important and + // overriding certain methods incorrectly may break the app + // First on the list are last called last, for instance the startup + // method on _ControllerBase is called FIRST, and _LayoutMixin is called LAST + // for the most part they are interchangeable, except _ConfigMixin + // and _ControllerBase + // _LayoutMixin, _WidgetsMixin, - - _WebMapMixin, + // _WebMapMixin, _MapMixin, + + // configMixin should be right before _ControllerBase so it is + // called first to initialize the config object _ConfigMixin, + + // controller base needs to be last _ControllerBase ]); var app = new App(); diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index e161a759f..f2355ee7d 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -62,7 +62,7 @@ define([ this.map = new Map(container, this.config.mapOptions); // let some other mixins modify or add map items async - wait = this.inherited(arguments) || wait; + var wait = this.inherited(arguments); if (wait) { wait.then(function (warnings) { // are warnings passed? From f3cf7784996ee2dd6b7d9dcadbbe09dc14a6aa5c Mon Sep 17 00:00:00 2001 From: roemhildtg Date: Wed, 1 Feb 2017 11:00:03 -0600 Subject: [PATCH 07/13] fix lint errors --- viewer/js/config/app.js | 8 ++++---- viewer/js/viewer/_MapMixin.js | 3 +-- viewer/js/viewer/_WidgetsMixin.js | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/viewer/js/config/app.js b/viewer/js/config/app.js index fcf63aefe..486259e58 100644 --- a/viewer/js/config/app.js +++ b/viewer/js/config/app.js @@ -31,9 +31,9 @@ 'viewer/_ConfigMixin', // manage the Configuration 'viewer/_LayoutMixin', // build and manage the Page Layout and User Interface 'viewer/_MapMixin', // build and manage the Map - 'viewer/_WidgetsMixin', // build and manage the Widgets + 'viewer/_WidgetsMixin' // build and manage the Widgets - 'viewer/_WebMapMixin' // for WebMaps + // 'viewer/_WebMapMixin' // for WebMaps //'config/_customMixin' ], function ( @@ -43,9 +43,9 @@ _ConfigMixin, _LayoutMixin, _MapMixin, - _WidgetsMixin, + _WidgetsMixin - _WebMapMixin + // _WebMapMixin //_MyCustomMixin ) { diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index f2355ee7d..05ed96a7f 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -55,7 +55,6 @@ define([ } // otherwise we can create the map - var returnWarnings = []; var mapDeferred = new Deferred(), container = dom.byId(this.config.layout.map) || 'mapCenter'; @@ -64,7 +63,7 @@ define([ // let some other mixins modify or add map items async var wait = this.inherited(arguments); if (wait) { - wait.then(function (warnings) { + wait.then(function () { // are warnings passed? // returnWarnings.push(warnings); mapDeferred.resolve(returnWarnings); diff --git a/viewer/js/viewer/_WidgetsMixin.js b/viewer/js/viewer/_WidgetsMixin.js index 44661c422..e78179b43 100644 --- a/viewer/js/viewer/_WidgetsMixin.js +++ b/viewer/js/viewer/_WidgetsMixin.js @@ -50,7 +50,7 @@ define([ })); } else { var deferreds = this.createWidgets(['loading']); - if (deferreds.length) { + if (deferreds && deferreds.length) { waitDeferred = promiseAll(deferreds); } } @@ -139,7 +139,7 @@ define([ source: 'Controller', error: 'Widget type "' + widgetConfig.type + '" (' + widgetConfig.title + ') at position ' + position + ' is not supported.' }); - return; + return null; } if (position) { From 5c6b537863f16321de708109539e69b375d821f0 Mon Sep 17 00:00:00 2001 From: roemhildtg Date: Wed, 1 Feb 2017 11:26:28 -0600 Subject: [PATCH 08/13] call `createPanes` when `mapDeferred` resolves --- viewer/js/viewer/_LayoutMixin.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/viewer/js/viewer/_LayoutMixin.js b/viewer/js/viewer/_LayoutMixin.js index 0b1657a16..d807956d1 100644 --- a/viewer/js/viewer/_LayoutMixin.js +++ b/viewer/js/viewer/_LayoutMixin.js @@ -77,6 +77,8 @@ define([ this.addTitles(); this.detectTouchDevices(); this.initPanes(); + + this.mapDeferred.then(lang.hitch(this, 'createPanes')); // resolve the layout deferred this.layoutDeferred.resolve(); From 5c65783f9f61fc99b105e5c453e40681df2fc3e2 Mon Sep 17 00:00:00 2001 From: roemhildtg Date: Wed, 1 Feb 2017 15:30:49 -0600 Subject: [PATCH 09/13] rename preStartup to postConfig for clarity --- viewer/js/viewer/_ControllerBase.js | 41 ++++++++++++++++++----------- viewer/js/viewer/_LayoutMixin.js | 4 +-- viewer/js/viewer/_MapMixin.js | 2 +- viewer/js/viewer/_WidgetsMixin.js | 2 +- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/viewer/js/viewer/_ControllerBase.js b/viewer/js/viewer/_ControllerBase.js index f9727882f..20958b0d8 100644 --- a/viewer/js/viewer/_ControllerBase.js +++ b/viewer/js/viewer/_ControllerBase.js @@ -7,6 +7,7 @@ define([ declare, lang, Deferred ) { return declare(null, { + /** * A method run before anything else, can be inherited by mixins to * load and process the config sync or async @@ -22,9 +23,32 @@ define([ * @return {undefined | Deferred} If the operation is async it should return * a deferred, otherwise it should return the value of `this.inherited(arguments)` */ - preStartup: function () { + postConfig: function () { return this.inherited(arguments); }, + /** + * Start the application mixin chain, once the + * startupDeferred is resolved + * @return {undefined} + */ + startup: function () { + + // cache the inherited + var inherited = this.getInherited(arguments); + + // load config and process it + this.startupDeferred = this.executeSync([ + this.loadConfig, + this.postConfig + ]); + + // wait for any loading to complete + this.startupDeferred.then(lang.hitch(this, function () { + + // start up the mixin chain + inherited.apply(this); + })); + }, /** * executes an array of asynchronous methods synchronously * @param {Array} methods The array of functions to execute @@ -51,21 +75,6 @@ define([ } return deferred; - }, - startup: function () { - - var inherited = this.getInherited(arguments); - this.executeSync([ - this.loadConfig, - this.preStartup - ]).then(lang.hitch(this, function () { - console.log(this); - - // start up the mixin chain - inherited.apply(this); - })); - - }, //centralized error handler diff --git a/viewer/js/viewer/_LayoutMixin.js b/viewer/js/viewer/_LayoutMixin.js index d807956d1..fa7e53630 100644 --- a/viewer/js/viewer/_LayoutMixin.js +++ b/viewer/js/viewer/_LayoutMixin.js @@ -65,7 +65,7 @@ define([ } }, collapseButtons: {}, - preStartup: function () { + postConfig: function () { this.layoutDeferred = new Deferred(); return this.inherited(arguments); }, @@ -77,7 +77,7 @@ define([ this.addTitles(); this.detectTouchDevices(); this.initPanes(); - + this.mapDeferred.then(lang.hitch(this, 'createPanes')); // resolve the layout deferred diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index 05ed96a7f..617021a19 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -25,7 +25,7 @@ define([ return declare(null, { - preStartup: function () { + postConfig: function () { this.mapDeferred = new Deferred(); return this.inherited(arguments); }, diff --git a/viewer/js/viewer/_WidgetsMixin.js b/viewer/js/viewer/_WidgetsMixin.js index e78179b43..de8ab196c 100644 --- a/viewer/js/viewer/_WidgetsMixin.js +++ b/viewer/js/viewer/_WidgetsMixin.js @@ -38,7 +38,7 @@ define([ widgets: {}, widgetTypes: ['titlePane', 'contentPane', 'floating', 'domNode', 'invisible', 'map', 'layer', 'layout', 'loading'], - preStartup: function (wait) { + postConfig: function (wait) { var waitDeferred; if (wait) { From 9300ebb8b5f6d0a8eacffbea5b0a829f403a454a Mon Sep 17 00:00:00 2001 From: roemhildtg Date: Wed, 1 Feb 2017 15:43:20 -0600 Subject: [PATCH 10/13] reset viewer.js to develop --- viewer/js/config/viewer.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/viewer/js/config/viewer.js b/viewer/js/config/viewer.js index 75cd8e984..f7c7a8c34 100644 --- a/viewer/js/config/viewer.js +++ b/viewer/js/config/viewer.js @@ -78,7 +78,7 @@ define([ sliderStyle: 'small' }, - webMapId: '880a967872114b44a63c207df10e0a75', // High Cost Mortgage + //webMapId: 'ef9c7fbda731474d98647bebb4b33c20', // High Cost Mortgage // webMapOptions: {}, // panes: { @@ -273,16 +273,6 @@ define([ }], // set include:true to load. For titlePane type set position the the desired order in the sidebar widgets: { - // a widget that loads and runs before the app - // loader: { - // type: 'loading', - // path: 'dijit/_WidgetBase', - // options: { - // constructor: function () { - // alert('Preload!'); - // } - // } - // }, growler: { include: true, id: 'growler', From 94baf8b409ac40793d6acdab88ef4496f515593f Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Sat, 11 Feb 2017 11:56:33 -0600 Subject: [PATCH 11/13] Cleanup /~https://github.com/cmv/cmv-app/pull/666 --- viewer/js/config/app.js | 6 +++--- viewer/js/viewer/_LayoutMixin.js | 2 -- viewer/js/viewer/_MapMixin.js | 6 +++--- viewer/js/viewer/_WebMapMixin.js | 2 -- viewer/js/viewer/_WidgetsMixin.js | 6 ++---- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/viewer/js/config/app.js b/viewer/js/config/app.js index fcf63aefe..c5870c5e4 100644 --- a/viewer/js/config/app.js +++ b/viewer/js/config/app.js @@ -31,9 +31,9 @@ 'viewer/_ConfigMixin', // manage the Configuration 'viewer/_LayoutMixin', // build and manage the Page Layout and User Interface 'viewer/_MapMixin', // build and manage the Map - 'viewer/_WidgetsMixin', // build and manage the Widgets + 'viewer/_WidgetsMixin' // build and manage the Widgets - 'viewer/_WebMapMixin' // for WebMaps + // 'viewer/_WebMapMixin' // for WebMaps //'config/_customMixin' ], function ( @@ -45,7 +45,7 @@ _MapMixin, _WidgetsMixin, - _WebMapMixin + // _WebMapMixin //_MyCustomMixin ) { diff --git a/viewer/js/viewer/_LayoutMixin.js b/viewer/js/viewer/_LayoutMixin.js index 0b1657a16..f415e7baf 100644 --- a/viewer/js/viewer/_LayoutMixin.js +++ b/viewer/js/viewer/_LayoutMixin.js @@ -12,7 +12,6 @@ define([ 'dojo/dom-geometry', 'dojo/sniff', 'dojo/Deferred', - 'dojo/promise/all', 'put-selector', @@ -36,7 +35,6 @@ define([ domGeom, has, Deferred, - promiseAll, put, diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index f2355ee7d..97062b582 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -55,7 +55,6 @@ define([ } // otherwise we can create the map - var returnWarnings = []; var mapDeferred = new Deferred(), container = dom.byId(this.config.layout.map) || 'mapCenter'; @@ -65,8 +64,9 @@ define([ var wait = this.inherited(arguments); if (wait) { wait.then(function (warnings) { - // are warnings passed? - // returnWarnings.push(warnings); + if (warnings) { + returnWarnings = returnWarnings.concat(warnings); + } mapDeferred.resolve(returnWarnings); }); } else { diff --git a/viewer/js/viewer/_WebMapMixin.js b/viewer/js/viewer/_WebMapMixin.js index 2731135b8..9a4fcd1d4 100644 --- a/viewer/js/viewer/_WebMapMixin.js +++ b/viewer/js/viewer/_WebMapMixin.js @@ -2,7 +2,6 @@ define([ 'dojo/_base/declare', 'dojo/_base/lang', 'dojo/_base/array', - 'dojo/promise/all', 'dojo/dom', 'esri/arcgis/utils', @@ -14,7 +13,6 @@ define([ declare, lang, array, - promiseAll, dom, arcgisUtils, diff --git a/viewer/js/viewer/_WidgetsMixin.js b/viewer/js/viewer/_WidgetsMixin.js index 75c6fdfd1..e1bdeb5bf 100644 --- a/viewer/js/viewer/_WidgetsMixin.js +++ b/viewer/js/viewer/_WidgetsMixin.js @@ -64,9 +64,7 @@ define([ } if (this.layoutDeferred) { promiseAll([this.mapDeferred, this.layoutDeferred]) - .then(lang.hitch(this, - 'createWidgets', ['titlePane', 'contentPane', 'floating', 'domNode', 'invisible', 'layout'] - )); + .then(lang.hitch(this, 'createWidgets')); } }, @@ -139,7 +137,7 @@ define([ source: 'Controller', error: 'Widget type "' + widgetConfig.type + '" (' + widgetConfig.title + ') at position ' + position + ' is not supported.' }); - return; + return null; } if (position) { From ce28af273926ad0405544eee02ee65d2876fca61 Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Sat, 11 Feb 2017 15:10:45 -0600 Subject: [PATCH 12/13] pass null to create 'all' widgets --- viewer/js/viewer/_WidgetsMixin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viewer/js/viewer/_WidgetsMixin.js b/viewer/js/viewer/_WidgetsMixin.js index 114d1ea2e..8ab99d897 100644 --- a/viewer/js/viewer/_WidgetsMixin.js +++ b/viewer/js/viewer/_WidgetsMixin.js @@ -64,7 +64,7 @@ define([ } if (this.layoutDeferred) { promiseAll([this.mapDeferred, this.layoutDeferred]) - .then(lang.hitch(this, 'createWidgets')); + .then(lang.hitch(this, 'createWidgets', null)); } }, From dd2f8dccdd7345d8a249913b9139b4eb85650d93 Mon Sep 17 00:00:00 2001 From: Gregg Roemhildt Date: Sat, 11 Feb 2017 15:35:51 -0600 Subject: [PATCH 13/13] remove extra promiseAll reference --- viewer/js/viewer/_MapMixin.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/viewer/js/viewer/_MapMixin.js b/viewer/js/viewer/_MapMixin.js index 55130e787..71e658d0a 100644 --- a/viewer/js/viewer/_MapMixin.js +++ b/viewer/js/viewer/_MapMixin.js @@ -5,7 +5,6 @@ define([ 'dojo/dom', 'dojo/_base/array', 'dojo/Deferred', - 'dojo/promise/all', 'esri/map', @@ -18,7 +17,6 @@ define([ dom, array, Deferred, - promiseAll, Map ) {