js Implementation Calendar

  • 2021-09-16 05:57:23
  • OfStack

This week, I found that I used a calendar again when I wrote my own project, and I also needed to write a calendar for the task I encountered in the first job after graduation (if the team members wrote it, I didn't have to write it)
Today, let's toss about how the calendar is written.

First, let's look at the calendar of windows. I found that there are so many elements in total. Try to implement it first.

1. Choice of year and month
2. Monday to Sunday (Sunday to Saturday)
3. Calendar grid 6*7 = 42

It is relatively simple to analyze the implementation of calendar from the perspective of data
1. We need to show the structure of 1 current time-new Date ()
2. We need to display information for the current month-[week (Monday to Sunday), date (1-[28, 29, 30, 31])]
Among them, as long as we know the day of the week on the 1st of each month, we can easily put the following days (everything is difficult at the beginning).

We need at most 6 lines to display our date, because if the first row contains only 1 day of this month 6 (last month's) + (1 + 4 * 7), it will be 5 lines, and if the number of days of the current month is greater than 29, it will not be displayed After identifying the six rows, we found that we might need to get the placement of the extra days of last month and next month. In February of different months in different years, we know that its date is different, so we also need to judge whether it is a normal year or a leap year.

3. Show the switch between last month and next month. We found that we need a function to help us update our calendar.

After the analysis, let's add/modify some code.


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
<style>
 .week-item {
  display: inline-block;
  width: 80px;
  height: 40px;
  line-height: 40px;
  border: 1px solid sandybrown;
  text-align: center;
 }
 .date-item {
  display: inline-block;
  width: 80px;
  height: 40px;
  line-height: 40px;
  border: 1px solid beige;
  text-align: center;
 }
</style>
</head>
<body>
 <div class="wrapper">
  <div class="year-line">
   <button id="preMonth" class="year-prev"> Upper 1 Month </button>
   <button id="nowYear" class="year-now"></button>
   <button id="nowMonth"></button>
   <button id="nowDate"></button>
   <button id="nextMonth" class="year-next"> Under 1 Month </button>
  </div>
  <div id="weekLine" class="week-line"></div>
  <div id="dateWrap" class="date-wrap"></div>
 </div>
</body>
<script>
 //  Tool method  - start
 // 1. In order to get the number of dates in each month, we need to judge   Ordinary Leap Year [4 Year 1 Leap, never leap in a hundred years, 4 Re-leap in a hundred years ]
 const isLeapYear = (year) => {
  return (year % 400 === 0) || (year % 100 !== 0 && year % 4 === 0);
 };
 // 2. Get the number of dates in each month, pay attention  month - [0-11]
 const getMonthCount = (year, month) => {
  let arr = [
   31, null, 31, 30, 
   31, 30, 31, 31,
   30, 31, 30, 31
  ];
  let count = arr[month] || (isLeapYear(year) ? 29 : 28);
  return Array.from(new Array(count), (item, value) => value + 1);
 };
 // 3. Get a certain year or month  1 No.   What day of the week is it? What should be noted here is  JS  Adj.  API-getDay()  Is from  [ Day -6](0-6) , return  number
 const getWeekday = (year, month) => {
  let date = new Date(year, month, 1);
  return date.getDay();
 };
 // 4. Get the number of days in the last month 
 const getPreMonthCount = (year, month) => {
  if (month === 0) {
   return getMonthCount(year - 1, 11);
  } else {
   return getMonthCount(year, month - 1);
  }
 };
 // 5. Get the number of days in the next month 
 const getNextMonthCount = (year, month) => {
  if (month === 11) {
   return getMonthCount(year + 1, 0);
  } else {
   return getMonthCount(year, month + 1);
  }
 };
 //  Tool method  - end
 let weekStr = ' Day 123456';
 weekArr = weekStr.split('').map(item => ' Week ' + item);
 //  Insert week  dom
 let weekDomStr = '';
 let oFragWeek = document.createDocumentFragment();
 weekArr.forEach(item => {
  let oSpan = document.createElement('span');
  let oText = document.createTextNode(item);
  oSpan.appendChild(oText);
  oSpan.classList.add('week-item');
  oFragWeek.appendChild(oSpan);
 });
 let weekWrap = document.getElementById('weekLine');
 weekWrap.appendChild(oFragWeek);

 //  Get our first here 1 Secondary   Data   Array 
 const updateCalendar = (year, month, day) => {
  if (typeof year === 'undefined' && typeof month === 'undefined' && typeof day === 'undefined') {
   let nowDate = new Date();
   year = nowDate.getFullYear();
   month = nowDate.getMonth();
   day = nowDate.getDate();
  }
  //  Update 1 Year and month display at the bottom top 
  document.getElementById('nowYear').innerHTML = year;
  document.getElementById('nowMonth').innerHTML = month + 1;
  document.getElementById('nowDate').innerHTML = day;
  //  Generate calendar data, the rest of the last month  x  Days  +  Of the current month  28 (Average 2 Month) or 29 (Leap year 2 Month) or 30 Or 31 Days  +  Next month's  y  Days  = 42
  let res = [];
  let currentMonth = getMonthCount(year, month);
  let preMonth = getPreMonthCount(year, month);
  let nextMonth = getNextMonthCount(year, month);
  let whereMonday = getWeekday(year, month);
  if (whereMonday === 0) {
   whereMonday = 7
  }
  //  Thanks to netizens  luoyiming  Test (haha! Thank you!) : When here  whereMonday  For  0  Will intercept all the data of last month 
  let preArr = preMonth.slice(-1 * whereMonday)
  let nextArr = nextMonth.slice(0, 42 - currentMonth.length - whereMonday);
  res = [].concat(preArr, currentMonth, nextArr);
  //  After my own test, there is no problem, and the next step is to update  dom  The problem of information 
  let hadDom = document.getElementsByClassName('date-item');
  if (hadDom && hadDom.length) {
   let domArr = document.getElementsByClassName('date-item');
   for (let i = 0; i < domArr.length; i++) {
    domArr[i].innerHTML = res.shift();
   }
  } else {
   //  If there was no structure before, 
   let str = '';
   for (let i = 0; i < 6; i++) {
    str += '<div class="date-line">';
    for (let j = 0; j < 7; j++) {
     str += `<span class='date-item'>${res.shift()}</span>`;
     if (j === 6) {
      str += '</div>';
     }
    }
   }
   document.getElementById('dateWrap').innerHTML = str;
  }
 };

 updateCalendar();
 //  Add on 1 Month, next 1 Monthly event 
 let oPreButton = document.getElementById('preMonth');
 let oNextButton = document.getElementById('nextMonth');
 oPreButton.addEventListener('click', function () {
  let currentYear = +document.getElementById('nowYear').textContent;
  let currentMonth = +document.getElementById('nowMonth').textContent - 1;
  let currentDate = +document.getElementById('nowDate').textContent;
  if (currentMonth === 0) {
   updateCalendar(currentYear - 1, 11, currentDate);
  } else {
   updateCalendar(currentYear, currentMonth - 1, currentDate);
  }
 });
 oNextButton.addEventListener('click', function () {
  let currentYear = +document.getElementById('nowYear').textContent;
  let currentMonth = +document.getElementById('nowMonth').textContent - 1;
  let currentDate = +document.getElementById('nowDate').textContent;
  if (currentMonth === 11) {
   updateCalendar(currentYear + 1, 0, currentDate);
  } else {
   updateCalendar(currentYear, currentMonth + 1, currentDate);
  }
 });
</script>
</html>

It is found that it is really painful to use dom to operate directly instead of mvvm framework. The following is the effect of this implementation.

When realizing a function, it is sometimes easier to understand from the data level

The above is the js calendar implementation details, more about the js calendar information please pay attention to this site other related articles!


Related articles: