MediaWiki:Common.js: Difference between revisions

No edit summary
No edit summary
Line 3: Line 3:
  * Changes vs v6:
  * Changes vs v6:
  *  1. BUG FIX: Main IIFE was never properly closed — About link block was
  *  1. BUG FIX: Main IIFE was never properly closed — About link block was
  *    pasted inside it without closing }() ); which broke the module
  *    pasted inside it without the closing }() ); which broke the module
  *    boundary and killed the by-Author toggle. Each block is now its
  *    boundary and killed the by-Author toggle. Each block is now its
  *    own self-contained IIFE.
  *    own self-contained IIFE.
  *  2. TOC: "Beginning" link removed.
  *  2. TOC: "Beginning" link removed.
  *  3. TOC: Heading label changed from "Contents" → "विषयसूची".
  *  3. TOC: Heading label → "विषयसूची".
  *  4. TOC: मूल / उल्लेख nav links injected at top of TOC panel.
  *  4. TOC: मूल / उल्लेख nav links injected at top of TOC panel.
  *  5. TOC: All subsections expanded by default on load.
  *  5. TOC: All subsections expanded by default.
  *  6. TOC: Only the active item is bold; all others reset to normal weight.
  *  6. TOC: Only the active item is bold; all others are normal weight.
  *  7. About link: URL now derived from wgArticlePath so it works under
  *  7. About link URL derived from wgArticlePath works under any
  *    any sub-path (e.g. /My_wiki/). Points to "My_wiki:About".
  *    sub-path install (e.g. /My_wiki/). Points to "My_wiki:About".
  *  8. TOC customisations skipped on Main_Page and About pages (no sidebar
  *  8. TOC customisations skipped on Main_Page and About pages.
*    TOC on those pages — consistent with __NOTOC__ treatment).
  */
  */


Line 96: Line 95:
       'य':'ய','र':'ர','ல':'ல','ळ':'ழ','व':'வ',
       'य':'ய','र':'ர','ல':'ல','ळ':'ழ','व':'வ',
       'श':'ஶ','ष':'ஷ','स':'ஸ','ह':'ஹ',
       'श':'ஶ','ष':'ஷ','स':'ஸ','ह':'ஹ',
       'ा':'ா','ि':'ி','ी':'ீ','':'ு','ू':'ூ',
       'ा':'ா','ि':'ி','ी':'ீ','':'ு','ू':'ூ',
       'ृ':'ு','ॄ':'ூ',
       'ृ':'ு','ॄ':'ூ',
       'े':'ே','ை':'ை','ो':'ோ','ौ':'ௌ',
       'े':'ே','ை':'ை','ो':'ோ','ौ':'ௌ',
Line 137: Line 136:
         if ( p.hasAttribute && p.hasAttribute( 'data-deva' ) ) return;
         if ( p.hasAttribute && p.hasAttribute( 'data-deva' ) ) return;
         if ( p.closest ) {
         if ( p.closest ) {
           if ( p.closest( '.gr-controls' )   ) return;
           if ( p.closest( '.gr-controls' )   ) return;
           if ( p.closest( '.mw-editsection' ) ) return;
           if ( p.closest( '.mw-editsection' ) ) return;
           if ( p.closest( '#gr-toc-doc-nav' ) ) return; /* don't wrap nav buttons */
           if ( p.closest( '#gr-toc-doc-nav' ) ) return;
         }
         }
         var orig = node.textContent;
         var orig = node.textContent;
