2022年12月30日 星期五

jQuery UI 學習筆記 (十七) : 用下拉式選單做倒數日數計數器

今天是 2022 年最後一個上班日, 單位裡有兩位老同事 65 歲屆齡退休, 看到人家明年就可以睡到自然醒, 令我好生羨慕. 我要到 2031 年 6 月 30 才退, 還有 8 年半左右, 我到 GitHub 個人網站查看上回寫的退休倒數計日程式, 精確來說是 8 年又 183 天, 參考 : 


其實還有很多倒數計日的應用時機, 例如會考, 學測, ... 甚至是預期的平均壽命都可以. 因為很久沒寫 jQueryUI 了, 一時技癢就拿這個來練習一下吧! 將我的退休倒時記日器一般化, 可以選定截止日期, 計算離那個日期還有幾年幾天. 

最直覺的方式是用下拉式選單 SelectMenu, 年月日都設一個, 然後監聽 onchange 事件, 任何一個選擇器改變就立即進行倒數計算. 關於 SelectMenu 用法參考 :


如下面範例 1 所示 : 


測試 1 : 用 jQueryUI 的 SelectMenu 選取年月日以計算倒數日數 [看原始碼]

<!doctype html>
<html>
  <head>
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://code.jquery.com/ui/1.12.1/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script> 
    <style>
      body {
        font-family: 微軟正黑體, Arial, Helvetica, sans-serif;
        font-size:12px;
        }
    </style>
  </head>
  <body>
    <div style="padding: 2px; margin: 3px;">
      <h3>倒數日數計算</h3>
      <p><b>請選擇截止日期 :</b></p>
      <select id="year">
        <option value="2023">2023 年</option>
        <option value="2024">2024 年</option>
        <option value="2025">2025 年</option>
        <option value="2026">2026 年</option>
        <option value="2027">2027 年</option>
        <option value="2028">2028 年</option>
        <option value="2029">2029 年</option>
        <option value="2030">2030 年</option>
        <option value="2031">2031 年</option>
        <option value="2032">2032 年</option>
        <option value="2033">2033 年</option>
        <option value="2034">2034 年</option>
        <option value="2035">2035 年</option>
        <option value="2036">2036 年</option>
        <option value="2037">2037 年</option>
        <option value="2038">2038 年</option>
        <option value="2039">2039 年</option>
        <option value="2040">2040 年</option>
        <option value="2041">2041 年</option>
        <option value="2042">2042 年</option>
        <option value="2043">2043 年</option>
        <option value="2044">2044 年</option>
        <option value="2045">2045 年</option>
        <option value="2046">2046 年</option>
        <option value="2047">2047 年</option>
        <option value="2048">2048 年</option>
        <option value="2049">2049 年</option>
        <option value="2050">2050 年</option>
      </select>
      <select id="month">
        <option value="Jan">1 月</option>
        <option value="Feb">2 月</option>
        <option value="Mar">3 月</option>
        <option value="Apr">4 月</option>
        <option value="May">5 月</option>
        <option value="Jun">6 月</option>
        <option value="Jul">7 月</option>
        <option value="Aug">8 月</option>
        <option value="Sep">9 月</option>
        <option value="Oct">10 月</option>
        <option value="Nov">11 月</option>
        <option value="Dec">12 月</option>
      </select>
      <select id="date">
        <option value="1">1 日</option>
        <option value="2">2 日</option>
        <option value="3">3 日</option>
        <option value="4">4 日</option>
        <option value="5">5 日</option>
        <option value="6">6 日</option>
        <option value="7">7 日</option>
        <option value="8">8 日</option>
        <option value="9">9 日</option>
        <option value="10">10 日</option>
        <option value="11">11 日</option>
        <option value="12">12 日</option>
        <option value="13">13 日</option>
        <option value="14">14 日</option>
        <option value="15">15 日</option>
        <option value="16">16 日</option>
        <option value="17">17 日</option>
        <option value="18">18 日</option>
        <option value="19">19 日</option>
        <option value="20">20 日</option>
        <option value="21">21 日</option>
        <option value="22">22 日</option>
        <option value="23">23 日</option>
        <option value="24">24 日</option>
        <option value="25">25 日</option>
        <option value="26">26 日</option>
        <option value="27">27 日</option>
        <option value="28">28 日</option>
        <option value="29">29 日</option>
        <option value="30">30 日</option>
        <option value="31">31 日</option>
      </select>
    </div>
    <div class="ui-state-highlight ui-corner-all" style="padding: 5px; margin: 5px; width:290px;">
      <span class="ui-icon ui-icon-info"></span>
      <span id="msg" style="font-weight: bold; "></span>
    </div>
    <input type='hidden' id='year_val' value='2023'>
    <input type='hidden' id='month_val' value='1'>
    <input type='hidden' id='date_val' value='1'>
    <script> 
      $(function(){
        function calculate(){
          var the_end=$("#month_val").val() + ' ' + 
                      $("#date_val").val() +  ', ' + 
                      $("#year_val").val();
          var t=Date.parse(the_end)-new Date().getTime();
          var total_days=Math.floor(t / (1000 * 60 * 60 * 24));
          var years=Math.floor(total_days / 365);
          var days=total_days % 365;
          var msg="離截止日期還有 " + years + " 年 " + days + " 天 (共 " + 
                  total_days + " 天)";
          $("#msg").text(msg);        
          }
        $("#year").selectmenu({width: 120});
        $("#month").selectmenu({width: 80});
        $("#date").selectmenu({width: 90});
        $('#year').on('selectmenuchange', function() {
          $("#year_val").val($(this).val());
          calculate();
          });
        $('#month').on('selectmenuchange', function() {
          $("#month_val").val($(this).val());
          calculate();
          });
        $('#date').on('selectmenuchange', function() {
          $("#date_val").val($(this).val());
          calculate();
          });
        calculate();   //初次仔入網頁時顯示初始值
        });
    </script>
  </body>
