月曜始まりのカレンダーを出力する(テンプレート&問題編)

昨日の話の続きで、月曜始まりのカレンダーを出力する方法をお話しします。
今日は、具体的なテンプレートの組み方を解説します。
また、昨日の考え方では不足している点があるので、その点も取り上げます。

1.テンプレートを組む

前日の話に基づいて、実際にテンプレートを組むと、以下のようになります。

<table>
  <tr><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th><th>日</th></tr>
<mt:Calendar>
  <mt:CalendarIfBlank>
    <$mt:SetVar name="blank" value="1"$>
  <mt:Else>
    <$mt:SetVar name="blank" value="0"$>
  </mt:CalendarIfBlank>
  <mt:CalendarIfEntries>
    <$mt:SetVar name="entries" value="1"$>
  <mt:Else>
    <$mt:SetVar name="entries" value="0"$>
  </mt:CalendarIfEntries>
  <mt:CalendarIfNoEntries>
    <$mt:SetVar name="no_entries" value="1"$>
  <mt:Else>
    <$mt:SetVar name="no_entries" value="0"$>
  </mt:CalendarIfNoEntries>
  <$mt:CalendarCellNumber setvar="cell_num"$>
  <mt:SetVarBlock name="week_flag"><$mt:GetVar name="cell_num" op="%" value="7"$></mt:SetVarBlock>
  <mt:If name="week_flag" eq="2">
    <$mt:SetVar name="week_header" value="1"$>
  <mt:Else>
    <$mt:SetVar name="week_header" value="0"$>
  </mt:If>
  <mt:If name="week_flag" eq="1">
    <$mt:SetVar name="week_footer" value="1"$>
  <mt:Else>
    <$mt:SetVar name="week_footer" value="0"$>
  </mt:If>
  <mt:If name="cell_num" eq="1">
  <mt:Else>
    <mt:If name="week_header">
      <tr>
    </mt:If>
    <mt:If name="blank">
      <td>&nbsp;</td>
    </mt:If>
    <mt:If name="entries">
      <td><mt:Entries lastn="1"><a href="<$mt:EntryPermalink$>"><$mt:CalendarDay$></a></mt:Entries></td>
    </mt:If>
    <mt:If name="no_entries">
      <td><$mt:CalendarDay$></td>
    </mt:If>
    <mt:If name="week_footer">
      </tr>
    </mt:If>
  </mt:If>
</mt:Calendar>
    <td>&nbsp;</td>
  </tr>
</table>

テンプレートの流れは以下の通りです。

1-1.4~18行目

昨日の記事で述べたように、カレンダーの日付をセルを出力する際には、通常はMTCalendarIfBlank/MTCalendarIfEntries/MTCalendarIfNoEntriesタグを組み合わせて、空のセル/記事がある日のセル/記事がない日のセルを判断します。
ところが、これらのテンプレートタグをMTIfタグのブロックの中で使うと、正しく動作しませんでした(おそらくMovable Typeの不具合)。
今取り上げている例では、MTIfタグのブロック中でMTCalendarIfBlank等のタグを使いたい処理が出てくるので、このままでは処理を上手く作ることができません。

そこで、4~18行目では、空/記事がある/記事がないの各条件を、blank/entries/no_entriesの各変数に代入しています。
後の処理では、これらの変数の値が0か1かで、処理を分けるようにします。

1-2.19~30行目

後の処理の中で、行の最初(月曜日)と最後(日曜日)を判断することが必要です(前日記事の2-2項を参照)。
そこで、まず繰り返し回数(MTCalendarCellNumberタグ)を7で割った余りを求めます(19~20行目)。
そして、その値が2(=月曜日)なら、変数week_headerに1を代入し、それ以外では0を代入します(21~25行目)
また、その値が1(=日曜日)なら、変数week_footerに1を代入し、それ以外では0を代入します(26~30行目)

1-3.31行目

前日記事の2-1項で述べたように、繰り返しの1回目(=先頭の日曜日)は出力しません。
そこで、繰り返しの先頭(=変数cell_numの値が1)かどうかを判断して、そうであれば何も出力しないようにしています。

1-4.32~48行目

カレンダーの個々のセルを出力します。
処理の流れは、通常のカレンダー(前日記事の1項で解説したもの)と同じです。
ただ、前述したように、MTIfタグのブロックの中ではMTCalendarIfBlank等のタグが正しく動作しないので、代わりにblank等の変数で条件判断を行っています。

1-5.50~51行目

前日記事2-3項の処理(最後の土曜日のセルと、行の最後の</tr>タグの出力)を行います。

2.問題点

現状のテンプレートで、たいていの月のカレンダーは出力できます。
ただし、以下の場合は正しいカレンダーになりません。

2-1.1日が日曜日の場合

まず、1日が日曜日である場合、カレンダーに1日が出力されず、2日の月曜日から始まってしまうという問題があります。

ここまでで作ったテンプレートでは、MTCalendarタグの繰り返しの1回目では、何も出力しないようにしていました。
しかし、1日が日曜日の場合、MTCalendarタグの繰り返しの1回目は、1日の日曜日にあたります。
そのため、単純に繰り返しの1回目をスキップするだけだと、1日が日曜日の場合に、1日が出力されなくなってしまいます。

そこで、1日が日曜日の場合は、その1日を含む行を別途出力する必要があります。

2-2.最後の日が日曜日の場合

また、月の最後の日が日曜日の場合、カレンダーの最後に空の行が1行できてしまうという問題もあります。

MTCalendarタグでは、月の最後の日が土曜日以外であれば、その次の日から土曜日までの空のセルが出力されます。
そのため、月の最後の日が日曜日だと、月曜日~土曜日の空のセルが出力されます。

ところが、月曜始まりのカレンダーの場合、月の最後の日が日曜日なら、そこでカレンダーの出力は終わりにしなければなりません。
しかし、MTCalendarタグそのままの動作だと、前述したように月曜日~土曜日の空のセルが出力されるため、空の行ができてしまいます。
この空の行を出力しないように、処理を考える必要があります。

2-3.問題の解決方法は明日解説

これらの問題を解決する方法は、明日の記事で解説します。