Skip to content

Instantly share code, notes, and snippets.

@w3core
Last active December 29, 2016 15:16
Show Gist options
  • Save w3core/5419adba065b9ab5a07f99a729b79da0 to your computer and use it in GitHub Desktop.
Save w3core/5419adba065b9ab5a07f99a729b79da0 to your computer and use it in GitHub Desktop.
Cross-browser implementation of swipe events for the any element by using mouse and touch native events.
/**
* Swipe v.1.0.0
* =============
* Cross-browser implementation of swipe events for the any element
* by using mouse and touch native events. It allows to handle events such
* as "swipestart", "swipemove" and "swipeend".
*
* @license MIT
* @author Max Chuhryaev
*
* Usage example
* -------------
* ```javascript
* var node = document.body;
* node.addEventListener("swipestart", swipeListener, !1);
* node.addEventListener("swipemove", swipeListener, !1);
* node.addEventListener("swipeend", swipeListener, !1);
*
* Swipe(node, function (data) {
* console.log("handler", data.type, data, this);
* });
*
* function swipeListener (event) {
* console.log("listener", event.type, event);
* }
* ```
*
* @param node (HTMLElement|String) [Required] HTML element or CSS selector of elements that should emit swipe events
* @param handler (Function) [Optional] An optional function that can be used to
* handle swipe events and preventing of original events.
* @returns void
*/
function Swipe (node, handler) {
var hasTouch = "ontouchstart" in window,
startEvent = hasTouch ? 'touchstart' : 'mousedown',
moveEvent = hasTouch ? 'touchmove' : 'mousemove',
dragEvent = hasTouch ? '' : 'dragover',
endEvent = hasTouch ? 'touchend' : 'mouseup',
cancelEvent = hasTouch ? 'touchcancel' : 'dragend'
;
var round = Math.round;
var root, startX, x, startY, y, way, direction;
constructor();
function constructor () {
window.addEventListener(startEvent, listener, !1);
window.addEventListener(moveEvent, listener, !1);
if (dragEvent) window.addEventListener(dragEvent, listener, !1);
window.addEventListener(endEvent, listener, !1);
window.addEventListener(cancelEvent, listener, !1);
}
function listener (e) {
if (e.type == startEvent) {
var node = getEventNode(e);
if (node) root = node;
}
if (root) {
var current = pointerLocationByEvent(e);
if (e.type == startEvent) {
startX = x = current.x;
startY = y = current.y;
fire("start", e);
}
else if (e.type == moveEvent || e.type == dragEvent) {
if (!way) {
var wdX = calcDiff(startX, current.x), wdY = calcDiff(startY, current.y);
if (wdX == wdY) return;
way = wdX > wdY ? "x" : "y";
}
direction = way == "x" ? (x>current.x?"left":"right") : (y>current.y?"top":"bottom");
x = current.x;
y = current.y;
fire("move", e);
}
else if (e.type == endEvent || e.type == cancelEvent) {
fire("end", e);
root = null;
way = direction = null;
}
}
}
function getEventNode (e) {
if (typeof node == "string") return bySelector(e.target, node, !0);
else return byNode(e.target, node);
}
function _matchesSelector(el, selector) {
if (el == window || el == document) return !1;
var p = Element.prototype;
var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
};
return f.call(el, selector);
}
function bySelector (el, selector, closest) {
if (_matchesSelector(el, selector)) return el;
if (!closest) return !1;
return el.parentNode ? bySelector (el.parentNode, selector, closest) : !1;
}
function byNode (node, parent) {
if (node == parent) return node;
return node.parentNode ? byNode(node.parentNode, parent) : false;
}
function calcDiff (prev, current) {
return Math.max(prev, current) - Math.min(prev, current);
}
function pointerLocationByEvent (e) {
var v = e.touches && e.touches[0] ? e.touches[0] : e;
return {
x: round(v.clientX || v.pageX || v.x),
y: round(v.clientY || v.pageY || v.y)
};
}
function getData (originalEvent) {
var o = {
x:x,
y:y,
startX:startX,
startY:startY,
diffX:x-startX,
diffY:y-startY
};
if (originalEvent) o.originalEvent = originalEvent;
if (way) {
o.way = way;
o.diffWay = way=="x"?o.diffX:o.diffY;
}
if (direction) o.direction = direction;
return o;
}
function fire (type, originalEvent) {
var event = "swipe"+type;
var data = getData(originalEvent);
var e = dispatch(root, event, data);
if (typeof handler == "function") handler.call(root, e);
}
function dispatch (node, event, data) {
var e = document.createEvent("HTMLEvents");
if (data) for (var i in data) e[i] = data[i];
e.initEvent(event, true, true);
node.dispatchEvent(e);
return e;
}
}
function Swipe(h,v){function e(a){var c,b;a.type==r&&(c="string"==typeof h?w(a.target,h,!0):x(a.target,h),c&&(k=c));if(k)if(b=a.touches&&a.touches[0]?a.touches[0]:a,c=y(b.clientX||b.pageX||b.x),b=y(b.clientY||b.pageY||b.y),a.type==r)l=m=c,n=p=b,t("start",a);else if(a.type==z||a.type==u){if(!g){var d=Math.max(l,c)-Math.min(l,c),e=Math.max(n,b)-Math.min(n,b);if(d==e)return;g=d>e?"x":"y"}q="x"==g?m>c?"left":"right":p>b?"top":"bottom";m=c;p=b;t("move",a)}else if(a.type==A||a.type==B)t("end",a),g=q=k=null}function C(a,c){if(a==window||a==document)return!1;var b=Element.prototype;return(b.matches||b.webkitMatchesSelector||b.mozMatchesSelector||b.msMatchesSelector||function(a){return-1!==[].indexOf.call(document.querySelectorAll(a),this)}).call(a,c)}function w(a,c,b){return C(a,c)?a:b?a.parentNode?w(a.parentNode,c,b):!1:!1}function x(a,c){return a==c?a:a.parentNode?x(a.parentNode,c):!1}function t(a,c){var b="swipe"+a,d={x:m,y:p,startX:l,startY:n,diffX:m-l,diffY:p-n};c&&(d.originalEvent=c);g&&(d.way=g,d.diffWay="x"==g?d.diffX:d.diffY);q&&(d.direction=q);var e=k,f=document.createEvent("HTMLEvents");if(d)for(var h in d)f[h]=d[h];f.initEvent(b,!0,!0);e.dispatchEvent(f);"function"==typeof v&&v.call(k,f)}var f="ontouchstart"in window,r=f?"touchstart":"mousedown",z=f?"touchmove":"mousemove",u=f?"":"dragover",A=f?"touchend":"mouseup",B=f?"touchcancel":"dragend",y=Math.round,k,l,m,n,p,g,q;window.addEventListener(r,e,!1);window.addEventListener(z,e,!1);u&&window.addEventListener(u,e,!1);window.addEventListener(A,e,!1);window.addEventListener(B,e,!1)};
@w3core
Copy link
Author

w3core commented Dec 16, 2016

Swipe v.1.0.0

Cross-browser implementation of swipe events for the any element
by using mouse and touch native events. It allows to handle events such
as "swipestart", "swipemove" and "swipeend".

Usage example

  var node = document.body;
  node.addEventListener("swipestart", swipeListener, !1);
  node.addEventListener("swipemove", swipeListener, !1);
  node.addEventListener("swipeend", swipeListener, !1);

  Swipe(node, function (data) {
    console.log("handler", data.type, data, this);
  });

  function swipeListener (event) {
    console.log("listener", event.type, event);
  }

Working example

20161216-113253_capture

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment