独自の「カウントダウン」ウィジェットを追加する方法

Cocoonカスタマイズ集
この記事は約10分で読めます。
記事内に広告が含まれています。

はじめに

Cocoonテーマにはcountdownショートコードが実装されていますが、このショートコードは表示時点での残り日数を計算するだけで、リアルタイム更新には対応していません。

そこで、Nishiki Proの「カウントダウン」ブロックのようにリアルタイムで残り時間を更新表示する独自ショートコードを追加します。

さらに、カウントダウンを表示するウィジェットも作成します。

この記事では、この方法について説明します。

完成イメージ

使用方法

以下にショートコードを示します。

[my_countdown]
オプション
オプション説明値初期値
textテキスト
to終了日時(必須)例:2015-01-15 23:59

実装手順

以下の手順で実装します。

  • ラベル
    PHPに追加

    以下のコードをfunctions.phpに追加します。

    add_shortcode('my_countdown', function ($atts) {
      $atts = shortcode_atts([
        'text' => '',
        'to'   => '',
      ], $atts);
    
      if (empty($atts['to'])) {
        return '<p>終了日時が指定されていません。</p>';
      }
    
      ob_start();
      ?>
      <div class="countdown" data-to="<?= esc_attr($atts['to']); ?>">
        <div class="countdown__text"><?= esc_html($atts['text']); ?></div>
        <div class="countdown__timer">
          <div class="countdown__box countdown__box--days"><span class="countdown__digit"></span><span class="countdown__label">日</span></div>
          <div class="countdown__box countdown__box--hours"><span class="countdown__digit"></span><span class="countdown__label">時</span></div>
          <div class="countdown__box countdown__box--minutes"><span class="countdown__digit"></span><span class="countdown__label">分</span></div>
          <div class="countdown__box countdown__box--seconds"><span class="countdown__digit"></span><span class="countdown__label">秒</span></div>
        </div>
      </div>
      <?php
      return ob_get_clean();
    });
  • ラベル
    JavaScriptを追加

    以下のコードをjavascript.jsに追加します。

    jQuery(function ($) {
    
      /**
       * カウントダウンを更新
       *
       * @return {void}
       */
      function updateCountdown() {
        $('.countdown').each(function () {
          const $wrap = $(this);
          const goal = new Date($wrap.attr('data-to'));
          const diff = goal.getTime() - Date.now();
    
          const days = Math.max(0, Math.floor(diff / (1000 * 60 * 60 * 24)));
          const hours = Math.max(0, Math.floor(diff / (1000 * 60 * 60)) % 24);
          const minutes = Math.max(0, Math.floor(diff / (1000 * 60)) % 60);
          const seconds = Math.max(0, Math.floor(diff / 1000) % 60);
    
          $wrap.find('.countdown__box--days .countdown__digit').text(days);
          $wrap.find('.countdown__box--hours .countdown__digit').text(String(hours).padStart(2, '0'));
          $wrap.find('.countdown__box--minutes .countdown__digit').text(String(minutes).padStart(2, '0'));
          $wrap.find('.countdown__box--seconds .countdown__digit').text(String(seconds).padStart(2, '0'));
    
          if (diff <= 0) {
            $wrap.addClass('is-closed');
          }
        });
      }
    
      // 初回更新
      updateCountdown();
    
      // 1秒ごとに更新
      setInterval(updateCountdown, 1000);
    
    });
  • ラベル
    CSSを追加

    以下のコードをstyle.cssに追加します。

    .countdown__timer {
      display: flex;
      justify-content: center;
    }
    
    .countdown__box {
      align-items: center;
      display: flex;
      flex-direction: column;
      width: 50px;
    }
    
    .countdown__digit {
      font-size: 30px;
      font-weight: bold;
      line-height: 1em;
    }

拡張:ウィジェットを追加

ショートコードのみを使用し、ウィジェットを使用しない場合、以下のコードは不要です。

ショートコードを拡張して、ウィジェットを追加します。

完成イメージ

実装手順

上記のコードに加え、以下のコードをfunctions.phpに追加します。

// ウィジェットを追加
add_action('widgets_init', function () {
  register_widget('Countdown_Widget');
});


/**
 * ウィジェットクラスを定義
 */
class Countdown_Widget extends WP_Widget {
  public function __construct() {
    parent::__construct(
      'my_countdown_widget',
      'カウントダウン',
      ['description' => 'カウントダウンタイマーを表示します。']
    );
  }


  /**
   * ウィジェットを表示
   *
   * @param array $args ウィジェット引数
   * @param array $instance 保存された値
   * @return void
   */
  public function widget($args, $instance) {
    $to    = $instance['to']    ?? '';
    $text  = $instance['text']  ?? '';
    $title = $instance['title'] ?? '';

    echo $args['before_widget'];

    // タイトルが設定された場合
    if (!empty($title)) {
      echo $args['before_title'] . apply_filters('widget_title', $title) . $args['after_title'];
    }

    // 日時が設定された場合
    if (!empty($to)) {
      echo do_shortcode("[my_countdown to='{$to}' text='{$text}']");
    }

    echo $args['after_widget'];
  }


  /**
   * ウィジェットの設定フォーム
   *
   * @param array $instance 保存された値
   * @return void
   */
  public function form($instance) {
    $to    = $instance['to']    ?? '';
    $text  = $instance['text']  ?? '';
    $title = $instance['title'] ?? '';

    // 現在の「終了日時」を分割
    $datetime = '';
    if ($to) {
      $datetime = new DateTime($to);
      $datetime = $datetime->format('Y-m-d\TH:i');
    }

    ?>
    <p>
      <label for="<?= $this->get_field_id('title'); ?>">タイトル</label>
      <input class="widefat" id="<?= $this->get_field_id('title'); ?>" name="<?= $this->get_field_name('title'); ?>" type="text" value="<?= esc_attr($title); ?>" />
    </p>
    <p>
      <label for="<?= $this->get_field_id('to'); ?>">終了日時</label>
      <input class="widefat" id="<?= $this->get_field_id('to'); ?>" name="<?= $this->get_field_name('to'); ?>" type="datetime-local" value="<?= esc_attr($datetime); ?>" />
    </p>
    <p>
      <label for="<?= $this->get_field_id('text'); ?>">表示テキスト</label>
      <input class="widefat" id="<?= $this->get_field_id('text'); ?>" name="<?= $this->get_field_name('text'); ?>" type="text" value="<?= esc_attr($text); ?>" />
    </p>
    <?php
  }


  /**
   * ウィジェットの設定を保存
   *
   * @param array $new_instance 新しい値
   * @param array $old_instance 古い値
   * @return array 保存する値
   */
  public function update($new_instance, $old_instance) {
    $instance = [];
    $instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
    $instance['to']    = sanitize_text_field($new_instance['to']    ?? '');
    $instance['text']  = sanitize_text_field($new_instance['text']  ?? '');

    return $instance;
  }
}

さいごに

今回紹介した方法を使えば、「カウントダウン」ショートコードを追加できます。
さらに、機能を拡張し、新たにウィジェットを追加することで、ウィジェットとショートコードの両方を利用できるため、設置場所や表示方法を柔軟にカスタマイズできます。

タイトルとURLをコピーしました