참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.
- 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
- 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
- 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
/* All JavaScript here will be loaded for users of the MinervaNeue skin */
/* 가온 위키 Minerva Neue 전용 커스텀 메뉴
* - PC/모바일 공통
* - Minerva 기본 메뉴와 같은 구조/클래스 사용
* (toggle-list__list / toggle-list-item / toggle-list-item__anchor /
* minerva-icon / toggle-list-item__label)
* - 상위 그룹(게시판, 버그/기능 개선, 도구, 도움말)은 접고 펼칠 수 있음
* - "파일 올리기" 아래에 3단계 메뉴 포함
*/
( function ( mw, $ ) {
'use strict';
// Minerva 스킨이 아닐 때는 아무 것도 하지 않는다.
if ( mw.config.get( 'skin' ) !== 'minerva' ) {
return;
}
/* -------------------------------------------------
* 1. 메뉴 설정 (질문에서 주신 내용을 JS 객체로 변환)
* ------------------------------------------------- */
// icon 필드에는 Minerva 메뉴에서 사용하는
// `minerva-icon minerva-icon--XXX` 의 XXX 부분만 넣는다.
// 예: icon: 'minerva-icon--speechBubbles'
var gaonMenuConfig = [
{
// 게시판 그룹
label: '게시판',
icon: 'minerva-icon--speechBubbles',
children: [
{
label: '위키방',
href: 'https://bbs.gaonwiki.com',
title: 'https://bbs.gaonwiki.com',
icon: 'minerva-icon--speechBubbles'
},
{
label: '저작권 처리 게시판',
href: 'https://bbs.gaonwiki.com/copyrights',
title: 'https://bbs.gaonwiki.com/copyrights',
icon: 'minerva-icon--speechBubbles'
},
{
label: '자유게시판',
href: 'https://bbs.gaonwiki.com/free',
title: 'https://bbs.gaonwiki.com/free',
icon: 'minerva-icon--speechBubbles'
}
]
},
{
// 버그/기능 개선 그룹
label: '버그/기능 개선',
icon: 'minerva-icon--die',
children: [
{
label: '이슈 등록',
href: 'https://bbs.gaonwiki.com/issue',
title: 'https://bbs.gaonwiki.com/issue',
icon: 'minerva-icon--die'
},
{
label: '기능 구현 도움',
href: 'https://www.gaonwiki.com/w/%EA%B0%80%EC%98%A8_%EC%9C%84%ED%82%A4:%EA%B8%B0%EB%8A%A5_%EA%B5%AC%ED%98%84_%EB%B6%88%EA%B0%80-%EB%88%84%EA%B0%80_%ED%95%B4%EA%B2%B0%EC%B1%85%EC%9D%84_%EC%95%8C%EB%A0%A4%EC%A3%BC%EC%84%B8%EC%9A%94!',
title: 'https://www.gaonwiki.com/w/가온_위키:기능_구현_불가-누가_해결책을_알려주세요!',
icon: 'minerva-icon--speechBubbles'
},
{
label: '알려진 문제들',
href: 'https://www.gaonwiki.com/w/%EA%B0%80%EC%98%A8_%EC%9C%84%ED%82%A4/%EC%95%8C%EB%A0%A4%EC%A7%84_%EB%AC%B8%EC%A0%9C%EB%93%A4',
title: 'https://www.gaonwiki.com/w/가온_위키/알려진_문제들',
icon: 'minerva-icon--recentChanges'
}
]
},
{
// 도구 그룹
label: '도구',
icon: 'minerva-icon--specialPages',
children: [
{
label: '특수 문서 목록',
href: mw.util.getUrl( '특수:특수문서' ),
title: '특수:특수문서',
icon: 'minerva-icon--specialPages'
},
{
// "파일 올리기" (3단계 메뉴를 가진 항목)
label: '파일 올리기',
href: '#', // 드롭다운 전용이므로 실제 링크는 없음
title: '파일 올리기',
icon: 'minerva-icon--specialPages',
children: [
{
label: '(기존) 업로드',
href: mw.util.getUrl( '특수:올리기' ),
title: '특수:올리기',
icon: 'minerva-icon--specialPages'
},
{
label: '(신규) 업로드 마법사',
href: mw.util.getUrl( '특수:UploadWizard' ),
title: '특수:UploadWizard',
icon: 'minerva-icon--specialPages'
}
]
},
{
label: '이슈 트래커',
href: 'https://bbs.gaonwiki.com/issue/',
title: 'https://bbs.gaonwiki.com/issue/',
icon: 'minerva-icon--die'
},
{
label: '가온 위키 베타',
href: 'https://beta.gaonwiki.com',
title: 'https://beta.gaonwiki.com',
icon: 'minerva-icon--specialPages'
}
]
},
{
// 도움말 그룹
label: '도움말',
icon: 'minerva-icon--specialPages',
children: [
{
label: '위키 문법',
href: mw.util.getUrl( '도움말:위키_문법' ),
title: '도움말:위키_문법',
icon: 'minerva-icon--specialPages'
},
{
label: '설명서',
href: mw.util.getUrl( '도움말:설명서' ),
title: '도움말:설명서',
icon: 'minerva-icon--specialPages'
}
]
}
];
/* -------------------------------------------------
* 2. DOM 생성 유틸리티
* ------------------------------------------------- */
/**
* Minerva 스타일의 아이콘 <span> 요소를 생성한다.
*
* @param {string} iconClass "minerva-icon--XXX" 형식의 클래스
* @return {jQuery}
*/
function buildIcon( iconClass ) {
var $icon = $( '<span>' ).addClass( 'minerva-icon' );
if ( iconClass ) {
$icon.addClass( iconClass );
}
return $icon;
}
/**
* 메뉴 라벨 <span> 요소를 생성한다.
*
* @param {string} text 화면에 보일 텍스트
* @return {jQuery}
*/
function buildLabel( text ) {
return $( '<span>' )
.addClass( 'toggle-list-item__label' )
.text( text || '' );
}
/**
* Minerva 스타일의 <a> 요소를 생성한다.
*
* @param {string} href 링크 URL (없으면 '#')
* @param {string} title title 속성
* @return {jQuery}
*/
function buildAnchor( href, title ) {
return $( '<a>' )
.addClass( 'toggle-list-item__anchor gaon-menu-link' )
.attr( 'href', href || '#' )
.attr( 'title', title || '' );
}
/**
* 하위 메뉴 항목(레벨 2, 3)을 재귀적으로 생성하여 <ul> 안에 추가한다.
*
* @param {jQuery} $ul 현재 레벨의 <ul>
* @param {Object} item 메뉴 정의 객체
* @param {number} level 레벨 번호(2, 3, ...)
*/
function appendGaonMenuItem( $ul, item, level ) {
var hasChildren = Array.isArray( item.children ) && item.children.length > 0;
// <li> 생성
var $li = $( '<li>' )
.addClass( 'toggle-list-item gaon-menu-item gaon-menu-item-level' + level );
if ( hasChildren ) {
$li.addClass( 'gaon-menu-item--has-children gaon-menu-item--collapsed' );
}
// <a> 생성
var $a = buildAnchor( item.href, item.title || item.label );
$a.append( buildIcon( item.icon ) );
$a.append( buildLabel( item.label ) );
$li.append( $a );
$ul.append( $li );
// 하위 레벨이 있으면 <ul> 을 만들어 재귀 호출
if ( hasChildren ) {
var nextLevel = level + 1;
var $subUl = $( '<ul>' )
.addClass( 'gaon-menu gaon-menu-level' + nextLevel );
item.children.forEach( function ( child ) {
appendGaonMenuItem( $subUl, child, nextLevel );
} );
// 이 부분이 중요:
// 하위 <ul> 은 반드시 <li> 안에 들어가야 한다.
$li.append( $subUl );
}
}
/**
* 한 개의 상위 그룹(게시판 / 버그/기능 개선 / 도구 / 도움말)을
* Minerva 스타일의 <ul> 블록으로 생성한다.
*
* @param {Object} group 그룹 정의
* @param {number} index 그룹 index
* @return {jQuery} 완성된 <ul> 요소
*/
function buildGroup( group, index ) {
// Minerva 기본 메뉴와 같은 class 사용
var $level1 = $( '<ul>' )
.addClass( 'toggle-list__list gaon-menu gaon-menu-level1' )
.attr( 'data-gaon-group-index', index );
var hasChildren = Array.isArray( group.children ) && group.children.length > 0;
// 헤더 <li>
var $headerLi = $( '<li>' )
.addClass( 'toggle-list-item gaon-menu-header gaon-menu-header--collapsed' );
var $headerA = buildAnchor( '#', group.label );
$headerA
.addClass( 'gaon-menu-header__anchor' )
.append( buildIcon( group.icon ) )
.append( buildLabel( group.label ) );
$headerLi.append( $headerA );
// 그룹에 하위 항목이 있으면 level2 <ul> 생성
if ( hasChildren ) {
var $level2 = $( '<ul>' )
.addClass( 'gaon-menu gaon-menu-level2' );
group.children.forEach( function ( item ) {
appendGaonMenuItem( $level2, item, 2 );
} );
// 헤더 <li> 안에 하위 <ul> 을 넣는다.
$headerLi.append( $level2 );
}
$level1.append( $headerLi );
return $level1;
}
/* -------------------------------------------------
* 3. 메뉴를 실제 Minerva 햄버거 메뉴 안에 삽입
* ------------------------------------------------- */
/**
* 가온 메뉴를 Minerva 왼쪽 메뉴에 삽입한다.
*/
function insertGaonMenuIntoMinerva() {
// 기본 내비게이션 블록(대문/임의의 문서로)이 들어 있는 첫 번째 toggle-list__list 를 찾는다.
var $firstList = $( '#p-navigation.toggle-list__list' ).first();
// 혹시 id 가 다르다면 fallback: 메뉴 안의 첫 toggle-list__list
if ( !$firstList.length ) {
$firstList = $( '#mw-mf-page-left .toggle-list__list' ).first();
}
if ( !$firstList.length ) {
return;
}
// 중복 삽입 방지
if ( $firstList.data( 'gaonMenuInjected' ) ) {
return;
}
$firstList.data( 'gaonMenuInjected', true );
// 여러 그룹을 한 번에 생성하여 첫 번째 리스트 뒤에 삽입
var $allGroups = $( [] );
gaonMenuConfig.forEach( function ( group, index ) {
$allGroups = $allGroups.add( buildGroup( group, index ) );
} );
$firstList.after( $allGroups );
// 모든 하위 레벨을 기본적으로 숨긴다.
$( '.gaon-menu-level2, .gaon-menu-level3' ).hide();
// 상위 그룹 헤더 클릭 시 level2 토글
$( '.gaon-menu-header__anchor' ).on( 'click', function ( e ) {
e.preventDefault();
var $headerLi = $( this ).closest( '.gaon-menu-header' );
var $sub = $headerLi.children( '.gaon-menu-level2' );
if ( !$sub.length ) {
return;
}
$headerLi.toggleClass( 'gaon-menu-header--collapsed' );
$sub.slideToggle( 150 );
} );
// "파일 올리기"처럼 children 이 있는 2단계 항목 클릭 시 level3 토글
$( '.gaon-menu-item--has-children > .gaon-menu-link' ).on( 'click', function ( e ) {
e.preventDefault();
var $li = $( this ).closest( '.gaon-menu-item--has-children' );
var $sub = $li.children( '.gaon-menu-level3' );
if ( !$sub.length ) {
return;
}
$li.toggleClass( 'gaon-menu-item--collapsed' );
$sub.slideToggle( 150 );
} );
}
/* -------------------------------------------------
* 4. 메뉴 HTML 로드 완료를 기다렸다가 삽입
* ------------------------------------------------- */
var maxAttempts = 50; // 최대 50번(약 5초 정도) 시도
var attemptCount = 0;
function waitForMinervaMenu() {
var $firstList = $( '#mw-mf-page-left .toggle-list__list' ).first();
if ( $firstList.length ) {
insertGaonMenuIntoMinerva();
} else if ( attemptCount < maxAttempts ) {
attemptCount += 1;
setTimeout( waitForMinervaMenu, 100 );
}
}
$( waitForMinervaMenu );
}( mediaWiki, jQuery ) );