아코디언 메뉴 플러그인
이 포스팅에서는 아코디언 메뉴타입의 플러그인을 소개합니다.
DEMO View
See the Pen 아코디언 메뉴 플러그인 by jaeheekim (@jaehee) on CodePen.
HTML
html
<div class="menu">
<ul class="accordion">
<li><a href="#menu01">메인메뉴 01</a>
<ul>
<li><a href="#menu01">서브메뉴 01-1</a>
<ul>
<li><a href="#none">01-1-1</a></li>
<li><a href="#none">01-1-2</a></li>
<li><a href="#none">01-1-3</a></li>
<li><a href="#none">01-1-4</a></li>
<li><a href="#none">01-1-5</a></li>
</ul>
</li>
<li><a href="#none">서브메뉴 01-2</a></li>
<li><a href="#menu01">서브메뉴 01-3</a>
<ul>
<li><a href="#none">01-2-1</a></li>
<li><a href="#none">01-2-2</a></li>
<li><a href="#none">01-2-3</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#menu02">메인메뉴 02</a>
<ul>
<li><a href="#menu02">서브메뉴 02-1</a>
<ul>
<li><a href="#none">02-1-1</a></li>
<li><a href="#none">02-1-2</a></li>
<li><a href="#none">02-1-3</a></li>
<li><a href="#none">02-1-4</a></li>
</ul>
</li>
<li><a href="#menu02">서브메뉴 02-2</a>
<ul>
<li><a href="#none">02-2-1</a></li>
<li><a href="#none">02-2-2</a></li>
<li><a href="#none">02-2-3</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#menu03">메인메뉴 03</a>
<ul>
<li><a href="#menu03">서브메뉴 03-1</a>
<ul>
<li><a href="#none">03-1-1</a></li>
<li><a href="#none">03-1-2</a></li>
<li><a href="#none">03-1-3</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#menu02">메인메뉴 04</a>
<ul>
<li><a href="#menu04">서브메뉴 04-1</a>
<ul>
<li><a href="#none">04-1-1</a></li>
<li><a href="#none">04-1-2</a></li>
</ul>
</li>
<li><a href="#menu04">서브메뉴 04-2</a>
<ul>
<li><a href="#none">04-2-1</a></li>
<li><a href="#none">04-2-2</a></li>
<li><a href="#none">04-2-3</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
JavaScript
javascript
(function(global, $){
// 플러그인 네이밍 정의
var pluginName = 'accordion';
function Accordion($selector, options) {
// 플러그인 대상 jQuery 객체 참조
this.$selector = $selector;
// 기본 옵션값과 사용자 정의 옵션값 merge
this.config = $.extend({}, this._defaults, options || {});
//
this.detect = {
children : this.$selector.find(this.config.descendant.ul + ', '+ this.config.descendant.div),
clickTarget : '.' + this.$selector.attr('class') + ' ' + this.config.eventTarget
};
this._init();
}
Accordion.prototype = {
'_defaults' : {
descendant : {
ul : 'ul',
div : 'li > div'
},
dataValue : 'accordiated',
className : 'active',
eventTarget: 'a'
},
'_init' : function () {
// 플러그인을 사용하지 않는 곳에서 실행하지 않기
if(!this.$selector.length) return;
this._menuInit();
this._initEvent();
},
'_menuInit' : function () {
var _self = this;
// 시용자 정의 데이터가 있다면 return
if ( this.$selector.data(this.config.dataValue) ) return false;
$.each(this.detect.children, function () {
var $this = $(this);
_self.$selector.data(_self.config.dataValue, true);
// 모든 서브 메뉴 숨기기
$this.hide();
});
},
'_initEvent' : function () {
// context 유지하기 위한 $.proxy() 정의(this 객체 유지)
$(document).on('click.acc.ck', this.detect.clickTarget, $.proxy(this._activate, this));
// hash 메뉴 열어 놓기
this._hashCheck();
},
'_activate' : function (e) {
// 변경된 context 로 인해 jQuery 객체를 참조
var $this = $(e.target);
$this
.parent('li')
.toggleClass(this.config.className)
.siblings()
.removeClass(this.config.className)
.children(this.config.descendant.ul + ', ' + this.config.descendant.div)
.slideUp('fast');
this._effect($this);
},
'_effect' : function (el, effect) {
$(el)
.siblings(this.config.descendant.ul + ', ' + this.config.descendant.div)[(effect || 'slideToggle')](!effect ? 'fast' : null);
},
'_hashCheck' : function () {
var hash = (location.hash) ? this.$selector.find('a[href="' + location.hash + '"]')[0] : '';
// hash 가 있는 메뉴는 펼쳐 놓기
if(hash) {
this._effect(hash, 'toggle');
if(this.$selector) {
$(hash).parents('ul').show();
}
}
}
};
// 이미 $.fn.accordion 이 있다면 이미 존재하는 $.fn.accordion 을 사용하고
// 그렇지 않다면 현재 사용자 정의된 $.fn.accordion 을 사용하기
$.fn[pluginName] = $.fn[pluginName] || function (options) {
// example : $('.selector').accordion();
// 플러그인을 적용한 대상 노드를 참조
var $this = this; // this 는 jQuery 객체
// 플러그인 재사용을 위해 반복문 사용하기
return $.each($this, function (idx, el) {
var $selector = $this.eq(idx);
// jQuery.data( DOM element, key, value )
// key 값이 없다면 value 에 생성자 함수 호출
if ( !$.data(this, 'plugin_' + pluginName) ) {
$.data(this, 'plugin_' + pluginName, new Accordion($selector, options))
}
// jQuery 체이닝을 위해 jQuery 객체 반환하기
return $selector;
})
};
})(window, window.jQuery);
$(function () {
$('.accordion').accordion();
});
주석 제거용
javascript
(function(global, $){
var pluginName = 'accordion';
function Accordion($selector, options) {
this.$selector = $selector;
this.config = $.extend({}, this._defaults, options || {});
this.detect = {
children : this.$selector.find(this.config.descendant.ul + ', '+ this.config.descendant.div),
clickTarget : '.' + this.$selector.attr('class') + ' ' + this.config.eventTarget
};
this._init();
}
Accordion.prototype = {
'_defaults' : {
descendant : {
ul : 'ul',
div : 'li > div'
},
dataValue : 'accordiated',
className : 'active',
eventTarget: 'a'
},
'_init' : function () {
if(!this.$selector.length) return;
this._menuInit();
this._initEvent();
},
'_menuInit' : function () {
var _self = this;
if ( this.$selector.data(this.config.dataValue) ) return false;
$.each(this.detect.children, function () {
var $this = $(this);
_self.$selector.data(_self.config.dataValue, true);
$this.hide();
});
},
'_initEvent' : function () {
$(document).on('click.acc.ck', this.detect.clickTarget, $.proxy(this._activate, this));
this._hashCheck();
},
'_activate' : function (e) {
var $this = $(e.target);
$this
.parent('li')
.toggleClass(this.config.className)
.siblings()
.removeClass(this.config.className)
.children(this.config.descendant.ul + ', ' + this.config.descendant.div)
.slideUp('fast');
this._effect($this);
},
'_effect' : function (el, effect) {
$(el)
.siblings(this.config.descendant.ul + ', ' + this.config.descendant.div)[(effect || 'slideToggle')](!effect ? 'fast' : null);
},
'_hashCheck' : function () {
var hash = (location.hash) ? this.$selector.find('a[href="' + location.hash + '"]')[0] : '';
if(hash) {
this._effect(hash, 'toggle');
if(this.$selector) {
$(hash).parents('ul').show();
}
}
}
};
$.fn[pluginName] = $.fn[pluginName] || function (options) {
var $this = this;
return $.each($this, function (idx, el) {
var $selector = $this.eq(idx);
if ( !$.data(this, 'plugin_' + pluginName) ) {
$.data(this, 'plugin_' + pluginName, new Accordion($selector, options))
}
return $selector;
})
};
})(window, window.jQuery);
$(function () {
$('.accordion').accordion();
});
Jaehee's WebClub
'Code Lab' 카테고리의 다른 글
thumbnail list banner #2(플러그인 타입) (0) | 2016.09.13 |
---|---|
thumbnail list banner #1 (ver1. 함수형 타입) (0) | 2016.09.12 |
리스트(댓글형) 탭 메뉴 UI (0) | 2016.08.30 |
카드 셔플 애니메이션 (0) | 2016.06.29 |
반응형 아코디언 타입 #2 (0) | 2016.06.21 |