ArcGIS Server 10.1 Geocoding

Maybe not widely known at this point, but a batch GeocodeAddresses operation is newly supported in ArcGIS Server 10.1 for geocoding — note the plural. I’ll be looking forward to testing this operation to perform batch geocoding.

http:///geocodeAddresses – The result of this operation is a resource representing the list of geocoded addresses. http://resources.arcgis.com/en/help/rest/apiref/

In ArcGIS Server 10.0, only SOAP supported batching with a GeocodeAddresses operation.

ArcGIS Server 10.1 Printing Resources

Mostly the help in ArcGIS Server 10.1
http://resources.arcgis.com/en/help/main/10.1/index.html#/ Printing_in_web_applications/0154000004w5000000/
http://resources.arcgis.com/en/help/main/10.1/0154/0154000005n1000000.htm

… but also this post in the esri forum about custom text areas

http://forums.arcgis.com/threads/61615-Printing-with-Custom-Text-Elements?highlight=print

PDF and javascript – export an image from print service and then create your own pdf — can’t do super complex stuff. Looks like you may be able to include jpeg images that are exported from the default print tools, but only jpegs. However, I would think anyone would be happier generating a pdf server side if that’s an option.
http://jspdf.com/
https://github.com/MrRio/jsPDF
http://stackoverflow.com/questions/742271/generating-pdf-files-with-javascript?lq=1 overview of the issue with author of jspdf weighing in…

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);
    });
}