「ウィジェットの複製」機能を追加する方法

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

はじめに

ウィジェットに「複製」リンクを追加し、ウィジェットを複製可能とします。

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

完成イメージ

実装手順

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

add_action('admin_enqueue_scripts', function ($hook_suffix) {
  if ($hook_suffix !== 'widgets.php') {
    return;
  }

  ob_start();
  ?>
  jQuery(function ($) {
    /**
     * ウィジェット複製機能を初期化
     *
     * @return void
     */
    function initCloneWidgets() {
      $('body').on('click', '.widget-control-actions .clone-me', cloneWidget);

      // 複製リンクを追加
      addCloneLinks();

      // ウィジェットの変更を監視
      const target = document.getElementById('widgets-right');
      if (target) {
        const observer = new MutationObserver(addCloneLinks);
        observer.observe(target, {
          childList: true,
          subtree: true
        });
      }
    }

    /**
     * 複製リンクを追加
     *
     * @return void
     */
    function addCloneLinks() {
      $('.widget-control-actions:not(.clone-enabled)').each(function () {
        const cloneHtml = ' | <a href="#" class="clone-me clone-action">複製</a>';
        $(this).addClass('clone-enabled');
        $('.alignleft .widget-control-remove', this).after(cloneHtml);
      });
    }

    /**
     * ウィジェットを複製
     *
     * @param {jQuery.Event} e - イベントオブジェクト
     * @return void
     */
    function cloneWidget(e) {
      e.preventDefault();
      e.stopPropagation();

      const $original = $(this).closest('.widget');
      const $widget = $original.clone();

      // ウィジェットのIDと番号を取得
      const idBase = $widget.find('input[name="id_base"]').val();
      const oldNumber = $widget.find('input[name="widget_number"]').val();

      // 新しいウィジェット番号を設定
      let maxNumber = 0;
      $('input.widget-id[value^="' + idBase + '-"]').each(function () {
        const match = this.value.match(/-(\d+)$/);
        if (match) {
          maxNumber = Math.max(maxNumber, parseInt(match[1], 10));
        }
      });
      const newNumber = maxNumber + 1;

      // 入力項目の番号を置換
      $widget.find('.widget-content input, .widget-content select, .widget-content textarea').each(function () {
        const name = $(this).attr('name');
        if (name) {
          $(this).attr('name', name.replace(oldNumber, newNumber));
        }
      });

      // 新しいウィジェットIDを設定
      let newId = 0;
      $('.widget').each(function () {
        const match = this.id.match(/^widget-(\d+)/);
        if (match) {
          newId = Math.max(newId, parseInt(match[1], 10));
        }
      });
      newId++;

      // ウィジェットの属性と番号を変更
      $widget.attr('id', `widget-${newId}_${idBase}-${newNumber}`);
      $widget.find('input.widget-id').val(`${idBase}-${newNumber}`);
      $widget.find('input.widget_number').val(newNumber);
      $widget.find('.multi_number').val(newNumber);

      // 複製したウィジェットを表示
      $widget.hide();
      $original.after($widget);
      $widget.fadeIn();

      // ウィジェットを保存
      wpWidgets.save($widget, 0, 0, 1);
    }

    // 複製機能を初期化
    initCloneWidgets();
  });
  <?php
  wp_add_inline_script('jquery', ob_get_clean());
});

さいごに

今回紹介した方法を使えば、WordPressのウィジェット画面に「複製」機能を簡単に追加でき、管理作業の効率が大幅に向上します。
特に同じ構成のウィジェットを何度も作成する場面では、手動コピーの手間を省き、設定ミスの防止にもつながります。

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