Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MediaWiki:Citizen.js: Difference between revisions

MediaWiki interface page
Default chiuso su TOC lunga + persistenza
sezioni collassabili + sostituzione box TBC
Line 63: Line 63:
} );
} );
} );
} );
/* === [SEZIONI] inizio ===
  Sezioni collassabili in tutta la wiki.
  - Granularità: intestazioni di 2º livello (== ==). Le sotto-sezioni (=== ===)
    restano dentro la loro sezione.
  - Default: CHIUSE al primo approdo (nessuno stato salvato per la pagina).
  - Lo stato (quali sezioni aperte) è ricordato per-pagina in localStorage.
  - I link interni / le voci della TOC riaprono la sezione di destinazione. */
mw.hook( 'wikipage.content' ).add( function () {
var body = document.querySelector( '#mw-content-text .mw-parser-output' );
if ( !body || body.dataset.ceSecDone ) {
return;
}
// intestazioni H2 di primo livello nel corpo (wrapper .mw-heading2 in MW 1.45,
// o <h2> nudo come fallback)
var headings = Array.prototype.slice.call( body.children ).filter( function ( n ) {
return ( n.classList && n.classList.contains( 'mw-heading2' ) ) || n.tagName === 'H2';
} );
if ( !headings.length ) {
return;
}
body.dataset.ceSecDone = '1';
function headingId( h ) {
var hx = h.querySelector ? ( h.querySelector( 'h1,h2,h3,h4' ) || h ) : h;
return hx.id || null;
}
var SKEY = 'ce-sections:' + mw.config.get( 'wgPageName' );
var stored = null;
try { stored = localStorage.getItem( SKEY ); } catch ( e ) {}
var openIds = {};
if ( stored ) {
try {
JSON.parse( stored ).forEach( function ( id ) { openIds[ id ] = 1; } );
} catch ( e ) {}
}
function save() {
var open = [];
headings.forEach( function ( h ) {
if ( !h.classList.contains( 'ce-collapsed' ) ) {
var id = headingId( h );
if ( id ) { open.push( id ); }
}
} );
try { localStorage.setItem( SKEY, JSON.stringify( open ) ); } catch ( e ) {}
}
headings.forEach( function ( h ) {
// avvolge i fratelli fino alla prossima intestazione H2
var content = document.createElement( 'div' );
content.className = 'ce-sec-content';
var sib = h.nextSibling;
while ( sib ) {
var next = sib.nextSibling;
if ( sib.nodeType === 1 &&
( ( sib.classList && sib.classList.contains( 'mw-heading2' ) ) || sib.tagName === 'H2' ) ) {
break;
}
content.appendChild( sib );
sib = next;
}
h.parentNode.insertBefore( content, h.nextSibling );
content._ceHeading = h;
h.classList.add( 'ce-sec-h' );
h.setAttribute( 'tabindex', '0' );
var hid = headingId( h );
var open = stored ? !!openIds[ hid ] : false; // default: chiusa
h.setAttribute( 'aria-expanded', open ? 'true' : 'false' );
if ( !open ) {
h.classList.add( 'ce-collapsed' );
}
var toggle = function () {
var c = h.classList.toggle( 'ce-collapsed' );
h.setAttribute( 'aria-expanded', c ? 'false' : 'true' );
save();
};
h.addEventListener( 'click', function ( e ) {
if ( e.target.closest( 'a' ) || e.target.closest( '.mw-editsection' ) ) {
return; // non interferire con i link / modifica-sezione
}
toggle();
} );
h.addEventListener( 'keydown', function ( e ) {
if ( ( e.key === 'Enter' || e.key === ' ' ) &&
!e.target.closest( 'a' ) && !e.target.closest( '.mw-editsection' ) ) {
e.preventDefault();
toggle();
}
} );
} );
// riapri la sezione di destinazione quando si segue un'àncora
function expandFor( hash ) {
if ( !hash || hash.length < 2 ) { return; }
var id;
try { id = decodeURIComponent( hash.replace( /^#/, '' ) ); } catch ( e ) { id = hash.slice( 1 ); }
var el = document.getElementById( id );
if ( !el ) { return; }
var hWrap = el.closest( '.ce-sec-h' );
if ( hWrap ) {
hWrap.classList.remove( 'ce-collapsed' );
hWrap.setAttribute( 'aria-expanded', 'true' );
} else {
var c = el.closest( '.ce-sec-content' );
if ( c && c._ceHeading ) {
c._ceHeading.classList.remove( 'ce-collapsed' );
c._ceHeading.setAttribute( 'aria-expanded', 'true' );
}
}
save();
setTimeout( function () {
var t = document.getElementById( id );
if ( t && t.scrollIntoView ) { t.scrollIntoView(); }
}, 0 );
}
window.addEventListener( 'hashchange', function () { expandFor( location.hash ); } );
document.addEventListener( 'click', function ( e ) {
var a = e.target.closest( 'a[href^="#"]' );
if ( a ) {
var href = a.getAttribute( 'href' );
setTimeout( function () { expandFor( href ); }, 0 );
}
} );
if ( location.hash ) { expandFor( location.hash ); }
} );
/* === [SEZIONI] fine === */

Revision as of 13:55, 16 June 2026

/* All JavaScript here will be loaded for users of the Citizen skin */

/* Indice d'archivio:
   1) dove esiste il rail di Citizen lo mettiamo lì SOPRA la TOC nativa (riuso);
      dove il rail non c'è, l'indice resta flottante (.ai-rail) e non sparisce.
   2) collassabile (chevron nella testata). Stato iniziale:
        - se l'utente ha già scelto, si ricorda (localStorage);
        - altrimenti default intelligente: chiuso se la TOC della pagina è lunga.
   3) la testata (link alla Dashboard) resta sempre visibile. */
mw.hook( 'wikipage.content' ).add( function () {
	var KEY = 'ce-indice-collapsed';

	// 1) posizionamento
	var floatBox = document.querySelector( '.archivio-indice.ai-rail' );
	if ( floatBox ) {
		var rail =
			document.querySelector( '.citizen-page-sidebar' ) ||
			document.querySelector( '.citizen-sidebar' ) ||
			document.querySelector( '.citizen-toc-container' );
		if ( rail ) {
			floatBox.classList.remove( 'ai-rail' );
			floatBox.classList.add( 'ai-in-rail' );
			rail.prepend( floatBox );
		}
	}

	var idx = document.querySelector( '.archivio-indice' );
	if ( !idx ) {
		return;
	}

	// 2) stato iniziale
	var saved = null;
	try {
		saved = localStorage.getItem( KEY );
	} catch ( e ) {}
	var tocCount = document.querySelectorAll( '.citizen-toc-link' ).length;
	var collapsed = ( saved === null ) ? ( tocCount > 8 ) : ( saved === '1' );
	if ( collapsed ) {
		idx.classList.add( 'ai-collapsed' );
	}

	// 3) toggle + persistenza
	document.querySelectorAll( '.archivio-indice .ai-toggle' ).forEach( function ( t ) {
		if ( t.dataset.bound ) {
			return;
		}
		t.dataset.bound = '1';
		var act = function () {
			var b = t.closest( '.archivio-indice' );
			b.classList.toggle( 'ai-collapsed' );
			try {
				localStorage.setItem( KEY, b.classList.contains( 'ai-collapsed' ) ? '1' : '0' );
			} catch ( e ) {}
		};
		t.addEventListener( 'click', act );
		t.addEventListener( 'keydown', function ( e ) {
			if ( e.key === 'Enter' || e.key === ' ' ) {
				e.preventDefault();
				act();
			}
		} );
	} );
} );
/* === [SEZIONI] inizio ===
   Sezioni collassabili in tutta la wiki.
   - Granularità: intestazioni di 2º livello (== ==). Le sotto-sezioni (=== ===)
     restano dentro la loro sezione.
   - Default: CHIUSE al primo approdo (nessuno stato salvato per la pagina).
   - Lo stato (quali sezioni aperte) è ricordato per-pagina in localStorage.
   - I link interni / le voci della TOC riaprono la sezione di destinazione. */
mw.hook( 'wikipage.content' ).add( function () {
	var body = document.querySelector( '#mw-content-text .mw-parser-output' );
	if ( !body || body.dataset.ceSecDone ) {
		return;
	}

	// intestazioni H2 di primo livello nel corpo (wrapper .mw-heading2 in MW 1.45,
	// o <h2> nudo come fallback)
	var headings = Array.prototype.slice.call( body.children ).filter( function ( n ) {
		return ( n.classList && n.classList.contains( 'mw-heading2' ) ) || n.tagName === 'H2';
	} );
	if ( !headings.length ) {
		return;
	}
	body.dataset.ceSecDone = '1';

	function headingId( h ) {
		var hx = h.querySelector ? ( h.querySelector( 'h1,h2,h3,h4' ) || h ) : h;
		return hx.id || null;
	}

	var SKEY = 'ce-sections:' + mw.config.get( 'wgPageName' );
	var stored = null;
	try { stored = localStorage.getItem( SKEY ); } catch ( e ) {}
	var openIds = {};
	if ( stored ) {
		try {
			JSON.parse( stored ).forEach( function ( id ) { openIds[ id ] = 1; } );
		} catch ( e ) {}
	}

	function save() {
		var open = [];
		headings.forEach( function ( h ) {
			if ( !h.classList.contains( 'ce-collapsed' ) ) {
				var id = headingId( h );
				if ( id ) { open.push( id ); }
			}
		} );
		try { localStorage.setItem( SKEY, JSON.stringify( open ) ); } catch ( e ) {}
	}

	headings.forEach( function ( h ) {
		// avvolge i fratelli fino alla prossima intestazione H2
		var content = document.createElement( 'div' );
		content.className = 'ce-sec-content';
		var sib = h.nextSibling;
		while ( sib ) {
			var next = sib.nextSibling;
			if ( sib.nodeType === 1 &&
				( ( sib.classList && sib.classList.contains( 'mw-heading2' ) ) || sib.tagName === 'H2' ) ) {
				break;
			}
			content.appendChild( sib );
			sib = next;
		}
		h.parentNode.insertBefore( content, h.nextSibling );
		content._ceHeading = h;
		h.classList.add( 'ce-sec-h' );
		h.setAttribute( 'tabindex', '0' );

		var hid = headingId( h );
		var open = stored ? !!openIds[ hid ] : false; // default: chiusa
		h.setAttribute( 'aria-expanded', open ? 'true' : 'false' );
		if ( !open ) {
			h.classList.add( 'ce-collapsed' );
		}

		var toggle = function () {
			var c = h.classList.toggle( 'ce-collapsed' );
			h.setAttribute( 'aria-expanded', c ? 'false' : 'true' );
			save();
		};
		h.addEventListener( 'click', function ( e ) {
			if ( e.target.closest( 'a' ) || e.target.closest( '.mw-editsection' ) ) {
				return; // non interferire con i link / modifica-sezione
			}
			toggle();
		} );
		h.addEventListener( 'keydown', function ( e ) {
			if ( ( e.key === 'Enter' || e.key === ' ' ) &&
				!e.target.closest( 'a' ) && !e.target.closest( '.mw-editsection' ) ) {
				e.preventDefault();
				toggle();
			}
		} );
	} );

	// riapri la sezione di destinazione quando si segue un'àncora
	function expandFor( hash ) {
		if ( !hash || hash.length < 2 ) { return; }
		var id;
		try { id = decodeURIComponent( hash.replace( /^#/, '' ) ); } catch ( e ) { id = hash.slice( 1 ); }
		var el = document.getElementById( id );
		if ( !el ) { return; }
		var hWrap = el.closest( '.ce-sec-h' );
		if ( hWrap ) {
			hWrap.classList.remove( 'ce-collapsed' );
			hWrap.setAttribute( 'aria-expanded', 'true' );
		} else {
			var c = el.closest( '.ce-sec-content' );
			if ( c && c._ceHeading ) {
				c._ceHeading.classList.remove( 'ce-collapsed' );
				c._ceHeading.setAttribute( 'aria-expanded', 'true' );
			}
		}
		save();
		setTimeout( function () {
			var t = document.getElementById( id );
			if ( t && t.scrollIntoView ) { t.scrollIntoView(); }
		}, 0 );
	}
	window.addEventListener( 'hashchange', function () { expandFor( location.hash ); } );
	document.addEventListener( 'click', function ( e ) {
		var a = e.target.closest( 'a[href^="#"]' );
		if ( a ) {
			var href = a.getAttribute( 'href' );
			setTimeout( function () { expandFor( href ); }, 0 );
		}
	} );
	if ( location.hash ) { expandFor( location.hash ); }
} );
/* === [SEZIONI] fine === */