mirror of
https://github.com/Choices-js/Choices.git
synced 2024-06-01 13:32:23 +02:00
Merge f0a3965d4e
into 5dbea2825a
This commit is contained in:
commit
9a37556d3f
|
@ -1,4 +1,4 @@
|
||||||
/*! choices.js v10.2.0 | © 2022 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
|
/*! choices.js v10.2.0 | © 2023 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
|
||||||
(function webpackUniversalModuleDefinition(root, factory) {
|
(function webpackUniversalModuleDefinition(root, factory) {
|
||||||
if(typeof exports === 'object' && typeof module === 'object')
|
if(typeof exports === 'object' && typeof module === 'object')
|
||||||
module.exports = factory();
|
module.exports = factory();
|
||||||
|
@ -1263,9 +1263,30 @@ var Choices = /** @class */function () {
|
||||||
var hasFocusedInput = this.input.isFocussed;
|
var hasFocusedInput = this.input.isFocussed;
|
||||||
var hasActiveDropdown = this.dropdown.isActive;
|
var hasActiveDropdown = this.dropdown.isActive;
|
||||||
var hasItems = this.itemList.hasChildren();
|
var hasItems = this.itemList.hasChildren();
|
||||||
var keyString = String.fromCharCode(keyCode);
|
/*
|
||||||
// eslint-disable-next-line no-control-regex
|
See:
|
||||||
var wasPrintableChar = /[^\x00-\x1F]/.test(keyString);
|
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
|
||||||
|
https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
|
||||||
|
https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF - UTF-16 surrogate pairs
|
||||||
|
https://stackoverflow.com/a/70866532 - "Unidentified" for mobile
|
||||||
|
http://www.unicode.org/versions/Unicode5.2.0/ch16.pdf#G19635 - U+FFFF is reserved (Section 16.7)
|
||||||
|
Logic: when a key event is sent, `event.key` represents its printable value _or_ one
|
||||||
|
of a large list of special values indicating meta keys/functionality. In addition,
|
||||||
|
key events for compose functionality contain a value of `Dead` when mid-composition.
|
||||||
|
I can't quite verify it, but non-English IMEs may also be able to generate key codes
|
||||||
|
for code points in the surrogate-pair range, which could potentially be seen as having
|
||||||
|
key.length > 1. Since `Fn` is one of the special keys, we can't distinguish by that
|
||||||
|
alone.
|
||||||
|
Here, key.length === 1 means we know for sure the input was printable and not a special
|
||||||
|
`key` value. When the length is greater than 1, it could be either a printable surrogate
|
||||||
|
pair or a special `key` value. We can tell the difference by checking if the _character
|
||||||
|
code_ value (not code point!) is in the "surrogate pair" range or not.
|
||||||
|
We don't use .codePointAt because an invalid code point would return 65535, which wouldn't
|
||||||
|
pass the >= 0x10000 check we would otherwise use.
|
||||||
|
> ...The Unicode Standard sets aside 66 noncharacter code points. The last two code points
|
||||||
|
> of each plane are noncharacters: U+FFFE and U+FFFF on the BMP...
|
||||||
|
*/
|
||||||
|
var wasPrintableChar = event.key.length === 1 || event.key.length === 2 && event.key.charCodeAt(0) >= 0xD800 || event.key === 'Unidentified';
|
||||||
var BACK_KEY = constants_1.KEY_CODES.BACK_KEY,
|
var BACK_KEY = constants_1.KEY_CODES.BACK_KEY,
|
||||||
DELETE_KEY = constants_1.KEY_CODES.DELETE_KEY,
|
DELETE_KEY = constants_1.KEY_CODES.DELETE_KEY,
|
||||||
ENTER_KEY = constants_1.KEY_CODES.ENTER_KEY,
|
ENTER_KEY = constants_1.KEY_CODES.ENTER_KEY,
|
||||||
|
@ -1275,15 +1296,15 @@ var Choices = /** @class */function () {
|
||||||
DOWN_KEY = constants_1.KEY_CODES.DOWN_KEY,
|
DOWN_KEY = constants_1.KEY_CODES.DOWN_KEY,
|
||||||
PAGE_UP_KEY = constants_1.KEY_CODES.PAGE_UP_KEY,
|
PAGE_UP_KEY = constants_1.KEY_CODES.PAGE_UP_KEY,
|
||||||
PAGE_DOWN_KEY = constants_1.KEY_CODES.PAGE_DOWN_KEY;
|
PAGE_DOWN_KEY = constants_1.KEY_CODES.PAGE_DOWN_KEY;
|
||||||
if (!this._isTextElement && !hasActiveDropdown && wasPrintableChar) {
|
if (!this._isTextElement && !hasActiveDropdown) {
|
||||||
this.showDropdown();
|
this.showDropdown();
|
||||||
if (!this.input.isFocussed) {
|
if (!this.input.isFocussed && wasPrintableChar) {
|
||||||
/*
|
/*
|
||||||
We update the input value with the pressed key as
|
We update the input value with the pressed key as
|
||||||
the input was not focussed at the time of key press
|
the input was not focussed at the time of key press
|
||||||
therefore does not have the value of the key.
|
therefore does not have the value of the key.
|
||||||
*/
|
*/
|
||||||
this.input.value += event.key.toLowerCase();
|
this.input.value += event.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
|
|
2
public/assets/scripts/choices.min.js
vendored
2
public/assets/scripts/choices.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
/*! choices.js v10.2.0 | © 2022 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
|
/*! choices.js v10.2.0 | © 2023 Josh Johnson | https://github.com/jshjohnson/Choices#readme */
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2196,16 +2196,17 @@ describe('choices', () => {
|
||||||
|
|
||||||
describe('direction key', () => {
|
describe('direction key', () => {
|
||||||
const keyCodes = [
|
const keyCodes = [
|
||||||
KEY_CODES.UP_KEY,
|
[KEY_CODES.UP_KEY, 'ArrowUp'],
|
||||||
KEY_CODES.DOWN_KEY,
|
[KEY_CODES.DOWN_KEY, 'ArrowDown'],
|
||||||
KEY_CODES.PAGE_UP_KEY,
|
[KEY_CODES.PAGE_UP_KEY, 'PageUp'],
|
||||||
KEY_CODES.PAGE_DOWN_KEY,
|
[KEY_CODES.PAGE_DOWN_KEY, 'PageDown'],
|
||||||
];
|
];
|
||||||
|
|
||||||
keyCodes.forEach((keyCode) => {
|
keyCodes.forEach(([keyCode, key]) => {
|
||||||
it(`calls _onDirectionKey with the expected arguments`, () => {
|
it(`calls _onDirectionKey with the expected arguments`, () => {
|
||||||
const event = {
|
const event = {
|
||||||
keyCode,
|
keyCode,
|
||||||
|
key,
|
||||||
};
|
};
|
||||||
|
|
||||||
instance._onKeyDown(event);
|
instance._onKeyDown(event);
|
||||||
|
@ -2222,6 +2223,7 @@ describe('choices', () => {
|
||||||
it(`calls _onSelectKey with the expected arguments`, () => {
|
it(`calls _onSelectKey with the expected arguments`, () => {
|
||||||
const event = {
|
const event = {
|
||||||
keyCode: KEY_CODES.A_KEY,
|
keyCode: KEY_CODES.A_KEY,
|
||||||
|
key: 'A',
|
||||||
};
|
};
|
||||||
|
|
||||||
instance._onKeyDown(event);
|
instance._onKeyDown(event);
|
||||||
|
@ -2237,6 +2239,7 @@ describe('choices', () => {
|
||||||
it(`calls _onEnterKey with the expected arguments`, () => {
|
it(`calls _onEnterKey with the expected arguments`, () => {
|
||||||
const event = {
|
const event = {
|
||||||
keyCode: KEY_CODES.ENTER_KEY,
|
keyCode: KEY_CODES.ENTER_KEY,
|
||||||
|
key: 'Enter',
|
||||||
};
|
};
|
||||||
|
|
||||||
instance._onKeyDown(event);
|
instance._onKeyDown(event);
|
||||||
|
@ -2250,12 +2253,20 @@ describe('choices', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('delete key', () => {
|
describe('delete key', () => {
|
||||||
const keyCodes = [KEY_CODES.DELETE_KEY, KEY_CODES.BACK_KEY];
|
// this is not an error; the constants are named the reverse of their assigned key names, according
|
||||||
|
// to their actual values, which appear to conform to the Windows VK mappings:
|
||||||
|
// 0x08 = 'Backspace', 0x2E = 'Delete'
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values#editing_keys
|
||||||
|
const keyCodes = [
|
||||||
|
[KEY_CODES.DELETE_KEY, 'Backspace'],
|
||||||
|
[KEY_CODES.BACK_KEY, 'Delete'],
|
||||||
|
];
|
||||||
|
|
||||||
keyCodes.forEach((keyCode) => {
|
keyCodes.forEach(([keyCode, key]) => {
|
||||||
it(`calls _onDeleteKey with the expected arguments`, () => {
|
it(`calls _onDeleteKey with the expected arguments`, () => {
|
||||||
const event = {
|
const event = {
|
||||||
keyCode,
|
keyCode,
|
||||||
|
key
|
||||||
};
|
};
|
||||||
|
|
||||||
instance._onKeyDown(event);
|
instance._onKeyDown(event);
|
||||||
|
|
|
@ -1440,9 +1440,39 @@ class Choices implements Choices {
|
||||||
const hasFocusedInput = this.input.isFocussed;
|
const hasFocusedInput = this.input.isFocussed;
|
||||||
const hasActiveDropdown = this.dropdown.isActive;
|
const hasActiveDropdown = this.dropdown.isActive;
|
||||||
const hasItems = this.itemList.hasChildren();
|
const hasItems = this.itemList.hasChildren();
|
||||||
const keyString = String.fromCharCode(keyCode);
|
/*
|
||||||
// eslint-disable-next-line no-control-regex
|
See:
|
||||||
const wasPrintableChar = /[^\x00-\x1F]/.test(keyString);
|
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
|
||||||
|
https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
|
||||||
|
https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF - UTF-16 surrogate pairs
|
||||||
|
https://stackoverflow.com/a/70866532 - "Unidentified" for mobile
|
||||||
|
http://www.unicode.org/versions/Unicode5.2.0/ch16.pdf#G19635 - U+FFFF is reserved (Section 16.7)
|
||||||
|
|
||||||
|
Logic: when a key event is sent, `event.key` represents its printable value _or_ one
|
||||||
|
of a large list of special values indicating meta keys/functionality. In addition,
|
||||||
|
key events for compose functionality contain a value of `Dead` when mid-composition.
|
||||||
|
|
||||||
|
I can't quite verify it, but non-English IMEs may also be able to generate key codes
|
||||||
|
for code points in the surrogate-pair range, which could potentially be seen as having
|
||||||
|
key.length > 1. Since `Fn` is one of the special keys, we can't distinguish by that
|
||||||
|
alone.
|
||||||
|
|
||||||
|
Here, key.length === 1 means we know for sure the input was printable and not a special
|
||||||
|
`key` value. When the length is greater than 1, it could be either a printable surrogate
|
||||||
|
pair or a special `key` value. We can tell the difference by checking if the _character
|
||||||
|
code_ value (not code point!) is in the "surrogate pair" range or not.
|
||||||
|
|
||||||
|
We don't use .codePointAt because an invalid code point would return 65535, which wouldn't
|
||||||
|
pass the >= 0x10000 check we would otherwise use.
|
||||||
|
|
||||||
|
> ...The Unicode Standard sets aside 66 noncharacter code points. The last two code points
|
||||||
|
> of each plane are noncharacters: U+FFFE and U+FFFF on the BMP...
|
||||||
|
*/
|
||||||
|
const wasPrintableChar = (
|
||||||
|
event.key.length === 1
|
||||||
|
|| (event.key.length === 2 && event.key.charCodeAt(0) >= 0xD800)
|
||||||
|
|| event.key === 'Unidentified'
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
BACK_KEY,
|
BACK_KEY,
|
||||||
|
@ -1456,16 +1486,16 @@ class Choices implements Choices {
|
||||||
PAGE_DOWN_KEY,
|
PAGE_DOWN_KEY,
|
||||||
} = KEY_CODES;
|
} = KEY_CODES;
|
||||||
|
|
||||||
if (!this._isTextElement && !hasActiveDropdown && wasPrintableChar) {
|
if (!this._isTextElement && !hasActiveDropdown) {
|
||||||
this.showDropdown();
|
this.showDropdown();
|
||||||
|
|
||||||
if (!this.input.isFocussed) {
|
if (!this.input.isFocussed && wasPrintableChar) {
|
||||||
/*
|
/*
|
||||||
We update the input value with the pressed key as
|
We update the input value with the pressed key as
|
||||||
the input was not focussed at the time of key press
|
the input was not focussed at the time of key press
|
||||||
therefore does not have the value of the key.
|
therefore does not have the value of the key.
|
||||||
*/
|
*/
|
||||||
this.input.value += event.key.toLowerCase();
|
this.input.value += event.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue