본문 바로가기
깃허브 링크!
node.js프로젝트(김아현,이무헌,박민우,신근호)

팀프로젝트day-3 popup 구현

<div class="popup-content chattingroom">​

 

클래스 이름 사이에 공백을 넣으면 두 클래스가 동시에 적용되는 것을 의미한다.

.popup-content.chattingroom{
  left: 900px;
  display: block;
}​


 

 

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="./style.css">
</head>

<body>
  <div class="custom-button" onclick="openPopup();"></div>
  <div class="popup-wrap">
    <div class="popup-content">

      <span onclick="openPopup();"></span>
      <div class="content-wrapper">
        <img src="https://blog.kakaocdn.net/dna/csnaXD/btqxB6Hdt3R/AAAAAAAAAAAAAAAAAAAAACOsYz9Dk08Taj47SHt3jzXtMw38QipPJjYO2VohyVru/img.jpg?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1777561199&allow_ip=&allow_referer=&signature=vs3It3VXfyCeiNilP3k5StMj0Ss%3D" alt="이미지 설명">
        <div class="offset">
          <img
            src="https://play-lh.googleusercontent.com/4ExClCk0jBhi_0PjUgWzvvAaoPBv1kcbhDchdTMKmARqtwj3RNX1-whKqYznY3IWtI8"
            alt="">

          <p>인터파크입니다😀</p>
          <p>안녕하세요? 국내외 항공권 숙소 여행 최저가 예약부터 뮤지컬 콘서트 연극 티켓까지 모두 한번에 예약하세요😁</p>
          <div class="inquire">
            <h3 class="content-wrapper2">새 문의하기</h3>
          </div>
        </div>
      </div>

      <div class="chatting">
        채팅💬
      </div>



      <div class="imgsize">
        <img
          src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMTExMDFfMjkx%2FMDAxNjM1NzcyNTAyMzM2.cJE1tVC6KDvRbLggbBVEvvTt44ThhLU0wXelkyRh_bgg.ogMtpmeg-v7VIqtsSBpxHCNzt--aP7oHwL3PVm2RgiQg.JPEG.yunalee1997%2F4cc82b04dee244c22d13aee91e4b5e58.jpg&type=sc960_832"
          alt="">
        <p onclick="chattingroom()">User1</p>



      </div>

      <div class="border-bottom"></div>

      <div class="imgsize">
        <img
          src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMTExMDFfMjkx%2FMDAxNjM1NzcyNTAyMzM2.cJE1tVC6KDvRbLggbBVEvvTt44ThhLU0wXelkyRh_bgg.ogMtpmeg-v7VIqtsSBpxHCNzt--aP7oHwL3PVm2RgiQg.JPEG.yunalee1997%2F4cc82b04dee244c22d13aee91e4b5e58.jpg&type=sc960_832"
          alt="">
        <p onclick="chattingroom()">User2</p>
      </div>

      <div class="border-bottom"></div>

      <div class="imgsize">
        <img
          src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMTExMDFfMjkx%2FMDAxNjM1NzcyNTAyMzM2.cJE1tVC6KDvRbLggbBVEvvTt44ThhLU0wXelkyRh_bgg.ogMtpmeg-v7VIqtsSBpxHCNzt--aP7oHwL3PVm2RgiQg.JPEG.yunalee1997%2F4cc82b04dee244c22d13aee91e4b5e58.jpg&type=sc960_832"
          alt="">
        <p onclick="chattingroom()">User3</p>
      </div>

      <div class="border-bottom"></div>
      <div class="imgsize">
        <img
          src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMTExMDFfMjkx%2FMDAxNjM1NzcyNTAyMzM2.cJE1tVC6KDvRbLggbBVEvvTt44ThhLU0wXelkyRh_bgg.ogMtpmeg-v7VIqtsSBpxHCNzt--aP7oHwL3PVm2RgiQg.JPEG.yunalee1997%2F4cc82b04dee244c22d13aee91e4b5e58.jpg&type=sc960_832"
          alt="">
        <p onclick="chattingroom()">User4</p>
      </div>

      <div class="border-bottom"></div>

      <div class="imgsize">
        <img
          src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMTExMDFfMjkx%2FMDAxNjM1NzcyNTAyMzM2.cJE1tVC6KDvRbLggbBVEvvTt44ThhLU0wXelkyRh_bgg.ogMtpmeg-v7VIqtsSBpxHCNzt--aP7oHwL3PVm2RgiQg.JPEG.yunalee1997%2F4cc82b04dee244c22d13aee91e4b5e58.jpg&type=sc960_832"
          alt="">
        <p onclick="chattingroom()">User5</p>
      </div>

      <div class="border-bottom"></div>








    </div>

    <div class="popup-content chattingroom">

      <span onclick="chattingpage();"></span>
      <div class="content-wrapper">
        <img src="https://blog.kakaocdn.net/dna/csnaXD/btqxB6Hdt3R/AAAAAAAAAAAAAAAAAAAAACOsYz9Dk08Taj47SHt3jzXtMw38QipPJjYO2VohyVru/img.jpg?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1777561199&allow_ip=&allow_referer=&signature=vs3It3VXfyCeiNilP3k5StMj0Ss%3D" alt="이미지 설명">
        <h3>인터파크에 문의하기</h3>
        <h5>⨳ 보통 수십 분 내 답변</h5>
        <p class="font-size">인터파크</p>
        <div class="offsetchatting">
          
        <div style="font-size: 14px;">안녕하세요? 고객의 편의성을 돕는 인터파크입니다.</div>
        <div style="font-size: 14px;">문의를 남겨주시면 최대한 신속하게 답변 드리겠습니다.😀</div>
        
        <img src="https://play-lh.googleusercontent.com/4ExClCk0jBhi_0PjUgWzvvAaoPBv1kcbhDchdTMKmARqtwj3RNX1-whKqYznY3IWtI8" alt="" style="width: 30px; height: 30px; margin-left: -30px; ">
        
        <div style="position: relative; text-align: center;">
          <div onclick="enableInput()" contentEditable="true" style="background-color: rgb(255, 255, 255); width: 250px; height: 40px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, 340%); border-radius: 10px; display: flex; align-items: center; justify-content: flex-start; padding-left: 10px;">
            <p id="message" style="text-align: left; margin: 0; color: rgb(58, 56, 54); font-size: 13px;">메시지를 입력해주세요.</p>
          </div>
        </div>
        
      </div>

