esri-leaflet-geocoder
Advanced tools
Comparing version 2.0.2 to 2.0.3
{ | ||
"name": "esri-leaflet-geocoder", | ||
"version": "v2.0.2", | ||
"version": "v2.0.3", | ||
"main": "dist/esri-leaflet-geocoder.js", | ||
"dependencies": { | ||
"esri-leaflet": "^2.0.0-beta.4", | ||
"leaflet": "^1.0.0-beta.2" | ||
}, | ||
"ignore": [ | ||
@@ -7,0 +11,0 @@ "**/.*", |
# Changelog | ||
## [Unreleased] | ||
## [Upcoming changes][Unreleased] | ||
## [2.0.2] | ||
## [2.0.3] | ||
### Added | ||
* exposed a parameter in `reverseGeocode` requests to fetch intersections. | ||
* new `searchBounds` parameter for `L.esri.Geocoding.geosearch` for filtering using a static bounding box. (#115 thanks to @nathanhilbert!) | ||
@@ -14,2 +14,3 @@ ### Fixed | ||
* appropriate l18n input parameter is now passed in `reverseGeocode` requests | ||
* made sure appropriate provider attribution is added to the map | ||
@@ -176,3 +177,4 @@ ## [2.0.1] | ||
[Unreleased]: https://github.com/Esri/esri-leaflet-geocoder/compare/v2.0.2...HEAD | ||
[2.0.1]: https://github.com/Esri/esri-leaflet-geocoder/compare/v2.0.1...v2.0.2 | ||
[2.0.3]: https://github.com/Esri/esri-leaflet-geocoder/compare/v2.0.2...v2.0.3 | ||
[2.0.2]: https://github.com/Esri/esri-leaflet-geocoder/compare/v2.0.1...v2.0.2 | ||
[2.0.1]: https://github.com/Esri/esri-leaflet-geocoder/compare/v2.0.0...v2.0.1 | ||
@@ -179,0 +181,0 @@ [2.0.0]: https://github.com/Esri/esri-leaflet-geocoder/compare/v2.0.0-beta.3...v2.0.0 |
@@ -1,5 +0,5 @@ | ||
/* esri-leaflet-geocoder - v2.0.2 - Thu Dec 03 2015 14:47:14 GMT-0800 (PST) | ||
* Copyright (c) 2015 Environmental Systems Research Institute, Inc. | ||
/* esri-leaflet-geocoder - v2.0.3 - Fri Jan 22 2016 20:32:34 GMT-0800 (PST) | ||
* Copyright (c) 2016 Environmental Systems Research Institute, Inc. | ||
* Apache-2.0 */ | ||
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports,require("leaflet"),require("esri-leaflet")):typeof define==="function"&&define.amd?define(["exports","leaflet","esri-leaflet"],factory):factory(global.L.esri.Geocoding={},L,L.esri)})(this,function(exports,L,esri_leaflet){"use strict";exports.Geocode=esri_leaflet.Task.extend({path:"find",params:{outSr:4326,forStorage:false,outFields:"*",maxLocations:20},setters:{address:"address",neighborhood:"neighborhood",city:"city",subregion:"subregion",region:"region",postal:"postal",country:"country",text:"text",category:"category",token:"token",key:"magicKey",fields:"outFields",forStorage:"forStorage",maxLocations:"maxLocations"},initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Task.prototype.initialize.call(this,options)},within:function(bounds){bounds=L.latLngBounds(bounds);this.params.bbox=esri_leaflet.Util.boundsToExtent(bounds);return this},nearby:function(latlng,radius){latlng=L.latLng(latlng);this.params.location=latlng.lng+","+latlng.lat;this.params.distance=Math.min(Math.max(radius,2e3),5e4);return this},run:function(callback,context){this.path=this.params.text?"find":"findAddressCandidates";if(this.path==="findAddressCandidates"&&this.params.bbox){this.params.searchExtent=this.params.bbox;delete this.params.bbox}return this.request(function(error,response){var processor=this.path==="find"?this._processFindResponse:this._processFindAddressCandidatesResponse;var results=!error?processor(response):undefined;callback.call(context,error,{results:results},response)},this)},_processFindResponse:function(response){var results=[];for(var i=0;i<response.locations.length;i++){var location=response.locations[i];var bounds;if(location.extent){bounds=esri_leaflet.Util.extentToBounds(location.extent)}results.push({text:location.name,bounds:bounds,score:location.feature.attributes.Score,latlng:L.latLng(location.feature.geometry.y,location.feature.geometry.x),properties:location.feature.attributes})}return results},_processFindAddressCandidatesResponse:function(response){var results=[];for(var i=0;i<response.candidates.length;i++){var candidate=response.candidates[i];var bounds=esri_leaflet.Util.extentToBounds(candidate.extent);results.push({text:candidate.address,bounds:bounds,score:candidate.score,latlng:L.latLng(candidate.location.y,candidate.location.x),properties:candidate.attributes})}return results}});function geocode(options){return new exports.Geocode(options)}exports.ReverseGeocode=esri_leaflet.Task.extend({path:"reverseGeocode",params:{outSR:4326,returnIntersection:false},setters:{distance:"distance",language:"langCode",intersection:"returnIntersection"},initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Task.prototype.initialize.call(this,options)},latlng:function(latlng){latlng=L.latLng(latlng);this.params.location=latlng.lng+","+latlng.lat;return this},run:function(callback,context){return this.request(function(error,response){var result;if(!error){result={latlng:L.latLng(response.location.y,response.location.x),address:response.address}}else{result=undefined}callback.call(context,error,result,response)},this)}});function reverseGeocode(options){return new exports.ReverseGeocode(options)}exports.Suggest=esri_leaflet.Task.extend({path:"suggest",params:{},setters:{text:"text",category:"category",countries:"countryCode"},initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Task.prototype.initialize.call(this,options)},within:function(bounds){bounds=L.latLngBounds(bounds);bounds=bounds.pad(.5);var center=bounds.getCenter();var ne=bounds.getNorthWest();this.params.location=center.lng+","+center.lat;this.params.distance=Math.min(Math.max(center.distanceTo(ne),2e3),5e4);this.params.searchExtent=esri_leaflet.Util.boundsToExtent(bounds);return this},nearby:function(latlng,radius){latlng=L.latLng(latlng);this.params.location=latlng.lng+","+latlng.lat;this.params.distance=Math.min(Math.max(radius,2e3),5e4);return this},run:function(callback,context){return this.request(function(error,response){callback.call(context,error,response,response)},this)}});function suggest(options){return new exports.Suggest(options)}exports.GeocodeService=esri_leaflet.Service.extend({initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Service.prototype.initialize.call(this,options);this._confirmSuggestSupport()},geocode:function(){return geocode(this)},reverse:function(){return reverseGeocode(this)},suggest:function(){return suggest(this)},_confirmSuggestSupport:function(){this.metadata(function(error,response){if(error){return}if(response.capabilities.includes("Suggest")){this.options.supportsSuggest=true}else{this.options.supportsSuggest=false}},this)}});function geocodeService(options){return new exports.GeocodeService(options)}exports.Geosearch=L.Control.extend({includes:L.Mixin.Events,options:{position:"topleft",zoomToResult:true,useMapBounds:12,collapseAfterResult:true,expanded:false,allowMultipleResults:true,placeholder:"Search for places or addresses",title:"Location Search"},initialize:function(options){L.Util.setOptions(this,options);if(!options||!options.providers||!options.providers.length){throw new Error("You must specificy at least one provider")}this._providers=options.providers;for(var i=0;i<this._providers.length;i++){this._providers[i].addEventParent(this)}this._pendingSuggestions=[];L.Control.prototype.initialize.call(options)},_geocode:function(text,key,provider){var activeRequests=0;var allResults=[];var bounds;var callback=L.Util.bind(function(error,results){activeRequests--;if(error){return}if(results){allResults=allResults.concat(results)}if(activeRequests<=0){bounds=this._boundsFromResults(allResults);this.fire("results",{results:allResults,bounds:bounds,latlng:bounds?bounds.getCenter():undefined,text:text});if(this.options.zoomToResult&&bounds){this._map.fitBounds(bounds)}L.DomUtil.removeClass(this._input,"geocoder-control-loading");this.fire("load");this.clear();this._input.blur()}},this);if(key){activeRequests++;provider.results(text,key,this._searchBounds(),callback)}else{for(var i=0;i<this._providers.length;i++){activeRequests++;this._providers[i].results(text,key,this._searchBounds(),callback)}}},_suggest:function(text){L.DomUtil.addClass(this._input,"geocoder-control-loading");var activeRequests=this._providers.length;var createCallback=L.Util.bind(function(text,provider){return L.Util.bind(function(error,suggestions){if(error){return}var i;activeRequests=activeRequests-1;if(this._input.value<2){this._suggestions.innerHTML="";this._suggestions.style.display="none";return}if(suggestions){for(i=0;i<suggestions.length;i++){suggestions[i].provider=provider}}if(provider._lastRender!==text&&provider.nodes){for(i=0;i<provider.nodes.length;i++){if(provider.nodes[i].parentElement){this._suggestions.removeChild(provider.nodes[i])}}provider.nodes=[]}if(suggestions.length&&this._input.value===text){if(provider.nodes){for(var k=0;k<provider.nodes.length;k++){if(provider.nodes[k].parentElement){this._suggestions.removeChild(provider.nodes[k])}}}provider._lastRender=text;provider.nodes=this._renderSuggestions(suggestions)}if(activeRequests===0){L.DomUtil.removeClass(this._input,"geocoder-control-loading")}},this)},this);this._pendingSuggestions=[];for(var i=0;i<this._providers.length;i++){var provider=this._providers[i];var request=provider.suggestions(text,this._searchBounds(),createCallback(text,provider));this._pendingSuggestions.push(request)}},_searchBounds:function(){if(this.options.useMapBounds===false){return null}if(this.options.useMapBounds===true){return this._map.getBounds()}if(this.options.useMapBounds<=this._map.getZoom()){return this._map.getBounds()}return null},_renderSuggestions:function(suggestions){var currentGroup;this._suggestions.style.display="block";this._suggestions.style.maxHeight=this._map.getSize().y-this._suggestions.offsetTop-this._wrapper.offsetTop-10+"px";var nodes=[];var list;var header;for(var i=0;i<suggestions.length;i++){var suggestion=suggestions[i];if(!header&&this._providers.length>1&¤tGroup!==suggestion.provider.options.label){header=L.DomUtil.create("span","geocoder-control-header",this._suggestions);header.textContent=suggestion.provider.options.label;header.innerText=suggestion.provider.options.label;currentGroup=suggestion.provider.options.label;nodes.push(header)}if(!list){list=L.DomUtil.create("ul","geocoder-control-list",this._suggestions)}var suggestionItem=L.DomUtil.create("li","geocoder-control-suggestion",list);suggestionItem.innerHTML=suggestion.text;suggestionItem.provider=suggestion.provider;suggestionItem["data-magic-key"]=suggestion.magicKey}nodes.push(list);return nodes},_boundsFromResults:function(results){if(!results.length){return}var nullIsland=L.latLngBounds([0,0],[0,0]);var resultBounds=[];var resultLatlngs=[];for(var i=results.length-1;i>=0;i--){var result=results[i];resultLatlngs.push(result.latlng);if(result.bounds&&result.bounds.isValid()&&!result.bounds.equals(nullIsland)){resultBounds.push(result.bounds)}}var bounds=L.latLngBounds(resultLatlngs);for(var j=0;j<resultBounds.length;j++){bounds.extend(resultBounds[i])}return bounds},clear:function(){this._suggestions.innerHTML="";this._suggestions.style.display="none";this._input.value="";if(this.options.collapseAfterResult){this._input.placeholder="";L.DomUtil.removeClass(this._wrapper,"geocoder-control-expanded")}if(!this._map.scrollWheelZoom.enabled()&&this._map.options.scrollWheelZoom){this._map.scrollWheelZoom.enable()}},getAttribution:function(){var attribs=[];for(var i=0;i<this._providers.length;i++){if(this._providers[i].options.attribution){attribs.push(this._providers[i].options.attribution)}}return attribs.join(", ")},onAdd:function(map){this._map=map;this._wrapper=L.DomUtil.create("div","geocoder-control "+(this.options.expanded?" "+"geocoder-control-expanded":""));this._input=L.DomUtil.create("input","geocoder-control-input leaflet-bar",this._wrapper);this._input.title=this.options.title;this._suggestions=L.DomUtil.create("div","geocoder-control-suggestions leaflet-bar",this._wrapper);var credits=this.getAttribution();map.attributionControl.addAttribution(credits);L.DomEvent.addListener(this._input,"focus",function(e){this._input.placeholder=this.options.placeholder;L.DomUtil.addClass(this._wrapper,"geocoder-control-expanded")},this);L.DomEvent.addListener(this._wrapper,"click",function(e){L.DomUtil.addClass(this._wrapper,"geocoder-control-expanded");this._input.focus()},this);L.DomEvent.addListener(this._suggestions,"mousedown",function(e){var suggestionItem=e.target||e.srcElement;this._geocode(suggestionItem.innerHTML,suggestionItem["data-magic-key"],suggestionItem.provider);this.clear()},this);L.DomEvent.addListener(this._input,"blur",function(e){this.clear()},this);L.DomEvent.addListener(this._input,"keydown",function(e){L.DomUtil.addClass(this._wrapper,"geocoder-control-expanded");var list=this._suggestions.querySelectorAll("."+"geocoder-control-suggestion");var selected=this._suggestions.querySelectorAll("."+"geocoder-control-selected")[0];var selectedPosition;for(var i=0;i<list.length;i++){if(list[i]===selected){selectedPosition=i;break}}switch(e.keyCode){case 13:if(selected){this._geocode(selected.innerHTML,selected["data-magic-key"],selected.provider);this.clear()}else if(this.options.allowMultipleResults){this._geocode(this._input.value,undefined);this.clear()}else{L.DomUtil.addClass(list[0],"geocoder-control-selected")}L.DomEvent.preventDefault(e);break;case 38:if(selected){L.DomUtil.removeClass(selected,"geocoder-control-selected")}var previousItem=list[selectedPosition-1];if(selected&&previousItem){L.DomUtil.addClass(previousItem,"geocoder-control-selected")}else{L.DomUtil.addClass(list[list.length-1],"geocoder-control-selected")}L.DomEvent.preventDefault(e);break;case 40:if(selected){L.DomUtil.removeClass(selected,"geocoder-control-selected")}var nextItem=list[selectedPosition+1];if(selected&&nextItem){L.DomUtil.addClass(nextItem,"geocoder-control-selected")}else{L.DomUtil.addClass(list[0],"geocoder-control-selected")}L.DomEvent.preventDefault(e);break;default:for(var x=0;x<this._pendingSuggestions.length;x++){var request=this._pendingSuggestions[x];if(request&&request.abort&&!request.id){request.abort()}}break}},this);L.DomEvent.addListener(this._input,"keyup",L.Util.throttle(function(e){var key=e.which||e.keyCode;var text=(e.target||e.srcElement).value;if(text.length<2){this._suggestions.innerHTML="";this._suggestions.style.display="none";L.DomUtil.removeClass(this._input,"geocoder-control-loading");return}if(key===27){this._suggestions.innerHTML="";this._suggestions.style.display="none";return}if(key!==13&&key!==38&&key!==40){if(this._input.value!==this._lastValue){this._lastValue=this._input.value;this._suggest(text)}}},50,this),this);L.DomEvent.disableClickPropagation(this._wrapper);L.DomEvent.addListener(this._suggestions,"mouseover",function(e){if(map.scrollWheelZoom.enabled()&&map.options.scrollWheelZoom){map.scrollWheelZoom.disable()}});L.DomEvent.addListener(this._suggestions,"mouseout",function(e){if(!map.scrollWheelZoom.enabled()&&map.options.scrollWheelZoom){map.scrollWheelZoom.enable()}});return this._wrapper},onRemove:function(map){map.attributionControl.removeAttribution("Geocoding by Esri")}});function geosearch(options){return new exports.Geosearch(options)}exports.ArcgisOnlineProvider=exports.GeocodeService.extend({options:{label:"Places and Addresses",maxResults:5,attribution:'<a href="https://developers.arcgis.com/en/features/geocoding/">Geocoding by Esri</a>'},suggestions:function(text,bounds,callback){var request=this.suggest().text(text);if(bounds){request.within(bounds)}if(this.options.countries){request.countries(this.options.countries)}if(this.options.categories){request.category(this.options.categories)}return request.run(function(error,results,response){var suggestions=[];if(!error){while(response.suggestions.length&&suggestions.length<=this.options.maxResults-1){var suggestion=response.suggestions.shift();if(!suggestion.isCollection){suggestions.push({text:suggestion.text,magicKey:suggestion.magicKey})}}}callback(error,suggestions)},this)},results:function(text,key,bounds,callback){var request=this.geocode().text(text);if(key){request.key(key)}else{request.maxLocations(this.options.maxResults)}if(bounds){request.within(bounds)}if(this.options.forStorage){request.forStorage(true)}return request.run(function(error,response){callback(error,response.results)},this)}});function arcgisOnlineProvider(options){return new exports.ArcgisOnlineProvider(options)}exports.FeatureLayerProvider=esri_leaflet.FeatureLayerService.extend({options:{label:"Feature Layer",maxResults:5,bufferRadius:1e3,formatSuggestion:function(feature){return feature.properties[this.options.searchFields[0]]}},initialize:function(options){esri_leaflet.FeatureLayerService.prototype.initialize.call(this,options);if(typeof this.options.searchFields==="string"){this.options.searchFields=[this.options.searchFields]}},suggestions:function(text,bounds,callback){var query=this.query().where(this._buildQuery(text)).returnGeometry(false);if(bounds){query.intersects(bounds)}if(this.options.idField){query.fields([this.options.idField].concat(this.options.searchFields))}var request=query.run(function(error,results,raw){if(error){callback(error,[])}else{this.options.idField=raw.objectIdFieldName;var suggestions=[];var count=Math.min(results.features.length,this.options.maxResults);for(var i=0;i<count;i++){var feature=results.features[i];suggestions.push({text:this.options.formatSuggestion.call(this,feature),magicKey:feature.id})}callback(error,suggestions.slice(0,this.options.maxResults).reverse())}},this);return request},results:function(text,key,bounds,callback){var query=this.query();if(key){query.featureIds([key])}else{query.where(this._buildQuery(text))}if(bounds){query.within(bounds)}return query.run(L.Util.bind(function(error,features){var results=[];for(var i=0;i<features.features.length;i++){var feature=features.features[i];if(feature){var bounds=this._featureBounds(feature);var result={latlng:bounds.getCenter(),bounds:bounds,text:this.options.formatSuggestion.call(this,feature),properties:feature.properties,geojson:feature};results.push(result)}}callback(error,results)},this))},_buildQuery:function(text){var queryString=[];for(var i=this.options.searchFields.length-1;i>=0;i--){var field='upper("'+this.options.searchFields[i]+'")';queryString.push(field+" LIKE upper('%"+text+"%')")}return queryString.join(" OR ")},_featureBounds:function(feature){var geojson=L.geoJson(feature);if(feature.geometry.type==="Point"){var center=geojson.getBounds().getCenter();var lngRadius=this.options.bufferRadius/40075017*360/Math.cos(180/Math.PI*center.lat);var latRadius=this.options.bufferRadius/40075017*360;return L.latLngBounds([center.lat-latRadius,center.lng-lngRadius],[center.lat+latRadius,center.lng+lngRadius])}else{return geojson.getBounds()}}});function featureLayerProvider(options){return new exports.FeatureLayerProvider(options)}exports.MapServiceProvider=esri_leaflet.MapService.extend({options:{layers:[0],label:"Map Service",bufferRadius:1e3,maxResults:5,formatSuggestion:function(feature){return feature.properties[feature.displayFieldName]+" <small>"+feature.layerName+"</small>"}},initialize:function(options){esri_leaflet.MapService.prototype.initialize.call(this,options);this._getIdFields()},suggestions:function(text,bounds,callback){var request=this.find().text(text).fields(this.options.searchFields).returnGeometry(false).layers(this.options.layers);return request.run(function(error,results,raw){var suggestions=[];if(!error){var count=Math.min(this.options.maxResults,results.features.length);raw.results=raw.results.reverse();for(var i=0;i<count;i++){var feature=results.features[i];var result=raw.results[i];var layer=result.layerId;var idField=this._idFields[layer];feature.layerId=layer;feature.layerName=this._layerNames[layer];feature.displayFieldName=this._displayFields[layer];if(idField){suggestions.push({text:this.options.formatSuggestion.call(this,feature),magicKey:result.attributes[idField]+":"+layer})}}}callback(error,suggestions.reverse())},this)},results:function(text,key,bounds,callback){var results=[];var request;if(key){var featureId=key.split(":")[0];var layer=key.split(":")[1];request=this.query().layer(layer).featureIds(featureId)}else{request=this.find().text(text).fields(this.options.searchFields).contains(false).layers(this.options.layers)}return request.run(function(error,features,response){if(!error){if(response.results){response.results=response.results.reverse()}for(var i=0;i<features.features.length;i++){var feature=features.features[i];layer=layer||response.results[i].layerId;if(feature&&layer!==undefined){var bounds=this._featureBounds(feature);feature.layerId=layer;feature.layerName=this._layerNames[layer];feature.displayFieldName=this._displayFields[layer];var result={latlng:bounds.getCenter(),bounds:bounds,text:this.options.formatSuggestion.call(this,feature),properties:feature.properties,geojson:feature};results.push(result)}}}callback(error,results.reverse())},this)},_featureBounds:function(feature){var geojson=L.geoJson(feature);if(feature.geometry.type==="Point"){var center=geojson.getBounds().getCenter();var lngRadius=this.options.bufferRadius/40075017*360/Math.cos(180/Math.PI*center.lat);var latRadius=this.options.bufferRadius/40075017*360;return L.latLngBounds([center.lat-latRadius,center.lng-lngRadius],[center.lat+latRadius,center.lng+lngRadius])}else{return geojson.getBounds()}},_layerMetadataCallback:function(layerid){return L.Util.bind(function(error,metadata){if(error){return}this._displayFields[layerid]=metadata.displayField;this._layerNames[layerid]=metadata.name;for(var i=0;i<metadata.fields.length;i++){var field=metadata.fields[i];if(field.type==="esriFieldTypeOID"){this._idFields[layerid]=field.name;break}}},this)},_getIdFields:function(){this._idFields={};this._displayFields={};this._layerNames={};for(var i=0;i<this.options.layers.length;i++){var layer=this.options.layers[i];this.get(layer,{},this._layerMetadataCallback(layer))}}});function mapServiceProvider(options){return new exports.MapServiceProvider(options)}exports.GeocodeServiceProvider=exports.GeocodeService.extend({options:{label:"Geocode Server",maxResults:5},suggestions:function(text,bounds,callback){if(this.options.supportsSuggest){var request=this.suggest().text(text);if(bounds){request.within(bounds)}return request.run(function(error,results,response){var suggestions=[];if(!error){while(response.suggestions.length&&suggestions.length<=this.options.maxResults-1){var suggestion=response.suggestions.shift();if(!suggestion.isCollection){suggestions.push({text:suggestion.text,magicKey:suggestion.magicKey})}}}callback(error,suggestions)},this)}else{callback(undefined,[]);return false}},results:function(text,key,bounds,callback){var request=this.geocode().text(text);request.maxLocations(this.options.maxResults);if(bounds){request.within(bounds)}return request.run(function(error,response){callback(error,response.results)},this)}});function geocodeServiceProvider(options){return new exports.GeocodeServiceProvider(options)}exports.VERSION="2.0.2";exports.WorldGeocodingServiceUrl=(window.location.protocol==="https:"?"https:":"http:")+"//geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/";exports.geocode=geocode;exports.reverseGeocode=reverseGeocode;exports.suggest=suggest;exports.geocodeService=geocodeService;exports.geosearch=geosearch;exports.arcgisOnlineProvider=arcgisOnlineProvider;exports.featureLayerProvider=featureLayerProvider;exports.mapServiceProvider=mapServiceProvider;exports.geocodeServiceProvider=geocodeServiceProvider}); | ||
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports,require("leaflet"),require("esri-leaflet")):typeof define==="function"&&define.amd?define(["exports","leaflet","esri-leaflet"],factory):factory(global.L.esri.Geocoding={},L,L.esri)})(this,function(exports,L,esri_leaflet){"use strict";exports.Geocode=esri_leaflet.Task.extend({path:"find",params:{outSr:4326,forStorage:false,outFields:"*",maxLocations:20},setters:{address:"address",neighborhood:"neighborhood",city:"city",subregion:"subregion",region:"region",postal:"postal",country:"country",text:"text",category:"category",token:"token",key:"magicKey",fields:"outFields",forStorage:"forStorage",maxLocations:"maxLocations"},initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Task.prototype.initialize.call(this,options)},within:function(bounds){bounds=L.latLngBounds(bounds);this.params.bbox=esri_leaflet.Util.boundsToExtent(bounds);return this},nearby:function(latlng,radius){latlng=L.latLng(latlng);this.params.location=latlng.lng+","+latlng.lat;this.params.distance=Math.min(Math.max(radius,2e3),5e4);return this},run:function(callback,context){this.path=this.params.text?"find":"findAddressCandidates";if(this.path==="findAddressCandidates"&&this.params.bbox){this.params.searchExtent=this.params.bbox;delete this.params.bbox}return this.request(function(error,response){var processor=this.path==="find"?this._processFindResponse:this._processFindAddressCandidatesResponse;var results=!error?processor(response):undefined;callback.call(context,error,{results:results},response)},this)},_processFindResponse:function(response){var results=[];for(var i=0;i<response.locations.length;i++){var location=response.locations[i];var bounds;if(location.extent){bounds=esri_leaflet.Util.extentToBounds(location.extent)}results.push({text:location.name,bounds:bounds,score:location.feature.attributes.Score,latlng:L.latLng(location.feature.geometry.y,location.feature.geometry.x),properties:location.feature.attributes})}return results},_processFindAddressCandidatesResponse:function(response){var results=[];for(var i=0;i<response.candidates.length;i++){var candidate=response.candidates[i];var bounds=esri_leaflet.Util.extentToBounds(candidate.extent);results.push({text:candidate.address,bounds:bounds,score:candidate.score,latlng:L.latLng(candidate.location.y,candidate.location.x),properties:candidate.attributes})}return results}});function geocode(options){return new exports.Geocode(options)}exports.ReverseGeocode=esri_leaflet.Task.extend({path:"reverseGeocode",params:{outSR:4326,returnIntersection:false},setters:{distance:"distance",language:"langCode",intersection:"returnIntersection"},initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Task.prototype.initialize.call(this,options)},latlng:function(latlng){latlng=L.latLng(latlng);this.params.location=latlng.lng+","+latlng.lat;return this},run:function(callback,context){return this.request(function(error,response){var result;if(!error){result={latlng:L.latLng(response.location.y,response.location.x),address:response.address}}else{result=undefined}callback.call(context,error,result,response)},this)}});function reverseGeocode(options){return new exports.ReverseGeocode(options)}exports.Suggest=esri_leaflet.Task.extend({path:"suggest",params:{},setters:{text:"text",category:"category",countries:"countryCode"},initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Task.prototype.initialize.call(this,options)},within:function(bounds){bounds=L.latLngBounds(bounds);bounds=bounds.pad(.5);var center=bounds.getCenter();var ne=bounds.getNorthWest();this.params.location=center.lng+","+center.lat;this.params.distance=Math.min(Math.max(center.distanceTo(ne),2e3),5e4);this.params.searchExtent=esri_leaflet.Util.boundsToExtent(bounds);return this},nearby:function(latlng,radius){latlng=L.latLng(latlng);this.params.location=latlng.lng+","+latlng.lat;this.params.distance=Math.min(Math.max(radius,2e3),5e4);return this},run:function(callback,context){return this.request(function(error,response){callback.call(context,error,response,response)},this)}});function suggest(options){return new exports.Suggest(options)}exports.GeocodeService=esri_leaflet.Service.extend({initialize:function(options){options=options||{};options.url=options.url||exports.WorldGeocodingServiceUrl;esri_leaflet.Service.prototype.initialize.call(this,options);this._confirmSuggestSupport()},geocode:function(){return geocode(this)},reverse:function(){return reverseGeocode(this)},suggest:function(){return suggest(this)},_confirmSuggestSupport:function(){this.metadata(function(error,response){if(error){return}if(response.capabilities.includes("Suggest")){this.options.supportsSuggest=true}else{this.options.supportsSuggest=false}},this)}});function geocodeService(options){return new exports.GeocodeService(options)}exports.Geosearch=L.Control.extend({includes:L.Mixin.Events,options:{position:"topleft",zoomToResult:true,searchBounds:null,useMapBounds:12,collapseAfterResult:true,expanded:false,allowMultipleResults:true,placeholder:"Search for places or addresses",title:"Location Search"},initialize:function(options){L.Util.setOptions(this,options);if(!options||!options.providers||!options.providers.length){throw new Error("You must specificy at least one provider")}this._providers=options.providers;for(var i=0;i<this._providers.length;i++){this._providers[i].addEventParent(this)}this._pendingSuggestions=[];L.Control.prototype.initialize.call(options)},_geocode:function(text,key,provider){var activeRequests=0;var allResults=[];var bounds;var callback=L.Util.bind(function(error,results){activeRequests--;if(error){return}if(results){allResults=allResults.concat(results)}if(activeRequests<=0){bounds=this._boundsFromResults(allResults);this.fire("results",{results:allResults,bounds:bounds,latlng:bounds?bounds.getCenter():undefined,text:text});if(this.options.zoomToResult&&bounds){this._map.fitBounds(bounds)}L.DomUtil.removeClass(this._input,"geocoder-control-loading");this.fire("load");this.clear();this._input.blur()}},this);if(key){activeRequests++;provider.results(text,key,this._searchBounds(),callback)}else{for(var i=0;i<this._providers.length;i++){activeRequests++;this._providers[i].results(text,key,this._searchBounds(),callback)}}},_suggest:function(text){L.DomUtil.addClass(this._input,"geocoder-control-loading");var activeRequests=this._providers.length;var createCallback=L.Util.bind(function(text,provider){return L.Util.bind(function(error,suggestions){if(error){return}var i;activeRequests=activeRequests-1;if(this._input.value<2){this._suggestions.innerHTML="";this._suggestions.style.display="none";return}if(suggestions){for(i=0;i<suggestions.length;i++){suggestions[i].provider=provider}}if(provider._lastRender!==text&&provider.nodes){for(i=0;i<provider.nodes.length;i++){if(provider.nodes[i].parentElement){this._suggestions.removeChild(provider.nodes[i])}}provider.nodes=[]}if(suggestions.length&&this._input.value===text){if(provider.nodes){for(var k=0;k<provider.nodes.length;k++){if(provider.nodes[k].parentElement){this._suggestions.removeChild(provider.nodes[k])}}}provider._lastRender=text;provider.nodes=this._renderSuggestions(suggestions)}if(activeRequests===0){L.DomUtil.removeClass(this._input,"geocoder-control-loading")}},this)},this);this._pendingSuggestions=[];for(var i=0;i<this._providers.length;i++){var provider=this._providers[i];var request=provider.suggestions(text,this._searchBounds(),createCallback(text,provider));this._pendingSuggestions.push(request)}},_searchBounds:function(){if(this.options.searchBounds!==null){return this.options.searchBounds}if(this.options.useMapBounds===false){return null}if(this.options.useMapBounds===true){return this._map.getBounds()}if(this.options.useMapBounds<=this._map.getZoom()){return this._map.getBounds()}return null},_renderSuggestions:function(suggestions){var currentGroup;this._suggestions.style.display="block";this._suggestions.style.maxHeight=this._map.getSize().y-this._suggestions.offsetTop-this._wrapper.offsetTop-10+"px";var nodes=[];var list;var header;for(var i=0;i<suggestions.length;i++){var suggestion=suggestions[i];if(!header&&this._providers.length>1&¤tGroup!==suggestion.provider.options.label){header=L.DomUtil.create("span","geocoder-control-header",this._suggestions);header.textContent=suggestion.provider.options.label;header.innerText=suggestion.provider.options.label;currentGroup=suggestion.provider.options.label;nodes.push(header)}if(!list){list=L.DomUtil.create("ul","geocoder-control-list",this._suggestions)}var suggestionItem=L.DomUtil.create("li","geocoder-control-suggestion",list);suggestionItem.innerHTML=suggestion.text;suggestionItem.provider=suggestion.provider;suggestionItem["data-magic-key"]=suggestion.magicKey}nodes.push(list);return nodes},_boundsFromResults:function(results){if(!results.length){return}var nullIsland=L.latLngBounds([0,0],[0,0]);var resultBounds=[];var resultLatlngs=[];for(var i=results.length-1;i>=0;i--){var result=results[i];resultLatlngs.push(result.latlng);if(result.bounds&&result.bounds.isValid()&&!result.bounds.equals(nullIsland)){resultBounds.push(result.bounds)}}var bounds=L.latLngBounds(resultLatlngs);for(var j=0;j<resultBounds.length;j++){bounds.extend(resultBounds[i])}return bounds},clear:function(){this._suggestions.innerHTML="";this._suggestions.style.display="none";this._input.value="";if(this.options.collapseAfterResult){this._input.placeholder="";L.DomUtil.removeClass(this._wrapper,"geocoder-control-expanded")}if(!this._map.scrollWheelZoom.enabled()&&this._map.options.scrollWheelZoom){this._map.scrollWheelZoom.enable()}},getAttribution:function(){var attribs=[];for(var i=0;i<this._providers.length;i++){if(this._providers[i].options.attribution){attribs.push(this._providers[i].options.attribution)}}return attribs.join(", ")},onAdd:function(map){this._map=map;this._wrapper=L.DomUtil.create("div","geocoder-control "+(this.options.expanded?" "+"geocoder-control-expanded":""));this._input=L.DomUtil.create("input","geocoder-control-input leaflet-bar",this._wrapper);this._input.title=this.options.title;this._suggestions=L.DomUtil.create("div","geocoder-control-suggestions leaflet-bar",this._wrapper);var credits=this.getAttribution();map.attributionControl.addAttribution(credits);L.DomEvent.addListener(this._input,"focus",function(e){this._input.placeholder=this.options.placeholder;L.DomUtil.addClass(this._wrapper,"geocoder-control-expanded")},this);L.DomEvent.addListener(this._wrapper,"click",function(e){L.DomUtil.addClass(this._wrapper,"geocoder-control-expanded");this._input.focus()},this);L.DomEvent.addListener(this._suggestions,"mousedown",function(e){var suggestionItem=e.target||e.srcElement;this._geocode(suggestionItem.innerHTML,suggestionItem["data-magic-key"],suggestionItem.provider);this.clear()},this);L.DomEvent.addListener(this._input,"blur",function(e){this.clear()},this);L.DomEvent.addListener(this._input,"keydown",function(e){L.DomUtil.addClass(this._wrapper,"geocoder-control-expanded");var list=this._suggestions.querySelectorAll("."+"geocoder-control-suggestion");var selected=this._suggestions.querySelectorAll("."+"geocoder-control-selected")[0];var selectedPosition;for(var i=0;i<list.length;i++){if(list[i]===selected){selectedPosition=i;break}}switch(e.keyCode){case 13:if(selected){this._geocode(selected.innerHTML,selected["data-magic-key"],selected.provider);this.clear()}else if(this.options.allowMultipleResults){this._geocode(this._input.value,undefined);this.clear()}else{L.DomUtil.addClass(list[0],"geocoder-control-selected")}L.DomEvent.preventDefault(e);break;case 38:if(selected){L.DomUtil.removeClass(selected,"geocoder-control-selected")}var previousItem=list[selectedPosition-1];if(selected&&previousItem){L.DomUtil.addClass(previousItem,"geocoder-control-selected")}else{L.DomUtil.addClass(list[list.length-1],"geocoder-control-selected")}L.DomEvent.preventDefault(e);break;case 40:if(selected){L.DomUtil.removeClass(selected,"geocoder-control-selected")}var nextItem=list[selectedPosition+1];if(selected&&nextItem){L.DomUtil.addClass(nextItem,"geocoder-control-selected")}else{L.DomUtil.addClass(list[0],"geocoder-control-selected")}L.DomEvent.preventDefault(e);break;default:for(var x=0;x<this._pendingSuggestions.length;x++){var request=this._pendingSuggestions[x];if(request&&request.abort&&!request.id){request.abort()}}break}},this);L.DomEvent.addListener(this._input,"keyup",L.Util.throttle(function(e){var key=e.which||e.keyCode;var text=(e.target||e.srcElement).value;if(text.length<2){this._suggestions.innerHTML="";this._suggestions.style.display="none";L.DomUtil.removeClass(this._input,"geocoder-control-loading");return}if(key===27){this._suggestions.innerHTML="";this._suggestions.style.display="none";return}if(key!==13&&key!==38&&key!==40){if(this._input.value!==this._lastValue){this._lastValue=this._input.value;this._suggest(text)}}},50,this),this);L.DomEvent.disableClickPropagation(this._wrapper);L.DomEvent.addListener(this._suggestions,"mouseover",function(e){if(map.scrollWheelZoom.enabled()&&map.options.scrollWheelZoom){map.scrollWheelZoom.disable()}});L.DomEvent.addListener(this._suggestions,"mouseout",function(e){if(!map.scrollWheelZoom.enabled()&&map.options.scrollWheelZoom){map.scrollWheelZoom.enable()}});return this._wrapper},onRemove:function(map){map.attributionControl.removeAttribution("Geocoding by Esri")}});function geosearch(options){return new exports.Geosearch(options)}exports.ArcgisOnlineProvider=exports.GeocodeService.extend({options:{label:"Places and Addresses",maxResults:5,attribution:'<a href="https://developers.arcgis.com/en/features/geocoding/">Geocoding by Esri</a>'},suggestions:function(text,bounds,callback){var request=this.suggest().text(text);if(bounds){request.within(bounds)}if(this.options.countries){request.countries(this.options.countries)}if(this.options.categories){request.category(this.options.categories)}return request.run(function(error,results,response){var suggestions=[];if(!error){while(response.suggestions.length&&suggestions.length<=this.options.maxResults-1){var suggestion=response.suggestions.shift();if(!suggestion.isCollection){suggestions.push({text:suggestion.text,magicKey:suggestion.magicKey})}}}callback(error,suggestions)},this)},results:function(text,key,bounds,callback){var request=this.geocode().text(text);if(key){request.key(key)}else{request.maxLocations(this.options.maxResults)}if(bounds){request.within(bounds)}if(this.options.forStorage){request.forStorage(true)}return request.run(function(error,response){callback(error,response.results)},this)}});function arcgisOnlineProvider(options){return new exports.ArcgisOnlineProvider(options)}exports.FeatureLayerProvider=esri_leaflet.FeatureLayerService.extend({options:{label:"Feature Layer",maxResults:5,bufferRadius:1e3,formatSuggestion:function(feature){return feature.properties[this.options.searchFields[0]]}},initialize:function(options){esri_leaflet.FeatureLayerService.prototype.initialize.call(this,options);if(typeof this.options.searchFields==="string"){this.options.searchFields=[this.options.searchFields]}},suggestions:function(text,bounds,callback){var query=this.query().where(this._buildQuery(text)).returnGeometry(false);if(bounds){query.intersects(bounds)}if(this.options.idField){query.fields([this.options.idField].concat(this.options.searchFields))}var request=query.run(function(error,results,raw){if(error){callback(error,[])}else{this.options.idField=raw.objectIdFieldName;var suggestions=[];var count=Math.min(results.features.length,this.options.maxResults);for(var i=0;i<count;i++){var feature=results.features[i];suggestions.push({text:this.options.formatSuggestion.call(this,feature),magicKey:feature.id})}callback(error,suggestions.slice(0,this.options.maxResults).reverse())}},this);return request},results:function(text,key,bounds,callback){var query=this.query();if(key){query.featureIds([key])}else{query.where(this._buildQuery(text))}if(bounds){query.within(bounds)}return query.run(L.Util.bind(function(error,features){var results=[];for(var i=0;i<features.features.length;i++){var feature=features.features[i];if(feature){var bounds=this._featureBounds(feature);var result={latlng:bounds.getCenter(),bounds:bounds,text:this.options.formatSuggestion.call(this,feature),properties:feature.properties,geojson:feature};results.push(result)}}callback(error,results)},this))},_buildQuery:function(text){var queryString=[];for(var i=this.options.searchFields.length-1;i>=0;i--){var field='upper("'+this.options.searchFields[i]+'")';queryString.push(field+" LIKE upper('%"+text+"%')")}return queryString.join(" OR ")},_featureBounds:function(feature){var geojson=L.geoJson(feature);if(feature.geometry.type==="Point"){var center=geojson.getBounds().getCenter();var lngRadius=this.options.bufferRadius/40075017*360/Math.cos(180/Math.PI*center.lat);var latRadius=this.options.bufferRadius/40075017*360;return L.latLngBounds([center.lat-latRadius,center.lng-lngRadius],[center.lat+latRadius,center.lng+lngRadius])}else{return geojson.getBounds()}}});function featureLayerProvider(options){return new exports.FeatureLayerProvider(options)}exports.MapServiceProvider=esri_leaflet.MapService.extend({options:{layers:[0],label:"Map Service",bufferRadius:1e3,maxResults:5,formatSuggestion:function(feature){return feature.properties[feature.displayFieldName]+" <small>"+feature.layerName+"</small>"}},initialize:function(options){esri_leaflet.MapService.prototype.initialize.call(this,options);this._getIdFields()},suggestions:function(text,bounds,callback){var request=this.find().text(text).fields(this.options.searchFields).returnGeometry(false).layers(this.options.layers);return request.run(function(error,results,raw){var suggestions=[];if(!error){var count=Math.min(this.options.maxResults,results.features.length);raw.results=raw.results.reverse();for(var i=0;i<count;i++){var feature=results.features[i];var result=raw.results[i];var layer=result.layerId;var idField=this._idFields[layer];feature.layerId=layer;feature.layerName=this._layerNames[layer];feature.displayFieldName=this._displayFields[layer];if(idField){suggestions.push({text:this.options.formatSuggestion.call(this,feature),magicKey:result.attributes[idField]+":"+layer})}}}callback(error,suggestions.reverse())},this)},results:function(text,key,bounds,callback){var results=[];var request;if(key){var featureId=key.split(":")[0];var layer=key.split(":")[1];request=this.query().layer(layer).featureIds(featureId)}else{request=this.find().text(text).fields(this.options.searchFields).contains(false).layers(this.options.layers)}return request.run(function(error,features,response){if(!error){if(response.results){response.results=response.results.reverse()}for(var i=0;i<features.features.length;i++){var feature=features.features[i];layer=layer||response.results[i].layerId;if(feature&&layer!==undefined){var bounds=this._featureBounds(feature);feature.layerId=layer;feature.layerName=this._layerNames[layer];feature.displayFieldName=this._displayFields[layer];var result={latlng:bounds.getCenter(),bounds:bounds,text:this.options.formatSuggestion.call(this,feature),properties:feature.properties,geojson:feature};results.push(result)}}}callback(error,results.reverse())},this)},_featureBounds:function(feature){var geojson=L.geoJson(feature);if(feature.geometry.type==="Point"){var center=geojson.getBounds().getCenter();var lngRadius=this.options.bufferRadius/40075017*360/Math.cos(180/Math.PI*center.lat);var latRadius=this.options.bufferRadius/40075017*360;return L.latLngBounds([center.lat-latRadius,center.lng-lngRadius],[center.lat+latRadius,center.lng+lngRadius])}else{return geojson.getBounds()}},_layerMetadataCallback:function(layerid){return L.Util.bind(function(error,metadata){if(error){return}this._displayFields[layerid]=metadata.displayField;this._layerNames[layerid]=metadata.name;for(var i=0;i<metadata.fields.length;i++){var field=metadata.fields[i];if(field.type==="esriFieldTypeOID"){this._idFields[layerid]=field.name;break}}},this)},_getIdFields:function(){this._idFields={};this._displayFields={};this._layerNames={};for(var i=0;i<this.options.layers.length;i++){var layer=this.options.layers[i];this.get(layer,{},this._layerMetadataCallback(layer))}}});function mapServiceProvider(options){return new exports.MapServiceProvider(options)}exports.GeocodeServiceProvider=exports.GeocodeService.extend({options:{label:"Geocode Server",maxResults:5},suggestions:function(text,bounds,callback){if(this.options.supportsSuggest){var request=this.suggest().text(text);if(bounds){request.within(bounds)}return request.run(function(error,results,response){var suggestions=[];if(!error){while(response.suggestions.length&&suggestions.length<=this.options.maxResults-1){var suggestion=response.suggestions.shift();if(!suggestion.isCollection){suggestions.push({text:suggestion.text,magicKey:suggestion.magicKey})}}}callback(error,suggestions)},this)}else{callback(undefined,[]);return false}},results:function(text,key,bounds,callback){var request=this.geocode().text(text);request.maxLocations(this.options.maxResults);if(bounds){request.within(bounds)}return request.run(function(error,response){callback(error,response.results)},this)}});function geocodeServiceProvider(options){return new exports.GeocodeServiceProvider(options)}exports.VERSION="2.0.3";exports.WorldGeocodingServiceUrl=(window.location.protocol==="https:"?"https:":"http:")+"//geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/";exports.geocode=geocode;exports.reverseGeocode=reverseGeocode;exports.suggest=suggest;exports.geocodeService=geocodeService;exports.geosearch=geosearch;exports.arcgisOnlineProvider=arcgisOnlineProvider;exports.featureLayerProvider=featureLayerProvider;exports.mapServiceProvider=mapServiceProvider;exports.geocodeServiceProvider=geocodeServiceProvider}); | ||
//# sourceMappingURL=./esri-leaflet-geocoder.js.map |
{ | ||
"name": "esri-leaflet-geocoder", | ||
"description": "Esri Geocoding utilities and search plguin for Leaflet.", | ||
"version": "2.0.2", | ||
"version": "2.0.3", | ||
"author": "Patrick Arlt <parlt@esri.com> (http://patrickarlt.com)", | ||
@@ -27,3 +27,3 @@ "browserify": { | ||
"esri-leaflet": "^2.0.0-beta.4", | ||
"leaflet": "^1.0.0-beta.1" | ||
"leaflet": "^1.0.0-beta.2" | ||
}, | ||
@@ -30,0 +30,0 @@ "devDependencies": { |
342
README.md
@@ -5,3 +5,3 @@ # Esri Leaflet Geocoder | ||
 | ||
[](https://travis-ci.org/Esri/esri-leaflet-geocoder) | ||
@@ -20,9 +20,9 @@ ## Example | ||
<!-- Load Leaflet from CDN--> | ||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-1.0.0-b1/leaflet.css" /> | ||
<script src="http://cdn.leafletjs.com/leaflet-1.0.0-b1/leaflet.js"></script> | ||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v1.0.0-beta.2/leaflet.css" /> | ||
<script src="http://cdn.leafletjs.com/leaflet/v1.0.0-beta.2/leaflet.js"></script> | ||
<!-- Esri Leaflet --> | ||
<script src="//cdn.jsdelivr.net/leaflet.esri/2.0.0-beta.6/esri-leaflet.js"></script> | ||
<script src="//cdn.jsdelivr.net/leaflet.esri/2.0.0-beta.7/esri-leaflet.js"></script> | ||
<!-- Esri Leaflet Geocoder --> | ||
<link rel="stylesheet" href="//cdn.jsdelivr.net/leaflet.esri.geocoder/2.0.0/esri-leaflet-geocoder.css"> | ||
<script src="//cdn.jsdelivr.net/leaflet.esri.geocoder/2.0.0/esri-leaflet-geocoder.js"></script> | ||
<link rel="stylesheet" href="//cdn.jsdelivr.net/leaflet.esri.geocoder/2.0.2/esri-leaflet-geocoder.css"> | ||
<script src="//cdn.jsdelivr.net/leaflet.esri.geocoder/2.0.2/esri-leaflet-geocoder.js"></script> | ||
<!-- Make the map fill the entire page --> | ||
@@ -69,327 +69,25 @@ <style> | ||
## L.esri.Geocoding.geosearch | ||
# API Reference | ||
### Constructor | ||
## Controls | ||
**Extends** [`L.Control`](http://leafletjs.com/reference.html#control) | ||
### [`L.esri.Geocoding.geosearch`](http://esri.github.io/esri-leaflet/api-reference/controls/geosearch.html) | ||
a control for auto-complete enabled search | ||
Constructor | Options | Description | ||
--- | --- | --- | ||
`L.esri.Geocoding.geosearch(options)` | [`<GeosearchOptions>`](#options) | Creates a new Geosearch control. | ||
## Services | ||
### Options | ||
Option | Type | Default | Description | ||
--- | --- | --- | --- | ||
`position` | `String` | `topleft` | One of the valid Leaflet [control positions](http://leafletjs.com/reference.html#control-positions). | ||
`zoomToResult` | `Boolean` | `true` | If `true` the map will zoom the result after geocoding is complete. | ||
`useMapBounds` | `Boolean` or <br> `Integer` | `12` | Determines if and when the geocoder should begin using the bounds of the map to enchance search results. If `true` the geocoder will always return results in the current map bounds. If `false` it will always search the world. If an integer like `11` is passed in the geocoder will use the bounds of the map for searching if the map is at a zoom level equal to or greater than the integer. This mean the geocoder will prefer local results when the map is zoomed in. | ||
`collapseAfterResult` | `Boolean` | `true` | If the geocoder is expanded after a result this will collapse it. | ||
`expanded` | `Boolean` | `false` | Start the control in an expanded state. | ||
`allowMultipleResults` | `Boolean` | `true` | If set to `true` and the user submits the form without a suggestion selected geocodes the current text in the input and zooms the user to view all the results. | ||
`providers` | `Array` | See Description | An array of [providers](#providers) to search. | ||
`placeholder` | `String` | `'Search for places or addresses'` | Placeholder text for the search input. | ||
`title` | `String` | `Location Search` | Title text for the search input. Shows as tool tip on hover. | ||
### Methods | ||
Method | Options | Description | ||
--- | --- | --- | ||
`clear()` | `null` | Clears the text currently in the geocoder and collapses it if `collapseAfterResult` is true. | ||
### Events | ||
Event | Data | Description | ||
--- | --- | --- | ||
`load` | `null` | A generic event fired when a request to the geocoder starts. | ||
`loading` | `null` | A generic event fired when a request to the geocoder finished. | ||
`results` | [`<ResultsEvent>`](#results-event) | Fired when a result is returned from the geocoder. | ||
Events from each [provider](#providers) and will match the events fired by [L.esri.service events](http://esri.github.io/esri-leaflet/api-reference/services/service.html). | ||
### Styling | ||
For reference here is the internal structure of the geocoder... | ||
```html | ||
<div class="geocoder-control leaflet-control"> | ||
<input class="geocoder-control-input leaflet-bar"> | ||
<ul class="geocoder-control-suggestions leaflet-bar"> | ||
<li class="geocoder-control-suggestion geocoder-control-selected">The Selected Result</li> | ||
<li class="geocoder-control-suggestion">Another Result</li> | ||
</ul> | ||
</div> | ||
``` | ||
### Providers | ||
The `Geosearch` control can also search for results from a variety of sources including Feature Layers and Map Services. This is done with plain text matching and is not "real" geocoding, but it allows you to mix in custom search results. | ||
```js | ||
var arcgisOnline = L.esri.Geocoding.arcgisOnlineProvider(); | ||
var gisDay = L.esri.Geocoding.featureLayerProvider({ | ||
url: 'https://services.arcgis.com/uCXeTVveQzP4IIcx/arcgis/rest/services/GIS_Day_Final/FeatureServer/0', | ||
searchFields: ['Name', 'Organization'], // Search these fields for text matches | ||
label: 'GIS Day Events', // Group suggestions under this header | ||
formatSuggestion: function(feature){ | ||
return feature.properties.Name + ' - ' + feature.properties.Organization; // format suggestions like this. | ||
} | ||
}); | ||
L.esri.Geocoding.geosearch({ | ||
providers: [arcgisOnline, gisDay] // will geocode via ArcGIS Online and search the GIS Day feature service. | ||
}).addTo(map); | ||
``` | ||
#### Available Providers | ||
* `L.esri.Geocoding.arcgisOnlineProvider(options)` - Uses the ArcGIS Online World Geocoding service. | ||
* `L.esri.Geocoding.featureLayerProvider(options)` - Gets results by querying the Feature Layer for text matches. | ||
* `L.esri.Geocoding.mapServiceProvider(options)` - Uses the find and query methods on the Map Service to get text matches. | ||
* `L.esri.Geocoding.geocodeServiceProvider` - Use an ArcGIS Server Geocode Service, supports suggestions if available with ARcGIS Server 10.3 and up. | ||
#### Providers | ||
All providers share the following options: | ||
Option | Type | Default | Description | ||
--- | --- | --- | --- | ||
`label` | `String` | Varies by Provider | Text that will be used to group suggestions under when more than one provider is being used. | ||
`maxResults` | `Integer` | 5 | Maximum number of results to show for this provider. | ||
`attribution` | `String` | Varies by Provider | Adds an attribution to the map. | ||
##### `arcgisOnlineProvider` | ||
Option | Type | Default | Description | ||
--- | --- | --- | --- | ||
`countries` | `String` `Array[Strings]` | null | Limit results to one or more countries. Any ISO 3166 2 or 3 digit [country code supported by the ArcGIS World Geocode service](https://developers.arcgis.com/rest/geocode/api-reference/geocode-coverage.htm) is allowed. *Note* using an array of country codes may result in inaccurate results even when a specific suggestion is supplied. | ||
`categories` | `String` `Array[Strings]` | null | Limit results to one or more categories. See the [list of valid categories](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-category-filtering.htm#ESRI_SECTION1_502B3FE2028145D7B189C25B1A00E17B) for possible values. | ||
`forStorage` | `Boolean` | false | Indicates whether results will be stored permanently (more information can be found [here](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-free-vs-paid.htm). | ||
Results from the `arcgisOnlineProvider` will have an additional `properties` key which will correspond with [all available fields on the ArcGIS Online World Geocode service](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-service-output.htm#ESRI_SECTION1_42D7D3D0231241E9B656C01438209440) | ||
##### `geocodeServiceProvider` | ||
Option | Type | Default | Description | ||
--- | --- | --- | --- | ||
`url` | `String` | *Required* | The URL for the service that will be searched. | ||
`label` | `String` | `'Geocode Service'` | Text that will be used to group suggestions under when more than one provider is being used. | ||
`maxResults` | `Integer` | 5 | Maximum number of results to show for this provider. | ||
Results from the `geocodeServiceProvider` will have an additional `properties` key which will correspond with all the available fields in the service. | ||
##### `featureLayerProvider` | ||
Option | Type | Default | Description | ||
--- | --- | --- | --- | ||
`url` | `String` | *Required* | The URL for the service that will be searched. | ||
`searchFields` | `String` `Array[Strings]` | None | An array of fields to search for text. | ||
`formatSuggestion`| `Function` | See Description | Formatting function for the suggestion text. Receives feature information and returns a string. | ||
`bufferRadius`, | `Integer` | If a service or layer contains points, buffer points by this radius to create bounds. | ||
Results from the `featureLayerProvider` will have an additional `properties` key which will contain all the information for the feature and a `geojson` key that will contain a [GeoJSON](http://geojson.org/) representation of the feature. | ||
##### `mapServiceProvider` | ||
Option | Type | Default | Description | ||
--- | --- | --- | --- | ||
`url` | `String` | *Required* | The URL for the service that will be searched. | ||
`searchFields` | `String` `Array[Strings]` | None | An array of fields to search for text. | ||
`layer` | `Integer` | `0` | The layer to find text matches on. Can also be an array of layer identifiers. | ||
`formatSuggestion`| `Function` | See Description | Formatting function for the suggestion text. Receives feature information and returns a string. | ||
`bufferRadius`, | `Integer` `Array[Integers]`| Buffer point results by this radius to create bounds. | ||
Results from the `mapServiceProvider` will have an additional `properties` key which will contain all the information for the feature and a `geojson` key that will contain a [GeoJSON](http://geojson.org/) representation of the feature. | ||
#### Results Event | ||
Property | Type | Description | ||
--- | --- | --- | ||
`bounds` | [`L.LatLngBounds`](http://leafletjs.com/reference.html#latlngbounds)| The bounds around this suggestion. Good for zooming to results like cities and states. | ||
`latlng` | [`L.LatLng`](http://leafletjs.com/reference.html#latlng)| The center of the results. | ||
`results` | [`[<ResultObject>]`](#result-object) | An array of [result objects](#result-object). | ||
#### Result Object | ||
A single result from a provider. You should not rely on all these properties being present in every result object and some providers may add additional properties. | ||
Property | Type | Description | ||
--- | --- | --- | ||
`text` | `String` | The text that was passed to the provider. | ||
`bounds` | [`L.LatLngBounds`](http://leafletjs.com/reference.html#latlngbounds)| The bounds around this result. Good for zooming to results like cities and states. | ||
`latlng` | [`L.LatLng`](http://leafletjs.com/reference.html#latlng)| The center of the result. | ||
The result object will also contain any additional properties from the provider. See the [available providers](#available-providers) for which additional fields may be present. | ||
## L.esri.Geocoding.geocodeService | ||
### [`L.esri.Geocoding.geocodeService`](http://esri.github.io/esri-leaflet/api-reference/services/geocode-service.html) | ||
A basic wrapper for ArcGIS Online geocoding services. Used internally by `L.esri.Geocoding.geosearch`. | ||
### Constructor | ||
## Tasks | ||
Constructor | Description | ||
--- | --- | ||
`L.esri.Geocoding.geocodeService(options)` | Creates a new Geocoding service. You can pass the `url` in the options to reference a custom geocoding endpoint if you do not want to use the ArcGIS Online World Geocoding service. | ||
### [`L.esri.Geocoding.geocode`](http://esri.github.io/esri-leaflet/api-reference/tasks/geocode.html) | ||
An abstraction for submitting requests to turn addresses into locations. | ||
### Options | ||
### [`L.esri.Geocoding.suggest`](http://esri.github.io/esri-leaflet/api-reference/tasks/suggest.html) | ||
An abstraction for submitting requests for geocoding suggestions. | ||
You can pass any options you can pass to L.esri.Services.Service. `url` will be the ArcGIS World Geocoder by default but a custom geocoding service can also be used. | ||
### [`L.esri.Geocoding.reverseGeocode`](http://esri.github.io/esri-leaflet/api-reference/tasks/reverse-geocode.html) | ||
An abstraction for submitting requests for address candidates associated with a particular location. | ||
### Methods | ||
Method | Returns | Description | ||
--- | --- | --- | ||
`geocode()` | L.esri.Geocoding.geocode | Returns a new Geocode task bound to this server. | ||
`suggest()` | L.esri.Geocoding.suggest | Returns a new Suggest task bound to this server. | ||
`reverse()` | L.esri.Geocoding.reverseGeocode | Returns a new ReverseGeocode task bound to this server. | ||
### Events | ||
L.esri.Geocoding.geocodeService fires all [L.esri.service events](http://esri.github.io/esri-leaflet/api-reference/services/service.html). | ||
## L.esri.Geocoding.geocode | ||
### Constructor | ||
Constructor | Description | ||
--- | --- | ||
`L.esri.Geocoding.geocode(options)` | Creates a new Geocode task. | ||
### Options | ||
You can pass any options you can pass to L.esri.Tasks.Task. `url` will be the [ArcGIS World Geocoder](https://developers.arcgis.com/rest/geocode/api-reference/overview-world-geocoding-service.htm) by default but a custom geocoding service can also be used. | ||
### Methods | ||
Method | Returns | Description | ||
--- | --- | --- | ||
`text(text <String>)` | `this` | The text to geocode. If you specify `text` all other params like `address`, `city`, `subregion`, and `region`, `postal`, and `country` will be ignored. | ||
`address(text <String>)` | Specify the street and house number to be geocoded. | ||
`neighborhood(text <String>)` | Specify the neighborhood to be geocoded. | ||
`city(text <String>)` | Specify the city to be geocoded. | ||
`subregion(text <String>)` | Specify the subregion to be geocoded. Depending on the country, subregion can represent a county, state, or province. | ||
`region(text <String>)` | Specify the region to be geocoded. Typically a state or province | ||
`postal(text <String>)` | Specify the postal code to be geocoded. | ||
`country(text <String>)` | Specify the country to be geocoded. | ||
`category(category <String>)` | The category to search for suggestions. By default no category. A list of categories can be found [here](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-category-filtering.htm#ESRI_SECTION1_502B3FE2028145D7B189C25B1A00E17B) | ||
`within(bounds <L.LatLngBounds>)` | A bounding box to search for suggestions in. | ||
`nearby(latlng <L.LatLng>, distance <Integer>)` | Searches for suggestions only inside an area around the LatLng. `distance` is in meters. | ||
`run(callback <Function>, context <Object>)` | `XMLHttpRequest` | Executes this request chain and accepts the response callback. | ||
### Examples | ||
```js | ||
L.esri.Geocoding.geocode().text('380 New York St, Redlands, California, 92373').run(function(err, results, response){ | ||
console.log(results); | ||
}); | ||
``` | ||
```js | ||
L.esri.Geocoding.geocode().address('380 New York St').city('Redlands').region('California').postal(92373).run(function(err, results, response){ | ||
console.log(results); | ||
}); | ||
``` | ||
```js | ||
//Using .within() | ||
var southWest = L.latLng(37.712, -108.227), | ||
northEast = L.latLng(41.774, -102.125), | ||
bounds = L.latLngBounds(southWest, northEast); // Colorado | ||
L.esri.Geocoding.geocode().text("Denver").within(bounds).run(function(err, response){ | ||
console.log(response); | ||
}); | ||
``` | ||
```js | ||
//Using .nearby() | ||
var denver = L.latLng(37.712, -108.227); | ||
L.esri.Geocoding.geocode().text("Highlands Ranch").nearby(denver, 20000).run(function(err, response){ | ||
console.log(response); | ||
}); | ||
``` | ||
### Results Object | ||
In the above examples the `results` object will look like this. | ||
```js | ||
{ | ||
results: [ | ||
{ | ||
latlng: L.LatLng, | ||
text: 'Formatted Address', | ||
score: 100, // ranking of the certainty of the match | ||
properties: { | ||
// additional info like specific address components like Country Code ect... | ||
} | ||
} | ||
] | ||
} | ||
``` | ||
## L.esri.Geocoding.suggest | ||
### Constructor | ||
Constructor | Description | ||
--- | --- | ||
`L.esri.Geocoding.suggest(options)` | Creates a new Suggest task using the ArcGIS World Geocoder. | ||
### Options | ||
You can pass any options you can pass to L.esri.Tasks.Task. `url` will be the [ArcGIS World Geocoder](https://developers.arcgis.com/rest/geocode/api-reference/overview-world-geocoding-service.htm) by default but a custom geocoding service can also be used. | ||
### Methods | ||
Method | Returns | Description | ||
--- | --- | --- | ||
`text(text <String>)` | `this` | The text to receive suggestions for. | ||
`category(category Array[Strings])` | The category to search for suggestions. By default no category. A list of categories can be found [here](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-category-filtering.htm#ESRI_SECTION1_502B3FE2028145D7B189C25B1A00E17B) | ||
`countries(category Array[Strings])` | Limit results to one or more countries. Any ISO 3166 2 or 3 digit [country code](https://developers.arcgis.com/rest/geocode/api-reference/geocode-coverage.htm) supported by the ArcGIS World Geocode service is allowed. *Note* using an array of country codes may result in inaccurate results even when a specific suggestion is supplied. | ||
`within(bounds <L.LatLngBounds>)` | A bounding box to search for suggestions in. | ||
`nearby(latlng <L.LatLng>, distance <Integer>)` | Improves the rank of suggestions near a known location. The unit of measure for `distance` is meters. | ||
`run(callback <Function>, context<Object>)` | `XMLHttpRequest` | Executes this request chain and accepts the response callback. | ||
### Example | ||
```js | ||
L.esri.Geocoding.suggest().text('trea').nearby([45,-121], 5000).run(function(error, response){ | ||
// response matches the suggest API response https://developers.arcgis.com/rest/geocode/api-reference/geocoding-suggest.htm#ESRI_SECTION1_FC3884A45AD24E62BD11C9888F1392DB | ||
}); | ||
``` | ||
## L.esri.Geocoding.reverseGeocode | ||
### Constructor | ||
Constructor | Description | ||
--- | --- | ||
`L.esri.Geocoding.reverseGeocode(options)` | Creates a new ReverseGeocode task. `L.esri.Geocoding.WorldGeocodingService` can be used as a reference to the [ArcGIS World Geocoder](https://developers.arcgis.com/rest/geocode/api-reference/overview-world-geocoding-service.htm). | ||
### Options | ||
You can pass any options you can pass to L.esri.Tasks.Task. `url` will be the ArcGIS World Geocoder by default but a custom geocoding service can also be used. | ||
### Methods | ||
Method | Returns | Description | ||
--- | --- | --- | ||
`latlng(latlng <L.LatLng>)` | The L.LatLng object for which the address will be looked up. | ||
`distance(distance <Integer>)` | The distance (in meters) around the point for which addresses will be looked up. | ||
`language(langCode <String>)` | `this` | The language to return the address in. More information can be found [here](https://developers.arcgis.com/rest/geocode/api-reference/geocoding-reverse-geocode.htm#ESRI_SECTION1_ABD1AD449DF54FFEB9527A606341714C). | ||
`intersection(returnIntersection <Boolean>)` | `this` | Set this value to `true` if you'd like the nearest intersection to be returned (Default value is `false`). | ||
`run(callback <Function>, context <Object>)` | `XMLHttpRequest` | Executes this request chain and accepts the response callback. | ||
### Example | ||
```js | ||
L.esri.Geocoding.reverseGeocode().intersection(true).latlng([48.8583, 2.2945]).run(function(error, result, response){ | ||
// callback is called with error, result, and response. | ||
// result.latlng contains the latlng of the located address | ||
// result.address contains the address information | ||
}); | ||
``` | ||
## Development Instructions | ||
@@ -400,3 +98,3 @@ | ||
5. Install the dependencies with `npm install` | ||
5. The example at `/index.html` should work | ||
5. The example at `/index.html` *should* 'just work' | ||
6. Make your changes and create a [pull request](https://help.github.com/articles/creating-a-pull-request) | ||
@@ -403,0 +101,0 @@ |
@@ -22,2 +22,20 @@ | ||
beforeEach(function(){ | ||
this.xhr = sinon.useFakeXMLHttpRequest(); | ||
var requests = this.requests = []; | ||
this.xhr.onCreate = function (xhr) { | ||
requests.push(xhr); | ||
}; | ||
}); | ||
afterEach(function(){ | ||
this.xhr.restore(); | ||
}); | ||
var southWest = L.latLng(29.30, -99.71); | ||
var northEast = L.latLng(31.34, -95.57); | ||
var mapbounds = L.latLngBounds(southWest, northEast); | ||
it('shouldnt overwrite custom options set in the constructor', function() { | ||
@@ -34,3 +52,4 @@ var geosearch = L.esri.Geocoding.geosearch({ | ||
placeholder: 'something clever', | ||
title: 'something not so clever' | ||
title: 'something not so clever', | ||
searchBounds: mapbounds | ||
}); | ||
@@ -45,2 +64,3 @@ | ||
expect(geosearch.options.title).to.equal('something not so clever'); | ||
expect(geosearch.options.searchBounds).to.equal(mapbounds); | ||
}); | ||
@@ -59,2 +79,21 @@ | ||
it('should correctly build the searchExtent for the provider', function (done) { | ||
var geosearch = L.esri.Geocoding.geosearch({ | ||
providers: [ | ||
L.esri.Geocoding.arcgisOnlineProvider() | ||
], | ||
searchBounds:mapbounds | ||
}).addTo(map); | ||
geosearch._suggest("Mayoworth, WY"); | ||
var request = geosearch._pendingSuggestions[0]; | ||
expect(request).to.be.an.instanceof(XMLHttpRequest); | ||
this.requests[0].respond(200, { "Content-Type": "application/json" }, | ||
JSON.stringify({"suggestions":[]})); | ||
expect(geosearch._pendingSuggestions[0].url).to.equal('http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/suggest?text=Mayoworth%2C%20WY&location=-97.64%2C30.32&distance=50000&searchExtent=%7B%22xmin%22%3A-101.78%2C%22ymin%22%3A28.28%2C%22xmax%22%3A-93.5%2C%22ymax%22%3A32.36%2C%22spatialReference%22%3A%7B%22wkid%22%3A4326%7D%7D&f=json'); | ||
done(); | ||
}); | ||
}); |
@@ -9,2 +9,3 @@ import L from 'leaflet'; | ||
zoomToResult: true, | ||
searchBounds: null, | ||
useMapBounds: 12, | ||
@@ -150,2 +151,6 @@ collapseAfterResult: true, | ||
_searchBounds: function () { | ||
if (this.options.searchBounds !== null) { | ||
return this.options.searchBounds; | ||
} | ||
if (this.options.useMapBounds === false) { | ||
@@ -152,0 +157,0 @@ return null; |
@@ -1,2 +0,2 @@ | ||
export var VERSION = '2.0.2'; | ||
export var VERSION = '2.0.3'; | ||
export var WorldGeocodingServiceUrl = (window.location.protocol === 'https:' ? 'https:' : 'http:') + '//geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/'; | ||
@@ -3,0 +3,0 @@ |
Sorry, the diff of this file is not supported yet
2268
398685
143
Updatedleaflet@^1.0.0-beta.2