/** * Zepto扩展 */ $.fn.scrollTo = function(options) { const defaults = { toT : 0, //滚动目标位置 durTime : 500, //过渡动画时间 delay : 30, //定时器时间 callback:null //回调函数 }; let opts = $.extend(defaults,options), timer = null, _this = this, curTop = _this.scrollTop(),//滚动条当前的位置 subTop = opts.toT - curTop, //滚动条目标位置和当前位置的差值 index = 0, dur = Math.round(opts.durTime / opts.delay), smoothScroll = function(t){ index++; let per = Math.round(subTop/dur); if(index >= dur) { _this.scrollTop(t); window.clearInterval(timer); if(opts.callback && typeof opts.callback == 'function'){ opts.callback(); } return; } else { _this.scrollTop(curTop + index*per); } }; timer = window.setInterval(function(){ smoothScroll(opts.toT); }, opts.delay); return _this; }; /** * Local Search * @author https://github.com/theme-next/hexo-theme-next */ const LocalSearch = { searchPath: '', trigger: 'auto', topN: '1', unescape: false, isfetched: false, isXml: true, initParams (data) { LocalSearch.searchPath = data.dbPath; LocalSearch.trigger = data.trigger; LocalSearch.topN = data.topN; LocalSearch.unescape = data.unescape === 'false' ? false : true; if (LocalSearch.searchPath.length === 0) { LocalSearch.searchPath = "/search.xml"; } else if (/json$/i.test(LocalSearch.searchPath)) { LocalSearch.isXml = false; } }, onPopupClose () { $('.popup').hide(); $('#local-search-input').val(''); $('.search-result-list').remove(); $('#no-result').remove(); $(".local-search-pop-overlay").remove(); $('body').css('overflow', ''); }, proceedsearch () { $("body").append('
').css('overflow', 'hidden'); $('.search-popup-overlay').click(LocalSearch.onPopupClose); $('.popup').toggle(); const $localSearchInput = $('#local-search-input'); $localSearchInput.attr("autocapitalize", "none"); $localSearchInput.attr("autocorrect", "off"); $localSearchInput.focus(); }, // search function; searchFunc (search_id, content_id) { // if loading exists then return. if (!$('.search-popup-overlay').is(':visible')) { // start loading animation $("body").append('
' + '
' + '' + '
' + '
').css('overflow', 'hidden'); $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center'); } else { alert("Fetching data...don't worry") } const input = document.getElementById(search_id); const resultContent = document.getElementById(content_id); if (!input || !resultContent) { console.error('Elements not exists with searchId: '+search_id+', resultContentId: '+content_id); return; } if (LocalSearch.unescape) { // ref: https://github.com/ForbesLindesay/unescape-html var unescapeHtml = function(html) { return String(html) .replace(/"/g, '"') .replace(/'/g, '\'') .replace(/:/g, ':') // replace all the other &#x; chars .replace(/&#(\d+);/g, function (m, p) { return String.fromCharCode(p); }) .replace(/</g, '<') .replace(/>/g, '>') .replace(/&/g, '&'); }; } $.ajax({ url: LocalSearch.searchPath, timeout: 5000, dataType: LocalSearch.isXml ? "xml" : "json", async: true, success (res) { // get the contents from search data LocalSearch.isfetched = true; $('.popup').detach().appendTo('body'); const datas = LocalSearch.isXml ? $("entry", res).map(function () { return { title: $("title", this).text(), content: $("content", this).text(), url: $("url", this).text() }; }).get() : res; const inputEventFunction = function () { const searchText = input.value.trim().toLowerCase(); const keywords = searchText.split(/[\s\-]+/); if (keywords.length > 1) { keywords.push(searchText); } const resultItems = []; if (searchText.length > 0 && Array.isArray(datas)) { for (const data of datas) { if (!data || !data.content) continue; let isMatch = false; let hitCount = 0; let searchTextCount = 0; const title = data.title.trim(); const titleInLowerCase = title.toLowerCase(); let content = data.content.trim().replace(/<[^>]+>/g, ""); if (LocalSearch.unescape && content) { content = unescapeHtml(content); } const contentInLowerCase = content.toLowerCase(); const articleUrl = decodeURIComponent(data.url).replace(/\/{2,}/g, '/'); let indexOfTitle = []; let indexOfContent = []; // only match articles with not empty titles if (title != '') { keywords.forEach(function (keyword) { function getIndexByWord(word, text, caseSensitive) { const wordLen = word.length; if (wordLen === 0) { return []; } let startPosition = 0, position = [], index = []; if (!caseSensitive) { text = text.toLowerCase(); word = word.toLowerCase(); } while ((position = text.indexOf(word, startPosition)) > -1) { index.push({position: position, word: word}); startPosition = position + wordLen; } return index; } indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false)); indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false)); }); if (indexOfTitle.length > 0 || indexOfContent.length > 0) { isMatch = true; hitCount = indexOfTitle.length + indexOfContent.length; } } // show search results if (isMatch) { // sort index by position of keyword [indexOfTitle, indexOfContent].forEach(function (index) { index.sort(function (itemLeft, itemRight) { if (itemRight.position !== itemLeft.position) { return itemRight.position - itemLeft.position; } else { return itemLeft.word.length - itemRight.word.length; } }); }); // merge hits into slices function mergeIntoSlice(text, start, end, index) { let item = index[index.length - 1]; let position = item.position; let word = item.word; let hits = []; let searchTextCountInSlice = 0; while (position + word.length <= end && index.length != 0) { if (word === searchText) { searchTextCountInSlice++; } hits.push({position: position, length: word.length}); const wordEnd = position + word.length; // move to next position of hit index.pop(); while (index.length != 0) { item = index[index.length - 1]; position = item.position; word = item.word; if (wordEnd > position) { index.pop(); } else { break; } } } searchTextCount += searchTextCountInSlice; return { hits: hits, start: start, end: end, searchTextCount: searchTextCountInSlice }; } const slicesOfTitle = []; if (indexOfTitle.length != 0) { slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle)); } let slicesOfContent = []; while (indexOfContent.length != 0) { const item = indexOfContent[indexOfContent.length - 1]; const position = item.position; const word = item.word; // cut out 100 characters let start = position - 20; let end = position + 80; if (start < 0) { start = 0; } if (end < position + word.length) { end = position + word.length; } if (end > content.length) { end = content.length; } slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent)); } // sort slices in content by search text's count and hits' count slicesOfContent.sort(function (sliceLeft, sliceRight) { if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) { return sliceRight.searchTextCount - sliceLeft.searchTextCount; } else if (sliceLeft.hits.length !== sliceRight.hits.length) { return sliceRight.hits.length - sliceLeft.hits.length; } else { return sliceLeft.start - sliceRight.start; } }); // select top N slices in content const upperBound = parseInt(LocalSearch.topN); if (upperBound >= 0) { slicesOfContent = slicesOfContent.slice(0, upperBound); } // highlight title and content function highlightKeyword(text, slice) { let result = ''; let prevEnd = slice.start; slice.hits.forEach(function (hit) { result += text.substring(prevEnd, hit.position); const end = hit.position + hit.length; result += '' + text.substring(hit.position, end) + ''; prevEnd = end; }); result += text.substring(prevEnd, slice.end); return result; } let resultItem = ''; if (slicesOfTitle.length != 0) { resultItem += "
  • " + highlightKeyword(title, slicesOfTitle[0]) + ""; } else { resultItem += "
  • " + title + ""; } slicesOfContent.forEach(function (slice) { resultItem += "" + "

    " + highlightKeyword(content, slice) + "...

    " + "
    "; }); resultItem += "
  • "; resultItems.push({ item: resultItem, searchTextCount: searchTextCount, hitCount: hitCount, id: resultItems.length }); } } } if (keywords.length === 1 && keywords[0] === "") { resultContent.innerHTML = `

    按Esc退出搜索...

    ` } else if (resultItems.length === 0) { resultContent.innerHTML = `

    暂未查到有关内容,催更点这里

    ` } else { resultItems.sort(function (resultLeft, resultRight) { if (resultLeft.searchTextCount !== resultRight.searchTextCount) { return resultRight.searchTextCount - resultLeft.searchTextCount; } else if (resultLeft.hitCount !== resultRight.hitCount) { return resultRight.hitCount - resultLeft.hitCount; } else { return resultRight.id - resultLeft.id; } }); let searchResultList = '"; resultContent.innerHTML = searchResultList; } }; if ('auto' === LocalSearch.trigger) { input.addEventListener('input', inputEventFunction); } else { $('.search-icon').click(inputEventFunction); input.addEventListener('keypress', function (event) { if (event.keyCode === 13) { inputEventFunction(); } }); } // remove loading animation $(".local-search-pop-overlay").remove(); $('body').css('overflow', ''); LocalSearch.proceedsearch(); }, error (xhr,status,error) { alert(status+', Load error when get '+ LocalSearch.searchPath); console.error(error); window.location.reload(true); } }); }, doSearch (e) { e && e.stopPropagation(); if (!LocalSearch.isfetched) { LocalSearch.searchFunc('local-search-input', 'local-search-result'); } else { LocalSearch.proceedsearch(); } } }; /** * JSimple Theme CoreLib * @author tangkunyin 2017/1/25. */ const SimpleCore = { creationTime: new Date(), highlightTheme: null, isPost: 'false', prevTop: 0, headerShow: true, localSearch: {}, readMode: 'day', chatLink: '/', initParams (params) { SimpleCore.creationTime = params.creationTime; SimpleCore.highlightTheme = params.highlightTheme; SimpleCore.isPost = params.isPost; SimpleCore.localSearch = params.localSearch; SimpleCore.readMode = params.readMode; SimpleCore.chatLink = params.chatLink; }, init (params) { SimpleCore.initParams(params); LocalSearch.initParams(SimpleCore.localSearch); $(window).resize(function () { SimpleCore.syncSize(); }); $(window).scroll(function (e) { SimpleCore.scrollCallback(); }); $(document).on('click', '.btn-read-mode', function (e) { e.preventDefault(); SimpleCore.switchReadMode(); }); $(document).on('click', '.btn-search', function (e) { e.preventDefault(); SimpleCore.switchSearch(); }); $(document).on('click', '#local-search-input-tip', function (e) { LocalSearch.doSearch(e); }); $(document).on('click', '.popup-btn-close', function (e) { e.preventDefault(); LocalSearch.onPopupClose(); }); $(document).on('click', '.popup', function (e) { e.stopPropagation(); }); $(document).on('click', '.btn-gotop', function (e) { e.preventDefault(); SimpleCore.goTop(); }); SimpleCore.changeReadModel(); SimpleCore.setPageCurrent(); SimpleCore.setBuildingTime(); SimpleCore.syncSize(); SimpleCore.printGreeting(); SimpleCore.registerHotKeyEvent(); SimpleCore.setDefaultReadingMode(); }, goTop () { $("html, body").scrollTo({toT: 0}); }, setPageCurrent () { if (SimpleCore.isPost === 'true') { $('#cover').hide(); $('body').addClass('single'); } else { $('#cover').show(); $('body').removeClass('single'); } $.each($('.nav-menu a'), function (k, v) { if (v.href === window.location.href || v.href === window.location.href.replace(/\/$/, '')) { $(v).addClass('current'); } else { $(v).removeClass('current'); } }); }, scrollCallback () { const top = document.documentElement.scrollTop || document.body.scrollTop || 0; if (top > 100) { $('.fixed-btn').show(); } else { $('.fixed-btn').hide(); } if ($('body').hasClass('single')) { SimpleCore.headerShow = (top < 100 || (SimpleCore.prevTop - top) > 0) ? true : false; SimpleCore.headerToggle(); } SimpleCore.prevTop = top; }, headerToggle () { if (SimpleCore.headerShow) { $('.page-title').css("top", 0); $('.nav-user').css("top", 0); if ($(window).width() < 480) { $('#nav').css("top", 0); } } else { $('.page-title').css("top", -45); $('.nav-user').css("top", -45); if ($(window).width() < 480) { $('#nav').css("top", -45); } } }, syncSize () { //同步窗口大小 const pageTitle = $('.page-title'); const size = $(window).width(); if (size > 768 && SimpleCore.isPost !== 'true') { pageTitle.width($('#body > .main').width()); } else { pageTitle.removeAttr('style'); } if (size < 768) { $('.site-name').click(function (e) { e.preventDefault(); }); } }, switchSearch () { const srh = $('#search'); if (srh.hasClass('active')) { srh.removeClass('active'); } else { srh.addClass('active'); } }, switchReadMode (mode) { let next_mode = $('body').hasClass('night-mode') ? 'day' : 'night'; if (typeof mode === 'string' && mode.length > 0) { next_mode = mode; } SimpleCore.setLocalData('read-mode', next_mode); SimpleCore.changeReadModel(); }, changeReadModel () { const btn = $('.btn-read-mode'); if (SimpleCore.getLocalData('read-mode') == 'night') { $('body').addClass('night-mode'); btn.find('i').attr('class', 'fa fa-moon-o'); $(".cover-img").attr('src', location.origin + '/images/cover-night.webp'); } else { $('body').removeClass('night-mode'); btn.find('i').attr('class', 'fa fa-sun-o'); $(".cover-img").attr('src', location.origin + '/images/cover-day.webp'); } // 设置高亮主题 let highlCss = SimpleCore.highlightTheme || 'default'; if (highlCss !== 'default') { highlCss += SimpleCore.getLocalData('read-mode') == 'night' ? '-dark' : '-light'; } $('#highl_css').load(`/css/${highlCss}.min.css`); }, alert (title,msg) { const notice = $('#notice'); if (notice.length > 0) { return false; } $('
    ').appendTo($('body')); const item = 'notice-' + (new Date().getTime()); const html = '
    ' + '' + '

    '+title+'

    ' + msg + '

    '; $(html).appendTo($('#notice')).on('click', '.notice-item-close', function () { $('#notice').remove(); return false; }); //居中显示,于x秒后自动关闭 $('#notice').css('margin-right', -$('#notice').width() / 2); setTimeout(function () { $('#notice').remove(); }, 10000); }, setLocalData (key, value) { if (window.localStorage) { window.localStorage.setItem(key, value); } }, getLocalData (key) { if (window.localStorage) { return window.localStorage.getItem(key); } }, setBuildingTime () { const urodz = new Date(SimpleCore.creationTime); //建站时间 const now = new Date(); const ile = now.getTime() - urodz.getTime(); const buildingDays = Math.floor(ile / (1000 * 60 * 60 * 24)); $('#cpYear').html(now.getFullYear()); $('#siteBuildingTime').html(buildingDays); return buildingDays; }, printGreeting () { const asciiTxt = " _ _ _ _ _ _ _ _ \n" + "( ) ( ) (_ ) (_ ) ( ) _ ( ) (_ ) ( )\n" + "| |_| | __ | | | | _ | | ( ) | | _ _ __ | | _| |\n" + "| _ | /'__`\\ | | | | /'_`\\ | | | | | | /'_`\\ ( '__)| | /'_` |\n" + "| | | |( ___/ | | | | ( (_) ) | (_/ \\_) |( (_) )| | | | ( (_| |\n" + "(_) (_)`\\____)(___)(___)`\\___/' `\\___x___/'`\\___/'(_) (___)`\\__,_)\n" + "\n已稳定运行" + this.setBuildingTime() + "天,拦截了无数次逗比攻击!🎉🎉🎉\n "; console.log("%c\n"+asciiTxt, "color: #527fe2; font-family:KaiTi;font-size: 16px"); }, registerHotKeyEvent(e) { $(document).on('keyup', function(event) { const shouldDismissSearchPopup = event.key === 'Escape' && $('.search-popup').css('display') === 'block'; if (shouldDismissSearchPopup) { $('.search-popup').hide(); $('.search-popup-overlay').remove(); $('body').css('overflow', ''); } const shouldShowSearchPopup = event.key === 'Shift' && $('.search-popup').css('display') === 'none'; if (shouldShowSearchPopup) { LocalSearch.doSearch(e); } }); }, setDefaultReadingMode() { if (!SimpleCore.getLocalData('read-mode') && ('day' === SimpleCore.readMode || 'night' === SimpleCore.readMode)) { SimpleCore.switchReadMode(SimpleCore.readMode); } } }; $(function () { window.jsi_config ? SimpleCore.init(window.jsi_config) : console.error('JSimple get wrong config: ', window.jsi_config) });