web-apps/vendor/framework7/src/js/pull-to-refresh.js
2016-11-11 16:24:21 +03:00

223 lines
8.4 KiB
JavaScript

/*======================================================
************ Pull To Refresh ************
======================================================*/
app.initPullToRefresh = function (pageContainer) {
var eventsTarget = $(pageContainer);
if (!eventsTarget.hasClass('pull-to-refresh-content')) {
eventsTarget = eventsTarget.find('.pull-to-refresh-content');
}
if (!eventsTarget || eventsTarget.length === 0) return;
var touchId, isTouched, isMoved, touchesStart = {}, isScrolling, touchesDiff, touchStartTime, container, refresh = false, useTranslate = false, startTranslate = 0, translate, scrollTop, wasScrolled, layer, triggerDistance, dynamicTriggerDistance, pullStarted;
var page = eventsTarget.hasClass('page') ? eventsTarget : eventsTarget.parents('.page');
var hasNavbar = false;
if (page.find('.navbar').length > 0 || page.parents('.navbar-fixed, .navbar-through').length > 0 || page.hasClass('navbar-fixed') || page.hasClass('navbar-through')) hasNavbar = true;
if (page.hasClass('no-navbar')) hasNavbar = false;
if (!hasNavbar) eventsTarget.addClass('pull-to-refresh-no-navbar');
container = eventsTarget;
// Define trigger distance
if (container.attr('data-ptr-distance')) {
dynamicTriggerDistance = true;
}
else {
triggerDistance = 44;
}
function handleTouchStart(e) {
if (isTouched) {
if (app.device.os === 'android') {
if ('targetTouches' in e && e.targetTouches.length > 1) return;
}
else return;
}
/*jshint validthis:true */
container = $(this);
if (container.hasClass('refreshing')) {
return;
}
isMoved = false;
pullStarted = false;
isTouched = true;
isScrolling = undefined;
wasScrolled = undefined;
if (e.type === 'touchstart') touchId = e.targetTouches[0].identifier;
touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = (new Date()).getTime();
}
function handleTouchMove(e) {
if (!isTouched) return;
var pageX, pageY, touch;
if (e.type === 'touchmove') {
if (touchId && e.touches) {
for (var i = 0; i < e.touches.length; i++) {
if (e.touches[i].identifier === touchId) {
touch = e.touches[i];
}
}
}
if (!touch) touch = e.targetTouches[0];
pageX = touch.pageX;
pageY = touch.pageY;
}
else {
pageX = e.pageX;
pageY = e.pageY;
}
if (!pageX || !pageY) return;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
}
if (!isScrolling) {
isTouched = false;
return;
}
scrollTop = container[0].scrollTop;
if (typeof wasScrolled === 'undefined' && scrollTop !== 0) wasScrolled = true;
if (!isMoved) {
/*jshint validthis:true */
container.removeClass('transitioning');
if (scrollTop > container[0].offsetHeight) {
isTouched = false;
return;
}
if (dynamicTriggerDistance) {
triggerDistance = container.attr('data-ptr-distance');
if (triggerDistance.indexOf('%') >= 0) triggerDistance = container[0].offsetHeight * parseInt(triggerDistance, 10) / 100;
}
startTranslate = container.hasClass('refreshing') ? triggerDistance : 0;
if (container[0].scrollHeight === container[0].offsetHeight || app.device.os !== 'ios') {
useTranslate = true;
}
else {
useTranslate = false;
}
}
isMoved = true;
touchesDiff = pageY - touchesStart.y;
if (touchesDiff > 0 && scrollTop <= 0 || scrollTop < 0) {
// iOS 8 fix
if (app.device.os === 'ios' && parseInt(app.device.osVersion.split('.')[0], 10) > 7 && scrollTop === 0 && !wasScrolled) useTranslate = true;
if (useTranslate) {
e.preventDefault();
translate = (Math.pow(touchesDiff, 0.85) + startTranslate);
container.transform('translate3d(0,' + translate + 'px,0)');
}
if ((useTranslate && Math.pow(touchesDiff, 0.85) > triggerDistance) || (!useTranslate && touchesDiff >= triggerDistance * 2)) {
refresh = true;
container.addClass('pull-up').removeClass('pull-down');
}
else {
refresh = false;
container.removeClass('pull-up').addClass('pull-down');
}
if (!pullStarted) {
container.trigger('pullstart');
pullStarted = true;
}
container.trigger('pullmove', {
event: e,
scrollTop: scrollTop,
translate: translate,
touchesDiff: touchesDiff
});
}
else {
pullStarted = false;
container.removeClass('pull-up pull-down');
refresh = false;
return;
}
}
function handleTouchEnd(e) {
if (e.type === 'touchend' && e.changedTouches && e.changedTouches.length > 0 && touchId) {
if (e.changedTouches[0].identifier !== touchId) return;
}
if (!isTouched || !isMoved) {
isTouched = false;
isMoved = false;
return;
}
if (translate) {
container.addClass('transitioning');
translate = 0;
}
container.transform('');
if (refresh) {
container.addClass('refreshing');
container.trigger('refresh', {
done: function () {
app.pullToRefreshDone(container);
}
});
}
else {
container.removeClass('pull-down');
}
isTouched = false;
isMoved = false;
if (pullStarted) container.trigger('pullend');
}
// Attach Events
var passiveListener = app.touchEvents.start === 'touchstart' && app.support.passiveListener ? {passive: true, capture: false} : false;
eventsTarget.on(app.touchEvents.start, handleTouchStart, passiveListener);
eventsTarget.on(app.touchEvents.move, handleTouchMove);
eventsTarget.on(app.touchEvents.end, handleTouchEnd, passiveListener);
// Detach Events on page remove
if (page.length === 0) return;
function destroyPullToRefresh() {
eventsTarget.off(app.touchEvents.start, handleTouchStart);
eventsTarget.off(app.touchEvents.move, handleTouchMove);
eventsTarget.off(app.touchEvents.end, handleTouchEnd);
}
eventsTarget[0].f7DestroyPullToRefresh = destroyPullToRefresh;
function detachEvents() {
destroyPullToRefresh();
page.off('pageBeforeRemove', detachEvents);
}
page.on('pageBeforeRemove', detachEvents);
};
app.pullToRefreshDone = function (container) {
container = $(container);
if (container.length === 0) container = $('.pull-to-refresh-content.refreshing');
container.removeClass('refreshing').addClass('transitioning');
container.transitionEnd(function () {
container.removeClass('transitioning pull-up pull-down');
container.trigger('refreshdone');
});
};
app.pullToRefreshTrigger = function (container) {
container = $(container);
if (container.length === 0) container = $('.pull-to-refresh-content');
if (container.hasClass('refreshing')) return;
container.addClass('transitioning refreshing');
container.trigger('refresh', {
done: function () {
app.pullToRefreshDone(container);
}
});
};
app.destroyPullToRefresh = function (pageContainer) {
pageContainer = $(pageContainer);
var pullToRefreshContent = pageContainer.hasClass('pull-to-refresh-content') ? pageContainer : pageContainer.find('.pull-to-refresh-content');
if (pullToRefreshContent.length === 0) return;
if (pullToRefreshContent[0].f7DestroyPullToRefresh) pullToRefreshContent[0].f7DestroyPullToRefresh();
};