본문 바로가기
jquery

숙소 인원 설정 해보기

by 다양성 2022. 7. 4.

완성화면

객실별 인원선택
객실 최대 3개 선택

 

  • 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 작동하지 않음.

댓글