MediaWiki:Gadget-GrAnnotations.js: Difference between revisions

No edit summary
No edit summary
Line 359: Line 359:
   function openCommentComposer() {
   function openCommentComposer() {
     hideFab();
     hideFab();
    // Keep selection alive — blur the textarea briefly then refocus
     positionComposer( $cmpComposer );
     positionComposer( $cmpComposer );
     $cmpComposer.addClass('gra-composer-visible');
     $cmpComposer.addClass('gra-composer-visible');
     $cmpInput.val('').focus();
    // Don't focus the textarea — it's hidden until "Others" chip is selected.
    // Focus the composer container so Escape key works.
     $cmpComposer[0].focus && $cmpComposer[0].setAttribute('tabindex', '-1');
   }
   }


Line 468: Line 469:
                   + commentText.slice(0,500)
                   + commentText.slice(0,500)
                   + ( commentText.length > 500 ? '\n...' : '' )
                   + ( commentText.length > 500 ? '\n...' : '' )
                   + '\n\n[[User:Chandrashekars|Chandrashekars]] ([[User talk:Chandrashekars|talk]]) 18:21, 25 April 2026 (UTC)';
                   + '\n\n[[User:Chandrashekars|Chandrashekars]] ([[User talk:Chandrashekars|talk]]) 18:31, 25 April 2026 (UTC)';
       new mw.Api().postWithEditToken({
       new mw.Api().postWithEditToken({
         action:'edit', title:'User_talk:' + ADMIN_USER, section:'new',
         action:'edit', title:'User_talk:' + ADMIN_USER, section:'new',
Line 676: Line 677:


     // ── Selection → show FAB ──────────────────────────────────────
     // ── Selection → show FAB ──────────────────────────────────────
     $( document ).on('mouseup keyup', function(e){
    // On mouseup: capture the selection and show the FAB strip.
       // Skip if a composer is open
    // We use mouseup (not click) so the selection is fully made.
       if ( $cmpComposer.hasClass('gra-composer-visible') ) return;
     $( document ).on('mouseup', function(e){
       if ( $bmComposer.hasClass('gra-composer-visible') ) return;
       // Ignore mouseup on FAB/composer — those are handled separately
      // Skip mouseup that originated inside the FAB itself
       if ( $(e.target).closest('#gra-fab, .gra-composer, .gra-bm-composer').length ) return;
      if ( $(e.target).closest('#gra-fab').length ) return;
      // Ignore if a composer is already open
      // Delay slightly so selection is fully committed by browser
       if ( $cmpComposer.hasClass('gra-composer-visible') ||
          $bmComposer.hasClass('gra-composer-visible') ) return;
       setTimeout(function(){
       setTimeout(function(){
         if ( captureSelection() ) {
         if ( captureSelection() ) {
           showFab( _selRect );
           showFab( _selRect );
         } else {
         } else {
           // Only hide if a composer isn't open
           hideFab();
          if ( !$cmpComposer.hasClass('gra-composer-visible') &&
              !$bmComposer.hasClass('gra-composer-visible') ) {
            hideFab();
          }
         }
         }
       }, 30);
       }, 10);
     });
     });


     // ── FAB mousedown — prevent browser from collapsing selection ────
     // ── FAB mousedown: block selection collapse ───────────────────
     // Browsers collapse the text selection on mousedown. Calling
     // Browsers collapse text selection on mousedown. preventDefault
     // preventDefault() on the FAB buttons stops that, keeping _selRange
     // keeps the selection alive so the click handler can wrap it.
    // valid so the subsequent click handler can use it.
     $fab.on('mousedown', function(e){
     $fab.on('mousedown', function(e){
       e.preventDefault();
       e.preventDefault();
     });
     });


     // ── Click outside hide FAB ──────────────────────────────────
     // ── Mousedown outside: hide FAB ───────────────────────────────
     $( document ).on('mousedown', function(e){
     $( document ).on('mousedown', function(e){
       var $t = $(e.target);
       var $t = $(e.target);
       if ( !$t.closest('#gra-fab').length &&
       if ( !$t.closest('#gra-fab, .gra-composer, .gra-bm-composer, #gra-toggle, #gra-panel').length ) {
          !$t.closest('.gra-composer').length &&
          !$t.closest('.gra-bm-composer').length ) {
         hideFab();
         hideFab();
       }
       }
     });
     });


     // ── FAB: Comment ──────────────────────────────────────────────
     // ── FAB: Comment button ───────────────────────────────────────
    // Use saved _selRange — do NOT call captureSelection() here.
    // By the time a click fires, mousedown has already collapsed
    // the browser selection, so getSelection() returns empty.
     $( '#gra-fab-comment' ).on('click', function(e){
     $( '#gra-fab-comment' ).on('click', function(e){
      e.preventDefault();
       e.stopPropagation();
       e.stopPropagation();
      if ( !_selRange ) return;
       openCommentComposer();
       openCommentComposer();
     });
     });


     // ── FAB: Bookmark ─────────────────────────────────────────────
     // ── FAB: Bookmark button ──────────────────────────────────────
     $( '#gra-fab-bookmark' ).on('click', function(e){
     $( '#gra-fab-bookmark' ).on('click', function(e){
      e.preventDefault();
       e.stopPropagation();
       e.stopPropagation();
      if ( !_selRange ) return;
       openBookmarkComposer();
       openBookmarkComposer();
     });
     });