Update code styling rules (#713)

* Enforce curly braces around conditionals

* Install sort class members + update rules

* Satisfy linting changes

* Add todo

* Add tests for clearChoices

* Update eslint-plugin-prettier to latest

* Resolve conflicts

* Fix linting errors
This commit is contained in:
Josh Johnson 2019-10-29 18:26:11 +00:00 committed by GitHub
parent 172366d6fa
commit 88f63faa0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 304 additions and 139 deletions

View file

@ -7,7 +7,7 @@
"plugin:prettier/recommended",
"plugin:compat/recommended"
],
"plugins": ["prettier"],
"plugins": ["prettier", "sort-class-members"],
"env": {
"es6": true,
"browser": true
@ -37,6 +37,23 @@
"array": false,
"object": true
}
],
"curly": ["error", "all"],
"newline-before-return": "error",
"sort-class-members/sort-class-members": [
2,
{
"order": [
"[static-properties]",
"[static-methods]",
"[properties]",
"[conventional-private-properties]",
"constructor",
"[methods]",
"[conventional-private-methods]"
],
"accessorPairPositioning": "getThenSet"
}
]
},
"overrides": [

173
package-lock.json generated
View file

@ -3629,9 +3629,9 @@
}
},
"eslint": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz",
"integrity": "sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==",
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz",
"integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
@ -3641,9 +3641,9 @@
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^1.4.2",
"eslint-utils": "^1.4.3",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.1.1",
"espree": "^6.1.2",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
@ -3653,7 +3653,7 @@
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"inquirer": "^6.4.1",
"inquirer": "^7.0.0",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
@ -3679,15 +3679,6 @@
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"glob-parent": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
"integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"import-fresh": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz",
@ -3698,21 +3689,6 @@
"resolve-from": "^4.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@ -3754,9 +3730,9 @@
}
},
"eslint-config-prettier": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz",
"integrity": "sha512-YrKucoFdc7SEko5Sxe4r6ixqXPDP1tunGw91POeZTTRKItf/AMFYt/YLEQtZMkR2LVpAVhcAcZgcWpm1oGPW7w==",
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.5.0.tgz",
"integrity": "sha512-cjXp8SbO9VFGW/Z7mbTydqS9to8Z58E5aYhj3e1+Hx7lS9s6gL5ILKNpCqZAFOVYRcSkWPFYljHrEh8QFEK5EQ==",
"dev": true,
"requires": {
"get-stdin": "^6.0.0"
@ -3990,6 +3966,12 @@
"prettier-linter-helpers": "^1.0.0"
}
},
"eslint-plugin-sort-class-members": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-sort-class-members/-/eslint-plugin-sort-class-members-1.6.0.tgz",
"integrity": "sha512-7+FEtnxeK0vtoPERAU7gtxpr//NsYYrPvMoDRIoqP6u999xbY7Lpgjr9KmalfXIOTuVxvRNgK7vJhAGVRi/z4A==",
"dev": true
},
"eslint-scope": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
@ -6619,78 +6601,87 @@
"dev": true
},
"inquirer": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
"integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz",
"integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==",
"dev": true,
"requires": {
"ansi-escapes": "^3.2.0",
"ansi-escapes": "^4.2.1",
"chalk": "^2.4.2",
"cli-cursor": "^2.1.0",
"cli-cursor": "^3.1.0",
"cli-width": "^2.0.0",
"external-editor": "^3.0.3",
"figures": "^2.0.0",
"lodash": "^4.17.12",
"mute-stream": "0.0.7",
"figures": "^3.0.0",
"lodash": "^4.17.15",
"mute-stream": "0.0.8",
"run-async": "^2.2.0",
"rxjs": "^6.4.0",
"string-width": "^2.1.0",
"string-width": "^4.1.0",
"strip-ansi": "^5.1.0",
"through": "^2.3.6"
},
"dependencies": {
"ansi-escapes": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
"dev": true
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
"integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
"dev": true,
"requires": {
"type-fest": "^0.5.2"
}
},
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"cli-cursor": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"dev": true,
"requires": {
"restore-cursor": "^2.0.0"
"restore-cursor": "^3.1.0"
}
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz",
"integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==",
"dev": true,
"requires": {
"escape-string-regexp": "^1.0.5"
}
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"onetime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
"integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
"dev": true,
"requires": {
"mimic-fn": "^1.0.0"
"mimic-fn": "^2.1.0"
}
},
"restore-cursor": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"dev": true,
"requires": {
"onetime": "^2.0.0",
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
}
},
@ -6704,24 +6695,14 @@
}
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz",
"integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
},
"dependencies": {
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"requires": {
"ansi-regex": "^3.0.0"
}
}
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^5.2.0"
}
},
"strip-ansi": {
@ -6731,15 +6712,13 @@
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
}
}
},
"type-fest": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
"integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==",
"dev": true
}
}
},
@ -8396,9 +8375,9 @@
}
},
"mimic-fn": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true
},
"mimic-response": {
@ -8588,9 +8567,9 @@
"dev": true
},
"mute-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
"nan": {

View file

@ -63,14 +63,15 @@
"chai": "^4.2.0",
"csso-cli": "^3.0.0",
"cypress": "3.5.0",
"eslint": "^6.5.1",
"eslint": "^6.6.0",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-config-prettier": "^6.4.0",
"eslint-config-prettier": "^6.5.0",
"eslint-loader": "^3.0.2",
"eslint-plugin-compat": "3.3.0",
"eslint-plugin-cypress": "^2.7.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-sort-class-members": "^1.6.0",
"express": "^4.16.4",
"husky": "^3.0.9",
"jsdom": "^15.2.0",

View file

@ -351,11 +351,13 @@ class Choices {
highlightAll() {
this._store.items.forEach(item => this.highlightItem(item));
return this;
}
unhighlightAll() {
this._store.items.forEach(item => this.unhighlightItem(item));
return this;
}
@ -431,6 +433,7 @@ class Choices {
const values = this._store.activeItems.reduce((selectedItems, item) => {
const itemValue = valueOnly ? item.value : item;
selectedItems.push(itemValue);
return selectedItems;
}, []);
@ -446,6 +449,7 @@ class Choices {
}
items.forEach(value => this._setChoiceOrItem(value));
return this;
}
@ -539,12 +543,14 @@ class Choices {
label = 'label',
replaceChoices = false,
) {
if (!this.initialised)
if (!this.initialised) {
throw new ReferenceError(
`setChoices was called on a non-initialized instance of Choices`,
);
if (!this._isSelectElement)
}
if (!this._isSelectElement) {
throw new TypeError(`setChoices can't be used with INPUT based Choices`);
}
if (typeof value !== 'string' || !value) {
throw new TypeError(
@ -558,10 +564,11 @@ class Choices {
}
if (!Array.isArray(choicesArrayOrFetcher)) {
if (typeof choicesArrayOrFetcher !== 'function')
if (typeof choicesArrayOrFetcher !== 'function') {
throw new TypeError(
`.setChoices must be called either with array of choices with a function resulting into Promise of array of choices`,
);
}
// it's a choices fetcher
requestAnimationFrame(() => this._handleLoadingState(true));
@ -571,21 +578,26 @@ class Choices {
return fetcher
.then(data => this.setChoices(data, value, label, replaceChoices))
.catch(err => {
if (!this.config.silent) console.error(err);
if (!this.config.silent) {
console.error(err);
}
})
.then(() => this._handleLoadingState(false))
.then(() => this);
}
// function returned something else than promise, let's check if it's an array of choices
if (!Array.isArray(fetcher))
if (!Array.isArray(fetcher)) {
throw new TypeError(
`.setChoices first argument function must return either array of choices or Promise, got: ${typeof fetcher}`,
);
}
// recursion with results, it's sync and choices were cleared already
return this.setChoices(fetcher, value, label, false);
}
this.containerOuter.removeLoadingState();
const addGroupsAndChoices = groupOrChoice => {
if (groupOrChoice.choices) {
this._addGroup({
@ -615,10 +627,13 @@ class Choices {
clearChoices() {
this._store.dispatch(clearChoices());
return this;
}
clearStore() {
this._store.dispatch(clearAll());
return this;
}
@ -769,6 +784,7 @@ class Choices {
if (this._isSelectOneElement) {
return choice.groupId === group.id;
}
return (
choice.groupId === group.id &&
(this.config.renderSelectedChoices === 'always' || !choice.selected)
@ -833,6 +849,7 @@ class Choices {
} else {
acc.normalChoices.push(choice);
}
return acc;
},
{ placeholderChoices: [], normalChoices: [] },
@ -980,7 +997,9 @@ class Choices {
// If we are clicking on an option
const { id } = element.dataset;
const choice = this._store.getChoiceById(id);
if (!choice) return;
if (!choice) {
return;
}
const passedKeyCode =
activeItems[0] && activeItems[0].keyCode ? activeItems[0].keyCode : null;
const hasActiveDropdown = this.dropdown.isActive;
@ -1921,6 +1940,7 @@ class Choices {
}
const { templates, classNames } = this.config;
return templates[template].call(this, classNames, ...args);
}
@ -2068,7 +2088,9 @@ class Choices {
});
// If sorting is enabled or the user is searching, filter choices
if (this.config.shouldSort) allChoices.sort(filter);
if (this.config.shouldSort) {
allChoices.sort(filter);
}
// Determine whether there is a selected choice
const hasSelectedChoice = allChoices.some(choice => choice.selected);
@ -2212,6 +2234,7 @@ class Choices {
return elements.reduce(
(instances, element) => {
instances.push(new Choices(element, config));
return instances;
},
[this],

View file

@ -15,16 +15,16 @@ describe('choices', () => {
});
};
beforeEach(() => {
passedElement = document.createElement('input');
passedElement.type = 'text';
passedElement.className = 'js-choices';
document.body.appendChild(passedElement);
instance = new Choices(passedElement);
});
describe('public methods', () => {
beforeEach(() => {
passedElement = document.createElement('input');
passedElement.type = 'text';
passedElement.className = 'js-choices';
document.body.appendChild(passedElement);
instance = new Choices(passedElement);
});
afterEach(() => {
output = null;
instance = null;
@ -798,6 +798,29 @@ describe('choices', () => {
});
});
describe('clearChoices', () => {
let storeDispatchStub;
beforeEach(() => {
storeDispatchStub = stub();
instance._store.dispatch = storeDispatchStub;
output = instance.clearChoices();
});
afterEach(() => {
instance._store.dispatch.reset();
});
returnsInstance(output);
it('dispatches clearChoices action', () => {
expect(storeDispatchStub.lastCall.args[0]).to.eql({
type: ACTION_TYPES.CLEAR_CHOICES,
});
});
});
describe('clearStore', () => {
let storeDispatchStub;
@ -930,6 +953,7 @@ describe('choices', () => {
expect(inst).to.eq(choice);
fetcherCalled = true;
await new Promise(resolve => setTimeout(resolve, 1000));
return [
{ label: 'l1', value: 'v1', customProperties: 'prop1' },
{ label: 'l2', value: 'v2', customProperties: 'prop2' },
@ -1440,7 +1464,9 @@ describe('choices', () => {
});
});
});
});
describe('private methods', () => {
describe('_createGroupsFragment', () => {
let _createChoicesFragmentStub;
const choices = [

View file

@ -15,6 +15,7 @@ export default class Dropdown {
this.position = Math.ceil(
this.dimensions.top + window.pageYOffset + this.element.offsetHeight,
);
return this.position;
}
@ -35,6 +36,7 @@ export default class Dropdown {
this.element.classList.add(this.classNames.activeState);
this.element.setAttribute('aria-expanded', 'true');
this.isActive = true;
return this;
}
@ -47,6 +49,7 @@ export default class Dropdown {
this.element.classList.remove(this.classNames.activeState);
this.element.setAttribute('aria-expanded', 'false');
this.isActive = false;
return this;
}
}

View file

@ -25,14 +25,14 @@ export default class Input {
this.element.placeholder = placeholder;
}
set value(value) {
this.element.value = value;
}
get value() {
return sanitise(this.element.value);
}
set value(value) {
this.element.value = value;
}
addEventListeners() {
this.element.addEventListener('paste', this._onPaste);
this.element.addEventListener('input', this._onInput, {

View file

@ -56,7 +56,8 @@ export default class WrappedElement {
this.element.removeAttribute('data-choice');
// Re-assign values - this is weird, I know
this.element.value = this.element.value;
// @todo Figure out why we need to do this
this.element.value = this.element.value; // eslint-disable-line no-self-assign
}
enable() {

View file

@ -6,6 +6,10 @@ export default class WrappedInput extends WrappedElement {
this.delimiter = delimiter;
}
get value() {
return this.element.value;
}
set value(items) {
const itemValues = items.map(({ value }) => value);
const joinedValues = itemValues.join(this.delimiter);
@ -13,8 +17,4 @@ export default class WrappedInput extends WrappedElement {
this.element.setAttribute('value', joinedValues);
this.element.value = joinedValues;
}
get value() {
return this.element.value;
}
}

View file

@ -0,0 +1,45 @@
window.delegateEvent = (function delegateEvent() {
let events;
let addedListenerTypes;
if (typeof events === 'undefined') {
events = new Map();
}
if (typeof addedListenerTypes === 'undefined') {
addedListenerTypes = [];
}
function _callback(event) {
const type = events.get(event.type);
if (!type) {
return;
}
type.forEach(fn => fn(event));
}
return {
add: function add(type, fn) {
// Cache list of events.
if (events.has(type)) {
events.get(type).push(fn);
} else {
events.set(type, [fn]);
}
// Setup events.
if (addedListenerTypes.indexOf(type) === -1) {
document.documentElement.addEventListener(type, _callback, true);
addedListenerTypes.push(type);
}
},
remove: function remove(type, fn) {
if (!events.get(type)) {
return;
}
events.set(type, events.get(type).filter(item => item !== fn));
if (!events.get(type).length) {
addedListenerTypes.splice(addedListenerTypes.indexOf(type), 1);
}
},
};
})();

View file

@ -36,6 +36,7 @@ export const wrap = (element, wrapper = document.createElement('div')) => {
} else {
element.parentNode.appendChild(wrapper);
}
return wrapper.appendChild(element);
};
@ -92,6 +93,7 @@ export const sanitise = value => {
export const strToEl = (() => {
const tmpEl = document.createElement('div');
return str => {
const cleanedInput = str.trim();
tmpEl.innerHTML = cleanedInput;
@ -133,6 +135,7 @@ export const dispatchEvent = (element, type, customArgs = null) => {
export const getWindowHeight = () => {
const { body } = document;
const html = document.documentElement;
return Math.max(
body.scrollHeight,
body.offsetHeight,

View file

@ -33,6 +33,7 @@ export default function choices(state = defaultState, action) {
return state.map(obj => {
const choice = obj;
choice.active = action.active;
return choice;
});
}
@ -45,6 +46,7 @@ export default function choices(state = defaultState, action) {
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = true;
}
return choice;
});
}
@ -61,6 +63,7 @@ export default function choices(state = defaultState, action) {
if (choice.id === parseInt(action.choiceId, 10)) {
choice.selected = false;
}
return choice;
});
}
@ -76,8 +79,10 @@ export default function choices(state = defaultState, action) {
choice.active = action.results.some(({ item, score }) => {
if (item.id === choice.id) {
choice.score = score;
return true;
}
return false;
});
@ -89,6 +94,7 @@ export default function choices(state = defaultState, action) {
return state.map(obj => {
const choice = obj;
choice.active = action.active;
return choice;
});
}

View file

@ -23,6 +23,7 @@ export default function items(state = defaultState, action) {
return newState.map(obj => {
const item = obj;
item.highlighted = false;
return item;
});
}
@ -34,6 +35,7 @@ export default function items(state = defaultState, action) {
if (item.id === action.id) {
item.active = false;
}
return item;
});
}
@ -44,6 +46,7 @@ export default function items(state = defaultState, action) {
if (item.id === action.id) {
item.highlighted = action.highlighted;
}
return item;
});
}

View file

@ -125,6 +125,7 @@ export default class Store {
const hasActiveOptions = choices.some(
choice => choice.active === true && choice.disabled === false,
);
return isActive && hasActiveOptions;
}, []);
}
@ -145,8 +146,10 @@ export default class Store {
getChoiceById(id) {
if (id) {
const n = parseInt(id, 10);
return this.activeChoices.find(choice => choice.id === n);
}
return false;
}

View file

@ -16,13 +16,24 @@ export const TEMPLATES = /** @type {Templates} */ ({
const div = Object.assign(document.createElement('div'), {
className: containerOuter,
});
div.dataset.type = passedElementType;
if (dir) div.dir = dir;
if (isSelectOneElement) div.tabIndex = 0;
if (dir) {
div.dir = dir;
}
if (isSelectOneElement) {
div.tabIndex = 0;
}
if (isSelectElement) {
div.setAttribute('role', searchEnabled ? 'combobox' : 'listbox');
if (searchEnabled) div.setAttribute('aria-autocomplete', 'list');
if (searchEnabled) {
div.setAttribute('aria-autocomplete', 'list');
}
}
div.setAttribute('aria-haspopup', 'true');
div.setAttribute('aria-expanded', 'false');
@ -63,20 +74,31 @@ export const TEMPLATES = /** @type {Templates} */ ({
className: item,
innerHTML: label,
});
Object.assign(div.dataset, {
item: '',
id,
value,
customProperties,
});
if (active) div.setAttribute('aria-selected', 'true');
if (disabled) div.setAttribute('aria-disabled', 'true');
if (isPlaceholder) div.classList.add(placeholder);
if (active) {
div.setAttribute('aria-selected', 'true');
}
if (disabled) {
div.setAttribute('aria-disabled', 'true');
}
if (isPlaceholder) {
div.classList.add(placeholder);
}
div.classList.add(highlighted ? highlightedState : itemSelectable);
if (removeItemButton) {
if (disabled) div.classList.remove(itemSelectable);
if (disabled) {
div.classList.remove(itemSelectable);
}
div.dataset.deletable = '';
/** @todo This MUST be localizable, not hardcoded! */
const REMOVE_ITEM_TEXT = 'Remove item';
@ -99,8 +121,12 @@ export const TEMPLATES = /** @type {Templates} */ ({
const div = Object.assign(document.createElement('div'), {
className: list,
});
if (!isSelectOneElement) div.setAttribute('aria-multiselectable', 'true');
if (!isSelectOneElement) {
div.setAttribute('aria-multiselectable', 'true');
}
div.setAttribute('role', 'listbox');
return div;
},
@ -108,15 +134,26 @@ export const TEMPLATES = /** @type {Templates} */ ({
const div = Object.assign(document.createElement('div'), {
className: `${group} ${disabled ? itemDisabled : ''}`,
});
div.setAttribute('role', 'group');
Object.assign(div.dataset, { group: '', id, value });
if (disabled) div.setAttribute('aria-disabled', 'true');
Object.assign(div.dataset, {
group: '',
id,
value,
});
if (disabled) {
div.setAttribute('aria-disabled', 'true');
}
div.appendChild(
Object.assign(document.createElement('div'), {
className: groupHeading,
innerHTML: value,
}),
);
return div;
},
@ -140,17 +177,22 @@ export const TEMPLATES = /** @type {Templates} */ ({
disabled ? itemDisabled : itemSelectable
} ${isPlaceholder ? placeholder : ''}`,
});
div.setAttribute('role', groupId > 0 ? 'treeitem' : 'option');
Object.assign(div.dataset, {
choice: '',
id,
value,
selectText,
});
if (disabled) {
div.dataset.choiceDisabled = '';
div.setAttribute('aria-disabled', 'true');
} else div.dataset.choiceSelectable = '';
} else {
div.dataset.choiceSelectable = '';
}
return div;
},
@ -162,21 +204,30 @@ export const TEMPLATES = /** @type {Templates} */ ({
autocapitalize: 'off',
spellcheck: false,
});
inp.setAttribute('role', 'textbox');
inp.setAttribute('aria-autocomplete', 'list');
inp.setAttribute('aria-label', placeholderValue);
return inp;
},
dropdown({ list, listDropdown }) {
const div = document.createElement('div');
div.classList.add(list, listDropdown);
div.setAttribute('aria-expanded', 'false');
return div;
},
notice({ item, itemChoice, noResults, noChoices }, innerHTML, type = '') {
const classes = [item, itemChoice];
if (type === 'no-choices') classes.push(noChoices);
else if (type === 'no-results') classes.push(noResults);
if (type === 'no-choices') {
classes.push(noChoices);
} else if (type === 'no-results') {
classes.push(noResults);
}
return Object.assign(document.createElement('div'), {
innerHTML,
className: classes.join(' '),
@ -184,8 +235,12 @@ export const TEMPLATES = /** @type {Templates} */ ({
},
option({ label, value, customProperties, active, disabled }) {
const opt = new Option(label, value, false, active);
if (customProperties) opt.dataset.customProperties = customProperties;
if (customProperties) {
opt.dataset.customProperties = customProperties;
}
opt.disabled = disabled;
return opt;
},
});