const puockGlobalData = { loads: {} } const TYPE_PRIMARY = "primary" const TYPE_WARNING = "warning" const TYPE_DANGER = "danger" const TYPE_SUCCESS = "success" const TYPE_INFO = "info" class Puock { data = { tag: 'puock', pc:true, params: { home: null, use_post_menu: false, is_single: false, is_pjax: false, vd_comment: false, vd_gt_id: null, vd_type: null, main_lazy_img: false, link_blank_open: false, async_view_id: null, mode_switch: false, async_view_generate_time: null, off_img_viewer:false, off_code_highlighting:false }, comment: { loading: false, time: 5, val: null, replyId: null }, instance: {}, modalStorage: {} } // 全局一次加载或注册的事件 onceInit() { this.pageInit() $(document).on("click", ".fancybox", () => { return false; }); $(document).on("click", "#rb-float-actions>div", (e) => { const el = $(this.ct(e)); const to = el.data("to"); if (to) { const scroll_val = to === 'top' ? 0 : window.document.body.clientHeight; $('html,body').stop().animate({scrollTop: scroll_val}, 50) return; } const toArea = el.data("to-area"); if (toArea) { this.gotoArea(toArea) } }); $(document).on("click", ".colorMode", () => { this.modeChange(null, true); }); if (this.data.params.is_pjax) { this.instanceClickLoad() } this.initBasicDOMEvent() this.sidebarMenuEventInit() this.searchInit() this.eventShareStart() this.modeInit(); this.registerMobileMenu() this.registerModeChangeEvent() this.eventCommentPageChangeEvent() this.eventCommentPreSubmit() this.eventSmiley() this.eventOpenCommentBox() this.eventCloseCommentBox() this.eventSendPostLike() this.eventPostMainBoxResize() this.swiperOnceEvent() this.initModalToggle() this.detectDevice() window.addEventListener('resize', ()=>this.detectDevice()); layer.config({shade: 0.5}) } pageInit() { this.loadParams() this.pageChangeInit() if (this.data.params.is_single) { if (this.data.params.use_post_menu) { this.generatePostMenuHTML() } } } instanceClickLoad() { InstantClick.init('mousedown'); InstantClick.go = (url) => { const link = document.createElement('a'); link.href = url; document.body.appendChild(link); link.click(); } InstantClick.on('change', (e) => { this.loadParams(); this.pageChangeInit() }) // InstantClick.on('receive',(url, body, title)=>{ // console.log(body) // this.loadParams($(body)) // }) this.loadCommentInfo(); } ct(e) { return e.currentTarget } detectDevice() { const screenWidth = window.innerWidth; this.data.pc = screenWidth >= 768 } initBasicDOMEvent() { // el show or hide event $(document).on("click", ".toggle-el-show-hide", (e) => { const el = $(this.ct(e)); const target = $(el.attr("data-target")); const self = $(el.attr("data-self")); const modalTitle = el.attr("data-modal-title"); if (target.hasClass("d-none")) { self.addClass("d-none"); target.removeClass("d-none"); } else { self.removeClass("d-none"); target.addClass("d-none"); } if (modalTitle) { el.closest(".modal").find(".modal-title").text(modalTitle); } }); // form ajax submit $(document).on("submit", ".ajax-form", (e) => { e.preventDefault(); const form = $(this.ct(e)); const formEls = form.find(":input") if (formEls.length === 0) { this.toast('表单元素为空', TYPE_DANGER) return false; } for (let i = 0; i < formEls.length; i++) { const el = $(formEls[i]); if (el.attr("data-required") !== undefined && el.val() === "") { this.toast(el.attr("data-tip") || el.attr("placeholder"), TYPE_WARNING) return false; } } const validateType = form.data("validate"); const startSubmit = (args = {}) => { const url = form.attr("action"); const method = form.attr("method"); const data = this.parseFormData(form, args); const dataType = "json"; const successTip = form.attr("data-success"); const errorTip = form.attr("data-error"); const loading = this.startLoading() $.ajax({ url, method, data, dataType, success: (res) => { this.stopLoading(loading) if (res.code === 0 || res.success) { this.toast(res.msg || successTip, TYPE_SUCCESS) if (form.data("no-reset") === undefined) { form.trigger("reset") } if (res.data) { const resData = res.data if (resData.action) { setTimeout(() => { switch (resData.action) { case 'reload': this.goUrl(window.location.href) break } }, 500) } } } else { this.toast(res.msg || res.data || errorTip, TYPE_DANGER) // this.loadCommentCaptchaImage(form, true) } }, error: (e) => { this.stopLoading(loading) this.toast(`请求错误:${e.statusText}`, TYPE_DANGER) // this.loadCommentCaptchaImage(form, true) } }) } if (validateType === 'gt') { this.gt.validate((code) => { startSubmit(code) }); } else { startSubmit() } return false; }) } pageLinkBlankOpenInit() { if (this.data.params.link_blank_open) { $(".entry-content").find("a").each((_, item) => { $(item).attr('target', 'blank') }) } } searchInit() { const toggle = () => { const search = $("#search"); const open = search.attr("data-open") === "true"; let tag = open ? 'Out' : 'In'; search.attr("class", "animated fade" + tag + "Left"); $("#search-backdrop").attr("class", "modal-backdrop animated fade" + tag + "Right"); search.attr("data-open", !open); if (!open) { search.find("input").focus(); } } $(document).on("click", ".search-modal-btn", () => { toggle(); }); $(document).on("click", "#search-backdrop", () => { toggle(); }) $(document).on("submit", ".global-search-form", (e) => { e.preventDefault(); const el = $(this.ct(e)); this.goUrl(el.attr("action") + "/?" + el.serialize()) }) } goUrl(url) { if (this.data.params.is_pjax) { InstantClick.go(url) } else { window.location.href = url } } gt = { validate: (success = undefined) => { this.data.instance.gt_callback = success // this.data.instance.gt.showCaptcha(); } } rippleInit() { const args = { debug: false, on: 'mousedown', opacity: 0.4, color: "var(--pk-c-light)", multi: false, duration: 0.6, rate: function (pxPerSecond) { return pxPerSecond; }, easing: 'linear' } jQuery.ripple(".btn", args); jQuery.ripple(".ww", args); } eventShareStart() { $(document).on("click", ".share-to", (e) => { const id = $(this.ct(e)).attr("data-id"); if (id === 'wx') return; const url = window.location.href; const title = $("#post-title").text(); const wb_key = ''; let to = null; switch (id) { case 'wb': to = 'https://service.weibo.com/share/share.php?pic=&title=' + title + '&url=' + url + '&appkey=' + wb_key; break; case 'qzone': to = 'https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?title=' + title + '&url=' + url; break; case 'tw': to = 'https://twitter.com/intent/tweet?url=' + url; break; case 'fb': to = 'https://www.facebook.com/sharer.php?u' + url; break; } if (to) window.open(to, '_blank'); }); } sidebarMenuEventInit() { let currentOpenSubMenu = null; $(document).on("touchend", ".post-menu-toggle", (e) => { e.preventDefault(); this.toggleMenu(); }); $(document).on("click", ".post-menu-toggle", () => { this.toggleMenu(); }); $(document).on("click", ".post-menu-item", (e) => { const el = $(this.ct(e)) const id = el.attr("data-id") if (currentOpenSubMenu) { const parentUl = el.parents("ul") let curClass = "post-menu-sub-" + currentOpenSubMenu while (true) { if (typeof (curClass) === "undefined") { break } const currentMenu = $("." + curClass) const classStr = currentMenu.attr("class") const und = typeof (classStr) == "undefined" if (und || parentUl.attr("class") === currentMenu.attr("class")) { break; } else { currentMenu.hide(); curClass = currentMenu.parents("ul").attr("class"); } } } const subMenu = $(".post-menu-sub-" + id) if (subMenu.length > 0) { subMenu.show() currentOpenSubMenu = id } }); $(document).on("click", ".pk-menu-to", (e) => { const to = $(this.ct(e)).attr("href"); const headerHeight = $("#header").innerHeight(); $("html, body").stop().animate({ scrollTop: ($(to).offset().top - headerHeight - 10) + "px" }, { duration: 50, easing: "swing" }); if(!this.data.pc){ this.toggleMenu() } return false; }); } toggleMenu() { const menuContainer = $("#post-menus"); const menuButton = $("#post-menu-state"); const className = "data-open"; const isOpen = menuButton.hasClass(className); if (isOpen) { // 关闭菜单 menuContainer.removeClass("show"); menuButton.removeClass(className); } else { // 打开菜单 menuContainer.addClass("show"); menuButton.addClass(className); } } lazyLoadInit(parent = null, el = '.lazy') { if (window.lozad) { const observer = lozad([el, 'img[data-lazy="true"]'], { rootMargin: '10px 0px', threshold: 0.1, enableAutoReload: true, load: (el) => { el.classList.add('loaded'); el.src = el.getAttribute('data-src'); } }); observer.observe(); } } loadParams() { this.data.params = puock_metas; //this.data.commentVd = this.data.params.vd_comment === 'on'; } initReadProgress() { const readProgress = $("#page-read-progress .progress-bar"); document.addEventListener('scroll', () => { const a = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight) * 100; readProgress.attr("style", "width:" + a.toFixed(0) + "%"); }); } tooltipInit(el = $("[data-bs-toggle=\"tooltip\"]")) { [...el].map(tooltipTriggerEl => { new bootstrap.Tooltip(tooltipTriggerEl, { placement: 'bottom', trigger: 'hover' }) }) } pageChangeInit() { this.initReadProgress() this.modeInit(); this.loadCommentInfo(); this.katexParse(); this.initCodeHighlight(); this.pageLinkBlankOpenInit() this.initGithubCard(); this.keyUpHandle(); this.loadHitokoto(); // this.asyncCacheViews(); this.swiperInit(); // this.validateInit(); this.rippleInit(); if (this.data.params.use_post_menu) { this.generatePostMenuHTML() } this.tooltipInit() if(!this.data.params.off_img_viewer){ jQuery(".entry-content").viewer({ navbar: false, url: this.data.params.main_lazy_img ? 'data-src' : 'src' }); } const cp = new ClipboardJS('.pk-copy', { text: (trigger) => { const t = $(trigger) let input = t.attr("data-cp-input") let el = t.attr("data-cp-el") let val = t.attr("data-cp-val") let func = t.attr("data-cp-func") let text; if(typeof func !=="undefined"){ text = window[func](t) }else if (typeof val !== "undefined") { text = val } else if (typeof input !== "undefined") { text = $(input).val() } else if (typeof el !== "undefined") { text = $(el).text() } else { text = t.text() } return text; }, }); cp.on("success", (e) => { let name = $(e.trigger).attr('data-cp-title') || ""; this.toast(`复制${name}成功`) }) cp.on("error", (e) => { let name = $(e.trigger).attr('data-cp-title') || ""; this.toast(`复制${name}失败`, TYPE_DANGER) }) this.lazyLoadInit() // $('#post-main, #sidebar').theiaStickySidebar({ // additionalMarginTop: 20 // }); } getPostMenuStructure() { $('.entry-content').find('h1,h2,h3,h4,h5,h6').each(function(index, el) { if (!$(el).attr('id')) { let safeText = $(el).text().trim().replace(/\s+/g, '-').replace(/[^\w\-]/g, '').toLowerCase(); // 防止重复id let uniqId = safeText || `heading-${index}`; // 如果已经有相同id,添加序号 let counter = 1; while($('#' + uniqId).length > 0) { uniqId = `${safeText}-${counter++}`; } $(el).attr('id', uniqId); } }); let res = [] for (let item of $(".entry-content").find('h1,h2,h3,h4,h5,h6')) { res.push({name: $(item).text().trim(), level: item.tagName.toLowerCase(), id: $(item).attr("id")}) } return res } generatePostMenuHTML() { const menus = this.getPostMenuStructure(); if (menus.length > 0) { let result = "" $("#post-menu-content-items").html(result); $(".post-menus-box").show(); } } initCodeHighlight(fullChange = true, bodyEl="body") { if(this.data.params.off_code_highlighting){ return } if (window.hljs !== undefined) { window.hljs.configure({ignoreUnescapedHTML: true}) $(bodyEl).find("pre").each((index, block) => { const el = $(block); const codeChildClass = el.children("code") ? el.children("code").attr("class") : undefined; if (codeChildClass) { if (codeChildClass.indexOf("katex") !== -1 || codeChildClass.indexOf("latex") !== -1 || codeChildClass.indexOf("flowchart") !== -1 || codeChildClass.indexOf("flow") !== -1 || codeChildClass.indexOf("seq") !== -1 || codeChildClass.indexOf("math") !== -1) { return; } } if (!el.attr("id")) { el.attr("id", "hljs-item-" + index) el.before("
" + "
") window.hljs.highlightBlock(block); window.hljs.lineNumbersBlock(block); } }); if (fullChange) { const cp = new ClipboardJS('.cp-code'); cp.on("success", (e) => { e.clearSelection(); this.toast('已复制到剪切板') }) } } } localstorageToggle(name, val = null) { return val != null ? localStorage.setItem(name, val) : localStorage.getItem(name); } loadCommentInfo() { const authorText = this.localstorageToggle("comment_author"), emailText = this.localstorageToggle("comment_email"), urlText = this.localstorageToggle("comment_url"); if (authorText != null && emailText != null) { $("#comment_author").val(authorText); $("#comment_email").val(emailText); $("#comment_url").val(urlText); } } setCommentInfo() { this.localstorageToggle("comment_author", $("#comment_author").val()); this.localstorageToggle("comment_email", $("#comment_email").val()); this.localstorageToggle("comment_url", $("#comment_url").val()); } modeInit() { this.modeChange(); } modeChange(toLight = null, isSwitch = false) { const body = $("body"); if (typeof (toLight) === "string") { toLight = toLight === 'true'; } let mode = Cookies.get('mode') || 'auto' if (toLight === null) { toLight = mode==='light'; if(mode==='auto'){ toLight = !window.matchMedia('(prefers-color-scheme:dark)').matches } } if (isSwitch) { if(mode==='light'){ mode = 'dark' toLight = false; }else if(mode==='dark'){ mode = 'auto' toLight = !window.matchMedia('(prefers-color-scheme:dark)').matches; }else{ mode = 'light' toLight = true; } console.log(mode, toLight) } let dn = 'd-none'; if (toLight) { $("#logo-light").removeClass(dn); $("#logo-dark").addClass(dn); } else { $("#logo-dark").removeClass(dn); $("#logo-light").addClass(dn); } $(".colorMode").each((_, e) => { const el = $(e); let target; if (el.prop("localName") === 'i') { target = el; } else { target = $(el).find("i"); } if (target) { target.removeClass("fa-sun").removeClass("fa-moon").removeClass('fa-circle-half-stroke') .addClass(mode==='auto' ? 'fa-circle-half-stroke' : (mode==='light' ? "fa-sun" : "fa-moon")); } }) body.removeClass(this.data.tag + "-auto") body.removeClass(toLight ? this.data.tag + "-dark" : this.data.tag + "-light"); body.addClass(toLight ? this.data.tag + "-light" : this.data.tag + "-dark"); // this.localstorageToggle('light', toLight) Cookies.set('mode', mode) } modeChangeListener() { if(Cookies.get('mode')==='auto'){ this.modeChange(!window.matchMedia('(prefers-color-scheme:dark)').matches); } } registerModeChangeEvent() { if (this.data.params.mode_switch) { try { window.matchMedia('(prefers-color-scheme:dark)').addEventListener('change', () => { this.modeChangeListener() }); } catch (ex) { window.matchMedia('(prefers-color-scheme:dark)').addListener(() => { this.modeChangeListener() }); } } } infoToastShow(text, title = '提示') { const infoToast = $('#infoToast'); $("#infoToastTitle").html(title); $("#infoToastText").html(text); infoToast.modal('show'); } registerMobileMenu() { const fn = (s) => { if (typeof (s) !== 'string') { s = 'Out' } $("#mobile-menu").attr("class", "animated fade" + s + "Left"); $("#mobile-menu-backdrop").attr("class", "modal-backdrop animated fade" + s + "Right"); } $(document).on("click", "#mobile-menu-backdrop", fn); $(document).on("click", ".mobile-menu-close", fn); $(document).on("click", ".mobile-menu-s", () => { fn('In'); }); } gotoArea(el, speed = 50) { const top = $(el).offset().top - $("#header").height() - 10; $('html,body').stop().animate({scrollTop: top}, speed); } pushAjaxCommentHistoryState(href) { history.pushState({foo: "bar"}, "page 2", href); } eventCommentPageChangeEvent() { $(document).on('click', '.comment-ajax-load a.page-numbers', (e) => { const postCommentsEl = $("#post-comments"); const loadBox = $("#comment-ajax-load"); $("#comment-cancel").click(); let href = $(this.ct(e)).attr("href"); this.pushAjaxCommentHistoryState(href); postCommentsEl.html(" "); this.gotoArea("#comments"); loadBox.removeClass('d-none'); $.post(href, {}, (data) => { postCommentsEl.html($(data).find("#post-comments")); loadBox.addClass('d-none'); this.initCodeHighlight(false); this.lazyLoadInit(postCommentsEl); }).fail(() => { location = href; }); return false; }) } parseFormData(formEl, args = {}) { const dataArr = formEl.serializeArray(); const data = {...args}; for (let i = 0; i < dataArr.length; i++) { data[dataArr[i].name] = dataArr[i].value; } return jQuery.param(data); } eventCommentPreSubmit() { $(document).on('submit', '#comment-form', (e) => { e.preventDefault(); if ($("#comment-logged").val() === '0' && ($.trim($("#comment_author").val()) === '' || $.trim($("#comment_email").val()) === '')) { this.toast('评论信息不能为空', TYPE_WARNING); return; } if ($.trim($("#comment").val()) === '') { this.toast('评论内容不能为空', TYPE_WARNING); return; } if (this.data.params.vd_comment) { if (this.data.params.vd_type === 'img') { if ($.trim($("#comment-vd").val()) === '') { this.toast('验证码不能为空', TYPE_WARNING); return; } } else { this.gt.validate((code) => { this.commentSubmit(this.ct(e), code) }) return; } } this.commentSubmit(this.ct(e)) }) } commentSubmit(target, args = {}) { let submitUrl = $("#comment-form").attr("action"); this.commentFormLoadStateChange(); const el = $(target); $.ajax({ url: submitUrl, data: this.parseFormData(el, args), type: el.attr('method'), success: (data) => { this.toast('评论已提交成功', TYPE_SUCCESS); $("#comment-vd").val(""); $("#comment").val(""); // 获取整个评论区域的新内容 const newComments = $(data).find("#comments").html(); // 替换当前评论区域 $("#comments").html(newComments); // 重置评论表单状态 $("#comment-form").trigger("reset"); $("#comment-cancel").click(); this.commentFormLoadStateChange(); this.setCommentInfo(); // 重新初始化相关组件 this.initCodeHighlight(false); this.lazyLoadInit(); this.tooltipInit(); // 重新绑定事件 this.eventCommentPageChangeEvent(); this.eventOpenCommentBox(); this.eventCloseCommentBox(); // 滚动到评论区域 this.gotoArea("#comments"); }, error: (res) => { this.commentFormLoadStateChange(); let msg = "评论提交失败"; if (res.responseJSON && res.responseJSON.msg) { msg = res.responseJSON.msg; } this.toast(msg, TYPE_DANGER); } }); } commentFormLoadStateChange() { const commentSubmit = $("#comment-submit"); if (this.data.comment.loading) { commentSubmit.html("请等待" + this.data.comment.time + "s"); this.data.comment.val = setInterval(() => { if (this.data.comment.time <= 1) { clearInterval(this.data.comment.val); commentSubmit.html("提交评论"); commentSubmit.removeAttr("disabled"); this.data.comment.time = 5; } else { --this.data.comment.time; commentSubmit.html("请等待" + this.data.comment.time + "s"); } }, 1000); } else { commentSubmit.html('提交中...'); commentSubmit.attr("disabled", true) } this.data.comment.loading = !this.data.comment.loading; } eventOpenCommentBox() { $(document).on("click", "[id^=comment-reply-]", (e) => { this.data.comment.replyId = $(this.ct(e)).attr("data-id"); if ($.trim(this.data.comment.replyId) === '') { this.toast('结构有误', TYPE_DANGER); return; } const cf = $("#comment-form"), cb = $("#comment-box-" + this.data.comment.replyId); cf.addClass("box-sw"); cb.removeClass("d-none").append(cf); $("#comment-cancel").removeClass("d-none"); $("#comment").val(""); $("#comment_parent").val(this.data.comment.replyId); }) } eventCloseCommentBox() { $(document).on("click", "#comment-cancel", () => { const cf = $("#comment-form"), cb = $("#comment-box-" + this.data.comment.replyId); cf.removeClass("box-sw"); cb.addClass("d-none"); $("#comment-form-box").append(cf); $("#comment-cancel").addClass("d-none"); this.data.comment.replyId = null; }) } eventSendPostLike() { let lastSendTime = 0; let throttleTimeMs = 3000; $(document).on("click", "#post-like", (e) => { const currentTime = new Date().getTime(); if (currentTime - lastSendTime < throttleTimeMs) { this.toast("操作过于频繁", TYPE_WARNING); return; } lastSendTime = currentTime; const vm = $(this.ct(e)); let cid = vm.attr("data-id"); // 发送 AJAX 请求到当前文章页面 $.ajax({ url: window.location.href, type: 'POST', data: { likeup: 1, cid: cid }, dataType: 'json', success: (response) => { // 检查返回的数据格式并更新点赞数 if (response.success) { vm.find("span").html(response.likes); vm.addClass("bg-primary text-light"); this.toast("点赞成功", TYPE_SUCCESS); } else { this.toast(response.msg || "点赞失败", TYPE_WARNING); } }, error: () => { this.toast('点赞异常', TYPE_DANGER); } }); }) } eventSmiley() { $(document).on('click', '.smiley-img', (e) => { const comment = $("#comment"); comment.val(comment.val() + ' ' + $(this.ct(e)).attr("data-id") + ' '); layer.closeAll(); }) } startLoading() { return layer.load(0, { shade: [0.5, '#000'] }) } stopLoading(id = null) { layer.close(id) } getRemoteHtmlNode(url, callback) { const loading = this.startLoading() $.ajax({ url: url, type: 'GET', success: (res)=>{ this.stopLoading(loading) callback(res) }, error: (err)=> { console.error(err) this.stopLoading(loading) this.toast("获取内容节点数据失败", TYPE_DANGER) } }) } initModalToggle() { $(document).on("click", ".pk-modal-toggle", (e) => { const el = $(this.ct(e)); const noTitle = el.data("no-title") !== undefined; const noPadding = el.data("no-padding") !== undefined; const title = el.attr("title") || el.data("title") || '提示'; const url = el.data("url"); const onceLoad = el.data("once-load") const id = SparkMD5.hash(url) if (onceLoad && this.data.modalStorage[id]) { this.modalLoadRender(id, this.data.modalStorage[id], title, noTitle, noPadding) } else { this.getRemoteHtmlNode(url, (res) => { if (onceLoad) { if (!this.data.modalStorage[id]) { this.data.modalStorage[id] = res; } } this.modalLoadRender(id, res, title, noTitle, noPadding) }) } }) } modalLoadRender(dataId, html, title, noTitle, noPadding) { const id = "pk-modal-" + dataId; layer.open({ type: 1, title: noTitle ? false : title, content: `
${html}
`, shadeClose: true, }) const idEl = $("#" + id); this.lazyLoadInit(idEl); this.tooltipInit(idEl.find("[data-bs-toggle=\"tooltip\"]")); } eventPostMainBoxResize() { $(document).on("click", ".post-main-size", () => { const postMain = $("#post-main"), postSlider = $("#sidebar"), min = postMain.hasClass("col-lg-8"); postMain.removeClass(min ? "col-lg-8" : "col-lg-12"); postMain.addClass(min ? "col-lg-12" : "col-lg-8"); min ? postSlider.removeClass("d-lg-block") : postSlider.addClass("d-lg-block"); }) } katexParse() { return; if (typeof katex !== 'undefined') { const ks = $(document).find(".language-katex"); const kl = $(document).find(".language-inline"); console.log(ks, kl) if (ks.length > 0) { ks.parent("pre").attr("style", "text-align: center; background: none;"); ks.addClass("katex-container").removeClass("language-katex"); $(".katex-container").each((_, v) => { this.katexItemParse($(v)) }); } if (kl.length > 0) { kl.each((_, v) => { this.katexItemParse($(v)) }); } } } katexItemParse(item) { const katexText = item.text(); const el = item.get(0); if (item.parent("code").length === 0) { try { katex.render(katexText, el) } catch (err) { item.html("" + err) } } } initGithubCard() { $.each($(".github-card"), (index, _el) => { const el = $(_el); const repo = el.attr("data-repo"); if (repo) { $.get(`https://api.github.com/repos/${repo}`, (res) => { const link_html = `class="hide-hover" href="${res.html_url}" target="_blank" rel="noreferrer"`; el.html(`
${res.full_name}
${res.description}
`); el.addClass("loaded"); }, 'json').fail((err) => { el.html(`
 请求Github项目详情异常:${repo}
`) }); } }) } keyUpHandle() { const prevOrNextEl = $(".single-next-or-pre") if (prevOrNextEl) { window.onkeyup = function (event) { if('BODY'===event.target?.tagName){ let url = null; switch (event.key) { case 'ArrowLeft': { url = prevOrNextEl.find("a[rel='prev']").attr("href"); break } case 'ArrowRight': { url = prevOrNextEl.find("a[rel='next']").attr("href"); break } } if (url) { window.location = url } } } } } swiperInit() { $("[data-swiper='init']").each((_, _el) => { const el = $(_el); const swiperClass = el.attr("data-swiper-class"); const elArgs = el.attr("data-swiper-args"); let args = {} if (elArgs) { args = JSON.parse(elArgs) } new Swiper('.' + swiperClass, args); }); } swiperOnceEvent() { $(document).on("click", ".swiper-slide a", (e) => { if (this.data.params.is_pjax) { e.preventDefault(); this.goUrl(e.currentTarget.href) } }); } loadHitokoto() { setTimeout(() => { $(".widget-puock-hitokoto").each((_, v) => { const el = $(v); const api = el.attr("data-api") || "https://v1.hitokoto.cn/" $.get(api, (res) => { el.find(".t").text(res.hitokoto ?? res.content ?? "无内容"); el.find('.f').text(res.from); el.find('.fb').removeClass("d-none"); }, 'json').fail((err) => { console.error(err) el.find(".t").text("加载失败:" + err.responseText || err); el.remove(".fb"); }) }) }, 300) } toast(msg, type = TYPE_PRIMARY, options = {}) { options = Object.assign({ duration: 2600, close: false, position: 'right', gravity: 'bottom', offset: {}, className: 't-' + type, }, options) const t = Toastify({ text: msg, ...options }); t.showToast(); return t; } } jQuery(() => { if (window.$ === undefined) { window.$ = jQuery; } window.Puock = new Puock() window.Puock.onceInit() } )