define(['dojo/_base/declare', 'dojo/_base/lang', 'dojo/_base/array', 'dojo/_base/html', 'dojo/Deferred', 'dojo/topic', 'dojo/Evented', 'dojo/on', 'dojo/aspect', 'dojo/json', 'dojo/query', 'dojo/request/xhr', 'dojo/promise/all', 'dijit/registry', './utils', './dijit/Message' ], function(declare, lang, array, html, Deferred, topic, Evented, on, aspect, json, query, xhr, all, registry, utils, Message) { var instance = null, clazz = declare(Evented, { constructor: function() { //the loaded widget list this.loaded = []; //action is triggered, but the widget has not been loaded //{id: widgetId, action: {}} this.missedActions = []; this.activeWidget = null; if(window.isBuilder){ topic.subscribe("app/mapLoaded", lang.hitch(this, this._onMapLoaded)); topic.subscribe("app/mapChanged", lang.hitch(this, this._onMapChanged)); }else{ topic.subscribe("mapLoaded", lang.hitch(this, this._onMapLoaded)); topic.subscribe("mapChanged", lang.hitch(this, this._onMapChanged)); } if(window.isBuilder){ topic.subscribe("app/sceneViewLoaded", lang.hitch(this, this._onSceneViewLoaded)); topic.subscribe("app/sceneViewChanged", lang.hitch(this, this._onSceneViewChanged)); }else{ topic.subscribe("sceneViewLoaded", lang.hitch(this, this._onSceneViewLoaded)); topic.subscribe("sceneViewChanged", lang.hitch(this, this._onSceneViewChanged)); } if(window.isBuilder){ topic.subscribe("app/appConfigLoaded", lang.hitch(this, this._onAppConfigLoaded)); topic.subscribe("app/appConfigChanged", lang.hitch(this, this._onAppConfigChanged)); }else{ topic.subscribe("appConfigLoaded", lang.hitch(this, this._onAppConfigLoaded)); topic.subscribe("appConfigChanged", lang.hitch(this, this._onAppConfigChanged)); } topic.subscribe('userSignIn', lang.hitch(this, this._onUserSignIn)); topic.subscribe('userSignOut', lang.hitch(this, this._onUserSignOut)); //events from builder topic.subscribe('builder/actionTriggered', lang.hitch(this, this._onActionTriggered)); //see panel manager topic.subscribe('/dnd/move/start', lang.hitch(this, this._onMoveStart)); }, loadWidget: function(setting) { // summary: // load and create widget, return deferred. when defer is resolved, // widget is returned. // description: // setting should contain 2 properties: // id: id should be unique, same id will return same widget object. // uri: the widget's main class var def = new Deferred(), findWidget; setting = lang.clone(setting); findWidget = this.getWidgetById(setting.id); if (findWidget) { //widget have loaded(identified by id) def.resolve(findWidget); } else { all([this.loadWidgetClass(setting), this.loadWidgetManifest(setting)]) .then(lang.hitch(this, function(results) { var clazz = results[0]; var setting = results[1]; this.loadWidgetResources(setting).then(lang.hitch(this, function(resouces) { try { var widget = this.createWidget(setting, clazz, resouces); html.setAttr(widget.domNode, 'data-widget-name', setting.name); console.log('widget [' + setting.uri + '] created.'); } catch (err) { console.log('create [' + setting.uri + '] error:' + err.stack); new Message({ message: window.jimuNls.widgetManager.createWidgetError + ': ' + setting.uri }); //when creation is failed, but the dijit is still registered if(registry.byId(setting.id)){ registry.byId(setting.id).destroy(); } def.reject(err); } //use timeout to let the widget can get the correct dimension in startup function setTimeout(lang.hitch(this, function() { def.resolve(widget); this.emit('widget-created', widget); topic.publish('widgetCreated', widget); }), 50); }), function(err) { def.reject(err); }); }), function(err) { def.reject(err); }); } return def; }, loadWidgetClass: function(setting) { // summary: // load the widget's main class, and return deferred var def = new Deferred(); var uri; if(setting.isRemote){ uri = setting.uri + '.js'; }else{ uri = setting.uri; } require(utils.getRequireConfig(), [uri], lang.hitch(this, function(clazz) { def.resolve(clazz); })); utils.checkError(setting.uri, def); return def; }, loadWidgetResources: function(setting) { // summary: // load the widget's resources(local, style, etc.), and return deferred var def = new Deferred(), defConfig, defI18n, defStyle, defTemplate, defs = []; var setting2 = lang.clone(setting); defConfig = this.tryLoadWidgetConfig(setting2); defI18n = this._tryLoadResource(setting2, 'i18n'); defStyle = this._tryLoadResource(setting2, 'style'); defTemplate = this._tryLoadResource(setting2, 'template'); defs.push(defConfig); defs.push(defI18n); defs.push(defTemplate); defs.push(defStyle); all(defs).then(lang.hitch(this, function(results) { var res = {}; res.config = results[0]; res.i18n = results[1]; res.template = results[2]; res.style = results[3]; def.resolve(res); }), function(err) { def.reject(err); }); return def; }, loadWidgetManifest: function(widgetJson){ var def = new Deferred(); var info = utils.getUriInfo(widgetJson.uri); var url; if(info.isRemote){ url = info.folderUrl + 'manifest.json?f=json'; }else{ url = info.folderUrl + 'manifest.json'; } //json.manifest is added in configmanager if manifest is merged. if(widgetJson.manifest){ def.resolve(widgetJson); return def; } xhr(url, { handleAs:'json', headers: { "X-Requested-With": null } }).then(lang.hitch(this, function(manifest){ if(manifest.error && manifest.error.code){ //request manifest from AGOL item, and there is an error //error code may be: 400, 403 return def.reject(manifest.error); } manifest.category = 'widget'; lang.mixin(manifest, utils.getUriInfo(widgetJson.uri)); utils.manifest.addI18NLabel(manifest).then(lang.hitch(this, function(){ this._processManifest(manifest); utils.widgetJson.addManifest2WidgetJson(widgetJson, manifest); def.resolve(widgetJson); })); }), function(err){ def.reject(err); }); return def; }, getWidgetMarginBox: function(widget) { if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return {}; } } if(widget._marginBox){ return widget._marginBox; } var position = { left: -9999, top: -9999, relativeTo: widget.position.relativeTo }; widget._isTestSizeFlag = true;//set flag for getSize widget.setPosition(position); this.openWidget(widget); widget._marginBox = widget.getMarginBox(); this.closeWidget(widget); if ("undefined" !== typeof widget._isTestSizeFlag) { delete widget._isTestSizeFlag;//delete flag } return widget._marginBox; }, _processManifest: function(manifest){ utils.manifest.addManifestProperies(manifest); utils.manifest.processManifestLabel(manifest, window.dojoConfig.locale); }, createWidget: function(setting, clazz, resouces) { var widget; //here, check whether widget have loaded again because loading and create a widget //needs some time. If in this period time, more then one loading request will create //more widgets with the same id, it's a error. if (this.getWidgetById(setting.id)) { return this.getWidgetById(setting.id); } //the config can contain i18n placeholders if (resouces.config && resouces.i18n) { resouces.config = utils.replacePlaceHolder(resouces.config, resouces.i18n); } setting.rawConfig = setting.config; setting.config = resouces.config || {}; if (this.appConfig._appData) { this._mergeAgolConfig(setting); } setting.nls = resouces.i18n || {}; if (resouces.template) { setting.templateString = resouces.template; } setting['class'] = 'jimu-widget'; if (!setting.label) { setting.label = setting.name; } if (this.map) { setting.map = this.map; } setting.appConfig = this.appConfig; // for IE8 var setting2 = {}; for (var prop in setting) { if (setting.hasOwnProperty(prop)) { setting2[prop] = setting[prop]; } } setting2.widgetManager = this; widget = new clazz(setting2); widget.clazz = clazz; aspect.after(widget, 'startup', lang.hitch(this, this._postWidgetStartup, widget)); aspect.before(widget, 'destroy', lang.hitch(this, this._onDestroyWidget, widget)); // on(widget.domNode, 'click', lang.hitch(this, this._onClickWidget, widget)); widget.domNode.addEventListener('click', lang.hitch(this, this._onClickWidget, widget), {capture: true}); this.loaded.push(widget); return widget; }, getAllWidgets: function() { return this.loaded; }, destroyAllWidgets: function() { var allWidgetIds = array.map(this.loaded, function(widget) { return widget.id; }); array.forEach(allWidgetIds, function(widgetId) { this.destroyWidget(widgetId); }, this); this.loaded = []; }, //load the widget setting page class and create setting page object //do not cache for now. loadWidgetSettingPage: function(setting) { var def = new Deferred(); setting = lang.clone(setting); setting.id = setting.id + '_setting'; all([this.loadWidgetSettingClass(setting)]). then(lang.hitch(this, function(results) { var clazz = results[0]; this.loadWidgetSettingPageResources(setting).then(lang.hitch(this, function(resources) { var settingObject; // style = results[2] // for IE8 var setting2 = { nls: resources.i18n, templateString: resources.template, appConfig: this.appConfig, // map: this.map, 'class': 'jimu-widget-setting' }; if(window.appInfo.appType === "HTML3D"){ //for 3D Map, we pass sceneView setting2.sceneView = this.sceneView; }else{ //for 2D Map, we pass map setting2.map = this.map; } for (var prop in setting) { if (setting.hasOwnProperty(prop)) { setting2[prop] = setting[prop]; } } try { settingObject = new clazz(setting2); html.setAttr(settingObject.domNode, 'data-widget-name-setting', setting2.name); aspect.before(settingObject, 'destroy', lang.hitch(this, this._onDestroyWidgetSetting, settingObject)); def.resolve(settingObject); } catch (err) { new Message({ message: window.jimuNls.widgetManager.createWidgetSettingPageError + ':' + setting.uri }); //when creation is failed, but the dijit is still registered if(registry.byId(setting2.id)){ registry.byId(setting2.id).destroy(); } def.reject(err); } }), function(err) { console.log(err); }); }), function(err) { def.reject(err); }); return def; }, loadWidgetSettingClass: function(setting) { // summary: // load the widget's main class, and return deferred var def = new Deferred(); var uri; if(setting.isRemote){ uri = setting.folderUrl + 'setting/Setting.js'; }else{ uri = setting.amdFolder + 'setting/Setting'; } require(utils.getRequireConfig(), [uri], lang.hitch(this, function(clazz) { def.resolve(clazz); })); utils.checkError(setting.folderUrl + 'setting/Setting.js', def); return def; }, loadWidgetSettingPageResources: function(setting) { var def = new Deferred(); var defI18n, defStyle, defTemplate, defs = []; setting = lang.clone(setting); defI18n = this._tryLoadResource(setting, 'settingI18n'); defTemplate = this._tryLoadResource(setting, 'settingTemplate'); defStyle = this._tryLoadResource(setting, 'settingStyle'); defs.push(defI18n); defs.push(defTemplate); defs.push(defStyle); all(defs).then(lang.hitch(this, function(results) { var res = {}; res.i18n = results[0] || {}; res.template = results[1]; res.style = results[2]; def.resolve(res); }), function(err) { console.log(err); }); return def; }, getWidgetById: function(id) { var ret; array.some(this.loaded, function(w) { if (w.id === id) { ret = w; return true; } }, this); return ret; }, getWidgetByLabel: function(label) { var ret; array.some(this.loaded, function(w) { if (w.label === label) { ret = w; return true; } }, this); return ret; }, getWidgetsByName: function(name) { var ret = []; array.some(this.loaded, function(w) { if (w.name === name) { ret.push(w); } }, this); return ret; }, //normal, minimized, maximized changeWindowStateTo: function(widget, state) { if (state === 'normal') { this.normalizeWidget(widget); } else if (state === 'minimized') { this.minimizeWidget(widget); } else if (state === 'maximized') { this.maximizeWidget(widget); } else { console.log('error state: ' + state); } }, closeWidget: function(widget) { if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return; } } if (widget.state !== 'closed') { if(this.activeWidget && this.activeWidget.id === widget.id){ this.activeWidget.onDeActive(); this.activeWidget = null; } html.setStyle(widget.domNode, 'display', 'none'); widget.setState('closed'); try { widget.onClose(); } catch (err) { console.log(console.error('fail to close widget ' + widget.name + '. ' + err.stack)); } } if(!this.appConfig.mode){ this._removeDataSourceUsage(widget); } }, openWidget: function(widget) { if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return; } } if(!widget.started){ try { widget.started = true; widget.startup(); } catch (err) { console.error('fail to startup widget ' + widget.name + '. ' + err.stack); } } if (widget.state === 'closed') { html.setStyle(widget.domNode, 'display', ''); widget.setState('opened'); try { widget.onOpen(); } catch (err) { console.error('fail to open widget ' + widget.name + '. ' + err.stack); } } if(!this.appConfig.mode){ this._addDataSourceUsage(widget); } }, activateWidget: function(widget){ //activate a widget, the widget must be opened first if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return; } } if(widget.state !== 'opened'){ return; } this._activeWidget(widget); }, maximizeWidget: function(widget) { if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return; } } if (widget.state === 'closed') { this.openWidget(widget); } widget.setWindowState('maximized'); try { widget.onMaximize(); } catch (err) { console.log(console.error('fail to maximize widget ' + widget.name + '. ' + err.stack)); } }, minimizeWidget: function(widget) { if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return; } } if (widget.state === 'closed') { this.openWidget(widget); } widget.setWindowState('minimized'); try { widget.onMinimize(); } catch (err) { console.log(console.error('fail to minimize widget ' + widget.name + '. ' + err.stack)); } }, normalizeWidget: function(widget) { if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return; } } if (widget.state === 'closed') { this.openWidget(widget); } widget.setWindowState('normal'); try { widget.onNormalize(); } catch (err) { console.log(console.error('fail to normalize widget ' + widget.name + '. ' + err.stack)); } }, destroyWidget: function(widget) { var m; if (typeof widget === 'string') { m = this.getWidgetById(widget); if (!m) { //maybe, the widget is loading return; } else { widget = m; } } this._removeWidget(widget); try { widget.destroy(); } catch (err) { console.log(console.error('fail to destroy widget ' + widget.name + '. ' + err.stack)); } }, tryLoadWidgetConfig: function(setting) { return this._tryLoadWidgetConfig(setting).then(lang.hitch(this, function(config) { return this._upgradeWidgetConfig(setting, config).then(function(widgetConfig){ setting.config = widgetConfig; return widgetConfig; }); })); }, triggerWidgetOpen: function(widgetId){ var def = new Deferred(); var widget = this.getWidgetById(widgetId); if(widget){ if(widget.state !== 'closed'){ def.resolve(widget); return def; }else{ resolveAfterOpen(widget); } }else{ var handle = topic.subscribe('widgetCreated', lang.hitch(this, function(_widget){ if(_widget.id === widgetId){ handle.remove(); //we resolve here instead of waiting for onOpen, because onOpen may have been //triggered before this call back. def.resolve(_widget); } })); } topic.publish('openWidget', widgetId); function resolveAfterOpen(widget){ var handle = aspect.after(widget, 'onOpen', function(){ handle.remove(); def.resolve(widget); }); } return def; }, _tryLoadWidgetConfig: function(setting) { var def = new Deferred(); //need load config first, because the template may be use the config data if (setting.config && lang.isObject(setting.config)) { //if widget is configurated in the app config.json, the i18n has beed processed def.resolve(setting.config); return def; } else if (setting.config) { if(require.cache['url:' + setting.config]){ def.resolve(json.parse(require.cache['url:' + setting.config])); return def; } var configFile = utils.processUrlInAppConfig(setting.config); // The widgetConfig filename is dependent on widget label, // IE8 & IE9 do not encode automatically while attempt to request file. var configFileArray = configFile.split('/'); configFileArray[configFileArray.length - 1] = encodeURIComponent(configFileArray[configFileArray.length - 1]); configFile = configFileArray.join('/'); return xhr(configFile, { handleAs: "json", headers: { "X-Requested-With": null } }); } else { return this._tryLoadResource(setting, 'config').then(function(config){ //this property is used in map config plugin setting.isDefaultConfig = true; return config; }); } }, _upgradeWidgetConfig: function(json, oldConfig){ var def = new Deferred(); var widgetVersion = json.manifest.version; var configVersion = json.version; var newConfig; if(widgetVersion === configVersion){ def.resolve(oldConfig); return def; } if(json.hasVersionManager === false){ //widget config loaded from builder needs update version json.version = widgetVersion; //if widget doesn't have version manager, we assume the widget //is old version compatible def.resolve(oldConfig); return def; } require(utils.getRequireConfig(), [json.amdFolder + (json.isRemote? 'VersionManager.js': 'VersionManager')], lang.hitch(this, function(VersionManager) { var versionManager = new VersionManager(); var configVersionIndex = versionManager.getVersionIndex(configVersion); var widgetVersionIndex = versionManager.getVersionIndex(widgetVersion); if(configVersionIndex > widgetVersionIndex){ def.reject('Bad widget version number, ' + json.name + ',' + configVersion); }else{ try{ newConfig = versionManager.upgrade(oldConfig, configVersion, widgetVersion); json.version = widgetVersion; def.resolve(newConfig); }catch(err){ console.log('Read widget [' + json.name + '] old config error,' + err.stack); def.resolve(oldConfig); } } })); return def; }, /* * Load the css file in a widget. * This function load the widget's css file and insert it into the HTML page through . * It also ensure that the css file is inserted only one time. */ loadWidgetStyle: function(widgetSetting) { var id = this._getStyleIdFromWidgetJson(widgetSetting, false), def = new Deferred(); if (html.byId(id)) { def.resolve('load'); return def; } var themeCommonStyleId = 'theme_' + this.appConfig.theme.name + '_style_common'; //insert widget style before theme style, to let theme style over widget style return utils.loadStyleLink(id, widgetSetting.styleFile, themeCommonStyleId); }, loadWidgetSettingStyle: function(widgetSetting) { var id = this._getStyleIdFromWidgetJson(widgetSetting, true), def = new Deferred(); if (html.byId(id)) { def.resolve('load'); return def; } return utils.loadStyleLink(id, widgetSetting.settingStyleFile); }, loadWidgetConfig: function(widgetSetting) { var configFilePath = require(utils.getRequireConfig()).toUrl(widgetSetting.configFile); if(require.cache['url:' + configFilePath]){ var def = new Deferred(); def.resolve(json.parse(require.cache['url:' + configFilePath])); return def; } return xhr(configFilePath, { handleAs: "json", headers: { "X-Requested-With": null } }); }, loadWidgetI18n: function(widgetSetting) { var def = new Deferred(); require(utils.getRequireConfig(), ['dojo/i18n!' + widgetSetting.i18nFile], function(bundle) { def.resolve(bundle); }); return def; }, loadWidgetSettingI18n: function(widgetSetting) { var def = new Deferred(); require(utils.getRequireConfig(), ['dojo/i18n!' + widgetSetting.settingI18nFile], function(bundle) { def.resolve(bundle); }); return def; }, loadWidgetTemplate: function(widgetSetting) { var def = new Deferred(); require(utils.getRequireConfig(), ['dojo/text!' + widgetSetting.templateFile], function(template) { def.resolve(template); }); utils.checkError(widgetSetting.templateFile, def); return def; }, loadWidgetSettingTemplate: function(widgetSetting) { var def = new Deferred(); require(utils.getRequireConfig(), ['dojo/text!' + widgetSetting.settingTemplateFile], function(template) { def.resolve(template); }); utils.checkError(widgetSetting.settingTemplateFile, def); return def; }, removeWidgetStyle: function(widget) { this._removeStyle(this._getStyleIdFromWidgetJson(widget, false)); }, removeWidgetSettingStyle: function(widget) { this._removeStyle(this._getStyleIdFromWidgetJson(widget, true)); }, _removeStyle: function(styleId){ if(!html.byId(styleId)){ return; } var importStyles = html.attr(styleId, 'data-import-styles'); if(importStyles){ for(var i = 0; i < parseInt(importStyles, 10); i ++){ html.destroy(styleId + '_import_' + i); } } html.destroy(styleId); }, _getStyleIdFromWidgetJson: function(widgetJson, isSetting){ var p = widgetJson.itemId? widgetJson.itemId: widgetJson.uri; var id = 'widget/style/' + p + (isSetting? '/setting': ''); return this._replaceId(id); }, getControllerWidgets: function() { return array.filter(this.loaded, function(widget) { return widget.isController; }); }, getOffPanelWidgets: function() { return array.filter(this.loaded, function(widget) { return !widget.inPanel; }); }, getOnScreenOffPanelWidgets: function() { return array.filter(this.loaded, function(widget) { return widget.isOnScreen && !widget.inPanel; }); }, closeOtherWidgetsInTheSameGroup: function(widget){ if (typeof widget === 'string') { widget = this.getWidgetById(widget); if (!widget) { return; } } for(var i = 0; i < this.loaded.length; i++){ if(this.loaded[i].gid === widget.gid && this.loaded[i].id !== widget.id){ this.closeWidget(this.loaded[i]); } } }, closeAllWidgetsInGroup: function (groupId){ for(var i = 0; i < this.loaded.length; i++){ if(this.loaded[i].gid === groupId){ this.closeWidget(this.loaded[i]); } } }, _addDataSourceUsage: function(widget){ }, _removeDataSourceUsage: function(widget){ }, _getUsedDataSourceIdFromWidget: function(widget){ var widgetJson = this.appConfig.getConfigElementById(widget.id); if(!widgetJson || !widgetJson.config){ return; } var configStr = json.stringify(widgetJson.config); return array.filter(Object.keys(this.appConfig.dataSource.dataSources), function(dsId){ return configStr.indexOf(dsId) > -1; }, this); }, // Merge AGOL configs when first open widget (because the // widgetConfig just loaded if the widget has not been edited yet). // This method only merge fields in widget config, // the other fields were merged in ConfigManager.js _mergeAgolConfig: function(setting) { var values = this.appConfig._appData.values; function doMerge(sectionKey) { for (var key in values) { var sectionKeyIndex = key.replace(/\//g, '_').indexOf(sectionKey + '_config'); if (sectionKeyIndex >= 0){ utils.template.setConfigValue(setting, key.replace(/\//g, '_').substr(sectionKeyIndex, key.length). replace(sectionKey, 'widget'), values[key]); } } } var sectionKey; sectionKey = 'widgets[' + setting.id + ']'; doMerge(sectionKey); }, _onUserSignIn: function(credential) { array.forEach(this.loaded, function(m) { m.onSignIn(credential); }, this); }, _onUserSignOut: function() { array.forEach(this.loaded, function(m) { m.onSignOut(); }, this); }, _activeWidget: function(widget){ if(this.activeWidget){ if(this.activeWidget.id === widget.id){ //zIndex may be reset by widget self, we do not set in-panel widget zindex if(this.activeWidget.inPanel === false && this.activeWidget.moveTopOnActive){ html.setStyle(this.activeWidget.domNode, 'zIndex', 101); } return; } if(this.activeWidget.state === 'active'){ this.activeWidget.setState('opened'); if(this.activeWidget.inPanel === false){ html.setStyle(widget.domNode, 'zIndex', 'zIndex' in widget.position? widget.position.zIndex: 'auto'); } this.activeWidget.onDeActive(); } } this.activeWidget = widget; if(this.activeWidget.state !== 'opened'){ return; } this.activeWidget.setState('active'); if(this.activeWidget.inPanel === false && this.activeWidget.moveTopOnActive){ html.setStyle(this.activeWidget.domNode, 'zIndex', 101); } this.activeWidget.onActive(); topic.publish('widgetActived', widget); }, _onClickWidget: function(widget, evt){ var childWidgets = query('.jimu-widget', widget.domNode); if(childWidgets.length > 0){ for(var i = 0; i < childWidgets.length; i++){ if(evt.target === childWidgets[i] || html.isDescendant(evt.target, childWidgets[i])){ //click on the child widget or child widget's children dom return; } } } this._activeWidget(widget); }, _onMoveStart: function(mover){ array.forEach(this.loaded, function(widget){ if(widget.domNode === mover.node){ this._activeWidget(widget); } }, this); }, _onAppConfigLoaded: function(_appConfig) { var appConfig = lang.clone(_appConfig); this.appConfig = appConfig; }, _onMapLoaded: function(map) { this.map = map; }, _onMapChanged: function(map) { this.map = map; }, _onSceneViewLoaded: function(sceneView){ this.sceneView = sceneView; }, _onSceneViewChanged: function(sceneView){ this.sceneView = sceneView; }, _onAppConfigChanged: function(_appConfig, reason, changedData, otherOptions) { var appConfig = lang.clone(_appConfig); this.appConfig = appConfig; array.forEach(this.loaded, function(w) { if (!w) { //widget maybe deleted in the handler of appConfigChange event return; } w.onAppConfigChanged(appConfig, reason, changedData, otherOptions); if (reason === 'widgetChange') { this._onConfigChanged(changedData.id, changedData.config, otherOptions); } }, this); }, _onConfigChanged: function(id, config) { //summary: // widget which care it's own config change should override onConfigChanged function var w = this.getWidgetById(id); if (!w) { return; } w.onConfigChanged(config); lang.mixin(w.config, config); }, _onActionTriggered: function(info) { if (info.elementId === 'map' || info.elementId === 'app') { return; } var m = this.getWidgetById(info.elementId); if (!m) { this.missedActions.push({ id: info.elementId, action: { name: info.action, data: info.data } }); } else { m.onAction(info.action, info.data); } //may be the controller widget also need process the action array.forEach(this.getControllerWidgets(), function(ctrlWidget) { if (ctrlWidget.widgetIsControlled(info.elementId)) { ctrlWidget.onAction(info.action, { widgetId: info.elementId, data: info.data }); } }, this); }, _postWidgetStartup: function(widgetObject) { widgetObject.started = true;//for backward compatibility utils.setVerticalCenter(widgetObject.domNode); aspect.after(widgetObject, 'resize', lang.hitch(this, utils.setVerticalCenter, widgetObject.domNode)); this.openWidget(widgetObject); // if(widgetObject.defaultState){ // this.changeWindowStateTo(widgetObject, widgetObject.defaultState); // } this._triggerMissedAction(widgetObject); }, _triggerMissedAction: function(widget) { this.missedActions.forEach(function(info) { if (info.id === widget.id) { widget.onAction(info.action.name, info.action.data); } }); }, _remove: function(id) { return array.some(this.loaded, function(w, i) { if (w.id === id) { this.loaded.splice(i, 1); return true; } }, this); }, _tryLoadResource: function(setting, flag) { var file, hasp, def = new Deferred(), doLoad = function() { var loadDef; if (flag === 'config') { loadDef = this.loadWidgetConfig(setting); } else if (flag === 'style') { loadDef = this.loadWidgetStyle(setting); } else if (flag === 'i18n') { loadDef = this.loadWidgetI18n(setting); } else if (flag === 'template') { loadDef = this.loadWidgetTemplate(setting); } else if (flag === 'settingTemplate') { loadDef = this.loadWidgetSettingTemplate(setting); } else if (flag === 'settingStyle') { loadDef = this.loadWidgetSettingStyle(setting); } else if (flag === 'settingI18n') { loadDef = this.loadWidgetSettingI18n(setting); } else { return def; } loadDef.then(function(data) { def.resolve(data); }, function(err) { console.error('Load widget resource error. resource:', flag); console.error(err); new Message({ message: window.jimuNls.widgetManager.loadWidgetResourceError + ': ' + setting.uri }); def.reject(err); }); }; if (flag === 'config') { file = setting.amdFolder + 'config.json'; setting.configFile = file; hasp = 'hasConfig'; } else if (flag === 'style') { file = setting.amdFolder + 'css/style.css'; setting.styleFile = file; hasp = 'hasStyle'; } else if (flag === 'i18n') { file = setting.amdFolder + 'nls/strings.js'; if(setting.isRemote){ setting.i18nFile = file; }else{ setting.i18nFile = setting.amdFolder + 'nls/strings'; } hasp = 'hasLocale'; } else if (flag === 'template') { file = setting.amdFolder + 'Widget.html'; setting.templateFile = file; hasp = 'hasUIFile'; } else if (flag === 'settingTemplate') { file = setting.amdFolder + 'setting/Setting.html'; setting.settingTemplateFile = file; hasp = 'hasSettingUIFile'; } else if (flag === 'settingI18n') { file = setting.amdFolder + 'setting/nls/strings.js'; if(setting.isRemote){ setting.settingI18nFile = file; }else{ setting.settingI18nFile = setting.amdFolder + 'setting/nls/strings'; } hasp = 'hasSettingLocale'; } else if (flag === 'settingStyle') { file = setting.amdFolder + 'setting/css/style.css'; setting.settingStyleFile = file; hasp = 'hasSettingStyle'; } else { return def; } if (setting[hasp]){ doLoad.apply(this); }else { def.resolve(null); } return def; }, _replaceId: function(id) { return id.replace(/\//g, '_').replace(/\./g, '_'); }, _onDestroyWidget: function(widget) { if (widget.state !== 'closed') { this.closeWidget(widget); } this._removeWidget(widget); this.emit('widget-destroyed', widget.id); topic.publish('widgetDestroyed', widget.id); console.log('destroy widget [' + widget.uri + '].'); }, _onDestroyWidgetSetting: function(settingWidget) { this.removeWidgetSettingStyle(settingWidget); }, _removeWidget: function(widget) { var m; if (typeof widget === 'string') { m = this.getWidgetById(widget); if (!m) { //maybe, the widget is loading return; } else { widget = m; } } if(this.activeWidget && this.activeWidget.id === widget.id){ this.activeWidget = null; } this._remove(widget.id); if(this.getWidgetsByName(widget.name).length === 0){ this.removeWidgetStyle(widget); } } }); clazz.getInstance = function(urlParams) { if (instance === null) { instance = new clazz(urlParams); window._widgetManager = instance; } return instance; }; return clazz; });