尝试上传shapefile时,dom是未定义的错误

时间:2014-06-24 18:58:16

标签: javascript html arcgis-js-api

过去两周我一直在研究arcgis项目,我在代码中遇到了上传shapefile函数的问题。我不断得到一个dom是未定义的错误,我不知道该怎么做。

以下是代码:

<div class="modal fade" id="UpdateShapefileForm" tabindex="-1" role="dialog" aria-    labelledby="Set View" aria-hidden="true">
 <div class="modal-dialog">
  <div class="modal-content">
   <div class="modal-header">
    <form enctype="multipart/form-data" method="post" id="uploadForm">
          <div class="field">
              <label class="file-upload">
                  <span><strong>Add File</strong></span>
                 <input type="file" name="file" id="inFile"/>
              </label>
          </div>
         </form>
        </div>
       </div>
      </div>
     </div>

<script src="http://js.arcgis.com/3.9/"></script>
<script src="/static/js/mapping/mapobject.js" type="text/javascript"></script>
<script src="/static/js/mapping/mapmanager.js" type="text/javascript"></script>
<script type="text/javascript">

    var map, toolbar;
    var PROJECT_OUTLINE, PROJECT_FILL, PARCEL_OUTLINE, PARCEL_FILL, PLOT_OUTLINE, PLOT_FILL;
    var toolbarEvent;
    var mapManager = new MapManager();

    var markerPictures = {
        'project': '/static/assets/grnball.png',
        'parcel': '/static/assets/bluball.png',
        'plot': '/static/assets/redball.png'
    }

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


        map = new Map("mapcanvas", {
            center: [-56.049, 38.485],
            zoom: 3,
            basemap: "hybrid"
        });

        map.on("load", function() {
            $("#waiting_img").hide();
            createToolbar();
            setConstants();
     parser.parse();

      var portalUrl = "http://www.arcgis.com";

      esriConfig.defaults.io.proxyUrl = "/proxy";

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

        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
          generateFeatureCollection(fileName);
        }
        else {
          dom.byId('upload-status').innerHTML = '<p style="color:red">Add shapefile as .zip file</p>';
        }

            map.graphics.on("click", function(evt) {
                console.log("geometry type: " + evt.graphic.geometry.type);
                if(evt.graphic.geometry.type == "polygon")
                {
                    selectPolygon();
                }
                else if(evt.graphic.geometry.type == "multipoint" || evt.graphic.geometry.type == "point")
                {
                    selectMarker();
                }
            });
        });

    });


      });

      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: http://davidwalsh.name/fakepath
        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
        //http://www.arcgis.com/apidocs/rest/index.html?generate.html
        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
        request({
          url: portalUrl + '/sharing/rest/content/features/generate',
          content: myContent,
          form: dom.byId('uploadForm'),
          handleAs: 'json',
          load: lang.hitch(this, function (response) {
            if (response.error) {
              errorHandler(response.error);
              return;
            }
            var layerName = response.featureCollection.layers[0].layerDefinition.name;
            dom.byId('upload-status').innerHTML = '<b>Loaded: </b>' + layerName;
            addShapefileToMap(response.featureCollection);
          }),
          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) {
            map.infoWindow.setFeatures([event.graphic]);
          });
          //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;
          layers.push(featureLayer);
        });
        map.addLayers(layers);
        map.setExtent(fullExtent.expand(1.25), true);

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

    function setConstants() {
        PROJECT_OUTLINE = new esri.Color(([0,255,0])); 
        PROJECT_FILL = new esri.Color([0,255,0,0.5]);
        PARCEL_OUTLINE = new esri.Color(([0,0,255])); 
        PARCEL_FILL = new esri.Color([0,0,255,0.5]);
        PLOT_OUTLINE = new esri.Color(([255,0,0])); 
        PLOT_FILL = new esri.Color([255,0,0,0.5]);
    }

    function createToolbar() {
        toolbar = new esri.toolbars.Draw(map);     
    }

    function drawEnd(geometry, pType, outline, fill) {
        toolbar.deactivate();
        map.showZoomSlider();
        console.log("geometry: " + geometry.type);
        var text_symbol = null;
        switch (geometry.type) {
            case "point":
            case "multipoint":
              symbol = new esri.symbol.PictureMarkerSymbol(markerPictures[pType], 13, 13);
              break;
            default:
              symbol = new esri.symbol.SimpleFillSymbol();
              symbol.setColor(fill);
              symbol.setOutline(new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, outline, 2)); 
              break;
        }

        var graphic = new esri.Graphic(geometry, symbol);
        map.graphics.add(graphic);

        var map_obj = new MapObject(pType, pType, graphic, geometry.type);
        mapManager.Add(map_obj);

        if(toolbarEvent != null)
        {
            toolbarEvent.remove();
            toolbarEvent = null;
        }

    }

错误发生在这一行:

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

1 个答案:

答案 0 :(得分:1)

您有一个简单的范围错误 - 变量dom被声明为此函数的参数:

require([...,"dojo/dom",...], function(...,dom,...) {...});

你的下一个功能声明是:

function generateFeatureCollection (fileName) {
    ...
    dom.byId(...);
    ...
}

但变量dom未在此函数中定义,因此您无法在此处使用它。您需要将其传递给函数:

function generateFeatureCollection (fileName, dom) {...}

如果您要将其传递给每个函数,它会变得非常笨拙,将dom函数中的require变量分配给全局变量,或者在需要它的地方重新声明它。来自docs

require(["dojo/dom"], function(dom){
    // fetch a node by id="someNode"
    var node = dom.byId("someNode");
});