Movabletype8で営業日カレンダーをつくる

らら
らら

はじめに

コンテンツタイプで営業日カレンダーをつくってみることに・・

Movabletype8って見出しだけど、7でもできます・・

つくってみる・・

コンテンツタイプで下記みたいに作る。項目をお好みで

必要なものは日付型・・・あとの項目はお好みで・・

salescalendar

日付型のものは必ず、必須にします。

salescalendar

下記はお好みでどうぞ・・

salescalendar

次にテーマのテンプレートへ移り、下記を選択、新規作成をクリックします。

salescalendar

テンプレート名をわかりやすいもので入力して、コンテンツタイプで登録したものを選択します。

salescalendar

テンプレート内容は下記で・・

ここでコンテンツデータを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

日付と時刻フィールドはコンテンツタイプで登録した日付を選択します。

ここは、コンテンツタイプで必須にしないと表示されません。

salescalendar

ここでは、月別ごとに掃き出しすることで、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">&raquo;&nbsp;</div>';
	} else {
		next_link = '<a href="javascript:void(0);" onclick="sales_calendar( jQuery(this), ' + next_year + ', ' + next_month + ')">&raquo;&nbsp;</a>';
	}
	if(target_year == prev_year_max && target_month == prev_month_max) {
		prev_link = '<div class="move_button prev_off">&laquo;&nbsp;</div>';
	} else {
		prev_link = '<a href="javascript:void(0);" onclick="sales_calendar( jQuery(this), ' + prev_year + ', ' + prev_month + ')">&laquo;&nbsp;</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">&nbsp;</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">&nbsp;</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>

完成はこんな感じ・・

salescalendar

さいごに

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

関連記事