2013年3月26日火曜日

[Twitter Bootstrap]typeaheadでの日本語入力問題への対策

[Twitter Bootstrap]typeaheadの項目をajaxで取得するコード例

上記の記事にて、日本語入力に問題ないと書きましたが嘘でした。

現状、問題を二つ発見しました。一応対処できたのでシェアします。

1.日本語を入力し、文字変換確定のEnterを押すと、その間に表示されていたtypeahedの候補を選択したことになってしまう。(Safari5.1.7で発生。chrome25.0.1364.172 mは問題なかった。)


【問題内容】

 A.キーボード入力開始
     ↓
 B.一つのキーを押すごとに候補が表示されていく。一番上の候補が選択状態となる。
     ↓
  C.文字変換確定のためにEnterキーを押す。
     ↓
 D.Bで表示されていた候補の一番上のものが選択され、テキストボックスに入ってしまう。

例として私の開発環境での事例を紹介する。
「ファ」と入力した段階(まだ候補確定のEnterキーは押していない)では、typeaheadの候補としては、「ファッション」、「メンズファッション」が表示され、一番上の「ファッション」が選択れた状態だった。
そこで、「ファ」を確定させるためEnterキーを押すと、「ファッション」とテキストボックスに入ってしまうのだ。「ファ」と入力したいだけなのに。

【対処方法】

1.Bで表示される候補のうちどれも選択されないようにする。

  このサイトを参考にさせていただいた。
 Bootstrap Typeaheadの日本語入力対応
 このサイトに書いてあるbootstrap.jsのある部分をコメントアウトする。
 ただし、私の場合、これだけだと足りなかった。
 確かに、Bで一つも選択状態になっていない候補が表示されるのがだ、CでEnterを押すと、テキストボックスが空になってしまう。おそらく、0文字の候補を選択してEnterを押したように解釈されてしまうのだろう。そこで以下の対処も行った。

2.オプションのupdaterを選択した候補が0文字だったらqueryを返すようなロジックにする。

下記の10~16行目を追加した。 これで、Enterを押しても空欄とならず、入力しようとしていた文字列が入ってくるようになった。
※7~9行目のsorterが気になる方は「[Twitter Bootstrap]typeaheadがせっかくサーバ側でソートした配列をソートし直しちゃう件への対処 」をご覧下さい。

$("#tagSelectInput").typeahead({
    source: function(query, process) {
        $.post($("#tagSelectInput").attr("data-url"), { 'data[Tag][content]': query}, function(data) {
            process(JSON.parse(data));
        });
    },
    sorter:function(items){
        return items;
    },
    updater:function(item){//選択してない状態でenter押すと、空欄になってしまうので。
        if(item.length==0){
            return this.query;
        }else{
            return item;
        }
    }
});

2.日本語入力にて文字列入力中も変換確定のEnter押下時もtypeahedの候補が表示されない。(FireFox19.0.2で発生。safari、chromeはOK)


【対処方法】

bootstrap.jsのEnterを押した時のイベントの部分に、明示的に候補を探してくるコマンドを入れた。(1950行目あたり。)
以下でいうと12~15行目あたりを修正した。もともとここに、this.lookup()はなかった。FireFoxのためにここにこれを入れてしまうと、正常に動いているブラウザでは一回余計に検索をかけにサーバ側にアクセスしてしまうかなと心配したが、なぜかアクセス回数は増えずに済んだ。 もし増えたら、ブラウザの種類を判定してFireFoxだけ行うようにしようと思っていたが。

 , keyup: function (e) {
    switch(e.keyCode) {
      case 40: // down arrow
      case 38: // up arrow
      case 16: // shift
      case 17: // ctrl
      case 18: // alt
        break

      case 9: // tab
      case 13: // enter
        if (!this.shown){
            this.lookup();
            return;
        }
        this.select()
        break

      case 27: // escape
        if (!this.shown) return
        this.hide()
        break

      default:
        this.lookup()
    }

    e.stopPropagation()
    e.preventDefault()
}
上記の対処で違和感なく動くようになっています。ついでにIE8でみたけど問題なかったです。
ちなみにbootstrapはbootstrap-transition.js v2.2.2です。

以下と合わせて読めば、Bootstrapのtypeahedをajaxで日本語入力で使うのにお役に立つかと思います。

[Twitter Bootstrap]typeaheadの項目をajaxで取得するコード例
[Twitter Bootstrap]typeaheadがせっかくサーバ側でソートした配列をソートし直しちゃう件への対処 


【その他参考ページ】
Getting More From Twitter Bootstrap’s Typeahead Library
How to Use JSON Objects With Twitter Bootstrap Typeahead

0 件のコメント:

コメントを投稿