1

In addition to MouseEvents I'd like to use a "long" TouchEvent of a single finger/digit/input for my application (change mode, e.g. to start drawing or select elements to manipulate), while retaining all default actions like clicking/tapping, scrolling/swiping and hold-for-context-menu or hold-to-select.

In other words:

  1. a short touch (tap) should be analogous to a normal mouse click (usually emulated by browser)
  2. (short) touch and move (swipe) should cause normal scrolling
  3. a "longer" touch should be analogous to a mouse click-and-hold
  4. consequent move events should not cause scrolling but are handled by the application
  5. a long touch without move should cause normal secondary function (select, context-menu)
  6. pinch and other multi-touch gestures should use default handlers (for now)

There is no "hold-to-select" or similar event to my knowledge, so I am attempting to implement this myself.

Detecting a "long" touch before drag is quite simple (setTimeout(), e.g. How to detect a long touch pressure with javascript for android and iphone?), however, the initial touchstart already seems to trigger default event handlers, causing

  • no scrolling (intended)
    • Chrome on Windows
    • Chrome on Android
  • scrolling
    • Safari on iOS (iPhone)
    • Firefox on Windows and Android
  • secondary functions
    • select (not intended if move occurs)
      • Safari on iOS (iPhone)
    • magnifier (not intended if move occurs)
      • Safari on iOS (iPhone)
    • context-menu (intended, when no move occurs)
    • Chrome on Windows: as intended (very long touch, no move)
    • Firefox on Windows: as intended (very long touch, no move)
    • Chrome on Android: none
    • Firefox on Android: none

on actual devices, despite preventDefault() and stopPropagation() calls from touchmove.

  • is there a "better" way already (an event I don't know about)?
  • is it possible to retroactively affect these envents/handlers (revert/undo events?)?
  • is there a way to determine the default actions (select, context menu) and the respective timeout (browser / OS implementation dependant)?

or

  • will I have to re-implement the very low-level handlers myself and then create and emit the necessary events (keeping different browser implementations in mind)?

Here's a preliminary snippet for testing (feel free to improve/extend):

let t = document.getElementById("t");
t.innerHTML += navigator.userAgent + '<br/>'; 

// timer
var timerid;
var touchduration = 500;
var longtouch = false;
function lt(e){
  timerid = undefined;
  longtouch = true;
  e.preventDefault();
  e.stopPropagation();
  ls("LONG");
}
function ct(){if (timerid)window.clearTimeout(timer); timerid = undefined;}

function ls(s){
  t.innerHTML += i + ' ' + s + '<br/>';  
  t.scrollTop = t.scrollHeight;
}

// log event
let i = 0;
let o;
function le(e){
  if (e.type!=o){
    ls( e.type + (longtouch?' LONG':'') );
    o = e.type;
    }
  i++;
}

// mouse
t.addEventListener("mouseenter",  e=>{le(e);});
t.addEventListener("mousedown",   e=>{le(e);});
t.addEventListener("mouseup",     e=>{le(e);});
t.addEventListener("mousemove",   e=>{le(e);});
t.addEventListener("mouseout",    e=>{le(e);});
t.addEventListener("mouseleave",  e=>{le(e);});

t.addEventListener("click",     e=>{le(e);});
t.addEventListener("dblclick",   e=>{le(e);});
t.addEventListener("auxclick",   e=>{le(e);});

// wheel
t.addEventListener("wheel",       e=>{le(e);});

// touch
t.addEventListener("touchstart",  e=>{le(e); 
  timerid = window.setTimeout(lt, 500, e);
  });
t.addEventListener("touchend",    e=>{le(e);
  ct();
  longtouch = false;
  });
t.addEventListener("touchmove",   e=>{le(e);
  ct();
  if (longtouch) {
    e.preventDefault();
    e.stopPropagation();
    //e.stopImmediatePropagation();
    }
  });
t.addEventListener("touchcancel", e=>{le(e);});


t.addEventListener("drag",        e=>{le(e);});

t.addEventListener("scroll",      e=>{le(e);});

t.addEventListener("contextmenu", e=>{le(e);});
t.addEventListener("select",      e=>{le(e);});
<div id="t" style="height:10em; max-height:100%; overflow-y:scroll; border: 1px solid green;"/>
handle
  • 5,859
  • 3
  • 54
  • 82
  • It might be an issue in Firefox - Chrome handles it better (does not scroll page). Tested on Windows and Android. – handle Mar 09 '20 at 13:55

0 Answers0