hexo-theme-stellar/layout/_partial/scripts/utils.ejs

159 lines
5.8 KiB
Plaintext
Raw Normal View History

2024-02-12 23:07:56 +08:00
<script type="text/javascript">
const utils = {
// 懒加载 css https://github.com/filamentgroup/loadCSS
css: (href, before, media, attributes) => {
var doc = window.document;
var ss = doc.createElement("link");
var ref;
if (before) {
ref = before;
} else {
var refs = (doc.body || doc.getElementsByTagName("head")[0]).childNodes;
ref = refs[refs.length - 1];
}
var sheets = doc.styleSheets;
if (attributes) {
for (var attributeName in attributes) {
if (attributes.hasOwnProperty(attributeName)) {
ss.setAttribute(attributeName, attributes[attributeName]);
}
}
}
ss.rel = "stylesheet";
ss.href = href;
ss.media = "only x";
function ready(cb) {
if (doc.body) {
return cb();
}
setTimeout(function () {
ready(cb);
});
}
ready(function () {
ref.parentNode.insertBefore(ss, before ? ref : ref.nextSibling);
});
var onloadcssdefined = function (cb) {
var resolvedHref = ss.href;
var i = sheets.length;
while (i--) {
if (sheets[i].href === resolvedHref) {
return cb();
}
}
setTimeout(function () {
onloadcssdefined(cb);
});
};
function loadCB() {
if (ss.addEventListener) {
ss.removeEventListener("load", loadCB);
}
ss.media = media || "all";
}
if (ss.addEventListener) {
ss.addEventListener("load", loadCB);
}
ss.onloadcssdefined = onloadcssdefined;
onloadcssdefined(loadCB);
return ss;
},
js: (src, opt) => new Promise((resolve, reject) => {
var script = document.createElement('script');
if (src.startsWith('/')){
src = ctx.root + src.substring(1);
}
script.src = src;
if (opt) {
for (let key of Object.keys(opt)) {
script[key] = opt[key]
}
} else {
// 默认异步,如果需要同步,第二个参数传入 {} 即可
script.async = true
}
script.onerror = reject
script.onload = script.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
script.onload = script.onreadystatechange = null
resolve()
}
document.head.appendChild(script)
}),
jq: (fn) => {
if (typeof jQuery === 'undefined') {
utils.js(deps.jquery).then(fn)
} else {
fn()
}
},
onLoading: (el) => {
if (el) {
$(el).append('<div class="loading-wrap"><svg xmlns="http://www.w3.org/2000/svg" width="2em" height="2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="2"><path stroke-dasharray="60" stroke-dashoffset="60" stroke-opacity=".3" d="M12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="1.3s" values="60;0"/></path><path stroke-dasharray="15" stroke-dashoffset="15" d="M12 3C16.9706 3 21 7.02944 21 12"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.3s" values="15;0"/><animateTransform attributeName="transform" dur="1.5s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/></path></g></svg></div>');
}
},
onLoadSuccess: (el) => {
if (el) {
$(el).find('.loading-wrap').remove();
}
},
onLoadFailure: (el) => {
if (el) {
$(el).find('.loading-wrap svg').remove();
$(el).find('.loading-wrap').append('<svg xmlns="http://www.w3.org/2000/svg" width="2em" height="2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path stroke-dasharray="60" stroke-dashoffset="60" d="M12 3L21 20H3L12 3Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.5s" values="60;0"/></path><path stroke-dasharray="6" stroke-dashoffset="6" d="M12 10V14"><animate fill="freeze" attributeName="stroke-dashoffset" begin="0.6s" dur="0.2s" values="6;0"/></path></g><circle cx="12" cy="17" r="1" fill="currentColor" fill-opacity="0"><animate fill="freeze" attributeName="fill-opacity" begin="0.8s" dur="0.4s" values="0;1"/></circle></svg>');
$(el).find('.loading-wrap').addClass('error');
}
},
request: (el, url, callback, onFailure) => {
let retryTimes = 3;
utils.onLoading(el);
function req() {
return new Promise((resolve, reject) => {
let status = 0; // 0 等待 1 完成 2 超时
let timer = setTimeout(() => {
if (status === 0) {
status = 2;
timer = null;
reject('请求超时');
if (retryTimes == 0) {
onFailure();
}
}
}, 5000);
fetch(url).then(function(response) {
if (status !== 2) {
clearTimeout(timer);
resolve(response);
timer = null;
status = 1;
}
if (response.ok) {
return response.json();
}
throw new Error('Network response was not ok.');
}).then(function(data) {
retryTimes = 0;
utils.onLoadSuccess(el);
callback(data);
}).catch(function(error) {
if (retryTimes > 0) {
retryTimes -= 1;
setTimeout(() => {
req();
}, 5000);
} else {
utils.onLoadFailure(el);
onFailure();
}
});
});
}
req();
},
};
</script>