Mobile Web 前端技術筆記(五): 觸控事件與滑鼠事件大不同

我一直想搞清楚手機的事件,quirks mode的iPhone events這篇文章有很好的解說。作者的中心概念是,觸控裝置與滑鼠的事件模型完全不同,互相比擬不是個好想法。就連蘋果官方的Safari Web Content Guide for iPhone也含糊其辭,堪稱有最爛說明文件的最好產品。

根據作者的測試,觸控裝置的實際情形是:

  1. 手指單點時,觸發mouseover, mousemove, mousedown, mouseup 和 click events,也將套用CSS的:hover樣式
    (而且你可以為這些事件加上event handler)
  2. 當user focus離開某元件,觸發mouseout event, 並移除:hover樣式

我們最常利用的mousedown/mouseup/click或mouseenter/mouseout/mousemove事件,和:hover樣式,在觸控裝置上都不能以桌機的概念來看。不同之處在於:

  1. 手指滑動(touch event)和連點兩下(double tapping)都被保留為系統事件,所以在瀏覽器裡並不會被解讀成mousemove或double click
  2. 桌機mouse的移動是連續的,游標一直存在於畫面上;但手機上是不連續的,手指可能在一處點擊,中途消失,然後又點了另一處。

進一步解釋,在桌機上一個滑鼠點擊可被看成三位一體的mousedown/mouseup/click,但在手機上未必會被分解成三個動作。又手指的移動被看作是不連續的,你不能像桌機一樣,在一處按下滑鼠,拖曳到另一處放開,這在手機會被解讀成touch event,而不是mousemove;許多手機browser對mouseover動作根本無動於衷,mousemove也不具意義。既然手機沒有如此多樣的互動,套用傳統的滑鼠事件來解釋觸控行為並不適當,我們也無需再企圖操控手指移動的事件了。

作者提出了一個新觀念: User focus/de-focus,在手機上只有這兩種情況。舉個明顯的例子,填表單時,把手指停在一個欄位上編輯就是focus,移到別的欄位就是de-focus。說穿了,利用“click”事件來引發動作是最好的方法,因為所有系統都支援click,click毫無疑問的是使用者確認的信號,利用click引發動作的application也將成為未來的主流。

而mouse雙擊和mouse右鍵event就不用談了,雙擊是iphone的系統事件(zoom),而由右鍵觸發contextmenu這種互動在iphone上根本不存在。

《資料來源》

作者還把幾種桌機和手機瀏覽器的測試結果整理成表,可作為寫javascript的參考:

Touch Table :各大手機系統支援的event整理

Event compatibility tables :用javascript的event如change、click來列表,看各大桌機和手機瀏覽器的支援度

廣告

Mobile Web 前端技術筆記(四): 不能播Flash時怎麼辦? — Flash與HTML5 video的相互替代

只要Steve Jobs還沒轉念,iPad和iPhone上的browser就難有支援flash的機會吧!但現在有新希望 — HTML5的<video> tag。當然兩者都只有部分瀏覽器支援,我們能做到的最好方式,就是fall back,或有人說fall forward,因為Flash與HTML5很難有孰高孰低之分。Vimeo 很努力的設計它的fall back機制,順序是這樣:

flash > html5 video > place holder

其中place holder的內容包括了圖片、文字、要求升級或加裝套件的訊息,或下載到本機觀看的連結,總之就是要想盡辦法引導user看到影音內容。

也有的網站是以html5優先的:

html5 video > flash > place holder。

《用法》

fall back基本的訣竅有點像俄羅斯娃娃,一層包一層,有開發者甚至想出了用HTML就能達成的超基本做法,類似這樣:

   1: <video>
   2:     <source ...aaa.MP4".../>
   3:     <source ...bbb.OGG"... />
   4:     <object ... data="ccc.SWF">
   5:         <param... />
   6:         <img src="__IMAGE__.JPG" alt="__TITLE__" title="No video playback" />
   7:     </object>
   8:
   9: </video>
  10: <p>
  11:     <strong>Download Video:</strong>
  12:     <a href="__.MP4">"MP4"</a>
  13: </p>
詳情請見 Video for Everyone,他的原理是:
  1. 如果browser支援HTML5,就會優先載入<video>採用的影音格式 — MP4或OGG;
  2. 如果browser看不懂HTML5,就會fall back到下一層<object>,載入SWF;
  3. 如果browser既看不懂HTML5又沒裝flash player,就只能fall back到最下層,也就是提示訊息。

除了用html寫hard code外,另有一些套件可判斷瀏覽器的狀況,決定要嵌入flash或html5 video,如MediaElement.jsVideoJS ,兩者的播放介面設計都還不錯,而且可自訂一些播放參數,如autoplay等等。其中VideoJS 執行的結果與Video for Everyone非常類似,只是用javascript產生HTML。

《資料來源》

  1. http://camendesign.com/code/video_for_everybody
  2. http://mediaelementjs.com/
  3. http://videojs.com/

Mobile Web 前端技術筆記(三): User Agent Sniffing

User Agent Sniffing

《基礎》

行動版網站和桌機版網站,使用的情境和需求都不同,現在大部分網站傾向把兩者分開,將使用行動裝置的user儘早redirect到行動版。用user agent string來分流不算是最好的方法,一來user agent的字串有可能是假的,二來瀏覽器和行動裝置日新月異,每當有新型號出品時,都有可能產生前所未見的user agent string。

單單使用media queries應付五花八門的裝置尺寸,在某些情況下會變得相當複雜(就像我雖然蠻喜歡7吋的Galaxy Tab,但它在開發上鐵定會成為一個頭痛的東西),這時User Agent Sniffing就成了目前少數有效的幾個方法之一。

Mobile Browser會將所有與 User Agent相關的資訊包含在User Agent String裡(平台、OS、瀏覽器、版本等),前端的User Agent Sniffing通常用javascript來做,藉由javascript偵測User Agent String裡的關鍵字眼,來做相應的處理,如redirect到行動版網站、指定特定的CSS、或在javascript做DOM操作時執行不同的動作

目前熱門行動的裝置的User Agent String:

  1. iPad: 有兩個,擇一使用
    (1) 

    Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10

    (2)

    Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10

     

  2. iPod
    Mozilla/5.0 (iPod; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16

     

  3. iPhone
    Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16

     

  4. Android上的瀏覽器
    Android系統的行動裝置幾乎都有“Android”字眼,且多搭配webkit引擎的瀏覽器,所以可用這兩者作為關鍵字

而Apple產品的User Agent String幾乎都包含iPhone字眼。

《用法》

Javascript

iPod touch和 iPhone用同樣的排版還說得過去,但小型裝置的版面設定可能就不適合iPad。幸好iPad的平台關鍵字是不變的,用以下偵測平台的方式即可:

   1: function isIPad(){
   2:     return navigator.platform == ""iPad"";
   3: }

執行完這個運算後會傳回true或false,再指定true或false各自的後續動作。

關於User Agent Sniffing,David Walsh這位Web Developer寫出許多有用的javascript片段,例如:

  • 偵測iPad的User Agent String
   1: // For use within normal web clients
   2: var isiPad = navigator.userAgent.match(/iPad/i) != null;
   3: // For use within iPad developer UIWebView
   4: var ua = navigator.userAgent;
   5: var isiPad = /iPad/i.test(ua) || /iPhone OS 3_1_2/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);

用match、indexOf或test來尋找navigator.userAgent裡面有沒有任何包含ipad的字眼,然後傳回true或false。

*註:navigator.userAgent.match(/iPad/i),其中/…/i 是正規表示法中的case insensitive,指的是兩斜線內的字串不分大小寫的意思

  • 偵測iPhone或iPod的User Agent String
   1: if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) {
   2:    if (document.cookie.indexOf("iphone_redirect=false") == -1) window.location = "http://m.espn.go.com/wireless/?iphone&i=COMR";
   3: }
  • 偵測Android的 User Agent String
   1: var ua = navigator.userAgent.toLowerCase();
   2: var isAndroid = ua.indexOf("android");
   3: if(isAndroid) {
   4:   // Do something!
   5:   // Redirect to Android-site?
   6:   window.location = 'http://android.davidwalsh.name';
   7: }

在後端寫PHP來偵測,原理也是一樣的,就不把code貼過來了。

.htaccess

另外還有在.htaccess裡設定的,.htaccess是在Apache HTTP Server下的一個對於系統目錄進行各種權限規則設置的文件,最常見的是設置404頁面,301轉向等等,http://dev-tips.com/featured/redirect-iphone-blackberry-palm-requests-with-htaccess 有一份.htaccess設置的實例:

   1: #redirect mobile browsers
   2: RewriteCond %{HTTP_USER_AGENT} ^.*iPhone.*$
   3: RewriteRule ^(.*)$ http://mobile.yourdomain.com [R=301]
   4: RewriteCond %{HTTP_USER_AGENT} ^.*BlackBerry.*$
   5: RewriteRule ^(.*)$ http://mobile.yourdomain.com [R=301]
   6: RewriteCond %{HTTP_USER_AGENT} ^.*Palm.*$
   7: RewriteRule ^(.*)$ http://mobile.yourdomain.com [R=301]

《資料來源》

  1. http://www.nczonline.net/blog/2010/04/06/ipad-web-development-tips/
  2. http://davidwalsh.name/detect-ipad
  3. http://davidwalsh.name/detect-android
  4. http://davidwalsh.name/detect-iphone
  5. .htaccess設置實例http://dev-tips.com/featured/redirect-iphone-blackberry-palm-requests-with-htaccess

Mobile Web 前端技術筆記(二): Media Queries 與 CSS

Media Queries

《基礎》

media queries的作用在偵測device的尺寸和方向等,指定相對應的CSS檔。使用情境粗分為兩種,一種是用於mobile compatible的網頁,也就是桌機版與行動版共用一份html文件,但要套用不同的排版;另一種是做行動版專用網頁,但想要依照不同的行動裝置給予適當的版面設定。

《用法》

HTML

<link rel="stylesheet" media="screen and (min-width: 400px) and (max-width: 700px)" href="example.css" />
CSS
@media screen and (min-width: 400px) and (max-width: 700px) {
    .selector1{...}
    .selector2{...}
}

意思就是在視窗寬度大於400px但小於700px時,套用example.css這個CSS檔。

CSS檔中,@media後面列的條件就是對應HTML<link media=“…..”> 引號內的東西。在@media{}大括號之內,就如往常一樣撰寫此media條件下的CSS設定。

import CSS的寫法也一樣:

@import "screen.css" screen and (min-width: 400px) and (max-width: 700px)

query條件的用法

@media [media type] and [(media feature)]

單一條件

例:如果視窗最小寬度為500px,就套用這些CSS

@media screen and (min-width:500px) {.....}

例:如果視窗為直立,就套用這些CSS

@media screen and  (orientation: portrait) {.....}

兩者需同時符合

例:如果視窗在400px和700px之間,就套用這些CSS

@media screen and (min-width: 400px) and (max-width: 700px)

兩者符合一種即可

例:如果是彩色螢幕或彩色投影機兩者之一,就套用這些CSS

@media screen and (color), projection and (color) {.....}

以not/only 迴避或強制舊版瀏覽器執行

<link rel="stylesheet" media="not|only screen and (color)" href="example.css" />

某些舊版瀏覽器只能讀media type(screen,projector等等),不會讀media feature,也不會讀not或only,因此也不會套用此media query後的CSS檔。

《屬性和值》

  • media type 有以下幾種:
    all | aural | braille | handheld | print | projection | screen | tty | tv | embossed
  • media features
    * (max-或min-)width:[數字]
    * (max-或min-)height:[數字]
    * (max-或min-)device-width:[數字]
    * (max-或min-)device-height:[數字]
    * orientation:portrait 或 landscape
    * aspect-ratio:[比值]
    * (max-或min-)device-aspect-ratio:[比值]
    * color
    * color-index
    * monochrome
    * (max-或min-)resolution:[數字]dpi
    * scan(只對tv)
    * grid

這方面W3C文件也還在W3C Recommandation的階段,也不算進入Standard

很多人關心handheld這個media type,但事實上它已無法有效偵測是否為手機browser。前一代智慧型手機很多用Opera上網,Opera確定是可以辨認這個media type的。

會讀handheld的手機瀏覽器有:
OpenWave, Nokia lite-web browsers, Netfront, Digia, BlackBerry browser, Opera Mini until v4, Opera Mobile until v9,Palm’s Blazer, Nokia S40 browser, IEMobile 6.x and 8.x

