MediaWiki:Gadget-wix-nav.js: Difference between revisions
Appearance
Content deleted Content added
Created page with "/* ================================================================ 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 wikit..." |
No edit summary |
||
| Line 24: | Line 24: | ||
mw.hook( 'wikipage.content' ).add( function () { |
mw.hook( 'wikipage.content' ).add( function () { |
||
var |
var navContainers = wix.initModules( 'nav' ); |
||
navContainers.forEach( initNav ); |
|||
if ( !containers.length ) { |
|||
return; |
|||
var dropdownContainers = wix.initModules( 'nav-dropdown' ); |
|||
} |
|||
dropdownContainers.forEach( initNavDropdown ); |
|||
} ); |
} ); |
||
| Line 98: | Line 98: | ||
}, 0 ); |
}, 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' ); |
|||
} |
|||
} ); |
|||
} |
} |
||
Revision as of 22:07, 31 March 2026
/* ================================================================
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' );
}
} );
}
}() );