Skip to content

Commit

Permalink
bxSlider 4.1.2 freezes on touch devices stevenwanderski#540
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Wafford committed Feb 8, 2015
1 parent c93f419 commit 7e0ba16
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 68 deletions.
8 changes: 7 additions & 1 deletion dist/jquery.bxslider.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***
* BxSlider v4.2.1 - Fully loaded, responsive content slider
* BxSlider v4.2.2 - Fully loaded, responsive content slider
* http://bxslider.com
*
* Written by: Steven Wanderski, 2014
Expand All @@ -16,6 +16,8 @@
margin: 0 auto 60px;
padding: 0;
*zoom: 1;
-ms-touch-action: pan-y;
touch-action: pan-y;
}
.bx-wrapper img {
max-width: 100%;
Expand Down Expand Up @@ -87,6 +89,10 @@ ul.bxslider {
*zoom: 1;
*display: inline;
}
.bx-wrapper .bx-pager-item {
font-size: 0;
line-height: 0;
}
/* DIRECTION CONTROLS (NEXT / PREV) */
.bx-wrapper .bx-prev {
left: 10px;
Expand Down
124 changes: 92 additions & 32 deletions dist/jquery.bxslider.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***
* BxSlider v4.2.1 - Fully loaded, responsive content slider
* BxSlider v4.2.2 - Fully loaded, responsive content slider
* http://bxslider.com
*
* Copyright 2014, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com
Expand Down Expand Up @@ -552,19 +552,21 @@
// add the CSS transition-duration
el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');
if(type === 'slide'){
// set the property value
el.css(slider.animProp, propValue);
// if value 0, just update
if(value === 0) {
updateAfterSlideTransition();
} else {
// bind a callback method - executes when CSS transition completes
el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
// unbind the callback
el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
setTimeout(function() {
// set the property value
el.css(slider.animProp, propValue);
// if value 0, just update
if(value === 0) {
updateAfterSlideTransition();
});
}
} else {
// bind a callback method - executes when CSS transition completes
el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
// unbind the callback
el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
updateAfterSlideTransition();
});
}
}, 0);
}else if(type === 'reset'){
el.css(slider.animProp, propValue);
}else if(type === 'ticker'){
Expand Down Expand Up @@ -646,7 +648,7 @@
slider.pagerEl = $(slider.settings.pagerCustom);
}
// assign the pager click binding
slider.pagerEl.on('click', 'a', clickPagerBind);
slider.pagerEl.on('click touchend', 'a', clickPagerBind);
};

/**
Expand All @@ -656,8 +658,8 @@
slider.controls.next = $('<a class="bx-next" href="">' + slider.settings.nextText + '</a>');
slider.controls.prev = $('<a class="bx-prev" href="">' + slider.settings.prevText + '</a>');
// bind click actions to the controls
slider.controls.next.bind('click', clickNextBind);
slider.controls.prev.bind('click', clickPrevBind);
slider.controls.next.bind('click touchend', clickNextBind);
slider.controls.prev.bind('click touchend', clickPrevBind);
// if nextSelector was supplied, populate it
if(slider.settings.nextSelector){
$(slider.settings.nextSelector).append(slider.controls.next);
Expand Down Expand Up @@ -728,10 +730,13 @@
* - DOM event object
*/
var clickNextBind = function(e){
e.preventDefault();
if (slider.controls.el.hasClass('disabled')) {
return;
}
// if auto show is running, stop it
if(slider.settings.auto){ el.stopAuto(); }
el.goToNextSlide();
e.preventDefault();
};

/**
Expand All @@ -741,10 +746,13 @@
* - DOM event object
*/
var clickPrevBind = function(e){
e.preventDefault();
if (slider.controls.el.hasClass('disabled')) {
return;
}
// if auto show is running, stop it
if(slider.settings.auto){ el.stopAuto(); }
el.goToPrevSlide();
e.preventDefault();
};

/**
Expand Down Expand Up @@ -776,14 +784,17 @@
* - DOM event object
*/
var clickPagerBind = function(e){
e.preventDefault();
if (slider.controls.el.hasClass('disabled')) {
return;
}
// if auto show is running, stop it
if(slider.settings.auto){ el.stopAuto(); }
var pagerLink = $(e.currentTarget);
if(pagerLink.attr('data-slide-index') !== undefined){
var pagerIndex = parseInt(pagerLink.attr('data-slide-index'));
// if clicked pager link is not active, continue with the goToSlide call
if(pagerIndex !== slider.active.index){ el.goToSlide(pagerIndex); }
e.preventDefault();
}
};

Expand Down Expand Up @@ -1055,7 +1066,16 @@
start: {x: 0, y: 0},
end: {x: 0, y: 0}
};
slider.viewport.bind('touchstart', onTouchStart);
slider.viewport.bind('touchstart MSPointerDown pointerdown', onTouchStart);

//for browsers that have implemented pointer events and fire a click after
//every pointerup regardless of whether pointerup is on same screen location as pointerdown or not
slider.viewport.on('click', '.bxslider a', function(e) {
if (slider.viewport.hasClass('click-disabled')) {
e.preventDefault();
slider.viewport.removeClass('click-disabled');
}
});
};

