완성화면
- ui 설명서
- 객실은 최대 3개까지 선택
- 객실별 성인은 최대 10명 (기본값 1)
- 객실별 아동은 최대 3명 (기본값 0)
html
<body>
<h4>인원 및 객실수</h4>
<div class="container">
<div class="roomunit" data-idx="1">
<div class="roomArea">
<p class="room">객실<span>1</span></p>
</div>
<div class="adultArea">
<dl class="num-remote">
<dt>성인</dt>
<dd>
<span class="num-ctn">
<a href="#" class="btn-base btn-minus">-</a>
<input type="text" readonly value="2" class="active">
<a href="#" class="btn-base btn-plus">+</a>
</span>
</dd>
</dl>
</div>
<div class="childArea">
<dl class="num-remote">
<dt>아동</dt>
<dd>
<span class="num-ctn">
<a href="#" class="btn-base btn-minus inactive">-</a>
<input type="text" readonly value="0" class="active">
<a href="#" class="btn-base btn-plus">+</a>
</span>
</dd>
</dl>
<ul class="age-remote" style="display:none;">
<li>
<select name="child1" id="child1">
<option >나이</option>
<option value="2">2세</option>
<option value="3">3세</option>
<option value="4">4세</option>
<option value="5">5세</option>
</select>
</li>
<li>
<select name="child2" id="child2" disabled>
<option >나이</option>
<option value="2">2세</option>
<option value="3">3세</option>
<option value="4">4세</option>
<option value="5">5세</option>
</select>
</li>
<li>
<select name="child3" id="child3" disabled>
<option >나이</option>
<option value="2">2세</option>
<option value="3">3세</option>
<option value="4">4세</option>
<option value="5">5세</option>
</select>
</li>
</ul>
</div>
</div>
</div>
<button id="roomAdd">객실추가</button>
</body>
css
a{text-decoration: none;}
input[type=text]{border:none;outline: none;width:20px;text-align: center;}
.ally{position:absolute;display:block;width:1px;height: 1px;margin:-1px;padding:0;border:0;overflow: hidden;}
.btn-base{background: #000;display:inline-block; width:20px; height:20px;line-height: 20px; color:#fff;border-radius: 50%;text-align: center;}
.inactive{background: #eee;cursor:auto;}
ul,li{list-style: none;}
li{display: inline-block;}
select,option{padding:4px 5px 2px;}
.roomunit{border:1px solid #eee; padding:0 10px;}
.roomArea{border-bottom: 2px solid #eee;position:relative;}
#roomAdd{margin-top:20px;}
.deleteBtn{position:absolute;right:5px;top:5px; background: #000; color:#fff;}
jquery
<script>
let roomCloneDefault = null; // 기본 객실
let roomCloneIdx =1;
var travelerCounting = {
init : function(){
// 기본 객실 정보 복사
roomCloneDefault = $('.roomunit').clone();
// event 콜백
travelerCounting.event();
},
event : function(){
// 성인 -
$('.adultArea .btn-minus').off('click').on('click',function(e){
e.preventDefault();
let _idx = $(this).closest('.roomunit').attr('data-idx');
const _minus = $('.roomunit').eq(_idx-1).find('.adultArea .btn-minus');
const _input = $('.roomunit').eq(_idx-1).find('.adultArea .active');
let _val = parseInt(_input.val());
_val -=1;
if(_val <= 1){
_input.val(1);
_minus.addClass('inactive');
}else{
_input.val(_val);
}
console.log('성인 -')
});
// 성인 +
$('.adultArea .btn-plus').off('click').on('click',function(e){
e.preventDefault();
let _idx = $(this).closest('.roomunit').attr('data-idx');
const _minus = $('.roomunit').eq(_idx-1).find('.adultArea .btn-minus');
const _input = $('.roomunit').eq(_idx-1).find('.adultArea .active');
const _plus = $('.roomunit').eq(_idx-1).find('.adultArea .btn-plus');
let _val = parseInt(_input.val());
if(_val == 10){
_input.val(_val);
return;
}else if(_val == 1){
_minus.removeClass('inactive');
}
_val +=1;
_input.val(_val);
})
// 아동 -
$('.childArea .btn-minus').off('click').on('click',function(e){
e.preventDefault();
let _idx = $(this).closest('.roomunit').attr('data-idx');
const _minus = $('.roomunit').eq(_idx-1).find('.childArea .btn-minus');
const _input = $('.roomunit').eq(_idx-1).find('.childArea .active');
const _ageArea = $('.roomunit').eq(_idx-1).find('.childArea .age-remote');
let _val = parseInt(_input.val());
_val -=1;
if(!_ageArea.find('select').eq(_val).is(':disabled')){
_ageArea.find('select').eq(_val).attr('disabled',true);
}
if(_val <= 0){
_input.val(0);
_minus.addClass('inactive');
_ageArea.hide();
}else{
_input.val(_val);
}
});
// 아동 +
$('.childArea .btn-plus').off('click').on('click',function(e){
e.preventDefault();
let _idx = $(this).closest('.roomunit').attr('data-idx');
const _minus = $('.roomunit').eq(_idx-1).find('.childArea .btn-minus');
const _input = $('.roomunit').eq(_idx-1).find('.childArea .active');
const _plus = $('.roomunit').eq(_idx-1).find('.childArea .btn-plus');
const _ageArea = $('.roomunit').eq(_idx-1).find('.childArea .age-remote');
let _val = parseInt(_input.val());
if(_val == 3){
_input.val(_val);
return;
}else if(_val == 0){
_minus.removeClass('inactive');
_ageArea.show();
}
if(_ageArea.find('select').eq(_val).is(':disabled')){
_ageArea.find('select').eq(_val).removeAttr('disabled');
}
_val +=1;
_input.val(_val);
})
// 객실추가
$('#roomAdd').off('click').on('click',function(){
travelerCounting.roomCreate();
})
// 객실삭제 event 콜백
$('.deleteBtn').off('click').on('click',function(){
$(this).closest('.roomunit').remove();
roomCloneIdx -= 1;
// 객실추가 버튼 보이기
$('#roomAdd').not(':visible') && $('#roomAdd').show();
})
},
roomCreate : function(){
// 객실복사
const roomClone = roomCloneDefault.clone();
// 삭제버튼 부착
const button = '<button class="deleteBtn">삭제</button>';
roomClone.find('.roomArea').append(button);
// 객실 번호 삽입
roomCloneIdx += 1;
roomClone.attr('data-idx',roomCloneIdx);
roomClone.find('.roomArea .room span').text(roomCloneIdx);
// 인원 초기화
roomClone.find('.adultArea .active').val(1);
roomClone.find('.childArea .btn-minus').addClass('inactive');
roomClone.find('.childArea .active').val(0);
roomClone.find('.childArea select').eq(1).attr('disabled','true');
roomClone.find('.childArea select').eq(2).attr('disabled','true');
roomClone.find('.childArea .age-remote').hide();
// 객실 추가
$('.container').append(roomClone);
// event 콜백
travelerCounting.event();
// 객실 3개면 객실추가 버튼 감추기
if(roomCloneIdx == 3) {
$('#roomAdd').hide();
}
},
}
travelerCounting.init();
</script>
- 어려웠던 점.
- 새 객실을 append할때마다 event 리스너를 call 해 주었더니, event callback이 중복호출 되어, 이를 해결하기 위해 event 리스너를 구현할 때, .off 사용후, on으로 처리하였더니, 해결되었다.
- append 할때, clone은 한번 쓰고, append만 여러번 했었음. 당연히, 1개만 붙지. append 하고 싶은 만큼 clone 하여 이를 해결했다.
- 버튼이 감춰져있는 지 상태확인 하기 위해 .not(' : visible ')을 사용.
- select를 disabled 처리 후, able처리하기위해 해당 removeAttr('disabled') 처리함.
- 남은 문제
- 총 3개의 객실이 있을때, 두번째 객실을 세번째 객실보다 먼저 지우면 event callback 작동하지 않음.
'jquery' 카테고리의 다른 글
모바일) 선택한 탭, 센터로 이동하기 (0) | 2022.06.29 |
---|---|
mCustomScrollbar 사용 (0) | 2022.01.12 |
현재 국내 도시 날씨 알아보기 (jquery) (0) | 2021.01.04 |
gallery 따라 만들기 (0) | 2020.12.25 |
캐러셀 구현 - owl carousel 플러그인 (feat. jquery) (0) | 2020.12.18 |
댓글