jQuery를 이용한 쇼핑몰 상품 옵션 동적 선택 및 가격계산
옵션 선택화면에서 옵션을 차례로 선택하는 부분을 간단하게 작업해 봤다. 실제 사이트에 적용하기엔 많이 부족한데.. 이 부분은 차츰 채워나가면 되지 않을까 싶다. 옵션 선택 후 화면은 아래와 같다.
디자인 부분은 아직 고려하지 않은 상태이고 쇼핑몰 솔루션에 어떻게 적용될지는 아직 잘 모르겠다. 그리고 위의 문제라고 해야할까? 모든 옵션을 선택해야하게 돼있는데 이게 맞는건지 아직 잘 모르겠다. 일단 구현에만 신경!!
option.css 파일
#container { width: 400px; margin: 0 auto; }
#container ul { margin: 0; padding: 0; list-style: none; }
#container select { width: 380px; }
#selected-result { display: none; }
#total-price { display: none; }
.option-delete { cursor: pointer; }
.option-price { display: none; }
.item-count input { width: 45px; text-align: right; padding-right: 5px; }
.add-item { cursor: pointer; }
.subtract-item { cursor: pointer; }
option.php 파일
<!doctype html>
<html lang='ko'>
<head>
<title>옵션 select</title>
<meta charset='utf-8' />
<link rel='stylesheet' href='./css/option.css' />
<script src='./js/jquery-1.8.2.min.js'></script>
</head>
<body >
<div id="container">
<span>상품가격 : </span><span id="item-price">20,000원</span>
<ul>
<li>
<select id="option-1" class="more-option" name="option-1">
<option value="">색상선택</option>
<option value="blue">blue</option>
<option value="black">black</option>
<option value="pink">pink</option>
</select>
</li>
<li>
<select id="option-11" name="option-11" disabled="disabled">
<option value="">가로길이선택</option>
<option value="200cm">200cm</option>
<option value="300cm||+500">300cm(+500원)</option>
<option value="400cm||+1000">400cm(+1,000원)</option>
</select>
</li>
<li>
<select id="option-12" name="option-12" disabled="disabled">
<option value="">세로길이선택</option>
<option value="200cm">200cm</option>
<option value="300cm||+500">300cm(+500원)</option>
<option value="400cm||+1000">400cm(+1,000원)</option>
</select>
</li>
<li>
<select id="option-13" class="nomore-option" name="option-13" disabled="disabled">
<option value="">높이선택</option>
<option value="200cm">200cm</option>
<option value="300cm||+500">300cm(+500원)</option>
<option value="400cm||+1000">400cm(+1,000원)</option>
</select>
</li>
</ul>
<ul id="selected-result">
</ul>
<div id="total-price">총 금액 : <span></span></div>
</div>
<script>
$(document).ready(function() {
$('#container li select').change(function() {
if(!$(this).hasClass('nomore-option')) {
var val = $(this).val();
var str = $(this).attr('id').split('-');
var id = str[0] + '-' + str[1].substr(0, 1);
var val = $(this).val();
var idx = $('select[id^=' + id + ']').index($(this));
if(val == '') {
var $el = $('select[id^=' + id + ']:gt(' + idx + ')');
$el.val('');
$el.attr('disabled', true);
} else {
var $el = $('select[id^=' + id + ']:gt(' + idx + ')');
$el.val('');
$el.attr('disabled', true);
$el.each(function() {
if($(this).is(':disabled')) {
$(this).attr('disabled', false);
return false;
}
});
}
}
});
$('#container li select.nomore-option').change(function() {
if($(this).hasClass('nomore-option')) {
var str = $(this).attr('id').split("-");
var id = str[0] + '-' + str[1].substr(0, 1);
optionDisplay(id);
}
});
// 상품개수증가
$('span.add-item').live('click', function() {
var $cntinput = $(this).closest('li').find('input');
var count = parseInt($cntinput.val());
count++;
$cntinput.val(count);
calculatePrice();
});
// 상품개수감소
$('span.subtract-item').live('click', function() {
var $cntinput = $(this).closest('li').find('input');
var count = parseInt($cntinput.val());
count--;
if(count < 1) {
alert('상품개수는 1이상 입력해 주십시오.');
count = 1;
}
$cntinput.val(count);
calculatePrice();
});
// 선택옵션삭제
$('span.option-delete').live('click', function() {
$(this).closest('li').remove();
var resultcount = $('ul#selected-result li').size();
if(resultcount < 1) {
$('ul#selected-result').css('display', 'none');
$('#total-price').css('display', 'none');
}
calculatePrice();
});
});
function optionDisplay(id)
{
var option = "";
var sep = "";
var optionval = "";
var optionprc = "";
var optionprice = "";
var optionid = "";
var optionadd = false;
if($('ul#selected-result').is(':hidden')) {
$('ul#selected-result').css('display', 'block');
$('#total-price').css('display', 'block');
}
$('#container li select[id^=' + id + ']').each(function() {
var str = $(this).val().split('||');
optionval = str[0];
if(str[1] == undefined) {
optionprc = "0";
} else {
optionprc = str[1];
}
optionid = $(this).attr('id');
if(optionval == '') {
optionadd = true;
return false;
}
option += sep + '<span class="selected-' + optionid + '">' + optionval + '</span>';
optionprice += '<span class="price-value">' + optionprc + '</span>';
sep = "/";
});
// 선택된 옵션체크
$('ul#selected-result li span.selected-value').each(function() {
var oldoption = $(this).html();
if(oldoption == option) {
alert('이미 선택된 옵션입니다.');
optionadd = true;
return false;
}
});
if(!optionadd) {
var resultcount = $('ul#selected-result li').size();
var optioncontent = '<li><span class="selected-value">' + option + '</span><span class="option-price">' + optionprice + '</span><span class="item-count"> <input type="text" name="itemcount[]" value="1" /></span><span class="add-item"> + </span><span class="subtract-item"> - </span><span class="option-delete"> 삭제</span></li>';
if(resultcount > 0) {
$('ul#selected-result li:last').after(optioncontent);
} else {
$('ul#selected-result').html(optioncontent);
}
calculatePrice();
}
}
function calculatePrice()
{
var totalprice = 0;
var itemprice = parseInt($('span#item-price').text().replace(/[^0-9]/g, ''));
$('ul#selected-result li').each(function() {
var $prcelmt = $(this).find('.price-value');
var optprc = 0;
var itcnt = parseInt($(this).find('input').val());
$prcelmt.each(function() {
var prc = parseInt($(this).text());
optprc += prc;
});
totalprice += (itemprice + optprc) * itcnt;
});
$('#total-price span').text(number_format(totalprice) + '원');
}
function number_format(input){
var input = String(input);
var reg = /(-?d+)(d{3})($|.d+)/;
if(reg.test(input)){
return input.replace(reg, function(str, p1,p2,p3){
return number_format(p1) + "," + p2 + "" + p3;
}
);
}else{
return input;
}
}
</script>
</body>
</html>
잘쓰겠습니다.
블로그 방문해 주셔서 감사합니다. 좋은 하루 되세요.
올려두신소스로 공부중인데요, 첫번째 색상선택이후 다른옵션들이 움직이지 않아서요 ㅠㅠ 1번째 옵션 change 되면 2번째 옵션이 열리는게 맞지요?
꽤 오래전에 작업했던 소스라서 정확하게 기억은 나지 않지만 그렇게 작동하는 게 맞습니다.
궁금한게 생겼어요~ span 에 금액 텍스트 들어간것을 POST 로 넘길수도 있나요? 자료 찾아보고 있는데 선뜻 나오지를 않네요 ㅠㅠ 따로 input 에 넣어야 할지요?
span의 금액을 post로 넘길 수는 없습니다. input을 따로 넣는 것이 가장 쉬운 방법이라 생각합니다.
php 파일에서 스크립트 시작하는 부분 $(‘#container li select’).change(function() { 여기에서 에러가 발생하는데요. 유효하지 않은 문자입니다<<<라며 에러발생하는데 당최 얻가 잘못된건지 모르겠어요.ㅠㅠ
데이터를 이전하면서 따옴표 부분이 변경됐을 수 있습니다. 새로운 코드로 다시 적용해보시기 바랍니다. 그리고 jQuery 라이브러리도 로드 되는 지 확인해보셔야할 겁니다.
아공..감사합니다. ^^ 말씀하신부분 확인해보았더니 에러사라졌어요~ 보면 볼수록 어려운 것같습니다. ㅠㅠ 공부할길이 먼것 같아요. 잘하려면 어떻게 해야하죠? 노하우좀 알려주세요 ㅠㅠ
문제가 해결되었다니 다행입니다.
특별히 잘하는 노하우가 있지는 않습니다. 저는 실무에서부터 배웠기 때문에 정해진 시간안에 문제를 해결하려다 보니 그만큼 많이 배우게 된 것 같습니다.
기능중에 삭제나 수량+ – 부분이 안되네요.
동적으로 생성되는 부분이라 안되는 거 같은데 해결 방법이 있을까요?
jQuery 1.9 이상의 버전에서는 .live() 를 사용할 수 없습니다.
$(‘span.add-item’).live(‘click’, function() {
를
$(document).on(‘click’, ‘span.add-item’, function() {
로 수정하면 live 와 같은 효과를 나타냅니다.