1/* global Fluid */ 2 3HTMLElement.prototype.wrap = function(wrapper) { 4 this.parentNode.insertBefore(wrapper, this); 5 this.parentNode.removeChild(this); 6 wrapper.appendChild(this); 7}; 8 9Fluid.events = { 10 11 registerNavbarEvent: function() { 12 var navbar = jQuery('#navbar'); 13 if (navbar.length === 0) { 14 return; 15 } 16 var submenu = jQuery('#navbar .dropdown-menu'); 17 if (navbar.offset().top > 0) { 18 navbar.removeClass('navbar-dark'); 19 submenu.removeClass('navbar-dark'); 20 } 21 Fluid.utils.listenScroll(function() { 22 navbar[navbar.offset().top > 50 ? 'addClass' : 'removeClass']('top-nav-collapse'); 23 submenu[navbar.offset().top > 50 ? 'addClass' : 'removeClass']('dropdown-collapse'); 24 if (navbar.offset().top > 0) { 25 navbar.removeClass('navbar-dark'); 26 submenu.removeClass('navbar-dark'); 27 } else { 28 navbar.addClass('navbar-dark'); 29 submenu.removeClass('navbar-dark'); 30 } 31 }); 32 33 var mobileGridMenu = jQuery('#mobile-grid-menu'); 34 35 jQuery('#navbar-toggler-btn').on('click', function() { 36 var $this = jQuery(this); 37 if ($this.data('animating')) { 38 return; 39 } 40 $this.data('animating', true); 41 jQuery('.animated-icon').toggleClass('open'); 42 43 // On mobile use grid menu; on desktop keep original collapse behavior 44 if (window.innerWidth < 992) { 45 navbar.addClass('top-nav-collapse'); 46 mobileGridMenu.toggleClass('show'); 47 // Apply staggered animation delays when opening 48 if (mobileGridMenu.hasClass('show')) { 49 mobileGridMenu.find('.mobile-grid-cell, .mobile-grid-group-header').each(function(i, el) { 50 el.style.animationDelay = (i * 20) + 'ms'; 51 }); 52 } 53 // Prevent body scroll when menu is open 54 jQuery('body').toggleClass('mobile-menu-open', mobileGridMenu.hasClass('show')); 55 } else { 56 jQuery('#navbar').toggleClass('navbar-col-show'); 57 } 58 59 setTimeout(function() { 60 $this.data('animating', false); 61 }, 300); 62 }); 63 64 // Close grid menu when a link inside it is clicked 65 mobileGridMenu.on('click', 'a[href]:not([href="javascript:;"])', function() { 66 mobileGridMenu.removeClass('show'); 67 jQuery('.animated-icon').removeClass('open'); 68 jQuery('body').removeClass('mobile-menu-open'); 69 navbar.removeClass('top-nav-collapse'); 70 jQuery('#navbar-toggler-btn').data('animating', false); 71 }); 72
73 // Close grid menu on resize to desktop 74 jQuery(window).on('resize', function() { 75 if (window.innerWidth >= 992 && mobileGridMenu.hasClass('show')) { 76 mobileGridMenu.removeClass('show'); 77 jQuery('.animated-icon').removeClass('open'); 78 jQuery('body').removeClass('mobile-menu-open'); 79 } 80 }); 81 }, 82 83 registerParallaxEvent: function() { 84 var ph = jQuery('#banner[parallax="true"]'); 85 if (ph.length === 0) { 86 return; 87 } 88 var board = jQuery('#board'); 89 if (board.length === 0) { 90 return; 91 } 92 var parallax = function() { 93 var pxv = jQuery(window).scrollTop() / 5; 94 var offset = parseInt(board.css('margin-top'), 10); 95 var max = 96 + offset; 96 if (pxv > max) { 97 pxv = max; 98 } 99 ph.css({ 100 transform: 'translate3d(0,' + pxv + 'px,0)' 101 }); 102 var sideCol = jQuery('.side-col'); 103 if (sideCol) { 104 sideCol.css({ 105 'padding-top': pxv + 'px' 106 }); 107 } 108 }; 109 Fluid.utils.listenScroll(parallax); 110 }, 111 112 registerScrollDownArrowEvent: function() { 113 var scrollbar = jQuery('.scroll-down-bar'); 114 if (scrollbar.length === 0) { 115 return; 116 } 117 scrollbar.on('click', function() { 118 Fluid.utils.scrollToElement('#board', -jQuery('#navbar').height()); 119 }); 120 }, 121 122 registerScrollTopArrowEvent: function() { 123 var topArrow = jQuery('#scroll-top-button'); 124 if (topArrow.length === 0) { 125 return; 126 } 127 var board = jQuery('#board'); 128 if (board.length === 0) { 129 return; 130 } 131 var posDisplay = false; 132 var scrollDisplay = false; 133 // Position 134 var setTopArrowPos = function() { 135 var boardRight = board[0].getClientRects()[0].right; 136 var bodyWidth = document.body.offsetWidth; 137 var right = bodyWidth - boardRight; 138 posDisplay = right >= 50; 139 topArrow.css({ 140 'bottom': posDisplay && scrollDisplay ? '20px' : '-60px', 141 'right' : right - 64 + 'px' 142 }); 143 }; 144 setTopArrowPos(); 145 jQuery(window).resize(setTopArrowPos); 146 // Display 147 var headerHeight = board.offset().top; 148 Fluid.utils.listenScroll(function() { 149 var scrollHeight = document.body.scrollTop + document.documentElement.scrollTop; 150 scrollDisplay = scrollHeight >= headerHeight; 151 topArrow.css({ 152 'bottom': posDisplay && scrollDisplay ? '20px' : '-60px' 153 }); 154 }); 155 // Click 156 topArrow.on('click', function() { 157 jQuery('body,html').animate({ 158 scrollTop: 0, 159 easing : 'swing' 160 }); 161 }); 162 }, 163 164 registerImageLoadedEvent: function() { 165 if (!('NProgress' in window)) { return; } 166 167 var bg = document.getElementById('banner'); 168 if (bg) { 169 var src = bg.style.backgroundImage; 170 var url = src.match(/\((.*?)\)/)[1].replace(/(['"])/g, ''); 171 var img = new Image(); 172 img.onload = function() { 173 window.NProgress && window.NProgress.status !== null && window.NProgress.inc(0.2); 174 }; 175 img.src = url; 176 if (img.complete) { img.onload(); } 177 } 178 179 var notLazyImages = jQuery('main img:not([lazyload])'); 180 var total = notLazyImages.length; 181 for (const img of notLazyImages) { 182 const old = img.onload; 183 img.onload = function() { 184 old && old(); 185 window.NProgress && window.NProgress.status !== null && window.NProgress.inc(0.5 / total); 186 }; 187 if (img.complete) { img.onload(); } 188 } 189 }, 190 191 registerRefreshCallback: function(callback) { 192 if (!Array.isArray(Fluid.events._refreshCallbacks)) { 193 Fluid.events._refreshCallbacks = []; 194 } 195 Fluid.events._refreshCallbacks.push(callback); 196 }, 197 198 refresh: function() { 199 if (Array.isArray(Fluid.events._refreshCallbacks)) { 200 for (var callback of Fluid.events._refreshCallbacks) { 201 if (callback instanceof Function) { 202 callback(); 203 } 204 } 205 } 206 }, 207 208 billboard: function() { 209 if (!('console' in window)) { 210 return; 211 } 212 // eslint-disable-next-line no-console 213 console.log(` 214------------------------------------------------- 215| | 216| ________ __ _ __ | 217| |_ __ |[ | (_) | ] | 218| | |_ \\_| | | __ _ __ .--.| | | 219| | _| | |[ | | | [ |/ /'\`\\' | | 220| _| |_ | | | \\_/ |, | || \\__/ | | 221| |_____| [___]'.__.'_/[___]'.__.;__] | 222| | 223| Powered by Hexo x Fluid | 224| https://github.com/fluid-dev/hexo-theme-fluid | 225| | 226------------------------------------------------- 227 `); 228 } 229};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.