1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

条件分岐 if を一切使わずに Jacascript でカレンダーを作る

Last updated at Posted at 2019-06-22

みなさん、カレンダーつくっていますか?

今どきは Google Calendar 埋め込んだりして済ませることも多いんでしょうけど、稀に自分で作らなければいけなくなることがありますよね?

無い方はさようなら。

で、カレンダーの作り方をいろいろ探してみたんですが、ちょっとまどろっこしいというか、条件分岐めっちゃつかっててスマートじゃないなって感じたんですよ。

ということで、ifに頼ることなくカレンダーを作ろうという試みです。

まずはコードを御覧ください

最初に結論というか、コードを載せてしまいます。

const date = new Date();

// 今月の最終日を取得する
date.setMonth(date.getMonth() + 1);
date.setDate(0);
const lastDate = date.getDate();

// 一ヶ月の日付を配列にする
const dateList = [...Array(lastDate).keys()].map(item => item + 1);

// 今月1日の曜日を取得する
date.setDate(1);
const firstDay = date.getDay();

// 月初より前の部分を作るための配列
const spacer = [...Array(firstDay)];

// カレンダーの最初から最後まであるリストを作る
calendarItems = [...spacer, ...dateList];

// カレンダーに何週分必要か計算
const weekCount = Math.ceil(calendarItems.length / 7);

// 空のカレンダーを作る
const $month = $('<div>')
const $week = $('<tr>');
for (let i = 0; i < 7; i++) {
  $week.append('<td>');
}

for (let i = 0; i < weekCount; i++) {
  $month.append($week.prop('outerHTML'), '\n');
}

// カレンダーに日付を記入
calendarItems.forEach((item, index) => {
  $month.find('td').eq(index).html(item);
})

// カレンダーTABLEに反映させる
$('#calendar-body').html($month.html());

HTMLは下記の通り。

<div id="calendar">
  <table>
    <thead>
      <tr>
        <td></td><td></td><td></td><td></td><td></td><td></td><td></td>
      </tr>
    </thead>
    <tbody id="calendar-body">
      
    </tbody>
  </table>
</div>

考え方

ここからはこのカレンダーに関する考え方を説明していきます。

なるべくわかりやすくするため、説明がコードの順序と異なります。ご了承ください。

カレンダーの枠が決まってるんだから

カレンダーって、枠が決まっているじゃないですか。

必ず1行あたりに7日間あって、それが並んでいるという。

ということは、日付を記載するHTML要素をリスト化して、1から最終日まで日付を入力していけばいいだけなんですよね。

そうすれば条件分岐無しで全然行けてしまいます。

ただ、問題が起こります。

はい、必ず初日が日曜日になってしまいます。

そこでどうするか。

日付リストの初日のインデックスが適切であればいいよね

ということで、初日のインデックスを適切にオフセットしてあげれば単純なループで済ませることができるんです。

でもどうやってオフセットしましょう。

そう、初日の曜日番号をとって、その数の要素を日付配列の最初に追加してあげるといいですね。

それが

const firstDay = date.getDay();
const spacer = [...Array(firstDay)];

ということです。

ここまでできたらあとはループをブンブン振り回してあげればカレンダーの完成です。

月曜日スタートにしたかったらどうすりゃいいの?

日付リストを calendarItems.shift() してあげればいいんじゃないでしょうか。

というわけで

無事、条件分岐を使わずにカレンダーを作ることができました。

これさえつくってしまえば、月の切り替えとかはさほど苦労なくできるでしょう。

もし時間があれば月の切り替えとか、曜日ごとの色付け、祝日の色付けあたりについても投稿してみようかな。

では、これで。

1
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?