소프트웨어/JavaScript • Dhtml

스위칭 탭 & 탭 메뉴

falconer 2007. 4. 24. 18:58
이 포스팅에서 '탭'이라함은 파이어폭스나 IE7에서 쓰이는 탭브라우징의 그 '탭'과 같은 의미이다.
다음 그림을 보면 쉽게 이해가 갈 것이다.

탭이란

Ariticles,Location log,Key Log 같은 것들이

컨텐츠가 표시되는 영역은 모든 탭이 똑 같다.
여러 컨턴츠 레이어들이 겹쳐져 있는 상태에서 선택된 탭에 해당하는 컨텐츠만 사용자에게 보여주는 것이다.

보통 이 탭기능을 웹에 표현하는 방법으로 이미지를 주로 쓴다.
이미지로 표현하는것이 미관상 좋고 만들기도 수월하기 때문인데, CSS 와 javascript 로 구현하는것도 가능하다.
심플한 텍스트 기반 페이지에 탭기능을 추가하고 싶다면 주목!

다음과 같은 탭을 만들어 보겠다.
오늘 이걸 하느라 아침 시간을 다 보냈다....내공부족...
사용자 삽입 이미지

tab1 ~ tab3 까지 총 세개의 탭은 각각 content1 ~ content3 까지 자기만의 컨텐츠를 갖고 있다.
tab을 누르면 활성화된 탭과 컨텐츠 레이어는 배경색이 흰색으로 바뀌고 활성상태에서 비활성 상태로 전환되는 탭은 배경색이 회색으로 바뀐다.

코드를 살펴보도록 하겠다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> Switching Tab </title>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<script type="text/javascript">
<!--
var model = new Array();

function init(){
}
-->
</script>
<style>
.tab{
   width: 50px;
   height: 20px;
   border-top: solid 1px #D9D9D9;
   border-right: solid 1px #D9D9D9;
   border-left: solid 1px #D9D9D9;
   background-color: #EEEEEE;
   position: absolute;
   z-index: 2;
}

#tab1{
   margin-left: 10px;
}

#tab2{
   margin-left: 60px;
}

#tab3{
   margin-left: 110px;
}

.content{
   width: 200px;
   height: 50px;
   border: solid 1px #D9D9D9;
   background-color: #EEEEEE;
   position: absolute;
   top: 19px;
   z-index: 1;
}

#layer1{
   top: 50px;
   left: 50px;
   position: absolute;
}

#layer2{
   top: 50px;
   left: 50px;
   position: absolute;
}

#layer3{
   top: 50px;
   left: 50px;
   position: absolute;
</style>
</head>

<body onload="init()">

<div id="layer1">
   <div id="tab1" class="tab">tab1</div>
   <div class="content">content 1</div>
</div>

<div id="layer2">
   <div id="tab2" class="tab">tab2</div>
   <div class="content">content 2</div>
</div>

<div id="layer3">
   <div id="tab3" class="tab">tab3</div>
   <div class="content">content 3</div>
</div>

</body>
</html>

model은 레이어의 레퍼런스를 담을 배열 객체이다.
매번 각 레이어 객체를 찾아야 하는 불편을 덜기 위해 사용했다.

이제 본격적으로 javascript를 구현해보자.
onload 시에 호출 되는 init() 함수와 그에 따른 몇개의 함수가 필요하다.

function init(){
   var layer1 = document.getElementById('layer1');
   var layer2 = document.getElementById('layer2');
   var layer3 = document.getElementById('layer3');

   model.push(layer1);
   model.push(layer2);
   model.push(layer3);

   for(var i=0,max=model.length; i<max; i++){
       set_event_listener(model[i],'mouseover','switching_tab');
   }

   switch_execute(layer1);
}
init()함수는 각 레이어의 레퍼런스를 배열 model 에 추가하고 이벤트를 걸어준 다음 첫번째 레이어를 활성화 시킨다.


function set_event_listener(obj,evt_type,callback){
   if(window.event){
       obj.attachEvent('on' + evt_type,eval(callback));
   }else{
       obj.addEventListener(evt_type,eval(callback),false);
   }
}
set_event_listener() 함수는 주어진 객체에 evt_type 형식의 이벤트를 걸어준다.


function switching_tab(e){
   var target;

   if(window.event){
       target = window.event.srcElement;
   }else{
       target = e.target;
   }

   switch_execute(target.parentNode);
}
switching_tab() 함수는 이벤트가 발생할때 호출 되며 이벤트가 일어난 객체를 switch_execute 로 보내는 역할을 한다.



function switch_execute(layer){
   var visible_tab_top = -1;
   var hidden_tab_top = 0;

   if(window.navigator.appName.indexOf('Explorer') > -1){
       visible_tab_top++;
       hidden_tab_top++;
   }


   for(var i=0,max=model.length; i<max; i++){
       var tab = get_tab_element(model[i]);
       var content = get_content_element(model[i]);

       if(model[i] == layer){
           model[i].style.zIndex = 99;
           tab.style.top = visible_tab_top;
           tab.style.backgroundColor = '#FFFFFF';
           content.style.backgroundColor = '#FFFFFF';
       }else{
           model[i].style.zIndex = 0;
           tab.style.top = hidden_tab_top;
           tab.style.backgroundColor = '#EEEEEE';
           content.style.backgroundColor = '#EEEEEE';
       }
   }
}
switch_execute() 함수는 주어진 레이어를 활성화 시키고 나머지 레이어를 비활성화 시키는 일을 한다.
visible_tab_top과 hidden_tab_top 값을 브라우져에 따라 달리한 이유는 IE와 Mozila 계열의 렌더링 방식의 차이때문이다.
기본값은 FF를 위한 값이다.
만약 위와 같은 처리를 생략했을 경우 IE에서 는 활성화 된 탭과 그에 해당하는 컨텐츠 레이어 사이의 경계선이 그대로 남게 되고 FF에서는 탭의 좌우 경계선이 컨텐츠 레이어 안으로 비집고 들어오는 모습을 보게 될 것이다.


function get_tab_element(model){
   var child = model.childNodes;

   for(var i=0,max=child.length; i<max; i++){
       if(child[i].nodeType == 1 && child[i].className == 'tab'){
           return child[i];
       }
   }
}

function get_content_element(model){
   var child = model.childNodes;

   for(var i=0,max=child.length; i<max; i++){
       if(child[i].nodeType == 1 && child[i].className == 'content'){
           return child[i];
       }
   }
}

위 두 함수는 레이어에서 탭과 컨텐츠 영역을 추출하는 용도로 쓰인다.
역시 IE와 FF의 차이가 있기 때문에 firstChild, lastChild 를 쓰지 않았다.
속도가 느려지는 일이 발생한다면 위 두함수를 하나로 묶어서 반복문을 하나로 축약해야 할 것이다.
별로 그럴일은 없을것 같지만...


출처 : http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=53583&page=1

소스 :