{"version":3,"file":"esri-leaflet.js","sources":["../src/EsriLeaflet.js","../src/Util.js","../src/Request.js","../src/Services/Service.js","../src/Services/FeatureLayer.js","../src/Services/MapService.js","../src/Services/ImageService.js","../src/Tasks/Task.js","../src/Tasks/Query.js","../src/Tasks/Find.js","../src/Tasks/Identify.js","../src/Tasks/IdentifyImage.js","../src/Tasks/IdentifyFeatures.js","../src/Layers/BasemapLayer.js","../src/Layers/RasterLayer.js","../src/Layers/DynamicMapLayer.js","../src/Layers/ImageMapLayer.js","../src/Layers/TiledMapLayer.js","../src/Layers/FeatureLayer/FeatureGrid.js","../src/Layers/FeatureLayer/FeatureManager.js","../src/Layers/FeatureLayer/FeatureLayer.js","../src/Controls/Logo.js"],"names":["EsriLeaflet","VERSION","Layers","Services","Controls","Tasks","Util","Support","CORS","window","XMLHttpRequest","pointerEvents","document","documentElement","style","L","esri","clone","obj","target","i","hasOwnProperty","pointsEqual","a","b","length","closeRing","coordinates","push","ringIsClockwise","ringToTest","pt2","total","rLength","pt1","vertexIntersectsVertex","a1","a2","b1","b2","uaT","ubT","uB","ua","ub","arrayIntersectsArray","j","coordinatesContainPoint","point","contains","l","coordinatesContainCoordinates","outer","inner","intersects","convertRingsToGeoJSON","rings","x","outerRing","hole","outerRings","holes","r","ring","slice","polygon","uncontainedHoles","pop","contained","reverse","type","orientRings","poly","output","shift","flattenMultiPolygonRings","raf","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","cb","setTimeout","extentToBounds","extent","sw","LatLng","ymin","xmin","ne","ymax","xmax","LatLngBounds","boundsToExtent","bounds","latLngBounds","getSouthWest","lng","lat","getNorthEast","spatialReference","wkid","arcgisToGeojson","arcgis","idAttribute","geojson","y","points","paths","geometry","attributes","properties","id","OBJECTID","FID","geojsonToArcGIS","result","features","geometries","responseToFeatureCollection","response","objectIdField","objectIdFieldName","fields","name","featureCollection","results","cleanUrl","url","replace","isArcgisOnline","test","geojsonTypeToArcGIS","geoJsonType","arcgisGeometryType","bind","serialize","params","data","f","key","value","param","Object","prototype","toString","call","JSON","stringify","join","valueOf","encodeURIComponent","createRequest","callback","context","httpRequest","onerror","onreadystatechange","falseFn","error","code","message","readyState","parse","responseText","e","callbacks","_EsriLeafletCallbacks","Request","request","paramString","requestLength","open","send","setRequestHeader","get","JSONP","console","warn","post","XMLHTTP","callbackId","script","DomUtil","create","body","src","responseType","abort","_callback","Service","Class","extend","includes","Mixin","Events","options","proxy","useCors","initialize","this","_requestQueue","_authenticating","setOptions","path","_request","metadata","authenticate","token","_runQueue","method","fire","wrappedCallback","_createServiceCallback","apply","service","FeatureLayer","query","Query","addFeature","feature","addResults","undefined","updateFeature","updateResults","deleteFeature","objectIds","deleteResults","deleteFeatures","ids","featureLayer","MapService","identify","identifyFeatures","find","Find","mapService","ImageService","IdentifyImage","imageService","Task","generateSetter","endpoint","_service","setters","setter","offset","limit","precision","featureIds","returnGeometry","where","outSr","outFields","within","_setGeometry","spatialRel","overlaps","nearby","latlng","radius","latLng","geometryType","units","distance","inSr","string","between","start","end","time","simplify","map","factor","mapWidth","Math","abs","getBounds","getWest","getEast","maxAllowableOffset","getSize","orderBy","fieldName","order","orderByFields","run","_cleanParams","count","returnCountOnly","returnIdsOnly","returnExtentOnly","pixelSize","layer","getLatLng","GeoJSON","getLayers","toGeoJSON","text","sr","layers","dynamicLayers","returnZ","returnM","gdbVersion","layerDefs","Identify","setMosaicRule","setRenderingRule","setPixelSize","returnCatalogItems","at","getMosaicRule","mosaicRule","getRenderingRule","renderingRule","getPixelSize","_responseToGeoJSON","location","catalogItems","catalogItemVisibilities","geoJSON","pixel","crs","objectId","Values","values","catalogItemVisibility","identifyImage","IdentifyFeatures","tolerance","on","size","imageDisplay","mapExtent","layerDef","layerId","tileProtocol","protocol","BasemapLayer","TileLayer","statics","TILES","Streets","urlTemplate","attributionUrl","hideLogo","logoPosition","minZoom","maxZoom","subdomains","attribution","Topographic","Oceans","OceansLabels","NationalGeographic","DarkGray","DarkGrayLabels","Gray","GrayLabels","Imagery","ImageryLabels","ImageryTransportation","ShadedRelief","ShadedReliefLabels","Terrain","TerrainLabels","config","Error","tileOptions","_getAttributionData","_logo","Logo","position","onAdd","_hasEsriLogo","addTo","_updateMapAttribution","onRemove","_container","removeControl","off","getAttribution","attributions","_attributions","c","contributors","contributor","coverageAreas","coverageArea","southWest","bbox","northEast","score","zoomMin","zoomMax","sort","_map","attributionControl","newAttributions","zoom","getZoom","match","substr","attributionElement","querySelector","innerHTML","maxWidth","basemapLayer","RasterLayer","opacity","_update","limitExecByInterval","updateInterval","split","bboxSR","imageSR","_currentImage","_bounds","equals","addLayer","removeLayer","_popup","_getPopupData","_resetPopupState","bindPopup","fn","popupOptions","_shouldRenderPopup","_lastClick","popup","_popupFunction","unbindPopup","closePopup","removeFrom","bringToFront","bringToBack","getOpacity","setOpacity","getTimeRange","from","to","setTimeRange","_renderImage","image","ImageOverlay","once","newImage","oldImage","_animatingZoom","_panTransition","_inProgress","_buildExportParams","_requestExport","_renderPopup","content","setLatLng","setContent","openOn","_propagateEvent","DynamicMapLayer","timeOptions","format","transparent","setLayers","getLayerDefs","setLayerDefs","getTimeOptions","setTimeOptions","identifyRequest","project","_northEast","_southWest","top","latLngToLayerPoint","bottom","dpi","href","getParamString","dynamicMapLayer","ImageMapLayer","setPixelType","pixelType","getPixelType","setBandIds","bandIds","isArray","getBandIds","setNoData","noData","noDataInterpretation","getNoData","getNoDataInterpretation","interpolation","compressionQuality","imageMapLayer","TiledMapLayer","tileUrl","tokenQs","tiledMapLayer","FeatureGrid","cellSize","addEventListener","getEvents","_reset","removeEventListener","_removeCells","events","viewreset","moveend","zoomend","_onZoom","hasLayer","_cells","_activeCells","_cellsToLoad","_cellsTotal","_resetWrap","infinite","_getCellSize","wrapLng","_wrapLng","floor","ceil","wrapLat","_wrapLat","getPixelBounds","cellPadding","topLeft","min","subtract","divideBy","max","cellBounds","add","_removeOtherCells","_addCells","coords","queue","center","getCenter","Point","z","cellsToLoad","distanceTo","_addCell","_cellCoordsToBounds","nwPoint","multiplyBy","sePoint","nw","unproject","wrap","se","_cellCoordsToKey","_keyToCellCoords","kArr","parseInt","_removeCell","cell","cellLeave","_wrapCoords","cellEnter","createCell","wrapNum","BinarySearchIndex","FeatureManager","timeField","timeFilterMode","simplifyFactor","oidCheck","_startTimeIndex","_endTimeIndex","_timeIndex","_cache","_currentSnapshot","_activeRequests","_pendingRequests","_requestFeatures","_buildQuery","exceededTransferLimit","_addFeatures","_cacheKey","_buildTimeIndexes","createLayers","setWhere","oldSnapshot","newShapshot","pendingRequests","requestError","requestCallback","removeLayers","addLayers","getWhere","oldFrom","oldTo","_filterExistingFeatures","refresh","newFrom","newTo","layersToRemove","_getFeaturesInTimeRange","layersToAdd","indexOf","shouldRemoveLayer","splice","search","startTimes","endTimes","concat","startTimeEntries","endTimeEntries","Date","bulkAdd","timeEntries","_featureWithinTimeRange","date","startDate","endDate","_getMetadata","_metadata","_query","currentIndex","currentElement","resultIndex","minIndex","maxIndex","round","dirty","startIndex","endIndex","items","EVENTS","cacheLayers","_layers","_leafletIds","_key","random","_zooming","createNewLayer","geometryToLayer","pointToLayer","coordsToLatLng","_updateLayerGeometry","latlngs","coordsToLatLngs","setLatLngs","newLayer","_originalStyle","_leaflet_id","_popupOptions","onEachFeature","resetStyle","permanent","cacheKey","cellKey","mapBounds","removable","setFeatureStyle","setStyle","eachFeature","defaultOptions","Path","fill","popupContent","groupLayers","gLayer","getFeature","Control","marginTop","marginLeft","marginBottom","marginRight","div","_adjustLogo","_size","newSize","mapSize","logo"],"mappings":"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","sourcesContent":["var EsriLeaflet = { //jshint ignore:line\n  VERSION: '1.0.0-rc.7',\n  Layers: {},\n  Services: {},\n  Controls: {},\n  Tasks: {},\n  Util: {},\n  Support: {\n    CORS: !!(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()),\n    pointerEvents: document.documentElement.style.pointerEvents === ''\n  }\n};\n\nif(typeof window !== 'undefined' && window.L){\n  window.L.esri = EsriLeaflet;\n}\n","(function(EsriLeaflet){\n\n  // normalize request animation frame\n  var raf = window.requestAnimationFrame ||\n     window.webkitRequestAnimationFrame ||\n     window.mozRequestAnimationFrame ||\n     window.msRequestAnimationFrame ||\n     function(cb) { return window.setTimeout(cb, 1000 / 60); };\n\n  // shallow object clone for feature properties and attributes\n  // from http://jsperf.com/cloning-an-object/2\n  function clone(obj) {\n    var target = {};\n    for (var i in obj) {\n      if (obj.hasOwnProperty(i)) {\n        target[i] = obj[i];\n      }\n    }\n    return target;\n  }\n\n  // checks if 2 x,y points are equal\n  function pointsEqual(a, b) {\n    for (var i = 0; i < a.length; i++) {\n      if (a[i] !== b[i]) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  // checks if the first and last points of a ring are equal and closes the ring\n  function closeRing(coordinates) {\n    if (!pointsEqual(coordinates[0], coordinates[coordinates.length - 1])) {\n      coordinates.push(coordinates[0]);\n    }\n    return coordinates;\n  }\n\n  // determine if polygon ring coordinates are clockwise. clockwise signifies outer ring, counter-clockwise an inner ring\n  // or hole. this logic was found at http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-\n  // points-are-in-clockwise-order\n  function ringIsClockwise(ringToTest) {\n    var total = 0,i = 0;\n    var rLength = ringToTest.length;\n    var pt1 = ringToTest[i];\n    var pt2;\n    for (i; i < rLength - 1; i++) {\n      pt2 = ringToTest[i + 1];\n      total += (pt2[0] - pt1[0]) * (pt2[1] + pt1[1]);\n      pt1 = pt2;\n    }\n    return (total >= 0);\n  }\n\n  // ported from terraformer.js https://github.com/Esri/Terraformer/blob/master/terraformer.js#L504-L519\n  function vertexIntersectsVertex(a1, a2, b1, b2) {\n    var uaT = (b2[0] - b1[0]) * (a1[1] - b1[1]) - (b2[1] - b1[1]) * (a1[0] - b1[0]);\n    var ubT = (a2[0] - a1[0]) * (a1[1] - b1[1]) - (a2[1] - a1[1]) * (a1[0] - b1[0]);\n    var uB  = (b2[1] - b1[1]) * (a2[0] - a1[0]) - (b2[0] - b1[0]) * (a2[1] - a1[1]);\n\n    if ( uB !== 0 ) {\n      var ua = uaT / uB;\n      var ub = ubT / uB;\n\n      if ( 0 <= ua && ua <= 1 && 0 <= ub && ub <= 1 ) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  // ported from terraformer.js https://github.com/Esri/Terraformer/blob/master/terraformer.js#L521-L531\n  function arrayIntersectsArray(a, b) {\n    for (var i = 0; i < a.length - 1; i++) {\n      for (var j = 0; j < b.length - 1; j++) {\n        if (vertexIntersectsVertex(a[i], a[i + 1], b[j], b[j + 1])) {\n          return true;\n        }\n      }\n    }\n\n    return false;\n  }\n\n  // ported from terraformer.js https://github.com/Esri/Terraformer/blob/master/terraformer.js#L470-L480\n  function coordinatesContainPoint(coordinates, point) {\n    var contains = false;\n    for(var i = -1, l = coordinates.length, j = l - 1; ++i < l; j = i) {\n      if (((coordinates[i][1] <= point[1] && point[1] < coordinates[j][1]) ||\n           (coordinates[j][1] <= point[1] && point[1] < coordinates[i][1])) &&\n          (point[0] < (coordinates[j][0] - coordinates[i][0]) * (point[1] - coordinates[i][1]) / (coordinates[j][1] - coordinates[i][1]) + coordinates[i][0])) {\n        contains = !contains;\n      }\n    }\n    return contains;\n  }\n\n  // ported from terraformer-arcgis-parser.js https://github.com/Esri/terraformer-arcgis-parser/blob/master/terraformer-arcgis-parser.js#L106-L113\n  function coordinatesContainCoordinates(outer, inner){\n    var intersects = arrayIntersectsArray(outer, inner);\n    var contains = coordinatesContainPoint(outer, inner[0]);\n    if(!intersects && contains){\n      return true;\n    }\n    return false;\n  }\n\n  // do any polygons in this array contain any other polygons in this array?\n  // used for checking for holes in arcgis rings\n  // ported from terraformer-arcgis-parser.js https://github.com/Esri/terraformer-arcgis-parser/blob/master/terraformer-arcgis-parser.js#L117-L172\n  function convertRingsToGeoJSON(rings){\n    var outerRings = [];\n    var holes = [];\n    var x; // iterator\n    var outerRing; // current outer ring being evaluated\n    var hole; // current hole being evaluated\n\n    // for each ring\n    for (var r = 0; r < rings.length; r++) {\n      var ring = closeRing(rings[r].slice(0));\n      if(ring.length < 4){\n        continue;\n      }\n      // is this ring an outer ring? is it clockwise?\n      if(ringIsClockwise(ring)){\n        var polygon = [ ring ];\n        outerRings.push(polygon); // push to outer rings\n      } else {\n        holes.push(ring); // counterclockwise push to holes\n      }\n    }\n\n    var uncontainedHoles = [];\n\n    // while there are holes left...\n    while(holes.length){\n      // pop a hole off out stack\n      hole = holes.pop();\n\n      // loop over all outer rings and see if they contain our hole.\n      var contained = false;\n      for (x = outerRings.length - 1; x >= 0; x--) {\n        outerRing = outerRings[x][0];\n        if(coordinatesContainCoordinates(outerRing, hole)){\n          // the hole is contained push it into our polygon\n          outerRings[x].push(hole);\n          contained = true;\n          break;\n        }\n      }\n\n      // ring is not contained in any outer ring\n      // sometimes this happens https://github.com/Esri/esri-leaflet/issues/320\n      if(!contained){\n        uncontainedHoles.push(hole);\n      }\n    }\n\n    // if we couldn't match any holes using contains we can try intersects...\n    while(uncontainedHoles.length){\n      // pop a hole off out stack\n      hole = uncontainedHoles.pop();\n\n      // loop over all outer rings and see if any intersect our hole.\n      var intersects = false;\n      for (x = outerRings.length - 1; x >= 0; x--) {\n        outerRing = outerRings[x][0];\n        if(arrayIntersectsArray(outerRing, hole)){\n          // the hole is contained push it into our polygon\n          outerRings[x].push(hole);\n          intersects = true;\n          break;\n        }\n      }\n\n      if(!intersects) {\n        outerRings.push([hole.reverse()]);\n      }\n    }\n\n    if(outerRings.length === 1){\n      return {\n        type: 'Polygon',\n        coordinates: outerRings[0]\n      };\n    } else {\n      return {\n        type: 'MultiPolygon',\n        coordinates: outerRings\n      };\n    }\n  }\n\n  // This function ensures that rings are oriented in the right directions\n  // outer rings are clockwise, holes are counterclockwise\n  // used for converting GeoJSON Polygons to ArcGIS Polygons\n  function orientRings(poly){\n    var output = [];\n    var polygon = poly.slice(0);\n    var outerRing = closeRing(polygon.shift().slice(0));\n    if(outerRing.length >= 4){\n      if(!ringIsClockwise(outerRing)){\n        outerRing.reverse();\n      }\n\n      output.push(outerRing);\n\n      for (var i = 0; i < polygon.length; i++) {\n        var hole = closeRing(polygon[i].slice(0));\n        if(hole.length >= 4){\n          if(ringIsClockwise(hole)){\n            hole.reverse();\n          }\n          output.push(hole);\n        }\n      }\n    }\n\n    return output;\n  }\n\n  // This function flattens holes in multipolygons to one array of polygons\n  // used for converting GeoJSON Polygons to ArcGIS Polygons\n  function flattenMultiPolygonRings(rings){\n    var output = [];\n    for (var i = 0; i < rings.length; i++) {\n      var polygon = orientRings(rings[i]);\n      for (var x = polygon.length - 1; x >= 0; x--) {\n        var ring = polygon[x].slice(0);\n        output.push(ring);\n      }\n    }\n    return output;\n  }\n\n  // convert an extent (ArcGIS) to LatLngBounds (Leaflet)\n  EsriLeaflet.Util.extentToBounds = function(extent){\n    var sw = new L.LatLng(extent.ymin, extent.xmin);\n    var ne = new L.LatLng(extent.ymax, extent.xmax);\n    return new L.LatLngBounds(sw, ne);\n  };\n\n  // convert an LatLngBounds (Leaflet) to extent (ArcGIS)\n  EsriLeaflet.Util.boundsToExtent = function(bounds) {\n    bounds = L.latLngBounds(bounds);\n    return {\n      'xmin': bounds.getSouthWest().lng,\n      'ymin': bounds.getSouthWest().lat,\n      'xmax': bounds.getNorthEast().lng,\n      'ymax': bounds.getNorthEast().lat,\n      'spatialReference': {\n        'wkid' : 4326\n      }\n    };\n  };\n\n  EsriLeaflet.Util.arcgisToGeojson = function (arcgis, idAttribute){\n    var geojson = {};\n\n    if(typeof arcgis.x === 'number' && typeof arcgis.y === 'number'){\n      geojson.type = 'Point';\n      geojson.coordinates = [arcgis.x, arcgis.y];\n    }\n\n    if(arcgis.points){\n      geojson.type = 'MultiPoint';\n      geojson.coordinates = arcgis.points.slice(0);\n    }\n\n    if(arcgis.paths) {\n      if(arcgis.paths.length === 1){\n        geojson.type = 'LineString';\n        geojson.coordinates = arcgis.paths[0].slice(0);\n      } else {\n        geojson.type = 'MultiLineString';\n        geojson.coordinates = arcgis.paths.slice(0);\n      }\n    }\n\n    if(arcgis.rings) {\n      geojson = convertRingsToGeoJSON(arcgis.rings.slice(0));\n    }\n\n    if(arcgis.geometry || arcgis.attributes) {\n      geojson.type = 'Feature';\n      geojson.geometry = (arcgis.geometry) ? EsriLeaflet.Util.arcgisToGeojson(arcgis.geometry) : null;\n      geojson.properties = (arcgis.attributes) ? clone(arcgis.attributes) : null;\n      if(arcgis.attributes) {\n        geojson.id =  arcgis.attributes[idAttribute] || arcgis.attributes.OBJECTID || arcgis.attributes.FID;\n      }\n    }\n\n    return geojson;\n  };\n\n  // GeoJSON -> ArcGIS\n  EsriLeaflet.Util.geojsonToArcGIS = function(geojson, idAttribute){\n    idAttribute = idAttribute || 'OBJECTID';\n    var spatialReference = { wkid: 4326 };\n    var result = {};\n    var i;\n\n    switch(geojson.type){\n    case 'Point':\n      result.x = geojson.coordinates[0];\n      result.y = geojson.coordinates[1];\n      result.spatialReference = spatialReference;\n      break;\n    case 'MultiPoint':\n      result.points = geojson.coordinates.slice(0);\n      result.spatialReference = spatialReference;\n      break;\n    case 'LineString':\n      result.paths = [geojson.coordinates.slice(0)];\n      result.spatialReference = spatialReference;\n      break;\n    case 'MultiLineString':\n      result.paths = geojson.coordinates.slice(0);\n      result.spatialReference = spatialReference;\n      break;\n    case 'Polygon':\n      result.rings = orientRings(geojson.coordinates.slice(0));\n      result.spatialReference = spatialReference;\n      break;\n    case 'MultiPolygon':\n      result.rings = flattenMultiPolygonRings(geojson.coordinates.slice(0));\n      result.spatialReference = spatialReference;\n      break;\n    case 'Feature':\n      if(geojson.geometry) {\n        result.geometry = EsriLeaflet.Util.geojsonToArcGIS(geojson.geometry, idAttribute);\n      }\n      result.attributes = (geojson.properties) ? clone(geojson.properties) : {};\n      if(geojson.id){\n        result.attributes[idAttribute] = geojson.id;\n      }\n      break;\n    case 'FeatureCollection':\n      result = [];\n      for (i = 0; i < geojson.features.length; i++){\n        result.push(EsriLeaflet.Util.geojsonToArcGIS(geojson.features[i], idAttribute));\n      }\n      break;\n    case 'GeometryCollection':\n      result = [];\n      for (i = 0; i < geojson.geometries.length; i++){\n        result.push(EsriLeaflet.Util.geojsonToArcGIS(geojson.geometries[i], idAttribute));\n      }\n      break;\n    }\n\n    return result;\n  };\n\n  EsriLeaflet.Util.responseToFeatureCollection = function(response, idAttribute){\n    var objectIdField;\n\n    if(idAttribute){\n      objectIdField = idAttribute;\n    } else if(response.objectIdFieldName){\n      objectIdField = response.objectIdFieldName;\n    } else if(response.fields) {\n      for (var j = 0; j <= response.fields.length - 1; j++) {\n        if(response.fields[j].type === 'esriFieldTypeOID') {\n          objectIdField = response.fields[j].name;\n          break;\n        }\n      }\n    } else {\n      objectIdField = 'OBJECTID';\n    }\n\n    var featureCollection = {\n      type: 'FeatureCollection',\n      features: []\n    };\n    var features = response.features || response.results;\n    if(features.length){\n      for (var i = features.length - 1; i >= 0; i--) {\n        featureCollection.features.push(EsriLeaflet.Util.arcgisToGeojson(features[i], objectIdField));\n      }\n    }\n\n    return featureCollection;\n  };\n\n    // trim url whitespace and add a trailing slash if needed\n  EsriLeaflet.Util.cleanUrl = function(url){\n    //trim leading and trailing spaces, but not spaces inside the url\n    url = url.replace(/^\\s+|\\s+$|\\A\\s+|\\s+\\z/g, '');\n\n    //add a trailing slash to the url if the user omitted it\n    if(url[url.length-1] !== '/'){\n      url += '/';\n    }\n\n    return url;\n  };\n\n  EsriLeaflet.Util.isArcgisOnline = function(url){\n    /* hosted feature services can emit geojson natively.\n    our check for 'geojson' support will need to be revisted\n    once the functionality makes its way to ArcGIS Server*/\n    return (/\\.arcgis\\.com.*?FeatureServer/g).test(url);\n  };\n\n  EsriLeaflet.Util.geojsonTypeToArcGIS = function (geoJsonType) {\n    var arcgisGeometryType;\n    switch (geoJsonType) {\n    case 'Point':\n      arcgisGeometryType = 'esriGeometryPoint';\n      break;\n    case 'MultiPoint':\n      arcgisGeometryType = 'esriGeometryMultipoint';\n      break;\n    case 'LineString':\n      arcgisGeometryType = 'esriGeometryPolyline';\n      break;\n    case 'MultiLineString':\n      arcgisGeometryType = 'esriGeometryPolyline';\n      break;\n    case 'Polygon':\n      arcgisGeometryType = 'esriGeometryPolygon';\n      break;\n    case 'MultiPolygon':\n      arcgisGeometryType = 'esriGeometryPolygon';\n      break;\n    }\n    return arcgisGeometryType;\n  };\n\n  EsriLeaflet.Util.requestAnimationFrame = L.Util.bind(raf, window);\n\n})(EsriLeaflet);","(function(EsriLeaflet){\n\n  var callbacks = 0;\n\n  window._EsriLeafletCallbacks = {};\n\n  function serialize(params){\n    var data = '';\n\n    params.f = params.f || 'json';\n\n    for (var key in params){\n      if(params.hasOwnProperty(key)){\n        var param = params[key];\n        var type = Object.prototype.toString.call(param);\n        var value;\n\n        if(data.length){\n          data += '&';\n        }\n\n        if (type === '[object Array]'){\n          value = (Object.prototype.toString.call(param[0]) === '[object Object]') ? JSON.stringify(param) : param.join(',');\n        } else if (type === '[object Object]') {\n          value = JSON.stringify(param);\n        } else if (type === '[object Date]'){\n          value = param.valueOf();\n        } else {\n          value = param;\n        }\n\n        data += encodeURIComponent(key) + '=' + encodeURIComponent(value);\n      }\n    }\n\n    return data;\n  }\n\n  function createRequest(callback, context){\n    var httpRequest = new XMLHttpRequest();\n\n    httpRequest.onerror = function(e) {\n      httpRequest.onreadystatechange = L.Util.falseFn;\n\n      callback.call(context, {\n        error: {\n          code: 500,\n          message: 'XMLHttpRequest error'\n        }\n      }, null);\n    };\n\n    httpRequest.onreadystatechange = function(){\n      var response;\n      var error;\n\n      if (httpRequest.readyState === 4) {\n        try {\n          response = JSON.parse(httpRequest.responseText);\n        } catch(e) {\n          response = null;\n          error = {\n            code: 500,\n            message: 'Could not parse response as JSON. This could also be caused by a CORS or XMLHttpRequest error.'\n          };\n        }\n\n        if (!error && response.error) {\n          error = response.error;\n          response = null;\n        }\n\n        httpRequest.onerror = L.Util.falseFn;\n\n        callback.call(context, error, response);\n      }\n    };\n\n    return httpRequest;\n  }\n\n  // AJAX handlers for CORS (modern browsers) or JSONP (older browsers)\n  EsriLeaflet.Request = {\n    request: function(url, params, callback, context){\n      var paramString = serialize(params);\n      var httpRequest = createRequest(callback, context);\n      var requestLength = (url + '?' + paramString).length;\n\n      // request is less then 2000 characters and the browser supports CORS, make GET request with XMLHttpRequest\n      if(requestLength <= 2000 && L.esri.Support.CORS){\n        httpRequest.open('GET', url + '?' + paramString);\n        httpRequest.send(null);\n\n      // request is less more then 2000 characters and the browser supports CORS, make POST request with XMLHttpRequest\n      } else if (requestLength > 2000 && L.esri.Support.CORS){\n        httpRequest.open('POST', url);\n        httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n        httpRequest.send(paramString);\n\n      // request is less more then 2000 characters and the browser does not support CORS, make a JSONP request\n      } else if(requestLength <= 2000 && !L.esri.Support.CORS){\n        return L.esri.Request.get.JSONP(url, params, callback, context);\n\n      // request is longer then 2000 characters and the browser does not support CORS, log a warning\n      } else {\n        if(console && console.warn){\n          console.warn('a request to ' + url + ' was longer then 2000 characters and this browser cannot make a cross-domain post request. Please use a proxy http://esri.github.io/esri-leaflet/api-reference/request.html');\n          return;\n        }\n      }\n\n      return httpRequest;\n    },\n    post: {\n      XMLHTTP: function (url, params, callback, context) {\n        var httpRequest = createRequest(callback, context);\n        httpRequest.open('POST', url);\n        httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n        httpRequest.send(serialize(params));\n\n        return httpRequest;\n      }\n    },\n\n    get: {\n      CORS: function (url, params, callback, context) {\n        var httpRequest = createRequest(callback, context);\n\n        httpRequest.open('GET', url + '?' + serialize(params), true);\n        httpRequest.send(null);\n\n        return httpRequest;\n      },\n      JSONP: function(url, params, callback, context){\n        var callbackId = 'c' + callbacks;\n\n        params.callback = 'window._EsriLeafletCallbacks.' + callbackId;\n\n        var script = L.DomUtil.create('script', null, document.body);\n        script.type = 'text/javascript';\n        script.src = url + '?' +  serialize(params);\n        script.id = callbackId;\n\n        window._EsriLeafletCallbacks[callbackId] = function(response){\n          if(window._EsriLeafletCallbacks[callbackId] !== true){\n            var error;\n            var responseType = Object.prototype.toString.call(response);\n\n            if(!(responseType === '[object Object]' || responseType === '[object Array]')){\n              error = {\n                error: {\n                  code: 500,\n                  message: 'Expected array or object as JSONP response'\n                }\n              };\n              response = null;\n            }\n\n            if (!error && response.error) {\n              error = response;\n              response = null;\n            }\n\n            callback.call(context, error, response);\n            window._EsriLeafletCallbacks[callbackId] = true;\n          }\n        };\n\n        callbacks++;\n\n        return {\n          id: callbackId,\n          url: script.src,\n          abort: function(){\n            window._EsriLeafletCallbacks._callback[callbackId]({\n              code: 0,\n              message: 'Request aborted.'\n            });\n          }\n        };\n      }\n    }\n  };\n\n  // choose the correct AJAX handler depending on CORS support\n  EsriLeaflet.get = (EsriLeaflet.Support.CORS) ? EsriLeaflet.Request.get.CORS : EsriLeaflet.Request.get.JSONP;\n\n  // always use XMLHttpRequest for posts\n  EsriLeaflet.post = EsriLeaflet.Request.post.XMLHTTP;\n\n  // expose a common request method the uses GET\\POST based on request length\n  EsriLeaflet.request = EsriLeaflet.Request.request;\n\n})(EsriLeaflet);","EsriLeaflet.Services.Service = L.Class.extend({\n\n  includes: L.Mixin.Events,\n\n  options: {\n    proxy: false,\n    useCors: EsriLeaflet.Support.CORS\n  },\n\n  initialize: function (options) {\n    options = options || {};\n    this._requestQueue = [];\n    this._authenticating = false;\n    L.Util.setOptions(this, options);\n    this.options.url = EsriLeaflet.Util.cleanUrl(this.options.url);\n  },\n\n  get: function (path, params, callback, context) {\n    return this._request('get', path, params, callback, context);\n  },\n\n  post: function (path, params, callback, context) {\n    return this._request('post', path, params, callback, context);\n  },\n\n  request: function (path, params, callback, context) {\n    return this._request('request', path, params, callback, context);\n  },\n\n  metadata: function (callback, context) {\n    return this._request('get', '', {}, callback, context);\n  },\n\n  authenticate: function(token){\n    this._authenticating = false;\n    this.options.token = token;\n    this._runQueue();\n    return this;\n  },\n\n  _request: function(method, path, params, callback, context){\n    this.fire('requeststart', {\n      url: this.options.url + path,\n      params: params,\n      method: method\n    });\n\n    var wrappedCallback = this._createServiceCallback(method, path, params, callback, context);\n\n    if (this.options.token) {\n      params.token = this.options.token;\n    }\n\n    if (this._authenticating) {\n      this._requestQueue.push([method, path, params, callback, context]);\n      return;\n    } else {\n      var url = (this.options.proxy) ? this.options.proxy + '?' + this.options.url + path : this.options.url + path;\n\n      if((method === 'get' || method === 'request') && !this.options.useCors){\n        return EsriLeaflet.Request.get.JSONP(url, params, wrappedCallback);\n      } else {\n        return EsriLeaflet[method](url, params, wrappedCallback);\n      }\n    }\n  },\n\n  _createServiceCallback: function(method, path, params, callback, context){\n    var request = [method, path, params, callback, context];\n\n    return L.Util.bind(function(error, response){\n\n      if (error && (error.code === 499 || error.code === 498)) {\n        this._authenticating = true;\n\n        this._requestQueue.push(request);\n\n        this.fire('authenticationrequired', {\n          authenticate: L.Util.bind(this.authenticate, this)\n        });\n      } else {\n        callback.call(context, error, response);\n\n        if(error) {\n          this.fire('requesterror', {\n            url: this.options.url + path,\n            params: params,\n            message: error.message,\n            code: error.code,\n            method: method\n          });\n        } else {\n          this.fire('requestsuccess', {\n            url: this.options.url + path,\n            params: params,\n            response: response,\n            method: method\n          });\n        }\n\n        this.fire('requestend', {\n          url: this.options.url + path,\n          params: params,\n          method: method\n        });\n      }\n    }, this);\n  },\n\n  _runQueue: function(){\n    for (var i = this._requestQueue.length - 1; i >= 0; i--) {\n      var request = this._requestQueue[i];\n      var method = request.shift();\n      this[method].apply(this, request);\n    }\n    this._requestQueue = [];\n  }\n\n});\n\nEsriLeaflet.Services.service = function(params){\n  return new EsriLeaflet.Services.Service(params);\n};","EsriLeaflet.Services.FeatureLayer = EsriLeaflet.Services.Service.extend({\n\n  options: {\n    idAttribute: 'OBJECTID'\n  },\n\n  query: function(){\n    return new EsriLeaflet.Tasks.Query(this);\n  },\n\n  addFeature: function(feature, callback, context) {\n    delete feature.id;\n\n    feature = EsriLeaflet.Util.geojsonToArcGIS(feature);\n\n    return this.post('addFeatures', {\n      features: [feature]\n    }, function(error, response){\n      var result = (response && response.addResults) ? response.addResults[0] : undefined;\n      if(callback){\n        callback.call(context, error || response.addResults[0].error, result);\n      }\n    }, context);\n  },\n\n  updateFeature: function(feature, callback, context) {\n    feature = EsriLeaflet.Util.geojsonToArcGIS(feature, this.options.idAttribute);\n\n    return this.post('updateFeatures', {\n      features: [feature]\n    }, function(error, response){\n      var result = (response && response.updateResults) ? response.updateResults[0] : undefined;\n      if(callback){\n        callback.call(context, error || response.updateResults[0].error, result);\n      }\n    }, context);\n  },\n\n  deleteFeature: function(id, callback, context) {\n    return this.post('deleteFeatures', {\n      objectIds: id\n    }, function(error, response){\n      var result = (response && response.deleteResults) ? response.deleteResults[0] : undefined;\n      if(callback){\n        callback.call(context, error || response.deleteResults[0].error, result);\n      }\n    }, context);\n  },\n\n  deleteFeatures: function(ids, callback, context) {\n    return this.post('deleteFeatures', {\n      objectIds: ids\n    }, function(error, response){\n      // pass back the entire array\n      var result = (response && response.deleteResults) ? response.deleteResults : undefined;\n      if(callback){\n        callback.call(context, error || response.deleteResults[0].error, result);\n      }\n    }, context);\n  }\n});\n\nEsriLeaflet.Services.featureLayer = function(options) {\n  return new EsriLeaflet.Services.FeatureLayer(options);\n};","EsriLeaflet.Services.MapService = EsriLeaflet.Services.Service.extend({\n\n  identify: function () {\n    return new EsriLeaflet.Tasks.identifyFeatures(this);\n  },\n\n  find: function () {\n    return new EsriLeaflet.Tasks.Find(this);\n  },\n\n  query: function () {\n    return new EsriLeaflet.Tasks.Query(this);\n  }\n\n});\n\nEsriLeaflet.Services.mapService = function(params){\n  return new EsriLeaflet.Services.MapService(params);\n};","EsriLeaflet.Services.ImageService = EsriLeaflet.Services.Service.extend({\n\n  query: function () {\n    return new EsriLeaflet.Tasks.Query(this);\n  },\n\n  identify: function() {\n    return new EsriLeaflet.Tasks.IdentifyImage(this);\n  }\n});\n\nEsriLeaflet.Services.imageService = function(params){\n  return new EsriLeaflet.Services.ImageService(params);\n};","EsriLeaflet.Tasks.Task = L.Class.extend({\n\n  options: {\n    proxy: false,\n    useCors: EsriLeaflet.Support.CORS\n  },\n\n  //Generate a method for each methodName:paramName in the setters for this task.\n  generateSetter: function(param, context){\n    return L.Util.bind(function(value){\n      this.params[param] = value;\n      return this;\n    }, context);\n  },\n\n  initialize: function(endpoint){\n    // endpoint can be either a url (and options) for an ArcGIS Rest Service or an instance of EsriLeaflet.Service\n    if(endpoint.request && endpoint.options){\n      this._service = endpoint;\n      L.Util.setOptions(this, endpoint.options);\n    } else {\n      L.Util.setOptions(this, endpoint);\n      this.options.url = L.esri.Util.cleanUrl(endpoint.url);\n    }\n\n    // clone default params into this object\n    this.params = L.Util.extend({}, this.params || {});\n\n    // generate setter methods based on the setters object implimented a child class\n    if(this.setters){\n      for (var setter in this.setters){\n        var param = this.setters[setter];\n        this[setter] = this.generateSetter(param, this);\n      }\n    }\n  },\n\n  token: function(token){\n    if(this._service){\n      this._service.authenticate(token);\n    } else {\n      this.params.token = token;\n    }\n    return this;\n  },\n\n  request: function(callback, context){\n    if(this._service){\n      return this._service.request(this.path, this.params, callback, context);\n    } else {\n      return this._request('request', this.path, this.params, callback, context);\n    }\n  },\n\n  _request: function(method, path, params, callback, context){\n    var url = (this.options.proxy) ? this.options.proxy + '?' + this.options.url + path : this.options.url + path;\n    if((method === 'get' || method === 'request') && !this.options.useCors){\n      return EsriLeaflet.Request.get.JSONP(url, params, callback, context);\n    } else{\n      return EsriLeaflet[method](url, params, callback, context);\n    }\n  }\n});","EsriLeaflet.Tasks.Query = EsriLeaflet.Tasks.Task.extend({\n  setters: {\n    'offset': 'offset',\n    'limit': 'limit',\n    'fields': 'outFields',\n    'precision': 'geometryPrecision',\n    'featureIds': 'objectIds',\n    'returnGeometry': 'returnGeometry',\n    'token': 'token'\n  },\n\n  path: 'query',\n\n  params: {\n    returnGeometry: true,\n    where: '1=1',\n    outSr: 4326,\n    outFields: '*'\n  },\n\n  within: function(geometry){\n    this._setGeometry(geometry);\n    this.params.spatialRel = 'esriSpatialRelContains'; // will make code read layer within geometry, to the api this will reads geometry contains layer\n    return this;\n  },\n\n  intersects: function(geometry){\n    this._setGeometry(geometry);\n    this.params.spatialRel = 'esriSpatialRelIntersects';\n    return this;\n  },\n\n  contains: function(geometry){\n    this._setGeometry(geometry);\n    this.params.spatialRel = 'esriSpatialRelWithin'; // will make code read layer contains geometry, to the api this will reads geometry within layer\n    return this;\n  },\n\n  // crosses: function(geometry){\n  //   this._setGeometry(geometry);\n  //   this.params.spatialRel = 'esriSpatialRelCrosses';\n  //   return this;\n  // },\n\n  // touches: function(geometry){\n  //   this._setGeometry(geometry);\n  //   this.params.spatialRel = 'esriSpatialRelTouches';\n  //   return this;\n  // },\n\n  overlaps: function(geometry){\n    this._setGeometry(geometry);\n    this.params.spatialRel = 'esriSpatialRelOverlaps';\n    return this;\n  },\n\n  // only valid for Feature Services running on ArcGIS Server 10.3 or ArcGIS Online\n  nearby: function(latlng, radius){\n    latlng = L.latLng(latlng);\n    this.params.geometry = [latlng.lng, latlng.lat];\n    this.params.geometryType = 'esriGeometryPoint';\n    this.params.spatialRel = 'esriSpatialRelIntersects';\n    this.params.units = 'esriSRUnit_Meter';\n    this.params.distance = radius;\n    this.params.inSr = 4326;\n    return this;\n  },\n\n  where: function(string){\n    this.params.where = string.replace(/\"/g, \"\\'\"); // jshint ignore:line\n    return this;\n  },\n\n  between: function(start, end){\n    this.params.time = [start.valueOf(), end.valueOf()];\n    return this;\n  },\n\n  simplify: function(map, factor){\n    var mapWidth = Math.abs(map.getBounds().getWest() - map.getBounds().getEast());\n    this.params.maxAllowableOffset = (mapWidth / map.getSize().y) * factor;\n    return this;\n  },\n\n  orderBy: function(fieldName, order){\n    order = order || 'ASC';\n    this.params.orderByFields = (this.params.orderByFields) ? this.params.orderByFields + ',' : '';\n    this.params.orderByFields += ([fieldName, order]).join(' ');\n    return this;\n  },\n\n  run: function(callback, context){\n    this._cleanParams();\n\n    // if the service is hosted on arcgis online request geojson directly\n    if(EsriLeaflet.Util.isArcgisOnline(this.options.url)){\n      this.params.f = 'geojson';\n\n      return this.request(function(error, response){\n        callback.call(context, error, response, response);\n      }, context);\n\n    // otherwise convert it in the callback then pass it on\n    } else {\n      return this.request(function(error, response){\n        callback.call(context, error, (response && EsriLeaflet.Util.responseToFeatureCollection(response)), response);\n      }, context);\n    }\n  },\n\n  count: function(callback, context){\n    this._cleanParams();\n    this.params.returnCountOnly = true;\n    return this.request(function(error, response){\n      callback.call(this, error, (response && response.count), response);\n    }, context);\n  },\n\n  ids: function(callback, context){\n    this._cleanParams();\n    this.params.returnIdsOnly = true;\n    return this.request(function(error, response){\n      callback.call(this, error, (response && response.objectIds), response);\n    }, context);\n  },\n\n  // only valid for Feature Services running on ArcGIS Server 10.3 or ArcGIS Online\n  bounds: function(callback, context){\n    this._cleanParams();\n    this.params.returnExtentOnly = true;\n    return this.request(function(error, response){\n      callback.call(context, error, (response && response.extent && EsriLeaflet.Util.extentToBounds(response.extent)), response);\n    }, context);\n  },\n\n  // only valid for image services\n  pixelSize: function(point){\n    point = L.point(point);\n    this.params.pixelSize = [point.x,point.y];\n    return this;\n  },\n\n  // only valid for map services\n  layer: function(layer){\n    this.path = layer + '/query';\n    return this;\n  },\n\n  _cleanParams: function(){\n    delete this.params.returnIdsOnly;\n    delete this.params.returnExtentOnly;\n    delete this.params.returnCountOnly;\n  },\n\n  _setGeometry: function(geometry) {\n    this.params.inSr = 4326;\n\n    // convert bounds to extent and finish\n    if ( geometry instanceof L.LatLngBounds ) {\n      // set geometry + geometryType\n      this.params.geometry = EsriLeaflet.Util.boundsToExtent(geometry);\n      this.params.geometryType = 'esriGeometryEnvelope';\n      return;\n    }\n\n    // convert L.Marker > L.LatLng\n    if(geometry.getLatLng){\n      geometry = geometry.getLatLng();\n    }\n\n    // convert L.LatLng to a geojson point and continue;\n    if (geometry instanceof L.LatLng) {\n      geometry = {\n        type: 'Point',\n        coordinates: [geometry.lng, geometry.lat]\n      };\n    }\n\n    // handle L.GeoJSON, pull out the first geometry\n    if ( geometry instanceof L.GeoJSON ) {\n      //reassign geometry to the GeoJSON value  (we are assuming that only one feature is present)\n      geometry = geometry.getLayers()[0].feature.geometry;\n      this.params.geometry = EsriLeaflet.Util.geojsonToArcGIS(geometry);\n      this.params.geometryType = EsriLeaflet.Util.geojsonTypeToArcGIS(geometry.type);\n    }\n\n    // Handle L.Polyline and L.Polygon\n    if (geometry.toGeoJSON) {\n      geometry = geometry.toGeoJSON();\n    }\n\n    // handle GeoJSON feature by pulling out the geometry\n    if ( geometry.type === 'Feature' ) {\n      // get the geometry of the geojson feature\n      geometry = geometry.geometry;\n    }\n\n    // confirm that our GeoJSON is a point, line or polygon\n    if ( geometry.type === 'Point' ||  geometry.type === 'LineString' || geometry.type === 'Polygon') {\n      this.params.geometry = EsriLeaflet.Util.geojsonToArcGIS(geometry);\n      this.params.geometryType = EsriLeaflet.Util.geojsonTypeToArcGIS(geometry.type);\n      return;\n    }\n\n    // warn the user if we havn't found a\n    /* global console */\n    if(console && console.warn) {\n      console.warn('invalid geometry passed to spatial query. Should be an L.LatLng, L.LatLngBounds or L.Marker or a GeoJSON Point Line or Polygon object');\n    }\n\n    return;\n  }\n});\n\nEsriLeaflet.Tasks.query = function(params){\n  return new EsriLeaflet.Tasks.Query(params);\n};","EsriLeaflet.Tasks.Find = EsriLeaflet.Tasks.Task.extend({\n  setters: {\n    // method name > param name\n    'contains': 'contains',\n    'text': 'searchText',\n    'fields': 'searchFields', // denote an array or single string\n    'spatialReference': 'sr',\n    'sr': 'sr',\n    'layers': 'layers',\n    'returnGeometry': 'returnGeometry',\n    'maxAllowableOffset': 'maxAllowableOffset',\n    'precision': 'geometryPrecision',\n    'dynamicLayers': 'dynamicLayers',\n    'returnZ' : 'returnZ',\n    'returnM' : 'returnM',\n    'gdbVersion' : 'gdbVersion',\n    'token' : 'token'\n  },\n\n  path: 'find',\n\n  params: {\n    sr: 4326,\n    contains: true,\n    returnGeometry: true,\n    returnZ: true,\n    returnM: false\n  },\n\n  layerDefs: function (id, where) {\n    this.params.layerDefs = (this.params.layerDefs) ? this.params.layerDefs + ';' : '';\n    this.params.layerDefs += ([id, where]).join(':');\n    return this;\n  },\n\n  simplify: function(map, factor){\n    var mapWidth = Math.abs(map.getBounds().getWest() - map.getBounds().getEast());\n    this.params.maxAllowableOffset = (mapWidth / map.getSize().y) * factor;\n    return this;\n  },\n\n  run: function (callback, context) {\n    return this.request(function(error, response){\n      callback.call(context, error, (response && EsriLeaflet.Util.responseToFeatureCollection(response)), response);\n    }, context);\n  }\n});\n\nEsriLeaflet.Tasks.find = function (params) {\n  return new EsriLeaflet.Tasks.Find(params);\n};","EsriLeaflet.Tasks.Identify = EsriLeaflet.Tasks.Task.extend({\n  path: 'identify',\n\n  between: function(start, end){\n    this.params.time = [start.valueOf(), end.valueOf()];\n    return this;\n  }\n});\n","EsriLeaflet.Tasks.IdentifyImage = EsriLeaflet.Tasks.Identify.extend({\n  setters: {\n    'setMosaicRule': 'mosaicRule',\n    'setRenderingRule': 'renderingRule',\n    'setPixelSize': 'pixelSize',\n    'returnCatalogItems': 'returnCatalogItems',\n    'returnGeometry': 'returnGeometry'\n  },\n\n  params: {\n    returnGeometry: false\n  },\n\n  at: function(latlng){\n    latlng = L.latLng(latlng);\n    this.params.geometry = JSON.stringify({\n      x: latlng.lng,\n      y: latlng.lat,\n      spatialReference:{\n        wkid: 4326\n      }\n    });\n    this.params.geometryType = 'esriGeometryPoint';\n    return this;\n  },\n\n  getMosaicRule: function() {\n    return this.params.mosaicRule;\n  },\n\n  getRenderingRule: function() {\n    return this.params.renderingRule;\n  },\n\n  getPixelSize: function() {\n    return this.params.pixelSize;\n  },\n\n  run: function (callback, context){\n    return this.request(function(error, response){\n      callback.call(context, error, (response && this._responseToGeoJSON(response)), response);\n    }, this);\n  },\n\n  // get pixel data and return as geoJSON point\n  // populate catalog items (if any)\n  // merging in any catalogItemVisibilities as a propery of each feature\n  _responseToGeoJSON: function(response) {\n    var location = response.location;\n    var catalogItems = response.catalogItems;\n    var catalogItemVisibilities = response.catalogItemVisibilities;\n    var geoJSON =  {\n      'pixel': {\n        'type': 'Feature',\n        'geometry': {\n          'type': 'Point',\n          'coordinates': [location.x, location.y]\n        },\n        'crs': {\n          'type': 'EPSG',\n          'properties': {\n            'code': location.spatialReference.wkid\n          }\n        },\n        'properties': {\n          'OBJECTID': response.objectId,\n          'name': response.name,\n          'value': response.value\n        },\n        'id': response.objectId\n      }\n    };\n    if (response.properties && response.properties.Values) {\n      geoJSON.pixel.properties.values = response.properties.Values;\n    }\n    if (catalogItems && catalogItems.features) {\n      geoJSON.catalogItems = EsriLeaflet.Util.responseToFeatureCollection(catalogItems);\n      if (catalogItemVisibilities && catalogItemVisibilities.length === geoJSON.catalogItems.features.length) {\n        for (var i = catalogItemVisibilities.length - 1; i >= 0; i--) {\n          geoJSON.catalogItems.features[i].properties.catalogItemVisibility = catalogItemVisibilities[i];\n        }\n      }\n    }\n    return geoJSON;\n  }\n\n});\n\nEsriLeaflet.Tasks.identifyImage = function(params){\n  return new EsriLeaflet.Tasks.IdentifyImage(params);\n};","EsriLeaflet.Tasks.IdentifyFeatures = EsriLeaflet.Tasks.Identify.extend({\n  setters: {\n    'layers': 'layers',\n    'precision': 'geometryPrecision',\n    'tolerance': 'tolerance',\n    'returnGeometry': 'returnGeometry'\n  },\n\n  params: {\n    sr: 4326,\n    layers: 'all',\n    tolerance: 3,\n    returnGeometry: true\n  },\n\n  on: function(map){\n    var extent = EsriLeaflet.Util.boundsToExtent(map.getBounds());\n    var size = map.getSize();\n    this.params.imageDisplay = [size.x, size.y, 96];\n    this.params.mapExtent = [extent.xmin, extent.ymin, extent.xmax, extent.ymax];\n    return this;\n  },\n\n  at: function(latlng){\n    latlng = L.latLng(latlng);\n    this.params.geometry = [latlng.lng, latlng.lat];\n    this.params.geometryType = 'esriGeometryPoint';\n    return this;\n  },\n\n  layerDef: function (id, where){\n    this.params.layerDefs = (this.params.layerDefs) ? this.params.layerDefs + ';' : '';\n    this.params.layerDefs += ([id, where]).join(':');\n    return this;\n  },\n\n  simplify: function(map, factor){\n    var mapWidth = Math.abs(map.getBounds().getWest() - map.getBounds().getEast());\n    this.params.maxAllowableOffset = (mapWidth / map.getSize().y) * (1 - factor);\n    return this;\n  },\n\n  run: function (callback, context){\n    return this.request(function(error, response){\n      // immediately invoke with an error\n      if(error) {\n        callback.call(context, error, undefined, response);\n        return;\n\n      // ok no error lets just assume we have features...\n      } else {\n        var featureCollection = EsriLeaflet.Util.responseToFeatureCollection(response);\n        response.results = response.results.reverse();\n        for (var i = 0; i < featureCollection.features.length; i++) {\n          var feature = featureCollection.features[i];\n          feature.layerId = response.results[i].layerId;\n        }\n        callback.call(context, undefined, featureCollection, response);\n      }\n    });\n  }\n});\n\nEsriLeaflet.Tasks.identifyFeatures = function(params){\n  return new EsriLeaflet.Tasks.IdentifyFeatures(params);\n};","(function(EsriLeaflet){\n\n  var tileProtocol = (window.location.protocol !== 'https:') ? 'http:' : 'https:';\n\n  EsriLeaflet.Layers.BasemapLayer = L.TileLayer.extend({\n    statics: {\n      TILES: {\n        Streets: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}',\n          attributionUrl: 'https://static.arcgis.com/attribution/World_Street_Map',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 19,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri'\n          }\n        },\n        Topographic: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}',\n          attributionUrl: 'https://static.arcgis.com/attribution/World_Topo_Map',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 19,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri'\n          }\n        },\n        Oceans: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer/tile/{z}/{y}/{x}',\n          attributionUrl: 'https://static.arcgis.com/attribution/Ocean_Basemap',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 16,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri'\n          }\n        },\n        OceansLabels: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Reference/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: true,\n            logoPosition: 'bottomright',\n            //pane: 'esri-label',\n            minZoom: 1,\n            maxZoom: 16,\n            subdomains: ['server', 'services']\n          }\n        },\n        NationalGeographic: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 16,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri'\n          }\n        },\n        DarkGray: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 16,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri, DeLorme, HERE'\n          }\n        },\n        DarkGrayLabels: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Reference/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: true,\n            logoPosition: 'bottomright',\n            //pane: 'esri-label',\n            minZoom: 1,\n            maxZoom: 16,\n            subdomains: ['server', 'services']\n          }\n        },\n        Gray: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 16,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri, NAVTEQ, DeLorme'\n          }\n        },\n        GrayLabels: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: true,\n            logoPosition: 'bottomright',\n            //pane: 'esri-label',\n            minZoom: 1,\n            maxZoom: 16,\n            subdomains: ['server', 'services']\n          }\n        },\n        Imagery: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 19,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri, DigitalGlobe, GeoEye, i-cubed, USDA, USGS, AEX, Getmapping, Aerogrid, IGN, IGP, swisstopo, and the GIS User Community'\n          }\n        },\n        ImageryLabels: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: true,\n            logoPosition: 'bottomright',\n            //pane: 'esri-label',\n            minZoom: 1,\n            maxZoom: 19,\n            subdomains: ['server', 'services']\n          }\n        },\n        ImageryTransportation: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer/tile/{z}/{y}/{x}',\n          //pane: 'esri-label',\n          options: {\n            hideLogo: true,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 19,\n            subdomains: ['server', 'services']\n          }\n        },\n        ShadedRelief: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 13,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri, NAVTEQ, DeLorme'\n          }\n        },\n        ShadedReliefLabels: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places_Alternate/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: true,\n            logoPosition: 'bottomright',\n            //pane: 'esri-label',\n            minZoom: 1,\n            maxZoom: 12,\n            subdomains: ['server', 'services']\n          }\n        },\n        Terrain: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: false,\n            logoPosition: 'bottomright',\n            minZoom: 1,\n            maxZoom: 13,\n            subdomains: ['server', 'services'],\n            attribution: 'Esri, USGS, NOAA'\n          }\n        },\n        TerrainLabels: {\n          urlTemplate: tileProtocol + '//{s}.arcgisonline.com/ArcGIS/rest/services/Reference/World_Reference_Overlay/MapServer/tile/{z}/{y}/{x}',\n          options: {\n            hideLogo: true,\n            logoPosition: 'bottomright',\n            //pane: 'esri-label',\n            minZoom: 1,\n            maxZoom: 13,\n            subdomains: ['server', 'services']\n          }\n        }\n      }\n    },\n    initialize: function(key, options){\n      var config;\n\n      // set the config variable with the appropriate config object\n      if (typeof key === 'object' && key.urlTemplate && key.options){\n        config = key;\n      } else if(typeof key === 'string' && EsriLeaflet.BasemapLayer.TILES[key]){\n        config = EsriLeaflet.BasemapLayer.TILES[key];\n      } else {\n        throw new Error('L.esri.BasemapLayer: Invalid parameter. Use one of \"Streets\", \"Topographic\", \"Oceans\", \"OceansLabels\", \"NationalGeographic\", \"Gray\", \"GrayLabels\", \"DarkGray\", \"DarkGrayLabels\", \"Imagery\", \"ImageryLabels\", \"ImageryTransportation\", \"ShadedRelief\", \"ShadedReliefLabels\", \"Terrain\" or \"TerrainLabels\"');\n      }\n\n      // merge passed options into the config options\n      var tileOptions = L.Util.extend(config.options, options);\n\n      // call the initialize method on L.TileLayer to set everything up\n      L.TileLayer.prototype.initialize.call(this, config.urlTemplate, L.Util.setOptions(this, tileOptions));\n\n      // if this basemap requires dynamic attribution set it up\n      if(config.attributionUrl){\n        this._getAttributionData(config.attributionUrl);\n      }\n      this._logo = new EsriLeaflet.Controls.Logo({\n        position: this.options.logoPosition\n      });\n    },\n    onAdd: function(map){\n      if(!this.options.hideLogo && !map._hasEsriLogo){\n        this._logo.addTo(map);\n        map._hasEsriLogo = true;\n      }\n\n      // if(this.options.pane && EsriLeaflet.Support.pointerEvents){\n      //   this._initPane();\n      // }\n\n      L.TileLayer.prototype.onAdd.call(this, map);\n\n      map.on('moveend', this._updateMapAttribution, this);\n    },\n    onRemove: function(map){\n      // check to make sure the logo hasn't already been removed\n      if(this._logo && this._logo._container){\n        map.removeControl(this._logo);\n        map._hasEsriLogo = false;\n      }\n\n      L.TileLayer.prototype.onRemove.call(this, map);\n\n      map.off('moveend', this._updateMapAttribution, this);\n    },\n    getAttribution:function(){\n      var attribution = '<span class=\"esri-attributions\" style=\"line-height:14px; vertical-align: -3px; text-overflow:ellipsis; white-space:nowrap; overflow:hidden; display:inline-block;\">' + this.options.attribution + '</span>'/* + logo*/;\n      return attribution;\n    },\n    // _initPane: function(){\n    //   if(!this._map.getPane(this.options.pane)){\n    //     var pane = this._map.createPane(this.options.pane);\n    //     pane.style.pointerEvents = 'none';\n    //     pane.style.zIndex = 5;\n    //   }\n    // },\n    _getAttributionData: function(url){\n      L.esri.Request.get.JSONP(url, {}, L.Util.bind(function(error, attributions){\n        this._attributions = [];\n\n        for (var c = 0; c < attributions.contributors.length; c++) {\n          var contributor = attributions.contributors[c];\n          for (var i = 0; i < contributor.coverageAreas.length; i++) {\n            var coverageArea = contributor.coverageAreas[i];\n            var southWest = new L.LatLng(coverageArea.bbox[0], coverageArea.bbox[1]);\n            var northEast = new L.LatLng(coverageArea.bbox[2], coverageArea.bbox[3]);\n            this._attributions.push({\n              attribution: contributor.attribution,\n              score: coverageArea.score,\n              bounds: new L.LatLngBounds(southWest, northEast),\n              minZoom: coverageArea.zoomMin,\n              maxZoom: coverageArea.zoomMax\n            });\n          }\n        }\n\n        this._attributions.sort(function(a, b){\n          return b.score - a.score;\n        });\n\n        this._updateMapAttribution();\n      }, this));\n    },\n    _updateMapAttribution: function(){\n      if(this._map && this._map.attributionControl && this._attributions){\n        var newAttributions = '';\n        var bounds = this._map.getBounds();\n        var zoom = this._map.getZoom();\n\n        for (var i = 0; i < this._attributions.length; i++) {\n          var attribution = this._attributions[i];\n          var text = attribution.attribution;\n          if(!newAttributions.match(text) && bounds.intersects(attribution.bounds) && zoom >= attribution.minZoom && zoom <= attribution.maxZoom) {\n            newAttributions += (', ' + text);\n          }\n        }\n        newAttributions = newAttributions.substr(2);\n        var attributionElement = this._map.attributionControl._container.querySelector('.esri-attributions');\n        attributionElement.innerHTML = newAttributions;\n        attributionElement.style.maxWidth =  (this._map.getSize().x * 0.65) + 'px';\n        this.fire('attributionupdated', {\n          attribution: newAttributions\n        });\n      }\n    }\n  });\n\n  EsriLeaflet.BasemapLayer = EsriLeaflet.Layers.BasemapLayer;\n\n  EsriLeaflet.Layers.basemapLayer = function(key, options){\n    return new EsriLeaflet.Layers.BasemapLayer(key, options);\n  };\n\n  EsriLeaflet.basemapLayer = function(key, options){\n    return new EsriLeaflet.Layers.BasemapLayer(key, options);\n  };\n\n})(EsriLeaflet);","EsriLeaflet.Layers.RasterLayer =  L.Class.extend({\n  includes: L.Mixin.Events,\n\n  options: {\n    opacity: 1,\n    position: 'front',\n    f: 'image'\n  },\n\n  onAdd: function (map) {\n    this._map = map;\n\n    this._update = L.Util.limitExecByInterval(this._update, this.options.updateInterval, this);\n\n    if (map.options.crs && map.options.crs.code) {\n      var sr = map.options.crs.code.split(':')[1];\n      this.options.bboxSR = sr;\n      this.options.imageSR = sr;\n    }\n\n    map.on('moveend', this._update, this);\n\n    // if we had an image loaded and it matches the\n    // current bounds show the image otherwise remove it\n    if(this._currentImage && this._currentImage._bounds.equals(this._map.getBounds())){\n      map.addLayer(this._currentImage);\n    } else if(this._currentImage) {\n      this._map.removeLayer(this._currentImage);\n      this._currentImage = null;\n    }\n\n    this._update();\n\n    if(this._popup){\n      this._map.on('click', this._getPopupData, this);\n      this._map.on('dblclick', this._resetPopupState, this);\n    }\n  },\n\n  bindPopup: function(fn, popupOptions){\n    this._shouldRenderPopup = false;\n    this._lastClick = false;\n    this._popup = L.popup(popupOptions);\n    this._popupFunction = fn;\n    if(this._map){\n      this._map.on('click', this._getPopupData, this);\n      this._map.on('dblclick', this._resetPopupState, this);\n    }\n    return this;\n  },\n\n  unbindPopup: function(){\n    if(this._map){\n      this._map.closePopup(this._popup);\n      this._map.off('click', this._getPopupData, this);\n      this._map.off('dblclick', this._resetPopupState, this);\n    }\n    this._popup = false;\n    return this;\n  },\n\n  onRemove: function (map) {\n    if (this._currentImage) {\n      this._map.removeLayer(this._currentImage);\n    }\n\n    if(this._popup){\n      this._map.off('click', this._getPopupData, this);\n      this._map.off('dblclick', this._resetPopupState, this);\n    }\n\n    this._map.off('moveend', this._update, this);\n    this._map = null;\n  },\n\n  addTo: function(map){\n    map.addLayer(this);\n    return this;\n  },\n\n  removeFrom: function(map){\n    map.removeLayer(this);\n    return this;\n  },\n\n  bringToFront: function(){\n    this.options.position = 'front';\n    if(this._currentImage){\n      this._currentImage.bringToFront();\n    }\n    return this;\n  },\n\n  bringToBack: function(){\n    this.options.position = 'back';\n    if(this._currentImage){\n      this._currentImage.bringToBack();\n    }\n    return this;\n  },\n\n  getAttribution: function () {\n    return this.options.attribution;\n  },\n\n  getOpacity: function(){\n    return this.options.opacity;\n  },\n\n  setOpacity: function(opacity){\n    this.options.opacity = opacity;\n    this._currentImage.setOpacity(opacity);\n    return this;\n  },\n\n  getTimeRange: function(){\n    return [this.options.from, this.options.to];\n  },\n\n  setTimeRange: function(from, to){\n    this.options.from = from;\n    this.options.to = to;\n    this._update();\n    return this;\n  },\n\n  metadata: function(callback, context){\n    this._service.metadata(callback, context);\n    return this;\n  },\n\n  authenticate: function(token){\n    this._service.authenticate(token);\n    return this;\n  },\n\n  _renderImage: function(url, bounds){\n    if(this._map){\n      // create a new image overlay and add it to the map\n      // to start loading the image\n      // opacity is 0 while the image is loading\n      var image = new L.ImageOverlay(url, bounds, {\n        opacity: 0\n      }).addTo(this._map);\n\n      // once the image loads\n      image.once('load', function(e){\n        var newImage = e.target;\n        var oldImage = this._currentImage;\n\n        // if the bounds of this image matches the bounds that\n        // _renderImage was called with and we have a map with the same bounds\n        // hide the old image if there is one and set the opacity\n        // of the new image otherwise remove the new image\n        if(newImage._bounds.equals(bounds) && newImage._bounds.equals(this._map.getBounds())){\n          this._currentImage = newImage;\n\n          if(this.options.position === 'front'){\n            this.bringToFront();\n          } else {\n            this.bringToBack();\n          }\n\n          if(this._map && this._currentImage._map){\n            this._currentImage.setOpacity(this.options.opacity);\n          } else {\n            this._currentImage._map.removeLayer(this._currentImage);\n          }\n\n          if(oldImage && this._map) {\n            this._map.removeLayer(oldImage);\n          }\n\n          if(oldImage && oldImage._map){\n            oldImage._map.removeLayer(oldImage);\n          }\n        } else {\n          this._map.removeLayer(newImage);\n        }\n\n        this.fire('load', {\n          bounds: bounds\n        });\n\n      }, this);\n\n      this.fire('loading', {\n        bounds: bounds\n      });\n    }\n  },\n\n  _update: function () {\n    if(!this._map){\n      return;\n    }\n\n    var zoom = this._map.getZoom();\n    var bounds = this._map.getBounds();\n\n    if(this._animatingZoom){\n      return;\n    }\n\n    if (this._map._panTransition && this._map._panTransition._inProgress) {\n      return;\n    }\n\n    if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {\n      return;\n    }\n    var params = this._buildExportParams();\n\n    this._requestExport(params, bounds);\n  },\n\n  // TODO: refactor these into raster layer\n  _renderPopup: function(latlng, error, results, response){\n    latlng = L.latLng(latlng);\n    if(this._shouldRenderPopup && this._lastClick.equals(latlng)){\n      //add the popup to the map where the mouse was clicked at\n      var content = this._popupFunction(error, results, response);\n      if (content) {\n        this._popup.setLatLng(latlng).setContent(content).openOn(this._map);\n      }\n    }\n  },\n\n  _resetPopupState: function(e){\n    this._shouldRenderPopup = false;\n    this._lastClick = e.latlng;\n  },\n\n  // from https://github.com/Leaflet/Leaflet/blob/v0.7.2/src/layer/FeatureGroup.js\n  // @TODO remove at Leaflet 0.8\n  _propagateEvent: function (e) {\n    e = L.extend({\n      layer: e.target,\n      target: this\n    }, e);\n    this.fire(e.type, e);\n  }\n});","EsriLeaflet.Layers.DynamicMapLayer = EsriLeaflet.Layers.RasterLayer.extend({\n\n  options: {\n    updateInterval: 150,\n    layers: false,\n    layerDefs: false,\n    timeOptions: false,\n    format: 'png24',\n    transparent: true,\n    f: 'json'\n  },\n\n  initialize: function (url, options) {\n    options = options || {};\n    options.url = EsriLeaflet.Util.cleanUrl(url);\n    this._service = new EsriLeaflet.Services.MapService(options);\n    this._service.on('authenticationrequired requeststart requestend requesterror requestsuccess', this._propagateEvent, this);\n    if ((options.proxy || options.token) && options.f !== 'json'){\n      options.f = 'json';\n    }\n    L.Util.setOptions(this, options);\n  },\n\n  getLayers: function(){\n    return this.options.layers;\n  },\n\n  setLayers: function(layers){\n    this.options.layers = layers;\n    this._update();\n    return this;\n  },\n\n  getLayerDefs: function(){\n    return this.options.layerDefs;\n  },\n\n  setLayerDefs: function(layerDefs){\n    this.options.layerDefs = layerDefs;\n    this._update();\n    return this;\n  },\n\n  getTimeOptions: function(){\n    return this.options.timeOptions;\n  },\n\n  setTimeOptions: function(timeOptions){\n    this.options.timeOptions = timeOptions;\n    this._update();\n    return this;\n  },\n\n  query: function(){\n    return this._service.query();\n  },\n\n  identify: function(){\n    return this._service.identify();\n  },\n\n  find: function(){\n    return this._service.find();\n  },\n\n  _getPopupData: function(e){\n    var callback = L.Util.bind(function(error, featureCollection, response) {\n      setTimeout(L.Util.bind(function(){\n        this._renderPopup(e.latlng, error, featureCollection, response);\n      }, this), 300);\n    }, this);\n\n    var identifyRequest = this.identify().on(this._map).at(e.latlng);\n\n    if(this.options.layers){\n      identifyRequest.layers('visible:' + this.options.layers.join(','));\n    } else {\n      identifyRequest.layers('visible');\n    }\n\n    identifyRequest.run(callback);\n\n    // set the flags to show the popup\n    this._shouldRenderPopup = true;\n    this._lastClick = e.latlng;\n  },\n\n  _buildExportParams: function () {\n    var bounds = this._map.getBounds();\n    var size = this._map.getSize();\n    var ne = this._map.options.crs.project(bounds._northEast);\n    var sw = this._map.options.crs.project(bounds._southWest);\n\n    //ensure that we don't ask ArcGIS Server for a taller image than we have actual map displaying\n    var top = this._map.latLngToLayerPoint(bounds._northEast);\n    var bottom = this._map.latLngToLayerPoint(bounds._southWest);\n\n    if (top.y > 0 || bottom.y < size.y){\n      size.y = bottom.y - top.y;\n    }\n\n    var params = {\n      bbox: [sw.x, sw.y, ne.x, ne.y].join(','),\n      size: size.x + ',' + size.y,\n      dpi: 96,\n      format: this.options.format,\n      transparent: this.options.transparent,\n      bboxSR: this.options.bboxSR,\n      imageSR: this.options.imageSR\n    };\n\n    if(this.options.layers){\n      params.layers = 'show:' + this.options.layers.join(',');\n    }\n\n    if(this.options.layerDefs){\n      params.layerDefs = JSON.stringify(this.options.layerDefs);\n    }\n\n    if(this.options.timeOptions){\n      params.timeOptions = JSON.stringify(this.options.timeOptions);\n    }\n\n    if(this.options.from && this.options.to){\n      params.time = this.options.from.valueOf() + ',' + this.options.to.valueOf();\n    }\n\n    if(this._service.options.token) {\n      params.token = this._service.options.token;\n    }\n\n    return params;\n  },\n\n  _requestExport: function (params, bounds) {\n    if(this.options.f === 'json'){\n      this._service.get('export', params, function(error, response){\n        this._renderImage(response.href, bounds);\n      }, this);\n    } else {\n      params.f = 'image';\n      this._renderImage(this.options.url + 'export' + L.Util.getParamString(params), bounds);\n    }\n  }\n});\n\nEsriLeaflet.DynamicMapLayer = EsriLeaflet.Layers.DynamicMapLayer;\n\nEsriLeaflet.Layers.dynamicMapLayer = function(url, options){\n  return new EsriLeaflet.Layers.DynamicMapLayer(url, options);\n};\n\nEsriLeaflet.dynamicMapLayer = function(url, options){\n  return new EsriLeaflet.Layers.DynamicMapLayer(url, options);\n};","EsriLeaflet.Layers.ImageMapLayer = EsriLeaflet.Layers.RasterLayer.extend({\n\n  options: {\n    updateInterval: 150,\n    format: 'jpgpng',\n    transparent: true\n  },\n\n  query: function(){\n    return this._service.query();\n  },\n\n  identify: function(){\n    return this._service.identify();\n  },\n\n  initialize: function (url, options) {\n    options = options || {};\n    options.url = EsriLeaflet.Util.cleanUrl(url);\n    this._service = new EsriLeaflet.Services.ImageService(options);\n    this._service.on('authenticationrequired requeststart requestend requesterror requestsuccess', this._propagateEvent, this);\n    L.Util.setOptions(this, options);\n  },\n\n  setPixelType: function (pixelType) {\n    this.options.pixelType = pixelType;\n    this._update();\n    return this;\n  },\n\n  getPixelType: function () {\n    return this.options.pixelType;\n  },\n\n  setBandIds: function (bandIds) {\n    if (L.Util.isArray(bandIds)) {\n      this.options.bandIds = bandIds.join(',');\n    } else {\n      this.options.bandIds = bandIds.toString();\n    }\n    this._update();\n    return this;\n  },\n\n  getBandIds: function () {\n    return this.options.bandIds;\n  },\n\n  setNoData: function (noData, noDataInterpretation) {\n    if (L.Util.isArray(noData)) {\n      this.options.noData = noData.join(',');\n    } else {\n      this.options.noData = noData.toString();\n    }\n    if (noDataInterpretation) {\n      this.options.noDataInterpretation = noDataInterpretation;\n    }\n    this._update();\n    return this;\n  },\n\n  getNoData: function () {\n    return this.options.noData;\n  },\n\n  getNoDataInterpretation: function () {\n    return this.options.noDataInterpretation;\n  },\n\n  setRenderingRule: function(renderingRule) {\n    this.options.renderingRule = renderingRule;\n    this._update();\n  },\n\n  getRenderingRule: function() {\n    return this.options.renderingRule;\n  },\n\n  setMosaicRule: function(mosaicRule) {\n    this.options.mosaicRule = mosaicRule;\n    this._update();\n  },\n\n  getMosaicRule: function() {\n    return this.options.mosaicRule;\n  },\n\n  _getPopupData: function(e){\n    var callback = L.Util.bind(function(error, results, response) {\n      setTimeout(L.Util.bind(function(){\n        this._renderPopup(e.latlng, error, results, response);\n      }, this), 300);\n    }, this);\n\n    var identifyRequest = this.identify().at(e.latlng);\n\n    // set mosaic rule for identify task if it is set for layer\n    if (this.options.mosaicRule) {\n      identifyRequest.setMosaicRule(this.options.mosaicRule);\n      // @TODO: force return catalog items too?\n    }\n\n    // @TODO: set rendering rule? Not sure,\n    // sometimes you want raw pixel values\n    // if (this.options.renderingRule) {\n    //   identifyRequest.setRenderingRule(this.options.renderingRule);\n    // }\n\n    identifyRequest.run(callback);\n\n    // set the flags to show the popup\n    this._shouldRenderPopup = true;\n    this._lastClick = e.latlng;\n  },\n\n  _buildExportParams: function () {\n    var bounds = this._map.getBounds();\n    var size = this._map.getSize();\n    var ne = this._map.options.crs.project(bounds._northEast);\n    var sw = this._map.options.crs.project(bounds._southWest);\n\n    var params = {\n      bbox: [sw.x, sw.y, ne.x, ne.y].join(','),\n      size: size.x + ',' + size.y,\n      format: this.options.format,\n      transparent: this.options.transparent,\n      bboxSR: this.options.bboxSR,\n      imageSR: this.options.imageSR\n    };\n\n    if (this.options.from && this.options.to) {\n      params.time = this.options.from.valueOf() + ',' + this.options.to.valueOf();\n    }\n\n    if (this.options.pixelType) {\n      params.pixelType = this.options.pixelType;\n    }\n\n    if (this.options.interpolation) {\n      params.interpolation = this.options.interpolation;\n    }\n\n    if (this.options.compressionQuality) {\n      params.compressionQuality = this.options.compressionQuality;\n    }\n\n    if (this.options.bandIds) {\n      params.bandIds = this.options.bandIds;\n    }\n\n    if (this.options.noData) {\n      params.noData = this.options.noData;\n    }\n\n    if (this.options.noDataInterpretation) {\n      params.noDataInterpretation = this.options.noDataInterpretation;\n    }\n\n    if (this._service.options.token) {\n      params.token = this._service.options.token;\n    }\n\n    if(this.options.renderingRule) {\n      params.renderingRule = JSON.stringify(this.options.renderingRule);\n    }\n\n    if(this.options.mosaicRule) {\n      params.mosaicRule = JSON.stringify(this.options.mosaicRule);\n    }\n\n    return params;\n  },\n\n  _requestExport: function (params, bounds) {\n    if (this.options.f === 'json') {\n      this._service.get('exportImage', params, function(error, response){\n        this._renderImage(response.href, bounds);\n      }, this);\n    } else {\n      params.f = 'image';\n      this._renderImage(this.options.url + 'exportImage' + L.Util.getParamString(params), bounds);\n    }\n  }\n});\n\nEsriLeaflet.ImageMapLayer = EsriLeaflet.Layers.ImageMapLayer;\n\nEsriLeaflet.Layers.imageMapLayer = function (url, options) {\n  return new EsriLeaflet.Layers.ImageMapLayer(url, options);\n};\n\nEsriLeaflet.imageMapLayer = function (url, options) {\n  return new EsriLeaflet.Layers.ImageMapLayer(url, options);\n};\n","EsriLeaflet.Layers.TiledMapLayer = L.TileLayer.extend({\n  initialize: function(url, options){\n    options = options || {};\n    options.url = EsriLeaflet.Util.cleanUrl(url);\n    options = L.Util.setOptions(this, options);\n\n    // set the urls\n    //this.url = L.esri.Util.cleanUrl(url);\n    this.tileUrl = L.esri.Util.cleanUrl(url) + 'tile/{z}/{y}/{x}';\n    this._service = new L.esri.Services.MapService(options);\n    this._service.on('authenticationrequired requeststart requestend requesterror requestsuccess', this._propagateEvent, this);\n\n    //if this is looking at the AGO tiles subdomain insert the subdomain placeholder\n    if(this.tileUrl.match('://tiles.arcgisonline.com')){\n      this.tileUrl = this.tileUrl.replace('://tiles.arcgisonline.com', '://tiles{s}.arcgisonline.com');\n      options.subdomains = ['1', '2', '3', '4'];\n    }\n\n    if(this.options.token) {\n      this.tileUrl += ('?token=' + this.options.token);\n    }\n\n    // init layer by calling TileLayers initialize method\n    L.TileLayer.prototype.initialize.call(this, this.tileUrl, options);\n  },\n\n  metadata: function(callback, context){\n    this._service.metadata(callback, context);\n    return this;\n  },\n\n  identify: function(){\n    return this._service.identify();\n  },\n\n  authenticate: function(token){\n    var tokenQs = '?token=' + token;\n    this.tileUrl = (this.options.token) ? this.tileUrl.replace(/\\?token=(.+)/g, tokenQs) : this.tileUrl + tokenQs;\n    this.options.token = token;\n    this._service.authenticate(token);\n    return this;\n  },\n\n  // from https://github.com/Leaflet/Leaflet/blob/v0.7.2/src/layer/FeatureGroup.js\n  // @TODO remove at Leaflet 0.8\n  _propagateEvent: function (e) {\n    e = L.extend({\n      layer: e.target,\n      target: this\n    }, e);\n    this.fire(e.type, e);\n  }\n});\n\nL.esri.TiledMapLayer = L.esri.Layers.tiledMapLayer;\n\nL.esri.Layers.tiledMapLayer = function(url, options){\n  return new L.esri.Layers.TiledMapLayer(url, options);\n};\n\nL.esri.tiledMapLayer = function(url, options){\n  return new L.esri.Layers.TiledMapLayer(url, options);\n};","EsriLeaflet.Layers.FeatureGrid = L.Class.extend({\n\n  includes: L.Mixin.Events,\n\n  options: {\n    cellSize: 512,\n    updateInterval: 150\n  },\n\n  initialize: function (options) {\n    options = L.setOptions(this, options);\n  },\n\n  onAdd: function (map) {\n    this._map = map;\n    this._update = L.Util.limitExecByInterval(this._update, this.options.updateInterval, this);\n\n    // @TODO remove for leaflet 0.8\n    this._map.addEventListener(this.getEvents(), this);\n\n    this._reset();\n    this._update();\n  },\n\n  onRemove: function(){\n    this._map.removeEventListener(this.getEvents(), this);\n    this._removeCells();\n  },\n\n  getEvents: function () {\n    var events = {\n      viewreset: this._reset,\n      moveend: this._update,\n      zoomend : this._onZoom\n    };\n\n    return events;\n  },\n\n  addTo: function(map){\n    map.addLayer(this);\n    return this;\n  },\n\n  removeFrom: function(map){\n    map.removeLayer(this);\n    return this;\n  },\n\n  _onZoom : function () {\n    var zoom = this._map.getZoom();\n\n    if (zoom > this.options.maxZoom ||\n        zoom < this.options.minZoom) {\n      this.removeFrom(this._map);\n      this._map.addEventListener('zoomend', this.getEvents().zoomend, this);\n    } else if (!this._map.hasLayer(this)) {\n      this._map.removeEventListener('zoomend', this.getEvents().zoomend, this);\n      this.addTo(this._map);\n    }\n\n  },\n\n  _reset: function () {\n    this._removeCells();\n\n    this._cells = {};\n    this._activeCells = {};\n    this._cellsToLoad = 0;\n    this._cellsTotal = 0;\n\n    // @TODO enable at Leaflet 0.8\n    // this._cellNumBounds = this._getCellNumBounds();\n\n    this._resetWrap();\n  },\n\n  _resetWrap: function () {\n    var map = this._map,\n        crs = map.options.crs;\n\n    if (crs.infinite) { return; }\n\n    var cellSize = this._getCellSize();\n\n    if (crs.wrapLng) {\n      this._wrapLng = [\n        Math.floor(map.project([0, crs.wrapLng[0]]).x / cellSize),\n        Math.ceil(map.project([0, crs.wrapLng[1]]).x / cellSize)\n      ];\n    }\n\n    if (crs.wrapLat) {\n      this._wrapLat = [\n        Math.floor(map.project([crs.wrapLat[0], 0]).y / cellSize),\n        Math.ceil(map.project([crs.wrapLat[1], 0]).y / cellSize)\n      ];\n    }\n  },\n\n  _getCellSize: function () {\n    return this.options.cellSize;\n  },\n\n  _update: function () {\n    if (!this._map) { return; }\n\n    var bounds = this._map.getPixelBounds(),\n        zoom = this._map.getZoom(),\n        cellSize = this._getCellSize(),\n        cellPadding = [cellSize/2,cellSize/2];\n        // cellPadding = [0,0]\n\n    if (zoom > this.options.maxZoom ||\n        zoom < this.options.minZoom) { return; }\n\n    // cell coordinates range for the current view\n    var topLeft = bounds.min.subtract(cellPadding).divideBy(cellSize).floor();\n    topLeft.x = Math.max(topLeft.x, 0);\n    topLeft.y = Math.max(topLeft.y, 0);\n\n    var cellBounds = L.bounds(topLeft, bounds.max.add(cellPadding).divideBy(cellSize).floor());\n\n    // remove any present cells that are off the specified bounds\n    this._removeOtherCells(cellBounds);\n    this._addCells(cellBounds);\n  },\n\n  _addCells: function (bounds) {\n    var queue = [],\n        center = bounds.getCenter(),\n        zoom = this._map.getZoom();\n\n    var j, i, coords;\n    // create a queue of coordinates to load cells from\n    for (j = bounds.min.y; j <= bounds.max.y; j++) {\n      for (i = bounds.min.x; i <= bounds.max.x; i++) {\n        coords = new L.Point(i, j);\n        coords.z = zoom;\n\n        // @TODO enable at Leaflet 0.8\n        // if (this._isValidCell(coords)) {\n        //   queue.push(coords);\n        // }\n\n        queue.push(coords);\n      }\n    }\n    var cellsToLoad = queue.length;\n\n    if (cellsToLoad === 0) { return; }\n\n    this._cellsToLoad += cellsToLoad;\n    this._cellsTotal += cellsToLoad;\n\n    // sort cell queue to load cells in order of their distance to center\n    queue.sort(function (a, b) {\n      return a.distanceTo(center) - b.distanceTo(center);\n    });\n\n    for (i = 0; i < cellsToLoad; i++) {\n      this._addCell(queue[i]);\n    }\n  },\n\n  // @TODO enable at Leaflet 0.8\n  // _isValidCell: function (coords) {\n  //   var crs = this._map.options.crs;\n\n  //   if (!crs.infinite) {\n  //     // don't load cell if it's out of bounds and not wrapped\n  //     var bounds = this._cellNumBounds;\n  //     if (\n  //       (!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) ||\n  //       (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))\n  //     ) {\n  //       return false;\n  //     }\n  //   }\n\n  //   if (!this.options.bounds) {\n  //     return true;\n  //   }\n\n  //   // don't load cell if it doesn't intersect the bounds in options\n  //   var cellBounds = this._cellCoordsToBounds(coords);\n  //   return L.latLngBounds(this.options.bounds).intersects(cellBounds);\n  // },\n\n  // converts cell coordinates to its geographical bounds\n  _cellCoordsToBounds: function (coords) {\n    var map = this._map,\n        cellSize = this.options.cellSize,\n\n        nwPoint = coords.multiplyBy(cellSize),\n        sePoint = nwPoint.add([cellSize, cellSize]),\n\n        // @TODO for Leaflet 0.8\n        // nw = map.wrapLatLng(map.unproject(nwPoint, coords.z)),\n        // se = map.wrapLatLng(map.unproject(sePoint, coords.z));\n\n        nw = map.unproject(nwPoint, coords.z).wrap(),\n        se = map.unproject(sePoint, coords.z).wrap();\n\n    return new L.LatLngBounds(nw, se);\n  },\n\n  // converts cell coordinates to key for the cell cache\n  _cellCoordsToKey: function (coords) {\n    return coords.x + ':' + coords.y;\n  },\n\n  // converts cell cache key to coordiantes\n  _keyToCellCoords: function (key) {\n    var kArr = key.split(':'),\n        x = parseInt(kArr[0], 10),\n        y = parseInt(kArr[1], 10);\n\n    return new L.Point(x, y);\n  },\n\n  // remove any present cells that are off the specified bounds\n  _removeOtherCells: function (bounds) {\n    for (var key in this._cells) {\n      if (!bounds.contains(this._keyToCellCoords(key))) {\n        this._removeCell(key);\n      }\n    }\n  },\n\n  _removeCell: function (key) {\n    var cell = this._activeCells[key];\n    if(cell){\n      delete this._activeCells[key];\n\n      if (this.cellLeave) {\n        this.cellLeave(cell.bounds, cell.coords);\n      }\n\n      this.fire('cellleave', {\n        bounds: cell.bounds,\n        coords: cell.coords\n      });\n    }\n  },\n\n  _removeCells: function(){\n    for (var key in this._cells) {\n      var bounds = this._cells[key].bounds;\n      var coords = this._cells[key].coords;\n\n      if (this.cellLeave) {\n        this.cellLeave(bounds, coords);\n      }\n\n      this.fire('cellleave', {\n        bounds: bounds,\n        coords: coords\n      });\n    }\n  },\n\n  _addCell: function (coords) {\n\n    // wrap cell coords if necessary (depending on CRS)\n    this._wrapCoords(coords);\n\n    // generate the cell key\n    var key = this._cellCoordsToKey(coords);\n\n    // get the cell from the cache\n    var cell = this._cells[key];\n    // if this cell should be shown as isnt active yet (enter)\n\n    if (cell && !this._activeCells[key]) {\n      if (this.cellEnter) {\n        this.cellEnter(cell.bounds, coords);\n      }\n\n      this.fire('cellenter', {\n        bounds: cell.bounds,\n        coords: coords\n      });\n\n      this._activeCells[key] = cell;\n    }\n\n    // if we dont have this cell in the cache yet (create)\n    if (!cell) {\n      cell = {\n        coords: coords,\n        bounds: this._cellCoordsToBounds(coords)\n      };\n\n      this._cells[key] = cell;\n      this._activeCells[key] = cell;\n\n      if(this.createCell){\n        this.createCell(cell.bounds, coords);\n      }\n\n      this.fire('cellcreate', {\n        bounds: cell.bounds,\n        coords: coords\n      });\n    }\n  },\n\n  _wrapCoords: function (coords) {\n    coords.x = this._wrapLng ? L.Util.wrapNum(coords.x, this._wrapLng) : coords.x;\n    coords.y = this._wrapLat ? L.Util.wrapNum(coords.y, this._wrapLat) : coords.y;\n  }\n\n  // get the global cell coordinates range for the current zoom\n  // @TODO enable at Leaflet 0.8\n  // _getCellNumBounds: function () {\n  //   // @TODO for Leaflet 0.8\n  //   // var bounds = this._map.getPixelWorldBounds(),\n  //   //     size = this._getCellSize();\n  //   //\n  //   // return bounds ? L.bounds(\n  //   //     bounds.min.divideBy(size).floor(),\n  //   //     bounds.max.divideBy(size).ceil().subtract([1, 1])) : null;\n  // }\n\n});","(function(EsriLeaflet){\n\n  EsriLeaflet.Layers.FeatureManager = EsriLeaflet.Layers.FeatureGrid.extend({\n\n    /**\n     * Options\n     */\n\n    options: {\n      where: '1=1',\n      fields: ['*'],\n      from: false,\n      to: false,\n      timeField: false,\n      timeFilterMode: 'server',\n      simplifyFactor: 0,\n      precision: 6\n    },\n\n    /**\n     * Constructor\n     */\n\n    initialize: function (url, options) {\n      EsriLeaflet.Layers.FeatureGrid.prototype.initialize.call(this, options);\n\n      options = options || {};\n      options.url = EsriLeaflet.Util.cleanUrl(url);\n      options = L.setOptions(this, options);\n\n      this._service = new EsriLeaflet.Services.FeatureLayer(options);\n\n      //use case insensitive regex to look for common fieldnames used for indexing\n      /*global console */\n      if (this.options.fields[0] !== '*'){\n        var oidCheck = false;\n        for (var i = 0; i < this.options.fields.length; i++){\n          if (this.options.fields[i].match(/^(OBJECTID|FID|OID|ID)$/i)){\n            oidCheck = true;\n          }\n        }\n        if (oidCheck === false && console && console.warn){\n          console.warn('no known esriFieldTypeOID field detected in fields Array.  Please add an attribute field containing unique IDs to ensure the layer can be drawn correctly.');\n        }\n      }\n\n      // Leaflet 0.8 change to new propagation\n      this._service.on('authenticationrequired requeststart requestend requesterror requestsuccess', function (e) {\n        e = L.extend({\n          target: this\n        }, e);\n        this.fire(e.type, e);\n      }, this);\n\n      if(this.options.timeField.start && this.options.timeField.end){\n        this._startTimeIndex = new BinarySearchIndex();\n        this._endTimeIndex = new BinarySearchIndex();\n      } else if(this.options.timeField){\n        this._timeIndex = new BinarySearchIndex();\n      }\n\n      this._cache = {};\n      this._currentSnapshot = []; // cache of what layers should be active\n      this._activeRequests = 0;\n      this._pendingRequests = [];\n    },\n\n    /**\n     * Layer Interface\n     */\n\n    onAdd: function(map){\n      return EsriLeaflet.Layers.FeatureGrid.prototype.onAdd.call(this, map);\n    },\n\n    onRemove: function(map){\n      return EsriLeaflet.Layers.FeatureGrid.prototype.onRemove.call(this, map);\n    },\n\n    getAttribution: function () {\n      return this.options.attribution;\n    },\n\n    /**\n     * Feature Managment\n     */\n\n    createCell: function(bounds, coords){\n      this._requestFeatures(bounds, coords);\n    },\n\n    _requestFeatures: function(bounds, coords, callback){\n      this._activeRequests++;\n\n      // our first active request fires loading\n      if(this._activeRequests === 1){\n        this.fire('loading', {\n          bounds: bounds\n        });\n      }\n\n      return this._buildQuery(bounds).run(function(error, featureCollection, response){\n        if(response && response.exceededTransferLimit){\n          this.fire('drawlimitexceeded');\n        }\n\n        //deincriment the request counter\n        this._activeRequests--;\n\n        if(!error && featureCollection.features.length){\n          // schedule adding features until the next animation frame\n          EsriLeaflet.Util.requestAnimationFrame(L.Util.bind(function(){\n            this._addFeatures(featureCollection.features, coords);\n          }, this));\n        }\n\n        if(callback){\n          callback.call(this, error, featureCollection);\n        }\n\n        // if there are no more active requests fire a load event for this view\n        if(this._activeRequests <= 0){\n          this.fire('load', {\n            bounds: bounds\n          });\n        }\n      }, this);\n    },\n\n    _cacheKey: function (coords){\n      return coords.z + ':' + coords.x + ':' +coords.y;\n    },\n\n    _addFeatures: function(features, coords){\n      var key = this._cacheKey(coords);\n      this._cache[key] = this._cache[key] || [];\n\n      for (var i = features.length - 1; i >= 0; i--) {\n        var id = features[i].id;\n        this._currentSnapshot.push(id);\n        this._cache[key].push(id);\n      }\n\n      if(this.options.timeField){\n        this._buildTimeIndexes(features);\n      }\n\n      var zoom = this._map.getZoom();\n\n      if (zoom > this.options.maxZoom ||\n          zoom < this.options.minZoom) { return; }\n\n      this.createLayers(features);\n    },\n\n    _buildQuery: function(bounds){\n      var query = this._service.query().intersects(bounds).where(this.options.where).fields(this.options.fields).precision(this.options.precision);\n\n      if(this.options.simplifyFactor){\n        query.simplify(this._map, this.options.simplifyFactor);\n      }\n\n      if(this.options.timeFilterMode === 'server' && this.options.from && this.options.to){\n        query.between(this.options.from, this.options.to);\n      }\n\n      return query;\n    },\n\n    /**\n     * Where Methods\n     */\n\n    setWhere: function(where, callback, context){\n\n      this.options.where = (where && where.length) ? where : '1=1';\n\n      var oldSnapshot = [];\n      var newShapshot = [];\n      var pendingRequests = 0;\n      var requestError = null;\n      var requestCallback = L.Util.bind(function(error, featureCollection){\n        if(error){\n          requestError = error;\n        }\n\n        if(featureCollection){\n          for (var i = featureCollection.features.length - 1; i >= 0; i--) {\n            newShapshot.push(featureCollection.features[i].id);\n          }\n        }\n\n        pendingRequests--;\n\n        if(pendingRequests <= 0){\n          this._currentSnapshot = newShapshot;\n          // schedule adding features until the next animation frame\n          EsriLeaflet.Util.requestAnimationFrame(L.Util.bind(function(){\n            this.removeLayers(oldSnapshot);\n            this.addLayers(newShapshot);\n            if(callback) {\n              callback.call(context, requestError);\n            }\n          }, this));\n\n        }\n      }, this);\n\n      for (var i = this._currentSnapshot.length - 1; i >= 0; i--) {\n        oldSnapshot.push(this._currentSnapshot[i]);\n      }\n\n      for(var key in this._activeCells){\n        pendingRequests++;\n        var coords = this._keyToCellCoords(key);\n        var bounds = this._cellCoordsToBounds(coords);\n        this._requestFeatures(bounds, key, requestCallback);\n      }\n\n      return this;\n    },\n\n    getWhere: function(){\n      return this.options.where;\n    },\n\n    /**\n     * Time Range Methods\n     */\n\n    getTimeRange: function(){\n      return [this.options.from, this.options.to];\n    },\n\n    setTimeRange: function(from, to, callback, context){\n      var oldFrom = this.options.from;\n      var oldTo = this.options.to;\n      var pendingRequests = 0;\n      var requestError = null;\n      var requestCallback = L.Util.bind(function(error){\n        if(error){\n          requestError = error;\n        }\n        this._filterExistingFeatures(oldFrom, oldTo, from, to);\n\n        pendingRequests--;\n\n        if(callback && pendingRequests <= 0){\n          callback.call(context, requestError);\n        }\n      }, this);\n\n      this.options.from = from;\n      this.options.to = to;\n\n      this._filterExistingFeatures(oldFrom, oldTo, from, to);\n\n      if(this.options.timeFilterMode === 'server') {\n        for(var key in this._activeCells){\n          pendingRequests++;\n          var coords = this._keyToCellCoords(key);\n          var bounds = this._cellCoordsToBounds(coords);\n          this._requestFeatures(bounds, key, requestCallback);\n        }\n      }\n    },\n\n    refresh: function(){\n      for(var key in this._activeCells){\n        var coords = this._keyToCellCoords(key);\n        var bounds = this._cellCoordsToBounds(coords);\n        this._requestFeatures(bounds, key);\n      }\n    },\n\n    _filterExistingFeatures: function (oldFrom, oldTo, newFrom, newTo) {\n      var layersToRemove = (oldFrom && oldTo) ? this._getFeaturesInTimeRange(oldFrom, oldTo) : this._currentSnapshot;\n      var layersToAdd = this._getFeaturesInTimeRange(newFrom, newTo);\n\n      if(layersToAdd.indexOf){\n        for (var i = 0; i < layersToAdd.length; i++) {\n          var shouldRemoveLayer = layersToRemove.indexOf(layersToAdd[i]);\n          if(shouldRemoveLayer >= 0){\n            layersToRemove.splice(shouldRemoveLayer, 1);\n          }\n        }\n      }\n\n      // schedule adding features until the next animation frame\n      EsriLeaflet.Util.requestAnimationFrame(L.Util.bind(function(){\n        this.removeLayers(layersToRemove);\n        this.addLayers(layersToAdd);\n      }, this));\n    },\n\n    _getFeaturesInTimeRange: function(start, end){\n      var ids = [];\n      var search;\n\n      if(this.options.timeField.start && this.options.timeField.end){\n        var startTimes = this._startTimeIndex.between(start, end);\n        var endTimes = this._endTimeIndex.between(start, end);\n        search = startTimes.concat(endTimes);\n      } else {\n        search = this._timeIndex.between(start, end);\n      }\n\n      for (var i = search.length - 1; i >= 0; i--) {\n        ids.push(search[i].id);\n      }\n\n      return ids;\n    },\n\n    _buildTimeIndexes: function(geojson){\n      var i;\n      var feature;\n      if(this.options.timeField.start && this.options.timeField.end){\n        var startTimeEntries = [];\n        var endTimeEntries = [];\n        for (i = geojson.length - 1; i >= 0; i--) {\n          feature = geojson[i];\n          startTimeEntries.push( {\n            id: feature.id,\n            value: new Date(feature.properties[this.options.timeField.start])\n          });\n          endTimeEntries.push( {\n            id: feature.id,\n            value: new Date(feature.properties[this.options.timeField.end])\n          });\n        }\n        this._startTimeIndex.bulkAdd(startTimeEntries);\n        this._endTimeIndex.bulkAdd(endTimeEntries);\n      } else {\n        var timeEntries = [];\n        for (i = geojson.length - 1; i >= 0; i--) {\n          feature = geojson[i];\n          timeEntries.push( {\n            id: feature.id,\n            value: new Date(feature.properties[this.options.timeField])\n          });\n        }\n\n        this._timeIndex.bulkAdd(timeEntries);\n      }\n    },\n\n    _featureWithinTimeRange: function(feature){\n      if(!this.options.from || !this.options.to){\n        return true;\n      }\n\n      var from = +this.options.from.valueOf();\n      var to = +this.options.to.valueOf();\n\n      if(typeof this.options.timeField === 'string'){\n        var date = +feature.properties[this.options.timeField];\n        return (date >= from) && (date <= to);\n      }\n\n      if(this.options.timeField.start &&  this.options.timeField.end){\n        var startDate = +feature.properties[this.options.timeField.start];\n        var endDate = +feature.properties[this.options.timeField.end];\n        return ((startDate >= from) && (startDate <= to)) || ((endDate >= from) && (endDate <= to));\n      }\n    },\n\n    /**\n     * Service Methods\n     */\n\n    authenticate: function(token){\n      this._service.authenticate(token);\n      return this;\n    },\n\n    metadata: function(callback, context){\n      this._service.metadata(callback, context);\n      return this;\n    },\n\n    query: function(){\n      return this._service.query();\n    },\n\n    _getMetadata: function(callback, context){\n      if(this._metadata){\n        var error;\n        callback(context, error, this._metadata);\n      } else {\n        this.metadata(L.Util.bind(function(error, response) {\n          this._metadata = response;\n          callback(context, error, this._metadata);\n        }, this));\n      }\n    },\n\n    addFeature: function(feature, callback, context){\n      //still need to pass 'undefined' as a placeholder, not sure how to fix\n      this._getMetadata(L.Util.bind(function(undefined, error, metadata){\n        this._service.addFeature(feature, L.Util.bind(function(error, response){\n          if(!error){\n            // assign ID from result to appropriate objectid field from service metadata\n            feature.properties[metadata.objectIdField] = response.objectId;\n\n            // we also need to update the geojson id for createLayers() to function\n            feature.id = response.objectId;\n            this.createLayers([feature]);\n          }\n\n          if(callback){\n            callback.call(context, error, response);\n          }\n        }, this));\n      }, this));\n    },\n\n    updateFeature: function(feature, callback, context){\n      this._service.updateFeature(feature, function(error, response){\n        if(!error){\n          this.removeLayers([feature.id], true);\n          this.createLayers([feature]);\n        }\n        if(callback){\n          callback.call(context, error, response);\n        }\n      }, this);\n    },\n\n    deleteFeature: function(id, callback, context){\n      this._service.deleteFeature(id, function(error, response){\n        if(!error && response.objectId){\n          this.removeLayers([response.objectId], true);\n        }\n        if(callback){\n          callback.call(context, error, response);\n        }\n      }, this);\n    },\n\n    deleteFeatures: function(ids, callback, context){\n      return this._service.deleteFeatures(ids, function(error, response){\n        if(!error && response.length > 0){\n          for (var i=0; i<response.length; i++){\n            this.removeLayers([response[i].objectId], true);\n          }\n        }\n        if(callback){\n          callback.call(context, error, response);\n        }\n      }, this);\n    }\n\n  });\n\n  /**\n   * Temporal Binary Search Index\n   */\n\n  function BinarySearchIndex(values) {\n    this.values = values || [];\n  }\n\n  BinarySearchIndex.prototype._query = function(query){\n    var minIndex = 0;\n    var maxIndex = this.values.length - 1;\n    var currentIndex;\n    var currentElement;\n    var resultIndex;\n\n    while (minIndex <= maxIndex) {\n      resultIndex = currentIndex = (minIndex + maxIndex) / 2 | 0;\n      currentElement = this.values[Math.round(currentIndex)];\n      if (+currentElement.value < +query) {\n        minIndex = currentIndex + 1;\n      } else if (+currentElement.value > +query) {\n        maxIndex = currentIndex - 1;\n      } else {\n        return currentIndex;\n      }\n    }\n\n    return ~maxIndex;\n  };\n\n  BinarySearchIndex.prototype.sort = function(){\n    this.values.sort(function(a, b) {\n      return +b.value - +a.value;\n    }).reverse();\n    this.dirty = false;\n  };\n\n  BinarySearchIndex.prototype.between = function(start, end){\n    if(this.dirty){\n      this.sort();\n    }\n\n    var startIndex = this._query(start);\n    var endIndex = this._query(end);\n\n    if(startIndex === 0 && endIndex === 0){\n      return [];\n    }\n\n    startIndex = Math.abs(startIndex);\n    endIndex = (endIndex < 0) ? Math.abs(endIndex): endIndex + 1;\n\n    return this.values.slice(startIndex, endIndex);\n  };\n\n  BinarySearchIndex.prototype.bulkAdd = function(items){\n    this.dirty = true;\n    this.values = this.values.concat(items);\n  };\n\n})(EsriLeaflet);","EsriLeaflet.Layers.FeatureLayer = EsriLeaflet.Layers.FeatureManager.extend({\n\n  statics: {\n    EVENTS: 'click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose'\n  },\n\n  options: {\n    cacheLayers: true\n  },\n\n  /**\n   * Constructor\n   */\n\n  initialize: function (url, options) {\n    EsriLeaflet.Layers.FeatureManager.prototype.initialize.call(this, url, options);\n\n    options = L.setOptions(this, options);\n\n    this._layers = {};\n    this._leafletIds = {};\n    this._key = 'c'+(Math.random() * 1e9).toString(36).replace('.', '_');\n  },\n\n  /**\n   * Layer Interface\n   */\n\n  onAdd: function(map){\n    map.on('zoomstart zoomend', function(e){\n      this._zooming = (e.type === 'zoomstart');\n    }, this);\n    return EsriLeaflet.Layers.FeatureManager.prototype.onAdd.call(this, map);\n  },\n\n  onRemove: function(map){\n    for (var i in this._layers) {\n      map.removeLayer(this._layers[i]);\n    }\n\n    return EsriLeaflet.Layers.FeatureManager.prototype.onRemove.call(this, map);\n  },\n\n  createNewLayer: function(geojson){\n    // @TODO Leaflet 0.8\n    //newLayer = L.GeoJSON.geometryToLayer(geojson, this.options);\n    return L.GeoJSON.geometryToLayer(geojson, this.options.pointToLayer, L.GeoJSON.coordsToLatLng, this.options);\n  },\n\n  _updateLayerGeometry: function(layer, geojson){\n    // convert the geojson coordinates into a Leaflet LatLng array/nested arrays\n    // pass it to setLatLngs to update layer geometries\n    var latlngs = [];\n    var coordsToLatLng = this.options.coordsToLatLng || L.GeoJSON.coordsToLatLng;\n\n    switch(geojson.geometry.type){\n      case 'LineString':\n        latlngs = L.GeoJSON.coordsToLatLngs(geojson.geometry.coordinates, 0, coordsToLatLng);\n        layer.setLatLngs(latlngs);\n        break;\n      case 'MultiLineString':\n        latlngs = L.GeoJSON.coordsToLatLngs(geojson.geometry.coordinates, 1, coordsToLatLng);\n        layer.setLatLngs(latlngs);\n        break;\n      case 'Polygon':\n        latlngs = L.GeoJSON.coordsToLatLngs(geojson.geometry.coordinates, 1, coordsToLatLng);\n        layer.setLatLngs(latlngs);\n        break;\n      case 'MultiPolygon':\n        latlngs = L.GeoJSON.coordsToLatLngs(geojson.geometry.coordinates, 2, coordsToLatLng);\n        layer.setLatLngs(latlngs);\n        break;\n    }\n  },\n\n  /**\n   * Feature Managment Methods\n   */\n\n  createLayers: function(features){\n    for (var i = features.length - 1; i >= 0; i--) {\n\n      var geojson = features[i];\n\n      var layer = this._layers[geojson.id];\n      var newLayer;\n\n      if(layer && !this._map.hasLayer(layer)){\n        this._map.addLayer(layer);\n        return;\n      }\n\n      if (layer && layer.setLatLngs) {\n        this._updateLayerGeometry(layer, geojson);\n        return;\n      }\n\n      if(!layer){\n        newLayer =  this.createNewLayer(geojson);\n        newLayer.feature = geojson;\n        newLayer._originalStyle = this.options.style;\n        newLayer._leaflet_id = this._key + '_' + geojson.id;\n\n        this._leafletIds[newLayer._leaflet_id] = geojson.id;\n\n        // bubble events from layers to this\n        // @TODO Leaflet 0.8\n        // newLayer.addEventParent(this);\n\n        newLayer.on(EsriLeaflet.Layers.FeatureLayer.EVENTS, this._propagateEvent, this);\n\n        // bind a popup if we have one\n        if(this._popup && newLayer.bindPopup){\n          newLayer.bindPopup(this._popup(newLayer.feature, newLayer), this._popupOptions);\n        }\n\n        if(this.options.onEachFeature){\n          this.options.onEachFeature(newLayer.feature, newLayer);\n        }\n\n        // cache the layer\n        this._layers[newLayer.feature.id] = newLayer;\n\n        // style the layer\n        this.resetStyle(newLayer.feature.id);\n\n        this.fire('createfeature', {\n          feature: newLayer.feature\n        });\n\n        // add the layer if it is within the time bounds or our layer is not time enabled\n        if(!this.options.timeField || (this.options.timeField && this._featureWithinTimeRange(geojson)) ){\n          this._map.addLayer(newLayer);\n        }\n      }\n    }\n  },\n\n  addLayers: function(ids){\n    for (var i = ids.length - 1; i >= 0; i--) {\n      var layer = this._layers[ids[i]];\n      if(layer){\n        this.fire('addfeature', {\n          feature: layer.feature\n        });\n        this._map.addLayer(layer);\n      }\n    }\n  },\n\n  removeLayers: function(ids, permanent){\n    for (var i = ids.length - 1; i >= 0; i--) {\n      var id = ids[i];\n      var layer = this._layers[id];\n      if(layer){\n        this.fire('removefeature', {\n          feature: layer.feature,\n          permanent: permanent\n        });\n        this._map.removeLayer(layer);\n      }\n      if(layer && permanent){\n        delete this._layers[id];\n      }\n    }\n  },\n\n  cellEnter: function(bounds, coords){\n    if(!this._zooming){\n      EsriLeaflet.Util.requestAnimationFrame(L.Util.bind(function(){\n        var cacheKey = this._cacheKey(coords);\n        var cellKey = this._cellCoordsToKey(coords);\n        var layers = this._cache[cacheKey];\n        if(this._activeCells[cellKey] && layers){\n          this.addLayers(layers);\n        }\n      }, this));\n    }\n  },\n\n  cellLeave: function(bounds, coords){\n    if(!this._zooming){\n      EsriLeaflet.Util.requestAnimationFrame(L.Util.bind(function(){\n        var cacheKey = this._cacheKey(coords);\n        var cellKey = this._cellCoordsToKey(coords);\n        var layers = this._cache[cacheKey];\n        var mapBounds = this._map.getBounds();\n        if(!this._activeCells[cellKey] && layers){\n          var removable = true;\n\n          for (var i = 0; i < layers.length; i++) {\n            var layer = this._layers[layers[i]];\n            if(layer && layer.getBounds && mapBounds.intersects(layer.getBounds())){\n              removable = false;\n            }\n          }\n\n          if(removable){\n            this.removeLayers(layers, !this.options.cacheLayers);\n          }\n\n          if(!this.options.cacheLayers && removable){\n            delete this._cache[cacheKey];\n            delete this._cells[cellKey];\n            delete this._activeCells[cellKey];\n          }\n        }\n      }, this));\n    }\n  },\n\n  /**\n   * Styling Methods\n   */\n\n  resetStyle: function (id) {\n    var layer = this._layers[id];\n\n    if(layer){\n      this.setFeatureStyle(layer.feature.id, layer._originalStyle);\n    }\n\n    return this;\n  },\n\n  setStyle: function (style) {\n    this.options.style = style;\n    this.eachFeature(function (layer) {\n      this.setFeatureStyle(layer.feature.id, style);\n    }, this);\n    return this;\n  },\n\n  setFeatureStyle: function (id, style) {\n    var layer = this._layers[id];\n\n    if (typeof style === 'function') {\n      style = style(layer.feature);\n    }\n\n    if (!style && !layer.defaultOptions) {\n      style = L.Path.prototype.options;\n      style.fill = true; //not set by default\n    }\n\n    if (layer && layer.setStyle) {\n      layer.setStyle(style);\n    }\n\n    return this;\n  },\n\n  /**\n   * Popup Methods\n   */\n\n  bindPopup: function (fn, options) {\n    this._popup = fn;\n    this._popupOptions = options;\n    for (var i in this._layers) {\n      var layer = this._layers[i];\n      var popupContent = this._popup(layer.feature, layer);\n      layer.bindPopup(popupContent, options);\n    }\n    return this;\n  },\n\n  unbindPopup: function () {\n    this._popup =  false;\n    for (var i in this._layers) {\n      var layer = this._layers[i];\n      if (layer.unbindPopup) {\n        layer.unbindPopup();\n      } else if (layer.getLayers) {\n        var groupLayers = layer.getLayers();\n        for (var j in groupLayers) {\n          var gLayer = groupLayers[j];\n          gLayer.unbindPopup();\n        }\n      }\n    }\n    return this;\n  },\n\n  /**\n   * Utility Methods\n   */\n\n  eachFeature: function (fn, context) {\n    for (var i in this._layers) {\n      fn.call(context, this._layers[i]);\n    }\n    return this;\n  },\n\n  getFeature: function (id) {\n    return this._layers[id];\n  },\n\n  // from https://github.com/Leaflet/Leaflet/blob/v0.7.2/src/layer/FeatureGroup.js\n  // @TODO remove at Leaflet 0.8\n  _propagateEvent: function (e) {\n    e.layer = this._layers[this._leafletIds[e.target._leaflet_id]];\n    e.target = this;\n    this.fire(e.type, e);\n  }\n});\n\nEsriLeaflet.FeatureLayer = EsriLeaflet.Layers.FeatureLayer;\n\nEsriLeaflet.Layers.featureLayer = function(url, options){\n  return new EsriLeaflet.Layers.FeatureLayer(url, options);\n};\n\nEsriLeaflet.featureLayer = function(url, options){\n  return new EsriLeaflet.Layers.FeatureLayer(url, options);\n};","EsriLeaflet.Controls.Logo = L.Control.extend({\n  options: {\n    position: 'bottomright',\n    marginTop: 0,\n    marginLeft: 0,\n    marginBottom: 0,\n    marginRight: 0\n  },\n\n  onAdd: function () {\n    var div = L.DomUtil.create('div', 'esri-leaflet-logo');\n    div.style.marginTop = this.options.marginTop;\n    div.style.marginLeft = this.options.marginLeft;\n    div.style.marginBottom = this.options.marginBottom;\n    div.style.marginRight = this.options.marginRight;\n    div.innerHTML = this._adjustLogo(this._map._size);\n\n    this._map.on('resize', function(e){\n      div.innerHTML = this._adjustLogo(e.newSize);\n    }, this);\n\n    return div;\n  },\n\n  _adjustLogo: function (mapSize) {\n    if (mapSize.x <= 600 || mapSize.y <= 600){\n      return '<a href=\"https://developers.arcgis.com\" style=\"border: none;\"><img src=\"https://js.arcgis.com/3.13/esri/images/map/logo-sm.png\" alt=\"Powered by Esri\" style=\"border: none;\"></a>';\n    }\n    else {\n      return '<a href=\"https://developers.arcgis.com\" style=\"border: none;\"><img src=\"https://js.arcgis.com/3.13/esri/images/map/logo-med.png\" alt=\"Powered by Esri\" style=\"border: none;\"></a>';\n    }\n  }\n\n});\n\nEsriLeaflet.Controls.logo = function(options){\n  return new L.esri.Controls.Logo(options);\n};\n"]}