2020年10月18日 星期日

jQuery Mobile 學習筆記 (六) : 表單元件 (上)

本篇繼續測試 jQuery Mobile 的表單元件. 本系列之前的文章參考 :

jQuery Mobile 學習筆記 (三) : 工具列
jQuery Mobile 學習筆記 (四) : 對話框
參考書籍 :
  1. jQuery Mobile 智慧型手機程式開發 (博碩, 岡本隆史)
  2. HTML5+CSS3+jQuery Mobile 輕鬆打造 App 與行動網站 (博碩, 陳婉凌)
  3. PhoneGap 跨平台手機程式開發實戰 (上奇, 張亞飛)
  4. 徹底研究 jQuery Mobile + PHP 手機程式及網站開發 (上奇, 張亞飛)
  5. jQuery Mobile 跨平台開發寶典 (上奇, 陶國榮)
  6. PHP+MySQL+jQuery Mobile 跨行動裝置網站開發 (碁峰, 陳會安)
  7. Visual Studio 2015 X Cordova跨平台App實戰特訓班 (碁峰, 文淵閣工作室)
  8. Javascript + jQuery Mobile + Node.js 跨平台網頁設計範例教本 (碁峰, 陳會安) 
  9. 錢沾計畫啟動:jQuery Mobile 跨平台賺錢 App 錢途無量 (佳魁, 李科泉) 

表單是常用的使用者互動介面, 例如使用者登入頁面的帳密輸入, 客戶滿意度調查, 以及論壇線上投票等等. 使用 jQuery Mobile 表單元件須注意下列幾點 : 

  • jQuery Mobile 表單元件大部分直接使用 HTML5 原生表單元素 (input, select, textarea), 幾乎不需要用到特定的 data-role 屬性, jQuery Mobile 函式庫會自動將其轉換成適合行動裝置觸控操作的 jQuery Mobile 表單元件.
  • jQuery Mobile 的表單預設使用 Ajax 提交給後端伺服器, 如果要以傳統的 HTTP 方式提交, 可在 form 元素中添加 data-ajax="false" 屬性, 例如 :
    <form method="POST" action="login.php" data-ajax="false">
    ...
    </form>
  • 為了讓使用者方便於表單元件中輸入資料, 每一個表單欄位應該搭配一個 label 元素, 並且用 for 屬性綁定表單欄位的 id 屬性, 例如 :
    <label for="account">帳號</label>
    <input type="text" id="account" placeholder="請輸入帳號">
    這樣此表單欄位可觸控面積也包含 label, 亦即點擊 "帳號" 也會讓焦點進入文字輸入欄位.
  • 為了讓 label 的欄位標籤與表單欄位因應行動裝置螢幕大小自動調整配置方式, jQuery Mobile 建議使用具有 data-role="fieldcontain" 屬性的 div 元素包覆表單欄位與其 label 元素, 例如 : 
    <div data-role="fieldcontain">
      <label for="account">帳號</label>
      <input type="text" id="account" placeholder="請輸入帳號">
    </div>
    這樣做也會在該欄位下方就會出現一條分隔線以示欄位區別.
  • 如果不想要 jQuery Mobile 將原生 HTML 表單自動初始化為 jQuery Mobile 表單, 可以在該表單元件中添加 data-role="none" 屬性, 例如 : 
    <label for="account">帳號</label>
    <input type="text" id="account" placeholder="請輸入帳號" data-role="none">
    不過這大概只有在測試比較時才會用上吧!

jQuery Mobile 支援的表單欄位如下表 : 


 表單元件 說明
 按鈕 button 元素, input 元素 (type=button/submit/reset)
 文字輸入 單行 : input 元素 (type=text/password), 多行 : textarea 元素
 選項 單選 : input 元素 (type=radio), 複選 : input 元素 (type=checkbox)
 下拉式選單 select 元素 (單選/複選)
 滑桿 input 元素 (type=range)
 滑動開關 select 元素 (data-role=slider)


其中按鈕部分已經測試過了, 參考 :

jQuery Mobile 學習筆記 (二) : 按鈕

關於 HTML5 表單參考 :

網頁技術速學筆記 (四) : HTML 表單


