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?
I too think the touchmove
event's callback is being fired on every touch move. By returning false
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 call self.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 time touchmove
is being triggered and set this flag to false
when the
pointer has travelled 100px.startEvent
to null
and check this variable on
touchmove
.touchmove
event when the pointer has
travelled 100px.NB: The touchmove
event is being bound each time touchstart
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):
// Unbind all touchmove.myNameSpace events on touchend.myNameSpace.
self._$body.bind('touchend.myNameSpace').function (event) {
self._$body.unbind('touchmove.myNameSpace');
});
and when the pointer has travelled 100px:
self.customScrollTo(nextStep);
// Unbind all touchmove.myNameSpace events.
self._$body.unbind('touchmove.myNameSpace');
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:
event.preventDefault();
// Unbind all touchmove.myNameSpace events and (re)bind touchmove.myNameSpace event.
self._$body.unbind('touchmove.myNameSpace').bind('touchmove.myNameSpace', function (event) {
var moveEvent = event.originalEvent.touches[0];
So you could try (I have not tested it):
/**
* 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.unbind('touchmove.myNameSpace').bind('touchmove.myNameSpace', function (event) {
var moveEvent = event.originalEvent.touches[0];
var diff = { x: startEvent.clientX - moveEvent.clientX, y: startEvent.clientY - moveEvent.clientY };
var nextStep;
event.preventDefault(); // <- Not necessary since you completely cancel the event by returning false.
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);
// Unbind all touchmove.myNameSpace events.
self._$body.unbind('touchmove.myNameSpace');
}
return false;
});
return false;
});
// Unbind all touchmove.myNameSpace events on touchend.myNameSpace.
self._$body.bind('touchend.myNameSpace').function (event) {
self._$body.unbind('touchmove.myNameSpace');
});
return this;
},
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.