2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JSでリンク入りカレンダー作ってみた

Posted at

はじめに

自前のサービス内でカレンダーの日付にリンクを貼り付けたかったのですが、良さげなものがすぐ見つからなかったので軽い気持ちで書いてみました。(ほしかったリンクは、ベースのURLにYYYY-MM-DDが入っているものです)

作ったもの

画像

スクリーンショット 2024-03-06 23.19.59.png

ディレクトリ構成

any_directory
∟ index.html
∟ calendar.js
∟ calendar.css
∟ reset.css (お好きなものをお使いください)

コード

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>Calendar Sample</title>
    <link rel="stylesheet" type="text/css" href="./reset.css">
    <link rel="stylesheet" type="text/css" href="./calendar.css">
    <script src="./calendar.js"></script>
</head>

<body>
    <div class="month-year-label" style="font-size: x-large;">
        <span id="calendar_year"></span><span id="calendar_month"></span>月のカレンダー
    </div>
    <div class="year-sending-area" style="font-size: large;">
        <div id='prev_year' class='prev-year calendar-sending'><<</div>
        <div>  年移動  </div>
        <div id='next_year' class='next-year calendar-sending'>>></div>
    </div>
    <div class="month-sending-area" style="font-size: large;">
        <div id='prev_month' class='prev-month calendar-sending'><<</div>
        <div>  月移動  </div>
        <div id='next_month' class='next-month calendar-sending'>>>
        </div>
    </div>
    <div id="calendar" class="calendar-area"></div>
</body>

<script>
    // ベースURL
    const calendarBaseUrl = "https://any_url_address.com/";
    // 年月の宣言と初期値設定
    let currentYear = new Date().getFullYear(),
        currentMonth = new Date().getMonth() + 1;
    // 週配列の作成とテーブル用のヘッダ作成
    const weekDays = ["", "", "", "", "", "", ""],
        calendarHeader = `<tr><th>${weekDays.join('</th><th>')}</th></tr>`;

    // 初期のカレンダ作成 (calendar.js内のカレンダー作成関数実行)
    createCalendar();

    // イベントリスナを設定
    document.getElementById('prev_month').addEventListener('click', ()=> {
        // カレンダーを1ヶ月戻す
        if (currentMonth == 1) {
            currentMonth = 12;
            currentYear = currentYear - 1;
        } else {
            currentMonth = currentMonth - 1;
        }
        // カレンダーの再作成
        createCalendar();
    })
    document.getElementById('next_month').addEventListener('click' ,() => {
        // カレンダーを1ヶ月進める
        if (currentMonth == 12) {
            currentMonth = 1;
            currentYear = currentYear + 1;
        } else {
            currentMonth = currentMonth + 1;
        }
        // カレンダーの再作成
        createCalendar();
    })
    document.getElementById('prev_year').addEventListener('click', ()=> {
        // カレンダーを1年戻す
        currentYear = currentYear - 1;
        // カレンダーの再作成
        createCalendar();
    })
    document.getElementById('next_year').addEventListener('click' ,() => {
        // カレンダーを1年進める
        currentYear = currentYear + 1;
        // カレンダーの再作成
        createCalendar();
    })
</script>
</html>

calendar.js

function createCalendar() {

    // カレンダー上部の年月を更新
    const calendarYearLabelElem = document.getElementById("calendar_year"),
        calendarMonthLabelElem = document.getElementById("calendar_month");
    calendarYearLabelElem.innerText = currentYear;
    calendarMonthLabelElem.innerText = currentMonth;

    // calendar要素
    const calendarElem = document.getElementById("calendar");
    const calendarTableElem = document.getElementById("table_calendar");

    // 存在する場合は削除。(削除後に新規作成する)
    if (calendarTableElem) {
        calendarTableElem.remove();
    }

    // 月の初めと最終日を取得
    const firstDate = new Date(currentYear, currentMonth-1, 1),
        firstDateWeekDay = firstDate.getDay(),
        monthLastDate = new Date(currentYear, currentMonth, 1 - 1);
    let loopDate = new Date(currentYear, currentMonth-1, 1 - firstDateWeekDay);

    // テーブル要素を作成
    const tableElem = document.createElement('table'),
        theadElem = document.createElement('thead'),
        tbodyElem = document.createElement('tbody');
    tableElem.setAttribute('id', 'table_calendar');
    tableElem.setAttribute('class', 'table-calendar w-50');

    // tbody > tr要素を作成
    for(i=0; (loopDate <= monthLastDate); i++) {
        const trElem = document.createElement('tr');
        for(j=0; j<7 ; j++) {
            tdElem = document.createElement('td');
            if (j == 0 && firstDate <= loopDate && loopDate <= monthLastDate) {
                tdElem.setAttribute('style', 'color: red;')
            } else if (j==6 && firstDate <= loopDate && loopDate <= monthLastDate) {
                tdElem.setAttribute('style', 'color: blue;')
            }
            const loopYearStr = loopDate.getFullYear(),
                loopMonthStr = ('0'+(loopDate.getMonth() + 1).toString()).slice(-2),
                loopDateStr = ('0'+(loopDate.getDate()).toString()).slice(-2);
            const dateStr = `${loopYearStr}-${loopMonthStr}-${loopDateStr}`,
                linkUrl = `${calendarBaseUrl}${dateStr}`,
                aTag = `<a href="${linkUrl}">${loopDate.getDate()}</a>`;
            if ( firstDate <= loopDate && loopDate <= monthLastDate ) {
                tdElem.innerHTML = aTag;
            } else {
                tdElem.innerHTML = `<span style="color: gray;">${aTag}</span>`;
            }
            trElem.appendChild(tdElem)
            loopDate.setDate(loopDate.getDate() + 1);
        }
        tbodyElem.appendChild(trElem)
    }

    theadElem.innerHTML = calendarHeader;
    tableElem.appendChild(theadElem);
    tableElem.appendChild(tbodyElem);
    calendarElem.appendChild(tableElem);
}

calendar.css

.month-year-label {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    margin-bottom: 1em;
}

.year-sending-area {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    margin-bottom: 1em;
}

.month-sending-area {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    margin-bottom: 1em;
}

.calendar-sending {
    cursor: pointer;
}

.calendar-area {
    width: 100%;
    display: flex;
    flex-direction: row;
    justify-content: center;
}

.calendar-area table {
    border-collapse: collapse;
}

.table-calendar {
    width: 50%;
}

.table-calendar a {
    color: inherit;
    text-decoration: none
}

.table-calendar th, td {
    font-size: x-large;
    border: solid 1px black;
    text-align: center;
}

.table-calendar > thead > tr > th {
    height: 35px;
    background-color: lightblue;
}

.table-calendar > tbody > tr > td {
    height: 45px;
    background-color: whitesmoke;
}

.table-calendar > tbody > tr > td:hover {
    background-color: lightyellow;
}

最後に

軽い気持ちで書いてみましたが、3時間くらい掛けてしまいました...
最近JS書いてなかったのでメソッドを忘れたりして結構時間ロスが結構ありました。
イメージができていたのでもう1時間くらい早く作りたかったなぁ、とも思っています。
とはいえ、作り方を知っていただけだったのが、作った経験があるにランクアップできたのは個人的にうれしかったです。
(自己満足の記事です)

2
3
1

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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?