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

Commit

Permalink
feat(autocomplete.js): create a reusable places autocomplete.js datas…
Browse files Browse the repository at this point in the history
…et (#173)

+ documentation
+ small fixes
+ no need for CSS nesting, also solves styling the dataset

BREAKING CHANGES:
- templates.inputValue => templates.value
- templates.dropdownSuggestion => templates.suggestion

fixes #165
  • Loading branch information
vvo authored and redox committed May 31, 2016
1 parent 27f5b78 commit ab0363c
Show file tree
Hide file tree
Showing 24 changed files with 476 additions and 383 deletions.
5 changes: 5 additions & 0 deletions autocompleteDataset.js
@@ -0,0 +1,5 @@
import createAutocompleteDataset from './src/createAutocompleteDataset.js';
import './src/places.scss';

// must use module.exports to be commonJS compatible
module.exports = createAutocompleteDataset;
7 changes: 5 additions & 2 deletions docs/config.rb
Expand Up @@ -26,11 +26,12 @@

# Reload the browser automatically whenever files change
configure :development do
config[:places_lib_url] = :places
activate :gzip
activate :livereload
config[:places_lib_url] = 'places'
config[:places_autocomplete_dataset_lib_url] = 'placesAutocompleteDataset'
activate :external_pipeline,
name: :places,
name: 'places',
command: 'npm run js:watch -- --output-path docs/.webpack/js',
source: '.webpack'
end
Expand Down Expand Up @@ -58,6 +59,7 @@

config[:places_lib_version] = ENV['VERSION']
config[:places_cdn_url] = 'https://cdn.jsdelivr.net/places.js/0/places.min.js'
config[:places_autocomplete_dataset_cdn_url] = 'https://cdn.jsdelivr.net/places.js/0/placesAutocompleteDataset.min.js'

helpers do
def nav_active(path)
Expand All @@ -68,6 +70,7 @@ def nav_active(path)
# Build-specific configuration
configure :build do
config[:places_lib_url] = config[:places_cdn_url]
config[:places_autocomplete_dataset_lib_url] = config[:places_autocomplete_dataset_cdn_url]
# this may trigger bad behavior, if so, see
# https://github.com/middleman/middleman-minify-html
activate :minify_html
Expand Down
13 changes: 9 additions & 4 deletions docs/source/javascripts/activateClipboard.js
Expand Up @@ -12,10 +12,15 @@ export default function activateClipboard(codeSamples) {
text: () => codeSample.textContent
});

copyToClipboard.classList.add('hint--top');
copyToClipboard.addEventListener('mouseleave', () => copyToClipboard.removeAttribute('data-hint'));
clipboard.on('success', () => copyToClipboard.setAttribute('data-hint', 'Copied!'));
copyToClipboard.addEventListener('mouseleave', () => {
copyToClipboard.removeAttribute('aria-label');
copyToClipboard.classList.remove('hint--top');
});
clipboard.on('success', () => {
copyToClipboard.classList.add('hint--top');
copyToClipboard.setAttribute('aria-label', 'Copied!');
});
// safari: https://clipboardjs.com/#browser-support
clipboard.on('error', () => copyToClipboard.setAttribute('data-hint', 'Hit ⌘+C to copy'));
clipboard.on('error', () => copyToClipboard.setAttribute('aria-label', 'Hit ⌘+C to copy'));
});
}
3 changes: 1 addition & 2 deletions docs/source/javascripts/docsearch.js
Expand Up @@ -3,8 +3,7 @@ import docsearch from 'docsearch.js';
const search = docsearch({
apiKey: '5718722ffb11e109821befd53a1d9fde',
indexName: 'places',
inputSelector: '#docsearch',
debug: true
inputSelector: '#docsearch'
});

