Jquery 새로고침 후 이벤트 - jquery saelogochim hu ibenteu

 <a> 태그가 들어간 요소를 누를 때마다 화면 번쩍번쩍 새로고침 되는 게 열 받아서 스크립트를 찾아봤다.
 나한테 필요해서 박제해둔다.

$('a').click(function(e) {
  e.preventDefault();
});

 잠시 헤맨 게 어이없을 정도로 아주 초간단...😉 웹디자인기능사 시험의 영향으로 이미지건 뭐건 일단 a 태그부터 박고 보는 버릇이 생겼는데, 여러모로 찾아보니까 그게 꼭 필수는 아닌 것 같다. 오히려 불필요하게 남발된 a 태그가 웹페이지 동작에 불편함을 주기도 하고 코딩도 복잡해지고... 아무 생각 없이 넣다가도 이게 왜 필요하지? 싶을 때가 많았다.

 그래도 아직까진 태그 넣고 보는 게 권장사항인가? 몰겠다..... 언젠간 알게 되겠지

Jquery 새로고침 후 이벤트 - jquery saelogochim hu ibenteu
탭메뉴 새로고침 후 현재 탭 유지

페이지를 새로고침을 했을 때 탭 메뉴의 선택했던 탭이 유지되도록 만들었다.

탭을 선택할 때 선택한 컨텐츠 요소의 아이디를 url 뒤에 파라미터로 남기고, 페이지가 로드되었을 때 파라미터 값에 따라 컨텐츠가 보이는 방식이다.

처음엔 해시태그를 추가하는 방식으로 작업했었는데, 페이지가 로드되었을 때 해시태그 값의 아이디를 가진 요소로 자동으로 이동하는 브라우저의 기본 동작을 완벽하게 막기가 어려웠다.

HTML

<div class="tab_wrap">
    <!-- 탭메뉴 제목 -->
    <ul class="tit_list">
        <!-- 디폴트 선택 li에 active 클래스 추가 -->
        <li class="active"><a href="#con01">1번째 탭</a></li>
        <li><a href="#con02">2번째 탭</a></li>
        <li><a href="#con03">3번째 탭</a></li>
    </ul>
    <!-- 탭메뉴 컨텐츠 -->
    <div class="tab_con">
        <div id="con01" class="tab_list">
            1번째 컨텐츠
        </div>
            
        <div id="con02" class="tab_list">
            2번째 컨텐츠
        </div>

        <div id="con03" class="tab_list">
            3번째 컨텐츠
        </div>
    </div>
</div>

.tit_list > li > a 태그에 선택될 컨텐츠의 id 값을 넣었다.

첫 번째 이외의 탭이 먼저 보이고 싶다면, 해당 li 태그에 active 클래스를 추가하면 된다.

CSS

.tab_wrap {max-width: 800px;margin: 50px auto 0;padding: 0 15px;}
.tab_wrap .tit_list {position: relative;font-size: 0;}
.tab_wrap .tit_list:before {content:'';position: absolute;bottom: 0;left: 0;width: 100%;height: 1px;background: #ddd;z-index: 1;}
.tab_wrap .tit_list > li {display: inline-block;vertical-align: top;margin-right: 3px;}
.tab_wrap .tit_list > li a {display: inline-block;padding: 10px 15px;border: 1px solid #fff;border-radius:4px 4px 0 0;font-size: 14px;color: #000;text-decoration: none;}
.tab_wrap .tit_list > li a:hover {background: #efefef;border-color: #efefef;}
.tab_wrap .tit_list > li.active a {position: relative;border-color: #ddd;border-bottom: 1px solid #fff;background: #fff;color: #337ab7;z-index: 2;}
.tab_wrap .tab_con {border: 1px solid #ddd;border-top: none;}
.tab_wrap .tab_con .tab_list {display: none;height: 200px;padding: 15px;}

JS

$(document).ready(function(){
    tab();
})

function tab(){
    //탭메뉴 클릭할 때 실행
    $('.tab_wrap .tit_list > li a').on('click', function(e) {
        e.preventDefault();
    
        //초기화
        $('.tab_wrap .tit_list > li').removeClass('active');
        $('.tab_wrap .tab_list').hide(); 
        
        //실행
        $(this).parent().addClass('active'); 
        var activeTab = $(this).attr('href');
        $(activeTab).show();

        //파라미터 확인
        urlParam =  location.search.substr(location.search.indexOf("?") + 1);
        if(urlParam != ''){
            urlParam = '?' + urlParam;
        }

        //파라미터 변경
        getNewUrl('tabName', urlParam); //(변경·추가할 파라미터 이름, 현재 파라미터)
        function getNewUrl(paramName, oldUrl) {
            var newUrl;
            var urlChk = new RegExp('[?&]'+paramName+'\\s*=');
            var urlChk2 = new RegExp('(?:([?&])'+paramName+'\\s*=[^?&]*)')
            
            
            if (urlChk.test(oldUrl)) { //해당 파라미터가 있을 때
                newUrl = oldUrl.replace(urlChk2, "$1"+paramName+"=" + activeTab.substr(1));
            } else if (/\?/.test(oldUrl)) { //해당 파라미터가 없고 다른 파라미터가 있을 때
                newUrl = oldUrl + "&"+paramName+"=" + activeTab.substr(1);
            } else { //파라미터가 없을 때
                newUrl = oldUrl + "?"+paramName+"=" + activeTab.substr(1);
            }

            history.pushState(null, null, newUrl);
        }
    });

    //파라미터 값 검사
    function getParameter(name) {
        name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
        var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
            results = regex.exec(location.search);
        return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
    }

    var getParam = getParameter('tabName'); //선택한 탭 파라미터
    var loadChk = getParameter('loadChk'); //첫 로드 여부 체크
    
    if(getParam != ''){ //파라미터 값이 있으면 파라미터 값 기준으로 탭메뉴 선택
        $('.tab_wrap .tit_list > li a[href="#'+getParam+'"]').parent().addClass('active'); 
        $('.tab_wrap .tit_list > li a[href="#'+getParam+'"]').trigger('click');

        if(loadChk == 'on'){ //처음 로드되었으면 스크롤 이동
            //탭 위치로 이동
            var tabTop = $('.tab_wrap').offset().top;
            $(window).scrollTop(tabTop - 100);

            //파라미터 확인
            var urlParam =  location.search.substr(location.search.indexOf("?") + 1);
            if(urlParam != ''){
                urlParam = '?' + urlParam;
            }
            
            //loadChk 파라미터 값 변경
            loadChange('loadChk', urlParam);
            function loadChange(paramName, oldUrl) {
                var newUrl;
                var urlChk = new RegExp('[?&]'+paramName+'\\s*=');
                var urlChk2 = new RegExp('(?:([?&])'+paramName+'\\s*=[^?&]*)')
                newUrl = oldUrl.replace(urlChk2, "$1"+paramName+"=off");
                history.pushState(null, null, newUrl);
            }
        }
    }else{ //파라미터 값이 없으면 active 클래스 기준으로 탭메뉴 선택
        var activeChk = 0;
        $('.tab_wrap .tit_list > li').each(function(i) { 
            if ($(this).hasClass('active')){
                $(this).addClass('active'); 
                $(this).find('a').trigger('click');
                activeChk ++
            }
        });

        //active 지정 안했을 시 첫 탭메뉴 선택
        if(activeChk == 0){
            $('.tab_wrap .tit_list > li:first-child a').trigger('click');
        }
    }

    //뒤로가기 탭메뉴 복구
    window.onpopstate = function(event) {
        //초기화
        $('.tab_wrap .tit_list > li').removeClass('active');
        $('.tab_wrap .tab_list').hide(); 
        var getParam2 = getParameter('tabName'); //선택한 탭 파라미터
        
        //탭메뉴 열기
        if(getParam2 != ''){
            $('.tab_wrap .tit_list > li a[href="#'+getParam2+'"]').parent().addClass('active');
            $('#'+getParam2).show()
        }else{
            $('.tab_wrap .tit_list > li:first-child').addClass('active');
            $('.tab_wrap .tab_list:first-of-type').show();
        }
    };
}

탭 메뉴는 모든 컨텐츠 요소를 숨기고 .tit_list > li > a 태그를 클릭했을 때 a 태그의 속성 값 (해시태그)에 따라 해당 id 값을 가진 요소만 보이도록 만들었다.

파라미터 값 검사 및 변경은 URLSearchParams를 사용하면 쉽게 할 수 있는데, 안타깝게도 IE 브라우저에서 지원되지 않는다. IE 점유율 보유 국가로서 짧고 편한 코드는 쓸 수가 없다. ㅡㅅㅡ

그래서 정규식을 활용하여 파라미터 변경 코드를 작성했다. (참고)

파라미터 값은 URL의 '?'를 기준으로 문자열을 잘라 변수에 담았다.

getNewUrl 함수에 파라미터 이름과 현재 파라미터 값을 전달 인자로 담고 호출했다.

getNewUrl 함수가 전달받은 파라미터 값을 검사하고 새로운 값(해시태그)으로 추가 · 변경하는 함수인데, 파라미터를 나열할 때 첫 번째는 '?' 두 번째부터는 '&'가 앞에 포함되기 때문에 각각 예외 처리 작업을 했다.

파라미터 값에 '#'이 포함되면 해시태그로 인식되는지 해당 요소로 이동되어서, '#'을 문자열에서 제거하고 넣었다.

getNewUrl 함수 실행 이후 history.pushState() 메서드를 사용하여 페이지 새로고침 없이 url를 변경했다.

이 메서드는 IE10 버전부터 지원해서 IE 하위 버전까지 고려해야 한다면 주의가 필요하다.

찾아보니 별도의 스크립트를 넣어주면 되는 것 같다. (참고)

페이지가 로드되었을 때 url의 파라미터를 검사하고, 파라미터가 있다면 해당 속성 값을 가진 a 링크에 .trigger() 메서드로 클릭 이벤트를 실행시켰다.

파라미터가 없다면  .tit_list > li 태그에 있는 active 클래스 기준으로 탭을 선택하고, active 클래스가 없다면 자동으로 첫 번째 탭을 선택하도록 만들었다.

++

뒤로가기나 앞으로 가기 버튼을 눌렀을 때 탭메뉴를 다시 선택해주는 코드를 추가했다.

탭메뉴 선택 방식은 동일하다.

[ DEMO ]

++JS (일반 탭 메뉴)

function tab(){
    //탭메뉴 클릭할 때 실행
    $(".tab_wrap .tit_list > li a").on( "click", function(e) {
        e.preventDefault();

        //초기화
        $(".tab_wrap .tit_list > li").removeClass("active");
        $(".tab_wrap .tab_list").hide(); 
        
        //실행
        $(this).parent().addClass("active"); 
        var activeTab = $(this).attr("href");
        $(activeTab).show();
    });

    //초기 탭 설정
    var activeChk = 0;
    $(".tab_wrap .tit_list > li").each(function(i) { 
        if ($(this).hasClass("active")){
            $(this).addClass("active"); 
            $(this).find('a').trigger("click");
            activeChk ++
        }
    });

    //active 지정 안했을 시 첫 탭메뉴 선택
    if(activeChk == 0){
        $(".tab_wrap .tit_list > li:first-child a").trigger("click");
    }
}

파라미터가 추가되지 않는 일반 탭 메뉴 스크립트다. 크게 다른 건 없고 파라미터 관련 스크립트가 삭제된 버전이다.

[ DEMO ]