MediaWiki:Common.js: Difference between revisions

No edit summary
Tag: Reverted
Undo revision 6214 by Vaishnavi (talk)
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 userName = window.mw ? mw.config.get( 'wgUserName' ) : null;
    var isAnon  = !userName || ( window.mw && mw.config.get( 'wgUserId' ) === null );
    // Build the trailing auth element (Login link for anon, dropdown for logged-in)
    var authEl = null;
    if ( isAnon ) {
      if ( !document.getElementById( 'gr-header-login' ) ) {
        authEl = makeHeaderLink( 'gr-header-login', wikiHref( 'Special:UserLogin' ), 'Login/Signup' );
      }
    } else if ( !document.getElementById( 'gr-header-user' ) ) {
      authEl = buildHeaderUserDropdown( userName );
    }
     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 ); }
      if ( authEl ) headerEnd.insertBefore( authEl, ul );
     else { headerEnd.appendChild( helpLink ); headerEnd.appendChild( aboutLink ); }
      headerEnd.insertBefore( aboutLink, authEl || ul );
      headerEnd.insertBefore( helpLink, aboutLink );
     } else {
      headerEnd.appendChild( helpLink );
      headerEnd.appendChild( aboutLink );
      if ( authEl ) headerEnd.appendChild( authEl );
    }
  }
 
  function buildHeaderUserDropdown( userName ) {
    var wrap = document.createElement( 'div' );
    wrap.id = 'gr-header-user';
    wrap.style.cssText = 'position:relative;display:inline-block;margin-right:4px;';
 
    var trigger = document.createElement( 'button' );
    trigger.id = 'gr-header-user-trigger';
    trigger.type = 'button';
    trigger.setAttribute( 'aria-haspopup', 'true' );
    trigger.setAttribute( 'aria-expanded', 'false' );
    trigger.style.cssText = [
      'display:inline-flex','align-items:center','gap:5px',
      'color:rgba(255,255,255,0.88)','font-size:0.88em',
      'font-family:system-ui,sans-serif','font-weight:500',
      'background:transparent','border:none','cursor:pointer',
      'padding:4px 10px','border-radius:4px','white-space:nowrap',
      'transition:color 0.15s,background 0.15s'
    ].join( ';' );
    trigger.innerHTML =
      '<span>' + userName.replace( /</g, '&lt;' ) + '</span>' +
      '<span id="gr-header-caret" style="font-size:0.8em;transition:transform 0.2s;">\u25be</span>';
    trigger.addEventListener( 'mouseover', function () { this.style.color = '#fff'; this.style.background = 'rgba(255,255,255,0.12)'; } );
    trigger.addEventListener( 'mouseout',  function () { if ( menu.style.display === 'none' ) { this.style.color = 'rgba(255,255,255,0.88)'; this.style.background = 'transparent'; } } );
 
    var menu = document.createElement( 'div' );
    menu.id = 'gr-header-user-menu';
    menu.setAttribute( 'role', 'menu' );
    menu.style.cssText = [
      'display:none','position:absolute','top:100%','right:0','margin-top:4px',
      'min-width:150px','background:#fff','border-radius:6px',
      'box-shadow:0 4px 16px rgba(0,0,0,0.18)','overflow:hidden','z-index:1000'
    ].join( ';' );
 
    var itemStyle = 'display:block;padding:10px 16px;font-size:0.9em;color:#2c1810;text-decoration:none;font-family:system-ui,sans-serif;background:#fff;';
    function makeMenuItem( href, label, id ) {
      var a = document.createElement( 'a' );
      a.href = href; a.setAttribute( 'role', 'menuitem' );
      a.textContent = label; a.style.cssText = itemStyle;
      if ( id ) a.id = id;
      a.addEventListener( 'mouseover', function () { this.style.background = '#f5efe9'; } );
      a.addEventListener( 'mouseout',  function () { this.style.background = '#fff'; } );
      return a;
    }
 
    menu.appendChild( makeMenuItem( wikiHref( 'Special:Profile' ), 'Profile' ) );
    menu.appendChild( makeMenuItem( '#', 'Log out', 'gr-header-logout' ) );
 
    function setOpen( open ) {
      menu.style.display = open ? 'block' : 'none';
      trigger.setAttribute( 'aria-expanded', open ? 'true' : 'false' );
      var caret = document.getElementById( 'gr-header-caret' );
      if ( caret ) caret.style.transform = open ? 'rotate(180deg)' : '';
      if ( open ) { trigger.style.color = '#fff'; trigger.style.background = 'rgba(255,255,255,0.12)'; }
      else { trigger.style.color = 'rgba(255,255,255,0.88)'; trigger.style.background = 'transparent'; }
    }
 
    trigger.addEventListener( 'click', function ( e ) {
      e.stopPropagation();
      setOpen( menu.style.display === 'none' );
    } );
    document.addEventListener( 'click', function ( e ) {
      if ( !wrap.contains( e.target ) ) setOpen( false );
    } );
 
    // Logout: POST with CSRF token (same approach as the desktop dropdown)
    menu.querySelector( '#gr-header-logout' ).addEventListener( 'click', function ( e ) {
      e.preventDefault();
      if ( window.mw && mw.user && mw.user.tokens ) {
        var t = mw.user.tokens.get( 'csrfToken' );
        if ( t ) {
          var script = ( mw.util && mw.util.wikiScript ) ? mw.util.wikiScript() : '/index.php';
          var form = document.createElement( 'form' );
          form.method = 'post';
          form.action = script + '?title=Special:UserLogout';
          form.style.display = 'none';
          form.innerHTML =
            '<input type="hidden" name="wpEditToken" value="' + String( t ).replace( /"/g, '&quot;' ) + '">' +
            '<input type="hidden" name="title" value="Special:UserLogout">' +
            '<input type="hidden" name="returnto" value="Main Page">';
          document.body.appendChild( form );
          form.submit();
          return;
        }
      }
      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';
      }
    } );
 
    wrap.appendChild( trigger );
    wrap.appendChild( menu );
    return wrap;
   }
   }
  if ( document.readyState === 'loading' ) document.addEventListener( 'DOMContentLoaded', injectHeaderLinks );
  else injectHeaderLinks();
}() );