From bfe93acf5b1d7acdc3f0fd7eb484be3b591fde4d Mon Sep 17 00:00:00 2001 From: Andy Davies Date: Wed, 11 Apr 2012 12:09:25 +0100 Subject: [PATCH] fixing bugs with swipe and drag --- index-dev.html | 4 +- js/DragController.js | 12 ++--- js/SwipeController.js | 102 +++++++++++++++++++++++------------------- jsTouchLayer.min.js | 2 +- 4 files changed, 66 insertions(+), 54 deletions(-) diff --git a/index-dev.html b/index-dev.html index fb0d5ff..4fe7e92 100644 --- a/index-dev.html +++ b/index-dev.html @@ -62,13 +62,13 @@

Touch Framework experiments

logger.appendChild(element); } - touchLayer.unbind(id); + //touchLayer.unbind(id); }; touchLayer.bind('tapstart', target, callback); touchLayer.bind('tapcancel', target, callback); - id = touchLayer.bind('tap', target, callback); + touchLayer.bind('tap', target, callback); touchLayer.bind('taphold', target, callback); touchLayer.bind('doubletap', target, callback); diff --git a/js/DragController.js b/js/DragController.js index 959677b..8d85ddf 100644 --- a/js/DragController.js +++ b/js/DragController.js @@ -41,16 +41,16 @@ var TouchLayer_DragController = function (options) { if (e.originalEvent) { e = e.originalEvent; } - + if (preventDefault) { e.preventDefault(); e.stopPropagation(); } - - if (e.touches) { + + if (e.touches !== undefined) { startX = previousX = e.touches[0].pageX; startY = previousY = e.touches[0].pageY; - } else if (e.startX && e.startY) { + } else if (e.pageX && e.pageY) { startX = previousX = e.pageX; startY = previousY = e.pageY; } @@ -61,11 +61,12 @@ var TouchLayer_DragController = function (options) { }; var onTouchMove = function (e) { + if (startX && startY) { if (e.originalEvent) { e = e.originalEvent; } - + if (preventDefault) { e.preventDefault(); e.stopPropagation(); @@ -140,6 +141,7 @@ var TouchLayer_DragController = function (options) { } dragging = false; touchStart = false; + startX = startY = null; }; mainController.bind(options.el, 'touchstart', onTouchStart, runOnBubble); diff --git a/js/SwipeController.js b/js/SwipeController.js index 2b3457b..d809789 100644 --- a/js/SwipeController.js +++ b/js/SwipeController.js @@ -49,65 +49,75 @@ var TouchLayer_SwipeController = function (options) { }; var onTouchMove = function (e) { - if (e.originalEvent) { - e = e.originalEvent; - } - - if (preventDefault) { - e.preventDefault(); - e.stopPropagation(); - } - - var deltaX = null, - deltaY = null; - if (e.touches) { //e.pageX / pageY give 0 values in android - deltaY = e.touches[0].pageY - startY; - deltaX = e.touches[0].pageX - startX; - } else if (e.pageX && e.pageY) { - deltaY = e.pageY - startY; - deltaX = e.pageX - startX; - } - - if (deltaX && deltaY) { - var absDeltaY = Math.abs(deltaY), - absDeltaX = Math.abs(deltaX), - deltaTime = e.timeStamp - startTime; - - // If the swipeTime is over, we are not gonna check for it again - if (absDeltaY - absDeltaX > 3 || deltaTime > swipeTime) { - stopped = true; - - } else if (absDeltaX > swipeThreshold && absDeltaX > absDeltaY) { - // If this is a swipe, a scroll is not possible anymore - var info = { - direction: (deltaX < 0) ? 'left' : 'right', - distance: absDeltaX, - deltaTime: deltaTime, - deltaX: deltaX, - deltaY: deltaY - }; - - if (options.eventName === 'swipe') { - var data = mainController.makeReturnData(e, options.el, info); - mainController.fire('swipe', options.callback, data); - - if (preventDefault) { - e.preventDefault(); - e.stopPropagation(); + + if (startX && startY) { + if (e.originalEvent) { + e = e.originalEvent; + } + + if (preventDefault) { + e.preventDefault(); + e.stopPropagation(); + } + + var deltaX = null, + deltaY = null; + if (e.touches) { //e.pageX / pageY give 0 values in android + deltaY = e.touches[0].pageY - startY; + deltaX = e.touches[0].pageX - startX; + } else if (e.pageX && e.pageY) { + deltaY = e.pageY - startY; + deltaX = e.pageX - startX; + } + + if (deltaX && deltaY) { + var absDeltaY = Math.abs(deltaY), + absDeltaX = Math.abs(deltaX), + deltaTime = e.timeStamp - startTime; + + // If the swipeTime is over, we are not gonna check for it again + if (absDeltaY - absDeltaX > 3 || deltaTime > swipeTime) { + stopped = true; + + } else if (absDeltaX > swipeThreshold && absDeltaX > absDeltaY) { + // If this is a swipe, a scroll is not possible anymore + var info = { + direction: (deltaX < 0) ? 'left' : 'right', + distance: absDeltaX, + deltaTime: deltaTime, + deltaX: deltaX, + deltaY: deltaY + }; + + if (options.eventName === 'swipe') { + var data = mainController.makeReturnData(e, options.el, info); + mainController.fire('swipe', options.callback, data); + + if (preventDefault) { + e.preventDefault(); + e.stopPropagation(); + } } + stopped = true; } - stopped = true; } } }; + var onTouchEnd = function () { + stopped = true; + startX = startY = null; + }; + mainController.bind(options.el, 'touchstart', onTouchStart, runOnBubble); mainController.bind(options.el, 'touchmove', onTouchMove, runOnBubble); + mainController.bind(options.el, 'touchend', onTouchEnd, runOnBubble); return { unbind: function () { mainController.unbind(options.el, 'touchstart', onTouchStart); mainController.unbind(options.el, 'touchmove', onTouchMove); + mainController.unbind(options.el, 'touchend', onTouchEnd); } }; }; \ No newline at end of file diff --git a/jsTouchLayer.min.js b/jsTouchLayer.min.js index bd8429a..df30275 100644 --- a/jsTouchLayer.min.js +++ b/jsTouchLayer.min.js @@ -1 +1 @@ -var TouchLayer_Controller=function(){var a=[],b=function(b){return a[b]!==undefined},c={touchstart:"ontouchstart"in document.documentElement?"touchstart":"mousedown",touchmove:"ontouchmove"in document.documentElement?"touchmove":"mousemove",touchend:"ontouchend"in document.documentElement?"touchend":"mouseup"};return{bind:function(a,b,d,e){var f=!1;if(!a||!b||!d)return;e!==undefined&&(f=e),c[b]!==undefined&&a.addEventListener(c[b],d,f)},unbind:function(a,b,d){if(!a||!b||!d)return;c[b]!==undefined&&a.removeEventListener(c[b],d)},fire:function(a,c,d){if(!a||!c)return;d.type=a,b(a)||c(d)},lock:function(b){if(b.length>0)for(var c=0;c0){for(var d=0;d=h||Math.abs(c-l)>=h},q=function(c){c.originalEvent&&(c=c.originalEvent),n&&(c.preventDefault(),c.stopPropagation()),c.touches!==undefined?(k=c.touches[0].pageX,l=c.touches[0].pageY):c.pageX&&c.pageY&&(k=c.pageX,l=c.pageY),m=!1;if(a.eventName==="tapstart"){var d=b.makeReturnData(c,a.el);b.fire("tapstart",a.callback,d)}a.eventName==="taphold"&&(j=setTimeout(function(){var d=b.makeReturnData(c,a.el);b.fire("taphold",a.callback,d),j=null},g))},r=function(c){c.originalEvent&&(c=c.originalEvent),n&&(c.preventDefault(),c.stopPropagation());if(p(c)&&!m&&k+l>0){if(a.eventName==="tapcancel"){var d=b.makeReturnData(c,a.el);b.fire("tapcancel",a.callback,d)}j&&(clearTimeout(j),j=null),m=!0}},s=function(c){c.originalEvent&&(c=c.originalEvent),n&&(c.preventDefault(),c.stopPropagation());if(!m){o(c);if(i&&c.timeStamp-i<=f){i=null;if(a.eventName==="doubletap"){var g=b.makeReturnData(c,a.el);b.fire("doubletap",a.callback,g)}}else i=c.timeStamp;if(e&&!d){if(a.eventName==="singletap"){var h=b.makeReturnData(c,a.el);b.fire("singletap",a.callback,h)}d=!0,setTimeout(function(){d=!1},e)}j&&(clearTimeout(j),j=null)}m=!0};return b.bind(a.el,"touchstart",q,c),b.bind(a.el,"touchmove",r,c),b.bind(a.el,"touchend",s,c),{unbind:function(){b.unbind(a.el,"touchstart",q),b.unbind(a.el,"touchmove",r),b.unbind(a.el,"touchend",s)}}},TouchLayer_DragController=function(a){if(!a.eventName||!a.el||!a.callback)return;var b=new TouchLayer_Controller,c=!1,d=30,e=!0,f=!0,g=0,h=0,i=0,j=0,k="",l="",m=!1,n=!1,o=!0;a.preventDefault!==undefined&&(o=a.preventDefault);var p=function(a){return e&&a.absDeltaX>=d||f&&a.absDeltaY>=d},q=function(a){a.originalEvent&&(a=a.originalEvent),o&&(a.preventDefault(),a.stopPropagation()),a.touches?(g=h=a.touches[0].pageX,i=j=a.touches[0].pageY):a.startX&&a.startY&&(g=h=a.pageX,i=j=a.pageY),k=l=a.timeStamp,l=a.timeStamp,m=!1},r=function(c){if(g&&i){c.originalEvent&&(c=c.originalEvent),o&&(c.preventDefault(),c.stopPropagation());var d={startX:g,startY:i,prevX:h,prevY:j,deltaY:0,deltaX:0,absDeltaY:0,absDeltaX:0,deltaTime:c.timeStamp-k};c.touches?(d.deltaY=c.touches[0].pageY-i,d.deltaX=c.touches[0].pageX-g):c.pageX&&c.pageY&&(d.deltaY=c.pageY-i,d.deltaX=c.pageX-g);if(d!==undefined){d.absDeltaY=Math.abs(d.deltaY),d.absDeltaX=Math.abs(d.deltaX);if(!m&&(!c.touches||c.touches.length<2)&&p(d)){m=!0;if(a.eventName==="dragstart"){var e=b.makeReturnData(c,a.el,d);b.fire("dragstart",a.callback,e)}}if(a.eventName==="drag"&&m){var f=b.makeReturnData(c,a.el,d);b.fire("drag",a.callback,f),c.touches?(h=c.touches[0].pageX,j=c.touches[0].pageY):c.pageX&&c.pageY&&(h=c.pageX,j=c.pageY)}}}},s=function(c){c.originalEvent&&(c=c.originalEvent),o&&(c.preventDefault(),c.stopPropagation());if(m&&a.eventName==="dragend"){var d=b.makeReturnData(c,a.el);b.fire("dragend",a.callback,d)}m=!1,n=!1};return b.bind(a.el,"touchstart",q,c),b.bind(a.el,"touchmove",r,c),b.bind(a.el,"touchend",s,c),{unbind:function(){b.unbind(a.el,"touchstart",q),b.unbind(a.el,"touchmove",r),b.unbind(a.el,"touchend",s)}}},TouchLayer_SwipeController=function(a){if(!a.eventName||!a.el||!a.callback)return;var b=new TouchLayer_Controller,c=!1,d=null,e=null,f=null,g=105,h=1e3,i=!1,j=!0;a.preventDefault!==undefined&&(j=a.preventDefault);var k=function(a){a.originalEvent&&(a=a.originalEvent),j&&(a.preventDefault(),a.stopPropagation()),a.touches?(e=a.touches[0].pageX,f=a.touches[0].pageY):a.pageX&&a.pageY&&(e=a.pageX,f=a.pageY),d=a.timeStamp,i=!1},l=function(c){c.originalEvent&&(c=c.originalEvent),j&&(c.preventDefault(),c.stopPropagation());var k=null,l=null;c.touches?(l=c.touches[0].pageY-f,k=c.touches[0].pageX-e):c.pageX&&c.pageY&&(l=c.pageY-f,k=c.pageX-e);if(k&&l){var m=Math.abs(l),n=Math.abs(k),o=c.timeStamp-d;if(m-n>3||o>h)i=!0;else if(n>g&&n>m){var p={direction:k<0?"left":"right",distance:n,deltaTime:o,deltaX:k,deltaY:l};if(a.eventName==="swipe"){var q=b.makeReturnData(c,a.el,p);b.fire("swipe",a.callback,q),j&&(c.preventDefault(),c.stopPropagation())}i=!0}}};return b.bind(a.el,"touchstart",k,c),b.bind(a.el,"touchmove",l,c),{unbind:function(){b.unbind(a.el,"touchstart",k),b.unbind(a.el,"touchmove",l)}}},TouchLayer=function(){var a={tapstart:TouchLayer_TapController,tapcancel:TouchLayer_TapController,tap:TouchLayer_TapController,doubletap:TouchLayer_TapController,taphold:TouchLayer_TapController,singletap:TouchLayer_TapController,drag:TouchLayer_DragController,dragstart:TouchLayer_DragController,dragend:TouchLayer_DragController,swipe:TouchLayer_SwipeController},b=[];return{bind:function(c,d,e,f){if(!c||!d||!e)return;f||(f={});if(a[c]){f.eventName=c,f.el=d,f.callback=e;var g=b.length;return b[g]=new a[c](f),g}},unbind:function(a){b[a]!==null&&(b[a].unbind(),b[a]=null)}}} \ No newline at end of file +var TouchLayer_Controller=function(){var a=[],b=function(b){return a[b]!==undefined},c={touchstart:"ontouchstart"in document.documentElement?"touchstart":"mousedown",touchmove:"ontouchmove"in document.documentElement?"touchmove":"mousemove",touchend:"ontouchend"in document.documentElement?"touchend":"mouseup"};return{bind:function(a,b,d,e){var f=!1;if(!a||!b||!d)return;e!==undefined&&(f=e),c[b]!==undefined&&a.addEventListener(c[b],d,f)},unbind:function(a,b,d){if(!a||!b||!d)return;c[b]!==undefined&&a.removeEventListener(c[b],d)},fire:function(a,c,d){if(!a||!c)return;d.type=a,b(a)||c(d)},lock:function(b){if(b.length>0)for(var c=0;c0){for(var d=0;d=h||Math.abs(c-l)>=h},q=function(c){c.originalEvent&&(c=c.originalEvent),n&&(c.preventDefault(),c.stopPropagation()),c.touches!==undefined?(k=c.touches[0].pageX,l=c.touches[0].pageY):c.pageX&&c.pageY&&(k=c.pageX,l=c.pageY),m=!1;if(a.eventName==="tapstart"){var d=b.makeReturnData(c,a.el);b.fire("tapstart",a.callback,d)}a.eventName==="taphold"&&(j=setTimeout(function(){var d=b.makeReturnData(c,a.el);b.fire("taphold",a.callback,d),j=null},g))},r=function(c){c.originalEvent&&(c=c.originalEvent),n&&(c.preventDefault(),c.stopPropagation());if(p(c)&&!m&&k+l>0){if(a.eventName==="tapcancel"){var d=b.makeReturnData(c,a.el);b.fire("tapcancel",a.callback,d)}j&&(clearTimeout(j),j=null),m=!0}},s=function(c){c.originalEvent&&(c=c.originalEvent),n&&(c.preventDefault(),c.stopPropagation());if(!m){o(c);if(i&&c.timeStamp-i<=f){i=null;if(a.eventName==="doubletap"){var g=b.makeReturnData(c,a.el);b.fire("doubletap",a.callback,g)}}else i=c.timeStamp;if(e&&!d){if(a.eventName==="singletap"){var h=b.makeReturnData(c,a.el);b.fire("singletap",a.callback,h)}d=!0,setTimeout(function(){d=!1},e)}j&&(clearTimeout(j),j=null)}m=!0};return b.bind(a.el,"touchstart",q,c),b.bind(a.el,"touchmove",r,c),b.bind(a.el,"touchend",s,c),{unbind:function(){b.unbind(a.el,"touchstart",q),b.unbind(a.el,"touchmove",r),b.unbind(a.el,"touchend",s)}}},TouchLayer_DragController=function(a){if(!a.eventName||!a.el||!a.callback)return;var b=new TouchLayer_Controller,c=!1,d=30,e=!0,f=!0,g=0,h=0,i=0,j=0,k="",l="",m=!1,n=!1,o=!0;a.preventDefault!==undefined&&(o=a.preventDefault);var p=function(a){return e&&a.absDeltaX>=d||f&&a.absDeltaY>=d},q=function(a){a.originalEvent&&(a=a.originalEvent),o&&(a.preventDefault(),a.stopPropagation()),a.touches!==undefined?(g=h=a.touches[0].pageX,i=j=a.touches[0].pageY):a.pageX&&a.pageY&&(g=h=a.pageX,i=j=a.pageY),k=l=a.timeStamp,l=a.timeStamp,m=!1},r=function(c){if(g&&i){c.originalEvent&&(c=c.originalEvent),o&&(c.preventDefault(),c.stopPropagation());var d={startX:g,startY:i,prevX:h,prevY:j,deltaY:0,deltaX:0,absDeltaY:0,absDeltaX:0,deltaTime:c.timeStamp-k};c.touches?(d.deltaY=c.touches[0].pageY-i,d.deltaX=c.touches[0].pageX-g):c.pageX&&c.pageY&&(d.deltaY=c.pageY-i,d.deltaX=c.pageX-g);if(d!==undefined){d.absDeltaY=Math.abs(d.deltaY),d.absDeltaX=Math.abs(d.deltaX);if(!m&&(!c.touches||c.touches.length<2)&&p(d)){m=!0;if(a.eventName==="dragstart"){var e=b.makeReturnData(c,a.el,d);b.fire("dragstart",a.callback,e)}}if(a.eventName==="drag"&&m){var f=b.makeReturnData(c,a.el,d);b.fire("drag",a.callback,f),c.touches?(h=c.touches[0].pageX,j=c.touches[0].pageY):c.pageX&&c.pageY&&(h=c.pageX,j=c.pageY)}}}},s=function(c){c.originalEvent&&(c=c.originalEvent),o&&(c.preventDefault(),c.stopPropagation());if(m&&a.eventName==="dragend"){var d=b.makeReturnData(c,a.el);b.fire("dragend",a.callback,d)}m=!1,n=!1,g=i=null};return b.bind(a.el,"touchstart",q,c),b.bind(a.el,"touchmove",r,c),b.bind(a.el,"touchend",s,c),{unbind:function(){b.unbind(a.el,"touchstart",q),b.unbind(a.el,"touchmove",r),b.unbind(a.el,"touchend",s)}}},TouchLayer_SwipeController=function(a){if(!a.eventName||!a.el||!a.callback)return;var b=new TouchLayer_Controller,c=!1,d=null,e=null,f=null,g=105,h=1e3,i=!1,j=!0;a.preventDefault!==undefined&&(j=a.preventDefault);var k=function(a){a.originalEvent&&(a=a.originalEvent),j&&(a.preventDefault(),a.stopPropagation()),a.touches?(e=a.touches[0].pageX,f=a.touches[0].pageY):a.pageX&&a.pageY&&(e=a.pageX,f=a.pageY),d=a.timeStamp,i=!1},l=function(c){if(e&&f){c.originalEvent&&(c=c.originalEvent),j&&(c.preventDefault(),c.stopPropagation());var k=null,l=null;c.touches?(l=c.touches[0].pageY-f,k=c.touches[0].pageX-e):c.pageX&&c.pageY&&(l=c.pageY-f,k=c.pageX-e);if(k&&l){var m=Math.abs(l),n=Math.abs(k),o=c.timeStamp-d;if(m-n>3||o>h)i=!0;else if(n>g&&n>m){var p={direction:k<0?"left":"right",distance:n,deltaTime:o,deltaX:k,deltaY:l};if(a.eventName==="swipe"){var q=b.makeReturnData(c,a.el,p);b.fire("swipe",a.callback,q),j&&(c.preventDefault(),c.stopPropagation())}i=!0}}}},m=function(){i=!0,e=f=null};return b.bind(a.el,"touchstart",k,c),b.bind(a.el,"touchmove",l,c),b.bind(a.el,"touchend",m,c),{unbind:function(){b.unbind(a.el,"touchstart",k),b.unbind(a.el,"touchmove",l),b.unbind(a.el,"touchend",m)}}},TouchLayer=function(){var a={tapstart:TouchLayer_TapController,tapcancel:TouchLayer_TapController,tap:TouchLayer_TapController,doubletap:TouchLayer_TapController,taphold:TouchLayer_TapController,singletap:TouchLayer_TapController,drag:TouchLayer_DragController,dragstart:TouchLayer_DragController,dragend:TouchLayer_DragController,swipe:TouchLayer_SwipeController},b=[];return{bind:function(c,d,e,f){if(!c||!d||!e)return;f||(f={});if(a[c]){f.eventName=c,f.el=d,f.callback=e;var g=b.length;return b[g]=new a[c](f),g}},unbind:function(a){b[a]!==null&&(b[a].unbind(),b[a]=null)}}} \ No newline at end of file