쇼피파이_5

김종민·2025년 2월 21일

쇼피파이

목록 보기
5/6
post-thumbnail

상세페이지 내 측면 옵션창 구현정리

카페24에서는 자주 볼 수 있는 상세페이지 내에서 스크롤을 내렸을 때!
옵션창이 노출되는 기능을 적용하여서 해당 코드를 기록하기 위함으로 글을 써내려간다!
작업하기에 앞서, gsap 라이브러리를 사용할 것이기에 cdn추가 하는거 잊지말긔



// header.liquid에 셋팅
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>

<html>
	<div class="option-area">
      <button class="close-btn">X</button>
      <div class="option-wrap">
          <div class="option-top">
              <span class="title">Option</span>
              <div class="select-box">
                  <button class="select-btn">Please Select Additional Product Option</button>
                  <ul class="select-list">
                  </ul>
              </div>
          </div>
          <div class="option-bot">
              <span class="together">Good to use together</span>
              <div class="img-wrap">
                <a href=""><img src="" alt="Product Image"></a>
              </div>
              <div class="text-wrap">
                  <span class="sub-title">Intimate Care Gel for Women</span>
                  <div class="select-box">
                    <button class="select-btn">Please Select Additional Product Option</button>
                    <ul class="select-list">
                    </ul>
                </div>
                <div class="option-box">
                    <button class="minus-btn">
                      <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" class="icon icon-minus" fill="none" viewBox="0 0 10 2">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M.5 1C.5.7.7.5 1 .5h8a.5.5 0 110 1H1A.5.5 0 01.5 1z" fill="currentColor">
                      </path></svg>
                    </button>
                    <span class="option-num">1</span>
                    <button class="plus-btn">
                      <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" class="icon icon-plus" fill="none" viewBox="0 0 10 10">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M1 4.51a.5.5 0 000 1h3.5l.01 3.5a.5.5 0 001-.01V5.5l3.5-.01a.5.5 0 00-.01-1H5.5L5.49.99a.5.5 0 00-1 .01v3.5l-3.5.01H1z" fill="currentColor">
                      </path></svg>
                    </button>
                </div>
              </div>
          </div>
      </div>
      <div class="select_item">
        <ul>
          <li class="defalut_pd">
            <p class="fs16 item_info">
              <strong>Product Name</strong>
              <span class="fs14">option</span>
            </p>
            <p class="fs16 item_price">Price</p>
          </li>
          <li class="add_pd">
            <p class="fs16 item_info">
              <strong>Product Name</strong>
              <span class="fs14">option</span>
            </p>
            <p class="fs16 item_price">Price</p>
          </li>
          <li class="add_pd_set">
            <p class="fs16 item_info">
              <strong>Product Name</strong>
              <span class="fs14">option</span>
            </p>
            <p class="fs16 item_price">Price</p>
          </li>
        </ul>
      </div>
      <div class="price-wrap">
          <div class="price-top">
              <div class="price-box">
                  <span class="total">Subtotal:</span>
                  <div class="current">
                      <span class="price">$0</span>
                      <!--span class="num">(1)</span-->
                  </div>
              </div>
          </div>
          <div class="price-bot">
              <button class="add-btn">Add to cart</button>
              <!--button class="buy-btn">Buy now</button-->
          </div>
      </div>
  </div>
</html>
<script>
$(function(){  
     //option창 셋트상품 일 경우 옵션 버튼 변경
    $('.option-wrap .option-bot .select-btn').click(function() {
      let optionUl = $(this).siblings('ul');
      
      let orifinish = parseFloat($('.color-background-1 .product-form__buttons span'));
      $('.color-background-1 .product-form__buttons span.fs16').text(orifinish);

      // relfinish 값을 strong 요소에 넣기
      let relfinish = parseFloat($('.color-background-1 .product-form__buttons strong'));
      $('.color-background-1 .product-form__buttons strong').text(relfinish);
      
      if (optionUl.length > 0 && optionUl.find('li').length === 0) {
        $(this).hide();
        $('.option-wrap .option-bot .option-box').addClass('on')
      }
    });
  
    $('.minus-btn').click(function() {
      let currentNum = parseInt($('.option-num').text());
      if (currentNum > 1) {
        currentNum--;
        $('.option-num').text(currentNum); 
      }
    });
  
    $('.plus-btn').click(function() {
      let currentNum = parseInt($('.option-num').text());
      currentNum++;
      $('.option-num').text(currentNum); 
    });

    $('.minus-btn').click(function() {
      $('.color-background-1 .quantity__button[name="minus"]').trigger('click');
    });
    $('.plus-btn').click(function() {
      $('.color-background-1 .quantity__button[name="plus"]').trigger('click');
    });


  
  // optValue 초기화 및 값 설정
  let optValue = parseInt($('.option-wrap .option-bot .option-box .option-num').text());
  
  $('.option-wrap .option-bot .option-box .minus-btn').on('click', function() {
      optValue = Math.max(1, optValue - 1); // 최소값 1으로 제한
      updateOptValueAndLog();
  });
  
  $('.option-wrap .option-bot .option-box .plus-btn').on('click', function() {
      optValue += 1;
      updateOptValueAndLog();
  });

// 초기값 설정 및 버튼 클릭 시 업데이트 함수
function updateOptValueAndLog() {
    $('.option-wrap .option-bot .option-box .option-num').text(optValue);
    console.log('Updated optValue: ' + optValue);
    
    // oriValue, relValue, orifinish, relfinish 값 업데이트
    // let oriValue = parseFloat($('.color-background-1 .price__sale #orign_p').text());
    // let relValue = parseFloat($('.color-background-1 .price__sale #real_p').text());
    // let orifinish = parseFloat($('.color-background-1 .product-form__buttons span').text());
    // let relfinish = parseFloat($('.color-background-1 .product-form__buttons strong').text());

  // id가 'orign_p'인 <s> 태그의 텍스트 내용 가져오기
  let oriValue = $('.color-background-1 .price__sale #orign_p').text().trim(); 
  let relValue = $('.color-background-1 .price__sale #real_p').text().trim(); 
  let orifinish = $('.color-background-1 .product-form__buttons span').text().trim(); 
  let relfinish = $('.color-background-1 .product-form__buttons strong').text().trim(); 

 let numberValue = parseFloat(oriValue.replace(/[^\d.]/g, ''));
  
  console.log(numberValue); // 숫자 값 출력

  
    let oriMulti = oriValue * optValue; // oriValue와 optValue를 곱해서 oriMulti 계산
    let relMulti = relValue * optValue; // relValue와 optValue를 곱해서 relMulti 계산
    console.log('oriValue: ' + oriValue);
    console.log('relValue: ' + relValue);
    console.log('orifinish: ' + orifinish);
    console.log('relfinish: ' + relfinish);
    // console.log('oriMulti: ' + oriMulti);
    // console.log('relMulti: ' + relMulti);
    
    // orifinish, relfinish 업데이트 및 로그 출력
    $('.color-background-1 .product-form__buttons span.fs16').attr('rel', oriMulti);
    $('.color-background-1 .product-form__buttons strong').attr('rel', relMulti);
  
    $('.color-background-1 .product-form__buttons span.fs16').text(orifinish); // span 요소에 oriMulti 값을 텍스트로 업데이트
    $('.color-background-1 .product-form__buttons strong').text(relfinish); // strong 요소에 relMulti 값을 텍스트로 업데이트
    console.log('Updated orifinish: ' + oriMulti);
    console.log('Updated relfinish: ' + relMulti);
}
  
  $('.option-area .close-btn').click(function(){
    $('.option-area').hide();
  })
  
  $('.select_item ul li').hide();
  
  for(var i=1; i <= $('.product:not(.featured-product) variant-radios label').length; i++){
    var pdOptlabel = $('.product:not(.featured-product) variant-radios label:nth-of-type('+i+')').attr('for');
    var pdOptText = $('.product:not(.featured-product) variant-radios label:nth-of-type('+i+') p strong').text();
    var pdOptPrice = $('.product:not(.featured-product) variant-radios label:nth-of-type('+i+') > strong').attr('rel');
    var pdOptVaild = $('.product:not(.featured-product) variant-radios label:nth-of-type('+i+') > strong').attr('valid');
    $('.option-wrap .option-top .select-list').append('<li class="select-item" rel="'+pdOptPrice+'" vaild_rel="'+pdOptVaild+'"><label for="'+pdOptlabel+'"><button>'+pdOptText+'</button></label></li>');   
  }
  
  $('.option-wrap .option-top .select-list li').click(function(){
    $(this).addClass('on').siblings().removeClass('on');
    $('.option-wrap .option-top .select-btn').text($(this).find('button').text()).removeClass('on');
    $('.option-wrap .option-top .select-list').slideUp();
    $('.select_item ul li.defalut_pd').attr('rel',($(this).attr('vaild_rel'))).show();
    $('.select_item ul li.defalut_pd .item_info strong').text($('.product:not(.featured-product) .product__info-wrapper .product__title h1').text());
    $('.select_item ul li.defalut_pd .item_info span').text($(this).find('button').text());
    $('.select_item ul li.defalut_pd .item_price').text($(this).attr('rel'));
  })

  if($('.section-featured-product').length > 0){    
    $('.section-featured-product').hide();
    $('.option-wrap .option-bot .img-wrap a').html($('.section-featured-product .product-media-container.constrain-height .media').html());
    $('.option-wrap .option-bot .img-wrap a').attr('href', $('.section-featured-product .product__view-details').attr('href'));
    $('.option-wrap .option-bot .text-wrap .sub-title').text($('.section-featured-product .product__text.caption-with-letter-spacing+.product__title').text());    
  }else{
    $('.option-wrap .option-bot').hide();
  }

  for(var j=1; j <= $('.section-featured-product variant-radios label').length; j++){
    var pdOptlabel_f = $('.section-featured-product variant-radios label:nth-of-type('+j+')').attr('for');
    var pdOptText_f = $('.section-featured-product variant-radios label:nth-of-type('+j+') p strong').text();
    var pdOptPrice_f = $('.section-featured-product variant-radios label:nth-of-type('+j+') > strong').attr('rel');
    var pdOptVaild_f = $('.section-featured-product variant-radios label:nth-of-type('+j+') > strong').attr('valid');
    $('.option-wrap .option-bot .select-list').append('<li class="select-item" rel="'+pdOptPrice_f+'" vaild_rel="'+pdOptVaild_f+'"><label for="'+pdOptlabel_f+'"><button>'+pdOptText_f+'</button></label></li>')
  }
  
  $('.option-wrap .option-bot .select-list li').click(function(){
    var opt_bot_idx = $(this).index() + 1;
    $(this).addClass('on').siblings().removeClass('on');
    $('.section-featured-product variant-radios label:nth-of-type('+opt_bot_idx+')').trigger('click');    
    $('.option-wrap .option-bot .select-btn').text($(this).find('button').text()).removeClass('on');
    $('.option-wrap .option-bot .select-list').slideUp();    
    $('.select_item ul li.add_pd').attr('rel',($(this).attr('vaild_rel'))).show();
    $('.select_item ul li.add_pd .item_info strong').text($('.option-wrap .option-bot .text-wrap .sub-title').text());
    $('.select_item ul li.add_pd .item_info span').text($(this).find('button').text());
    $('.select_item ul li.add_pd .item_price').text($(this).attr('rel'));
  })

  $('.option-wrap .option-bot .option-box button').click(function(){
    cosole.log('ddd');
    // var opt_num_idx = $(this).index() + 1;
    // $(this).addClass('on').siblings().removeClass('on');
    // $('.section-featured-product variant-radios label:nth-of-type('+opt_bot_idx+')').trigger('click');    
    // $('.option-wrap .option-bot .select-btn').text($(this).find('button').text()).removeClass('on');
    // $('.option-wrap .option-bot .select-list').slideUp();    
    // $('.select_item ul li.add_pd').attr('rel',($(this).attr('vaild_rel'))).show();
    // $('.select_item ul li.add_pd .item_info strong').text($('.option-wrap .option-bot .text-wrap .sub-title').text());
    // $('.select_item ul li.add_pd .item_info span').text($(this).find('button').text());
    // $('.select_item ul li.add_pd .item_price').text($(this).attr('rel'));
  })

  setInterval(function(){
    var regexp = /\B(?=(\d{3})+(?!\d))/g;
    var add_price = Number.isNaN(Number($('.select_item ul li.add_pd .item_price').text().replace('$','').replace(/,/g, ""))) ? 0 : Number($('.select_item ul li.add_pd .item_price').text().replace('$','').replace(/,/g, ""));
    var def_price = Number.isNaN(Number($('.select_item ul li.defalut_pd .item_price').text().replace('$','').replace(/,/g, ""))) ? 0 : Number($('.select_item ul li.defalut_pd .item_price').text().replace('$','').replace(/,/g, ""));
    var fin_price = Number.isNaN(((def_price + add_price)).toFixed(2).toString().replace(regexp, ',')) ? 0 : ((def_price + add_price)).toFixed(2).toString().replace(regexp, ',');      
    $('.price-wrap .current .price').text('$'+fin_price);    
    $('.price-wrap .price-bot .add-btn').attr('data-def',$('.select_item ul li.defalut_pd').attr('rel')) ;  
    $('.price-wrap .price-bot .add-btn').attr('data-add',$('.select_item ul li.add_pd').attr('rel')) ;    
  },1000)

  $('.price-wrap .price-bot .add-btn').click(function(){
    if($(this).attr('data-def') && $(this).attr('data-add')){
      window.location.href = '/cart/add?id[]='+$(this).attr('data-def')+'&amp;id[]='+$(this).attr('data-add'); 
    }else if($(this).attr('data-add')){
      window.location.href = '/cart/add?id[]='+$(this).attr('data-add');      
    }else if($(this).attr('data-def')){      
      window.location.href = '/cart/add?id[]='+$(this).attr('data-def');
    }
  })

  
})
  
