vant-ui
Version:
Mobile UI Components
813 lines (811 loc) • 26.4 kB
JavaScript
/*!
* mescroll -- 精致的下拉刷新和上拉加载js框架 ( a great JS framework for pull-refresh and pull-up-loading )
* version 1.3.2
* 2018-01-01
*
* 您如果在vue,angular等环境中,因作用域的问题未能正常引入或初始化Mescroll对象,则可引用mescroll.m.js;
* mescroll.m.js去掉了mescroll.min.js套的一层模块规范的代码
* 因为没有闭包限制作用域,所以能解决某些情况下引用mescroll.min.js报'Mescroll' undefined的问题
* 具体请参考: https://github.com/mescroll/mescroll/issues/56
*/
function MeScroll(a, d) {
var f = this;
f.version = "1.3.2";
f.isScrollBody = (!a || a == "body");
f.scrollDom = f.isScrollBody ? document.body : f.getDomById(a);
if (!f.scrollDom) {
return
}
f.options = d || {};
var c = navigator.userAgent;
var b = !!c.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
var g = typeof window.orientation == "undefined";
var e = c.indexOf("Android") > -1 || c.indexOf("Adr") > -1;
f.os = {
ios: b,
pc: g,
android: e
};
f.isDownScrolling = false;
f.isUpScrolling = false;
f.initDownScroll();
f.initUpScroll();
setTimeout(function () {
if (f.optDown.use && f.optDown.auto) {
if (f.optDown.autoShowLoading) {
f.triggerDownScroll()
} else {
f.optDown.callback && f.optDown.callback(f)
}
}
f.optUp.use && f.optUp.auto && !f.isUpAutoLoad && f.triggerUpScroll()
}, 30)
}
MeScroll.prototype.extendDownScroll = function (a) {
MeScroll.extend(a, {
use: true,
auto: true,
autoShowLoading: false,
isLock: false,
isBoth: false,
offset: 80,
outOffsetRate: 0.2,
bottomOffset: 20,
minAngle: 45,
hardwareClass: "mescroll-hardware",
warpId: null,
warpClass: "mescroll-downwarp",
resetClass: "mescroll-downwarp-reset",
htmlContent: '<p class="downwarp-progress"></p><p class="downwarp-tip">下拉刷新 </p>',
inited: function (c, b) {
c.downTipDom = b.getElementsByClassName("downwarp-tip")[0];
c.downProgressDom = b.getElementsByClassName("downwarp-progress")[0]
},
inOffset: function (b) {
if (b.downTipDom) {
b.downTipDom.innerHTML = "下拉刷新"
}
if (b.downProgressDom) {
b.downProgressDom.classList.remove("mescroll-rotate")
}
},
outOffset: function (b) {
if (b.downTipDom) {
b.downTipDom.innerHTML = "释放更新"
}
},
onMoving: function (c, e, b) {
if (c.downProgressDom) {
var d = 360 * e;
c.downProgressDom.style.webkitTransform = "rotate(" + d + "deg)";
c.downProgressDom.style.transform = "rotate(" + d + "deg)"
}
},
beforeLoading: function (c, b) {
return false
},
showLoading: function (b) {
if (b.downTipDom) {
b.downTipDom.innerHTML = "加载中 ..."
}
if (b.downProgressDom) {
b.downProgressDom.classList.add("mescroll-rotate")
}
},
callback: function (b) {
b.resetUpScroll()
}
})
};
MeScroll.prototype.extendUpScroll = function (a) {
var b = this.os.pc;
MeScroll.extend(a, {
use: true,
auto: true,
isLock: false,
isBoth: false,
isBounce: true,
callback: null,
page: {
num: 0,
size: 10,
time: null
},
noMoreSize: 5,
offset: 100,
toTop: {
warpId: null,
src: null,
html: null,
offset: 1000,
warpClass: "mescroll-totop",
showClass: "mescroll-fade-in",
hideClass: "mescroll-fade-out",
duration: 300,
supportTap: false
},
loadFull: {
use: false,
delay: 500
},
empty: {
warpId: null,
icon: null,
tip: "暂无相关数据~",
btntext: "",
btnClick: null,
supportTap: false
},
clearId: null,
clearEmptyId: null,
hardwareClass: "mescroll-hardware",
warpId: null,
warpClass: "mescroll-upwarp",
htmlLoading: '<p class="upwarp-progress mescroll-rotate"></p><p class="upwarp-tip">加载中..</p>',
htmlNodata: '<p class="upwarp-nodata">-- END --</p>',
inited: function (c, d) {},
showLoading: function (c, d) {
d.innerHTML = c.optUp.htmlLoading
},
showNoMore: function (c, d) {
d.innerHTML = c.optUp.htmlNodata
},
onScroll: null,
scrollbar: {
use: b,
barClass: "mescroll-bar"
}
})
};
MeScroll.extend = function (b, a) {
if (!b) {
return a
}
for (var key in a) {
if (b[key] == null) {
b[key] = a[key]
} else {
if (typeof b[key] == "object") {
MeScroll.extend(b[key], a[key])
}
}
}
return b
};
MeScroll.prototype.initDownScroll = function () {
var b = this;
b.optDown = b.options.down || {};
b.extendDownScroll(b.optDown);
b.touchstartEvent = function (c) {
if (b.isScrollTo) {
c.preventDefault()
}
b.startPoint = b.getPoint(c);
b.lastPoint = b.startPoint;
b.maxTouchmoveY = b.getBodyHeight() - b.optDown.bottomOffset;
b.inTouchend = false;
if (b.os.pc && b.getScrollTop() <= 0) {
b.scrollDom.addEventListener("mousemove", b.touchmoveEvent);
document.ondragstart = function () {
return false
}
}
};
b.scrollDom.addEventListener("mousedown", b.touchstartEvent);
b.scrollDom.addEventListener("touchstart", b.touchstartEvent);
b.touchmoveEvent = function (k) {
var c = b.getScrollTop();
var g = b.getPoint(k);
var d = g.y - b.startPoint.y;
if (d > 0) {
if (c <= 0) {
if (k.cancelable && !k.defaultPrevented) {
k.preventDefault()
}
if (b.optDown.use && !b.inTouchend && !b.isDownScrolling && !b.optDown.isLock && (!b.isUpScrolling || (b.isUpScrolling && b.optUp.isBoth))) {
var n = Math.abs(b.lastPoint.x - g.x);
var m = Math.abs(b.lastPoint.y - g.y);
var l = Math.sqrt(n * n + m * m);
if (l != 0) {
var f = Math.asin(m / l) / Math.PI * 180;
if (f < b.optDown.minAngle) {
return
}
}
if (b.maxTouchmoveY > 0 && g.y >= b.maxTouchmoveY) {
b.inTouchend = true;
b.touchendEvent();
return
}
var o = g.y - b.lastPoint.y;
if (!b.downHight) {
b.downHight = 0
}
if (b.downHight < b.optDown.offset) {
if (b.movetype != 1) {
b.movetype = 1;
b.optDown.inOffset(b);
b.downwarp.classList.remove(b.optDown.resetClass);
b.scrollDom.classList.add(b.optDown.hardwareClass);
b.scrollDom.style.webkitOverflowScrolling = "auto";
b.isMoveDown = true
}
b.downHight += o
} else {
if (b.movetype != 2) {
b.movetype = 2;
b.optDown.outOffset(b);
b.downwarp.classList.remove(b.optDown.resetClass);
b.scrollDom.classList.add(b.optDown.hardwareClass);
b.scrollDom.style.webkitOverflowScrolling = "auto";
b.isMoveDown = true
}
if (o > 0) {
b.downHight += o * b.optDown.outOffsetRate
} else {
b.downHight += o
}
}
b.downwarp.style.height = b.downHight + "px";
var j = b.downHight / b.optDown.offset;
b.optDown.onMoving(b, j, b.downHight)
}
}
} else {
if (d < 0) {
var p = b.getScrollHeight();
var i = b.getClientHeight();
var h = p - i - c;
if (!b.optUp.isBounce && k.cancelable && !k.defaultPrevented && h <= 0) {
k.preventDefault()
}
if (b.optUp.use && !b.optUp.isLock && b.optUp.hasNext && !b.isUpScrolling && (!b.isDownScrolling || (b.isDownScrolling && b.optDown.isBoth)) && (i + b.optUp.offset >= p || h <= 0)) {
b.triggerUpScroll()
}
}
}
b.lastPoint = g
};
b.scrollDom.addEventListener("touchmove", b.touchmoveEvent);
b.touchendEvent = function () {
if (b.optDown.use && b.isMoveDown) {
if (b.downHight >= b.optDown.offset) {
b.triggerDownScroll()
} else {
b.downwarp.classList.add(b.optDown.resetClass);
b.downHight = 0;
b.downwarp.style.height = 0
}
b.scrollDom.style.webkitOverflowScrolling = "touch";
b.scrollDom.classList.remove(b.optDown.hardwareClass);
b.movetype = 0;
b.isMoveDown = false
}
if (b.os.pc) {
b.scrollDom.removeEventListener("mousemove", b.touchmoveEvent);
document.ondragstart = function () {
return true
}
}
};
b.scrollDom.addEventListener("mouseup", b.touchendEvent);
b.scrollDom.addEventListener("mouseleave", b.touchendEvent);
b.scrollDom.addEventListener("touchend", b.touchendEvent);
b.scrollDom.addEventListener("touchcancel", b.touchendEvent);
if (b.optDown.use) {
b.downwarp = document.createElement("div");
b.downwarp.className = b.optDown.warpClass;
b.downwarp.innerHTML = '<div class="downwarp-content">' + b.optDown.htmlContent + "</div>";
var a = b.optDown.warpId ? b.getDomById(b.optDown.warpId) : b.scrollDom;
if (b.optDown.warpId && a) {
a.appendChild(b.downwarp)
} else {
if (!a) {
a = b.scrollDom
}
a.insertBefore(b.downwarp, b.scrollDom.firstChild)
}
setTimeout(function () {
b.optDown.inited(b, b.downwarp)
}, 0)
}
};
MeScroll.prototype.getPoint = function (a) {
return {
x: a.touches ? a.touches[0].pageX : a.clientX,
y: a.touches ? a.touches[0].pageY : a.clientY
}
};
MeScroll.prototype.triggerDownScroll = function () {
if (!this.optDown.beforeLoading(this, this.downwarp)) {
this.showDownScroll();
this.optDown.callback && this.optDown.callback(this)
}
};
MeScroll.prototype.showDownScroll = function () {
this.isDownScrolling = true;
this.optDown.showLoading(this);
this.downHight = this.optDown.offset;
this.downwarp.classList.add(this.optDown.resetClass);
this.downwarp.style.height = this.optDown.offset + "px"
};
MeScroll.prototype.endDownScroll = function () {
this.downHight = 0;
this.downwarp.style.height = 0;
this.isDownScrolling = false;
if (this.downProgressDom) {
this.downProgressDom.classList.remove("mescroll-rotate")
}
};
MeScroll.prototype.lockDownScroll = function (a) {
if (a == null) {
a = true
}
this.optDown.isLock = a
};
MeScroll.prototype.initUpScroll = function () {
var b = this;
b.optUp = b.options.up || {
use: false
};
b.extendUpScroll(b.optUp);
if (b.optUp.scrollbar.use) {
b.scrollDom.classList.add(b.optUp.scrollbar.barClass)
}
if (!b.optUp.isBounce) {
b.setBounce(false)
}
if (b.optUp.use == false) {
return
}
b.optUp.hasNext = true;
b.upwarp = document.createElement("div");
b.upwarp.className = b.optUp.warpClass;
var a;
if (b.optUp.warpId) {
a = b.getDomById(b.optUp.warpId)
}
if (!a) {
a = b.scrollDom
}
a.appendChild(b.upwarp);
b.preScrollY = 0;
b.scrollEvent = function () {
var e = b.getScrollTop();
var d = e - b.preScrollY > 0;
b.preScrollY = e;
if (!b.isUpScrolling && (!b.isDownScrolling || (b.isDownScrolling && b.optDown.isBoth))) {
if (!b.optUp.isLock && b.optUp.hasNext) {
var c = b.getScrollHeight() - b.getClientHeight() - e;
if (c <= b.optUp.offset && d) {
b.triggerUpScroll()
}
}
var f = b.optUp.toTop;
if (f.src || f.html) {
if (e >= f.offset) {
b.showTopBtn()
} else {
b.hideTopBtn()
}
}
}
b.optUp.onScroll && b.optUp.onScroll(b, e, d)
};
if (b.isScrollBody) {
window.addEventListener("scroll", b.scrollEvent)
} else {
b.scrollDom.addEventListener("scroll", b.scrollEvent)
}
setTimeout(function () {
b.optUp.inited(b, b.upwarp)
}, 0)
};
MeScroll.prototype.setBounce = function (a) {
if (this.isScrollBody || !this.os.ios) {
return
}
if (a == false) {
this.optUp.isBounce = false;
window.addEventListener("touchmove", this.bounceTouchmove)
} else {
this.optUp.isBounce = true;
window.removeEventListener("touchmove", this.bounceTouchmove)
}
};
MeScroll.prototype.bounceTouchmove = function (g) {
var i = this;
var c = g.target;
var d = true;
while (c !== document.body && c !== document) {
var l = c.classList;
if (l) {
if (l.contains("mescroll") || l.contains("mescroll-touch")) {
d = false;
break
} else {
if (l.contains("mescroll-touch-x") || l.contains("mescroll-touch-y")) {
var b = g.touches ? g.touches[0].pageX : g.clientX;
var a = g.touches ? g.touches[0].pageY : g.clientY;
if (!i.preWinX) {
i.preWinX = b
}
if (!i.preWinY) {
i.preWinY = a
}
var k = Math.abs(i.preWinX - b);
var j = Math.abs(i.preWinY - a);
var h = Math.sqrt(k * k + j * j);
i.preWinX = b;
i.preWinY = a;
if (h != 0) {
var f = Math.asin(j / h) / Math.PI * 180;
if ((f <= 45 && l.contains("mescroll-touch-x")) || (f > 45 && l.contains("mescroll-touch-y"))) {
d = false;
break
}
}
}
}
}
c = c.parentNode
}
if (d && g.cancelable && !g.defaultPrevented) {
g.preventDefault()
}
};
MeScroll.prototype.triggerUpScroll = function () {
if (!this.isUpScrolling) {
this.showUpScroll();
this.optUp.page.num++;
this.isUpAutoLoad = true;
this.optUp.callback && this.optUp.callback(this.optUp.page, this)
}
};
MeScroll.prototype.showUpScroll = function () {
this.isUpScrolling = true;
this.upwarp.classList.add(this.optUp.hardwareClass);
this.upwarp.style.display = "block";
this.optUp.showLoading(this, this.upwarp)
};
MeScroll.prototype.showNoMore = function () {
this.upwarp.style.display = "block";
this.optUp.hasNext = false;
this.optUp.showNoMore(this, this.upwarp)
};
MeScroll.prototype.hideUpScroll = function () {
this.upwarp.style.display = "none";
this.upwarp.classList.remove(this.optUp.hardwareClass);
var a = this.upwarp.getElementsByClassName("upwarp-progress")[0];
if (a) {
a.classList.remove("mescroll-rotate")
}
};
MeScroll.prototype.endUpScroll = function (a) {
if (a != null) {
if (a) {
this.showNoMore()
} else {
this.hideUpScroll()
}
}
this.isUpScrolling = false
};
MeScroll.prototype.resetUpScroll = function (b) {
if (this.optUp && this.optUp.use) {
var a = this.optUp.page;
this.prePageNum = a.num;
this.prePageTime = a.time;
a.num = 1;
a.time = null;
if (!this.isDownScrolling && b != false) {
if (b == null) {
this.removeEmpty();
this.clearDataList();
this.showUpScroll()
} else {
this.showDownScroll()
}
}
this.isUpAutoLoad = true;
this.optUp.callback && this.optUp.callback(a, this)
}
};
MeScroll.prototype.setPageNum = function (a) {
this.optUp.page.num = a - 1
};
MeScroll.prototype.setPageSize = function (a) {
this.optUp.page.size = a
};
MeScroll.prototype.clearDataList = function () {
var b = this.optUp.clearId || this.optUp.clearEmptyId;
if (b) {
var a = this.getDomById(b);
if (a) {
a.innerHTML = ""
}
}
};
MeScroll.prototype.endByPage = function (b, d, c) {
var a;
if (this.optUp.use && d != null) {
a = this.optUp.page.num < d
}
this.endSuccess(b, a, c)
};
MeScroll.prototype.endBySize = function (c, b, d) {
var a;
if (this.optUp.use && b != null) {
var e = (this.optUp.page.num - 1) * this.optUp.page.size + c;
a = e < b
}
this.endSuccess(c, a, d)
};
MeScroll.prototype.endSuccess = function (c, a, e) {
if (this.isDownScrolling) {
this.endDownScroll()
}
if (this.optUp.use) {
var d;
if (c != null) {
var f = this.optUp.page.num;
var b = this.optUp.page.size;
if (f == 1) {
this.clearDataList();
if (e) {
this.optUp.page.time = e
}
}
if (c < b || a == false) {
this.optUp.hasNext = false;
if (c == 0 && f == 1) {
d = false;
this.showEmpty()
} else {
var g = (f - 1) * b + c;
if (g < this.optUp.noMoreSize) {
d = false
} else {
d = true
}
this.removeEmpty()
}
} else {
d = false;
this.optUp.hasNext = true;
this.removeEmpty()
}
}
this.endUpScroll(d);
this.loadFull()
}
};
MeScroll.prototype.endErr = function () {
if (this.isDownScrolling) {
var a = this.optUp.page;
if (a && this.prePageNum) {
a.num = this.prePageNum;
a.time = this.prePageTime
}
this.endDownScroll()
}
if (this.isUpScrolling) {
this.optUp.page.num--;
this.endUpScroll(false)
}
};
MeScroll.prototype.loadFull = function () {
var a = this;
if (a.optUp.loadFull.use && !a.optUp.isLock && a.optUp.hasNext && a.getScrollHeight() <= a.getClientHeight()) {
setTimeout(function () {
if (a.getScrollHeight() <= a.getClientHeight()) {
a.triggerUpScroll()
}
}, a.optUp.loadFull.delay)
}
};
MeScroll.prototype.lockUpScroll = function (a) {
if (a == null) {
a = true
}
this.optUp.isLock = a
};
MeScroll.prototype.showEmpty = function () {
var b = this;
var c = b.optUp.empty;
var a = c.warpId || b.optUp.clearEmptyId;
if (a == null) {
return
}
var f = b.getDomById(a);
if (f) {
b.removeEmpty();
var e = "";
if (c.icon) {
e += '<img class="empty-icon" src="' + c.icon + '"/>'
}
if (c.tip) {
e += '<p class="empty-tip">' + c.tip + "</p>"
}
if (c.btntext) {
e += '<p class="empty-btn">' + c.btntext + "</p>"
}
b.emptyDom = document.createElement("div");
b.emptyDom.className = "mescroll-empty";
b.emptyDom.innerHTML = e;
f.appendChild(b.emptyDom);
if (c.btnClick) {
var d = b.emptyDom.getElementsByClassName("empty-btn")[0];
if (c.supportTap) {
d.addEventListener("tap", function (g) {
g.stopPropagation();
g.preventDefault();
c.btnClick()
})
} else {
d.onclick = function () {
c.btnClick()
}
}
}
}
};
MeScroll.prototype.removeEmpty = function () {
this.removeChild(this.emptyDom)
};
MeScroll.prototype.showTopBtn = function () {
if (!this.topBtnShow) {
this.topBtnShow = true;
var b = this;
var c = b.optUp.toTop;
if (b.toTopBtn == null) {
if (c.html) {
b.toTopBtn = document.createElement("div");
b.toTopBtn.innerHTML = c.html
} else {
b.toTopBtn = document.createElement("img");
b.toTopBtn.src = c.src
}
b.toTopBtn.className = c.warpClass;
if (c.supportTap) {
b.toTopBtn.addEventListener("tap", function (d) {
d.stopPropagation();
d.preventDefault();
b.scrollTo(0, b.optUp.toTop.duration)
})
} else {
b.toTopBtn.onclick = function () {
b.scrollTo(0, b.optUp.toTop.duration)
}
}
var a;
if (c.warpId) {
a = b.getDomById(c.warpId)
}
if (!a) {
a = document.body
}
a.appendChild(b.toTopBtn)
}
b.toTopBtn.classList.remove(c.hideClass);
b.toTopBtn.classList.add(c.showClass)
}
};
MeScroll.prototype.hideTopBtn = function () {
if (this.topBtnShow && this.toTopBtn) {
this.topBtnShow = false;
this.toTopBtn.classList.remove(this.optUp.toTop.showClass);
this.toTopBtn.classList.add(this.optUp.toTop.hideClass)
}
};
MeScroll.prototype.scrollTo = function (f, b) {
var c = this;
var e = c.getScrollTop();
var a = f;
if (a > 0) {
var d = c.getScrollHeight() - c.getClientHeight();
if (a > d) {
a = d
}
} else {
a = 0
}
c.isScrollTo = true;
c.getStep(e, a, function (g) {
c.setScrollTop(g);
if (g == a) {
c.isScrollTo = false
}
}, b)
};
MeScroll.prototype.getStep = function (e, c, j, k, g) {
var h = c - e;
if (k == 0 || h == 0) {
j && j(c);
return
}
k = k || 300;
g = g || 30;
var f = k / g;
var b = h / f;
var d = 0;
var a = window.setInterval(function () {
if (d < f - 1) {
e += b;
j && j(e, a);
d++
} else {
j && j(c, a);
window.clearInterval(a)
}
}, g)
};
MeScroll.prototype.getScrollHeight = function () {
return this.scrollDom.scrollHeight
};
MeScroll.prototype.getClientHeight = function () {
if (this.isScrollBody && document.compatMode == "CSS1Compat") {
return document.documentElement.clientHeight
} else {
return this.scrollDom.clientHeight
}
};
MeScroll.prototype.getBodyHeight = function () {
return document.body.clientHeight || document.documentElement.clientHeight
};
MeScroll.prototype.getScrollTop = function () {
if (this.isScrollBody) {
return document.documentElement.scrollTop || document.body.scrollTop
} else {
return this.scrollDom.scrollTop
}
};
MeScroll.prototype.getToBottom = function () {
return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
};
MeScroll.prototype.setScrollTop = function (a) {
if (this.isScrollBody) {
document.documentElement.scrollTop = a;
document.body.scrollTop = a
} else {
this.scrollDom.scrollTop = a
}
};
MeScroll.prototype.getDomById = function (b) {
var a;
if (b) {
a = document.getElementById(b)
}
if (!a) {
console.error('the element with id as "' + b + '" can not be found: document.getElementById("' + b + '")==null')
}
return a
};
MeScroll.prototype.removeChild = function (b) {
if (b) {
var a = b.parentNode;
a && a.removeChild(b);
b = null
}
};
MeScroll.prototype.destroy = function () {
var a = this;
a.scrollDom.removeEventListener("touchstart", a.touchstartEvent);
a.scrollDom.removeEventListener("touchmove", a.touchmoveEvent);
a.scrollDom.removeEventListener("touchend", a.touchendEvent);
a.scrollDom.removeEventListener("touchcancel", a.touchendEvent);
a.scrollDom.removeEventListener("mousedown", a.touchstartEvent);
a.scrollDom.removeEventListener("mousemove", a.touchmoveEvent);
a.scrollDom.removeEventListener("mouseup", a.touchendEvent);
a.scrollDom.removeEventListener("mouseleave", a.touchendEvent);
a.removeChild(a.downwarp);
if (a.isScrollBody) {
window.removeEventListener("scroll", a.scrollEvent)
} else {
a.scrollDom.removeEventListener("scroll", a.scrollEvent)
}
a.removeChild(a.upwarp);
a.removeChild(a.toTopBtn);
a.setBounce(true)
};
export default MeScroll