diff --git a/.editorconfig b/.editorconfig index cdded46..8dccd84 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,10 +2,13 @@ root = true [*] charset = utf-8 -# 2 space indentation indent_style = space indent_size = 2 trim_trailing_whitespace = true # Unix-style newlines with a newline ending every file end_of_line = lf insert_final_newline = true + + +[*.js] +indent_size = 4 diff --git a/_javascript/commons/back-to-top.js b/_javascript/commons/back-to-top.js index 1807332..e876147 100644 --- a/_javascript/commons/back-to-top.js +++ b/_javascript/commons/back-to-top.js @@ -1,20 +1,20 @@ -/* -Reference: https://bootsnipp.com/snippets/featured/link-to-top-page -*/ +/** + * Reference: https://bootsnipp.com/snippets/featured/link-to-top-page + */ $(function() { - $(window).scroll(() => { - if ($(this).scrollTop() > 50 && - $("#sidebar-trigger").css("display") === "none") { - $("#back-to-top").fadeIn(); - } else { - $("#back-to-top").fadeOut(); - } - }); + $(window).scroll(() => { + if ($(this).scrollTop() > 50 && + $("#sidebar-trigger").css("display") === "none") { + $("#back-to-top").fadeIn(); + } else { + $("#back-to-top").fadeOut(); + } + }); - $("#back-to-top").click(() => { - $("body,html").animate({ - scrollTop: 0 - }, 800); - return false; - }); + $("#back-to-top").click(() => { + $("body,html").animate({ + scrollTop: 0 + }, 800); + return false; + }); }); diff --git a/_javascript/commons/mode-toggle.js b/_javascript/commons/mode-toggle.js index 1a3b3d6..6581f08 100644 --- a/_javascript/commons/mode-toggle.js +++ b/_javascript/commons/mode-toggle.js @@ -1,13 +1,13 @@ -/* +/** * Listener for theme mode toggle */ -$(function() { - $(".mode-toggle").click((e) => { - const $target = $(e.target); - let $btn = ($target.prop("tagName") === "button".toUpperCase() ? - $target : $target.parent()); +$(function () { + $(".mode-toggle").click((e) => { + const $target = $(e.target); + let $btn = ($target.prop("tagName") === "button".toUpperCase() ? + $target : $target.parent()); - $btn.blur(); // remove the clicking outline - flipMode(); - }); + $btn.blur(); // remove the clicking outline + flipMode(); + }); }); diff --git a/_javascript/commons/scroll-helper.js b/_javascript/commons/scroll-helper.js index 7892b08..419418c 100644 --- a/_javascript/commons/scroll-helper.js +++ b/_javascript/commons/scroll-helper.js @@ -2,35 +2,37 @@ * A tool for smooth scrolling and topbar switcher */ const ScrollHelper = (function () { - const $body = $("body"); - const ATTR_TOPBAR_VISIBLE = "data-topbar-visible"; - const topbarHeight = $("#topbar-wrapper").outerHeight(); + const $body = $("body"); + const ATTR_TOPBAR_VISIBLE = "data-topbar-visible"; + const topbarHeight = $("#topbar-wrapper").outerHeight(); - let scrollUpCount = 0; // the number of times the scroll up was triggered by ToC or anchor - let topbarLocked = false; - let orientationLocked = false; + let scrollUpCount = 0; // the number of times the scroll up was triggered by ToC or anchor + let topbarLocked = false; + let orientationLocked = false; - return { - hideTopbar: () => $body.attr(ATTR_TOPBAR_VISIBLE, false), - showTopbar: () => $body.attr(ATTR_TOPBAR_VISIBLE, true), + return { + hideTopbar: () => $body.attr(ATTR_TOPBAR_VISIBLE, false), + showTopbar: () => $body.attr(ATTR_TOPBAR_VISIBLE, true), - // scroll up + // scroll up - addScrollUpTask: () => { - scrollUpCount += 1; - if (!topbarLocked) { topbarLocked = true; } - }, - popScrollUpTask: () => scrollUpCount -= 1, - hasScrollUpTask: () => scrollUpCount > 0, - topbarLocked: () => topbarLocked === true, - unlockTopbar: () => topbarLocked = false, - getTopbarHeight: () => topbarHeight, + addScrollUpTask: () => { + scrollUpCount += 1; + if (!topbarLocked) { + topbarLocked = true; + } + }, + popScrollUpTask: () => scrollUpCount -= 1, + hasScrollUpTask: () => scrollUpCount > 0, + topbarLocked: () => topbarLocked === true, + unlockTopbar: () => topbarLocked = false, + getTopbarHeight: () => topbarHeight, - // orientation change + // orientation change - orientationLocked: () => orientationLocked === true, - lockOrientation: () => orientationLocked = true, - unLockOrientation: () => orientationLocked = false - }; + orientationLocked: () => orientationLocked === true, + lockOrientation: () => orientationLocked = true, + unLockOrientation: () => orientationLocked = false + }; }()); diff --git a/_javascript/commons/search-display.js b/_javascript/commons/search-display.js index 85e6b0a..ddc73c1 100644 --- a/_javascript/commons/search-display.js +++ b/_javascript/commons/search-display.js @@ -1,129 +1,129 @@ -/* -* This script make #search-result-wrapper switch to unloaded or shown automatically. -*/ +/** + * This script make #search-result-wrapper switch to unloaded or shown automatically. + */ -$(function() { - const btnSbTrigger = $("#sidebar-trigger"); - const btnSearchTrigger = $("#search-trigger"); - const btnCancel = $("#search-cancel"); - const main = $("#main"); - const topbarTitle = $("#topbar-title"); - const searchWrapper = $("#search-wrapper"); - const resultWrapper = $("#search-result-wrapper"); - const results = $("#search-results"); - const input = $("#search-input"); - const hints = $("#search-hints"); +$(function () { + const btnSbTrigger = $("#sidebar-trigger"); + const btnSearchTrigger = $("#search-trigger"); + const btnCancel = $("#search-cancel"); + const main = $("#main"); + const topbarTitle = $("#topbar-title"); + const searchWrapper = $("#search-wrapper"); + const resultWrapper = $("#search-result-wrapper"); + const results = $("#search-results"); + const input = $("#search-input"); + const hints = $("#search-hints"); - const scrollBlocker = (function () { - let offset = 0; - return { - block() { - offset = window.scrollY; - $("html,body").scrollTop(0); - }, - release() { - $("html,body").scrollTop(offset); - }, - getOffset() { - return offset; - } - }; - }()); + const scrollBlocker = (function () { + let offset = 0; + return { + block() { + offset = window.scrollY; + $("html,body").scrollTop(0); + }, + release() { + $("html,body").scrollTop(offset); + }, + getOffset() { + return offset; + } + }; + }()); - /*--- Actions in mobile screens (Sidebar hidden) ---*/ + /*--- Actions in mobile screens (Sidebar hidden) ---*/ - const mobileSearchBar = (function () { - return { - on() { - btnSbTrigger.addClass("unloaded"); - topbarTitle.addClass("unloaded"); - btnSearchTrigger.addClass("unloaded"); - searchWrapper.addClass("d-flex"); - btnCancel.addClass("loaded"); - }, - off() { - btnCancel.removeClass("loaded"); - searchWrapper.removeClass("d-flex"); - btnSbTrigger.removeClass("unloaded"); - topbarTitle.removeClass("unloaded"); - btnSearchTrigger.removeClass("unloaded"); - } - }; - }()); + const mobileSearchBar = (function () { + return { + on() { + btnSbTrigger.addClass("unloaded"); + topbarTitle.addClass("unloaded"); + btnSearchTrigger.addClass("unloaded"); + searchWrapper.addClass("d-flex"); + btnCancel.addClass("loaded"); + }, + off() { + btnCancel.removeClass("loaded"); + searchWrapper.removeClass("d-flex"); + btnSbTrigger.removeClass("unloaded"); + topbarTitle.removeClass("unloaded"); + btnSearchTrigger.removeClass("unloaded"); + } + }; + }()); - const resultSwitch = (function () { - let visible = false; + const resultSwitch = (function () { + let visible = false; - return { - on() { - if (!visible) { - // the block method must be called before $(#main) unloaded. - scrollBlocker.block(); - resultWrapper.removeClass("unloaded"); - main.addClass("unloaded"); - visible = true; - } - }, - off() { - if (visible) { - results.empty(); - if (hints.hasClass("unloaded")) { - hints.removeClass("unloaded"); - } - resultWrapper.addClass("unloaded"); - main.removeClass("unloaded"); + return { + on() { + if (!visible) { + // the block method must be called before $(#main) unloaded. + scrollBlocker.block(); + resultWrapper.removeClass("unloaded"); + main.addClass("unloaded"); + visible = true; + } + }, + off() { + if (visible) { + results.empty(); + if (hints.hasClass("unloaded")) { + hints.removeClass("unloaded"); + } + resultWrapper.addClass("unloaded"); + main.removeClass("unloaded"); - // now the release method must be called after $(#main) display - scrollBlocker.release(); + // now the release method must be called after $(#main) display + scrollBlocker.release(); - input.val(""); - visible = false; - } - }, - isVisible() { - return visible; - } - }; + input.val(""); + visible = false; + } + }, + isVisible() { + return visible; + } + }; - }()); + }()); - function isMobileView() { - return btnCancel.hasClass("loaded"); - } - - btnSearchTrigger.click(function() { - mobileSearchBar.on(); - resultSwitch.on(); - input.focus(); - }); - - btnCancel.click(function() { - mobileSearchBar.off(); - resultSwitch.off(); - }); - - input.focus(function() { - searchWrapper.addClass("input-focus"); - }); - - input.focusout(function() { - searchWrapper.removeClass("input-focus"); - }); - - input.on("input", () => { - if (input.val() === "") { - if (isMobileView()) { - hints.removeClass("unloaded"); - } else { - resultSwitch.off(); - } - - } else { - resultSwitch.on(); - if (isMobileView()) { - hints.addClass("unloaded"); - } + function isMobileView() { + return btnCancel.hasClass("loaded"); } - }); + + btnSearchTrigger.click(function () { + mobileSearchBar.on(); + resultSwitch.on(); + input.focus(); + }); + + btnCancel.click(function () { + mobileSearchBar.off(); + resultSwitch.off(); + }); + + input.focus(function () { + searchWrapper.addClass("input-focus"); + }); + + input.focusout(function () { + searchWrapper.removeClass("input-focus"); + }); + + input.on("input", () => { + if (input.val() === "") { + if (isMobileView()) { + hints.removeClass("unloaded"); + } else { + resultSwitch.off(); + } + + } else { + resultSwitch.on(); + if (isMobileView()) { + hints.addClass("unloaded"); + } + } + }); }); diff --git a/_javascript/commons/sidebar.js b/_javascript/commons/sidebar.js index 014411a..121353f 100644 --- a/_javascript/commons/sidebar.js +++ b/_javascript/commons/sidebar.js @@ -2,29 +2,27 @@ * Expand or close the sidebar in mobile screens. */ -$(function() { +$(function () { + const sidebarUtil = (function () { + const ATTR_DISPLAY = "sidebar-display"; + let isExpanded = false; + const body = $("body"); - const sidebarUtil = (function () { - const ATTR_DISPLAY = "sidebar-display"; - let isExpanded = false; - const body = $("body"); + return { + toggle() { + if (isExpanded === false) { + body.attr(ATTR_DISPLAY, ""); + } else { + body.removeAttr(ATTR_DISPLAY); + } - return { - toggle() { - if (isExpanded === false) { - body.attr(ATTR_DISPLAY, ""); - } else { - body.removeAttr(ATTR_DISPLAY); - } + isExpanded = !isExpanded; + } + }; - isExpanded = !isExpanded; - } - }; + }()); - }()); - - $("#sidebar-trigger").click(sidebarUtil.toggle); - - $("#mask").click(sidebarUtil.toggle); + $("#sidebar-trigger").click(sidebarUtil.toggle); + $("#mask").click(sidebarUtil.toggle); }); diff --git a/_javascript/commons/tooltip-loader.js b/_javascript/commons/tooltip-loader.js index 90c6a98..0b2f0b1 100644 --- a/_javascript/commons/tooltip-loader.js +++ b/_javascript/commons/tooltip-loader.js @@ -1,6 +1,6 @@ /** * Initial Bootstrap Tooltip. -*/ + */ $(function () { - $("[data-toggle=\"tooltip\"]").tooltip(); + $("[data-toggle=\"tooltip\"]").tooltip(); }); diff --git a/_javascript/commons/topbar-switcher.js b/_javascript/commons/topbar-switcher.js index f1c42bf..91c857e 100644 --- a/_javascript/commons/topbar-switcher.js +++ b/_javascript/commons/topbar-switcher.js @@ -1,90 +1,89 @@ -/* +/** * Hide Header on scroll down */ -$(function() { - const $searchInput = $("#search-input"); - const delta = ScrollHelper.getTopbarHeight(); +$(function () { + const $searchInput = $("#search-input"); + const delta = ScrollHelper.getTopbarHeight(); - let didScroll; - let lastScrollTop = 0; + let didScroll; + let lastScrollTop = 0; - function hasScrolled() { - let st = $(this).scrollTop(); + function hasScrolled() { + let st = $(this).scrollTop(); - /* Make sure they scroll more than delta */ - if (Math.abs(lastScrollTop - st) <= delta) { - return; - } - - if (st > lastScrollTop ) { // Scroll Down - ScrollHelper.hideTopbar(); - - if ($searchInput.is(":focus")) { - $searchInput.blur(); /* remove focus */ - } - - } else { // Scroll up - // has not yet scrolled to the bottom of the screen, that is, there is still space for scrolling - if (st + $(window).height() < $(document).height()) { - - if (ScrollHelper.hasScrollUpTask()) { - return; + /* Make sure they scroll more than delta */ + if (Math.abs(lastScrollTop - st) <= delta) { + return; } - if (ScrollHelper.topbarLocked()) { // avoid redundant scroll up event from smooth scrolling - ScrollHelper.unlockTopbar(); - } else { - if (ScrollHelper.orientationLocked()) { // avoid device auto scroll up on orientation change - ScrollHelper.unLockOrientation(); - } else { - ScrollHelper.showTopbar(); - } + if (st > lastScrollTop) { // Scroll Down + ScrollHelper.hideTopbar(); + + if ($searchInput.is(":focus")) { + $searchInput.blur(); /* remove focus */ + } + + } else { // Scroll up + // has not yet scrolled to the bottom of the screen, that is, there is still space for scrolling + if (st + $(window).height() < $(document).height()) { + + if (ScrollHelper.hasScrollUpTask()) { + return; + } + + if (ScrollHelper.topbarLocked()) { // avoid redundant scroll up event from smooth scrolling + ScrollHelper.unlockTopbar(); + } else { + if (ScrollHelper.orientationLocked()) { // avoid device auto scroll up on orientation change + ScrollHelper.unLockOrientation(); + } else { + ScrollHelper.showTopbar(); + } + } + } } - } + + lastScrollTop = st; + + } // hasScrolled() + + function handleLandscape() { + if ($(window).scrollTop() === 0) { + return; + } + ScrollHelper.lockOrientation(); + ScrollHelper.hideTopbar(); } - lastScrollTop = st; + if (screen.orientation) { + screen.orientation.onchange = () => { + const type = screen.orientation.type; + if (type === "landscape-primary" || type === "landscape-secondary") { + handleLandscape(); + } + }; - } // hasScrolled() - - function handleLandscape() { - if ($(window).scrollTop() === 0) { - return; + } else { + // for the browsers that not support `window.screen.orientation` API + $(window).on("orientationchange", () => { + if ($(window).width() < $(window).height()) { // before rotating, it is still in portrait mode. + handleLandscape(); + } + }); } - ScrollHelper.lockOrientation(); - ScrollHelper.hideTopbar(); - } - if (screen.orientation) { - screen.orientation.onchange = () => { - const type = screen.orientation.type; - if (type === "landscape-primary" || type === "landscape-secondary") { - handleLandscape(); - } - }; - - } else { - // for the browsers that not support `window.screen.orientation` API - $(window).on("orientationchange",() => { - if ($(window).width() < $(window).height()) { // before rotating, it is still in portrait mode. - handleLandscape(); - } + $(window).scroll(() => { + if (didScroll) { + return; + } + didScroll = true; }); - } - - $(window).scroll(() => { - if (didScroll) { - return; - } - didScroll = true; - }); - - setInterval(() => { - if (didScroll) { - hasScrolled(); - didScroll = false; - } - }, 250); + setInterval(() => { + if (didScroll) { + hasScrolled(); + didScroll = false; + } + }, 250); }); diff --git a/_javascript/commons/topbar-title.js b/_javascript/commons/topbar-title.js index ff82151..fd27a7d 100644 --- a/_javascript/commons/topbar-title.js +++ b/_javascript/commons/topbar-title.js @@ -1,67 +1,67 @@ -/* +/** * Top bar title auto change while scrolling up/down in mobile screens. -*/ + */ -$(function() { - const titleSelector = "div.post>h1:first-of-type"; - const $pageTitle = $(titleSelector); - const $topbarTitle = $("#topbar-title"); +$(function () { + const titleSelector = "div.post>h1:first-of-type"; + const $pageTitle = $(titleSelector); + const $topbarTitle = $("#topbar-title"); - if ($pageTitle.length === 0 /* on Home page */ - || $pageTitle.hasClass("dynamic-title") - || $topbarTitle.is(":hidden")) {/* not in mobile views */ - return; - } - - const defaultTitleText = $topbarTitle.text().trim(); - let pageTitleText = $pageTitle.text().trim(); - let hasScrolled = false; - let lastScrollTop = 0; - - if ($("#page-category").length || $("#page-tag").length) { - /* The title in Category or Tag page will be " <count_of_posts>" */ - if (/\s/.test(pageTitleText)) { - pageTitleText = pageTitleText.replace(/[0-9]/g, "").trim(); - } - } - - // When the page is scrolled down and then refreshed, the topbar title needs to be initialized - if ($pageTitle.offset().top < $(window).scrollTop()) { - $topbarTitle.text(pageTitleText); - } - - let options = { - rootMargin: '-48px 0px 0px 0px', // 48px equals to the topbar height (3rem) - threshold: [0, 1] - }; - - let observer = new IntersectionObserver((entries) => { - if (!hasScrolled) { - hasScrolled = true; - return; + if ($pageTitle.length === 0 /* on Home page */ + || $pageTitle.hasClass("dynamic-title") + || $topbarTitle.is(":hidden")) {/* not in mobile views */ + return; } - let curScrollTop = $(window).scrollTop(); - let isScrollDown = lastScrollTop < curScrollTop; - lastScrollTop = curScrollTop; - let heading = entries[0]; + const defaultTitleText = $topbarTitle.text().trim(); + let pageTitleText = $pageTitle.text().trim(); + let hasScrolled = false; + let lastScrollTop = 0; - if (isScrollDown) { - if (heading.intersectionRatio === 0) { + if ($("#page-category").length || $("#page-tag").length) { + /* The title in Category or Tag page will be "<title> <count_of_posts>" */ + if (/\s/.test(pageTitleText)) { + pageTitleText = pageTitleText.replace(/[0-9]/g, "").trim(); + } + } + + // When the page is scrolled down and then refreshed, the topbar title needs to be initialized + if ($pageTitle.offset().top < $(window).scrollTop()) { $topbarTitle.text(pageTitleText); - } - } else { - if (heading.intersectionRatio === 1) { - $topbarTitle.text(defaultTitleText); - } } - }, options); - observer.observe(document.querySelector(titleSelector)); + let options = { + rootMargin: '-48px 0px 0px 0px', // 48px equals to the topbar height (3rem) + threshold: [0, 1] + }; - /* Click title will scroll to top */ - $topbarTitle.click(function() { - $("body,html").animate({scrollTop: 0}, 800); - }); + let observer = new IntersectionObserver((entries) => { + if (!hasScrolled) { + hasScrolled = true; + return; + } + + let curScrollTop = $(window).scrollTop(); + let isScrollDown = lastScrollTop < curScrollTop; + lastScrollTop = curScrollTop; + let heading = entries[0]; + + if (isScrollDown) { + if (heading.intersectionRatio === 0) { + $topbarTitle.text(pageTitleText); + } + } else { + if (heading.intersectionRatio === 1) { + $topbarTitle.text(defaultTitleText); + } + } + }, options); + + observer.observe(document.querySelector(titleSelector)); + + /* Click title will scroll to top */ + $topbarTitle.click(function () { + $("body,html").animate({scrollTop: 0}, 800); + }); }); diff --git a/_javascript/utils/category-collapse.js b/_javascript/utils/category-collapse.js index 904b448..965bcfd 100644 --- a/_javascript/utils/category-collapse.js +++ b/_javascript/utils/category-collapse.js @@ -1,30 +1,30 @@ -/* +/** * Tab 'Categories' expand/close effect. */ -$(function() { - const childPrefix = "l_"; - const parentPrefix = "h_"; - const collapse = $(".collapse"); +$(function () { + const childPrefix = "l_"; + const parentPrefix = "h_"; + const collapse = $(".collapse"); - /* close up top-category */ - collapse.on("hide.bs.collapse", function () { /* Bootstrap collapse events. */ - const parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); - if (parentId) { - $(`#${parentId} .far.fa-folder-open`).attr("class", "far fa-folder fa-fw"); - $(`#${parentId} i.fas`).addClass("rotate"); - $(`#${parentId}`).removeClass("hide-border-bottom"); - } - }); + /* close up top-category */ + collapse.on("hide.bs.collapse", function () { /* Bootstrap collapse events. */ + const parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); + if (parentId) { + $(`#${parentId} .far.fa-folder-open`).attr("class", "far fa-folder fa-fw"); + $(`#${parentId} i.fas`).addClass("rotate"); + $(`#${parentId}`).removeClass("hide-border-bottom"); + } + }); - /* expand the top category */ - collapse.on("show.bs.collapse", function() { - const parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); - if (parentId) { - $(`#${parentId} .far.fa-folder`).attr("class", "far fa-folder-open fa-fw"); - $(`#${parentId} i.fas`).removeClass("rotate"); - $(`#${parentId}`).addClass("hide-border-bottom"); - } - }); + /* expand the top category */ + collapse.on("show.bs.collapse", function () { + const parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); + if (parentId) { + $(`#${parentId} .far.fa-folder`).attr("class", "far fa-folder-open fa-fw"); + $(`#${parentId} i.fas`).removeClass("rotate"); + $(`#${parentId}`).addClass("hide-border-bottom"); + } + }); }); diff --git a/_javascript/utils/clipboard.js b/_javascript/utils/clipboard.js index fb2899d..1b5001b 100644 --- a/_javascript/utils/clipboard.js +++ b/_javascript/utils/clipboard.js @@ -1,4 +1,4 @@ -/* +/** * Clipboard functions * * Dependencies: @@ -6,128 +6,128 @@ * - clipboard.js (https://github.com/zenorocha/clipboard.js) */ -$(function() { - const btnSelector = '.code-header>button'; - const ICON_SUCCESS = 'fas fa-check'; - const ATTR_TIMEOUT = 'timeout'; - const ATTR_TITLE_SUCCEED = 'data-title-succeed'; - const ATTR_TITLE_ORIGIN = 'data-original-title'; - const TIMEOUT = 2000; // in milliseconds +$(function () { + const btnSelector = '.code-header>button'; + const ICON_SUCCESS = 'fas fa-check'; + const ATTR_TIMEOUT = 'timeout'; + const ATTR_TITLE_SUCCEED = 'data-title-succeed'; + const ATTR_TITLE_ORIGIN = 'data-original-title'; + const TIMEOUT = 2000; // in milliseconds - function isLocked(node) { - if ($(node)[0].hasAttribute(ATTR_TIMEOUT)) { - let timeout = $(node).attr(ATTR_TIMEOUT); - if (Number(timeout) > Date.now()) { - return true; - } - } - return false; - } - - function lock(node) { - $(node).attr(ATTR_TIMEOUT, Date.now() + TIMEOUT); - } - - function unlock(node) { - $(node).removeAttr(ATTR_TIMEOUT); - } - - /* --- Copy code block --- */ - - // Initial the clipboard.js object - const clipboard = new ClipboardJS(btnSelector, { - target(trigger) { - let codeBlock = trigger.parentNode.nextElementSibling; - return codeBlock.querySelector('code .rouge-code'); - } - }); - - $(btnSelector).tooltip({ - trigger: 'hover', - placement: 'left' - }); - - function getIcon(btn) { - let iconNode = $(btn).children(); - return iconNode.attr('class'); - } - - const ICON_DEFAULT = getIcon(btnSelector); - - function showTooltip(btn) { - const succeedTitle = $(btn).attr(ATTR_TITLE_SUCCEED); - $(btn).attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show'); - } - - function hideTooltip(btn) { - $(btn).tooltip('hide').removeAttr(ATTR_TITLE_ORIGIN); - } - - function setSuccessIcon(btn) { - let btnNode = $(btn); - let iconNode = btnNode.children(); - iconNode.attr('class', ICON_SUCCESS); - } - - function resumeIcon(btn) { - let btnNode = $(btn); - let iconNode = btnNode.children(); - iconNode.attr('class', ICON_DEFAULT); - } - - clipboard.on('success', (e) => { - e.clearSelection(); - - const trigger = e.trigger; - if (isLocked(trigger)) { - return; + function isLocked(node) { + if ($(node)[0].hasAttribute(ATTR_TIMEOUT)) { + let timeout = $(node).attr(ATTR_TIMEOUT); + if (Number(timeout) > Date.now()) { + return true; + } + } + return false; } - setSuccessIcon(trigger); - showTooltip(trigger); - lock(trigger); - - setTimeout(() => { - hideTooltip(trigger); - resumeIcon(trigger); - unlock(trigger); - }, TIMEOUT); - - }); - - /* --- Post link sharing --- */ - - $('#copy-link').click((e) => { - - let target = $(e.target); - - if (isLocked(target)) { - return; + function lock(node) { + $(node).attr(ATTR_TIMEOUT, Date.now() + TIMEOUT); } - // Copy URL to clipboard + function unlock(node) { + $(node).removeAttr(ATTR_TIMEOUT); + } - const url = window.location.href; - const $temp = $("<input>"); + /* --- Copy code block --- */ - $("body").append($temp); - $temp.val(url).select(); - document.execCommand("copy"); - $temp.remove(); + // Initial the clipboard.js object + const clipboard = new ClipboardJS(btnSelector, { + target(trigger) { + let codeBlock = trigger.parentNode.nextElementSibling; + return codeBlock.querySelector('code .rouge-code'); + } + }); - // Switch tooltip title + $(btnSelector).tooltip({ + trigger: 'hover', + placement: 'left' + }); - const defaultTitle = target.attr(ATTR_TITLE_ORIGIN); - const succeedTitle = target.attr(ATTR_TITLE_SUCCEED); + function getIcon(btn) { + let iconNode = $(btn).children(); + return iconNode.attr('class'); + } - target.attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show'); - lock(target); + const ICON_DEFAULT = getIcon(btnSelector); - setTimeout(() => { - target.attr(ATTR_TITLE_ORIGIN, defaultTitle); - unlock(target); - }, TIMEOUT); + function showTooltip(btn) { + const succeedTitle = $(btn).attr(ATTR_TITLE_SUCCEED); + $(btn).attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show'); + } - }); + function hideTooltip(btn) { + $(btn).tooltip('hide').removeAttr(ATTR_TITLE_ORIGIN); + } + + function setSuccessIcon(btn) { + let btnNode = $(btn); + let iconNode = btnNode.children(); + iconNode.attr('class', ICON_SUCCESS); + } + + function resumeIcon(btn) { + let btnNode = $(btn); + let iconNode = btnNode.children(); + iconNode.attr('class', ICON_DEFAULT); + } + + clipboard.on('success', (e) => { + e.clearSelection(); + + const trigger = e.trigger; + if (isLocked(trigger)) { + return; + } + + setSuccessIcon(trigger); + showTooltip(trigger); + lock(trigger); + + setTimeout(() => { + hideTooltip(trigger); + resumeIcon(trigger); + unlock(trigger); + }, TIMEOUT); + + }); + + /* --- Post link sharing --- */ + + $('#copy-link').click((e) => { + + let target = $(e.target); + + if (isLocked(target)) { + return; + } + + // Copy URL to clipboard + + const url = window.location.href; + const $temp = $("<input>"); + + $("body").append($temp); + $temp.val(url).select(); + document.execCommand("copy"); + $temp.remove(); + + // Switch tooltip title + + const defaultTitle = target.attr(ATTR_TITLE_ORIGIN); + const succeedTitle = target.attr(ATTR_TITLE_SUCCEED); + + target.attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show'); + lock(target); + + setTimeout(() => { + target.attr(ATTR_TITLE_ORIGIN, defaultTitle); + unlock(target); + }, TIMEOUT); + + }); }); diff --git a/_javascript/utils/img-extra.js b/_javascript/utils/img-extra.js index efdb4d4..528f867 100644 --- a/_javascript/utils/img-extra.js +++ b/_javascript/utils/img-extra.js @@ -1,47 +1,46 @@ /** - Lazy load images (https://github.com/ApoorvSaxena/lozad.js) - and popup when clicked (https://github.com/dimsemenov/Magnific-Popup) -*/ + Lazy load images (https://github.com/ApoorvSaxena/lozad.js) + and popup when clicked (https://github.com/dimsemenov/Magnific-Popup) + */ -$(function() { +$(function () { + const IMG_SCOPE = '#main > div.row:first-child > div:first-child'; - const IMG_SCOPE = '#main > div.row:first-child > div:first-child'; - - if ($(`${IMG_SCOPE} img`).length <= 0 ) { - return; - } - - /* lazy loading */ - - const imgList = document.querySelectorAll(`${IMG_SCOPE} img[data-src]`); - const observer = lozad(imgList); - observer.observe(); - - /* popup */ - - $(`${IMG_SCOPE} p > img[data-src],${IMG_SCOPE} img[data-src].preview-img`).each( - function() { - let nextTag = $(this).next(); - const title = nextTag.prop('tagName') === 'EM' ? nextTag.text() : ''; - const src = $(this).attr('data-src'); // created by lozad.js - - $(this).wrap(`<a href="${src}" title="${title}" class="popup"></a>`); + if ($(`${IMG_SCOPE} img`).length <= 0) { + return; } - ); - $('.popup').magnificPopup({ - type: 'image', - closeOnContentClick: true, - showCloseBtn: false, - zoom: { - enabled: true, - duration: 300, - easing: 'ease-in-out' - } - }); + /* lazy loading */ - /* markup the image links */ + const imgList = document.querySelectorAll(`${IMG_SCOPE} img[data-src]`); + const observer = lozad(imgList); + observer.observe(); - $(`${IMG_SCOPE} a`).has('img').addClass('img-link'); + /* popup */ + + $(`${IMG_SCOPE} p > img[data-src], ${IMG_SCOPE} img[data-src].preview-img`).each( + function () { + let nextTag = $(this).next(); + const title = nextTag.prop('tagName') === 'EM' ? nextTag.text() : ''; + const src = $(this).attr('data-src'); // created by lozad.js + + $(this).wrap(`<a href="${src}" title="${title}" class="popup"></a>`); + } + ); + + $('.popup').magnificPopup({ + type: 'image', + closeOnContentClick: true, + showCloseBtn: false, + zoom: { + enabled: true, + duration: 300, + easing: 'ease-in-out' + } + }); + + /* markup the image links */ + + $(`${IMG_SCOPE} a`).has('img').addClass('img-link'); }); diff --git a/_javascript/utils/locale-datetime.js b/_javascript/utils/locale-datetime.js index 5d6a68b..80d86c9 100644 --- a/_javascript/utils/locale-datetime.js +++ b/_javascript/utils/locale-datetime.js @@ -6,38 +6,38 @@ /* A tool for locale datetime */ const LocaleHelper = (function () { - const locale = $('html').attr('lang').substr(0, 2); - const attrTimestamp = 'data-ts'; - const attrDateFormat = 'data-df'; + const locale = $('html').attr('lang').substr(0, 2); + const attrTimestamp = 'data-ts'; + const attrDateFormat = 'data-df'; - return { - locale: () => locale, - attrTimestamp: () => attrTimestamp, - attrDateFormat: () => attrDateFormat, - getTimestamp: ($elem) => Number($elem.attr(attrTimestamp)), // unix timestamp - getDateFormat: ($elem) => $elem.attr(attrDateFormat) - }; + return { + locale: () => locale, + attrTimestamp: () => attrTimestamp, + attrDateFormat: () => attrDateFormat, + getTimestamp: ($elem) => Number($elem.attr(attrTimestamp)), // unix timestamp + getDateFormat: ($elem) => $elem.attr(attrDateFormat) + }; }()); -$(function() { - dayjs.locale(LocaleHelper.locale()); - dayjs.extend(window.dayjs_plugin_localizedFormat); +$(function () { + dayjs.locale(LocaleHelper.locale()); + dayjs.extend(window.dayjs_plugin_localizedFormat); - $(`[${LocaleHelper.attrTimestamp()}]`).each(function () { - const date = dayjs.unix(LocaleHelper.getTimestamp($(this))); - const text = date.format(LocaleHelper.getDateFormat($(this))); - $(this).text(text); - $(this).removeAttr(LocaleHelper.attrTimestamp()); - $(this).removeAttr(LocaleHelper.attrDateFormat()); + $(`[${LocaleHelper.attrTimestamp()}]`).each(function () { + const date = dayjs.unix(LocaleHelper.getTimestamp($(this))); + const text = date.format(LocaleHelper.getDateFormat($(this))); + $(this).text(text); + $(this).removeAttr(LocaleHelper.attrTimestamp()); + $(this).removeAttr(LocaleHelper.attrDateFormat()); - // setup tooltips - const tooltip = $(this).attr('data-toggle'); - if (typeof tooltip === 'undefined' || tooltip !== 'tooltip') { - return; - } + // setup tooltips + const tooltip = $(this).attr('data-toggle'); + if (typeof tooltip === 'undefined' || tooltip !== 'tooltip') { + return; + } - const tooltipText = date.format('llll'); // see: https://day.js.org/docs/en/display/format#list-of-localized-formats - $(this).attr('data-original-title', tooltipText); - }); + const tooltipText = date.format('llll'); // see: https://day.js.org/docs/en/display/format#list-of-localized-formats + $(this).attr('data-original-title', tooltipText); + }); }); diff --git a/_javascript/utils/pageviews.js b/_javascript/utils/pageviews.js index 1b71508..1e875d8 100644 --- a/_javascript/utils/pageviews.js +++ b/_javascript/utils/pageviews.js @@ -1,4 +1,4 @@ -/* +/** * Count page views form GA or local cache file. * * Dependencies: @@ -7,244 +7,244 @@ */ const getInitStatus = (function () { - let hasInit = false; - return () => { - let ret = hasInit; - if (!hasInit) { - hasInit = true; - } - return ret; - }; + let hasInit = false; + return () => { + let ret = hasInit; + if (!hasInit) { + hasInit = true; + } + return ret; + }; }()); const PvOpts = (function () { - function getContent(selector) { - return $(selector).attr("content"); - } - - function hasContent(selector) { - let content = getContent(selector); - return (typeof content !== "undefined" && content !== false); - } - - return { - getProxyMeta() { - return getContent("meta[name=pv-proxy-endpoint]"); - }, - getLocalMeta() { - return getContent("meta[name=pv-cache-path]"); - }, - hasProxyMeta() { - return hasContent("meta[name=pv-proxy-endpoint]"); - }, - hasLocalMeta() { - return hasContent("meta[name=pv-cache-path]"); + function getContent(selector) { + return $(selector).attr("content"); } - }; + + function hasContent(selector) { + let content = getContent(selector); + return (typeof content !== "undefined" && content !== false); + } + + return { + getProxyMeta() { + return getContent("meta[name=pv-proxy-endpoint]"); + }, + getLocalMeta() { + return getContent("meta[name=pv-cache-path]"); + }, + hasProxyMeta() { + return hasContent("meta[name=pv-proxy-endpoint]"); + }, + hasLocalMeta() { + return hasContent("meta[name=pv-cache-path]"); + } + }; }()); const PvStorage = (function () { - const Keys = { - KEY_PV: "pv", - KEY_PV_SRC: "pv_src", - KEY_CREATION: "pv_created_date" - }; + const Keys = { + KEY_PV: "pv", + KEY_PV_SRC: "pv_src", + KEY_CREATION: "pv_created_date" + }; - const Source = { - LOCAL: "same-origin", - PROXY: "cors" - }; + const Source = { + LOCAL: "same-origin", + PROXY: "cors" + }; - function get(key) { - return localStorage.getItem(key); - } - - function set(key, val) { - localStorage.setItem(key, val); - } - - function saveCache(pv, src) { - set(Keys.KEY_PV, pv); - set(Keys.KEY_PV_SRC, src); - set(Keys.KEY_CREATION, new Date().toJSON()); - } - - return { - keysCount() { - return Object.keys(Keys).length; - }, - hasCache() { - return (localStorage.getItem(Keys.KEY_PV) !== null); - }, - getCache() { - return JSON.parse(localStorage.getItem(Keys.KEY_PV)); - }, - saveLocalCache(pv) { - saveCache(pv, Source.LOCAL); - }, - saveProxyCache(pv) { - saveCache(pv, Source.PROXY); - }, - isExpired() { - let date = new Date(get(Keys.KEY_CREATION)); - date.setHours(date.getHours() + 1); // per hour - return Date.now() >= date.getTime(); - }, - isFromLocal() { - return get(Keys.KEY_PV_SRC) === Source.LOCAL; - }, - isFromProxy() { - return get(Keys.KEY_PV_SRC) === Source.PROXY; - }, - newerThan(pv) { - return PvStorage.getCache().totalsForAllResults["ga:pageviews"] > pv.totalsForAllResults["ga:pageviews"]; - }, - inspectKeys() { - if (localStorage.length !== PvStorage.keysCount()) { - localStorage.clear(); - return; - } - - for(let i = 0; i < localStorage.length; i++){ - const key = localStorage.key(i); - switch (key) { - case Keys.KEY_PV: - case Keys.KEY_PV_SRC: - case Keys.KEY_CREATION: - break; - default: - localStorage.clear(); - return; - } - } + function get(key) { + return localStorage.getItem(key); } - }; + + function set(key, val) { + localStorage.setItem(key, val); + } + + function saveCache(pv, src) { + set(Keys.KEY_PV, pv); + set(Keys.KEY_PV_SRC, src); + set(Keys.KEY_CREATION, new Date().toJSON()); + } + + return { + keysCount() { + return Object.keys(Keys).length; + }, + hasCache() { + return (localStorage.getItem(Keys.KEY_PV) !== null); + }, + getCache() { + return JSON.parse(localStorage.getItem(Keys.KEY_PV)); + }, + saveLocalCache(pv) { + saveCache(pv, Source.LOCAL); + }, + saveProxyCache(pv) { + saveCache(pv, Source.PROXY); + }, + isExpired() { + let date = new Date(get(Keys.KEY_CREATION)); + date.setHours(date.getHours() + 1); // per hour + return Date.now() >= date.getTime(); + }, + isFromLocal() { + return get(Keys.KEY_PV_SRC) === Source.LOCAL; + }, + isFromProxy() { + return get(Keys.KEY_PV_SRC) === Source.PROXY; + }, + newerThan(pv) { + return PvStorage.getCache().totalsForAllResults["ga:pageviews"] > pv.totalsForAllResults["ga:pageviews"]; + }, + inspectKeys() { + if (localStorage.length !== PvStorage.keysCount()) { + localStorage.clear(); + return; + } + + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + switch (key) { + case Keys.KEY_PV: + case Keys.KEY_PV_SRC: + case Keys.KEY_CREATION: + break; + default: + localStorage.clear(); + return; + } + } + } + }; }()); /* PvStorage */ function countUp(min, max, destId) { - if (min < max) { - let numAnim = new CountUp(destId, min, max); - if (!numAnim.error) { - numAnim.start(); - } else { - console.error(numAnim.error); + if (min < max) { + let numAnim = new CountUp(destId, min, max); + if (!numAnim.error) { + numAnim.start(); + } else { + console.error(numAnim.error); + } } - } } function countPV(path, rows) { - let count = 0; + let count = 0; - if (typeof rows !== "undefined" ) { - for (let i = 0; i < rows.length; ++i) { - const gaPath = rows[parseInt(i, 10)][0]; - if (gaPath === path) { /* path format see: site.permalink */ - count += parseInt(rows[parseInt(i, 10)][1], 10); - break; - } + if (typeof rows !== "undefined") { + for (let i = 0; i < rows.length; ++i) { + const gaPath = rows[parseInt(i, 10)][0]; + if (gaPath === path) { /* path format see: site.permalink */ + count += parseInt(rows[parseInt(i, 10)][1], 10); + break; + } + } } - } - return count; + return count; } function tacklePV(rows, path, elem, hasInit) { - let count = countPV(path, rows); - count = (count === 0 ? 1 : count); + let count = countPV(path, rows); + count = (count === 0 ? 1 : count); - if (!hasInit) { - elem.text(new Intl.NumberFormat().format(count)); - } else { - const initCount = parseInt(elem.text().replace(/,/g, ""), 10); - if (count > initCount) { - countUp(initCount, count, elem.attr("id")); + if (!hasInit) { + elem.text(new Intl.NumberFormat().format(count)); + } else { + const initCount = parseInt(elem.text().replace(/,/g, ""), 10); + if (count > initCount) { + countUp(initCount, count, elem.attr("id")); + } } - } } function displayPageviews(data) { - if (typeof data === "undefined") { - return; - } + if (typeof data === "undefined") { + return; + } - let hasInit = getInitStatus(); - const rows = data.rows; /* could be undefined */ + let hasInit = getInitStatus(); + const rows = data.rows; /* could be undefined */ - if ($("#post-list").length > 0) { /* the Home page */ - $(".post-preview").each(function() { - const path = $(this).find("a").attr("href"); - tacklePV(rows, path, $(this).find(".pageviews"), hasInit); - }); + if ($("#post-list").length > 0) { /* the Home page */ + $(".post-preview").each(function () { + const path = $(this).find("a").attr("href"); + tacklePV(rows, path, $(this).find(".pageviews"), hasInit); + }); - } else if ($(".post").length > 0) { /* the post */ - const path = window.location.pathname; - tacklePV(rows, path, $("#pv"), hasInit); - } + } else if ($(".post").length > 0) { /* the post */ + const path = window.location.pathname; + tacklePV(rows, path, $("#pv"), hasInit); + } } function fetchProxyPageviews() { - if (PvOpts.hasProxyMeta()) { - $.ajax({ - type: "GET", - url: PvOpts.getProxyMeta(), - dataType: "jsonp", - jsonpCallback: "displayPageviews", - success: (data) => { - PvStorage.saveProxyCache(JSON.stringify(data)); - }, - error: (jqXHR, textStatus, errorThrown) => { - console.log("Failed to load pageviews from proxy server: " + errorThrown); - } - }); - } + if (PvOpts.hasProxyMeta()) { + $.ajax({ + type: "GET", + url: PvOpts.getProxyMeta(), + dataType: "jsonp", + jsonpCallback: "displayPageviews", + success: (data) => { + PvStorage.saveProxyCache(JSON.stringify(data)); + }, + error: (jqXHR, textStatus, errorThrown) => { + console.log("Failed to load pageviews from proxy server: " + errorThrown); + } + }); + } } function fetchLocalPageviews(hasCache = false) { - return fetch(PvOpts.getLocalMeta()) - .then(response => response.json()) - .then(data => { - if (hasCache) { - // The cache from the proxy will sometimes be more recent than the local one - if (PvStorage.isFromProxy() && PvStorage.newerThan(data)) { - return; - } - } - displayPageviews(data); - PvStorage.saveLocalCache(JSON.stringify(data)); - }); + return fetch(PvOpts.getLocalMeta()) + .then(response => response.json()) + .then(data => { + if (hasCache) { + // The cache from the proxy will sometimes be more recent than the local one + if (PvStorage.isFromProxy() && PvStorage.newerThan(data)) { + return; + } + } + displayPageviews(data); + PvStorage.saveLocalCache(JSON.stringify(data)); + }); } -$(function() { - if ($(".pageviews").length <= 0) { - return; - } - - PvStorage.inspectKeys(); - - if (PvStorage.hasCache()) { - displayPageviews(PvStorage.getCache()); - - if (PvStorage.isExpired()) { - if (PvOpts.hasLocalMeta()) { - fetchLocalPageviews(true).then(fetchProxyPageviews); - } else { - fetchProxyPageviews(); - } - - } else { - if (PvStorage.isFromLocal()) { - fetchProxyPageviews(); - } +$(function () { + if ($(".pageviews").length <= 0) { + return; } - } else { // no cached + PvStorage.inspectKeys(); - if (PvOpts.hasLocalMeta()) { - fetchLocalPageviews().then(fetchProxyPageviews); - } else { - fetchProxyPageviews(); + if (PvStorage.hasCache()) { + displayPageviews(PvStorage.getCache()); + + if (PvStorage.isExpired()) { + if (PvOpts.hasLocalMeta()) { + fetchLocalPageviews(true).then(fetchProxyPageviews); + } else { + fetchProxyPageviews(); + } + + } else { + if (PvStorage.isFromLocal()) { + fetchProxyPageviews(); + } + } + + } else { // no cached + + if (PvOpts.hasLocalMeta()) { + fetchLocalPageviews().then(fetchProxyPageviews); + } else { + fetchProxyPageviews(); + } } - } }); diff --git a/_javascript/utils/smooth-scroll.js b/_javascript/utils/smooth-scroll.js index ff3146d..f8aba66 100644 --- a/_javascript/utils/smooth-scroll.js +++ b/_javascript/utils/smooth-scroll.js @@ -1,96 +1,96 @@ -/* - Safari doesn't support CSS `scroll-behavior: smooth`, - so here is a compatible solution for all browser to smooth scrolling +/** + Safari doesn't support CSS `scroll-behavior: smooth`, + so here is a compatible solution for all browser to smooth scrolling - See: <https://css-tricks.com/snippets/jquery/smooth-scrolling/> + See: <https://css-tricks.com/snippets/jquery/smooth-scrolling/> - Warning: It must be called after all `<a>` tags (e.g., the dynamic TOC) are ready. -*/ + Warning: It must be called after all `<a>` tags (e.g., the dynamic TOC) are ready. + */ -$(function() { - const $topbarTitle = $("#topbar-title"); - const REM = 16; // in pixels - const ATTR_SCROLL_FOCUS = "scroll-focus"; +$(function () { + const $topbarTitle = $("#topbar-title"); + const REM = 16; // in pixels + const ATTR_SCROLL_FOCUS = "scroll-focus"; - $("a[href*='#']") - .not("[href='#']") - .not("[href='#0']") - .click(function(event) { - if (this.pathname.replace(/^\//, "") !== - location.pathname.replace(/^\//, "")) { - return; - } + $("a[href*='#']") + .not("[href='#']") + .not("[href='#0']") + .click(function (event) { + if (this.pathname.replace(/^\//, "") !== + location.pathname.replace(/^\//, "")) { + return; + } - if (location.hostname !== this.hostname) { - return; - } + if (location.hostname !== this.hostname) { + return; + } - const hash = decodeURI(this.hash); - let toFootnoteRef = RegExp(/^#fnref:/).test(hash); - let toFootnote = toFootnoteRef ? false : RegExp(/^#fn:/).test(hash); - let selector = hash.includes(":") ? hash.replace(/:/g, "\\:") : hash; - let $target = $(selector); + const hash = decodeURI(this.hash); + let toFootnoteRef = RegExp(/^#fnref:/).test(hash); + let toFootnote = toFootnoteRef ? false : RegExp(/^#fn:/).test(hash); + let selector = hash.includes(":") ? hash.replace(/:/g, "\\:") : hash; + let $target = $(selector); - let isMobileViews = $topbarTitle.is(":visible"); - let isPortrait = $(window).width() < $(window).height(); + let isMobileViews = $topbarTitle.is(":visible"); + let isPortrait = $(window).width() < $(window).height(); - if (typeof $target === "undefined") { - return; - } + if (typeof $target === "undefined") { + return; + } - event.preventDefault(); + event.preventDefault(); - if (history.pushState) { /* add hash to URL */ - history.pushState(null, null, hash); - } + if (history.pushState) { /* add hash to URL */ + history.pushState(null, null, hash); + } - let curOffset = $(window).scrollTop(); - let destOffset = $target.offset().top -= REM / 2; + let curOffset = $(window).scrollTop(); + let destOffset = $target.offset().top -= REM / 2; - if (destOffset < curOffset) { // scroll up - ScrollHelper.hideTopbar(); - ScrollHelper.addScrollUpTask(); + if (destOffset < curOffset) { // scroll up + ScrollHelper.hideTopbar(); + ScrollHelper.addScrollUpTask(); - if (isMobileViews && isPortrait) { - destOffset -= ScrollHelper.getTopbarHeight(); - } + if (isMobileViews && isPortrait) { + destOffset -= ScrollHelper.getTopbarHeight(); + } - } else { // scroll down - if (isMobileViews && isPortrait) { - destOffset -= ScrollHelper.getTopbarHeight(); - } - } + } else { // scroll down + if (isMobileViews && isPortrait) { + destOffset -= ScrollHelper.getTopbarHeight(); + } + } - $("html").animate({ - scrollTop: destOffset - }, 500, () => { - $target.focus(); + $("html").animate({ + scrollTop: destOffset + }, 500, () => { + $target.focus(); - /* clean up old scroll mark */ - if ($(`[${ATTR_SCROLL_FOCUS}=true]`).length) { - $(`[${ATTR_SCROLL_FOCUS}=true]`).attr(ATTR_SCROLL_FOCUS, false); - } + /* clean up old scroll mark */ + if ($(`[${ATTR_SCROLL_FOCUS}=true]`).length) { + $(`[${ATTR_SCROLL_FOCUS}=true]`).attr(ATTR_SCROLL_FOCUS, false); + } - /* Clean :target links */ - if ($(":target").length) { /* element that visited by the URL with hash */ - $(":target").attr(ATTR_SCROLL_FOCUS, false); - } + /* Clean :target links */ + if ($(":target").length) { /* element that visited by the URL with hash */ + $(":target").attr(ATTR_SCROLL_FOCUS, false); + } - /* set scroll mark to footnotes */ - if (toFootnote || toFootnoteRef) { - $target.attr(ATTR_SCROLL_FOCUS, true); - } + /* set scroll mark to footnotes */ + if (toFootnote || toFootnoteRef) { + $target.attr(ATTR_SCROLL_FOCUS, true); + } - if ($target.is(":focus")) { /* Checking if the target was focused */ - return false; - } else { - $target.attr("tabindex", "-1"); /* Adding tabindex for elements not focusable */ - $target.focus(); /* Set focus again */ - } + if ($target.is(":focus")) { /* Checking if the target was focused */ + return false; + } else { + $target.attr("tabindex", "-1"); /* Adding tabindex for elements not focusable */ + $target.focus(); /* Set focus again */ + } - if (ScrollHelper.hasScrollUpTask()) { - ScrollHelper.popScrollUpTask(); - } - }); - }); /* click() */ + if (ScrollHelper.hasScrollUpTask()) { + ScrollHelper.popScrollUpTask(); + } + }); + }); /* click() */ }); diff --git a/assets/js/data/swcache.js b/assets/js/data/swcache.js index b004d05..14a9f56 100644 --- a/assets/js/data/swcache.js +++ b/assets/js/data/swcache.js @@ -5,51 +5,50 @@ layout: compress --- const resource = [ + /* --- CSS --- */ + '{{ "/assets/css/style.css" | relative_url }}', - /* --- CSS --- */ - '{{ "/assets/css/style.css" | relative_url }}', + /* --- PWA --- */ + '{{ "/app.js" | relative_url }}', + '{{ "/sw.js" | relative_url }}', - /* --- PWA --- */ - '{{ "/app.js" | relative_url }}', - '{{ "/sw.js" | relative_url }}', + /* --- HTML --- */ + '{{ "/index.html" | relative_url }}', + '{{ "/404.html" | relative_url }}', - /* --- HTML --- */ - '{{ "/index.html" | relative_url }}', - '{{ "/404.html" | relative_url }}', - {% for tab in site.tabs %} - '{{ tab.url | relative_url }}', - {% endfor %} - - /* --- Favicons & compressed JS --- */ - {% assign cache_list = site.static_files | where: 'swcache', true %} - {% for file in cache_list %} - '{{ file.path | relative_url }}'{%- unless forloop.last -%},{%- endunless -%} - {% endfor %} + {% for tab in site.tabs %} + '{{ tab.url | relative_url }}', + {% endfor %} + /* --- Favicons & compressed JS --- */ + {% assign cache_list = site.static_files | where: 'swcache', true %} + {% for file in cache_list %} + '{{ file.path | relative_url }}'{%- unless forloop.last -%},{%- endunless -%} + {% endfor %} ]; /* The request url with below domain will be cached */ const allowedDomains = [ - {% if site.google_analytics.id != empty and site.google_analytics.id %} - 'www.googletagmanager.com', - 'www.google-analytics.com', - {% endif %} + {% if site.google_analytics.id != empty and site.google_analytics.id %} + 'www.googletagmanager.com', + 'www.google-analytics.com', + {% endif %} - '{{ site.url | split: "//" | last }}', + '{{ site.url | split: "//" | last }}', - {% if site.img_cdn contains '//' and site.img_cdn %} - '{{ site.img_cdn | split: '//' | last | split: '/' | first }}', - {% endif %} + {% if site.img_cdn contains '//' and site.img_cdn %} + '{{ site.img_cdn | split: '//' | last | split: '/' | first }}', + {% endif %} - 'fonts.gstatic.com', - 'fonts.googleapis.com', - 'cdn.jsdelivr.net', - 'polyfill.io' + 'fonts.gstatic.com', + 'fonts.googleapis.com', + 'cdn.jsdelivr.net', + 'polyfill.io' ]; /* Requests that include the following path will be banned */ const denyUrls = [ - {% if site.google_analytics.pv.cache_path %} - '{{ site.google_analytics.pv.cache_path | absolute_url }}' - {% endif %} + {% if site.google_analytics.pv.cache_path %} + '{{ site.google_analytics.pv.cache_path | absolute_url }}' + {% endif %} ]; diff --git a/assets/js/dist/page.min.js b/assets/js/dist/page.min.js index 871a865..4028799 100644 --- a/assets/js/dist/page.min.js +++ b/assets/js/dist/page.min.js @@ -3,4 +3,4 @@ * © 2019 Cotes Chung * MIT Licensed */ -$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$(".mode-toggle").click(e=>{e=$(e.target);(e.prop("tagName")==="button".toUpperCase()?e:e.parent()).blur(),flipMode()})});const ScrollHelper=function(){const e=$("body"),t="data-topbar-visible",o=$("#topbar-wrapper").outerHeight();let r=0,a=!1,l=!1;return{hideTopbar:()=>e.attr(t,!1),showTopbar:()=>e.attr(t,!0),addScrollUpTask:()=>{r+=1,a=a||!0},popScrollUpTask:()=>--r,hasScrollUpTask:()=>0<r,topbarLocked:()=>!0===a,unlockTopbar:()=>a=!1,getTopbarHeight:()=>o,orientationLocked:()=>!0===l,lockOrientation:()=>l=!0,unLockOrientation:()=>l=!1}}();$(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),r=$("#main"),a=$("#topbar-title"),l=$("#search-wrapper"),n=$("#search-result-wrapper"),i=$("#search-results"),s=$("#search-input"),c=$("#search-hints"),d=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),a.addClass("unloaded"),t.addClass("unloaded"),l.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),l.removeClass("d-flex"),e.removeClass("unloaded"),a.removeClass("unloaded"),t.removeClass("unloaded")}},u=function(){let e=!1;return{on(){e||(d.block(),n.removeClass("unloaded"),r.addClass("unloaded"),e=!0)},off(){e&&(i.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),r.removeClass("unloaded"),d.release(),s.val(""),e=!1)},isVisible(){return e}}}();function h(){return o.hasClass("loaded")}t.click(function(){p.on(),u.on(),s.focus()}),o.click(function(){p.off(),u.off()}),s.focus(function(){l.addClass("input-focus")}),s.focusout(function(){l.removeClass("input-focus")}),s.on("input",()=>{""===s.val()?h()?c.removeClass("unloaded"):u.off():(u.on(),h()&&c.addClass("unloaded"))})}),$(function(){var e=function(){const e="sidebar-display";let t=!1;const o=$("body");return{toggle(){!1===t?o.attr(e,""):o.removeAttr(e),t=!t}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const t=$("#search-input"),o=ScrollHelper.getTopbarHeight();let e,r=0;function a(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var e=screen.orientation.type;"landscape-primary"!==e&&"landscape-secondary"!==e||a()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&a()}),$(window).scroll(()=>{e=e||!0}),setInterval(()=>{e&&(!function(){var e=$(this).scrollTop();if(!(Math.abs(r-e)<=o)){if(e>r)ScrollHelper.hideTopbar(),t.is(":focus")&&t.blur();else if(e+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}r=e}}(),e=!1)},250)}),$(function(){var e="div.post>h1:first-of-type",t=$(e);const n=$("#topbar-title");if(0!==t.length&&!t.hasClass("dynamic-title")&&!n.is(":hidden")){const i=n.text().trim();let r=t.text().trim(),a=!1,l=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(r)&&(r=r.replace(/[0-9]/g,"").trim()),t.offset().top<$(window).scrollTop()&&n.text(r);new IntersectionObserver(e=>{var t,o;a?(o=$(window).scrollTop(),t=l<o,l=o,o=e[0],t?0===o.intersectionRatio&&n.text(r):1===o.intersectionRatio&&n.text(i)):a=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]}).observe(document.querySelector(e)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),$(function(){var e,t="#main > div.row:first-child > div:first-child";$(t+" img").length<=0||(e=document.querySelectorAll(t+" img[data-src]"),lozad(e).observe(),$(t+` p > img[data-src],${t} img[data-src].preview-img`).each(function(){var e=$(this).next(),e="EM"===e.prop("tagName")?e.text():"",t=$(this).attr("data-src");$(this).wrap(`<a href="${t}" title="${e}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(t+" a").has("img").addClass("img-link"))}),$(function(){var e=".code-header>button";const t="timeout",a="data-title-succeed",l="data-original-title";function n(e){if($(e)[0].hasAttribute(t)){e=$(e).attr(t);if(Number(e)>Date.now())return 1}}function i(e){$(e).attr(t,Date.now()+2e3)}function s(e){$(e).removeAttr(t)}var o=new ClipboardJS(e,{target(e){return e.parentNode.nextElementSibling.querySelector("code .rouge-code")}});$(e).tooltip({trigger:"hover",placement:"left"});const r=$(e).children().attr("class");o.on("success",e=>{e.clearSelection();const t=e.trigger;var o;n(t)||(e=t,$(e).children().attr("class","fas fa-check"),e=t,o=$(e).attr(a),$(e).attr(l,o).tooltip("show"),i(t),setTimeout(()=>{var e;e=t,$(e).tooltip("hide").removeAttr(l),e=t,$(e).children().attr("class",r),s(t)},2e3))}),$("#copy-link").click(e=>{let t=$(e.target);if(!n(t)){var e=window.location.href,o=$("<input>");$("body").append(o),o.val(e).select(),document.execCommand("copy"),o.remove();const r=t.attr(l);e=t.attr(a);t.attr(l,e).tooltip("show"),i(t),setTimeout(()=>{t.attr(l,r),s(t)},2e3)}})}),$(function(){const e=$("#topbar-title"),s="scroll-focus";$("a[href*='#']").not("[href='#']").not("[href='#0']").click(function(a){if(this.pathname.replace(/^\//,"")===location.pathname.replace(/^\//,"")&&location.hostname===this.hostname){var l=decodeURI(this.hash);let t=RegExp(/^#fnref:/).test(l),o=!t&&RegExp(/^#fn:/).test(l);var n=l.includes(":")?l.replace(/:/g,"\\:"):l;let r=$(n);var n=e.is(":visible"),i=$(window).width()<$(window).height();if(void 0!==r){a.preventDefault(),history.pushState&&history.pushState(null,null,l);a=$(window).scrollTop();let e=r.offset().top-=8;e<a&&(ScrollHelper.hideTopbar(),ScrollHelper.addScrollUpTask()),n&&i&&(e-=ScrollHelper.getTopbarHeight()),$("html").animate({scrollTop:e},500,()=>{if(r.focus(),$(`[${s}=true]`).length&&$(`[${s}=true]`).attr(s,!1),$(":target").length&&$(":target").attr(s,!1),(o||t)&&r.attr(s,!0),r.is(":focus"))return!1;r.attr("tabindex","-1"),r.focus(),ScrollHelper.hasScrollUpTask()&&ScrollHelper.popScrollUpTask()})}}})}); +$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$(".mode-toggle").click(e=>{e=$(e.target);(e.prop("tagName")==="button".toUpperCase()?e:e.parent()).blur(),flipMode()})});const ScrollHelper=function(){const e=$("body"),t="data-topbar-visible",o=$("#topbar-wrapper").outerHeight();let r=0,a=!1,l=!1;return{hideTopbar:()=>e.attr(t,!1),showTopbar:()=>e.attr(t,!0),addScrollUpTask:()=>{r+=1,a=a||!0},popScrollUpTask:()=>--r,hasScrollUpTask:()=>0<r,topbarLocked:()=>!0===a,unlockTopbar:()=>a=!1,getTopbarHeight:()=>o,orientationLocked:()=>!0===l,lockOrientation:()=>l=!0,unLockOrientation:()=>l=!1}}();$(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),r=$("#main"),a=$("#topbar-title"),l=$("#search-wrapper"),n=$("#search-result-wrapper"),i=$("#search-results"),s=$("#search-input"),c=$("#search-hints"),d=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),a.addClass("unloaded"),t.addClass("unloaded"),l.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),l.removeClass("d-flex"),e.removeClass("unloaded"),a.removeClass("unloaded"),t.removeClass("unloaded")}},u=function(){let e=!1;return{on(){e||(d.block(),n.removeClass("unloaded"),r.addClass("unloaded"),e=!0)},off(){e&&(i.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),r.removeClass("unloaded"),d.release(),s.val(""),e=!1)},isVisible(){return e}}}();function h(){return o.hasClass("loaded")}t.click(function(){p.on(),u.on(),s.focus()}),o.click(function(){p.off(),u.off()}),s.focus(function(){l.addClass("input-focus")}),s.focusout(function(){l.removeClass("input-focus")}),s.on("input",()=>{""===s.val()?h()?c.removeClass("unloaded"):u.off():(u.on(),h()&&c.addClass("unloaded"))})}),$(function(){var e=function(){const e="sidebar-display";let t=!1;const o=$("body");return{toggle(){!1===t?o.attr(e,""):o.removeAttr(e),t=!t}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const t=$("#search-input"),o=ScrollHelper.getTopbarHeight();let e,r=0;function a(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var e=screen.orientation.type;"landscape-primary"!==e&&"landscape-secondary"!==e||a()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&a()}),$(window).scroll(()=>{e=e||!0}),setInterval(()=>{e&&(!function(){var e=$(this).scrollTop();if(!(Math.abs(r-e)<=o)){if(e>r)ScrollHelper.hideTopbar(),t.is(":focus")&&t.blur();else if(e+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}r=e}}(),e=!1)},250)}),$(function(){var e="div.post>h1:first-of-type",t=$(e);const n=$("#topbar-title");if(0!==t.length&&!t.hasClass("dynamic-title")&&!n.is(":hidden")){const i=n.text().trim();let r=t.text().trim(),a=!1,l=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(r)&&(r=r.replace(/[0-9]/g,"").trim()),t.offset().top<$(window).scrollTop()&&n.text(r);new IntersectionObserver(e=>{var t,o;a?(o=$(window).scrollTop(),t=l<o,l=o,o=e[0],t?0===o.intersectionRatio&&n.text(r):1===o.intersectionRatio&&n.text(i)):a=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]}).observe(document.querySelector(e)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),$(function(){var e,t="#main > div.row:first-child > div:first-child";$(t+" img").length<=0||(e=document.querySelectorAll(t+" img[data-src]"),lozad(e).observe(),$(t+` p > img[data-src], ${t} img[data-src].preview-img`).each(function(){var e=$(this).next(),e="EM"===e.prop("tagName")?e.text():"",t=$(this).attr("data-src");$(this).wrap(`<a href="${t}" title="${e}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(t+" a").has("img").addClass("img-link"))}),$(function(){var e=".code-header>button";const t="timeout",a="data-title-succeed",l="data-original-title";function n(e){if($(e)[0].hasAttribute(t)){e=$(e).attr(t);if(Number(e)>Date.now())return 1}}function i(e){$(e).attr(t,Date.now()+2e3)}function s(e){$(e).removeAttr(t)}var o=new ClipboardJS(e,{target(e){return e.parentNode.nextElementSibling.querySelector("code .rouge-code")}});$(e).tooltip({trigger:"hover",placement:"left"});const r=$(e).children().attr("class");o.on("success",e=>{e.clearSelection();const t=e.trigger;var o;n(t)||(e=t,$(e).children().attr("class","fas fa-check"),e=t,o=$(e).attr(a),$(e).attr(l,o).tooltip("show"),i(t),setTimeout(()=>{var e;e=t,$(e).tooltip("hide").removeAttr(l),e=t,$(e).children().attr("class",r),s(t)},2e3))}),$("#copy-link").click(e=>{let t=$(e.target);if(!n(t)){var e=window.location.href,o=$("<input>");$("body").append(o),o.val(e).select(),document.execCommand("copy"),o.remove();const r=t.attr(l);e=t.attr(a);t.attr(l,e).tooltip("show"),i(t),setTimeout(()=>{t.attr(l,r),s(t)},2e3)}})}),$(function(){const e=$("#topbar-title"),s="scroll-focus";$("a[href*='#']").not("[href='#']").not("[href='#0']").click(function(a){if(this.pathname.replace(/^\//,"")===location.pathname.replace(/^\//,"")&&location.hostname===this.hostname){var l=decodeURI(this.hash);let t=RegExp(/^#fnref:/).test(l),o=!t&&RegExp(/^#fn:/).test(l);var n=l.includes(":")?l.replace(/:/g,"\\:"):l;let r=$(n);var n=e.is(":visible"),i=$(window).width()<$(window).height();if(void 0!==r){a.preventDefault(),history.pushState&&history.pushState(null,null,l);a=$(window).scrollTop();let e=r.offset().top-=8;e<a&&(ScrollHelper.hideTopbar(),ScrollHelper.addScrollUpTask()),n&&i&&(e-=ScrollHelper.getTopbarHeight()),$("html").animate({scrollTop:e},500,()=>{if(r.focus(),$(`[${s}=true]`).length&&$(`[${s}=true]`).attr(s,!1),$(":target").length&&$(":target").attr(s,!1),(o||t)&&r.attr(s,!0),r.is(":focus"))return!1;r.attr("tabindex","-1"),r.focus(),ScrollHelper.hasScrollUpTask()&&ScrollHelper.popScrollUpTask()})}}})}); diff --git a/assets/js/dist/post.min.js b/assets/js/dist/post.min.js index 49529ec..235ea13 100644 --- a/assets/js/dist/post.min.js +++ b/assets/js/dist/post.min.js @@ -3,4 +3,4 @@ * © 2019 Cotes Chung * MIT Licensed */ -$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$(".mode-toggle").click(t=>{t=$(t.target);(t.prop("tagName")==="button".toUpperCase()?t:t.parent()).blur(),flipMode()})});const ScrollHelper=function(){const t=$("body"),e="data-topbar-visible",o=$("#topbar-wrapper").outerHeight();let a=0,r=!1,l=!1;return{hideTopbar:()=>t.attr(e,!1),showTopbar:()=>t.attr(e,!0),addScrollUpTask:()=>{a+=1,r=r||!0},popScrollUpTask:()=>--a,hasScrollUpTask:()=>0<a,topbarLocked:()=>!0===r,unlockTopbar:()=>r=!1,getTopbarHeight:()=>o,orientationLocked:()=>!0===l,lockOrientation:()=>l=!0,unLockOrientation:()=>l=!1}}(),LocaleHelper=($(function(){const t=$("#sidebar-trigger"),e=$("#search-trigger"),o=$("#search-cancel"),a=$("#main"),r=$("#topbar-title"),l=$("#search-wrapper"),n=$("#search-result-wrapper"),i=$("#search-results"),s=$("#search-input"),c=$("#search-hints"),d=function(){let t=0;return{block(){t=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(t)},getOffset(){return t}}}(),p={on(){t.addClass("unloaded"),r.addClass("unloaded"),e.addClass("unloaded"),l.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),l.removeClass("d-flex"),t.removeClass("unloaded"),r.removeClass("unloaded"),e.removeClass("unloaded")}},u=function(){let t=!1;return{on(){t||(d.block(),n.removeClass("unloaded"),a.addClass("unloaded"),t=!0)},off(){t&&(i.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),a.removeClass("unloaded"),d.release(),s.val(""),t=!1)},isVisible(){return t}}}();function h(){return o.hasClass("loaded")}e.click(function(){p.on(),u.on(),s.focus()}),o.click(function(){p.off(),u.off()}),s.focus(function(){l.addClass("input-focus")}),s.focusout(function(){l.removeClass("input-focus")}),s.on("input",()=>{""===s.val()?h()?c.removeClass("unloaded"):u.off():(u.on(),h()&&c.addClass("unloaded"))})}),$(function(){var t=function(){const t="sidebar-display";let e=!1;const o=$("body");return{toggle(){!1===e?o.attr(t,""):o.removeAttr(t),e=!e}}}();$("#sidebar-trigger").click(t.toggle),$("#mask").click(t.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#search-input"),o=ScrollHelper.getTopbarHeight();let t,a=0;function r(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var t=screen.orientation.type;"landscape-primary"!==t&&"landscape-secondary"!==t||r()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&r()}),$(window).scroll(()=>{t=t||!0}),setInterval(()=>{t&&(!function(){var t=$(this).scrollTop();if(!(Math.abs(a-t)<=o)){if(t>a)ScrollHelper.hideTopbar(),e.is(":focus")&&e.blur();else if(t+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}a=t}}(),t=!1)},250)}),$(function(){var t="div.post>h1:first-of-type",e=$(t);const n=$("#topbar-title");if(0!==e.length&&!e.hasClass("dynamic-title")&&!n.is(":hidden")){const i=n.text().trim();let a=e.text().trim(),r=!1,l=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),e.offset().top<$(window).scrollTop()&&n.text(a);new IntersectionObserver(t=>{var e,o;r?(o=$(window).scrollTop(),e=l<o,l=o,o=t[0],e?0===o.intersectionRatio&&n.text(a):1===o.intersectionRatio&&n.text(i)):r=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]}).observe(document.querySelector(t)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),$(function(){var t,e="#main > div.row:first-child > div:first-child";$(e+" img").length<=0||(t=document.querySelectorAll(e+" img[data-src]"),lozad(t).observe(),$(e+` p > img[data-src],${e} img[data-src].preview-img`).each(function(){var t=$(this).next(),t="EM"===t.prop("tagName")?t.text():"",e=$(this).attr("data-src");$(this).wrap(`<a href="${e}" title="${t}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(e+" a").has("img").addClass("img-link"))}),function(){const t=$("html").attr("lang").substr(0,2),e="data-ts",o="data-df";return{locale:()=>t,attrTimestamp:()=>e,attrDateFormat:()=>o,getTimestamp:t=>Number(t.attr(e)),getDateFormat:t=>t.attr(o)}}());$(function(){dayjs.locale(LocaleHelper.locale()),dayjs.extend(window.dayjs_plugin_localizedFormat),$(`[${LocaleHelper.attrTimestamp()}]`).each(function(){var t=dayjs.unix(LocaleHelper.getTimestamp($(this))),e=t.format(LocaleHelper.getDateFormat($(this))),e=($(this).text(e),$(this).removeAttr(LocaleHelper.attrTimestamp()),$(this).removeAttr(LocaleHelper.attrDateFormat()),$(this).attr("data-toggle"));void 0!==e&&"tooltip"===e&&(e=t.format("llll"),$(this).attr("data-original-title",e))})}),$(function(){var t=".code-header>button";const e="timeout",r="data-title-succeed",l="data-original-title";function n(t){if($(t)[0].hasAttribute(e)){t=$(t).attr(e);if(Number(t)>Date.now())return 1}}function i(t){$(t).attr(e,Date.now()+2e3)}function s(t){$(t).removeAttr(e)}var o=new ClipboardJS(t,{target(t){return t.parentNode.nextElementSibling.querySelector("code .rouge-code")}});$(t).tooltip({trigger:"hover",placement:"left"});const a=$(t).children().attr("class");o.on("success",t=>{t.clearSelection();const e=t.trigger;var o;n(e)||(t=e,$(t).children().attr("class","fas fa-check"),t=e,o=$(t).attr(r),$(t).attr(l,o).tooltip("show"),i(e),setTimeout(()=>{var t;t=e,$(t).tooltip("hide").removeAttr(l),t=e,$(t).children().attr("class",a),s(e)},2e3))}),$("#copy-link").click(t=>{let e=$(t.target);if(!n(e)){var t=window.location.href,o=$("<input>");$("body").append(o),o.val(t).select(),document.execCommand("copy"),o.remove();const a=e.attr(l);t=e.attr(r);e.attr(l,t).tooltip("show"),i(e),setTimeout(()=>{e.attr(l,a),s(e)},2e3)}})}),$(function(){const t=$("#topbar-title"),s="scroll-focus";$("a[href*='#']").not("[href='#']").not("[href='#0']").click(function(r){if(this.pathname.replace(/^\//,"")===location.pathname.replace(/^\//,"")&&location.hostname===this.hostname){var l=decodeURI(this.hash);let e=RegExp(/^#fnref:/).test(l),o=!e&&RegExp(/^#fn:/).test(l);var n=l.includes(":")?l.replace(/:/g,"\\:"):l;let a=$(n);var n=t.is(":visible"),i=$(window).width()<$(window).height();if(void 0!==a){r.preventDefault(),history.pushState&&history.pushState(null,null,l);r=$(window).scrollTop();let t=a.offset().top-=8;t<r&&(ScrollHelper.hideTopbar(),ScrollHelper.addScrollUpTask()),n&&i&&(t-=ScrollHelper.getTopbarHeight()),$("html").animate({scrollTop:t},500,()=>{if(a.focus(),$(`[${s}=true]`).length&&$(`[${s}=true]`).attr(s,!1),$(":target").length&&$(":target").attr(s,!1),(o||e)&&a.attr(s,!0),a.is(":focus"))return!1;a.attr("tabindex","-1"),a.focus(),ScrollHelper.hasScrollUpTask()&&ScrollHelper.popScrollUpTask()})}}})}); +$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$(".mode-toggle").click(t=>{t=$(t.target);(t.prop("tagName")==="button".toUpperCase()?t:t.parent()).blur(),flipMode()})});const ScrollHelper=function(){const t=$("body"),e="data-topbar-visible",o=$("#topbar-wrapper").outerHeight();let a=0,r=!1,l=!1;return{hideTopbar:()=>t.attr(e,!1),showTopbar:()=>t.attr(e,!0),addScrollUpTask:()=>{a+=1,r=r||!0},popScrollUpTask:()=>--a,hasScrollUpTask:()=>0<a,topbarLocked:()=>!0===r,unlockTopbar:()=>r=!1,getTopbarHeight:()=>o,orientationLocked:()=>!0===l,lockOrientation:()=>l=!0,unLockOrientation:()=>l=!1}}(),LocaleHelper=($(function(){const t=$("#sidebar-trigger"),e=$("#search-trigger"),o=$("#search-cancel"),a=$("#main"),r=$("#topbar-title"),l=$("#search-wrapper"),n=$("#search-result-wrapper"),i=$("#search-results"),s=$("#search-input"),c=$("#search-hints"),d=function(){let t=0;return{block(){t=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(t)},getOffset(){return t}}}(),p={on(){t.addClass("unloaded"),r.addClass("unloaded"),e.addClass("unloaded"),l.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),l.removeClass("d-flex"),t.removeClass("unloaded"),r.removeClass("unloaded"),e.removeClass("unloaded")}},u=function(){let t=!1;return{on(){t||(d.block(),n.removeClass("unloaded"),a.addClass("unloaded"),t=!0)},off(){t&&(i.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),a.removeClass("unloaded"),d.release(),s.val(""),t=!1)},isVisible(){return t}}}();function h(){return o.hasClass("loaded")}e.click(function(){p.on(),u.on(),s.focus()}),o.click(function(){p.off(),u.off()}),s.focus(function(){l.addClass("input-focus")}),s.focusout(function(){l.removeClass("input-focus")}),s.on("input",()=>{""===s.val()?h()?c.removeClass("unloaded"):u.off():(u.on(),h()&&c.addClass("unloaded"))})}),$(function(){var t=function(){const t="sidebar-display";let e=!1;const o=$("body");return{toggle(){!1===e?o.attr(t,""):o.removeAttr(t),e=!e}}}();$("#sidebar-trigger").click(t.toggle),$("#mask").click(t.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#search-input"),o=ScrollHelper.getTopbarHeight();let t,a=0;function r(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var t=screen.orientation.type;"landscape-primary"!==t&&"landscape-secondary"!==t||r()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&r()}),$(window).scroll(()=>{t=t||!0}),setInterval(()=>{t&&(!function(){var t=$(this).scrollTop();if(!(Math.abs(a-t)<=o)){if(t>a)ScrollHelper.hideTopbar(),e.is(":focus")&&e.blur();else if(t+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}a=t}}(),t=!1)},250)}),$(function(){var t="div.post>h1:first-of-type",e=$(t);const n=$("#topbar-title");if(0!==e.length&&!e.hasClass("dynamic-title")&&!n.is(":hidden")){const i=n.text().trim();let a=e.text().trim(),r=!1,l=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),e.offset().top<$(window).scrollTop()&&n.text(a);new IntersectionObserver(t=>{var e,o;r?(o=$(window).scrollTop(),e=l<o,l=o,o=t[0],e?0===o.intersectionRatio&&n.text(a):1===o.intersectionRatio&&n.text(i)):r=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]}).observe(document.querySelector(t)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),$(function(){var t,e="#main > div.row:first-child > div:first-child";$(e+" img").length<=0||(t=document.querySelectorAll(e+" img[data-src]"),lozad(t).observe(),$(e+` p > img[data-src], ${e} img[data-src].preview-img`).each(function(){var t=$(this).next(),t="EM"===t.prop("tagName")?t.text():"",e=$(this).attr("data-src");$(this).wrap(`<a href="${e}" title="${t}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(e+" a").has("img").addClass("img-link"))}),function(){const t=$("html").attr("lang").substr(0,2),e="data-ts",o="data-df";return{locale:()=>t,attrTimestamp:()=>e,attrDateFormat:()=>o,getTimestamp:t=>Number(t.attr(e)),getDateFormat:t=>t.attr(o)}}());$(function(){dayjs.locale(LocaleHelper.locale()),dayjs.extend(window.dayjs_plugin_localizedFormat),$(`[${LocaleHelper.attrTimestamp()}]`).each(function(){var t=dayjs.unix(LocaleHelper.getTimestamp($(this))),e=t.format(LocaleHelper.getDateFormat($(this))),e=($(this).text(e),$(this).removeAttr(LocaleHelper.attrTimestamp()),$(this).removeAttr(LocaleHelper.attrDateFormat()),$(this).attr("data-toggle"));void 0!==e&&"tooltip"===e&&(e=t.format("llll"),$(this).attr("data-original-title",e))})}),$(function(){var t=".code-header>button";const e="timeout",r="data-title-succeed",l="data-original-title";function n(t){if($(t)[0].hasAttribute(e)){t=$(t).attr(e);if(Number(t)>Date.now())return 1}}function i(t){$(t).attr(e,Date.now()+2e3)}function s(t){$(t).removeAttr(e)}var o=new ClipboardJS(t,{target(t){return t.parentNode.nextElementSibling.querySelector("code .rouge-code")}});$(t).tooltip({trigger:"hover",placement:"left"});const a=$(t).children().attr("class");o.on("success",t=>{t.clearSelection();const e=t.trigger;var o;n(e)||(t=e,$(t).children().attr("class","fas fa-check"),t=e,o=$(t).attr(r),$(t).attr(l,o).tooltip("show"),i(e),setTimeout(()=>{var t;t=e,$(t).tooltip("hide").removeAttr(l),t=e,$(t).children().attr("class",a),s(e)},2e3))}),$("#copy-link").click(t=>{let e=$(t.target);if(!n(e)){var t=window.location.href,o=$("<input>");$("body").append(o),o.val(t).select(),document.execCommand("copy"),o.remove();const a=e.attr(l);t=e.attr(r);e.attr(l,t).tooltip("show"),i(e),setTimeout(()=>{e.attr(l,a),s(e)},2e3)}})}),$(function(){const t=$("#topbar-title"),s="scroll-focus";$("a[href*='#']").not("[href='#']").not("[href='#0']").click(function(r){if(this.pathname.replace(/^\//,"")===location.pathname.replace(/^\//,"")&&location.hostname===this.hostname){var l=decodeURI(this.hash);let e=RegExp(/^#fnref:/).test(l),o=!e&&RegExp(/^#fn:/).test(l);var n=l.includes(":")?l.replace(/:/g,"\\:"):l;let a=$(n);var n=t.is(":visible"),i=$(window).width()<$(window).height();if(void 0!==a){r.preventDefault(),history.pushState&&history.pushState(null,null,l);r=$(window).scrollTop();let t=a.offset().top-=8;t<r&&(ScrollHelper.hideTopbar(),ScrollHelper.addScrollUpTask()),n&&i&&(t-=ScrollHelper.getTopbarHeight()),$("html").animate({scrollTop:t},500,()=>{if(a.focus(),$(`[${s}=true]`).length&&$(`[${s}=true]`).attr(s,!1),$(":target").length&&$(":target").attr(s,!1),(o||e)&&a.attr(s,!0),a.is(":focus"))return!1;a.attr("tabindex","-1"),a.focus(),ScrollHelper.hasScrollUpTask()&&ScrollHelper.popScrollUpTask()})}}})}); diff --git a/assets/js/pwa/app.js b/assets/js/pwa/app.js index ab4b174..c798fe2 100644 --- a/assets/js/pwa/app.js +++ b/assets/js/pwa/app.js @@ -7,41 +7,41 @@ const $notification = $('#notification'); const $btnRefresh = $('#notification .toast-body>button'); if ('serviceWorker' in navigator) { - /* Registering Service Worker */ - navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}') - .then(registration => { + /* Registering Service Worker */ + navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}') + .then(registration => { - /* in case the user ignores the notification */ - if (registration.waiting) { - $notification.toast('show'); - } - - registration.addEventListener('updatefound', () => { - registration.installing.addEventListener('statechange', () => { - if (registration.waiting) { - if (navigator.serviceWorker.controller) { - $notification.toast('show'); + /* in case the user ignores the notification */ + if (registration.waiting) { + $notification.toast('show'); } - } + + registration.addEventListener('updatefound', () => { + registration.installing.addEventListener('statechange', () => { + if (registration.waiting) { + if (navigator.serviceWorker.controller) { + $notification.toast('show'); + } + } + }); + }); + + $btnRefresh.click(() => { + if (registration.waiting) { + registration.waiting.postMessage('SKIP_WAITING'); + } + $notification.toast('hide'); + }); }); - }); - $btnRefresh.click(() => { - if (registration.waiting) { - registration.waiting.postMessage('SKIP_WAITING'); + let refreshing = false; + + /* Detect controller change and refresh all the opened tabs */ + navigator.serviceWorker.addEventListener('controllerchange', () => { + if (!refreshing) { + window.location.reload(); + refreshing = true; } - $notification.toast('hide'); - }); - } - ); - - let refreshing = false; - - /* Detect controller change and refresh all the opened tabs */ - navigator.serviceWorker.addEventListener('controllerchange', () => { - if (!refreshing) { - window.location.reload(); - refreshing = true; - } - }); + }); } + diff --git a/assets/js/pwa/sw.js b/assets/js/pwa/sw.js index 7492ac3..3213b4f 100644 --- a/assets/js/pwa/sw.js +++ b/assets/js/pwa/sw.js @@ -9,81 +9,82 @@ self.importScripts('{{ "/assets/js/data/swcache.js" | relative_url }}'); const cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M%S" }}'; function verifyDomain(url) { - for (const domain of allowedDomains) { - const regex = RegExp(`^http(s)?:\/\/${domain}\/`); - if (regex.test(url)) { - return true; + for (const domain of allowedDomains) { + const regex = RegExp(`^http(s)?:\/\/${domain}\/`); + if (regex.test(url)) { + return true; + } } - } - return false; + return false; } function isExcluded(url) { - for (const item of denyUrls) { - if (url === item) { - return true; + for (const item of denyUrls) { + if (url === item) { + return true; + } } - } - return false; + return false; } self.addEventListener('install', event => { - event.waitUntil( - caches.open(cacheName).then(cache => { - return cache.addAll(resource); - }) - ); + event.waitUntil( + caches.open(cacheName).then(cache => { + return cache.addAll(resource); + }) + ); }); self.addEventListener('activate', event => { - event.waitUntil( - caches.keys().then(keyList => { - return Promise.all( - keyList.map(key => { - if (key !== cacheName) { - return caches.delete(key); - } + event.waitUntil( + caches.keys().then(keyList => { + return Promise.all( + keyList.map(key => { + if (key !== cacheName) { + return caches.delete(key); + } + }) + ); }) - ); - }) - ); + ); }); self.addEventListener('message', (event) => { - if (event.data === 'SKIP_WAITING') { - self.skipWaiting(); - } + if (event.data === 'SKIP_WAITING') { + self.skipWaiting(); + } }); self.addEventListener('fetch', event => { - event.respondWith( - caches.match(event.request).then(response => { - if (response) { - return response; - } + event.respondWith( + caches.match(event.request).then(response => { + if (response) { + return response; + } - return fetch(event.request).then(response => { - const url = event.request.url; + return fetch(event.request).then(response => { + const url = event.request.url; - if (event.request.method !== 'GET' || - !verifyDomain(url) || - isExcluded(url)) { - return response; - } + if (event.request.method !== 'GET' || + !verifyDomain(url) || + isExcluded(url)) { + return response; + } - /* - see: <https://developers.google.com/web/fundamentals/primers/service-workers#cache_and_return_requests> - */ - let responseToCache = response.clone(); + /* + see: <https://developers.google.com/web/fundamentals/primers/service-workers#cache_and_return_requests> + */ + let responseToCache = response.clone(); - caches.open(cacheName).then(cache => { - /* console.log('[sw] Caching new resource: ' + event.request.url); */ - cache.put(event.request, responseToCache); - }); + caches.open(cacheName).then(cache => { + /* console.log('[sw] Caching new resource: ' + event.request.url); */ + cache.put(event.request, responseToCache); + }); - return response; - }); - }) - ); + return response; + }); + }) + ); }); + diff --git a/assets/js/pwa/unregister.js b/assets/js/pwa/unregister.js index da8cbb8..bd91150 100644 --- a/assets/js/pwa/unregister.js +++ b/assets/js/pwa/unregister.js @@ -4,9 +4,9 @@ permalink: '/unregister.js' --- if ('serviceWorker' in navigator) { - navigator.serviceWorker.getRegistrations().then((registrations) => { - for (let reg of registrations) { - reg.unregister(); - } - }); + navigator.serviceWorker.getRegistrations().then((registrations) => { + for (let reg of registrations) { + reg.unregister(); + } + }); }