MediaWiki:Gadget-wix-nav.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* ================================================================
WIX-NAV.JS — Wiki Interactive Experience: Training Navigation
================================================================
Depends on: ext.gadget.wix-core (window.wix must exist)
Finds every container with data-wix-module="nav", reads the
page list from data-wix-pages (JSON), and builds a horizontal
navigation bar with the current page highlighted.
DOM contract (set by wikitext snippet):
─────────────────────────────────────────
Container: [data-wix-module="nav"]
data-wix-pages JSON array of [label, pageName] pairs
Example:
data-wix-pages='[["Module 1","Internal:Training/IFRS17/module-1"],
["Module 2","Internal:Training/IFRS17/module-2"]]'
================================================================ */
( function () {
'use strict';
/* ── Guard ──────────────────────────────────────────────────── */
mw.hook( 'wikipage.content' ).add( function () {
var navContainers = wix.initModules( 'nav' );
navContainers.forEach( initNav );
var dropdownContainers = wix.initModules( 'nav-dropdown' );
dropdownContainers.forEach( initNavDropdown );
} );
/* ── Main init ──────────────────────────────────────────────── */
function initNav( container ) {
// 1. Read and parse page list
var raw = wix.data( container, 'wix-pages', '[]' );
var pages;
try {
pages = JSON.parse( raw );
} catch ( e ) {
return;
}
if ( !pages.length ) {
return;
}
// 2. Detect current page
var currentPage = mw.config.get( 'wgPageName' ).replace( / /g, '_' );
// 3. Build menu
wix.empty( container );
var menu = wix.el( 'div', {
className: 'wix-menu',
'role': 'navigation',
'aria-label': 'Training navigation'
} );
var currentBtn = null;
pages.forEach( function ( entry ) {
var label = entry[ 0 ];
var pageName = entry[ 1 ];
var normalizedPage = pageName.replace( / /g, '_' );
var isCurrent = ( normalizedPage === currentPage );
var btn;
if ( isCurrent ) {
btn = wix.el( 'span', {
className: 'wix-menu-btn wix-menu-btn--current',
textContent: label,
'aria-current': 'page'
} );
currentBtn = btn;
} else {
btn = wix.el( 'a', {
className: 'wix-menu-btn',
textContent: label,
href: mw.util.getUrl( pageName )
} );
}
menu.appendChild( btn );
} );
container.appendChild( menu );
// 4. Scroll current button into view on mobile
if ( currentBtn ) {
setTimeout( function () {
currentBtn.scrollIntoView( {
inline: 'center',
block: 'nearest',
behavior: 'smooth'
} );
}, 0 );
}
}
/* ── Dropdown init ──────────────────────────────────────────── */
function initNavDropdown( container ) {
// 1. Read and parse page list
var raw = wix.data( container, 'wix-pages', '[]' );
var pages;
try {
pages = JSON.parse( raw );
} catch ( e ) {
return;
}
if ( !pages.length ) {
return;
}
// 2. Detect current page
var currentPage = mw.config.get( 'wgPageName' ).replace( / /g, '_' );
var currentLabel = 'Navigate to\u2026';
pages.forEach( function ( entry ) {
var normalizedPage = entry[ 1 ].replace( / /g, '_' );
if ( normalizedPage === currentPage ) {
currentLabel = entry[ 0 ];
}
} );
// 3. Build dropdown
wix.empty( container );
var wrapper = wix.el( 'div', {
className: 'wix-dropdown',
'role': 'navigation',
'aria-label': 'Training navigation'
} );
// Toggle button
var chevron = wix.el( 'span', {
className: 'wix-dropdown-chevron',
textContent: '\u25BC'
} );
var toggle = wix.el( 'button', {
className: 'wix-dropdown-toggle'
}, [
wix.el( 'span', { textContent: currentLabel } ),
chevron
] );
// Panel
var panel = wix.el( 'div', { className: 'wix-dropdown-panel' } );
pages.forEach( function ( entry ) {
var label = entry[ 0 ];
var pageName = entry[ 1 ];
var normalizedPage = pageName.replace( / /g, '_' );
var isCurrent = ( normalizedPage === currentPage );
var item;
if ( isCurrent ) {
item = wix.el( 'span', {
className: 'wix-dropdown-item wix-dropdown-item--current',
textContent: label,
'aria-current': 'page'
} );
} else {
item = wix.el( 'a', {
className: 'wix-dropdown-item',
textContent: label,
href: mw.util.getUrl( pageName )
} );
}
panel.appendChild( item );
} );
wrapper.appendChild( toggle );
wrapper.appendChild( panel );
container.appendChild( wrapper );
// 4. Toggle open/close
var isOpen = false;
toggle.addEventListener( 'click', function () {
isOpen = !isOpen;
toggle.classList.toggle( 'wix-dropdown-toggle--open', isOpen );
panel.classList.toggle( 'wix-dropdown-panel--open', isOpen );
} );
// 5. Close on click outside
document.addEventListener( 'click', function ( e ) {
if ( isOpen && !wrapper.contains( e.target ) ) {
isOpen = false;
toggle.classList.remove( 'wix-dropdown-toggle--open' );
panel.classList.remove( 'wix-dropdown-panel--open' );
}
} );
}
}() );