一. 文字輸入 : 

單行文字輸入欄位為 input 元素, 其 type 有如下四個 : 

  • text (任何字元輸入)
  • password (隱藏之任何字元輸入)
  • search (任何字元輸入, 具有按 enter 提交之功能)
  • number (只能輸入 0~9 數字字元與小數點)

這四個元件基本上都是單行文字欄位, 不同處在於 password 中的字元預設以黑點表示, search 會在文字框前端顯示一個放大鏡圖示, 後端顯示一個刪除圖示; 而 number 則只能輸入數字. 存取文字欄位之輸入值可用 jQuery 物件的 val() 方法, 無傳入參數為 getter (取), 有傳入參數為 setter (存), 例如 :


測試 1-1 : 單行文字欄位 (1) [看原始碼]

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form>
          <label for="account">帳號</label>
          <input type="text" id="account" name="account" placeholder="請輸入帳號">
          <label for="password">密碼</label>
          <input type="password" id="password" name="password" placeholder="請輸入密碼">
          <label for="age">年齡</label>
          <input type="number" id="age" name="age" placeholder="請輸入年齡">          
          <label for="search">搜尋</label>          
          <input type="search" id="search" name="search" placeholder="請輸入搜尋字串">
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
           $("#ok_btn").on("click", function(e) {
             var msg="帳號=" + $("#account").val() + "\n" +
                     "密碼=" + $("#password").val() + "\n" +
                     "年齡=" + $("#age").val() + "\n" +
                     "搜尋=" + $("#search").val();
             alert(msg);
             });
          });
      </script>
    </section>
  </body>
</html>

此例有四個 input 單行文字欄位以及一個按鈕, 按下按鈕會將各欄位輸入值以 alert() 顯示 : 




此例網址 QR code 如下 : 


此例在 form 表單元素中沒有 method 屬性, 預設為用 get 方法提交表單, 但因為沒有 action 屬性, 因此提交表單會出現 "Error Loading Page" 的錯誤訊息. 下面範例指定後端處理程式 form_test_1_2.php, 同時將有 label 的表單元件用含有 data-role="fieldcontain" 的 div 元素包覆 :


測試 1-2 : 單行文字欄位 (2) : 有 fieldcontain [看原始碼]

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_1_2.php">
          <div data-role="fieldcontain">
            <label for="account">帳號</label>
            <input type="text" id="account" name="account" placeholder="請輸入帳號">
          </div>
          <div data-role="fieldcontain">
            <label for="password">密碼</label>
            <input type="password" id="password" name="password" placeholder="請輸入密碼">
          </div>
          <div data-role="fieldcontain">
            <label for="age">年齡</label>            
            <input type="number" id="age" name="age" placeholder="請輸入年齡">
          </div>
          <div data-role="fieldcontain">
            <label for="search">搜尋</label>
            <input type="search" id="search" name="search" placeholder="請輸入搜尋字串">
          </div>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

此例與上例差別是將表單元件以具有 data-role="fieldcontain" 屬性之 div 元素包覆, 其次是 form 元素有 action 屬性指定提交表單給位於另一個網域的後端 PHP 程式處理 (因 GitHub 不支援動態網頁) 並輸出網頁. 注意, jQuery Mobile 會自動將 form 元素內的按鈕元素改成 type=submit 之提交按鈕, 因此上面的 this.form.submit() 其實是多餘的, 沒有這些程式碼還是會提交. 結果如下 : 




可見使用 fieldcontain 包覆表單欄位, 每個欄位後面會出現一條分隔線. 按下確定鈕後會執行 this.form.submit() 提交表單, 但其實不用這個按鈕也是可以的, 在任何一個欄位中按下 Enter 都會提交網頁, 這是 jQuery Mobile 較特別之處. 後端 PHP 程式 form_test_1_2.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">
    <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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
      <?php
        $msg="帳號=".$_REQUEST["account"]."<br>".
             "密碼=".$_REQUEST["password"]."<br>".
             "年齡=".$_REQUEST["age"]."<br>".
             "搜尋=". $_REQUEST["search"];
        echo $msg;
      ?>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
    </section>
  </body>
</html>