</script>

css는 빼먹으면 섭섭하니까 추가🤭

<style>

button {
  border: none;
  background: none;
  padding: 0;
  margin: 0;
  cursor:pointer;
}

.more,.close{
  cursor:pointer;
}

.product_desc{
  position:relative;
}

.option-area{
    display: flex;
    position: fixed;
    justify-content: space-between;
    align-items: center;
    top: 72px;
    right: 0;
    flex-direction: column;
    max-width:400px;
    width: 20vw;
    max-height: 690px;
    background: #f4fbff;
    padding: 40px;
    z-index:10;
    opacity: 0;
    visibility: hidden;
    overflow-y:scroll !important;
}
.close-btn{
  position:absolute;
  top:10px;
  right:10px;
  font-size:25px;
}

.option-wrap{
    display: flex;
    flex-direction: column;
    width:100%;
    gap:50px;
}

.option-wrap .option-top{display:flex;flex-direction:column;gap:30px;}
.option-wrap .option-top .title{font-size:36px;letter-spacing:1.08px;color:#0d0d0d;margin:0 !important;}

.option-wrap .select-item{border-top: 1px solid #ccc; padding: 10px 75px 10px 16px;background: #fff;width: 100%;height: 100%;}
.option-wrap .select-btn{display:flex;justify-content:flex-start;align-items:center;color:#888;width:100%; height:50px;background:#fff;border-radius:10px;border:solid 1px #ccc;padding:10px;transition:1s;}
.option-wrap .select-btn.on{border-radius:10px 10px 0 0;}
.option-wrap .select-list{display: none;width: 100%;max-height: 160px;overflow-y:scroll;border:solid 1px #ccc;border-radius:0px 0px 10px 10px;border-top:none;}
.option-wrap .select-item:first-child{border:none;}
.option-wrap .select-item:last-child{border-radius:0px 0px 10px 10px;}
.option-wrap .select-item button{display:block;text-align:left;width:100%;cursor:pointer;transition:.3s;}
.option-wrap .select-item button:hover{color:#5cb6e1;}

.option-wrap .option-bot{display:flex;flex-direction:column;gap:10px;padding-bottom:50px;border-bottom:1px solid #888;}
.option-wrap .option-bot .img-wrap{width:80px;height:100px;background:#fff;border-radius:10px;overflow:hidden;}
.option-wrap .option-bot img{width:100%;height:100%;object-fit:cover;}
.option-wrap .option-bot .together{font-size:15px;letter-spacing:-0.3px;color:#fff;width:155px;text-align:center;height:auto;background:#0877af;padding:5px 10px;border-radius:20px;}
.option-wrap .option-bot .text-wrap{display:flex;flex-direction:column;gap:10px;}
.option-wrap .option-bot .text-wrap .sub-title{font-size:16px; line-height:21px;letter-spacing:-0.32px;color:#000;font-weight:900;}

.option-wrap .option-bot .option-box{display:none;align-items:center;justify-content:space-between;width:100%;height:50px;background:#fff;border-radius:10px;border:solid 1px #ccc;}
.option-wrap .option-bot .option-box.on{display:flex;}
.option-wrap .option-bot .option-box button{display:flex;justify-content:center;align-items:center;}
.option-wrap .option-bot .option-box button svg{width:20%;}
.option-wrap .option-bot .option-box .minus-btn{width:30%;height:70%;text-align:center;border-right:1px solid #ccc;}
.option-wrap .option-bot .option-box .plus-btn{width:30%;height:70%;text-align:center;border-left:1px solid #ccc;}
.option-wrap .option-bot .option-box .option-num{width:40%;text-align:center;font-size:20px;}

.price-wrap{display:flex;flex-direction:column;width:100%;}
.price-wrap .price-top{padding:10px 0 20px;}
.price-wrap .price-box{display:flex;align-items:center;justify-content:space-between;}
.price-wrap .total{font-size:18px;font-weight:900;}
.price-wrap .current{display:flex;flex-direction:column;align-items:flex-end;}
.price-wrap .current .price{font-size:35px;}
.price-wrap .current .num{font-size:20px;}

.price-wrap .price-bot{display:flex;flex-direction:column;gap:10px;}
.price-wrap .price-bot button{border:1px solid #888;border-radius:25px;padding:10px;font-size:22px;font-weight:900;letter-spacing:-0.44px}
.price-wrap .price-bot .add-btn{background:#fff;}
.price-wrap .price-bot .buy-btn{background:#000;color:#fff;}

.product_desc{display:flex;flex-direction:column;align-items:center;width:100%;position:relative;}
.product_desc p{max-width:900px;}
.product_desc p img{width:100%;}
.product_desc .more{display:flex;justify-content:center;align-items:center;width:900px;height:96px;background:#0085cb;color:#fff;position:relative;gap:50px;font-size:26pt;transition:.3s;}
.product_desc .more:after{content:'';position:relative;width:47px;height:47px;background:url(https://cdn.zeplin.io/641bb2343b418f35db3d8f64/assets/050F16BD-8974-486E-84F2-3C010F25C47B.svg) no-repeat center/100%;}
.product_desc .close{display:flex;justify-content:center;align-items:center;width:900px;height:96px;background:#0085cb;color:#fff;position:relative;gap:50px;font-size:26pt;transition:.3s;}
.product_desc .close:after{content:'';position:relative;transform:rotate(180deg);width:47px;height:47px;background:url(https://cdn.zeplin.io/641bb2343b418f35db3d8f64/assets/050F16BD-8974-486E-84F2-3C010F25C47B.svg) no-repeat center/100%;}

.select_item{display:block; width:100%;}
.select_item ul li:not(:first-child){border-top:1px solid var(--black5);}
.select_item ul li{display:flex; align-items:center; justify-content:space-between; padding:12px 0;}
.select_item ul li .item_info strong{display:block; margin-bottom:3px;}
.select_item ul li .item_info span{color:var(--black3);}
.select_item ul li .item_price{color:var(--main1);}

@media all and (max-width:990px){
  .option-area{display:none;}
  .product_desc .more{width:100% !important;font-size:19px;gap:20px;}
  .product_desc .more:after{width:30px;height:30px;}
  .product_desc .close{width:100% !important;font-size:19px;gap:20px;}
  .product_desc .close:after{width:30px;height:30px;}
}
  
</style>
profile
웹 퍼블리셔의 코딩 일기

0개의 댓글