Skip to content
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## HEAD

### Bug fixes 🐛

- The `marker` and `flyTo` options are now respected when geolocation is enabled [#462](https://github.com/mapbox/mapbox-gl-geocoder/pull/462)

## 5.0.1

### Bug fixes 🐛
Expand Down
46 changes: 36 additions & 10 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ MapboxGeocoder.prototype = {
footerNode.addEventListener('mousedown', function() {
this.selectingListItem = true;
}.bind(this));

footerNode.addEventListener('mouseup', function() {
this.selectingListItem = false;
}.bind(this));
Expand Down Expand Up @@ -331,8 +331,13 @@ MapboxGeocoder.prototype = {
}
};

this._handleMarker(geojson);
this._fly(geojson);
if (this._shouldAddMarker()) {
this._handleMarker(geojson);
}

if (this._shouldFly()) {
this._fly(geojson);
}

this._typeahead.clear();
this._typeahead.selected = true;
Expand All @@ -355,11 +360,11 @@ MapboxGeocoder.prototype = {
} else {
this.geocoderService.reverseGeocode(config).send().then(function (resp) {
const feature = resp.body.features[0];

if (feature) {
const locationText = utils.transformFeatureToGeolocationText(feature, this.options.addressAccuracy);
this._setInputValue(locationText);

feature.user_coordinates = geojson.geometry.coordinates;
this._eventEmitter.emit('result', { result: feature });
} else {
Expand Down Expand Up @@ -407,7 +412,7 @@ MapboxGeocoder.prototype = {

_setInputValue: function (value) {
this._inputEl.value = value;

setTimeout(function () {
this._inputEl.focus();
this._inputEl.scrollLeft = 0;
Expand Down Expand Up @@ -487,15 +492,15 @@ MapboxGeocoder.prototype = {
_showLoadingIcon: function() {
this._loadingEl.style.display = 'block';
},

_hideLoadingIcon: function() {
this._loadingEl.style.display = 'none';
},

_showAttribution: function() {
this._footerNode.style.display = 'block'
},

_hideAttribution: function() {
this._footerNode.style.display = 'none'
},
Expand All @@ -508,14 +513,17 @@ MapboxGeocoder.prototype = {
this._collapse();
}
},

_onChange: function() {
var selected = this._typeahead.selected;
if (selected && JSON.stringify(selected) !== this.lastSelected) {
this._hideClearButton();
if (this.options.flyTo) {

if (this._shouldFly()) {
this._fly(selected);
}
if (this.options.marker && this._mapboxgl){

if (this._shouldAddMarker()) {
this._handleMarker(selected);
}

Expand All @@ -530,6 +538,15 @@ MapboxGeocoder.prototype = {
}
},

/**
* Determine whether the map should fly to a new location after geocoding.
* @returns {Boolean} `true` if the map should fly to new locations, `false` if not
* @private
*/
_shouldFly: function() {
return this.options.flyTo;
},

_fly: function(selected) {
var flyOptions;
if (selected.properties && exceptions[selected.properties.short_code]) {
Expand Down Expand Up @@ -1282,6 +1299,15 @@ MapboxGeocoder.prototype = {
return this.options.worldview
},

/**
* Determine whether a marker should be added to the map.
* @returns {Boolean} `true` if a marker should be added, `false` if not
* @private
*/
_shouldAddMarker: function() {
return this.options.marker && this._mapboxgl;
},

/**
* Handle the placement of a result marking the selected result
* @private
Expand Down
184 changes: 170 additions & 14 deletions test/test.geocoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ test('geocoder', function(tt) {
map.addControl(geocoder);
}

function stubGeolocationPosition() {
const geolocationPositionStub = {
coords: {
accuracy: 10,
altitude: null,
altitudeAccuracy: null,
heading: null,
latitude: 38.8999242,
longitude: -77.0361813,
speed: null
},
timestamp: new Date('2022-01-01T00:00:00Z')
};

sinon.replace(geocoder.geolocation, 'getCurrentPosition',
sinon.fake.resolves(geolocationPositionStub));

return geolocationPositionStub;
}

tt.test('initialized', function(t) {
setup();
t.ok(geocoder, 'geocoder is initialized');
Expand Down Expand Up @@ -717,39 +737,114 @@ test('geocoder', function(tt) {
t.end()
});

tt.test('options.flyTo [false]', function(t){
t.plan(1)
tt.test('options.flyTo [false] when querying', function(t){
t.plan(1);

setup({
flyTo: false
});

var mapFlyMethod = sinon.spy(map, "flyTo");
const mapFlySpy = sinon.spy(map, 'flyTo');

geocoder.query('Golden Gate Bridge');

geocoder.on(
'result',
once(function() {
t.ok(mapFlyMethod.notCalled, "The map flyTo was not called when the option was set to false")
t.ok(mapFlySpy.notCalled, 'flyTo() was not called after querying');
})
);
});

tt.test('options.flyTo [false] when geolocating', function(t) {
t.plan(1);

t.teardown(function() {
sinon.restore();
});

setup({
flyTo: false
});

stubGeolocationPosition();
const flyToSpy = sinon.spy(map, 'flyTo');

geocoder._geolocateUser();

geocoder.on(
'result',
once(function() {
t.ok(flyToSpy.notCalled, 'flyTo() was not called after geolocating');
})
);
});

tt.test('options.flyTo [true] when querying', function(t){
t.plan(4);

tt.test('options.flyTo [true]', function(t){
t.plan(4)
setup({
flyTo: true
});

var mapFlyMethod = sinon.spy(map, "flyTo");
const flyToSpy = sinon.spy(map, 'flyTo');

geocoder.query('Golden Gate Bridge');

geocoder.on(
'result',
once(function() {
t.ok(mapFlyMethod.calledOnce, "The map flyTo was called when the option was set to true");
var calledWithArgs = mapFlyMethod.args[0][0];
t.equals(+calledWithArgs.center[0].toFixed(4), +-122.4809.toFixed(4), 'the map is directed to fly to the right longitude');
t.equals(+calledWithArgs.center[1].toFixed(4), +37.8181.toFixed(4), 'the map is directed to fly to the right latitude');
t.deepEqual(calledWithArgs.zoom, 16, 'the map is directed to fly to the right zoom');
t.ok(flyToSpy.calledOnce, 'flyTo() is called after querying');

const calledWithArgs = flyToSpy.args[0][0];

t.equals(+calledWithArgs.center[0].toFixed(4),
+-122.4809.toFixed(4),
'the map is directed to fly to the right longitude');

t.equals(+calledWithArgs.center[1].toFixed(4),
+37.8181.toFixed(4),
'the map is directed to fly to the right latitude');

t.deepEqual(calledWithArgs.zoom, 16,
'the map is directed to fly to the right zoom level');
})
);
});

tt.test('options.flyTo [true] when geolocating', function(t) {
t.plan(4);

t.teardown(function() {
sinon.restore();
});

setup({
flyTo: true
});

const geolocationPositionStub = stubGeolocationPosition();
const flyToSpy = sinon.spy(map, 'flyTo');

geocoder._geolocateUser();

geocoder.on(
'result',
once(function() {
t.ok(flyToSpy.calledOnce, 'flyTo() is called after geolocating');

const calledWithArgs = flyToSpy.args[0][0];

t.equals(+calledWithArgs.center[0].toFixed(4),
+geolocationPositionStub.coords.longitude.toFixed(4),
'the map is directed to fly to the right longitude');

t.equals(+calledWithArgs.center[1].toFixed(4),
+geolocationPositionStub.coords.latitude.toFixed(4),
'the map is directed to fly to the right latitude');

t.deepEqual(calledWithArgs.zoom, 16,
'the map is directed to fly to the right zoom level');
})
);
});
Expand Down Expand Up @@ -828,7 +923,7 @@ test('geocoder', function(tt) {
t.end();
});

tt.test('options.marker [true]', function(t) {
tt.test('options.marker [true] when querying', function(t) {
t.plan(2);

setup({
Expand All @@ -849,6 +944,43 @@ test('geocoder', function(tt) {
);
});

tt.test('options.marker [true] when geolocating', function(t) {
t.plan(4);

t.teardown(function() {
sinon.restore();
});

setup({
marker: true,
mapboxgl: mapboxgl
});

const geolocationPositionStub = stubGeolocationPosition();
const markerConstructorSpy = sinon.spy(mapboxgl, 'Marker');

geocoder._geolocateUser();

geocoder.on(
'result',
once(function(event) {
t.ok(markerConstructorSpy.calledOnce, 'a new marker is added to the map');

const calledWithOptions = markerConstructorSpy.args[0][0];

t.equals(calledWithOptions.color, '#4668F2', 'a default color is set');

t.equals(+event.result.user_coordinates[1].toFixed(4),
+geolocationPositionStub.coords.latitude.toFixed(4),
'the marker is placed at the correct latitude');

t.equals(+event.result.user_coordinates[0].toFixed(4),
+geolocationPositionStub.coords.longitude.toFixed(4),
'the marker is placed at the correct longitude');
})
);
});

tt.test('options.marker [constructor properties]', function(t) {
t.plan(4);

Expand Down Expand Up @@ -876,7 +1008,7 @@ test('geocoder', function(tt) {
);
});

tt.test('options.marker [false]', function(t) {
tt.test('options.marker [false] when querying', function(t) {
t.plan(1);

setup({
Expand All @@ -894,6 +1026,30 @@ test('geocoder', function(tt) {
);
});

tt.test('options.marker [false] when geolocating', function(t) {
t.plan(1);

t.teardown(function() {
sinon.restore();
});

setup({
marker: false
});

stubGeolocationPosition();
const markerConstructorSpy = sinon.spy(mapboxgl, 'Marker');

geocoder._geolocateUser();

geocoder.on(
'result',
once(function() {
t.ok(markerConstructorSpy.notCalled, 'a new marker is not added to the map');
})
);
});

tt.test('geocode#onRemove', function(t){
setup({marker: true});

Expand Down