MediaWiki:Gadget-GrAnnotations.js: Difference between revisions

No edit summary
No edit summary
Line 60: Line 60:
   var $fbComposer, $fbIssueType, $fbText, $fbEmail, $fbSubmit, $fbQuote;
   var $fbComposer, $fbIssueType, $fbText, $fbEmail, $fbSubmit, $fbQuote;
   // CHANGED: added $tabFootnotes / $paneFootnotes alongside the existing
   // CHANGED: added $tabFootnotes / $paneFootnotes alongside the existing
   // Notes/Bookmarks tab+pane refs, for the new Footnotes tab.
   // Notes/Bookmarks tab+pane refs, for the Footnotes tab. NEW: now also
   var $tabNotes, $tabBookmarks, $tabFootnotes, $paneNotes, $paneBookmarks, $paneFootnotes;
  // $tabSandarbha / $paneSandarbha, for References.
   var $tabNotes, $tabBookmarks, $tabFootnotes, $tabSandarbha, $paneNotes, $paneBookmarks, $paneFootnotes, $paneSandarbha;


   function buildDom() {
   function buildDom() {
Line 168: Line 169:
       '    <button class="gra-tab" id="gra-tab-footnotes">',
       '    <button class="gra-tab" id="gra-tab-footnotes">',
       '      <span class="gra-icon gra-icon-footnote" aria-hidden="true"></span> Footnotes',
       '      <span class="gra-icon gra-icon-footnote" aria-hidden="true"></span> Footnotes',
      '    </button>',
      '    <button class="gra-tab" id="gra-tab-sandarbha">',
      '      <span class="gra-icon gra-icon-sandarbha" aria-hidden="true"></span> References',
       '    </button>',
       '    </button>',
       '  </div>',
       '  </div>',
Line 174: Line 178:
       '    <div class="gra-pane" id="gra-pane-bookmarks"></div>',
       '    <div class="gra-pane" id="gra-pane-bookmarks"></div>',
       '    <div class="gra-pane" id="gra-pane-footnotes"></div>',
       '    <div class="gra-pane" id="gra-pane-footnotes"></div>',
      '    <div class="gra-pane" id="gra-pane-sandarbha"></div>',
       '  </div>',
       '  </div>',
       '</div>',
       '</div>',
Line 197: Line 202:
     $tabBookmarks = $('#gra-tab-bookmarks');
     $tabBookmarks = $('#gra-tab-bookmarks');
     $tabFootnotes = $('#gra-tab-footnotes');
     $tabFootnotes = $('#gra-tab-footnotes');
    $tabSandarbha = $('#gra-tab-sandarbha');
     $paneNotes    = $('#gra-pane-notes');
     $paneNotes    = $('#gra-pane-notes');
     $paneBookmarks= $('#gra-pane-bookmarks');
     $paneBookmarks= $('#gra-pane-bookmarks');
     $paneFootnotes= $('#gra-pane-footnotes');
     $paneFootnotes= $('#gra-pane-footnotes');
    $paneSandarbha= $('#gra-pane-sandarbha');
     $ntInput      = $('#gra-nt-input');
     $ntInput      = $('#gra-nt-input');
     $ntSubmit    = $('#gra-nt-submit');
     $ntSubmit    = $('#gra-nt-submit');
Line 464: Line 471:
     $tabBookmarks.toggleClass('gra-tab-active', tab==='bookmarks');
     $tabBookmarks.toggleClass('gra-tab-active', tab==='bookmarks');
     $tabFootnotes.toggleClass('gra-tab-active', tab==='footnotes');
     $tabFootnotes.toggleClass('gra-tab-active', tab==='footnotes');
    $tabSandarbha.toggleClass('gra-tab-active', tab==='sandarbha');
     $paneNotes.toggleClass('gra-pane-active', tab==='notes');
     $paneNotes.toggleClass('gra-pane-active', tab==='notes');
     $paneBookmarks.toggleClass('gra-pane-active', tab==='bookmarks');
     $paneBookmarks.toggleClass('gra-pane-active', tab==='bookmarks');
     $paneFootnotes.toggleClass('gra-pane-active', tab==='footnotes');
     $paneFootnotes.toggleClass('gra-pane-active', tab==='footnotes');
    $paneSandarbha.toggleClass('gra-pane-active', tab==='sandarbha');
     if (tab==='notes') renderNoteCards();
     if (tab==='notes') renderNoteCards();
     else if (tab==='bookmarks') renderBookmarkCards();
     else if (tab==='bookmarks') renderBookmarkCards();
     else renderFootnoteCards();
     else if (tab==='footnotes') renderFootnoteCards();
    else renderSandarbhaCards();
   }
   }