const form = document.querySelector('#docsearch-form');
Expand Down
14 changes: 13 additions & 1 deletion docs/source/javascripts/index.js
Expand Up @@ -20,7 +20,12 @@ if (process.env.NODE_ENV === 'development') {
if (typeof console.table === 'function') {
Object.keys(eventData).forEach(dataKeyName => {
console.log(`data: ${dataKeyName}`);
console.table(eventData[dataKeyName]);
const data = eventData[dataKeyName];
if (Array.isArray(data)) {
console.table(data);
} else {
console.log(data);
}
});
} else {
console.log('event data:', eventData);
Expand All @@ -40,6 +45,13 @@ placesAutocomplete.on('change', function(e) {
const content = {
...e,
// hide advanced API event data in demo
suggestion: {
...e.suggestion,
hit: undefined,
hitIndex: undefined,
query: undefined,
rawAnswer: undefined
},
rawAnswer: undefined,
suggestionIndex: undefined
};
Expand Down
83 changes: 57 additions & 26 deletions docs/source/partials/documentation.md.erb
Expand Up @@ -184,13 +184,13 @@ Change the templates used in place.js.

Available templates:

- inputValue
- dropdownSuggestion
- value
- suggestion

Each template is a function that will receive a [suggestion object](#suggestion-object) and must return
a `string`.

`inputValue` must return a plain string as it's used to fill the `input.value`. `dropdownSuggestion` can
`value` must return a plain string as it's used to fill the `input.value`. `suggestion` should
return an HTML string to be displayed in the dropdown.
</td>
</tr>
Expand Down Expand Up @@ -425,9 +425,39 @@ Examples:
</tbody>
</table>

### API
### autocomplete.js

The documentation of the underlying REST API can be found [here](rest.html).
places.js is reusing [Algolia's autocomplete.js](https://github.com/algolia/autocomplete.js) library.

To be able to mix and search into your own data along with showing results of places,
we provide an [autocomplete.js dataset](https://github.com/algolia/autocomplete.js#datasets):

```html
<%= javascript_include_tag config[:places_autocomplete_dataset_cdn_url] %>
```

See the [autocomplete.js dataset example](examples.html#autocompletejs).

You will need an [Algolia account](https://www.algolia.com/) to be able to search into your own data.

The autocomplete.js dataset is exported as `placesAutocompleteDataset` in the window, also available with npm
using:

```js
import placesAutocompleteDataset from 'places.js/placesAutocompleteDataset';
```

All the places.js [options](#options) are available and can be passed to
the `placesAutocompleteDataset` function.

The places.js CSS file is automatically loaded so that the rendering of suggestions is already the one
you will expect.

### REST API

Behind the places.js the JavaScript library lies a complete REST API.

Read the underlying [REST API documentation](rest.html).

## Styling

Expand Down Expand Up @@ -475,54 +505,54 @@ Here's a default empty CSS file you can copy paste to tune the default styling:
.algolia-places {}

/* The algolia-places input */
.algolia-places .ap-input, .algolia-places .ap-hint {}
.ap-input, .ap-hint {}

/* The style of the svg icons when the input is on hover */
.algolia-places .ap-input:hover ~ .ap-input-icon svg,
.algolia-places .ap-input:focus ~ .ap-input-icon svg,
.algolia-places .ap-input-icon:hover svg {}
.ap-input:hover ~ .ap-input-icon svg,
.ap-input:focus ~ .ap-input-icon svg,
.ap-input-icon:hover svg {}

/* The dropdown style */
.algolia-places .ap-dropdown-menu {}
.ap-dropdown-menu {}

/* The suggestions style */
.algolia-places .ap-suggestion {}
.ap-suggestion {}

/* The highlighted names style */
.algolia-places .ap-suggestion em {}
.ap-suggestion em {}

/* The addresses style */
.algolia-places .ap-address {}
.ap-address {}

/* The icons of each suggestions ( can be a building or a pin ) */
.algolia-places .ap-suggestion-icon {}
.ap-suggestion-icon {}

/* The style of the svg inside the .ap-suggestion-icon */
.algolia-places .ap-suggestion-icon svg {}
.ap-suggestion-icon svg {}

/* The icons inside the input ( can be a pin or a cross ) */
.algolia-places .ap-input-icon {}
.ap-input-icon {}

/* The style of the svg inside the .ap-input-icon */
.algolia-places .ap-input-icon svg {}
.ap-input-icon svg {}

/* .a-cursor is the class a suggestion go on hover */
.algolia-places .ap-cursor {}
.ap-cursor {}

/* The style of the svg icon, when the .ap-suggestion is on hover */
.algolia-places .ap-cursor .ap-suggestion-icon svg {}
.ap-cursor .ap-suggestion-icon svg {}

/* The styles of the Algolia Places input footer */
.algolia-places .ap-footer {}
.ap-footer {}

/* The styles of the Algolia Places input footer links */
.algolia-places .ap-footer a {}
.ap-footer a {}

/* The styles of the Algolia Places input footer svg icons */
.algolia-places .ap-footer a svg {}
.ap-footer a svg {}

/* The styles of the Algolia Places input footer on hover */
.algolia-places .ap-footer:hover {}
.ap-footer:hover {}
```

### Disabling default style
Expand All @@ -533,13 +563,14 @@ Once you do so, the default `algolia-places` class name will turn into `algolia-

## Browser support

Algolia Places comes with native support for all current major browsers: Chrome, Firefox, Edge, Opera and Safari.
Algolia Places comes with native support for all latest stable versions of
current major browsers: Chrome, Firefox, Edge, Opera and Safari. Previous versions of those
modern browsers should also work. But since those are auto-updating browsers, we do not guarantee it.

It also works natively on Internet Explorer 11 and 10.
Algolia Places also works natively on Internet Explorer 11 and 10.

To support Internet Explorer 9, you need to include a polyfill for [Element.classList](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList). To do so, you can use the [Polyfill.io service](https://cdn.polyfill.io/v2/docs/).


## Rate limits

The Algolia Places API enforces some rate limits.
Expand Down
70 changes: 70 additions & 0 deletions docs/source/partials/examples/_autocomplete_dataset.html.erb
@@ -0,0 +1,70 @@
<input type="search" id="autocomplete-dataset" class="form-control" placeholder="Search for products or places" />

<script src="https://cdn.jsdelivr.net/algoliasearch/3/algoliasearchLite.min.js"></script>
<script src="https://cdn.jsdelivr.net/autocomplete.js/0/autocomplete.js"></script>
<style>
.ad-example-dropdown-menu {
width: 100%;
background-color: #fff;
border: 1px solid #ccc;
border-top: none;
border-radius: 5px;
padding: .5em;
box-shadow: 1px 1px 32px -10px rgba(0,0,0,0.62);
}
.ad-example-dropdown-menu .ad-example-suggestion {
cursor: pointer;
padding: 5px 4px;
}
.ad-example-dropdown-menu .ad-example-suggestion.ad-example-cursor {
background-color: #B2D7FF;
}
.ad-example-dropdown-menu .ad-example-suggestion em {
font-weight: bold;
font-style: normal;
}
.ad-example-header {
font-weight: bold;
padding: .5em 0;
margin-bottom: 1em;
border-bottom: 1px solid #ccc;
}
</style>
<%= javascript_include_tag config[:places_autocomplete_dataset_lib_url] %>
<script>
(function() {
var client = algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76');
var index = client.initIndex('instant_search');

// create the first autocomplete.js dataset: products
var productsDataset = {
source: autocomplete.sources.hits(index, {hitsPerPage: 5, attributesToSnippet: ['name:7']}),
displayKey: 'name',
name: 'products',
templates: {
header: '<div class="ad-example-header">Products</div>',
suggestion: function(suggestion) {
return suggestion._snippetResult.name.value;
}
}
};

// create the second dataset: places
// we automatically inject the default CSS
// all the places.js options are available
var placesDataset = placesAutocompleteDataset({
algoliasearch: algoliasearch,
templates: {
header: '<div class="ad-example-header">Places</div>'
}
});

// init
var datasets = [productsDataset, placesDataset];
autocomplete(
document.querySelector('#autocomplete-dataset'),
{hint: false, cssClasses: {prefix: 'ad-example'}},
datasets
);
})();
</script>
2 changes: 1 addition & 1 deletion docs/source/partials/examples/_city_search.html.erb
Expand Up @@ -7,7 +7,7 @@
container: document.querySelector('#city'),
type: 'city',
templates: {
inputValue: function(suggestion) {
value: function(suggestion) {
return suggestion.name;
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/source/partials/examples/_complete_form.html.erb
Expand Up @@ -24,7 +24,7 @@
container: document.querySelector('#form-address'),
type: 'address',
templates: {
inputValue: function(suggestion) {
value: function(suggestion) {
return suggestion.name;
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/source/partials/examples/_country_search.html.erb
Expand Up @@ -11,7 +11,7 @@
container: document.querySelector('#country'),
type: 'country',
templates: {
dropdownSuggestion: function(suggestion) {
suggestion: function(suggestion) {
return '<i class="flag ' + suggestion.countryCode + '"></i> ' +
suggestion.name;
}
Expand Down
16 changes: 15 additions & 1 deletion docs/source/partials/examples/_index.md.erb
Expand Up @@ -121,7 +121,21 @@ To disable all styling, use the `style` option:
```html
<%= partial '/partials/examples/full_styling' %>
```

Once you do so, the default `algolia-places` class name will turn into `algolia-places-nostyle`.

See our [documentation about styling](./documentation.html#styling) for more details.

## autocomplete.js

Using [Algolia's autocomplete.js](https://github.com/algolia/autocomplete.js) library, you can search
in your own data along with showing Algolia Places results.

You need an Algolia account to do so and the Algolia Places dataset:

<%= partial '/partials/examples/autocomplete_dataset' %>

```html
<%= partial '/partials/examples/autocomplete_dataset' %>
```

See the documentation about the [placesAutocompleteDataset function](documentation.html##autocompletejs).
7 changes: 2 additions & 5 deletions docs/source/partials/examples/_simple_input.html.erb
@@ -1,7 +1,6 @@
<input type="search" id="address" class="form-control" placeholder="Where are we going?" />

<p>Change event data:</p>
<pre id="address-value"></pre>
<p>Selected: <strong id="address-value">none</strong></p>

<%= javascript_include_tag config[:places_lib_url] %>
<script>
Expand All @@ -11,11 +10,9 @@
});

placesAutocomplete.on('change', function(e) {
console.log(e);

document
.querySelector('#address-value')
.textContent = JSON.stringify(e, null, 2);
.textContent = e.suggestion ? e.suggestion.value : 'none';
});
})();
</script>

0 comments on commit ab0363c

Please sign in to comment.