コメントカスタムフィールドの値をクッキーに保存する方法
Movable Typeのコメント投稿フォームで、コメントカスタムフィールドの値をクッキーに保存する方法を紹介します。
1.概要
Movable Typeのコメント投稿フォームは、「ログイン情報を記憶」をチェックしておくことで、投稿時に入力した名前やメールアドレスなどをクッキーに保存し、次回のコメント投稿時に利用することができます。
ただし、クッキーに保存できるのはデフォルトで用意されているフィールドのみで、カスタムフィールドで作成したフィールドは保存できません。
例えば下の画像のように、「テキストフィールド」というコメントカスタムフィールドに入力した値は、次回のコメント投稿時には反映されません。
本エントリーでは、コメントカスタムフィールドに入力した値をクッキーに保存できるようにする方法を紹介します。
カスタマイズ後のコメント投稿フォーム
2.カスタマイズ
カスタマイズ対象は、コミュニティ機能を使っていない場合は、インデックステンプレートの「JavaScript」、コミュニティ機能を使っている場合はグローバルテンプレートの「GlobalJavaScript」になります。
以下に解説するサンプルは、カスタムフィールドのベースネームが「cf」で、カスタムフィールドがテキストフィールドの場合です。
2.1 mtSaveUser()の変更
まず、コメント投稿時に実行される関数mtSaveUser()に、コメント投稿フォームからカスタムフィールドの値を取得する処理(青色部分)を追加します。赤色部分の「cf」がカスタムフィールドのベースネームになります。
function mtSaveUser(f) {
// We can't reliably store the user cookie during a preview.
if (is_preview) return;
var u = mtGetUser();
if (f && (!u || u.is_anonymous)) {
if ( !u ) {
…中略…
}
if (f.customfield_cf != undefined) u.customfield_cf = f.customfield_cf.value;
if (f.author != undefined) u.name = f.author.value;
if (f.email != undefined) u.email = f.email.value;
if (f.url != undefined) u.url = f.url.value;
}
…後略…
コメント投稿フォームから取得したデータは、「u」という変数に任意の変数名、ここでは「customfield_cf」という名前で保存します。
2.2 mtBakeUserCookie()の変更
投稿者情報をクッキーに保存する関数mtBakeUserCookie()に、カスタムフィールドの値を保存する処理を追加します。
function mtBakeUserCookie(u) {
var str = "";
if (u.customfield_cf) str += "customfield_cf:'" + mtEscapeJS(u.customfield_cf) + "';";
if (u.name) str += "name:'" + mtEscapeJS(u.name) + "';";
…後略…
u.customfield_cfをクッキーに保存用フォーマットに整形し、変数strに設定します。シングルクォーテーションやダブルクォーテーションの記述位置に気をつけてください。
2.3 mtUnbakeUserCookie()の変更
クッキーから投稿者情報を取得する関数mtUnbakeUserCookie()に、カスタムフィールドデータを取得する処理を記述します。
【変更前】
function mtUnbakeUserCookie(s) {
if (!s) return;
var u = {};
var m;
while (m = s.match(/^((name|url|email|is_authenticated|profile|userpic|…後略…
…後略…
【変更後】
function mtUnbakeUserCookie(s) {
if (!s) return;
var u = {};
var m;
while (m = s.match(/^((customfield_cf|name|url|email|is_authenticated|profile|userpic|…後略…
…後略…
2.2項で設定したクッキー名「customfield_cf」をそのまま設定します。この記述をしておけば、mtUnbakeUserCookie()の処理でクッキーの値が変数uに収集されるようになっています。
2.4 mtUserOnLoad()の変更
ページロード時に実行される関数mtUserOnLoad()に、クッキーから読み出したカスタムフィールドの値を、コメント投稿フォーム反映用の変数に設定する処理を追加します。
function mtUserOnLoad() {
var u = mtGetUser();
…中略…
if (cf) {
if (u && u.is_anonymous) {
if (u.customfield_cf) cf.customfield_cf.value = u.customfield_cf;
if (u.email) cf.email.value = u.email;
if (u.name) cf.author.value = u.name;
if (u.url) cf.url.value = u.url;
…後略…
変数uに保存されているcustomfield_cfの値を、コメント投稿フォームに反映するときに利用する変数cf(comment formの略と思います)のcustomfield_cfに代入します。
3.複数のカスタムフィールドを保存する場合
複数のカスタムフィールドをクッキーに保存するには、2項の設定で、必要な分を同じように追加してください。2.1項であれば次のようになります。
function mtSaveUser(f) {
// We can't reliably store the user cookie during a preview.
if (is_preview) return;
var u = mtGetUser();
if (f && (!u || u.is_anonymous)) {
if ( !u ) {
…中略…
}
if (f.customfield_cf != undefined) u.customfield_cf = f.customfield_cf.value;
if (f.customfield_cf_2 != undefined) u.customfield_cf_2 = f.customfield_cf_2.value;
if (f.customfield_cf_3 != undefined) u.customfield_cf_3 = f.customfield_cf_3.value;
if (f.author != undefined) u.name = f.author.value;
if (f.email != undefined) u.email = f.email.value;
if (f.url != undefined) u.url = f.url.value;
}
…後略…
チェックボックス・ラジオボタン・セレクトボックスはデータの取得や設定はサンプル異なるかもしれません。通常のJavaScriptのお作法に従ってください。
コメントプレビューでカスタムフィールドの値を表示する
Movable Typeのコメントプレビュー画面でコメントのカスタムフィールドの値を引き継いで表示するカスタマイズを紹介します。
1.問題点
コメントのカスタムフィールドをコメント投稿フォームに表示する方法は次のようになっています。
<input type="hidden" name="blog_id" value="<MTBlogID>" />
<input type="hidden" name="customfield_beacon" value="1" id="customfield_beacon" />
<mt:CommentCustomFields>
<mt:SetVarBlock name="custom_field_name"><$mt:CustomFieldName$></mt:SetVarBlock>
<mt:SetVarBlock name="field-content"><$mt:CustomFieldHTML$></mt:SetVarBlock>
<mt:SetVarBlock name="custom_field_id">profile_<$mt:CustomFieldName dirify="1"$></mt:SetVarBlock>
<$mt:Include module="フォームフィールド" id="$custom_field_id" class="" label="$custom_field_name"$>
</mt:CommentCustomFields>
ただし、このサブテンプレートとコメントプレビューテンプレートに設定しても、ドロップダウンやラジオボタンなど、一部の形式のカスタムフィールドについては値が引き継がれないようです。
試しに、コメントカスタムフィールドのすべての種類を登録して、ブログ記事ページのコメントフォームとコメントプレビューのコメントフォームの表示を比較してみました。
ブログ記事ページのコメントフォーム
コメントプレビューのコメントフォーム
この結果、赤枠で括ったドロップダウンとラジオボタンの値が引き継がれていないことが分かりました。次項ではドロップダウンとラジオボタンの値を引き継ぐ対処方法を紹介します。
2.対処方法
まず、「CustomFieldExtensionTagsプラグイン」と「Splitプラグイン」をインストールしてください。
次に、コメントプレビューテンプレートのform要素の中に次のサブテンプレートを記述します。
<input type="hidden" name="blog_id" value="<MTBlogID>" />
<input type="hidden" name="customfield_beacon" value="1" id="customfield_beacon" />
ドロップダウンを表示したい場合、コメントプレビューテンプレートのform要素の中に次のサブテンプレートを記述します。
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="select">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<mt:CustomFieldOptions split="," setvar="selectdata" />
<select name="customfield_<mt:CustomFieldBasename />">
<mt:loop name="selectdata">
<mt:GetVar name="__value__" setvar="option_data" />
<option value="<mt:GetVar name="option_data" />"<mt:if tag="CommentCustomFieldValue" eq="$option_data"> selected="selected"</mt:if>><mt:GetVar name="option_data" /></option>
</mt:loop>
</select>
</mt:if>
</mt:CommentCustomFields>
ラジオボタンを表示したい場合、コメントプレビューテンプレートのform要素の中に次のサブテンプレートを記述します。
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="radio">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<mt:CustomFieldOptions split="," setvar="radiodata" />
<mt:loop name="radiodata">
<mt:GetVar name="__value__" setvar="option_data" />
<input type="radio" name="customfield_<mt:CustomFieldBasename />" value="<mt:GetVar name="option_data" />"<mt:if tag="CommentCustomFieldValue" eq="$option_data"> checked="checked"</mt:if> /><mt:GetVar name="option_data" /><br />
</mt:loop>
</mt:if>
</mt:CommentCustomFields>
3.複数のドロップダウンやラジオボタンを表示する方法
表示したいドロップダウンやラジオボタンが複数存在する場合は、前項のMTIfタグでMTCustomFieldTypeタグを判定している箇所を、MTCustomFieldBasenameタグやMTCustomFieldNameタグなど、一意になる値に置き換えて判定します。
例えば、表示したいドロップダウンのベースネームが「cf_6」の場合は、前述のサブテンプレートの2行目を次のように書き換えます(青色部分)。
<mt:CommentCustomFields>
<mt:if tag="CustomFieldBasename" eq="cf_6">
…中略…
なお、1項も含め、複数のカスタムフィールドを表示する場合は、一番外側にあるMTCommentCustomFieldsタグはひとつずつに与えるのではなく、すべてのカスタムフィールドを次のようにまとめてひと括りにしてください(青色部分)。
<mt:CommentCustomFields>
<mt:if tag="CustomFieldBasename" eq="cf_6">
…中略…
</mt:if>
<mt:if tag="CustomFieldType" eq="radio">
…中略…
</mt:if>
<mt:if tag="CustomFieldBasename" eq="cf_8">
…中略…
</mt:if>
</mt:CommentCustomFields>
4.他の種類を表示する方法
1項・2項の対処を行うことで必然的に他の種類もフォームを手作りすることになりますので、一通り掲載しておきます。
テキストの場合
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="text">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<input type="text" name="customfield_<mt:CustomFieldBasename />" id="customfield_<mt:CustomFieldBasename />" value="<mt:CommentCustomFieldValue>" />
</mt:if>
</mt:CommentCustomFields>
テキスト(複数行)の場合
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="textarea">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<textarea name="customfield_<mt:CustomFieldBasename />" id="customfield_<mt:CustomFieldBasename />"><mt:CommentCustomFieldValue></textarea>
</mt:if>
</mt:CommentCustomFields>
チェックボックスの場合
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="checkbox">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<input type="checkbox" name="customfield_<mt:CustomFieldBasename />" id="customfield_<mt:CustomFieldBasename />"<mt:if tag="CommentCustomFieldValue"> checked="checked"</mt:if> />
</mt:if>
</mt:CommentCustomFields>
URLの場合
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="url">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<input type="text" name="customfield_<mt:CustomFieldBasename />" id="customfield_<mt:CustomFieldBasename />" value="<mt:CommentCustomFieldValue>" />
</mt:if>
</mt:CommentCustomFields>
日付と時刻の場合
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="datetime">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<span class="date-time-fields">
<input type="text" name="d_customfield_<mt:CustomFieldBasename />" id="d_customfield_<mt:CustomFieldBasename />" value="<mt:CommentCustomFieldValue regex_replace="/^(\d+年\d+月\d+日).*$/","$1">" />
<input type="text" name="t_customfield_<mt:CustomFieldBasename />" id="t_customfield_<mt:CustomFieldBasename />" value="<mt:CommentCustomFieldValue regex_replace="/^.*\s(.*)$/","$1">" />
</span>
</mt:if>
</mt:CommentCustomFields>
オブジェクトの場合
<mt:CommentCustomFields>
<mt:if tag="CustomFieldType" eq="embed">
<label for="customfield_<mt:CustomFieldBasename />"><mt:CustomFieldName /></label>
<textarea name="customfield_<mt:CustomFieldBasename />" id="customfield_<mt:CustomFieldBasename />"><mt:CommentCustomFieldValue></textarea>
</mt:if>
</mt:CommentCustomFields>