Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
feat(controlled-search): expose search method in places.js (#659)
Browse files Browse the repository at this point in the history
* feat(controlled-search): expose search method in places.js and update example to use it

* chore(whitespace): fix whitespace error from rebase

* test(controlled-search): add test for .search method
  • Loading branch information
JonathanMontane authored Feb 25, 2019
1 parent 2b0e06c commit 4ddd681
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 50 deletions.
20 changes: 18 additions & 2 deletions docs/source/examples.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,27 @@ See the documentation about the [placesAutocompleteDataset function](documentati

### Nearby City Search

**Concepts:** type parameter, aroundLatLngViaIP, aroundPrecision, Places API Client.
**Concepts:** type parameter, aroundLatLngViaIP, aroundPrecision, programmatic search.

In this section, we will see how you can _emulate_ reverse geocoding to find city closest to a user using the Places API Client.

<%= partial '/partials/examples/reverse-city-search/demo', locals: config[:credentials][:documentation] %>
<%= partial '/partials/examples/reverse-city-search/demo_places', locals: config[:credentials][:documentation] %>

```html
<%= partial '/partials/examples/reverse-city-search/code_places', locals: config[:credentials][:placeholder] %>
```

**Note:** This is not a reverse geocoding API, and it is still bound by the ranking used for search, which means that in some cases large close-by cities can be promoted over a more closely located city.

### Using an API client

In some cases, you may not want to tie your Places search to an input, but rather access it only programmatically.

In these cases, you can use the regular JavaScript API Client, or the api client in your preferred language. You can head to the [API Clients page](api-clients.html) to see which api clients support Places.

For instance, here we will rewrite the previous example using the JS api client instead.

<%= partial '/partials/examples/reverse-city-search/code', locals: config[:credentials][:documentation] %>

```html
<%= partial '/partials/examples/reverse-city-search/code', locals: config[:credentials][:placeholder] %>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div>
<strong>Searching around: </strong>
<div id="reverse-city"></div>
<div id="api-client-reverse-city"></div>
</div>

<script src="https://cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js"></script>
Expand All @@ -27,7 +27,7 @@ placesClient.search({
var country = hits[0].country;
var formattedCity = locale_names[0] + ', ' + country;

var infoElt = document.querySelector("#reverse-city");
var infoElt = document.querySelector("#api-client-reverse-city");
infoElt.textContent = formattedCity;
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div>
<strong>Searching around: </strong>
<input type="search" id="reverse-city" placeholder="What's your favorite city?"></div>
</div>

<%= javascript_include_tag config[:places_lib_url] %>
<script>
var placesAutocomplete = places({
appId: '<%= app_id %>',
apiKey: '<%= api_key %>',
container: document.querySelector('#reverse-city')
}).configure({
type: 'city',
hitsPerPage: 1,
aroundLatLngViaIP: true
});

placesAutocomplete.search().then(function(suggestions) {
if (!suggestions[0]) {
return;
}

var name = suggestions[0].name;
var country = suggestions[0].country;
var formattedCity = locale_names[0] + ', ' + country;

var infoElt = document.querySelector("#reverse-city");
infoElt.value = formattedCity;
});
</script>
46 changes: 0 additions & 46 deletions docs/source/partials/examples/reverse-city-search/_demo.html.erb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<div>
<p>When constructing a search UI using InstantSearch, you may want to filter your dataset to only display some of your products based on the distance to the end user. This is usually done using the aroundLatLngViaIP filter, or aroundLatLng filter if you have access to precise geolocation information. However geographical filters are hard to interpret when displayed in raw format, as noone really knows where the coordinates <span id="coords"><code>48.8566, 2.34287</code></span> are.</p>

<p>Using Places, you can do a query to find the city in which your user is located and display that city name instead of a geolocation.</p>
</div>

<p><strong>Example:</strong></p>

<div>
<strong>Searching around: </strong>
<input type="search" id="reverse-city" placeholder="Your favorite city" />
</div>

<%= javascript_include_tag config[:places_lib_url] %>
<script>
var placesAutocomplete = places({
appId: '<%= app_id %>',
apiKey: '<%= api_key %>',
container: document.querySelector('#reverse-city')
}).configure({
type: 'city',
hitsPerPage: 5,
aroundLatLngViaIP: true,
debug: true
});

placesAutocomplete.search().then(function(suggestions) {
if (!suggestions[0]) {
return;
}

var name = suggestions[0].name;
var country = suggestions[0].country;
var latlng = suggestions[0].latlng;
var formattedCity = name + ', ' + country;

var coordElt = document.querySelector("#coords");
var lat = latlng.lat;
var lng = latlng.lng;
coordElt.innerHTML = '<code>' + lat + ', ' + lng + '</code>';

var infoElt = document.querySelector("#reverse-city");
infoElt.value = formattedCity;
});

placesAutocomplete.on('change', (response) => {
var suggestion = response.suggestion;
var latlng = suggestion.latlng;
var coordElt = document.querySelector("#coords");
var lat = latlng.lat;
var lng = latlng.lng;
coordElt.innerHTML = '<code>' + lat + ', ' + lng + '</code>';
});
</script>
5 changes: 5 additions & 0 deletions src/places.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ export default function places(options) {

placesInstance.autocomplete = autocompleteInstance;

placesInstance.search = (query = '') =>
new Promise(resolve => {
autocompleteDataset.source(query, resolve);
});

placesInstance.configure = configuration => {
const safeConfig = { ...configuration };

Expand Down
22 changes: 22 additions & 0 deletions src/places.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,26 @@ describe('places', () => {
language: 'de',
});
});

it('has a search method which calls autocomplete.source', () => {
autocomplete.mockClear();
const container = document
.querySelector('body')
.appendChild(document.createElement('input'));

const searchMock = jest.fn();
createAutocompleteDataset.mockImplementation(() => ({
source: searchMock,
other: 'autocompleteDataset',
}));

const placesInstance = places({
container,
autocompleteOptions: { option: 'value' },
});

placesInstance.search('some Query');

expect(searchMock.mock.calls[0][0]).toEqual('some Query');
});
});

0 comments on commit 4ddd681

Please sign in to comment.