はじめに
コンテンツタイプで営業日カレンダーをつくってみることに・・
Movabletype8って見出しだけど、7でもできます・・
つくってみる・・
コンテンツタイプで下記みたいに作る。項目をお好みで
必要なものは日付型・・・あとの項目はお好みで・・
日付型のものは必ず、必須にします。
下記はお好みでどうぞ・・
次にテーマのテンプレートへ移り、下記を選択、新規作成をクリックします。
テンプレート名をわかりやすいもので入力して、コンテンツタイプで登録したものを選択します。
テンプレート内容は下記で・・
ここでコンテンツデータをjavascriptの変数化します。
<mt:Unless name="blanklinedel" regex_replace="/^[\s\t]*\n/gm","">
var calendartbl = [
<mt:Contents content_type="営業日カレンダー" sort_order="ascend" sort_by="field:休業日">
['<mt:ContentField content_field="休業日"><mt:ContentFieldValue format="%Y"></mt:ContentField>','<mt:ContentField content_field="休業日"><mt:ContentFieldValue format="%b" trim="1"></mt:ContentField>','<mt:ContentField content_field="休業日"><mt:ContentFieldValue format="%e" trim="1"></mt:ContentField>','<mt:ContentField content_field="表示タイプ"><mt:ContentFieldValue></mt:ContentField>'],
</mt:Contents>
];
</mt:Unless>
アーカイブマッピングで作成を選んで
種類をコンテンツタイプ月別
パスはカスタムで下記を入力
calendar/%y/%m/sales.js
日付と時刻フィールドはコンテンツタイプで登録した日付を選択します。
ここは、コンテンツタイプで必須にしないと表示されません。
ここでは、月別ごとに掃き出しすることで、js側の負荷を減らします。
calendar/2025/01/sales.jsは下記のように生成されます。
休業日のみ登録する感じになります。
var calendartbl = [
['2025','1','18','1'],
['2025','1','19','1'],
];
sales-calendar.jsはこんな感じ
$(function(){
$(".sales-calendar").each( function() {
sales_calendar($(this));
return true;
});
});
function sales_calendar(obj, target_year, target_month) {
var now = new Date(); // 現在時カレンダー
var close_data = new Array(); //
var today = false; // 当月であれば true
var month_prev; //
var month_next; //
var week_no; //
var target_date; // 表示年月の先頭日
var firstday; // 表示年月の先頭日の曜日
var lastday; // 表示年月の末日
var next_year; // 次月の年
var next_month; // 次月の月
var prev_year; // 前月の年
var prev_month; // 前月の月
var next_yaer_max; // 次月の年最大値
var next_month_max; // 次月の月最大値
var prev_year_max; // 前月の年最大値
var prev_month_max; // 前月の月最大値
var next_link; // 前月へのリンクhtml
var prev_link; // 次月へのリンクhtml
var week_array; // 曜日表示文字の配列
var dayclass = new Array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
var today_class = '';
var holiday_class = '';
var close_class = '';
var week = -1;
var max_date;
var html;
var i;
var diff;
var calendartbl;
if(target_year == undefined) {
target_year = now.getFullYear(); //現在年
}
if(target_month == undefined) {
target_month = now.getMonth() + 1; //現在月
}
now_day = now.getDate();
while(obj.attr("class") != "sales-calendar") {
obj = obj.parent();
}
// 当月か確認
if(target_year == now.getFullYear() && target_month == now.getMonth() + 1) {
today = true;
}
var recvdata;
var zero_month = ('0'+target_month).slice(-2);
$.ajax({
url:'./calendar/' + target_year + '/' + zero_month + '/sales.js?dev='+Math.random(),
dataType: 'text',
type:"GET",
async: false,
success: function(data) {
recvdata = data;
}
});
eval(recvdata);
if(calendartbl != undefined) {
for(var i = 0; i < calendartbl.length; i++) {
var item = calendartbl[i];
syear = item[0];
smonth = item[1];
sday = item[2];
sclose = item[3];
if(target_year == syear && target_month == smonth && sclose != 0) {
close_data[sday] = sclose;
}
}
}
month_prev = parseInt(obj.children(".month_prev").val());
month_next = parseInt(obj.children(".month_next").val());
week_no = parseInt(obj.children(".week_no").val());
// 次月
next_yaer_max = now.getFullYear();
next_month_max = (now.getMonth() + 1) + month_next;
if(next_month_max > 12) {
next_yaer_max = next_yaer_max + 1;
next_month_max = next_month_max - 12;
}
max_date = new Date(next_yaer_max,(next_month_max - 1), 1);
target_date = new Date(target_year, (target_month - 1), 1);
if((max_date - target_date) < 0) {
target_year = next_yaer_max;
target_month = next_month_max;
}
// 前月
prev_year_max = now.getFullYear();
prev_month_max = (now.getMonth() + 1) - month_next;
if(prev_month_max < 0) {
prev_year_max = prev_year_max - 1;
prev_month_max = prev_month_max + 12;
}
max_date = new Date(prev_year_max,(prev_month_max - 1), 1);
target_date = new Date(target_year ,(target_month - 1), 1);
if((target_date - max_date) < 0) {
target_year = prev_year_max;
target_month = prev_month_max;
}
// 次月、前月を取得
if(target_month == 1) {
next_year = target_year;
next_month = target_month + 1;
prev_year = target_year - 1;
prev_month = 12;
} else if(target_month == 12) {
next_year = target_year + 1;
next_month = 1;
prev_year = target_year;
prev_month = target_month - 1;
} else {
next_year = target_year;
next_month = target_month + 1;
prev_year = target_year;
prev_month = target_month - 1;
}
// リンクを取得
if(target_year == next_yaer_max && target_month == next_month_max) {
next_link = '<div class="move_button next_off">» </div>';
} else {
next_link = '<a href="javascript:void(0);" onclick="sales_calendar( jQuery(this), ' + next_year + ', ' + next_month + ')">» </a>';
}
if(target_year == prev_year_max && target_month == prev_month_max) {
prev_link = '<div class="move_button prev_off">« </div>';
} else {
prev_link = '<a href="javascript:void(0);" onclick="sales_calendar( jQuery(this), ' + prev_year + ', ' + prev_month + ')">« </a>';
}
// 指定年月の最後の日を取得
target_date = new Date(target_year, target_month, 0);
lastday = target_date.getDate();
// 指定年指定月1日の曜日
target_date = new Date(target_year, (target_month - 1), 1);
firstday = target_date.getDay();
// 週始めを取得
if(week_no == 0) {
week_array = new Array("日", "月", "火", "水", "木", "金", "土");
} else if(week_no == 1) {
week_array = new Array("月", "火", "水", "木", "金", "土", "日");
} else {
week_no = 0;
week_array = new Array("日", "月", "火", "水", "木", "金", "土");
}
// カレンダーの作成
html = '<table summary="営業日カレンダー" class="calendar">'
+ '<caption>'
+ '<span class="sales-calendar-prev">' + prev_link + '</span>'
+ target_year + '年' + target_month + '月'
+ '<span class="sales-calendar-next">' + next_link + '</span>'
+ '</caption>'
+ '<thead>';
+ '<tr>';
//曜日を表示
for(var i=0; i < week_array.length; i++) {
html += '<th>' + week_array[i] + '</th>';
}
html += '</tr>';
html += '</thead>';
html += '<tbody>';
// 1日になるまで空白のセルを作成
if(firstday < week_no) {
diff = Math.abs((7 + firstday) - week_no);
} else {
diff = Math.abs(firstday - week_no);
}
if(diff > 0) {
html += '<tr valign="middle">';
for(var i=0; i < diff; i++) {
html += '<td class="space"> </td>';
}
}
// カレンダー作成
for(var i=1; i <= lastday; i++) {
myday = target_date.getDay();
if(myday == week_no && i != 1) {
html += '</tr>';
html += '<tr valign="middle">';
}
if(myday == firstday) week++;
// 休日の確認
holiday_class = "";
var jp_holiday = JapaneseHolidays.isHoliday(target_date);
if(jp_holiday) {
holiday_class = " holiday";
}
// 本日の確認
if(today) {
if(i == now.getDate()) { // 日が同じか?
today_class = ' today';
} else {
today_class = '';
}
}
close_class = '';
if(close_data[i]) {
close_class = ' close';
}
var sweek = new Date(target_year, target_month - 1, i).getDay();
html += '<td class="' + holiday_class + close_class + today_class + ' ' + dayclass[sweek] +'">' + i + '</td>';
target_date.setDate(target_date.getDate() + 1);
// 末日以降のデータを埋める
if(i == lastday) {
while(target_date.getDay() != week_no) {
html += '<td class="space"> </td>';
target_date.setDate(target_date.getDate() + 1);
}
}
}
html += '</tr>';
html += '</tbody>';
html += '</table>';
obj.children(".sales-calendar-table").html(html);
// リターン
return true;
}
html側には、ヘッドはこんな感じ
japanese-holidayで祝日を判断します。
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type='text/javascript' src='sales-calendar.js?ver=1.0'></script>
<script src="https://cdn.rawgit.com/osamutake/japanese-holidays-js/v1.0.6/lib/japanese-holidays.min.js"></script>
お好みでCSSを当ててください・・
<style>
.sales-calendar-table .today { background: #EAEAEA; }
.sales-calendar-table .holiday { background: #FF0000; }
.sales-calendar-table .close { background: #FF6600; }
</style>
呼び出しHTML
Movabletypeのテンプレートに組み込みます。
<div class="sales-calendar">
<input type="hidden" class="week_no" value="0" />
<div class="sales-calendar-table"></div>
</div>
完成はこんな感じ・・
さいごに
Movabletypeのコンテンツデータで登録して、JSデータ化すれば、rest api風に動的に表示できます。
月別アーカイブにすることで、jsデータの量を減らすことができるのでPC側の負荷もないでしょう・・
関連
Movabletype7でイベントカレンダー
https://www.omakase.net/blog/2023/03/movabletype7event.html
ContentCalendarつかってみた
https://www.omakase.net/blog/2024/03/contentcalendar.html