MediaWiki:Gadget-GrAnnotations.js: Difference between revisions

Undo revision 6155 by Vaishnavi (talk)
Tag: Undo
No edit summary
Line 1: Line 1:
/**
/**
  * gr_annotations.js  —  grantha.io inline Notes + Bookmarks + Feedback  (v6)
  * gr_annotations.js  —  grantha.io inline Notes + Bookmarks + Feedback  (v6 + Strategy B)
  */
  */


Line 37: Line 37:
   var _fabSelVer  = -1;
   var _fabSelVer  = -1;
   var _mobile    = window.innerWidth < 768 || 'ontouchstart' in window;
   var _mobile    = window.innerWidth < 768 || 'ontouchstart' in window;
   var _fabTouched = false;  // NEW: flag to prevent hideActions when tapping fab
   var _fabTouched = false;  // flag to prevent hideActions when tapping fab


   function uid() { return 'gra_' + Date.now() + '_' + Math.random().toString(36).slice(2,7); }
   function uid() { return 'gra_' + Date.now() + '_' + Math.random().toString(36).slice(2,7); }
Line 244: Line 244:
     if (_mobile) {
     if (_mobile) {
       fabW = 200; fabH = 48;
       fabW = 200; fabH = 48;
       top  = rect.top + window.scrollY - fabH - 14;
      /* Strategy B: place fab BELOW the selection — the native iOS/Android
        selection menu appears ABOVE it, so the two never collide. */
       top  = rect.bottom + window.scrollY + 14;
       left = rect.left + rect.width / 2 - fabW / 2;
       left = rect.left + rect.width / 2 - fabW / 2;
      /* Near viewport bottom: flip above, clearing the native bar (~42px) */
      if (rect.bottom + fabH + 22 > window.innerHeight) {
        top = rect.top + window.scrollY - fabH - 56;
      }
       top  = clamp(top,  window.scrollY + 8, window.scrollY + window.innerHeight - fabH - 8);
       top  = clamp(top,  window.scrollY + 8, window.scrollY + window.innerHeight - fabH - 8);
       left = clamp(left, 8, window.innerWidth - fabW - 8);
       left = clamp(left, 8, window.innerWidth - fabW - 8);
Line 527: Line 533:
   function wireEvents() {
   function wireEvents() {


     /* Suppress native context menu inside article content */
     /* Suppress native context menu inside article content (Android/desktop) */
     document.addEventListener('contextmenu', function(e) {
     document.addEventListener('contextmenu', function(e) {
       var tag = e.target.tagName;
       var tag = e.target.tagName;
Line 542: Line 548:
     });
     });


     /* Mobile: intercept selection as early as possible */
     /* Mobile: show fab once selection settles (~350ms, alongside native menu).
var _lastTouchEnd = 0;
      Strategy B: don't race the native menu — appear with it, in our own space. */
document.addEventListener('touchend', function(e) {
    var _lastTouchEnd = 0;
  if (!_mobile) return;
    document.addEventListener('touchend', function(e) {
  if ($fab[0] && $fab[0].contains(e.target)) return;
      if (!_mobile) return;
  _lastTouchEnd = Date.now();
      if ($fab[0] && $fab[0].contains(e.target)) return;
  clearTimeout(_selTimer);
      _lastTouchEnd = Date.now();
  /* Fire at 100ms — before browser popup (~300ms) */
      clearTimeout(_selTimer);
  _selTimer = setTimeout(tryShowActions, 100);
      _selTimer = setTimeout(function() {
}, { passive: true });
        var sel = window.getSelection();
        if (!sel || sel.isCollapsed || !sel.toString().trim()) return;
        tryShowActions();
      }, 350);
    }, { passive: true });


     /* selectionchange debounced */
    /* Mobile: reposition fab live while user drags the selection handles,
      hide it if selection is cleared */
    document.addEventListener('selectionchange', function() {
      if (!_mobile) return;
      if (!$fab.hasClass('gra-fab-visible')) return;
      clearTimeout(_selTimer);
      _selTimer = setTimeout(function() {
        var sel = window.getSelection();
        if (!sel || sel.isCollapsed || !sel.toString().trim()) { hideActions(); return; }
        if (captureSelection()) showFab(_selRect);
      }, 250);
    });
 
     /* selectionchange debounced (desktop) */
     var _selTimer = null;
     var _selTimer = null;
     document.addEventListener('selectionchange', function() {
     document.addEventListener('selectionchange', function() {