MediaWiki:Common.js: Difference between revisions

No edit summary
No edit summary
Tag: Reverted
Line 179: Line 179:


   // ── TOC: rename "Contents" → "विषयसूची" ────────────────────────
   // ── TOC: rename "Contents" → "विषयसूची" ────────────────────────
function renameTocTitle() {
  function renameTocTitle() {
  if ( _isNoTocPage() ) return;
    if ( _isNoTocPage() ) return;
 
    var toc = document.querySelector( '.vector-toc' );
  var toc = document.querySelector('.vector-toc');
    if ( !toc ) return;
  if ( !toc ) return;
    var titleEl = toc.querySelector( '.vector-toc-title' );
 
     if ( !titleEl ) return;
  var titleEl =
    var TITLE = 'विषयसूची';
    toc.querySelector('.vector-toc-title') ||
    var replaced = false;
     toc.querySelector('.vector-pinnable-header-label');
    titleEl.childNodes.forEach( function ( n ) {
 
      if ( n.nodeType === 3 && n.textContent.trim() ) {
  if ( !titleEl ) return;
        n.textContent = TITLE;
 
        replaced = true;
  var LABEL = 'विषयसूची';
      }
 
    } );
  /* If already inserted, just refresh text */
    if ( !replaced && titleEl.childElementCount === 0 ) {
  var span = titleEl.querySelector('.gr-toc-title');
      titleEl.textContent = TITLE;
 
    }
  if ( !span ) {
     // Fix up any <span data-deva> wrappers that tagTextNodes created
    titleEl.innerHTML = '';
    // over "Contents" — update their data-deva to the new Sanskrit text
 
    titleEl.querySelectorAll( '[data-deva]' ).forEach( function ( span ) {
     span = document.createElement('span');
      span.setAttribute( 'data-deva', TITLE );
    span.className = 'gr-toc-title';
      if ( currentScript !== 'deva' ) {
    span.setAttribute('data-deva', LABEL);
        span.textContent = transliterateText( TITLE, currentScript );
 
      } else {
    titleEl.appendChild(span);
        span.textContent = TITLE;
     translatableSpans.push(span);   // uses your internal array
      }
     } );
   }
   }


  span.textContent =
    currentScript === 'deva'
      ? LABEL
      : transliterateText(LABEL, currentScript);
}
   // ── TOC: Remove the "Beginning" / top-of-page link ─────────────
   // ── TOC: Remove the "Beginning" / top-of-page link ─────────────
   function removeTocBeginning() {
   function removeTocBeginning() {
Line 617: Line 613:
     }
     }


     // Track which anchors are visible
     // ── Scroll-based active anchor detection ──────────────────────
     var _visibleIds = new Set();
    // Find the last anchor whose top edge is above the scroll threshold
    // (1/3 of viewport height). This is robust for zero-height anchor spans
    // and matches how the ref site tracks active sections.
     var SCROLL_THRESHOLD_RATIO = 0.33; // top 1/3 of viewport


     var observer = new IntersectionObserver( function ( entries ) {
     function findActiveAnchor() {
       entries.forEach( function ( entry ) {
       var threshold = window.innerHeight * SCROLL_THRESHOLD_RATIO;
         var id = entry.target.id;
      var best = null;
         if ( entry.isIntersecting ) {
      // Walk anchors in order; keep updating best as long as anchor is above threshold
           _visibleIds.add( id );
      for ( var k = 0; k < anchors.length; k++ ) {
         var r = anchors[ k ].getBoundingClientRect();
        // Use top of the heading AFTER the anchor (anchor is height:0)
        // The anchor has padding-top:60px so its effective visual top is r.top
         if ( r.top <= threshold ) {
           best = anchors[ k ].id;
         } else {
         } else {
           _visibleIds.delete( id );
           break; // anchors are in document order — no need to continue
         }
         }
       } );
       }
      return best;
    }


      // Find the topmost visible anchor
    var _scrollRaf = null;
      var topId = null;
    function onScroll() {
       var topY  = Infinity;
       if ( _scrollRaf ) return;
       _visibleIds.forEach( function ( id ) {
       _scrollRaf = requestAnimationFrame( function () {
         var el = document.getElementById( id );
         _scrollRaf = null;
         if ( el ) {
         setTocActive( findActiveAnchor() );
          var y = el.getBoundingClientRect().top;
          if ( y < topY ) { topY = y; topId = id; }
        }
       } );
       } );
    }


      // If nothing visible (scrolled past), find the last anchor above viewport
    window.addEventListener( 'scroll', onScroll, { passive: true } );
      if ( !topId ) {
    // Also run once on load so initial position is highlighted
        var best = null, bestBottom = -Infinity;
     setTimeout( function () { setTocActive( findActiveAnchor() ); }, 200 );
        anchors.forEach( function ( span ) {
          var r = span.getBoundingClientRect();
          if ( r.bottom < 80 && r.bottom > bestBottom ) {
            bestBottom = r.bottom;
            best = span.id;
          }
        } );
        topId = best;
      }
 
      setTocActive( topId );
    }, { rootMargin: '-60px 0px -70% 0px', threshold: 0 } );
 
     anchors.forEach( function ( span ) { observer.observe( span ); } );
   }
   }