</body>
<script src="./index.js"></script>

</html>​


body{
  margin: 0;
  padding: 0;
}

.popup-wrap{
  /* 브라우저 크기 vw 가로 */
  /* 브라우저 크기 vh 세로 */
  /* 100vw 보고있는 브라우저 창의 전체 너비 */
  /* 100vh 보고있는 브라우저 창의 전체 높이 */
  width: 100vw;
  height: 100vh;
  position: fixed;
  display: none;
  background-color: rgba(0, 0, 0, 0.5);
}

/* popup-wrap클래스와 is-active 둘다 클래스를 가지고 있을때 */
/* 태그 한개가 클래스를 두개 가지고 있을때 */
.popup-wrap.is-active{
  display: block;
}

.popup-wrap .popup-content{
  background-color: #fff;
  border-radius:12px;
  width: 300px;
  height: 500px;
  /* 보고있는 브라우저 기준으로 위치를 맞출수 있다. fixed */
  position: fixed;
  top: 50%;
  left: 500px;
  transform: translate(-50%, -50%);
}


.popup-wrap .popup-content span {
  width: 30px;
  height: 30px;
  /* 안보이면 block 속성이 없는거다.. */
  display: block;
  position: absolute;
  right: 0;
  cursor: pointer;
}

.popup-wrap .popup-content span::after,
.popup-wrap .popup-content span::before {
  content: '';
  width: 15px;
  height: 4px;
  background-color: black;
  border-radius: 5px;
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(45deg);
}

.popup-wrap .popup-content span::before {
  transform: translate(-50%, -50%) rotate(-45deg);
}



.custom-button {
  position: fixed;
  bottom: 20px;
  right: 20px;
  width: 50px;
  height: 50px;
  background-color: antiquewhite;
  border: none;
  border-radius: 20px;
  cursor: pointer;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  background-image: url("https://image.fmkorea.com/files/attach/new/20201219/1135415169/2380230120/3269864399/997c818d2ed1029cde9e9a29ce518f31.png");
  background-size: cover;
  background-position: center;
}

.content-wrapper{
  text-align: center;
  cursor: pointer;
}
.content-wrapper{
  text-align: center;
  margin: auto;
}

