I went through the code several times and I cannot find the reason it fails on touch based devices:
/**
* Initialize touch event listener.
*
* @returns {Plugin}
*/
touch: function () {
var self = this;
this._$body.bind('touchstart', function (event) {
var startEvent = event.originalEvent.touches[0];
event.preventDefault();
self._$body.bind('touchmove', function (event) {
var moveEvent = event.originalEvent.touches[0];
var diff = { x: startEvent.clientX - moveEvent.clientX, y: startEvent.clientY - moveEvent.clientY };
var nextStep;
event.preventDefault();
if ((diff.y <= -100 || diff.y >= 100) && Math.abs(diff.y) > Math.abs(diff.x)) {
nextStep = diff.y < 0 ? self._currentStep - 1 : self._currentStep + 1;
self.customScrollTo(nextStep);
}
return false;
});
return false;
});
return this;
},
demo (self signed ssl, don't worry!): https://sandbox.idev.ge/roomshotel/html5_v3/
Problem: Scroll jumps straight to bottom when touch is activated.
Expected result: One touch interaction equals 1 section scrolled.
Any thoughts?
First I will suggest you to use Modernizr to detect touch
I am just putting logic above. "self" is your object only.
for swipe event to work you have to include a jquery plugin https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
I guess there is a simple edit required. After you have exceeded the "diff" by 100 or -100 then just update the value of "startEvent" variable. Hence I have added the statement
So when the event for "self.customScrollTo(nextStep)" is triggered, the "startEvent" value is new value which is the current position of the touched point. And hence when again the touchmove event is called. It will again get a new set of values to calculate. Please check this code and tell me if this works or not. Even if it is not right.
I think the event touchmove is firing multiple times, try to use touchend instead.
Regarding to: http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/ I have tested your code with google chrome live javascript edit. and it worked with the following modification in touchmove event.
I too think the
touchmove
event's callback is being fired on every touch move. By returningfalse
from that function you only cancel that single touch move event and not all following touch move events.You cannot use a
touchend
event since you want to callself.customScrollTo(nextStep);
as soon as the pointer has travelled 100px.You want to prevent your
touchmove
callback from being executed after the pointer has travelled 100px, this can be done in many ways, ie.var trackPointer = true;
, check this flag each timetouchmove
is being triggered and set this flag tofalse
when the pointer has travelled 100px.startEvent
tonull
and check this variable ontouchmove
.touchmove
event when the pointer has travelled 100px.NB: The
touchmove
event is being bound each timetouchstart
is triggered on this element, these events do not overwrite each other but get stacked! So you might want to consider binding the event only once (ie. on DOM ready) or unbind the event when it's no longer necessary.The latter is probably the easiest and could be done ie. on
touchend
(use namespaces just to be sure to not unbind the same events bound by other scripts):and when the pointer has travelled 100px:
Since 'touchend' is not triggered when the pointer is outside the element (I am not sure about
touchmove
), you might also want to unbind right before binding:So you could try (I have not tested it):
PS: You might want to use a library like HammerJS (https://github.com/hammerjs/hammer.js) to make gestures work cross browser and also on non-touch devices.