1"use strict"; 2 3var blogboost = blogboost || {}; 4 5// Nodelist forEach polyfill 6if (window.NodeList && !NodeList.prototype.forEach) { 7 NodeList.prototype.forEach = function (callback, thisArg) { 8 thisArg = thisArg || window; 9 for (let i = 0; i < this.length; i++) { 10 callback.call(thisArg, this[i], i, this); 11 } 12 }; 13} 14 15/* Handle Accessiblity for Menu Items 16 **-----------------------------------------------------*/ 17blogboost.traverseMenu = { 18 init: function () { 19 let topNavigation = document.querySelector(".blogboost-top-nav"); 20 let primaryNavigation = document.getElementById("site-navigation"); 21 22 // For top menu navigation 23 if (topNavigation) { 24 this.traverse(topNavigation); 25 } 26 // For primary menu navigation 27 if (primaryNavigation) { 28 this.traverse(primaryNavigation); 29 } 30 }, 31 32 traverse: function (navigation) { 33 let menu = navigation.getElementsByTagName("ul")[0]; 34 if ("undefined" !== typeof menu) { 35 if (!menu.classList.contains("nav-menu")) { 36 menu.classList.add("nav-menu"); 37 } 38 // Get all the link elements within the menu. 39 let links = menu.getElementsByTagName("a"); 40 41 // Get all the link elements with children within the menu. 42 let linksWithChildren = menu.querySelectorAll( 43 ".menu-item-has-children > a, .page_item_has_children > a" 44 ); 45 46 // Toggle focus each time a menu link is focused or blurred. 47 for (let link of links) { 48 link.addEventListener("focus", this.toggleFocus, true); 49 link.addEventListener("blur", this.toggleFocus, true); 50 } 51 52 // Toggle focus each time a menu link with children receive a touch event. 53 for (let link of linksWithChildren) { 54 link.addEventListener("touchstart", this.toggleFocus, false); 55 } 56 } 57 }, 58 59 toggleFocus: function (event) { 60 if (event.type === "focus" || event.type === "blur") { 61 let self = this; 62 // Move up through the ancestors of the current link until we hit .nav-menu. 63 while (!self.classList.contains("nav-menu")) { 64 // On li elements toggle the class .focus. 65 if ("li" === self.tagName.toLowerCase()) { 66 self.classList.toggle("focus"); 67 } 68 self = self.parentNode; 69 } 70 } 71 72 if (event.type === "touchstart") { 73 let menuItem = this.parentNode; 74 event.preventDefault(); 75 for (let link of menuItem.parentNode.children) { 76 if (menuItem !== link) { 77 link.classList.remove("focus"); 78 } 79 } 80 menuItem.classList.toggle("focus"); 81 } 82 }, 83}; 84 85/* Handle Focus for Dialog Accessiblity 86 **-----------------------------------------------------*/ 87blogboost.handleFocus = { 88 init: function () { 89 this.keepFocusInModal(); 90 }, 91 92 keepFocusInModal: function () { 93 let searchModal = document.querySelector(".theme-search-panel"); 94 let canvasMenuModal = document.querySelector(".theme-offcanvas-panel-menu"); 95 let canvasWidgetModal = document.querySelector(".theme-offcanvas-panel-widget"); 96 97 document.addEventListener("keydown", function (event) { 98 // Check for if tab key is pressed 99 let KEYCODE_TAB = 9; 100 let isTabPressed = 101 event.key === "Tab" || event.keyCode === KEYCODE_TAB; 102 if (!isTabPressed) { 103 return; 104 } 105 106 let modal; 107 108 if (document.body.classList.contains("blogboost-search-canvas-open")) { 109 modal = searchModal; 110 } 111 112 if (document.body.classList.contains("blogboost-offcanvas-menu-open")) { 113 modal = canvasMenuModal; 114 } 115 116 if (document.body.classList.contains("blogboost-offcanvas-widget-open")) { 117 modal = canvasWidgetModal; 118 } 119 120 if (modal) { 121 let focusableEls = modal.querySelectorAll( 122 'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="search"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled]), [tabindex]:not
122([tabindex="-1"])' 123 ); 124 125 let firstFocusableEl = focusableEls[0]; 126 let lastFocusableEl = focusableEls[focusableEls.length - 1]; 127 128 // if shift key pressed for shift + tab combination 129 if (event.shiftKey) { 130 if (document.activeElement === firstFocusableEl) { 131 lastFocusableEl.focus(); // add focus for the last focusable element 132 event.preventDefault(); 133 } 134 } else { 135 // if tab key is pressed 136 if (document.activeElement === lastFocusableEl) { 137 // if focused has reached to last focusable element then focus first focusable element after pressing tab 138 firstFocusableEl.focus(); // add focus for the first focusable element 139 event.preventDefault(); 140 } 141 } 142 } 143 }); 144 }, 145}; 146 147/* Preloader 148 **-----------------------------------------------------*/ 149blogboost.fadeOutPreloader = { 150 init: function () { 151 152 let preloader = document.querySelector("#theme-preloader-initialize"); 153 154 if (preloader) { 155 let fadeOut = setInterval(function () { 156 preloader.style.transition = "0.2s"; 157 158 if (!preloader.style.opacity) { 159 preloader.style.opacity = 1; 160 } 161 if (preloader.style.opacity > 0) { 162 preloader.style.opacity -= 0.2; 163 } else { 164 preloader.style.display = "none"; 165 clearInterval(fadeOut); 166 } 167 }, 100); 168 } 169 }, 170}; 171 172/* Scroll to top 173 **-----------------------------------------------------*/ 174blogboost.scrollToTop = { 175 init: function () { 176 let scrollToTopBtn = document.getElementById("theme-scroll-to-start"); 177 let rootElement = document.documentElement; 178 179 if (scrollToTopBtn) { 180 // Scroll to top on click 181 this.goToTop(scrollToTopBtn, rootElement); 182 183 // Render scroll to top button 184 this.scrollToTopPosition(scrollToTopBtn, rootElement); 185 } 186 }, 187 188 goToTop: function (scrollToTopBtn, rootElement) { 189 scrollToTopBtn.addEventListener("click", function (elem) { 190 elem.preventDefault(); 191 rootElement.scrollTo({ 192 top: 0, 193 behavior: "smooth", 194 }); 195 }); 196 }, 197 198 scrollToTopPosition: function (scrollToTopBtn, rootElement) { 199 window.addEventListener("scroll", function (event) { 200 let scrollTotal = 201 rootElement.scrollHeight - rootElement.clientHeight; 202 // Show on certain window height 203 if (rootElement.scrollTop / scrollTotal > 0.4) { 204 scrollToTopBtn.classList.add("visible"); 205 } else { 206 scrollToTopBtn.classList.remove("visible"); 207 } 208 }); 209 }, 210}; 211 212/* Display Clock 213 **-----------------------------------------------------*/ 214blogboost.currentClock = { 215 init: function () { 216 if (document.getElementsByClassName("theme-display-clock").length > 0) { 217 setInterval(function () { 218 let currentTime = new Date(); 219 let hours = currentTime.getHours(); 220 let minutes = currentTime.getMinutes(); 221 let seconds = currentTime.getSeconds(); 222 let ampm = hours >= 12 ? "PM" : "AM"; 223 hours = hours % 12; 224 hours = hours ? hours : 12; 225 minutes = minutes < 10 ? "0" + minutes : minutes; 226 seconds = seconds < 10 ? "0" + seconds : seconds; 227 let timeString = 228 '<span class="theme-clock-unit clock-unit-hours">' + 229 hours + 230 "</span>" + 231 ":" + 232 '<span class="theme-clock-unit clock-unit-minute">' + 233 minutes + 234 "</span>" + 235 ":" + 236 '<span class="theme-clock-unit clock-unit-seconds">' + 237 seconds + 238 "</span>" + 239 " " + 240 '<span class="theme-clock-unit clock-unit-format">' + 241 ampm + 242 "</span>"; 243 document.getElementsByClassName( 244 "theme-display-clock"
245 )[0].innerHTML = timeString; 246 }, 1000); 247 } 248 }, 249}; 250 251/* Sticky Menu 252 **-----------------------------------------------------*/ 253blogboost.stickyMenu = { 254 init: function () { 255 let navBar = document.querySelector(".masthead-main-navigation"); 256 257 // Handle stikcy menu on scroll 258 if (navBar && navBar.classList.contains("has-sticky-header")) { 259 this.stickMenuOnScroll(navBar); 260 } 261 }, 262 263 stickMenuOnScroll: function (navBar) { 264 window.addEventListener("scroll", function (event) { 265 let navOffset = navBar.offsetTop; 266 let currentScrollPos = window.pageYOffset; 267 268 if (navOffset > currentScrollPos || currentScrollPos === 0) { 269 navBar.classList.remove("sticky-header-active"); 270 } else { 271 navBar.classList.add("sticky-header-active"); 272 } 273 }); 274 }, 275}; 276 277/* Off Canvas 278 **-----------------------------------------------------*/ 279blogboost.offCanvasModal = { 280 init: function () { 281 let offCanvasBtn = document.getElementById( 282 "theme-toggle-offcanvas-button" 283 ); 284 let closeOffCanvas = document.getElementById("theme-offcanvas-close"); 285 let overlayDiv = document.querySelector("#page.site"); 286 287 if (offCanvasBtn) { 288 let focusElement = document.querySelector( 289 "#theme-offcanvas-close" 290 ); 291 292 // Handle canvas modal when opened 293 this.onOpen(offCanvasBtn, focusElement); 294 295 // Handle canvas modal when closed 296 this.onClose(offCanvasBtn, closeOffCanvas, focusElement); 297 298 // When open, close if visitor clicks on the wrapping element of the modal. 299 this.outsideModal(offCanvasBtn, overlayDiv, focusElement); 300 301 // Close on escape key press. 302 this.closeOnEscape(offCanvasBtn, focusElement); 303 } 304 }, 305 306 onOpen: function (offCanvasBtn, focusElement) { 307 offCanvasBtn.addEventListener("click", function (event) { 308 event.preventDefault(); 309 document.body.classList.add("blogboost-offcanvas-menu-open"); 310 311 offCanvasBtn.setAttribute("aria-expanded", true); 312 313 // Add focus after a timeout to take effect on hidden element to make the "all" transition work 314 setTimeout(function () { 315 focusElement.focus(); 316 }, 500); 317 }); 318 }, 319 320 onClose: function (offCanvasBtn, closeOffCanvas, focusElement) { 321 closeOffCanvas.addEventListener("click", function (event) { 322 event.preventDefault(); 323 document.body.classList.remove("blogboost-offcanvas-menu-open"); 324 offCanvasBtn.setAttribute("aria-expanded", false); 325 focusElement.blur(); 326 offCanvasBtn.focus(); 327 }); 328 }, 329 330 outsideModal: function (offCanvasBtn, overlayDiv, focusElement) { 331 document.addEventListener("click", function (event) { 332 if (document.body.classList.contains("blogboost-offcanvas-menu-open")) { 333 if (event.target == overlayDiv) { 334 document.body.classList.remove("blogboost-offcanvas-menu-open"); 335 offCanvasBtn.setAttribute("aria-expanded", false); 336 focusElement.blur(); 337 offCanvasBtn.focus(); 338 console.log(offCanvasBtn); 339 } 340 } 341 }); 342 }, 343 344 closeOnEscape: function (offCanvasBtn, focusElement) { 345 document.addEventListener("keydown", function (event) { 346 if (document.body.classList.contains("blogboost-offcanvas-menu-open")) { 347 if (event.key === "Escape") { 348 event.preventDefault(); 349 document.body.classList.remove("blogboost-offcanvas-menu-open"); 350 offCanvasBtn.setAttribute("aria-expanded", false); 351 focusElement.blur(); 352 offCanvasBtn.focus(); 353 } 354 } 355 }); 356 }, 357}; 358 359/* Off Canvas Dropdown menu item 360 **-----------------------------------------------------*/ 361blogboost.offCanvasDropdown = { 362 init: function () { 363 let subMenuToggles = document.querySelectorAll(".sub-menu
363-toggle"); 364 subMenuToggles.forEach(function (toggle) { 365 toggle.addEventListener("click", function () { 366 let duration = 367 toggle.getAttribute("data-toggle-duration") || 350; 368 toggle.classList.toggle("active"); 369 toggle.setAttribute( 370 "aria-expanded", 371 toggle.getAttribute("aria-expanded") === "true" 372 ? "false" 373 : "true" 374 ); 375 let currentClass = toggle.getAttribute("data-toggle-target"); 376 let currentTargets = document.querySelectorAll(currentClass); 377 currentTargets.forEach(function (currentTarget) { 378 currentTarget.classList.toggle("active"); 379 currentTarget.style.transition = `height ${duration}ms ease`; 380 if (currentTarget.style.display === "block") { 381 currentTarget.style.height = 382 currentTarget.offsetHeight + "px"; 383 setTimeout(() => { 384 currentTarget.style.height = "0"; 385 }, 20); 386 setTimeout(() => { 387 currentTarget.style.display = "none"; 388 }, duration); 389 } else { 390 currentTarget.style.display = "block"; 391 currentTarget.style.height = "0"; 392 setTimeout(() => { 393 currentTarget.style.height = "auto"; 394 }, duration); 395 } 396 }); 397 }); 398 }); 399 }, 400}; 401 402/* Off-Canvas Widget 403**-----------------------------------------------------*/ 404blogboost.offCanvasWidget = { 405 init: function () { 406 let offCanvasWidgetBtn = document.getElementById("theme-offcanvas-widget-button"); 407 let closeOffCanvasWidget = document.getElementById("theme-offcanvas-widget-close"); 408 let overlayWidgetDiv = document.querySelector("#page.site"); 409 410 if (offCanvasWidgetBtn) { 411 let focusElement = document.querySelector("#theme-offcanvas-widget-close"); 412 413 // Handle canvas widget when opened 414 this.onOpen(offCanvasWidgetBtn, focusElement); 415 416 // Handle canvas widget when closed 417 this.onClose(offCanvasWidgetBtn, closeOffCanvasWidget, focusElement); 418 419 // When open, close if visitor clicks on the wrapping element of the widget. 420 this.outsideWidget(offCanvasWidgetBtn, overlayWidgetDiv, focusElement); 421 422 // Close on escape key press. 423 this.closeOnEscape(offCanvasWidgetBtn, focusElement); 424 } 425 }, 426 427 onOpen: function (offCanvasWidgetBtn, focusElement) { 428 offCanvasWidgetBtn.addEventListener("click", function (event) { 429 event.preventDefault(); 430 document.body.classList.add("blogboost-offcanvas-widget-open"); 431 432 offCanvasWidgetBtn.setAttribute("aria-expanded", true); 433 434 // Add focus after a timeout to take effect on hidden element to make the "all" transition work 435 setTimeout(function () { 436 focusElement.focus(); 437 }, 500); 438 }); 439 }, 440 441 onClose: function (offCanvasWidgetBtn, closeOffCanvasWidget, focusElement) { 442 closeOffCanvasWidget.addEventListener("click", function (event) { 443 event.preventDefault(); 444 document.body.classList.remove("blogboost-offcanvas-widget-open"); 445 offCanvasWidgetBtn.setAttribute("aria-expanded", false); 446 focusElement.blur(); 447 offCanvasWidgetBtn.focus(); 448 }); 449 }, 450 451 outsideWidget: function (offCanvasWidgetBtn, overlayWidgetDiv, focusElement) { 452 document.addEventListener("click", function (event) { 453 if (document.body.classList.contains("blogboost-offcanvas-widget-open")) { 454 if (event.target == overlayWidgetDiv) { 455 document.body.classList.remove("blogboost-offcanvas-widget-open"); 456 offCanvasWidgetBtn.setAttribute("aria-expanded", false); 457 focusElement.blur(); 458 offCanvasWidgetBtn.focus(); 459 } 460 } 461 }); 462 }, 463 464 closeOnEscape: function (offCanvasWidgetBtn, focusElement) { 465 document.addEventListener("keydown", function (event) { 466 if (document.body.classList.contains("blogboost-offcanvas-widget-open")) { 467 if (event.key === "Escape") { 468 event.preventDefault(); 469 document.body.classList.remove("blogboost-offcanvas-widget-open"); 470 offCanvasWidgetBtn.setAttribute("aria-expanded", false); 471 focusElement.blur(); 472 offCanvasWidgetBtn.focus(); 473 } 474 } 475 }); 476 }, 477}; 478 479/* Search Canvas 480 **-----------------------------------------------------*/ 481blogboost.searchCanvasModal = { 482 init: function () { 483 let searchCanvasBtn = document.getElementById( 484 "theme-toggle-search-button" 485 ); 486 let closeSearchCanvas = document.getElementById( 487 "blogboost-search-canvas-close" 488 ); 489 let overlayDiv = document.querySelector("#page.site"); 490 491 if (searchCanvasBtn) { 492 let focusElement = document.querySelector( 493 ".theme-search-panel .search-field" 494 ); 495 496 // Handle cover modals when they're opened 497 this.onOpen(searchCanvasBtn, focusElement); 498 499 // Handle cover modals when they're closed 500 this.onClose(searchCanvasBtn, closeSearchCanvas, focusElement); 501 502 // When open, close if visitor clicks on the outside the modal. 503 this.outsideModal(searchCanvasBtn, overlayDiv, focusElement); 504 505 // Close on escape key press. 506 this.closeOnEscape(searchCanvasBtn, focusElement); 507 } 508 }, 509 510 onOpen: function (searchCanvasBtn, focusElement) { 511 searchCanvasBtn.addEventListener("click", function (event) { 512 event.preventDefault(); 513 document.body.classList.add("blogboost-search-canvas-open"); 514 515 searchCanvasBtn.setAttribute("aria-expanded", true); 516 517 // Add focus after a timeout to take effect on hidden element to make the "all" transition work 518 setTimeout(function () { 519 focusElement.focus(); 520 }, 500); 521 }); 522 }, 523 524 onClose: function (searchCanvasBtn, closeSearchCanvas, focusElement) { 525 closeSearchCanvas.addEventListener("click", function (event) { 526 event.preventDefault(); 527 document.body.classList.remove("blogboost-search-canvas-open"); 528 searchCanvasBtn.setAttribute("aria-expanded", false); 529 focusElement.blur(); 530 searchCanvasBtn.focus(); 531 }); 532 }, 533 534 outsideModal: function (searchCanvasBtn, overlayDiv, focusElement) { 535 document.addEventListener("click", function (event) { 536 if (document.body.classList.contains("blogboost-search-canvas-open")) { 537 if (event.target == overlayDiv) { 538 document.body.classList.remove("blogboost-search-canvas-open"); 539 searchCanvasBtn.setAttribute("aria-expanded", false); 540 focusElement.blur(); 541 searchCanvasBtn.focus(); 542 } 543 } 544 }); 545 }, 546 547 closeOnEscape: function (searchCanvasBtn, focusElement) { 548 document.addEventListener("keydown", function (event) { 549 if (document.body.classList.contains("blogboost-search-canvas-open")) { 550 if (event.key === "Escape") { 551 event.preventDefault(); 552 document.body.classList.remove("blogboost-search-canvas-open"); 553 searchCanvasBtn.setAttribute("aria-expanded", false); 554 focusElement.blur(); 555 searchCanvasBtn.focus(); 556 } 557 } 558 }); 559 }, 560}; 561
562/* Background Image 563 **-----------------------------------------------------*/ 564blogboost.setBackgroundImage = { 565 init: function () { 566 let bgImageContainer = document.querySelectorAll(".blogboost-bg-image"); 567 if (bgImageContainer) { 568 bgImageContainer.forEach(function (item) { 569 let image = item.querySelector("img"); 570 if (image) { 571 let imageSrc = image.getAttribute("src"); 572 if (imageSrc) { 573 item.style.backgroundImage = "url(" + imageSrc + ")"; 574 if (item.classList.contains("blogboost-header-image")) { 575 image.style.visibility = "hidden"; 576 } else { 577 image.style.display = "none"; 578 } 579 } 580 } 581 }); 582 } 583 584 let pageSections = document.querySelectorAll(".data-bg"); 585 pageSections.forEach(function (section) { 586 let background = section.getAttribute("data-background"); 587 if (background) { 588 section.style.backgroundImage = "url(" + background + ")"; 589 } 590 }); 591 }, 592}; 593 594/* Progress Bar 595 **-----------------------------------------------------*/ 596blogboost.progressBar = { 597 init: function () { 598 let progressBarDiv = document.getElementById("blogboost-progress-bar"); 599 600 if (progressBarDiv) { 601 let body = document.body; 602 let rootElement = document.documentElement; 603 604 window.addEventListener("scroll", function (event) { 605 let winScroll = body.scrollTop || rootElement.scrollTop; 606 let height = 607 rootElement.scrollHeight - rootElement.clientHeight; 608 let scrolled = (winScroll / height) * 100; 609 progressBarDiv.style.width = scrolled + "%"; 610 }); 611 } 612 }, 613}; 614 615/* Tab Widget 616 **-----------------------------------------------------*/ 617blogboost.tabWidget = { 618 init: function () { 619 620 const widgetContainers = document.querySelectorAll(".theme-widget-tab"); 621 widgetContainers.forEach((container) => { 622 const tabs = container.querySelectorAll( 623 ".tab-header-list .widget-tab-presentation" 624 ); 625 const tabPanes = container.querySelectorAll( 626 ".widget-tab-content .tab-content-panel" 627 ); 628
629 tabs.forEach((tab) => { 630 tab.addEventListener("click", function (event) { 631 const tabid = this.getAttribute("tab-data"); 632 tabs.forEach((tab) => tab.classList.remove("active")); 633 tabPanes.forEach((tabPane) => 634 tabPane.classList.remove("active") 635 ); 636 this.classList.add("active"); 637 container 638 .querySelector(`.content-${tabid}`) 639 .classList.add("active"); 640 }); 641 }); 642 }); 643 }, 644}; 645 646/* Swiper slides 647 **-----------------------------------------------------*/ 648blogboost.swiperJs = { 649 init: function() { 650 const commonOptions = { 651 loop: true, 652 pagination: { 653 el: ".swiper-pagination", 654 clickable: true, 655 }, 656 autoplay: { 657 disableOnInteraction: false, 658 delay: 9000, 659 }, 660 speed: 1000, 661 simulateTouch: false, 662 roundLengths: true, 663 keyboard: true, 664 mousewheel: false, 665 a11y: { 666 prevSlideMessage: 'Previous slide', 667 nextSlideMessage: 'Next slide', 668 }, 669 navigation: { 670 nextEl: ".swiper-button-next", 671 prevEl: ".swiper-button-prev", 672 }, 673 }; 674 675 const sliderOptions = { 676 slidesPerView: 1, 677 effect: "slide", 678 }; 679 680 const carousalOptions = { 681 slidesPerView: 1, 682 spaceBetween: 20, 683 breakpoints: { 684 640: { 685 slidesPerView: 1, 686 }, 687 768: { 688 slidesPerView: 2, 689 }, 690 1300: { 691 slidesPerView: 3, 692 }, 693 }, 694 }; 695 696 const swiperSlider = new Swiper(".site-banner-layout-slider", { 697 ...commonOptions, 698 ...sliderOptions, 699 }); 700 701 const swiperCarousal = new Swiper(".site-banner-layout-carousal", { 702 ...commonOptions, 703 ...carousalOptions, 704 }); 705 }, 706}; 707 708 709/* Popup ModelBox 710 **-----------------------------------------------------*/ 711blogboost.lightBox = { 712 init: function () { 713 let light = document.querySelector("[data-glightbox]"); 714 if (light) { 715 GLightbox({ 716 selector: "[data-glightbox]", 717 openEffect: "zoom", 718 closeEffect: "fade", 719 }); 720 } 721 }, 722}; 723 724/* Sticky Footer 725 **-----------------------------------------------------*/ 726blogboost.stickyFooter = { 727 init: function () { 728 const footer = document.querySelector('[data-sticky-footer=true]'); 729 const spacer = document.querySelector('.sticky-footer-spacer'); 730 731 if (!footer || !spacer) return; 732 733 const footerHeight = footer.offsetHeight; 734 735 function updateSpacerHeight() { 736 spacer.style.height = `${footerHeight}px`; 737 } 738 739 window.addEventListener('load', updateSpacerHeight); 740 window.addEventListener('resize', updateSpacerHeight); 741 742 function handleScroll() { 743 const scrollPosition = window.pageYOffset; 744 const spacerTopOffset = spacer.offsetTop; 745 const shouldStickyFooter = scrollPosition >= spacerTopOffset - window.innerHeight; 746 footer.classList.toggle('has-footer-stuck', shouldStickyFooter); 747 } 748 749 document.body.classList.add('has-sticky-footer'); 750 window.addEventListener('scroll', handleScroll); 751 }, 752}; 753 754/* Welcome Screen Advertisement 755 **-----------------------------------------------------*/ 756 757blogboost.fullpageAdvertisement = { 758 init() { 759 const adCountDown = document.querySelector('.welcome-screen-countdown'); 760 const headerAds = document.querySelector('.welcome-screen-banner'); 761 const adBtn = document.querySelector('.welcome-screen-skip'); 762 763 if (!headerAds) return; 764 765 let counter = 6; 766 let startCount = null; 767 768 function startScroll() { 769 headerAds.classList.add('welcome-screen-vanished'); 770 } 771 772 adBtn.addEventListener('click', () => { 773 clearInterval(startCount); 774 startScroll(); 775 }); 776 777 startCount = setInterval(() => { 778 counter--; 779 adCountDown.textContent = `${counter}sec`; 780 781 if (counter === 0) { 782 clearInterval(startCount); 783 startScroll(); 784 } 785 }, 1000); 786 }, 787}; 788 789/* Custom Cursor 790 **-----------------------------------------------------*/ 791let cursorObj; 792blogboost.customCursor = { 793 init: function () { 794 cursorObj = this; 795 this.customCursor(); 796 }, 797 isVariableDefined: function (el) { 798 return typeof !!el && el != "undefined" && el != null; 799 }, 800 select: function (selectors) { 801 return document.querySelector(selectors); 802 }, 803 selectAll: function (selectors) { 804 return document.querySelectorAll(selectors); 805 }, 806 customCursor: function () { 807 let c = cursorObj.select(".cursor-dot"); 808 if (cursorObj.isVariableDefined(c)) { 809 let cursor = { 810 delay: 8, 811 _x: 0, 812 _y: 0, 813 endX: window.innerWidth / 2, 814 endY: window.innerHeight / 2, 815 cursorVisible: true, 816 cursorEnlarged: false, 817 $dot: cursorObj.select(".cursor-dot"), 818 $outline: cursorObj.select(".cursor-dot-outline"), 819 820 init: function () { 821 // Set up element sizes 822 this.dotSize = this.$dot.offsetWidth; 823 this.outlineSize = this.$outline.offsetWidth; 824 825 this.setupEventListeners(); 826 this.animateDotOutline(); 827 }, 828 829 updateCursor: function (e) { 830 let self = this; 831 832 // Show the cursor 833 self.cursorVisible = true; 834 self.toggleCursorVisibility(); 835 836 // Position the dot 837 self.endX = e.clientX; 838 self.endY = e.clientY; 839 self.$dot.style.top = self.endY + "px"; 840 self.$dot.style.left = self.endX + "px"; 841 }, 842 843 setupEventListeners: function () { 844 let self = this; 845 846 // Reposition cursor on window load 847 window.addEventListener("load", (event) => { 848 self.cursorEnlarged = false;
849 self.toggleCursorSize(); 850 }); 851 852 // Anchor hovering 853 cursorObj.selectAll("a, button").forEach(function (el) { 854 el.addEventListener("mouseover", function () { 855 self.cursorEnlarged = true; 856 self.toggleCursorSize(); 857 }); 858 el.addEventListener("mouseout", function () { 859 self.cursorEnlarged = false; 860 self.toggleCursorSize(); 861 }); 862 }); 863 864 // Click events 865 document.addEventListener("mousedown", function () { 866 self.cursorEnlarged = true; 867 self.toggleCursorSize(); 868 }); 869 document.addEventListener("mouseup", function () { 870 self.cursorEnlarged = false; 871 self.toggleCursorSize(); 872 }); 873 874 document.addEventListener("mousemove", function (e) { 875 // Show the cursor 876 self.cursorVisible = true; 877 self.toggleCursorVisibility(); 878 879 // Position the dot 880 self.endX = e.clientX; 881 self.endY = e.clientY; 882 self.$dot.style.top = self.endY + "px"; 883 self.$dot.style.left = self.endX + "px"; 884 }); 885 886 // Hide/show cursor 887 document.addEventListener("mouseenter", function (e) { 888 self.cursorVisible = true; 889 self.toggleCursorVisibility(); 890 self.$dot.style.opacity = 1; 891 self.$outline.style.opacity = 1; 892 }); 893 894 document.addEventListener("mouseleave", function (e) { 895 self.cursorVisible = true; 896 self.toggleCursorVisibility(); 897 self.$dot.style.opacity = 0; 898 self.$outline.style.opacity = 0; 899 }); 900 }, 901 902 animateDotOutline: function () { 903 let self = this; 904 905 self._x += (self.endX - self._x) / self.delay; 906 self._y += (self.endY - self._y) / self.delay; 907 self.$outline.style.top = self._y + "px"; 908 self.$outline.style.left = self._x + "px"; 909 910 requestAnimationFrame(this.animateDotOutline.b
910ind(self)); 911 }, 912 913 toggleCursorSize: function () { 914 let self = this; 915 916 if (self.cursorEnlarged) { 917 self.$dot.style.transform = 918 "translate(-50%, -50%) scale(0.75)"; 919 self.$outline.style.transform = 920 "translate(-50%, -50%) scale(1.6)"; 921 } else { 922 self.$dot.style.transform = 923 "translate(-50%, -50%) scale(1)"; 924 self.$outline.style.transform = 925 "translate(-50%, -50%) scale(1)"; 926 } 927 }, 928 929 toggleCursorVisibility: function () { 930 let self = this; 931 932 if (self.cursorVisible) { 933 self.$dot.style.opacity = 1; 934 self.$outline.style.opacity = 1; 935 } else { 936 self.$dot.style.opacity = 0; 937 self.$outline.style.opacity = 0; 938 } 939 }, 940 }; 941 cursor.init(); 942 } 943 }, 944}; 945 946/* Load functions at proper events 947 *--------------------------------------------------*/ 948/** 949 * Is the DOM ready? 950 * 951 * This implementation is coming from https://gomakethings.com/a-native-javascript-equivalent-of-jquerys-ready-method/ 952 * 953 * @param {Function} fn Callback function to run. 954 */ 955function blogboostDomReady(fn) { 956 if (typeof fn !== "function") { 957 return; 958 } 959 960 if ( 961 document.readyState === "interactive" || 962 document.readyState === "complete" 963 ) { 964 return fn(); 965 } 966 967 document.addEventListener("DOMContentLoaded", fn, false); 968} 969 970blogboostDomReady(function () { 971 blogboost.offCanvasModal.init(); 972 blogboost.offCanvasDropdown.init(); 973 blogboost.offCanvasWidget.init(); 974 blogboost.searchCanvasModal.init(); 975 blogboost.currentClock.init(); 976 blogboost.stickyMenu.init(); 977 blogboost.scrollToTop.init(); 978 blogboost.handleFocus.init(); 979 blogboost.traverseMenu.init(); 980 blogboost.setBackgroundImage.init(); 981 blogboost.progressBar.init(); 982 blogboost.tabWidget.init(); 983 blogboost.swiperJs.init(); 984 blogboost.lightBox.init(); 985 blogboost.stickyFooter.init(); 986 blogboost.fullpageAdvertisement.init(); 987 blogboost.customCursor.init(); 988}); 989 990window.addEventListener("load", function (event) { 991 blogboost.fadeOutPreloader.init(); 992});
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.