MediaWiki:Common.js: Difference between revisions
Tag: Undo |
Tag: Undo |
||
| Line 450: | Line 450: | ||
return a; | return a; | ||
} | } | ||
function injectHeaderLinks() { | function injectHeaderLinks() { | ||
if ( document.getElementById( 'gr-about-link' ) ) return; | if ( document.getElementById( 'gr-about-link' ) ) return; | ||
var headerEnd = document.querySelector( '.vector-header-end' ) || document.querySelector( '#vector-user-links' ) || document.querySelector( '.mw-header' ); | var headerEnd = document.querySelector( '.vector-header-end' ) || document.querySelector( '#vector-user-links' ) || document.querySelector( '.mw-header' ); | ||
| Line 456: | Line 456: | ||
var helpLink = makeHeaderLink( 'gr-help-link', wikiHref( 'My_wiki:Help' ), 'Help' ); | var helpLink = makeHeaderLink( 'gr-help-link', wikiHref( 'My_wiki:Help' ), 'Help' ); | ||
var aboutLink = makeHeaderLink( 'gr-about-link', wikiHref( 'My_wiki:About' ), 'About' ); | var aboutLink = makeHeaderLink( 'gr-about-link', wikiHref( 'My_wiki:About' ), 'About' ); | ||
var ul = document.querySelector( '.vector-user-links' ) || document.querySelector( '#pt-userpage' ); | var ul = document.querySelector( '.vector-user-links' ) || document.querySelector( '#pt-userpage' ); | ||
if ( ul && ul.parentNode === headerEnd ) { | if ( ul && ul.parentNode === headerEnd ) { headerEnd.insertBefore( aboutLink, ul ); headerEnd.insertBefore( helpLink, aboutLink ); } | ||
else { headerEnd.appendChild( helpLink ); headerEnd.appendChild( aboutLink ); } | |||
} | } | ||
if ( document.readyState === 'loading' ) document.addEventListener( 'DOMContentLoaded', injectHeaderLinks ); | |||
else injectHeaderLinks(); | |||
}() ); | |||
| Line 1,131: | Line 1,015: | ||
return form; | return form; | ||
} | } | ||
function injectUserDropdown() { | |||
if ( document.getElementById( 'gr-user-dropdown' ) ) return; | |||
var userName = window.mw ? mw.config.get( 'wgUserName' ) : null; | |||
var isAnon = !userName || ( window.mw && mw.config.get( 'wgUserId' ) === null ); | |||
var container = document.querySelector( '.vector-user-links-main' ) | |||
|| document.querySelector( '.vector-user-links' ); | |||
if ( !container ) return; | |||
// Logged-out: show a single Login/Signup link, nothing else | |||
if ( isAnon ) { | |||
// Remove MediaWiki's native account links so only our button shows | |||
[ '#pt-createaccount', '#pt-login', '#pt-anoncontribs', | |||
'#pt-anontalk', '#pt-anonuserpage' ].forEach( function ( sel ) { | |||
document.querySelectorAll( sel ).forEach( function ( el ) { | |||
if ( el && el.parentNode ) el.parentNode.removeChild( el ); | |||
} ); | |||
} ); | |||
if ( document.getElementById( 'gr-login-link' ) ) return; | |||
var loginA = document.createElement( 'a' ); | |||
loginA.id = 'gr-login-link'; | |||
loginA.href = wikiHref( 'Special:UserLogin' ); | |||
loginA.textContent = 'Login/Signup'; | |||
loginA.style.cssText = 'color:#fff;font-size:0.9em;font-weight:500;' + | |||
'text-decoration:none;padding:6px 12px;border-radius:6px;' + | |||
'background:rgba(255,255,255,0.12);white-space:nowrap;'; | |||
loginA.addEventListener( 'mouseover', function(){ this.style.background='rgba(255,255,255,0.2)'; } ); | |||
loginA.addEventListener( 'mouseout', function(){ this.style.background='rgba(255,255,255,0.12)'; } ); | |||
container.appendChild( loginA ); | |||
return; | |||
} | |||
// Logout token (csrf token works for logout in modern MW) | |||
var token = ( window.mw && mw.user && mw.user.tokens ) | |||
? mw.user.tokens.get( 'csrfToken' ) : '+\\'; | |||
var wrap = document.createElement( 'div' ); | |||
wrap.id = 'gr-user-dropdown'; | |||
wrap.innerHTML = | |||
'<button id="gr-user-trigger" type="button" aria-haspopup="true" aria-expanded="false">' + | |||
'<span>' + (userName.replace(/</g,'<')) + '</span>' + | |||
'<span class="gr-caret">▾</span>' + | |||
'</button>' + | |||
'<div id="gr-user-menu" role="menu">' + | |||
'<a href="' + wikiHref( 'Special:Profile' ) + '" role="menuitem">Profile</a>' + | |||
'<a href="#" id="gr-logout-link" role="menuitem">Log out</a>' + | |||
'</div>'; | |||
container.appendChild( wrap ); | |||
var trigger = document.getElementById( 'gr-user-trigger' ); | |||
var menu = document.getElementById( 'gr-user-menu' ); | |||
trigger.addEventListener( 'click', function ( e ) { | |||
e.stopPropagation(); | |||
var open = menu.classList.toggle( 'gr-open' ); | |||
trigger.setAttribute( 'aria-expanded', open ? 'true' : 'false' ); | |||
} ); | |||
document.addEventListener( 'click', function ( e ) { | |||
if ( !wrap.contains( e.target ) ) { | |||
menu.classList.remove( 'gr-open' ); | |||
trigger.setAttribute( 'aria-expanded', 'false' ); | |||
} | |||
} ); | |||
document.getElementById( 'gr-logout-link' ).addEventListener( 'click', function ( e ) { | |||
e.preventDefault(); | |||
// Fetch a fresh CSRF token at click time (more reliable than at load time) | |||
if ( window.mw && mw.user && mw.user.tokens ) { | |||
var t = mw.user.tokens.get( 'csrfToken' ); | |||
if ( t ) { buildLogoutForm( t ).submit(); return; } | |||
} | |||
// Fallback: use the API to get a logout token, then submit | |||
if ( window.mw && mw.Api ) { | |||
new mw.Api().postWithToken( 'csrf', { action: 'logout' } ) | |||
.done( function () { location.href = '/Main_Page'; } ) | |||
.fail( function () { location.href = '/index.php?title=Special:UserLogout'; } ); | |||
} else { | |||
location.href = '/index.php?title=Special:UserLogout'; | |||
} | |||
} ); | |||
} | |||
if ( document.readyState === 'loading' ) { | |||
document.addEventListener( 'DOMContentLoaded', injectUserDropdown ); | |||
} else { | |||
injectUserDropdown(); | |||
} | |||
}() ); | |||