@@ -7,6 +7,7 @@ var EventEmitter = require('events').EventEmitter;
77var exceptions = require ( './exceptions' ) ;
88var MapboxClient = require ( '@mapbox/mapbox-sdk' ) ;
99var mbxGeocoder = require ( '@mapbox/mapbox-sdk/services/geocoding' ) ;
10+ var mbxGeocoderV6 = require ( "@mapbox/mapbox-sdk/services/geocoding-v6" ) ;
1011var MapboxEventManager = require ( './events' ) ;
1112var localization = require ( './localization' ) ;
1213var subtag = require ( 'subtag' ) ;
@@ -31,6 +32,36 @@ function getFooterNode() {
3132 return div ;
3233}
3334
35+ function getItemValue ( item ) {
36+ return item . place_name
37+ }
38+
39+ function render ( item ) {
40+ var placeName = item . place_name . split ( ',' ) ;
41+ return '<div class="mapboxgl-ctrl-geocoder--suggestion"><div class="mapboxgl-ctrl-geocoder--suggestion-title">' + placeName [ 0 ] + '</div><div class="mapboxgl-ctrl-geocoder--suggestion-address">' + placeName . splice ( 1 , placeName . length ) . join ( ',' ) + '</div></div>' ;
42+ }
43+
44+ function getItemValueV6 ( item ) {
45+ const { name, place_formatted } = item . properties ;
46+ return name + ( place_formatted ? `, ${ place_formatted } ` : "" ) ;
47+ }
48+
49+ function renderV6 ( item ) {
50+ const { name, place_formatted } = item . properties ;
51+ return `<div class="mapboxgl-ctrl-geocoder--suggestion">
52+ ${
53+ name
54+ ? `<div class="mapboxgl-ctrl-geocoder--suggestion-title">${ name } </div>`
55+ : ""
56+ }
57+ ${
58+ place_formatted
59+ ? `<div class="mapboxgl-ctrl-geocoder--suggestion-address">${ place_formatted } </div>`
60+ : ""
61+ }
62+ </div>` ;
63+ }
64+
3465/**
3566 * A geocoder component using the [Mapbox Geocoding API](https://docs.mapbox.com/api/search/#geocoding)
3667 * @class MapboxGeocoder
@@ -75,6 +106,7 @@ function getFooterNode() {
75106 * @param {Boolean } [options.routing=false] Specify whether to request additional metadata about the recommended navigation destination corresponding to the feature or not. Only applicable for address features.
76107 * @param {String } [options.worldview="us"] Filter results to geographic features whose characteristics are defined differently by audiences belonging to various regional, cultural, or political groups.
77108 * @param {Boolean } [options.enableGeolocation=false] If `true` enable user geolocation feature.
109+ * @param {'v5'|'v6' } [options.version='v5'] If `v6` use v6 endpoint instead of v5. The default value is set to v5 API.
78110 * @param {('address'|'street'|'place'|'country') } [options.addressAccuracy="street"] The accuracy for the geolocation feature with which we define the address line to fill. The browser API returns the user's position with accuracy, and sometimes we can get the neighbor's address. To prevent receiving an incorrect address, you can reduce the accuracy of the definition.
79111 * @example
80112 * var geocoder = new MapboxGeocoder({ accessToken: mapboxgl.accessToken });
@@ -85,11 +117,15 @@ function getFooterNode() {
85117
86118function MapboxGeocoder ( options ) {
87119 this . _eventEmitter = new EventEmitter ( ) ;
88- this . options = extend ( { } , this . options , options ) ;
120+ this . options = extend ( { } , this . options , {
121+ getItemValue : options . version === 'v6' ? getItemValueV6 : getItemValue ,
122+ render : options . version === 'v6' ? renderV6 : render ,
123+ } , options ) ;
89124 this . inputString = '' ;
90125 this . fresh = true ;
91126 this . lastSelected = null ;
92127 this . geolocation = new Geolocation ( ) ;
128+ this . geocoderFactory = this . options . version === 'v6' ? mbxGeocoderV6 : mbxGeocoder ;
93129}
94130
95131MapboxGeocoder . prototype = {
@@ -110,13 +146,7 @@ MapboxGeocoder.prototype = {
110146 clearOnBlur : false ,
111147 enableGeolocation : false ,
112148 addressAccuracy : 'street' ,
113- getItemValue : function ( item ) {
114- return item . place_name
115- } ,
116- render : function ( item ) {
117- var placeName = item . place_name . split ( ',' ) ;
118- return '<div class="mapboxgl-ctrl-geocoder--suggestion"><div class="mapboxgl-ctrl-geocoder--suggestion-title">' + placeName [ 0 ] + '</div><div class="mapboxgl-ctrl-geocoder--suggestion-address">' + placeName . splice ( 1 , placeName . length ) . join ( ',' ) + '</div></div>' ;
119- }
149+ version : 'v5'
120150 } ,
121151
122152 /**
@@ -181,7 +211,7 @@ MapboxGeocoder.prototype = {
181211 this . setLanguage ( ) ;
182212
183213 if ( ! this . options . localGeocoderOnly ) {
184- this . geocoderService = mbxGeocoder (
214+ this . geocoderService = this . geocoderFactory (
185215 MapboxClient ( {
186216 accessToken : this . options . accessToken ,
187217 origin : this . options . origin
@@ -340,7 +370,13 @@ MapboxGeocoder.prototype = {
340370 this . _showClearButton ( ) ;
341371 this . fresh = false ;
342372
343- const config = {
373+ const config = this . options . version === 'v6' ? {
374+ longitude : geojson . geometry . coordinates [ 0 ] ,
375+ latitude : geojson . geometry . coordinates [ 1 ] ,
376+ limit : 1 ,
377+ language : this . options . language ,
378+ types : [ "address" ] ,
379+ } : {
344380 limit : 1 ,
345381 language : [ this . options . language ] ,
346382 query : geojson . geometry . coordinates ,
@@ -532,7 +568,11 @@ MapboxGeocoder.prototype = {
532568
533569 _fly : function ( selected ) {
534570 var flyOptions ;
535- if ( selected . properties && exceptions [ selected . properties . short_code ] ) {
571+ const { context, short_code } = selected . properties ;
572+ const countryCode = this . options . version === 'v6' ?
573+ context && context . country && context . country . country_code . toLowerCase ( ) :
574+ short_code ;
575+ if ( selected . properties && exceptions [ countryCode ] ) {
536576 // Certain geocoder search results return (and therefore zoom to fit)
537577 // an unexpectedly large bounding box: for example, both Russia and the
538578 // USA span both sides of -180/180, or France includes the island of
@@ -541,7 +581,7 @@ MapboxGeocoder.prototype = {
541581 // short-term solution; this may be amended as necessary.
542582 flyOptions = extend ( { } , this . options . flyTo ) ;
543583 if ( this . _map ) {
544- this . _map . fitBounds ( exceptions [ selected . properties . short_code ] . bbox , flyOptions ) ;
584+ this . _map . fitBounds ( exceptions [ countryCode ] . bbox , flyOptions ) ;
545585 }
546586 } else if ( selected . bbox ) {
547587 var bbox = selected . bbox ;
@@ -581,32 +621,36 @@ MapboxGeocoder.prototype = {
581621
582622 _setupConfig : function ( requestType , search ) {
583623 // Possible config properties to pass to client
624+ const v5Keys = [
625+ 'fuzzyMatch' ,
626+ 'routing' ,
627+ 'reverseMode' ,
628+ ] ;
584629 const keys = [
585630 'bbox' ,
586631 'limit' ,
587632 'proximity' ,
588633 'countries' ,
589634 'types' ,
590635 'language' ,
591- 'reverseMode' ,
592636 'mode' ,
593637 'autocomplete' ,
594- 'fuzzyMatch' ,
595- 'routing' ,
596638 'worldview'
597639 ] ;
640+ const allKeys = [ ...( this . options . version === 'v6' ? [ ] : v5Keys ) , ...keys ] ;
641+ // countries, types, and language need to be passed in as arrays to client
642+ // https://github.com/mapbox/mapbox-sdk-js/blob/master/services/geocoding.js#L38-L47
643+ const arrayParameters = [ 'countries' , 'types' , ...( this . options . version === 'v6' ? [ ] : [ 'language' ] ) ] ;
598644 const spacesOrCommaRgx = / [ \s , ] + / ;
599645
600646 var self = this ;
601- var config = keys . reduce ( function ( config , key ) {
647+ var config = allKeys . reduce ( function ( config , key ) {
602648 // don't include undefined/null params, but allow boolean, among other, values
603649 if ( self . options [ key ] === undefined || self . options [ key ] === null ) {
604650 return config ;
605651 }
606652
607- // countries, types, and language need to be passed in as arrays to client
608- // https://github.com/mapbox/mapbox-sdk-js/blob/master/services/geocoding.js#L38-L47
609- [ 'countries' , 'types' , 'language' ] . indexOf ( key ) > - 1
653+ arrayParameters . indexOf ( key ) > - 1
610654 ? ( config [ key ] = self . options [ key ] . split ( spacesOrCommaRgx ) )
611655 : ( config [ key ] = self . options [ key ] ) ;
612656
@@ -626,6 +670,7 @@ MapboxGeocoder.prototype = {
626670
627671 switch ( requestType ) {
628672 case GEOCODE_REQUEST_TYPE . REVERSE : {
673+ // expected to be coordinates in the form `lat, lon`
629674 var coords = search . split ( spacesOrCommaRgx ) . map ( function ( c ) {
630675 return parseFloat ( c , 10 ) ;
631676 } )
@@ -634,16 +679,13 @@ MapboxGeocoder.prototype = {
634679 }
635680
636681 // client only accepts one type for reverseGeocode, so
637- // use first config type if one, if not default to poi
638- config . types ? [ config . types [ 0 ] ] : [ "poi" ] ;
639- config = extend ( config , { query : coords , limit : 1 } ) ;
640-
641- // Remove config options not supported by the reverseGeocoder
642- [ 'proximity' , 'autocomplete' , 'fuzzyMatch' , 'bbox' ] . forEach ( function ( key ) {
643- if ( key in config ) {
644- delete config [ key ]
645- }
646- } ) ;
682+ // use first config type if one, if not default to poi for v5 and address for v6
683+ const defaultType = this . options . version === 'v6' ? [ "address" ] : [ "poi" ] ;
684+ config . types = config . types ? [ config . types [ 0 ] ] : defaultType ;
685+ config = extend ( config ,
686+ this . options . version === 'v6' ? { longitude : coords [ 0 ] , latitude : coords [ 1 ] } : { query : coords } ,
687+ { limit : 1 }
688+ ) ;
647689 } break ;
648690 case GEOCODE_REQUEST_TYPE . FORWARD : {
649691 // Ensure that any reverse geocoding looking request is cleaned up
@@ -657,6 +699,23 @@ MapboxGeocoder.prototype = {
657699 } break ;
658700 }
659701
702+ if ( this . options . version === 'v6' && config . mode ) {
703+ config . permanent = config . mode === 'mapbox.places-permanent' ;
704+ delete config . mode ;
705+ }
706+
707+ // Remove config options not supported by the reverseGeocoder and v5 keys if v6 mode chosen
708+ const unsupportedKeys = [
709+ ...( requestType === GEOCODE_REQUEST_TYPE . REVERSE ? [ 'proximity' , 'autocomplete' , 'fuzzyMatch' , 'bbox' ] : [ ] ) ,
710+ ...( this . options . version === 'v6' ? v5Keys : [ ] )
711+ ] ;
712+
713+ unsupportedKeys . forEach ( function ( key ) {
714+ if ( key in config ) {
715+ delete config [ key ]
716+ }
717+ } ) ;
718+
660719 return config ;
661720 } ,
662721
@@ -840,7 +899,7 @@ MapboxGeocoder.prototype = {
840899 if ( ! results . features . length ) return ;
841900 var result = results . features [ 0 ] ;
842901 this . _typeahead . selected = result ;
843- this . _inputEl . value = result . place_name ;
902+ this . _inputEl . value = this . options . version === 'v6' ? result . properties . name : result . place_name ;
844903 this . _onChange ( ) ;
845904 } ,
846905
@@ -1177,7 +1236,7 @@ MapboxGeocoder.prototype = {
11771236 */
11781237 setOrigin : function ( origin ) {
11791238 this . options . origin = origin ;
1180- this . geocoderService = mbxGeocoder (
1239+ this . geocoderService = this . geocoderFactory (
11811240 MapboxClient ( {
11821241 accessToken : this . options . accessToken ,
11831242 origin : this . options . origin
@@ -1201,7 +1260,7 @@ MapboxGeocoder.prototype = {
12011260 */
12021261 setAccessToken : function ( accessToken ) {
12031262 this . options . accessToken = accessToken ;
1204- this . geocoderService = mbxGeocoder (
1263+ this . geocoderService = this . geocoderFactory (
12051264 MapboxClient ( {
12061265 accessToken : this . options . accessToken ,
12071266 origin : this . options . origin
0 commit comments