.content-wrapper img {
  width: 150px;
  height: auto;
  margin-right: 15px;
  margin: 0;
}

.offset{
  background-color: white;
  width: 270px;
  margin: auto;
  height: 160px;
  border: 1px solid white;
  border-radius: 10px;
  box-shadow: rgba(255, 255, 255, 0.12) 0px 0px 2px 0px inset, rgba(0, 0, 0, 0.05) 0px 0px 2px 1px, rgba(0, 0, 0, 0.08) 0px 2px 6px;
  
}

.offsetchatting{
  background-color: white;
  width: 230px;
  margin: auto;
  height: 100px;
  border: 1px solid white;
  border-radius: 10px;
  box-shadow: rgba(255, 255, 255, 0.12) 0px 0px 2px 0px inset, rgba(0, 0, 0, 0.05) 0px 0px 2px 1px, rgba(0, 0, 0, 0.08) 0px 2px 6px;
  text-align: left;
  transform: perspective(600px) rotateX(5deg) translateY(5px);
}


.offset p {
  margin: 10;
  margin-top:10px ;
  width: 180px;
  
}

.inquire{
  background-color: powderblue;
  width: 240px;
  margin: auto;
  height: 40px;
  border: 1px solid powderblue;
  border-radius: 10px;
}

.popup-wrap .popup-content .offset img {
  max-width: 15%;
  float: left;
  height: auto;
}

.imgsize{
  display: flex;
  margin-left: 10px;
  margin-top: 10px;
  height: 40px;
}

.chatting{
  display: flex;
  margin-left: 15px;

}

.popup-wrap .popup-content .offset p {
  width: 100%;
  margin: 10px 0;
}


.popup-wrap .popup-content .offset .inquire {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 20%;
}

.popup-wrap .popup-content .offset .inquire .content-wrapper2 {
  background-color: powderblue;
  width: 240px;
  height: 10px;
  border: 1px solid powderblue;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-size: 16px;
}

.border-bottom{
  border-bottom: 1px solid gray;
}

.imgsize{
  display: flex;
  align-items: center;
  cursor: pointer;
}

.imgsize img{
  margin-right: 10px;
  width: 40px;
  height: 40px;
}

.popup-content.chattingroom{
  left: 900px;
  display: none;
}

.font-size{
  font-size: 5px;
  color: gray;
  display: flex;
  margin-left: 40px;
}​

// 팝업 열어주는 함수
function openPopup(){
    let popup =  document.querySelector(".popup-wrap");
    // 디버깅 습관
    console.log(popup);
    
    console.log(popup.className);
    console.log(popup.classList);

    // popup.className
    // popup.classList

    // popup.className을 사용하면 문자열을 그대로 대입해주면 되고
    // popup.classList을 사용하면 메소드를 사용하면 된다.
    //

    // popup.className 써보자
    // 클래스 구분을 줘야 하기때문에 ' is-active'앞에 한칸 띄워줬다.
    // popup.className = popup.className + " is-active";
    // popup.classList.add("is-active");
    // 와 메소드 편하네

    // 조건문으로 해보자 클래스가 있는지 확인을 하고 있으면 붙히지말고
    // 없으면 붙히자..
    // popup.classList.contains("is-active") : is-active 클래스가
    //                                          있는지 확인
    // 문자열 버전
    // let strArr = popup.className.split(" ");
    // if(strArr.indexOf("is-active") != -1){
    //     // class 있으면
    //     // 문자열 제거해서 클래스를 지울수도 있고.
    // }else{
    //     // class 없으면
    //     popup.className = popup.className + " is-active";
    // }

    // 메소드 사용해서 조건 추가
    if(popup.classList.contains("is-active")){
        // is-active 있으면 제거할거임 ㅎㅎ
        // remove 클래스 제거 메소드
        popup.classList.remove("is-active");
        var chattingRoom = document.querySelector('.popup-content.chattingroom');
        chattingRoom.style.display = 'none';
        
    }else{
        // is-active 없으면 추가할거임
        // add 클래스 추가 메소드
        popup.classList.add("is-active");
    }
}
// 어렵고 힘든게 정상...

function chattingroom(){
    var chattingRoom = document.querySelector('.popup-content.chattingroom');
  chattingRoom.style.display = 'block';
}

function chattingpage(){
    var chattingRoom = document.querySelector('.popup-content.chattingroom');
  chattingRoom.style.display = 'none';
}

