よーし、パパ jQuery と CSS3 でフリック入力風の UI 作っちゃうぞ!の巻

去年の8月末に長年のドコモ人生に終わりをつげ SoftbankiPhone 4S に変えて4ヶ月半。
告白しよう自分はフリック入力が苦手、いや極論すればフリック入力出来ないと言える。そう、すげー遅いのだ。

iPhone 使って練習するのも大変なんで、フリック入力を練習する UI を作ってみようと思う。
あ・か・さ・た・な・っつーようなボタンをクリックしたら4近傍(十字)に、その行のそれ以外の文字が出る。

<ul class="key-pad">
    <li id="a" class="button"></li>
    <li id="ka" class="button"></li>
    <li id="sa" class="button"></li>
    <li id="ta" class="button"></li>
    <li id="na" class="button"></li>
    <li id="ha" class="button"></li>
</ul>

最近のトレンドっつーか、inline-block 化したリストをボタンに見立てる構成。
適用する CSS はリセット CSS と少しだけ。

 *
{
    font-size: 16px;
    font-family: 'ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro','メイリオ',Meiryo,Verdana,'MS Pゴシック',sans-serif;
    margin: 0px;
    padding: 0px;
}
 
.key-pad li {
    position: absolute;
    display: inline-block;
    width: 40px;
    height: 40px;
    border: 1px solid gray;
    line-height: 40px;
    text-align: center;
}

jQuery つかってマウスイベント取っ捕まえる。自分が使ってるのは Mac Book Air なんやけど、わざわざマウス繋いで実験してる。
class='button' の上でマウスダウンしたら、背景色が青くなって、マウスアップしたら白くなる。

    $(document).ready(function(){
        $('.button').mousedown(function() {
            $(this).css('background-color', 'blue');
        });
        $(window).mouseup(function() {
            $('.button').css('background-color', 'white');
        });
    });

マウスキャプチャーって概念があるけど、クライアント領域を外れたところでのイベント通知って無くなるのが普通なんで

    $(document).ready(function(){
        $('.button').mousedown(function() {
            $(this).css('background-color', 'blue');
        }).mouseup(function() {
            $(this).css('background-color', 'white');
        });
    });

こういう風に描いちゃうと、マウスダウンした HTML 要素を外れた位置でマウスアップされた時にイベントが取れないのな。

※もしも JavaScript でやってて、実際にウェブブラウザの外でマウスアップされたら拾えるのかな?
(OS レベルでマウスキャプチャーしててくれれば大丈夫かも)

この辺からちょっと大変になってくるかも。
マウスダウン時に4近傍隣接区間に同じ矩形を出したいんで、クローンして実体化させて位置だけずらす。
HTML5 時代だと逆に 2Dゲームよろしく Canvas にゴリゴリ書くっつーアプローチもあるかもやけど、ここでは純粋に HTML と CSS で解決する。

    $(document).ready(function(){
        var left = 100, top = 100;
        var cnt = 0;
        //初期の位置に移動させる。
        $('.button').each(function() {
            var x = cnt % 3;
            var y = Math.floor(cnt / 3);
            $(this).css({
                'left' : (x * 40 + left) + 'px',
                'top' : (y * 40 + top) + 'px'
            });
            cnt = cnt + 1;
        });
        //ボタンのクリック処理
        $('.button').mousedown(function() {
            var parent = $(this).parent();
            //jQuery UI の力も借りる
            var sx = $(this).position().left;
            var sy = $(this).position().top;
            var left = $(this).clone();
            left.css({
                'background-color' : 'whitesmoke',
                'z-index' : 1000
            }).addClass('temporal');
            var right = left.clone();
            var top = left.clone();
            var bottom = left.clone();
            //要素に 1px のボーダーついてるんで、40 + 1 + 1
            left.css({
                'left' : (sx - 42) + 'px'
            }).text('い');//とりあえず決め打ちで。座標系を先に解決する
            right.css({
                'left' : (sx + 42) + 'px'
            }).text('え');
            top.css({
                'top' : (sy - 42) + 'px'
            }).text('う');
            bottom.css({
                'top' : (sy + 42) + 'px'
            }).text('お');
            parent.append(left);
            parent.append(right);
            parent.append(top);
            parent.append(bottom);
        });
        $(window).mouseup(function() {
            $('.temporal').remove();
        });
    });

平易な実装を心がけたんで、DRY 違反と即値が気になるけど習作レベルなので、まあええわ。(本当はローカル変数名の被りはアカンけどな、スコープチェインとかクロージャの話は雑にすまして良い話じゃ無いんで、命名はきちんとせなアカン)
きちんとリファクタリングはする予定。

HTML の要素ってのは原則的に相対位置に配置されていく。それを乗り越えるのが CSS での position :absolute って奴で実際の座標を指定してる感じ。
実行結果は


こんな感じ。

ここまでの全ソースは

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja-JP" xml:lang="ja-JP">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="ja" />
<meta name="robots" content="all" />
<title></title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script src="jquery-1.8.2.js" type="text/javascript" charset="UTF-8"></script>
<script src="jquery-ui.custom.js" type="text/javascript" type="text/javascript" charset="UTF-8"></script>
<style type="text/css">
*
{
    font-size: 16px;
    font-family: 'ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro','メイリオ',Meiryo,Verdana,'MS Pゴシック',sans-serif;
    margin: 0px;
    padding: 0px;
}
 
.key-pad li {
    position: absolute;
    display: inline-block;
    width: 40px;
    height: 40px;
    border: 1px solid gray;
    line-height: 40px;
    text-align: center;
}
</style>
<script type="text/javascript">
    $(document).ready(function(){
        var left = 100, top = 100;
        var cnt = 0;
        //初期の位置に移動させる。
        $('.button').each(function() {
            var x = cnt % 3;
            var y = Math.floor(cnt / 3);
            $(this).css({
                'left' : (x * 40 + left) + 'px',
                'top' : (y * 40 + top) + 'px'
            });
            cnt = cnt + 1;
        });
        //ボタンのクリック処理
        $('.button').mousedown(function() {
            var parent = $(this).parent();
            //jQuery UI の力も借りる
            var sx = $(this).position().left;
            var sy = $(this).position().top;
            var left = $(this).clone();
            left.css({
                'background-color' : 'whitesmoke',
                'z-index' : 1000
            }).addClass('temporal');
            var right = left.clone();
            var top = left.clone();
            var bottom = left.clone();
            //要素に 1px のボーダーついてるんで、40 + 1 + 1
            left.css({
                'left' : (sx - 42) + 'px'
            }).text('い');//とりあえず決め打ちで。座標系を先に解決する
            right.css({
                'left' : (sx + 42) + 'px'
            }).text('え');
            top.css({
                'top' : (sy - 42) + 'px'
            }).text('う');
            bottom.css({
                'top' : (sy + 42) + 'px'
            }).text('お');
            parent.append(left);
            parent.append(right);
            parent.append(top);
            parent.append(bottom);
        });
        $(window).mouseup(function() {
            $('.temporal').remove();
        });
    });
</script>
</head>
<body>
<ul class="key-pad">
    <li id="a" class="button"></li>
    <li id="ka" class="button"></li>
    <li id="sa" class="button"></li>
    <li id="ta" class="button"></li>
    <li id="na" class="button"></li>
    <li id="ha" class="button"></li>
</ul>
</body>
</html>

jQueryjQuery UI だけあれば、ここまでは大体動くと思う。
眠くなってきちゃったんで、今日はここまで。

IE10 での CSS3 の実装状況も確認したいから最終的にはきちんと CSS3 でデザインするとこまで持ってく。