🧊

ファーストビューからはみ出した部分だけ、touch*イベントが発火しない

記事らしいものではないんですけど、
書いておかないと忘れそう
+
そのうちなんかの足しになればいいなと思ったのでメモ。

発生した機種

Android4.0 GalaxyS3(SC-06D) 標準ブラウザで確認。

どんなページ

Twitterのタイムラインのような、なんでもないリストビューのページ。
で、そのリストをタップすると詳細画面に遷移して・・っていう。

コードでみる

Marionetteです。

/**
 * ul
 *   li.list
 *     img.thumb
 *     div
 *       span.name
 *   li
 *   li
 *
 * って感じのHTMLで。CollectionViewじゃないのには深い理由があるので割愛
 */
var SampleTimelineView = Marionette.ItemView.extend({
  ui: {
    list:  '.list',
    thumb: '.thumb',
    name:  '.name'
  },
  events: {
    'tap @ui.list':  '_showPostDetail',
    'tap @ui.thumb': '_showUserDetail',
    'tap @ui.name':  '_showUserDetail'
  },
  // ...
});

tapイベントは、それ用のライブラリを入れてて、
touchstart->touchendで何かとよしなに判別してtapイベントを発火してくれるやつです。

そして事件は起きる

ファーストビューから見きれた部分に対して、イベントが発火しない。
ファーストビューに収まってる部分は、問題なくイベント発火して動く。

仮説1: tapイベントが悪い

たしかに、tapではなくclickイベントでやると動く。

ならtapの実装に問題がある・・?
他のとこではまったく問題なく動いてるけど・・。

仮説2: touchstartが死んでる

tapをやめればいいだけなら、clickじゃなくて単にtouchstartでも動くはずよね、と思い試す。
でもダメ。

そこでこんな記事を見つける。
関係ないけどしばし絶望する。

android 4.0 - WebView in ICS touch events not being fired properly - Stack Overflow

そんなことありえんのか・・。

そして突然なおる

ほんと偶然なんですけど、以下のコードで動くように。

var SampleTimelineView = Marionette.ItemView.extend({
  events: {
    //...

    // まさかの何もしない関数をはさむとなおる
    'touchstart': '_noop'
  },
  _noop: function() {}
  // ...
});

そう、何もしない関数をかませただけ。

いままでうんともすんとも言わなかったtapイベント。
そんな彼が元気に動き回る姿がそこにはありました!
感動!

意味わからん!

真面目に考えてみる

ファーストビューというか

このView、実はposition: absoluteで、その親要素のheight: 100%の高さと実際のコンテンツの高さが違う。
そこで何かあるとか?

でもclickで動くなら関係ないと思うし・・。

touch*イベント

2013年10月に勧告なこいつ。

Touch Events is a W3C Recommendation | W3C News
Touch Events

そしてこの端末の発売は2012年6月。

なんか実装がバグってんのでは!
どうなんですかサム○ンさん!

でもなら要素全体をtouchstartで動くようになる理由に一歩足りないような・・。

空関数になんかある

空の関数をバインドすると何か内部的に動作変わるとかないんかね?
イベントハンドラの優先度がどうにかなるとか!

答えは闇の中

やー(モバイル)フロントエンド楽しくて泣きそう。