前回、「[MT]今日以降の2ヶ月分のエントリー一覧を表示する」で、
* 今日以降のエントリーを
* 月ごとに表示する
のを試してみた。発展系でさらに、
* table表示に対応し、同月エントリー行の”月”欄はrowspanでくくられるようにする
* 月あたり最大10件まで表示
* 該当エントリーなしの月は月名だけの空行を表示する
ようにしてみた。
同月エントリー行の”月”をrowspanでくくるのが案外面倒だった。方針として、
* あらかじめその月の該当エントリーをリストアップして、該当エントリー数を取得 (rowspan=”N”に使う)
* 同時に、エントリーの内容もハッシュに保存しておく
* 最後に、一気に1ヶ月分のtableデータを出力
とすることで解決した。
<mt:Ignore><!--=== サブルーチンみたいなもん[MonthlyEvent] === --></mt:Ignore>
<mt:SetVarTemplate name="MonthlyEvent">
<mt:Ignore><!-- 月ごとの変数を初期化 --></mt:Ignore>
<mt:SetVar name="monthly_cnt" value="0"><mt:Ignore><!-- 今月のエントリー数カウンタ --></mt:Ignore>
<mt:SetVar name="tag_htmls" function="undef"><mt:Ignore><!-- ハッシュのクリア --></mt:Ignore>
<mt:Ignore><!-- ハッシュにテーブル要素を蓄積 --></mt:Ignore>
<mt:Calendar month="$this_ym">
<mt:CalendarIfToday>
<mt:SetVar name="after_today" value="1">
<mt:Ignore><!-- 今日だったらフラグis_todayに"1"をセット --></mt:Ignore>
</mt:CalendarIfToday>
<mt:If name="after_today" eq="1"><mt:Ignore><!-- 今日以降なら --></mt:Ignore>
<mt:CalendarIfEntries>
<mt:Entries>
<mt:If name="monthly_cnt" lt="10"><mt:Ignore><!-- 今月10件以下なら --></mt:Ignore>
<mt:Ignore><!-- ハッシュに値をセット --></mt:Ignore>
<mt:SetVarBlock name="tag_htmls" function="push">
<td><mt:EntryDate format="%e日"><mt:EntryDate format="%a" setvar="youbi"><mt:if name="youbi" like="日"><span style="color:red">(日)</span><mt:elseif like="土"><span style="color:blue">(土)</span><mt:else>(<mt:Getvar name="youbi">)</mt:if></td>
<td><a href="<mt:EntryPermalink abs2rel="1">" title="<mt:EntryTitle>"><mt:EntryTitle></a></td>
</tr>
</mt:SetVarBlock>
<mt:SetVar name="monthly_cnt" op="++"><mt:Ignore><!-- 今月のエントリー数カウンタを+1 --></mt:Ignore>
</mt:If>
</mt:Entries>
</mt:CalendarIfEntries>
</mt:If>
</mt:Calendar>
<mt:Ignore><!-- /ハッシュにテーブル要素を蓄積 --></mt:Ignore<mt:Ignore><!-- ここからテーブル要素出力 --></mt:Ignore>
<mt:If name="monthly_cnt" eq="0"><mt:Ignore><!-- 0個の時 --></mt:Ignore>
<tr>
<td valign="top"><mt:Var name="this_month"></td>
<td>(ないぉ)</td>
<td>(ないぉ)</td>
</tr>
<mt:Else>
<mt:Loop name="tag_htmls" sort_by="key">
<mt:If name="__first__"><mt:Ignore><!-- ≠0, 1つめheadder --></mt:Ignore>
<tr>
<td valign="top" rowspan="<mt:Var name="monthly_cnt">"><mt:Var name="this_month"></td>
<mt:Else><mt:Ignore><!-- ≠0, 2つめ以降headder --></mt:Ignore>
<tr>
</mt:If>
<MTVar name="__value__"><mt:Ignore><!-- ハッシュ値出力 --></mt:Ignore>
</mt:Loop>
</mt:If><mt:Ignore><!-- /テーブル要素出力 ここまで --></mt:Ignore>
</mt:SetVarTemplate>
<mt:Ignore><!-- === サブルーチンみたいなもん[GetNextMonth] === --></mt:Ignore>
<mt:SetVarTemplate name="GetNextMonth">
<mt:If name="this_month" eq="12"><!-- 12月なら年送り処理をする -->
<mt:SetVar name="this_month" value="01">
<mt:SetVar name="this_year" op="++">
<mt:Else>
<mt:SetVar name="this_month" op="++">
</mt:If>
<mt:SetVarBlock name="this_ym"><mt:GetVar name="this_year"><mt:GetVar name="this_month" zero_pad="2"></mt:SetVarBlock>
</mt:SetVarTemplate>
<mt:Ignore><!-- 実際の処理はここから --></mt:Ignore>
<mt:SetVar name="after_today" value="0"><mt:Ignore><!-- 今日以降かの判定フラグを初期化 --></mt:Ignore>
<mt:Ignore><!-- 再構築日(≒今日)の年をyyyymmフォーマットで取得 --></mt:Ignore>
<mt:Date format="%Y" setvar="this_year">
<mt:Date format="%b" setvar="this_month">
<mt:Date format="%Y%m" setvar="this_ym">
<table width="80%" border="1" cellpadding="2" cellspacing="2" id="event-info">
<tr>
<th>月</th>
<th>日</th>
<th><span>イベント内容</span></th>
</tr>
<mt:Ignore><!-- 今月の処理 --></mt:Ignore>
<mt:GetVar name="MonthlyEvent"
<mt:Ignore><!-- 来月の処理 --></mt:Ignore>
<mt:GetVar name="GetNextMonth">
<mt:GetVar name="MonthlyEvent">
<mt:Ignore><!-- さ来月の処理 --></mt:Ignore>
<mt:GetVar name="GetNextMonth">
<mt:GetVar name="MonthlyEvent">
</table>
実際の処理本体部分はこんな感じ。
繰り返し処理部分は2つのmt:SetVarTemplate でサブルーチン化しているので一見シンプル。
ちなみに、SetVarTemplateではそれぞれ↓こういう処理をしている(後述)。
* GetNextMonth: 翌月の年月を生成。翌月が年をまたぐ場合の処理。
* MonthlyEvent: 該当月のエントリー数のカウント, 該当エントリーをハッシュに保存していく処理。
<mt:SetVar name="after_today" value="0"><mt:Ignore><!-- 今日以降かの判定フラグを初期化 --></mt:Ignore> <mt:Ignore><!-- 再構築日(≒今日)の年をyyyymmフォーマットで取得 --></mt:Ignore> <mt:Date format="%Y" setvar="this_year"> <mt:Date format="%b" setvar="this_month"> <mt:Date format="%Y%m" setvar="this_ym">
ここで全体の初期値のセットを行っている。
after_today は”今日以降”のエントリーかを判定するフラグ。[MonthlyEvent]の中で、 mt:CalendarIfTodayがtrueになったら”1″にセットされて以降ずっと”1″のまま。
その後、↓tableの開始タグと、見だし行を出力。
<table width="80%" border="1" cellpadding="2" cellspacing="2" id="event-info"> <tr> <th>月</th> <th>日</th> <th><span>イベント内容</span></th> </tr>
これ以降、今月, 来月, さ来月のデータを出力(実処理はサブルーチン内で出力)
<mt:Ignore><!-- 今月の処理 --></mt:Ignore> <mt:GetVar name="MonthlyEvent"> <mt:Ignore><!-- 来月の処理 --></mt:Ignore> <mt:GetVar name="GetNextMonth"> <mt:GetVar name="MonthlyEvent"> <mt:Ignore><!-- さ来月の処理 --></mt:Ignore> <mt:GetVar name="GetNextMonth"> <mt:GetVar name="MonthlyEvent">
最後に、tableの終了タグを出力しておしまい。
</table>
翌月の年月を生成。翌月が年をまたぐ場合の処理をしている部分。
<mt:SetVarTemplate name="GetNextMonth"> <mt:If name="this_month" eq="12"> <mt:SetVar name="this_month" value="01"> <mt:SetVar name="this_year" op="++"> <mt:Else> <mt:SetVar name="this_month" op="++"> </mt:If>
前段で年をまたぐ場合の月送り処理をして、最後の行↓で、this_ym に”%Y%m”フォーマットのデータをセットしている。
mt:Calendar month=”$this_ym”で使えるフォーマット(YYYYMM)を得るためにわざわざ月と年にバラしてから月を+1して再び合体するということをしている。
月にzero_pad=”2″を指定している部分がキモ。ちと苦労した部分。
<mt:SetVarBlock name="this_ym"> <mt:GetVar name="this_year"><mt:GetVar name="this_month" zero_pad="2"> </mt:SetVarBlock> </mt:SetVarTemplate>
3つのパートに分かれている。最初はローカル変数の初期化みたいなことをしている部分。
<mt:Ignore><!-- 月ごとの変数を初期化 --></mt:Ignore> <mt:SetVar name="monthly_cnt" value="0"><mt:Ignore><!-- 今月のエントリー数カウンタ --></mt:Ignore> <mt:SetVar name="tag_htmls" function="undef"><mt:Ignore><!-- ハッシュのクリア --></mt:Ignore>
2番目のパートではmt:Calendar month=”$this_ym” ブロックタグ内で、ここでは
* “今日以降”になったかどうかのフラグのセット。
* 今日以降なら指定月のエントリーをリストアップして、ハッシュに保存。
* 月のカウンター(monthly_cnt)により、(今日以降の)同月最大10件までのエントリーのみに限る部分の判定。
* このパートを回し終わると その月のエントリー数が得られる(monthly_cnt)。
を行っている。
<mt:Ignore><!-- ハッシュにテーブル要素を蓄積 --></mt:Ignore> <mt:Calendar month="$this_ym"> <mt:CalendarIfToday> <mt:SetVar name="after_today" value="1"> <mt:Ignore><!-- 今日だったらフラグis_todayに"1"をセット --></mt:Ignore></mt:CalendarIfToday> <mt:If name="after_today" eq="1"><mt:Ignore><!-- 今日以降なら --></mt:Ignore> <mt:CalendarIfEntries> <mt:Entries> <mt:If name="monthly_cnt" lt="10"><mt:Ignore><!-- 今月10件以下なら --></mt:Ignore> <mt:Ignore><!-- ハッシュに値をセット --></mt:Ignore> <mt:SetVarBlock name="tag_htmls" function="push"> <td><mt:EntryDate format="%e日"><mt:EntryDate format="%a" setvar="youbi"><mt:if name="youbi" like="日"><span style="color:red">(日)</span><mt:elseif like="土"><span style="color:blue">(土)</span><mt:else>(<mt:Getvar name="youbi">)</mt:if></td> <td><a href="<mt:EntryPermalink abs2rel="1">" title="<mt:EntryTitle>"><mt:EntryTitle></a></td> </tr> </mt:SetVarBlock> <mt:SetVar name="monthly_cnt" op="++"><mt:Ignore><!-- 今月のエントリー数カウンタを+1 --></mt:Ignore> </mt:If> </mt:Entries> </mt:CalendarIfEntries> </mt:If> </mt:Calendar> <mt:Ignore><!-- /ハッシュにテーブル要素を蓄積 --></mt:Ignore>
最後のパートで、1ヶ月分のtable要素を出力。
月のカラムをrowspanしたいために、2番目のパートであらかじめエントリー数(monthly_cnt)を数えておき、最後にまとめて出力処理する、ということになっている。
* <mt:Loop name=”tag_htmls” sort_by=”key”> ~</mt:Loop>ブロック内で1行ずつ順に出力。
* <mt:If name=”__first__”>で、その月の先頭行の場合は、<tr><td rowspan=”※エントリー数値をセット”>をセットしている。
* ハッシュの値を出す部分は、<MTVar name=”__value__”>。
* なお、その月のエントリーが一つもない時は(ないぉ)と表示。
<mt:Ignore><!-- ここからテーブル要素出力 --></mt:Ignore> <mt:If name="monthly_cnt" eq="0"><mt:Ignore><!-- 0個の時 --></mt:Ignore> <tr> <td valign="top"><mt:Var name="this_month"></td> <td>(ないぉ)</td> <td>(ないぉ)</td> </tr> <mt:Else> <mt:Loop name="tag_htmls" sort_by="key"> <mt:If name="__first__"><mt:Ignore><!-- ≠0, 1つめheadder --></mt:Ignore> <tr> <td valign="top" rowspan="<mt:Var name="monthly_cnt">"><mt:Var name="this_month"></td> <mt:Else><mt:Ignore><!-- ≠0, 2つめ以降headder --></mt:Ignore> <tr> </mt:If> <MTVar name="__value__"><mt:Ignore><!-- ハッシュ値出力 --></mt:Ignore> </mt:Loop> </mt:If> <mt:Ignore><!-- /テーブル要素出力 ここまで --></mt:Ignore>
以上でっす。
7/12 追記
「今月10件以下なら・・・」の判定箇所が間違っていたので修正。mt:Entriesの外で判定すると、10件目近くで同日複数エントリーある場合に、10件を超えて表示されてしまう→ハッシュに保存する直前にmt:Ifを移動。