Disable "pull to refresh" in Chrome for Android
Posted onIn mobile Chrome, pulling the top of the page will reload it. Although it’s a convenient UI pattern, it might get in the way if you are trying to implement gestures in your app.
After careful observation, I have come up with a simple solution.
AngularJS
I have successfully disabled “pull to reload” with this AngularJS directive:
//Prevents "pull to reload" behaviour in Chrome. Assign to child scrollable elements.
angular.module('hereApp.directive').directive('noPullToReload', function() {
'use strict';
return {
link: function(scope, element) {
var initialY = null,
previousY = null,
bindScrollEvent = function(e) {
previousY = initialY = e.touches[0].clientY;
// Pull to reload won't be activated if the element is not initially at scrollTop === 0
if (element[0].scrollTop <= 0) {
element.on("touchmove", blockScroll);
}
},
blockScroll = function(e) {
if (previousY && previousY < e.touches[0].clientY) { //Scrolling up
e.preventDefault();
} else if (initialY >= e.touches[0].clientY) { //Scrolling down
//As soon as you scroll down, there is no risk of pulling to reload
element.off("touchmove", blockScroll);
}
previousY = e.touches[0].clientY;
},
unbindScrollEvent = function(e) {
element.off("touchmove", blockScroll);
};
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);
}
};
});
It’s safe to stop watching as soon as the user scrolls down, as the pull to refresh has no chance of being triggered.
Likewise, if scrolltop > 0
, the event won’t be triggered. In my implementation, I bind the touchmove event on touchstart, only if scrollTop <= 0
. I unbind it as soon as the user scrolls down (initialY >= e.touches[0].clientY
). If the user scrolls up (previousY < e.touches[0].clientY
), then I call preventDefault()
.
This saves us from watching scroll events needlessly, yet blocks overscrolling, and thus pulling to reload.
jQuery
If you are using jQuery, this is the untested equivalent. element
is a jQuery element:
var initialY = null,
previousY = null,
bindScrollEvent = function(e) {
previousY = initialY = e.touches[0].clientY;
// Pull to reload won't be activated if the element is not initially at scrollTop === 0
if (element[0].scrollTop <= 0) {
element.on("touchmove", blockScroll);
}
},
blockScroll = function(e) {
if (previousY && previousY < e.touches[0].clientY) { //Scrolling up
e.preventDefault();
} else if (initialY >= e.touches[0].clientY) { //Scrolling down
//As soon as you scroll down, there is no risk of pulling to reload
element.off("touchmove");
}
previousY = e.touches[0].clientY;
},
unbindScrollEvent = function(e) {
element.off("touchmove");
};
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);
Naturally, the same can also be achieved with pure JS.