LoginSignup
92
92

More than 5 years have passed since last update.

[jQuery] click / touch / pointer イベントを完全に制御する

Last updated at Posted at 2014-05-13

デバイスごとのイベント判定方法と問題点

タッチデバイスとポインティングデバイスでバインドするイベントを分別する際、いままでは以下のようにしてきました。

JavaScript
var event = 'ontouchstart' in window ? 'touchend' : 'click';

$('hoge').on(event, function());

しかし、この記述で判定すると、特定の環境でイベントの判別がうまくいかないのです。

  1. タッチディスプレイを搭載したPC
  2. Google Chrome

上記の組み合わせだと、event変数は必ずtrueを返します。
iOSやAndroidなどのスマートフォンOSでは、touchendとclickが時間差で発生するため (本当はもっといろんなイベントが発生していますが)、以下のようなことは当然できません。

JavaScript
$('hoge').on('touchend click', function());

新しい (?) イベント判定方法

そこで、最初に発生したイベント (touchstartやmousedownなど) を判別して、正しいイベントをバインドするようなスクリプトを作りました。

JavaScript
var event = {
  all: 'mousedown touchstart pointerdown mouseenter mouseleave',
  type: '',
  start: '',
  enter: '',
  leave: '',
  move: '',
  end: ''
};

// イベント判定
event.check = function(e){
  var _default = e.type;
  event.start = _default;
  event.move = _default === 'pointerdown' ? 'pointermove' : (_default === 'touchstart' ? 'touchmove' : 'mousemove');
  event.end = _default === 'pointerdown' ? 'pointerup' : (_default === 'touchstart' ? 'touchend' : 'click');
  event.enter = _default === 'pointerenter' ? _default : (_default === 'touchenter' ? _default : 'mouseenter');
  event.leave = _default === 'pointerleave' ? _default : (_default === 'touchleave' ? _default : 'mouseleave');
};

event.on = function(type, elm, fn, delegate){
  $(document).off(event.all, elm).on(event.all, elm, function(e){
    e.preventDefault();
    event.check(e);
    if (fn != null) {
      if (e.type === event.enter || e.type === event.leave) {
        // mouseenter mouseleaveのとき、コールバック関数を即実行
        fn(this, e);
      } else {
        if (type === 'bind') {
          // jQuery $(element).on(event, func);
          $(elm).off(event.end).on(event.end, function(e){
            fn(this, e);
          });
        } else if (type === 'live') {
          // jQuery $(document).on(event, element, func);
          $(document).off(event.end, elm).on(event.end, elm, function(e){
            fn(this, e);
          });
        } else if (type === 'delegate') {
          // jQuery $(parentsElement).on(event, element, func);
          $(delegate).off(event.end, elm).on(event.end, elm, function(e){
            fn(this, e);
          });
        }
      }
    } else {
      // 引数にコールバック関数が定義されていないときの処理
    }
  });
};

処理はそんなに難しいことをしていないはずなので、内容の説明は省きます。
実際の使い方は以下のようになります。

JavaScript
event.on(type, element, func, parentsElement);

var func = function(elm, e) {
  if (e.type === event.end) {
    //touchend、pointerup、clickのいずれかのときに実行
  }
};

// example
event.on('bind', '.hoge', func);
event.on('live', '.hoge', func);
event.on('delegate', '.fuga', func, '.hoge');

これでどの (?) デバイスでも正しいイベントが自動的にバインドされるようになりました。

改善のアドバイスがございましたら、是非ご連絡ください。

92
92
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
92
92