[javascript note.] Events on mobile devices

W3C 所定義的 Touches 文件:http://www.w3.org/TR/touch-events/ HTML5 Rocks 所寫多點觸控文件:http://www.html5rocks.com/en/mobile/touch.html

jQuery Mobile 關於觸控的 Event:http://jquerymobile.com/demos/1.0b1/#/demos/1.0b1/docs/api/events.html

Safari Blog 所解釋的 Touch 與手勢流程:http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html

這些東西現在我測試的環境下,只有 Safari 或是 Webkit 核心的瀏覽器比較能夠正常反應。像是 Firefox 雖然也有支援多點觸控,但是我用 MozTouch* 都沒有反應(在 Android 上面的 Firefox 5 Mobile 是無反應的)。至於 jQueryMobile 我並沒有拿到 Firefox 上面測試,所以我這裡就先不提 jQueryMobile 所提供的 Events 了。

超強的 Touch* 系列

大概很好奇為什麼這樣說?如果我們有一個元件,本身綁定了 touchstart 這個動作的話,那麼,在這個元件所屬的字元件,如果再綁定 touchstart 或是 click 的話,非常有機會被父元件的 touchstart 吃掉。也許你會很好奇,依照 DOM 的規則來說,子元件在上,應該是由子元件向下傳遞轉向父元件才對,偏偏,我在手機上測試的結果並不如預期。

這樣的圖示應該很清楚了吧!

在某些情況(甚至無法知道是什麼條件)下,外部所進入的 Event 會跳過子元件,直接由父元件所接收,依照 DOM 的條件,我父元件所包含的子元件,理當應該是兒子先接收,之後在傳遞給老爸,然而,我實際在手機上面測試的,恰好相反。BUT!

人生最厲害的就是這個 BUT!

子元件倘若是一樣使用 touchstart(或是 mousedown) ,你是有機會讓子元件的動作被執行的,不過只是有機會,像是我按了子元件 3~5 次,才有可能被引發一次而已!這是很弔詭的地方,倘若只是單純的 return false 或是 return true,子元件一樣會被忽略,然後繼續由父元件執行。BUT!

人生最厲害的就是這個 BUT!

倘若子元件發出中斷訊息(像是 Alert() 這種),那麼瀏覽器就會很乖的先把兒子的 Alert() 給秀出來,然後再交由老爸去執行。

BUT!天殺地誰會先 Alert() 再繼續做其他事情的,你說說看,你說說看啊(丟滑鼠!

所以,根據三天三夜的的測試,關於觸控的東西,倘若要使用在複雜元件中,還是得將你所要使用的熱區(hot-area)給切割開來,除了避免 Events 互相干擾之外,也可以避開各種 Mobile devices 的瀏覽器所衍生出來的問題。所以說,像是我的 jQuery iPhone Slide 就不能在滑動頁面中加入鍊結或是可點擊的元件,會被干擾(這是一個可愛的歪國人提出來的需求)。

解決的辦法就是,將 slide 滑動熱區換到別的地方,然後內容頁面就可以很正常的利用其他的 Events 來作動作。主要還是因為 Touch* 的動作,在不同的裝置上,很有可能都會有不同的反應(請看 Safari 對於觸控的那篇文章)。雖然那是針對 iOS 所做的說明,而,我想各家的方式可能都不太一樣

總結就是,如果要使用觸控功能,還是不要混在一起用比較好。畢竟,現在市面上也只有 iOS 有說明他的執行方式(雖然也未必準確),其他家的只能自己猜測而已(翻桌)。

下次再來聊聊 jQueryMobile 的觸控功能吧。

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei