accessible-autocomplete
Advanced tools
Comparing version 1.0.3 to 1.0.4
@@ -7,2 +7,6 @@ # CHANGELOG | ||
## 1.0.4 - 2017-05-15 | ||
- Add support for handling null/placeholder options when using `enhanceSelectElement`. Use `preserveNullOptions: true` to include options with `value=''` in the autocomplete results when enhancing a select element. | ||
## 1.0.3 - 2017-05-15 | ||
@@ -9,0 +13,0 @@ |
@@ -26,3 +26,3 @@ # Contributing | ||
To run the integration tests locally with Chrome and FireFox (specified in [wdio.config.js](test/wdio.config.js)): | ||
To run the integration tests locally with Chrome (specified in [wdio.config.js](test/wdio.config.js)): | ||
@@ -29,0 +29,0 @@ ```bash |
{ | ||
"name": "accessible-autocomplete", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"main": "dist/accessible-autocomplete.min.js", | ||
@@ -5,0 +5,0 @@ "style": "dist/accessible-autocomplete.min.css", |
@@ -227,2 +227,28 @@ # Accessible autocomplete | ||
### Null options | ||
If your `<select>` element has a "null" option - a default option with no value - then you can pass a `defaultValue` option to `enhanceSelectElement` which will replace the label of this option when it is selected. | ||
With the following HTML: | ||
```html | ||
<select id="location-picker"> | ||
<option value="">Select a country</option> | ||
<option value="fr">France</option> | ||
<option value="de">Germany</option> | ||
<option value="gb">United Kingdom</option> | ||
</select> | ||
``` | ||
Then passing a `defaultValue` option of `''` will then leave the autocomplete blank if the null option is selected. | ||
```js | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
defaultValue: '', | ||
selectElement: document.querySelector('#location-picker') | ||
}) | ||
``` | ||
Any null options will also be filtered out of the options used to populate the `source` of the autocomplete element. To preserve options with no value in the autcomplete then pass a `preserveNullOptions` flag of `true` to `enhanceSelectElement`. | ||
## Analytics and tracking | ||
@@ -229,0 +255,0 @@ |
@@ -24,14 +24,15 @@ import { h, render } from 'preact' /** @jsx h */ | ||
if (!opts.source) { | ||
const availableOptions = Array.prototype.map.call(opts.selectElement.options, o => o.innerHTML) | ||
let availableOptions = [].filter.call(opts.selectElement.options, o => (o.value || opts.preserveNullOptions)) | ||
availableOptions = availableOptions.map(o => o.innerHTML) | ||
opts.source = createSimpleEngine(availableOptions) | ||
} | ||
opts.onConfirm = opts.onConfirm || (query => { | ||
const requestedOption = Array.prototype.filter.call(opts.selectElement.options, o => o.innerHTML === query)[0] | ||
const requestedOption = [].filter.call(opts.selectElement.options, o => o.innerHTML === query)[0] | ||
if (requestedOption) { requestedOption.selected = true } | ||
}) | ||
if (!opts.defaultValue && opts.defaultValue !== '') { | ||
if (opts.selectElement.value || opts.defaultValue === undefined) { | ||
opts.defaultValue = opts.selectElement.options[opts.selectElement.options.selectedIndex].innerHTML | ||
} else { | ||
opts.selectElement.value = opts.defaultValue | ||
} | ||
opts.name = opts.name || '' | ||
@@ -38,0 +39,0 @@ opts.id = opts.id || opts.selectElement.id || '' |
/* global before, beforeEach, after, describe, expect, it */ | ||
import accessibleAutocomplete from '../../src/wrapper' | ||
const injectSelectToEnhanceIntoDOM = (element, id, name, options, selectedOption) => { | ||
const DEFAULT_OPTIONS = { | ||
'': 'Select', | ||
fr: 'France', | ||
de: 'Germany', | ||
gb: 'United Kingdom' | ||
} | ||
const injectSelectToEnhanceIntoDOM = (element, settings) => { | ||
settings = settings || {} | ||
settings.options = settings.options || DEFAULT_OPTIONS | ||
settings.id = settings.id !== undefined ? settings.id : 'location-picker-id' | ||
settings.name = settings.name !== undefined ? settings.name : 'location-picker-name' | ||
var $select = document.createElement('select') | ||
if (id) { | ||
$select.id = id | ||
if (settings.id) { | ||
$select.id = settings.id | ||
} | ||
if (name) { | ||
$select.name = name | ||
if (settings.name) { | ||
$select.name = settings.name | ||
} | ||
Object.keys(options) | ||
Object.keys(settings.options) | ||
.map(optionKey => { | ||
const option = document.createElement('option') | ||
option.value = optionKey | ||
option.text = options[optionKey] | ||
option.selected = (selectedOption === optionKey) | ||
option.text = settings.options[optionKey] | ||
option.selected = (settings.selected === optionKey) | ||
return option | ||
@@ -24,2 +35,4 @@ }) | ||
element.appendChild($select) | ||
return $select | ||
} | ||
@@ -80,14 +93,7 @@ | ||
it('can enhance a select element', () => { | ||
const id = 'location-picker-id' | ||
const name = 'location-picker-name' | ||
const options = { | ||
fr: 'France', | ||
de: 'Germany', | ||
gb: 'United Kingdom' | ||
} | ||
const selectedOption = 'gb' | ||
injectSelectToEnhanceIntoDOM(scratch, id, name, options, selectedOption) | ||
const select = injectSelectToEnhanceIntoDOM(scratch) | ||
const id = select.id | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
selectElement: document.querySelector('#' + id) | ||
selectElement: select | ||
}) | ||
@@ -99,7 +105,48 @@ | ||
const autocompleteInstance = autocompleteInstances[0] | ||
expect(autocompleteInstance.innerHTML).to.contain(`id="${id}"`) | ||
const autocompleteOption = autocompleteInstance.querySelector('.autocomplete__option') | ||
expect(autocompleteOption.textContent).to.equal(options[selectedOption]) | ||
const autocompleteInput = autocompleteInstance.querySelector('.autocomplete__input') | ||
expect(autocompleteInput.tagName.toLowerCase()).to.equal('input') | ||
expect(autocompleteInput.id).to.equal(id) | ||
}) | ||
it('uses the defaultValue setting to populate the input field if no option is selected', () => { | ||
const select = injectSelectToEnhanceIntoDOM(scratch, { selected: '' }) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
defaultValue: '', | ||
selectElement: select | ||
}) | ||
const autocompleteInstances = document.querySelectorAll('.autocomplete__wrapper') | ||
const autocompleteInstance = autocompleteInstances[0] | ||
const autocompleteInput = autocompleteInstance.querySelector('.autocomplete__input') | ||
expect(autocompleteInput.value).to.equal('') | ||
}) | ||
it('uses the option label as the default input element value if an option is selected', () => { | ||
const select = injectSelectToEnhanceIntoDOM(scratch, { selected: 'de' }) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
defaultValue: '', | ||
selectElement: select | ||
}) | ||
const autocompleteInstances = document.querySelectorAll('.autocomplete__wrapper') | ||
const autocompleteInstance = autocompleteInstances[0] | ||
const autocompleteInput = autocompleteInstance.querySelector('.autocomplete__input') | ||
expect(autocompleteInput.value).to.equal('Germany') | ||
}) | ||
it('gives the autocomplete element a blank name attribute by default', () => { | ||
const select = injectSelectToEnhanceIntoDOM(scratch) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
selectElement: select | ||
}) | ||
const autocompleteInstances = document.querySelectorAll('.autocomplete__wrapper') | ||
const autocompleteInstance = autocompleteInstances[0] | ||
const autocompleteInput = autocompleteInstance.querySelector('.autocomplete__input') | ||
expect(autocompleteInput.name).to.equal('') | ||
@@ -109,14 +156,7 @@ }) | ||
it('can define a name for the autocomplete element', () => { | ||
const id = 'location-picker-id' | ||
const name = 'location-picker-name' | ||
const options = { | ||
fr: 'France', | ||
de: 'Germany', | ||
gb: 'United Kingdom' | ||
} | ||
injectSelectToEnhanceIntoDOM(scratch, id, name, options) | ||
const select = injectSelectToEnhanceIntoDOM(scratch) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
name: 'location-picker-autocomplete', | ||
selectElement: document.querySelector('#' + id) | ||
selectElement: select | ||
}) | ||
@@ -132,16 +172,7 @@ | ||
it('can overwrite selectedOption with defaultValue', () => { | ||
const id = 'location-picker-id' | ||
const name = 'location-picker-name' | ||
const options = { | ||
fr: 'France', | ||
de: 'Germany', | ||
gb: 'United Kingdom' | ||
} | ||
const selectedOption = 'gb' | ||
injectSelectToEnhanceIntoDOM(scratch, id, name, options, selectedOption) | ||
it('does not include "null" options in autocomplete', (done) => { | ||
const select = injectSelectToEnhanceIntoDOM(scratch) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
defaultValue: 'France', | ||
selectElement: document.querySelector('#' + id) | ||
selectElement: select | ||
}) | ||
@@ -151,20 +182,20 @@ | ||
const autocompleteInstance = autocompleteInstances[0] | ||
const autocompleteOption = autocompleteInstance.querySelector('.autocomplete__option') | ||
expect(autocompleteOption.textContent).to.equal('France') | ||
const autocompleteInput = autocompleteInstance.querySelector('.autocomplete__input') | ||
// Using setTimeouts here since changes in values take a while to reflect in lists | ||
autocompleteInput.value = 'e' | ||
setTimeout(() => { | ||
const autocompleteOptions = autocompleteInstance.querySelectorAll('.autocomplete__option') | ||
expect(autocompleteOptions.length).to.equal(3) | ||
expect([].map.call(autocompleteOptions, o => o.textContent)).not.to.contain('Select') | ||
done() | ||
}, 250) | ||
}) | ||
it('can overwrite selectedOption with an empty defaultValue', () => { | ||
const id = 'location-picker-id' | ||
const name = 'location-picker-name' | ||
const options = { | ||
fr: 'France', | ||
de: 'Germany', | ||
gb: 'United Kingdom' | ||
} | ||
const selectedOption = 'gb' | ||
injectSelectToEnhanceIntoDOM(scratch, id, name, options, selectedOption) | ||
it('includes "null" options in autocomplete if `preserveNullOptions` flag is true', (done) => { | ||
const select = injectSelectToEnhanceIntoDOM(scratch) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
defaultValue: '', | ||
selectElement: document.querySelector('#' + id) | ||
preserveNullOptions: true, | ||
selectElement: select | ||
}) | ||
@@ -175,17 +206,18 @@ | ||
const autocompleteInput = autocompleteInstance.querySelector('.autocomplete__input') | ||
expect(autocompleteInput.value).to.equal('') | ||
// Using setTimeouts here since changes in values take a while to reflect in lists | ||
autocompleteInput.value = 'e' | ||
setTimeout(() => { | ||
const autocompleteOptions = autocompleteInstance.querySelectorAll('.autocomplete__option') | ||
expect(autocompleteOptions.length).to.equal(4) | ||
expect([].map.call(autocompleteOptions, o => o.textContent)).to.contain('Select') | ||
done() | ||
}, 250) | ||
}) | ||
it('has all options when typing', (done) => { | ||
const id = 'location-picker-id' | ||
const name = 'location-picker-name' | ||
const options = { | ||
fr: 'France', | ||
de: 'Germany', | ||
gb: 'United Kingdom' | ||
} | ||
injectSelectToEnhanceIntoDOM(scratch, id, name, options) | ||
const select = injectSelectToEnhanceIntoDOM(scratch) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
selectElement: document.querySelector('#' + id) | ||
selectElement: select | ||
}) | ||
@@ -200,10 +232,12 @@ | ||
autocompleteInput.value = 'Fran' | ||
expect(autocompleteOption.textContent).to.equal('France') | ||
autocompleteInput.value = 'Ger' | ||
setTimeout(() => { | ||
expect(autocompleteOption.textContent).to.equal('Germany') | ||
autocompleteInput.value = 'United' | ||
expect(autocompleteOption.textContent).to.equal('France') | ||
autocompleteInput.value = 'Ger' | ||
setTimeout(() => { | ||
expect(autocompleteOption.textContent).to.equal('United Kingdom') | ||
done() | ||
expect(autocompleteOption.textContent).to.equal('Germany') | ||
autocompleteInput.value = 'United' | ||
setTimeout(() => { | ||
expect(autocompleteOption.textContent).to.equal('United Kingdom') | ||
done() | ||
}, 250) | ||
}, 250) | ||
@@ -214,15 +248,6 @@ }, 250) | ||
it('onConfirm updates original select', (done) => { | ||
const id = 'location-picker-id' | ||
const name = 'location-picker-name' | ||
const options = { | ||
fr: 'France', | ||
de: 'Germany', | ||
gb: 'United Kingdom' | ||
} | ||
const selectedOption = 'gb' | ||
injectSelectToEnhanceIntoDOM(scratch, id, name, options, selectedOption) | ||
const select = injectSelectToEnhanceIntoDOM(scratch, { selected: 'de' }) | ||
accessibleAutocomplete.enhanceSelectElement({ | ||
defaultValue: 'de', | ||
selectElement: document.querySelector('#' + id) | ||
selectElement: select | ||
}) | ||
@@ -235,5 +260,4 @@ | ||
const originalSelectElement = document.querySelector(`#${id}-select`) | ||
// Check the defaultValue has been reflected on the original selectElement | ||
expect(originalSelectElement.value).to.equal('de') | ||
// Check the initial value of the original selectElement | ||
expect(select.value).to.equal('de') | ||
// Using setTimeouts here since changes in values take a while to reflect in lists | ||
@@ -244,3 +268,3 @@ autocompleteInput.value = 'United' | ||
autocompleteOption.click() | ||
expect(originalSelectElement.value).to.equal('gb') | ||
expect(select.value).to.equal('gb') | ||
done() | ||
@@ -247,0 +271,0 @@ }, 250) |
@@ -53,4 +53,4 @@ require('babel-register') | ||
capabilities: [ | ||
{ browserName: 'chrome' }, | ||
{ browserName: 'firefox' } | ||
// { browserName: 'firefox' }, | ||
{ browserName: 'chrome' } | ||
], | ||
@@ -57,0 +57,0 @@ baseUrl: 'http://localhost:' + staticServerPort, |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
408018
1603
287
1