此程式使用 PHP 的 $_REQUEST[] 全域變數取得前端表單傳送之參數並用 echo 輸出. 注意, 為了頁面視覺上的一致, 該程式必須複製 jQuery Mobile 網頁之頁面 HTML 碼, 若僅僅是將提交的表單元件內容以 echo 輸出則會失去 jQuery Mobile 頁面外觀, 結果如下 : 



此例網址 QR code 如下 :


輸入多行文字要使用 textarea 元素, 與原生 HTML5 不同的是, jQuery Mobile 會將 textarea 固定繪製成兩列高度, 亦即使用 rows 屬性指定列數是沒有用的, jQuery Mobile 會隨使用者輸入之內容自動調整列高, 例如 :


測試 1-3 : 多行文字欄位 : 有 fieldcontain [看原始碼]

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_1_3.php">
          <div data-role="fieldcontain">
            <label for="remark">評論</label>
            <textarea id="remark" name="remark" placeholder="請輸入評論"></textarea>
          </div>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert($("#remark").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

注意, 此例中的提交按鈕是必要的, 因為在 textarea 中按 Enter 的作用是跳行, 不像單行文字欄位那樣被視為是提交. 其次, 雖然 textarea 元素有結束標籤, 但輸入的內容是放在 value 屬性而非 innerHTML 屬性中, 因此以 jQuery 存取其值時需呼叫 val() 方法, 不是 html() 方法. 結果如下 :




按下確定鈕會將表單提交給另一網域的 form_test_1_3.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">
    <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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_1_3.php">
          <div data-role="fieldcontain">
            <label for="remark">評論</label>
            <textarea id="remark" name="remark" placeholder="請輸入評論"></textarea>
          </div>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert($("#remark").val());
            this.form.submit();  //也可以不用
            });
          });
      </script>
    </section>
  </body>
</html>

此 PHP 程式會輸出 jQuery Mobile 網頁 : 




此例網址 QR code 如下 :



二. 選擇元件 : 

HTML5 的選擇元件有下列四種 :

  • 單選圓鈕 (radio) : 單選
  • 核取方塊 (checkbox) : 複選
  • 下拉式選單 (select) : 單選或複選 
  • 選項開關 (select) : 二選一單選

其中 radio 與 checkbox 都是由數個選項組成, 它們的 name 屬性值必須相同 radio 才會有單選的效果, 且對後端而言它們代表單一變數, 因此 name 必須一樣. 其次, 它們的選項可以用 checked 屬性來設定為預設被選取. 

使用 jQuery 存取 radio 被選取之選項值可使用名稱選擇器搭配 checked 狀態, 例如 :

$("[name=元素名稱]:radio:checked").val();

對於 checkbox 而言也是一樣, 但由於 checkbox 可以複選, 因此選擇器取得的是被選取選項之物件集合, 必須用 each() 方法迭代取出其值並放到陣列中 : 

var selected=[];
$("[name=元素名稱]:checkbox:checked").each(function(){
  selected.push($(this).val());
  })

對於單選的下拉式選單與滑動開關而言, 直接呼叫 val() 方法即可取得被選取之選項值 (未選傳回 null); 但對於複選的下拉式選單來說, 也與 checkbox 一樣須使用 each() 方法迭代 :

var selected=[];
$("[name=元素名稱] :selected").each(function(){  //注意 :selected 前要空一格
  selected.push($(this).val());
  })

參考 : 

jQuery 常用技法整理


下面是 radio 的範例 :


測試 2-1 : 單選圓鈕 (1) : 無 fieldset [看原始碼]

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_1.php">
          <div data-role="fieldcontain">
            <p>學歷:</p>
            <label for="ed-1">國中</label>
            <input type="radio" name="education" id="ed-1" value="國中">
            <label for="ed-2">高中</label>
            <input type="radio" name="education" id="ed-2" value="高中">
            <label for="ed-3">大學</label>
            <input type="radio" name="education" id="ed-3" value="大學" checked>
            <label for="ed-4">研究所</label>
            <input type="radio" name="education" id="ed-4" value="研究所">
          </div>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert($("[name=education]:radio:checked").val());
            this.form.submit();  //也可以不用
            });
          });
      </script>
    </section>
  </body>
