Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No Map #295

Merged
merged 15 commits into from
Oct 10, 2019
Merged

No Map #295

merged 15 commits into from
Oct 10, 2019

Conversation

scottsfarley93
Copy link

@scottsfarley93 scottsfarley93 commented Sep 19, 2019

This PR allows using the mapbox-gl-geocoder plugin without a map, as requested in #270.

Currently, the plugin is added to the map using the map's addControl method. In order to facilitate adding the map to other elements, I added a new addTo method on the geocoder class. If the addTo method is called with a mapbox-gl-js map, it will be added like normal (the map's addControl method will be called under the hood). If, on the other hand, geocoder.addTo is called with a string that looks like a reference to an HTML class or ID, it will add the search bar to that element. In these cases, the geocoder will have no _map property and all map-related methods (like updateProximity or flyTo result) will not be executed.

This still needs tests and I want to make sure there's no edge cases where the lack of a map causes unexpected problems.

I will also need to:

  • return the debug page to it's original state
  • Add a new mapbox-gl-js example that shows how to use the geocoder without the map

\cc @kbauhausness @shabnomnom

Launch Checklist

  • briefly describe the changes in this PR
  • write tests for all new functionality
  • run npm run docs and commit changes to API.md
  • update CHANGELOG.md with changes under master heading before merging

debug/index.js Outdated Show resolved Hide resolved
@scottsfarley93 scottsfarley93 changed the title [WIP] No Map No Map Sep 24, 2019
@scottsfarley93
Copy link
Author

Tapping @yuletide for review.

@andrewharvey
Copy link
Collaborator

Is it worth linking to the Mapbox TOS obligations when using places? https://www.mapbox.com/legal/tos#[GAGA], since you wouldn't be able to use no map unless you exclude places.

Copy link
Contributor

@yuletide yuletide left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome. Added a few comments and suggestions

README.md Outdated
@@ -19,6 +19,9 @@ so in browserify or webpack, you can require it like:
var MapboxGeocoder = require('@mapbox/mapbox-gl-geocoder');
```

### Using without a Map
It is possible to use the plugin without it being placed as a control on a mapbox-gl map. Keep in mind that the Mapbox [Terms of Service](https://www.mapbox.com/legal/tos#[GAGA]) require that POI search results be shown on a Mapbox map. If you don't need a POIs, you can exclude them from your search results with the `options.types` parameter when constructing a new Geocoder.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typo

README.md Outdated Show resolved Hide resolved
lib/events.js Outdated
//pass invalid event
if (!keyEvent.key) return;
// don't send events for keys that don't change the input
// TAB, ESC, LEFT, RIGHT, ENTER, UP, DOWN
if (keyEvent.metaKey || [9, 27, 37, 39, 13, 38, 40].indexOf(keyEvent.keyCode) !== -1) return;
var payload = this.getEventPayload('search.keystroke', geocoder);
payload.lastAction = keyEvent.key;
console.log("action: ", payload.lastAction)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
console.log("action: ", payload.lastAction)

lib/events.js Outdated
//pass invalid event
if (!keyEvent.key) return;
// don't send events for keys that don't change the input
// TAB, ESC, LEFT, RIGHT, ENTER, UP, DOWN
if (keyEvent.metaKey || [9, 27, 37, 39, 13, 38, 40].indexOf(keyEvent.keyCode) !== -1) return;
var payload = this.getEventPayload('search.keystroke', geocoder);
payload.lastAction = keyEvent.key;
console.log("action: ", payload.lastAction)
console.log(payload)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
console.log(payload)

throw new Error("Element ", container, "not found.")
}

parent.forEach(function(parentEl){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to create two geocodes with the same class applied to two different elements, but they behave unpredictably once created
gif

lib/index.js Show resolved Hide resolved
@@ -182,20 +217,20 @@ MapboxGeocoder.prototype = {
this.setRenderFunction(this.options.render);
this._typeahead.getItemValue = this.options.getItemValue;

if (this.options.trackProximity) {
if (this.options.trackProximity && this._map) {
this._updateProximity();
this._map.on('moveend', this._updateProximity);
}

this.mapMarker = null;
this._handleMarker = this._handleMarker.bind(this);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would never be called if there's no map right? I'd move this stuff to the if (this._map) block below for simplicity. Also means you don't need to check for map in the handler

notMapDiv.style.top = 0;
notMapDiv.style.right = 0;
notMapDiv.style.left = 0;
notMapDiv.style.bottom = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To reproduce the double stuff add in:

Suggested change
notMapDiv.style.bottom = 0;
notMapDiv.style.bottom = '50%';
var anotherNotMapDiv = document.body.appendChild(document.createElement('div'));
anotherNotMapDiv.style.position = 'absolute';
anotherNotMapDiv.style.top = '50%';
anotherNotMapDiv.style.right = 0;
anotherNotMapDiv.style.left = 0;
anotherNotMapDiv.style.bottom = 0;
anotherNotMapDiv.style.backgroundColor = 'green';
anotherNotMapDiv.classList.add('notAMap');

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test to test.ui.js, so I'm not sure we need to add this to the debug page.

* It will also throw an error if the referenced html element cannot be found in the document.body
* @param {String|mapboxgl.Map} container A reference to the container to which to add the geocoder
*/
addTo: function(container){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the new recommended way to invoke the geocoder? If so we should update the debug/index.js and docs to recommend using this method first, and not onAdd (which I think was always awkward so this is a welcome change)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the recommended method should still be map.addControl(geocoder) -- since I believe this will still be the primary usage. We can add an example that uses this method though.

Copy link
Contributor

@yuletide yuletide Oct 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. So map.addControl if you have a map, otherwise use addTo(container)

This is the example I had in mind that we could update to use addTo instead of onAdd (which sounds like and should probably be a private, internal method) since its more logical: https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-geocoder-outside-the-map/

container.addControl(this)
}
// if the container is not a map, but an html element, then add the control to that element
else if (typeof container == 'string' && (container.startsWith('#') || container.startsWith('.'))){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Allow passing in an HTMLElement

if (container instanceof HTMLElement){parent = container} and skip the querySelector bit

Scott Farley and others added 4 commits September 30, 2019 10:54
@scottsfarley93 scottsfarley93 mentioned this pull request Oct 2, 2019
4 tasks
@scottsfarley93 scottsfarley93 merged commit ccded5b into master Oct 10, 2019
@scottsfarley93 scottsfarley93 deleted the sans-map branch October 10, 2019 18:33
@pauloanalista
Copy link

Does anyone know if this issue has been resolved?

I want to replace Google Maps with MapBox and use a places autocomplete and I don't have a map.

@scottsfarley93
Copy link
Author

@pauloanalista this feature was released in v4.5.0. See some documentation here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants