MediaWiki:Common.js: Difference between revisions

No edit summary
No edit summary
Line 90: Line 90:
       'क':'க','ख':'க','ग':'க','घ':'க','ङ':'ங',
       'क':'க','ख':'க','ग':'க','घ':'க','ङ':'ங',
       'च':'ச','छ':'ச','ज':'ஜ','झ':'ஜ','ञ':'ஞ',
       'च':'ச','छ':'ச','ज':'ஜ','झ':'ஜ','ञ':'ஞ',
       '':'ட','ठ':'ட','ड':'ட','ढ':'ட','ண':'ண',
       '':'ட','ठ':'ட','ड':'ட','ढ':'ட','ண':'ண',
       'त':'த','थ':'த','द':'த','ध':'த','न':'ந',
       'त':'த','थ':'த','द':'த','ध':'த','न':'ந',
       'प':'ப','फ':'ப','ब':'ப','भ':'ப','म':'ம',
       'प':'ப','फ':'ப','ब':'ப','भ':'ப','म':'ம',
       'य':'ய','र':'ர','':'ல','ळ':'ழ','व':'வ',
       'य':'ய','र':'ர','':'ல','ळ':'ழ','व':'வ',
       'श':'ஶ','ष':'ஷ','स':'ஸ','ह':'ஹ',
       'श':'ஶ','ष':'ஷ','स':'ஸ','ह':'ஹ',
       'ा':'ா','ि':'ி','ी':'ீ','ு':'ு','ू':'ூ',
       'ा':'ா','ि':'ி','ी':'ீ','ு':'ு','ू':'ூ',
Line 138: Line 138:
           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;
           // #gr-toc-doc-nav buttons manage their own data-deva spans in makeBtn
         }
         }
         var orig = node.textContent;
         var orig = node.textContent;
Line 251: Line 251:
     var ullekhaUrl = wikiUrl( primarySlug + '/Ullekha' );
     var ullekhaUrl = wikiUrl( primarySlug + '/Ullekha' );


    /* ── Button visibility rules ────────────────────────────────────────
    *
    * Three separate concepts share the label "मूल" depending on page type:
    *
    *  1. On a BHASHYA page (e.g. Bhagavadgitabhashya):
    *      मूलम् → /Moola  (verse-text-only filtered view of the same doc)
    *      Shown when the importer set data-has-moola on .gr-doc-title.
    *
    *  2. On a TEEKA page (e.g. Nyayasudha):
    *      मूल  → the primary bhashya this teeka comments on (Anuvyakhyana)
    *      Always shown on teeka pages (teekaPage div is present).
    *
    *  उल्लेख:
    *      Shown on bhashya pages when data-has-ullekha is set, or on
    *      teeka pages (links to primary bhashya's Ullekha page).
    * ──────────────────────────────────────────────────────────────── */
     var docTitleEl  = document.querySelector( '.gr-doc-title' );
     var docTitleEl  = document.querySelector( '.gr-doc-title' );
     var hasMoolaPage  = docTitleEl && docTitleEl.getAttribute( 'data-has-moola' )  === '1';
     var hasMoolaPage  = docTitleEl && docTitleEl.getAttribute( 'data-has-moola' )  === '1';
     var hasUllekhaPage = docTitleEl && docTitleEl.getAttribute( 'data-has-ullekha' ) === '1';
     var hasUllekhaPage = docTitleEl && docTitleEl.getAttribute( 'data-has-ullekha' ) === '1';


    /* On a bhashya page, मूलम् links to the /Moola sub-page */
     var moolaPageUrl = wikiUrl( primarySlug + '/Moola' );
     var moolaPageUrl = wikiUrl( primarySlug + '/Moola' );


    /* On a teeka page, मूल links to the primary bhashya (already in moolaUrl) */
     var showMoolaPage  = !teekaPage && hasMoolaPage;
     var showMoolaPage  = !teekaPage && hasMoolaPage;   /* bhashya → /Moola */
     var showMoolaBack  = !!teekaPage;
     var showMoolaBack  = !!teekaPage;                   /* teeka  → primary bhashya */
     var showUllekha    = hasUllekhaPage || !!teekaPage;
     var showUllekha    = hasUllekhaPage || !!teekaPage;


Line 285: Line 267:
     nav.setAttribute( 'class', 'toc-main-links');
     nav.setAttribute( 'class', 'toc-main-links');


     var base = [
     // ── CHANGE: makeBtn now wraps label in a data-deva span so
      'display:inline-block', 'padding:2px 9px', 'border-radius:3px',
     // transliteration (script switching) applies to button text.
      'font-size:0.80em', 'font-weight:500', 'text-decoration:none',
      'border:1px solid currentColor', 'line-height:1.65',
      'white-space:nowrap', 'font-family:inherit',
     ].join( ';' );
 
     function makeBtn( href, label ) {
     function makeBtn( href, label ) {
       var a = document.createElement( 'a' );
       var a = document.createElement( 'a' );
       a.href = href;
       a.href = href;
      a.textContent = label;
       a.setAttribute( 'class', 'toc-main-link-item');
       a.setAttribute( 'class', 'toc-main-link-item');
      var lspan = document.createElement( 'span' );
      lspan.setAttribute( 'data-deva', label );
      lspan.textContent = ( currentScript && currentScript !== 'deva' )
        ? transliterateText( label, currentScript )
        : label;
      translatableSpans.push( lspan );
      a.appendChild( lspan );
       a.addEventListener( 'mouseover', function () { this.style.opacity = '0.72'; } );
       a.addEventListener( 'mouseover', function () { this.style.opacity = '0.72'; } );
       a.addEventListener( 'mouseout',  function () { this.style.opacity = '1';    } );
       a.addEventListener( 'mouseout',  function () { this.style.opacity = '1';    } );
Line 302: Line 285:
     }
     }


    /* Bhashya page: show मूलम् (→ /Moola filtered view) */
     if ( showMoolaPage ) nav.appendChild( makeBtn( moolaPageUrl, 'मूलम्' ) );
     if ( showMoolaPage ) nav.appendChild( makeBtn( moolaPageUrl, 'मूलम्' ) );
    /* Teeka page: show मूल (→ primary bhashya) */
     if ( showMoolaBack ) nav.appendChild( makeBtn( moolaUrl,    'मूल' ) );
     if ( showMoolaBack ) nav.appendChild( makeBtn( moolaUrl,    'मूल' ) );
    /* Either page type: show उल्लेख when available */
     if ( showUllekha  ) nav.appendChild( makeBtn( ullekhaUrl,  'उल्लेख') );
     if ( showUllekha  ) nav.appendChild( makeBtn( ullekhaUrl,  'उल्लेख') );


Line 315: Line 295:


   // ── TOC active-item highlight ────────────────────────────────────
   // ── TOC active-item highlight ────────────────────────────────────
  // v7: inactive items get font-weight:400 explicitly — only active gets 700.
   function watchTocActive() {
   function watchTocActive() {
     if ( _isNoTocPage() ) return;
     if ( _isNoTocPage() ) return;
Line 333: Line 312:
       var link = li.querySelector( '.vector-toc-link' ) || li.querySelector( 'a' );
       var link = li.querySelector( '.vector-toc-link' ) || li.querySelector( 'a' );
       if ( !link ) return;
       if ( !link ) return;
      /* Only highlight as "active" if this is the LEAF active item —
      * i.e. no child list-item is also active. Vector marks both the
      * parent section AND the current sub-item as active. We only want
      * the innermost active item coloured orange. */
       var hasActiveChild = !!li.querySelector(
       var hasActiveChild = !!li.querySelector(
         '.vector-toc-list-item .vector-toc-list-item-active'
         '.vector-toc-list-item .vector-toc-list-item-active'
Line 379: Line 354:


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


          // 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 541: Line 514:
     if ( script ) applyScript( script );
     if ( script ) applyScript( script );
   } );
   } );
  // ── React to script changes from OTHER tabs (BroadcastChannel) ──
  try {
    var _grBC = new BroadcastChannel( 'gr-script' );
    _grBC.onmessage = function ( e ) {
      var script = e && e.data && e.data.script;
      if ( script ) {
        currentScript = script;
        var sel = document.querySelector( '.gr-script-sel' );
        if ( sel ) sel.value = script;
        applyScript( script );
      }
    };
  } catch ( e ) {}


   // ── MediaWiki SPA-style navigation ──────────────────────────────
   // ── MediaWiki SPA-style navigation ──────────────────────────────