function enableInput(){
    let messageElement = document.getElementById("message");
    messageElement.contentEditable = true;
    messageElement.focus();
}



 

.popup-wrap{  /* 브라우저 크기 vw 가로 */  /* 브라우저 크기 vh 세로 */  /* 100vw 보고있는 브라우저 창의 전체 너비 */  /* 100vh 보고있는 브라우저 창의 전체 높이 */  width: 100vw;  height: 100vh;  position: fixed;  display: none;  background-color: rgba(0, 0, 0, 0.5);}

.popup-content.chattingroom{  left: 900px;  display: none;}

두개를 display:none으로 해놓아서 처음에는 화면이 안뜨게 한다.


하지만 .custom-button으로 클릭할수 있는 맨 처음 상하단에 버튼같은게 있는데 
클릭하면 openPopup() 이 실행되서 아래 구문이 실행된다.
<div class="custom-button" onclick="openPopup();"></div>
  <div class="popup-wrap">
    <div class="popup-content">​

function openPopup(){
    let popup =  document.querySelector(".popup-wrap");

    if(popup.classList.contains("is-active")){
        // is-active 있으면 제거할거임 ㅎㅎ
        // remove 클래스 제거 메소드
        popup.classList.remove("is-active");
        var chattingRoom = document.querySelector('.popup-content.chattingroom');
        chattingRoom.style.display = 'none';
        
    }else{
        // is-active 없으면 추가할거임
        // add 클래스 추가 메소드
        popup.classList.add("is-active");
    }
}​

 

팝업창을 열면 containes is-active가 활성화되고 
팝업창을 끄면 remove("is-active)가 활성화되는데 만약 그 이전에 user1이라는 채팅방에 들어가서 팝업창을 더 띄웠을때도 같이 꺼지게 설정해놓았다. 

?? 왜 user를 클릭전에는 popup-content chattingroom이 왜 안보이는지  설명하자면
if (popup.classList.contains("is-active")) {
  // is-active 클래스가 있는 경우
  popup.classList.remove("is-active"); // is-active 클래스 제거
  var chattingRoom = document.querySelector('.popup-content.chattingroom');
  chattingRoom.style.display = 'none'; // 팝업 내용 숨김 처리
} else {
  // is-active 클래스가 없는 경우
  popup.classList.add("is-active"); // is-active 클래스 추가
}​

 

1. 초기 상태에서 popup 요소는 is-active 클래스를 가지고 있지 않으므로 else 블록이 실행되고
2. popup-classList.add("is-active") 코드는 popup 요소에 "is-active" 클래스를 추가한다.
3. 이로 인해 popup요소는 활성화 상태로 변경된다.
4. 그러나 이 단계에서는 chattingRoom 이라는 클래스를 가진 요소가 초기에 display: none 으로 설정되어 있으므로 보이지 않는다.


아래 코드는 chattingroom 부분인데
<div class="imgsize">
        <img
          src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMTExMDFfMjkx%2FMDAxNjM1NzcyNTAyMzM2.cJE1tVC6KDvRbLggbBVEvvTt44ThhLU0wXelkyRh_bgg.ogMtpmeg-v7VIqtsSBpxHCNzt--aP7oHwL3PVm2RgiQg.JPEG.yunalee1997%2F4cc82b04dee244c22d13aee91e4b5e58.jpg&type=sc960_832"
          alt="">
        <p onclick="chattingroom()">User1</p>​
function chattingroom(){
    var chattingRoom = document.querySelector('.popup-content.chattingroom');
  chattingRoom.style.display = 'block';
}
.popup-content.chattingroom{
  left: 900px;
  display: none;
}

user1을 클릭하기 이전에는 display:none으로 설정해 놓아서 안보이는거고 
자바스크립트 부분 queryselector를 활용해서 chattingroom의 요소를 가져온후 (onclick의 요소)
클릭을 하면 chattingRoom.style.display = 'block'으로 설정해놓아서 
클릭하면 user1의 chattingroom 이 보이게 된다.  

 

 

 

😱또 팀프로제트시에

1. 태그 속성의 기본 body나 span div 등등은 css에 적용하지말고

2. class 나 value(가급적 영어로 한글로 해도 되지만) 모두 영어로 해야되는데 특히 class는 무조건 영어로