mirror of
https://github.com/Choices-js/Choices.git
synced 2026-03-14 14:45:47 +01:00
fix: account for wide CJK characters in setWidth() ch calculation
The setWidth() method used str.length to compute the ch-unit width for the search input's min-width / width style properties. This is incorrect for wide (full-width) Unicode characters such as Japanese (Hiragana / Katakana), Chinese (CJK Ideographs), Korean (Hangul), and fullwidth Latin forms -- each of these occupies 2ch in a standard browser font yet was counted as only 1. The result is that a Japanese placeholder like 'エリアを選択してください' (12 characters -> 24ch wide) was only given 13ch of min-width, causing the text to be clipped. Fix: replace both .length calls in setWidth() with a new module-level helper getStringWidth() that iterates the string's Unicode code points and adds 2 for any character in a wide/fullwidth Unicode block (standard wcwidth-style logic), and 1 for everything else. Fixes #1216
This commit is contained in:
parent
095ecb3589
commit
2d5bfd31f2
1 changed files with 46 additions and 3 deletions
|
|
@ -1,6 +1,46 @@
|
|||
import { ClassNames } from '../interfaces/class-names';
|
||||
import { PassedElementType, PassedElementTypes } from '../interfaces/passed-element-type';
|
||||
|
||||
/**
|
||||
* Returns the display width of a string in `ch` units.
|
||||
* Wide characters (CJK, Hangul, fullwidth forms, etc.) count as 2,
|
||||
* all other characters count as 1. This matches how browsers render
|
||||
* these characters relative to the `ch` unit (width of '0').
|
||||
*/
|
||||
function getStringWidth(str: string): number {
|
||||
let width = 0;
|
||||
for (const char of str) {
|
||||
const code = char.codePointAt(0) ?? 0;
|
||||
/* eslint-disable no-mixed-operators */
|
||||
if (
|
||||
(code >= 0x1100 && code <= 0x115f) || // Hangul Jamo
|
||||
code === 0x2329 ||
|
||||
code === 0x232a ||
|
||||
(code >= 0x2e80 && code <= 0x303e) || // CJK Radicals, Kangxi, CJK Symbols
|
||||
(code >= 0x3041 && code <= 0x33bf) || // Hiragana, Katakana, Bopomofo, CJK Compat
|
||||
(code >= 0x3400 && code <= 0x4dbf) || // CJK Extension A
|
||||
(code >= 0x4e00 && code <= 0x9fff) || // CJK Unified Ideographs
|
||||
(code >= 0xa000 && code <= 0xa4cf) || // Yi Syllables / Radicals
|
||||
(code >= 0xa960 && code <= 0xa97f) || // Hangul Jamo Extended-A
|
||||
(code >= 0xac00 && code <= 0xd7af) || // Hangul Syllables
|
||||
(code >= 0xf900 && code <= 0xfaff) || // CJK Compatibility Ideographs
|
||||
(code >= 0xfe10 && code <= 0xfe1f) || // Vertical Forms
|
||||
(code >= 0xfe30 && code <= 0xfe6f) || // CJK Compatibility Forms
|
||||
(code >= 0xff01 && code <= 0xff60) || // Fullwidth Latin / Punctuation
|
||||
(code >= 0xffe0 && code <= 0xffe6) || // Fullwidth Signs
|
||||
(code >= 0x1b000 && code <= 0x1b001) || // Kana Supplement
|
||||
(code >= 0x20000 && code <= 0x2fffd) || // CJK Extension B–D
|
||||
(code >= 0x30000 && code <= 0x3fffd) // CJK Extension E+
|
||||
) {
|
||||
width += 2;
|
||||
} else {
|
||||
width += 1;
|
||||
}
|
||||
/* eslint-enable no-mixed-operators */
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
export default class Input {
|
||||
element: HTMLInputElement;
|
||||
|
||||
|
|
@ -110,10 +150,13 @@ export default class Input {
|
|||
* value or input value
|
||||
*/
|
||||
setWidth(): void {
|
||||
// Resize input to contents or placeholder
|
||||
// Resize input to contents or placeholder.
|
||||
// Uses getStringWidth() instead of .length so that wide characters
|
||||
// (CJK, Hangul, fullwidth forms, etc.) are counted as 2ch rather than 1ch,
|
||||
// preventing placeholder text truncation for languages like Japanese.
|
||||
const { element } = this;
|
||||
element.style.minWidth = `${element.placeholder.length + 1}ch`;
|
||||
element.style.width = `${element.value.length + 1}ch`;
|
||||
element.style.minWidth = `${getStringWidth(element.placeholder) + 1}ch`;
|
||||
element.style.width = `${getStringWidth(element.value) + 1}ch`;
|
||||
}
|
||||
|
||||
setActiveDescendant(activeDescendantID: string): void {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue