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