Loading the same map twice causes feature querying to go wonky

412
3
01-09-2014 05:34 AM
BenStewart
New Contributor III
I am working on a template that loads a map twice (side by side) to allow layers to be compared. The maps load and the layer switching works, but, when I click on a feature to query it, it only queries on the first map clicked. If I query a feature in the right map, a pop-up appears that shows all the values, if I then click on a feature in the left map, it shows the pop-up on the right map.

Not sure this entirely makes sense, but has anyone experienced anything like this?

var leftMap, rightMap;    
var lyrDefn = {};
var leftLegend, rightLegend;

require(["esri/arcgis/utils", "esri/layers/FeatureLayer", "esri/dijit/Legend", "dojo/domReady!"], 
function(arcgisUtils, FeatureLayer, Legend) {
    //Direct the arcgis url to the local portal
    arcgisUtils.arcgisUrl = "My Company ArcGIS Portal";

    //Get the url from the web address
    var webmapId = getUrlVars()['webmap'];
    if (!webmapId) { webmapId = "d9ee972fc36f44fd9eb07e5f71b75564"; }  

    var mapOptions = { logo: false };
    var varLeftDeferred = arcgisUtils.createMap(webmapId, "left_column", mapOptions);
    
    varLeftDeferred.addCallback(function (leftResponse) {
        leftMap = leftResponse.map;
        var curLayers = leftMap.getLayersVisibleAtScale();
        //For each layer in the map, add an item into each of the layer selectors
        for (var lyrIdx = 1; lyrIdx < curLayers.length; lyrIdx++) {
            var curLyr = curLayers[lyrIdx];
            if (curLyr.declaredClass == "esri.layers.FeatureLayer") {
                $("#leftMapSelect").append($("<option></option>").attr("value",lyrIdx).text(curLyr.name));
                $("#rightMapSelect").append($("<option></option>").attr("value",lyrIdx).text(curLyr.name)); 
                lyrDefn[curLyr.name] = { name:curLyr.name, lyrId: lyrIdx, parentID: lyrIdx, 
                    description:tempLyr.description, copyright:tempLyr.copyright, type:"feature" }                    
            } else {
                for (var lyrInfoIdx = 0; lyrInfoIdx < curLyr.layerInfos.length; lyrInfoIdx++) {
                    var lyrInfo = curLyr.layerInfos[lyrInfoIdx];
                    if (!lyrInfo.subLayerIds) { 
                        lyrDefn[lyrInfo.name] = { name:lyrInfo.name, lyrId: lyrInfoIdx, parentID: lyrIdx, 
                                description:"", copyright:"", type:"mapService", url:curLyr.url + "/" + lyrInfo.id }
                        $("#leftMapSelect").append($("<option></option>").attr("value",lyrInfoIdx).text(lyrInfo.name));
                        $("#rightMapSelect").append($("<option></option>").attr("value",lyrInfoIdx).text(lyrInfo.name));        
                    }
                }                
            }
        }
        leftMap.on('extent-change', function(extent, delta, levelChange, lod) { syncMaps('left'); }); 
        leftLegend = new Legend({ map: leftMap }, "tabLeftLegend");
        leftLegend.startup();
        //Once everything has been run, force a change of layers
        $('#leftMapSelect').prop('selectedIndex', 1);
        changeLyr('left');
    });

    var varRightDeferred = arcgisUtils.createMap(webmapId, "middle_column", mapOptions);  
    varRightDeferred.addCallback(function (rightResponse) {
        rightMap = rightResponse.map;
        rightMap.on('extent-change', function(extent, delta, levelChange, lod) { syncMaps('right'); });                       
        rightLegend = new Legend({ map: rightMap }, "tabRightLegend");        
        rightLegend.startup();
        //$("#intro_description").text = rightMap.description;
        $('#rightMapSelect').prop('selectedIndex', 2);
        changeLyr('right');
    });
});    
    var extentCnt = 0;
    
    function syncMaps(sideMoved) {
        if (extentCnt == 0) {
            if (sideMoved == 'left') { rightMap.setExtent(leftMap.extent); }
            if (sideMoved == 'right') { leftMap.setExtent(rightMap.extent); }
            extentCnt = 1;
        } else { extentCnt = 0; }                 
    }
      
    // Change the layer being shown in the map
    function changeLyr(side) {
        var curMap = leftMap;
        var lyrIdx = $("#leftMapSelect option:selected").text();
        if (side == 'right') { 
            curMap = rightMap; 
            var lyrIdx = $("#rightMapSelect option:selected").text();
        }
        var curDesc = "No Metadata";
        if (lyrIdx != "Choose Layer") {
            var lyrDefinition = lyrDefn[lyrIdx];
            var allLayers = curMap.getLayersVisibleAtScale();
            //Loop through all the map layers. If the layer matches the selected layer, turn it on        
            for (var lyrIdx = 1; lyrIdx < allLayers.length; lyrIdx ++) {
                var chngLyr = allLayers[lyrIdx];
                if (lyrDefinition.parentID == lyrIdx) { 
                    chngLyr.show();                     
                    //For the non-feature layers, turn on the specific sub layer as well
                    if (lyrDefinition.type != "feature") {
                        if (chngLyr.declaredClass == "esri.layers.ArcGISTiledMapServiceLayer") { 
                            chngLyr.show()
                            curDesc = chngLyr.description;
                        } else {
                            //Set the sub layer visibility
                            chngLyr.setVisibleLayers([lyrDefinition.lyrId]);                    
                            //Search through all layers and find the description information
                            for (lIdx = 0; lIdx < allLayers.length; lIdx ++) {
                                if (allLayers[lIdx].name == lyrDefinition.name) { curDesc = allLayers[lIdx].description; }
                            }
                        }
                    }
                } else { chngLyr.hide(); } // Otherwise, hide the layer
            }
            $("#tab" + side + "Metadata").html("<p>" + curDesc + "</p>");
        }
        leftLegend.refresh();
        rightLegend.refresh();
    }

    
    //Change the map and reload the browser when a new map is chosen
    function changeMap() {
        var mapID = $("#countrySelect option:selected").val();
        if (mapID != "NA") {
            window.location.assign("http://" + window.location.hostname + window.location.pathname + "?webmap=" + mapID);
        }
    }
    
    //Expertly borrowed from http://papermashup.com/read-url-get-variables-withjavascript/ 
    function getUrlVars() {
    var vars = {};
    var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
        vars[key] = value;
    });
    return vars;
}
0 Kudos
3 Replies
JonathanUihlein
Esri Regular Contributor
Hi Ben!

I was trying to troubleshoot this but couldn't create a working sample between not knowing what your HTML looks like and all the jQuery markup.

Could you recreate the issue in http://jsfiddle.net/ so I can play around and potentially offer a helpful solution.

Thanks!!
0 Kudos
BenStewart
New Contributor III
I have uploaded a modified sample http://geographyis.com/MapStories/ESRIViewer/
0 Kudos
JonathanUihlein
Esri Regular Contributor
Awesome! I'm going to take a closer look.

I immediately noticed an error in the console:


TypeError: lyrDefinition is undefined


if (lyrDefinition.parentID == lyrIdx) {...


Might be a clue. Going to play around for a bit.

*edit

It also looks like each map uses svg layers with the same IDs... so the API is probably getting confused.

<svg id="left_column_gc" overflow="hidden" width="949" height="600" style="overflow: visible; position: absolute;"><g id="gpx_1756_0_layer" transform="matrix(1.00000000,0.00000000,0.00000000,1.00000000,0.00000000,0.00000000)" style="display: none;"> 
<g id="gpx_1756_1_layer" transform="matrix(1.00000000,0.00000000,0.00000000,1.00000000,0.00000000,0.00000000)" style="display: block;"> ...
<g id="gpx_1756_2_layer" style="display: none;" transform="matrix(1.00000000,0.00000000,0.00000000,1.00000000,0.00000000,0.00000000)"> ...


<svg id="middle_column_gc" overflow="hidden" width="940" height="600" style="overflow: visible; position: absolute;"><g id="gpx_1756_0_layer" style="display: none;">
<g id="gpx_1756_1_layer" transform="matrix(1.00000000,0.00000000,0.00000000,1.00000000,0.00000000,0.00000000)" style="display: block;"> ...
<g id="gpx_1756_2_layer" style="display: none;"> ...
0 Kudos