311 lines
11 KiB
JavaScript
311 lines
11 KiB
JavaScript
/**
|
||
* dropload
|
||
* 西門(http://ons.me/526.html)
|
||
* 0.9.0(160215)
|
||
*/
|
||
|
||
; (function ($) {
|
||
'use strict';
|
||
var win = window;
|
||
var doc = document;
|
||
var $win = $(win);
|
||
var $doc = $(doc);
|
||
$.fn.dropload = function (options) {
|
||
console.log('this', this);
|
||
return new MyDropLoad(this, options);
|
||
};
|
||
var MyDropLoad = function (element, options) {
|
||
var me = this;
|
||
me.$element = element;
|
||
// 上方是否插入DOM
|
||
me.upInsertDOM = false;
|
||
// loading狀態
|
||
me.loading = false;
|
||
// 是否鎖定
|
||
me.isLockUp = false;
|
||
me.isLockDown = false;
|
||
// 是否有數據
|
||
me.isData = true;
|
||
me._scrollTop = 0;
|
||
me._threshold = 0;
|
||
me.init(options);
|
||
console.log('element', element);
|
||
|
||
};
|
||
|
||
// 初始化
|
||
MyDropLoad.prototype.init = function (options) {
|
||
var me = this;
|
||
me.opts = $.extend(true, {}, {
|
||
scrollArea: me.$element, // 滑動區域
|
||
domUp: { // 上方DOM
|
||
domClass: 'dropload-up',
|
||
domRefresh: '<div class="dropload-refresh">↓下拉刷新</div>',
|
||
domUpdate: '<div class="dropload-update">↑釋放更新</div>',
|
||
domLoad: '<div class="dropload-load"><span class="loading"></span>加載中...</div>'
|
||
},
|
||
domDown: { // 下方DOM
|
||
domClass: 'dropload-down',
|
||
domRefresh: '<div class="dropload-refresh">↑上拉加載更多</div>',
|
||
domLoad: '<div class="dropload-load"><span class="loading"></span>加載中...</div>',
|
||
domNoData: '<div class="dropload-noData">沒有更多了</div>'
|
||
},
|
||
autoLoad: true, // 自動加載
|
||
distance: 50, // 拉動距離
|
||
threshold: '', // 提前加載距離
|
||
loadUpFn: '', // 上方function
|
||
loadDownFn: '' // 下方function
|
||
}, options);
|
||
|
||
// 如果加載下方,事先在下方插入DOM
|
||
if (me.opts.loadDownFn != '') {
|
||
me.$element.append('<div class="' + me.opts.domDown.domClass + '">' + me.opts.domDown.domRefresh + '</div>');
|
||
me.$domDown = $('.' + me.opts.domDown.domClass);
|
||
}
|
||
|
||
// 計算提前加載距離
|
||
if (!!me.$domDown && me.opts.threshold === '') {
|
||
// 默認滑到加載區2/3處時加載
|
||
me._threshold = Math.floor(me.$domDown.height() * 1 / 3);
|
||
} else {
|
||
me._threshold = me.opts.threshold;
|
||
}
|
||
|
||
// 判斷滾動區域
|
||
if (me.opts.scrollArea == win) {
|
||
me.$scrollArea = $win;
|
||
// 獲取文檔高度
|
||
me._scrollContentHeight = $doc.height();
|
||
// 獲取win顯示區高度 —— 這裏有坑
|
||
me._scrollWindowHeight = doc.documentElement.clientHeight;
|
||
} else {
|
||
me.$scrollArea = me.opts.scrollArea;
|
||
me._scrollContentHeight = me.$element[0].scrollHeight;
|
||
me._scrollWindowHeight = me.$element.height();
|
||
}
|
||
fnAutoLoad(me);
|
||
|
||
// 窗口調整
|
||
$win.on('resize', function () {
|
||
if (me.opts.scrollArea == win) {
|
||
// 重新獲取win顯示區高度
|
||
me._scrollWindowHeight = win.innerHeight;
|
||
} else {
|
||
me._scrollWindowHeight = me.$element.height();
|
||
}
|
||
});
|
||
|
||
// 綁定觸摸
|
||
me.$element.on('touchstart', function (e) {
|
||
if (!me.loading) {
|
||
fnTouches(e);
|
||
fnTouchstart(e, me);
|
||
}
|
||
});
|
||
me.$element.on('touchmove', function (e) {
|
||
if (!me.loading) {
|
||
fnTouches(e, me);
|
||
fnTouchmove(e, me);
|
||
}
|
||
});
|
||
me.$element.on('touchend', function () {
|
||
if (!me.loading) {
|
||
fnTouchend(me);
|
||
}
|
||
});
|
||
|
||
// 加載下方
|
||
me.$scrollArea.on('scroll', function () {
|
||
me._scrollTop = me.$scrollArea.scrollTop();
|
||
|
||
// 滾動頁面觸發加載數據
|
||
if (me.opts.loadDownFn != '' && !me.loading && !me.isLockDown && (me._scrollContentHeight - me._threshold) <= (me._scrollWindowHeight + me._scrollTop)) {
|
||
loadDown(me);
|
||
}
|
||
});
|
||
};
|
||
|
||
// touches
|
||
function fnTouches (e) {
|
||
if (!e.touches) {
|
||
e.touches = e.originalEvent.touches;
|
||
}
|
||
}
|
||
|
||
// touchstart
|
||
function fnTouchstart (e, me) {
|
||
me._startY = e.touches[0].pageY;
|
||
// 記住觸摸時的scrolltop值
|
||
me.touchScrollTop = me.$scrollArea.scrollTop();
|
||
}
|
||
|
||
// touchmove
|
||
function fnTouchmove (e, me) {
|
||
me._curY = e.touches[0].pageY;
|
||
me._moveY = me._curY - me._startY;
|
||
|
||
if (me._moveY > 0) {
|
||
me.direction = 'down';
|
||
} else if (me._moveY < 0) {
|
||
me.direction = 'up';
|
||
}
|
||
|
||
var _absMoveY = Math.abs(me._moveY);
|
||
|
||
// 加載上方
|
||
if (me.opts.loadUpFn != '' && me.touchScrollTop <= 0 && me.direction == 'down' && !me.isLockUp) {
|
||
e.preventDefault();
|
||
|
||
me.$domUp = $('.' + me.opts.domUp.domClass);
|
||
// 如果加載區沒有DOM
|
||
if (!me.upInsertDOM) {
|
||
me.$element.prepend('<div class="' + me.opts.domUp.domClass + '"></div>');
|
||
me.upInsertDOM = true;
|
||
}
|
||
|
||
fnTransition(me.$domUp, 0);
|
||
|
||
// 下拉
|
||
if (_absMoveY <= me.opts.distance) {
|
||
me._offsetY = _absMoveY;
|
||
// todo:move時會不斷清空、增加dom,有可能影響性能,下同
|
||
me.$domUp.html(me.opts.domUp.domRefresh);
|
||
// 指定距離 < 下拉距離 < 指定距離*2
|
||
} else if (_absMoveY > me.opts.distance && _absMoveY <= me.opts.distance * 2) {
|
||
me._offsetY = me.opts.distance + (_absMoveY - me.opts.distance) * 0.5;
|
||
me.$domUp.html(me.opts.domUp.domUpdate);
|
||
// 下拉距離 > 指定距離*2
|
||
} else {
|
||
me._offsetY = me.opts.distance + me.opts.distance * 0.5 + (_absMoveY - me.opts.distance * 2) * 0.2;
|
||
}
|
||
|
||
me.$domUp.css({ 'height': me._offsetY });
|
||
}
|
||
}
|
||
|
||
// touchend
|
||
function fnTouchend (me) {
|
||
var _absMoveY = Math.abs(me._moveY);
|
||
if (me.opts.loadUpFn != '' && me.touchScrollTop <= 0 && me.direction == 'down' && !me.isLockUp) {
|
||
fnTransition(me.$domUp, 300);
|
||
|
||
if (_absMoveY > me.opts.distance) {
|
||
me.$domUp.css({ 'height': me.$domUp.children().height() });
|
||
me.$domUp.html(me.opts.domUp.domLoad);
|
||
me.loading = true;
|
||
me.opts.loadUpFn(me);
|
||
} else {
|
||
me.$domUp.css({ 'height': '0' }).on('webkitTransitionEnd mozTransitionEnd transitionend', function () {
|
||
me.upInsertDOM = false;
|
||
$(this).remove();
|
||
});
|
||
}
|
||
me._moveY = 0;
|
||
}
|
||
}
|
||
|
||
// 如果文檔高度不大於窗口高度,數據較少,自動加載下方數據
|
||
function fnAutoLoad (me) {
|
||
if (me.opts.autoLoad) {
|
||
if ((me._scrollContentHeight - me._threshold) <= me._scrollWindowHeight) {
|
||
loadDown(me);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 重新獲取文檔高度
|
||
function fnRecoverContentHeight (me) {
|
||
if (me.opts.scrollArea == win) {
|
||
me._scrollContentHeight = $doc.height();
|
||
} else {
|
||
me._scrollContentHeight = me.$element[0].scrollHeight;
|
||
}
|
||
}
|
||
|
||
// 加載下方
|
||
function loadDown (me) {
|
||
me.direction = 'up';
|
||
me.$domDown.html(me.opts.domDown.domLoad);
|
||
me.loading = true;
|
||
me.opts.loadDownFn(me);
|
||
}
|
||
|
||
// 鎖定
|
||
MyDropLoad.prototype.lock = function (direction) {
|
||
var me = this;
|
||
// 如果不指定方向
|
||
if (direction === undefined) {
|
||
// 如果操作方向向上
|
||
if (me.direction == 'up') {
|
||
me.isLockDown = true;
|
||
// 如果操作方向向下
|
||
} else if (me.direction == 'down') {
|
||
me.isLockUp = true;
|
||
} else {
|
||
me.isLockUp = true;
|
||
me.isLockDown = true;
|
||
}
|
||
// 如果指定鎖上方
|
||
} else if (direction == 'up') {
|
||
me.isLockUp = true;
|
||
// 如果指定鎖下方
|
||
} else if (direction == 'down') {
|
||
me.isLockDown = true;
|
||
// 為了解決DEMO5中tab效果bug,因為滑動到下面,再滑上去點tab,direction=down,所以有bug
|
||
me.direction = 'up';
|
||
}
|
||
};
|
||
|
||
// 解鎖
|
||
MyDropLoad.prototype.unlock = function () {
|
||
var me = this;
|
||
// 簡單粗暴解鎖
|
||
me.isLockUp = false;
|
||
me.isLockDown = false;
|
||
// 為了解決DEMO5中tab效果bug,因為滑動到下面,再滑上去點tab,direction=down,所以有bug
|
||
me.direction = 'up';
|
||
};
|
||
|
||
// 無數據
|
||
MyDropLoad.prototype.noData = function (flag) {
|
||
var me = this;
|
||
if (flag === undefined || flag == true) {
|
||
me.isData = false;
|
||
} else if (flag == false) {
|
||
me.isData = true;
|
||
}
|
||
};
|
||
|
||
// 重置
|
||
MyDropLoad.prototype.resetload = function () {
|
||
var me = this;
|
||
if (me.direction == 'down' && me.upInsertDOM) {
|
||
me.$domUp.css({ 'height': '0' }).on('webkitTransitionEnd mozTransitionEnd transitionend', function () {
|
||
me.loading = false;
|
||
me.upInsertDOM = false;
|
||
$(this).remove();
|
||
fnRecoverContentHeight(me);
|
||
});
|
||
} else if (me.direction == 'up') {
|
||
me.loading = false;
|
||
// 如果有數據
|
||
if (me.isData) {
|
||
// 加載區修改樣式
|
||
me.$domDown.html(me.opts.domDown.domRefresh);
|
||
fnRecoverContentHeight(me);
|
||
fnAutoLoad(me);
|
||
} else {
|
||
// 如果沒數據
|
||
me.$domDown.html(me.opts.domDown.domNoData);
|
||
}
|
||
}
|
||
};
|
||
|
||
// css過渡
|
||
function fnTransition (dom, num) {
|
||
dom.css({
|
||
'-webkit-transition': 'all ' + num + 'ms',
|
||
'transition': 'all ' + num + 'ms'
|
||
});
|
||
}
|
||
})(window.Zepto || window.jQuery); |