Hi All,
I have a point dataset which represents the x,y of where photos were taken. Each photo is a member of a route (as identified by an attribute column). When a particular photo is clicked, I would like all of the photos in that route to be selected and added to the resulting infoWindow so the user can scroll back and forth along the particular route.
I currently have an IdentifyTask setup on this layer and am wondering if it's easiest to just modify that in some way? Any hints would be much appreciated, I have no idea where to begin. My code for the identify is below, it's basically the same as in the ESRI sample.
identifyAssetsParams = new IdentifyParameters();
identifyAssetsParams.tolerance = 3;
identifyAssetsParams.returnGeometry = true;
identifyAssetsParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;
identifyAssetsParams.width = mapObj.width;
identifyAssetsParams.height = mapObj.height;
identifyAssetsParams.geometry = event.mapPoint;
identifyAssetsParams.mapExtent = mapObj.extent;
identifyAssetsParams.layerIds = layerAssets.visibleLayers;
var assetsDeferred = identifyAssetsTask
.execute(identifyAssetsParams)
.addCallback(function (response) {
return arrayUtils.map(response, function (result) {
var feature = result.feature;
var layerName = result.layerName;
feature.attributes.layerName = layerName;
if (layerName === 'Primary Direction'){
var assetsTemplate = new InfoTemplate();
assetsTemplate.setTitle("Primary Direction");
feature.setInfoTemplate(assetsTemplate);
assetsTemplate.setContent("</br> ID: ${ID} </br> Route: ${ROUTE} \n\
</br><img src='${REL_PATH}'/>");
}
if (layerName === 'Opposite Direction'){
var assetsTemplate = new InfoTemplate();
assetsTemplate.setTitle("Opposite Direction");
feature.setInfoTemplate(assetsTemplate);
assetsTemplate.setContent("</br> ID: ${ID} </br> Route: ${ROUTE} \n\
</br><img src='${REL_PATH}'/>");
}
if (layerName === 'SeaView'){
var assetsTemplate = new InfoTemplate();
assetsTemplate.setTitle("SeaView");
feature.setInfoTemplate(assetsTemplate);
assetsTemplate.setContent("Series: ${Series} \n\
</br><img src='${REL_PATH}' width='200'/>");
}
else {
var generalTemplate = new InfoTemplate(layerName);
feature.setInfoTemplate(generalTemplate);
}
return feature;
});
});
mapObj.infoWindow.clearFeatures();
mapObj.infoWindow.setFeatures([assetsDeferred]);
mapObj.infoWindow.show(event.mapPoint);
Solved! Go to Solution.
Laura,
Here is a working sample:
<!DOCTYPE html> <html> <head> <title>Maps on Request</title> <script src="http://js.arcgis.com/3.15/"></script> <link rel="stylesheet" href="http://js.arcgis.com/3.15/dijit/themes/claro/claro.css"> <link rel="stylesheet" href="http://js.arcgis.com/3.15/esri/css/esri.css"> <style> html, body { height: 100%; } #mapDiv { width: 100%; height: 100%; z-index: 0; position: absolute; } #container { overflow: hidden; height: 100%; } #Coords { display: block; position: absolute; z-index: 2; bottom: 25px; left: 50%; alignment-adjust: 50%; margin-left: -140px; background-color: lightgray; -moz-border-radius: 15px; border-radius: 15px; padding: 5px; padding-left: 15px; padding-right: 15px; opacity: .8; text-align: center; cursor: pointer; } #testdiv { float: right; width: 50px; } #btnMenuToggle { width: 50px; height: 50px; margin-left: -50px; margin-bottom: -90px; position: relative; z-index: 1; } #TOC { margin: 10px; padding: 10px; font-family: verdana, helvetica, arial; z-index: 10; -moz-border-radius: 5px; border-radius: 5px; border-style: solid; border-color: black; border-width: 1px; } #leftPanel { height: 100%; overflow: hidden; width: 275px; z-index: 10; } #rightPanel { font-family: verdana, helvetica, arial; height: 100%; top: 0px; position: absolute; float: right; width: 275px; background-color: white; -moz-border-radius: 5px; border-radius: 5px; border-style: solid; border-color: black; border-width: 1px; z-index: 10; right: 0%; } #BasemapToggle { //position: fixed; //right: 350px; //top: 10px; position: relative; float: right; margin: 10px; margin-right: 70px; margin-bottom: -90px; width: 80px; height: 80px; z-index: 1; } #search { display: block; position: relative; z-index: 2; margin-top: 20px; margin-bottom: -54px; left: 50%; alignment-adjust: 50%; margin-left: -140px; } #menuHeader { padding: 10px; font-size: 18px; font-weight: bold; background-color: lightgray; border-bottom: solid 1px black; } #menuContent { padding: 10px; border-bottom: solid 1px black; } .nav { padding: 5px 10px; background: #4479BA; color: #FFF; border-radius: 5px; border: solid 1px #20538D; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); } .accordion-toggle { cursor: pointer; margin: 0; } .accordion-content { display: none; } .accordion-content.default { display: block; } </style> <script type="application/javascript"> var map; require([ "esri/InfoTemplate", "esri/map", "esri/dijit/Popup", "esri/tasks/query", "esri/tasks/QueryTask", "esri/Color", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/symbols/SimpleFillSymbol", "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleMarkerSymbol", "esri/tasks/IdentifyTask", "esri/tasks/IdentifyParameters", "dojo/_base/array", "dojo/_base/lang", "dojo/on", "dojo/dom-construct", "dojo/parser", "dojo/domReady!" ], function ( InfoTemplate, Map, Popup, Query, QueryTask, Color, ArcGISDynamicMapServiceLayer, SimpleFillSymbol, SimpleLineSymbol, SimpleMarkerSymbol, IdentifyTask, IdentifyParameters, arrayUtils, lang, on, domConstruct, parser ) { var identifyCadastralTask, identifyCadastralParams, queryAPTask, queryAP; var popup = new Popup({ fillSymbol: new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.25])), }, domConstruct.create("div")); var mapObj; mapObj = new Map("mapDiv", { basemap: "topo", center: [-95.249, 38.954], zoom: 14, infoWindow: popup, autoResize: true }); var symbol = new SimpleMarkerSymbol({ "color": [0, 0, 0, 1], "size": 0, "angle": -30, "xoffset": 0, "yoffset": 0, "type": "esriSMS", "style": "esriSMSCircle", }); var layerCadastral = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer"); mapObj.addLayers([layerCadastral]); identifyTaskSetup(); function identifyTaskSetup() { //create identify tasks and setup parameters identifyCadastralTask = new IdentifyTask("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer"); queryAPTask = new QueryTask("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/0"); queryAP = new Query(); queryAP.returnGeometry = true; queryAP.outFields = ["*"]; identifyCadastralParams = new IdentifyParameters(); identifyCadastralParams.tolerance = 3; identifyCadastralParams.returnGeometry = true; identifyCadastralParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE; identifyCadastralParams.width = mapObj.width; identifyCadastralParams.height = mapObj.height; }; mapObj.on("click", executeIdentifyTask); function executeIdentifyTask(event) { identifyCadastralParams.geometry = event.mapPoint; identifyCadastralParams.mapExtent = mapObj.extent; identifyCadastralParams.layerIds = layerCadastral.visibleLayers; var cadastralDeferred = identifyCadastralTask .execute(identifyCadastralParams) .addCallback(lang.hitch(this, function (response) { // response is an array of identify result objects // Let's return an array of features. return arrayUtils.map(response, lang.hitch(this, function (result) { var feature = result.feature; var layerName = result.layerName; var generalTemplate = new InfoTemplate(layerName); feature.attributes.layerName = layerName; if (layerName === 'Census Block Points') { queryAP.where = "TRACT = '" + feature.attributes.TRACT + "'"; var queryDeferred = queryAPTask .execute(queryAP) .addCallback(lang.hitch(this, function (qresponse) { return arrayUtils.map(qresponse.features, function (qresult) { qresult.setInfoTemplate(generalTemplate); return qresult; }); })); mapObj.infoWindow.clearFeatures(); mapObj.infoWindow.set("markerSymbol", symbol); mapObj.infoWindow.setFeatures([queryDeferred]); mapObj.infoWindow.show(event.mapPoint); } return feature; })); })); }; }); </script> </head> <body> <div id="container"> <div id="leftPanel"> <div id="mapDiv"> </div> </div> </div> </body> </html>
Laura,
Do you still plan to use an IdentifyTask as the means of clicking on a feature in the map and then get that route id from those results and have the maps popup show all the routes photos based on that route id?
Hi Robert, yes I do, if that makes the most sense. I'm not sure how to access the selected photo's attributes though.
Laura,
This me writing freehand code (untested). But this is what I came up with:
var queryTask = new QueryTask("your photos service url"); var query = new Query(); query.returnGeometry = true; query.outFields = ["*"]; identifyAssetsTask.execute(identifyAssetsParams, lang.hitch(this, function(response){ arrayUtils.map(response, function (result) { var feature = result.feature; var layerName = result.layerName; if (layerName === 'Primary Direction' || layerName === 'Opposite Direction'){ query.where = "ROUTE = '" + feature.attributes.route + "'"; var queryDeferred = queryTask.execute(query, lang.hitch(this, function(qresponse){ return arrayUtils.map(qresponse, function (qresult) { return qresult; } }); } }); mapObj.infoWindow.clearFeatures(); mapObj.infoWindow.setFeatures([queryDeferred]); mapObj.infoWindow.show(event.mapPoint); });
Hi Robert,
Thanks so much for your guidance. I'm trying to get this working but I'm getting an error on lang.hitch. Looking at the API reference, I changed it to esriLang.hitch but still getting an error ("TypeError: esriLang.hitch" is not a function) - hitch isn't mentioned in the "lang" section of the reference, what does it do?
Laura,
Sorry lang is in the dojo _base library. You need to add the require for "dojo/_base/lang" to your code.
Thanks Robert, that fixed it. I've not quite gotten it working, I think something might be going wrong with the query but I'm not sure what or why. I have a jsfiddle: Edit fiddle - JSFiddle
I don't have queryDeferred in mapObj.infoWindow.setFeatures because when I add it, the infoWindow doesn't pop up at all.
Wanted to add - if you comment out the "if" section, the identify still runs and shows data for the points in the infoWindow. As you can see it's saying "No information available".
Laura,
Here is a working sample:
<!DOCTYPE html> <html> <head> <title>Maps on Request</title> <script src="http://js.arcgis.com/3.15/"></script> <link rel="stylesheet" href="http://js.arcgis.com/3.15/dijit/themes/claro/claro.css"> <link rel="stylesheet" href="http://js.arcgis.com/3.15/esri/css/esri.css"> <style> html, body { height: 100%; } #mapDiv { width: 100%; height: 100%; z-index: 0; position: absolute; } #container { overflow: hidden; height: 100%; } #Coords { display: block; position: absolute; z-index: 2; bottom: 25px; left: 50%; alignment-adjust: 50%; margin-left: -140px; background-color: lightgray; -moz-border-radius: 15px; border-radius: 15px; padding: 5px; padding-left: 15px; padding-right: 15px; opacity: .8; text-align: center; cursor: pointer; } #testdiv { float: right; width: 50px; } #btnMenuToggle { width: 50px; height: 50px; margin-left: -50px; margin-bottom: -90px; position: relative; z-index: 1; } #TOC { margin: 10px; padding: 10px; font-family: verdana, helvetica, arial; z-index: 10; -moz-border-radius: 5px; border-radius: 5px; border-style: solid; border-color: black; border-width: 1px; } #leftPanel { height: 100%; overflow: hidden; width: 275px; z-index: 10; } #rightPanel { font-family: verdana, helvetica, arial; height: 100%; top: 0px; position: absolute; float: right; width: 275px; background-color: white; -moz-border-radius: 5px; border-radius: 5px; border-style: solid; border-color: black; border-width: 1px; z-index: 10; right: 0%; } #BasemapToggle { //position: fixed; //right: 350px; //top: 10px; position: relative; float: right; margin: 10px; margin-right: 70px; margin-bottom: -90px; width: 80px; height: 80px; z-index: 1; } #search { display: block; position: relative; z-index: 2; margin-top: 20px; margin-bottom: -54px; left: 50%; alignment-adjust: 50%; margin-left: -140px; } #menuHeader { padding: 10px; font-size: 18px; font-weight: bold; background-color: lightgray; border-bottom: solid 1px black; } #menuContent { padding: 10px; border-bottom: solid 1px black; } .nav { padding: 5px 10px; background: #4479BA; color: #FFF; border-radius: 5px; border: solid 1px #20538D; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2); } .accordion-toggle { cursor: pointer; margin: 0; } .accordion-content { display: none; } .accordion-content.default { display: block; } </style> <script type="application/javascript"> var map; require([ "esri/InfoTemplate", "esri/map", "esri/dijit/Popup", "esri/tasks/query", "esri/tasks/QueryTask", "esri/Color", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/symbols/SimpleFillSymbol", "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleMarkerSymbol", "esri/tasks/IdentifyTask", "esri/tasks/IdentifyParameters", "dojo/_base/array", "dojo/_base/lang", "dojo/on", "dojo/dom-construct", "dojo/parser", "dojo/domReady!" ], function ( InfoTemplate, Map, Popup, Query, QueryTask, Color, ArcGISDynamicMapServiceLayer, SimpleFillSymbol, SimpleLineSymbol, SimpleMarkerSymbol, IdentifyTask, IdentifyParameters, arrayUtils, lang, on, domConstruct, parser ) { var identifyCadastralTask, identifyCadastralParams, queryAPTask, queryAP; var popup = new Popup({ fillSymbol: new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.25])), }, domConstruct.create("div")); var mapObj; mapObj = new Map("mapDiv", { basemap: "topo", center: [-95.249, 38.954], zoom: 14, infoWindow: popup, autoResize: true }); var symbol = new SimpleMarkerSymbol({ "color": [0, 0, 0, 1], "size": 0, "angle": -30, "xoffset": 0, "yoffset": 0, "type": "esriSMS", "style": "esriSMSCircle", }); var layerCadastral = new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer"); mapObj.addLayers([layerCadastral]); identifyTaskSetup(); function identifyTaskSetup() { //create identify tasks and setup parameters identifyCadastralTask = new IdentifyTask("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer"); queryAPTask = new QueryTask("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/0"); queryAP = new Query(); queryAP.returnGeometry = true; queryAP.outFields = ["*"]; identifyCadastralParams = new IdentifyParameters(); identifyCadastralParams.tolerance = 3; identifyCadastralParams.returnGeometry = true; identifyCadastralParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE; identifyCadastralParams.width = mapObj.width; identifyCadastralParams.height = mapObj.height; }; mapObj.on("click", executeIdentifyTask); function executeIdentifyTask(event) { identifyCadastralParams.geometry = event.mapPoint; identifyCadastralParams.mapExtent = mapObj.extent; identifyCadastralParams.layerIds = layerCadastral.visibleLayers; var cadastralDeferred = identifyCadastralTask .execute(identifyCadastralParams) .addCallback(lang.hitch(this, function (response) { // response is an array of identify result objects // Let's return an array of features. return arrayUtils.map(response, lang.hitch(this, function (result) { var feature = result.feature; var layerName = result.layerName; var generalTemplate = new InfoTemplate(layerName); feature.attributes.layerName = layerName; if (layerName === 'Census Block Points') { queryAP.where = "TRACT = '" + feature.attributes.TRACT + "'"; var queryDeferred = queryAPTask .execute(queryAP) .addCallback(lang.hitch(this, function (qresponse) { return arrayUtils.map(qresponse.features, function (qresult) { qresult.setInfoTemplate(generalTemplate); return qresult; }); })); mapObj.infoWindow.clearFeatures(); mapObj.infoWindow.set("markerSymbol", symbol); mapObj.infoWindow.setFeatures([queryDeferred]); mapObj.infoWindow.show(event.mapPoint); } return feature; })); })); }; }); </script> </head> <body> <div id="container"> <div id="leftPanel"> <div id="mapDiv"> </div> </div> </div> </body> </html>
Hi Robert, this has been a huge help. I have it working with my data. I have one final question, because I would like for the first feature in the array (first feature that shows up in the infoWindow) to be the feature the user clicked on. Currently it starts with the first item in the array, which geographically could be elsewhere on the map. I don't have a great grasp of callback functions or deferred lists. I know I would have to reorder the array depending on which feature is the "selected feature", which is fine enough if I know how to access the array elements. As far as I can tell queryDeferred is an array of arrays? If I log it to the console it tells me there are two results, one empty and one containing the 1000 items from the query. Do you know how I can access these 1000 items to reorder them?