Leaflet + Mapzen Search geocoding plugin
A plugin that adds the ability to search (geocode) a Leaflet-powered map using Mapzen Search or your own hosted version of the Pelias Geocoder API.
Demo
See it in action!
Requirements
Requires the Leaflet mapping library. Supports Leaflet v0.7.3 (and higher) and v1.0.0. (Previous Leaflet versions may work, but are not actively tested or supported.)
Browser support is IE8+ (more details below).
To use the Mapzen Search service, you need a Mapzen API key.
Get one from the Mapzen developers portal. It's free!
Basic usage
Step 1: In HTML, import the required Leaflet JavaScript and CSS files. Start quickly with hosted libraries on cdnjs!
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet-geocoder-mapzen/1.9.4/leaflet-geocoder-mapzen.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-geocoder-mapzen/1.9.4/leaflet-geocoder-mapzen.js"></script>
Step 2: In JavaScript, initialize your Leaflet map.
var map = L.map('map').setView([40.7259, -73.9805], 12);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
Step 3: In JavaScript, add your geocoder with your Mapzen API key.
L.control.geocoder('<your-api-key>').addTo(map);
Step 4: Rejoice!
There is also a tutorial
It has much more detailed walkthrough instructions and is very friendly for beginners. No coding experience is necessary! Check it out here.
Want this as a module?
Experienced developers can install with npm:
npm install leaflet-geocoder-mapzen
And then import it in your module system. For instance, with Browserify:
var L = require('leaflet');
require('leaflet-geocoder-mapzen');
var MyGeocoderPlugin = require('leaflet-geocoder-mapzen');
This plugin implements the Universal Module Definition so you can also use it in AMD and CommonJS environments.
ES2015 (ECMAScript 6)
To import this plugin in ES2015 environments, the import
syntax is supported:
import L from 'leaflet';
import 'leaflet-geocoder-mapzen';
import MyGeocoderPlugin from 'leaflet-geocoder-mapzen';
Customizing the plugin
You can optionally specify additional settings to the plugin by passing in an object as a second argument to the geocoder()
method, like so:
var options = {
bounds: true,
position: 'topright',
expanded: true
};
L.control.geocoder('<your-api-key>', options).addTo(map);
Here are a list all the settings and their default values.
Query behavior
Some options affect the Mapzen Search / Pelias query itself.
option | description | default value |
---|
url | String. Host endpoint for a Pelias-compatible search API. | 'https://search.mapzen.com/v1' |
bounds | Leaflet LatLngBounds object or Boolean. If true , search is bounded by the current map view. You may also provide a custom bounding box in form of a LatLngBounds object. Note: bounds is not supported by autocomplete. | false |
focus | Leaflet LatLng object or Boolean. If true , search and autocomplete prioritizes results near the center of the current view. You may also provide a custom LatLng value (in any of the accepted Leaflet formats) to act as the center bias. | true |
latlng | Deprecated. Please use focus instead. | |
layers | String or Array. Filters results by layers (documentation). If left blank, results will come from all available layers. | null |
params | Object. An object of key-value pairs which will be serialized into query parameters that will be passed to the API. This allows custom queries that are not already supported by the convenience options listed above. For a full list of supported parameters, please read the Mapzen Search documentation. IMPORTANT: some parameters only work with the /search endpoint, and do not apply to /autocomplete requests! All supplied parameters are passed through; this library doesn't know which are valid parameters and which are not. In the event that other options conflict with parameters passed passed through params , the params option takes precedence. | null |
Examples
L.control.geocoder('<your-api-key>', {
focus: [50.5, 30.5],
placeholder: 'Search nearby [50.5, 30.5]'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
focus: true,
placeholder: 'Search nearby'
}).addTo(map);
var southWest = L.latLng(40.712, -74.227);
var northEast = L.latLng(40.774, -74.125);
var bounds = L.latLngBounds(southWest, northEast);
L.control.geocoder('<your-api-key>', {
bounds: bounds,
placeholder: 'Search within ' + bounds.toBBoxString()
}).addTo(map);
L.control.geocoder('<your-api-key>', {
bounds: true,
placeholder: 'Search within the bounds'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
layers: 'coarse',
placeholder: 'Coarse geocoder'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
layers: 'address',
placeholder: 'Address geocoder'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
layers: 'venue',
placeholder: 'Venues geocoder'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
layers: ['venue', 'address'],
placeholder: 'Street geocoder'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
params: {
sources: 'whosonfirst',
'boundary.country': 'AUS'
},
placeholder: 'Results via Who’s on First in Australia'
}).addTo(map);
Interaction behavior
These options affect the plugin's appearance and interaction behavior.
option | description | default value |
---|
position | String. Corner in which to place the geocoder control. Values correspond to Leaflet control positions. | 'topleft' |
attribution | String. Attribution text that will be appended to Leaflet’s attribution control. Set to a blank string or null to disable adding the plugin’s default attribution. | 'Geocoding by <a href="https://mapzen.com/projects/search/">Mapzen</a>' |
textStrings | Object. An object of string values that replace text strings in the geocoder control, so you can provide your own custom messages or localization. | See “Custom text strings” section below. |
placeholder | String. Placeholder text to display in the search input box. This is an alias for textStrings.INPUT_PLACEHOLDER . Set to a blank string or null to disable. | 'Search' |
title | Deprecated. Please use `textStrings.INPUT_TITLE_ATTRIBUTE instead. | |
panToPoint | Boolean. If true , highlighting a search result pans the map to that location. | true |
pointIcon | Boolean or String. If true , an icon is used to indicate a point result, matching the "venue" or "address" layer types. If false , no icon is displayed. For custom icons, pass a string containing a path to the image. | true |
polygonIcon | Boolean or String. If true , an icon is used to indicate a polygonal result, matching any non-"venue" or non-"address" layer type. If false , no icon is displayed. For custom icons, pass a string containing a path to the image. | true |
markers | Leaflet Marker options object or Boolean. If true , search results drops Leaflet's default blue markers onto the map. You may customize this marker's appearance and behavior using Leaflet marker options. | true |
overrideBbox | Boolean. Some search results will zoom to a bounding box if it is available, instead of dropping a point marker. If true , selecting a result will always drop a point marker regardless of whether bounding box data is present. | false |
fullWidth | Integer or Boolean. If true , the input box will expand to take up the full width of the map container. If an integer breakpoint is provided, the full width applies only if the map container width is below this breakpoint. | 650 |
expanded | Boolean. If true , the search input is always expanded. It does not collapse into a button-only state. | false |
autocomplete | Boolean. If true , suggested results are fetched on each keystroke. If false , this is disabled and users must obtain results by pressing the Enter key after typing in their query. | true |
place | Boolean. If true , selected results will make a request to the service /place endpoint. If false , this is disabled. The geocoder does not handle responses to /place , you will need to do handle it yourself in the results event listener (see below). | false |
Examples
L.control.geocoder('<your-api-key>', {
position: 'topright'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
pointIcon: 'http://www.somewhereontheweb.com/download/img/point.png',
polygonIcon: 'https://cloud.com/polygon-icon.svg'
}).addTo(map);
L.control.geocoder('<your-api-key>', {
pointIcon: false,
polygonIcon: false
}).addTo(map);
L.control.geocoder('<your-api-key>', {
panToPoint: false
}).addTo(map);
L.control.geocoder('<your-api-key>', {
fullWidth: true
}).addTo(map);
L.control.geocoder('<your-api-key>', {
markers: false
}).addTo(map);
L.control.geocoder('<your-api-key>', {
expanded: true
}).addTo(map);
L.control.geocoder('<your-api-key>', {
attribution: null
}).addTo(map);
Custom text strings
These are the text strings that are used by the geocoder control. You can override these strings by passing in a textStrings
options object containing the names of the string(s) you want to customize. You can use this method to localize the controls for a different language, for instance.
UI text
string name | default value |
---|
INPUT_PLACEHOLDER | 'Search' |
INPUT_TITLE_ATTRIBUTE | 'Search' |
RESET_TITLE_ATTRIBUTE | 'Reset' |
NO_RESULTS | 'No results were found.' |
HTTP status code errors
Learn more about possible error messages in Mapzen Search documentation. ERROR_DEFAULT
is a catch-all error that displays when a request returns an error with an unexpected HTTP status code (or none at all) — one example where this can happen is when a browser is prevented from making a request due to a security concern, such as the lack of CORS headers on the search endpoint.
string name | default value |
---|
ERROR_403 | 'A valid API key is needed for this search feature.' |
ERROR_404 | 'The search service cannot be found. :-(' |
ERROR_408 | 'The search service took too long to respond. Try again in a second.' |
ERROR_429 | 'There were too many requests. Try again in a second.' |
ERROR_500 | 'The search service is not working right now. Please try again later.' |
ERROR_502 | 'Connection lost. Please try again later.' |
ERROR_DEFAULT | 'The search service is having problems :-(' |
Examples
L.control.geocoder('<your-api-key>', {
textStrings: {
INPUT_PLACEHOLDER: '도시, 지명 등을 검색해보세요.',
INPUT_TITLE_ATTRIBUTE: '도시, 지명 등을 검색해보세요.',
RESET_TITLE_ATTRIBUTE: '다시 검색하기',
NO_RESULTS: '해당 결과가 없습니다.',
ERROR_403: '해당 서비스를 사용하기 위해서는 API KEY가 필요합니다.',
ERROR_404: '검색 서비스를 찾을 수 없습니다. :-(',
ERROR_408: '검색에 예상보다 긴 시간이 소요되고 있습니다. 조금 있다가 다시 시도해보는 건 어떨까요?',
ERROR_429: '지나치게 많은 리퀘스트가 발생했습니다. 조금 있다가 다시 시도해보는 건 어떨까요?',
ERROR_500: '검색 서비스가 현재 작동하지 않고있습니다. 조금 있다가 다시 시도해보는 건 어떨까요?',
ERROR_502: '네트워크 상태가 불안정합니다. 조금 있다가 다시 시도해보는 건 어떨까요?',
ERROR_DEFAULT: '검색 서비스에 문제가 있는 것으로 보입니다. :-('
}
}).addTo(map);
See this in action!
Advanced usage
Examples with running code can be found in the examples directory.
Alternate syntax
You can instantiate a geocoder with the new
keyword. Notice that the class names are capitalized. This is what actually happens under the hood of L.control.geocoder()
, so this syntax does not do anything different, but you may prefer it for clarity or stylistic reasons.
new L.Control.Geocoder('<your-api-key>').addTo(map);
Scripting with the plugin
When instantiating a geocoder, you may assign it to a variable. This will allow you to use its methods later on.
var geocoder = L.control.geocoder('<your-api-key>');
var geocoder = new L.Control.Geocoder('<your-api-key>');
geocoder.addTo(map);
The plugin extends Leaflet's Control class, so you may use any of those methods to modify plugin behavior in your script.
geocoder.setPosition('topright');
var element = geocoder.getContainer();
geocoder.removeFrom(map);
With alternate require()
or import
syntax
If you require()
or import
and set it to a variable, you can also use new
with that variable.
var MyGeocoderPlugin = require('leaflet-geocoder-mapzen');
import MyGeocoderPlugin from 'leaflet-geocoder-mapzen';
var geocoder = new MyGeocoderPlugin('<your-api-key>');
Properties
You can retrieve the current version of the geocoder.
console.log(geocoder.version);
Methods
There are additional methods on the geocoder that you can use.
geocoder.expand();
geocoder.collapse();
geocoder.focus();
geocoder.blur();
geocoder.reset();
Events
The geocoder includes all of Leaflet's events methods and adds additional events that you can subscribe to, so that you can customize what happens when users interact with the geocoder. When you instantiate a new geocoder, assign it to variable, as above, and then you can use the event methods to listen for the events that it's firing. For example:
geocoder.on('select', function (e) {
console.log('You’ve selected', e.feature.properties.label);
});
All of Leaflet's event methods are available, such as on
, off
, once
, and so on. The exact syntax and how it behaves are inherited from the version of Leaflet you are plugging into, so there are slight differences between the 0.7.x version line and the 1.0.0 version line.
The following events are fired:
event | description |
---|
results | Fired when search results are obtained. |
error | Fired if there was an error with a search request. |
select | Fired when a result is actively selected from the results list (not just highlighted.) |
highlight | Fired when a result is highlighted by the up/down arrow keys. |
expand | Fired when the geocoder is expanded. |
collapse | Fired when the geocoder is collapsed. |
reset | Fired when the geocoder is reset ("x" button is clicked). |
focus | Fired when the geocoder is focused on the input. |
blur | Fired when the geocoder loses focus on the input. |
Here is a demo of the events.
Getting data
Certain events will pass data as the first argument to the event listener's callback function.
on results
or error
In addition to the base event object from Leaflet, the event object will contain these other useful properties:
property | description |
---|
endpoint | A string of the Mapzen API endpoint that was called. |
requestType | A string, either autocomplete , search , or place , depending on the request made. |
params | An object containing the parameters that have been passed to the Mapzen Search request. |
results | The original response object returned from Mapzen Search, including all feature geometries and properties. |
If there was an error with the request, the event object will contain the additional properties:
property | description |
---|
errorCode | The HTTP status code received. More information. |
errorMessage | The error message string that the geocoder will display. |
on select
and highlight
on focus
and blur
property | description |
---|
originalEvent | The original FocusEvent event object reported by the browser. |
Browser support
This plugin supports all Leaflet-supported browsers except for Internet Explorer 7. It makes a cross-domain request in Javascript to obtain search results, which is not supported in IE7 without JSONP. Mapzen Search does not support API requests in JSONP.
Using a Pelias-compatible endpoint
This project was renamed as of v1.3.0 to be more closely associated with Mapzen Search, the hosted geocoding service provided by Mapzen that requires an API key. You can still point the geocoder at a different service running Pelias, Mapzen's open-source geocoder, by changing the url
option (see Query behavior, above) to the desired endpoint. If an API key is not required, the parameter may be omitted or be set to undefined
or null
.
Accessing other plugin internals
Properties and methods used internally by the geocoder are also available on the returned object. These are purposefully not private or obscured, but they are also not publicly documented right now, since functionality may fluctuate without notice. Depending on usage and demand we will lock down and document internal properties and methods for general use. Please let us know in the issues tracker if you have feedback.
Do you support TypeScript?
Not officially. There are community-supplied type definitions at DefinitelyTyped.
Projects using this plugin
Let us know if you have a project you'd like to share!