223 lines
7.0 KiB
JavaScript
223 lines
7.0 KiB
JavaScript
//thx http://stackoverflow.com/questions/1517924/javascript-mapping-touch-events-to-mouse-events#1781750
|
|
/*global jQuery*/
|
|
|
|
function touchHandler(event) {
|
|
"use strict";
|
|
|
|
const nn = event.target.nodeName.toLowerCase();
|
|
|
|
if (nn === "input" || nn === "select" || nn === "button" || nn === "textarea") {
|
|
return;
|
|
}
|
|
|
|
const touches = event.changedTouches;
|
|
const first = touches ? touches[0] : event;
|
|
let type = "";
|
|
|
|
switch (event.type) {
|
|
case "touchstart":
|
|
type = "mousedown";
|
|
break;
|
|
case "touchmove":
|
|
type = "mousemove";
|
|
break;
|
|
case "touchend":
|
|
type = "mouseup";
|
|
break;
|
|
case "tap":
|
|
type = "click";
|
|
break;
|
|
case "dbltap":
|
|
type = "dblclick";
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
//initMouseEvent(type, canBubble, cancelable, view, clickCount,
|
|
// screenX, screenY, clientX, clientY, ctrlKey,
|
|
// altKey, shiftKey, metaKey, button, relatedTarget);
|
|
|
|
const simulatedEvent = document.createEvent("MouseEvent");
|
|
simulatedEvent.initMouseEvent(type, true, true, window, 1,
|
|
first.screenX, first.screenY,
|
|
first.clientX, first.clientY, false,
|
|
false, false, false, 0/*left*/, null);
|
|
first.target.dispatchEvent(simulatedEvent);
|
|
event.preventDefault();
|
|
}
|
|
|
|
document.addEventListener("touchend", (function (speed, distance) {
|
|
// Copyright (c)2012 Stephen M. McKamey.
|
|
// Licensed under The MIT License.
|
|
// src: https://raw.github.com/mckamey/doubleTap.js/master/doubleTap.js
|
|
|
|
"use strict";
|
|
|
|
// default dblclick speed to half sec (default for Windows & Mac OS X)
|
|
speed = Math.abs(Number(speed)) || 500;//ms
|
|
// default dblclick distance to within 40x40 pixel area
|
|
distance = Math.abs(Number(distance)) || 40;//px
|
|
|
|
// Date.now() polyfill
|
|
const now = Date.now || function () {
|
|
return Number(new Date());
|
|
};
|
|
|
|
function cancelEvent(e) {
|
|
e = (e || window.event);
|
|
|
|
if (e) {
|
|
if (e.preventDefault) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
} else {
|
|
try {
|
|
e.cancelBubble = true;
|
|
e.returnValue = false;
|
|
} catch (ex) {
|
|
// IE6
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
let taps = 0;
|
|
let last = 0;
|
|
// NaN will always test false
|
|
let x = NaN;
|
|
let y = NaN;
|
|
|
|
return function (e) {
|
|
e = (e || window.event);
|
|
|
|
const time = now();
|
|
const touch = e.changedTouches ? e.changedTouches[0] : e;
|
|
const nextX = Number(touch.clientX);
|
|
const nextY = Number(touch.clientY);
|
|
const target = e.target || e.srcElement;
|
|
let e2;
|
|
let parent;
|
|
|
|
if ((last + speed) > time &&
|
|
Math.abs(nextX - x) < distance &&
|
|
Math.abs(nextY - y) < distance) {
|
|
// continue series
|
|
taps++;
|
|
|
|
} else {
|
|
// reset series if too slow or moved
|
|
taps = 1;
|
|
}
|
|
|
|
// update starting stats
|
|
last = time;
|
|
x = nextX;
|
|
y = nextY;
|
|
|
|
// fire tap event
|
|
if (document.createEvent) {
|
|
e2 = document.createEvent("MouseEvents");
|
|
e2.initMouseEvent(
|
|
"tap",
|
|
true, // click bubbles
|
|
true, // click cancelable
|
|
e.view, // copy view
|
|
taps, // click count
|
|
touch.screenX, // copy coordinates
|
|
touch.screenY,
|
|
touch.clientX,
|
|
touch.clientY,
|
|
e.ctrlKey, // copy key modifiers
|
|
e.altKey,
|
|
e.shiftKey,
|
|
e.metaKey,
|
|
e.button, // copy button 0: left, 1: middle, 2: right
|
|
e.relatedTarget); // copy relatedTarget
|
|
|
|
if (!target.dispatchEvent(e2)) {
|
|
// pass on cancel
|
|
cancelEvent(e);
|
|
}
|
|
|
|
} else {
|
|
e.detail = taps;
|
|
|
|
// manually bubble up
|
|
parent = target;
|
|
while (parent && !parent.tap && !parent.ontap) {
|
|
parent = parent.parentNode || parent.parent;
|
|
}
|
|
if (parent && parent.tap) {
|
|
// DOM Level 0
|
|
parent.tap(e);
|
|
|
|
} else if (parent && parent.ontap) {
|
|
// DOM Level 0, IE
|
|
parent.ontap(e);
|
|
|
|
} else if (typeof jQuery !== "undefined") {
|
|
// cop out and patch IE6-8 with jQuery
|
|
jQuery(this).trigger("tap", e); /* eslint-disable-line no-invalid-this */
|
|
}
|
|
}
|
|
|
|
if (taps === 2) {
|
|
// fire dbltap event only for 2nd click
|
|
if (document.createEvent) {
|
|
e2 = document.createEvent("MouseEvents");
|
|
e2.initMouseEvent(
|
|
"dbltap",
|
|
true, // dblclick bubbles
|
|
true, // dblclick cancelable
|
|
e.view, // copy view
|
|
taps, // click count
|
|
touch.screenX, // copy coordinates
|
|
touch.screenY,
|
|
touch.clientX,
|
|
touch.clientY,
|
|
e.ctrlKey, // copy key modifiers
|
|
e.altKey,
|
|
e.shiftKey,
|
|
e.metaKey,
|
|
e.button, // copy button 0: left, 1: middle, 2: right
|
|
e.relatedTarget); // copy relatedTarget
|
|
|
|
if (!target.dispatchEvent(e2)) {
|
|
// pass on cancel
|
|
cancelEvent(e);
|
|
}
|
|
|
|
} else {
|
|
e.detail = taps;
|
|
|
|
// manually bubble up
|
|
parent = target;
|
|
while (parent && !parent.dbltap && !parent.ondbltap) {
|
|
parent = parent.parentNode || parent.parent;
|
|
}
|
|
if (parent && parent.dbltap) {
|
|
// DOM Level 0
|
|
parent.dbltap(e);
|
|
|
|
} else if (parent && parent.ondbltap) {
|
|
// DOM Level 0, IE
|
|
parent.ondbltap(e);
|
|
|
|
} else if (typeof jQuery !== "undefined") {
|
|
// cop out and patch IE6-8 with jQuery
|
|
jQuery(this).trigger("dbltap", e); /* eslint-disable-line no-invalid-this */
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}()), false);
|
|
|
|
document.addEventListener("tap", touchHandler, true);
|
|
// document.addEventListener("dbltap", touchHandler, true);
|
|
document.addEventListener("touchstart", touchHandler, true);
|
|
document.addEventListener("touchmove", touchHandler, true);
|
|
document.addEventListener("touchend", touchHandler, true);
|
|
document.addEventListener("touchcancel", touchHandler, true);
|