matsuoka

PowerCMSのスニペット・カスタムフィールドを使用して管理画面を見やすくカスタマイズ

PowerCMS snippet custom field

PowerCMSを用いて開発する際、ウェブサイト上のページのレイアウトが縦長であった場合に入力用のカスタムフィールドの数が増えて投稿画面が縦長になり見にくい管理画面になりがちです。投稿画面が縦長にならない方法を探してみました。

・「MTAppjQueryプラグイン(有償)」を用いて、jQueryにてクリックするごとにカスタムフィールドの続きを表示する。
・「ひな形から作成」機能を用いる。条件によって投稿画面が異なる場合に有効。
・「スニペット・カスタムフィールド」を用いて入力フィールドをタブにする。

今回はスニペット・カスタムフィールドを使用してみました。

スニペット・カスタムフィールドとは

スニペット・カスタムフィールドは HTML・CSS・JavaScriptを用いて管理画面をカスタマイズすることができます。
input 要素や textarea 要素の name 属性をカンマ区切りで指定することで値を自動的に保存してくれます。
受け取り側のコード(プログラム)は一切書く必要がありません。保存された値は、MTタグで出力することができます。
今回作成したようなタブで切り替えの投稿管理画面を作ることができます。

投稿画面(完成)

カスタムフィールドを作成

スニペット・カスタムフィールドで使用するためのカスタムフィールドを最初に作ります。

1.テキスト ( カスタムフィールドのベースネーム : websiteentrytext )
2.エディタ付きテキスト ( カスタムフィールドのベースネーム : websiteentrytextarea )
3.チェックボックス ( カスタムフィールドのベースネーム : websiteentrycheckbox )
4.ラジオボタン ( カスタムフィールドのベースネーム : websiteentryradio )
5.画像 (カスタムフィールドのベースネーム : websiteentryimage )

スニペットのカスタムフィールドを作成

先ほど作ったカスタムフィールドを読み込んで、タブにするためのスニペット・カスタムフィールドを作成します。
入力項目は以下のようになっています。

この中で特に重要なのは、オプションと規定値の項目です。

システムオブジェクト : 記事
名前 : 製品詳細
種類 : スニペット
オプション :

websiteentrytext,websiteentrytextarea___websiteentrycheckbox,websiteentryradio___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 #]"> [# if (i == 0) { #]特 長[#  } #][# if (i == 1) { #]仕 様[#  } #][# if (i == 2) { #]製品画像[#  } #]</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>

<style scoped>
#cfgroups-tabs ul li {
    font-size: 14px;
}
</style>
※規定値は、今回のタブUIを作っているHTMLやJavaScriptのコードが入力されています。
 ベースネームとテンプレートタグのところは入力されていますが任意の項目で、
 今回のカスタマイズでは特に使用しません。

記事テンプレート内で出力

スニペット・カスタムフィールドでオプションに設定したカスタムフィールドは、通常のカスタムフィールドと同じように、記事テンプレート内で読み込むことが出きます。

// 特長
 <mt:websiteentrytext> // :テキスト
 <mt:websiteentrytextarea> // :テキスト複数行
// 仕様
 <mt:websiteentrycheckbox> // :チェックボックス
 <mt:websiteentryradio> // :ラジオボタン
// 製品画像
 <mt:websiteentryimageAsset><img src="<$MTAssetURL$>"></mt:websiteentryimageAsset> // :画像

まとめ

スニペット・カスタムフィールドはHTML、CSS、JavaScriptの知識があれば投稿画面や管理画面を自由に設計することができます。また既定値内でMTタグも使用でき、今後応用して使用していきたいと思います。

参考

新しいウェブ体験を作ろう TAMのPWA開発
お問い合わせはこちら