AnsweredAssumed Answered

How to customize a map tool so as to be able to add a shapefile then create an object and zoom to it?

Question asked by Majdoleen on Apr 18, 2020
Latest reply on May 1, 2020 by Majdoleen

How to customize a map tool so as to be able to add a shapefile then create an object and zoom to it?


We tried to customize a map tool so as to be able to add a shapefile then create an object and zoom to it to use this tool in the cityworks map and zoom to it, but seems that we missing something, I highly appreciate if someone can have a look on this:


define(["dojo/dom", "dojo/json", "dojo/on", "dojo/parser", "dojo/sniff", "dojo/_base/array", "esri/Color", "dojo/domReady!", "esri/config", "esri/InfoTemplate",
       "esri/request", "esri/geometry/scaleUtils", "esri/layers/FeatureLayer", "esri/renderers/SimpleRenderer", "esri/symbols/PictureMarkerSymbol", "esri/symbols/SimpleFillSymbol", "esri/symbols/SimpleLineSymbol"   
        function (
        esriConfig, InfoTemplate, Map, request, scaleUtils, FeatureLayer,
        SimpleRenderer, PictureMarkerSymbol, SimpleFillSymbol, SimpleLineSymbol,
        dom, JSON, on, parser, sniff, arrayUtils, Color, lang
      ) {


          var portalUrl = "";

 = "/proxy/";

          on(dom.byId("uploadForm"), "change", function (event) {
            var fileName =;

            if (sniff("ie")) { //filename is full path in IE so extract the file name
              var arr = fileName.split("\\");
              fileName = arr[arr.length - 1];
            if (fileName.indexOf(".zip") !== -1) {//is file a zip - if not notify user
            else {
              dom.byId('upload-status').innerHTML = '<p style="color:red">Add shapefile as .zip file</p>';


          function generateFeatureCollection (fileName) {
            var name = fileName.split(".");
            //Chrome and IE add c:\fakepath to the value - we need to remove it
            //See this link for more info:
            name = name[0].replace("c:\\fakepath\\", "");

            dom.byId('upload-status').innerHTML = '<b>Loading </b>' + name;

            //Define the input params for generate see the rest doc for details
            var params = {
              'name': name,
              'targetSR': map.spatialReference,
              'maxRecordCount': 1000,
              'enforceInputFileSizeLimit': true,
              'enforceOutputJsonSizeLimit': true

            //generalize features for display Here we generalize at 1:40,000 which is approx 10 meters
            //This should work well when using web mercator.
            var extent = scaleUtils.getExtentForScale(map, 40000);
            var resolution = extent.getWidth() / map.width;
            params.generalize = true;
            params.maxAllowableOffset = resolution;
            params.reducePrecision = true;
            params.numberOfDigitsAfterDecimal = 0;

            var myContent = {
              'filetype': 'shapefile',
              'publishParameters': JSON.stringify(params),
              'f': 'json',
              'callback.html': 'textarea'

            //use the rest generate operation to generate a feature collection from the zipped shapefile
              url: portalUrl + '/sharing/rest/content/features/generate',
              content: myContent,
              form: dom.byId('uploadForm'),
              handleAs: 'json',
              load: lang.hitch(this, function (response) {
                if (response.error) {
                var layerName = response.featureCollection.layers[0];
                dom.byId('upload-status').innerHTML = '<b>Loaded: </b>' + layerName;
              error: lang.hitch(this, errorHandler)

          function errorHandler (error) {
            dom.byId('upload-status').innerHTML =
            "<p style='color:red'>" + error.message + "</p>";

          function addShapefileToMap (featureCollection) {
            //add the shapefile to the map and zoom to the feature collection extent
            //If you want to persist the feature collection when you reload browser you could store the collection in
            //local storage by serializing the layer using featureLayer.toJson()  see the 'Feature Collection in Local Storage' sample
            //for an example of how to work with local storage.
            var fullExtent;
            var layers = [];

            arrayUtils.forEach(featureCollection.layers, function (layer) {
              var infoTemplate = new InfoTemplate("Details", "${*}");
              var featureLayer = new FeatureLayer(layer, {
                infoTemplate: infoTemplate
              //associate the feature with the popup on click to enable highlight and zoom to
              featureLayer.on('click', function (event) {
              //change default symbol if desired. Comment this out and the layer will draw with the default symbology
              fullExtent = fullExtent ?
                fullExtent.union(featureLayer.fullExtent) : featureLayer.fullExtent;
            map.setExtent(fullExtent.expand(1.25), true);

            dom.byId('upload-status').innerHTML = "";

          function changeRenderer (layer) {
            //change the default symbol for the feature collection for polygons and points
            var symbol = null;
            switch (layer.geometryType) {
              case 'esriGeometryPoint':
                symbol = new PictureMarkerSymbol({
                  'angle': 0,
                  'xoffset': 0,
                  'yoffset': 0,
                  'type': 'esriPMS',
                  'url': '',
                  'contentType': 'image/png',
                  'width': 20,
                  'height': 20
              case 'esriGeometryPolygon':
                symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                  new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                    new Color([112, 112, 112]), 1), new Color([136, 136, 136, 0.25]));
            if (symbol) {
              layer.setRenderer(new SimpleRenderer(symbol));
             function selectChild() {
            proxy.layout.toggleRegion({ region: "trailing", expanded: true });

        this.init = function() {
            var dfd = proxy.utility.deferred();
            return dfd;
        }; = function() {
            if (!initialized) {
                //We will create the UI here before showing it
                initialized = true;
                var uiConfig = initUI();
                displayPanel = proxy.layout.createTrailingPanel(uiConfig);
            } else {
                //The UI is already created so just show it

It should be written the same way as shown in the attached file (the attached file is how to add xy to cityworks map, and it works perfectly)

Highly appreciate your effort.


Thank you in advance