/**
Expand All @@ -1065,22 +1085,54 @@
* - DOM event object
*/
var onTouchStart = function(e){
//disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls
slider.controls.el.addClass('disabled');

if(slider.working){
e.preventDefault();
slider.controls.el.removeClass('disabled');
}else{
// record the original position when touch starts
slider.touch.originalPos = el.position();
var orig = e.originalEvent;
var touchPoints = (typeof orig.changedTouches != 'undefined') ? orig.changedTouches : [orig];
// record the starting touch x, y coordinates
slider.touch.start.x = orig.changedTouches[0].pageX;
slider.touch.start.y = orig.changedTouches[0].pageY;
slider.touch.start.x = touchPoints[0].pageX;
slider.touch.start.y = touchPoints[0].pageY;

if (slider.viewport.get(0).setPointerCapture) {
slider.pointerId = orig.pointerId;
slider.viewport.get(0).setPointerCapture(slider.pointerId);
}
// bind a "touchmove" event to the viewport
slider.viewport.bind('touchmove', onTouchMove);
slider.viewport.bind('touchmove MSPointerMove pointermove', onTouchMove);
// bind a "touchend" event to the viewport
slider.viewport.bind('touchend', onTouchEnd);
slider.viewport.bind('touchend MSPointerUp pointerup', onTouchEnd);
slider.viewport.bind('MSPointerCancel pointercancel', onPointerCancel);
}
};

/**
* Cancel Pointer for Windows Phone
*
* @param e (event)
* - DOM event object
*/
var onPointerCancel = function(e) {
/* onPointerCancel handler is needed to deal with situations when a touchend
doesn't fire after a touchstart (this happens on windows phones only) */
setPositionProperty(slider.touch.originalPos.left, 'reset', 0);

//remove handlers
slider.controls.el.removeClass('disabled');
slider.viewport.unbind('MSPointerCancel pointercancel', onPointerCancel);
slider.viewport.unbind('touchmove MSPointerMove pointermove', onTouchMove);
slider.viewport.unbind('touchend MSPointerUp pointerup', onTouchEnd);
if (slider.viewport.get(0).releasePointerCapture) {
slider.viewport.get(0).releasePointerCapture(slider.pointerId);
}
}

/**
* Event handler for "touchmove"
*
Expand All @@ -1089,9 +1141,10 @@
*/
var onTouchMove = function(e){
var orig = e.originalEvent;
var touchPoints = (typeof orig.changedTouches != 'undefined') ? orig.changedTouches : [orig];
// if scrolling on y axis, do not prevent default
var xMovement = Math.abs(orig.changedTouches[0].pageX - slider.touch.start.x);
var yMovement = Math.abs(orig.changedTouches[0].pageY - slider.touch.start.y);
var xMovement = Math.abs(touchPoints[0].pageX - slider.touch.start.x);
var yMovement = Math.abs(touchPoints[0].pageY - slider.touch.start.y);
// x axis swipe
if((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){
e.preventDefault();
Expand All @@ -1103,11 +1156,11 @@
var value = 0, change = 0;
// if horizontal, drag along x axis
if(slider.settings.mode === 'horizontal'){
change = orig.changedTouches[0].pageX - slider.touch.start.x;
change = touchPoints[0].pageX - slider.touch.start.x;
value = slider.touch.originalPos.left + change;
// if vertical, drag along y axis
}else{
change = orig.changedTouches[0].pageY - slider.touch.start.y;
change = touchPoints[0].pageY - slider.touch.start.y;
value = slider.touch.originalPos.top + change;
}
setPositionProperty(value, 'reset', 0);
Expand All @@ -1121,13 +1174,16 @@
* - DOM event object
*/
var onTouchEnd = function(e){
slider.viewport.unbind('touchmove', onTouchMove);
slider.viewport.unbind('touchmove MSPointerMove pointermove', onTouchMove);
//enable slider controls as soon as user stops interacing with slides
slider.controls.el.removeClass('disabled');
var orig = e.originalEvent;
var touchPoints = (typeof orig.changedTouches != 'undefined') ? orig.changedTouches : [orig];
var value = 0;
var distance = 0;
// record end x, y positions
slider.touch.end.x = orig.changedTouches[0].pageX;
slider.touch.end.y = orig.changedTouches[0].pageY;
slider.touch.end.x = touchPoints[0].pageX;
slider.touch.end.y = touchPoints[0].pageY;
// if fade mode, check if absolute x distance clears the threshold
if(slider.settings.mode === 'fade'){
distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
Expand Down Expand Up @@ -1167,7 +1223,10 @@
}
}
}
slider.viewport.unbind('touchend', onTouchEnd);
slider.viewport.unbind('touchend MSPointerUp pointerup', onTouchEnd);
if (slider.viewport.get(0).releasePointerCapture) {
slider.viewport.get(0).releasePointerCapture(slider.pointerId);
}
};

/**
Expand Down Expand Up @@ -1318,6 +1377,7 @@
position = slider.children.eq(requestEl).position();
}


/* If the position doesn't exist
* (e.g. if you destroy the slider on a next click),
* it doesn't throw an error.
Expand Down
Loading

0 comments on commit 7e0ba16

Please sign in to comment.