캘린더 구현 및 js에서 장고 post 불러오기

강다·2022년 11월 20일
0

캘린더 만들기 및 사진 띄우기

인스타그램의 스토리 보관함(아래 사진)과 비슷한 장고 게시물 보관 캘린더 만들기

: 인스타그램 스토리 보관함(왼), 완성된 게시물 보관 캘린더(오)



1. 초기화

//기존 달력 구현에 필요한 초기화 코드 부분 생략(전체 코드 참고)
//달력의 날짜마다 헤드 이미지를 포함한 포스트에 대한 정보가 필요
//동적으로 장고 데이터 불러오기 위해 장고 템플릿 기능 사용( {%, {{ )
posts: [
    {% for post in postall %}
    {
        post_date: "{{ post.created_at|date:"Ymd" }}",
        title: "{{ post.title }}",
        url: "{{ post.get_absolute_url }}",
        {% if post.head_image %}
        head_image: "{{ post.head_image.url }}"
        {% else %}
				#헤드이미지 없을 시 picsum으로 자동 이미지 지정
        head_image: "https://picsum.photos/seed/{{ post.id }}/139/139"
        {% endif %}

    },
    {% endfor %}
  ],



2. 날짜 클릭 시 반응 설정

$calBody.addEventListener('click', (e) => {
    if (e.target.classList.contains('day')) {
      if (init.activeDTag) {
        init.activeDTag.classList.remove('day-active');
      }
      let day = Number(e.target.textContent); //클릭한 날짜의 day 받아오는 코드
      if (day<10){
        seDate[2]="0"+String(day);
      }
      else{
        seDate[2]=String(day);
      }
      e.target.classList.add('day-active'); //해당 날짜를 클릭했음을 하얀 동그라미로 표시
      loadDate(day, e.target.cellIndex);
      open(); //모달 창 open ('hidden'을 지우는 방식으로)
      document.querySelector("#bg").addEventListener("click", close);//배경클릭하면 모달 close
      init.activeDTag = e.target;
      init.activeDate.setDate(day);
    }
  }



3. load YY/MM

//달력 main 구성
loadYYMM(init.today); //호출
$btnNext.addEventListener('click', () => loadYYMM(init.nextMonth()));//다음
$btnPrev.addEventListener('click', () => loadYYMM(init.prevMonth()));//이전
//일부 내용 생략
//inner html을 통한 캘린더에 포스트 헤더 이미지 삽입
    let trtd = '';
    let startCount;
    let countDay = 0;
    for (let i = 0; i < 6; i++) {
      trtd += '<tr>';
      for (let j = 0; j < 7; j++) {
        if (i === 0 && !startCount && j === firstDay.getDay()) {
          startCount = 1;
        }
        if (!startCount) {
          trtd += '<td>'
        } else {
          let fullDate = seDate[0]+seDate[1] + String(init.addZero(countDay + 1));
          var flag=true;
          trtd += '<td ';

          for(var p=0;p<init.posts.length;p++){
            if(init.posts[p].post_date=== fullDate){//post작성 날과 같은 날짜 생성시 이미지 삽입
              flag=false;
							//head_image 불러오기
              trtd += `style="background-image:url(${init.posts[p].head_image});background-size:cover;" class="day day-img`;
              break;
            }
          }
          if(flag){
            trtd+='class="day'
          }
          trtd += (markToday && markToday === countDay + 1) ? ' today" ' : '"';
          trtd += ` data-date="${countDay + 1}" data-fdate="${fullDate}">`;
        }
        trtd += (startCount) ? ++countDay : '';
        if (countDay === lastDay.getDate()) {
          startCount = 0;
        }
        trtd += '</td>';
      }
      trtd += '</tr>';
    }
    $calBody.innerHTML = trtd;



4. load Day

//inner html을 통한 모달창에 포스트 url 및 제목 정보 삽입
function loadDate (date, dayIn) {
    document.querySelector('.url-body').innerHTML="";
    for (var i = 0; i < init.posts.length; i++) {
      var what_day=seDate[0] + seDate[1]+seDate[2]; //클릭한 날짜의 fullDate
        if (init.posts[i].post_date == what_day) {
						//객체에 innerHTML을 통해 href 속성 추가
            document.querySelector('.url-body').innerHTML+= `<a href=${init.posts[i].url} style="font-size:6px; color:black;"><i class="fas fa-heart"></i> ${init.posts[i].title}</a><br>`;
            console.log(document.querySelector('.url-body'));
        }
      }

  document.querySelector('.cal-date').textContent = date;
  document.querySelector('.cal-day').textContent = init.dayList[dayIn];
}



전체 코드

const init = {
    monList: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    dayList: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    today: new Date(),
    monForChange: new Date().getMonth(),
    posts: [
    {% for post in postall %}
    {
        post_date: "{{ post.created_at|date:"Ymd" }}",
        title: "{{ post.title }}",
        url: "{{ post.get_absolute_url }}",
        {% if post.head_image %}
        head_image: "{{ post.head_image.url }}"
        {% else %}
        head_image: "https://picsum.photos/seed/{{ post.id }}/139/139"
        {% endif %}

    },
    {% endfor %}
  ],
    activeDate: new Date(),
    getFirstDay: (yy, mm) => new Date(yy, mm, 1),
    getLastDay: (yy, mm) => new Date(yy, mm + 1, 0),
    nextMonth: function () {
      let d = new Date();
      d.setDate(1);
      d.setMonth(++this.monForChange);
      this.activeDate = d;
      return d;
    },
    prevMonth: function () {
      let d = new Date();
      d.setDate(1);
      d.setMonth(--this.monForChange);
      this.activeDate = d;
      return d;
    },
    addZero: (num) => (num < 10) ? '0' + num : num,
    activeDTag: null,
    getIndex: function (node) {
      let index = 0;
      while (node = node.previousElementSibling) {
        index++;
      }
      return index;
    }

  };

  const $calBody = document.querySelector('.cal-body');
  const $btnNext = document.querySelector('.btn-cal.next');
  const $btnPrev = document.querySelector('.btn-cal.prev');

  const seDate=[] //현재 클릭한 날짜에 대한 정보

function loadDate (date, dayIn) {
    document.querySelector('.url-body').innerHTML="";
    for (var i = 0; i < init.posts.length; i++) {
      var what_day=seDate[0] + seDate[1]+seDate[2];
        if (init.posts[i].post_date == what_day) {
            document.querySelector('.url-body').innerHTML+= `<a href=${init.posts[i].url} style="font-size:6px; color:black;"><i class="fas fa-heart"></i> ${init.posts[i].title}</a><br>`;
            console.log(document.querySelector('.url-body'));
        }
      }

  document.querySelector('.cal-date').textContent = date;
  document.querySelector('.cal-day').textContent = init.dayList[dayIn];
}

  function loadYYMM (fullDate) {
    let yy = fullDate.getFullYear();
    let mm = fullDate.getMonth();
    let firstDay = init.getFirstDay(yy, mm);
    let lastDay = init.getLastDay(yy, mm);
    let markToday;

    if (mm === init.today.getMonth() && yy === init.today.getFullYear()) {
      markToday = init.today.getDate();
    }

    document.querySelector('.cal-month').textContent = init.monList[mm];
    document.querySelector('.cal-year').textContent = yy;
    seDate[0]=String(yy);
    if(mm+1<10){
      seDate[1]='0'+String(mm+1);    }
    else{
      seDate[1]=String(mm+1);
    }

    let trtd = '';
    let startCount;
    let countDay = 0;
    for (let i = 0; i < 6; i++) {
      trtd += '<tr>';
      for (let j = 0; j < 7; j++) {
        if (i === 0 && !startCount && j === firstDay.getDay()) {
          startCount = 1;
        }
        if (!startCount) {
          trtd += '<td>'
        } else {
          let fullDate = seDate[0]+seDate[1] + String(init.addZero(countDay + 1));
          var flag=true;
          trtd += '<td ';

          for(var p=0;p<init.posts.length;p++){
            if(init.posts[p].post_date=== fullDate){
              flag=false;
              trtd += `style="background-image:url(${init.posts[p].head_image});background-size:cover;" class="day day-img`;
              break;
            }
          }
          if(flag){
            trtd+='class="day'
          }
          trtd += (markToday && markToday === countDay + 1) ? ' today" ' : '"';
          trtd += ` data-date="${countDay + 1}" data-fdate="${fullDate}">`;
        }
        trtd += (startCount) ? ++countDay : '';
        if (countDay === lastDay.getDate()) {
          startCount = 0;
        }
        trtd += '</td>';
      }
      trtd += '</tr>';
    }
    $calBody.innerHTML = trtd;
  }

  loadYYMM(init.today);

  $btnNext.addEventListener('click', () => loadYYMM(init.nextMonth()));
  $btnPrev.addEventListener('click', () => loadYYMM(init.prevMonth()));

  var open = () =>{
    document.getElementById("todo").classList.remove("hidden");
  }
  var close = () =>{
    document.getElementById("todo").classList.add("hidden");
  }

  $calBody.addEventListener('click', (e) => {
    if (e.target.classList.contains('day')) {
      if (init.activeDTag) {
        init.activeDTag.classList.remove('day-active');
      }
      let day = Number(e.target.textContent);
      if (day<10){
        seDate[2]="0"+String(day);
      }
      else{
        seDate[2]=String(day);
      }
      e.target.classList.add('day-active');
      loadDate(day, e.target.cellIndex);
      open();
      document.querySelector("#bg").addEventListener("click", close);
      init.activeDTag = e.target;
      init.activeDate.setDate(day);
    }
  });

참고
https://songsong.dev/11
https://wonpaper.tistory.com/223
https://gurtn.tistory.com/54
https://zenna9.tistory.com/36
https://im-developer.tistory.com/115

0개의 댓글