[TIL] 210923

Lee Syong·2021년 9월 23일
0

TIL

목록 보기
36/204
post-thumbnail

📝 오늘 한 것

  1. 달력 구현 중

📚 배운 것

달력

어제 풀이에서 이어서


4. 네 번째 요구 사항

우측 화살표를 클릭했을 때, 다음 달의 요일 및 날짜 표기

💡 이제까지 구현한 요구 사항

  • 오늘의 현재 [요일, 일, 월, 연도] 표기
  • 현재 월의 1일이 무슨 요일인지 판별하기
  • 현재 월의 1일부터 마지막 날짜(30, 31, 28)까지 달력에 표기하기

모든 코드의 시작은 아래와 같으므로

YMDD = new Date();

const currYear = YMDD.getFullYear();
const currMonth = YMDD.getMonth();
// next 버튼을 눌렀을 때, 이 부분을 1씩 증가시키면 되지 않을까

const currMonthFirst = new Date(currYear, currMonth, 1);
const currMonthFirstDay = currMonthFirst.getDay();

const currMonthLast = new Date (currYear, currMonth+1, 0);
const currMonthLastDate = currMonthLast.getDate();

💡 버튼 클릭 시 '현재 월의 바로 다음 월' 날짜 구현

const next = document.querySelector('.next');

next.addEventListener('click', function () {
  currMonth = YMDD.getMonth() + 1;
  // currMonth 변수에 '현재 월의 바로 다음 월'을 담아줌

  const currMonthFirst = new Date(currYear, currMonth, 1);
  const currMonthFirstDay = currMonthFirst.getDay();

  const currMonthLast = new Date(currYear, currMonth+1, 0);
  const currMonthLastDate = currMonthLast.getDate();

  const td = document.getElementsByTagName('td');
  for (let i = 0; i < td.length; i++) {
    td[i].innerHTML = '';
  }

  function insert (limit) {
    fetch('calendarDate31').then(function(response){
      response.text().then(function(text){
        const textArray = text.split(',', limit);
        for (let i = 0; i < textArray.length; i++) {
          td[i+currMonthFirstDay].innerHTML = textArray[i];
        }
      })
    });
  }

  if (currMonthLastDate === 31) {
    insert(31);
  } else if (currMonthLastDate === 30) {
    insert(30);
  } else {
    insert(28);
  }
});

💡 문제 발생

  • 다음 달 날짜들로 바뀌긴 하는데 한 번만 바뀌고, console 창에 아래와 같은 오류가 뜸

    Uncaught (in promise) TypeError: Cannot set properties of undefined (setting 'innerHTML')

  • 애매하게 ajax뼟 잠깐 배우고 실습을 시작했더니 오류가 발생했다. ajax 공부하면서 본 단어이긴 한데 실습 잠깐 끊고 추가로 공부하러 가야 하나 고민하던 차에 코드에서 예상욘 못했던 잘못된 부분을 또 발견했다.

currMonth = YMDD.getMonth() + 1;
  • 이 코드로는 next 버튼을 몇 번 누르든 현 시점에선 currMonth 변수에 9밖에 담지 못한다. (YMDD.getMonth()가 언제나 8로 고정 값이기 때문에)

💡 해결 방법

currMonth = currMonth + 1;
  • 위처럼 코드를 수정해 next 버튼을 클릭할 때 계속해서 다음 월의 날짜들이 표기되게끔 하는 데에는 성공함. 다만, console 창에 위에서 언급한 오류는 계속 뜨는 상태임. 저 오류가 계속 뜨는 것도 아니고, next 버튼을 누를 때마다 간헐적으로 뜸.

5. 다섯 번째 요구 사항

좌측 화살표를 클릭했을 때, 다음 달의 요일 및 날짜 표기

💡 우측 화살표 코드를 복사해서 수정

// 모든 next를 prev로 바꿈
const prev = document.querySelector('.prev');

prev.addEventListener('click', function () {
  currMonth = YMDD.getMonth() - 1;
  // 여기서 +1을 -1로 바꿈

  const currMonthFirst = new Date(currYear, currMonth, 1);
  const currMonthFirstDay = currMonthFirst.getDay();

  const currMonthLast = new Date(currYear, currMonth+1, 0);
  const currMonthLastDate = currMonthLast.getDate();

  const td = document.getElementsByTagName('td');
  for (let i = 0; i < td.length; i++) {
    td[i].innerHTML = '';
  }

  function insert (limit) {
    fetch('calendarDate31').then(function(response){
      response.text().then(function(text){
        const textArray = text.split(',', limit);
        for (let i = 0; i < textArray.length; i++) {
          td[i+currMonthFirstDay].innerHTML = textArray[i];
        }
      })
    });
  }

  if (currMonthLastDate === 31) {
    insert(31);
  } else if (currMonthLastDate === 30) {
    insert(30);
  } else {
    insert(28);
  }
});

💡 좀 더 간결하게

function clickBtn (num) {
  currMonth = currMonth + num;

  const currMonthFirst = new Date(currYear, currMonth, 1);
  const currMonthFirstDay = currMonthFirst.getDay();

  const currMonthLast = new Date(currYear, currMonth+1, 0);
  const currMonthLastDate = currMonthLast.getDate();

  const td = document.getElementsByTagName('td');
  for (let j = 0; j < td.length; j++) {
    td[j].innerHTML = '';
  }

  function insert (limit) {
    fetch('calendarDate31').then(function(response){
      response.text().then(function(text){
        const textArray = text.split(',', limit);
        for (let i = 0; i < textArray.length; i++) {
          td[i+currMonthFirstDay].innerHTML = textArray[i];
        }
      })
    });
  }

  if (currMonthLastDate === 31) {
    insert(31);
  } else if (currMonthLastDate === 30) {
    insert(30);
  } else {
    insert(28);
  }
}

// 4. 우측 화살표를 클릭 시, 다음 달의 요일 & 날짜 표기
const next = document.querySelector('.next');
next.addEventListener('click', () => clickBtn(1));

// 5. 좌측 화살표를 클릭 시, 이전 달의 요일 & 날짜 표기
const prev = document.querySelector('.prev');
prev.addEventListener('click', () => clickBtn(-1));

6. 여섯 번째 요구 사항

특정 날짜를 클릭했을 때, 상단의 요일 및 날짜 반영하기

🔥 fetch API 삭제

  • 이 부분은 괜히 쓸 줄도 모뼴고 의미 없게 쓴 ęą° 같아서 ꡸냼 삭제하고, 아래와 같이 for 반복문으로 대체했다
let date_start = currMonthFirst.getDate();

for (let i = 0; i < currMonthLastDate; i++) {
  td[i+currMonthFirstDay].innerHTML = date_start;
  date_start++;
}

💡 선택한 날짜의 요일 구하기

  • 일단은 td[3] 을 눌렀을 때만, 상단의 날짜와 요일이 변하도록 해보았다
const date = document.querySelector('.date');
const day = document.querySelector('.day');

td[3].addEventListener('click', function() {
  // 선택한 '날짜'를 상단에 표기
  date.innerHTML = td[3].innerHTML;
  // 선택한 '요일'을 상단에 표기
  let makeDate = new Date(currYear, currMonth, td[3].innerHTML);
  day.innerHTML = (makeDate.toDateString().split(' '))[0];
});

선택한 '요일'을 상단에 표기하는 방법

  • 현재 화면에 띄워져 있는 달력의 연도와 월이 무엇인지 구한 후, 이를 td[3].innerHTMLęłź 조합해 선택한 날짜를 Date 객체 형태로 구함

  • toDateString().split('')뼟 이용해 Date 객체에서 요일 부분만 구한 후 이를 day에 innerHTML을 이용해 삽입

💡 문제 발생

  • td[3] 말고도 다른 모든 셀을 클릭했을 때 상단이 변하도록 해야 함

💡 해결 방법

  • td의 index 값에 3이 아닌 다른 숫자도 넣을 수 있도록 위의 코드를 통째로 changeTop이라는 함수 안에 넣고, ꡸ 매개변수를 num이라고 적어준 후 3이 쓰여 있는 자리를 num이라는 변수로 바꿔주었다

  • 셀의 개수만큼 changeTop 함수를 실행하기 위해 for 반복문을 추가했다

  • 이렇게만 하니까 비어 있는 셀을 선택한 경우에도 선택한 '요일'은 상단에 고정 값(현재 띄워져 있는 월의 이전 월의 마지막 날의 요일)으로 표기가 되었다

  • 이 문제를 해결하기 위해 이벤트 리스너 안에 if 조건문을 추가해 선택한 셀이 비어 있는 경우( td[num].innerHTML === '' ) 이벤트 리스너가 제거되어 상단에 변화를 주지 않도록 했다

    이때, 기존 코드들을 else 구문 안으로 옮겨야만 if 구문이 제대로 작동한다