</html>

此例網頁中設置了三個隱藏元件 (type=hidden 的 input 元素), 分別用來儲存三個 SelectMenu 元件所選定之值, 每一個下拉式選單都有綁定 onchange 事件, 只要選項被改變就會更新相對應之隱藏元件之值, 這部分邏輯被寫成 calculate() 函式來處理. 下拉式選單的初始值就是第一個選項 (2023-01-01) 之值. 注意, SelectMenu 元件的寬度無法用 style 屬性設定 (無效), 必須在初始化時傳入 {width: } 物件來設定. 結果如下 : 




哈哈, 這正是我的退休倒數日數. 

下面改用 HTML5 的 Date 表單元件來選取截止日期, 用法參考下面這篇的範例 4 :


Date 元件可綁定 onchange 事件, 以便選定日期後觸發事件處理函式, 參考 :




<!doctype html>
<html>
  <head>
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://code.jquery.com/ui/1.12.1/themes/hot-sneaks/jquery-ui.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
    <script> 
      function calculate(e){
        alert(e.target.value);
        }
    </script>
    <style>
      body {
        font-family: 微軟正黑體, Arial, Helvetica, sans-serif;
        font-size:12px;
        }
    </style>
  </head>
  <body>
    <div style="padding: 2px; margin: 3px;">
      <h3>倒數日數計算</h3>
      <p><b>請選擇截止日期 :</b></p>
      <input type="date" id="date" onchange="handler(event)"> 
    </div>
    <div class="ui-state-highlight ui-corner-all" style="padding: 5px; margin: 5px; width:290px;">
      <span class="ui-icon ui-icon-info"></span>
      <span id="msg" style="font-weight: bold; "></span>
    </div>
    <script>
      function handler(event){
        var YMD=event.target.value.split("-");   // [2022,12,31]
        var month=['Jan', 'Feb', 'Apr', 'Mar', 'May', 'Jun', 'Jul', 'Aug',
                   'Sep','Oct', 'Nov', 'Dec'];
        var the_end=month[parseInt(YMD[1])-1] + ' ' + YMD[2] +  ', ' + YMD[0];
        var t=Date.parse(the_end)-new Date().getTime();
        var total_days=Math.floor(t / (1000 * 60 * 60 * 24));
        var years=Math.floor(total_days / 365);
        var days=total_days % 365;
        var msg="離截止日期還有 " + years + " 年 " + days + " 天 (共 " + 
                total_days + " 天)";
        $("#msg").text(msg);      
        }
    </script>
  </body>
</html>

此例使用 HTML5 表單元件中的日期選擇器 (type=date 的 input 元件) 來選取截止日期, 注意, 此處所綁定的 onchange 事件, 呼叫端之傳入參數名稱一定要用 event, 亦即必須用 onchange="handler(event)",  用其他參數名稱會出現錯誤 (函式端則不受限, 可用 event 或 e 等等). 由於 Date 元件預設的日期格式為 YYYY-MM-DD, 所以要用 split() 將 Y, M, D 拆開, 其中 M 用陣列對照轉換成英文簡寫, 再與 Y, D 組成例如 'Dec 31, 2022' 的日期格式字串, 結果如下 : 





因為過了 12 點, 所以比上面範例 1 少一天啦. 

有空可以用 jQueryUI 本身的 datepicker 來做, 參考 : 


沒有留言 :