PowerCMS™

【東京セミナー】6月6日(木) 企業Webリニューアル。最初に押えたい要件定義の進め方と、最新CMSで出来ること

PowerCMS ブログ

ホーム > PowerCMS ブログ > スニペット・カスタムフィールドでカスタムフィールドをタブグループにまとめる

2014年06月13日

スニペット・カスタムフィールドでカスタムフィールドをタブグループにまとめる

PowerCMS に同梱されているスニペットフィールドを使うと、任意の UI でカスタムフィールドを作ることが可能です。

PowerCMS ユーザーガイドに掲載されているシンプルな管理画面 UI の作成から、MT タグや JavaScript を活用した高機能な管理画面 UI 作成まで、カスタマイズ次第であらゆる管理画面 UI を作ることができます。

今回はスニペットカスタムフィールドを利用して、任意のカスタムフィールドをタブでグループ化するカスタマイズ Tips を紹介します。

本記事で紹介するサンプルは、PowerCMS 4.03 にて動作確認をしています。

完成図

  • タブ1を表示した時のカスタムフィールドの状態
  • タブ2を表示した時のカスタムフィールドの状態
  • タブ3を表示した時のカスタムフィールドの状態

上記の完成図にするためのスニペット・カスタムフィールドのサンプルが下記になります。

スニペット・カスタムフィールドの設定

タブグループ化するための、記事のカスタムフィールドが複数あることを前提としています。

上記の完成図では、テキスト、チェックボックス、テキスト(複数行)、ラジオボタン、画像のカスタムフィールドが事前にあり、それをグループ化しました。

仮に、今回作成するカスタムフィールドは、ウェブサイトの記事のカスタムフィールドで、それぞれのカスタムフィールドのベースネームが下記であるとします。

  1. テキスト ( websiteentrytext )
  2. チェックボックス ( websiteentrycheckbox )
  3. テキスト複数行 ( websiteentrytextarea )
  4. ラジオボタン ( websiteentryradio )
  5. 画像 ( websiteentryimage )

以下は、スニペット・カスタムフィールドで作成するカスタムフィールドの具体的な設定項目とその値です。

名前

カスタムフィールドグループ

任意の名前を指定してください。

説明

なし

任意の説明文を指定してください。

種類

スニペット

保存後に表示される既定値の設定は後述します。

オプション

websiteentrytext,websiteentrycheckbox___websiteentrytextarea,websiteentryradio___websiteentryimage

スニペット・カスタムフィールドでは、オプションに指定した値をパラメータとしてリクエストに含めることで、任意の値を保存できる仕組みです。

今回のサンプルは、オプションの項目を、本来の用途ではなく、タブグループをどのようにグループ化するかを記述するために使っています。

指定する値は、タブグループに利用するカスタムフィールドのベースネームで、「___」(アンダースコアが三つ)がタブの区切りで、「,」(カンマ)がベースネームの区切りになります。

また、PowerRevision プラグインでは、このオプション値をバックアップファイルとして生成する XML ファイル中のタグ名として利用する制約があるため、「___」(アンダースコアが三つ)の前後に空白などの XML の要素名として利用できない文字を含めることはできません。

上記の設定は、1つ目のタブに、websiteentrytextwebsiteentrycheckbox を表示し、2つ目のタブに、websiteentrytextareawebsiteentryradio を表示し、最後のタブに、ベースネームが websiteentryimage であるカスタムフィールドを表示するという設定になります。

ベースネーム

websiteentrycfgroups

任意のベースネームを指定してください。

テンプレートタグ

websiteentrycfgroups

任意のテンプレートタグを指定してください。

今回のサンプルでは、スニペット・カスタムフィールド自体には値を保存しないため、このタグを利用する機会はありません。

既定値

<div id="cfgroups"></div>

