|
|
/* eslint-disable */
|
|
|
/**
|
|
|
* Created by TaoHuang on 2016/10/10.
|
|
|
*/
|
|
|
function dataLazyLoad(doc) {
|
|
|
|
|
|
// 兼容低版本 IE
|
|
|
Function.prototype.bind = Function.prototype.bind || function(context) {
|
|
|
var that = this;
|
|
|
return function() {
|
|
|
return that.apply(context, arguments);
|
|
|
};
|
|
|
};
|
|
|
|
|
|
// 工具方法 begin
|
|
|
var Util = {
|
|
|
getElementsByClassName: function(cls) {
|
|
|
if (doc.getElementsByClassName) {
|
|
|
return doc.getElementsByClassName(cls);
|
|
|
}
|
|
|
|
|
|
var o = doc.getElementsByTagName("*"),
|
|
|
rs = [];
|
|
|
|
|
|
for (var i = 0, t, len = o.length; i < len; i++) {
|
|
|
(t = o[i]) && ~t.className.indexOf(cls) && rs.push(t);
|
|
|
}
|
|
|
|
|
|
return rs;
|
|
|
},
|
|
|
addEvent: function(ele, type, fn) {
|
|
|
ele.attachEvent ? ele.attachEvent("on" + type, fn) : ele.addEventListener(type, fn, false);
|
|
|
},
|
|
|
removeEvent: function(ele, type, fn) {
|
|
|
ele.detachEvent ? ele.detachEvent("on" + type, fn) : ele.removeEventListener(type, fn, false);
|
|
|
},
|
|
|
getPos: function(ele) {
|
|
|
var pos = {
|
|
|
x: 0,
|
|
|
y: 0
|
|
|
};
|
|
|
|
|
|
while (ele.offsetParent) {
|
|
|
pos.x += ele.offsetLeft;
|
|
|
pos.y += ele.offsetTop;
|
|
|
ele = ele.offsetParent;
|
|
|
}
|
|
|
|
|
|
return pos;
|
|
|
},
|
|
|
getViewport: function() {
|
|
|
var html = doc.documentElement;
|
|
|
|
|
|
return {
|
|
|
w: !window.innerWidth ? html.clientHeight : window.innerWidth,
|
|
|
h: !window.innerHeight ? html.clientHeight : window.innerHeight
|
|
|
};
|
|
|
},
|
|
|
getScrollHeight: function() {
|
|
|
html = doc.documentElement, bd = doc.body;
|
|
|
return Math.max(window.pageYOffset || 0, html.scrollTop, bd.scrollTop);
|
|
|
},
|
|
|
getEleSize: function(ele) {
|
|
|
return {
|
|
|
w: ele.offsetWidth,
|
|
|
h: ele.offsetHeight
|
|
|
};
|
|
|
}
|
|
|
};
|
|
|
// 工具方法 end
|
|
|
|
|
|
return {
|
|
|
threshold: 0, // {number} 阈值,预加载高度,单位(px)
|
|
|
els: null, // {Array} 延迟加载元素集合(数组)
|
|
|
fn: null, // {Function} scroll、resize、touchmove 所绑定方法,即为 pollTextareas()
|
|
|
|
|
|
evalScripts: function(code) {
|
|
|
var head = doc.getElementsByClassName("yoho-footer")[0],
|
|
|
js = doc.createElement("script");
|
|
|
|
|
|
js.text = code;
|
|
|
head.appendChild(js, head.firstChild);
|
|
|
head.removeChild(js);
|
|
|
},
|
|
|
|
|
|
evalStyles: function(code) {
|
|
|
var head = doc.getElementsByTagName("head")[0],
|
|
|
css = doc.createElement("style");
|
|
|
|
|
|
css.type = "text/css";
|
|
|
|
|
|
try {
|
|
|
css.appendChild(doc.createTextNode(code));
|
|
|
} catch (e) {
|
|
|
css.styleSheet.cssText = code;
|
|
|
}
|
|
|
|
|
|
head.appendChild(css);
|
|
|
},
|
|
|
|
|
|
extractCode: function(str, isStyle) {
|
|
|
var cata = isStyle ? "style" : "script",
|
|
|
scriptFragment = "<" + cata + "[^>]*>([\\S\\s]*?)</" + cata + "\\s*>",
|
|
|
matchAll = new RegExp(scriptFragment, "img"),
|
|
|
matchOne = new RegExp(scriptFragment, "im"),
|
|
|
matchResults = str.match(matchAll) || [],
|
|
|
ret = [];
|
|
|
|
|
|
for (var i = 0, len = matchResults.length; i < len; i++) {
|
|
|
var temp = (matchResults[i].match(matchOne) || ["", ""])[1];
|
|
|
temp && ret.push(temp);
|
|
|
}
|
|
|
return ret;
|
|
|
},
|
|
|
|
|
|
decodeHTML: function(str) {
|
|
|
return str.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&")
|
|
|
.replace(/</g, '<').replace(/>/g, '>');
|
|
|
},
|
|
|
|
|
|
insert: function(ele) {
|
|
|
var parent = ele.parentNode,
|
|
|
txt = this.decodeHTML(ele.innerHTML),
|
|
|
matchStyles = this.extractCode(txt, true),
|
|
|
matchScripts = this.extractCode(txt);
|
|
|
|
|
|
parent.innerHTML = txt
|
|
|
.replace(new RegExp("<script[^>]*>([\\S\\s]*?)</script\\s*>", "img"), "")
|
|
|
.replace(new RegExp("<style[^>]*>([\\S\\s]*?)</style\\s*>", "img"), "");
|
|
|
|
|
|
if (matchStyles.length) {
|
|
|
for (var i = matchStyles.length; i--;) {
|
|
|
this.evalStyles(matchStyles[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// 如果延迟部分需要做 loading 效果
|
|
|
parent.className = parent.className.replace("loading", "");
|
|
|
|
|
|
if (matchScripts.length) {
|
|
|
for (var i = 0, len = matchScripts.length; i < len; i++) {
|
|
|
this.evalScripts(matchScripts[i]);
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
|
|
|
inView: function(ele) {
|
|
|
var top = Util.getPos(ele).y
|
|
|
, viewVal = Util.getViewport().h
|
|
|
, scrollVal = Util.getScrollHeight()
|
|
|
, eleHeight = Util.getEleSize(ele).h;
|
|
|
|
|
|
if (top >= scrollVal - eleHeight - this.threshold && top <= scrollVal + viewVal + this.threshold) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
},
|
|
|
|
|
|
pollTextareas: function() {
|
|
|
// 需延迟加载的元素已经全部加载完
|
|
|
if (!this.els.length) {
|
|
|
Util.removeEvent(window, "scroll", this.fn);
|
|
|
Util.removeEvent(window, "resize", this.fn);
|
|
|
Util.removeEvent(doc.body, "touchMove", this.fn);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 判断是否需要加载
|
|
|
for (var i = this.els.length; i--;) {
|
|
|
var ele = this.els[i];
|
|
|
|
|
|
if (!this.inView(ele)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
this.insert(ele);
|
|
|
this.els.splice(i, 1);
|
|
|
}
|
|
|
},
|
|
|
|
|
|
init: function(config) {
|
|
|
var cls = config.cls;
|
|
|
this.threshold = config.threshold ? config.threshold : 0;
|
|
|
|
|
|
this.els = Array.prototype.slice.call(Util.getElementsByClassName(cls));
|
|
|
this.fn = this.pollTextareas.bind(this);
|
|
|
|
|
|
this.fn();
|
|
|
Util.addEvent(window, "scroll", this.fn);
|
|
|
Util.addEvent(window, "resize", this.fn);
|
|
|
Util.addEvent(doc.body, "touchMove", this.fn);
|
|
|
}
|
|
|
};
|
|
|
}
|
|
|
|
|
|
module.exports = dataLazyLoad;
|
|
|
|
|
|
/**
|
|
|
* demo
|
|
|
* datalazyload.init({
|
|
|
* cls: "datalazyload", // 需要延迟加载的类,即 textarea 的类名
|
|
|
* threshold: 100 // 距离底部多高,进行延迟加载的阈值
|
|
|
* });
|
|
|
*/ |
...
|
...
|
|