a-blog cmsのモジュール変数をJavaScript で取得する
目次
今回の話は、a-blog cmsのモジュールの変数、グローバル変数までを JavaScript で取得する方法です。基本的にa-blog cmsのモジュールを使用するときはHTML上にモジュールのスニペットを貼り付けて書くと思います。しかし、モジュール内の変数ををJavaScript で使いたいなぁと思ったことはありませんか?今回はJavaScript 側でモジュールの変数を取得して使用する方法をご紹介します。
JavaScriptをインラインで書こう
結論から言うと、JavaScriptをインラインで書こうね〜ということです。つまり、HTML内にscriptタグを書いて、その中にJavaScriptを書くということです。 簡単ですよね〜
インラインでJavaScript を書けば、HTML内にJavaScriptを書くことができますよね…
そうです!ということは a-blog cms のモジュールを script タグの中に書いちゃえばいいので〜す。(ペガサス会長風)
なんだかなんでもできそうな気がしてきませんか???
例えば、、、簡単な例ですが、こんな風にエントリーのタイトルをEntry_Summaryで取得してコンソールに出力することができるんです!
<!-- demo.html -->
<script>
const entries = [
<!-- END_MODULE Entry_Summary -->
<!-- BEGIN entry:loop -->
{
id: {eid}, title: {title},
},
<!-- END entry:loop -->
<!-- END_MODULE Entry_Summary -->
];
</script>
// demo.js
entries.map(entry => console.log(`このエントリーのエントリーIDは${entry.id}でタイトルは${entry.title}です`));
このようにjsファイル側からモジュールの変数を使用することができます。これを利用できれば何でもできる気がしてきませんか??
一応、冒頭では html ファイル内に script タグをインラインで記述すると言いましたが、実は a-blog cms ではCSSファイルや、JSファイルでもモジュールを動かすことができるらしいです。(未検証)ですが、最近のフロントエンドでは、そのままのJavaScriptやCSSを動かすことは少なく、BabelやWebpackを通すことが多いと思います。その際、エラーが出てしまうため、htmlファイルに書くことがおすすめです。また、jsonファイルを作成してもモジュールを動かすことはできますが、HTTP通信を行う必要があるため、パフォーマンスに差が出てしまいます。
実践例
次に、自分が実際に実務で上記のテクニックを初めて使用したときの実践例をお伝えします。先に謝っておきますが、この実践例ではイベントカレンダーモジュールという標準のモジュール機能出ないモジュールを使用しています。機能としては eventFrom
と eventTo
という2つのフィールドでカスタムフィールドグループを作成し、イベントの開催日をEntry_Calendarモジュールに出力することができるようになるモジュールです。
通常のEntry_Calendarモジュールですとエントリーの公開日を取得して表示することしかできないため、イベント掲載サイトやセミナー掲載サイトなどで重宝するかと思います。
今回実装した仕様といたしましては、標準モジュールのCalendar_Monthモジュールで出力したカレンダー(リンクは削除して、公開日にリンクが挿入されないようにしてあります。)
と、ここまで書いて思ったのですが、 Calendar_Month の標準機能を使用せずに、エントリーの公開日にリンクを挿入するという機能を作成したほうがいいんじゃないかと思ってきました。特注の Event_Calendar モジュールを使用せずに事例を紹介できるためです。
うん。そうしましょう。
では実際にサンプルコードを置いておきます。
calendar-month.html
<!-- BEGIN_MODULE Calendar_Month id="calendar_month" -->
@include("/admin/module/setting.html")
<div>
<div>
<h3 class="acms-text-center"><a href="{monthUrl}">{month}月</a></h3>
<ul class="acms-text-center acms-list-inline">
<li><a href="{prevUrl}" class="acms-btn-flat" title="前月へ">«</a></li>
<li><a href="{yearUrl}" class="acms-btn-flat" title="年間カレンダーへ">{year}</a></li>
<li><a href="{nextUrl}" class="acms-btn-flat" title="次月へ">»</a></li>
</ul>
</div>
<table class="acms-table acms-table-bordered">
<thead>
<tr class="acms-text-center">
<!-- BEGIN weekLabel:loop -->
<td >{label}</td>
<!-- END weekLabel:loop -->
</tr>
</thead>
<tbody>
<!-- BEGIN week:loop -->
<tr class="acms-text-center">
<!-- BEGIN day:loop -->
<!-- BEGIN spacer -->
<td> </td>
<!-- END spacer -->
<!-- BEGIN none -->
<td class="js-calendar-day" data-day="{day}">{day}</td>
<!-- END none -->
<!-- BEGIN link -->
<td class="js-calendar-day" data-day="{day}">{day}</td>
<!-- END link -->
<!-- END day:loop -->
</tr>
<!-- END week:loop -->
</tbody>
</table>
</div>
<!-- END_MODULE Calendar_Month -->
<script>
<!-- BEGIN_MODULE Entry_Calendar id="" -->
<!-- BEGIN date -->
const url = "%{BASE_URL}{year}/{month}/calendar.html";
<!-- END date -->
const entriesSchedule = [
<!-- BEGIN week:loop -->
<!-- BEGIN day:loop -->
{
day: {day},
title: [<!-- BEGIN entry:loop -->"{title}", <!-- END entry:loop -->],
},
<!-- END day:loop -->
<!-- END week:loop -->
];
<!-- END_MODULE Entry_Calendar -->
</script>
この書き方をすると、表示されているURLコンテキストにあったエントリーの作成日の日付とタイトルのオブジェクトが配列になったものが出力されます。 例として、下記のような配列です。
const entriesSchedule = [
{
day: 1,
title: [],
},
{
day: 2,
title: ["エントリーのタイトル", "エントリーのタイトル", ],
},
{
day: 3,
title: ["エントリーのタイトル", ],
},
// 以下省略
];
この配列をもとに、
- エントリーの作成日にはカレンダーのtdタグの中にaタグを挿入する
- aタグの
href
属性には、Entry_Calendarが表示されているページのリンクを入れる - tdタグには
success
というクラスを付与する。
という要件をクリアしていきます。
やり方としては、カレンダーのtdタグに js-calendar-day
というクラスをつけておいて、その中からエントリーがある日のtdタグにのみ success
クラスの付与とリンクの挿入をするというようなやり方でやっていきたいと思います。
まずは、先ほど作成した配列からエントリーがある日を抽出していきます。
具体的には、JavaScriptの配列操作メソッドである、filterメソッドとmapメソッドを使用します。 コードとしては、こんな感じです。
const datesHasEntry = entriesSchedule.filter(({title}) => title.length).map(({day}) => day);
console.log(datesHasEntry) // 結果:[12]
このソースコードのポイントは2つです。 1つ目は、fillterメソッドや、mapメソッドの引数にオブジェクトをとっているということです。これはJavaScriptのショートハンドテクニックの1つで、mapやfilterなどの配列操作メソッドは、配列の要素1つずつに対して何かしらの処理をして新しい配列を返すメソッドなのですが、引数に取れるコールバック関数の引数は、配列の要素になります。(言語化難しい…)
しかし、コールバック関数の引数にオブジェクトを書くことで、その配列の要素が持つプロパティを取り出して引数に取ることができます。
つまり、引数に ({title})
と書くことで、今回でいうと、entriesScheduleの各要素であるオブジェクトのtitleをkeyにしたプロパティの値を引数に取ることができます。つまり、内部的には { title } = obj[i]
のような分割代入の応用テクニックになっています。
2つ目は配列の中身が存在するかしないかで、その日付にエントリーがあるかどうかを判別しているのですが、その判別に length
プロパティを指定していることです。何も考えず、titleだけ書くと、JavaScriptにおいて、空の配列はtruthlyな値なため、エントリーが無い日も取得してしまいます。
以上の点が、上記のコードのポイントです。
次に、js-calendar-day
クラスをつけたtdタグを全て取得し、先程、取得したエントリーがぞんざいする日とtdタグに data-day
属性として設定した日付を比較し、一致していれば、success
クラスの付与ととaタグを挿入するという関数を作っていきます。
関数のコードは以下になります。
const assignEntry = () => (date) => {
[...calendarDateElems].some((elem) => {
const day = parseInt(elem.dataset.day, 10);
if (day !== date) return;
elem.classList.add('success');
elem.innerHTML = `<a href="${url}">${date}</a>`;
return true;
});
};
datesHasEntry.map(assignEntry());
上記の関数を作成して、dateHasEntryのそれぞれの要素に対して、mapメソッドで実行してあげればいいかなと思います。
この時ポイントとしては、無駄な繰り返し処理をしないために、someメソッドを使用している点です。someメソッドを使うことで、繰り返しの中で日付が一致した時点で処理を終了させることができます。 そのため、パフォーマンス的に見てメリットがあります。
カレンダーを見ると、リンクの挿入とsuccessクラスの付与ができているのがわかるかと思います。
まとめ
今回は、a-blog cmsのモジュール変数をJavaScript で取得するといろいろ便利だよということを解説しました。今回やってみて思ったのは、a-blog cmsのカレンダー系統のモジュールはまだまだ改善の余地があるなぁというところです。標準のカレンダーモジュールで色々なことができるようになると、もっとa-blog cmsがよくなっていくのではないかな?と思いました。これから乞うご期待ですね。!