ウェンブ

フロントエンドエンジニア うぇびんのよしなし語り

MovableType.netで複数の設定項目を持ったカスタムブロックを作る

前回の記事では、MovableType.netのブロックエディタに、設定の変更が可能なブロックを追加する方法を紹介しました。

MovableType.net用の「余白」カスタムブロックを作る


ドロップダウンが複数あるブロック


ですが、ブロックによっては複数の設定項目が必要なものがあります。例えばWordPressでおなじみの、div要素で包括して幅を拡張したり背景色を付ける「グループ」は、以下が考えられます。

  • 幅を選択(ドロップダウン)
  • 背景色(ドロップダウン)
  • 追加クラス(テキスト)

このうちドロップダウンとテキストは、以下のようにtype属性で判別ができますが…

<mt:BlockEditorBlocks>
<mt:If name="type" eq="sixapart-select">
ドロップダウン
<mt:ElseIf name="type" eq="sixapart-input">
テキスト
<mt:Else>
上記以外
</mt:If>
</mt:BlockEditorBlocks>

この記事を書いている2020年11月時点では、同じタイプの子ブロックを判別する方法がありません。つまり「幅を選択」と「背景色」の設定内容を、Movable Typeのテンプレートでそれぞれ独立した変数として取得できないのです。

※カスタムスクリプト(JavaScript)なら取得できる可能性がありますが、確実なドキュメントがないためここでは触れません

「何番目」で判定する方法

ループ内でカウントを行い「ブロック内でその子ブロックが何番目にあるか」で判定することも考えました。例えば1番目なら幅、2番目なら背景色という感じです。レンタルCMSで演算ができるのすごいっすね。

<mt:SetVar name="__i__" value="0" />
<mt:BlockEditorBlocks>
<mt:SetVarBlock name="__i__"><mt:Var name="__i__" op="++" /></mt:SetVarBlock>
<mt:If name="__i__" eq="1">
1番目のドロップダウン
<mt:If name="__i__" eq="2">
2番目のドロップダウン
<mt:Else>
上記以外
</mt:If>
</mt:BlockEditorBlocks>

…が、カスタムブロック内の子ブロックは、編集者が順番を変えることができてしまう=確実に1・2番目になるとは限らないため、没になりました。

また、ドロップダウン・テキストボックスは包括要素とクラス名を入力できますが、これらの値をMovable Typeのタグで取得する方法も見当たりませんでした。

値の接頭辞で判別する方法

最終的に、ここから解説する方法で実装できました。今後のバージョンアップにも対応できますが、少々荒っぽい方法になります。使用したい場合は注意点をよく読んでください。
テンプレートはGistでも公開しています。

https://gist.github.com/webbingstudio/13c3b98d3a99ea64d446f4a71edb102c

値に共通の文字列を付ける

この方法は、値が固定となるドロップダウンでしかできません。値=選択肢を決める際に、共通の文字列をつけます。編集画面で見て違和感がないものということで、ここでは以下のようにしました。

  • 幅を選択・・・「幅 : 」
  • 背景色・・・「背景 : 」

ドロップダウン「幅を選択」の設定例


typeと値で二重の判定を行う

表示側のテンプレートでは以下の通り、typeがドロップダウンだった場合、さらに値に先程の文字列が含まれているかを、mt:Ifのlikeモディファイアで判定します。
完全一致のeqではなく、あいまい検索のlikeです。

mt:BlockEditorBlocksのループ前に空の変数を宣言しているのは、Movable Typeのmt:SetVarで作成した値はテンプレート間をまたいで使用できる(グローバル変数)ためです。このように初期化しておかないと、ページ内に同じタイプのブロックが複数あると前のブロックの設定値が反映されて不具合が出てしまいます。

<mt:SetVar name="__group_align__" value="" /><mt:SetVar name="__group_bg__" value="" />
<mt:BlockEditorBlocks>
<mt:If name="type" eq="sixapart-select">
    <mt:If name="__value__" like="幅 :">
        <mt:SetVarBlock name="__group_align__"><mt:Var name="__value__" /></mt:SetVarBlock>
    <mt:ElseIf name="__value__" like="背景 :">
        <mt:SetVarBlock name="__group_bg__"><mt:Var name="__value__" /></mt:SetVarBlock>
    </mt:If>
<mt:Else>
    <mt:Var name="__value__" />
</mt:If>
</mt:BlockEditorBlocks>

これでそれぞれの選択した値が、変数「group_align」「group_bg」に入ってくれるので、あとはさらにmt:Ifで判定するなりして、目的のHTMLに加工して出力します。

テンプレート側でHTMLを加工するメリットとデメリット

今回はカスタムスクリプト(JavaScript)でエディタの入力値を変えずに、本文を出力するテンプレート内で加工を行っています。

入力値を変えないメリットは、たとえ記事やページが1,000件あってもあとから修正できることです。今後バージョンアップで仕様が変更されたときに対応可能ですし、利用者が出力結果のHTMLをカスタマイズできます。

一方でデメリットは、このテンプレートを削除してしまうと「幅 : 広い」などの変数化するはずだった値が表示部分に出力されてしまうことです。一長一短で悩ましいですが、現状ではテンプレート側でHTMLを加工する前提でカスタムブロックを作成するのが、安全でスマートなように思います。

編集画面内のプレビューで複数のドロップダウンの値を取得する方法がわかれば、プレビュー画面にもデザインを反映できるのですが…