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