Line 570: Line 580:
     });
     });
     $paneFootnotes.html(html);
     $paneFootnotes.html(html);
  }
  // NEW: References (Sandarbha) tab. Simpler than footnotes — reads
  // straight off .gra-qe-sandarbha-highlight elements, no separate list
  // to scan. The highlighted text itself is the primary line (matching
  // how Notes/Bookmarks already identify themselves by quote); the
  // reference content stored in the hidden nested span is secondary.
  // Deliberately excludes that hidden span's own text when computing the
  // quote — el.textContent alone would include it too, regardless of its
  // display:none.
  function renderSandarbhaCards() {
    var items = document.querySelectorAll(CONTENT_SEL + ' .gra-qe-sandarbha-highlight');
    if (!items.length) {
      $paneSandarbha.html('<div class="gra-empty-state">No references on this page.</div>');
      return;
    }
    var html = '';
    Array.prototype.forEach.call(items, function (el) {
      var contentSpan = el.querySelector('.gra-qe-sandarbha-content');
      var refText = contentSpan ? contentSpan.textContent : '';
      var quote = '';
      Array.prototype.forEach.call(el.childNodes, function (node) {
        if (node === contentSpan) return;
        quote += node.textContent || '';
      });
      var id = el.getAttribute('data-gra-id') || '';
      html += '<div class="gra-bookmark-card gra-sandarbha-card" data-gra-id="'+esc(id)+'">'
            + '<span class="gra-icon gra-icon-sandarbha" aria-hidden="true"></span>'
            + '<div class="gra-bookmark-info">'
            + '<div class="gra-bookmark-name">'+esc(quote)+'</div>'
            + (refText ? '<div class="gra-bookmark-quote">'+esc(refText)+'</div>' : '')
            + '</div>'
            + '</div>';
    });
    $paneSandarbha.html(html);
   }
   }


Line 751: Line 796:
     // NEW: third tab.
     // NEW: third tab.
     $tabFootnotes.on('click', function(){ switchTab('footnotes'); });
     $tabFootnotes.on('click', function(){ switchTab('footnotes'); });
    // NEW: fourth tab.
    $tabSandarbha.on('click', function(){ switchTab('sandarbha'); });


     $paneNotes.on('click', '.gra-note-card', function(e){
     $paneNotes.on('click', '.gra-note-card', function(e){
Line 778: Line 825:
     // that broke every time the marker format changed.
     // that broke every time the marker format changed.
     $paneFootnotes.on('click', '.gra-footnote-card', function(){
     $paneFootnotes.on('click', '.gra-footnote-card', function(){
      var id = $(this).attr('data-gra-id');
      if (id) { closePanel(); scrollToHighlight(id); }
    });
    // NEW: same reuse for Sandarbha - it was designed from the start to
    // carry data-gra-id for exactly this reason.
    $paneSandarbha.on('click', '.gra-sandarbha-card', function(){
       var id = $(this).attr('data-gra-id');
       var id = $(this).attr('data-gra-id');
       if (id) { closePanel(); scrollToHighlight(id); }
       if (id) { closePanel(); scrollToHighlight(id); }
Line 811: Line 864:
       setTimeout(function(){
       setTimeout(function(){
         var $card = $paneFootnotes.find('[data-gra-id="'+id+'"]');
         var $card = $paneFootnotes.find('[data-gra-id="'+id+'"]');
        if ($card.length) {
          $card.addClass('gra-card-active');
          $card[0].scrollIntoView({behavior:'smooth', block:'nearest'});
          setTimeout(function(){ $card.removeClass('gra-card-active'); }, 2000);
        }
      }, 100);
    });
    // NEW: same pattern for Sandarbha highlights.
    $(CONTENT_SEL).on('click', '.gra-qe-sandarbha-highlight', function(){
      var id = $(this).attr('data-gra-id');
      openPanel('sandarbha');
      setTimeout(function(){
        var $card = $paneSandarbha.find('[data-gra-id="'+id+'"]');
         if ($card.length) {
         if ($card.length) {
           $card.addClass('gra-card-active');
           $card.addClass('gra-card-active');