Hi Robert,
I have included my MapManager.js
define([
'dojo/_base/declare',
'dojo/_base/lang',
'dojo/_base/array',
'dojo/_base/html',
'dojo/query',
'dojo/topic',
'dojo/on',
'dojo/aspect',
'dojo/keys',
'dojo/i18n',
'dojo/_base/config',
'esri/dijit/InfoWindow',
'esri/dijit/PopupMobile',
'esri/InfoTemplate',
'esri/request',
'esri/arcgis/utils',
'esri/geometry/Extent',
'esri/geometry/Point',
'require',
'./utils',
'jimu/LayerInfos/LayerInfos',
'jimu/dijit/Message',
'jimu/dijit/AppStatePopup',
'./MapUrlParamsHandler',
'./AppStateManager',
'./PopupManager',
'./FilterManager'
], function(declare, lang, array, html, query, topic, on, aspect, keys, i18n, dojoConfig, InfoWindow,
PopupMobile, InfoTemplate, esriRequest, arcgisUtils, Extent, Point, require, jimuUtils,
LayerInfos, Message, AppStatePopup, MapUrlParamsHandler, AppStateManager, PopupManager, FilterManager) {
var instance = null,
clazz = declare(null, {
appConfig: null,
mapDivId: '',
map: null,
previousInfoWindow: null,
mobileInfoWindow: null,
isMobileInfoWindow: false,
layerInfosObj: null,
SERVICE_ID: "_M",
constructor: function( options, mapDivId) {
this.appConfig = options.appConfig;
this.urlParams = options.urlParams;
this.mapDivId = mapDivId;
this.id = mapDivId;
this.appStateManager = AppStateManager.getInstance(this.urlParams);
this.popupManager = PopupManager.getInstance(this);
this.filterManager = FilterManager.getInstance();
this.nls = window.jimuNls;
topic.subscribe("appConfigChanged", lang.hitch(this, this.onAppConfigChanged));
topic.subscribe("syncExtent", lang.hitch(this, this.onSyncExtent));
topic.subscribe("mapContentModified", lang.hitch(this, this.onMapContentModified));
on(window, 'resize', lang.hitch(this, this.onWindowResize));
on(window, 'beforeunload', lang.hitch(this, this.onBeforeUnload));
},
showMap: function() {
this._showMap(this.appConfig);
},
_showMap: function(appConfig) {
console.time('Load Map');
if (appConfig.map['3D']) {
if (appConfig.map.itemId) {
this._show3DWebScene(appConfig);
} else {
this._show3DLayersMap(appConfig);
}
} else {
if (appConfig.map.itemId) {
this._show2DWebMap(appConfig);
} else {
console.log('No webmap found. Please set map.itemId in config.json.');
}
}
},
onBeforeUnload: function() {
if(this.appConfig.keepAppState) {
this.appStateManager.saveWabAppState(this.map, this.layerInfosObj);
}
},
onWindowResize: function() {
if (this.map && this.map.resize) {
this.map.resize();
this.resetInfoWindow(false);
}
},
getMapInfoWindow: function(){
return {
mobile: this._mapMobileInfoWindow,
bigScreen: this._mapInfoWindow
};
},
resetInfoWindow: function(isNewMap) {
if(isNewMap){
this._mapInfoWindow = this.map.infoWindow;
if(this._mapMobileInfoWindow){
this._mapMobileInfoWindow.destroy();
query("div.esriMobileInfoView.esriMobilePopupInfoView").forEach(function(node){
html.destroy(node);
});
query("div.esriMobileNavigationBar").forEach(function(node){
html.destroy(node);
});
}
this._mapMobileInfoWindow =
new PopupMobile(null, html.create("div", null, null, this.map.root));
this.isMobileInfoWindow = false;
}
if (jimuUtils.inMobileSize() && !this.isMobileInfoWindow) {
this.map.infoWindow.hide();
this.map.setInfoWindow(this._mapMobileInfoWindow);
this.isMobileInfoWindow = true;
} else if (!jimuUtils.inMobileSize() && this.isMobileInfoWindow) {
this.map.infoWindow.hide();
this.map.setInfoWindow(this._mapInfoWindow);
this.isMobileInfoWindow = false;
}
},
onSyncExtent: function(map){
if(this.map){
var extJson = map.extent;
var ext = new Extent(extJson);
this.map.setExtent(ext);
}
},
_visitConfigMapLayers: function(appConfig, cb) {
array.forEach(appConfig.map.basemaps, function(layerConfig, i) {
layerConfig.isOperationalLayer = false;
cb(layerConfig, i);
}, this);
array.forEach(appConfig.map.operationallayers, function(layerConfig, i) {
layerConfig.isOperationalLayer = true;
cb(layerConfig, i);
}, this);
},
_show3DLayersMap: function(appConfig) {
require(['esri3d/Map'], lang.hitch(this, function(Map) {
var initCamera = appConfig.map.mapOptions.camera,
map;
map = new Map(this.mapDivId, {
camera: initCamera
});
this._visitConfigMapLayers(appConfig, lang.hitch(this, function(layerConfig) {
this.createLayer(map, '3D', layerConfig);
}));
map.usePlugin = Map.usePlugin;
this._publishMapEvent(map);
}));
},
_show3DWebScene: function(appConfig) {
this._getWebsceneData(appConfig.map.itemId).then(lang.hitch(this, function(data) {
require(['esri3d/Map'], lang.hitch(this, function(Map) {
var map = new Map(this.mapDivId, appConfig.map.mapOptions);
array.forEach(data.itemData.operationalLayers, function(layerConfig) {
this.createLayer(map, '3D', layerConfig);
}, this);
array.forEach(data.itemData.baseMap.baseMapLayers, function(layerConfig) {
layerConfig.type = "tile";
this.createLayer(map, '3D', layerConfig);
}, this);
array.forEach(data.itemData.baseMap.elevationLayers, function(layerConfig) {
layerConfig.type = "elevation";
this.createLayer(map, '3D', layerConfig);
}, this);
map.toc = data.itemData.toc;
map.bookmarks = data.itemData.bookmarks;
map.tours = data.itemData.tours;
}));
}));
},
_publishMapEvent: function(map) {
topic.subscribe('toggleChanged', lang.hitch(this, function(visible, layer){
if(visible && layer.title=='_M'||layer.title=='_M2'){
this.SERVICE_ID = layer.title;
}
}));
var tip = "Click on problem location";
var tooltip = dojo.create("div", { "class": "tooltip", "innerHTML": tip, "style": "color: red; font-size:22px;width:200px"}, map.container);
dojo.style(tooltip, "position", "fixed");
dojo.connect(map, "onMouseMove", function(evt) {
var px, py;
if (evt.clientX || evt.pageY) {
px = evt.clientX;
py = evt.clientY;
} else {
px = evt.clientX + dojo.body().scrollLeft - dojo.body().clientLeft;
py = evt.clientY + dojo.body().scrollTop - dojo.body().clientTop;
}
tooltip.style.display = "none";
dojo.style(tooltip, { left: (px + 15) + "px", top: (py) + "px" });
tooltip.style.display = "";
});
dojo.connect(map, "onMouseOut", function(evt){
tooltip.style.display = "none";
});
window._viewerMap = map;
MapUrlParamsHandler.postProcessUrlParams(this.urlParams, map);
console.timeEnd('Load Map');
if (this.map) {
this.map = map;
this.resetInfoWindow(true);
console.log('map changed.');
topic.publish('mapChanged', this.map, this.layerInfosObj);
} else {
this.map = map;
this.resetInfoWindow(true);
topic.publish('mapLoaded', this.map, this.layerInfosObj);
}
require([
'esri/graphic',
'esri/symbols/SimpleMarkerSymbol',
'esri/symbols/SimpleLineSymbol',
'esri/Color'
],
lang.hitch(this, function(Graphic, SimpleMarkerSymbol, SimpleLineSymbol, Color){
var symbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE, 0.01,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_CIRCLE,
new Color([207, 16, 45, 0.9]),
1
),
new Color([207, 16, 45, 0.9])
);
map.on("click", lang.hitch(this, function(evt){
var gra = new Graphic(evt.mapPoint, symbol);
setTimeout(lang.hitch(this, function(){
var selFeats = map.infoWindow.features;
if(!selFeats){
map.graphics.clear();
map.graphics.add(gra);
map.infoWindow.setContent('<a href="https://survey123.arcgis.com/share/xyz123?center='+ evt.mapPoint.getLatitude().toString() + ','+ evt.mapPoint.getLongitude().toString() + '&field:Floor_Selection=' + this.SERVICE_ID.split('_')[1]+"_Floor " + '" target="_"><font size="4">Click here to submit a service request</font></a>');
SERVICE_ID: null;
map.infoWindow.show(evt.mapPoint);
}
}), 1000);
}));
}));
},
_getWebsceneData: function(itemId) {
return esriRequest({
url: 'http://184.169.133.166/sharing/rest/content/items/' + itemId + '/data',
handleAs: "json"
});
},
_show2DWebMap: function(appConfig) {
if(!appConfig.map.mapOptions){
appConfig.map.mapOptions = {};
}
var mapOptions = this._processMapOptions(appConfig.map.mapOptions) || {};
mapOptions.isZoomSlider = false;
var webMapPortalUrl = appConfig.map.portalUrl;
var webMapItemId = appConfig.map.itemId;
var webMapOptions = {
mapOptions: mapOptions,
bingMapsKey: appConfig.bingMapsKey,
usePopupManager: true
};
if(!window.isBuilder && !appConfig.mode && appConfig.map.appProxy &&
appConfig.map.appProxy.mapItemId === appConfig.map.itemId) {
var layerMixins = [];
array.forEach(appConfig.map.appProxy.proxyItems, function(proxyItem){
if (proxyItem.useProxy && proxyItem.proxyUrl) {
layerMixins.push({
url: proxyItem.sourceUrl,
mixin: {
url: proxyItem.proxyUrl
}
});
}
});
if(layerMixins.length > 0) {
webMapOptions.layerMixins = layerMixins;
}
}
var mapDeferred = this._createWebMapRaw(webMapPortalUrl, webMapItemId, this.mapDivId, webMapOptions);
mapDeferred.then(lang.hitch(this, function(response) {
var map = response.map;
map.hideZoomSlider();
map.infoWindow.resize(270, 316);
map.itemId = appConfig.map.itemId;
map.itemInfo = response.itemInfo;
map.webMapResponse = response;
var options = {
snapKey: keys.copyKey
};
map.enableSnapping(options);
html.setStyle(map.root, 'zIndex', 0);
map._initialExtent = map.extent;
this.layerInfosObj = LayerInfos.getInstanceSyncForInit(map, map.itemInfo);
this.layerInfosObj.traversalLayerInfosOfWebmap(lang.hitch(this, function(layerInfo){
layerInfo.getLayerObject().then(lang.hitch(this, function(layerObject){
if(layerObject){
lang.setObject("_wabProperties.originalRefreshinterval", layerObject.refreshInterval, layerObject);
}
}), lang.hitch(this, function(err){
console.error("can't get layerObject", err);
}));
}));
if(appConfig.map.mapRefreshInterval && !appConfig.map.mapRefreshInterval.useWebMapRefreshInterval){
this._updateRefreshInterval(appConfig.map.mapRefreshInterval);
}
this._showUnreachableLayersTitleMessage();
this._publishMapEvent(map);
setTimeout(lang.hitch(this, this._checkAppState), 500);
this._addDataLoadingOnMapUpdate(map);
}), lang.hitch(this, function(error) {
console.error(error);
this._showError(error);
topic.publish('mapCreatedFailed');
}));
},
_handleRefreshLayer: function(featureLayer){
var _drawFeatures = featureLayer._mode._drawFeatures;
var _clearIf = featureLayer._mode._clearIIf;
var _cellMap = null;
featureLayer._mode._drawFeatures = function(response, cell) {
if (cell && typeof cell.row === 'number' && typeof cell.col === 'number') {
featureLayer._mode._removeCell(cell.row, cell.col);
}
_drawFeatures.apply(featureLayer._mode, arguments);
};
aspect.before(featureLayer, 'refresh', function() {
_cellMap = featureLayer._mode._cellMap;
featureLayer._mode._clearIIf = function() {};
});
aspect.after(featureLayer, 'refresh', function() {
featureLayer._mode._cellMap = _cellMap;
featureLayer._mode._clearIIf = _clearIf;
});
on(featureLayer, 'update-start', function(){
featureLayer.isUpdating = true;
});
on(featureLayer, 'update-end', function(){
featureLayer.isUpdating = false;
});
},
_showError: function(err){
if(err && err.message){
html.create('div', {
'class': 'app-error',
innerHTML: err.message
}, document.body);
}
},
_createWebMapRaw: function(webMapPortalUrl, webMapItemId, mapDivId, webMapOptions){
var mapDef = jimuUtils.createWebMap(webMapPortalUrl, webMapItemId, mapDivId, webMapOptions);
return mapDef.then(lang.hitch(this, function(response){
return response;
}), lang.hitch(this, function(error){
console.error(error);
if(error && error instanceof Error && error.message){
var cache = i18n.cache;
var key = "esri/nls/jsapi/" + dojoConfig.locale;
var esriLocaleNls = cache[key];
var str = lang.getObject("arcgis.utils.baseLayerError", false, esriLocaleNls);
if(str && error.message.indexOf(str) >= 0){
new Message({
message: window.jimuNls.map.basemapNotAvailable + window.jimuNls.map.displayDefaultBasemap
});
return arcgisUtils.getItem(webMapItemId).then(lang.hitch(this, function(itemInfo){
itemInfo.itemData.spatialReference = {
wkid: 102100,
latestWkid: 3857
};
itemInfo.itemData.baseMap = {
baseMapLayers: [{
url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
opacity: 1,
layerType: "ArcGISTiledMapServiceLayer",
visibility: true,
id: "defaultBasemap_0"
}],
title: "Topographic"
};
return jimuUtils.createWebMap(webMapPortalUrl, itemInfo, mapDivId, webMapOptions);
}));
}
}
throw error;
}));
},
_showUnreachableLayersTitleMessage: function() {
var unreachableLayersTitle = this.layerInfosObj.getUnreachableLayersTitle();
var layersTitleString = "";
var message = window.jimuNls.map.layerLoadedError ||
"The layer, ${layers} cannot be added to the map.";
if(message && unreachableLayersTitle && unreachableLayersTitle.length > 0) {
array.forEach(unreachableLayersTitle, lang.hitch(this, function(title) {
layersTitleString = layersTitleString + title + ", ";
}));
new Message({
message: message.replace("${layers}", layersTitleString)
});
}
},
_addDataLoadingOnMapUpdate: function(map) {
var loadHtml = '<div class="map-loading">Loading...</div>';
var loadContainer = html.toDom(loadHtml);
html.place(loadContainer, map.root);
if(map.updating){
html.addClass(loadContainer, 'loading');
}
on(map, 'update-start', lang.hitch(this, function() {
html.addClass(loadContainer, 'loading');
}));
on(map, 'update-end', lang.hitch(this, function() {
html.removeClass(loadContainer, 'loading');
}));
on(map, 'unload', lang.hitch(this, function() {
html.destroy(loadContainer);
loadContainer = null;
}));
},
_checkAppState: function() {
var urlKeys = ['extent', 'center', 'marker', 'find', 'query', 'scale', 'level'];
var useAppState = this.appConfig.keepAppState;
if(useAppState) {
array.forEach(urlKeys, function(k){
if(k in this.urlParams){
useAppState = false;
}
}, this);
}
if(useAppState){
this.appStateManager.getWabAppState().then(lang.hitch(this, function(stateData) {
if (stateData.extent || stateData.layers) {
var appStatePopup = new AppStatePopup({
nls: {
title: this.nls.appState.title,
restoreMap: this.nls.appState.restoreMap
}
});
appStatePopup.placeAt('main-page');
on(appStatePopup, 'applyAppState', lang.hitch(this, function() {
this._applyAppState(stateData, this.map);
}));
appStatePopup.startup();
appStatePopup.show();
}
}));
}
},
_applyAppState: function(stateData, map) {
var layerOptions = stateData.layers;
this.layerInfosObj.restoreState({
layerOptions: layerOptions || null
});
if (stateData.extent) {
map.setExtent(stateData.extent);
}
},
_processMapOptions: function(mapOptions) {
if (!mapOptions) {
return;
}
if(!mapOptions.lods){
delete mapOptions.lods;
}
if(mapOptions.lods && mapOptions.lods.length === 0){
delete mapOptions.lods;
}
var ret = lang.clone(mapOptions);
if (ret.extent) {
ret.extent = new Extent(ret.extent);
}
if (ret.center && !lang.isArrayLike(ret.center)) {
ret.center = new Point(ret.center);
}
if (ret.infoWindow) {
ret.infoWindow = new InfoWindow(ret.infoWindow, html.create('div', {}, this.mapDivId));
}
return ret;
},
createLayer: function(map, maptype, layerConfig) {
var layMap = {
'2D_tiled': 'esri/layers/ArcGISTiledMapServiceLayer',
'2D_dynamic': 'esri/layers/ArcGISDynamicMapServiceLayer',
'2D_image': 'esri/layers/ArcGISImageServiceLayer',
'2D_feature': 'esri/layers/FeatureLayer',
'2D_rss': 'esri/layers/GeoRSSLayer',
'2D_kml': 'esri/layers/KMLLayer',
'2D_webTiled': 'esri/layers/WebTiledLayer',
'2D_wms': 'esri/layers/WMSLayer',
'2D_wmts': 'esri/layers/WMTSLayer',
'3D_tiled': 'esri3d/layers/ArcGISTiledMapServiceLayer',
'3D_dynamic': 'esri3d/layers/ArcGISDynamicMapServiceLayer',
'3D_image': 'esri3d/layers/ArcGISImageServiceLayer',
'3D_feature': 'esri3d/layers/FeatureLayer',
'3D_elevation': 'esri3d/layers/ArcGISElevationServiceLayer',
'3D_3dmodle': 'esri3d/layers/SceneLayer'
};
require([layMap[maptype + '_' + layerConfig.type]], lang.hitch(this, function(layerClass) {
var layer, infoTemplate, options = {},
keyProperties = ['label', 'url', 'type', 'icon', 'infoTemplate', 'isOperationalLayer'];
for (var p in layerConfig) {
if (keyProperties.indexOf(p) < 0) {
options[p] = layerConfig[p];
}
}
if (layerConfig.infoTemplate) {
infoTemplate = new InfoTemplate(layerConfig.infoTemplate.title,
layerConfig.infoTemplate.content);
options.infoTemplate = infoTemplate;
layer = new layerClass(layerConfig.url, options);
if (layerConfig.infoTemplate.width && layerConfig.infoTemplate.height) {
aspect.after(layer, 'onClick', lang.hitch(this, function() {
map.infoWindow.resize(layerConfig.infoTemplate.width,
layerConfig.infoTemplate.height);
}), true);
}
} else {
layer = new layerClass(layerConfig.url, options);
}
layer.isOperationalLayer = layerConfig.isOperationalLayer;
layer.label = layerConfig.label;
layer.icon = layerConfig.icon;
map.addLayer(layer);
}));
},
onAppConfigChanged: function(appConfig, reason, changedJson) {
this.appConfig = appConfig;
if(reason === 'mapChange'){
this._recreateMap(appConfig);
}else if(reason === 'mapOptionsChange'){
if(changedJson.lods){
this._recreateMap(appConfig);
}
}else if(reason === 'mapRefreshIntervalChange'){
var itemData = this.map && this.map.itemInfo.itemData;
if (itemData && this.layerInfosObj) {
this._updateRefreshInterval(changedJson);
}
}
},
onMapContentModified: function() {
this._recreateMap(this.appConfig);
},
_updateRefreshInterval: function(refreshInterval){
var minutes = -1;
if (refreshInterval.useWebMapRefreshInterval) {
minutes = -1;
} else {
minutes = refreshInterval.minutes;
}
this.layerInfosObj.traversalLayerInfosOfWebmap(lang.hitch(this, function(layerInfo) {
layerInfo.getLayerObject().then(lang.hitch(this, function(layerObject) {
if(!layerObject){
return;
}
var originalRefreshinterval = lang.getObject("_wabProperties.originalRefreshinterval", false, layerObject);
if(originalRefreshinterval > 0){
if (typeof layerObject.setRefreshInterval === 'function') {
if (minutes < 0) {
layerObject.setRefreshInterval(originalRefreshinterval);
} else {
layerObject.setRefreshInterval(minutes);
}
}
}
}), lang.hitch(this, function(err) {
console.error("can't get layerObject", err);
}));
}));
},
_recreateMap: function(appConfig){
if(this.map){
topic.publish('beforeMapDestory', this.map);
this.map.destroy();
}
this._showMap(appConfig);
},
disableWebMapPopup: function() {
this.map.setInfoWindowOnClick(false);
},
enableWebMapPopup: function() {
this.map.setInfoWindowOnClick(true);
}
});
clazz.getInstance = function(options, mapDivId) {
if (instance === null) {
instance = new clazz(options, mapDivId);
}
return instance;
};
return clazz;
});