「カスタムHTML」ウィジェットに指定期間だけ表示する機能を追加する方法

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

はじめに

Cocoonにはcampaignショートコードが実装されていますが、このショートコードは表示された時点で内容を表示し、リアルタイムでの更新は行われません。

そこで、「カスタムHTML」ウィジェットに「開始日時」と「終了日時」のオプションを追加し、リアルタイムで時間を監視して、指定した期間のみ内容を表示できるようにします。

ただし、開始日時、終了日時の両方を設定した場合にのみ機能する仕様とします。

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

完成イメージ

ウィジェット
ウィジェット表示

実装手順

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

  • ラベル
    PHPを追加

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

    // ウィジェットに設定メニューを追加
    add_action('in_widget_form', function ($widget, $return, $instance) {
      if ($widget->id_base == 'custom_html') {
        $st_date = empty($instance['st_date']) ? '' : $instance['st_date'];
        $ed_date = empty($instance['ed_date']) ? '' : $instance['ed_date'];
    
        ?>
        <p>
          <label for="<?= esc_attr($widget->get_field_id('st_date')); ?>">開始日時:</label>
          <input class="widefat" id="<?= esc_attr($widget->get_field_id('st_date')); ?>" name="<?= esc_attr($widget->get_field_name('st_date')); ?>" type="datetime-local" value="<?= esc_attr($st_date); ?>">
        </p>
        <p>
          <label for="<?= esc_attr($widget->get_field_id('ed_date')); ?>">終了日時:</label>
          <input class="widefat" id="<?= esc_attr($widget->get_field_id('ed_date')); ?>" name="<?= esc_attr($widget->get_field_name('ed_date')); ?>" type="datetime-local" value="<?= esc_attr($ed_date); ?>">
        </p>
        <?php
      }
    }, 10, 3);
    
    
    // ウィジェットの入力デーを更新
    add_filter('widget_update_callback', function ($instance, $new_instance, $old_instance) {
      if (isset($new_instance['st_date'])) {
        $instance['st_date'] = sanitize_text_field($new_instance['st_date']);
      }
    
      if (isset($new_instance['ed_date'])) {
        $instance['ed_date'] = sanitize_text_field($new_instance['ed_date']);
      }
    
      return $instance;
    }, 10, 3);
    
    
    // カスタムHTMLウィジェットを出力
    add_filter('widget_custom_html_content', function ($content, $instance, $widget) {
      if (empty($instance['st_date']) || empty($instance['ed_date'])) {
        return $content;
      }
    
      $st_date = esc_attr($instance['st_date']);
      $ed_date = esc_attr($instance['ed_date']);
    
      // 開始日時>終了日時は処理対象外
      if (strtotime($st_date) >= strtotime($ed_date)) {
        return $content;
      }
    
      ob_start();
      ?>
      <div class="countdown">
        <div class="countdown__content" data-start="<?= $st_date; ?>" data-end="<?= $ed_date; ?>"></div>
        <div class="countdown__widget-content"><?= $content; ?></div>
      </div>
      <?php
      return ob_get_clean();
    }, 10, 3);
  • ラベル
    JavaScriptを追加

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

    jQuery(function ($) {
      $('.countdown').each(function () {
        const el        = $(this);
        const startDate = el.find('.countdown__content').data('start');
        const endDate   = el.find('.countdown__content').data('end');
    
        /**
         * カウントダウンを更新
         *
         * @return {void}
         */
        function updateCountdown() {
          const now   = new Date().getTime();
          const start = new Date(startDate).getTime();
          const end   = new Date(endDate).getTime();
          let displayText = '';
    
          if (now < start) {
            // 開始前を設定
            const timeUntilStart = start - now;
            displayText          = 'あと ' + formatTime(timeUntilStart) + ' で開始';
          } else if (now < end) {
            // 期間中を設定
            const timeUntilEnd = end - now;
            displayText        = 'あと ' + formatTime(timeUntilEnd) + ' で終了';
            el.closest('.widget').find('.countdown__widget-content').addClass('is-active');
          } else {
            // 終了後を設定
            displayText = '終了しました';
            el.closest('.widget').find('.countdown__widget-content').remove();
          }
    
          el.find('.countdown__content').text(displayText);
        }
    
        /**
         * 残り時間を表示形式に変換
         *
         * @param {number} ms 残り時間(ミリ秒)
         * @return {string} 表示用の時間
         */
        function formatTime(ms) {
          const seconds = Math.floor(ms / 1000);
          const minutes = Math.floor(seconds / 60);
          const hours   = Math.floor(minutes / 60);
          const days    = Math.floor(hours / 24);
    
          const displayDays    = days > 0 ? days + '日 ' : '';
          const displayHours   = (hours % 24) + '時間 ';
          const displayMinutes = (minutes % 60) + '分 ';
          const displaySeconds = (seconds % 60) + '秒';
    
          return displayDays + displayHours + displayMinutes + displaySeconds;
        }
    
        updateCountdown();
        setInterval(updateCountdown, 1000);
      });
    });
  • ラベル
    CSSを追加

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

    .widget_custom_html .countdown__widget-content {
      display: none;
    
      &.is-active {
        display: block;
      }
    }

さいごに

今回紹介した方法を使えば、WordPressの「カスタムHTML」ウィジェットに期間限定で表示する機能を簡単に追加することができます。
開始日時と終了日時を設定するだけで、その期間内にのみウィジェットの内容が表示されるため、キャンペーンやセールなど、特定の期間に合わせたコンテンツの管理が非常に効率的です。

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