Line 151: Line 150:
     }
     }


    // Tag .vector-toc-text spans for TOC transliteration
     document.querySelectorAll( '.vector-toc .vector-toc-text' ).forEach( function ( span ) {
     document.querySelectorAll( '.vector-toc .vector-toc-text' ).forEach( function ( span ) {
       if ( span.hasAttribute( 'data-deva' ) ) return;
       if ( span.hasAttribute( 'data-deva' ) ) return;
Line 174: Line 172:
   }
   }


   // ── Pages where the sidebar TOC is absent / should be left alone ─
   // ── Pages where sidebar TOC should not be modified ──────────────
  // Main_Page uses __NOTOC__; About pages are similar full-page views.
   function _isNoTocPage() {
   function _isNoTocPage() {
     var pn = ( window.mw && mw.config && mw.config.get( 'wgPageName' ) ) || '';
     var pn = ( window.mw && mw.config && mw.config.get( 'wgPageName' ) ) || '';
Line 188: Line 185:
     var titleEl = toc.querySelector( '.vector-toc-title' );
     var titleEl = toc.querySelector( '.vector-toc-title' );
     if ( !titleEl ) return;
     if ( !titleEl ) return;
    /* Replace direct text nodes only — preserves the toggle button sibling */
     var replaced = false;
     var replaced = false;
     titleEl.childNodes.forEach( function ( n ) {
     titleEl.childNodes.forEach( function ( n ) {
Line 201: Line 197:
   }
   }


   // ── TOC: Remove the auto-generated "Beginning" / top-of-page link
   // ── TOC: Remove the "Beginning" / top-of-page link ─────────────
   function removeTocBeginning() {
   function removeTocBeginning() {
     if ( _isNoTocPage() ) return;
     if ( _isNoTocPage() ) return;
Line 208: Line 204:
     var el = toc.querySelector( '#vector-toc-beginning' );
     var el = toc.querySelector( '#vector-toc-beginning' );
     if ( !el ) {
     if ( !el ) {
      /* Fallback: first <li> whose anchor has no "#" fragment */
       var items = toc.querySelectorAll( '.vector-toc-list-item' );
       var items = toc.querySelectorAll( '.vector-toc-list-item' );
       for ( var i = 0; i < items.length; i++ ) {
       for ( var i = 0; i < items.length; i++ ) {
Line 256: Line 251:
     var ullekhaUrl = wikiUrl( primarySlug + '/Ullekha' );
     var ullekhaUrl = wikiUrl( primarySlug + '/Ullekha' );


    /* Hide Moola button when we are already on the moola/bhashya page */
     var isMoola = !teekaPage &&
     var isMoola = !teekaPage &&
                   ( pageTitle === primarySlug ||
                   ( pageTitle === primarySlug ||
Line 264: Line 258:
     nav.id = 'gr-toc-doc-nav';
     nav.id = 'gr-toc-doc-nav';
     nav.setAttribute( 'style', [
     nav.setAttribute( 'style', [
       'display:flex', 'gap:6px',
       'display:flex', 'gap:6px', 'padding:5px 8px 6px',
      'padding:5px 8px 6px',
       'border-bottom:1px solid var(--border-color-base,#dcc9a8)',
       'border-bottom:1px solid var(--border-color-base,#dcc9a8)',
       'margin-bottom:4px', 'flex-wrap:wrap',
       'margin-bottom:4px', 'flex-wrap:wrap',
Line 277: Line 270:
     ].join( ';' );
     ].join( ';' );


     function btn( href, label, color, bg ) {
     function makeBtn( href, label, color, bg ) {
       var a = document.createElement( 'a' );
       var a = document.createElement( 'a' );
       a.href = href;
       a.href = href;
Line 287: Line 280:
     }
     }


     if ( !isMoola ) nav.appendChild( btn( moolaUrl,  'मूल',    '#b04b00', '#fff3e0' ) );
     if ( !isMoola ) nav.appendChild( makeBtn( moolaUrl,  'मूल',    '#b04b00', '#fff3e0' ) );
     nav.appendChild(                btn( ullekhaUrl, 'उल्लेख', '#1a5f8a', '#e8f4fc' ) );
     nav.appendChild(                makeBtn( ullekhaUrl, 'उल्लेख', '#1a5f8a', '#e8f4fc' ) );


     var tocContents = toc.querySelector( '.vector-toc-contents' );
     var tocContents = toc.querySelector( '.vector-toc-contents' );
Line 296: Line 289:


   // ── TOC active-item highlight ────────────────────────────────────
   // ── TOC active-item highlight ────────────────────────────────────
  // Uses MutationObserver on each <li> to apply/remove orange colour and
   // v7: inactive items get font-weight:400 explicitly — only active gets 700.
  // bold imperatively — bypasses CSS specificity entirely.
  //
   // v7 change: inactive items get font-weight:400 explicitly set so that
  // no CSS rule can accidentally make them bold. Only the active item
  // gets font-weight:700. This replaces all the level-1/2/3 bold rules
  // in the CSS that were also making non-active headings bold.
   function watchTocActive() {
   function watchTocActive() {
     if ( _isNoTocPage() ) return;
     if ( _isNoTocPage() ) return;
Line 358: Line 345:


         if ( active ) {
         if ( active ) {
           /* Expand any collapsed ancestor sections */
           // Expand collapsed ancestor sections
           var anc = li.parentNode;
           var anc = li.parentNode;
           while ( anc && anc !== document.body ) {
           while ( anc && anc !== document.body ) {
Line 369: Line 356:
           }
           }


           /* Scroll active item into visible TOC area */
           // Scroll active item into visible TOC area
           var container = document.querySelector( '.vector-sticky-pinned-container' );
           var container = document.querySelector( '.vector-sticky-pinned-container' );
           if ( container ) {
           if ( container ) {
Line 384: Line 371:
                   var ov = window.getComputedStyle( node ).overflowY;
                   var ov = window.getComputedStyle( node ).overflowY;
                   if ( ( ov === 'auto' || ov === 'scroll' ) &&
                   if ( ( ov === 'auto' || ov === 'scroll' ) &&
                       node.scrollHeight > node.clientHeight ) {
                       node.scrollHeight > node.clientHeight ) { sh = node; break; }
                    sh = node; break;
                  }
                   node = node.parentNode;
                   node = node.parentNode;
                 }
                 }
Line 409: Line 394:
           if ( n.classList && n.classList.contains( 'vector-toc-list-item' ) ) attachHighlight( n );
           if ( n.classList && n.classList.contains( 'vector-toc-list-item' ) ) attachHighlight( n );
           if ( n.querySelectorAll ) n.querySelectorAll( '.vector-toc-list-item' ).forEach( attachHighlight );
           if ( n.querySelectorAll ) n.querySelectorAll( '.vector-toc-list-item' ).forEach( attachHighlight );
           var newSpans = [];
           var newSpans = [];
           if ( n.classList && n.classList.contains( 'vector-toc-text' ) ) newSpans.push( n );
           if ( n.classList && n.classList.contains( 'vector-toc-text' ) ) newSpans.push( n );
Line 465: Line 449:
     removeHiddenEls();
     removeHiddenEls();


    /* ── Teeka view-mode detection ──────────────────────────────── */
     ( function detectTeekaMode() {
     ( function detectTeekaMode() {
       var tp = document.querySelector( '.gr-teeka-page' );
       var tp = document.querySelector( '.gr-teeka-page' );
Line 478: Line 461:
       }
       }
       var ref = document.referrer || '';
       var ref = document.referrer || '';
       document.body.classList.add( ( ref && primary && ref.indexOf( mainUrl ) !== -1 )
       document.body.classList.add(
        ? 'gr-ref-mode' : 'gr-standalone' );
        ( ref && primary && ref.indexOf( mainUrl ) !== -1 ) ? 'gr-ref-mode' : 'gr-standalone'
      );
     }() );
     }() );


Line 512: Line 496:
     else { currentScript = 'deva'; }
     else { currentScript = 'deva'; }


     /* TOC setup — Vector 2022 defers TOC render, retry at 300ms / 800ms */
     // Vector 2022 defers TOC render retry at 300ms and 800ms
     setupToc();
     setupToc();
     setTimeout( setupToc, 300 );
     setTimeout( setupToc, 300 );
Line 524: Line 508:
   } );
   } );


   // ── MediaWiki SPA-style navigation hook ─────────────────────────
   // ── MediaWiki SPA-style navigation ──────────────────────────────
   if ( window.mw ) {
   if ( window.mw ) {
     mw.hook( 'wikipage.content' ).add( function () {
     mw.hook( 'wikipage.content' ).add( function () {
Line 553: Line 537:
   }
   }


}() );  /* ← end of main transliteration / TOC IIFE */
}() );  /* ← end of main IIFE */




// ── Inject "About" link into the header ────────────────────────────
// ── Inject "About" link into the header ────────────────────────────
// Own IIFE — was incorrectly nested inside main IIFE in v6 (the missing
// Separate IIFE — v6 had this nested inside the main IIFE without a
// }() ); broke the module boundary and killed the by-Author toggle).
// closing }() ); which broke the module boundary and killed the
// by-Author toggle on the main page.
( function () {
( function () {
   function injectAboutLink() {
   function injectAboutLink() {
Line 568: Line 553:
     if ( !headerEnd ) return;
     if ( !headerEnd ) return;


     /* Build the URL correctly for any sub-path install.
     // mw.util.getUrl() uses wgArticlePath internally, so it always produces
    * wgArticlePath looks like "/My_wiki/index.php/$1" or "/wiki/$1".
    // the correct URL regardless of whether the wiki is at / or /My_wiki/.
    * mw.util.getUrl() uses that internally, so it always produces the
    * right URL for whatever MediaWiki thinks its own root is. */
     var href;
     var href;
     if ( window.mw && mw.util && mw.util.getUrl ) {
     if ( window.mw && mw.util && mw.util.getUrl ) {
Line 580: Line 563:
     }
     }


     var a   = document.createElement( 'a' );
     var a = document.createElement( 'a' );
     a.id   = 'gr-about-link';
     a.id = 'gr-about-link';
     a.href = href;
     a.href = href;
     a.textContent = 'About';
     a.textContent = 'About';
     a.style.cssText = [
     a.style.cssText = [
Line 592: Line 575:
     ].join( ';' );
     ].join( ';' );
     a.addEventListener( 'mouseover', function () {
     a.addEventListener( 'mouseover', function () {
       this.style.color = '#fff'; this.style.background = 'rgba(255,255,255,0.12)';
       this.style.color = '#fff';
      this.style.background = 'rgba(255,255,255,0.12)';
     } );
     } );
     a.addEventListener( 'mouseout', function () {
     a.addEventListener( 'mouseout', function () {
       this.style.color = 'rgba(255,255,255,0.88)'; this.style.background = 'transparent';
       this.style.color = 'rgba(255,255,255,0.88)';
      this.style.background = 'transparent';
     } );
     } );