💡 수정한 코드

const date = document.querySelector('.date');
const day = document.querySelector('.day');

function changeTop(num) {
  td[num].addEventListener('click', function changeDateAndDay () {
    // 선택한 셀에 아무 숫자도 없을 경우, 아무런 변화도 일어나지 않도록
    if (td[num].innerHTML === '') {
      this.removeEventListener('click', changeDateAndDay);
    } else {
      // 선택한 '날짜'를 상단에 표기
      date.innerHTML = td[num].innerHTML;
      // 선택한 '요일'을 상단에 표기
      let makeDate = new Date(currYear, currMonth, td[num].innerHTML);
      day.innerHTML = (makeDate.toDateString().split(' '))[0];
    }
  });
}

for (let i = 0; i < td.length; i++) {
  changeTop(i);
}

7. 테스트 및 점검

안내된 요구 사항은 모두 구현을 완료했고, 제대로 동작하는 걸 확인했다
다만, 몇 가지 수정할 부분이 남아 있다

7.1. 좌우 버튼 클릭 시, 상단의 월과 연도 변경

7.2. 달력의 날짜 클릭 시, 날짜(숫자) 색깔 바꾸기

7.3. console 창에 뜨는 오류 해결

7.1. 좌우 버튼 클릭 시, 상단의 월과 연도 변경

  • 여섯 번째 요구 사항에서 '월'을 구했던 방법을 응용해서 작성했다
// 1) 좌우 버튼 클릭 시, 상단의 월과 연도 변경
const month = document.querySelector('.month');
const year = document.querySelector('.year');

// (1) 우측 버튼 클릭 시, 상단의 월과 연도 변경
next.addEventListener('click', function changeMonthAndYear () {
  // 월 변경
  makeDate = new Date(currYear, currMonth);
  month.innerHTML = (makeDate.toDateString().split(' '))[1];

  // 연도 변경
  makeDate = new Date(currYear, currMonth);
  year.innerHTML = (makeDate.toDateString().split(' '))[3];
});

// (2) 좌측 버튼 클릭 시, 상단의 월과 연도 변경
prev.addEventListener('click', function changeMonthAndYear () {
  // 월 변경
  makeDate = new Date(currYear, currMonth);
  month.innerHTML = (makeDate.toDateString().split(' '))[1];

  // 연도 변경
  makeDate = new Date(currYear, currMonth);
  year.innerHTML = (makeDate.toDateString().split(' '))[3];
});
  • 처음에는 위와 같이 작성한 후 바로 이전에 이미 만들어 놓은 해당 좌우 버튼의 이벤트 리스너로 코드를 이동해주었다

  • 그런데 이렇게 옮기니까 실행이 되긴 되는데 간혹 가다가 뒤에 나올 7.3의 오류와 똑같은 오류가 똑같은 주기로 뜬다.


7.2. 달력의 날짜 클릭 시, 날짜(숫자) 색깔 바꾸기

  • 아래 코드는 달력의 날짜를 클릭하면 날짜(숫자)의 색깔이 바뀌도록, changeDateAndDay 콜백 함수의 본문으로 추가한 것이다
for (let i = 0; i < td.length; i++) {
  td[i].style.color = 'black';
  td[num].style.color = '#ffb94f';
}
  • 좌우 버튼을 클릭해서 월이 바뀌면 위의 과정을 통해 변했던 숫자의 색깔이 원래대로 검정색이 되도록, 좌우 버튼의 이벤트 리스너에도 각각 아래의 코드를 추가해줬다
  for (let i = 0; i < td.length; i++) {
    td[i].style.color = 'black';
  }
  • 이번에도 실행이 되긴 되지만, 7.1에서 발생했던 오류와 같은 오류가 같은 주기로 뜬다

✨ 내일 할 것

  1. 달력 구현 계속
profile
능동적으로 살자, 행복하게😁

0개의 댓글