HTMLフォームの数値入力で増減(スピナー)ボタンを実装

ユーザーに数値の入力を求めるフォームを作成する時があると思います。

その際、いちいちフォームをクリック(またはタップ)して数値を打ってもらうのではなく、ゲームみたいに直感的にボタンで操作できたほうがユーザーは楽できますよね。

ユーザーってとにかく「入力」という行為を嫌いますからね。

例を挙げると、ポケモンGOアプリのこういった↓操作です。

こんな風に、ボタンで数値を変動させられる機能があれば、入力を介する必要がなく、フォームのUIの向上に繋がると思います。

実はHTML標準で、<input type="number">とすると増減ボタンを表示させることが出来るのですが…。

これはボタン領域が狭すぎたり、そもそも大多数の人が扱うスマホでは扱えなかったり等、とても使えません。

jQuery UIでも「spinner」という機能が用意されていますが、やはりスマホユーザーに最適化されていませんでした。

他にもググって探してみましたが、長押しに対応していなかったり等、痒い所に手が届かないものが多かったので、自作するに至りました。

スピナー(増減)ボタンのソースコード

HTMLコード、CSSコード、JavaScript(jQueryコード)をそれぞれご確認ください。

HTMLコード

<div class="spinner_area">
    <input type="number" value="0" class="counter1" data-max="500" data-min="0">
    <input type="button" value="+" class="btnspinner" data-cal="1" data-target=".counter1">
    <input type="button" value="-" class="btnspinner" data-cal="-1" data-target=".counter1">
</div>

増減ボタンのクラスにbtnspinnerのクラスを設定してください。

また、増減ボタンにはdata-target属性を追加し、対象のinputフォームを指定してください。

また、inputフォームには、ボタンで操作できる数値の最大値(data-max)と最小値(data-min)を設定する必要があります。

CSSコード

.btnspinner{
    -ms-user-select: none;
    -moz-user-select: -moz-none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    user-select: none;
}

.spinner_area input{
    padding: 11px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 18px;
    width: auto;
    vertical-align: middle;
    /* デフォルトのスピナーを消す */
    -webkit-appearance: none;
    -moz-appearance:textfield;
}

.spinner_area input[type="button"]{
    cursor: pointer;
}

ボタンにuser-select: noneを付けている理由は、ボタンの長押しで選択領域の画面を表示させないようにするためです。

設定しないとスマホでは下記画像のように、吹き出しが表示される可能性があります。

JavaScript(jQuery)コード

<script>
$(function(){
    
    var arySpinnerCtrl = [];
    var spin_speed = 20; //変動スピード
    
    //長押し押下時
    $('.btnspinner').on('touchstart mousedown click', function(e){
        if(arySpinnerCtrl['interval']) return false;
        var target = $(this).data('target');
        arySpinnerCtrl['target'] = target;
        arySpinnerCtrl['timestamp'] = e.timeStamp;
        arySpinnerCtrl['scroll'] = $(window).scrollTop();
        arySpinnerCtrl['cal'] = Number($(this).data('cal'));
        //クリックは単一の処理に留める
        if(e.type == 'click'){
            spinnerCal();
            arySpinnerCtrl = [];
            return false;
        }
        //長押し時の処理
        setTimeout(function(){
            //インターバル未実行中 + 長押しのイベントタイプスタンプ一致時に計算処理
            if(!arySpinnerCtrl['interval'] && arySpinnerCtrl['timestamp'] == e.timeStamp){
                arySpinnerCtrl['interval'] = setInterval(spinnerCal, spin_speed);
            }
        }, 500);
    });
    
    //長押し解除時 画面スクロールも解除に含む
    $(document).on('touchend mouseup scroll', function(e){
        if(arySpinnerCtrl['interval']){
            if(e.type != 'scroll'){
                clearInterval(arySpinnerCtrl['interval']);
                arySpinnerCtrl = [];
            }else{
                /* 一定数スクロールしたら長押しではないと判断し止める */
                if( Math.abs(arySpinnerCtrl['scroll'] - $(window).scrollTop()) >= 10 ){
                    clearInterval(arySpinnerCtrl['interval']);
                    arySpinnerCtrl = [];
                }
            }
        }
    });
    
    //変動計算関数
    function spinnerCal(){
        var target = $(arySpinnerCtrl['target']);
        var num = Number(target.val());
        num = num + arySpinnerCtrl['cal'];
        if(num > Number(target.data('max'))){
            target.val(Number(target.data('max')));
        }else if(Number(target.data('min')) > num){
            target.val(Number(target.data('min')));
        }else{
            target.val(num);
        }
    }
    
});
</script>

各処理毎にコメントで解説しておりますのでご確認ください。

PCスマホの両対応と、「単一のクリック処理と長押し時処理」を分けるために、少しソースコードが冗長化してしまいました…。

実行結果

上記のコードを当てはめると以下のフォームが出来上がります。

実際に触って試してみてください。



こだわった点として、

  • 単一のクリック(タップ)と長押しに両対応
  • パソコン、スマホ両対応(コード切り替えなし)

などを意識しました。

広範囲の数値の入力を求めるフォームでは、使いやすいUIに仕上がっていると思います。

以上、HTMLフォームの数値入力で増減(スピナー)ボタンを実装、でした。

コメント

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