<div class="utility-08 p-2" id="js-utility-08">
    <div class="field">
        <div class="control"><input class="input" id="js-utility-08-input" type="text" placeholder="Text input" /></div>
    </div>
    <div class="field is-grouped is-grouped-centered">
        <div class="control"><button class="button is-primary" id="js-utility-08-start" disabled="disabled">開始</button></div>
        <div class="control"><button class="button is-danger" id="js-utility-08-stop" disabled="disabled">中止</button></div>
    </div>
    <p class="mt-4 has-text-centered is-size-3" id="js-utility-08-text"></p>
</div>
#js-utility-08.utility-08.p-2
  .field
    .control
      input#js-utility-08-input.input(type='text', placeholder='Text input')
  .field.is-grouped.is-grouped-centered
    .control
      button#js-utility-08-start.button.is-primary(disabled) 開始
    .control
      button#js-utility-08-stop.button.is-danger(disabled) 中止
  p#js-utility-08-text.mt-4.has-text-centered.is-size-3
/* No context defined. */
  • Content:
    $BLOCK_NAME: '.utility-08';
    
    // 変数
    
    #{ $BLOCK_NAME } {
      //
    }
    
  • URL: /components/raw/utility08/utility08.scss
  • Filesystem Path: src/components/utilities/utility08/utility08.scss
  • Size: 73 Bytes
  • Content:
    'use strict';
    
    import flatpickr from 'flatpickr';
    import { Japanese } from 'flatpickr/dist/l10n/ja.js';
    
    export const utility08 = () => {
      const utility = new Utility08();
      utility.init();
    }
    
    class Utility08 {
      el: HTMLElement;
      inputEl: HTMLInputElement;
      startEl: HTMLButtonElement;
      stopEl: HTMLButtonElement;
      textEl: HTMLElement;
      targetDate: Date;
      timer: any;
      constructor() {
        this.el = document.getElementById('js-utility-08');
        this.inputEl = <HTMLInputElement>document.getElementById('js-utility-08-input');
        this.startEl = <HTMLButtonElement>document.getElementById('js-utility-08-start');
        this.stopEl = <HTMLButtonElement>document.getElementById('js-utility-08-stop');
        this.textEl = document.getElementById('js-utility-08-text');
        this.targetDate = null;
        this.timer = null;
      }
    
      /**
       * 初期化
       */
      init(): void {
        if (!this.el) return;
        this.inputInit();
        this.onClickStart();
        this.onClickStop();
      }
    
      /**
       * 日時入力の初期化
       */
      inputInit(): void {
        const now = new Date();
        flatpickr(this.inputEl, {
          locale : Japanese,
          dateFormat : 'Y年m月d日(D)H:i',
          defaultDate : now,
          minDate: now,
          enableTime: true,
          minuteIncrement: 1,
        });
        this.startEl.disabled = null;
      }
    
      /**
       * カウントダウン開始
       */
      countDown(): void {
        const remainTime = this.getRemainTime();
        if (!remainTime) {
          this.countDownFinish();
          this.timer = null;
          return;
        }
        // カウントダウン文字列を設定
        this.countDownSetText(remainTime.d, remainTime.h, remainTime.m, remainTime.s);
        // 1秒後にカウントダウンを実行
        this.timer = setTimeout(() => {
          this.countDown();
        }, 1000);
      }
    
      /**
       * 残り時間を取得
       * @returns 残り時間の数値のオブジェクト
       */
      getRemainTime(): { d: number, h: number, m: number, s: number } | null {
        const now = new Date();
        // 現在日時と目標日時の秒数差分を計算
        const diff = this.targetDate.getTime() - now.getTime();
        // 目標日時を過ぎている場合、nullを返す
        if (diff <= 0) {
          return null;
        }
        // 差分から残り日時の数値を計算
        const d = Math.floor(diff / (24 * 60 * 60 * 1000));
        const h = Math.floor(diff % (24 * 60 * 60 * 1000) / (60 * 60 * 1000));
        const m = Math.floor(diff % (60 * 60 * 1000) / (60 * 1000));
        const s = Math.floor(diff % (60 * 1000) / 1000);
        return { d, h, m, s };
      }
    
      /**
       * カウントダウン文字列を設定
       * @param day 残りの日
       * @param hour 残りの時間
       * @param minute 残りの分
       * @param second 残りの秒
       */
      countDownSetText(day: number, hour: number, minute: number, second: number): void {
        this.textEl.innerText = `残り ${day}${hour}時間 ${minute}${second}秒`;
      }
    
      /**
       * カウントダウンを完了
       */
      countDownFinish(): void {
        // 完了メッセージを表示
        this.textEl.innerText = 'カウントダウンが完了しました';
        // 目標日時をクリア
        this.targetDate = null;
        this.startEl.disabled = null;
        this.stopEl.disabled = true;
      }
    
      /**
       * 開始ボタンクリック時のイベント設定
       */
      onClickStart(): void {
        this.startEl.addEventListener('click', () => {
          // 入力されている日時から目標日時を設定
          const inputVal = this.inputEl.value;
          const year = Number(inputVal.substring(0, 4));
          const month = Number(inputVal.substring(5, 7)) - 1;
          const day = Number(inputVal.substring(8, 10));
          const hour = Number(inputVal.substring(14, 16));
          const minute = Number(inputVal.substring(17, 19));
          this.targetDate = new Date(
            year,
            month,
            day,
            hour,
            minute
          );
          const now = new Date();
          if (this.targetDate.getTime() > now.getTime()) {
            this.startEl.disabled = true;
            this.stopEl.disabled = null;
            // 未来の日付が設定されている場合、カウントダウンを開始
            this.countDown();
          } else {
            // 未来の日付が設定されていない場合、処理を終了
            alert('カウントダウンの目標日時は未来の時間を設定してください。');
            return;
          }
        });
      }
    
      /**
       * 中止ボタンクリック時のイベント設定
       */
      onClickStop(): void {
        this.stopEl.addEventListener('click', () => {
          // タイマーを停止
          clearTimeout(this.timer);
          this.timer = null;
          // 中止メッセージを表示
          const remainTime = this.getRemainTime();
          this.textEl.innerHTML = `残り ${remainTime.d}${remainTime.h}時間 ${remainTime.m}${remainTime.s}秒で<br>カウントダウンを中止しました`;
          // 目標日時をクリア
          this.targetDate = null;
          this.startEl.disabled = null;
          this.stopEl.disabled = true;
        });
      }
    }
    
  • URL: /components/raw/utility08/utility08.ts
  • Filesystem Path: src/components/utilities/utility08/utility08.ts
  • Size: 5.2 KB

入力された目標日時に向けてカウントダウンを行うスクリプト。