(http://www.alistapart.com/articles/putyourcontentinmypocket/)

CSS支援度

目前大部分手機瀏覽器與桌機瀏覽器支援的CSS相差不大,但有需要慎用的的CSS屬性

  • overflow
  • position:fixed(iphone safari確定不支援)
  • font-family:手機上的字型比桌機少
  • font-size: 用small, medium, large,最好不要用px設死
  • margin與padding的算法可能有個別差異

box model的處理

手機版網頁在自動適應畫面寬度時,目前標準的padding算法會是個困擾,因為如果width:100%,加上padding可能就破版了,但不使用width:100%又很難估計內容的實際寬度。這時可考慮回復到IE6模式,把border和padding的移到box內部,如此一來宣告width為100%就能保證不破版。

div{
     -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
     -moz-box-sizing: border-box;    /* Firefox, other Gecko */
     box-sizing: border-box;
}

*註:border-box是IE6的模式,content-box是目前的標準模式

行動裝置的CSS reset

行動裝置頻寬寶貴,即使做CSS reset也要保持精簡只reset基本元素。目前網路上所有mobile CSS reset都指向一份文件,

http://www.vcarrer.com/2010/11/css-mobile-reset.html

他的CSS reset只有短短幾個元素而已

/* CSS Mobile Reset */
html, body
{
 margin: 0;
 padding: 0;
 border: 0;
}

body
{
 font-family:Arial,  sans-serif;
 line-height:1.5;
 font-size:16px;
 background: #fff;
 padding:5px;
 color: #000;
 word-wrap: break-word;
 -webkit-text-size-adjust: none;
}

h1, h2, h3, h4, h5, h6{ font-weight: normal; }

p img { float: left; margin: 0 10px 5px 0; padding: 0; }

img { border: 0; max-width: 100%; }

table { width:auto; border-collapse: collapse;border-spacing: 0; }

簡單來說就是保持輕巧,不需要的元素就不重設。

《備註》

media queries基本上與user agent無關,它僅以辨認當前browser的狀況來因應,而非透過辨認user agent來執行不同的動作。

《資料來源》

  1. W3C文件 http://www.w3.org/TR/css3-mediaqueries/
  2. 某網友翻譯W3C文件
    http://zetajames.wordpress.com/2010/02/26/css3-media-queries/
  3. media feature整理表 http://reference.sitepoint.com/css/mediaqueries
  4. 會讀handheld的手機瀏覽器 http://www.alistapart.com/articles/putyourcontentinmypocket/
  5. box model的處理 http://css-tricks.com/box-sizing/
...

Mobile Web 前端技術筆記(一): Viewport的設定

Viewport的設定

《基礎》

viewport的作用是告訴瀏覽器,目前裝置有多寬(或多高),以便在縮放時有個基準。尤其當設定頁面寬度需自動調整時,如寬度100%或螢幕由垂直轉為水平,viewport大小是一個根據。

《用法》

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">

(這個例子中的maximum-scale也設為1,其實就是不讓使用者縮放,以維持頁面的設計,行動裝置專用的網頁常有必要這樣做。)

《屬性和值》

根據W3C草案,在meta tag中viewport有以下屬性可設定

  • width:[數字] 或 device-width
  • height:[數字] 或 device-height
  • initial-scale:最小0.25,最大5
  • minimum-scale:最小0.25,最大5
  • maximum-scale:最小0.25,最大5
  • user-scalable:1 或 0 (yes 或 no)

雖然是W3C文件,但還在草案(Editor’s Draft)階段,尚未標準化,iOS上的Safari最先實作這些屬性,所以比較完整,表現也比較穩定;其他瀏覽器不見得能解譯,但新版的Opera, Android, Fennec(Mobile Firefox)應該是可以實現其中幾項屬性的。但Opera Moblie 9.5中minimum-scale/maximum-scale、user-scalable的功能是不作用,因為Opera當時認為自家的Zoom功能是必要的。

width通常設為device-width,用意是適應各家裝置的大小,這樣寫CSS時就能放心的把版面寬度設為100%(雖然還有一個box model的問題,容後再述)。

user-scalable的實際行為就等於zoom,zoom=1可以配合行動版專用網頁的設定,剛剛好填滿畫面,不過桌機版網頁超出畫面是必然的。

mobile_mediaqueries

《備註》

螢幕解析度不一定等於device-width,
Nexus One 是螢幕解析度(800)不等於device-width(320)的典型例子,
iPhone 4 亦同 – 螢幕解析度(960),但device-width回報為(320)。
新出的手機傾向採用高畫素的面板,如果照實體螢幕解析度作為device-width,有可能進入大部分網站時都看到縮小的畫面,這是使用方便上的一個考量。

《資料來源》

  1. W3C文件 http://dev.w3.org/csswg/css-device-adapt/
  2. device-width的解說
    http://www.quirksmode.org/blog/archives/2010/09/combining_meta.html
  3. Pou’s IT Life
    http://www.dotblogs.com.tw/pou/archive/2010/09/26/17890.aspx