JavaScript -- 現在時刻を設定するボタンを作る (django用)

概要

  • 時/分/秒のフォームに現在時刻を設定してくれるボタンが欲しい
  • djangoでフォームを定義すると、フォーム要素のidが"id_" + "フィールド名"、となることを利用する

イメージ

ボタン要素の id を指定する。ボタンをラップするイメージ。

/* 現在時刻をセットするためのボタン (イベントを登録する) */
/*<button id="datetime-btn"></button> が存在する状態 */
let datetimeBtn = NowButton.wrap("datetime-btn");

背景 (django 側の forms.py)

以下のようなフォームを想定する。

# forms.py
from django import forms


def create_continuous_number_choices(max_val):
    """連続する数値の選択肢を作成する"""
    max_val_range = max_val + 1    # range() に渡すため
    nums = list(range(0, max_val_range))
    nums_choices = list(zip(nums, nums))    # 転置するイメージ
    return nums_choices


class MyDateTimeForm(forms.Form):

    # ※日付フォームは省略

    # 時
    # <option>が多く表示されるので max_val を省略 (24 → 2)
    hour_choices = \
        create_continuous_number_choices(max_val=2)
    hour = forms.ChoiceField(
        choices=hour_choices
    )

    # 分
    minute_choices = \
        create_continuous_number_choices(max_val=2)    # max_val を省略 (59 → 2)
    minute = forms.ChoiceField(
        choices=minute_choices
    )

    # 秒
    second_choices = \
        create_continuous_number_choices(max_val=2)    # max_val を省略 (59 → 2)
    second= forms.ChoiceField(
        choices=second_choices
    )


form = MyDateTimeForm()
str(form)
# ↓
# <tr>
#   <th><label for="id_hour">Hour:</label></th>
#   <td>
#     <select name="hour" id="id_hour">\n
#       <option value="0">0</option>\n\n
#       <option value="1">1</option>\n\n
#       <option value="2">2</option>\n\n
#     </select>
#   </td>
# </tr>\n
# <tr>
#   <th><label for="id_minute">Minute:</label></th>
#   <td>
#     <select name="minute" id="id_minute">\n
#       <option value="0">0</option>\n\n
#       <option value="1">1</option>\n\n
#       <option value="2">2</option>\n\n
#     </select>
#   </td>
# </tr>\n
# <tr>
#   <th><label for="id_second">Second:</label></th>
#   <td>
#     <select name="second" id="id_second">\n
#       <option value="0">0</option>\n\n
#       <option value="1">1</option>\n\n
#       <option value="2">2</option>\n\n
#     </select>
#   </td>
# </tr>

NowButton.wrap() を定義する (ボタン要素の取得 + イベント登録)

/**
 *
 * now-button.js
 *
 */
const NowButton = (function () {

  /* 
   * ボタン要素を取得して、
   * フォームに現在時刻をセットするイベントを登録する
   */
  function wrap(buttonId, 
    hourFieldName="hour",
    minuteFieldName="minute",
    secondFieldName="second") {

    /* ボタンを取得する */
    let button = document.getElementById(buttonId);
    if (!button) {
      let emsg = `button #${buttonId} not found`;
      throw new Error(emsg);
    }

    /* フォームを取得する */
    let fieldNames = [
      hourFieldName, minuteFieldName, secondFieldName
    ];
    let [hourForm, minuteForm, secondForm] = fieldNames.map(function (fn) {

      // django でフォームを定義すると、
      // フォーム要素の id は id_ + "フィールド名"になる
      let form = document.getElementById(`id_${fn}`);

      if (!form) {
        let emsg = `form #id_${fn} not found`;
        throw new Error(emsg);
      }

      return form;
    });
    
    /* ボタンクリック時の処理を追加する */
    button.addEventListener("click", function () {

      /* 現在時刻を取得する */
      let now = new Date();

      /* フォームに値をセットする */
      hourForm.value = now.getHours();
      minuteForm.value = now.getMinutes();
      secondForm.value = now.getSeconds();

    }, false);

    return button;
  }    // end of function wrap() {...}

  return {
    wrap: wrap,
  };
}());