</html>

此例四個選項之 name 都相同為 education, 使用 checked 屬性將大學這一項預設為被選取, 結果如下 : 



按確定鈕會將表單提交給後端程式 form_test_2_1.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">
    <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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
      <?php
        $msg="學歷:".$_REQUEST["education"];
        echo $msg;
      ?>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
    </section>
  </body>
</html>

此程式用 $_REQUEST["education"] 取得表單所傳遞之變數 education 並輸出, 結果如下 : 



此例網址 QR code 如下 :


也可以將選項元件用具有 data-role="controlgroup" 的 fieldset 元素包覆起來, jQuery Mobile 會以控制群組繪製這些選項, 使其組合在一起, 例如 : 


測試 2-2 : 單選圓鈕 (2) : 使用 fieldset 包覆表單元件 (圖示預設在左邊) [看原始碼]

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_1.php">
          <fieldset data-role="controlgroup">
            <legend>學歷:</legend>
            <div data-role="fieldcontain">
              <label for="ed-1">國中</label>
              <input type="radio" name="education" id="ed-1" value="國中">
              <label for="ed-2">高中</label>
              <input type="radio" name="education" id="ed-2" value="高中">
              <label for="ed-3">大學</label>
              <input type="radio" name="education" id="ed-3" value="大學" checked>
              <label for="ed-4">研究所</label>
              <input type="radio" name="education" id="ed-4" value="研究所">
            </div>
            <button id="ok_btn">確定</button>
          </fieldset>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert($("[name=education]:radio:checked").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

此例將表單元件用 fieldset 元素包覆, 並添加 data-role="controlgroup" 屬性, 這樣做的好處是可讓個選項變成一個控制群組, 同時原先使用 p 元素包覆的標題文字也可以直接放到 legend 元素裡面, 結果如下 : 




與上例比較, 可見在 fieldset 中使用 data-role="controlgroup"  可使個選項無空隙地綁在一起, 具有整體之視覺效果, 以下範例均採此結構. 按確定鈕仍與上例一樣將表單提交給後端程式 form_test_2_1.php 處理, 結果相同不再列出. 此例網址 QR code 如下 :



單選圓鈕 radio 與核取方塊  checkbox 圖示都在前面 (左邊), 也可以在 fieldset 元素中添加 data-iconpos="right" 屬性將其改為放在後面 (右邊), 例如 :


測試 2-3 : 單選圓鈕 (3) : 使用 fieldset 包覆表單元件 (圖示改在右邊) [看原始碼]

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_1.php">
          <fieldset data-role="controlgroup" data-iconpos="right">
            <legend>學歷:</legend>
            <div data-role="fieldcontain">
              <label for="ed-1">國中</label>
              <input type="radio" name="education" id="ed-1" value="國中">
              <label for="ed-2">高中</label>
              <input type="radio" name="education" id="ed-2" value="高中">
              <label for="ed-3">大學</label>
              <input type="radio" name="education" id="ed-3" value="大學" checked>
              <label for="ed-4">研究所</label>
              <input type="radio" name="education" id="ed-4" value="研究所">
            </div>
            <button id="ok_btn">確定</button>
          </fieldset>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert($("[name=education]:radio:checked").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

結果如下 : 



此例網址 QR code 如下 :


也可以在 fieldset 上添加 data-type="horizontal" 來使選項做水平排列, 例如 : 


測試 2-4 : 單選圓鈕 (4) : 使用 data-type="horizontal" 使選項水平排列 (圖示改在右邊) [看原始碼]

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_1.php">
          <fieldset data-role="controlgroup" data-type="horizontal">
            <legend>學歷:</legend>
            <div data-role="fieldcontain">
              <label for="ed-1">國中</label>
              <input type="radio" name="education" id="ed-1" value="國中">
              <label for="ed-2">高中</label>
              <input type="radio" name="education" id="ed-2" value="高中">
              <label for="ed-3">大學</label>
              <input type="radio" name="education" id="ed-3" value="大學" checked>
              <label for="ed-4">研究所</label>
              <input type="radio" name="education" id="ed-4" value="研究所">
            </div>
          </fieldset>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert($("[name=education]:radio:checked").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

注意, 此例將確定按鈕從 fieldset 中移出, 否則按鈕會與選項黏在一起, 結果如下 : 



可見水平排列時 radio 選項都被繪製成按鈕群組, 沒有圓鈕了, 當選項較多時排到列尾會折返, 視覺上沒有比預設垂直排列好看 (少了圓鈕圖示似乎失去單選的意涵), 此例網址 QR code 如下 :



接下來是可複選的 checkbox, 與 radio 一樣每個選項之 name 屬性值相同, 但若向 radio 那樣直接提交, 則後端將只取得複選選項中的一個值, 例如 : 



<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_5.php">
          <fieldset data-role="controlgroup">
            <legend>擅長的程式語言:</legend>
            <div data-role="fieldcontain">
              <label for="lan-1">Python</label>
              <input type="checkbox" name="language" id="lan-1" value="Python" checked>
              <label for="lan-2">Javascript</label>
              <input type="checkbox" name="language" id="lan-2" value="Javascript">
              <label for="lan-3">R 語言</label>
              <input type="checkbox" name="language" id="lan-3" value="R 語言">
              <label for="lan-4">Swift</label>
              <input type="checkbox" name="language" id="lan-4" value="Swift" checked>
              <label for="lan-5">C 語言</label>
              <input type="checkbox" name="language" id="lan-5" value="C 語言">
            </div>
          </fieldset>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            var selected=[];
            $("[name=language]:checkbox:checked").each(function(){
              selected.push($(this).val());
              });
            alert("選取的語言=" + selected.join());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

此例五個選項 name 屬性相同都是 language (不同的 id 是為了綁定各自的 label), 按下確定鈕後再提交前利用 each() 可以取得被選取之選項值陣列, 但提交到後端後用 $_REQUEST["language"] 卻只取得最後一個被選取選項之值 (此例為 "R 語言"), 結果如下 : 






後端處理程式 form_test_2_5.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">
    <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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
      <?php
        $msg="選取的語言=".$_REQUEST["language"];
        echo $msg;
      ?>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
    </section>
  </body>
</html>

此例網址 QR code 如下 :



此問題的解決辦法之一是在提交至後端前先對被選取項之值進行預處理, 通常是在表單中新增一個隱藏欄位 (input[type=hidden]), 按確定鈕後用 each() 取得被選取項之值陣列, 再呼叫 join() 轉成字串後存入隱藏欄位中, 這時 PHP 後端程式只要擷取此隱藏欄位變數再用 explode() 函數拆解字串即可獲得被選取值, 例如 : 



<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_4.php">
          <fieldset data-role="controlgroup">
            <legend>擅長的程式語言:</legend>
            <div data-role="fieldcontain">
              <label for="lan-1">Python</label>
              <input type="checkbox" name="language" id="lan-1" value="Python" checked>
              <label for="lan-2">Javascript</label>
              <input type="checkbox" name="language" id="lan-2" value="Javascript">
              <label for="lan-3">R 語言</label>
              <input type="checkbox" name="language" id="lan-3" value="R 語言">
              <label for="lan-4">Swift</label>
              <input type="checkbox" name="language" id="lan-4" value="Swift" checked>
              <label for="lan-5">C 語言</label>
              <input type="checkbox" name="language" id="lan-5" value="C 語言">
            </div>
          </fieldset>          
          <button id="ok_btn">確定</button>
          <input type="hidden" name="selected_languages" id="selected_languages">
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            var selected=[];
            $("[name=language]:checkbox:checked").each(function(){
              selected.push($(this).val());
              });
            $("#selected_languages").val(selected.join());
            alert("選取的語言=" + $("#selected_languages").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

此例在 form 表單內新增一個 name="selected_languages" 的隱藏欄位, 並在按下確定鈕時將 each() 所取得的被選取項值陣列以 join() 轉成逗號相隔之字串後儲存於此隱藏欄位中, 然後在後端程式中擷取 selected_languages 參數 (而非 checkbox 的 language 參數), 結果如下 :






可見這樣後端程式就可以取得正確的被選取值了, 此後端程式內容如下 : 

<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
      <?php
        $msg="選取的語言=".$_REQUEST["selected_languages"];
        echo $msg;
      ?>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
    </section>
  </body>
</html>

此例網址 QR code 如下 :



核取方塊也可以水平放置, 下面範例是在上例的 fieldset 元素中添加 data-type="horizontal" 屬性 :



<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_6.php">
          <fieldset data-role="controlgroup" data-type="horizontal">
            <legend>擅長的程式語言:</legend>
            <div data-role="fieldcontain">
              <label for="lan-1">Python</label>
              <input type="checkbox" name="language" id="lan-1" value="Python" checked>
              <label for="lan-2">Javascript</label>
              <input type="checkbox" name="language" id="lan-2" value="Javascript">
              <label for="lan-3">R 語言</label>
              <input type="checkbox" name="language" id="lan-3" value="R 語言">
              <label for="lan-4">Swift</label>
              <input type="checkbox" name="language" id="lan-4" value="Swift" checked>
              <label for="lan-5">C 語言</label>
              <input type="checkbox" name="language" id="lan-5" value="C 語言">
            </div>
          </fieldset>
          <button id="ok_btn">確定</button>
          <input type="hidden" name="selected_languages" id="selected_languages">
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            var selected=[];
            $("[name=language]:checkbox:checked").each(function(){
              selected.push($(this).val());
              });
            $("#selected_languages").val(selected.join());
            alert("選取的語言=" + $("#selected_languages").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

結果如下 :





可見水平放置時核取方塊圖示不見了, 且選項太多時會折回, 視覺效果沒有比預設垂直時好, 此例網址 QR code 如下 :



從上面測試可知, 不管是 radio 或 checkbox, 當選項多的時候就會佔去螢幕大部分高度, 這時最好是改用 select 元素製作下拉式選單以節省螢幕空間, select 元素透過 multiple 屬性值為 true 或 false 可控制選項為複選 (true, 與 checkbox 功能相同) 或單選 (false, 與 radio 功能相同), 沒有multiple 屬性預設為單選 :

單選的下拉式選單 : 

<select>
  <option value="值1">選項1</option>
  <option value="值2">選項2</option>
  <option value="值3">選項3</option>
</select>

複選的下拉式選單 : 

<select multiple="true">
  <option value="值1">選項1</option>
  <option value="值2">選項2</option>
  <option value="值3">選項3</option>
</select>

在 option 元素中添加 selected 屬性可將該選項設定為預設被選取狀態, 預設的 HTML5 原生單選下拉式選單例如 :



<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_5.php">
          <fieldset data-role="controlgroup">
            <legend>擅長的程式語言:</legend>
            <div data-role="fieldcontain">
              <select id="language" name="language">
                <option value="Python" selected>Python</option>
                <option value="Javascript">Javascript</option>
                <option value="R 語言">R 語言</option>
                <option value="Swift">Swift</option>
                <option value="C 語言">C 語言</option>
              </select>
            </div>
          </fieldset>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert("選取的語言=" + $("#language").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

單選的下拉式選單只要用 val() 存取即可, 後端處理程式沿用同樣擷取 language 變數的 form_test_2_5.php, 結果如下 :




點按下拉式選單會彈出選項表, 由右方的圓鈕圖示可知為單選, 點選後該表會自動消失. 此例網址 QR code 如下 :



與 radio/checkbox 不同的是, jQuery Mobile 有特別為 select 元素製作樣式主題, 使用此樣式的方法是在 select 元素中添加 data-native-menu="false" 屬性, 這樣就會可關閉原生樣式而改用 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">
    <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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_5.php">
          <fieldset data-role="controlgroup">
            <legend>擅長的程式語言:</legend>
            <div data-role="fieldcontain">
              <select id="language" name="language" data-native-menu="false">
                <option value="Python" selected>Python</option>
                <option value="Javascript">Javascript</option>
                <option value="R 語言">R 語言</option>
                <option value="Swift">Swift</option>
                <option value="C 語言">C 語言</option>
              </select>
            </div>
          </fieldset>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert("選取的語言=" + $("#language").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

此例在 select 元素中添加 data-native-menu="false" 屬性以關閉原生 HTML5 樣式, 結果如下 : 




可見 jQuery Mobile 自訂的下拉式選單捨棄了右邊的圓鈕圖示, 故面積較小且較美觀. 此例網址 QR code 如下 :



下面是複選的下拉式選單, 其功能與 checkbox 相同, 存取被選取項目的方法也是一樣要用空陣列搭配 each() 迴圈 : 



<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_6.php">
          <fieldset data-role="controlgroup">
            <legend>擅長的程式語言:</legend>
            <div data-role="fieldcontain">
              <select id="language" name="language" data-native-menu="false" multiple>
                <option value="Python" selected>Python</option>
                <option value="Javascript">Javascript</option>
                <option value="R 語言">R 語言</option>
                <option value="Swift">Swift</option>
                <option value="C 語言">C 語言</option>
              </select>
            </div>
          </fieldset>
          <input type="hidden" name="selected_languages" id="selected_languages">
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            var selected=[];
            $("[name=language] :selected").each(function(){   //注意 :selected 前面要空一格
              selected.push($(this).val());
              });
            $("#selected_languages").val(selected.join());
            alert("選取的語言=" + $("#selected_languages").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

此例與 checkbox 一樣使用隱藏欄位 id=selected_languages 來儲存被選取項目值之組合字串, 因此後端處理程式需改用 form_tes_2_6.php, 結果如下 : 




可見雖然採用 jQuery Mobile 自訂樣式, 但與單選時不同的是保留了右邊的核取方塊圖示, 點選選項後按上方的 X 圖示關閉選單, 這時所選之選項值會顯示於按鈕上, 且被選取數會以計數泡泡呈現, 結果如下 : 




按確定提交給後端處理程式輸出 jQuery Mobile 網頁 :




此例網址 QR code 如下 :


jQuery Mobile 還有一個選擇元件叫做滑動開關, 它其實只是個二選一的單選 select 元素, 但 jQuery Mobile 為此元件製作了 data-rol="slider" 屬性, 只要添加此屬性, 原本的下拉式選單就變成美美的滑動開關了, 通常用做 "是/否" 或 "開啟/關閉" 等二選一的設定, 例如 : 



<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_11.php">
          <div data-role="fieldcontain">
            <label for="auto_update">自動更新</label>
            <select id="auto_update" name="auto_update" data-role="slider">
              <option value="是" selected>是</option>
              <option value="否">否</option>
            </select>
          </div>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            alert("自動更新=" + $("#auto_update").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

此例是沒有使用 fieldset 包覆的範例, 因為是單選, 只要用 val() 方法即可存取滑動開關之值, 結果如下 :




顯示 "是" 表示目前之值為 "是", 左右滑動可切換設定 : 




顯示 "否" 表示目前之值為 "否", 按確定提交表單 :




此例網址 QR code 如下 :



下面是用有 controlgroup 屬性的 fieldset 包覆的範例 : 



<!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">
        <h1>表單元件測試</h1>
      </header>
      <article data-role="content">
        <form method="post" action="http://tony1966.xyz/test/jqmtest/form_test_2_11.php">
          <fieldset data-role="controlgroup">
            <legend>系統設定</legend>
            <div data-role="fieldcontain">
              <label for="auto_update">自動更新:</label>
              <select id="auto_update" name="auto_update" data-role="slider">
                <option value="是" selected>是</option>
                <option value="否">否</option>
              </select>
            </div>
          </fieldset>
          <button id="ok_btn">確定</button>
        </form>
      </article>
      <footer data-role="footer">
        <h3>頁尾</h3>
      </footer>
      <script>
        $(document).on("pageinit", "#page1", function(e) {
          $("#ok_btn").on("click", function(e) {
            var selected=[];
            $("[name=language] :selected").each(function(){
              selected.push($(this).val());
              });
            $("#selected_languages").val(selected.join());
            alert("選取的語言=" + $("#selected_languages").val());
            this.form.submit();
            });
          });
      </script>
    </section>
  </body>
</html>

結果如下 :






此例網址 QR code 如下 :



1 則留言: