HTMLのselectboxをクリックだけで複数選択できるようにしようとして失敗した話

HTMLのselectboxはmultiple属性を持たせることで複数選択できるようになります。便利でありがたいのですが、複数選択するには、Ctrlを押しながらクリックする必要があります。普通にクリックすると選んでいたものが全て消えてしまうので、不慣れな方には残酷な動作です。

普通にクリックしても、Ctrlを押したときと同じように複数選択できたら嬉しい。

プラグインは色々あるようなのですが、まるごと置き換える系が主のようです。見た目が変わらずにできないの?ちょこちょこっと何とかすればいけるんじゃないの?と思い試しにやってみました。

Ctrlキーを押してることにならないか

javascriptのevent引数にctrlKeyというプロパティがあり、押されているとtrueが返ってきます。こいつに無理やりtrueを入れてやると押されてることにならないか。

MouseEvent.ctrlKey – Web API インターフェイス | MDN

残念。read-onlyなプロパティでした。きっと大本のプロパティがいるのでしょうが、判りませんでした。秩序のために操作できないのかもしれません。

選択項目を押したときに代わりにCtrlの動作をさせる

選択項目をクリックしたときに、普通にクリックされていたらCtrlを押したときみたいた動作をさせられないか。それにはまず通常の動作を握り潰す必要がありますが、そこは以下で可能です。

event.preventDefault – Web API インターフェイス | MDN

HTMLは階層になっていますが、こいつを呼ぶとイベントが上に行かなくなるようです???(いまいち詳しく判っていません)。握りつぶせたら代わりに選択する動作を書きましょう。jqueryだと以下になります。

var selected = $(this).prop('selected');
$(this).prop('selected', (!selected) ? true : false);

書き方は洗練されていないと思われます。いい加減ちゃんと学びたいものです。

そんで完成したのがこれです

    $('#multiple_select option').on('mousedown', function(e) {
        if (!e.ctrlKey && !e.shiftKey) {
            var selected = $(this).prop('selected');
            $(this).prop('selected', (!selected) ? true : false);
            $(this).parent().focus();

            e.preventDefault();
        }
    });

clickイベントでは確かイベントが潰せず、mousedownイベントになりました。crtlかshiftが押されていたら通常動作に任せています。また、フォーカスも付けてみました。

Firefox 52.0.2で動作確認し、Chrome 56.0.2924.87でもぎりぎり動いていました。やったんじゃない?と思いましたが、IE11.953.14393.0ではまったく動作しませんでした。

何が起きたか

どうやらIE11では選択項目のmousedownイベントが発火されないようでした。それはまずい。もし、selectbox自体のmousedownイベントからクリックされた選択項目を見つけないといけないとなると、クリックされた座標をもらい、スクロール位置と選択要素の高さから、選択された要素を割り出す処理が必要です。

実現できますが、そこまで泥臭いことをする気にはなりませんでした。ブラウザの違いに影響を受けそうですし。そういった訳で、簡単には実現できませんでしたという話でした。ChromeやFirefoxだけで良いというならギリギリ動く感じですが、大人しく、ちゃんとしたライブラリを適用した方が早そうです。同じ轍を踏まぬようお願い致します。

以上です。