1단 메뉴 제이쿼리 스터디 단계별 학습 #1
이 글에서는 제이쿼리 그리고 자바스크립트의 생성자함수 및 프로토타입을 이용하여 심플한 1단 메뉴를 구현해 보는 시간을 가져보겠습니다.
다음 단계별 학습 #2를 통해서는 이 1단 메뉴를 플러그인 타입으로 리팩토링해 보도록 하겠습니다.
HTML
간단한 1단 메뉴를 위해 다음과 같은 마크업을 작성합니다.
html
<div class="bar-menu" id="barMenu1">
<ul class="menu-body">
<li>MENU 01</li>
<li>MENU 02</li>
<li>MENU 03</li>
<li>MENU 04</li>
<li>MENU 05</li>
</ul>
<div class="bar"> </div>
</div>
CSS
1단 메뉴에 대한 스타일시트는 다음과 같이 준비합니다.
css
* { padding:0; margin:0; }
body{ font-size:9pt; }
#barMenu1 { position:relative; left:100px; top:100px; width:450px; overflow: hidden; }
.bar-menu { position:relative; height:50px; cursor:pointer; }
.bar-menu ul.menu-body { position:relative; list-style: none; height:100%; }
.bar-menu ul.menu-body li {
height:20px; padding:10px; margin-left:10px; float:left;
line-height:20px; vertical-align:middle; border:2px solid #93b0bc;
display:inline-block; border-radius: 10px;
}
/* 선택 메뉴 아이템 스타일 */
.bar-menu ul.menu-body li.select { background-color: #bddeea; }
/* 오버 메뉴 아이템 스타일 */
.bar-menu ul.menu-body li.over { background-color:#eee; }
.bar-menu .bar { width:0; height:5px; background-color: #468ebc; position: absolute; left:0; bottom:0; }
JavaScript
다음의 코드에는 사용자 이벤트를 정의하는 방법을 포함하고 있습니다.
콘솔창에서 그 결과를 확인하실 수 있습니다.
javascript
function BarMenu(selector) {
// 프로퍼티 생성
this.$barMenu = null;
this._$menuBody = null;
this._$menuItems = null;
this._$overItem = null;
this._$bar = null;
// 선택 메뉴 아이템
this.$selectItem = null;
this._init(selector);
this._initEvent();
}
BarMenu.prototype = {
// 요소 초기화
"_init" : function (selector) {
this.$barMenu = $(selector);
this._$menuBody = this.$barMenu.find('.menu-body');
this._$menuItems = this._$menuBody.find('li');
this._$bar = this.$barMenu.find('.bar');
},
// 이벤트 초기화
"_initEvent" : function () {
var _self = this;
// 오버 메뉴 및 선택(클릭한)메뉴 이벤트 호출
this._$menuItems.on('mouseenter click', function (e) {
var $this = $(this);
if(e.type == 'mouseenter') {
_self._setOverMenuItem($this);
} else if(e.type == 'click') {
_self.setSelectMenuItem($this);
}
});
// 전체 메뉴 영역을 벗어난 경우
this.$barMenu.on('mouseleave', function () {
var $this = $(this);
// 기존 오버 메뉴아이템이 있는 경우 제거
_self._removeOverItem($this);
// 기존 선택한 메뉴아이템이 있는 경우 선택처리
_self._reSelectMenuItem();
});
},
// 오버 메뉴아이템 처리하기
"_setOverMenuItem" : function ($item) {
// 기존 오버되어 있는 아이템이 있다면 over 스타일을 제거
if(this._$overItem) {
this._$overItem.removeClass('over');
}
// 신규 오버 메뉴아이템이 선택한 메뉴아이템과 같지 않은 경우에만 메뉴아이템 스타일 적용하기
// 선택 메뉴 아이템 인덱스 값 구하기
var selectIndex = -1;
if (this.$selectItem != null) {
selectIndex = this.$selectItem.index();
}
// 신규 오버 메뉴아이템 인덱스 값과 선택한 메뉴아이템의 인덱스 값을 비교
if ($item.index() != selectIndex) {
this._$overItem = $item;
this._$overItem.addClass('over');
} else {
this._$overItem = null;
}
// 메뉴바 이동
this._moveBar($item);
},
// 전체 메뉴 영역 벗어날 때 오버 효과 제거
"_removeOverItem" : function () {
if(this._$overItem) {
this._$overItem.removeClass('over');
}
this._$overItem = null;
this._moveBar(null);
},
// 이동 메뉴 효과
"_moveBar" : function ($item, animation) {
var left = -100,
width = 0;
if ($item != null) {
left = $item.position(true).left + parseInt($item.css('margin-left'));
width = $item.outerWidth();
}
if(animation == false) {
// 애니메이션 없이 바로 이동
this._$bar.css({
'left': left,
'width' : width
})
} else {
// 애니메이션 이동
this._$bar
.stop()
.animate({
'left': left,
'width': width
}, 300)
}
},
// 선택(클릭) 메뉴 아이템 처리
'setSelectMenuItem' : function ($item, aniamtion) {
var $oldItem = this.$selectItem;
// 기존에 선택한 메뉴가 있는 경우 처리
if(this.$selectItem) {
this.$selectItem.removeClass('select');
}
this.$selectItem = $item;
this.$selectItem.addClass('select');
// 메뉴바 이동
this._moveBar($item, aniamtion);
// 사용자 정의 이벤트 발생(호출)
this._dispatchSelectEvent($oldItem, $item);
},
// 기존 선택한 메뉴아이템이 있는 경우 선택 처리
"_reSelectMenuItem" : function () {
if(this.$selectItem) {
this._moveBar(this.$selectItem);
}
},
// 메뉴아이템이 선택된 상태에서 시작하도록 설정하는 경우
'setSelectMenuItemAt' : function (index, animation) {
var target = this._$menuItems.eq(index);
this.setSelectMenuItem(target, animation);
},
// 사용자 정의 이벤트 발생
"_dispatchSelectEvent" : function ($oldItem, $newItem) {
var customEvent = jQuery.Event('selected');
customEvent.$oldItem = $oldItem;
customEvent.$newItem = $newItem;
this.$barMenu.trigger(customEvent);
}
};
$(function () {
var barMenu = new BarMenu('#barMenu1');
// 메뉴아이템 선택 설정
barMenu.setSelectMenuItemAt(2, false);
// 사용자 정의 이벤트
// 위에서 정의한 select 이벤트 리스너 등록하기
barMenu.$barMenu.on('selected', function (e) {
var oldIndex = -1;
if (e.$oldItem) {
oldIndex = e.$oldItem.index();
}
console.log('old = ' + oldIndex + ', new = ' + e.$newItem.index());
});
});
Result View
See the Pen 1단메뉴 #1 by jaeheekim (@jaehee) on CodePen.
Related Info
- 1단 메뉴(플러그인 타입) - 단계별 학습 #2
Jaehee's WebClub
'Code Lab' 카테고리의 다른 글
메뉴 슬라이딩 효과 (0) | 2016.06.17 |
---|---|
1단 메뉴 jQuery Study #2 (0) | 2016.06.15 |
simple tab menu (0) | 2016.06.13 |
jQuery 사용자 유틸리티 - 세자릿수 콤마 찍어보기 (0) | 2016.06.02 |
match box height (같은 박스 높이값을 설정하는 스크립트) (0) | 2016.05.29 |