ArcGIS Javascript IdentifyTask Returns Scale Dependent Layers

Problem: IdentifyTask returns scale dependent layers outside of scale range. It’s different between jsapi 2.x and 3.x. It’s taken me about six attempts to get this right, each time declaring that I’ve nailed it!!.. in mock irony, because one of my C++ professor’s favorite lines was “…Son, programming is like nailing jello to a wall.” Guess the post modern irony didn’t help.

A Solution: Note the checking of subLayerIds for null, scale checking, after getting the visibleLayers from service.


function doIdentify(evt) {
    var referenceLayer = new esri.layers.ArcGISDynamicMapServiceLayer(referenceMapServiceName, {id: 'referenceLayer'});
    var aVisibleSubLayers = referenceLayer.visibleLayers,
        aLayersInScale = [],
        identifyParams = new esri.tasks.IdentifyParameters(),
        identifyTask = new esri.tasks.IdentifyTask(referenceLayer.url);

    //loop thru visible sublayers that are not group layers, then check within scale
    if (referenceLayer.visible === true && aVisibleSubLayers.length !== 0 && aVisibleSubLayers[0] !== -1) {
        dojo.forEach(referenceLayer.createDynamicLayerInfosFromLayerInfos(), function (dLayInfo) {
            if (dLayInfo.subLayerIds === null && dojo.indexOf(aVisibleSubLayers, dLayInfo.id) !== -1 &&
                    (dLayInfo.minScale === undefined || dLayInfo.minScale === 0 || map.getScale() <= dLayInfo.minScale) &&
                    (dLayInfo.maxScale === undefined || dLayInfo.maxScale === 0 || map.getScale() >= dLayInfo.maxScale)) {
                aLayersInScale.push(dLayInfo.id);
            }
        });
    }

    if (aLayersInScale.length > 0) {
        identifyParams.geometry = evt.mapPoint;
        identifyParams.mapExtent = map.extent;
        identifyParams.tolerance = 3;
        identifyParams.returnGeometry = true;
        identifyParams.layerIds = aLayersInScale;
        identifyParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_ALL;
        identifyParams.width = map.width;
        identifyParams.height = map.height;
        identifyTask.execute(identifyParams, function(idResults) { 
            doSomethingWithIdentifyResults(idResults);
        });
    }
}

Bonus: Identifies on multiple services at once and returns results as one array using dojo.DeferredList


dojo.require("dojo.DeferredList");

referenceLayer = new esri.layers.ArcGISDynamicMapServiceLayer(referenceMapServiceName, {id: 'referenceLayer'});

//Operational layers
operationalLayer = new esri.layers.ArcGISDynamicMapServiceLayer(operationalMapServiceName, {id: 'operationalLayer'});

function executeIdentify(geom, serviceName, aLayerIds) {
    var identifyParams = new esri.tasks.IdentifyParameters(),
        identifyTask = new esri.tasks.IdentifyTask(serviceName);
    identifyParams.geometry = geom;
    identifyParams.mapExtent = map.extent;
    identifyParams.tolerance = 3;
    identifyParams.returnGeometry = true;
    identifyParams.layerIds = aLayerIds;
    identifyParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_ALL;
    identifyParams.width = map.width;
    identifyParams.height = map.height;
    return identifyTask.execute(identifyParams);
}

function doIdentify(evt) {
    var geom = evt.mapPoint,
        aLayersInScale,
        aDeferreds = [],
        deferredList,
        currentScale = map.getScale(),
        aVisibleSubLayers,
        aAGSDynMapServicesToIdentify = [referenceLayer, operationalLayer];

    map.graphics.clear();
    identifyLayerKeyPrevious = undefined;

    //loop thru dynamic services, then thru visible sublayers that are not group layers, then check within scale
    dojo.forEach(aAGSDynMapServicesToIdentify, function (agsDynMapService) {
        aVisibleSubLayers = agsDynMapService.visibleLayers;
        if (agsDynMapService.visible === true && aVisibleSubLayers.length !== 0 && aVisibleSubLayers[0] !== -1) {
            aLayersInScale = [];
            dojo.forEach(agsDynMapService.createDynamicLayerInfosFromLayerInfos(), function (dLayInfo) {
                if (dLayInfo.subLayerIds === null && dojo.indexOf(aVisibleSubLayers, dLayInfo.id) !== -1 &&
                        (dLayInfo.minScale === undefined || dLayInfo.minScale === 0 || currentScale <= dLayInfo.minScale) &&
                        (dLayInfo.maxScale === undefined || dLayInfo.maxScale === 0 || currentScale >= dLayInfo.maxScale)) {
                    aLayersInScale.push(dLayInfo.id);
                }
            });
            if (aLayersInScale.length > 0) {
                aDeferreds.push(executeIdentify(evt.mapPoint, agsDynMapService.url, aLayersInScale));
            }
        }
    });

    // create a deferred list to aggregate the state for multiple asynchronous identify queries
    deferredList = new dojo.DeferredList(aDeferreds);
    deferredList.then(function (aIdentifyResults) {
        // "aIdentifyResults" is 2D array of results
        // array[n][0] boolean true or false, success or failure of individual call
        // array[n][1] is the array of identity results returned
        doSomethingWithIdentifyResults(aIdentifyResults);
    });
}

One comment

  1. Simon says:

    This looks very helpful. Can you also share the “doSomethingWithIdentifyResults” function?

    Thanks
    Simon

Leave a Reply

Your email address will not be published. Required fields are marked *

*