Line 575: Line 562:


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


    // mw.util.getUrl() uses wgArticlePath internally, so it always produces
    // the correct URL regardless of whether the wiki is at / or /My_wiki/.
     var href;
     var href;
     if ( window.mw && mw.util && mw.util.getUrl ) {
     if ( window.mw && mw.util && mw.util.getUrl ) {
Line 665: Line 647:


// ── Ullekha reference link handler ─────────────────────────────────
// ── Ullekha reference link handler ─────────────────────────────────
// Two behaviours:
//  A) On the Ullekha page: clicking a .gr-ullekha-ref-link opens the
//      bhashya page at the anchor with a ?hlUllekha= param that triggers
//      highlight on arrival. Opens in the same tab (wiki navigation).
//  B) On the bhashya page: if URL has ?hlUllekha=<text>, find that text
//      in the page, scroll to it, and highlight it with a yellow background.
( function () {
( function () {


  // ── B) Bhashya page — highlight on arrival ──────────────────────
   function highlightOnArrival() {
   function highlightOnArrival() {
     var search = window.location.search;
     var search = window.location.search;
Line 686: Line 661:
     if ( !content ) return;
     if ( !content ) return;


    /* Walk all text nodes and find the first occurrence of needle.
    * We search in the textContent of every leaf element. */
     var walker = document.createTreeWalker( content, NodeFilter.SHOW_TEXT );
     var walker = document.createTreeWalker( content, NodeFilter.SHOW_TEXT );
     var found = false;
     var found = false;
Line 693: Line 666:
       var node = walker.currentNode;
       var node = walker.currentNode;
       var txt  = node.textContent || '';
       var txt  = node.textContent || '';
      /* partial match — needle may span multiple text nodes,
        so check for the first 30 chars */
       var snippet = needle.slice( 0, 30 );
       var snippet = needle.slice( 0, 30 );
       if ( txt.indexOf( snippet ) !== -1 ) {
       if ( txt.indexOf( snippet ) !== -1 ) {
Line 701: Line 672:
         span.style.cssText = 'background:#fff176;border-radius:2px;padding:0 2px;';
         span.style.cssText = 'background:#fff176;border-radius:2px;padding:0 2px;';
         var parent = node.parentNode;
         var parent = node.parentNode;
        /* Wrap the matching portion */
         var idx = txt.indexOf( snippet );
         var idx = txt.indexOf( snippet );
         if ( idx >= 0 ) {
         if ( idx >= 0 ) {
Line 712: Line 682:
           parent.insertBefore( after,  node );
           parent.insertBefore( after,  node );
           parent.removeChild( node );
           parent.removeChild( node );
          /* Scroll into view */
           setTimeout( function () {
           setTimeout( function () {
             span.scrollIntoView( { behavior: 'smooth', block: 'center' } );
             span.scrollIntoView( { behavior: 'smooth', block: 'center' } );
Line 722: Line 691:
   }
   }


  // ── A) Ullekha page — make ref links navigate with hlUllekha param ──
   function wireUllekhaLinks() {
   function wireUllekhaLinks() {
     document.querySelectorAll( '.gr-ullekha-ref-link' ).forEach( function ( wrap ) {
     document.querySelectorAll( '.gr-ullekha-ref-link' ).forEach( function ( wrap ) {
Line 730: Line 698:
       if ( !a ) return;
       if ( !a ) return;


      /* Rebuild the href to include ?hlUllekha= */
       var base = a.href.split( '#' )[ 0 ];
       var base = a.href.split( '#' )[ 0 ];
       var encoded = encodeURIComponent( hl );
       var encoded = encodeURIComponent( hl );