Skip to content

Instantly share code, notes, and snippets.

@searls
Created June 17, 2018 19:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save searls/32668e9f358d8fe35253da857ea96277 to your computer and use it in GitHub Desktop.
Save searls/32668e9f358d8fe35253da857ea96277 to your computer and use it in GitHub Desktop.

Accept Japanese full-width numerals in HTML5 input[type=number] fields

As a compassionate human, the fact that full-width alphanumeric characters (i.e. 'abc' or '123') produced by Japanese IME/keyboards don't work in virtually any software form fields (even in software created in Japan!) has always bothered the hell out of me. Being a software user is a miserable enough existence before you start piling on unintended consequences of the Western hegemony of consumer technology on top.

Since HTML 5 is new-ish and technologists are starting to come around to the idea that users exist outside the English-speaking Bay Area, I figured they'd have considered full-width numeric characters for the 'number' input type (e.g. <input type="number"/>). If you're not familiar, the type is super handy for providing client-side validation "for free" by the browser. If someone types something else in there, the browser will bark at them.

Well, in my new app I'm encouraging users to practice Japanese with Japanese keyboards, and users started complaining that my number fields were broken.

I started digging into this in this little Tootstorm, and was disappointed (but not surprised) to find that the WHATWG specifies that only valid floating point numbers are accepted as valid by this field type. What I'd prefer to have happened is that this semantic form type would have specified that full-width numerals would be magically converted to parseable strings of numbers when provided as form data or to JavaScript code. Instead, the browser does the stupid thing and will report to the user that '123' not a number and Japanese users will be forced to retype it.

Making matters worse, layer after layer of well-intended protections to withhold invalid values via JavaScript made fixing my user's issue unnecessarily difficult.

I wound up having to give up on the number type field, falling back on text, and then writing my own custom validation logic and conversion from full-width numbers to parseable ascii (half-width) ones.

Here's the preact component that shook out:

const japanFriendlyNumberInput = (name, defaultValue) => {
  return h('input', {id: name, name: name,
    value: defaultValue,
    type: 'text',
    pattern: '[0-9]*',
    required: true,
    autocomplete: 'off',
    onChange (e) {
      const input = e.target
      input.value = input.value.replace(/[\uFF10-\uFF19]/g, c =>
        String.fromCharCode(c.charCodeAt(0) - 0xfee0)
      )
      input.setCustomValidity(/^\d+$/.test(input.value) ? '' :
        'Please input a number')
    }
  })
}

Neat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment