2021年3月4日 星期四

MicroPython v1.14 釋出

這幾天回頭收尾 jQuery Mobile, 突然想到之前在 MicroPython 連線 WiFi 基地台實驗中使用 HTML5 設計的 SSID/PWD 設定網頁是 PC 版的, 在手機上看起來表單欄位都很小需要手動放大, 如果用 jQuery Mobile 做應該較美觀實用, 想說這幾天來測試看看, 太久沒玩 MicroPython 有點生疏, 今天追蹤才發現 v1.14 版已在春節前釋出, 下載網址如下 : 

# https://micropython.org/download/esp32/
# https://micropython.org/download/esp8266/

此新版韌體的主要的改變如下 : 
  1. 為樹莓派 Pico 微控器新增了 rp2 埠.
  2. 模組 sys 已改名為 usys.
  3. 軟體 I2C 與 SPI 的建構子 machine.I2C() 已改為 machine.SoftI2C(); 而 machine.SPI() 改為 machine.SoftSPI(), 但硬體 I2C 與 SPI 則不變.
參考 :

# https://micropython.org/resources/micropython-ChangeLog.txt

高科大還書 2 本

下面二書有人預約須先還 : 
剛好有兩本預約書來了, 所以兩命抵兩命, 哈. 

2021年3月3日 星期三

jQuery Mobile 學習筆記 (十八) : 用 appsgeyser 將行動網頁轉成 App

以前曾經找到一個 appsgeyser 網站可將行動網頁轉成原生 App, 那時只用一個簡單的網頁測試了一下, 確定產生的 Apk 檔可順利安裝到 Android 手機 (手機設定須開啟 "允許不明的來源"), 這對不需要用到手機硬體例如相機與 GPS 等功能的行動網頁而言非常方便, 參考 :



首先在 appsgeyser 首頁按 "CREATE APP NOW" 鈕 :




在 "Website URL" 欄填入行動網頁首頁 index.htm 網址, 按 NEXT 鈕 :




在 "APP NAME" 欄位填入 App 名稱, 按 NEXT 鈕 :




在 "ICON" 欄勾選 "Custom icon" (也可用預設), 再按右邊的 "Upload" 鈕上傳最大 512*512 px 的圖檔 (png/jpg/gif 等), 我下載聯合國的 Covid-19 圖示加以編輯, 加上 STOP 字樣作為 App 的圖示, 再用線上軟體 https://www.remove.bg/ 去背, 上傳後還可以截圖, 不需要就直接按 "Crop 鈕" 即可, 按 NEXT 鈕即完成 App 製作準備 : 

 




按 "CREATE" 鈕即開始轉換為 App 作業 :  




但轉換前會要求註冊為會員 (免費會員一次只能轉一個 App), 我因上回已註冊過, 故按 Log In 鈕直接登入, 一會兒便轉換完畢了 (檔名為 _Vaccine_Test_13322400.apk) : 






按 Download 鈕出現 Email 傳送 Apk 檔與 QR code 兩種下載方式 :




也可以按 Apk id 旁的下載鈕將其下載到電腦中保存 :




我用手機掃 QR code 直接下載 Apk 檔, 但安裝前須在手機設定中開啟 Chrome "允許安裝未知來源程式" 權限才行, 以我的三星 Note8 為例 (Android 9), 程序如下 :







參考 :


這樣便能安裝從 Chrome 下載的 Apk 檔了 (因為 appsgeyser 是網路服務, 所產生的 Apk 是從 Chrome 下載, 所以要選擇 Chrome), 安裝時還會出現安全警示, 接受後即可順利安裝, 完畢就可在桌面看到這個有自訂圖示特色的 App 了 : 




點擊執行此 App 確認功能與使用瀏覽器操作行動網頁時完全相同, 轉成原生 App 的好處就是不需要記網址了. 由於 appsgeyser 免費用戶一次只能保存一個專案, 因此上面轉換出來的 Apk 下載 QR code 因為轉別的行動網頁而失效, 因此我將這次下載的 Apk 檔與其圖示 vaccine_test.png 壓縮為 zip 檔寄存 GitHub :

2021年3月2日 星期二

試做燒酒雞

前陣子用鍋寶電子壓力鍋試做了麻油雞後, 就躍躍欲試想換做燒酒雞, 但壓力鍋所附食譜並無燒酒雞 (是因為含酒精的原因嗎), 所以我上網查到阿基師的燒酒雞教學, 覺得遵循大師的做法應該可以做出好吃的燒酒雞 :





製作程序摘要如下 :
  1. 中藥材 (蔘鬚, 川芎, 青耆, 當歸, 枸杞) 先用熱水泡軟後, 放入一瓶米酒煮十分鐘.
  2. 藥材撈起後放入鍋中 (中藥湯水留下備用), 加少許香油拌炒一會兒, 放入雞肉炒至外皮赤黃.
  3. 加入第二瓶米酒煮十分鐘, 倒入中藥湯即可. 
