ブラウザでのテキスト入力の制御や監視について

数ヶ月前に調べた、ブラウザでのテキスト入力の制御や監視についてのメモを埋もれさせておくのがもったいなく感じたので一応ここに書いておこうかと。

HTML

  • type属性
    • email
    • url
    • tel
    • number
    • date
    • etc.

iOSだったり、Androidだったりではキーボードが変化するものもあるのでそもそも入力が制限されたりするのを利用できるかも。

  • pattern属性
    • 正規表現でパターンを指定できる
    • ブラウザ側では制御してくれない?
  • maxlength属性
    • 文字数制限できる

pattern属性は正規表現で入力パターンを限定できるようなのだけど、Google ChromeとMozilla Firefoxで試してみて思った通りには動いてないような気が…… maxlength属性は入力文字数を制限できる。昔からある。

CSS

  • ime-mode

    • Windows Internet Explorer限定
    • disabledにすれば英数字しか入力できなくなる
  • text-transform

    • テキストの大文字・小文字を変換する
    • 実際に入力されたデータが小文字でも、uppercaseを指定すれば見た目は大文字で入力されたようになる
    • 逆もしかり

ime-modeプロパティはIEでしか使えないのだけど、英数字だけしか入力させたくないときにとても便利。JavaScriptで制御する必要もない。 text-transformは見た目上は大文字にしなければいけないのだけど、変換ロジック書くのが面倒なときで、一度だけ使うことがあった。 まあ、JavaScriptでtoUpperCase()をすればよいのだけど、このときは文字入力毎にと言われた上に時間も無かったので見た目だけ大文字にして、サーバサイドで変換するようにしてもらった。

JavaScript

大抵は上記のいずれかでも出来ない制御をしようとすることが多いと思うのだけど、そうするとどうしてもJavaScriptを使う必要が出てくると思う。 ここからはいろいろ試してみたりしたものだったりとか、参考リンクだったりとか。

入力制御が出来るjQueryプラグインを作ろうとしていろいろ調べたのだけど、ブラウザ毎の挙動がかなり異なっていたり面倒だったのでちょっと諦めた。 そこそこ頑張ったのでちょっとした参考にはなるかもしれないので一応……

  • onChange
    • おなじみonChange
  • onKeyDown
    • おなじみonKeyDown
  • onKeyPress
    • おなじみonKeyPress
  • onPaste
    • 貼付けをしたときのイベント
  • onInput
    • input, textareaの文字列が変更されたときに発生するイベント
    • モダンブラウザでないと対応していない上に、IE9はバグがあるらしい
    • http://help.dottoro.com/ljhxklln.php
    • The oninput event is buggy in Internet Explorer 9. It is not fired when characters are deleted from a text field through the user interface only when characters are inserted. Although the onpropertychange event is supported in Internet Explorer 9, but similarly to the oninput event, it is also buggy, it is not fired on deletion.
  • onTextInput
  • onpropertychange

    • Internet Explorer専用イベント
    • これはこれでバグがある
    • http://stackoverflow.com/questions/6835375/onpropertychange-event-vs-keyup
    • onpropertychange is buggy in IE and doesn't fire for all keys (delete and backspace I think).
    • 自分で試したときは、jQueryでonKeyDownとonKeyPressを指定したらイベントが削除時しか実行されなくなった
  • backspaceについて

    • FirefoxはbackspaceがonKeyPressでも来る
    • 他のブラウザはonKeyDownで来るのだったかな?
  • IEでのonInput pollyfill

    • pastekeypressの末尾にinputのtriggerをsetTimeout(-> , 0)で入れると似た動きになるかも
    • 貼付けたときにonKeyPressが呼ばれる呼ばれないはブラウザによる

ペーストした際のイベント発生について

onKeyDown, onKeyPress, onInput, onKeyUpにログを入れて試した結果? たぶん上に貼ったjQueryプラグインのテストをしてるときの各ブラウザ毎の差異のはず。 onKeyDownとonKeyUpが2度入力されているのは、Ctrlキーとvキーそれぞれを押下したことによるものかと。

Fx

keydw: 
keydw: 
keypr: 
input: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html
keyup: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html
keyup: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html

Ch

keydw: 
keydw: 
input: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html
keyup: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html
keyup: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html

Sf

keydw: 
keydw: 
keypr: 
input: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html
keyup: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html

polyfilled IE8

keydw: 
keydw: 
input: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html
keyup: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html
keyup: http://ie.microsoft.com/testdrive/Performance/setImmediateSorting/Default.html

監視系メソッド

イベントがブラウザ毎に辛いなら、特定のブラウザだけとはいえ監視系イベントを使えばいいかも?と思って調べたもの。 結論からいうと、これらのイベントでvalueを監視しようとしても監視できない。DOMとイベントとかその辺を良く理解していないからわからないのかも。

Knockout.js / textInputバインディング

とまあ、いろいろと調べていてから少し放置していました。そのあとKnockout.jsを使うようになってtextInputバインディングというものがあるのを知ったのですが。

とても頑張ってる感があるというか…… コメントにとても詳しく書いてあるので、参考になると思う。

See the Pen Knockout convert from textInput by sasa+1 (@sasaplus1) on CodePen.

でもまあ、こんな感じで監視しつつ、入力してもらったら値を変えて別の変数に保存して、それを読み込むとかできるので古いブラウザにも対応する必要があるのならKnockout.jsのtextInputバインディングは有用なんじゃないかなーと思いました。 そもそも、モダンブラウザだけであればonInputが普通に使えるのでこんなに困らないし、Knockout.js以外のライブラリも使えるからtextInputバインディングにこだわる必要もないのだけど。

というわけで、レトロなブラウザも対象にした文字入力関連の制御をする場合は少しは参考になるかなーと書いてみた記事でした。