워드프레스 테마 만들기: 사이드 네비게이션 (2)
이전 포스트에서는 네비게이션을 만드는 Walker
를 살펴봤습니다.
종류별로 아이콘 만들기
이제는 종류별로 아이콘을 붙이기 위해 워커의 start_el()
을 개조합니다. Font Awesome 4.7.0를 사용했습니다. Font Awesome의 CDN을 cdnjs에서 찾아 CSS에 추가했습니다.
아이콘은 Font Awesome Icon에서 찾아볼 수 있습니다.
다음 내용을 start_el()
에 추가했습니다.
if ( in_array( 'front-item', $classes ) ) :
if ( in_array( 'menu-item-object-custom' , $classes ) ) :
$item_icon = "fa-link";
elseif ( in_array( 'menu-item-object-post' , $classes ) ) :
$item_icon = "fa-file-text-o";
elseif ( in_array( 'menu-item-object-page' , $classes ) ) :
$item_icon = "fa-file-o";
elseif ( in_array( 'menu-item-object-category' , $classes ) ) :
$item_icon = "fa-list";
endif;
else :
$item_icon = "";
endif;
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
// 아이콘 추가
$item_output .= '<i class="fa ' . $item_icon . '" aria-hidden="true"></i>';
$item_output .= $args->link_before . $title . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
서브메뉴 아코디언으로 만들기
start_el
과 start_lvl
를 손봐서 서브메뉴를 아코디언으로 만드려고 합니다.
아코디언 구조
아코디언 메뉴는 .accordion
클래스 아래에 .accordion-header
와 .accordion-body
를 두어 자바스크립트를 이용해 제어합니다. 제가 만드려고 하는 구조는 대략 이렇습니다.
<ul class="accordion">
<li><a>메뉴 1</a></li>
<li>
<a class="accordion-header">메뉴 2</a>
<ul class="accordion-body">
<li><a>메뉴 2-1</a></li>
<li><a>메뉴 2-2</a></li>
</ul>
</li>
<li>
<a class="accordion-header">메뉴 3</a>
<ul class="accordion-body">
<li><a>메뉴 3-1</a></li>
<li><a>메뉴 3-2</a></li>
</ul>
</li>
</ul>
원래 숨겨져 있는 .accordion-body
는 .accordion-header
를 누르면 펼쳐집니다. .accordion
아래 들어있는 다른 .accordion-body
들은 숨깁니다.
네비게이션 워커
start_lvl
는 .accordion-body
와 .accordion
클래스를 담아둡니다. .accordion
은 서브 메뉴에 있는 하위 아코디언 메뉴를 클릭했을 때 부모 아코디언까지 닫이버리는 오작동을 피하기 위해 추가하기 위한 것 입니다.
<?php
public function start_lvl( &$output, $depth = 0, $args = array() ) {
$classes = array(
'sub-menu',
"sub-menu-$depth",
'accordion-body',
'accordion',
);
$class_names = join( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$output .= "<ul$class_names>";
}
자바스크립트
문서를 로드한 후 .accordion-header
클래스의 요소에 드롭다운 아이콘을 추가합니다. 아이콘은 material icons에서 제공하는 것을 이용했습니다. 이 함수는 jQuery 기반으로 작성되었습니다.
var $document = $(document);
var $accordion_header = $('.accordion-header');
$document.ready(function(){
html = $accordion_header.html();
html += '<i class="accordion-icon material-icons right">arrow_drop_down</i>';
$accordion_header.html(html);
});
이 아이콘은 활성화 되어있을 때 뒤집힙니다. 아코디언 헤더(.accordion-header
)를 눌러 활성화 시키는 경우 해당 요소는 .accordion-active
를 새로 얻도록 클릭 이벤트를 작성할 것입니다. 스타일을 이렇게 작성할 수 있습니다.
.accordion-header .accordion-icon {
transition: transform .4s;
}
.accordion-header.accordion-active .accordion-icon {
transform: rotate(180deg);
}
클릭 이벤트 를 작성합니다.
$accordion_header.click(function() {
var $this = $(this);
var $body = $this.next('.accordion-body');
var $root = $this.closest('.accordion');
var $others = $root.find($accordion_header).not($this);
$others.next('.accordion-body').slideUp(200);
$others.removeClass('accordion-active');
$this.toggleClass('accordion-active');
$body.slideToggle(200);
});
jQuery의 몇 가지 함수를 알아야 이 스크립트를 이해하기 편합니다. 우선 $( A ).next( B )
는 A 선택자 바로 다음에 오는 B선택자 요소를 가져옵니다. $body
의 경우 헤더요소 바로 뒤에 있는 몸통 요소를 불러오게 됩니다. $( A ).closest( B )
은 A요소와 가장 가까운 B 부모를 가져옵니다. $root
는 한 아코디언으로 묶인 헤더와 몸통을 가져오기 위한 것입니다. $( A ).find( B )
는 A를 부모로 가진 B 선택자를 가져옵니다. .not( C )
를 붙이면 선택된 것 중 C를 제외합니다.
이제 동작 부분입니다. 처음, .slideUp(200)
으로 선택한 요소를 제외한 나머지 몸통을 슬라이드 0.2초 동안 애니메이션으로 숨깁니다. 그리고 .accordion-active
클래스가 있다면 제거하죠. 다음에는 toggleClass( A )
를 이용해 A가 있다면 지우고, 없다면 추가하도록 만듭니다. 마지막으로 slideToggle(200)
을 이용해 선택한 요소 바로 다음의 몸통을 열려있으면 닫고 닫혀있으면 열도록 합니다.
결과
실제 동작은 제가 작성한 CodePen에서 확인하실 수 있습니다.