2019年10月07日
スニペットフィールドを使ってリンク入力欄(複数)を作成する
完成イメージ
記事編集画面に次の様なフィールドを作成するのが本記事のゴールとなります。
機能としては下記要件を満たしたものを作ります。
- リンクテキストとリンク URL がセットになった入力欄を作成
- 入力欄は追加する事が出来る
- 入力欄数の上限はなし ( JavaScript によって入力欄を増減 ) [1]
さて、それでは実際に作成していきましょう。
- ステップ 1. カスタムフィールドを作成
- ステップ 2. 入力画面用のテンプレートモジュールを作成
- ステップ 3. フロント用のテンプレートモジュールを作成
- ステップ 4. 記事アーカイブテンプレートに作成したテンプレートモジュールをインクルード
※ 本記事の動作確認は執筆時点で最新の PowerCMS 5.12 で行っております。
ステップ 1. カスタムフィールドを作成
先ず、何は無くともカスタムフィールドを作成します。
「既定値」には編集画面用のテンプレートを記入するのですが、今回はそこそこの行数となります関係で別途テンプレートモジュールを作成してインクルードする事にします。
項目名 | 設定値 |
---|---|
システムオブジェクト | 記事 |
名前 | 関連リンク |
種類 | スニペット |
オプション | customfield_entry_outerlink_title,customfield_entry_outerlink_url |
既定値 [2] | <mt:Include module="cf-entry_outerlink" blog_id="1" /> |
ベースネーム | entry_outerlink |
テンプレートタグ | entry_outerlink |
ステップ 2. 入力画面用のテンプレートモジュールを作成
複数の値を持つ入力欄を作成する場合、ユーザーガイドには次のように記載されています。
複数の値を持つ入力欄を作成する
例えば複数選択可能なチェックボックスなど、同じ name 属性の input 要素を指定することができます。
下記は複数選択可能なチェックボックスのテンプレート (既定値欄に入力するテンプレート) の例です。name 属性値に「_loop」を付け加えた名前のループ変数を MTLoop ブロックタグでループして snipet_option という変数で値を受け取ります。『PowerCMS ユーザーガイド』(PDF) より
今回実装する上でのポイントは『同名の name
属性を持つ <input type="text">
要素を複数用意し、一つのオプションに対して複数の値を保存する』ところにあります。
cf-entry_outerlink テンプレートモジュール
入力画面用のテンプレートでは、入力欄の HTML と CSS 、そして JavaScript による入力欄を増減する機能を記述しています。
テンプレート名 | cf-entry_outerlink |
---|
<div class="customfield_entry_outerlink-content"> <mt:LocalVars> <mt:SetVar name="titles"> <mt:Loop name="customfield_entry_outerlink_title_loop"> <mt:SetVarBlock name="titles" function="push"><mt:Var name="snippet_option"></mt:SetVarBlock> </mt:Loop> <mt:SetVar name="urls"> <mt:Loop name="customfield_entry_outerlink_url_loop"> <mt:SetVarBlock name="urls" function="push"><mt:Var name="snippet_option"></mt:SetVarBlock> </mt:Loop> <mt:If name="titles"> <mt:Loop name="titles"> <mt:Var name="__counter__" op="--" setvar="index"> <div class="customfield_entry_outerlink-wrap"> <button type="button" class="js-outerlink__btn--remove">削除</button> <label for="customfield_entry_outerlink_title_<mt:Var name="index">" id="customfield_entry_outerlink_title_<mt:Var name="index">-label">リンクテキスト</label><br> <input name="customfield_entry_outerlink_title" id="customfield_entry_outerlink_title_<mt:Var name="index">" type="text" value="<mt:Var name="titles" index="$index" escape="html">"> <label for="customfield_entry_outerlink_url_<mt:Var name="index">" id="customfield_entry_outerlink_url_<mt:Var name="index">-label">URL</label><br> <input name="customfield_entry_outerlink_url" id="customfield_entry_outerlink_url_<mt:Var name="index">" type="text" value="<mt:Var name="urls" index="$index" escape="html">"> </div> </mt:Loop> <mt:Else> <div class="customfield_entry_outerlink-wrap"> <button type="button" class="js-outerlink__btn--remove">削除</button> <label for="customfield_entry_outerlink_title_0" id="customfield_entry_outerlink_title_0-label">リンクテキスト</label><br> <input name="customfield_entry_outerlink_title" id="customfield_entry_outerlink_title_0" type="text" value=""> <label for="customfield_entry_outerlink_url_0" id="customfield_entry_outerlink_url_0-label">URL</label><br> <input name="customfield_entry_outerlink_url" id="customfield_entry_outerlink_url_0" type="text" value=""> </div> </mt:If> </mt:LocalVars> </div> <p style="margin: 0; text-align: right;"><button type="button" class="js-outerlink__btn--add">追加する</button></p> <style> .customfield_entry_outerlink-wrap { overflow: hidden; margin-bottom: 10px; padding: 10px; border: 1px solid #c0c6c9; background-color: #fff; border-radius: 3px; line-height: 1.5; } .js-outerlink__btn--remove { float: right; margin-bottom: 2px; } .customfield_entry_outerlink-wrap input[type="text"] { box-sizing: border-box; width: 100%; } </style> <script> ;(function($){ const createElement = function (options) { const index = options.index || 0; const labels = options.labels || {}; const values = options.values || {}; const wrap = document.createElement('div'); if (options.wrap_class) wrap.setAttribute('class', options.wrap_class); const btn = document.createElement('button'); btn.textContent = '削除'; btn.setAttribute('type', 'button'); btn.setAttribute('class', 'js-outerlink__btn--remove'); wrap.appendChild(btn); ['title', 'url'].forEach(function(value){ const name = 'customfield_entry_outerlink_' + value; // create label if (labels[value]) { const label = document.createElement('label'); label.textContent = labels[value]; label.setAttribute('for', name + '_' + index); label.setAttribute('id', name + '_' + index + '-label'); wrap.appendChild(label); wrap.appendChild(document.createElement('br')); } // create input const input = document.createElement('input'); input.setAttribute('name', name); input.setAttribute('type', 'text'); input.setAttribute('id', name + '_' + index); input.setAttribute('class', 'text'); if (values[value]) input.setAttribute('value', values[value]); wrap.appendChild(input); }); const e = document.createDocumentFragment(); e.appendChild(wrap); return e; }; $(function(){ const $content = $('.customfield_entry_outerlink-content'); const item_class = 'customfield_entry_outerlink-wrap'; let index = $content.find('.' + item_class).length || 0; // add unit $(document).on('click', '.js-outerlink__btn--add', function(event){ event.preventDefault(); let element = createElement({ index: ++index, labels: { title: 'リンクテキスト', url: 'URL' }, wrap_class: item_class }); if (element) { $content.append(element); } }); // remove unit $(document).on('click', '.js-outerlink__btn--remove', function(event){ event.preventDefault(); if (window.confirm('削除しますか?')) { $(this).parent().remove(); } }); }); })(jQuery); </script>
ステップ 3. フロント用のテンプレートモジュールを作成
同名のオプションに格納されたデータは、カスタムフィールドのタグに Vars
を追加するとループ処理で取り出す事が可能です。
ユーザーガイドには次のように記載されています。
このケースでタグ名が
MTEntrySnippet
、オプションが foo の場合、下記のようにテンプレートを記述します。
- テンプレート
<MTEntrySnippetVars key="foo"> <$MTVar name="__value__"$> </MTEntrySnippetVars>- コンテキスト (MTVar) にセットされる値
__first__: ループの最初 __counter__: ループの何回目か __odd__: 奇数回目の出力 __even__: 偶数回目の出力 __last__: ループの最後 __value__: 値『PowerCMS ユーザーガイド』(PDF) より
関連リンク テンプレートモジュール
今回は「リンクテキスト ( customfield_entry_outerlink_title ) 」と「リンク URL ( customfield_entry_outerlink_url ) 」をループで取り出します。
テンプレート名 | 関連リンク |
---|
<mt:Ignore>** 関連リンク **</mt:Ignore> <mt:LocalVars> <mt:SetVar name="titles" /> <mt:SetVar name="urls" /> <mt:entry_outerlinkVars key="customfield_entry_outerlink_title"> <mt:SetVarBlock name="titles" function="push"><mt:Var name="__value__" /></mt:SetVarBlock> </mt:entry_outerlinkVars> <mt:entry_outerlinkVars key="customfield_entry_outerlink_url"> <mt:SetVarBlock name="urls" function="push"><mt:Var name="__value__" /></mt:SetVarBlock> </mt:entry_outerlinkVars> <mt:If name="titles"> <mt:SetVar name="list" /> <mt:Loop name="titles"> <mt:If name="__value__"> <mt:Var name="__counter__" op="--" setvar="index" /> <mt:If name="urls" index="$index"> <mt:SetVarBlock name="list" function="push"><a href="<mt:Var name="urls" index="$index" escape="html" />" class="link-outside" target="_blank"><mt:Var name="__value__" escape="html" /></a>(別ウィンドウが開きます)</mt:SetVarBlock> </mt:If> </mt:If> </mt:Loop> <mt:Loop name="list"> <mt:If name="__first__"> <h3 id="relation_link">関連リンク</h3> <ul> </mt:If> <li><mt:Var name="__value__" /></li> <mt:If name="__last__"> </ul> </mt:If> </mt:Loop> </mt:If> </mt:LocalVars>
ステップ 4. 記事アーカイブテンプレートに作成したテンプレートモジュールをインクルード
あとは記事アーカイブに作成したフロント用のテンプレートモジュール『関連リンク』をインクルードして完成です。
<mt:Include module="関連リンク" />
おわりに
スニペットフィールドは工夫次第で様々な入力項目を作成する事が可能です。ぜひご活用ください。
関連リンク
- スニペットフィールドを使って複数のカスタムフィールドを整理する
- スニペットフィールドでアイテムを登録する
- スニペットフィールドとカスタムオブジェクトによる入力欄セット追加UIのご紹介
- リッチテキストエディタが選択可能なカスタムフィールド(スニペットフィールド)を作成する
- スニペッドフィールドを使用したカラーピッカー
- スニペッドフィールドを使用したドラッグ&ドロップインターフェイス
- スニペット・カスタムフィールドでカスタムフィールドをタブグループにまとめる
- スニペット・カスタムフィールドでアイテム選択ダイアログを使用する
コメントを投稿する