jQuery Mobile 是基於 jQuery 而建立的行動網頁框架, 由於多了頁面控制與行動裝置觸控等操作需求, jQuery Mobile 除了繼承 jQuery 的事件處理函式外, 還定義了專屬於頁面與行動觸控等事件之處理函式. 本系列測試文章索引參考 :
jQuery Mobile 的特有的事件可分為下列五類 :
- 頁面事件 (pagexxx)
- 觸控事件 (tapxxx/swipexxx)
- 捲動事件 (scrollstart/scrollstop)
- 方向改變事件 (orientationchange)
- 初始化事件 (mobileinit)
各類事件名稱如下表 :
頁面事件 | 說明 |
pagebeforecreate | 頁面建立前觸發 |
pagecreate | 頁面建立時觸發 |
pagebeforeshow | 頁面顯示前觸發 |
pageshow | 頁面顯示後觸發 |
pagebeforehide | 頁面隱藏前觸發 |
pagehide | 頁面隱藏後觸發 |
觸控事件 | 說明 |
tap | 快速點擊螢幕觸發 |
taphold | 長按螢幕觸發 |
swipe | 於 1 秒內在螢幕上水平拖曳滑動超過 30px, 但垂直距離不超過 75px 觸發 |
swipeleft | 於螢幕上水平向左拖曳滑動觸發 |
swiperight | 於螢幕上水平向右拖曳滑動觸發 |
捲動事件 | 說明 |
scrollstart | 於螢幕上捲動開始時觸發 |
scrollstop | 於螢幕上捲動結束時觸發 |
方向改變事件 | 說明 |
orientationchange | 螢幕方位改變時觸發 |
mobileinit 事件是指在 jQuery Mobile 載入後, 於全部元件建立之前所觸發之初始化事件, 主要用 $.mobile 物件之屬性來變更 jQuery Mobile 之系統預設值, 常用的物件屬性如下表 :
初始化事件 | 說明 |
ajaxEnabled | 是否允許以 Ajax 方式提交 (預設 true) |
defaultPageTransition | 預設頁面切換特效 (預設 "fade") |
allowCrossDomainPages | 以 Ajax 連結外部網頁時是否允許跨網域存取 (預設 false) |
pageLoadErrorMessage | 頁面載入錯誤時顯示之訊息 (預設 "Error Loading Page") |
pageLoadErrorMessageTheme | 錯誤訊息之主題佈景 (預設 "e") |
phonegapNavigationEnabled | 以 PhoneGap 的導覽取代 window.history.back (預設 false) |
初始化事件只要用來做 jQuery Mobile 的全域設定 (global configuration), 參考 :
監聽這些事件的方式是先選取 document 或 body 元素取得其 jQuery 物件, 然後呼叫 on() 方法並傳入事件名稱, 語法如下 :
$("document").on("事件名稱", function(e)){
事件處理程式碼
});
但方位改變事件卻必須綁定在 window 物件上, 用事件物件的 orientation 可取得行動裝置目前擺放的方位是直放 (portrait) 還是橫放 (landscape) :
$(window).on("orientationchange" , function(e){
alert(e.orientation);
});
監聽初始化事件時在處理函式中以 $.mobile.屬性值來變更系統預設值 :
$(document).on("mobileinit", function(e) {
$.mobile.ajaxEnabled=false;
$.mobile.defaultPageTransition="turn";
.....
});
下面範例為頁面事件之測試 :
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script>
$(document).on("pagebeforecreate" , function(e){
alert("頁面即將新增 (pagebeforecreate) : " + e.target.id);
});
$(document).on("pagecreate" , function(e){
alert("頁面新增 (pagecreate) : " + e.target.id);
});
$(document).on("pagebeforeshow" , function(e){
alert("即將要顯示的是 (pagebeforeshow) : " + e.target.id);
});
$(document).on("pageshow" , function(e){
alert("顯示頁面 (pageshow) : " + e.target.id);
});
$(document).on("pagebeforehide" , function(e){
alert("即將要隱藏的是 (pagebeforehide) : " + e.target.id);
});
$(document).on("pagehide" , function(e){
alert("隱藏的是 (pagehide) : " + e.target.id);
});
</script>
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<ul data-role="listview" data-inset="true">
<li><a href="#page2">第 2 頁</a></li>
<li><a href="#page3">第 3 頁</a></li>
</ul>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<!-- 第二頁頁面 -->
<section data-role="page" id="page2">
<header data-role="header" data-add-back-btn="true">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<p>第二頁</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<!-- 第三頁頁面 -->
<section data-role="page" id="page3">
<header data-role="header" data-add-back-btn="true">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<p>第三頁</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
</body>
</html>
此例有三個頁面, 第一個頁面上有兩個放在列表清單中的超連結按鈕, 分別前往第一頁與第三頁, 頁面事件監聽器程式放在 head 內以便在網頁未載入前執行.
網頁載入過程會依序觸發下列 4 個事件 :
- pagebeforecreate
- pagecreate
- pagebeforeshow
- pageshow
然後整份網頁載入完成就顯示第一個頁面, 結果如下 :
點第 2 頁超連結會切換頁面至第 2 頁, 切換到新頁的過程會依序觸發下列 6 個事件 :
- pagebeforecreate (新頁)
- pagecreate (新頁)
- pagebeforehide (舊頁)
- pagebeforeshow (新頁)
- pagehide (舊頁)
- pageshow (新頁)
結果如下 :
尚未顯示過的頁面第一次切進去時都會觸發 pagebeforecreate 與 pagecreate 這兩個建立頁面相關的事件, 而舊的頁面會被放進頁面堆疊中暫存. 按左上方的 Back 按鈕返回時會依序觸發下列 4 個事件 :
- pagebeforehide (舊頁)
- pagebeforeshow (新頁)
- pagehide (舊頁)
- pageshow (新頁)
亦即第 2 頁頁面會被送進頁面池暫存而隱藏, 然後從頁面池中取出第 1 頁顯示, 結果如下 :
這時若再點第 1 頁按鈕進去, 因為第 2 頁頁面之前已經建立過了, 就會直接從頁面池中直接取出並顯示, 因此不會觸發 pagebeforecreate 與 pagecreate 事件, 而是跟上面按 Back 鈕返回第 1 頁那樣依序觸發 pagebeforehide, pagebeforeshow, pagehide, pageshow 這四個事件, 結果與上面第一次進入 page2 時之後面四步相同. 本例測試網頁 QR code 如下 :
在單檔多頁面架構中, 我們可以很方便地利用 data-role="page" 屬性在超連結按鈕中以 href="#page_id" 方式進行換頁, 事實上也可以透過 $.mobile.changePage() 函式用程式控制換頁, 特別是在需要一些判斷才能決定換到哪一頁的情況時. 下面測試是將上面測試 1 改用 $.mobile.changePage() 控制換頁 :
測試 2 : 頁面事件測試 (利用 $.mobile.changePage 控制換頁) [看原始碼]
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script>
$(document).on("pagebeforecreate" , function(e){
alert("頁面即將新增 (pagebeforecreate) : " + e.target.id);
});
$(document).on("pagecreate" , function(e){
alert("頁面新增 (pagecreate) : " + e.target.id);
});
$(document).on("pagebeforeshow" , function(e){
alert("即將要顯示的是 (pagebeforeshow) : " + e.target.id);
});
$(document).on("pageshow" , function(e){
alert("顯示頁面 (pageshow) : " + e.target.id);
});
$(document).on("pagebeforehide" , function(e){
alert("即將要隱藏的是 (pagebeforehide) : " + e.target.id);
});
$(document).on("pagehide" , function(e){
alert("隱藏的是 (pagehide) : " + e.target.id);
});
</script>
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<ul data-role="listview" data-inset="true">
<li><a href="#" id="to_page2">第 2 頁</a></li>
<li><a href="#" id="to_page3">第 3 頁</a></li>
</ul>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<!-- 第二頁頁面 -->
<section data-role="page" id="page2">
<header data-role="header" data-add-back-btn="true">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<p>第二頁</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<!-- 第三頁頁面 -->
<section data-role="page" id="page3">
<header data-role="header" data-add-back-btn="true">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<p>第三頁</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<script>
$(document).ready(function() {
$("#to_page2").on("click", function(e) {
$.mobile.changePage("#page2");
});
$("#to_page3").on("click", function(e) {
$.mobile.changePage("#page3");
});
});
</script>
</body>
</html>
此例取消兩個 a 元素超連結按鈕 href 中的 page id, 新增 id 屬性, 並在程式中為此二超連結綁定 click 事件處理器, 呼叫 $.mobile.changePage() 函式進行換頁, 結果與上面測試 1 相同. 本例測試網頁 QR code 如下 :
$.mobile.changePage() 除了可傳入 "#page_id" 參數進行 HTML 檔內換頁外, 也可以傳入 URL 切換到外部網頁, 還可以用第二參數以物件形式傳遞變數到其他頁面, 其介面如下 :
$.mobile.changePage(dest [,attr])
其中第一參數 dest 可以是頁面 id 或 URL, 第二參數 attr 為物件, 可用之屬性如下表 :
$.mobile.changePage() 之屬性 | 說明 |
allowSamePageTransition | 是否允許同頁切換 (預設 false) |
changeHash | 是否更新瀏覽紀錄 (預設 true), 若設為 false 無法回上一頁 |
data | 以 Ajax 方式換頁時所傳遞之資料 (物件) |
loadMsgDelay | 頁面載入之延遲時間 (預設 50 毫秒), 超過設定值會顯示訊息 |
reload | 是否要重新載入頁面至 DOM 中 (預設 false) |
reverse | 回上一頁時是否要使用逆向的換頁特效 (預設 false) |
showLoadMsg | 是否要顯示載入訊息 (預設 false) |
transition | 換頁時之特效名稱 |
type | 以 Ajax 方式換頁時使用之 HTTP 方法 (預設 get) |
例如 :
測試 3 : $.mobile.changePage 換頁測試 (特效) [看原始碼]
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<ul data-role="listview" data-inset="true">
<li><a href="#" id="to_page2">第 2 頁</a></li>
<li><a href="#" id="to_page3">第 3 頁</a></li>
</ul>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<!-- 第二頁頁面 -->
<section data-role="page" id="page2">
<header data-role="header" data-add-back-btn="true">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<p>第二頁</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<!-- 第三頁頁面 -->
<section data-role="page" id="page3">
<header data-role="header" data-add-back-btn="true">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<p>第三頁</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<script>
$(document).ready(function() {
$("#to_page2").on("click", function(e) {
$.mobile.changePage("#page2", {transition:"slideup"});
});
$("#to_page3").on("click", function(e) {
$.mobile.changePage("#page3", {transition:"slidedown"});
});
});
</script>
</body>
</html>
此例測試網頁 QR code 如下 :
用 $.mobile.changePage() 換頁也可以切換到外部網頁, 特別是切換到後端網頁程式 (例如 PHP) 時可以用 type 與 data 屬性透過 Ajax 傳遞變數, 例如 :
測試 4 : $.mobile.changePage 換頁測試 (傳遞變數) [看原始碼]
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>換頁測試</h1>
</header>
<article data-role="content">
<ul data-role="listview" data-inset="true">
<li><a href="#" id="to_page2">第 2 頁</a></li>
<li><a href="#" id="to_page3">第 3 頁</a></li>
</ul>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<script>
$(document).one("pageinit", function(){
$("#to_page2").on("click", function(e) {
$.mobile.changePage("change_page_test.php, {
type:"post",
data:{name:"tony", msg:"hello"}
});
});
$("#to_page3").on("click", function(e) {
$.mobile.changePage("hello.htm");
});
});
</script>
</body>
</html>
此例因為用到 Ajax 傳遞變數至後端, GitHub 不支援動態網頁, 故改在 Hostinger 虛擬主機上測試. 其次, 書中範例呼叫 jQuery 的 one() 方法綁定 pageinit 事件, 其實用 $(document).ready(function() {} 也是可以的. 按 "第二頁" 會載入 change_page_test.php, 此程式會用 $_REQUEST[] 取得前一頁所傳來的變數, 程式內容如下 :
# change_page_test.php
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>換頁傳送 data 測試</h1>
</header>
<article data-role="content">
<?php
echo "name:".$_REQUEST["name"]."<br>".
"msg:".$_REQUEST["msg"];
?>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
</body>
</html>
按 "第三頁" 則是載入純網頁 hello.htm, 內容如下 :
#hello.htm
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>換頁測試</h1>
</header>
<article data-role="content">
<p>Hello</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
</body>
</html>
結果如下 :
此例測試網頁 QR code 為 :
接下來測試觸控事件 :
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script>
$(document).on("tap" , function(e){
$("#msg").html("<h1>觸發 tap 事件</h1>");
});
$(document).on("taphold" , function(e){
$("#msg").html("<h1>觸發 taphold 事件</h1>");
});
$(document).on("swipe" , function(e){
$("#msg").html("<h1>觸發 swipe 事件</h1>");
});
$(document).on("swipeleft" , function(e){
$("#msg").html("<h1>觸發 swipeleft 事件</h1>");
});
$(document).on("swiperight" , function(e){
$("#msg").html("<h1>觸發 swiperight 事件</h1>");
});
</script>
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>觸控事件測試</h1>
</header>
<article data-role="content">
<h1 id="msg"></h1>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
</body>
</html>
此例在頁面中用一個 id=msg 的 p 元素來顯示所發生的觸控事件, 結果如下 :
實際操作發現 swipeleft 與 swiperight 都很容易觸發, 唯獨 swipe 我怎麼滑都沒辦法, 只好算了. 此例測試網頁 QR code 如下 :
接著測試捲動事件 scrollstart 與 scrollstop :
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script>
$(document).on("scrollstart" , function(e){
$("#msg").html("<h1>觸發 scrollstart 事件</h1>");
});
$(document).on("scrollstop" , function(e){
$("#msg").html("<h1>觸發 scrollstop 事件</h1>");
});
</script>
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>捲動事件測試</h1>
</header>
<article data-role="content">
<h1 id="msg"></h1>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
</body>
</html>
結果如下 :
此例測試網頁 QR code :
接下來是 orientationchange 事件測試, 所謂 orientation 是指行動裝置的方位是直的 (portrait) 還是恆的 (landscape), 注意, 此事件要選取 window 物件來綁定 orientationchange 事件 :
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script>
$(window).on("orientationchange" , function(e){
$("#msg").html("目前螢幕的方向是 : " + e.orientation);
});
</script>
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>方位變化事件測試</h1>
</header>
<article data-role="content">
<h1 id="msg"></h1>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
</body>
</html>
將手機直放與橫放切換, 結果如下 :
最後來測試 mobileinit 事件, 此事件也是綁定在 document 物件上, 並且事件處理程式碼須放在 head 內, 重要的是, 初始化事件處理程式必須放在 jQuery Mobile 函式庫前面, 以便函式庫初始化之前這些設定值就已存在, 這樣才能夠執行初始化動作, 順序若顛倒則初始化設定將無效, 例如 :
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script>
$(document).on("mobileinit" , function(e){ //須在 jQuery Mobile 函式庫之前
$.mobile.defaultPageTransition="turn";
$.mobile.pageLoadErrorMessage="無法載入頁面";
$.mobile.pageLoadErrorMessageTheme="b";
});
</script>
<script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<!-- 第一頁頁面 -->
<section data-role="page" id="page1">
<header data-role="header">
<h1>初始化事件測試</h1>
</header>
<article data-role="content">
<ul data-role="listview" data-inset="true">
<li><a href="#page2">第 2 頁</a></li>
<li><a href="nothispage.htm">第 3 頁</a></li>
</ul>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
<!-- 第二頁頁面 -->
<section data-role="page" id="page2">
<header data-role="header" data-add-back-btn="true">
<h1>頁面事件測試</h1>
</header>
<article data-role="content">
<p>第二頁</p>
</article>
<footer data-role="footer">
<h3>頁尾</h3>
</footer>
</section>
</section>
</body>
</html>
結果如下 :
此例測試網頁 QR code 為 :