Hi all -
I have a popup from my old Flex site that I would like to re-create in WAB. It's displayed below and was configured using the <description> tag with <![CDATA[ {NAME}<br> <img src="assets'images\popup_icons\{I_bike}"> <img src="assets'images\popup_icons\{I_hike}">, etc etc.>
to pull in image icons referenced in the data table.
Question #1: I'm trying to configure the pop-up in the web map using the "custom attribute display" option, but I don't see a way to display the icons horizontally referencing an <img> tag, or via a virtual directory. Is that possible to do? And if not - egads, where would I begin to recreate the popup? The images represent Yes or No values for whether the activity is available at that location.
Question #2: Ideally I'd like to configure the popup to be queried for only the activities available at each location, similar to the Park Locator Local Government template. This seems more extensive with coding, but if anyone has suggestions on where to begin or what forums to read and get started, I'd appreciate the guidance.
Thank you. - Meg
Solved! Go to Solution.
Meg,
OK, I have completed the code additions for the MapManager.js for adding the custom infoWindow for your parks layer:
There are three new functions and one line of code to add to an existing function in MapManager.js.
New functions to add:
_getParksLayer: function() { require(["jimu/LayerInfos/LayerInfos"], lang.hitch(this, function(LayerInfos){ if (this.map.itemId) { LayerInfos.getInstance(this.map, this.map.itemInfo) .then(lang.hitch(this, function(operLayerInfos) { this.operLayerInfos = operLayerInfos; array.forEach(this.operLayerInfos.getLayerInfoArray(), function(layerInfo) { console.info(layerInfo); if(layerInfo.title === 'ParksFinder'){ this._setupParksPopup(layerInfo); } }, this); })); } else { var itemInfo = this._obtainMapLayers(); LayerInfos.getInstance(this.map, itemInfo) .then(lang.hitch(this, function(operLayerInfos) { this.operLayerInfos = operLayerInfos; array.forEach(this.operLayerInfos.getLayerInfoArray(), function(layerInfo) { console.info(layerInfo); if(layerInfo.title === 'ParksFinder'){ this._setupParksPopup(layerInfo); } }, this); })); } })); }, _setupParksPopup: function(LayerInfo) { var infoTemplate = new InfoTemplate(); infoTemplate.setTitle("Park Name: ${PARK}"); var templateString = "<b>${NAME}</b><br/>" + "<b>Park Website: </b>${PARK_URL:convertLink}<br/>" + "<b>Park Map: </b>${PARK_MAP:convertLink}<br/><br/>" + "${I_BIKE:checkAvailable}" + "${I_WALK:checkAvailable}" + "${I_SWIMP:checkAvailable}" + "${I_SWIML:checkAvailable}" + "${I_DOGWALK:checkAvailable}" + "${I_FISH:checkAvailable}" + "${I_INTERP:checkAvailable}" + "${I_HORSE:checkAvailable}" + "${I_PICNIC:checkAvailable}" + "${I_RESTRM:checkAvailable}" + "${I_PLAYGRD:checkAvailable}" + "${I_BOAT:checkAvailable}" + "${I_GOLF:checkAvailable}" + "${I_ARCHERY:checkAvailable}" + "${I_GCAMP:checkAvailable}" + "${I_BPCAMP:checkAvailable}" + "${I_FCAMP:checkAvailable}"; infoTemplate.setContent(templateString); checkAvailable = function (value, key, data) { var boolTest = value.toLowerCase().indexOf('_no_') > 0 ? false : true; var retRslt = ""; if(boolTest){ retRslt = "<img src='http://gislap183/ParkIcons/" + value + "'/> "; } return retRslt; }; convertLink = function (value, key, data) { var retRslt = "", linkAlias = ""; switch (key){ case 'PARK_URL':{ linkAlias = "More Info"; break; } case 'PARK_MAP':{ linkAlias = "Print Park Map"; break; } } retRslt = "<a href='" + value + "' target='_blank'>" + linkAlias + "</a>"; return retRslt; }; LayerInfo.layerObject.setInfoTemplate(infoTemplate); }, _obtainMapLayers: function() { // summary: // obtain basemap layers and operational layers if the map is not webmap. var basemapLayers = [], operLayers = []; // emulate a webmapItemInfo. var retObj = { itemData: { baseMap: { baseMapLayers: [] }, operationalLayers: [] } }; array.forEach(this.map.graphicsLayerIds, function(layerId) { var layer = this.map.getLayer(layerId); if (layer.isOperationalLayer) { operLayers.push({ layerObject: layer, title: layer.label || layer.title || layer.name || layer.id || " ", id: layer.id || " " }); } }, this); array.forEach(this.map.layerIds, function(layerId) { var layer = this.map.getLayer(layerId); if (layer.isOperationalLayer) { operLayers.push({ layerObject: layer, title: layer.label || layer.title || layer.name || layer.id || " ", id: layer.id || " " }); } else { basemapLayers.push({ layerObject: layer, id: layer.id || " " }); } }, this); retObj.itemData.baseMap.baseMapLayers = basemapLayers; retObj.itemData.operationalLayers = operLayers; return retObj; },
Code to add to _publishMapEvent function is on line 19:
_publishMapEvent: function(map) { //add this property for debug purpose window._viewerMap = map; if (this.loading) { this.loading.destroy(); } console.timeEnd('Load Map'); if (this.map) { this.map = map; this.resetInfoWindow(true); console.log('map changed.'); topic.publish('mapChanged', this.map); } else { this.map = map; this.resetInfoWindow(true); topic.publish('mapLoaded', this.map); } this._getParksLayer(); },
Meg,
Is the service that feeds this popup public?
Is it a field in the data that is null or not that defines if that particular service is available?
Hi Robert -
The service is not public. The data table looks like this though and there are no Null values.
The icons shown in the popup above reference these fields.
Icons are displayed based on the gif image value in each field, referencing them in the assest\images folder in flex or via a virtual directory. i_bile_35.gif displays a white icon for the activity is available; i_no_bike_35.gif displays a grey icon that the activity is not available.
There are also corresponding fields with Y / N values. Ideally I'd like the popup to only reflect the Y values but display the icon images.
Is there a way in the WAB to develop the mapclick popup (infowindow?), or should it be set in the web map? I'm felt I was just getting a handle on Flex and am now treading water in WAB. Thanks.
Meg,
Is this going to be a one app deal or are you going to want to make it reusable in more than one app? If it is a one app deal then I can help provide code that you would add the mapManager.js to set the infoWidow content using click event for that particular layer. If it will be something that will need to be added to multiple apps the development of a custom non panel widget.
It would greatly help if you could provide a a sample set of data for dev and testing purposes.
It's a one app deal (for now!). I'll send you a sample set of the data tomorrow when I'm back in the office.
Thank you++
Meg,
OK, I have completed the code additions for the MapManager.js for adding the custom infoWindow for your parks layer:
There are three new functions and one line of code to add to an existing function in MapManager.js.
New functions to add:
_getParksLayer: function() { require(["jimu/LayerInfos/LayerInfos"], lang.hitch(this, function(LayerInfos){ if (this.map.itemId) { LayerInfos.getInstance(this.map, this.map.itemInfo) .then(lang.hitch(this, function(operLayerInfos) { this.operLayerInfos = operLayerInfos; array.forEach(this.operLayerInfos.getLayerInfoArray(), function(layerInfo) { console.info(layerInfo); if(layerInfo.title === 'ParksFinder'){ this._setupParksPopup(layerInfo); } }, this); })); } else { var itemInfo = this._obtainMapLayers(); LayerInfos.getInstance(this.map, itemInfo) .then(lang.hitch(this, function(operLayerInfos) { this.operLayerInfos = operLayerInfos; array.forEach(this.operLayerInfos.getLayerInfoArray(), function(layerInfo) { console.info(layerInfo); if(layerInfo.title === 'ParksFinder'){ this._setupParksPopup(layerInfo); } }, this); })); } })); }, _setupParksPopup: function(LayerInfo) { var infoTemplate = new InfoTemplate(); infoTemplate.setTitle("Park Name: ${PARK}"); var templateString = "<b>${NAME}</b><br/>" + "<b>Park Website: </b>${PARK_URL:convertLink}<br/>" + "<b>Park Map: </b>${PARK_MAP:convertLink}<br/><br/>" + "${I_BIKE:checkAvailable}" + "${I_WALK:checkAvailable}" + "${I_SWIMP:checkAvailable}" + "${I_SWIML:checkAvailable}" + "${I_DOGWALK:checkAvailable}" + "${I_FISH:checkAvailable}" + "${I_INTERP:checkAvailable}" + "${I_HORSE:checkAvailable}" + "${I_PICNIC:checkAvailable}" + "${I_RESTRM:checkAvailable}" + "${I_PLAYGRD:checkAvailable}" + "${I_BOAT:checkAvailable}" + "${I_GOLF:checkAvailable}" + "${I_ARCHERY:checkAvailable}" + "${I_GCAMP:checkAvailable}" + "${I_BPCAMP:checkAvailable}" + "${I_FCAMP:checkAvailable}"; infoTemplate.setContent(templateString); checkAvailable = function (value, key, data) { var boolTest = value.toLowerCase().indexOf('_no_') > 0 ? false : true; var retRslt = ""; if(boolTest){ retRslt = "<img src='http://gislap183/ParkIcons/" + value + "'/> "; } return retRslt; }; convertLink = function (value, key, data) { var retRslt = "", linkAlias = ""; switch (key){ case 'PARK_URL':{ linkAlias = "More Info"; break; } case 'PARK_MAP':{ linkAlias = "Print Park Map"; break; } } retRslt = "<a href='" + value + "' target='_blank'>" + linkAlias + "</a>"; return retRslt; }; LayerInfo.layerObject.setInfoTemplate(infoTemplate); }, _obtainMapLayers: function() { // summary: // obtain basemap layers and operational layers if the map is not webmap. var basemapLayers = [], operLayers = []; // emulate a webmapItemInfo. var retObj = { itemData: { baseMap: { baseMapLayers: [] }, operationalLayers: [] } }; array.forEach(this.map.graphicsLayerIds, function(layerId) { var layer = this.map.getLayer(layerId); if (layer.isOperationalLayer) { operLayers.push({ layerObject: layer, title: layer.label || layer.title || layer.name || layer.id || " ", id: layer.id || " " }); } }, this); array.forEach(this.map.layerIds, function(layerId) { var layer = this.map.getLayer(layerId); if (layer.isOperationalLayer) { operLayers.push({ layerObject: layer, title: layer.label || layer.title || layer.name || layer.id || " ", id: layer.id || " " }); } else { basemapLayers.push({ layerObject: layer, id: layer.id || " " }); } }, this); retObj.itemData.baseMap.baseMapLayers = basemapLayers; retObj.itemData.operationalLayers = operLayers; return retObj; },
Code to add to _publishMapEvent function is on line 19:
_publishMapEvent: function(map) { //add this property for debug purpose window._viewerMap = map; if (this.loading) { this.loading.destroy(); } console.timeEnd('Load Map'); if (this.map) { this.map = map; this.resetInfoWindow(true); console.log('map changed.'); topic.publish('mapChanged', this.map); } else { this.map = map; this.resetInfoWindow(true); topic.publish('mapLoaded', this.map); } this._getParksLayer(); },
Meg,
OK, I have completed the code additions for the MapManager.js for adding the custom infoWindow for your parks layer:
There are three new functions and one line of code to add to an existing function in MapManager.js.
New functions to add:
_getParksLayer: function() { require(["jimu/LayerInfos/LayerInfos"], lang.hitch(this, function(LayerInfos){ if (this.map.itemId) { LayerInfos.getInstance(this.map, this.map.itemInfo) .then(lang.hitch(this, function(operLayerInfos) { this.operLayerInfos = operLayerInfos; array.forEach(this.operLayerInfos.getLayerInfoArray(), function(layerInfo) { console.info(layerInfo); if(layerInfo.title === 'ParksFinder'){ this._setupParksPopup(layerInfo); } }, this); })); } else { var itemInfo = this._obtainMapLayers(); LayerInfos.getInstance(this.map, itemInfo) .then(lang.hitch(this, function(operLayerInfos) { this.operLayerInfos = operLayerInfos; array.forEach(this.operLayerInfos.getLayerInfoArray(), function(layerInfo) { console.info(layerInfo); if(layerInfo.title === 'ParksFinder'){ this._setupParksPopup(layerInfo); } }, this); })); } })); }, _setupParksPopup: function(LayerInfo) { var infoTemplate = new InfoTemplate(); infoTemplate.setTitle("Park Name: ${PARK}"); var templateString = "<b>${NAME}</b><br/>" + "<b>Park Website: </b>${PARK_URL:convertLink}<br/>" + "<b>Park Map: </b>${PARK_MAP:convertLink}<br/><br/>" + "${I_BIKE:checkAvailable}" + "${I_WALK:checkAvailable}" + "${I_SWIMP:checkAvailable}" + "${I_SWIML:checkAvailable}" + "${I_DOGWALK:checkAvailable}" + "${I_FISH:checkAvailable}" + "${I_INTERP:checkAvailable}" + "${I_HORSE:checkAvailable}" + "${I_PICNIC:checkAvailable}" + "${I_RESTRM:checkAvailable}" + "${I_PLAYGRD:checkAvailable}" + "${I_BOAT:checkAvailable}" + "${I_GOLF:checkAvailable}" + "${I_ARCHERY:checkAvailable}" + "${I_GCAMP:checkAvailable}" + "${I_BPCAMP:checkAvailable}" + "${I_FCAMP:checkAvailable}"; infoTemplate.setContent(templateString); checkAvailable = function (value, key, data) { var boolTest = value.toLowerCase().indexOf('_no_') > 0 ? false : true; var retRslt = ""; if(boolTest){ retRslt = "<img src='http://gislap183/ParkIcons/" + value + "'/> "; } return retRslt; }; convertLink = function (value, key, data) { var retRslt = "", linkAlias = ""; switch (key){ case 'PARK_URL':{ linkAlias = "More Info"; break; } case 'PARK_MAP':{ linkAlias = "Print Park Map"; break; } } retRslt = "<a href='" + value + "' target='_blank'>" + linkAlias + "</a>"; return retRslt; }; LayerInfo.layerObject.setInfoTemplate(infoTemplate); }, _obtainMapLayers: function() { // summary: // obtain basemap layers and operational layers if the map is not webmap. var basemapLayers = [], operLayers = []; // emulate a webmapItemInfo. var retObj = { itemData: { baseMap: { baseMapLayers: [] }, operationalLayers: [] } }; array.forEach(this.map.graphicsLayerIds, function(layerId) { var layer = this.map.getLayer(layerId); if (layer.isOperationalLayer) { operLayers.push({ layerObject: layer, title: layer.label || layer.title || layer.name || layer.id || " ", id: layer.id || " " }); } }, this); array.forEach(this.map.layerIds, function(layerId) { var layer = this.map.getLayer(layerId); if (layer.isOperationalLayer) { operLayers.push({ layerObject: layer, title: layer.label || layer.title || layer.name || layer.id || " ", id: layer.id || " " }); } else { basemapLayers.push({ layerObject: layer, id: layer.id || " " }); } }, this); retObj.itemData.baseMap.baseMapLayers = basemapLayers; retObj.itemData.operationalLayers = operLayers; return retObj; },
Code to add to _publishMapEvent function is on line 19:
_publishMapEvent: function(map) { //add this property for debug purpose window._viewerMap = map; if (this.loading) { this.loading.destroy(); } console.timeEnd('Load Map'); if (this.map) { this.map = map; this.resetInfoWindow(true); console.log('map changed.'); topic.publish('mapChanged', this.map); } else { this.map = map; this.resetInfoWindow(true); topic.publish('mapLoaded', this.map); } this._getParksLayer(); },
Example screenshot:
Robert - You are invaluable! I'm hoping to load this before taking off today. If not, I'll check in on Monday. A million thanks for your time - I really can't say that enough.
Meg,
If you get this working can you post a link.
I have the esri solutions parks viewer and am thinking about moving it over to WAB.
Thank you