前天去全聯時便買了一包中藥包 (80 元), 昨天 228 補假下午老同學建興來鄉下家拜訪, 我便做此料理留他吃晚餐, 我在廚房一邊跟他聊天, 一邊照記憶中的程序製作, 結果原本說飯吃不多的建興居然連吃四碗飯, 直說好吃好吃. 嗯, 連我樣初次依樣畫葫蘆的也能獲得讚聲, 阿基師不愧是有經驗的大廚啊! 

jQuery Mobile 學習筆記 (十七) : 疫苗登記表專案 (下)

這幾天回頭整理 jQuery Mobile 未完成部分, 這個項目終於接近尾聲了, 就剩下上次幫水某寫的疫苗登記小專案還有一個資料表匯出功能尚未實作, 趁 228 連假待在鄉下就繼續來把它收尾做個 happy ending, 此專案之前的兩篇參考 : 


全部 jQuery Mobile 測試筆記參考 :



6. 匯出資料表 : 

受試者於網頁表單中輸入的資料會被後端 PHP 程式儲存於 MySQL 資料庫的 vaccine 資料表中, 為了資料統計方便最好將其匯出為 EXCEL 試算表, 下載到本機進行資料統計. 匯出資料表為 EXCEL 試算表的方法參考 : 



匯出為 CSV 檔是最簡單的一種方式, 速度快且較不占記憶體. CSV 檔為純文字檔, 既可用一般文字處理軟體開啟, 也可以用 EXCEL 軟體開啟, 一舉兩得.

首先修改 vaccine_subject_admin.php 檔, 為匯出資料表的超連結按鈕加上 href="vaccine_subject_export_csv.php" 屬性值, 注意, 同樣要把預設的 Ajax 功能關掉 : 

# vaccine_subject_admin.php
<?php
//啟動 session 功能
session_start();
//設定台北時間
date_default_timezone_set("Asia/Taipei");
if (!isset($_SESSION["vaccine_admin_account"])) { //未登入回首頁
  header("Location: index.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">
    <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>
    <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">
        <a href="index.htm" data-icon="home" data-ajax="false">回首頁</a>
        <h1>系統管理</h1>
        <a href="logout.php" class="ui-btn-right" data-icon="power" data-ajax="false">登出</a>
      </header>
      <article data-role="content">
        <a href="vaccine_subject_list.php" data-role="button" data-icon="user" data-ajax="false">受試者列表</a>
        <a href="vaccine_subject_export_csv.php" data-role="button" data-icon="action" data-ajax="false">匯出受試者 (CSV)</a>
        <a href="#" data-role="button" data-icon="gear" data-ajax="false">系統設定</a>
      </article>
      <footer data-role="footer" data-position="fixed">
        <h3>小狐狸事務所 07-1234567</h3>
      </footer>
    </section>
    <script>
      $(document).ready(function() {
        });
    </script>
  </body>
</html>

匯出程式 vaccine_subject_export_csv.php 主要任務就是讀取 vaccine 資料表, 然後走訪每一筆紀錄, 並將各欄位值輸出到檔案 vaccine.csv 內, 其內容如下 : 

# vaccine_subject_export_csv.php
<?php
//啟動 session 功能
session_start();
//設定台北時間
date_default_timezone_set("Asia/Taipei");
if (!isset($_SESSION["vaccine_admin_account"])) { //未登入回首頁
  header("Location: index.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">
    <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>
    <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" data-position="fixed">
        <a href="vaccine_admin.php" data-role="button" data-icon="back" data-mini="true"  data-ajax="false">返回</a>
        <h1>匯出受試者資料</h1>
      </header>
      <article data-role="content">
<?php
//設定 CSV 欄位標題
$csv_header=['序號','姓名','年齡','電話','性別','登記日期'];  //CSV 欄位標題
$csv_content=chr(0xEF).chr(0xBB).chr(0xBF);  //UTF-8 BOM 開頭字元 (避免亂碼)
$csv_content .= join(',',$csv_header)."\n";  //合併 BOM 開頭與欄位標題
//建立 PDO 連線物件
$dsn="mysql:host=localhost;port=3306;dbname=test"; 
$username="root"; 
$password="mysql";
try {$conn=new PDO($dsn, $username, $password);}
catch (PDOException $e) {
  echo "資料庫連線錯誤!";
  die();
  }
//設定資料編碼
$conn->exec("SET CHARACTER SET utf8"); 
//讀取受試者資料表
$SQL="SELECT * FROM `vaccine` ORDER BY rdate DESC"; 
$RS=$conn->query($SQL);
$row=$RS->fetch(); 
//迭代整個資料集
while(!empty($row)) {
  $csv_content .= $row["id"].",".$row["name"].",".$row["age"].",".
                  $row["phone"].",".$row["gender"].",".$row["rdate"]."\n";
  $row=$RS->fetch();
  }
$conn=NULL;
file_put_contents('vaccine.csv', $csv_content);
?>
        <h3>資料表匯出成功!</h3>
        <a data-role="button" href="vaccine_subject_download_csv.php" data-ajax="false">下載 vaccine.csv</a>
      </article>
      <footer data-role="footer" data-position="fixed">
        <h3>小狐狸事務所 07-1234567</h3>
      </footer>
    </section>
  </body>
</html>

此程式須注意的是要在 CSV 檔案開頭加上 chr(0xEF).chr(0xBB).chr(0xBF) 這三個 BOM 開頭字元, 否則產生的 utf-8 檔案會出現亂碼, 參考 :


接著讀取 vaccine 資列表,於走訪整個紀錄集時製作 CSV 檔的各列, 結束後呼叫 file_put_contents() 函數將 CSV 內容寫入 vaccine.csv 檔案中, 並輸出匯出成功訊息, 結果如下 : 





按 "下載 vaccine.csv" 鈕即轉至 vaccine_subject_download_csv.php 執行下載, 其內容為 :

#vaccine_subject_download_csv.php
<?php
//啟動 session 功能
session_start();
//設定台北時間
date_default_timezone_set("Asia/Taipei");
if (!isset($_SESSION["vaccine_admin_account"])) { //未登入回首頁
  header("Location: index.htm");
  }
//設定檔案下載標頭
header('Content-Encoding: UTF-8');
header('Content-type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=vaccine.csv');
readfile("vaccine.csv"); //讀取檔案內容並下載
?>  

用純文字編輯軟體例如記事本或 EditPlus 開啟下載的 vaccine.csv 發現內容正常無亂碼 :



 
用 Office 365 的 EXCEL 開啟也 OK (登記日期欄要拉開, 否則顯示 "######") :




但如果用 Office 2003 中的 EXCEL 開啟則出現亂碼 : 




用另存新檔檢查檔案編碼格式, 確定是 UTF-8 + BOM :




其實也可以將 CSV 文字檔偽裝成 XLS 檔案直接下載, 不需要做匯出檔案的動作 (其實上面的 CSV 也可以這樣做), 參考下面這篇的做法 :


修改 vaccine_admin.php, 添加一個 "下載受試者 (XLS)" 按鈕, 導向 vaccine_subject_download_xls.php 程式直接下載 (不需先匯出) :

#vaccine_admin.php
<?php
//啟動 session 功能
session_start();
//設定台北時間
date_default_timezone_set("Asia/Taipei");
if (!isset($_SESSION["vaccine_admin_account"])) { //未登入回首頁
  header("Location: index.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">
    <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>
    <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">
        <a href="index.htm" data-icon="home" data-ajax="false">回首頁</a>
        <h1>系統管理</h1>
        <a href="logout.php" class="ui-btn-right" data-icon="power" data-ajax="false">登出</a>
      </header>
      <article data-role="content">
        <a href="vaccine_subject_list.php" data-role="button" data-icon="user" data-ajax="false">受試者列表</a>
        <a href="vaccine_subject_export_csv.php" data-role="button" data-icon="action" data-ajax="false">匯出受試者 (CSV)</a>
        <a href="vaccine_subject_download_xls.php" data-role="button" data-icon="action" data-ajax="false">下載受試者 (XLS)</a>
        <a href="#" data-role="button" data-icon="gear" data-ajax="false">系統設定</a>
      </article>
      <footer data-role="footer" data-position="fixed">
        <h3>小狐狸事務所 07-1234567</h3>
      </footer>
    </section>
    <script>
      $(document).ready(function() {
        });
    </script>
  </body>
</html>

頁面如下 : 




按 "下載受試者 (XLS)" 按鈕即由 vaccine_subject_download_xls.php 程式下載 XLS 檔案, 程式內容如下 :

#vaccine_subject_download_xls.php
<?php
//啟動 session 功能
session_start();
//設定台北時間
date_default_timezone_set("Asia/Taipei");
if (!isset($_SESSION["vaccine_admin_account"])) { //未登入回首頁
  header("Location: index.htm");
  }
//設定檔案下載標頭
header('Content-type: text/html; charset=utf-8');
header("Content-type:application/vnd.ms-excel;charset=UTF-8"); 
header("Content-Disposition:filename=vaccine.xls");
//建立 PDO 連線物件
$dsn="mysql:host=localhost;port=3306;dbname=test"; 
$username="root"; 
$password="mysql";
try {$conn=new PDO($dsn, $username, $password);}
catch (PDOException $e) {
  echo "資料庫連線錯誤!";
  die();
  }
//設定資料編碼
$conn->exec("SET CHARACTER SET utf8"); 
//讀取受試者資料表
$SQL="SELECT * FROM `vaccine` ORDER BY rdate DESC"; 
$RS=$conn->query($SQL);
$row=$RS->fetch();
echo chr(0xEF).chr(0xBB).chr(0xBF); //UTF-8 BOM
echo "序號,姓名,年齡,電話,性別,登記日期\n"; //輸出表頭
//迭代整個資料集
while(!empty($row)) {
  echo $row["id"].",".$row["name"].",".$row["age"].",".
       $row["phone"].",".$row["gender"].",".$row["rdate"]."\n";
  $row=$RS->fetch();
  }
$conn=NULL;
?>

注意, 基於避免亂碼問題, 同樣要在輸出標頭前先輸出 UTF-8 的 BOM 字元. 其次, 所下載的 vaccine.xls 其實內部檔案格式還是純文字檔 (可用記事本開啟), 使用 Office 365 開啟時會出現格式不符警語, 但不理會它直接開啟即可, 內容正確 (用 Office 2003 開啟則有亂碼):





如果要用 PHP 匯出真正的 XSLX 格式檔案需借助 PHP 的 EXCEL 函式庫, 參考 : 


OK, 終於搞定此專案了, 雖然沒派上用場, 但卻藉此大致寫完 jQuery Mobile 筆記了 (剩下用 Cordova 將行動網頁轉成 App, 但這部分嚴格來說算 Cordova, 不算在 jQuery Mobile 這分類裡). 以上整個系統各網頁程式互動流程更新如下 :




整個專案 zip 壓縮檔先封存在 GitHub :


參考 : 


2021年3月1日 星期一

試作金瓜米粉

去年拜拜時 (端午節? 中秋節?) 爸誤買的米粉放在食物櫃已多時, 剛好今天開了一顆南瓜, 用剩的半顆若放冰箱恐又被塞到下層放到爛, 不如今天與米粉一起做伙來試做金瓜米粉唄! 我搜尋食譜資料找到下面這篇 :


裡面用到小蝦米, 凡是海產乾貨我都不愛 (那腥味~~~哇), 這作法需要將胡蘿蔔與南瓜切絲, 好費工, 所以我又看了阿基師的做法 :





大師做菜果然不同凡響, 但我時間有限 (正在忙著測試 PHP 匯出資料庫與下載檔案), 所以決定照冬粉螞蟻上樹的老戲法來做, 剛好可以把阿泉伯母給的大白菜用掉. 

先將南瓜蒸熟, 米粉浸軟, 絞肉炒香備用, 大白菜做底, 鋪上剪段的米粉, 絞肉, 以及南瓜, 加水 3~4 碗, 淋上醬油, 蓋上鍋蓋, 開中火煮到汁快收乾時補醬油翻炒, 將南瓜充分絞碎即可.





嗯, 金黃色的南瓜香甜味道完全滲入米粉中, 吃起來別有風味. 但老實說, 與冬粉比起來, 我還是比較喜歡冬粉啦! 

PS : 晚上回來找到詹姆士在貴州衛視節目中示範的家傳炒米粉, 下次來試試看 :


2021年2月28日 星期日

jQuery Mobile 學習筆記 (十六) : 事件處理

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 個事件 :
  1. pagebeforecreate
  2. pagecreate
  3. pagebeforeshow
  4. pageshow
然後整份網頁載入完成就顯示第一個頁面, 結果如下 :








點第 2 頁超連結會切換頁面至第 2 頁, 切換到新頁的過程會依序觸發下列 6 個事件 :
  1. pagebeforecreate (新頁)
  2. pagecreate (新頁)
  3. pagebeforehide (舊頁)
  4. pagebeforeshow (新頁)
  5. pagehide (舊頁)
  6. pageshow (新頁)
結果如下 : 










尚未顯示過的頁面第一次切進去時都會觸發 pagebeforecreate 與 pagecreate 這兩個建立頁面相關的事件, 而舊的頁面會被放進頁面堆疊中暫存. 按左上方的 Back 按鈕返回時會依序觸發下列 4 個事件 : 
  1. pagebeforehide (舊頁)
  2. pagebeforeshow (新頁)
  3. pagehide (舊頁)
  4. 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() 控制換頁 :



<!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)

 
例如 : 


<!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 傳遞變數, 例如 : 



<!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>

將手機直放與橫放切換, 結果如下 : 





此例測試網頁 QR code : 



最後來測試 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 為 :