1// Theme 2window.theme = {}; 3 4// Theme Common Functions 5window.theme.fn = { 6 7 getOptions(opts) { 8 9 if (typeof(opts) == 'object') { 10 11 return opts; 12 13 } else if (typeof(opts) == 'string') { 14 15 try { 16 return JSON.parse(opts.replace(/'/g, '"').replace(';', '')); 17 } catch (e) { 18 return {}; 19 } 20 21 } else { 22 23 return {}; 24 25 } 26 27 }, 28 29 execPluginFunction(functionName, context) { 30 const args = Array.prototype.slice.call(arguments, 2); 31 const namespaces = functionName.split("."); 32 const func = namespaces.pop(); 33 34 for (let i = 0; i < namespaces.length; i++) { 35 context = context[namespaces[i]]; 36 } 37 38 return context[func](...args); 39 }, 40 41 intObs(selector, functionName, intObsOptions, alwaysObserve) { 42 const $el = document.querySelectorAll(selector); 43 let intersectionObserverOptions = { 44 rootMargin: '0px 0px 200px 0px' 45 }; 46 47 if (Object.keys(intObsOptions).length) { 48 intersectionObserverOptions = $.extend(intersectionObserverOptions, intObsOptions); 49 } 50 51 const observer = new IntersectionObserver(entries => { 52 for (const entry of entries) { 53 if (entry.intersectionRatio > 0) { 54 if (typeof functionName === 'string') { 55 const func = Function('return ' + functionName)(); 56 } else { 57 const callback = functionName; 58 59 callback.call($(entry.target)); 60 } 61 62 // Unobserve 63 if (!alwaysObserve) { 64 observer.unobserve(entry.target); 65 } 66 67 } 68 } 69 }, intersectionObserverOptions); 70 71 $($el).each(function() { 72 observer.observe($(this)[0]); 73 }); 74 }, 75 76 intObsInit(selector, functionName) { 77 const $el = document.querySelectorAll(selector); 78 const intersectionObserverOptions = { 79 rootMargin: '200px' 80 }; 81 82 const observer = new IntersectionObserver(entries => { 83 for (const entry of entries) { 84 if (entry.intersectionRatio > 0) { 85 const $this = $(entry.target); 86 let opts; 87 88 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 89 if (pluginOptions) 90 opts = pluginOptions; 91 92 theme.fn.execPluginFunction(functionName, $this, opts); 93 94 // Unobserve 95 observer.unobserve(entry.target); 96 } 97 } 98 }, intersectionObserverOptions); 99 100 $($el).each(function() { 101 observer.observe($(this)[0]); 102 }); 103 }, 104 105 dynIntObsInit(selector, functionName, pluginDefaults) { 106 const $el = document.querySelectorAll(selector); 107 108 $($el).each(function() { 109 const $this = $(this); 110 let opts; 111 112 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 113 if (pluginOptions) 114 opts = pluginOptions; 115 116 const mergedPluginDefaults = theme.fn.mergeOptions(pluginDefaults, opts); 117 118 const intersectionObserverOptions = { 119 rootMargin: theme.fn.getRootMargin(functionName, mergedPluginDefaults), 120 threshold: 0 121 }; 122 123 if (!mergedPluginDefaults.forceInit) { 124 125 const observer = new IntersectionObserver(entries => { 126 for (const entry of entries) { 127 if (entry.intersectionRatio > 0) { 128 theme.fn.execPluginFunction(functionName, $this, mergedPluginDefaults); 129 130 // Unobserve 131 observer.unobserve(entry.target); 132 } 133 } 134 }, intersectionObserverOptions); 135 136 observer.observe($this[0]); 137 138 } else { 139 theme.fn.execPluginFunction(functionName, $this, mergedPluginDefaults); 140 } 141 }); 142 }, 143 144 getRootMargin(plugin, { accY }) { 145 switch (plugin) { 146 case 'themePluginCounter': 147 return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px'; 148 break; 149 150 case 'themePluginAnimate': 151 return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px'; 152 break; 153 154 case 'themePluginIcon': 155 return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px'; 156 break; 157 158 case 'themePluginRandomImages': 159 return accY ? `0px 0px ${accY}px 0px` : '0px 0px 200px 0px'; 160 break; 161 162 default: 163 return '0px 0px 200px 0px'; 164 break; 165 } 166 }, 167 168 mergeOptions(obj1, obj2) { 169 const obj3 = {}; 170 171 for (var attrname in obj1) { 172 obj3[attrname] = obj1[attrname]; 173 } 174 for (var attrname in obj2) { 175 obj3[attrname] = obj2[attrname]; 176 } 177 178 return obj3; 179 }, 180 181 execOnceTroughEvent($el, event, callback) { 182 const self = this, 183 dataName = self.formatDataName(event); 184 185 $($el).on(event, function() { 186 if (!$(this).data(dataName)) { 187 188 // Exec Callback Function 189 callback.call($(this)); 190 191 // Add data name 192 $(this).data(dataName, true); 193 194 // Unbind event 195 $(this).off(event); 196 } 197 }); 198 199 return this; 200 }, 201 202 execOnceTroughWindowEvent($el, event, callback) { 203 const self = this, 204 dataName = self.formatDataName(event); 205 206 $($el).on(event, function() { 207 if (!$(this).data(dataName)) { 208 209 // Exec Callback Function 210 callback(); 211 212 // Add data name 213 $(this).data(dataName, true); 214 215 // Unbind event 216 $(this).off(event); 217 } 218 }); 219 220 return this; 221 }, 222 223 formatDataName(name) { 224 name = name.replace('.', ''); 225 return name; 226 }, 227 228 isElementInView($el) { 229 const rect = $el[0].getBoundingClientRect(); 230 231 return ( 232 rect.top <= (window.innerHeight / 3) 233 ); 234 }, 235 236 getScripts(arr, path) { 237 const _arr = $.map(arr, scr => $.getScript((path || "") + scr)); 238 239 _arr.push($.Deferred(({ resolve }) => { 240 $(resolve); 241 })); 242 243 return $.when(..._arr); 244 }, 245 246 showErrorMessage(title, content) { 247 248 if ($('html').hasClass('disable-local-warning')) { 249 return; 250 } 251 252 $('.modalThemeErrorMessage').remove(); 253 $('body').append('<div class="modal fade" id="modalThemeErrorMessage"><div class="modal-dialog modal-dialog-centered"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">' + title + '</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body">' + content + '</div><div class="modal-footer"><button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button></div></div></div></div>'); 254 255 var modalThemeErrorMessage = document.getElementById('modalThemeErrorMessage'); 256 var modalThemeErrorMessage = bootstrap.Modal.getOrCreateInstance(modalThemeErrorMessage); 257 modalThemeErrorMessage.show(); 258 259 } 260 261}; 262 263(((theme = {}, $) => { 264 /*
265 Local Environment Warning 266 */ 267 try { 268 if ("file://" === location.origin) { 269 if ($('[data-icon]').length || $('iframe').length) { 270 271 theme.fn.showErrorMessage('Local Environment Warning', 'SVG Objects, Icons, YouTube and Vimeo Videos might not show correctly on local environment. For better result, please preview on a server.<br><br><a target="_blank" href="https://www.okler.net/forums/topic/how-to-disable-local-environment-warning/" class="fw-semibold"><i class="fa-solid fa-link"></i> How to Disable Local Environment Warning</a>'); 272 273 } 274 } 275 } catch (e) {} 276 277 /* 278 Browser Selector 279 */ 280 $.extend({ 281 282 browserSelector() { 283 284 // jQuery.browser.mobile (http://detectmobilebrowser.com/) 285 (a => { 286 (jQuery.browser = jQuery.browser || {}).mobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4)) 287 })(navigator.userAgent || navigator.vendor || window.opera); 288 289 // Touch 290 const hasTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints; 291 292 const u = navigator.userAgent, 293 ua = u.toLowerCase(), 294 is = t => ua.includes(t), 295 g = 'gecko', 296 w = 'webkit', 297 s = 'safari', 298 o = 'opera', 299 h = document.documentElement, 300 b = [(!(/opera|webtv/i.test(ua)) && /msie\s(\d)/.test(ua)) ? (`ie ie${parseFloat(navigator.appVersion.split("MSIE")[1])}`) : is('firefox/2') ? `${g} ff2` : is('firefox/3.5') ? `${g} ff3 ff3_5` : is('firefox/3') ? `${g} ff3` : is('gecko/') ? g : is('opera') ? o + (/version\/(\d+)/.test(ua) ? ` ${o}${RegExp.jQuery1}` : (/opera(\s|\/)(\d+)/.test(ua) ? ` ${o}${RegExp.jQuery2}` : '')) : is('konqueror') ? 'konqueror' : is('chrome') ? `${w} chrome` : is('iron') ? `${w} iron` : is('applewebkit/') ? `${w} ${s}${/version\/(\d+)/.test(ua) ? ` ${s}${RegExp.jQuery1}` : ''}` : is('mozilla/') ? g : '', is('j2me') ? 'mobile' : is('iphone') ? 'iphone' : is('ipod') ? 'ipod' : is('mac') ? 'mac' : is('darwin') ? 'mac' : is('webtv') ? 'webtv' : is('win') ? 'win' : is('freebsd') ? 'freebsd' : (is('x11') || is('linux')) ? 'linux' : '', 'js']; 301 302 c = b.join(' '); 303 304 if ($.browser.mobile) { 305 c += ' mobile'; 306 } 307 308 if (hasTouch) { 309 c += ' touch'; 310 } 311 312 h.className += ` ${c}`; 313 314 // Edge Detect 315 const isEdge = /Edge/.test(navigator.userAgent); 316 317 if(isEdge) { 318 $('html').removeClass('chrome').addClass('edge'); 319 } 320 321 // Dark and Boxed Compatibility 322 if($('body').hasClass('dark')) { 323 $('html').addClass('dark'); 324 } 325 326 if($('body').hasClass('boxed')) { 327 $('html').addClass('boxed'); 328 } 329 330 } 331 332 }); 333 334 $.browserSelector(); 335 336 /* 337 Browser Workarounds 338 */ 339 if (/iPad|iPhone|iPod/.test(navigator.platform)) { 340
341 // iPad/Iphone/iPod Hover Workaround 342 $(document).ready($ => { 343 $('.thumb-info').attr('onclick', 'return true'); 344 }); 345 } 346 347 /* 348 Lazy Load Bacground Images 349 */ 350 351 // Check for IntersectionObserver support 352 if ('IntersectionObserver' in window) { 353 document.addEventListener("DOMContentLoaded", function() { 354 355 function handleIntersection(entries) { 356 entries.map((entry) => { 357 if (entry.isIntersecting) { 358 // Item has crossed our observation 359 // threshold - load src from data-src 360 entry.target.style.backgroundImage = "url('" + entry.target.dataset.bgSrc + "')"; 361 // Job done for this item - no need to watch it! 362 observer.unobserve(entry.target); 363 } 364 }); 365 } 366 367 const lazyLoadElements = document.querySelectorAll('.lazyload'); 368 const observer = new IntersectionObserver( 369 handleIntersection, { 370 rootMargin: "100px" 371 } 372 ); 373 lazyLoadElements.forEach(lazyLoadEl => observer.observe(lazyLoadEl)); 374 }); 375 } else { 376 // No interaction support? Load all background images automatically 377 const lazyLoadElements = document.querySelectorAll('.lazyload'); 378 lazyLoadElements.forEach(lazyLoadEl => { 379 lazyLoadEl.style.backgroundImage = "url('" + lazyLoadEl.dataset.bgSrc + "')"; 380 }); 381 } 382 383 /* 384 Tabs 385 */ 386 if( $('a[data-bs-toggle="tab"]').length ) { 387 $('a[data-bs-toggle="tab"]').on('shown.bs.tab', function({target}) { 388 const $tabPane = $($(target).attr('href')); 389 390 // Carousel Refresh 391 if($tabPane.length) { 392 $tabPane.find('.owl-carousel').trigger('refresh.owl.carousel'); 393 } 394 395 // Change Active Class 396 $(this).parents('.nav-tabs').find('.active').removeClass('active'); 397 $(this).addClass('active').parent().addClass('active'); 398 }); 399 400 if( window.location.hash ) { 401 $(window).on('load', () => { 402 if( window.location.hash !== '*' && $( window.location.hash ).get(0) ) { 403 new bootstrap.Tab( $('a.nav-link[href="'+ window.location.hash +'"]:not([data-hash])')[0] ).show(); 404 } 405 }); 406 } 407 } 408 409 /* 410 On Load Scroll 411 */ 412 if( !$('html').hasClass('disable-onload-scroll') && window.location.hash && !['#*'].includes( window.location.hash ) ) { 413 414 window.scrollTo(0, 0); 415 416 $(window).on('load', () => { 417 setTimeout(() => { 418 const target = window.location.hash; 419 let offset = ( $(window).width() < 768 ) ? 180 : 90; 420 421 if (!$(target).length) { 422 return; 423 } 424 425 if ( $("a[href$='" + window.location.hash + "']").is('[data-hash-offset]') ) { 426 offset = parseInt( $("a[href$='" + window.location.hash + "']").first().attr('data-hash-offset') ); 427 } else if ( $("html").is('[data-hash-offset]') ) { 428 offset = parseInt( $("html").attr('data-hash-offset') ); 429 } 430 431 if (isNaN(offset)) { 432 offset = 0; 433 } 434 435 $('body').addClass('scrolling'); 436 437 $('html, body').animate({ 438 scrollTop: $(target).offset().top - offset 439 }, 600, 'easeOutQuad', () => { 440 $('body').removeClass('scrolling'); 441 }); 442 }, 1); 443 }); 444 } 445 446 /* 447 * Text Rotator 448 */ 449 $.fn.extend({ 450 textRotator(options) { 451 452 const defaults = { 453 fadeSpeed: 500, 454 pauseSpeed: 100, 455 child: null 456 }; 457 458 var options = $.extend(defaults, options); 459 460 return this.each(function() { 461 const o = options; 462 const obj = $(this); 463 const items = $(obj.children(), obj); 464 items.each(function() { 465 $(this).hide(); 466 }) 467 if (!o.child) { 468 var next = $(obj).children(':first'); 469 } else { 470 var next = o.child; 471 } 472 $(next).fadeIn(o.fadeSpeed, () => { 473 $(next).delay(o.pauseSpeed).fadeOut(o.fadeSpeed, function() { 474 let next = $(this).next(); 475 if (next.length == 0) { 476 next = $(obj).children(':first'); 477 } 478 $(obj).textRotator({ 479 child: next, 480 fadeSpeed: o.fadeSpeed, 481 pauseSpeed: o.pauseSpeed 482 }); 483 }) 484 }); 485 }); 486 } 487 }); 488 489 /* 490 * Notice Top bar 491 */ 492 const $noticeTopBar = { 493 $wrapper: $('.notice-top-bar'), 494 $closeBtn: $('.notice-top-bar-close'), 495 $header: $('#header'), 496 $body: $('.body'), 497 init() { 498 const self = this; 499 500 if( !$.cookie('portoNoticeTopBarClose') ) { 501 self 502 .build() 503 .events(); 504 } else { 505 self.$wrapper.parent().prepend( '<!-- Notice Top Bar removed by cookie -->' ); 506 self.$wrapper.remove(); 507 } 508 509 return this; 510 }, 511 build() { 512 const self = this; 513 514 $(window).on('load', () => { 515 setTimeout(() => { 516 self.$body.css({ 517 'margin-top': self.$wrapper.outerHeight(), 518 'transition': 'ease margin 300ms' 519 });
520 521 $('#noticeTopBarContent').textRotator({ 522 fadeSpeed: 500, 523 pauseSpeed: 5000 524 }); 525 526 if( ['absolute', 'fixed'].includes( self.$header.css('position') ) ) { 527 self.$header.css({ 528 'top': self.$wrapper.outerHeight(), 529 'transition': 'ease top 300ms' 530 }); 531 } 532 533 $(window).trigger('notice.top.bar.opened'); 534 535 }, 1000); 536 }); 537 538 return this; 539 }, 540 events() { 541 const self = this; 542 543 self.$closeBtn.on('click', e => { 544 e.preventDefault(); 545 546 self.$body.animate({ 547 'margin-top': 0, 548 }, 300, () => { 549 self.$wrapper.remove(); 550 self.saveCookie(); 551 }); 552 553 if( ['absolute', 'fixed'].includes( self.$header.css('position') ) ) { 554 self.$header.animate({ 555 top: 0 556 }, 300); 557 } 558 559 // When header has shrink effect 560 if( self.$header.hasClass('header-effect-shrink') ) { 561 self.$header.find('.header-body').animate({ 562 top: 0 563 }, 300); 564 } 565 566 $(window).trigger('notice.top.bar.closed'); 567 }); 568 569 return this; 570 }, 571 checkCookie() { 572 const self = this; 573 574 if( $.cookie('portoNoticeTopBarClose') ) { 575 return true; 576 } else { 577 return false; 578 } 579 580 return this; 581 }, 582 saveCookie() { 583 const self = this; 584 585 $.cookie('portoNoticeTopBarClose', true); 586 587 return this; 588 } 589 }; 590 591 if( $('.notice-top-bar').length ) { 592 $noticeTopBar.init(); 593 } 594 595 /* 596 * Image Hotspots 597 */ 598 if( $('.image-hotspot').length ) { 599 $('.image-hotspot') 600 .append('<span class="ring"></span>') 601 .append('<span class="circle"></span>'); 602 } 603 604 /* 605 * Reading Progress 606 */ 607 if( $('.progress-reading').length ) { 608 609 function updateScrollProgress() { 610 const pixels = $(document).scrollTop(); 611 pageHeight = $(document).height() - $(window).height() 612 progress = 100 * pixels / pageHeight; 613 614 $('.progress-reading .progress-bar').width(parseInt(progress) + "%"); 615 } 616 617 $(document).on('scroll ready', () => { 618 updateScrollProgress(); 619 }); 620 621 $(document).ready(() => { 622 $(window).afterResize(() => { 623 updateScrollProgress(); 624 }); 625 }); 626 627 } 628 629 /* 630 * Page Transition 631 */ 632 if( $('body[data-plugin-page-transition]').length ) { 633 634 let link_click = false; 635 636 $(document).on('click', 'a', function(e){ 637 link_click = $(this); 638 }); 639 640 $(window).on("beforeunload", e => { 641 if( typeof link_click === 'object' ) { 642 const href = link_click.attr('href'); 643 644 if( href.indexOf('mailto:') != 0 && href.indexOf('tel:') != 0 && !link_click.data('rm-from-transition') ) { 645 $('body').addClass('page-transition-active'); 646 } 647 } 648 }); 649 650 $(window).on("pageshow", ({persisted, originalEvent}) => { 651 if( persisted || originalEvent.persisted) { 652 if( $('html').hasClass('safari') ) { 653 window.location.reload(); 654 } 655 656 $('body').removeClass('page-transition-active'); 657 } 658 }); 659 } 660 661 /* 662 * Clone Element 663 */ 664 if( $('[data-clone-element]').length ) { 665 666 $('[data-clone-element]').each(function() { 667 668 const $el = $(this), content = $el.html(), qty = $el.attr('data-clone-element'); 669 670 for (let i = 0; i < qty; i++) { 671 $el.html($el.html() + content); 672 } 673 674 }); 675 676 } 677 678 if( $('[data-clone-element-to]').length ) { 679 680 $('[data-clone-element-to]').each(function() { 681 682 const $el = $(this); 683 const content = $el.html(); 684 const $to = $($el.attr('data-clone-element-to')); 685 686 $to.html($to.html() + content); 687 688 }); 689 690 } 691 692 /* 693 * Thumb Info Floating Caption 694 */ 695 $('.thumb-info-floating-caption').each(function() { 696 697 $(this) 698 .addClass('thumb-info-floating-element-wrapper') 699 .append( '<span class="thumb-info-floating-element thumb-info-floating-caption-title d-none">'+ $(this).data('title') +'</span>' ); 700 701 if( $(this).data('type') ) { 702 $('.thumb-info-floating-caption-title', $(this)) 703 .append( '<div class="thumb-info-floating-caption-type">'+ $(this).data('type') +'</div>' ) 704 .css({ 705 'padding-bottom' : 22 706 }); 707 } 708 709 if( $(this).hasClass('thumb-info-floating-caption-clean') ) { 710 $('.thumb-info-floating-element', $(this)).addClass('bg-transparent'); 711 } 712 713 }); 714 715 /* 716 * Thumb Info Floating Element 717 */ 718 if( $('.thumb-info-floating-element-wrapper').length ) { 719 720 if (typeof gsap !== 'undefined') { 721 722 $('.thumb-info-floating-element-wrapper').on('mouseenter', function({clientX, clientY}) { 723 724 if(!$(this).data('offset')) { 725 $(this).data('offset', 0); 726 } 727 728 const offset = parseInt($(this).data('offset')); 729 730 $('.thumb-info-floating-element-clone').remove(); 731 732 $('.thumb-info-floating-element', $(this)).clone().addClass('thumb-info-floating-element-clone p-fixed p-events-none').attr('style', 'transform: scale(0.1);').removeClass('d-none').appendTo('body'); 733 734 $('.thumb-info-floating-element-clone').css({ 735 left: clientX + (offset), 736 top: clientY + (offset) 737 }).fadeIn(300); 738 739 gsap.to('.thumb-info-floating-element-clone', 0.5, { 740 css: { 741 scaleX: 1, 742 scaleY: 1 743 } 744 }); 745 746 $(document).off('mousemove').on('mousemove', ({clientX, clientY}) => { 747 748 gsap.to('.thumb-info-floating-element-clone', 0.5, { 749 css: { 750 left: clientX + (offset), 751 top: clientY + (offset) 752 } 753 });
754 755 }); 756 757 }).on('mouseout', () => { 758 759 gsap.to('.thumb-info-floating-element-clone', 0.5, { 760 css: { 761 scaleX: 0.5, 762 scaleY: 0.5, 763 opacity: 0 764 } 765 }); 766 767 }); 768 769 } else { 770 theme.fn.showErrorMessage('Failed to Load File', 'Failed to load: GSAP - Include the following file(s): (vendor/gsap/gsap.min.js)'); 771 } 772 773 } 774 775 /* 776 * Thumb Info Direction Aware 777 */ 778 $(window).on('load', () => { 779 $('.thumb-info-wrapper-direction-aware').each( function() { 780 $(this).hoverdir({ 781 speed : 300, 782 easing : 'ease', 783 hoverDelay : 0, 784 inverse : false, 785 hoverElem: '.thumb-info-wrapper-overlay' 786 }); 787 }); 788 }); 789 790 /* 791 * Thumb Info Container Full 792 */ 793 $('.thumb-info-container-full-img').each(function() { 794 795 const $container = $(this); 796 797 $('[data-full-width-img-src]', $container).each(function() { 798 const uniqueId = 'img' + Math.floor(Math.random() * 10000); 799 $(this).attr('data-rel', uniqueId); 800 801 $container.append('<div style="background-image: url(' + $(this).attr('data-full-width-img-src') + ');" id="' + uniqueId + '" class="thumb-info-container-full-img-large opacity-0"></div>'); 802 }); 803 804 $('.thumb-info', $container).on('mouseenter', function(e){ 805 $('.thumb-info-container-full-img-large').removeClass('active'); 806 $('#' + $(this).attr('data-rel')).addClass('active'); 807 }); 808 809 }); 810 811 /* 812 * Toggle Text Click 813 */ 814 $('[data-toggle-text-click]').on('click', function () { 815 $(this).text(function(i, text){ 816 return text === $(this).attr('data-toggle-text-click') ? $(this).attr('data-toggle-text-click-alt') : $(this).attr('data-toggle-text-click'); 817 }); 818 }); 819 820 /* 821 * Toggle Class 822 */ 823 $('[data-toggle-class]').on('click', function (e) { 824 e.preventDefault(); 825 826 $(this).toggleClass( $(this).data('toggle-class') ); 827 }); 828 829 /* 830 * Shape Divider Aspect Ratio 831 */ 832 if( $('.shape-divider').length ) { 833 aspectRatioSVG(); 834 $(window).on('resize', () => { 835 aspectRatioSVG(); 836 }); 837 } 838 839 /* 840 * Shape Divider Animated 841 */ 842 if( $('.shape-divider-horizontal-animation').length ) { 843 theme.fn.intObs('.shape-divider-horizontal-animation', function(){ 844 for( let i = 0; i <= 1; i++ ) { 845 const svgClone = $(this).find('svg:nth-child(1)').clone(); 846 847 $(this).append( svgClone ) 848 } 849 850 $(this).addClass('start'); 851 }, {}); 852 } 853 854 /* 855 * Shape Divider - SVG Aspect Ratio 856 */ 857 function aspectRatioSVG() { 858 if( $(window).width() < 1950 ) { 859 $('.shape-divider svg[preserveAspectRatio]').each(function(){ 860 if( !$(this).parent().hasClass('shape-divider-horizontal-animation') ) { 861 $(this).attr('preserveAspectRatio', 'xMinYMin'); 862 } else { 863 $(this).attr('preserveAspectRatio', 'none'); 864 } 865 }); 866 } else { 867 $('.shape-divider svg[preserveAspectRatio]').each(function(){ 868 $(this).attr('preserveAspectRatio', 'none'); 869 }); 870 } 871 } 872 873 /* 874 * Content Switcher 875 */ 876 $('[data-content-switcher]').on('change', function(e, v) { 877 const switcherRel = ($(this).is(':checked') ? '1' : '2' ), switcherId = $(this).attr('data-content-switcher-content-id'); 878 879 $('[data-content-switcher-id=' + switcherId + ']').addClass('initialized').removeClass('active'); 880 881 const $activeEl = $('[data-content-switcher-id=' + switcherId + '][data-content-switcher-rel=' + switcherRel + ']'); 882 883 $activeEl.addClass('active'); 884 885 $activeEl.parent().css('height', $activeEl.height()); 886 }); 887 888 $('[data-content-switcher]').trigger('change'); 889 890 /* 891 * Dynamic Height 892 */ 893 var $window = $(window); 894 $window.on('resize dynamic.height.resize', () => { 895 $('[data-dynamic-height]').each(function(){ 896 const $this = $(this), values = JSON.parse($this.data('dynamic-height').replace(/'/g,'"').replace(';','')); 897 898 // XS 899 if( $window.width() < 576 ) { 900 $this.height( values[4] ); 901 } 902 903 // SM 904 if( $window.width() > 575 && $window.width() < 768 ) { 905 $this.height( values[3] ); 906 } 907 908 // MD 909 if( $window.width() > 767 && $window.width() < 992 ) { 910 $this.height( values[2] ); 911 } 912 913 // LG 914 if( $window.width() > 991 && $window.width() < 1200 ) { 915 $this.height( values[1] ); 916 } 917 918 // XS 919 if( $window.width() > 1199 ) { 920 $this.height( values[0] ); 921 } 922 }); 923 }); 924 925 // Mobile First Load 926 if( $window.width() < 992 ) { 927 $window.trigger('dynamic.height.resize'); 928 } 929 930 /* 931 * Video - Trigger Play 932 */ 933 if( $('[data-trigger-play-video]').length ) { 934 theme.fn.execOnceTroughEvent( '[data-trigger-play-video]', 'mouseover.trigger.play.video', function(){
935 const $video = $( $(this).data('trigger-play-video') ); 936 937 $(this).on('click', function(e){ 938 e.preventDefault(); 939 940 if( $(this).data('trigger-play-video-remove') == 'yes' ) { 941 $(this).animate({ 942 opacity: 0 943 }, 300, function(){ 944 $video[0].play(); 945 946 $(this).remove(); 947 }); 948 } else { 949 setTimeout(() => { 950 $video[0].play(); 951 },300); 952 } 953 }); 954 }); 955 } 956 957 /* 958 * Video - Auto Play 959 */ 960 if( $('video[data-auto-play]').length ) { 961 $(window).on('load', () => { 962 $('video[data-auto-play]').each(function(){ 963 const $video = $(this); 964 965 setTimeout(() => { 966 if( $( '#' + $video.attr('id') ).length ) { 967 if( $( '[data-trigger-play-video="#' + $video.attr('id') + '"]' ).data('trigger-play-video-remove') == 'yes' ) { 968 $( '[data-trigger-play-video="#' + $video.attr('id') + '"]' ).animate({ 969 opacity: 0 970 }, 300, () => { 971 $video[0].play(); 972 973 $( '[data-trigger-play-video="#' + $video.attr('id') + '"]' ).remove(); 974 }); 975 } else { 976 setTimeout(() => { 977 $video[0].play(); 978 },300); 979 } 980 } 981 }, 100); 982 983 }); 984 }); 985 } 986 987 /* 988 * Remove min height after the load of page 989 */ 990 if( $('[data-remove-min-height]').length ) { 991 $(window).on('load', () => { 992 $('[data-remove-min-height]').each(function(){ 993 $(this).css({ 994 'min-height': 0 995 }); 996 }); 997 }); 998 } 999 1000 /* 1001 * Title Border 1002 */ 1003 if($('[data-title-border]').length) { 1004 1005 const $pageHeaderTitleBorder = $('<span class="page-header-title-border"></span>'), $pageHeaderTitle = $('[data-title-border]'), $window = $(window); 1006 1007 $pageHeaderTitle.before($pageHeaderTitleBorder); 1008 1009 const setPageHeaderTitleBorderWidth = () => { 1010 $pageHeaderTitleBorder.width($pageHeaderTitle.width()); 1011 }; 1012 1013 $window.afterResize(() => { 1014 setPageHeaderTitleBorderWidth(); 1015 }); 1016 1017 setPageHeaderTitleBorderWidth(); 1018 1019 $pageHeaderTitleBorder.addClass('visible'); 1020 } 1021 1022 /* 1023 * Footer Reveal 1024 */ 1025 ($ => { 1026 const $footerReveal = { 1027 $wrapper: $('.footer-reveal'), 1028 init() { 1029 const self = this; 1030 1031 self.build(); 1032 self.events(); 1033 }, 1034 build() { 1035 const self = this, footer_height = self.$wrapper.outerHeight(true), window_height = ( $(window).height() - $('.header-body').height() ); 1036 1037 if( footer_height > window_height ) { 1038 $('#footer').removeClass('footer-reveal'); 1039 $('body').css('margin-bottom', 0); 1040 } else { 1041 $('#footer').addClass('footer-reveal'); 1042 $('body').css('margin-bottom', footer_height); 1043 } 1044 1045 }, 1046 events() { 1047 const self = this, $window = $(window); 1048 1049 $window.on('load', () => { 1050 $window.afterResize(() => { 1051 self.build(); 1052 }); 1053 }); 1054 } 1055 }; 1056 1057 if( $('.footer-reveal').length ) { 1058 $footerReveal.init(); 1059 } 1060 })(jQuery); 1061 1062 /* 1063 * Re-Init Plugin 1064 */ 1065 if( $('[data-reinit-plugin]').length ) { 1066 $('[data-reinit-plugin]').on('click', function(e) { 1067 e.preventDefault(); 1068 1069 const pluginInstance = $(this).data('reinit-plugin'), pluginFunction = $(this).data('reinit-plugin-function'), pluginElement = $(this).data('reinit-plugin-element'), pluginOptions = theme.fn.getOptions($(this).data('reinit-plugin-options')); 1070 1071 $( pluginElement ).data( pluginInstance ).destroy(); 1072 1073 setTimeout(() => { 1074 theme.fn.execPluginFunction(pluginFunction, $( pluginElement ), pluginOptions); 1075 }, 1000); 1076 1077 }); 1078 } 1079 1080 /* 1081 * Simple Copy To Clipboard 1082 */ 1083 if( $('[data-copy-to-clipboard]').length ) { 1084 theme.fn.intObs( '[data-copy-to-clipboard]', function(){ 1085 const $this = $(this); 1086
1087 $this.wrap( '<div class="copy-to-clipboard-wrapper position-relative"></div>' ); 1088 1089 const $copyButton = $('<a href="#" class="btn btn-primary btn-px-2 py-1 text-0 position-absolute top-8 right-8">COPY</a>'); 1090 $this.parent().prepend( $copyButton ); 1091 1092 $copyButton.on('click', function(e){ 1093 e.preventDefault(); 1094 1095 const $btn = $(this), $temp = $('<textarea class="d-block opacity-0" style="height: 0;">'); 1096 1097 $btn.parent().append( $temp ); 1098 1099 $temp.val( $this.text() ); 1100 1101 $temp[0].select(); 1102 $temp[0].setSelectionRange(0, 99999); 1103 1104 document.execCommand("copy"); 1105 1106 $btn.addClass('copied'); 1107 setTimeout(() => { 1108 $btn.removeClass('copied'); 1109 }, 1000); 1110 1111 $temp.remove(); 1112 }); 1113 }, { 1114 rootMargin: '0px 0px 0px 0px' 1115 } ); 1116 } 1117 1118 /* 1119 * Marquee 1120 */ 1121 if( $('.marquee').length && $.isFunction($.fn.marquee) ) { 1122 $('.marquee').marquee({ 1123 duration: 5000, 1124 gap: 0, 1125 delayBeforeStart: 0, 1126 direction: 'left', 1127 duplicated: true 1128 }); 1129 } 1130 1131 /* 1132 * Style Switcher Open Loader Button 1133 */ 1134 if( $('.style-switcher-open-loader').length ) { 1135 1136 const urlParams = new URLSearchParams(window.location.search); 1137 1138 let hideStyleSwitcherAfterShow = false; 1139 1140 $('.style-switcher-open-loader').on('click', function(e){ 1141 e.preventDefault(); 1142 1143 const $this = $(this); 1144 1145 // Add Spinner to icon 1146 $this.addClass('style-switcher-open-loader-loading'); 1147 1148 const basePath = $(this).data('base-path'), skinSrc = $(this).data('skin-src'); 1149 1150 const script1 = document.createElement("script"); 1151 script1.src = basePath + "master/style-switcher/style.switcher.localstorage.js"; 1152 1153 const script2 = document.createElement("script"); 1154 script2.src = basePath + "master/style-switcher/style.switcher.js"; 1155 script2.id = "styleSwitcherScript"; 1156 script2.setAttribute('data-base-path', basePath); 1157 script2.setAttribute('data-skin-src', skinSrc); 1158 1159 script2.onload = () => { 1160 setTimeout(() => { 1161 // Trigger a click to open the style switcher sidebar 1162 function checkIfReady() { 1163 if( !$('.style-switcher-open').length ) { 1164 window.setTimeout(checkIfReady, 100); 1165 } else { 1166 $('.style-switcher-open').trigger('click'); 1167 1168 if (hideStyleSwitcherAfterShow) { 1169 setTimeout(() => { 1170 $('.style-switcher-open').trigger('click'); 1171 }, 2000); 1172 } 1173 } 1174 } 1175 checkIfReady(); 1176 1177 }, 500); 1178 } 1179 1180 document.body.appendChild(script1); 1181 document.body.appendChild(script2); 1182 1183 }); 1184 1185 let htmlDataOptions = $('html').data('style-switcher-options'); 1186 let showSwitcher = false; 1187 1188 if(htmlDataOptions) { 1189 htmlDataOptions = htmlDataOptions.replace(/'/g, '"'); 1190 1191 if (JSON.parse(htmlDataOptions).showSwitcher) { 1192 showSwitcher = true; 1193 } 1194 1195 if (JSON.parse(htmlDataOptions).hideStyleSwitcherAfterShow) { 1196 hideStyleSwitcherAfterShow = true; 1197 } 1198 } 1199 1200 if (urlParams.has("showStyleSwitcher")) { 1201 showSwitcher = true; 1202 } 1203 1204 if (urlParams.has("hideStyleSwitcherAfterShow")) { 1205 hideStyleSwitcherAfterShow = true; 1206 } 1207 1208 if (showSwitcher) { 1209 $('.style-switcher-open-loader').trigger('click'); 1210 } 1211 1212 } 1213 1214})).apply(this, [ window.theme, jQuery ]); 1215 1216// Animate 1217(((theme = {}, $) => { 1218 const instanceName = '__animate'; 1219 1220 class PluginAnimate { 1221 constructor($el, opts) { 1222 return this.initialize($el, opts); 1223 } 1224 1225 initialize($el, opts) { 1226 if ($el.data(instanceName)) { 1227 return this; 1228 } 1229 1230 this.$el = $el; 1231 1232 this 1233 .setData() 1234 .setOptions(opts) 1235 .build(); 1236 1237 return this; 1238 } 1239 1240 setData() { 1241 this.$el.data(instanceName, this); 1242 1243 return this; 1244 } 1245 1246 setOptions(opts) { 1247 this.options = $.extend(true, {}, PluginAnimate.defaults, opts, { 1248 wrapper: this.$el 1249 }); 1250 1251 return this; 1252 } 1253 1254 build() { 1255 const self = this; 1256 1257 // Flag Class Only 1258 // - Useful for simple animations like hightlight 1259 // - Less ourwork and memory 1260 if( self.options.flagClassOnly ) {
1261 const delay = self.options.wrapper.attr('data-appear-animation-delay') ? self.options.wrapper.attr('data-appear-animation-delay') : self.options.delay; 1262 1263 self.options.wrapper.css({ 1264 'animation-delay': delay + 'ms', 1265 'transition-delay': delay + 'ms' 1266 }); 1267 self.options.wrapper.addClass( self.options.wrapper.attr('data-appear-animation') ); 1268 1269 return this; 1270 } 1271 1272 if($('body').hasClass('loading-overlay-showing')) { 1273 $(window).on('loading.overlay.ready', () => { 1274 self.animate(); 1275 }); 1276 } else { 1277 self.animate(); 1278 } 1279 1280 return this; 1281 } 1282 1283 animate() { 1284 const self = this; 1285 const $el = this.options.wrapper; 1286 let delay = 0; 1287 let duration = this.options.duration; 1288 const elTopDistance = $el.offset().top; 1289 const windowTopDistance = $(window).scrollTop(); 1290 1291 // If has appear animation elements inside a SVG. 1292 // Intersection Observer API do not check elements inside SVG's, so we need initialize trough top parent SVG 1293 if( $el.data('appear-animation-svg') ) { 1294 $el.find('[data-appear-animation]').each(function(){ 1295 const $this = $(this); 1296 let opts; 1297 1298 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 1299 if (pluginOptions) 1300 opts = pluginOptions; 1301 1302 $this.themePluginAnimate(opts); 1303 }); 1304 1305 return this; 1306 } 1307 1308 // No animation at the first load of page. This is good for performance 1309 if( self.options.firstLoadNoAnim ) { 1310 $el.removeClass('appear-animation'); 1311 1312 // Inside Carousel 1313 if( $el.closest('.owl-carousel').get(0) ) { 1314 setTimeout(() => { 1315 $el.closest('.owl-carousel').on('change.owl.carousel', () => { 1316 self.options.firstLoadNoAnim = false; 1317 $el.removeData('__animate'); 1318 $el.themePluginAnimate( self.options ); 1319 }); 1320 }, 500); 1321 } 1322 1323 return this; 1324 } 1325 1326 $el.addClass('appear-animation animated'); 1327 1328 if (!$('html').hasClass('no-csstransitions') && $(window).width() > self.options.minWindowWidth && elTopDistance >= windowTopDistance || self.options.forceAnimation == true) { 1329 delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay); 1330 duration = ($el.attr('data-appear-animation-duration') ? $el.attr('data-appear-animation-duration') : self.options.duration); 1331 1332 if (duration != '750ms') { 1333 $el.css('animation-duration', duration); 1334 } 1335 1336 $el.css('animation-delay', delay + 'ms'); 1337 $el.addClass($el.attr('data-appear-animation') + ' appear-animation-visible'); 1338 1339 $el.trigger('animation:show'); 1340 1341 } else { 1342 $el.addClass('appear-animation-visible'); 1343 } 1344 1345 return this; 1346 } 1347 } 1348 1349 PluginAnimate.defaults = { 1350 accX: 0, 1351 accY: -80, 1352 delay: 100, 1353 duration: '750ms', 1354 minWindowWidth: 0, 1355 forceAnimation: false, 1356 flagClassOnly: false 1357 }; 1358 1359 // expose to scope 1360 $.extend(theme, { 1361 PluginAnimate 1362 }); 1363 1364 // jquery plugin 1365 $.fn.themePluginAnimate = function(opts) { 1366 return this.map(function() { 1367 const $this = $(this); 1368 1369 if ($this.data(instanceName)) { 1370 return $this.data(instanceName); 1371 } else { 1372 return new PluginAnimate($this, opts); 1373 } 1374 1375 }); 1376 }; 1377})).apply(this, [window.theme, jQuery]); 1378 1379// Animated Content 1380(((theme = {}, $) => { 1381 const instanceName = '__animatedContent'; 1382 1383 class PluginAnimatedContent { 1384 constructor($el, opts) { 1385 return this.initialize($el, opts); 1386 } 1387 1388 initialize($el, opts) { 1389 if ($el.data(instanceName)) { 1390 return this; 1391 } 1392 1393 const self = this; 1394 1395 this.$el = $el; 1396 this.initialText = $el.text(); 1397 1398 this 1399 .setData() 1400 .setOptions(opts) 1401 .build() 1402 .events(); 1403 1404 return this; 1405 } 1406 1407 setData() { 1408 this.$el.data(instanceName, this); 1409 1410 return this; 1411 } 1412 1413 setOptions(opts) { 1414 this.options = $.extend(true, {}, PluginAnimatedContent.defaults, opts, { 1415 wrapper: this.$el 1416 }); 1417 1418 return this; 1419 } 1420 1421 build() { 1422 const self = this; 1423 1424 if( $(window).width() < self.options.minWindowWidth ) { 1425 return this; 1426 } 1427 1428 if( self.options.firstLoadNoAnim ) { 1429 self.$el.css({ 1430 visibility: 'visible' 1431 }); 1432 1433 // Inside Carousel 1434 if( self.$el.closest('.owl-carousel').get(0) ) { 1435 setTimeout(() => { 1436 self.$el.closest('.owl-carousel').on('change.owl.carousel', () => { 1437 self.options.firstLoadNoAnim = false; 1438 self.build(); 1439 });
1440 }, 500); 1441 } 1442 1443 return this; 1444 } 1445 1446 // Set Min Height to avoid flicking issues 1447 self.setMinHeight(); 1448 1449 // Letter 1450 if( self.options.contentType == 'letter' ) { 1451 1452 self.$el.addClass('initialized'); 1453 1454 const letters = self.$el.text().split(''); 1455 1456 self.$el.text(''); 1457 1458 // Type Writer 1459 if( self.options.animationName == 'typeWriter' ) { 1460 self.$el.append( '<span class="letters-wrapper"></span><span class="typeWriter"></pre>' ); 1461 1462 let index = 0; 1463 1464 setTimeout(() => { 1465 1466 const timeout = () => { 1467 const st = setTimeout(() => { 1468 const letter = letters[index]; 1469 1470 self.$el.find('.letters-wrapper').append( '<span class="letter '+ ( self.options.letterClass ? self.options.letterClass + ' ' : '' ) +'">' + letter + '</span>' ); 1471 1472 index++; 1473 timeout(); 1474 }, self.options.animationSpeed); 1475 1476 if( index >= letters.length ) { 1477 clearTimeout(st); 1478 } 1479 }; 1480 timeout(); 1481 1482 }, self.options.startDelay); 1483 1484 // Class Animation 1485 } else { 1486 setTimeout(() => { 1487 for( let i = 0; i < letters.length; i++ ) { 1488 const letter = letters[i]; 1489 1490 self.$el.append( '<span class="animated-letters-wrapper ' + self.options.wrapperClass + '"><span class="animated-letters-item letter '+ ( self.options.letterClass ? self.options.letterClass + ' ' : '' ) + self.options.animationName +' animated" style="animation-delay: '+ ( i * self.options.animationSpeed ) +'ms;">' + ( letter == ' ' ? ' ' : letter ) + '</span></span>' ); 1491 1492 } 1493 }, self.options.startDelay); 1494 } 1495 1496 // Words 1497 } else if( self.options.contentType == 'word' ) { 1498 const words = self.$el.text().split(" "); 1499 let delay = self.options.startDelay; 1500 1501 self.$el.empty(); 1502 1503 $.each(words, (i, v) => { 1504 self.$el.append( $('<span class="animated-words-wrapper ' + self.options.wrapperClass + '">').html('<span class="animated-words-item ' + self.options.wordClass + ' appear-animation" data-appear-animation="' + self.options.animationName + '" data-appear-animation-delay="' + delay + '">' + v + ' </span>') );
1505 delay = delay + self.options.animationSpeed; 1506 }); 1507 1508 if ($.isFunction($.fn['themePluginAnimate']) && $('.animated-words-item[data-appear-animation]').length) { 1509 theme.fn.dynIntObsInit( '.animated-words-item[data-appear-animation]', 'themePluginAnimate', theme.PluginAnimate.defaults ); 1510 } 1511 1512 self.$el.addClass('initialized'); 1513 } 1514 1515 return this; 1516 } 1517 1518 setMinHeight() { 1519 const self = this; 1520 1521 // if it's inside carousel 1522 if( self.$el.closest('.owl-carousel').get(0) ) { 1523 self.$el.closest('.owl-carousel').addClass('d-block'); 1524 self.$el.css( 'min-height', self.$el.height() ); 1525 self.$el.closest('.owl-carousel').removeClass('d-block'); 1526 } else { 1527 self.$el.css( 'min-height', self.$el.height() ); 1528 } 1529 1530 return this; 1531 } 1532 1533 destroy() { 1534 const self = this; 1535 1536 self.$el 1537 .html( self.initialText ) 1538 .css( 'min-height', '' ); 1539 1540 return this; 1541 } 1542 1543 events() { 1544 const self = this; 1545 1546 // Destroy 1547 self.$el.on('animated.letters.destroy', () => { 1548 self.destroy(); 1549 }); 1550 1551 // Initialize 1552 self.$el.on('animated.letters.initialize', () => { 1553 self.build(); 1554 }); 1555 1556 return this; 1557 } 1558 } 1559 1560 PluginAnimatedContent.defaults = { 1561 contentType: 'letter', 1562 animationName: 'fadeIn', 1563 animationSpeed: 50, 1564 startDelay: 500, 1565 minWindowWidth: 768, 1566 letterClass: '', 1567 wordClass: '', 1568 wrapperClass: '' 1569 }; 1570 1571 // expose to scope 1572 $.extend(theme, { 1573 PluginAnimatedContent 1574 }); 1575 1576 // jquery plugin 1577 $.fn.themePluginAnimatedContent = function(opts) { 1578 return this.map(function() { 1579 const $this = $(this); 1580 1581 if ($this.data(instanceName)) { 1582 return $this.data(instanceName); 1583 } else { 1584 return new PluginAnimatedContent($this, opts); 1585 } 1586 1587 }); 1588 } 1589})).apply(this, [window.theme, jQuery]); 1590 1591// Before / After 1592(((theme = {}, $) => { 1593 const instanceName = '__beforeafter'; 1594 1595 class PluginBeforeAfter { 1596 constructor($el, opts) { 1597 return this.initialize($el, opts); 1598 } 1599 1600 initialize($el, opts) { 1601 this.$el = $el; 1602 1603 this 1604 .setData() 1605 .setOptions(opts) 1606 .build(); 1607 1608 return this; 1609 } 1610 1611 setData() { 1612 this.$el.data(instanceName, this); 1613 1614 return this; 1615 } 1616 1617 setOptions(opts) { 1618 this.options = $.extend(true, {}, PluginBeforeAfter.defaults, opts, { 1619 wrapper: this.$el 1620 }); 1621 1622 return this; 1623 } 1624 1625 build() { 1626 1627 if ($.isFunction($.fn.twentytwenty)) { 1628 1629 const self = this; 1630 1631 self.options.wrapper.waitForImages(() => { 1632 self.options.wrapper.twentytwenty(self.options); 1633 }); 1634 1635 } else { 1636 1637 theme.fn.showErrorMessage('Failed to Load File', 'Failed to load: twentytwenty - Include the following file(s): (vendor/twentytwenty/css/twentytwenty.css, vendor/twentytwenty/js/jquery.event.move.js, vendor/twentytwenty/js/jquery.twentytwenty.js)'); 1638 1639 } 1640 1641 return this; 1642 1643 } 1644 } 1645 1646 PluginBeforeAfter.defaults = { 1647 forceInit: true, 1648 default_offset_pct: 0.5, 1649 orientation: 'horizontal', 1650 before_label: 'Before', 1651 after_label: 'After', 1652 no_overlay: false, 1653 move_slider_on_hover: false, 1654 move_with_handle_only: true, 1655 click_to_move: false 1656 }; 1657 1658 // expose to scope 1659 $.extend(theme, { 1660 PluginBeforeAfter 1661 }); 1662 1663 // jquery plugin 1664 $.fn.themePluginBeforeAfter = function(opts) { 1665 return this.map(function() { 1666 const $this = $(this); 1667 1668 if ($this.data(instanceName)) { 1669 return $this.data(instanceName); 1670 } else { 1671 return new PluginBeforeAfter($this, opts); 1672 } 1673 1674 }); 1675 } 1676})).apply(this, [window.theme, jQuery]); 1677 1678// Carousel Light 1679(((theme = {}, $) => { 1680 const instanceName = '__carouselLight'; 1681 1682 class PluginCarouselLight { 1683 constructor($el, opts) { 1684 return this.initialize($el, opts); 1685 } 1686 1687 initialize($el, opts) { 1688 if ($el.data(instanceName)) { 1689 return this; 1690 } 1691 1692 this.$el = $el; 1693 this.clickFlag = true; 1694 1695 this 1696 .setData() 1697 .setOptions(opts) 1698 .build() 1699 .owlNav() 1700 .owlDots() 1701 .autoPlay() 1702 .events(); 1703 1704 return this; 1705 } 1706 1707 setData() { 1708 this.$el.data(instanceName, this); 1709 1710 return this; 1711 } 1712 1713 setOptions(opts) { 1714 this.options = $.extend(true, {}, PluginCarouselLight.defaults, opts, { 1715 wrapper: this.$el 1716 }); 1717 1718 return this; 1719 } 1720 1721 build() { 1722 const self = this; 1723 1724 self.$el 1725 .css('opacity', 1) 1726 .find('.owl-item:first-child') 1727 .addClass('active'); 1728 1729 self.$el.trigger('initialized.owl.carousel'); 1730 1731 // Carousel Navigate By ID and item index 1732 self.carouselNavigate(); 1733 1734 return this; 1735 } 1736 1737 changeSlide($nextSlide) { 1738 const self = this, $prevSlide = self.$el.find('.owl-item.active'); 1739 1740 self.$el.find('.owl-item.active').addClass('removing'); 1741 1742 $prevSlide 1743 .removeClass('fadeIn') 1744 .addClass( 'fadeOut animated' ); 1745 1746 setTimeout(() => { 1747 setTimeout(() => { 1748 $prevSlide.removeClass('active'); 1749 }, 400); 1750 1751 $nextSlide 1752 .addClass('active') 1753 .removeClass('fadeOut') 1754 .addClass( 'fadeIn animated' ); 1755 1756 }, 200); 1757 1758 // Dots 1759 self.$el 1760 .find('.owl-dot') 1761 .removeClass('active') 1762 .eq( $nextSlide.index() ) 1763 .addClass('active'); 1764 1765 self.$el.trigger({ 1766 type: 'change.owl.carousel', 1767 nextSlideIndex: $nextSlide.index(), 1768 prevSlideIndex: $prevSlide.index() 1769 }); 1770 1771 setTimeout(() => { 1772 self.$el.trigger({ 1773 type: 'changed.owl.carousel', 1774 nextSlideIndex: $nextSlide.index(), 1775 prevSlideIndex: $prevSlide.index() 1776 }); 1777 }, 500); 1778 } 1779 1780 owlNav() { 1781 const self = this, $owlNext = self.$el.find('.owl-next'), $owlPrev = self.$el.find('.owl-prev'); 1782 1783 $owlPrev.on('click', e => { 1784 e.preventDefault(); 1785 1786 if( self.options.disableAutoPlayOnClick ) { 1787 window.clearInterval(self.autoPlayInterval); 1788 } 1789 1790 if( self.avoidMultipleClicks() ) { 1791 return false; 1792 } 1793
1794 self.owlPrev(); 1795 }); 1796 1797 $owlNext.on('click', e => { 1798 e.preventDefault(); 1799 1800 if( self.options.disableAutoPlayOnClick ) { 1801 window.clearInterval(self.autoPlayInterval); 1802 } 1803 1804 if( self.avoidMultipleClicks() ) { 1805 return false; 1806 } 1807 1808 self.owlNext(); 1809 }); 1810 1811 return this; 1812 } 1813 1814 owlDots() { 1815 const self = this, $owlDot = self.$el.find('.owl-dot'); 1816 1817 $owlDot.on('click', function(e){ 1818 let $this = $(this); 1819 1820 e.preventDefault(); 1821 1822 if( self.options.disableAutoPlayOnClick ) { 1823 window.clearInterval(self.autoPlayInterval); 1824 } 1825 1826 if( self.avoidMultipleClicks() ) { 1827 return false; 1828 } 1829 1830 const dotIndex = $(this).index(); 1831 1832 // Do nothing if respective dot slide is active/showing 1833 if( $this.hasClass('active') ) { 1834 return false; 1835 } 1836 1837 self.changeSlide( self.$el.find('.owl-item').eq( dotIndex ) ); 1838 }); 1839 1840 return this; 1841 } 1842 1843 owlPrev() { 1844 const self = this; 1845 1846 if( self.$el.find('.owl-item.active').prev().get(0) ) { 1847 self.changeSlide( self.$el.find('.owl-item.active').prev() ); 1848 } else { 1849 self.changeSlide( self.$el.find('.owl-item:last-child') ); 1850 } 1851 } 1852 1853 owlNext() { 1854 const self = this; 1855 1856 if( self.$el.find('.owl-item.active').next().get(0) ) { 1857 self.changeSlide( self.$el.find('.owl-item.active').next() ); 1858 } else { 1859 self.changeSlide( self.$el.find('.owl-item').eq(0) ); 1860 } 1861 } 1862 1863 avoidMultipleClicks() { 1864 const self = this; 1865 1866 if( !self.clickFlag ) { 1867 return true; 1868 } 1869 1870 if( self.clickFlag ) { 1871 self.clickFlag = false; 1872 setTimeout(() => { 1873 self.clickFlag = true; 1874 }, 1000); 1875 } 1876 1877 return false; 1878 } 1879 1880 autoPlay() { 1881 const self = this, $el = this.options.wrapper; 1882 1883 if( self.options.autoplay ) { 1884 self.autoPlayInterval = window.setInterval(() => { 1885 self.owlNext(); 1886 }, self.options.autoplayTimeout); 1887 } 1888 1889 return this; 1890 } 1891 1892 carouselNavigate() { 1893 const self = this, $el = this.options.wrapper, $carousel = $el; 1894 1895 if( $('[data-carousel-navigate]').get(0) ) { 1896 $('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').each(function(){ 1897 const $this = $(this), hasCarousel = $( $this.data('carousel-navigate-id') ).get(0), toIndex = $this.data('carousel-navigate-to'); 1898 1899 if( hasCarousel ) { 1900 1901 $this.on('click', () => { 1902 1903 if( self.options.disableAutoPlayOnClick ) { 1904 window.clearInterval(self.autoPlayInterval); 1905 } 1906 1907 self.changeSlide( self.$el.find('.owl-item').eq( parseInt(toIndex) - 1 ) ); 1908 }); 1909 1910 } 1911 }); 1912 1913 $el.on('change.owl.carousel', e => { 1914 $('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').removeClass('active'); 1915 }); 1916 1917 $el.on('changed.owl.carousel', ({nextSlideIndex}) => { 1918 $('[data-carousel-navigate-id="#'+ $el.attr('id') +'"][data-carousel-navigate-to="'+ ( nextSlideIndex + 1 ) +'"]').addClass('active'); 1919 }); 1920 } 1921 1922 return this; 1923 } 1924 1925 events() { 1926 const self = this; 1927 1928 self.$el.on('change.owl.carousel', event => { 1929 1930 // Hide elements inside carousel 1931 self.$el.find('[data-appear-animation]:not(.background-image-wrapper), [data-plugin-animated-letters]').addClass('invisible'); 1932 1933 // Animated Letters 1934 self.$el.find('[data-plugin-animated-letters]').trigger('animated.letters.destroy'); 1935 1936 // Remove "d-none" class before show the element. This is useful when using background images inside a carousel. Like ken burns effect 1937 self.$el.find('.owl-item:not(.active) [data-carousel-onchange-show]').removeClass('d-none'); 1938 1939 }); 1940 1941 self.$el.on('changed.owl.carousel', event => { 1942 setTimeout(() => { 1943 1944 // Appear Animation 1945 if( self.$el.find('.owl-item.cloned [data-appear-animation]').get(0) ) { 1946 self.$el.find('.owl-item.cloned [data-appear-animation]').each(function() { 1947 const $this = $(this); 1948 let opts; 1949 1950 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 1951 if (pluginOptions) 1952 opts = pluginOptions; 1953 1954 $this.themePluginAnimate(opts); 1955 }); 1956 } 1957 1958 // Show elements inside carousel 1959 self.$el.find('.owl-item.active [data-appear-animation]:not(.background-image-wrapper), [data-plugin-animated-letters]').removeClass('invisible'); 1960 1961 // Animated Letters 1962 self.$el.find('.owl-item.active [data-plugin-animated-letters]').trigger('animated.letters.initialize'); 1963
1964 // Background Video 1965 self.$el.find('.owl-item.cloned.active [data-plugin-video-background]').trigger('video.background.initialize'); 1966 1967 }, 500); 1968 1969 }); 1970 1971 if( self.options.swipeEvents ) { 1972 self.$el.swipe({ 1973 swipe(event, direction, distance, duration, fingerCount, fingerData) { 1974 switch ( direction ) { 1975 case 'right': 1976 self.owlPrev(); 1977 break; 1978 1979 case 'left': 1980 self.owlNext(); 1981 break; 1982 } 1983 }, 1984 allowPageScroll: "vertical" 1985 }); 1986 } 1987 } 1988 } 1989 1990 PluginCarouselLight.defaults = { 1991 autoplay: true, 1992 autoplayTimeout: 7000, 1993 disableAutoPlayOnClick: true, 1994 swipeEvents: true 1995 }; 1996 1997 // expose to scope 1998 $.extend(theme, { 1999 PluginCarouselLight 2000 }); 2001 2002 // jquery plugin 2003 $.fn.themePluginCarouselLight = function(opts) { 2004 return this.map(function() { 2005 const $this = $(this); 2006 2007 if ($this.data(instanceName)) { 2008 return $this.data(instanceName); 2009 } else { 2010 return new PluginCarouselLight($this, opts); 2011 } 2012 2013 }); 2014 }; 2015})).apply(this, [window.theme, jQuery]); 2016 2017// Carousel 2018(((theme = {}, $) => { 2019 const instanceName = '__carousel'; 2020 2021 class PluginCarousel { 2022 constructor($el, opts) { 2023 return this.initialize($el, opts); 2024 } 2025 2026 initialize($el, opts) { 2027 if ($el.data(instanceName)) { 2028 return this; 2029 } 2030 2031 this.$el = $el; 2032 2033 // If has data-icon inside, initialize only after icons get rendered 2034 // Prevent flicking issues 2035 if( $el.find('[data-icon]').get(0) ) { 2036 const self = this; 2037 2038 $(window).on('icon.rendered', function(){ 2039 if ($el.data(instanceName)) { 2040 return this; 2041 } 2042 2043 setTimeout(() => { 2044 self 2045 .setData() 2046 .setOptions(opts) 2047 .build(); 2048 }, 1000); 2049 }); 2050 2051 return this; 2052 } 2053 2054 this 2055 .setData() 2056 .setOptions(opts) 2057 .build(); 2058 2059 return this; 2060 } 2061 2062 setData() { 2063 this.$el.data(instanceName, this); 2064 2065 return this; 2066 } 2067 2068 setOptions(opts) { 2069 this.options = $.extend(true, {}, PluginCarousel.defaults, opts, { 2070 wrapper: this.$el 2071 }); 2072 2073 return this; 2074 } 2075 2076 build() { 2077 if (!($.isFunction($.fn.owlCarousel))) { 2078 return this; 2079 } 2080 2081 const self = this, $el = this.options.wrapper; 2082 2083 // Add Theme Class 2084 $el.addClass('owl-theme'); 2085 2086 // Add Loading 2087 $el.addClass('owl-loading'); 2088 2089 // Force RTL according to HTML dir attribute 2090 if ($('html').attr('dir') == 'rtl') { 2091 this.options = $.extend(true, {}, this.options, { 2092 rtl: true 2093 }); 2094 } 2095 2096 if (this.options.items == 1) { 2097 this.options.responsive = {} 2098 } 2099 2100 if (this.options.items > 4) { 2101 this.options = $.extend(true, {}, this.options, { 2102 responsive: { 2103 1199: { 2104 items: this.options.items 2105 } 2106 } 2107 }); 2108 } 2109 2110 // Auto Height Fixes 2111 if (this.options.autoHeight) { 2112 const itemsHeight = []; 2113 2114 $el.find('.owl-item').each(function(){ 2115 if( $(this).hasClass('active') ) { 2116 itemsHeight.push( $(this).height() ); 2117 } 2118 }); 2119 2120 $(window).afterResize(() => { 2121 $el.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) ); 2122 }); 2123 2124 $(window).on('load', () => { 2125 $el.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) ); 2126 }); 2127 } 2128 2129 // Initialize OwlCarousel 2130 $el.owlCarousel(this.options).addClass('owl-carousel-init animated fadeIn'); 2131 2132 // Remove "animated fadeIn" class to prevent conflicts 2133 setTimeout(() => { 2134 $el.removeClass('animated fadeIn'); 2135 }, 1000); 2136 2137 // Owl Carousel Wrapper 2138 if( $el.closest('.owl-carousel-wrapper').get(0) ) { 2139 setTimeout(() => { 2140 $el.closest('.owl-carousel-wrapper').css({ 2141 height: '' 2142 }); 2143 }, 500); 2144 } 2145 2146 // Owl Carousel Loader 2147 if( $el.prev().hasClass('owl-carousel-loader') ) { 2148 $el.prev().remove(); 2149 } 2150 2151 // Nav Offset 2152 self.navigationOffsets(); 2153 2154 // Nav Outside 2155 if( $el.hasClass('nav-outside') ) { 2156 $(window).on('owl.carousel.nav.outside', () => { 2157 if( $(window).width() < 992 ) { 2158 self.options.stagePadding = 40; 2159 $el.addClass('stage-margin'); 2160 } else { 2161 self.options.stagePadding = 0; 2162 $el.removeClass('stage-margin'); 2163 } 2164 2165 $el.owlCarousel('destroy').owlCarousel( self.options ); 2166
2167 // Nav Offset 2168 self.navigationOffsets(); 2169 }); 2170 2171 // Window Resize 2172 $(window).on('load', () => { 2173 $(window).afterResize(() => { 2174 $(window).trigger('owl.carousel.nav.outside'); 2175 }); 2176 }); 2177 2178 // First Load 2179 $(window).trigger('owl.carousel.nav.outside'); 2180 } 2181 2182 // Nav style 5 (SVG Arrows) 2183 if( $el.hasClass('nav-svg-arrows-1') ) { 2184 const svg_arrow = '' + 2185 '<svg version="1.1" viewBox="0 0 15.698 8.706" width="17" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' + 2186 '<polygon stroke="#212121" stroke-width="0.1" fill="#212121" points="11.354,0 10.646,0.706 13.786,3.853 0,3.853 0,4.853 13.786,4.853 10.646,8 11.354,8.706 15.698,4.353 "/>' + 2187 '</svg>'; 2188 2189 $el.find('.owl-next, .owl-prev').append( svg_arrow ); 2190 } 2191 2192 // Sync 2193 if( $el.attr('data-sync') ) { 2194 $el.on('change.owl.carousel', ({namespace, property, relatedTarget}) => { 2195 if (namespace && property.name === 'position') { 2196 const target = relatedTarget.relative(property.value, true); 2197 $( $el.data('sync') ).owlCarousel('to', target, 300, true); 2198 } 2199 }); 2200 } 2201 2202 // Carousel Center Active Item 2203 if( $el.hasClass('carousel-center-active-item') ) { 2204 const itemsActive = $el.find('.owl-item.active'), indexCenter = Math.floor( ($el.find('.owl-item.active').length - 1) / 2 ), itemCenter = itemsActive.eq
2204(indexCenter); 2205 2206 itemCenter.addClass('current'); 2207 2208 $el.on('change.owl.carousel', event => { 2209 $el.find('.owl-item').removeClass('current'); 2210 2211 setTimeout(() => { 2212 const itemsActive = $el.find('.owl-item.active'), indexCenter = Math.floor( ($el.find('.owl-item.active').length - 1) / 2 ), itemCenter = itemsActive.eq(indexCenter); 2213 2214 itemCenter.addClass('current'); 2215 }, 100); 2216 }); 2217 2218 // Refresh 2219 $el.trigger('refresh.owl.carousel'); 2220 2221 } 2222 2223 // AnimateIn / AnimateOut Fix 2224 if( self.options.animateIn || self.options.animateOut ) { 2225 $el.on('change.owl.carousel', event => { 2226 2227 // Hide elements inside carousel 2228 $el.find('[data-appear-animation], [data-plugin-animated-letters]').addClass('d-none'); 2229 2230 // Animated Letters 2231 $el.find('[data-plugin-animated-letters]').trigger('animated.letters.destroy'); 2232 2233 // Remove "d-none" class before show the element. This is useful when using background images inside a carousel. Like ken burns effect 2234 $el.find('.owl-item:not(.active) [data-carousel-onchange-show]').removeClass('d-none'); 2235 2236 }); 2237 2238 $el.on('changed.owl.carousel', event => { 2239 setTimeout(() => { 2240 2241 // Appear Animation 2242 $el.find('[data-appear-animation]').each(function() { 2243 const $this = $(this); 2244 let opts; 2245 2246 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 2247 if (pluginOptions) 2248 opts = pluginOptions; 2249 2250 $this.themePluginAnimate(opts); 2251 }); 2252 2253 // Show elements inside carousel 2254 $el.find('.owl-item.active [data-appear-animation], [data-plugin-animated-letters]').removeClass('d-none'); 2255 2256 // Animated Letters 2257 $el.find('.owl-item.active [data-plugin-animated-letters]').trigger('animated.letters.initialize'); 2258 2259 // Background Video 2260 $el.find('.owl-item.cloned.active [data-plugin-video-background]').trigger('video.background.initialize'); 2261 2262 }, 10); 2263 2264 }); 2265 } 2266 2267 // data-icon inside carousel 2268 if( $el.find('[data-icon]').length ) { 2269 $el.on('change.owl.carousel drag.owl.carousel', () => { 2270 $el.find('.owl-item.cloned [data-icon]').each(function(){ 2271 const $this = $(this); 2272 let opts; 2273 2274 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 2275 if (pluginOptions) 2276 opts = pluginOptions; 2277 2278 $this.themePluginIcon(opts); 2279 }); 2280 }); 2281 } 2282 2283 // Render Background Videos inside carousel. Just a trigger on window is sufficient to render 2284 if( $el.find('[data-plugin-video-background]').get(0) ) { 2285 $(window).resize(); 2286 } 2287 2288 // Remove Loading 2289 $el.removeClass('owl-loading'); 2290 2291 // Remove Height 2292 $el.css('height', 'auto'); 2293 2294 // Carousel Navigate By ID and item index 2295 self.carouselNavigate(); 2296 2297 // Refresh Carousel 2298 if( self.options.refresh ) { 2299 $el.owlCarousel('refresh'); 2300 } 2301 2302 return this; 2303 } 2304 2305 navigationOffsets() { 2306 const self = this, $el = this.options.wrapper, navHasTransform = $el.find('.owl-nav').css('transform') == 'none' ? false : true, dotsHasTransform = $el.find('.owl-dots').css('transform') == 'none' ? false : true; 2307 2308 // ************* NAV ***************** 2309 // Nav Offset - Horizontal 2310 if( self.options.navHorizontalOffset && !self.options.navVerticalOffset ) { 2311 if( !navHasTransform ) { 2312 $el.find('.owl-nav').css({ 2313 transform: 'translate3d('+ self.options.navHorizontalOffset +', 0, 0)' 2314 }); 2315 } else { 2316 $el.find('.owl-nav').css({ 2317 left: self.options.navHorizontalOffset 2318 }); 2319 } 2320 } 2321 2322 // Nav Offset - Vertical 2323 if( self.options.navVerticalOffset && !self.options.navHorizontalOffset ) { 2324 if( !navHasTransform ) { 2325 $el.find('.owl-nav').css({ 2326 transform: 'translate3d(0, '+ self.options.navVerticalOffset +', 0)' 2327 });
2328 } else { 2329 $el.find('.owl-nav').css({ 2330 top: 'calc( 50% - '+ self.options.navVerticalOffset +' )' 2331 }); 2332 } 2333 } 2334 2335 // Nav Offset - Horizontal & Vertical 2336 if( self.options.navVerticalOffset && self.options.navHorizontalOffset ) { 2337 if( !navHasTransform ) { 2338 $el.find('.owl-nav').css({ 2339 transform: 'translate3d('+ self.options.navHorizontalOffset +', '+ self.options.navVerticalOffset +', 0)' 2340 }); 2341 } else { 2342 $el.find('.owl-nav').css({ 2343 top: 'calc( 50% - '+ self.options.navVerticalOffset +' )', 2344 left: self.options.navHorizontalOffset 2345 }); 2346 } 2347 } 2348 2349 // ********** DOTS ********************* 2350 // Dots Offset - Horizontal 2351 if( self.options.dotsHorizontalOffset && !self.options.dotsVerticalOffset ) { 2352 $el.find('.owl-dots').css({ 2353 transform: 'translate3d('+ self.options.dotsHorizontalOffset +', 0, 0)' 2354 }); 2355 } 2356 2357 // Dots Offset - Vertical 2358 if( self.options.dotsVerticalOffset && !self.options.dotsHorizontalOffset ) { 2359 if( !dotsHasTransform ) { 2360 $el.find('.owl-dots').css({ 2361 transform: 'translate3d(0, '+ self.options.dotsVerticalOffset +', 0)' 2362 }); 2363 } else { 2364 $el.find('.owl-dots').css({ 2365 top: 'calc( 50% - '+ self.options.dotsVerticalOffset +' )' 2366 }); 2367 } 2368 } 2369 2370 // Dots Offset - Horizontal & Vertical 2371 if( self.options.dotsVerticalOffset && self.options.dotsHorizontalOffset ) { 2372 $el.find('.owl-dots').css({ 2373 transform: 'translate3d('+ self.options.dotsHorizontalOffset +', '+ self.options.dotsVerticalOffset +', 0)' 2374 }); 2375 } 2376 2377 return this; 2378 } 2379 2380 carouselNavigate() { 2381 const self = this, $el = this.options.wrapper, $carousel = $el.data('owl.carousel'); 2382 2383 if( $('[data-carousel-navigate]').get(0) ) { 2384 $('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').each(function(){ 2385 const $this = $(this), hasCarousel = $( $this.data('carousel-navigate-id') ).get(0), toIndex = $this.data('carousel-navigate-to'); 2386 2387 if( hasCarousel ) { 2388 2389 $this.on('click', () => { 2390 $carousel.to( parseInt(toIndex) - 1 ); 2391 }); 2392 2393 } 2394 }); 2395 2396 $el.on('change.owl.carousel', () => { 2397 $('[data-carousel-navigate-id="#'+ $el.attr('id') +'"]').removeClass('active'); 2398 }); 2399 2400 $el.on('changed.owl.carousel', ({item}) => { 2401 $('[data-carousel-navigate-id="#'+ $el.attr('id') +'"][data-carousel-navigate-to="'+ ( item.index + 1 ) +'"]').addClass('active'); 2402 }); 2403 } 2404 2405 return this; 2406 } 2407 } 2408 2409 PluginCarousel.defaults = { 2410 loop: true, 2411 responsive: { 2412 0: { 2413 items: 1 2414 }, 2415 479: { 2416 items: 1 2417 }, 2418 768: { 2419 items: 2 2420 }, 2421 979: { 2422 items: 3 2423 }, 2424 1199: { 2425 items: 4 2426 } 2427 }, 2428 navText: [], 2429 refresh: false 2430 }; 2431 2432 // expose to scope 2433 $.extend(theme, { 2434 PluginCarousel 2435 }); 2436 2437 // jquery plugin 2438 $.fn.themePluginCarousel = function(opts) { 2439 return this.map(function() { 2440 const $this = $(this); 2441 2442 if ($this.data(instanceName)) { 2443 return $this.data(instanceName); 2444 } else { 2445 return new PluginCarousel($this, opts); 2446 } 2447 2448 }); 2449 } 2450})).apply(this, [window.theme, jQuery]); 2451 2452// Chart Circular 2453(((theme = {}, $) => { 2454 const instanceName = '__chartCircular'; 2455 2456 class PluginChartCircular { 2457 constructor($el, opts) { 2458 return this.initialize($el, opts); 2459 } 2460 2461 initialize($el, opts) { 2462 if ($el.data(instanceName)) { 2463 return this; 2464 } 2465 2466 this.$el = $el; 2467 2468 this 2469 .setData() 2470 .setOptions(opts) 2471 .build(); 2472 2473 return this; 2474 } 2475 2476 setData() { 2477 this.$el.data(instanceName, this); 2478 2479 return this; 2480 } 2481 2482 setOptions(opts) { 2483 this.options = $.extend(true, {}, PluginChartCircular.defaults, opts, { 2484 wrapper: this.$el 2485 }); 2486 2487 return this; 2488 } 2489 2490 build() { 2491 if (!($.isFunction($.fn.easyPieChart))) { 2492 return this; 2493 } 2494 2495 const self = this, $el = this.options.wrapper, value = ($el.attr('data-percent') ? $el.attr('data-percent') : 0), percentEl = $el.find('.percent'); 2496 2497 $.extend(true, self.options, { 2498 onStep(from, to, currentValue) { 2499 percentEl.html(parseInt(currentValue)); 2500 } 2501 }); 2502 2503 $el.attr('data-percent', 0); 2504 2505 $el.easyPieChart(self.options); 2506 2507 setTimeout(() => { 2508 2509 $el.data('easyPieChart').update(value); 2510 $el.attr('data-percent', value); 2511 2512 }, self.options.delay); 2513 2514 return this; 2515 } 2516 } 2517 2518 PluginChartCircular.defaults = { 2519 accX: 0, 2520 accY: -150, 2521 delay: 1, 2522 barColor: '#0088CC', 2523 trackColor: '#f2f2f2', 2524 scaleColor: false, 2525 scaleLength: 5, 2526 lineCap: 'round', 2527 lineWidth: 13, 2528 size: 175, 2529 rotate: 0, 2530 animate: ({ 2531 duration: 2500, 2532 enabled: true 2533 }) 2534 }; 2535 2536 // expose to scope 2537 $.extend(theme, { 2538 PluginChartCircular 2539 }); 2540 2541 // jquery plugin 2542 $.fn.themePluginChartCircular = function(opts) { 2543 return this.map(function() { 2544 const $this = $(this); 2545 2546 if ($this.data(instanceName)) { 2547 return $this.data(instanceName); 2548 } else { 2549 return new PluginChartCircular($this, opts); 2550 } 2551 2552 }); 2553 } 2554})).apply(this, [window.theme, jQuery]); 2555 2556// Countdown 2557(((theme = {}, $) => { 2558 const instanceName = '__countdown'; 2559 2560 class PluginCountdown { 2561 constructor($el, opts) { 2562 return this.initialize($el, opts); 2563 } 2564 2565 initialize($el, opts) { 2566 if ($el.data(instanceName)) { 2567 return this; 2568 } 2569 2570 this.$el = $el; 2571 2572 this 2573 .setData() 2574 .setOptions(opts) 2575 .build(); 2576 2577 return this; 2578 } 2579 2580 setData() { 2581 this.$el.data(instanceName, this); 2582 2583 return this; 2584 } 2585 2586 setOptions(opts) { 2587 this.options = $.extend(true, {}, PluginCountdown.defaults, opts, { 2588 wrapper: this.$el 2589 }); 2590 2591 return this; 2592 } 2593 2594 build() { 2595 if (!($.isFunction($.fn.countTo))) { 2596 return this; 2597 } 2598 2599 const self = this, $el = this.options.wrapper, numberClass = ( self.options.numberClass ) ? ' ' + self.options.numberClass : '', wrapperClass = ( self.options.wrapperClass ) ? ' ' + self.options.wrapperClass : ''; 2600 2601 if( self.options.uppercase ) { 2602 $el.countdown(self.options.date).on('update.countdown', function(event) { 2603 const $this = $(this).html(event.strftime(self.options.insertHTMLbefore 2604 + '<span class="days'+ wrapperClass +'"><span class="'+ numberClass +'">%D</span> '+ self.options.textDay +'</span> ' 2605 + '<span class="hours'+ wrapperClass +'"><span class="'+ numberClass +'">%H</span> '+ self.options.textHour +'</span> ' 2606 + '<span class="minutes'+ wrapperClass +'"><span class="'+ numberClass +'">%M</span> '+ self.options.textMin +'</span> ' 2607 + '<span class="seconds'+ wrapperClass +'"><span class="'+ numberClass +'">%S</span> '+ self.options.textSec +'</span> ' 2608 + self.options.insertHTMLafter 2609 )); 2610 }); 2611 } else { 2612 $el.countdown(self.options.date).on('update.countdown', function(event) { 2613 const $this = $(this).html(event.strftime(self.options.insertHTMLbefore 2614 + '<span class="days'+ wrapperClass +'"><span class="'+ numberClass +'">%D</span> '+ self.options.textDay +'</span> ' 2615 + '<span class="hours'+ wrapperClass +'"><span class="'+ numberClass +'">%H</span> '+ self.options.textHour +'</span> ' 2616 + '<span class="minutes'+ wrapperClass +'"><span class="'+ numberClass +'">%M</span> '+ self.options.textMin +'</span> ' 2617 + '<span class="seconds'+ wrapperClass +'"><span class="'+ numberClass +'">%S</span> '+ self.options.textSec +'</span> ' 2618 + self.options.insertHTMLafter 2619 )); 2620 }); 2621 } 2622 2623 return this; 2624 } 2625 } 2626 2627 PluginCountdown.defaults = { 2628 date: '2030/06/10 12:00:00', 2629 textDay: 'DAYS', 2630 textHour: 'HRS', 2631 textMin: 'MIN', 2632 textSec: 'SEC', 2633 uppercase: true, 2634 numberClass: '', 2635 wrapperClass: '', 2636 insertHTMLbefore: '', 2637 insertHTMLafter: '' 2638 }; 2639 2640 // expose to scope 2641 $.extend(theme, { 2642 PluginCountdown 2643 }); 2644 2645 // jquery plugin 2646 $.fn.themePluginCountdown = function(opts) { 2647 return this.map(function() { 2648 const $this = $(this); 2649 2650 if ($this.data(instanceName)) { 2651 return $this.data(instanceName); 2652 } else { 2653 return new PluginCountdown($this, opts); 2654 } 2655 2656 }); 2657 } 2658})).apply(this, [window.theme, jQuery]); 2659 2660// Counter 2661(((theme = {}, $) => { 2662 const instanceName = '__counter'; 2663 2664 class PluginCounter { 2665 constructor($el, opts) { 2666 return this.initialize($el, opts); 2667 } 2668 2669 initialize($el, opts) { 2670 if ($el.data(instanceName)) { 2671 return this; 2672 } 2673 2674 this.$el = $el; 2675 2676 this 2677 .setData() 2678 .setOptions(opts) 2679 .build(); 2680 2681 return this; 2682 } 2683 2684 setData() { 2685 this.$el.data(instanceName, this); 2686 2687 return this; 2688 } 2689 2690 setOptions(opts) { 2691 this.options = $.extend(true, {}, PluginCounter.defaults, opts, { 2692 wrapper: this.$el 2693 }); 2694 2695 return this; 2696 } 2697 2698 build() { 2699 if (!($.isFunction($.fn.countTo))) { 2700 return this; 2701 } 2702 2703 const self = this, $el = this.options.wrapper; 2704 2705 if (self.options.comma) { 2706 self.options.formatter = (value, {decimals}) => value.toFixed(decimals).toString().replace('.',',') 2707 } 2708 2709 $.extend(self.options, { 2710 onComplete() { 2711 2712 if ($el.data('append')) { 2713 if( self.options.appendWrapper ) { 2714 const appendWrapper = $( self.options.appendWrapper ); 2715 2716 appendWrapper.append( $el.data('append') ); 2717 2718 $el.html( $el.html() + appendWrapper[0].outerHTML ); 2719 } else { 2720 $el.html($el.html() + $el.data('append')); 2721 } 2722 } 2723 2724 if ($el.data('prepend')) { 2725 if( self.options.prependWrapper ) { 2726 const prependWrapper = $( self.options.prependWrapper ); 2727 2728 prependWrapper.append( $el.data('prepend') ); 2729 2730 $el.html( $el.html() + prependWrapper[0].outerHTML ); 2731 } else { 2732 $el.html($el.data('prepend') + $el.html()); 2733 } 2734 } 2735 } 2736 }); 2737 2738 $el.countTo(self.options); 2739 2740 return this; 2741 } 2742 } 2743 2744 PluginCounter.defaults = { 2745 accX: 0, 2746 accY: 0, 2747 appendWrapper: false, 2748 prependWrapper: false, 2749 speed: 3000, 2750 refreshInterval: 100, 2751 decimals: 0, 2752 comma: false, 2753 onUpdate: null, 2754 onComplete: null 2755 } 2756 2757 // expose to scope 2758 $.extend(theme, { 2759 PluginCounter 2760 }); 2761 2762 // jquery plugin 2763 $.fn.themePluginCounter = function(opts) { 2764 return this.map(function() { 2765 const $this = $(this); 2766 2767 if ($this.data(instanceName)) { 2768 return $this.data(instanceName); 2769 } else { 2770 return new PluginCounter($this, opts); 2771 } 2772 2773 }); 2774 } 2775})).apply(this, [window.theme, jQuery]); 2776 2777// CursorEffect 2778(((theme = {}, $) => { 2779 const instanceName = '__cursorEffect'; 2780 2781 class PluginCursorEffect { 2782 constructor($el, opts) { 2783 return this.initialize($el, opts); 2784 } 2785 2786 initialize($el, opts) { 2787 if ($el.data(instanceName)) { 2788 return this; 2789 } 2790 2791 this.$el = $el; 2792 2793 this 2794 .setData() 2795 .setOptions(opts) 2796 .build() 2797 .events(); 2798 2799 return this; 2800 } 2801 2802 setData() { 2803 this.$el.data(instanceName, this); 2804 2805 return this; 2806 } 2807 2808 setOptions(opts) { 2809 this.options = $.extend(true, {}, PluginCursorEffect.defaults, opts, { 2810 wrapper: this.$el 2811 }); 2812 2813 return this; 2814 } 2815 2816 build() { 2817 const self = this; 2818 2819 // Global Variables for cursor position 2820 self.clientX = -100; 2821 self.clientY = -100; 2822 2823 // Hide Mouse Cursor 2824 if( self.options.hideMouseCursor ) { 2825 self.$el.addClass('hide-mouse-cursor'); 2826 } 2827 2828 // Creates the cursor wrapper node 2829 const cursorOuter = document.createElement('DIV'); 2830 cursorOuter.className = 'cursor-outer'; 2831 2832 // Creates the cursor inner node 2833 const cursorInner = document.createElement('DIV'); 2834 cursorInner.className = 'cursor-inner'; 2835 2836 // Custom Cursor Outer Color 2837 if( self.options.cursorOuterColor ) { 2838 cursorOuter.style = 'border-color: ' + self.options.cursorOuterColor + ';'; 2839 } 2840 2841 // Custom Cursor Inner Color 2842 if( self.options.cursorInnerColor ) { 2843 cursorInner.style = 'background-color: ' + self.options.cursorInnerColor + ';'; 2844 } 2845 2846 // Size 2847 if( self.options.size ) { 2848 switch ( self.options.size ) { 2849 case 'small': 2850 self.$el.addClass( 'cursor-effect-size-small' ); 2851 break; 2852 2853 case 'big': 2854 self.$el.addClass( 'cursor-effect-size-big' ); 2855 break; 2856 } 2857 } 2858 2859 // Style 2860 if( self.options.style ) { 2861 self.$el.addClass( self.options.style ); 2862 } 2863 2864 // Prepend cursor wrapper node to the body 2865 document.body.prepend( cursorOuter ); 2866 2867 // Prepend cursor inner node to the body 2868 document.body.prepend( cursorInner ); 2869 2870 // Loop for render 2871 const render = () => { 2872 cursorOuter.style.transform = 'translate('+ self.clientX +'px, '+ self.clientY +'px)'; 2873 cursorInner.style.transform = 'translate('+ self.clientX +'px, '+ self.clientY +'px)'; 2874 2875 self.loopInside = requestAnimationFrame(render); 2876 }; 2877 self.loop = requestAnimationFrame(render); 2878 2879 return this; 2880 } 2881 2882 events() { 2883 const self = this, $cursorOuter = $('.cursor-outer'), $cursorInner = $('.cursor-inner'); 2884
2885 const initialCursorOuterBox = $cursorOuter[0].getBoundingClientRect(), initialCursorOuterRadius = $cursorOuter.css('border-radius'); 2886 2887 // Update Cursor Position 2888 document.addEventListener('mousemove', ({clientX, clientY}) => { 2889 if( !self.isStuck ) { 2890 self.clientX = clientX - 20; 2891 self.clientY = clientY - 20; 2892 } 2893 2894 $cursorOuter.removeClass('opacity-0'); 2895 }); 2896 2897 self.isStuck = false; 2898 $('[data-cursor-effect-hover]').on('mouseenter', function(e){ 2899 2900 // Identify Event With Hover Class 2901 $cursorOuter.addClass('cursor-outer-hover'); 2902 $cursorInner.addClass('cursor-inner-hover'); 2903 2904 // Hover Color 2905 const hoverColor = $(this).data('cursor-effect-hover-color'); 2906 $cursorOuter.addClass( 'cursor-color-' + hoverColor ); 2907 $cursorInner.addClass( 'cursor-color-' + hoverColor ); 2908 2909 // Effect Types 2910 switch ( $(this).data('cursor-effect-hover') ) { 2911 case 'fit': 2912 const thisBox = $(this)[0].getBoundingClientRect(); 2913 2914 self.clientX = thisBox.x; 2915 self.clientY = thisBox.y; 2916 2917 $cursorOuter.css({ 2918 width: thisBox.width, 2919 height: thisBox.height, 2920 'border-radius': $(this).css('border-radius') 2921 }).addClass('cursor-outer-fit'); 2922 2923 $cursorInner.addClass('opacity-0'); 2924 2925 self.isStuck = true; 2926 break; 2927 2928 case 'plus': 2929 $cursorInner.addClass('cursor-inner-plus'); 2930 break; 2931 } 2932 }); 2933 2934 $('[data-cursor-effect-hover]').on('mouseleave', function(){ 2935 2936 // Identify Event With Hover Class 2937 $cursorOuter.removeClass('cursor-outer-hover'); 2938 $cursorInner.removeClass('cursor-inner-hover'); 2939 2940 // Remove Color Class 2941 const hoverColor = $(this).data('cursor-effect-hover-color'); 2942 $cursorOuter.removeClass( 'cursor-color-' + hoverColor ); 2943 $cursorInner.removeClass( 'cursor-color-' + hoverColor ); 2944 2945 // Effect Types 2946 switch ( $(this).data('cursor-effect-hover') ) { 2947 case 'fit': 2948 $cursorOuter.css({ 2949 width: initialCursorOuterBox.width, 2950 height: initialCursorOuterBox.height, 2951 'border-radius': initialCursorOuterRadius 2952 }).removeClass('cursor-outer-fit'); 2953 2954 $cursorInner.removeClass('opacity-0'); 2955 2956 self.isStuck = false; 2957 break; 2958 2959 case 'plus': 2960 $cursorInner.removeClass('cursor-inner-plus'); 2961 break; 2962 } 2963 }); 2964 2965 $(window).on('scroll', () => { 2966 if( $cursorOuter.hasClass('cursor-outer-fit') ) { 2967 $cursorOuter.addClass('opacity-0').removeClass('cursor-outer-fit'); 2968 } 2969 }); 2970 2971 return this; 2972 } 2973 2974 destroy() { 2975 const self = this; 2976 2977 self.$el.removeClass('hide-mouse-cursor cursor-effect-size-small cursor-effect-size-big cursor-effect-style-square'); 2978 2979 cancelAnimationFrame( self.loop ); 2980 cancelAnimationFrame( self.loopInside ); 2981 2982 document.querySelector('.cursor-outer').remove(); 2983 document.querySelector('.cursor-inner').remove(); 2984 2985 self.$el.removeData( instanceName, self ); 2986 } 2987 } 2988 2989 PluginCursorEffect.defaults = { 2990 2991 } 2992 2993 // expose to scope 2994 $.extend(theme, { 2995 PluginCursorEffect 2996 }); 2997 2998 // jquery plugin 2999 $.fn.themePluginCursorEffect = function(opts) { 3000 return this.map(function() { 3001 const $this = $(this); 3002 3003 if ($this.data(instanceName)) { 3004 return $this.data(instanceName); 3005 } else { 3006 return new PluginCursorEffect($this, opts); 3007 } 3008 3009 }); 3010 } 3011})).apply(this, [window.theme, jQuery]); 3012 3013// Float Element 3014(((theme = {}, $) => { 3015 const instanceName = '__floatElement'; 3016 3017 class PluginFloatElement { 3018 constructor($el, opts) { 3019 return this.initialize($el, opts); 3020 } 3021 3022 initialize($el, opts) { 3023 if ($el.data(instanceName)) { 3024 return this; 3025 } 3026 3027 this.$el = $el; 3028 3029 this 3030 .setData() 3031 .setOptions(opts) 3032 .build(); 3033 3034 return this; 3035 } 3036 3037 setData() { 3038 this.$el.data(instanceName, this); 3039 3040 return this; 3041 } 3042 3043 setOptions(opts) { 3044 this.options = $.extend(true, {}, PluginFloatElement.defaults, opts, { 3045 wrapper: this.$el 3046 }); 3047 3048 return this; 3049 } 3050 3051 build() { 3052 const self = this; 3053 const $el = this.options.wrapper; 3054 const $window = $(window); 3055 let minus; 3056 3057 // If has floating elements inside a SVG. 3058 // Intersection Observer API do not check elements inside SVG's, so we need initialize trough top parent SVG 3059 if( $el.data('plugin-float-element-svg') ) { 3060 $el.find('[data-plugin-float-element]').each(function(){ 3061 const $this = $(this); 3062 let opts; 3063 3064 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 3065 if (pluginOptions) 3066 opts = pluginOptions; 3067 3068 $this.themePluginFloatElement(opts); 3069 }); 3070 3071 return this; 3072 } 3073 3074 if( self.options.style ) { 3075 $el.attr('style', self.options.style); 3076 } 3077 3078 if( $window.width() > self.options.minWindowWidth ) { 3079 3080 // Set Start Position 3081 if( self.options.startPos == 'none' ) { 3082 minus = ''; 3083 } else if( self.options.startPos == 'top' ) { 3084 $el.css({ 3085 top: 0 3086 });
3087 minus = ''; 3088 } else { 3089 $el.css({ 3090 bottom: 0 3091 }); 3092 minus = '-'; 3093 } 3094 3095 // Set Transition 3096 if( self.options.transition ) { 3097 $el.css({ 3098 transition: 'ease-out transform '+ self.options.transitionDuration +'ms ' + self.options.transitionDelay + 'ms' 3099 }); 3100 } 3101 3102 // First Load 3103 self.movement(minus); 3104 3105 // Scroll 3106 $window.on('scroll', () => { 3107 self.movement(minus); 3108 }); 3109 3110 } 3111 3112 return this; 3113 } 3114 3115 movement(minus) { 3116 const self = this, $el = this.options.wrapper, $window = $(window), scrollTop = $window.scrollTop(), elementOffset = $el.offset().top, currentElementOffset = (elementOffset - scrollTop), factor = ( self.options.isInsideSVG ) ? 2 : 100; 3117 3118 const scrollPercent = factor * currentElementOffset / ($window.height()); 3119 3120 if( $el.visible( true ) ) { 3121 3122 if( !self.options.horizontal ) { 3123 3124 $el.css({ 3125 transform: 'translate3d(0, '+ minus + scrollPercent / self.options.speed +'%, 0)' 3126 }); 3127 3128 } else { 3129 3130 $el.css({ 3131 transform: 'translate3d('+ minus + scrollPercent / self.options.speed +'%, 0, 0)' 3132 }); 3133 3134 } 3135 3136 } 3137 3138 } 3139 } 3140 3141 PluginFloatElement.defaults = { 3142 startPos: 'top', 3143 speed: 3, 3144 horizontal: false, 3145 isInsideSVG: false, 3146 transition: false, 3147 transitionDelay: 0, 3148 transitionDuration: 500, 3149 minWindowWidth: 991 3150 }; 3151 3152 // expose to scope 3153 $.extend(theme, { 3154 PluginFloatElement 3155 }); 3156 3157 // jquery plugin 3158 $.fn.themePluginFloatElement = function(opts) { 3159 return this.map(function() { 3160 const $this = $(this); 3161 3162 if ($this.data(instanceName)) { 3163 return $this.data(instanceName); 3164 } else { 3165 return new PluginFloatElement($this, opts); 3166 } 3167 3168 }); 3169 } 3170})).apply(this, [window.theme, jQuery]); 3171 3172// GDPR 3173(((theme = {}, $) => { 3174 const instanceName = '__gdpr'; 3175 3176 class PluginGDPR { 3177 constructor($el, opts) { 3178 return this.initialize($el, opts); 3179 } 3180 3181 initialize($el, opts) { 3182 const self = this; 3183 3184 this.$el = $el; 3185 3186 this 3187 .setData() 3188 .setOptions(opts) 3189 .build() 3190 .events(); 3191 3192 return this; 3193 } 3194 3195 setData() { 3196 this.$el.data(instanceName, this); 3197 3198 return this; 3199 } 3200 3201 setOptions(opts) { 3202 this.options = $.extend(true, {}, PluginGDPR.defaults, opts, { 3203 wrapper: this.$el 3204 }); 3205 3206 return this; 3207 } 3208 3209 build() { 3210 const self = this; 3211 3212 // Show 3213 if( !$.cookie( 'porto-privacy-bar' ) ) { 3214 setTimeout(() => { 3215 self.options.wrapper.addClass('show'); 3216 }, self.options.cookieBarShowDelay); 3217 } 3218 3219 // If already has preferences cookie, check inputs according preferences cookie data 3220 if( $.cookie( 'porto-gdpr-preferences' ) ) { 3221 const preferencesArr = $.cookie( 'porto-gdpr-preferences' ).split(','); 3222 3223 for( let i = 0; i < preferencesArr.length; i++ ) { 3224 if( $('input[value="'+ preferencesArr[i] +'"]').get(0) ) { 3225 if( $('input[value="'+ preferencesArr[i] +'"]').is(':checkbox') ) { 3226 $('input[value="'+ preferencesArr[i] +'"]').prop('checked', true); 3227 } 3228 } 3229 } 3230 } 3231 3232 return this; 3233 3234 } 3235 3236 events() { 3237 const self = this; 3238 3239 // Agree Trigger 3240 self.options.wrapper.find('.gdpr-agree-trigger').on('click', e => { 3241 e.preventDefault(); 3242 3243 $('.gdpr-preferences-form').find('.gdpr-input').each(function(){ 3244 if( $(this).is(':checkbox') || $(this).is(':hidden') ) { 3245 $(this).prop('checked', true); 3246 } 3247 }); 3248 3249 $('.gdpr-preferences-form').trigger('submit').removeClass('show'); 3250 3251 self.removeCookieBar(); 3252 }); 3253 3254 // Preferences Trigger 3255 self.options.wrapper.find('.gdpr-preferences-trigger').on('click', e => { 3256 e.preventDefault(); 3257 3258 $('.gdpr-preferences-popup').addClass('show'); 3259 }); 3260 3261 // Close Popup Button 3262 $('.gdpr-close-popup').on('click', e => { 3263 e.preventDefault(); 3264 3265 $('.gdpr-preferences-popup').removeClass('show'); 3266 }); 3267 3268 // Close Popup When Click Outside of popup area 3269 $('.gdpr-preferences-popup').on('click', ({target}) => { 3270 if( !$(target).closest('.gdpr-preferences-popup-content').get(0) ) { 3271 $('.gdpr-preferences-popup').removeClass('show'); 3272 } 3273 }); 3274 3275 // Preference Form 3276 $('.gdpr-preferences-form').on('submit', function(e){
3277 e.preventDefault(); 3278 3279 const $this = $(this); 3280 3281 // Save Preferences Button 3282 $this.find('button[type="submit"]').text( 'SAVING...' ); 3283 3284 // Form Data 3285 const formData = []; 3286 $this.find('.gdpr-input').each(function(){ 3287 if( $(this).is(':checkbox') && $(this).is(':checked') || $(this).is(':hidden') ) { 3288 formData.push( $(this).val() ); 3289 } 3290 }); 3291 3292 $.cookie( 'porto-privacy-bar', true, {expires: self.options.expires} ); 3293 3294 setTimeout(() => { 3295 $this.find('button[type="submit"]').text( 'SAVED!' ).removeClass('btn-primary').addClass('btn-success'); 3296 3297 setTimeout(() => { 3298 $('.gdpr-preferences-popup').removeClass('show'); 3299 self.removeCookieBar(); 3300 3301 $this.find('button[type="submit"]').text( 'SAVE PREFERENCES' ).removeClass('btn-success').addClass('btn-primary'); 3302 3303 if( $.cookie( 'porto-gdpr-preferences' ) ) { 3304 3305 $.cookie( 'porto-gdpr-preferences', formData, {expires: self.options.expires} ); 3306 location.reload(); 3307 3308 } else { 3309 3310 $.cookie( 'porto-gdpr-preferences', formData, {expires: self.options.expires} ); 3311 3312 if ($.isFunction($.fn['themePluginGDPRWrapper']) && $('[data-plugin-gdpr-wrapper]').length) { 3313 3314 $(() => { 3315 $('[data-plugin-gdpr-wrapper]:not(.manual)').each(function() { 3316 const $this = $(this); 3317 let opts; 3318 3319 $this.removeData('__gdprwrapper'); 3320 3321 const pluginOptions = theme.fn.getOptions($this.data('plugin-options')); 3322 if (pluginOptions) 3323 opts = pluginOptions; 3324 3325 $this.themePluginGDPRWrapper(opts); 3326 }); 3327 });
3328 3329 } 3330 3331 } 3332 3333 }, 500); 3334 }, 1000); 3335 }); 3336 3337 // Remove/Reset Cookies 3338 $('.gdpr-reset-cookies').on('click', e => { 3339 e.preventDefault(); 3340 3341 self.clearCookies(); 3342 3343 location.reload(); 3344 }); 3345 3346 // Open Preferences 3347 $('.gdpr-open-preferences').on('click', e => { 3348 e.preventDefault(); 3349 3350 $('.gdpr-preferences-popup').toggleClass('show'); 3351 }); 3352 3353 return this; 3354 } 3355 3356 removeCookieBar() { 3357 const self = this; 3358 3359 self.options.wrapper.addClass('removing').on('transitionend', () => { 3360 setTimeout(() => { 3361 self.options.wrapper.removeClass('show removing'); 3362 }, 500); 3363 }); 3364 3365 return this; 3366 } 3367 3368 clearCookies() { 3369 const self = this; 3370 3371 $.removeCookie( 'porto-privacy-bar' ); 3372 $.removeCookie( 'porto-gdpr-preferences' ); 3373 3374 return this; 3375 } 3376 } 3377 3378 PluginGDPR.defaults = { 3379 cookieBarShowDelay: 3000, 3380 expires: 365 3381 }; 3382 3383 // expose to scope 3384 $.extend(theme, { 3385 PluginGDPR 3386 }); 3387 3388 // jquery plugin 3389 $.fn.themePluginGDPR = function(opts) { 3390 return this.map(function() { 3391 const $this = $(this); 3392 3393 if ($this.data(instanceName)) { 3394 return $this.data(instanceName); 3395 } else { 3396 return new PluginGDPR($this, opts); 3397 } 3398 3399 }); 3400 } 3401})).apply(this, [window.theme, jQuery]); 3402 3403// GDPR Wrapper 3404(((theme = {}, $) => { 3405 const instanceName = '__gdprwrapper'; 3406 3407 class PluginGDPRWrapper { 3408 constructor($el, opts) { 3409 return this.initialize($el, opts); 3410 } 3411 3412 initialize($el, opts) { 3413 const self = this; 3414 3415 this.$el = $el; 3416 3417 this 3418 .setData() 3419 .setOptions(opts) 3420 .build(); 3421 3422 return this; 3423 } 3424 3425 setData() { 3426 this.$el.data(instanceName, this); 3427 3428 return this; 3429 } 3430 3431 setOptions(opts) { 3432 this.options = $.extend(true, {}, PluginGDPRWrapper.defaults, opts, { 3433 wrapper: this.$el 3434 }); 3435 3436 return this; 3437 } 3438 3439 build() { 3440 const self = this; 3441 3442 if( $.cookie( 'porto-gdpr-preferences' ) && $.cookie( 'porto-gdpr-preferences' ).includes(self.options.checkCookie) ) { 3443 3444 $.ajax({
3445 url: self.options.ajaxURL, 3446 cache: false, 3447 complete({responseText}) { 3448 3449 setTimeout(() => { 3450 3451 self.options.wrapper.html(responseText).addClass('show'); 3452 3453 }, 1000); 3454 3455 } 3456 }); 3457 3458 } else { 3459 self.options.wrapper.addClass('show'); 3460 } 3461 3462 return this; 3463 3464 } 3465 } 3466 3467 PluginGDPRWrapper.defaults = { 3468 3469 }; 3470 3471 // expose to scope 3472 $.extend(theme, { 3473 PluginGDPRWrapper 3474 }); 3475 3476 // jquery plugin 3477 $.fn.themePluginGDPRWrapper = function(opts) { 3478 return this.map(function() { 3479 const $this = $(this); 3480 3481 if ($this.data(instanceName)) { 3482 return $this.data(instanceName); 3483 } else { 3484 return new PluginGDPRWrapper($this, opts); 3485 } 3486 3487 }); 3488 } 3489})).apply(this, [window.theme, jQuery]); 3490 3491// Hover Effect 3492(((theme = {}, $) => { 3493 const instanceName = '__hoverEffect'; 3494 3495 class PluginHoverEffect { 3496 constructor($el, opts) { 3497 return this.initialize($el, opts); 3498 } 3499 3500 initialize($el, opts) { 3501 if ($el.data(instanceName)) { 3502 return this; 3503 } 3504 3505 this.$el = $el; 3506 3507 this 3508 .setData() 3509 .setOptions(opts) 3510 .build(); 3511 3512 return this; 3513 } 3514 3515 setData() { 3516 this.$el.data(instanceName, this); 3517 3518 return this; 3519 } 3520 3521 setOptions(opts) { 3522 this.options = $.extend(true, {}, PluginHoverEffect.defaults, opts, { 3523 wrapper: this.$el 3524 }); 3525 3526 return this; 3527 } 3528 3529 build() { 3530 const self = this; 3531 3532 if(self.$el.hasClass('hover-effect-3d')) { 3533 self.options.effect = '3d'; 3534 } 3535 3536 // Magnetic 3537 if(self.options.effect == 'magnetic') { 3538 self.magnetic(); 3539 } 3540 3541 // 3d 3542 if(self.options.effect == '3d') { 3543 self.hover3d(); 3544 } 3545 3546 return this; 3547 } 3548 3549 magnetic() { 3550 const self = this; 3551 3552 self.$el.mousemove(function({clientX, clientY}) { 3553 3554 const pos = this.getBoundingClientRect(); 3555 const mx = clientX - pos.left - pos.width/2; 3556 const my = clientY - pos.top - pos.height/2; 3557 3558 this.style.transform = 'translate('+ mx * self.options.magneticMx +'px, '+ my * self.options.magneticMx +'px)'; 3559 3560 }); 3561 3562 self.$el.mouseleave(function(e) { 3563 3564 this.style.transform = 'translate3d(0px, 0px, 0px)'; 3565 3566 }); 3567 3568 return this; 3569 3570 } 3571 3572 hover3d() { 3573 const self = this; 3574 3575 if ($.isFunction($.fn['hover3d'])) { 3576 3577 self.$el.hover3d({ 3578 selector: self.options.selector, 3579 sensitivity: self.options.sensitivity 3580 }); 3581 3582 } 3583 3584 return this; 3585 3586 } 3587 } 3588 3589 PluginHoverEffect.defaults = { 3590 effect: 'magnetic', 3591 magneticMx: 0.15, 3592 magneticMy: 0.3, 3593 magneticDeg: 12, 3594 selector: '.thumb-info, .hover-effect-3d-wrapper', 3595 sensitivity: 20 3596 }; 3597 3598 // expose to scope 3599 $.extend(theme, { 3600 PluginHoverEffect 3601 }); 3602 3603 // jquery plugin 3604 $.fn.themePluginHoverEffect = function(opts) { 3605 return this.map(function() { 3606 const $this = $(this); 3607 3608 if ($this.data(instanceName)) { 3609 return $this.data(instanceName); 3610 } else { 3611 return new PluginHoverEffect($this, opts); 3612 } 3613 3614 }); 3615 }; 3616})).apply(this, [window.theme, jQuery]); 3617 3618// Icon 3619(((theme = {}, $) => { 3620 const instanceName = '__icon'; 3621 3622 class PluginIcon { 3623 constructor($el, opts) { 3624 return this.initialize($el, opts); 3625 } 3626 3627 initialize($el, opts) { 3628 if ($el.data(instanceName)) { 3629 return this; 3630 } 3631 3632 this.$el = $el; 3633 3634 this 3635 .setData() 3636 .setOptions(opts) 3637 .build(); 3638 3639 return this; 3640 } 3641 3642 setData() { 3643 this.$el.data(instanceName, this); 3644 3645 return this; 3646 } 3647 3648 setOptions(opts) { 3649 this.options = $.extend(true, {}, PluginIcon.defaults, opts, { 3650 wrapper: this.$el 3651 }); 3652 3653 return this; 3654 } 3655 3656 build() { 3657 const self = this; 3658 let $el = this.options.wrapper; 3659 const color = self.options.color; 3660 const elTopDistance = $el.offset().top; 3661 const windowTopDistance = $(window).scrollTop(); 3662 let duration = ( self.options.animated && !self.options.strokeBased ) ? 200 : 100; 3663 3664 // Check origin 3665 if( window.location.protocol === 'file:' ) { 3666 $el.css({ 3667 opacity: 1, 3668 width: $el.attr('width') 3669 }); 3670 3671 if( self.options.extraClass ) { 3672 $el.addClass( self.options.extraClass ); 3673 } 3674 3675 if( self.options.extraClass.indexOf('-color-light') > 0 ) { 3676 $el.css({ 3677 filter: 'invert(1)' 3678 });
3679 } 3680 3681 $(window).trigger('icon.rendered'); 3682 return; 3683 } 3684 3685 // Duration 3686 if( self.options.duration ) { 3687 duration = self.options.duration; 3688 } 3689 3690 // SVG Content 3691 const fileName = $el.attr('src'); 3692 3693 if(fileName.split('.').pop() == 'svg') { 3694 const SVGContent = $.get({ 3695 url: fileName, 3696 success(data, status, {responseText}) { 3697 const iconWrapper = self.options.fadeIn ? $('<div class="animated-icon animated fadeIn">'+ responseText +'</div>') : $('<div class="animated-icon animated">'+ responseText +'</div>'), uniqid = 'icon_' + Math.floor(Math.random() * 26) + Date.now(); 3698 3699 // Add ID 3700 iconWrapper.find('svg').attr('id', uniqid); 3701 3702 // Identify with filename 3703 iconWrapper.find('svg').attr('data-filename', $el.attr('src').split(/(\\|\/)/g).pop()); 3704 3705 if( $el.attr('width') ) { 3706 iconWrapper.find('svg') 3707 .attr('width', $el.attr('width')) 3708 .attr('height', $el.attr('width')); 3709 } 3710 3711 if( $el.attr('height') ) { 3712 iconWrapper.find('svg') 3713 .attr('height', $el.attr('height')); 3714 } 3715 3716 if( self.options.svgViewBox ) { 3717 iconWrapper.find('svg') 3718 .attr('viewBox', self.options.svgViewBox); 3719 } 3720 3721 $el.replaceWith(iconWrapper); 3722 3723 if( self.options.extraClass ) { 3724 iconWrapper.addClass( self.options.extraClass ); 3725 } 3726 3727 if( self.options.removeClassAfterInit ) { 3728 iconWrapper.removeClass(self.options.removeClassAfterInit); 3729 } 3730 3731 if( self.options.onlySVG ) { 3732 $(window).trigger('icon.rendered'); 3733 return this; 3734 } 3735 3736 $el = iconWrapper; 3737 3738 const icon = new Vivus(uniqid, {start: 'manual', type: 'sync', selfDestroy: true, duration, onReady({el}) { 3739 const styleElement = document.createElementNS("http://www.w3.org/2000/svg", "style"); 3740 let animateStyle = ''; 3741 3742 // SVG Fill Based 3743 if( self.options.animated && !self.options.strokeBased || !self.options.animated && color && !self.options.strokeBased ) { 3744 animateStyle = 'stroke-width: 0.1px; fill-opacity: 0; transition: ease fill-opacity 300ms;'; 3745 3746 // Set Style on SVG inside object 3747 styleElement.textContent = '#' + uniqid + ' path, #' + uniqid + ' line, #' + uniqid + ' rect, #' + uniqid + ' circle, #' + uniqid + ' polyline { fill: '+ color +'; stroke: '+ color +'; '+ animateStyle + (self.options.svgStyle ? self.options.svgStyle : "") + ' } .finished path { fill-opacity: 1; }'; 3748 el.appendChild(styleElement); 3749 } 3750 3751 // SVG Stroke Based 3752 if( self.options.animated && self.options.strokeBased || !self.options.animated && color && self.options.strokeBased ) { 3753 3754 // Set Style on SVG inside object 3755 styleElement.textContent = '#' + uniqid + ' path, #' + uniqid + ' line, #' + uniqid + ' rect, #' + uniqid + ' circle, #' + uniqid + ' polyline { stroke: '+ color +'; ' + (self.options.svgStyle ? self.options.svgStyle : "") + '}'; 3756 el.appendChild(styleElement); 3757 } 3758 3759 $.event.trigger('theme.plugin.icon.svg.ready'); 3760 }}); 3761 3762 // Isn't animated 3763 if( !self.options.animated ) { 3764 setTimeout(() => { 3765 icon.finish(); 3766 }, 10); 3767 $el.css({ opacity: 1 }); 3768 } 3769 3770 // Animated 3771 if( self.options.animated && $(window).width() > 767 ) { 3772 3773 // First Load 3774 if( $el.visible( true ) ) { 3775 self.startIconAnimation( icon, $el ); 3776 } else if( elTopDistance < windowTopDistance ) { 3777 self.startIconAnimation( icon, $el ); 3778 } 3779 3780 // On Scroll 3781 $(window).on('scroll', () => { 3782 if( $el.visible( true ) ) { 3783 self.startIconAnimation( icon, $el ); 3784 } 3785 }); 3786 3787 } else { 3788 3789 $el.css({ opacity: 1 }); 3790 icon.finish(); 3791 3792 $(window).on('theme.plugin.icon.svg.ready', () => { 3793 setTimeout(() => { 3794 icon.el.setAttribute('class', 'finished'); 3795 icon.finish(); 3796 }, 300); 3797 });
3798 3799 } 3800 3801 $(window).trigger('icon.rendered'); 3802 } 3803 }); 3804 } else { 3805 $el.removeAttr('data-icon'); 3806 } 3807 3808 return this; 3809 } 3810 3811 startIconAnimation(icon, $el) { 3812 const self = this; 3813 3814 // Animate for better performance 3815 $({to:0}).animate({to:1}, ((self.options.strokeBased) ? self.options.delay : self.options.delay + 300 ), () => { 3816 $el.css({ opacity: 1 }); 3817 }); 3818 3819 $({to:0}).animate({to:1}, self.options.delay, () => { 3820 icon.play(1); 3821 3822 setTimeout(() => { 3823 icon.el.setAttribute('class', 'finished'); 3824 }, icon.duration * 5 ); 3825 }); 3826 } 3827 } 3828 3829 PluginIcon.defaults = { 3830 color: '#2388ED', 3831 animated: false, 3832 delay: 300, 3833 onlySVG: false, 3834 removeClassAfterInit: false, 3835 fadeIn: true, 3836 accY: 0 3837 }; 3838 3839 // expose to scope 3840 $.extend(theme, { 3841 PluginIcon 3842 }); 3843 3844 // jquery plugin 3845 $.fn.themePluginIcon = function(opts) { 3846 return this.map(function() { 3847 const $this = $(this); 3848 3849 if ($this.data(instanceName)) { 3850 return $this.data(instanceName); 3851 } else { 3852 return new PluginIcon($this, opts); 3853 } 3854 3855 }); 3856 }; 3857})).apply(this, [window.theme, jQuery]); 3858 3859// In Viewport Style 3860(((theme = {}, $) => { 3861 const instanceName = '__inviewportstyle'; 3862 3863 class PluginInViewportStyle { 3864 constructor($el, opts) { 3865 return this.initialize($el, opts); 3866 } 3867 3868 initialize($el, opts) { 3869 if ($el.data(instanceName)) { 3870 return this; 3871 } 3872 3873 this.$el = $el; 3874 3875 this 3876 .setData() 3877 .setOptions(opts) 3878 .build(); 3879 3880 return this; 3881 } 3882 3883 setData() { 3884 this.$el.data(instanceName, this); 3885 3886 return this; 3887 } 3888 3889 setOptions(opts) { 3890 this.options = $.extend(true, {}, PluginInViewportStyle.defaults, opts, {}); 3891 3892 return this; 3893 } 3894 3895 build() { 3896 const self = this, el = self.$el.get(0); 3897 3898 self.$el.css(self.options.style); 3899 3900 if (typeof window.IntersectionObserver === 'function') { 3901 const un = observeElementInViewport.observeElementInViewport( 3902 el, () => { 3903 self.$el.css(self.options.styleIn); 3904 self.$el 3905 .addClass(self.options.classIn) 3906 .removeClass(self.options.classOut); 3907 }, () => { 3908 self.$el.css(self.options.styleOut); 3909 self.$el 3910 .addClass(self.options.classOut) 3911 .removeClass(self.options.classIn); 3912 }, { 3913 viewport: self.options.viewport, 3914 threshold: self.options.threshold, 3915 modTop: self.options.modTop, 3916 modBottom: self.options.modBottom 3917 } 3918 ) 3919 }; 3920 3921 return this; 3922 } 3923 } 3924 3925 PluginInViewportStyle.defaults = { 3926 viewport: window, 3927 threshold: [0], 3928 modTop: '-200px', 3929 modBottom: '-200px', 3930 style: {'transition': 'all 1s ease-in-out'}, 3931 styleIn: '', 3932 styleOut: '', 3933 classIn: '', 3934 classOut: '' 3935 }; 3936 3937 // expose to scope 3938 $.extend(theme, { 3939 PluginInViewportStyle 3940 }); 3941 3942 // jquery plugin 3943 $.fn.themePluginInViewportStyle = function(opts) { 3944 return this.map(function() { 3945 const $this = $(this); 3946 3947 if ($this.data(instanceName)) { 3948 return $this.data(instanceName); 3949 } else { 3950 return new PluginInViewportStyle($this, opts); 3951 } 3952 3953 }); 3954 } 3955})).apply(this, [window.theme, jQuery]); 3956 3957// Lightbox 3958(((theme = {}, $) => { 3959 const instanceName = '__lightbox'; 3960 3961 class PluginLightbox { 3962 constructor($el, opts) { 3963 return this.initialize($el, opts); 3964 } 3965 3966 initialize($el, opts) { 3967 if ($el.data(instanceName)) { 3968 return this; 3969 } 3970 3971 this.$el = $el; 3972 3973 this 3974 .setData() 3975 .setOptions(opts) 3976 .build(); 3977 3978 return this; 3979 } 3980 3981 setData() { 3982 this.$el.data(instanceName, this); 3983 3984 return this; 3985 } 3986 3987 setOptions(opts) { 3988 this.options = $.extend(true, {}, PluginLightbox.defaults, opts, { 3989 wrapper: this.$el 3990 }); 3991 3992 return this; 3993 } 3994 3995 build() { 3996 if (!($.isFunction($.fn.magnificPopup))) { 3997 return this; 3998 } 3999 4000 this.options.wrapper.magnificPopup(this.options); 4001 4002 return this; 4003 } 4004 } 4005 4006 PluginLightbox.defaults = { 4007 tClose: 'Close (Esc)', // Alt text on close button 4008 tLoading: 'Loading...', // Text that is displayed during loading. Can contain %curr% and %total% keys 4009 gallery: { 4010 tPrev: 'Previous (Left arrow key)', // Alt text on left arrow 4011 tNext: 'Next (Right arrow key)', // Alt text on right arrow 4012 tCounter: '%curr% of %total%' // Markup for "1 of 7" counter 4013 }, 4014 image: { 4015 tError: '<a href="%url%">The image</a> could not be loaded.' // Error message when image could not be loaded 4016 }, 4017 ajax: { 4018 tError: '<a href="%url%">The content</a> could not be loaded.' // Error message when ajax request failed 4019 }, 4020 callbacks: { 4021 open() { 4022 $('html').addClass('lightbox-opened'); 4023 }, 4024 close() { 4025 $('html').removeClass('lightbox-opened'); 4026 } 4027 } 4028 }; 4029 4030 // expose to scope 4031 $.extend(theme, { 4032 PluginLightbox 4033 }); 4034 4035 // jquery plugin 4036 $.fn.themePluginLightbox = function(opts) { 4037 return this.map(function() { 4038 const $this = $(this); 4039 4040 if ($this.data(instanceName)) { 4041 return $this.data(instanceName); 4042 } else { 4043 return new PluginLightbox($this, opts); 4044 } 4045 4046 }); 4047 } 4048})).apply(this, [window.theme, jQuery]); 4049 4050// Loading Overlay 4051(((theme = {}, $) => { 4052 // Default 4053 const loadingOverlayDefaultTemplate = [ 4054 '<div class="loading-overlay">', 4055 '<div class="bounce-loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>', 4056 '</div>' 4057 ].join(''); 4058 4059 // Percentage 4060 const loadingOverlayPercentageTemplate = [ 4061 '<div class="loading-overlay loading-overlay-percentage">', 4062 '<div class="page-loader-progress-wrapper"><span class="page-loader-progress">0</span><span class="page-loader-progress-symbol">%</span></div>', 4063 '</div>' 4064 ].join(''); 4065 4066 // Cubes 4067 const loadingOverlayCubesTemplate = [ 4068 '<div class="loading-overlay">', 4069 '<div class="bounce-loader"><div class="cssload-thecube"><div class="cssload-cube cssload-c1"></div><div class="cssload-cube cssload-c2"></div><div class="cssload-cube cssload-c4"></div><div class="cssload-cube cssload-c3"></div></div></div>', 4070 '</div>' 4071 ].join(''); 4072 4073 // Cube Progress 4074 const loadingOverlayCubeProgressTemplate = [ 4075 '<div class="loading-overlay">', 4076 '<div class="bounce-loader"><span class="cssload-cube-progress"><span class="cssload-cube-progress-inner"></span></span></div>', 4077 '</div>' 4078 ].join(''); 4079 4080 // Float Rings 4081 const loadingOverlayFloatRingsTemplate = [ 4082 '<div class="loading-overlay">', 4083 '<div class="bounce-loader"><div class="cssload-float-rings-loader"><div class="cssload-float-rings-inner cssload-one"></div><div class="cssload-float-rings-inner cssload-two"></div><div class="cssload-float-rings-inner cssload-three"></div></div></div>', 4084 '</div>' 4085 ].join(''); 4086 4087 // Floating Bars 4088 const loadingOverlayFloatBarsTemplate = [ 4089 '<div class="loading-overlay">', 4090 '<div class="bounce-loader"><div class="cssload-float-bars-container"><ul class="cssload-float-bars-flex-container"><li><span class="cssload-float-bars-loading"></span></li></div></div></div>', 4091 '</div>' 4092 ].join(''); 4093 4094 // Speeding Wheel 4095 const loadingOverlaySpeedingWheelTemplate = [ 4096 '<div class="loading-overlay">', 4097 '<div class="bounce-loader"><div class="cssload-speeding-wheel-container"><div class="cssload-speeding-wheel"></div></div></div>', 4098 '</div>' 4099 ].join(''); 4100 4101 // Zenith 4102 const loadingOverlayZenithTemplate = [ 4103 '<div class="loading-overlay">', 4104 '<div class="bounce-loader"><div class="cssload-zenith-container"><div class="cssload-zenith"></div></div></div>', 4105 '</div>' 4106 ].join(''); 4107 4108 // Spinning Square 4109 const loadingOverlaySpinningSquareTemplate = [ 4110 '<div class="loading-overlay">', 4111 '<div class="bounce-loader"><div class="cssload-spinning-square-loading"></div></div>', 4112 '</div>' 4113 ].join(''); 4114 4115 // Pulse
4116 const loadingOverlayPulseTemplate = [ 4117 '<div class="loading-overlay">', 4118 '<div class="bounce-loader"><div class="wrapper-pulse"><div class="cssload-pulse-loader"></div></div></div>', 4119 '</div>' 4120 ].join(''); 4121 4122 const LoadingOverlay = function( $wrapper, options, noInheritOptions ) { 4123 return this.initialize( $wrapper, options, noInheritOptions ); 4124 }; 4125 4126 LoadingOverlay.prototype = { 4127 4128 options: { 4129 css: {}, 4130 hideDelay: 500, 4131 progressMinTimeout: 0, 4132 effect: 'default' 4133 }, 4134 4135 initialize($wrapper, options, noInheritOptions) { 4136 this.$wrapper = $wrapper; 4137 4138 this 4139 .setVars() 4140 .setOptions( options, noInheritOptions ) 4141 .build() 4142 .events() 4143 .dynamicShowHideEvents(); 4144 4145 this.$wrapper.data( 'loadingOverlay', this ); 4146 }, 4147 4148 setVars() { 4149 this.$overlay = this.$wrapper.find('.loading-overlay'); 4150 this.pageStatus = null; 4151 this.progress = null; 4152 this.animationInterval = 33; 4153 4154 return this; 4155 }, 4156 4157 setOptions(options, noInheritOptions) { 4158 if ( !this.$overlay.get(0) ) { 4159 this.matchProperties(); 4160 } 4161 4162 if( noInheritOptions ) { 4163 this.options = $.extend( true, {}, this.options, options ); 4164 } else { 4165 this.options = $.extend( true, {}, this.options, options, theme.fn.getOptions(this.$wrapper.data('plugin-options')) ); 4166 } 4167 4168 this.loaderClass = this.getLoaderClass( this.options.css.backgroundColor ); 4169 4170 return this; 4171 }, 4172 4173 build() { 4174 const _self = this; 4175 4176 if ( !this.$overlay.closest(document.documentElement).get(0) ) { 4177 if ( !this.$cachedOverlay ) { 4178 4179 switch ( _self.options.effect ) { 4180 case 'percentageProgress1': 4181 this.$overlay = $( loadingOverlayPercentageTemplate ).clone(); 4182 break; 4183 4184 case 'percentageProgress2': 4185 this.$overlay = $( loadingOverlayPercentageTemplate ).clone(); 4186 this.$overlay 4187 .addClass('loading-overlay-percentage-effect-2') 4188 .prepend('<div class="loading-overlay-background-layer"></div>'); 4189 break; 4190 4191 case 'cubes': 4192 this.$overlay = $( loadingOverlayCubesTemplate ).clone(); 4193 break; 4194 4195 case 'cubeProgress': 4196 this.$overlay = $( loadingOverlayCubeProgressTemplate ).clone(); 4197 break; 4198 4199 case 'floatRings': 4200 this.$overlay = $( loadingOverlayFloatRingsTemplate ).clone(); 4201 break; 4202 4203 case 'floatBars': 4204 this.$overlay = $( loadingOverlayFloatBarsTemplate ).clone(); 4205 break; 4206 4207 case 'speedingWheel': 4208 this.$overlay = $( loadingOverlaySpeedingWheelTemplate ).clone(); 4209 break; 4210 4211 case 'zenith': 4212 this.$overlay = $( loadingOverlayZenithTemplate ).clone(); 4213 break; 4214 4215 case 'spinningSquare': 4216 this.$overlay = $( loadingOverlaySpinningSquareTemplate ).clone(); 4217 break; 4218 4219 case 'pulse': 4220 this.$overlay = $( loadingOverlayPulseTemplate ).clone(); 4221 break; 4222 4223 case 'default': 4224 default: 4225 this.$overlay = $( loadingOverlayDefaultTemplate ).clone(); 4226 break; 4227 } 4228 4229 if ( this.options.css ) { 4230 this.$overlay.css( this.options.css ); 4231 this.$overlay.find( '.loader' ).addClass( this.loaderClass ); 4232 } 4233 } else { 4234 this.$overlay = this.$cachedOverlay.clone(); 4235 } 4236 4237 this.$wrapper.prepend( this.$overlay ); 4238 } 4239 4240 if ( !this.$cachedOverlay ) { 4241 this.$cachedOverlay = this.$overlay.clone(); 4242 } 4243 4244 if( ['percentageProgress1', 'percentageProgress2'].includes(_self.options.effect) ) { 4245 _self.updateProgress(); 4246 4247 if( _self.options.isDynamicHideShow ) { 4248 setTimeout(() => { 4249 _self.progress = 'complete'; 4250 4251 $('.page-loader-progress').text(100); 4252 4253 if( ['percentageProgress2'].includes(_self.options.effect) ) { 4254 $('.loading-overlay-background-layer').css({ 4255 width: '100%' 4256 }); 4257 } 4258 }, 2800); 4259 } 4260 } 4261 4262 return this; 4263 }, 4264 4265 events() { 4266 const _self = this; 4267 4268 if ( this.options.startShowing ) { 4269 _self.show(); 4270 } 4271 4272 if ( this.$wrapper.is('body') || this.options.hideOnWindowLoad ) { 4273 $( window ).on( 'load error', () => { 4274 setTimeout(() => { 4275 _self.hide(); 4276 }, _self.options.progressMinTimeout); 4277 }); 4278 } 4279 4280 if ( this.options.listenOn ) { 4281 $( this.options.listenOn ) 4282 .on( 'loading-overlay:show beforeSend.ic', e => { 4283 e.stopPropagation(); 4284 _self.show(); 4285 }) 4286 .on( 'loading-overlay:hide complete.ic', e => { 4287 e.stopPropagation(); 4288 _self.hide(); 4289 });
4290 } 4291 4292 this.$wrapper 4293 .on( 'loading-overlay:show beforeSend.ic', e => { 4294 if ( e.target === _self.$wrapper.get(0) ) { 4295 e.stopPropagation(); 4296 _self.show(); 4297 return true; 4298 } 4299 return false; 4300 }) 4301 .on( 'loading-overlay:hide complete.ic', e => { 4302 if ( e.target === _self.$wrapper.get(0) ) { 4303 e.stopPropagation(); 4304 _self.hide(); 4305 return true; 4306 } 4307 return false; 4308 }); 4309 4310 if( ['percentageProgress1', 'percentageProgress2'].includes(_self.options.effect) ) { 4311 $(window).on('load', () => { 4312 setTimeout(() => { 4313 _self.pageStatus = "complete"; 4314 4315 $('.page-loader-progress').text(100); 4316 4317 if( ['percentageProgress2'].includes(_self.options.effect) ) { 4318 $('.loading-overlay-background-layer').css({ 4319 width: '100%' 4320 }); 4321 } 4322 }, _self.options.progressMinTimeout); 4323 }); 4324 } 4325 4326 return this; 4327 }, 4328 4329 show() { 4330 this.build(); 4331 4332 this.position = this.$wrapper.css( 'position' ).toLowerCase(); 4333 if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) { 4334 this.$wrapper.css({ 4335 position: 'relative' 4336 }); 4337 } 4338 this.$wrapper.addClass( 'loading-overlay-showing' ); 4339 }, 4340 4341 hide() { 4342 const _self = this; 4343 4344 setTimeout(function() { 4345 _self.$wrapper.removeClass( 'loading-overlay-showing' ); 4346 4347 if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) { 4348 _self.$wrapper.css({ position: '' }); 4349 } 4350 4351 $(window).trigger('loading.overlay.ready'); 4352 }, _self.options.hideDelay); 4353 }, 4354 4355 updateProgress() { 4356 const _self = this; 4357 4358 const render = () => { 4359 if(_self.pageStatus == "complete"){ 4360 $('.page-loader-progress').text(100); 4361 setTimeout(() => { 4362 $('.page-loader-progress').addClass('d-none'); 4363 }, 700); 4364 } 4365 else{ 4366 if(_self.progress == null){ 4367 _self.progress = 1; 4368 } 4369 4370 _self.progress = _self.progress + 1; 4371 if(_self.progress >= 0 && _self.progress <= 30){ 4372 _self.animationInterval += 1; 4373 $('.page-loader-progress').text(_self.progress); 4374 } 4375 else if(_self.progress > 30 && _self.progress <= 60){ 4376 _self.animationInterval += 2; 4377 $('.page-loader-progress').text(_self.progress); 4378 } 4379 else if(_self.progress > 60 && _self.progress <= 80){ 4380 _self.animationInterval += 40; 4381 $('.page-loader-progress').text(_self.progress); 4382 } 4383 else if(_self.progress > 80 && _self.progress <= 90){ 4384 _self.animationInterval += 80; 4385 $('.page-loader-progress').text(_self.progress); 4386 } 4387 else if(_self.progress > 90 && _self.progress <= 95){ 4388 _self.animationInterval += 150; 4389 $('.page-loader-progress').text(_self.progress); 4390 } 4391 else if(_self.progress > 95 && _self.progress <= 99){ 4392 _self.animationInterval += 400; 4393 $('.page-loader-progress').text(_self.progress); 4394 } 4395 else if(_self.progress >= 100){ 4396 $('.page-loader-progress').text(99); 4397 } 4398 4399 if( ['percentageProgress2'].includes(_self.options.effect) ) { 4400 $('.loading-overlay-background-layer').css({ 4401 width: _self.progress + '%' 4402 }); 4403 } 4404 4405 self.loopInside = setTimeout(render, _self.animationInterval); 4406 } 4407 4408 }; 4409 render(); 4410 4411 return this; 4412 }, 4413 4414 matchProperties() { 4415 let i, l, properties; 4416 4417 properties = [ 4418 'backgroundColor', 4419 'borderRadius' 4420 ]; 4421 4422 l = properties.length; 4423 4424 for( i = 0; i < l; i++ ) { 4425 const obj = {}; 4426 obj[ properties[ i ] ] = this.$wrapper.css( properties[ i ] ); 4427 4428 $.extend( this.options.css, obj ); 4429 } 4430 }, 4431 4432 getLoaderClass(backgroundColor) { 4433 if ( !backgroundColor || backgroundColor === 'transparent' || backgroundColor === 'inherit' ) { 4434 return 'black'; 4435 } 4436 4437 let hexColor, r, g, b, yiq; 4438
4439 const colorToHex = color => { 4440 let hex, rgb; 4441 4442 if( color.includes('#') ){ 4443 hex = color.replace('#', ''); 4444 } else { 4445 rgb = color.match(/\d+/g); 4446 hex = ('0' + parseInt(rgb[0], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2); 4447 } 4448 4449 if ( hex.length === 3 ) { 4450 hex = hex + hex; 4451 } 4452 4453 return hex; 4454 }; 4455 4456 hexColor = colorToHex( backgroundColor ); 4457 4458 r = parseInt( hexColor.substr( 0, 2), 16 ); 4459 g = parseInt( hexColor.substr( 2, 2), 16 ); 4460 b = parseInt( hexColor.substr( 4, 2), 16 ); 4461 yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; 4462 4463 return ( yiq >= 128 ) ? 'black' : 'white'; 4464 }, 4465 4466 dynamicShowHide(effect) { 4467 const _self = this; 4468 4469 // Remove Loading Overlay Data 4470 $('body').removeData('loadingOverlay'); 4471 4472 // Remove Html Of Loading Overlay 4473 $('.loading-overlay').remove(); 4474 4475 if( effect == '' ) { 4476 return this; 4477 } 4478 4479 // Initialize New Loading Overlay (second parameter is to NO inherit data-plugin-options) 4480 $('body').loadingOverlay({ 4481 effect: effect ? effect : 'pulse', 4482 isDynamicHideShow: true 4483 }, true); 4484 4485 // Show Loading Overlay Loader 4486 $('body').data('loadingOverlay').show(); 4487 4488 // Hide Loading Overlay Loader 4489 setTimeout(() => { 4490 $('body').data('loadingOverlay').hide(); 4491 }, 3000); 4492 4493 return this; 4494 }, 4495 4496 dynamicShowHideEvents() { 4497 const _self = this; 4498 4499 // Button 4500 $(document).off('click.loading-overlay-button').on('click.loading-overlay-button', '.loading-overlay-button', function(e){ 4501 e.preventDefault(); 4502 4503 _self.dynamicShowHide( $(this).data('effect') ); 4504 }); 4505 4506 // Select 4507 $(document).off('change.loading-overlay-select').on('change.loading-overlay-select', '.loading-overlay-select', function(){ 4508 _self.dynamicShowHide( $(this).val() ); 4509 }); 4510 4511 return this; 4512 } 4513 4514 }; 4515 4516 // expose to scope 4517 $.extend(theme, { 4518 LoadingOverlay 4519 }); 4520 4521 // expose as a jquery plugin 4522 $.fn.loadingOverlay = function( opts, noInheritOptions ) { 4523 return this.each(function() { 4524 const $this = $( this ); 4525 4526 const loadingOverlay = $this.data( 'loadingOverlay' ); 4527 if ( loadingOverlay ) { 4528 return loadingOverlay; 4529 } else { 4530 const options = opts || $this.data( 'loading-overlay-options' ) || {}; 4531 return new LoadingOverlay( $this, options, noInheritOptions ); 4532 } 4533 }); 4534 } 4535 4536 // auto init 4537 $('[data-loading-overlay]').loadingOverlay(); 4538})).apply(this, [window.theme, jQuery]); 4539 4540// Masonry 4541(((theme = {}, $) => { 4542 const instanceName = '__masonry'; 4543 4544 class PluginMasonry { 4545 constructor($el, opts) { 4546 return this.initialize($el, opts); 4547 } 4548 4549 initialize($el, opts) { 4550 if ($el.data(instanceName)) { 4551 return this; 4552 } 4553 4554 this.$el = $el; 4555 4556 this 4557 .setData() 4558 .setOptions(opts) 4559 .build(); 4560 4561 return this; 4562 } 4563 4564 setData() { 4565 this.$el.data(instanceName, this); 4566 4567 return this; 4568 } 4569 4570 setOptions(opts) { 4571 this.options = $.extend(true, {}, PluginMasonry.defaults, opts, { 4572 wrapper: this.$el 4573 }); 4574 4575 return this; 4576 } 4577 4578 build() { 4579 if (!($.isFunction($.fn.isotope))) { 4580 return this; 4581 } 4582 4583 const self = this, $window = $(window); 4584 4585 self.$loader = false; 4586 4587 if (self.options.wrapper.parents('.masonry-loader').get(0)) { 4588 self.$loader = self.options.wrapper.parents('.masonry-loader'); 4589 self.createLoader(); 4590 } 4591 4592 self.options.wrapper.one('layoutComplete', (event, laidOutItems) => { 4593 self.removeLoader(); 4594 }); 4595 4596 self.options.wrapper.waitForImages(() => { 4597 self.options.wrapper.isotope(self.options); 4598 }); 4599 4600 $(window).on('resize', () => { 4601 setTimeout(() => { 4602 self.options.wrapper.isotope('layout'); 4603 }, 300); 4604 }); 4605 4606 setTimeout(() => { 4607 self.removeLoader(); 4608 }, 3000); 4609 4610 return this; 4611 } 4612 4613 createLoader() { 4614 const self = this; 4615 4616 const loaderTemplate = [ 4617 '<div class="bounce-loader">', 4618 '<div class="bounce1"></div>', 4619 '<div class="bounce2"></div>', 4620 '<div class="bounce3"></div>', 4621 '</div>' 4622 ].join(''); 4623 4624 self.$loader.append(loaderTemplate); 4625 4626 return this; 4627 } 4628 4629 removeLoader() { 4630 4631 const self = this; 4632 4633 if (self.$loader) { 4634 4635 self.$loader.removeClass('masonry-loader-showing'); 4636 4637 setTimeout(() => { 4638 self.$loader.addClass('masonry-loader-loaded'); 4639 }, 300); 4640 4641 } 4642 4643 } 4644 } 4645 4646 PluginMasonry.defaults = { 4647 4648 }; 4649 4650 // expose to scope 4651 $.extend(theme, { 4652 PluginMasonry 4653 }); 4654 4655 // jquery plugin 4656 $.fn.themePluginMasonry = function(opts) { 4657 return this.map(function() { 4658 const $this = $(this); 4659 4660 if ($this.data(instanceName)) { 4661 return $this.data(instanceName); 4662 } else { 4663 return new PluginMasonry($this, opts); 4664 } 4665 4666 }); 4667 } 4668})).apply(this, [window.theme, jQuery]); 4669 4670// Match Height 4671(((theme = {}, $) => { 4672 const instanceName = '__matchHeight'; 4673 4674 class PluginMatchHeight { 4675 constructor($el, opts) { 4676 return this.initialize($el, opts); 4677 } 4678 4679 initialize($el, opts) { 4680 if ($el.data(instanceName)) { 4681 return this; 4682 } 4683 4684 this.$el = $el; 4685 4686 this 4687 .setData() 4688 .setOptions(opts) 4689 .build(); 4690 4691 return this; 4692 } 4693 4694 setData() { 4695 this.$el.data(instanceName, this); 4696 4697 return this; 4698 } 4699 4700 setOptions(opts) { 4701 this.options = $.extend(true, {}, PluginMatchHeight.defaults, opts, { 4702 wrapper: this.$el 4703 }); 4704 4705 return this; 4706 } 4707 4708 build() { 4709 if (!($.isFunction($.fn.matchHeight))) { 4710 return this; 4711 } 4712 4713 const self = this; 4714 4715 self.options.wrapper.matchHeight(self.options); 4716 4717 return this; 4718 } 4719 } 4720 4721 PluginMatchHeight.defaults = { 4722 byRow: true, 4723 property: 'height', 4724 target: null, 4725 remove: false 4726 }; 4727 4728 // expose to scope 4729 $.extend(theme, { 4730 PluginMatchHeight 4731 }); 4732 4733 // jquery plugin 4734 $.fn.themePluginMatchHeight = function(opts) { 4735 return this.map(function() { 4736 const $this = $(this); 4737 4738 if ($this.data(instanceName)) { 4739 return $this.data(instanceName); 4740 } else { 4741 return new PluginMatchHeight($this, opts); 4742 } 4743 4744 }); 4745 } 4746})).apply(this, [window.theme, jQuery]); 4747 4748// Parallax 4749(((theme = {}, $) => { 4750 const instanceName = '__parallax'; 4751 4752 class PluginParallax { 4753 constructor($el, opts) { 4754 return this.initialize($el, opts); 4755 } 4756 4757 initialize($el, opts) { 4758 if ($el.data(instanceName)) { 4759 return this; 4760 } 4761 4762 this.$el = $el; 4763 4764 this 4765 .setData() 4766 .setOptions(opts) 4767 .build(); 4768 4769 return this; 4770 } 4771 4772 setData() { 4773 this.$el.data(instanceName, this); 4774 4775 return this; 4776 } 4777 4778 setOptions(opts) { 4779 this.options = $.extend(true, {}, PluginParallax.defaults, opts, { 4780 wrapper: this.$el 4781 }); 4782 4783 return this; 4784 } 4785 4786 build() { 4787 const self = this; 4788 const $window = $(window); 4789 let offset; 4790 let yPos; 4791 let plxPos; 4792 let background; 4793 let rotateY; 4794 4795 // Mouse Parallax 4796 if( self.options.mouseParallax ) { 4797 4798 $window.mousemove(({clientX, clientY}) => { 4799 4800 $('.parallax-mouse-object', self.options.wrapper).each(function() { 4801 4802 const moving_value = $( this ).attr('data-value');
4803 const x = (clientX * moving_value) / 250; 4804 const y = (clientY * moving_value) / 250; 4805 4806 $( this ).css('transform', 'translateX(' + x + 'px) translateY(' + y + 'px)'); 4807 }); 4808 4809 }); 4810 4811 return this; 4812 4813 } 4814 4815 // Scrollable 4816 if( self.options.scrollableParallax && $(window).width() > self.options.scrollableParallaxMinWidth ) { 4817 const $scrollableWrapper = self.options.wrapper.find('.scrollable-parallax-wrapper'); 4818 4819 if( $scrollableWrapper.get(0) ) { 4820 let progress = ( $(window).scrollTop() > ( self.options.wrapper.offset().top + $(window).outerHeight() ) ) ? self.options.cssValueEnd : self.options.cssValueStart; 4821 const cssValueUnit = self.options.cssValueUnit ? self.options.cssValueUnit : ''; 4822 4823 $scrollableWrapper.css({ 4824 'background-image' : 'url(' + self.options.wrapper.data('image-src') + ')', 4825 'background-size' : 'cover', 4826 'background-position' : 'center', 4827 'background-attachment' : 'fixed', 4828 'transition' : 'ease '+ self.options.cssProperty +' '+ self.options.transitionDuration, 4829 'width' : progress + '%' 4830 }); 4831 4832 $(window).on('scroll', e => { 4833 if( self.options.wrapper.visible( true ) ) { 4834 const $window = $(window), scrollTop = $window.scrollTop(), elementOffset = self.options.wrapper.offset().top, currentElementOffset = (elementOffset - scrollTop); 4835 4836 const scrollPercent = Math.abs( +( currentElementOffset - $window.height() ) / (self.options.startOffset ? self.options.startOffset : 7) ); 4837 4838 // Increment progress value according scroll position 4839 if( scrollPercent <= self.options.cssValueEnd && progress <= self.options.cssValueEnd ) { 4840 progress = self.options.cssValueStart + scrollPercent; 4841 } 4842 4843 // Adjust CSS end value 4844 if( progress > self.options.cssValueEnd ) { 4845 progress = self.options.cssValueEnd; 4846 } 4847 4848 // Adjust CSS start value 4849 if( progress < self.options.cssValueStart ) { 4850 progress = self.options.cssValueStart; 4851 } 4852 4853 const styles = {}; 4854 styles[self.options.cssProperty] = progress + cssValueUnit; 4855 4856 $scrollableWrapper.css(styles); 4857 } 4858 }); 4859 } 4860 4861 return; 4862 } 4863 4864 // Create Parallax Element 4865 if( self.options.fadeIn ) { 4866 background = $('<div class="parallax-background fadeIn animated"></div>'); 4867 } else { 4868 background = $('<div class="parallax-background"></div>'); 4869 } 4870 4871 // Set Style for Parallax Element 4872 background.css({ 4873 'background-image' : 'url(' + self.options.wrapper.data('image-src') + ')', 4874 'background-size' : 'cover', 4875 'position' : 'absolute', 4876 'top' : 0, 4877 'left' : 0, 4878 'width' : '100%', 4879 'height' : self.options.parallaxHeight 4880 }); 4881 4882 if( self.options.parallaxScale ) { 4883 background.css({ 4884 'transition' : 'transform 500ms ease-out' 4885 }); 4886 } 4887 4888 // Add Parallax Element on DOM 4889 self.options.wrapper.prepend(background); 4890 4891 // Set Overlfow Hidden and Position Relative to Parallax Wrapper 4892 self.options.wrapper.css({ 4893 'position' : 'relative', 4894 'overflow' : 'hidden' 4895 }); 4896 4897 // Parallax Effect on Scroll & Resize 4898 const parallaxEffectOnScrolResize = () => { 4899 $window.on('scroll resize', () => { 4900 offset = self.options.wrapper.offset(); 4901 yPos = -($window.scrollTop() - (offset.top - 100)) / ((self.options.speed + 2 )); 4902 plxPos = (yPos < 0) ? Math.abs(yPos) : -Math.abs(yPos); 4903 rotateY = ( $('html[dir="rtl"]').get(0) ) ? ' rotateY(180deg)' : ''; // RTL 4904 4905 offset = self.options.wrapper.offset(); 4906 yPos = -($window.scrollTop() - (offset.top - 100)) / ((self.options.speed + 2 )); 4907 plxPos = (yPos < 0) ? Math.abs(yPos) : -Math.abs(yPos); 4908 rotateY = ( $('html[dir="rtl"]').get(0) ) ? ' rotateY(180deg)' : ''; // RTL 4909 4910 if( !self.options.parallaxScale ) { 4911 4912 if( self.options.parallaxDirection == 'bottom' ) { 4913 self.options.offset = 250; 4914 } 4915 4916 let y = ( (plxPos - 50) + (self.options.offset) ); 4917 if( self.options.parallaxDirection == 'bottom' ) { 4918 y = ( y < 0 ) ? Math.abs( y ) : -Math.abs( y ); 4919 } 4920 4921 background.css({
4922 'transform' : 'translate3d(0, '+ y +'px, 0)' + rotateY, 4923 'background-position-x' : self.options.horizontalPosition 4924 }); 4925 4926 } else { 4927 const scrollTop = $window.scrollTop(); 4928 const elementOffset = self.options.wrapper.offset().top; 4929 const currentElementOffset = (elementOffset - scrollTop); 4930 let scrollPercent = Math.abs( +( currentElementOffset - $window.height() ) / (self.options.startOffset ? self.options.startOffset : 7) ); 4931 4932 scrollPercent = parseInt((scrollPercent >= 100) ? 100 : scrollPercent); 4933 4934 const currentScale = (scrollPercent / 100) * 50; 4935 4936 if ( !self.options.parallaxScaleInvert ) { 4937 background.css({ 4938 'transform' : 'scale(1.' + String(currentScale).padStart(2, '0') + ', 1.' + String(currentScale).padStart(2, '0') + ')' 4939 }); 4940 } else { 4941 background.css({ 4942 'transform' : 'scale(1.' + String(50 - currentScale).padStart(2, '0') + ', 1.' + String(50 - currentScale).padStart(2, '0') + ')' 4943 }); 4944 } 4945 } 4946 }); 4947 4948 $window.trigger('scroll'); 4949 }; 4950 4951 if (!$.browser.mobile) { 4952 parallaxEffectOnScrolResize(); 4953 } else { 4954 if( self.options.enableOnMobile == true ) { 4955 parallaxEffectOnScrolResize(); 4956 } else { 4957 self.options.wrapper.addClass('parallax-disabled'); 4958 } 4959 } 4960 4961 return this; 4962 } 4963 } 4964 4965 PluginParallax.defaults = { 4966 speed: 1.5, 4967 horizontalPosition: '50%', 4968 offset: 0, 4969 parallaxDirection: 'top', 4970 parallaxHeight: '180%', 4971 parallaxScale: false, 4972 parallaxScaleInvert: false, 4973 scrollableParallax: false, 4974 scrollableParallaxMinWidth: 991, 4975 startOffset: 7, 4976 transitionDuration: '200ms', 4977 cssProperty: 'width', 4978 cssValueStart: 40, 4979 cssValueEnd: 100, 4980 cssValueUnit: 'vw', 4981 mouseParallax: false, 4982 enableOnMobile: true 4983 }; 4984 4985 // expose to scope 4986 $.extend(theme, { 4987 PluginParallax 4988 }); 4989 4990 // jquery plugin 4991 $.fn.themePluginParallax = function(opts) { 4992 return this.map(function() { 4993 const $this = $(this); 4994 4995 if ($this.data(instanceName)) { 4996 return $this.data(instanceName); 4997 } else { 4998 return new PluginParallax($this, opts); 4999 } 5000 5001 }); 5002 } 5003})).apply(this, [window.theme, jQuery]); 5004 5005// Progress Bar 5006(((theme = {}, $) => { 5007 const instanceName = '__progressBar'; 5008 5009 class PluginProgressBar { 5010 constructor($el, opts) { 5011 return this.initialize($el, opts); 5012 } 5013 5014 initialize($el, opts) { 5015 if ($el.data(instanceName)) { 5016 return this; 5017 } 5018 5019 this.$el = $el; 5020 5021 this 5022 .setData() 5023 .setOptions(opts) 5024 .build(); 5025 5026 return this; 5027 } 5028 5029 setData() { 5030 this.$el.data(instanceName, this); 5031 5032 return this; 5033 } 5034 5035 setOptions(opts) { 5036 this.options = $.extend(true, {}, PluginProgressBar.defaults, opts, { 5037 wrapper: this.$el 5038 }); 5039 5040 return this; 5041 } 5042 5043 build() { 5044 const self = this; 5045 const $el = this.options.wrapper; 5046 let delay = 1; 5047 5048 delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay); 5049 5050 $el.addClass($el.attr('data-appear-animation')); 5051 5052 setTimeout(() => { 5053 5054 $el.animate({ 5055 width: $el.attr('data-appear-progress-animation') 5056 }, 1500, 'easeOutQuad', () => { 5057 $el.find('.progress-bar-tooltip').animate({ 5058 opacity: 1 5059 }, 500, 'easeOutQuad'); 5060 }); 5061 5062 }, delay); 5063 5064 return this; 5065 } 5066 } 5067 5068 PluginProgressBar.defaults = { 5069 accX: 0, 5070 accY: -50, 5071 delay: 1 5072 }; 5073 5074 // expose to scope 5075 $.extend(theme, { 5076 PluginProgressBar 5077 }); 5078 5079 // jquery plugin 5080 $.fn.themePluginProgressBar = function(opts) { 5081 return this.map(function() { 5082 const $this = $(this); 5083 5084 if ($this.data(instanceName)) { 5085 return $this.data(instanceName); 5086 } else { 5087 return new PluginProgressBar($this, opts); 5088 } 5089 5090 }); 5091 } 5092})).apply(this, [window.theme, jQuery]); 5093 5094// Random Images 5095(((theme = {}, $) => { 5096 const instanceName = '__randomimages'; 5097 5098 class PluginRandomImages { 5099 constructor($el, opts) { 5100 return this.initialize($el, opts); 5101 } 5102 5103 initialize($el, opts) { 5104 this.$el = $el; 5105 this.st = ''; 5106 this.times = 0; 5107 this.perImageIndex = 0; 5108 5109 if( $el.is('img') && typeof opts.imagesListURL == 'undefined' ) { 5110 return false; 5111 } 5112 5113 this 5114 .setData() 5115 .setOptions(opts) 5116 .build(); 5117 5118 return this; 5119 } 5120 5121 setData() { 5122 this.$el.data(instanceName, this); 5123 5124 return this; 5125 } 5126 5127 setOptions(opts) { 5128 this.options = $.extend(true, {}, PluginRandomImages.defaults, opts, { 5129 wrapper: this.$el 5130 }); 5131 5132 return this; 5133 } 5134 5135 build() { 5136 const self = this; 5137 5138 // Control the screens size we want to have the plugin working 5139 if( $(window).width() < self.options.minWindowWidth ) { 5140 return false; 5141 } 5142 5143 // Check if is single image or wrapper with images inside 5144 if( self.$el.is('img') ) { 5145 5146 // Check it's inside a lightbox 5147 self.isInsideLightbox = self.$el.closest('.lightbox').length ? true : false; 5148 5149 // Push the initial image to lightbox list/array 5150 if( self.isInsideLightbox && self.options.lightboxImagesListURL ) { 5151 self.options.lightboxImagesListURL.push( self.$el.closest('.lightbox').attr('href') ); 5152 } 5153 5154 // Push the current image src to the array 5155 self.options.imagesListURL.push( self.$el.attr('src') ); 5156 5157 // Start with lastIndex as the first image loaded on the page 5158 self.lastIndex = self.options.imagesListURL.length - 1; 5159 5160 // Identify the last random image element (if has more than one on the page) 5161 if( self.options.random == false ) { 5162 $('.plugin-random-images').each(function(i){ 5163 if( i == $('.plugin-random-images').length - 1 ) { 5164 $(this).addClass('the-last'); 5165 } 5166 });
5167 } 5168 5169 // Start the recursive timeout 5170 setTimeout(() => { 5171 self.recursiveTimeout( 5172 self.perImageTag, 5173 self.options.delay == null ? 3000 : self.options.delay 5174 ); 5175 }, self.options.delay == null ? 300 : self.options.delay / 3); 5176 5177 } else { 5178 5179 // Start the recursive timeout 5180 setTimeout( self.recursiveTimeout( 5181 self.perWrapper, 5182 self.options.delay ? self.options.delay : getPerWrapperHighDelay(), 5183 false 5184 ), 300); 5185 5186 } 5187 5188 // Stop After Few Seconds 5189 if( self.options.stopAfterFewSeconds ) { 5190 setTimeout(() => { 5191 clearTimeout(self.st); 5192 }, self.options.stopAfterFewSeconds); 5193 } 5194 5195 return this; 5196 5197 } 5198 5199 perImageTag() { 5200 const self = this; 5201 5202 // Generate a random index to make the images rotate randomly 5203 let index = self.options.random ? Math.floor(Math.random() * self.options.imagesListURL.length) : self.lastIndex; 5204 5205 // Avoid repeat the same image 5206 if( self.lastIndex !== '' && self.lastIndex == index ) { 5207 if( self.options.random ) { 5208 while( index == self.lastIndex ) { 5209 index = Math.floor(Math.random() * self.options.imagesListURL.length); 5210 } 5211 } else { 5212 index = index - 1; 5213 if( index == -1 ) { 5214 index = self.options.imagesListURL.length - 1; 5215 } 5216 } 5217 } 5218 5219 // Turn the image ready for animations 5220 self.$el.addClass('animated'); 5221 5222 // Remove the entrance animation class and add the out animation class 5223 self.$el.removeClass( self.options.animateIn ).addClass( self.options.animateOut ); 5224 5225 // Change the image src and add the class for entrance animation 5226 setTimeout( () => { 5227 self.$el.attr('src', self.options.imagesListURL[index]).removeClass( self.options.animateOut ).addClass(self.options.animateIn); 5228 5229 if( self.isInsideLightbox && self.options.lightboxImagesListURL ) { 5230 self.$el.closest('.lightbox').attr('href', self.options.lightboxImagesListURL[index]); 5231 } 5232 }, 1000); 5233 5234 // Save the last index for future checks 5235 self.lastIndex = index; 5236 5237 // Increment the times var 5238 self.times++; 5239 5240 // Save the index for stopAtImageIndex option 5241 self.perImageIndex = index; 5242 5243 return this; 5244 } 5245 5246 // Iterate the imaes loop and get the higher value 5247 getPerWrapperHighDelay() { 5248 const self = this; 5249 const $wrapper = self.$el; 5250 let delay = 0; 5251 5252 $wrapper.find('img').each(function(){ 5253 const $image = $(this); 5254 5255 if( $image.data('rimage-delay') && parseInt( $image.data('rimage-delay') ) > delay ) {
5256 delay = parseInt( $image.data('rimage-delay') ); 5257 } 5258 }); 5259 5260 return delay; 5261 } 5262 5263 perWrapper() { 5264 const self = this, $wrapper = self.$el; 5265 5266 // Turns the imageLlistURL into an array 5267 self.options.imagesListURL = []; 5268 5269 // Find all images inside the element wrapper and push their sources to image list array 5270 $wrapper.find('img').each(function(){ 5271 const $image = $(this); 5272 self.options.imagesListURL.push( $image.attr('src') ); 5273 }); 5274 5275 // Shuffle the images list array (random effect) 5276 self.options.imagesListURL = self.shuffle( self.options.imagesListURL ); 5277 5278 // Iterate over each image and make some checks like delay for each image, animations, etc... 5279 $wrapper.find('img').each(function(index){ 5280 const $image = $(this), animateIn = $image.data('rimage-animate-in') ? $image.data('rimage-animate-in') : self.options.animateIn, animateOut = $image.data('rimage-animate-out') ? $image.data('rimage-animate-out') : self.options.animateOut, delay = $image.data('rimage-delay') ? $image.data('rimage-delay') : 2000; 5281 5282 $image.addClass('animated'); 5283 5284 setTimeout( () => { 5285 $image.removeClass( animateIn ).addClass( animateOut ); 5286 }, delay / 2); 5287 5288 setTimeout( () => { 5289 $image.attr('src', self.options.imagesListURL[index]).removeClass( animateOut ).addClass(animateIn); 5290 }, delay); 5291 5292 }); 5293 5294 // Increment the times variable 5295 self.times++; 5296 5297 return this; 5298 } 5299 5300 recursiveTimeout(callback, delay) { 5301 const self = this; 5302 5303 const timeout = () => { 5304 5305 if( callback !== null ) { 5306 callback.call(self); 5307 } 5308 5309 // Recursive 5310 self.st = setTimeout(timeout, delay == null ? 1000 : delay); 5311 5312 if( self.options.random == false ) { 5313 if( self.$el.hasClass('the-last') ) { 5314 $('.plugin-random-images').trigger('rimages.start'); 5315 } else { 5316 clearTimeout(self.st); 5317 } 5318 } 5319 5320 // Stop At Image Index 5321 if( self.options.stopAtImageIndex && parseInt(self.options.stopAtImageIndex) == self.perImageIndex ) { 5322 clearTimeout(self.st); 5323 } 5324 5325 // Stop After X Timers 5326 if( self.options.stopAfterXTimes == self.times ) { 5327 clearTimeout(self.st); 5328 } 5329 }; 5330 timeout(); 5331 5332 self.$el.on('rimages.start', () => { 5333 clearTimeout(self.st); 5334 self.st = setTimeout(timeout, delay == null ? 1000 : delay); 5335 }); 5336 5337 } 5338 5339 shuffle(array) { 5340 for (let i = array.length - 1; i > 0; i--) { 5341 const j = Math.floor(Math.random() * (i + 1)); 5342 const temp = array[i]; 5343 array[i] = array[j]; 5344 array[j] = temp; 5345 } 5346 5347 return array; 5348 } 5349 } 5350 5351 PluginRandomImages.defaults = { 5352 minWindowWidth: 0, 5353 random: true, 5354 imagesListURL: null, 5355 lightboxImagesListURL: null, 5356 delay: null, 5357 animateIn: 'fadeIn', 5358 animateOut: 'fadeOut',
5359 stopAtImageIndex: false, // The value shoudl be the index value of array with images as string. Eg: '2' 5360 stopAfterFewSeconds: false, // The value should be in mili-seconds. Eg: 10000 = 10 seconds 5361 stopAfterXTimes: false, 5362 accY: 0 5363 }; 5364 5365 // expose to scope 5366 $.extend(theme, { 5367 PluginRandomImages 5368 }); 5369 5370 // jquery plugin 5371 $.fn.themePluginRandomImages = function(opts) { 5372 return this.map(function() { 5373 const $this = $(this); 5374 5375 if ($this.data(instanceName)) { 5376 return $this.data(instanceName); 5377 } else { 5378 return new PluginRandomImages($this, opts); 5379 } 5380 5381 }); 5382 } 5383})).apply(this, [window.theme, jQuery]); 5384 5385// Read More 5386(((theme = {}, $) => { 5387 const instanceName = '__readmore'; 5388 5389 class PluginReadMore { 5390 constructor($el, opts) { 5391 return this.initialize($el, opts); 5392 } 5393 5394 initialize($el, opts) { 5395 const self = this; 5396 5397 this.$el = $el; 5398 5399 this 5400 .setData() 5401 .setOptions(opts) 5402 .build() 5403 .events(); 5404 5405 if( self.options.startOpened ) { 5406 self.options.wrapper.find('.readmore-button-wrapper > a').trigger('click'); 5407 } 5408 5409 return this; 5410 } 5411 5412 setData() { 5413 this.$el.data(instanceName, this); 5414 5415 return this; 5416 } 5417 5418 setOptions(opts) { 5419 this.options = $.extend(true, {}, PluginReadMore.defaults, opts, { 5420 wrapper: this.$el 5421 }); 5422 5423 return this; 5424 } 5425 5426 build() { 5427 const self = this; 5428 5429 self.options.wrapper.addClass('position-relative'); 5430 5431 // Overlay 5432 self.options.wrapper.append( '<div class="readmore-overlay"></div>' ); 5433 5434 // Check if is Safari 5435 let backgroundCssValue = 'linear-gradient(180deg, rgba(2, 0, 36, 0) 0%, '+ self.options.overlayColor +' 100%)'; 5436 if( $('html').hasClass('safari') ) { 5437 backgroundCssValue = '-webkit-linear-gradient(top, rgba(2, 0, 36, 0) 0%, '+ self.options.overlayColor +' 100%)' 5438 } 5439 5440 self.options.wrapper.find('.readmore-overlay').css({ 5441 background: backgroundCssValue, 5442 position: 'absolute', 5443 bottom: 0, 5444 left: 0, 5445 width: '100%', 5446 height: self.options.overlayHeight, 5447 'z-index': 1 5448 }); 5449 5450 // Read More Button 5451 self.options.wrapper.find('.readmore-button-wrapper').removeClass('d-none').css({ 5452 position: 'absolute', 5453 bottom: 0, 5454 left: 0, 5455 width: '100%', 5456 'z-index': 2 5457 }); 5458 5459 // Button Label 5460 self.options.wrapper.find('.readmore-button-wrapper > a').html( self.options.buttonOpenLabel ); 5461 5462 self.options.wrapper.css({ 5463 'height': self.options.maxHeight, 5464 'overflow-y': 'hidden' 5465 }); 5466 5467 // Alignment 5468 switch ( self.options.align ) { 5469 case 'center': 5470 self.options.wrapper.find('.readmore-button-wrapper').addClass('text-center'); 5471 break; 5472 5473 case 'end': 5474 self.options.wrapper.find('.readmore-button-wrapper').addClass('text-end'); 5475 break; 5476 5477 case 'start': 5478 default: 5479 self.options.wrapper.find('.readmore-button-wrapper').addClass('text-start'); 5480 break; 5481 } 5482 5483 return this; 5484 5485 } 5486 5487 events() { 5488 const self = this; 5489 5490 // Read More 5491 self.readMore = () => { 5492 self.options.wrapper.find('.readmore-button-wrapper > a:not(.readless)').on('click', function(e){ 5493 e.preventDefault(); 5494 5495 const $this = $(this); 5496 5497 setTimeout(() => { 5498 self.options.wrapper.animate({ 5499 'height': self.options.wrapper[0].scrollHeight 5500 }, () => { 5501 if( !self.options.enableToggle ) { 5502 $this.fadeOut(); 5503 } 5504 5505 $this.html( self.options.buttonCloseLabel ).addClass('readless').off('click'); 5506 5507 self.readLess(); 5508 5509 self.options.wrapper.find('.readmore-overlay').fadeOut(); 5510 self.options.wrapper.css({ 5511 'max-height': 'none', 5512 'overflow': 'visible' 5513 }); 5514 5515 self.options.wrapper.find('.readmore-button-wrapper').animate({ 5516 bottom: -20 5517 }); 5518 }); 5519 }, 200); 5520 }); 5521 } 5522 5523 // Read Less 5524 self.readLess = () => { 5525 self.options.wrapper.find('.readmore-button-wrapper > a.readless').on('click', function(e){
5526 e.preventDefault(); 5527 5528 const $this = $(this); 5529 5530 // Button 5531 self.options.wrapper.find('.readmore-button-wrapper').animate({ 5532 bottom: 0 5533 }); 5534 5535 // Overlay 5536 self.options.wrapper.find('.readmore-overlay').fadeIn(); 5537 5538 setTimeout(() => { 5539 self.options.wrapper.height(self.options.wrapper[0].scrollHeight).animate({ 5540 'height': self.options.maxHeight 5541 }, () => { 5542 $this.html( self.options.buttonOpenLabel ).removeClass('readless').off('click'); 5543 5544 self.readMore(); 5545 5546 self.options.wrapper.css({ 5547 'overflow': 'hidden' 5548 }); 5549 }); 5550 }, 200); 5551 }); 5552 } 5553 5554 // First Load 5555 self.readMore(); 5556 5557 return this; 5558 } 5559 } 5560 5561 PluginReadMore.defaults = { 5562 buttonOpenLabel: 'Read More <i class="fas fa-chevron-down text-2 ms-1"></i>', 5563 buttonCloseLabel: 'Read Less <i class="fas fa-chevron-up text-2 ms-1"></i>', 5564 enableToggle: true, 5565 maxHeight: 110, 5566 overlayColor: '#FFF', 5567 overlayHeight: 100, 5568 startOpened: false, 5569 align: 'left' 5570 }; 5571 5572 // expose to scope 5573 $.extend(theme, { 5574 PluginReadMore 5575 }); 5576 5577 // jquery plugin 5578 $.fn.themePluginReadMore = function(opts) { 5579 return this.map(function() { 5580 const $this = $(this); 5581 5582 if ($this.data(instanceName)) { 5583 return $this.data(instanceName); 5584 } else { 5585 return new PluginReadMore($this, opts); 5586 } 5587 5588 }); 5589 } 5590})).apply(this, [window.theme, jQuery]); 5591 5592// Revolution Slider 5593(((theme = {}, $) => { 5594 const instanceName = '__revolution'; 5595 5596 class PluginRevolutionSlider { 5597 constructor($el, opts) { 5598 return this.initialize($el, opts); 5599 } 5600 5601 initialize($el, opts) { 5602 if ($el.data(instanceName)) { 5603 return this; 5604 } 5605 5606 this.$el = $el; 5607 5608 this 5609 .setData() 5610 .setOptions(opts) 5611 .build() 5612 .events(); 5613 5614 return this; 5615 } 5616 5617 setData() { 5618 this.$el.data(instanceName, this); 5619 5620 return this; 5621 } 5622 5623 setOptions(opts) { 5624 this.options = $.extend(true, {}, PluginRevolutionSlider.defaults, opts, { 5625 wrapper: this.$el 5626 }); 5627 5628 return this; 5629 } 5630 5631 build() { 5632 if (!($.isFunction($.fn.revolution))) { 5633 return this; 5634 } 5635 5636 // Single Slider Class 5637 if(this.options.wrapper.find('> ul > li').length == 1) { 5638 this.options.wrapper.addClass('slider-single-slide'); 5639 5640 // Remove Bullets 5641 // this.options.navigation.bullets.enable = false; 5642 $.extend(this.options.navigation, { 5643 bullets: { 5644 enable: false 5645 } 5646 }); 5647 5648 } 5649 5650 // Full Screen Class 5651 if(this.options.sliderLayout == 'fullscreen') { 5652 this.options.wrapper.closest('.slider-container').addClass('fullscreen-slider'); 5653 } 5654 5655 // Initialize Revolution Slider 5656 this.options.wrapper.revolution(this.options); 5657 5658 // Addon Init - Typewriter 5659 if(this.options.addOnTypewriter.enable) { 5660 RsTypewriterAddOn($, this.options.wrapper); 5661 } 5662 5663 // Addon Init - Whiteboard 5664 if(this.options.addOnWhiteboard.enable) { 5665 this.options.wrapper.rsWhiteBoard(); 5666 } 5667 5668 // Addon Init - Particles 5669 if(this.options.addOnParticles.enable) { 5670 RsParticlesAddOn(this.options.wrapper); 5671 } 5672 5673 // Addon Init - Countdown 5674 if(this.options.addOnCountdown.enable) { 5675 tp_countdown(this.options.wrapper, this.options.addOnCountdown.targetdate, this.options.addOnCountdown.slidechanges); 5676 } 5677 5678 // Addon Init - Slicey 5679 if(this.options.addOnSlicey.enable) { 5680 this.options.wrapper.revSliderSlicey(); 5681 } 5682 5683 // Addon Init - Filmstrip 5684 if(this.options.addOnFilmstrip.enable) { 5685 RsFilmstripAddOn($, this.options.wrapper, '../vendor/rs-plugin/revolution-addons/filmstrip/', false); 5686 } 5687 5688 // Addon Init - Before After 5689 if(this.options.addOnBeforeAfter.enable) { 5690 RevSliderBeforeAfter($, this.options.wrapper, this.options.addOnBeforeAfter.options); 5691 } 5692 5693 // Addon Init - Panorama 5694 if(this.options.addOnPanorama.enable) { 5695 RsAddonPanorama($, this.options.wrapper); 5696 } 5697 5698 // Addon Init - Revealer 5699 if(this.options.addOnRevealer.enable) { 5700 RsRevealerAddOn($, this.options.wrapper, this.options.revealer.spinnerHtml); 5701 } 5702 5703 // Addon Init - Duotone 5704 if(this.options.addOnDuotone.enable) { 5705 RsAddonDuotone($, this.options.wrapper, true, "cubic-bezier(0.645, 0.045, 0.355, 1.000)", "1000"); 5706 } 5707 5708 // Addon Init - Bubblemorph
5709 if(this.options.addOnBubblemorph.enable) { 5710 BubbleMorphAddOn($, this.options.wrapper, false); 5711 } 5712 5713 // Addon Init - Distortion 5714 if(this.options.addOnDistortion.enable) { 5715 RsLiquideffectAddOn($, this.options.wrapper); 5716 } 5717 5718 return this; 5719 } 5720 5721 events() { 5722 5723 return this; 5724 } 5725 } 5726 5727 PluginRevolutionSlider.defaults = { 5728 sliderType: 'standard', 5729 sliderLayout: 'fullwidth', 5730 delay: 9000, 5731 gridwidth: 1170, 5732 gridheight: 500, 5733 spinner: 'spinner3', 5734 disableProgressBar: 'on', 5735 parallax: { 5736 type: 'off', 5737 bgparallax: 'off' 5738 }, 5739 navigation: { 5740 keyboardNavigation: 'off', 5741 keyboard_direction: 'horizontal', 5742 mouseScrollNavigation: 'off', 5743 onHoverStop: 'off', 5744 touch: { 5745 touchenabled: 'on', 5746 swipe_threshold: 75, 5747 swipe_min_touches: 1, 5748 swipe_direction: 'horizontal', 5749 drag_block_vertical: false 5750 }, 5751 arrows: { 5752 enable: true, 5753 hide_onmobile: false, 5754 hide_under: 0, 5755 hide_onleave: true, 5756 hide_delay: 200, 5757 hide_delay_mobile: 1200, 5758 left: { 5759 h_align: 'left', 5760 v_align: 'center', 5761 h_offset: 30, 5762 v_offset: 0 5763 }, 5764 right: { 5765 h_align: 'right', 5766 v_align: 'center', 5767 h_offset: 30, 5768 v_offset: 0 5769 } 5770 } 5771 }, 5772 5773 /* ADDONS */ 5774 addOnTypewriter: { 5775 enable: false 5776 }, 5777 addOnWhiteboard: { 5778 enable: false, 5779 5780 }, 5781 whiteboard: { 5782 movehand: { 5783 src: '../vendor/rs-plugin/revolution-addons/whiteboard/assets/images/hand_point_right.png', 5784 width: 400, 5785 height: 1000, 5786 handtype: 'right', 5787 transform: { 5788 transformX: 50, 5789 transformY: 50 5790 }, 5791 jittering: { 5792 distance: '80', 5793 distance_horizontal: '100', 5794 repeat: '5', 5795 offset: '10', 5796 offset_horizontal: '0' 5797 }, 5798 rotation: { 5799 angle: '10', 5800 repeat: '3' 5801 } 5802 }, 5803 writehand: { 5804 src: '../vendor/rs-plugin/revolution-addons/whiteboard/assets/images/write_right_angle.png', 5805 width: 572, 5806 height: 691, 5807 handtype: 'right', 5808 transform: { 5809 transformX: 50, 5810 transformY: 50 5811 }, 5812 jittering: { 5813 distance: '80', 5814 distance_horizontal: '100', 5815 repeat: '5', 5816 offset: '10', 5817 offset_horizontal: '0' 5818 }, 5819 rotation:{ 5820 angle: '10', 5821 repeat: '3' 5822 } 5823 } 5824 }, 5825 addOnParticles: { 5826 enable: false 5827 }, 5828 particles: { 5829 startSlide: "first", 5830 endSlide: "last", 5831 zIndex: "1", 5832 particles: { 5833 number: {value: 80}, color: {value: "#ffffff"}, 5834 shape: { 5835 type: "circle", stroke: {width: 0, color: "#ffffff", opacity: 1}, 5836 image: {src: ""} 5837 }, 5838 opacity: {value: 0.5, random: true, min: 0.25, anim: {enable: false, speed: 3, opacity_min: 0, sync: false}}, 5839 size: {value: 2, random: false, min: 30, anim: {enable: false, speed: 40, size_min: 1, sync: false}}, 5840 line_linked: {enable: true, distance: 150, color: "#ffffff", opacity: 0.4, width: 1}, 5841 move: {enable: true, speed: 6, direction: "none", random: true, min_speed: 6, straight: false, out_mode: "out"} 5842 }, 5843 interactivity: { 5844 events: {onhover: {enable: false, mode: "repulse"}, onclick: {enable: false, mode: "repulse"}}, 5845 modes: {grab: {distance: 400, line_linked: {opacity: 0.5}}, bubble: {distance: 400, size: 40, opacity: 0.4}, repulse: {distance: 200}} 5846 } 5847 }, 5848 addOnCountdown: { 5849 enable: false, 5850 targetdate: new Date().getTime() + 864000000, // http://www.freeformatter.com/epoch-timestamp-to-date-converter.html 5851 slidechanges: [{days: 0, hours: 0, minutes: 0, seconds: 0, slide: 2}] 5852 }, 5853 addOnSlicey: { 5854 enable: false 5855 }, 5856 addOnFilmstrip: { 5857 enable: false 5858 },
5859 addOnBeforeAfter : { 5860 enable: false, 5861 options: { 5862 cursor: "move", 5863 carousel: false, 5864 arrowStyles: { 5865 leftIcon: "fa-icon-caret-left", 5866 rightIcon: "fa-icon-caret-right", 5867 topIcon: "fa-icon-caret-up", 5868 bottomIcon: "fa-icon-caret-down", 5869 size: "35", 5870 color: "#ffffff", 5871 spacing: "10", 5872 bgColor: "transparent", 5873 padding: "0", 5874 borderRadius: "0" 5875 }, 5876 dividerStyles: { 5877 width: "1", 5878 color: "rgba(255, 255, 255, 0.5)" 5879 } 5880 } 5881 }, 5882 addOnPanorama: { 5883 enable: false 5884 }, 5885 addOnRevealer: { 5886 enable: false, 5887 }, 5888 revealer: { 5889 direction: "open_horizontal", 5890 color: "#ffffff", 5891 duration: "1500", 5892 delay: "0", 5893 easing: "Power2.easeInOut", 5894 overlay_enabled: true, 5895 overlay_color: "#000000", 5896 overlay_duration: "1500", 5897 overlay_delay: "0", 5898 overlay_easing: "Power2.easeInOut", 5899 spinner: "1", 5900 spinnerColor: "#006dd2", 5901 spinnerHtml: "<div class='rsaddon-revealer-spinner rsaddon-revealer-spinner-1'><div class='rsaddon-revealer-1'><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><span style='background: {{color}}'><\/span><\/div><\/div \/>" 5902 }, 5903 addOnDuotone: { 5904 enable: false 5905 }, 5906 addOnBubblemorph: { 5907 enable: false 5908 }, 5909 addOnDistortion: { 5910 enable: false 5911 } 5912 5913 }; 5914 5915 // expose to scope 5916 $.extend(theme, { 5917 PluginRevolutionSlider 5918 }); 5919 5920 // jquery plugin 5921 $.fn.themePluginRevolutionSlider = function(opts) { 5922 return this.map(function() { 5923 const $this = $(this); 5924 5925 if ($this.data(instanceName)) { 5926 return $this.data(instanceName); 5927 } else { 5928 return new PluginRevolutionSlider($this, opts); 5929 } 5930 5931 }); 5932 } 5933})).apply(this, [window.theme, jQuery]); 5934 5935// Scroll Spy 5936(((theme = {}, $) => { 5937 const instanceName = '__scrollSpy'; 5938 5939 class PluginScrollSpy { 5940 constructor($el, opts) { 5941 return this.initialize($el, opts); 5942 } 5943 5944 initialize($el, opts) { 5945 5946 if( document.querySelector( opts.target ) == null ) { 5947 return false; 5948 } 5949 5950 this.$el = $el; 5951 5952 this 5953 .setData() 5954 .setOptions(opts); 5955 5956 this.build(); 5957 5958 return this; 5959 } 5960 5961 setData() { 5962 this.$el.data(instanceName, this); 5963 5964 return this; 5965 } 5966 5967 setOptions(opts) { 5968 this.options = $.extend(true, {}, PluginScrollSpy.defaults, opts, { 5969 wrapper: this.$el 5970 }); 5971 5972 return this; 5973 } 5974 5975 build() { 5976 const self = this, target = document.querySelector( self.options.target ) != null ? document.querySelector( self.options.target ) : false, navItems = target == '#header' || target == '.wrapper-spy' ? target.querySelectorAll('.header-nav .nav > li a') : target.querySelectorAll('.nav > li a'); 5977 5978 // Get all section ID's 5979 let sectionIDs = Object.keys(navItems).map((key, index) => navItems[key].hash); 5980 5981 // Remove empty values from sectionIDs array 5982 sectionIDs = sectionIDs.filter(value => value != ''); 5983 5984 // Store in a global variable 5985 self.sectionIDs = sectionIDs; 5986 5987 for( let i = 0; i < sectionIDs.length; i++ ) { 5988 5989 // Default Root Margin 5990 let rootMargin = '-20% 0px -79.9% 0px'; 5991 5992 // Spy Offset 5993 if( $( sectionIDs[i] ).data('spy-offset') ) { 5994 const rootMarginOffset = $( sectionIDs[i] ).data('spy-offset'), isNegativeOffset = parseInt( rootMarginOffset ) < 0 ? true : false; 5995 5996 // Mount a new rootMargin based on offset value 5997 rootMargin = rootMargin.split(' ').map((element, index) => { 5998 if( element.indexOf('%') > 0 ) { 5999 const valueToInt = parseInt( element.replace('%','') ); 6000 let newValue = 0; 6001 6002 switch ( index ) { 6003 case 0: 6004 if( isNegativeOffset ) { 6005 newValue = valueToInt - rootMarginOffset; 6006 } else { 6007 newValue = Math.abs(valueToInt) + rootMarginOffset; 6008 } 6009 break; 6010 6011 case 2: 6012 if( isNegativeOffset ) { 6013 newValue = valueToInt + rootMarginOffset; 6014 } else { 6015 newValue = Math.abs(valueToInt) - rootMarginOffset; 6016 } 6017 break; 6018 6019 } 6020 6021 if( isNegativeOffset ) { 6022 newValue = newValue + '%'; 6023 } else { 6024 newValue = '-' + newValue + '%'; 6025 } 6026 6027 return newValue; 6028 } else { 6029 return element; 6030 } 6031 }).join(' '); 6032 } 6033 6034 const selector = sectionIDs[i], 6035 callback = function() { 6036 const $section = $(this); 6037 6038 if( target == '#header' || target == '.wrapper-spy' ) { 6039 $('#header .header-nav .nav > li a').removeClass('active'); 6040 $('#header .header-nav .nav > li a[href="#'+ $section[0].id +'"]').addClass('active'); 6041 } else { 6042 $( target ).find('.nav > li a').removeClass('active'); 6043 $( target ).find('.nav > li a[href="#'+ $section[0].id +'"]').addClass('active'); 6044 } 6045 6046 }; 6047 6048 this.scrollSpyIntObs( selector, callback, { 6049 rootMargin, 6050 threshold: 0 6051 }, true, i, true); 6052 6053 } 6054 6055 return this; 6056 6057 } 6058 6059 scrollSpyIntObs(selector, functionName, intObsOptions, al
6059waysObserve, index, firstLoad) { 6060 const self = this; 6061 6062 const $el = document.querySelectorAll( selector ); 6063 let intersectionObserverOptions = { 6064 rootMargin: '0px 0px 200px 0px' 6065 }; 6066 6067 if( Object.keys(intObsOptions).length ) { 6068 intersectionObserverOptions = $.extend(intersectionObserverOptions, intObsOptions); 6069 } 6070 6071 const observer = new IntersectionObserver(entries => { 6072 for (const entry of entries) { 6073 if (entry.intersectionRatio > 0 ) { 6074 if( typeof functionName === 'string' ) { 6075 const func = Function( 'return ' + functionName )(); 6076 } else { 6077 const callback = functionName; 6078 6079 callback.call( $(entry.target) ); 6080 } 6081 6082 // Unobserve 6083 if( !alwaysObserve ) { 6084 observer.unobserve(entry.target); 6085 } 6086 6087 } else { 6088 if( firstLoad == false ) { 6089 if( index == self.sectionIDs.length - 1 ) { 6090 $('#header .header-nav .nav > li a').removeClass('active'); 6091 $('#header .header-nav .nav > li a[href="#'+ entry.target.id +'"]').parent().prev().find('a').addClass('active'); 6092 } 6093 } 6094 firstLoad = false; 6095 6096 } 6097 } 6098 }, intersectionObserverOptions); 6099 6100 $( $el ).each(function(){ 6101 observer.observe( $(this)[0] ); 6102 }); 6103 6104 return this; 6105 } 6106 } 6107 6108 PluginScrollSpy.defaults = { 6109 target: '#header' 6110 }; 6111 6112 // expose to scope 6113 $.extend(theme, { 6114 PluginScrollSpy 6115 }); 6116 6117 // jquery plugin 6118 $.fn.themePluginScrollSpy = function(opts) { 6119 return this.map(function() { 6120 const $this = $(this); 6121 6122 if ($this.data(instanceName)) { 6123 return $this.data(instanceName); 6124 } else { 6125 return new PluginScrollSpy($this, opts); 6126 } 6127 6128 }); 6129 } 6130})).apply(this, [window.theme, jQuery]); 6131 6132// Scroll to Top 6133(((theme = {}, $) => { 6134 $.extend(theme, { 6135 6136 PluginScrollToTop: { 6137 6138 defaults: { 6139 wrapper: $('body'), 6140 offset: 150, 6141 buttonClass: 'scroll-to-top', 6142 buttonAriaLabel: 'Scroll To Top', 6143 iconClass: 'fas fa-chevron-up', 6144 delay: 1000, 6145 visibleMobile: false, 6146 label: false, 6147 easing: 'easeOutBack' 6148 }, 6149 6150 initialize(opts) { 6151 initialized = true; 6152 6153 // Don't initialize if the page has Section Scroll 6154 if( $('body[data-plugin-section-scroll]').get(0) ) { 6155 return; 6156 } 6157 6158 this 6159 .setOptions(opts) 6160 .build() 6161 .events(); 6162 6163 return this; 6164 }, 6165 6166 setOptions(opts) { 6167 this.options = $.extend(true, {}, this.defaults, opts); 6168 6169 return this; 6170 }, 6171 6172 build() { 6173 const self = this; 6174 let $el; 6175 6176 // Base HTML Markup 6177 $el = $('<a />') 6178 .addClass(self.options.buttonClass) 6179 .attr({ 6180 'href': '#', 6181 'aria-label': self.options.buttonAriaLabel 6182 }) 6183 .append( 6184 $('<i />') 6185 .addClass(self.options.iconClass) 6186 ); 6187 6188 // Visible Mobile 6189 if (!self.options.visibleMobile) { 6190 $el.addClass('hidden-mobile'); 6191 } 6192 6193 // Label 6194 if (self.options.label) { 6195 $el.append( 6196 $('<span />').html(self.options.label) 6197 ); 6198 } 6199 6200 this.options.wrapper.append($el); 6201 6202 this.$el = $el; 6203 6204 return this; 6205 }, 6206 6207 events() { 6208 const self = this; 6209 let _isScrolling = false; 6210 6211 // Click Element Action 6212 self.$el.on('click', e => { 6213 e.preventDefault(); 6214 $('html').animate({ 6215 scrollTop: 0 6216 }, self.options.delay, self.options.easing); 6217 return false; 6218 }); 6219 6220 // Show/Hide Button on Window Scroll event. 6221 $(window).scroll(() => { 6222 6223 if (!_isScrolling) { 6224 6225 _isScrolling = true; 6226 6227 if ($(window).scrollTop() > self.options.offset) { 6228 6229 self.$el.stop(true, true).addClass('visible'); 6230 _isScrolling = false; 6231 6232 } else { 6233 6234 self.$el.stop(true, true).removeClass('visible'); 6235 _isScrolling = false; 6236 6237 } 6238 6239 } 6240 6241 }); 6242 6243 return this; 6244 } 6245 6246 } 6247 6248 }); 6249})).apply(this, [window.theme, jQuery]); 6250 6251// Scrollable 6252(((theme = {}, $) => { 6253 const instanceName = '__scrollable'; 6254 6255 class PluginScrollable { 6256 constructor($el, opts) { 6257 return this.initialize($el, opts); 6258 } 6259 6260 static updateModals() { 6261 PluginScrollable.updateBootstrapModal(); 6262 } 6263 6264 static updateBootstrapModal() { 6265 let updateBoostrapModal; 6266 6267 updateBoostrapModal = typeof $.fn.modal !== 'undefined'; 6268 updateBoostrapModal = updateBoostrapModal && typeof $.fn.modal.Constructor !== 'undefined'; 6269 updateBoostrapModal = updateBoostrapModal && typeof $.fn.modal.Constructor.prototype !== 'undefined'; 6270 updateBoostrapModal = updateBoostrapModal && typeof $.fn.modal.Constructor.prototype.enforceFocus !== 'undefined'; 6271 6272 if ( !updateBoostrapModal ) { 6273 return false; 6274 } 6275 6276 const originalFocus = $.fn.modal.Constructor.prototype.enforceFocus; 6277 $.fn.modal.Constructor.prototype.enforceFocus = function() { 6278 originalFocus.apply( this ); 6279 6280 const $scrollable = this.$element.find('.scrollable'); 6281 if ( $scrollable ) { 6282 if ( $.isFunction($.fn['themePluginScrollable']) ) { 6283 $scrollable.themePluginScrollable(); 6284 } 6285 6286 if ( $.isFunction($.fn['nanoScroller']) ) { 6287 $scrollable.nanoScroller(); 6288 } 6289 } 6290 }; 6291 } 6292 6293 initialize($el, opts) { 6294 if ( $el.data( instanceName ) ) { 6295 return this; 6296 } 6297 6298 this.$el = $el; 6299 6300 this 6301 .setData() 6302 .setOptions(opts) 6303 .build(); 6304 6305 return this; 6306 } 6307 6308 setData() { 6309 this.$el.data(instanceName, this); 6310 6311 return this; 6312 } 6313 6314 setOptions(opts) { 6315 this.options = $.extend(true, {}, PluginScrollable.defaults, opts, { 6316 wrapper: this.$el 6317 }); 6318 6319 return this; 6320 } 6321 6322 build() { 6323 this.options.wrapper.nanoScroller(this.options); 6324 6325 return this; 6326 } 6327 } 6328 6329 PluginScrollable.defaults = { 6330 contentClass: 'scrollable-content', 6331 paneClass: 'scrollable-pane', 6332 sliderClass: 'scrollable-slider', 6333 alwaysVisible: true, 6334 preventPageScrolling: true 6335 }; 6336 6337 // expose to scope 6338 $.extend(theme, { 6339 PluginScrollable 6340 }); 6341 6342 // jquery plugin 6343 $.fn.themePluginScrollable = function(opts) { 6344 return this.each(function() { 6345 const $this = $(this); 6346 6347 if ($this.data(instanceName)) { 6348 return $this.data(instanceName); 6349 } else { 6350 return new PluginScrollable($this, opts); 6351 } 6352 6353 }); 6354 }; 6355 6356 $(() => { 6357 PluginScrollable.updateModals(); 6358 }); 6359})).apply(this, [window.theme, jQuery]); 6360 6361// Section Scroll 6362(((theme = {}, $) => { 6363 const instanceName = '__sectionScroll'; 6364 6365 class PluginSectionScroll { 6366 constructor($el, opts) { 6367 return this.initialize($el, opts); 6368 } 6369 6370 initialize($el, opts) { 6371 if ($el.data(instanceName)) { 6372 return this; 6373 } 6374 6375 this.$el = $el; 6376 6377 this 6378 .setData() 6379 .setOptions(opts) 6380 .build() 6381 .events(); 6382 6383 return this; 6384 } 6385 6386 setData() { 6387 this.$el.data(instanceName, this); 6388 6389 return this; 6390 } 6391 6392 setOptions(opts) { 6393 this.options = $.extend(true, {}, PluginSectionScroll.defaults, opts, { 6394 wrapper: this.$el 6395 }); 6396 6397 return this; 6398 } 6399 6400 build() { 6401 const self = this, $el = this.options.wrapper; 6402 6403 // Check type of header and change the target for header (by change header color purpose) 6404 if( $('html').hasClass('side-header-overlay-full-screen') ) { 6405 self.$header = $('.sticky-wrapper'); 6406 } else { 6407 self.$header = $('#header'); 6408 } 6409 6410 // Turn the section full height or not depeding on the content size 6411 self.updateSectionsHeight(); 6412 6413 // Wrap all sections in a section wrapper 6414 $( this.options.targetClass ).wrap('<div class="section-wrapper"></div>'); 6415 6416 // Set the section wrapper height 6417 $('.section-wrapper').each(function(){ 6418 $(this).height( $(this).find('.section-scroll').outerHeight() ); 6419 });
6420 6421 // Add active class to the first section on page load 6422 $('.section-wrapper').first().addClass('active'); 6423 6424 let flag = false, scrollableFlag = false, touchDirection = '', touchstartY = 0, touchendY = 0; 6425 6426 $(window).on('touchstart', ({changedTouches}) => { 6427 touchstartY = changedTouches[0].screenY; 6428 }); 6429 6430 let wheelEvent = 'onwheel' in document ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll'; 6431 if( $(window).width() < 992 && $('html').hasClass('touch') ) { 6432 wheelEvent = 'onwheel' in document ? 'wheel touchend' : document.onmousewheel !== undefined ? 'mousewheel touchend' : 'DOMMouseScroll touchend'; 6433 } 6434 6435 if( $(window).width() < 992 ) { 6436 $('html').removeClass('overflow-hidden'); 6437 $(window).on('scroll', () => { 6438 6439 let index = 0; 6440 $('.section-scroll').each(function(){ 6441 if( $(this).offset().top <= $(window).scrollTop() + 50 ) { 6442 const $currentSection2 = $('.section-wrapper').eq( index ).find('.section-scroll'); 6443 6444 $('.section-scroll-dots-navigation > ul > li').removeClass('active'); 6445 $('.section-scroll-dots-navigation > ul > li').eq( index ).addClass('active'); 6446 6447 $(window).trigger({ 6448 type: 'section.scroll.mobile.change.header.color', 6449 currentSection: $currentSection2 6450 }); 6451 } 6452 6453 index++; 6454 }); 6455 6456 }); 6457 6458 $(window).on('section.scroll.mobile.change.header.color', ({currentSection}) => { 6459 if( typeof currentSection == 'undefined' ) { 6460 return; 6461 } 6462 6463 const $currentSection = currentSection, headerColor = $currentSection.data('section-scroll-header-color'); 6464 6465 $('#header .header-nav').removeClass('header-nav-light-text header-nav-dark-text').addClass('header-nav-' + headerColor + '-text'); 6466 $('#header .header-nav-features').removeClass('header-nav-features-dark header-nav-features-light').addClass('header-nav-features-' + headerColor); 6467 $('#header .header-social-icons').removeClass('social-icons-icon-dark social-icons-icon-light').addClass('social-icons-icon-' + headerColor); 6468 6469 // Change Logo 6470 if( self.options.changeHeaderLogo && headerColor != undefined ) { 6471 if( headerColor == 'light' ) { 6472 $('#header .header-logo img').attr('src', self.options.headerLogoLight); 6473 } else if( headerColor == 'dark' ) { 6474 $('#header .header-logo img').attr('src', self.options.headerLogoDark); 6475 } 6476 } 6477 6478 self.$header.css({ 6479 opacity: 1 6480 }); 6481 6482 }); 6483 } 6484 6485 $(window).on(wheelEvent, ({target, originalEvent}) => { 6486 if( $(window).width() < 992 ) { 6487 return; 6488 } 6489 6490 if( $(window).width() < 992 && $('html').hasClass('touch') ) { 6491 if( $(target).closest('.section-scroll-dots-navigation').get(0) || $(target).closest('.header-body').get(0) || $(target).closest('.owl-carousel').get(0) ) { 6492 return; 6493 } 6494 } 6495 6496 // Side Header Overlay Full Screen 6497 if( $('html.side-header-overlay-full-screen.side-header-hide').get(0) ) { 6498 return; 6499 } 6500 6501 const wheelDirection = originalEvent.wheelDelta == undefined ? originalEvent.deltaY > 0 : originalEvent.wheelDelta < 0; 6502 if( $(window).width() < 992 && $('html').hasClass('touch') ) { 6503 touchendY = event.changedTouches[0].screenY; 6504 6505 if( touchendY <= touchstartY ) { 6506 touchDirection = 'up'; 6507 } 6508 6509 if( touchendY >= touchstartY ) { 6510 touchDirection = 'down'; 6511 } 6512 6513 if( touchendY == touchstartY ) { 6514 return; 6515 } 6516 } 6517 6518 const $currentSection = $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll'); 6519 const $nextSection = self.getNextSection(wheelDirection, touchDirection); 6520 let nextSectionOffsetTop; 6521 6522 // If is the last section, then change the offsetTop value
6523 if( self.getCurrentIndex() == $('.section-wrapper').length - 1 ) { 6524 nextSectionOffsetTop = $(document).height(); 6525 } else { 6526 nextSectionOffsetTop = $nextSection.offset().top; 6527 } 6528 6529 if( $(window).width() < 992 && $('html').hasClass('touch') ) { 6530 setTimeout(() => { 6531 if( $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll').hasClass('section-scroll-scrollable') ) { 6532 $('html').removeClass('overflow-hidden'); 6533 } else { 6534 $('html').addClass('overflow-hidden'); 6535 } 6536 }, 1200); 6537 } 6538 6539 // For non full height sections 6540 if( $currentSection.hasClass('section-scroll-scrollable') ) { 6541 if( !flag && !scrollableFlag ) { 6542 6543 // Scroll Direction 6544 if(wheelDirection || touchDirection == 'up') { 6545 if( ( $(window).scrollTop() + $(window).height() ) >= nextSectionOffsetTop ) { 6546 flag = true; 6547 setTimeout(() => { 6548 $(window).trigger('section.scroll.change.header.color'); 6549 6550 setTimeout(() => { 6551 flag = false; 6552 }, 500); 6553 }, 1000); 6554 6555 if( self.getCurrentIndex() == ( $('.section-wrapper').length - 1 ) ) { 6556 return false; 6557 } 6558 6559 // Move to the next section 6560 self.moveTo( $currentSection.offset().top + $currentSection.outerHeight() ); 6561 6562 // Change Section Active Class 6563 self.changeSectionActiveState( $nextSection ); 6564 6565 self.$header.css({ 6566 opacity: 0, 6567 transition: 'ease opacity 500ms' 6568 }); 6569 } 6570 6571 if( !$('html').hasClass('touch') ) { 6572 for( var i = 1; i < 100; i++ ) { 6573 $('body, html').scrollTop( $(window).scrollTop() + 1 ); 6574 6575 if( ( $(window).scrollTop() + $(window).height() ) >= nextSectionOffsetTop ) { 6576 scrollableFlag = true; 6577 setTimeout(() => { 6578 $(window).trigger('section.scroll.change.header.color'); 6579 scrollableFlag = false; 6580 }, 500); 6581 break; 6582 } 6583 } 6584 } 6585 } else { 6586 if( $(window).scrollTop() <= $currentSection.offset().top ) { 6587 flag = true; 6588 setTimeout(() => { 6589 $(window).trigger('section.scroll.change.header.color'); 6590 6591 setTimeout(() => { 6592 flag = false; 6593 }, 500); 6594 }, 1000); 6595 6596 if( self.getCurrentIndex() == 0 ) { 6597 return false; 6598 } 6599 6600 // Move to the next section 6601 self.moveTo( $currentSection.offset().top - $(window).height() ); 6602 6603 // Change Section Active Class 6604 self.changeSectionActiveState( $nextSection ); 6605 6606 self.$header.css({ 6607 opacity: 0, 6608 transition: 'ease opacity 500ms' 6609 }); 6610 } 6611 6612 if( !$('html').hasClass('touch') ) { 6613 for( var i = 1; i < 100; i++ ) { 6614 $('body, html').scrollTop( $(window).scrollTop() - 1 ); 6615 6616 if( $(window).scrollTop() <= $currentSection.offset().top ) { 6617 scrollableFlag = true; 6618 setTimeout(() => { 6619 $(window).trigger('section.scroll.change.header.color'); 6620 scrollableFlag = false; 6621 }, 500); 6622 break; 6623 } 6624 } 6625 } 6626 } 6627 6628 // Change Dots Active Class 6629 self.changeDotsActiveState(); 6630 6631 return; 6632 6633 } 6634 } 6635 6636 // For full height sections 6637 if( !flag && !scrollableFlag ) { 6638 if(wheelDirection || touchDirection == 'up') { 6639 if( self.getCurrentIndex() == ( $('.section-wrapper').length - 1 ) ) { 6640 return false; 6641 } 6642 6643 // Change Section Active Class 6644 self.changeSectionActiveState( $nextSection ); 6645 6646 setTimeout(() => { 6647 // Move to the next section 6648 self.moveTo( $nextSection.offset().top ); 6649 6650 }, 150); 6651 } else { 6652 if( self.getCurrentIndex() == 0 ) { 6653 return false; 6654 } 6655 6656 // Change Section Active Class 6657 self.changeSectionActiveState( $nextSection ); 6658 6659 if( $nextSection.height() > $(window).height() ) { 6660 // Move to the next section 6661 self.moveTo( $currentSection.offset().top - $(window).height() ); 6662 } else { 6663 setTimeout(() => { 6664 // Move to the next section 6665 self.moveTo( $nextSection.offset().top ); 6666 6667 }, 150); 6668 } 6669 } 6670 6671 // Change Dots Active Class 6672 self.changeDotsActiveState(); 6673 6674 self.$header.css({ 6675 opacity: 0, 6676 transition: 'ease opacity 500ms' 6677 }); 6678 6679 // Style next section 6680 $nextSection.css({ 6681 position: 'relative', 6682 opacity: 1, 6683 'z-index': 1,
6684 transform: 'translate3d(0,0,0) scale(1)' 6685 }); 6686 6687 // Style previous section 6688 $currentSection.css({ 6689 position: 'fixed', 6690 width: '100%', 6691 top: 0, 6692 left: 0, 6693 opacity: 0, 6694 'z-index': 0, 6695 transform: 'translate3d(0,0,-10px) scale(0.7)', 6696 transition: 'ease transform 600ms, ease opacity 600ms', 6697 }); 6698 6699 setTimeout(() => { 6700 $currentSection.css({ 6701 position: 'relative', 6702 opacity: 1, 6703 transform: 'translate3d(0,0,-10px) scale(1)' 6704 }); 6705 6706 $(window).trigger('section.scroll.change.header.color'); 6707 6708 setTimeout(() => { 6709 flag = false; 6710 }, 500); 6711 }, 1000); 6712 6713 flag = true; 6714 6715 } 6716 6717 return; 6718 }); 6719 6720 // Dots Navigation 6721 if( this.options.dotsNav ) { 6722 self.dotsNavigation(); 6723 } 6724 6725 // First Load 6726 setTimeout(() => { 6727 if( $(window.location.hash).get(0) ) { 6728 self.moveTo( $(window.location.hash).parent().offset().top ); 6729 6730 self.changeSectionActiveState( $(window.location.hash) ); 6731 6732 // Change Dots Active Class 6733 self.changeDotsActiveState(); 6734 6735 self.updateHash( true ); 6736 } else { 6737 const hash = window.location.hash; 6738 let index = hash.replace('#',''); 6739 6740 if( !hash ) { 6741 index = 1; 6742 } 6743 6744 self.moveTo( $('.section-wrapper').eq( index - 1 ).offset().top ); 6745 6746 self.changeSectionActiveState( $('.section-wrapper').eq( index - 1 ).find('.section-scroll') ); 6747 6748 // Change Dots Active Class 6749 self.changeDotsActiveState(); 6750 6751 self.updateHash( true ); 6752 } 6753 6754 $(window).trigger('section.scroll.ready'); 6755 $(window).trigger('section.scroll.change.header.color'); 6756 }, 500); 6757 6758 return this; 6759 } 6760 6761 updateSectionsHeight() { 6762 const self = this; 6763 6764 $('.section-scroll').css({ height: '' }); 6765 6766 $('.section-scroll').each(function(){ 6767 if( $(this).outerHeight() < ( $(window).height() + 3 ) ) { 6768 $(this).css({ height: '100vh' }); 6769 } else { 6770 $(this).addClass('section-scroll-scrollable'); 6771 } 6772 }); 6773 6774 // Set the section wrapper height 6775 $('.section-wrapper').each(function(){ 6776 $(this).height( $(this).find('.section-scroll').outerHeight() ); 6777 }); 6778 6779 return this; 6780 } 6781 6782 updateHash(first_load) { 6783 const self = this; 6784 6785 if( !window.location.hash ) { 6786 window.location.hash = 1; 6787 } else { 6788 if(!first_load) { 6789 const $section = $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll'), section_id = $section.attr('id') ? $section.attr('id') : $section.parent().index() + 1; 6790 6791 window.location.hash = section_id; 6792 } 6793 } 6794 6795 return this; 6796 } 6797 6798 getCurrentIndex() { 6799 const self = this; 6800 let currentIndex = 0; 6801 6802 currentIndex = $('.section-wrapper.active').index(); 6803 6804 return currentIndex; 6805 } 6806 6807 moveTo($scrollTopValue, first_load) { 6808 const self = this; 6809 6810 $('body, html').animate({ 6811 scrollTop: $scrollTopValue 6812 }, 1000, 'easeOutQuint'); 6813 6814 setTimeout(() => { 6815 self.updateHash(); 6816 }, 500); 6817 6818 return this; 6819 } 6820 6821 getNextSection(wheelDirection, touchDirection) { 6822 const self = this; 6823 let $nextSection = ''; 6824 6825 // Scroll Direction 6826 if(wheelDirection || touchDirection == 'up') { 6827 $nextSection = $('.section-wrapper').eq( self.getCurrentIndex() + 1 ).find('.section-scroll'); 6828 } else { 6829 $nextSection = $('.section-wrapper').eq( self.getCurrentIndex() - 1 ).find('.section-scroll'); 6830 } 6831 6832 return $nextSection; 6833 } 6834 6835 changeSectionActiveState($nextSection) { 6836 const self = this; 6837 6838 $('.section-wrapper').removeClass('active'); 6839 $nextSection.parent().addClass('active'); 6840 6841 return this; 6842 } 6843 6844 changeDotsActiveState() { 6845 const self = this; 6846 6847 $('.section-scroll-dots-navigation > ul > li').removeClass('active'); 6848 $('.section-scroll-dots-navigation > ul > li').eq( self.getCurrentIndex() ).addClass('active'); 6849 6850 return this; 6851 } 6852 6853 dotsNavigation() { 6854 const self = this; 6855
6856 const dotsNav = $('<div class="section-scroll-dots-navigation"><ul class="list list-unstyled"></ul></div>'), currentSectionIndex = self.getCurrentIndex(); 6857 6858 if( self.options.dotsClass ) { 6859 dotsNav.addClass( self.options.dotsClass ); 6860 } 6861 6862 for( let i = 0; i < $('.section-scroll').length; i++ ) { 6863 const title = $('.section-wrapper').eq( i ).find('.section-scroll').data('section-scroll-title'); 6864 6865 dotsNav.find('> ul').append( '<li'+ ( ( currentSectionIndex == i ) ? ' class="active"' : '' ) +'><a href="#'+ i +'" data-nav-id="'+ i +'"><span>'+ title +'</span></a></li>' ); 6866 } 6867 6868 $('.body').append( dotsNav ); 6869 6870 dotsNav.find('a[data-nav-id]').on('click touchstart', function(e){ 6871 e.preventDefault(); 6872 const $this = $(this); 6873 6874 $('.section-scroll').css({ 6875 opacity: 0, 6876 transition: 'ease opacity 300ms' 6877 }); 6878 6879 self.$header.css({ 6880 opacity: 0, 6881 transition: 'ease opacity 500ms' 6882 }); 6883 6884 setTimeout(() => { 6885 self.moveTo( $('.section-wrapper').eq( $this.data('nav-id') ).offset().top ) 6886 6887 $('.section-wrapper').removeClass('active'); 6888 $('.section-wrapper').eq( $this.data('nav-id') ).addClass('active'); 6889 6890 $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll').css({ 6891 opacity: 1 6892 }); 6893 6894 setTimeout(() => { 6895 $('.section-scroll').css({ opacity: 1 }); 6896 6897 $(window).trigger('section.scroll.change.header.color'); 6898 }, 500); 6899 6900 if( $(window).width() > 991 ) { 6901 self.changeDotsActiveState(); 6902 } 6903 }, 500); 6904 }); 6905 6906 return this; 6907 } 6908 6909 events() { 6910 const self = this; 6911 6912 $(window).on('section.scroll.ready', () => { 6913 $(window).scrollTop(0); 6914 }); 6915 6916 $(window).on('section.scroll.change.header.color', () => { 6917 const headerColor = $('.section-wrapper').eq( self.getCurrentIndex() ).find('.section-scroll').data('section-scroll-header-color'); 6918 6919 $('#header .header-nav').removeClass('header-nav-light-text header-nav-dark-text').addClass('header-nav-' + headerColor + '-text'); 6920 $('#header .header-nav-features').removeClass('header-nav-features-dark header-nav-features-light').addClass('header-nav-features-' + headerColor); 6921 $('#header .header-social-icons').removeClass('social-icons-icon-dark social-icons-icon-light').addClass('social-icons-icon-' + headerColor); 6922 6923 // Change Logo 6924 if( self.options.changeHeaderLogo && headerColor != undefined ) { 6925 if( headerColor == 'light' ) { 6926 $('#header .header-logo img').attr('src', self.options.headerLogoLight); 6927 } else if( headerColor == 'dark' ) { 6928 $('#header .header-logo img').attr('src', self.options.headerLogoDark); 6929 } 6930 } 6931 6932 self.$header.css({ 6933 opacity: 1 6934 }); 6935 }); 6936 6937 $(document).ready(() => { 6938 $(window).afterResize(() => { 6939 self.updateSectionsHeight(); 6940 6941 if( $(window).width() < 992 ) { 6942 $('html').removeClass('overflow-hidden'); 6943 } 6944 }); 6945 }); 6946 6947 return this; 6948 } 6949 } 6950 6951 PluginSectionScroll.defaults = { 6952 targetClass: '.section', 6953 dotsNav: true, 6954 changeHeaderLogo: true, 6955 headerLogoDark: 'img/logo-default-slim.png', 6956 headerLogoLight: 'img/logo-default-slim-dark.png' 6957 }; 6958 6959 // expose to scope 6960 $.extend(theme, { 6961 PluginSectionScroll 6962 }); 6963 6964 // jquery plugin 6965 $.fn.themePluginSectionScroll = function(opts) { 6966 return this.map(function() { 6967 const $this = $(this); 6968 6969 if ($this.data(instanceName)) { 6970 return $this.data(instanceName); 6971 } else { 6972 return new PluginSectionScroll($this, opts); 6973 } 6974 6975 }); 6976 }; 6977})).apply(this, [window.theme, jQuery]); 6978 6979// Sort 6980(((theme = {}, $) => { 6981 const instanceName = '__sort'; 6982 6983 class PluginSort { 6984 constructor($el, opts) { 6985 return this.initialize($el, opts); 6986 } 6987 6988 initialize($el, opts) { 6989 if ($el.data(instanceName)) { 6990 return this; 6991 } 6992 6993 this.$el = $el; 6994 6995 this 6996 .setData() 6997 .setOptions(opts) 6998 .build(); 6999 7000 return this; 7001 } 7002 7003 setData() { 7004 this.$el.data(instanceName, this); 7005 7006 return this; 7007 } 7008 7009 setOptions(opts) { 7010 this.options = $.extend(true, {}, PluginSort.defaults, opts, { 7011 wrapper: this.$el 7012 }); 7013 7014 return this; 7015 } 7016 7017 build() { 7018 if (!($.isFunction($.fn.isotope))) { 7019 return this; 7020 } 7021 7022 const self = this, $source = this.options.wrapper, $destination = $('.sort-destination[data-sort-id="' + $source.attr('data-sort-id') + '"]'), $window = $(window); 7023 7024 if ($destination.get(0)) { 7025 7026 self.$source = $source; 7027 self.$destination = $destination; 7028 self.$loader = false; 7029 7030 self.setParagraphHeight($destination); 7031
7032 if (self.$destination.parents('.sort-destination-loader').get(0)) { 7033 self.$loader = self.$destination.parents('.sort-destination-loader'); 7034 self.createLoader(); 7035 } 7036 7037 $destination.attr('data-filter', '*'); 7038 7039 $destination.one('layoutComplete', (event, laidOutItems) => { 7040 self.removeLoader(); 7041 7042 // If has data-plugin-sticky on the page we need recalculate sticky position 7043 if( $('[data-plugin-sticky]').length ) { 7044 setTimeout(() => { 7045 $('[data-plugin-sticky]').each(function(){ 7046 $(this).data('__sticky').build(); 7047 $(window).trigger('resize'); 7048 }); 7049 }, 500); 7050 } 7051 }); 7052 7053 if ( $('#' + self.options.filterFieldId).length ) { 7054 7055 const $filterField = $('#' + self.options.filterFieldId); 7056 7057 $filterField.keyup(function() { 7058 self.options.filterFieldText = $(this).val(); 7059 self.setFilter(self.options.filter); 7060 }); 7061 7062 } 7063 7064 $destination.waitForImages(() => { 7065 $destination.isotope(self.options); 7066 self.events(); 7067 }); 7068 7069 setTimeout(() => { 7070 self.removeLoader(); 7071 }, 3000); 7072 7073 } 7074 7075 return this; 7076 } 7077 7078 events() { 7079 const self = this; 7080 let filter = null; 7081 const $window = $(window); 7082 7083 self.$source.find('a').click(function(e) { 7084 e.preventDefault(); 7085 7086 filter = $(this).parent().data('option-value'); 7087 7088 self.setFilter(filter); 7089 7090 if (e.originalEvent) { 7091 self.$source.trigger('filtered'); 7092 } 7093 7094 return this; 7095 }); 7096 7097 self.$destination.trigger('filtered'); 7098 self.$source.trigger('filtered'); 7099 7100 if (self.options.useHash) { 7101 self.hashEvents(); 7102 } 7103 7104 $window.on('resize sort.resize', () => { 7105 setTimeout(() => { 7106 self.$destination.isotope('layout'); 7107 }, 300); 7108 }); 7109 7110 setTimeout(() => { 7111 $window.trigger('sort.resize'); 7112 }, 300); 7113 7114 return this; 7115 } 7116 7117 setFilter(filter) { 7118 const self = this; 7119 const page = false; 7120 let currentFilter = filter; 7121 7122 self.$source.find('.active').removeClass('active'); 7123 self.$source.find('li[data-option-value="' + filter + '"], li[data-option-value="' + filter + '"] > a').addClass('active'); 7124 7125 self.options.filter = currentFilter; 7126 7127 if (self.$destination.attr('data-current-page')) { 7128 currentFilter = currentFilter + '[data-page-rel=' + self.$destination.attr('data-current-page') + ']'; 7129 } 7130 7131 if (self.options.filterFieldText != '') { 7132 currentFilter = currentFilter + '[data-sort-search*=' + self.options.filterFieldText.toLowerCase() + ']'; 7133 } 7134 7135 self.$destination.attr('data-filter', filter).isotope({ 7136 filter: currentFilter 7137 }).one('arrangeComplete', (event, filteredItems) => { 7138 7139 if (self.options.useHash) { 7140 if (window.location.hash != '' || self.options.filter.replace('.', '') != '*') { 7141 window.location.hash = self.options.filter.replace('.', ''); 7142 } 7143 } 7144 7145 $(window).trigger('scroll'); 7146 7147 }).trigger('filtered'); 7148 7149 return this; 7150 } 7151 7152 hashEvents() { 7153 const self = this; 7154 let hash = null; 7155 let hashFilter = null; 7156 let initHashFilter = '.' + location.hash.replace('#', ''); 7157 7158 // Check if has scroll to section trough URL hash and prevent the sort plugin from show nothing 7159 if( $(location.hash).length ) { 7160 initHashFilter = '.'; 7161 } 7162 7163 if (initHashFilter != '.' && initHashFilter != '.*') { 7164 self.setFilter(initHashFilter); 7165 } 7166 7167 $(window).on('hashchange', e => { 7168 7169 hashFilter = '.' + location.hash.replace('#', ''); 7170 hash = (hashFilter == '.' || hashFilter == '.*' ? '*' : hashFilter); 7171 7172 self.setFilter(hash); 7173 7174 }); 7175 7176 return this; 7177 } 7178 7179 setParagraphHeight() { 7180 const self = this; 7181 let minParagraphHeight = 0; 7182 const paragraphs = $('span.thumb-info-caption p', self.$destination); 7183 7184 paragraphs.each(function() { 7185 if ($(this).height() > minParagraphHeight) { 7186 minParagraphHeight = ($(this).height() + 10);
7187 } 7188 }); 7189 7190 paragraphs.height(minParagraphHeight); 7191 7192 return this; 7193 } 7194 7195 createLoader() { 7196 const self = this; 7197 7198 const loaderTemplate = [ 7199 '<div class="bounce-loader">', 7200 '<div class="bounce1"></div>', 7201 '<div class="bounce2"></div>', 7202 '<div class="bounce3"></div>', 7203 '</div>' 7204 ].join(''); 7205 7206 self.$loader.append(loaderTemplate); 7207 7208 return this; 7209 } 7210 7211 removeLoader() { 7212 7213 const self = this; 7214 7215 if (self.$loader) { 7216 7217 self.$loader.removeClass('sort-destination-loader-showing'); 7218 7219 setTimeout(() => { 7220 self.$loader.addClass('sort-destination-loader-loaded'); 7221 }, 300); 7222 7223 } 7224 7225 } 7226 } 7227 7228 PluginSort.defaults = { 7229 useHash: true, 7230 itemSelector: '.isotope-item', 7231 layoutMode: 'masonry', 7232 filter: '*', 7233 filterFieldId: false, 7234 filterFieldText: '', 7235 hiddenStyle: { 7236 opacity: 0 7237 }, 7238 visibleStyle: { 7239 opacity: 1 7240 }, 7241 stagger: 30, 7242 isOriginLeft: ($('html').attr('dir') == 'rtl' ? false : true) 7243 }; 7244 7245 // expose to scope 7246 $.extend(theme, { 7247 PluginSort 7248 }); 7249 7250 // jquery plugin 7251 $.fn.themePluginSort = function(opts) { 7252 return this.map(function() { 7253 const $this = $(this); 7254 7255 if ($this.data(instanceName)) { 7256 return $this.data(instanceName); 7257 } else { 7258 return new PluginSort($this, opts); 7259 } 7260 7261 }); 7262 } 7263})).apply(this, [window.theme, jQuery]); 7264 7265// Star Rating 7266(((theme = {}, $) => { 7267 const instanceName = '__starrating'; 7268 7269 class PluginStarRating { 7270 constructor($el, opts) { 7271 return this.initialize($el, opts); 7272 } 7273 7274 initialize($el, opts) { 7275 this.$el = $el; 7276 7277 this 7278 .setData() 7279 .setOptions(opts) 7280 .build(); 7281 7282 return this; 7283 } 7284 7285 setData() { 7286 this.$el.data(instanceName, this); 7287 7288 return this; 7289 } 7290 7291 setOptions(opts) { 7292 this.options = $.extend(true, {}, PluginStarRating.defaults, opts, { 7293 wrapper: this.$el 7294 }); 7295 7296 return this; 7297 } 7298 7299 build() { 7300 7301 if (!($.isFunction($.fn.rating))) { 7302 return this; 7303 } 7304 7305 const self = this; 7306 7307 self.options.wrapper 7308 .rating(self.options); 7309 7310 self.options.wrapper.parents('.rating-container') 7311 .addClass('rating-' + self.options.color); 7312 7313 if( self.options.extraClass ) { 7314 self.options.wrapper.parents('.rating-container') 7315 .addClass(self.options.extraClass); 7316 } 7317 7318 return this; 7319 7320 } 7321 } 7322 7323 PluginStarRating.defaults = { 7324 theme: 'krajee-fas', 7325 color: 'primary', 7326 showClear: false, 7327 showCaption: false 7328 }; 7329 7330 // expose to scope 7331 $.extend(theme, { 7332 PluginStarRating 7333 }); 7334 7335 // jquery plugin 7336 $.fn.themePluginStarRating = function(opts) { 7337 return this.map(function() { 7338 const $this = $(this); 7339 7340 if ($this.data(instanceName)) { 7341 return $this.data(instanceName); 7342 } else { 7343 return new PluginStarRating($this, opts); 7344 } 7345 7346 }); 7347 } 7348})).apply(this, [window.theme, jQuery]); 7349 7350// Sticky 7351(((theme = {}, $) => { 7352 const instanceName = '__sticky'; 7353 7354 class PluginSticky { 7355 constructor($el, opts) { 7356 return this.initialize($el, opts); 7357 } 7358 7359 initialize($el, opts) { 7360 if ( $el.data( instanceName ) ) { 7361 return this; 7362 } 7363 7364 this.$el = $el; 7365 7366 this 7367 .setData() 7368 .setOptions(opts) 7369 .build() 7370 .events(); 7371 7372 return this; 7373 } 7374 7375 setData() { 7376 this.$el.data(instanceName, this); 7377 7378 return this; 7379 } 7380 7381 setOptions(opts) { 7382 this.options = $.extend(true, {}, PluginSticky.defaults, opts, { 7383 wrapper: this.$el 7384 }); 7385 7386 return this; 7387 } 7388 7389 build() { 7390 if (!($.isFunction($.fn.pin))) { 7391 return this; 7392 } 7393 7394 const self = this, $window = $(window); 7395 7396 self.options.wrapper.pin(self.options); 7397 7398 if( self.options.wrapper.hasClass('sticky-wrapper-transparent') ) { 7399 self.options.wrapper.parent().addClass('position-absolute w-100'); 7400 } 7401 7402 $window.afterResize(() => { 7403 self.options.wrapper.removeAttr('style').removeData('pin'); 7404 self.options.wrapper.pin(self.options); 7405 $window.trigger('scroll'); 7406 }); 7407 7408 // Change Logo Src 7409 if( self.options.wrapper.find('img').attr('data-change-src') ) { 7410 const $logo = self.options.wrapper.find('img'), logoSrc = $logo.attr('src'), logoNewSrc = $logo.attr('data-change-src'); 7411 7412 self.changeLogoSrc = activate => { 7413 if(activate) { 7414 $logo.attr('src', logoNewSrc); 7415 } else { 7416 $logo.attr('src', logoSrc); 7417 } 7418 } 7419 } 7420 7421 return this; 7422 } 7423 7424 events() { 7425 const self = this; 7426 const $window = $(window); 7427 const $logo = self.options.wrapper.find('img');
7428 const classToCheck = ( self.options.wrapper.hasClass('sticky-wrapper-effect-1') ) ? 'sticky-effect-active' : 'sticky-active'; 7429 let stickyActivateFlag = true; 7430 let stickyDeactivateFlag = false; 7431 7432 $window.on('scroll sticky.effect.active', () => { 7433 if( self.options.wrapper.hasClass( classToCheck ) ) { 7434 if( stickyActivateFlag ) { 7435 if( $logo.attr('data-change-src') ) { 7436 self.changeLogoSrc(true); 7437 } 7438 7439 stickyActivateFlag = false; 7440 stickyDeactivateFlag = true; 7441 } 7442 } else { 7443 if( stickyDeactivateFlag ) { 7444 if( $logo.attr('data-change-src') ) { 7445 self.changeLogoSrc(false); 7446 } 7447 7448 stickyDeactivateFlag = false; 7449 stickyActivateFlag = true; 7450 } 7451 } 7452 }); 7453 7454 let isGoingUp = false; 7455 if( self.options.stickyStartEffectAt ) { 7456 7457 // First Load 7458 if( self.options.stickyStartEffectAt < $window.scrollTop() ) { 7459 self.options.wrapper.addClass('sticky-effect-active'); 7460 7461 $window.trigger('sticky.effect.active'); 7462 } 7463 7464 $window.on('scroll', () => { 7465 if( self.options.stickyStartEffectAt < $window.scrollTop() ) { 7466 self.options.wrapper.addClass('sticky-effect-active'); 7467 isGoingUp = true; 7468 7469 $window.trigger('sticky.effect.active'); 7470 } else { 7471 if( isGoingUp ) { 7472 self.options.wrapper.find('.sticky-body').addClass('position-fixed'); 7473 isGoingUp = false; 7474 } 7475 7476 if( $window.scrollTop() == 0 ) { 7477 self.options.wrapper.find('.sticky-body').removeClass('position-fixed'); 7478 } 7479 7480 self.options.wrapper.removeClass('sticky-effect-active'); 7481 } 7482 }); 7483 } 7484 7485 // Refresh Sticky Plugin if click in a data-toggle="collapse" 7486 if( $('[data-bs-toggle="collapse"]').get(0) ) { 7487 7488 $('[data-bs-toggle="collapse"]').on('click', () => { 7489 setTimeout(() => { 7490 self.build(); 7491 $(window).trigger('scroll'); 7492 }, 1000); 7493 }); 7494 7495 } 7496 7497 // Visibility Issue 7498 document.addEventListener('visibilitychange', () => { 7499 $(window).trigger('resize'); 7500 }); 7501 7502 setInterval(() => { 7503 $(window).trigger('resize'); 7504 }, 1000); 7505 7506 } 7507 } 7508 7509 PluginSticky.defaults = { 7510 minWidth: 991, 7511 activeClass: 'sticky-active' 7512 }; 7513 7514 // expose to scope 7515 $.extend(theme, { 7516 PluginSticky 7517 }); 7518 7519 // jquery plugin 7520 $.fn.themePluginSticky = function(opts) { 7521 return this.map(function() { 7522 const $this = $(this); 7523 7524 if ($this.data(instanceName)) { 7525 return $this.data(instanceName); 7526 } else { 7527 return new PluginSticky($this, opts); 7528 } 7529 7530 }); 7531 } 7532})).apply(this, [ window.theme, jQuery ]); 7533 7534// Toggle 7535(((theme = {}, $) => { 7536 const instanceName = '__toggle'; 7537 7538 class PluginToggle { 7539 constructor($el, opts) { 7540 return this.initialize($el, opts); 7541 } 7542 7543 initialize($el, opts) { 7544 if ($el.data(instanceName)) { 7545 return this; 7546 } 7547 7548 this.$el = $el; 7549 7550 this 7551 .setData() 7552 .setOptions(opts) 7553 .build(); 7554 7555 return this; 7556 } 7557 7558 setData() { 7559 this.$el.data(instanceName, this); 7560 7561 return this; 7562 } 7563 7564 setOptions(opts) { 7565 this.options = $.extend(true, {}, PluginToggle.defaults, opts, { 7566 wrapper: this.$el 7567 }); 7568 7569 return this; 7570 } 7571 7572 build() { 7573 const self = this; 7574 const $wrapper = this.options.wrapper; 7575 const $items = $wrapper.find('> .toggle'); 7576 let $el = null; 7577 7578 $items.each(function() { 7579 $el = $(this); 7580 7581 if ($el.hasClass('active')) { 7582 $el.find('> p').addClass('preview-active'); 7583 $el.find('> .toggle-content').slideDown(self.options.duration); 7584 } 7585 7586 self.events($el); 7587 }); 7588 7589 if (self.options.isAccordion) { 7590 self.options.duration = self.options.duration / 2; 7591 } 7592 7593 return this; 7594 } 7595 7596 events($el) { 7597 const self = this; 7598 let previewParCurrentHeight = 0; 7599 let previewParAnimateHeight = 0; 7600 let toggleContent = null; 7601 7602 $el.find('> label, > .toggle-title').click(function({originalEvent}) { 7603 const $this = $(this); 7604 const parentSection = $this.parent(); 7605 const parentWrapper = $this.parents('.toggle'); 7606 let previewPar = null; 7607 let closeElement = null; 7608 7609 if (self.options.isAccordion && typeof(originalEvent) != 'undefined') { 7610 closeElement = parentWrapper.find('.toggle.active > label, .toggle.active > .toggle-title'); 7611 7612 if (closeElement[0] == $this[0]) { 7613 return; 7614 } 7615 } 7616 7617 parentSection.toggleClass('active'); 7618 7619 // Preview Paragraph 7620 if (parentSection.find('> p').get(0)) { 7621 7622 previewPar = parentSection.find('> p'); 7623 previewParCurrentHeight = previewPar.css('height'); 7624 previewPar.css('height', 'auto'); 7625 previewParAnimateHeight = previewPar.css('height'); 7626 previewPar.css('height', previewParCurrentHeight); 7627 7628 } 7629 7630 // Content 7631 toggleContent = parentSection.find('> .toggle-content'); 7632 7633 if (parentSection.hasClass('active')) { 7634 7635 $(previewPar).animate({ 7636 height: previewParAnimateHeight 7637 }, self.options.duration, function() { 7638 $(this).addClass('preview-active'); 7639 });
7640 7641 toggleContent.slideDown(self.options.duration, () => { 7642 if (closeElement) { 7643 closeElement.trigger('click'); 7644 } 7645 }); 7646 7647 } else { 7648 7649 $(previewPar).animate({ 7650 height: 0 7651 }, self.options.duration, function() { 7652 $(this).removeClass('preview-active'); 7653 }); 7654 7655 toggleContent.slideUp(self.options.duration); 7656 7657 } 7658 }); 7659 } 7660 } 7661 7662 PluginToggle.defaults = { 7663 duration: 350, 7664 isAccordion: false 7665 }; 7666 7667 // expose to scope 7668 $.extend(theme, { 7669 PluginToggle 7670 }); 7671 7672 // jquery plugin 7673 $.fn.themePluginToggle = function(opts) { 7674 return this.map(function() { 7675 const $this = $(this); 7676 7677 if ($this.data(instanceName)) { 7678 return $this.data(instanceName); 7679 } else { 7680 return new PluginToggle($this, opts); 7681 } 7682 7683 }); 7684 } 7685})).apply(this, [window.theme, jQuery]); 7686 7687// Validation 7688(((theme = {}, $) => { 7689 $.extend(theme, { 7690 7691 PluginValidation: { 7692 7693 defaults: { 7694 formClass: 'needs-validation', 7695 validator: { 7696 highlight(element) { 7697 $(element) 7698 .addClass('is-invalid') 7699 .removeClass('is-valid') 7700 .parent() 7701 .removeClass('has-success') 7702 .addClass('has-danger'); 7703 }, 7704 success(label, element) { 7705 $(element) 7706 .removeClass('is-invalid') 7707 .addClass('is-valid') 7708 .parent() 7709 .removeClass('has-danger') 7710 .addClass('has-success') 7711 .find('label.error') 7712 .remove(); 7713 }, 7714 errorPlacement(error, element) { 7715 if (element.attr('type') == 'radio' || element.attr('type') == 'checkbox') { 7716 error.appendTo(element.parent().parent()); 7717 } else { 7718 error.insertAfter(element); 7719 } 7720 } 7721 } 7722 }, 7723 7724 initialize(opts) { 7725 initialized = true; 7726 7727 this 7728 .setOptions(opts) 7729 .build(); 7730 7731 return this; 7732 }, 7733 7734 setOptions(opts) { 7735 this.options = $.extend(true, {}, this.defaults, opts); 7736 7737 return this; 7738 }, 7739 7740 build() { 7741 const self = this; 7742 7743 if (!($.isFunction($.validator))) { 7744 return this; 7745 } 7746 7747 self.setMessageGroups(); 7748 7749 $.validator.setDefaults(self.options.validator); 7750 7751 $('.' + self.options.formClass).validate(); 7752 7753 return this; 7754 }, 7755 7756 setMessageGroups() { 7757 7758 $('.checkbox-group[data-msg-required], .radio-group[data-msg-required]').each(function() { 7759 const message = $(this).data('msg-required'); 7760 $(this).find('input').attr('data-msg-required', message); 7761 }); 7762 7763 } 7764 7765 } 7766 7767 }); 7768})).apply(this, [window.theme, jQuery]); 7769 7770// Video Background 7771(((theme = {}, $) => { 7772 const instanceName = '__videobackground'; 7773 7774 class PluginVideoBackground { 7775 constructor($el, opts) { 7776 return this.initialize($el, opts); 7777 } 7778 7779 initialize($el, opts) { 7780 this.$el = $el; 7781 7782 this 7783 .setData() 7784 .setOptions(opts) 7785 .build() 7786 .events(); 7787 7788 return this; 7789 } 7790 7791 setData() { 7792 this.$el.data(instanceName, this); 7793 7794 return this; 7795 } 7796 7797 setOptions(opts) { 7798 this.options = $.extend(true, {}, PluginVideoBackground.defaults, opts, { 7799 path: this.$el.data('video-path'), 7800 wrapper: this.$el 7801 }); 7802 7803 return this; 7804 } 7805 7806 build() { 7807 const self = this; 7808 7809 if (!($.isFunction($.fn.vide)) || (!this.options.path)) { 7810 return this; 7811 } 7812 7813 if (this.options.overlay) { 7814 7815 const overlayClass = this.options.overlayClass; 7816 7817 this.options.wrapper.prepend( 7818 $('<div />').addClass(overlayClass) 7819 ); 7820 } 7821 7822 this.options.wrapper 7823 .vide(this.options.path, this.options) 7824 .first() 7825 .css('z-index', 0); 7826 7827 // Change Poster 7828 self.changePoster(); 7829 7830 // Initialize Vide inside a carousel 7831 if( self.options.wrapper.closest('.owl-carousel').get(0) ) { 7832 self.options.wrapper.closest('.owl-carousel').on('initialized.owl.carousel', () => { 7833 $('.owl-item.cloned') 7834 .find('[data-plugin-video-background] .vide-video-wrapper') 7835 .remove(); 7836 7837 $('.owl-item.cloned')
7838 .find('[data-plugin-video-background]') 7839 .vide(self.options.path, self.options) 7840 .first() 7841 .css('z-index', 0); 7842 7843 self.changePoster( self.options.wrapper.closest('.owl-carousel') ); 7844 }); 7845 } 7846 7847 // Play Video Button 7848 const $playButton = self.options.wrapper.find('.video-background-play'); 7849 7850 if( $playButton.get(0) ) { 7851 const $playWrapper = self.options.wrapper.find('.video-background-play-wrapper'); 7852 7853 self.options.wrapper.find('.video-background-play').on('click', e => { 7854 e.preventDefault(); 7855 7856 if( $playWrapper.get(0) ) { 7857 $playWrapper.animate({ 7858 opacity: 0 7859 }, 300, () => { 7860 $playWrapper.parent().height( $playWrapper.outerHeight() ); 7861 $playWrapper.remove(); 7862 }); 7863 } else { 7864 $playButton.animate({ 7865 opacity: 0 7866 }, 300, () => { 7867 $playButton.remove(); 7868 }); 7869 } 7870 7871 setTimeout(() => { 7872 self.options.wrapper.find('video')[0].play(); 7873 }, 500) 7874 }); 7875 } 7876 7877 $(window).trigger('vide.video.inserted.on.dom'); 7878 7879 return this; 7880 } 7881 7882 changePoster($carousel) { 7883 const self = this; 7884 7885 // If it's inside carousel 7886 if( $carousel && self.options.changePoster ) { 7887 $carousel.find('.owl-item [data-plugin-video-background] .vide-video-wrapper').css({ 7888 'background-image': 'url(' + self.options.changePoster + ')' 7889 }); 7890 7891 return this; 7892 } 7893 7894 if( self.options.changePoster ) { 7895 self.options.wrapper.find('.vide-video-wrapper').css({ 7896 'background-image': 'url(' + self.options.changePoster + ')' 7897 }); 7898 } 7899 7900 return this; 7901 } 7902 7903 events() { 7904 const self = this; 7905 7906 // Initialize 7907 self.options.wrapper.on('video.background.initialize', () => { 7908 self.build(); 7909 }); 7910 7911 return this; 7912 } 7913 } 7914 7915 PluginVideoBackground.defaults = { 7916 overlay: false, 7917 volume: 1, 7918 playbackRate: 1, 7919 muted: true, 7920 loop: true, 7921 autoplay: true, 7922 position: '50% 50%', 7923 posterType: 'detect', 7924 className: 'vide-video-wrapper' 7925 }; 7926 7927 // expose to scope 7928 $.extend(theme, { 7929 PluginVideoBackground 7930 }); 7931 7932 // jquery plugin 7933 $.fn.themePluginVideoBackground = function(opts) { 7934 return this.map(function() { 7935 const $this = $(this); 7936 7937 if ($this.data(instanceName)) { 7938 return $this.data(instanceName); 7939 } else { 7940 return new PluginVideoBackground($this, opts); 7941 } 7942 7943 }); 7944 } 7945})).apply(this, [window.theme, jQuery]); 7946 7947// Account 7948(((theme = {}, $) => { 7949 let initialized = false; 7950 7951 $.extend(theme, { 7952 7953 Account: { 7954 7955 defaults: { 7956 wrapper: $('#headerAccount') 7957 }, 7958 7959 initialize($wrapper, opts) { 7960 if (initialized) { 7961 return this; 7962 } 7963 7964 initialized = true; 7965 this.$wrapper = ($wrapper || this.defaults.wrapper); 7966 7967 this 7968 .setOptions(opts) 7969 .events(); 7970 7971 return this; 7972 }, 7973 7974 setOptions(opts) { 7975 this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options'))); 7976 7977 return this; 7978 }, 7979 7980 events() { 7981 const self = this; 7982 7983 $(window).on('load', () => { 7984 $(document).ready(() => { 7985 setTimeout(() => { 7986 7987 self.$wrapper.find('input').on('focus', () => { 7988 self.$wrapper.addClass('open'); 7989 7990 $(document).mouseup(({target}) => { 7991 if (!self.$wrapper.is(target) && self.$wrapper.has(target).length === 0) { 7992 self.$wrapper.removeClass('open'); 7993 } 7994 });
7995 }); 7996 7997 }, 1500); 7998 }); 7999 }); 8000 8001 $('#headerSignUp').on('click', e => { 8002 e.preventDefault(); 8003 self.$wrapper.addClass('signup').removeClass('signin').removeClass('recover'); 8004 self.$wrapper.find('.signup-form input:first').focus(); 8005 }); 8006 8007 $('#headerSignIn').on('click', e => { 8008 e.preventDefault(); 8009 self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover'); 8010 self.$wrapper.find('.signin-form input:first').focus(); 8011 }); 8012 8013 $('#headerRecover').on('click', e => { 8014 e.preventDefault(); 8015 self.$wrapper.addClass('recover').removeClass('signup').removeClass('signin'); 8016 self.$wrapper.find('.recover-form input:first').focus(); 8017 }); 8018 8019 $('#headerRecoverCancel').on('click', e => { 8020 e.preventDefault(); 8021 self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover'); 8022 self.$wrapper.find('.signin-form input:first').focus(); 8023 }); 8024 } 8025 8026 } 8027 8028 }); 8029})).apply(this, [window.theme, jQuery]); 8030 8031// Nav 8032(((theme = {}, $) => { 8033 let initialized = false; 8034 8035 $.extend(theme, { 8036 8037 Nav: { 8038 8039 defaults: { 8040 wrapper: $('#mainNav'), 8041 scrollDelay: 600, 8042 scrollAnimation: 'easeOutQuad' 8043 }, 8044 8045 initialize($wrapper, opts) { 8046 if (initialized) { 8047 return this; 8048 } 8049 8050 initialized = true; 8051 this.$wrapper = ($wrapper || this.defaults.wrapper); 8052 8053 this 8054 .setOptions(opts) 8055 .build() 8056 .events(); 8057 8058 return this; 8059 }, 8060 8061 setOptions(opts) { 8062 this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options'))); 8063 8064 return this; 8065 }, 8066 8067 build() { 8068 const self = this; 8069 const $html = $('html'); 8070 const $header = $('#header'); 8071 const $headerNavMain = $('#header .header-nav-main'); 8072 let thumbInfoPreview; 8073 8074 // Preview Thumbs 8075 if( self.$wrapper.find('a[data-thumb-preview]').length ) { 8076 self.$wrapper.find('a[data-thumb-preview]').each(function() { 8077 thumbInfoPreview = $('<span />').addClass('thumb-info thumb-info-preview') 8078 .append($('<span />').addClass('thumb-info-wrapper') 8079 .append($('<span />').addClass('thumb-info-image').css('background-image', 'url(' + $(this).data('thumb-preview') + ')') 8080 ) 8081 ); 8082 8083 $(this).append(thumbInfoPreview); 8084 }); 8085 } 8086 8087 // Side Header / Side Header Hamburguer Sidebar (Reverse Dropdown) 8088 if($html.hasClass('side-header') || $html.hasClass('side-header-hamburguer-sidebar')) { 8089 8090 // Side Header Right / Side Header Hamburguer Sidebar Right 8091 if($html.hasClass('side-header-right') || $html.hasClass('side-header-hamburguer-sidebar-right')) { 8092 if(!$html.hasClass('side-header-right-no-reverse')) { 8093 $header.find('.dropdown-submenu').addClass('dropdown-reverse'); 8094 } 8095 } 8096 8097 } else { 8098 8099 // Reverse 8100 let checkReverseFlag = false; 8101 self.checkReverse = () => { 8102 if( !checkReverseFlag ) { 8103 self.$wrapper.find('.dropdown, .dropdown-submenu').removeClass('dropdown-reverse'); 8104 8105 self.$wrapper.find('.dropdown:not(.manual):not(.dropdown-mega), .dropdown-submenu:not(.manual)').each(function() { 8106 if(!$(this).find('.dropdown-menu').visible( false, true, 'horizontal' ) ) { 8107 $(this).addClass('dropdown-reverse'); 8108 } 8109 }); 8110 8111 checkReverseFlag = true; 8112 } 8113 } 8114 8115 $(window).on('resize', () => { 8116 checkReverseFlag = false; 8117 }); 8118 8119 $header.on('mouseover', () => { 8120 self.checkReverse(); 8121 }); 8122 8123 } 8124 8125 // Clone Items 8126 if($headerNavMain.hasClass('header-nav-main-clone-items')) { 8127 8128 $headerNavMain.find('nav > ul > li > a').each(function(){ 8129 const parent = $(this).parent(), clone = $(this).clone(), clone2 = $(this).clone(), wrapper = $('<span class="wrapper-items-cloned"></span>'); 8130 8131 // Config Classes 8132 $(this).addClass('item-original'); 8133 clone2.addClass('item-two'); 8134 8135 // Insert on DOM
8136 parent.prepend(wrapper); 8137 wrapper.append(clone).append(clone2); 8138 }); 8139 8140 } 8141 8142 // Floating 8143 if($('#header.header-floating-icons').length && $(window).width() > 991) { 8144 8145 const menuFloatingAnim = { 8146 $menuFloating: $('#header.header-floating-icons .header-container > .header-row'), 8147 8148 build() { 8149 const self = this; 8150 8151 self.init(); 8152 }, 8153 init() { 8154 const self = this; 8155 let divisor = 0; 8156 8157 $(window).scroll(function() { 8158 const scrollPercent = 100 * $(window).scrollTop() / ($(document).height() - $(window).height()), st = $(this).scrollTop(); 8159 8160 divisor = $(document).height() / $(window).height(); 8161 8162 self.$menuFloating.find('.header-column > .header-row').css({ 8163 transform : 'translateY( calc('+ scrollPercent +'vh - '+ st / divisor +'px) )' 8164 }); 8165 }); 8166 } 8167 }; 8168 8169 menuFloatingAnim.build(); 8170 8171 } 8172 8173 // Slide 8174 if($('.header-nav-links-vertical-slide').length) { 8175 const slideNavigation = { 8176 $mainNav: $('#mainNav'), 8177 $mainNavItem: $('#mainNav li'), 8178 8179 build() { 8180 const self = this; 8181 8182 self.menuNav(); 8183 }, 8184 menuNav() { 8185 const self = this; 8186 8187 self.$mainNavItem.on('click', function(e){ 8188 const currentMenuItem = $(this), currentMenu = $(this).parent(), nextMenu = $(this).find('ul').first(), prevMenu = $(this).closest('.next-menu'), isSubMenu = currentMenuItem.hasClass('dropdown') || currentMenuItem.hasClass('dropdown-submenu'), isBack = currentMenuItem.hasClass('back-button'), nextMenuHeightDiff = ( ( nextMenu.find('> li').length * nextMenu.find('> li').outerHeight() ) - nextMenu.outerHeight() ), prevMenuHeightDiff = ( ( prevMenu.find('> li').length * prevMenu.find('> li').outerHeight() ) - prevMenu.outerHeight() ); 8189 8190 if( isSubMenu ) { 8191 currentMenu.addClass('next-menu'); 8192 nextMenu.addClass('visible'); 8193 currentMenu.css({ 8194 overflow: 'visible', 8195 'overflow-y': 'visible' 8196 }); 8197 8198 if( nextMenuHeightDiff > 0 ) { 8199 nextMenu.css({ 8200 overflow: 'hidden', 8201 'overflow-y': 'scroll' 8202 }); 8203 } 8204 8205 for( i = 0; i < nextMenu.find('> li').length; i++ ) { 8206 if( nextMenu.outerHeight() < ($('.header-row-side-header').outerHeight() - 100) ) { 8207 nextMenu.css({ 8208 height: nextMenu.outerHeight() + nextMenu.find('> li').outerHeight() 8209 }); 8210 } 8211 } 8212 8213 nextMenu.css({ 8214 'padding-top': nextMenuHeightDiff + 'px' 8215 }); 8216 } 8217 8218 if( isBack ) { 8219 currentMenu.parent().parent().removeClass('next-menu'); 8220 currentMenu.removeClass('visible'); 8221 8222 if( prevMenuHeightDiff > 0 ) { 8223 prevMenu.css({ 8224 overflow: 'hidden', 8225 'overflow-y': 'scroll' 8226 }); 8227 } 8228 } 8229 8230 e.stopPropagation(); 8231 }); 8232 } 8233 }; 8234 8235 $(window).trigger('resize'); 8236 8237 if( $(window).width() > 991 ) { 8238 slideNavigation.build(); 8239 } 8240 8241 $(document).ready(() => { 8242 $(window).afterResize(() => { 8243 if( $(window).width() > 991 ) { 8244 slideNavigation.build(); 8245 } 8246 }); 8247 }); 8248 } 8249 8250 // Header Nav Main Mobile Dark 8251 if($('.header-nav-main-mobile-dark').length) { 8252 $('#header:not(.header-transparent-dark-bottom-border):not(.header-transparent-light-bottom-border)').addClass('header-no-border-bottom'); 8253 } 8254 8255 // Keyboard Navigation / Accessibility 8256 if( $(window).width() > 991 ) { 8257 let focusFlag = false; 8258 $header.find('.header-nav-main nav > ul > li > a').on('focus', function(){ 8259 8260 if( $(window).width() > 991 ) { 8261 if( !focusFlag ) { 8262 focusFlag = true; 8263 $(this).trigger('blur'); 8264 8265 self.focusMenuWithChildren();
8266 } 8267 } 8268 8269 }); 8270 } 8271 8272 return this; 8273 }, 8274 8275 focusMenuWithChildren() { 8276 // Get all the link elements within the primary menu. 8277 let links; 8278 8279 let i; 8280 let len; 8281 const menu = document.querySelector( 'html:not(.side-header):not(.side-header-hamburguer-sidebar):not(.side-header-overlay-full-screen) .header-nav-main > nav' ); 8282 8283 if ( ! menu ) { 8284 return false; 8285 } 8286 8287 links = menu.getElementsByTagName( 'a' ); 8288 8289 // Each time a menu link is focused or blurred, toggle focus. 8290 for ( i = 0, len = links.length; i < len; i++ ) { 8291 links[i].addEventListener( 'focus', toggleFocus, true ); 8292 links[i].addEventListener( 'blur', toggleFocus, true ); 8293 } 8294 8295 //Sets or removes the .focus class on an element. 8296 function toggleFocus() { 8297 let self = this; 8298 8299 // Move up through the ancestors of the current link until we hit .primary-menu. 8300 while ( !self.className.includes('header-nav-main') ) { 8301 // On li elements toggle the class .focus. 8302 if ( 'li' === self.tagName.toLowerCase() ) { 8303 if ( self.className.includes('accessibility-open') ) { 8304 self.className = self.className.replace( ' accessibility-open', '' ); 8305 } else { 8306 self.className += ' accessibility-open'; 8307 } 8308 } 8309 self = self.parentElement; 8310 } 8311 } 8312 }, 8313 8314 events() { 8315 const self = this; 8316 const $html = $('html'); 8317 let $header = $('#header'); 8318 const $window = $(window); 8319 let headerBodyHeight = $('.header-body').outerHeight(); 8320 8321 if( $header.hasClass('header') ) { 8322 $header = $('.header'); 8323 } 8324 8325 $header.find('a[href="#"]').on('click', e => { 8326 e.preventDefault(); 8327 }); 8328 8329 // Mobile Arrows 8330 if( $html.hasClass('side-header-hamburguer-sidebar') ) { 8331 $header.find('.dropdown-toggle, .dropdown-submenu > a') 8332 .append('<i class="fas fa-chevron-down fa-chevron-right"></i>'); 8333 } else { 8334 $header.find('.dropdown-toggle, .dropdown-submenu > a') 8335 .append('<i class="fas fa-chevron-down"></i>'); 8336 } 8337 8338 $header.find('.dropdown-toggle[href="#"], .dropdown-submenu a[href="#"], .dropdown-toggle[href!="#"] .fa-chevron-down, .dropdown-submenu a[href!="#"] .fa-chevron-down').on('click', function(e) { 8339 e.preventDefault(); 8340 if ($window.width() < 992) { 8341 $(this).closest('li').toggleClass('open'); 8342 8343 // Adjust Header Body Height 8344 const height = ( $header.hasClass('header-effect-shrink') && $html.hasClass('sticky-header-active') ) ? theme.StickyHeader.options.stickyHeaderContainerHeight : headerBodyHeight; 8345 $('.header-body').animate({ 8346 height: ($('.header-nav-main nav').outerHeight(true) + height) + 10 8347 }, 0); 8348 } 8349 }); 8350 8351 $header.find('li a.active').addClass('current-page-active'); 8352 8353 // Add Open Class 8354 $header.find('.header-nav-click-to-open .dropdown-toggle[href="#"], .header-nav-click-to-open .dropdown-submenu a[href="#"], .header-nav-click-to-open .dropdown-toggle > i').on('click', function(e) { 8355 if( !$('html').hasClass('side-header-hamburguer-sidebar') && $window.width() > 991 ) { 8356 e.preventDefault(); 8357 e.stopPropagation(); 8358 } 8359 8360 if ($window.width() > 991) { 8361 e.preventDefault(); 8362 e.stopPropagation(); 8363 8364 $header.find('li a.active').removeClass('active'); 8365 8366 if( $(this).prop('tagName') == 'I' ) { 8367 $(this).parent().addClass('active'); 8368 } else { 8369 $(this).addClass('active'); 8370 } 8371 8372 if (!$(this).closest('li').hasClass('open')) { 8373 const $li = $(this).closest('li'); 8374 let isSub = false; 8375 8376 if( $(this).prop('tagName') == 'I' ) { 8377 $('#header .dropdown.open').removeClass('open'); 8378 $('#header .dropdown-menu .dropdown-submenu.open').removeClass('open'); 8379 } 8380 8381 if ( $(this).parent().hasClass('dropdown-submenu') ) { 8382 isSub = true; 8383 } 8384 8385 $(this).closest('.dropdown-menu').find('.dropdown-submenu.open').removeClass('open'); 8386 $(this).parent('.dropdown').parent().find('.dropdown.open').removeClass('open'); 8387 8388 if (!isSub) { 8389 $(this).parent().find('.dropdown-submenu.open').removeClass('open'); 8390 } 8391 8392 $li.addClass('open'); 8393
8394 $(document).off('click.nav-click-to-open').on('click.nav-click-to-open', ({target}) => { 8395 if (!$li.is(target) && $li.has(target).length === 0) { 8396 $li.removeClass('open'); 8397 $li.parents('.open').removeClass('open'); 8398 $header.find('li a.active').removeClass('active'); 8399 $header.find('li a.current-page-active').addClass('active'); 8400 } 8401 }); 8402 } else { 8403 $(this).closest('li').removeClass('open'); 8404 $header.find('li a.active').removeClass('active'); 8405 $header.find('li a.current-page-active').addClass('active'); 8406 } 8407 8408 $window.trigger({ 8409 type: 'resize', 8410 from: 'header-nav-click-to-open' 8411 }); 8412 } 8413 }); 8414 8415 // Collapse Nav 8416 $header.find('[data-collapse-nav]').on('click', function(e) { 8417 $(this).parents('.collapse').removeClass('show'); 8418 }); 8419 8420 // Top Features 8421 $header.find('.header-nav-features-toggle').on('click', function(e) { 8422 e.preventDefault(); 8423 8424 const $toggleParent = $(this).parent(); 8425 8426 if (!$(this).siblings('.header-nav-features-dropdown').hasClass('show')) { 8427 8428 const $dropdown = $(this).siblings('.header-nav-features-dropdown'); 8429 8430 $('.header-nav-features-dropdown.show').removeClass('show'); 8431 8432 $dropdown.addClass('show'); 8433 8434 $(document).off('click.header-nav-features-toggle').on('click.header-nav-features-toggle', ({target}) => { 8435 if (!$toggleParent.is(target) && $toggleParent.has(target).length === 0) { 8436 $('.header-nav-features-dropdown.show').removeClass('show'); 8437 } 8438 }); 8439 8440 if ($(this).attr('data-focus')) { 8441 $('#' + $(this).attr('data-focus')).focus(); 8442 } 8443 8444 } else { 8445 $(this).siblings('.header-nav-features-dropdown').removeClass('show'); 8446 } 8447 }); 8448 8449 // Hamburguer Menu 8450 const $hamburguerMenuBtn = $('.hamburguer-btn:not(.side-panel-toggle)'), $hamburguerSideHeader = $('#header.side-header, #header.side-header-overlay-full-screen'); 8451 8452 $hamburguerMenuBtn.on('click', function(){ 8453 if($(this).attr('data-set-active') != 'false') { 8454 $(this).toggleClass('active'); 8455 } 8456 $hamburguerSideHeader.toggleClass('side-header-hide'); 8457 $html.toggleClass('side-header-hide'); 8458 8459 $window.trigger('resize'); 8460 }); 8461 8462 // Toggle Side Header 8463 $('.toggle-side-header').on('click', () => { 8464 $('.hamburguer-btn-side-header.active').trigger('click'); 8465 }); 8466 8467 $('.hamburguer-close:not(.side-panel-toggle)').on('click', () => { 8468 $('.hamburguer-btn:not(.hamburguer-btn-side-header-mobile-show)').trigger('click'); 8469 }); 8470 8471 // Set Header Body Height when open mobile menu 8472 $('.header-nav-main nav').on('show.bs.collapse', function () { 8473 $(this).removeClass('closed'); 8474 8475 // Add Mobile Menu Opened Class 8476 $('html').addClass('mobile-menu-opened'); 8477 8478 $('.header-body').animate({ 8479 height: ($('.header-body').outerHeight() + $('.header-nav-main nav').outerHeight(true)) + 10 8480 }); 8481 8482 // Header Below Slider / Header Bottom Slider - Scroll to menu position 8483 if( $('#header').is('.header-bottom-slider, .header-below-slider') && !$('html').hasClass('sticky-header-active') ) { 8484 self.scrollToTarget( $('#header'), 0 ); 8485 } 8486 }); 8487 8488 // Set Header Body Height when collapse mobile menu 8489 $('.header-nav-main nav').on('hide.bs.collapse', function () { 8490 $(this).addClass('closed'); 8491 8492 // Remove Mobile Menu Opened Class 8493 $('html').removeClass('mobile-menu-opened'); 8494 8495 $('.header-body').animate({ 8496 height: ($('.header-body').outerHeight() - $('.header-nav-main nav').outerHeight(true)) 8497 }, function(){ 8498 $(this).height('auto'); 8499 }); 8500 }); 8501 8502 // Header Effect Shrink - Adjust header body height on mobile 8503 $window.on('stickyHeader.activate', () => { 8504 if( $window.width() < 992 && $header.hasClass('header-effect-shrink') ) { 8505 if( $('.header-btn-collapse-nav').attr('aria-expanded') == 'true' ) { 8506 $('.header-body').animate({ 8507 height: ( $('.header-nav-main nav').outerHeight(true) + theme.StickyHeader.options.stickyHeaderContainerHeight ) + ( ($('.header-nav-bar').length) ? $('.header-nav-bar').outerHeight() : 0 ) 8508 });
8509 } 8510 } 8511 }); 8512 8513 $window.on('stickyHeader.deactivate', () => { 8514 if( $window.width() < 992 && $header.hasClass('header-effect-shrink') ) { 8515 if( $('.header-btn-collapse-nav').attr('aria-expanded') == 'true' ) { 8516 $('.header-body').animate({ 8517 height: headerBodyHeight + $('.header-nav-main nav').outerHeight(true) + 10 8518 }); 8519 } 8520 } 8521 }); 8522 8523 // Remove Open Class on Resize 8524 $window.on('resize.removeOpen', ({from}) => { 8525 if( from == 'header-nav-click-to-open' ) { 8526 return; 8527 } 8528 8529 setTimeout(() => { 8530 if( $window.width() > 991 ) { 8531 $header.find('.dropdown.open').removeClass('open'); 8532 } 8533 }, 100); 8534 }); 8535 8536 // Side Header - Change value of initial header body height 8537 $(document).ready(() => { 8538 if( $window.width() > 991 ) { 8539 let flag = false; 8540 8541 $window.on('resize', ({from}) => { 8542 if( from == 'header-nav-click-to-open' ) { 8543 return; 8544 } 8545 8546 $header.find('.dropdown.open').removeClass('open'); 8547 8548 if( $window.width() < 992 && flag == false ) { 8549 headerBodyHeight = $('.header-body').outerHeight(); 8550 flag = true; 8551 8552 setTimeout(() => { 8553 flag = false; 8554 }, 500); 8555 } 8556 }); 8557 } 8558 }); 8559 8560 // Side Header - Set header height on mobile 8561 if( $html.hasClass('side-header') ) { 8562 if( $window.width() < 992 ) { 8563 $header.css({ 8564 height: $('.header-body .header-container').outerHeight() + (parseInt( $('.header-body').css('border-top-width') ) + parseInt( $('.header-body').css('border-bottom-width') )) 8565 }); 8566 } 8567 8568 $(document).ready(() => { 8569 $window.afterResize(() => { 8570 if( $window.width() < 992 ) { 8571 $header.css({ 8572 height: $('.header-body .header-container').outerHeight() + (parseInt( $('.header-body').css('border-top-width') ) + parseInt( $('.header-body').css('border-bottom-width') )) 8573 });
8574 } else { 8575 $header.css({ 8576 height: '' 8577 }); 8578 } 8579 }); 8580 }); 8581 } 8582 8583 // Anchors Position 8584 if( $('[data-hash]').length ) { 8585 $('[data-hash]').on('mouseover', function(){ 8586 const $this = $(this); 8587 8588 if( !$this.data('__dataHashBinded') ) { 8589 let target = $this.attr('href'); 8590 let offset = ($this.is("[data-hash-offset]") ? $this.data('hash-offset') : 0); 8591 const delay = ($this.is("[data-hash-delay]") ? $this.data('hash-delay') : 0); 8592 const force = ($this.is("[data-hash-force]") ? true : false); 8593 const windowWidth = $(window).width(); 8594 8595 // Hash Offset SM 8596 if ($this.is("[data-hash-offset-sm]") && windowWidth > 576) { 8597 offset = $this.data('hash-offset-sm'); 8598 } 8599 8600 // Hash Offset MD 8601 if ($this.is("[data-hash-offset-md]") && windowWidth > 768) { 8602 offset = $this.data('hash-offset-md'); 8603 } 8604 8605 // Hash Offset LG 8606 if ($this.is("[data-hash-offset-lg]") && windowWidth > 992) { 8607 offset = $this.data('hash-offset-lg'); 8608 } 8609 8610 // Hash Offset XL 8611 if ($this.is("[data-hash-offset-xl]") && windowWidth > 1200) { 8612 offset = $this.data('hash-offset-xl'); 8613 } 8614 8615 // Hash Offset XXL 8616 if ($this.is("[data-hash-offset-xxl]") && windowWidth > 1400) { 8617 offset = $this.data('hash-offset-xxl'); 8618 } 8619 8620 if( !$(target).length ) { 8621 target = target.split('#'); 8622 target = '#'+target[1]; 8623 } 8624 8625 if( target.includes('#') && $(target).length) { 8626 $this.on('click', e => { 8627 e.preventDefault(); 8628 8629 if( !$(e.target).is('i') || force ) { 8630 8631 setTimeout(() => { 8632 8633 // Close Collapse if open 8634 $this.parents('.collapse.show').collapse('hide'); 8635 8636 // Close Side Header 8637 $hamburguerSideHeader.addClass('side-header-hide'); 8638 $html.addClass('side-header-hide'); 8639 8640 $window.trigger('resize'); 8641 8642 self.scrollToTarget(target, offset); 8643 8644 // Data Hash Trigger Click 8645 if( $this.data('hash-trigger-click') ) { 8646 8647 const $clickTarget = $( $this.data('hash-trigger-click') ), clickDelay = $this.data('hash-trigger-click-delay') ? $this.data('hash-trigger-click-delay') : 0; 8648 8649 if( $clickTarget.length ) { 8650 8651 setTimeout(() => { 8652 // If is a "Tabs" plugin link 8653 if( $clickTarget.closest('.nav-tabs').length ) { 8654 new bootstrap.Tab( $clickTarget[0] ).show(); 8655 } else { 8656 $clickTarget.trigger('click'); 8657 } 8658 8659 }, clickDelay); 8660 } 8661 8662 } 8663 8664 }, delay); 8665 8666 } 8667 8668 return; 8669 });
8670 } 8671 8672 $(this).data('__dataHashBinded', true); 8673 } 8674 }); 8675 } 8676 8677 // Floating 8678 if($('#header.header-floating-icons').length) { 8679 8680 $('#header.header-floating-icons [data-hash]').off().each(function() { 8681 8682 const target = $(this).attr('href'), offset = ($(this).is("[data-hash-offset]") ? $(this).data('hash-offset') : 0); 8683 8684 if($(target).length) { 8685 $(this).on('click', e => { 8686 e.preventDefault(); 8687 8688 $('html, body').animate({ 8689 scrollTop: $(target).offset().top - offset 8690 }, 600, 'easeOutQuad', () => { 8691 8692 }); 8693 8694 return; 8695 }); 8696 } 8697 8698 }); 8699 8700 } 8701 8702 // Side Panel Toggle 8703 if( $('.side-panel-toggle').length ) { 8704 const init_html_class = $('html').attr('class'); 8705 8706 $('.side-panel-toggle').on('click', function(e){ 8707 const extra_class = $(this).data('extra-class'), delay = ( extra_class ) ? 100 : 0, isActive = $(this).data('is-active') ? $(this).data('is-active') : false; 8708 8709 e.preventDefault(); 8710 8711 if( isActive ) { 8712 $('html').removeClass('side-panel-open'); 8713 $(this).data('is-active', false); 8714 return false; 8715 } 8716 8717 if( extra_class ) { 8718 $('.side-panel-wrapper').css('transition','none'); 8719 $('html') 8720 .removeClass() 8721 .addClass( init_html_class ) 8722 .addClass( extra_class ); 8723 } 8724 setTimeout(() => { 8725 $('.side-panel-wrapper').css('transition',''); 8726 $('html').toggleClass('side-panel-open'); 8727 }, delay); 8728 8729 $(this).data('is-active', true); 8730 }); 8731 8732 $(document).on('click', ({target}) => { 8733 if( !$(target).closest('.side-panel-wrapper').length && !$(target).hasClass('side-panel-toggle') ) { 8734 $('.hamburguer-btn.side-panel-toggle:not(.side-panel-close)').removeClass('active'); 8735 $('html').removeClass('side-panel-open'); 8736 $('.side-panel-toggle').data('is-active', false); 8737 } 8738 }); 8739 } 8740 8741 // OffCanvas 8742 self.offCanvasMenu(); 8743 8744 return this; 8745 }, 8746 8747 scrollToTarget(target, offset) { 8748 const self = this, targetPosition = $(target).offset().top; 8749 8750 $('body').addClass('scrolling'); 8751 8752 $('html, body').animate({ 8753 scrollTop: $(target).offset().top - offset 8754 }, self.options.scrollDelay, self.options.scrollAnimation, () => { 8755 $('body').removeClass('scrolling'); 8756 8757 // If by some reason the scroll finishes in a wrong position, this code will run the scrollToTarget() again until get the correct position 8758 // We need do it just one time to prevent infinite recursive loop at scrollToTarget() function 8759 if( $(target).offset().top != targetPosition) { 8760 $('html, body').animate({ 8761 scrollTop: $(target).offset().top - offset 8762 }, 1, self.options.scrollAnimation, () => {}); 8763 } 8764 }); 8765 8766 return this; 8767 8768 }, 8769 8770 offCanvasMenu() { 8771 const $headerNavMain = $('#header .header-nav-main'); 8772 const $offCanvasNav = $('.offcanvas-nav'); 8773 8774 if($offCanvasNav.length > 0) { 8775 const $navToClone = $headerNavMain.find('nav'); 8776 8777 if($navToClone.length > 0) { 8778 $offCanvasNav.html($offCanvasNav.html() + $navToClone.html()); 8779 $offCanvasNav.find('#mainNav').removeAttr('id').removeClass().addClass('nav flex-column w-100'); 8780 8781 // Clean Classes 8782 $offCanvasNav.find('.dropdown').removeClass().addClass('dropdown'); 8783 8784 $offCanvasNav.find('.dropdown-item:not(.dropdown-toggle)').removeClass().addClass('dropdown-item'); 8785 $offCanvasNav.find('.dropdown-item.dropdown-toggle').removeClass().addClass('dropdown-item dropdown-toggle'); 8786 8787 $offCanvasNav.find('.nav-link:not(.dropdown-toggle)').removeClass().addClass('nav-link'); 8788 $offCanvasNav.find('.nav-link.dropdown-toggle').removeClass().addClass('nav-link dropdown-toggle'); 8789 8790 $offCanvasNav.find('.dropdown-menu').removeClass().addClass('dropdown-menu'); 8791 8792 // Dropdowns 8793 $offCanvasNav.find('.dropdown-toggle').each(function() { 8794 const $el = $(this); 8795 const $arrow = $el.find('i'); 8796 8797 $arrow.on('click', function(e) { 8798 e.preventDefault(); 8799 e.stopPropagation(); 8800 $el.parents('li').toggleClass('open'); 8801 }) 8802 8803 if ($el.attr('href') == '#') { 8804 $el.on('click', function() { 8805 $arrow.trigger('click'); 8806 });
8807 } 8808 }); 8809 } 8810 } 8811 8812 return this; 8813 } 8814 8815 } 8816 8817 }); 8818})).apply(this, [window.theme, jQuery]); 8819 8820 8821// Newsletter 8822(((theme = {}, $) => { 8823 let initialized = false; 8824 8825 $.extend(theme, { 8826 8827 Newsletter: { 8828 8829 defaults: { 8830 wrapper: $('#newsletterForm') 8831 }, 8832 8833 initialize($wrapper, opts) { 8834 if (initialized) { 8835 return this; 8836 } 8837 8838 initialized = true; 8839 this.$wrapper = ($wrapper || this.defaults.wrapper); 8840 8841 this 8842 .setOptions(opts) 8843 .build(); 8844 8845 return this; 8846 }, 8847 8848 setOptions(opts) { 8849 this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options'))); 8850 8851 return this; 8852 }, 8853 8854 build() { 8855 if (!($.isFunction($.fn.validate))) { 8856 return this; 8857 } 8858 8859 const self = this, $email = self.$wrapper.find('#newsletterEmail'), $success = $('#newsletterSuccess'), $error = $('#newsletterError'); 8860 8861 self.$wrapper.validate({ 8862 submitHandler(form) { 8863 8864 $.ajax({ 8865 type: 'POST', 8866 url: self.$wrapper.attr('action'), 8867 data: { 8868 'email': $email.val() 8869 }, 8870 dataType: 'json', 8871 success({response, message}) { 8872 if (response == 'success') { 8873 8874 $success.removeClass('d-none'); 8875 $error.addClass('d-none'); 8876 8877 $email 8878 .val('') 8879 .blur() 8880 .closest('.control-group') 8881 .removeClass('success') 8882 .removeClass('error'); 8883 8884 } else { 8885 8886 $error.html(message); 8887 $error.removeClass('d-none'); 8888 $success.addClass('d-none'); 8889 8890 $email 8891 .blur() 8892 .closest('.control-group') 8893 .removeClass('success') 8894 .addClass('error'); 8895 8896 } 8897 } 8898 }); 8899 8900 }, 8901 rules: { 8902 newsletterEmail: { 8903 required: true, 8904 email: true 8905 } 8906 }, 8907 errorPlacement(error, element) { 8908 8909 } 8910 }); 8911 8912 return this; 8913 } 8914 8915 } 8916 8917 }); 8918})).apply(this, [window.theme, jQuery]); 8919 8920// Search 8921(((theme = {}, $) => { 8922 let initialized = false; 8923 8924 $.extend(theme, { 8925 8926 Search: { 8927 8928 defaults: { 8929 wrapper: $('#searchForm') 8930 }, 8931 8932 initialize($wrapper, opts) { 8933 if (initialized) { 8934 return this; 8935 } 8936 8937 initialized = true; 8938 this.$wrapper = ($wrapper || this.defaults.wrapper); 8939 8940 this 8941 .setOptions(opts) 8942 .build(); 8943 8944 return this; 8945 }, 8946 8947 setOptions(opts) { 8948 this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options'))); 8949 8950 return this; 8951 }, 8952 8953 build() { 8954 if (!($.isFunction($.fn.validate))) { 8955 return this; 8956 } 8957 8958 this.$wrapper.validate({ 8959 errorPlacement(error, element) {} 8960 }); 8961 8962 // Search Reveal 8963 theme.fn.execOnceTroughEvent( '#header', 'mouseover.search.reveal', () => { 8964 $('.header-nav-features-search-reveal').each(function() { 8965 const $el = $(this), $header = $('#header'), $html = $('html'); 8966 8967 $el.find('.header-nav-features-search-show-icon').on('click', () => { 8968 $el.addClass('show'); 8969 $header.addClass('search-show'); 8970 $html.addClass('search-show'); 8971 $('#headerSearch').focus(); 8972 }); 8973 8974 $el.find('.header-nav-features-search-hide-icon').on('click', () => { 8975 $el.removeClass('show'); 8976 $header.removeClass('search-show'); 8977 $html.removeClass('search-show'); 8978 }); 8979 }); 8980 } ); 8981 8982 return this; 8983 } 8984 8985 } 8986 8987 }); 8988})).apply(this, [window.theme, jQuery]); 8989 8990// Sticky Header 8991(((theme = {}, $) => { 8992 let initialized = false; 8993 8994 $.extend(theme, { 8995 8996 StickyHeader: { 8997 8998 defaults: { 8999 wrapper: $('#header'), 9000 headerBody: $('#header .header-body'), 9001 stickyEnabled: true, 9002 stickyEnableOnBoxed: true, 9003 stickyEnableOnMobile: false, 9004 stickyStartAt: 0, 9005 stickyStartAtElement: false, 9006 stickySetTop: 0, 9007 stickyEffect: '', 9008 stickyHeaderContainerHeight: false, 9009 stickyChangeLogo: false, 9010 stickyChangeLogoWrapper: true, 9011 stickyForce: false, 9012 stickyScrollUp: false, 9013 stickyScrollValue: 0 9014 }, 9015 9016 initialize($wrapper, opts) { 9017 if (initialized) { 9018 return this; 9019 } 9020 9021 initialized = true; 9022 this.$wrapper = ($wrapper || this.defaults.wrapper); 9023 9024 if( this.$wrapper.hasClass('header') ) {
9025 this.$wrapper = $('.header[data-plugin-options]'); 9026 } 9027 9028 this 9029 .setOptions(opts) 9030 .build() 9031 .events(); 9032 9033 return this; 9034 }, 9035 9036 setOptions(opts) { 9037 this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options'))); 9038 return this; 9039 }, 9040 9041 build() { 9042 if( $(window).width() < 992 && this.options.stickyEnableOnMobile == false ) { 9043 $('html').addClass('sticky-header-mobile-disabled'); 9044 return this; 9045 } 9046 9047 if (!this.options.stickyEnableOnBoxed && $('html').hasClass('boxed') || $('html').hasClass('side-header-hamburguer-sidebar') && !this.options.stickyForce || !this.options.stickyEnabled) { 9048 return this; 9049 } 9050 9051 const self = this; 9052 9053 if( self.options.wrapper.hasClass('header') ) { 9054 self.options.wrapper = $('.header'); 9055 self.options.headerBody = $('.header .header-body'); 9056 } 9057 9058 const $html = $('html'); 9059 const $window = $(window); 9060 const sideHeader = $html.hasClass('side-header'); 9061 const initialHeaderTopHeight = self.options.wrapper.find('.header-top').outerHeight(); 9062 const initialHeaderContainerHeight = self.options.wrapper.find('.header-container').outerHeight(); 9063 let minHeight; 9064 9065 // HTML Classes 9066 $html.addClass('sticky-header-enabled'); 9067 9068 if (parseInt(self.options.stickySetTop) < 0) { 9069 $html.addClass('sticky-header-negative'); 9070 } 9071 9072 if (self.options.stickyScrollUp) { 9073 $html.addClass('sticky-header-scroll-direction'); 9074 } 9075 9076 // Notice Top Bar First Load 9077 if( $('.notice-top-bar').get(0) ) { 9078 if (parseInt(self.options.stickySetTop) == 1 || self.options.stickyEffect == 'shrink') { 9079 $('.body').on('transitionend webkitTransitionEnd oTransitionEnd', () => { 9080 setTimeout(() => { 9081 if( !$html.hasClass('sticky-header-active') ) { 9082 self.options.headerBody.animate({ 9083 top: $('.notice-top-bar').outerHeight() 9084 }, 300, () => { 9085 if( $html.hasClass('sticky-header-active') ) { 9086 self.options.headerBody.css('top', 0); 9087 } 9088 }); 9089 } 9090 }, 0); 9091 }); 9092 } 9093 } 9094 9095 // Set Start At 9096 if(self.options.stickyStartAtElement) { 9097 9098 const $stickyStartAtElement = $(self.options.stickyStartAtElement); 9099 9100 $(window).on('scroll resize sticky.header.resize', () => { 9101 self.options.stickyStartAt = $stickyStartAtElement.offset().top; 9102 }); 9103 9104 $(window).trigger('sticky.header.resize'); 9105 } 9106 9107 // Define Min Height value 9108 if( self.options.wrapper.find('.header-top').get(0) ) { 9109 minHeight = ( initialHeaderTopHeight + initialHeaderContainerHeight ); 9110 } else { 9111 minHeight = initialHeaderContainerHeight; 9112 } 9113 9114 // Set Wrapper Min-Height 9115 if( !sideHeader ) { 9116 if( !$('.header-logo-sticky-change').get(0) ) { 9117 self.options.wrapper.css('height', self.options.headerBody.outerHeight()); 9118 } else { 9119 $window.on('stickyChangeLogo.loaded', () => { 9120 self.options.wrapper.css('height', self.options.headerBody.outerHeight()); 9121 }); 9122 } 9123 9124 if( self.options.stickyEffect == 'shrink' ) { 9125 9126 // Prevent wrong visualization of header when reload on middle of page 9127 $(document).ready(() => { 9128 if( $window.scrollTop() >= self.options.stickyStartAt ) { 9129 self.options.wrapper.find('.header-container').on('transitionend webkitTransitionEnd oTransitionEnd', () => { 9130 self.options.headerBody.css('position', 'fixed'); 9131 });
9132 } else { 9133 if( !$html.hasClass('boxed') ) { 9134 self.options.headerBody.css('position', 'fixed'); 9135 } 9136 } 9137 }); 9138 9139 self.options.wrapper.find('.header-container').css('height', initialHeaderContainerHeight); 9140 self.options.wrapper.find('.header-top').css('height', initialHeaderTopHeight); 9141 } 9142 } 9143 9144 // Sticky Header Container Height 9145 if( self.options.stickyHeaderContainerHeight ) { 9146 self.options.wrapper.find('.header-container').css('height', self.options.wrapper.find('.header-container').outerHeight()); 9147 } 9148 9149 // Boxed 9150 if($html.hasClass('boxed') && self.options.stickyEffect == 'shrink') { 9151 self.boxedLayout(); 9152 } 9153 9154 // Check Sticky Header / Flags prevent multiple runs at same time 9155 let activate_flag = true; 9156 9157 let deactivate_flag = false; 9158 const initialStickyStartAt = self.options.stickyStartAt; 9159 9160 self.checkStickyHeader = () => { 9161 9162 // Notice Top Bar 9163 const $noticeTopBar = $('.notice-top-bar'); 9164 if ( $noticeTopBar.get(0) ) { 9165 self.options.stickyStartAt = ( $noticeTopBar.data('sticky-start-at') ) ? $noticeTopBar.data('sticky-start-at') : $('.notice-top-bar').outerHeight(); 9166 } else { 9167 if( $html.hasClass('boxed') ) { 9168 self.options.stickyStartAt = initialStickyStartAt + 25; 9169 } else { 9170 self.options.stickyStartAt = initialStickyStartAt; 9171 } 9172 } 9173 9174 if( $window.width() > 991 && $html.hasClass('side-header') ) { 9175 $html.removeClass('sticky-header-active'); 9176 activate_flag = true; 9177 return; 9178 } 9179 9180 if ($window.scrollTop() >= parseInt(self.options.stickyStartAt)) { 9181 if( activate_flag ) { 9182 self.activateStickyHeader(); 9183 activate_flag = false; 9184 deactivate_flag = true; 9185 } 9186 } else { 9187 if( deactivate_flag ) { 9188 self.deactivateStickyHeader(); 9189 deactivate_flag = false; 9190 activate_flag = true; 9191 } 9192 } 9193 9194 // Scroll Up 9195 if (self.options.stickyScrollUp) { 9196 9197 // Get the new Value 9198 self.options.stickyScrollNewValue = window.pageYOffset; 9199 9200 //Subtract the two and conclude 9201 if(self.options.stickyScrollValue - self.options.stickyScrollNewValue < 0){ 9202 $html.removeClass('sticky-header-scroll-up').addClass('sticky-header-scroll-down'); 9203 } else if(self.options.stickyScrollValue - self.options.stickyScrollNewValue > 0){ 9204 $html.removeClass('sticky-header-scroll-down').addClass('sticky-header-scroll-up'); 9205 } 9206 9207 // Update the old value 9208 self.options.stickyScrollValue = self.options.stickyScrollNewValue; 9209 9210 } 9211 }; 9212 9213 // Activate Sticky Header 9214 self.activateStickyHeader = () => { 9215 if ($window.width() < 992) { 9216 if (self.options.stickyEnableOnMobile == false) { 9217 self.deactivateStickyHeader(); 9218 self.options.headerBody.css({ 9219 position: 'relative' 9220 }); 9221 return false; 9222 } 9223 } else { 9224 if (sideHeader) { 9225 self.deactivateStickyHeader(); 9226 return; 9227 } 9228 } 9229 9230 $html.addClass('sticky-header-active'); 9231 9232 // Sticky Effect - Reveal 9233 if( self.options.stickyEffect == 'reveal' ) { 9234 9235 self.options.headerBody.css('top','-' + self.options.stickyStartAt + 'px'); 9236 9237 self.options.headerBody.animate({ 9238 top: self.options.stickySetTop 9239 }, 400, () => {}); 9240 9241 } 9242 9243 // Sticky Effect - Shrink 9244 if( self.options.stickyEffect == 'shrink' ) { 9245 9246 // If Header Top 9247 if( self.options.wrapper.find('.header-top').get(0) ) { 9248 self.options.wrapper.find('.header-top').css({ 9249 height: 0, 9250 'min-height': 0, 9251 overflow: 'hidden' 9252 }); 9253 } 9254 9255 // Header Container 9256 if( self.options.stickyHeaderContainerHeight ) { 9257 self.options.wrapper.find('.header-container').css({ 9258 height: self.options.stickyHeaderContainerHeight, 9259 'min-height': 0 9260 });
9261 } else { 9262 self.options.wrapper.find('.header-container').css({ 9263 height: (initialHeaderContainerHeight / 3) * 2, // two third of container height 9264 'min-height': 0 9265 }); 9266 9267 const y = initialHeaderContainerHeight - ((initialHeaderContainerHeight / 3) * 2); 9268 $('.main').css({ 9269 transform: 'translate3d(0, -'+ y +'px, 0)', 9270 transition: 'ease transform 300ms' 9271 }).addClass('has-sticky-header-transform'); 9272 9273 if($html.hasClass('boxed')) { 9274 self.options.headerBody.css('position','fixed'); 9275 } 9276 } 9277 9278 } 9279 9280 self.options.headerBody.css('top', self.options.stickySetTop); 9281 9282 if (self.options.stickyChangeLogo) { 9283 self.changeLogo(true); 9284 } 9285 9286 // Set Elements Style 9287 if( $('[data-sticky-header-style]').length ) { 9288 $('[data-sticky-header-style]').each(function() { 9289 const $el = $(this), css = theme.fn.getOptions($el.data('sticky-header-style-active')), opts = theme.fn.getOptions($el.data('sticky-header-style')); 9290 9291 if( $window.width() > opts.minResolution ) { 9292 $el.css(css); 9293 } 9294 }); 9295 } 9296 9297 $.event.trigger({ 9298 type: 'stickyHeader.activate' 9299 }); 9300 }; 9301 9302 // Deactivate Sticky Header 9303 self.deactivateStickyHeader = () => { 9304 $html.removeClass('sticky-header-active'); 9305 9306 if ( $(window).width() < 992 && self.options.stickyEnableOnMobile == false) { 9307 return false; 9308 } 9309 9310 // Sticky Effect - Shrink 9311 if( self.options.stickyEffect == 'shrink' ) { 9312 9313 // Boxed Layout 9314 if( $html.hasClass('boxed') ) { 9315 9316 // Set Header Body Position Absolute 9317 self.options.headerBody.css('position','absolute'); 9318 9319 if( $window.scrollTop() > $('.body').offset().top ) { 9320 // Set Header Body Position Fixed 9321 self.options.headerBody.css('position','fixed'); 9322 } 9323 9324 } else { 9325 // Set Header Body Position Fixed 9326 self.options.headerBody.css('position','fixed'); 9327 } 9328 9329 // If Header Top 9330 if( self.options.wrapper.find('.header-top').get(0) ) { 9331 self.options.wrapper.find('.header-top').css({ 9332 height: initialHeaderTopHeight, 9333 overflow: 'visible' 9334 }); 9335 9336 // Fix [data-icon] issue when first load is on middle of the page 9337 if( self.options.wrapper.find('.header-top [data-icon]').length ) { 9338 theme.fn.intObsInit( '.header-top [data-icon]:not(.svg-inline--fa)', 'themePluginIcon' ); 9339 } 9340 } 9341 9342 // Header Container 9343 self.options.wrapper.find('.header-container').css({ 9344 height: initialHeaderContainerHeight 9345 }); 9346 9347 } 9348 9349 self.options.headerBody.css('top', 0); 9350 9351 if (self.options.stickyChangeLogo) { 9352 self.changeLogo(false); 9353 } 9354 9355 // Set Elements Style 9356 if( $('[data-sticky-header-style]').length ) { 9357 $('[data-sticky-header-style]').each(function() { 9358 const $el = $(this), css = theme.fn.getOptions($el.data('sticky-header-style-deactive')), opts = theme.fn.getOptions($el.data('sticky-header-style')); 9359 9360 if( $window.width() > opts.minResolution ) { 9361 $el.css(css); 9362 } 9363 }); 9364 } 9365 9366 $.event.trigger({ 9367 type: 'stickyHeader.deactivate' 9368 }); 9369 }; 9370 9371 // Always Sticky 9372 if (parseInt(self.options.stickyStartAt) <= 0) { 9373 self.activateStickyHeader(); 9374 } 9375 9376 // Set Logo 9377 if (self.options.stickyChangeLogo) { 9378 9379 const $logoWrapper = self.options.wrapper.find('.header-logo'), $logo = $logoWrapper.find('img'), logoWidth = $logo.attr('width'), logoHeight = $logo.attr('height'), logoSmallTop = parseInt($logo.attr('data-sticky-top') ? $logo.attr('data-sticky-top') : 0), logoSmallWidth = parseInt($logo.attr('data-sticky-width') ? $logo.attr('data-sticky-width') : 'auto'), logoSmallHeight = parseInt($logo.attr('data-sticky-height') ? $logo.attr('data-sticky-height') : 'auto'); 9380 9381 if (self.options.stickyChangeLogoWrapper) { 9382 $logoWrapper.css({ 9383 'width': $logo.outerWidth(true), 9384 'height': $logo.outerHeight(true) 9385 });
9386 } 9387 9388 self.changeLogo = activate => { 9389 if(activate) { 9390 9391 $logo.css({ 9392 'top': logoSmallTop, 9393 'width': logoSmallWidth, 9394 'height': logoSmallHeight 9395 }); 9396 9397 } else { 9398 9399 $logo.css({ 9400 'top': 0, 9401 'width': logoWidth, 9402 'height': logoHeight 9403 }); 9404 9405 } 9406 } 9407 9408 $.event.trigger({ 9409 type: 'stickyChangeLogo.loaded' 9410 }); 9411 9412 } 9413 9414 // Side Header 9415 let headerBodyHeight, flag = false; 9416 9417 self.checkSideHeader = () => { 9418 if($window.width() < 992 && flag == false) { 9419 headerBodyHeight = self.options.headerBody.height(); 9420 flag = true; 9421 } 9422 9423 if(self.options.stickyStartAt == 0 && sideHeader) { 9424 self.options.wrapper.css('min-height', 0); 9425 } 9426 9427 if(self.options.stickyStartAt > 0 && sideHeader && $window.width() < 992) { 9428 self.options.wrapper.css('min-height', headerBodyHeight); 9429 } 9430 } 9431 9432 return this; 9433 }, 9434 9435 events() { 9436 const self = this; 9437 9438 if( $(window).width() < 992 && this.options.stickyEnableOnMobile == false ) { 9439 return this; 9440 } 9441 9442 if (!this.options.stickyEnableOnBoxed && $('body').hasClass('boxed') || $('html').hasClass('side-header-hamburguer-sidebar') && !this.options.stickyForce || !this.options.stickyEnabled) { 9443 return this; 9444 } 9445 9446 if (!self.options.alwaysStickyEnabled) { 9447 $(window).on('scroll resize', () => { 9448 if ( $(window).width() < 992 && self.options.stickyEnableOnMobile == false) { 9449 self.options.headerBody.css({ 9450 position: '' 9451 }); 9452 9453 if( self.options.stickyEffect == 'shrink' ) { 9454 self.options.wrapper.find('.header-top').css({ 9455 height: '' 9456 });
9457 } 9458 9459 self.deactivateStickyHeader(); 9460 } else { 9461 self.checkStickyHeader(); 9462 } 9463 }); 9464 } else { 9465 self.activateStickyHeader(); 9466 } 9467 9468 $(window).on('load resize', () => { 9469 self.checkSideHeader(); 9470 }); 9471 9472 $(window).on('layout.boxed', () => { 9473 self.boxedLayout(); 9474 }); 9475 9476 return this; 9477 }, 9478 9479 boxedLayout() { 9480 const self = this, $window = $(window); 9481 9482 if($('html').hasClass('boxed') && self.options.stickyEffect == 'shrink') { 9483 if( (parseInt(self.options.stickyStartAt) == 0) && $window.width() > 991) { 9484 self.options.stickyStartAt = 30; 9485 } 9486 9487 // Set Header Body Position Absolute 9488 self.options.headerBody.css({ 9489 position: 'absolute', 9490 top: 0 9491 }); 9492 9493 // Set position absolute because top margin from boxed layout 9494 $window.on('scroll', () => { 9495 if( $window.scrollTop() > $('.body').offset().top ) { 9496 self.options.headerBody.css({ 9497 'position' : 'fixed', 9498 'top' : 0 9499 }); 9500 } else { 9501 self.options.headerBody.css({ 9502 'position' : 'absolute', 9503 'top' : 0 9504 }); 9505 } 9506 }); 9507 } 9508 9509 return this; 9510 } 9511 9512 } 9513 9514 }); 9515})).apply(this, [window.theme, jQuery]);
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.