CMSで更新する予定のコンテンツで、上の画像のように
「『お客様の声』や『ボタン』のパーツを、本文中の好きな場所に表示したい」
と要望があったら、どう対応しますか。
カスタムフィールドだと、表示位置をあらかじめ固定しなければなりません。
WordPressの「AddQuicktag」や、ウィジウィグのテンプレート機能は、HTMLを編集できるためページが崩れる危険性が高くなります。
ブロック単位の編集ができるCMS、concrete5や、WordPressのプラグイン「Page Builder」なら解決するように思えます。しかし、いずれも独自の入力欄を持ったパーツを作ろうとすると、専用のプログラムを書くことになり、制作コストがかかります。
a-blog cmsはバージョン2.1から、自作のユニット(パーツ)を追加できる「カスタムユニット」機能が追加されました。
- カスタムユニット | ユニット | ドキュメント | a-blog cms 制作者向け情報
- カスタムユニット ハンズオン | acmscamp | 開発ブログ | a-blog cms 制作者向け情報
冒頭のような要望を簡単に実装でき、制作者・更新担当者をどちらも幸せにする、おすすめの機能です。使い方を詳しくご紹介します。
メリット
- PHPを書かない
- HTMLと条件分岐などの基礎知識があれば実装できます。書くのはa-blog cmsの独自タグのみで、PHPは一切書きません。間違えてもサイトが真っ白になることはありません。
- UIを自由に作成できる
- form要素のルールさえ守っていれば、ユーザーインターフェースは制作者が決められます。通常は管理画面用のCSSフレームワーク「acms.css」で充分ですが、外部のUIも実装できます。
- モバイル対応
- 「acms.css」はレスポンシブWebデザインで設計されています。このため、カスタムユニットもスマートフォンやタブレットでの更新に対応できます。
- タグがカスタムフィールドとほぼ同じ
- カスタムユニット専用のタグは、開始・終了のみです。既存のカスタムフィールドと同じHTML構造なので、a-blog cmsを学習したことがあれば、コストはかかりません。
- 使い回しがきく
- 基本はHTMLファイルなので、一度作成するとその後の案件でも簡単に複製・改変できます。後述する「ボタン」は要望が多いので、作っておいて損はありません。
デメリット
いろいろ考えましたが、この機能には大きなデメリットがありません。
- フィールド検索の対象にできない
- カスタムユニットで入力したデータは通常の全文検索にはヒットしますが、カスタムフィールド別検索の対象にはできません。物件・書籍情報など、絞り込みが必要なコンテンツには利用しないようにしてください。
- iOSアプリが使えない
- a-blog cmsのiOSアプリは、公式ユニットのみ対応しています。カスタムユニットを実装したサイトは、Safariなどのブラウザでログインして更新することになります。
カスタムユニット作成の流れ
ID・入力項目を考える
最初に、ユニットに対する一意のIDを考えます。基本的に英語・数字・アンダーバーを使います。ボタンなら「button」、吹き出しなら「balloon」などとすればよいでしょう。
ここでは便宜上「hoge」で説明します。
また、どのような入力項目が必要かも考えておきましょう。ボタンなら、ボタンの文字列とリンク先URLのテキスト入力が必要です。
編集画面用のテンプレートを作る
編集画面用のテンプレートを作ります。テキストエディタで新規HTMLファイルを作成し、以下のコードを貼り付けてください。
<!-- BEGIN custom_hoge --> <table class="entryFormColumnSettingTable entryFormColumnTable"> <tr> <td class="entryFormFileControl"> <table class="entryFormColumnSettingTable"> <!-- 入力項目 --> </table> </td> </tr> </table> <!-- END custom_hoge -->
a-blog cmsのフレームワークのコードを流用していますが、CSSのカスタマイズをする余裕があるなら、マークアップに大きな制限はありません。
重要なのは「BEGIN」「END」と書かれている、HTMLのコメントを模した開始・終了タグです。ここに入るコードネームは必ず「custom_考えておいたID」としてください。
作成したテンプレートを、カスタムユニットを実装したいテーマに、以下のパス・ファイル名で保存してください。ディレクトリがない場合は作成します。テンプレートファイル名は変更できません。
/テーマのディレクトリ/admin/entry/unit/extend.html
表示用のテンプレートを作る
表示用のテンプレートを作ります。テキストエディタで新規HTMLファイルを作成し、以下のコードを貼り付けてください。
<!-- BEGIN unit#custom_hoge --> <!-- ユニットの表示 --> <!-- END unit#custom_hoge -->
こちらにも開始・終了タグがあるので同様に「custom_考えておいたID」としてください。
作成したテンプレートを、制作中のテーマに以下のパス・ファイル名で保存してください。ディレクトリがない場合は作成します。テンプレートファイル名は変更できません。
/テーマのディレクトリ/include/unit/extend.html
編集設定にユニットを追加する
ここで一旦、a-blog cmsにログインし、管理ページ内の「コンフィグ > 編集設定」へ移動してください。
ページ冒頭に、サイト内で利用可能なユニットの追加画面があります。スクリーンショットの通りに新しいユニットを追加し、モードのプルダウンを「拡張」、IDの入力欄に先ほどの「custom_考えておいたID」を入力してください。
プルダウンには「カスタム」というものもありますが「拡張」です。間違えないようにしてください。
ラベルは、更新担当者向けのユニットの表示名です。わかりやすく簡潔な名前にしてください。
ユニット設定にユニットを追加する
続いて、同じく管理ページ内の「コンフィグ > ユニット設定」へ移動してください。
ページをスクロールしていくと、先ほど追加したユニット項目が見つかるはずです。また、それぞれの項目についている「ユニットの追加ボタン」にもボタンが増えています。
ボタンを押してみると、見出しだけの項目が追加されます。この状態を確認したら「保存」ボタンを押して更新してください。
編集画面用テンプレートにフォームを追加する
いよいよ、編集画面のフォームを作成していきます。
a-blog cmsは、入力画面のスニペットを自動生成してくれるツールが管理画面内に用意されています。
「コンフィグ > カスタムフィールドメーカー」にありますが、ここではいろいろな入力フォームを全部盛りしているサンプルコードを出してしまいます。
以下のコードを、編集画面用の「extend.html」内の「<!– 入力項目 –>」のところにコピー・ペーストしてください。
<!-- ユニットの入力項目:テキストの場合 --> <tr> <th style="white-space: nowrap;">テキスト</th> <td> <input type="text" name="hoge_text{id}" value="{hoge_text}" class="acms-admin-form-width-full" /> <input type="hidden" name="unit{id}[]" value="hoge_text{id}" /> </td> </tr> <!-- ユニットの入力項目:テキストエリアの場合 --> <tr> <th style="white-space: nowrap;">テキストエリア</th> <td> <textarea name="hoge_textarea{id}" class="acms-admin-form-width-full" rows="5">{hoge_textarea}[raw]</textarea> <input type="hidden" name="unit{id}[]" value="hoge_textarea{id}" /> </td> </tr> <!-- ユニットの入力項目:画像の場合 --> <tr> <th style="white-space: nowrap;">画像</th> <td class="js-img_resize_cf"> <!-- BEGIN_IF [{hoge_img@tinyPath}/em] --> <img src="" style="display:none; max-width: 150px;" class="js-img_resize_preview acms-admin-img-responsive" /> <!-- END_IF --> <!-- BEGIN_IF [{hoge_img@path}/nem] --> <img src="%{ARCHIVES_DIR}{hoge_img@tinyPath}" class="js-img_resize_preview acms-admin-img-responsive" /> <input type="hidden" name="hoge_img{id}@old" value="{hoge_img@path}" /> <label class="acms-admin-form-checkbox"> <input type="checkbox" name="hoge_img{id}@edit" value="delete" /> <i class="acms-admin-ico-checkbox"></i> 削除 </label> <!-- END_IF --> <input type="file" name="hoge_img{id}" size="20" class="js-img_resize_input" /><br /> 代替テキスト:<input type="text" name="hoge_img{id}@alt" value="{hoge_img@alt}" size="40" /> <input type="hidden" name="unit{id}[]" value="hoge_img{id}" /> <input type="hidden" name="hoge_img{id}:extension" value="image" /> <input type="hidden" name="hoge_img{id}@width" value="960" /> <input type="hidden" name="hoge_img{id}@tinyWidth" value="150" /> <input type="hidden" name="hoge_img{id}@filename" value="" /> </td> </tr> <!-- ユニットの入力項目:チェックボックスの場合 --> <tr> <th style="white-space: nowrap;">チェックボックス</th> <td> <label class="acms-admin-form-checkbox" for="input-hoge_check{id}"> <input type="checkbox" name="hoge_check{id}[]" value="1" id="input-hoge_check{id}"{hoge_check:checked#1} /> <i class="acms-admin-ico-checkbox"></i>チェックを入れると値に1が入ります </label> <input type="hidden" name="unit{id}[]" value="hoge_check{id}" /> </td> </tr> <!-- ユニットの入力項目:ラジオボタンの場合 --> <tr> <th style="white-space: nowrap;">ラジオボタン</th> <td> <label class="acms-admin-form-radio"><input type="radio" name="hoge_radio{id}" value=""<!-- BEGIN_IF [{hoge_radio}/em] --> checked="checked"<!-- END_IF --> /><i class="acms-admin-ico-radio"></i>選択肢null</label> <label class="acms-admin-form-radio"><input type="radio" name="hoge_radio{id}" value="選択肢1"{hoge_radio:checked#選択肢1} /><i class="acms-admin-ico-radio"></i>選択肢1</label> <label class="acms-admin-form-radio"><input type="radio" name="hoge_radio{id}" value="選択肢2"{hoge_radio:checked#選択肢2} /><i class="acms-admin-ico-radio"></i>選択肢2</label> <label class="acms-admin-form-radio"><input type="radio" name="hoge_radio{id}" value="選択肢3"{hoge_radio:checked#選択肢3} /><i class="acms-admin-ico-radio"></i>選択肢3</label> <input type="hidden" name="unit{id}[]" value="hoge_radio{id}" /> </td> </tr> <!-- ユニットの入力項目:セレクトボックスの場合 --> <tr> <th style="white-space: nowrap;">セレクトボックス</th> <td> <select name="hoge_select{id}" class="acms-admin-form-width-full"> <option value="">(選択してください)</option> <option value="選択肢1"{hoge_select:selected#選択肢1}>選択肢1</option> <option value="選択肢2"{hoge_select:selected#選択肢2}>選択肢2</option> <option value="選択肢3"{hoge_select:selected#選択肢3}>選択肢3</option> </select> <input type="hidden" name="unit{id}[]" value="hoge_select{id}" /> </td> </tr> <!-- ユニットの入力項目:PDFファイルの場合 --> <tr> <th style="white-space: nowrap;">PDFファイル</th> <td> <!-- BEGIN_IF [{hoge_file@path}/nem] --> <input type="hidden" name="hoge_file{id}@old" value="{hoge_file@path}" /> <input type="hidden" name="hoge_file{id}@secret" value="{hoge_file@secret}" /> <input type="hidden" name="hoge_file{id}@fileSize" value="{hoge_file@fileSize}" /> <label for="input-checkbox-hoge_file@edit" class="acms-admin-form-checkbox"> <input type="checkbox" name="hoge_file{id}@edit" value="delete" id="input-checkbox-hoge_file@edit" /> <i class="acms-admin-ico-checkbox"></i> 削除 </label> <a href="%{ARCHIVES_DIR}{hoge_file@path}"><img src="/images/fileicon/pdf.gif" width="64" height="64" alt="pdf" /></a> {hoge_file@baseName}<br /> <!-- END_IF --> <input type="file" name="hoge_file{id}" size="20" /> <input type="hidden" name="unit{id}[]" value="hoge_file{id}" /> <input type="hidden" name="hoge_file{id}@baseName" value="{hoge_file@baseName}" /> <input type="hidden" name="hoge_file{id}:extension" value="file" /> <input type="hidden" name="hoge_file{id}@extension" value="pdf" /> </td> </tr>
それぞれのフォーム項目には一意のIDを設けます。「考えておいたID_項目名」とするとわかりやすいです。例えば、ボタンユニットのURLだと「button_url」、フキダシユニットの人物画像だと「balloon_img」となります。
コーディングに慣れている人だとすぐ気付くと思いますが、上記スニペットの「hoge_」を置換するだけで流用できます。
出力用テンプレートの体裁を整える
続いて、出力用テンプレートを作っていきます。
こちらも先述の「カスタムフィールドメーカー」を使うことができますが、案件によってマークアップは全く変わってきます。今回は単純に表で一覧させるコードにしてみました。
以下のコードを、出力用の「extend.html」内の「<!– ユニットの表示 –>」のところにコピー・ペーストしてください。
<table class="acms-table acms-table-borderd"> <!-- ユニットの表示:テキストの場合 --> <tr> <th>テキスト</th> <td> {hoge_text} </td> </tr> <!-- ユニットの表示:テキストエリアの場合 --> <tr> <th>テキストエリア</th> <td> {hoge_textarea}[nl2br|raw] </td> </tr> <!-- ユニットの表示:画像の場合 --> <tr> <th>画像</th> <td> <!-- BEGIN_IF [{hoge_img@largePath}/nem] --> <img src="%{ARCHIVES_DIR}{hoge_img@largePath}" alt="{hoge_img@alt}" class="acms-img-responsive" /> <!-- END_IF --> </td> </tr> <!-- ユニットの表示:チェックボックスの場合 --> <tr> <th style="white-space: nowrap;">チェックボックス</th> <td> <!-- BEGIN_IF [{hoge_check}/eq/1] --> チェックが入っています <!-- ELSE --> <strong>チェックが入っていません</strong> <!-- END_IF --> </td> </tr> <!-- ユニットの表示:ラジオボタンの場合 --> <tr> <th>ラジオボタン</th> <td> <!-- BEGIN_IF [{hoge_radio}/em] --> 選択肢Null <!-- ELSE --> <strong>{hoge_radio}</strong> <!-- END_IF --> </td> </tr> <!-- ユニットの表示:セレクトボックスの場合 --> <tr> <th>セレクトボックス</th> <td> <!-- BEGIN_IF [{hoge_select}/em] --> 選択肢Null <!-- ELSE --> <strong>{hoge_select}</strong> <!-- END_IF --> </td> </tr> <!-- ユニットの表示:PDFファイルの場合 --> <tr> <th>PDFファイル</th> <td> <!-- BEGIN_IF [{hoge_file@path}/nem] --> <a href="%{ARCHIVES_DIR}{hoge_file@path}" target="_blank"><img src="/images/fileicon/pdf.gif" width="64" height="64" alt="pdf" /></a> <!-- END_IF --> </td> </tr> </table>
投稿テストをしてみる
これで、カスタムユニットの準備ができました。
実際にエントリーを作成して、ユニットが正しく表示されるか、入力した内容が保存されるか確認してください。
実際の表示画面に表が出てくるか、入力内容が反映されるか、ダイレクト編集機能でも更新できるかもチェックしてください。
まとめ
カスタムユニットの解説は以上です。
サンプルコードを流用すれば、だいたいのユニットは数十分くらいで作ることができます。予算や工数でこういった要望を断ってきた経験がある人には、ありがたい機能ではないかと思います。
最初の方にスクリーンショットを出した「ボタンユニット」のサンプルコードを、Gistで公開しています。bootstrapなどの他のフレームワークにも対応できますので、こちらも自由にお使いください。