Line 986: Line 976:
     wireUllekhaLinks();
     wireUllekhaLinks();
   }
   }
}() );
// ── Special pages: remove MW branding + wire "Forgot password" ───────
// Runs on Special:UserLogin, Special:CreateAccount, Special:UserLogout
// Hides all elements that reveal the site is built on MediaWiki.
( function () {
  var ns = window.mw && mw.config.get( 'wgNamespaceNumber' );
  if ( ns !== -1 ) return;  // -1 = Special namespace
  var specialPage = ( window.mw && mw.config.get( 'wgCanonicalSpecialPageName' ) ) || '';
  var isLogin    = specialPage === 'Userlogin';
  var isCreate  = specialPage === 'CreateAccount';
  var isLogout  = specialPage === 'UserLogout';
  var isPwReset  = specialPage === 'PasswordReset';
  function hideEl( sel ) {
    document.querySelectorAll( sel ).forEach( function ( el ) {
      el.style.setProperty( 'display', 'none', 'important' );
    } );
  }
  function cleanSpecialPage() {
    // ── Always: remove "Powered by MediaWiki" and footer ─────────────
    hideEl( '#footer, .mw-footer, #footer-icons, #footer-places' );
    hideEl( 'a[href*="mediawiki.org"], img[alt*="MediaWiki"]' );
    hideEl( '#mw-panel, .vector-sidebar, .vector-sidebar-container' );
    if ( isLogin ) {
      // "Help with logging in" → external MW help link
      hideEl( '.mw-userlogin-help' );
      // "Don't have an account?" CTA block + avatar
      hideEl( '#mw-createaccount-cta' );
      hideEl( '.mw-createacct-benefits-container' );
      // "Forgot your password?" — replace href with mailto
      document.querySelectorAll( 'a[href*="PasswordReset"], .mw-userlogin-forgotpassword a' )
        .forEach( function ( a ) {
          a.href = 'mailto:feedback@anandamakaranda.in?subject=Password%20Reset%20Request';
          a.textContent = 'Forgot your password?';
        } );
    }
    if ( isCreate ) {
      hideEl( '.mw-createacct-benefits-container' );
      hideEl( '.mw-createacct-help' );
      // Replace any MW-branded heading
      var h1 = document.querySelector( '#firstHeading, h1.firstHeading' );
      if ( h1 ) h1.style.display = 'none';
    }
  }
  if ( document.readyState === 'loading' ) {
    document.addEventListener( 'DOMContentLoaded', cleanSpecialPage );
  } else {
    cleanSpecialPage();
  }
  // Re-run after a short delay in case Vector injects elements dynamically
  setTimeout( cleanSpecialPage, 500 );
}() );
}() );