<script type="application/x-mt-js-template" id="cfgroups-tabs-tmpl">
 <div id="cfgroups-tabs">
   <ul>
 [# jQuery.each(tabs, function (i) { #]
     <li><a href="#cfgroups-tabs-[#= i + 1 #]">タブ[#= i + 1 #]</a></li>
 [# }) #]
   </ul>
 [# jQuery.each(tabs, function (i) { #]
   <div id="cfgroups-tabs-[#= i + 1 #]"></div>
 [# }) #]
 </div>
</script>

<script>
 jQuery(function ($) {
   'use strict';

   // 変数を宣言する
   var $me, $me_display_option, $cfgroups, options, tabs, html;

   // スニペット・カスタムフィールド自身の jQuery オブジェクトをキャッシュする
   $me = $('#customfield_<$mt:var name="basename" encode_js="1"$>-field');
   // スニペット・カスタムフィールド自身の表示オプションチェックボックスの jQuery オブジェクトをキャッシュする
   $me_display_option = $('#custom-prefs-customfield_<$mt:var name="basename" encode_js="1"$>');

   // div#cfgroups の jQuery オブジェクトをキャッシュする
   $cfgroups = $('#cfgroups');

   // オプションの値を変数に代入する
   options = '<$mt:var name="options" encode_js="1"$>';

   // オプションの値を配列に変換する
   tabs = $.map(options.split('___'), function (option) {
     return [option.split(/\s*,\s*/)];
   });

   // script#cfgroups-tabs-tmpl の innerHTML をテンプレートとして、テンプレートをビルドする
   // テンプレート内で利用する tabs という変数に、上記の tabs 変数をアサインしている
   html = Template.process('tabs', { tabs: tabs }, { tabs: $('#cfgroups-tabs-tmpl').html() });

   // スニペット・カスタムフィールド自身が表示されているかどうかを判定するための関数
   function isHidden ($me) {
     return $me.is(':hidden');
   }

   // flatten で利用するためのユーティリティ関数
   function identity (a) {
     return a;
   }

   // ネストされた配列(2階層まで)をフラットにする関数
   function flatten (arr) {
     return $.map(arr, identity);
   }

   // タブグループをレンダリングするための関数
   function render () {
     // div#cfgroups の innerHTML にテンプレートのビルド結果を反映する
     $cfgroups.html(html);

     // カスタムフィールドをタブグループの該当タブに移動する
     $.each(tabs, function (i) {
       var basenames = this;
       $.each(basenames, function () {
         var basename, $customfield;
         basename = this.valueOf();
         $customfield = $('#customfield_' + basename + '-field');
         // カスタムフィールドの見出し部分はソート不可にするため、
         // ソート対象になるクラス名を除去し、最低限のスタイル調整をする
         $customfield
           .find('.field-header')
             .removeClass('field-header')
             .css('padding', '5px 10px');
         // カスタムフィールドを該当のタブグループに移動する
         $customfield.appendTo('#cfgroups-tabs-' + (i + 1));
       });
     });

     // div#cfgroups-tabs をタブ化する
     $cfgroups.find('#cfgroups-tabs').tabs();
   }

   // カスタムフィールドを通常の位置に戻すための関数
   function restore () {
     $.each(flatten(tabs), function () {
       // タブグループ内のカスタムフィールドの jQuery オブジェクトを取得する
       var $field = $('#customfield_' + this + '-field');
       // カスタムフィードの見出し部分に、クラス名 .field-header を再設定し、ソート可能にする
       $field.children().first().addClass('field-header');
       // フィールドの並びの最後に移動する
       $field.appendTo('#sortable');
     });
   }

   // 自身の表示オプションが変更された時、HTML を組み立て直すためのイベントハンドラ
   $me_display_option.on('change', function () {
     if ($(this).is(':checked')) {
       // 表示オプションが ON になったら、タブグループを表示する
       render();
     }
     else {
       // 表示オプションが OFF になったら、タブグループから、本来の場所にカスタムフィールドを移動する
       restore();
     }
     return true;
   });

   // 自身が非表示であれば何もしない
   if (isHidden($me)) return;

   // 自身が非表示でなければタブグループを組み立てて表示する
   render();
 });
</script>

上記が、タブグループを実現するための、スニペット・カスタムフィールドの具体的なロジックになります。

冒頭の <div id="cfgroups"></div> は、JavaScript で生成した DOM を挿入するためのラッパー要素です。

次の、<script type="application/x-mt-js-template" id="cfgroups-tabs-tmpl"> ... </script> で囲まれた部分は、タブグループを描画する HTML の JavaScript テンプレートになります。

JavaScript テンプレートは、Movable Type の管理画面でも利用されている、Movable Type 標準の Template.js という JavaScript テンプレートエンジンを利用しています。

script 要素の type 属性にブラウザが理解できない Media タイプが指定された時、その内容を無視するという特徴を利用して、テンプレートの記述のために利用しています。
※ 本来は script 要素の type 属性に指定する Media タイプは、RFC にて定義された妥当な Media タイプを指定するべきですが、すでに広く使われている手法のため、今回はこの方法を採用しました。

その後の script 要素にて、具体的な処理内容を記述しています。

処理内容を大きく捉えると、共通で使う変数の初期化、ユーティリティ関数の定義、イベントハンドラの登録、メインの処理といった内容が記述されています。コメントをヒントにご確認ください。

jQuery の ready イベントが発火するまでは、通常のカスタムフィールドとして表示され、その要素自体をタブグループ内に移動するため、並び順や表示オプションの状態などはそのまま引き継がれます。(タブグルーブ内の並びはオプションの指定順によって変更します)また、非表示の時は何もしないようにしています。

本サンプルの利点は、スニペット・カスタムフィールド自身で UI を作り込むわけではないため、通常のカスタムフィールドの編集や追加(スニペット・カスタムフィールドのオプションの値を追加する必要はあります)の操作にて UI を変更できる点にあります。

以上、スニペット・カスタムフィールドのカスタマイズの一例をご紹介しました。

スニペット・カスタムフィールドは、管理画面 UI の柔軟なカスタマイズが可能ですので、ぜひご活用ください。

追記

投稿当初、オプション値タブでグループ化する範囲の区切り文字を「|」(バーティカルバー)にしておりましたが、PowerRevision との組み合わせで問題があることが確認されたため、記事中の「|」は、「___」(アンダースコアが三つ)に変更いたしました。


カテゴリー
設定・管理画面カスタマイズ

Recent Entries