0
0

JavaScript カレンダーメモ

Last updated at Posted at 2024-09-14

自分用メモです。
参考ページ:https://www.geeksforgeeks.org/how-to-design-a-simple-calendar-using-javascript/ をもとに、若干スタイルを変更。

calender.html
<!DOCTYPE html>
<!-- 参考: https://www.geeksforgeeks.org/how-to-design-a-simple-calendar-using-javascript/ -->
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Calendar</title>
    <link rel="stylesheet" href="calender_style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="wrapper">
      <header>
        <p class="current-date"></p>
        <div class="icons">
          <span id="prev">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16">
              <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>
            </svg>
          </span>
          <span id="next">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16">
              <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/>
            </svg>
          </span>
        </div>
      </header>
      <div class="calendar">
        <ul class="weeks">
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
          <li></li>
        </ul>
        <ul class="days"></ul>
      </div>
    </div>
  </body>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
  <script src="calender_script.js" defer></script>
</html>
calender_style.css
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: sans-serif;
}
body{
  display: flex;
  align-items: center;
  padding: 0 10px;
  justify-content: center;
  min-height: 100vh;
  background: #9B59B6;
}
.wrapper{
  width: 450px;
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 15px 40px rgba(0,0,0,0.12);
}
.wrapper header{
  display: flex;
  align-items: center;
  padding: 25px 30px 10px;
  justify-content: space-between;
}
header .icons{
  display: flex;
}
header .icons span{
  height: 38px;
  width: 38px;
  margin: 0 1px;
  cursor: pointer;
  color: #878787;
  text-align: center;
  line-height: 38px;
  font-size: 1.9rem;
  user-select: none;
  border-radius: 50%;
}
.icons span:last-child{
  margin-right: -10px;
}
header .icons span:hover{
  background: #f2f2f2;
}
header .current-date{
  font-size: 1.45rem;
  font-weight: 500;
}
.calendar{
  padding: 20px;
}
.calendar ul{
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  text-align: center;
  padding-left: 0; /* ここで左側のスペースを調整 */
  margin-left: -4px; /* カレンダーの左右のバランスを取るためにマージンを微調整 */
}
.calendar .days{
  margin-bottom: 20px;
}
.calendar li{
  color: #333;
  width: calc(100% / 7);
  font-size: 1.07rem;
}
.calendar .weeks li{
  font-weight: 500;
  cursor: default;
}
.calendar .days li{
  z-index: 1;
  cursor: pointer;
  position: relative;
  margin-top: 30px;
}
.days li.inactive{
  color: #aaa;
}
.days li.active{
  color: #fff;
}
.days li::before{
  position: absolute;
  content: "";
  left: 50%;
  top: 50%;
  height: 40px;
  width: 40px;
  z-index: -1;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
.days li.active::before{
  background: #9B59B6;
}
.days li:not(.active):hover::before{
  background: #f2f2f2;
}

/* 非アクティブな日付(前月・次月の日付)にはポインターを無効に */
.days li.inactive {
    color: #aaa;
    cursor: default; /* カーソルをデフォルトに */
}
/* 非アクティブな日付にはホバー時の背景色変更を無効に */
.days li.inactive:hover::before {
    background: none; /* ホバー時に背景色を無効に */
}
calender_script.js
document.addEventListener("DOMContentLoaded", () => {
  const daysTag = document.querySelector(".days"),
    currentDate = document.querySelector(".current-date"),
    prevNextIcons = document.querySelectorAll(".icons span");

  let date = new Date(),
    currYear = date.getFullYear(),
    currMonth = date.getMonth();

  const renderCalendar = () => {
    let firstDayofMonth = new Date(currYear, currMonth, 1).getDay(),
        lastDateofMonth = new Date(currYear, currMonth + 1, 0).getDate(),
        lastDayofMonth = new Date(currYear, currMonth, lastDateofMonth).getDay(),
        lastDateofLastMonth = new Date(currYear, currMonth, 0).getDate();

    let liTag = "";
    // 前の月の最後の日を表示
    for (let i = firstDayofMonth; i > 0; i--) {
        liTag += `<li class="inactive">${lastDateofLastMonth - i + 1}</li>`;
    }
    // 現在の月の日付を表示
    for (let i = 1; i <= lastDateofMonth; i++) {
        liTag += `<li class="activeMonth" data-day="${i}">${i}</li>`;
    }
    // 次の月の最初の日を表示
    for (let i = lastDayofMonth; i < 6; i++) {
        liTag += `<li class="inactive">${i - lastDayofMonth + 1}</li>`;
    }

    currentDate.innerText = `${currYear}${currMonth + 1}月`;
    daysTag.innerHTML = liTag;
    // カレンダーがレンダリングされた後にクリックイベントを再度追加
    addClickEvents();
  }

  const addClickEvents = () => {
    const allDays = document.querySelectorAll(".days li.activeMonth");
    allDays.forEach(day => {
      day.addEventListener("click", () => {
        const dayValue = day.getAttribute("data-day");

        // dayValue が取得できない場合の対策
        if (!dayValue) {
            console.error("Day value is not available.");
            return;
        }

        const formattedDayValue = dayValue.toString().padStart(2, '0');
        const selectedDate = `${currYear}-${(currMonth + 1).toString().padStart(2, '0')}-${formattedDayValue}`;

        console.log("Selected date:", selectedDate);
      });
    });
  }

  renderCalendar();

  prevNextIcons.forEach(icon => {
    icon.addEventListener("click", () => {
      currMonth = icon.id === "prev" ? currMonth - 1 : currMonth + 1;

      if (currMonth < 0 || currMonth > 11) {
          date = new Date(currYear, currMonth, new Date().getDate());
          currYear = date.getFullYear();
          currMonth = date.getMonth();
      } else {
          date = new Date();
      }
      renderCalendar();
    });
  });
});
0
0
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
0
0