HTMLでフリックキーボードを作ろうとして、mouseupとtouchendの挙動の違いを知った

最近、会社でiPad用の業務用ウェブサイトを作っているのですが、ここは数値しか入力しないから数値しか入力できないようにしてほしいとか、ここは英数字とハイフンか入力しないからそれしか入力できないようにしてほしいとかいろいろ要望をいわれるため、HTMLでソフトウェアキーボードを自作してなんとか対応しています(まあ確かに、iPadのソフトウェアキーボードは使いにくい気はする)。
ちなみに、そういったキーボードを作成するのに参考にしたのは下記のサイト。
javascript、大きなテンキーのサンプル: 赤須Muのブログ
jQueryとCSSでソフトウェアキーボードをつくるチュートリアル | IDEA*IDEA
ここからいらないキーを排除したり、必要なキー(全て消すキー等)を入れたり、大きいボタンのレイアウトに調子したりして対応しました。最初、クリックイベントで作ってたんですが、どうもクリックイベントだと挙動がワンテンポ遅れるのでtouchendで実装しました(preventDefault()を使ってダブルタップで拡大しないようにもしている)。

まあそれはともかくとして、そういったキーボードを作っているうちにふと、テンキー入力のキーボードだってやろうと思えばHTMLで作れるんじゃね? と思って簡単なものを作ってみようと思いました。
で、作ってみたので、以下ソースコードと実行サンプル。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width"> 
        <title>フリックキーボード</title>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        <style>
            .flick-list{
                list-style:none;
                position:relative;
                padding:0;
                margin-left:50px;
                margin-top:50px;
            }
            .flick-list li{
                border:1px solid gray;
                font-size:25px;
                width:40px;
                height:40px;
                text-align:center;
                line-height:40px;
            }
            .flick-list li:hover{
                background-color:blue;
                color:white;
            }
            .flick-left,.flick-top,.flick-right,.flick-bottom{
                display: none;
                position:absolute;
                top:0;
                left:0;
            }
            .flick-list .flick-left{
                top:0;
                left:-41px;
            }
            .flick-list .flick-top{
                top:-41px;
                left:0;
            }
            .flick-list .flick-right{
                top:0px;
                left:41px;
            }   
            .flick-list .flick-bottom{
                top:41px;
                left:0;
            }
        </style>
    </head>
    <input type="text" id="flickInput">
    <ul class="flick-list">
        <li class="flick-median">あ</li>
        <li class="flick-left">い</li>
        <li class="flick-top">う</li>
        <li class="flick-right">え</li>
        <li class="flick-bottom">お</li>
    </ul>
    <script>
        var isTouch = ((typeof window.ontouchstart) !== 'undefined');
        var touchStart = isTouch ? 'touchstart' : 'mousedown';
        var touchEnd = isTouch ? 'touchend' : 'mouseup';

        $('.flick-median').on(touchStart, function(e){
            e.preventDefault();
            
            $(this).nextAll().show();
        });
        $('.flick-list li').on(touchEnd, function(e){
            e.preventDefault();
            
            var inputVal =$('#flickInput').val() + $(this).html();
            $('#flickInput').val(inputVal)
            
            $(this).parent().children(':not(.flick-median)').hide();
        });
    </script>
</html>

実行サンプル:フリックキーボード

61行目でタッチ対応のデバイスか確認し、62行目と63行目でタッチ対応端末と非対応の端末でイベントを分けています。mouseupに対応するのはtouchendだといろんなところで書いてあるので、マウスではmouseupとするところをタッチ対応端末ではtouchendとしています。

動作としては、『あ』と書かれたところをタッチ(もしくはマウスのボタンを押した時)に周りに『い』『う』『え』『お』と表示され、その部分に指を動かして手を離す(もしくはマウスのボタンを離す)と、その文字がテキストボックスに表示されるという動作にしようと思って作ってみました。

まずはマウスで試してみました。ちゃんと想定した動きになっています。

続いて、タッチで試してみました。CSSでhoverの指定をしたところがうまく動かないのはある程度予想していました。が、肝心のフリック入力までうまく動きません。『あ』のところをタッチすると『い』『う』『え』『お』が表示されるものの、そちらに指を動かして指を話しても、テキストボックスに入力されるのは『あ』。『い』のほうに指を動かして話しても『あ』。『お』のほうに指を動かして話しても『あ』。iPod touchのSafariでやっても、AndroidのChromeで試しても、PCのChromeで試してもそうなります(自分が使っているWindows7はタッチ対応です)。なんじゃこりゃ。

どうも、マウスイベントと違ったタッチイベントは、タッチした要素から外にでてもその要素上でタッチしたままと考えられているらしい(参考:androidとWebアプリケーション | 日記というか備忘録というか)。
W3Cのサイトにある勧告文もそんな感じのことが書いてあった(Touch Events)。touchmoveイベントの2つ目の段落にそれっぽいことが書かれているような気はする。ただ、英語は苦手なので本当にそう書いてあるかどうかはわからない。

ということで、簡単にはフリックキーボードは実装できなさそう。やるとしたら、touchendが発生した座標がどの位置にあたるかを見ればできるかもしれない。

ただ、フリックキーボード自体は思いつきで作ろうとしただけであり、必要にせまられて作ろうとしたわけではないので、実際に作るかどうかはわからないです。

2014年5月22日追記:
作ってみました:JavaScriptでフリックキーボードを作ってみた(再挑戦) | while(isプログラマ)

コメント

タイトルとURLをコピーしました