mirror of
https://github.com/Choices-js/Choices.git
synced 2024-06-15 20:25:18 +02:00
Add support for standard-compliant placeholder option (#617)
* Add support for standard-compliant placeholder option * Bump version and rebuild files
This commit is contained in:
parent
4de6e677d1
commit
8782564ddf
|
@ -400,13 +400,15 @@ const example = new Choices(element, {
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<select>
|
<select>
|
||||||
<option placeholder>This is a placeholder</option>
|
<option value="">This is a placeholder</option>
|
||||||
<option>...</option>
|
<option>...</option>
|
||||||
<option>...</option>
|
<option>...</option>
|
||||||
<option>...</option>
|
<option>...</option>
|
||||||
</select>
|
</select>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For backward compatibility, `<option placeholder>This is a placeholder</option>` is also supported.
|
||||||
|
|
||||||
### placeholderValue
|
### placeholderValue
|
||||||
**Type:** `String` **Default:** `null`
|
**Type:** `String` **Default:** `null`
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "choices.js",
|
"name": "choices.js",
|
||||||
"version": "7.0.6",
|
"version": "7.1.0",
|
||||||
"description": "A vanilla JS customisable text input/select box plugin",
|
"description": "A vanilla JS customisable text input/select box plugin",
|
||||||
"main": "./public/assets/scripts/choices.min.js",
|
"main": "./public/assets/scripts/choices.min.js",
|
||||||
"types": "./types/index.d.ts",
|
"types": "./types/index.d.ts",
|
||||||
|
|
File diff suppressed because it is too large
Load diff
6
public/assets/scripts/choices.min.js
vendored
6
public/assets/scripts/choices.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -78,8 +78,7 @@ a:focus {
|
||||||
border-radius: 2.5px;
|
border-radius: 2.5px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
appearance: none;
|
||||||
appearance: none;
|
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
public/assets/styles/base.min.css
vendored
2
public/assets/styles/base.min.css
vendored
|
@ -1 +1 @@
|
||||||
*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label,p{margin-bottom:8px}label{font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:#f9f9f9;padding:12px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}label+p{margin-top:-4px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{display:block;margin-bottom:12px}.logo__img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.push-bottom{margin-bottom:24px}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}.is-hidden{display:none}[data-test-hook]{margin-bottom:24px}
|
*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{position:relative;margin:0;width:100%;height:100%}body{font-family:"Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-size:16px;line-height:1.4;color:#fff;background-color:#333;overflow-x:hidden}hr,label{display:block}label,p{margin-bottom:8px}label{font-size:14px;font-weight:500;cursor:pointer}p{margin-top:0}hr{margin:30px 0;border:0;border-bottom:1px solid #eaeaea;height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:12px;font-weight:400;line-height:1.2}a,a:focus,a:visited{color:#fff;text-decoration:none;font-weight:600}.form-control{display:block;width:100%;background-color:#f9f9f9;padding:12px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;-webkit-appearance:none;appearance:none;margin-bottom:24px}.h1,h1{font-size:32px}.h2,h2{font-size:24px}.h3,h3{font-size:20px}.h4,h4{font-size:18px}.h5,h5{font-size:16px}.h6,h6{font-size:14px}label+p{margin-top:-4px}.container{display:block;margin:auto;max-width:40em;padding:48px}@media (max-width:620px){.container{padding:0}}.section{background-color:#fff;padding:24px;color:#333}.section a,.section a:focus,.section a:visited{color:#00bcd4}.logo{display:block;margin-bottom:12px}.logo__img{width:100%;height:auto;display:inline-block;max-width:100%;vertical-align:top;padding:6px 0}.visible-ie{display:none}.push-bottom{margin-bottom:24px}.zero-bottom{margin-bottom:0}.zero-top{margin-top:0}.text-center{text-align:center}.is-hidden{display:none}[data-test-hook]{margin-bottom:24px}
|
|
@ -19,7 +19,9 @@
|
||||||
.choices.is-disabled .choices__input {
|
.choices.is-disabled .choices__input {
|
||||||
background-color: #EAEAEA;
|
background-color: #EAEAEA;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
user-select: none;
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.choices.is-disabled .choices__item {
|
.choices.is-disabled .choices__item {
|
||||||
|
@ -302,7 +304,9 @@
|
||||||
|
|
||||||
.choices__item--disabled {
|
.choices__item--disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
user-select: none;
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
opacity: .5;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
public/assets/styles/choices.min.css
vendored
2
public/assets/styles/choices.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -157,7 +157,7 @@
|
||||||
<h2>Single select input</h2>
|
<h2>Single select input</h2>
|
||||||
<label for="choices-single-default">Default</label>
|
<label for="choices-single-default">Default</label>
|
||||||
<select class="form-control" data-trigger name="choices-single-default" id="choices-single-default" placeholder="This is a search placeholder">
|
<select class="form-control" data-trigger name="choices-single-default" id="choices-single-default" placeholder="This is a search placeholder">
|
||||||
<option placeholder>This is a placeholder</option>
|
<option value="">This is a placeholder</option>
|
||||||
<option value="Choice 1">Choice 1</option>
|
<option value="Choice 1">Choice 1</option>
|
||||||
<option value="Choice 2">Choice 2</option>
|
<option value="Choice 2">Choice 2</option>
|
||||||
<option value="Choice 3">Choice 3</option>
|
<option value="Choice 3">Choice 3</option>
|
||||||
|
@ -167,12 +167,12 @@
|
||||||
|
|
||||||
<label for="choices-single-remote-fetch">Options from remote source (Fetch API)</label>
|
<label for="choices-single-remote-fetch">Options from remote source (Fetch API)</label>
|
||||||
<select class="form-control" name="choices-single-remote-fetch" id="choices-single-remote-fetch">
|
<select class="form-control" name="choices-single-remote-fetch" id="choices-single-remote-fetch">
|
||||||
<option placeholder>Pick an Arctic Monkeys' record</option>
|
<option value="">Pick an Arctic Monkeys' record</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<label for="choices-single-remove-xhr">Options from remote source (XHR) & remove button</label>
|
<label for="choices-single-remove-xhr">Options from remote source (XHR) & remove button</label>
|
||||||
<select class="form-control" name="choices-single-remove-xhr" id="choices-single-remove-xhr">
|
<select class="form-control" name="choices-single-remove-xhr" id="choices-single-remove-xhr">
|
||||||
<option placeholder>Pick a Smiths' record</option>
|
<option value="">Pick a Smiths' record</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<label for="choices-single-groups">Option groups</label>
|
<label for="choices-single-groups">Option groups</label>
|
||||||
|
|
|
@ -7,7 +7,11 @@ export default class WrappedSelect extends WrappedElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
get placeholderOption() {
|
get placeholderOption() {
|
||||||
return this.element.querySelector('option[placeholder]');
|
return (
|
||||||
|
this.element.querySelector('option[value=""]') ||
|
||||||
|
// Backward compatibility layer for the non-standard placeholder attribute supported in older versions.
|
||||||
|
this.element.querySelector('option[placeholder]')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get optionGroups() {
|
get optionGroups() {
|
||||||
|
|
|
@ -12,11 +12,16 @@ describe('components/wrappedSelect', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
element = document.createElement('select');
|
element = document.createElement('select');
|
||||||
element.id = 'target';
|
element.id = 'target';
|
||||||
for (let i = 1; i <= 4; i++) {
|
for (let i = 0; i <= 4; i++) {
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
|
|
||||||
option.value = `Value ${i}`;
|
if (i === 0) {
|
||||||
option.innerHTML = `Label ${i}`;
|
option.value = '';
|
||||||
|
option.innerHTML = 'Placeholder label';
|
||||||
|
} else {
|
||||||
|
option.value = `Value ${i}`;
|
||||||
|
option.innerHTML = `Label ${i}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (i === 1) {
|
if (i === 1) {
|
||||||
option.setAttribute('placeholder', '');
|
option.setAttribute('placeholder', '');
|
||||||
|
@ -69,8 +74,16 @@ describe('components/wrappedSelect', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('placeholderOption getter', () => {
|
describe('placeholderOption getter', () => {
|
||||||
it('returns option element with placeholder attribute', () => {
|
it('returns option element with empty value attribute', () => {
|
||||||
expect(instance.placeholderOption).to.be.instanceOf(HTMLOptionElement);
|
expect(instance.placeholderOption).to.be.instanceOf(HTMLOptionElement);
|
||||||
|
expect(instance.placeholderOption.value).to.equal('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns option element with placeholder attribute as fallback', () => {
|
||||||
|
instance.element.removeChild(instance.element.firstChild);
|
||||||
|
|
||||||
|
expect(instance.placeholderOption).to.be.instanceOf(HTMLOptionElement);
|
||||||
|
expect(instance.placeholderOption.value).to.equal('Value 1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -145,7 +158,7 @@ describe('components/wrappedSelect', () => {
|
||||||
describe('appendDocFragment', () => {
|
describe('appendDocFragment', () => {
|
||||||
it('empties contents of element', () => {
|
it('empties contents of element', () => {
|
||||||
expect(instance.element.getElementsByTagName('option').length).to.equal(
|
expect(instance.element.getElementsByTagName('option').length).to.equal(
|
||||||
4,
|
5,
|
||||||
);
|
);
|
||||||
instance.appendDocFragment(document.createDocumentFragment());
|
instance.appendDocFragment(document.createDocumentFragment());
|
||||||
expect(instance.element.getElementsByTagName('option').length).to.equal(
|
expect(instance.element.getElementsByTagName('option').length).to.equal(
|
||||||
|
|
Loading…
Reference in a new issue