1"use strict"; 2(function () { 3 // Global variables 4 let 5 userAgent = navigator.userAgent.toLowerCase(), 6 isIE = userAgent.indexOf("msie") !== -1 ? parseInt(userAgent.split("msie")[1], 10) : userAgent.indexOf("trident") !== -1 ? 11 : userAgent.indexOf("edge") !== -1 ? 12 : false; 7 8 // Unsupported browsers 9 if (isIE !== false && isIE < 12) { 10 console.warn("[Core] detected IE" + isIE + ", load alert"); 11 var script = document.createElement("script"); 12 script.src = "./js/support.js"; 13 document.querySelector("head").appendChild(script); 14 } 15 16 let 17 initialDate = new Date(), 18 19 $document = $(document), 20 $window = $(window), 21 $html = $("html"), 22 $body = $("body"), 23 24 isDesktop = $html.hasClass("desktop"), 25 isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent), 26 windowReady = false, 27 isNoviBuilder = false, 28 loaderTimeoutId, 29 plugins = { 30 bootstrapTooltip: $("[data-bs-toggle='tooltip']"), 31 bootstrapModalDialog: $('.modal'), 32 bootstrapTabs: $(".tabs-custom"), 33 rdNavbar: $(".rd-navbar"), 34 materialParallax: $(".parallax-container"), 35 rdMailForm: $(".rd-mailform"), 36 rdInputLabel: $(".form-label"), 37 regula: $("[data-constraints]"), 38 selectFilter: $("select"), 39 stepper: $("input[type='number']"), 40 wow: $(".wow"), 41 owl: $(".owl-carousel"), 42 swiper: $(".swiper-slider"), 43 slick: $('.slick-slider'), 44 search: $(".rd-search"), 45 searchResults: $('.rd-search-results'), 46 statefulButton: $('.btn-stateful'), 47 isotope: $(".isotope"), 48 popover: $('[data-bs-toggle="popover"]'), 49 viewAnimate: $('.view-animate'), 50 radio: $("input[type='radio']"), 51 checkbox: $("input[type='checkbox']"), 52 customToggle: $("[data-custom-toggle]"), 53 preloader: $(".preloader"), 54 captcha: $('.recaptcha'), 55 lightGallery: $("[data-lightgallery='group']"), 56 lightGalleryItem: $("[data-lightgallery='item']"), 57 lightDynamicGalleryItem: $("[data-lightgallery='dynamic']"), 58 mailchimp: $('.mailchimp-mailform'), 59 campaignMonitor: $('.campaign-mailform'), 60 copyrightYear: $(".copyright-year"), 61 buttonWinona: $('.button-winona'), 62 rdRange: $('.rd-range'), 63 radioPanel: $('.radio-panel .radio-inline'), 64 hoverdir: $('.hoverdir .hoverdir-item'), 65 maps: $( '.google-map-container' ), 66 counter: document.querySelectorAll( '.counter' ), 67 progressLinear: document.querySelectorAll( '.progress-linear' ), 68 countdown: document.querySelectorAll( '[data-countdown]') 69 }; 70 71 // Initialize scripts that require a loaded page 72 $window.on('load', function () { 73 // Page loader & Page transition 74 if (plugins.preloader.length && !isNoviBuilder) { 75 pageTransition({ 76 target: document.querySelector( '.page' ), 77 delay: 500, 78 duration: 500, 79 classIn: 'fadeIn', 80 classOut: 'fadeOut', 81 classActive: 'animated', 82 conditions: function (event, link) { 83 return link && !/(\#|javascript:void\(0\)|callto:|tel:|mailto:|:\/\/)/.test(link) && !event.currentTarget.hasAttribute('data-lightgallery'); 84 }, 85 onTransitionStart: function ( options ) { 86 setTimeout( function () { 87 plugins.preloader.removeClass('loaded'); 88 }, options.duration * .75 ); 89 }, 90 onReady: function () { 91 plugins.preloader.addClass('loaded'); 92 windowReady = true; 93 } 94 }); 95 } 96 97 // Isotope 98 if (plugins.isotope.length) { 99 for (var i = 0; i < plugins.isotope.length; i++) { 100 var isotopeItem = plugins.isotope[i]; 101 isotopeItem.isotope.layout(); 102 103 window.addEventListener('resize', function () { 104 setTimeout(function () { 105 isotopeItem.isotope.layout(); 106 }, 2000); 107 }); 108 } 109 } 110 111 // Progress Bar 112 if ( plugins.progressLinear ) { 113 for ( var i = 0; i < plugins.progressLinear.length; i++ ) { 114 var 115 container = plugins.progressLinear[i], 116 bar = container.querySelector('.progress-bar-linear'), 117 duration = container.getAttribute('data-duration') || 1000, 118 counter = aCounter({ 119 node: container.querySelector( '.progress-value' ), 120 duration: duration, 121 onStart: function() { 122 this.custom.bar.style.width = this.params.to + '%'; 123 } 124 });
125 126 bar.style.transitionDuration = duration / 1000 + 's'; 127 counter.custom = { 128 container: container, 129 bar: bar, 130 onScroll: (function() { 131 if ( ( Util.inViewport( this.custom.container ) && !this.custom.container.classList.contains( 'animated' ) ) || isNoviBuilder ) { 132 this.run(); 133 this.custom.container.classList.add( 'animated' ); 134 } 135 }).bind( counter ), 136 onBlur: (function() { 137 this.params.to = parseInt( this.params.node.textContent, 10 ); 138 this.run(); 139 }).bind( counter ) 140 }; 141 142 if ( isNoviBuilder ) { 143 counter.run(); 144 counter.params.node.addEventListener( 'blur', counter.custom.onBlur ); 145 } else { 146 counter.custom.onScroll(); 147 document.addEventListener( 'scroll', counter.custom.onScroll ); 148 } 149 } 150 } 151 152 // Counter 153 if ( plugins.counter ) { 154 for (let i = 0; i < plugins.counter.length; i++) { 155 let 156 node = plugins.counter[i], 157 counter = aCounter({ 158 node: node, 159 duration: node.getAttribute('data-duration') || 1000 160 }), 161 scrollHandler = (function () { 162 if (Util.inViewport(this) && !this.classList.contains('animated-first')) { 163 this.counter.run(); 164 this.classList.add('animated-first'); 165 } 166 }).bind(node), 167 blurHandler = (function () { 168 this.counter.params.to = parseInt(this.textContent, 10); 169 this.counter.run(); 170 }).bind(node); 171 172 if (isNoviBuilder) { 173 node.counter.run(); 174 node.addEventListener('blur', blurHandler); 175 } else { 176 scrollHandler(); 177 window.addEventListener('scroll', scrollHandler); 178 } 179 } 180 } 181 }); 182 183 // Initialize scripts that require a finished document 184 $(function () { 185 isNoviBuilder = window.xMode; 186 187 /** 188 * Wrapper to eliminate json errors 189 * @param {string} str - JSON string 190 * @returns {object} - parsed or empty object 191 */ 192 function parseJSON(str) { 193 try { 194 if (str) return JSON.parse(str); 195 else return {}; 196 } catch (error) { 197 console.warn(error); 198 return {}; 199 } 200 } 201 202 /** 203 * @desc Sets the actual previous index based on the position of the slide in the markup. Should be the most recent action. 204 * @param {object} swiper - swiper instance 205 */ 206 function setRealPrevious(swiper) { 207 let element = swiper.$wrapperEl[0].children[swiper.activeIndex]; 208 swiper.realPrevious = Array.prototype.indexOf.call(element.parentNode.children, element); 209 } 210 211 /** 212 * @desc Sets slides background images from attribute 'data-slide-bg' 213 * @param {object} swiper - swiper instance 214 */ 215 function setBackgrounds(swiper) { 216 let swipersBg = swiper.el.querySelectorAll('[data-slide-bg]'); 217 218 for (let i = 0; i < swipersBg.length; i++) { 219 let swiperBg = swipersBg[i]; 220 swiperBg.style.backgroundImage = 'url(' + swiperBg.getAttribute('data-slide-bg') + ')'; 221 } 222 } 223 224 /** 225 * @desc Animate captions on active slides 226 * @param {object} swiper - swiper instance 227 */ 228 function initCaptionAnimate(swiper) { 229 let 230 animate = function (caption) { 231 return function () { 232 let duration; 233 if (duration = caption.getAttribute('data-caption-duration')) caption.style.animationDuration = duration + 'ms'; 234 caption.classList.remove('not-animated'); 235 caption.classList.add(caption.getAttribute('data-caption-animate'));
236 caption.classList.add('animated'); 237 }; 238 }, 239 initializeAnimation = function (captions) { 240 for (let i = 0; i < captions.length; i++) { 241 let caption = captions[i]; 242 caption.classList.remove('animated'); 243 caption.classList.remove(caption.getAttribute('data-caption-animate')); 244 caption.classList.add('not-animated'); 245 } 246 }, 247 finalizeAnimation = function (captions) { 248 for (let i = 0; i < captions.length; i++) { 249 let caption = captions[i]; 250 if (caption.getAttribute('data-caption-delay')) { 251 setTimeout(animate(caption), Number(caption.getAttribute('data-caption-delay'))); 252 } else { 253 animate(caption)(); 254 } 255 } 256 }; 257 258 // Caption parameters 259 swiper.params.caption = { 260 animationEvent: 'slideChangeTransitionEnd' 261 }; 262 263 initializeAnimation(swiper.$wrapperEl[0].querySelectorAll('[data-caption-animate]')); 264 finalizeAnimation(swiper.$wrapperEl[0].children[swiper.activeIndex].querySelectorAll('[data-caption-animate]')); 265 266 if (swiper.params.caption.animationEvent === 'slideChangeTransitionEnd') { 267 swiper.on(swiper.params.caption.animationEvent, function () { 268 initializeAnimation(swiper.$wrapperEl[0].children[swiper.previousIndex].querySelectorAll('[data-caption-animate]')); 269 finalizeAnimation(swiper.$wrapperEl[0].children[swiper.activeIndex].querySelectorAll('[data-caption-animate]')); 270 }); 271 } else { 272 swiper.on('slideChangeTransitionEnd', function () { 273 initializeAnimation(swiper.$wrapperEl[0].children[swiper.previousIndex].querySelectorAll('[data-caption-animate]')); 274 }); 275 276 swiper.on(swiper.params.caption.animationEvent, function () { 277 finalizeAnimation(swiper.$wrapperEl[0].children[swiper.activeIndex].querySelectorAll('[data-caption-animate]')); 278 }); 279 } 280 } 281 282 /** 283 * @desc Set slides preview for navigation button 284 * @param {object} swiper - swiper slider 285 */ 286 function setSwiperNavPreview(swiper){ 287 var activeSlideIndex, slidesCount; 288 289 activeSlideIndex = swiper.activeIndex; 290 slidesCount = swiper.slides.filter(function(inx,el){return !el.classList.contains('swiper-slide-duplicate')}).length; 291 292 if( activeSlideIndex === slidesCount + 1 ){ 293 activeSlideIndex = 1; 294 }else if( activeSlideIndex === 0 ){ 295 activeSlideIndex = slidesCount; 296 } 297 //Replace btn img 298 if(swiper.$el.find('.preview__img')[0] !== undefined ){ 299 300 swiper.$el.find('.swiper-button-prev .preview__img').css("background-image", "url(" + swiper.slides[activeSlideIndex - 1].getAttribute("data-slide-bg") + ")"); 301 swiper.$el.find('.swiper-button-next .preview__img').css("background-image", "url(" + swiper.slides[activeSlideIndex + 1].getAttribute("data-slide-bg") + ")"); 302 } 303 } 304 305 /** 306 * @desc Initialize owl carousel plugin 307 * @param {object} c - carousel jQuery object 308 */ 309 function initOwlCarousel(c) { 310 var aliaces = ["-", "-sm-", "-md-", "-lg-", "-xl-", "-xxl-"], 311 values = [0, 576, 768, 992, 1200, 1600], 312 responsive = {}; 313 314 for (var j = 0; j < values.length; j++) { 315 responsive[values[j]] = {}; 316 for (var k = j; k >= -1; k--) { 317 if (!responsive[values[j]]["items"] && c.attr("data" + aliaces[k] + "items")) { 318 responsive[values[j]]["items"] = k < 0 ? 1 : parseInt(c.attr("data" + aliaces[k] + "items"), 10); 319 } 320 if (!responsive[values[j]]["stagePadding"] && responsive[values[j]]["stagePadding"] !== 0 && c.attr("data" + aliaces[k] + "stage-padding")) { 321 responsive[values[j]]["stagePadding"] = k < 0 ? 0 : parseInt(c.attr("data" + aliaces[k] + "stage-padding"), 10); 322 } 323 if (!responsive[values[j]]["margin"] && responsive[values[j]]["margin"] !== 0 && c.attr("data" + aliaces[k] + "margin")) { 324 responsive[values[j]]["margin"] = k < 0 ? 30 : parseInt(c.attr("data" + aliaces[k] + "margin"), 10); 325 } 326 } 327 } 328 329 // Enable custom pagination 330 if (c.attr('data-dots-custom')) { 331 c.on("initialized.owl.carousel", function (event) { 332 var carousel = $(event.currentTarget),
333 customPag = $(carousel.attr("data-dots-custom")), 334 active = 0; 335 336 if (carousel.attr('data-active')) { 337 active = parseInt(carousel.attr('data-active'), 10); 338 } 339 340 carousel.trigger('to.owl.carousel', [active, 300, true]); 341 customPag.find("[data-owl-item='" + active + "']").addClass("active"); 342 343 customPag.find("[data-owl-item]").on('click', function (e) { 344 e.preventDefault(); 345 carousel.trigger('to.owl.carousel', [parseInt(this.getAttribute("data-owl-item"), 10), 300, true]); 346 }); 347 348 carousel.on("translate.owl.carousel", function (event) { 349 customPag.find(".active").removeClass("active"); 350 customPag.find("[data-owl-item='" + event.item.index + "']").addClass("active") 351 }); 352 }); 353 } 354 355 c.on("initialized.owl.carousel", function () { 356 initLightGalleryItem(c.find('[data-lightgallery="item"]'), 'lightGallery-in-carousel'); 357 }); 358 359 // Create custom Numbering 360 if (typeof(c.attr("data-numbering")) !== 'undefined') { 361 var numberingObject = $(c.attr("data-numbering")); 362 363 c.on('initialized.owl.carousel changed.owl.carousel', function (numberingObject) { 364 return function (e) { 365 if (!e.namespace) return; 366 if (isNoviBuilder ? false : c.attr("data-loop") !== "false") { 367 var tempFix = (e.item.index + 1) - (e.relatedTarget.clones().length / 2); 368 if (tempFix > 0) { 369 numberingObject.find('.numbering-current').text(tempFix > e.item.count ? tempFix % e.item.count : tempFix); 370 } else { 371 numberingObject.find('.numbering-current').text(e.item.index + 1); 372 } 373 } else { 374 numberingObject.find('.numbering-current').text(e.item.index + 1); 375 } 376 377 numberingObject.find('.numbering-count').text(e.item.count); 378 }; 379 }(numberingObject)); 380 } 381 382 c.owlCarousel({ 383 autoplay: isNoviBuilder ? false : c.attr("data-autoplay") === "true", 384 loop: isNoviBuilder ? false : c.attr("data-loop") !== "false", 385 items: 1, 386 merge: true, 387 center: c.attr("data-center") === "true", 388 dotsContainer: c.attr("data-pagination-class") || false, 389 navContainer: c.attr("data-navigation-class") || false, 390 mouseDrag: isNoviBuilder ? false : c.attr("data-mouse-drag") !== "false", 391 nav: c.attr("data-nav") === "true", 392 dots: c.attr("data-dots") === "true", 393 dotsEach: c.attr("data-dots-each") ? parseInt(c.attr("data-dots-each"), 10) : false, 394 animateIn: c.attr('data-animation-in') ? c.attr('data-animation-in') : false, 395 animateOut: c.attr('data-animation-out') ? c.attr('data-animation-out') : false, 396 responsive: responsive, 397 smartSpeed: c.attr('data-smart-speed') ? c.attr('data-smart-speed') : 250, 398 navText: function () { 399 try { 400 return JSON.parse(c.attr("data-nav-text")); 401 } catch (e) { 402 return []; 403 } 404 }(), 405 navClass: function () { 406 try { 407 return JSON.parse(c.attr("data-nav-class")); 408 } catch (e) { 409 return ['owl-prev', 'owl-next']; 410 } 411 }() 412 }); 413 } 414 415 /** 416 * @desc Check the element whas been scrolled into the view 417 * @param {object} elem - jQuery object 418 * @return {boolean} 419 */ 420 function isScrolledIntoView(elem) { 421 if (!isNoviBuilder) { 422 return elem.offset().top + elem.outerHeight() >= $window.scrollTop() && elem.offset().top <= $window.scrollTop() + $window.height(); 423 } 424 else { 425 return true; 426 } 427 } 428 429 /** 430 * @desc Calls a function when element has been scrolled into the view 431 * @param {object} element - jQuery object 432 * @param {function} func - callback function 433 */ 434 function lazyInit(element, func) { 435 $document.on('scroll', function () { 436 if ((!element.hasClass('lazy-loaded') && (isScrolledIntoView(element)))) { 437 func.call(); 438 element.addClass('lazy-loaded'); 439 } 440 }).trigger("scroll"); 441 } 442 443 /** 444 * @desc Create live search results 445 * @param {object} options 446 */ 447 function liveSearch(options) { 448 $('#' + options.live).removeClass('cleared').html(); 449 options.current++; 450 options.spin.addClass('loading'); 451 $.get(handler, {
452 s: decodeURI(options.term), 453 liveSearch: options.live, 454 dataType: "html", 455 liveCount: options.liveCount, 456 filter: options.filter, 457 template: options.template 458 }, function (data) { 459 options.processed++; 460 var live = $('#' + options.live); 461 if ((options.processed === options.current) && !live.hasClass('cleared')) { 462 live.find('> #search-results').removeClass('active'); 463 live.html(data); 464 setTimeout(function () { 465 live.find('> #search-results').addClass('active'); 466 }, 50); 467 } 468 options.spin.parents('.rd-search').find('.input-group-addon').removeClass('loading'); 469 }) 470 } 471 472 /** 473 * @desc Attach form validation to elements 474 * @param {object} elements - jQuery object 475 */ 476 function attachFormValidator(elements) { 477 // Custom validator - phone number 478 regula.custom({ 479 name: 'PhoneNumber', 480 defaultMessage: 'Invalid phone number format', 481 validator: function () { 482 if (this.value === '') return true; 483 else return /^(\+\d)?[0-9\-\(\) ]{5,}$/i.test(this.value); 484 } 485 }); 486 487 for (var i = 0; i < elements.length; i++) { 488 var o = $(elements[i]), v; 489 o.addClass("form-control-has-validation").after("<span class='form-validation'></span>"); 490 v = o.parent().find(".form-validation"); 491 if (v.is(":last-child")) o.addClass("form-control-last-child"); 492 } 493 494 elements.on('input change propertychange blur', function (e) { 495 var $this = $(this), results; 496 497 if (e.type !== "blur") if (!$this.parent().hasClass("has-error")) return; 498 if ($this.parents('.rd-mailform').hasClass('success')) return; 499 500 if ((results = $this.regula('validate')).length) { 501 for (i = 0; i < results.length; i++) { 502 $this.siblings(".form-validation").text(results[i].message).parent().addClass("has-error"); 503 } 504 } else { 505 $this.siblings(".form-validation").text("").parent().removeClass("has-error") 506 } 507 }).regula('bind'); 508 509 var regularConstraintsMessages = [ 510 { 511 type: regula.Constraint.Required, 512 newMessage: "The text field is required." 513 }, 514 { 515 type: regula.Constraint.Email, 516 newMessage: "The email is not a valid email." 517 }, 518 { 519 type: regula.Constraint.Numeric, 520 newMessage: "Only numbers are required" 521 }, 522 { 523 type: regula.Constraint.Selected, 524 newMessage: "Please choose an option." 525 } 526 ]; 527 528 529 for (var i = 0; i < regularConstraintsMessages.length; i++) { 530 var regularConstraint = regularConstraintsMessages[i]; 531 532 regula.override({ 533 constraintType: regularConstraint.type, 534 defaultMessage: regularConstraint.newMessage 535 }); 536 } 537 } 538 539 /** 540 * @desc Check if all elements pass validation 541 * @param {object} elements - object of items for validation 542 * @param {object} captcha - captcha object for validation 543 * @return {boolean} 544 */ 545 function isValidated(elements, captcha) { 546 var results, errors = 0; 547 548 if (elements.length) { 549 for (var j = 0; j < elements.length; j++) { 550 551 var $input = $(elements[j]); 552 if ((results = $input.regula('validate')).length) { 553 for (k = 0; k < results.length; k++) { 554 errors++; 555 $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error"); 556 } 557 } else { 558 $input.siblings(".form-validation").text("").parent().removeClass("has-error") 559 } 560 } 561 562 if (captcha) { 563 if (captcha.length) { 564 return validateReCaptcha(captcha) && errors === 0 565 } 566 } 567 568 return errors === 0; 569 } 570 return true; 571 } 572 573 /** 574 * @desc Validate google reCaptcha 575 * @param {object} captcha - captcha object for validation 576 * @return {boolean} 577 */ 578 function validateReCaptcha(captcha) { 579 var captchaToken = captcha.find('.g-recaptcha-response').val(); 580 581 if (captchaToken.length === 0) { 582 captcha 583 .siblings('.form-validation') 584 .html('Please, prove that you are not robot.') 585 .addClass('active'); 586 captcha 587 .closest('.form-wrap') 588 .addClass('has-error'); 589 590 captcha.on('propertychange', function () { 591 var $this = $(this), 592 captchaToken = $this.find('.g-recaptcha-response').val(); 593 594 if (captchaToken.length > 0) { 595 $this 596 .closest('.form-wrap') 597 .removeClass('has-error'); 598 $this 599 .siblings('.form-validation') 600 .removeClass('active') 601 .html(''); 602 $this.off('propertychange'); 603 } 604 }); 605 606 return false; 607 } 608 609 return true; 610 } 611 612 /** 613 * @desc Initialize Google reCaptcha 614 */ 615 window.onloadCaptchaCallback = function () { 616 for (var i = 0; i < plugins.captcha.length; i++) { 617 var $capthcaItem = $(plugins.captcha[i]); 618 619 grecaptcha.render( 620 $capthcaItem.attr('id'), 621 { 622 sitekey: $capthcaItem.attr('data-sitekey'), 623 size: $capthcaItem.attr('data-size') ? $capthcaItem.attr('data-size') : 'normal', 624 theme: $capthcaItem.attr('data-theme') ? $capthcaItem.attr('data-theme') : 'light', 625 callback: function (e) { 626 $('.recaptcha').trigger('propertychange'); 627 } 628 } 629 ); 630 $capthcaItem.after("<span class='form-validation'></span>"); 631 } 632 }; 633 634 /** 635 * @desc Initialize Bootstrap tooltip with required placement 636 * @param {string} tooltipPlacement 637 */ 638 function initBootstrapTooltip(tooltipPlacement) { 639 plugins.bootstrapTooltip.tooltip('dispose'); 640 641 if (window.innerWidth < 576) { 642 plugins.bootstrapTooltip.tooltip({placement: 'bottom'}); 643 } else { 644 plugins.bootstrapTooltip.tooltip({placement: tooltipPlacement}); 645 } 646 } 647 648 /** 649 * @desc Initialize the gallery with set of images 650 * @param {object} itemsToInit - jQuery object 651 * @param {string} addClass - additional gallery class 652 */ 653 function initLightGallery(itemsToInit, addClass) { 654 if (!isNoviBuilder) { 655 $(itemsToInit).lightGallery({ 656 thumbnail: $(itemsToInit).attr("data-lg-thumbnail") !== "fal
656se", 657 selector: "[data-lightgallery='item']", 658 autoplay: $(itemsToInit).attr("data-lg-autoplay") === "true", 659 pause: parseInt($(itemsToInit).attr("data-lg-autoplay-delay")) || 5000, 660 addClass: addClass, 661 mode: $(itemsToInit).attr("data-lg-animation") || "lg-slide", 662 loop: $(itemsToInit).attr("data-lg-loop") !== "false" 663 }); 664 } 665 } 666 667 /** 668 * @desc Initialize the gallery with dynamic addition of images 669 * @param {object} itemsToInit - jQuery object 670 * @param {string} addClass - additional gallery class 671 */ 672 function initDynamicLightGallery(itemsToInit, addClass) { 673 if (!isNoviBuilder) { 674 $(itemsToInit).on("click", function () { 675 $(itemsToInit).lightGallery({ 676 thumbnail: $(itemsToInit).attr("data-lg-thumbnail") !== "false", 677 selector: "[data-lightgallery='item']", 678 autoplay: $(itemsToInit).attr("data-lg-autoplay") === "true", 679 pause: parseInt($(itemsToInit).attr("data-lg-autoplay-delay")) || 5000, 680 addClass: addClass, 681 mode: $(itemsToInit).attr("data-lg-animation") || "lg-slide", 682 loop: $(itemsToInit).attr("data-lg-loop") !== "false", 683 dynamic: true, 684 dynamicEl: JSON.parse($(itemsToInit).attr("data-lg-dynamic-elements")) || [] 685 }); 686 }); 687 } 688 } 689 690 /** 691 * @desc Initialize the gallery with one image 692 * @param {object} itemToInit - jQuery object 693 * @param {string} addClass - additional gallery class 694 */ 695 function initLightGalleryItem(itemToInit, addClass) { 696 if (!isNoviBuilder) { 697 $(itemToInit).lightGallery({ 698 selector: "this", 699 addClass: addClass, 700 counter: false, 701 youtubePlayerParams: { 702 modestbranding: 1, 703 showinfo: 0, 704 rel: 0, 705 controls: 0 706 }, 707 vimeoPlayerParams: { 708 byline: 0, 709 portrait: 0 710 } 711 }); 712 } 713 } 714 715 /** 716 * @desc Google map function for getting latitude and longitude 717 */ 718 function getLatLngObject(str, marker, map, callback) { 719 var coordinates = {}; 720 try { 721 coordinates = JSON.parse(str); 722 callback(new google.maps.LatLng( 723 coordinates.lat, 724 coordinates.lng 725 ), marker, map) 726 } catch (e) { 727 map.geocoder.geocode({'address': str}, function (results, status) { 728 if (status === google.maps.GeocoderStatus.OK) { 729 var latitude = results[0].geometry.location.lat(); 730 var longitude = results[0].geometry.location.lng(); 731 732 callback(new google.maps.LatLng( 733 parseFloat(latitude), 734 parseFloat(longitude) 735 ), marker, map) 736 } 737 }) 738 } 739 } 740 741 /** 742 * @desc Initialize Google maps 743 */ 744 function initMaps() { 745 var key; 746 747 for ( var i = 0; i < plugins.maps.length; i++ ) { 748 if ( plugins.maps[i].hasAttribute( "data-key" ) ) { 749 key = plugins.maps[i].getAttribute( "data-key" ); 750 break; 751 } 752 } 753 754 $.getScript('//maps.google.com/maps/api/js?'+ ( key ? 'key='+ key + '&' : '' ) +'sensor=false&libraries=geometry,places&v=quarterly', function () { 755 var geocoder = new google.maps.Geocoder; 756 for (var i = 0; i < plugins.maps.length; i++) { 757 var zoom = parseInt(plugins.maps[i].getAttribute("data-zoom"), 10) || 11; 758 var styles = plugins.maps[i].hasAttribute('data-styles') ? JSON.parse(plugins.maps[i].getAttribute("data-styles")) : []; 759 var center = plugins.maps[i].getAttribute("data-center") || "New York"; 760 761 // Initialize map 762 var map = new google.maps.Map(plugins.maps[i].querySelectorAll(".google-map")[0], { 763 zoom: zoom, 764 styles: styles, 765 scrollwheel: false, 766 center: {lat: 0, lng: 0} 767 }); 768 769 // Add map object to map node 770 plugins.maps[i].map = map; 771 plugins.maps[i].geocoder = geocoder; 772 plugins.maps[i].keySupported = true; 773 plugins.maps[i].google = google; 774 775 // Get Center coordinates from attribute 776 getLatLngObject(center, null, plugins.maps[i], function (location, markerElement, mapElement) { 777 mapElement.map.setCenter(location); 778 }); 779 780 // Add markers from google-map-markers array 781 var markerItems = plugins.maps[i].querySelectorAll(".google-map-markers li"); 782 if (markerItems.length){ 783 var markers = []; 784 for (var j = 0; j < markerItems.length; j++){ 785 786 var markerElement = markerItems[j];
787 getLatLngObject(markerElement.getAttribute("data-location"), markerElement, plugins.maps[i], function(location, markerElement, mapElement){ 788 var icon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon"); 789 var activeIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active"); 790 var info = markerElement.getAttribute("data-description") || ""; 791 var infoImg = markerElement.getAttribute("data-img"); 792 var contentString = '<div class="map-info-window">'+ (infoImg ? `<img class='map-info-img' src="${infoImg}" alt> ` : '') + `<div class="map-info-text">${info}</div>` + '</div>'; 793 794 var infoWindow = new google.maps.InfoWindow({ 795 content: contentString, 796 maxWidth: 385 797 }); 798 markerElement.infoWindow = infoWindow; 799 var markerData = { 800 position: location, 801 map: mapElement.map 802 } 803 if (icon){ 804 markerData.icon = icon; 805 } 806 var marker = new google.maps.Marker(markerData); 807 markerElement.gmarker = marker; 808 markers.push({markerElement: markerElement, infoWindow: infoWindow}); 809 marker.isActive = false; 810 // Handle infoWindow close click 811 google.maps.event.addListener(infoWindow,'closeclick',(function(markerElement, mapElement){ 812 var markerIcon = null; 813 markerElement.gmarker.isActive = false; 814 markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon"); 815 markerElement.gmarker.setIcon(markerIcon); 816 }).bind(this, markerElement, mapElement)); 817 818 819 // Set marker active on Click and open infoWindow 820 google.maps.event.addListener(marker, 'click', (function(markerElement, mapElement) { 821 if (markerElement.infoWindow.getContent().length === 0) return; 822 var gMarker, currentMarker = markerElement.gmarker, currentInfoWindow; 823 for (var k =0; k < markers.length; k++){ 824 var markerIcon; 825 if (markers[k].markerElement === markerElement){ 826 currentInfoWindow = markers[k].infoWindow; 827 } 828 gMarker = markers[k].markerElement.gmarker; 829 if (gMarker.isActive && markers[k].markerElement !== markerElement){ 830 gMarker.isActive = false; 831 markerIcon = markers[k].markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon") 832 gMarker.setIcon(markerIcon); 833 markers[k].infoWindow.close(); 834 } 835 } 836 837 currentMarker.isActive = !currentMarker.isActive; 838 if (currentMarker.isActive) { 839 if (markerIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active")){ 840 currentMarker.setIcon(markerIcon); 841 } 842 843 currentInfoWindow.open(map, marker); 844 }else{ 845 if (markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon")){ 846 currentMarker.setIcon(markerIcon); 847 } 848 currentInfoWindow.close(); 849 } 850 }).bind(this, markerElement, mapElement)) 851 }) 852 } 853 } 854 } 855 }); 856 } 857 858 /** 859 * @desc Initialize the direction-aware hover 860 * @param {object} elements - jQuery object 861 */ 862 function initHoverDir(elements) { 863 if (!isNoviBuilder && isDesktop) { 864 for (var z = 0; z < elements.length; z++) { 865 var $element = $(elements[z]); 866 867 $element.hoverdir({ 868 hoverElem: $element.attr('data-hoverdir-target') ? $element.attr('data-hoverdir-target') : 'div' 869 } 870 ); 871 } 872 } 873 } 874 875 // Google ReCaptcha 876 if (plugins.captcha.length) { 877 $.getScript("//www.google.com/recaptcha/api.js?onload=onloadCaptchaCallback&render=explicit&hl=en"); 878 } 879 880 // Additional class on html if mac os. 881 if (navigator.platform.match(/(Mac)/i)) { 882 $html.addClass("mac-os"); 883 } 884 885 // Adds some loosing functionality to IE browsers (IE Polyfills) 886 if (isIE) { 887 if (isIE === 12) $html.addClass("ie-edge"); 888 if (isIE === 11) $html.addClass("ie-11"); 889 if (isIE < 10) $html.addClass("lt-ie-10"); 890 if (isIE < 11) $html.addClass("ie-10"); 891 } 892 893 // Bootstrap Tooltips 894 if (plugins.bootstrapTooltip.length) { 895 var tooltipPlacement = plugins.bootstrapTooltip.attr('data-bs-placement'); 896 initBootstrapTooltip(tooltipPlacement); 897 898 $window.on('resize orientationchange', function () { 899 initBootstrapTooltip(tooltipPlacement); 900 }) 901 } 902 903 // Stop vioeo in bootstrapModalDialog 904 if (plugins.bootstrapModalDialog.length) { 905 for (var i = 0; i < plugins.bootstrapModalDialog.length; i++) { 906 var modalItem = $(plugins.bootstrapModalDialog[i]); 907 908 modalItem.on('hidden.bs.modal', $.proxy(function () { 909 var activeModal = $(this), 910 rdVideoInside = activeModal.find('video'), 911 youTubeVideoInside = activeModal.find('iframe'); 912 913 if (rdVideoInside.length) { 914 rdVideoInside[0].pause(); 915 } 916 917 if (youTubeVideoInside.length) { 918 var videoUrl = youTubeVideoInside.attr('src'); 919 920 youTubeVideoInside 921 .attr('src', '') 922 .attr('src', videoUrl); 923 } 924 }, modalItem)) 925 } 926 } 927 928 // Popovers 929 if (plugins.popover.length) { 930 if (window.innerWidth < 767) { 931 plugins.popover.attr('data-bs-placement', 'bottom'); 932 plugins.popover.popover(); 933 } 934 else { 935 plugins.popover.popover(); 936 } 937 } 938 939 // Bootstrap Buttons 940 if (plugins.statefulButton.length) { 941 $(plugins.statefulButton).on('click', function () { 942 var statefulButtonLoading = $(this).button('loading'); 943 944 setTimeout(function () { 945 statefulButtonLoading.button('reset') 946 }, 2000); 947 }) 948 } 949 950 // Bootstrap tabs 951 if (plugins.bootstrapTabs.length) { 952 for (var i = 0; i < plugins.bootstrapTabs.length; i++) { 953 var bootstrapTabsItem = $(plugins.bootstrapTabs[i]); 954 955 //If have slick carousel inside tab - resize slick carousel on click 956 if (bootstrapTabsItem.find('.slick-slider').length) { 957 bootstrapTabsItem.find('.tabs-custom-list > li > a').on('click', $.proxy(function () { 958 var $this = $(this); 959 var setTimeOutTime = isNoviBuilder ? 1500 : 300; 960 961 setTimeout(function () { 962 $this.find('.tab-content .tab-pane.active .slick-slider').slick('setPosition'); 963 }, setTimeOutTime); 964 }, bootstrapTabsItem)); 965 } 966 967 if (bootstrapTabsItem.attr('data-view-triggerable') === 'true') { 968 (function (bootstrapTabsItem) { 969 bootstrapTabsItem.on('shown.bs.tab', function (event) { 970 var prevTriggerable = bootstrapTabsItem.find('[data-view-trigger="' + event.relatedTarget.getAttribute('href') + '"]'), 971 triggerable = bootstrapTabsItem.find('[data-view-trigger="' + event.target.getAttribute('href') + '"]'); 972 973 prevTriggerable.removeClass('active'); 974 triggerable.addClass('active'); 975 });
976 977 })(bootstrapTabsItem); 978 } 979 } 980 } 981 982 // Copyright Year (Evaluates correct copyright year) 983 if (plugins.copyrightYear.length) { 984 plugins.copyrightYear.text(initialDate.getFullYear()); 985 } 986 987 // Google maps 988 if( plugins.maps.length ) { 989 lazyInit( plugins.maps, initMaps ); 990 } 991 992 // Add custom styling options for input[type="radio"] 993 if (plugins.radio.length) { 994 for (var i = 0; i < plugins.radio.length; i++) { 995 $(plugins.radio[i]).addClass("radio-custom").after("<span class='radio-custom-dummy'></span>") 996 } 997 } 998 999 // Add custom styling options for input[type="checkbox"] 1000 if (plugins.checkbox.length) { 1001 for (var i = 0; i < plugins.checkbox.length; i++) { 1002 $(plugins.checkbox[i]).addClass("checkbox-custom").after("<span class='checkbox-custom-dummy'></span>") 1003 } 1004 } 1005 1006 // UI To Top 1007 if (isDesktop && !isNoviBuilder) { 1008 $().UItoTop({ 1009 easingType: 'easeOutQuad', 1010 containerClass: 'ui-to-top mdi mdi-arrow-up' 1011 }); 1012 } 1013 1014 // RD Navbar 1015 if (plugins.rdNavbar.length) { 1016 var aliaces, i, j, len, value, values, responsiveNavbar; 1017 1018 aliaces = ["-", "-sm-", "-md-", "-lg-", "-xl-", "-xxl-"]; 1019 values = [0, 576, 768, 992, 1200, 1600]; 1020 responsiveNavbar = {}; 1021 1022 for (i = j = 0, len = values.length; j < len; i = ++j) { 1023 value = values[i]; 1024 if (!responsiveNavbar[values[i]]) { 1025 responsiveNavbar[values[i]] = {}; 1026 } 1027 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'layout')) { 1028 responsiveNavbar[values[i]].layout = plugins.rdNavbar.attr('data' + aliaces[i] + 'layout'); 1029 } 1030 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'device-layout')) { 1031 responsiveNavbar[values[i]]['deviceLayout'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'device-layout'); 1032 } 1033 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'hover-on')) { 1034 responsiveNavbar[values[i]]['focusOnHover'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'hover-on') === 'true'; 1035 } 1036 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'auto-height')) { 1037 responsiveNavbar[values[i]]['autoHeight'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'auto-height') === 'true'; 1038 } 1039 1040 if (isNoviBuilder) { 1041 responsiveNavbar[values[i]]['stickUp'] = false; 1042 } else if (plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up')) { 1043 responsiveNavbar[values[i]]['stickUp'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up') === 'true'; 1044 } 1045 1046 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up-offset')) { 1047 responsiveNavbar[values[i]]['stickUpOffset'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up-offset'); 1048 } 1049 } 1050 1051 1052 plugins.rdNavbar.RDNavbar({ 1053 anchorNav: !isNoviBuilder, 1054 stickUpClone: (plugins.rdNavbar.attr("data-stick-up-clone") && !isNoviBuilder) ? plugins.rdNavbar.attr("data-stick-up-clone") === 'true' : false, 1055 responsive: responsiveNavbar, 1056 callbacks: { 1057 onStuck: function () { 1058 var navbarSearch = this.$element.find('.rd-search input'); 1059 1060 if (navbarSearch) { 1061 navbarSearch.val('').trigger('propertychange'); 1062 } 1063 }, 1064 onDropdownOver: function () { 1065 return !isNoviBuilder; 1066 }, 1067 onUnstuck: function () { 1068 if (this.$clone === null) 1069 return; 1070 1071 var navbarSearch = this.$clone.find('.rd-search input'); 1072 1073 if (navbarSearch) { 1074 navbarSearch.val('').trigger('propertychange'); 1075 navbarSearch.trigger('blur'); 1076 } 1077 1078 } 1079 } 1080 }); 1081 1082 1083 if (plugins.rdNavbar.attr("data-body-class")) { 1084 document.body.className += ' ' + plugins.rdNavbar.attr("data-body-class"); 1085 } 1086 } 1087 1088 // RD Search 1089 if (plugins.search.length || plugins.searchResults) { 1090 var handler = "bat/rd-search.php"; 1091 var defaultTemplate = '<h5 class="search-title"><a target="_top" href="#{href}" class="search-link">#{title}</a></h5>' + 1092 '<p>...#{token}...</p>' + 1093 '<p class="match"><em>Terms matched: #{count} - URL: #{href}</em></p>'; 1094 var defaultFilter = '*.html'; 1095 1096 if (plugins.search.length) { 1097 for (var i = 0; i < plugins.search.length; i++) { 1098 var searchItem = $(plugins.search[i]), 1099 options = { 1100 element: searchItem, 1101 filter: (searchItem.attr('data-search-filter')) ? searchItem.attr('data-search-filter') : defaultFilter, 1102 template: (searchItem.attr('data-search-template')) ? searchItem.attr('data-search-template') : defaultTemplate, 1103 live: (searchItem.attr('data-search-live')) ? searchItem.attr('data-search-live') : false, 1104 liveCount: (searchItem.attr('data-search-live-count')) ? parseInt(searchItem.attr('data-search-live'), 10) : 4, 1105 current: 0, processed: 0, timer: {} 1106 }; 1107 1108 var $toggle = $('.rd-navbar-search-toggle'); 1109 if ($toggle.length) { 1110 $toggle.on('click', (function (searchItem) { 1111 return function () { 1112 if (!($(this).hasClass('active'))) { 1113 searchItem.find('input').val('').trigger('propertychange'); 1114 } 1115 } 1116 })(searchItem)); 1117 } 1118 1119 if (options.live) { 1120 var clearHandler = false; 1121 1122 searchItem.find('input').on("input propertychange", $.proxy(function () { 1123 this.term = this.element.find('input').val().trim(); 1124 this.spin = this.element.find('.input-group-addon'); 1125 1126 clearTimeout(this.timer); 1127 1128 if (this.term.length > 2) { 1129 this.timer = setTimeout(liveSearch(this), 200); 1130 1131 if (clearHandler === false) { 1132 clearHandler = true; 1133 1134 $body.on("click", function (e) { 1135 if ($(e.toElement).parents('.rd-search').length === 0) { 1136 $('#rd-search-results-live').addClass('cleared').html(''); 1137 } 1138 }) 1139 } 1140 1141 } else if (this.term.length === 0) { 1142 $('#' + this.live).addClass('cleared').html(''); 1143 } 1144 }, options, this)); 1145 } 1146 1147 searchItem.submit($.proxy(function () { 1148 $('<input />').attr('type', 'hidden') 1149 .attr('name', "filter") 1150 .attr('value', this.filter) 1151 .appendTo(this.element); 1152 return true; 1153 }, options, this)) 1154 } 1155 } 1156 1157 if (plugins.searchResults.length) { 1158 var regExp = /\?.*s=([^&]+)\&filter=([^&]+)/g; 1159 var match = regExp.exec(location.search); 1160 1161 if (match !== null) { 1162 $.get(handler, {
1163 s: decodeURI(match[1]), 1164 dataType: "html", 1165 filter: match[2], 1166 template: defaultTemplate, 1167 live: '' 1168 }, function (data) { 1169 plugins.searchResults.html(data); 1170 }) 1171 } 1172 } 1173 } 1174 1175 // Add class in viewport 1176 if (plugins.viewAnimate.length) { 1177 for (var i = 0; i < plugins.viewAnimate.length; i++) { 1178 var $view = $(plugins.viewAnimate[i]).not('.active'); 1179 $document.on("scroll", $.proxy(function () { 1180 if (isScrolledIntoView(this)) { 1181 this.addClass("active"); 1182 } 1183 }, $view)) 1184 .trigger("scroll"); 1185 } 1186 } 1187 1188 // Swiper 1189 if (plugins.swiper.length) { 1190 for (let i = 0; i < plugins.swiper.length; i++) { 1191 let 1192 node = plugins.swiper[i], 1193 pagination = node.querySelector('.swiper-pagination'), 1194 params = parseJSON(node.getAttribute('data-swiper')), 1195 defaults = { 1196 speed: 1000, 1197 loop: true, 1198 pagination: { 1199 el: '.swiper-pagination', 1200 clickable: true 1201 }, 1202 navigation: { 1203 nextEl: '.swiper-button-next', 1204 prevEl: '.swiper-button-prev' 1205 }, 1206 autoplay: false 1207 }, 1208 xMode = { 1209 autoplay: false, 1210 loop: false, 1211 simulateTouch: false 1212 }; 1213 if( pagination && pagination.getAttribute('data-bullet-custom')) { 1214 defaults.pagination.renderBullet = function (index, className) { 1215 return '<span class="' + className + '">' + 1216 ' <svg width="100%" height="100%" viewbox="0 0 24 24">' + 1217 ' <circle class="swiper-bullet-line" cx="12" cy="12" r="10"></circle>' + 1218 ' <circle class="swiper-bullet-line-2" cx="12" cy="12" r="10"></circle>' + 1219 ' </svg>' + 1220 '</span>'; 1221 } 1222 } 1223 1224 params.on = { 1225 init: function () { 1226 setBackgrounds(this); 1227 setRealPrevious(this); 1228 initCaptionAnimate(this); 1229 1230 var $swiper = $(node); 1231 1232 var swiperCustomIndex = $swiper.find('.swiper-pagination__fraction-index').get(0), 1233 swiperCustomCount = $swiper.find('.swiper-pagination__fraction-count').get(0); 1234 1235 if (swiperCustomIndex && swiperCustomCount) { 1236 swiperCustomIndex.innerHTML = formatIndex(this.realIndex + 1); 1237 if (swiperCustomCount) { 1238 swiperCustomCount.innerHTML = formatIndex($(this.slides).not(".swiper-slide-duplicate").length); 1239 } 1240 } 1241 1242 // Real Previous Index must be set recent 1243 this.on('slideChangeTransitionEnd', function () { 1244 setRealPrevious(this); 1245 }); 1246 }, 1247 slideChangeTransitionStart: function(){ 1248 setSwiperNavPreview(this); 1249 1250 var swiperCustomIndex = $(node).find('.swiper-pagination__fraction-index').get(0); 1251 var activeSlideIndex, slidesCount; 1252 1253 if (swiperCustomIndex) { 1254 swiperCustomIndex.innerHTML = formatIndex(this.realIndex + 1); 1255 } 1256 1257 activeSlideIndex = this.activeIndex; 1258 slidesCount = $(this.slides).not(".swiper-slide-duplicate").length; 1259 1260 if (activeSlideIndex === slidesCount + 1) { 1261 activeSlideIndex = 1; 1262 } else if (activeSlideIndex === 0) { 1263 activeSlideIndex = slidesCount; 1264 } 1265 if ($(this.slides)[activeSlideIndex - 1].getAttribute("data-slide-title")) { 1266 $(this.container).find('.swiper-button-next .title')[0].innerHTML = $(this.slides)[activeSlideIndex + 1267 1].getAttribute("data-slide-title"); 1268 $(this.container).find('.swiper-button-prev .title')[0].innerHTML = $(this.slides)[activeSlideIndex - 1269 1].getAttribute("data-slide-title"); 1270 } 1271 1272 if ($(this.slides)[activeSlideIndex - 1].getAttribute("data-slide-subtitle")) { 1273 $(this.container).find('.swiper-button-prev .subtitle')[0].innerHTML = $(this.slides)[activeSlideIndex - 1274 1].getAttribute("data-slide-subtitle"); 1275 $(this.container).find('.swiper-button-next .subtitle')[0].innerHTML = $(this.slides)[activeSlideIndex + 1276 1].getAttribute("data-slide-subtitle"); 1277 } 1278 } 1279 }; 1280 new Swiper(node, Util.merge(isNoviBuilder ? [defaults, params, xMode] : [defaults, params])); 1281 } 1282 } 1283 1284 function formatIndex(index) { 1285 return index < 10 ? '0' + index : index; 1286 } 1287 1288 // Owl carousel 1289 if (plugins.owl.length) { 1290 for (var i = 0; i < plugins.owl.length; i++) { 1291 var c = $(plugins.owl[i]); 1292 plugins.owl[i].owl = c; 1293 1294 initOwlCarousel(c); 1295 } 1296 } 1297 1298 // Isotope 1299 if (plugins.isotope.length) { 1300 var isogroup = []; 1301 for (var i = 0; i < plugins.isotope.length; i++) { 1302 var isotopeItem = plugins.isotope[i], 1303 isotopeInitAttrs = { 1304 itemSelector: '.isotope-item', 1305 layoutMode: isotopeItem.getAttribute('data-isotope-layout') ? isotopeItem.getAttribute('data-isotope-layout') : 'masonry', 1306 filter: '*' 1307 }; 1308 1309 var iso = new Isotope(isotopeItem, isotopeInitAttrs); 1310 isotopeItem.isotope = iso; 1311 isogroup.push(iso); 1312 } 1313 1314 $("[data-isotope-filter]").on("click", function (e) { 1315 e.preventDefault(); 1316 var filter = $(this); 1317 1318 filter.parents(".isotope-filters").find('.active').removeClass("active"); 1319 filter.addClass("active"); 1320 var iso = $('.isotope[data-isotope-group="' + this.getAttribute("data-isotope-group") + '"]'), 1321 isotopeAttrs = { 1322 itemSelector: '.isotope-item', 1323 layoutMode: iso.attr('data-isotope-layout') ? iso.attr('data-isotope-layout') : 'masonry', 1324 filter: this.getAttribute("data-isotope-filter") === '*' ? '*' : '[data-filter*="' + this.getAttribute("data-isotope-filter") + '"]' 1325 }; 1326 1327 iso.isotope(isotopeAttrs); 1328 }).eq(0).trigger("click") 1329 } 1330 1331 // WOW 1332 if ($html.hasClass("wow-animation") && plugins.wow.length && !isNoviBuilder && isDesktop) { 1333 new WOW().init(); 1334 } 1335 1336 // RD Input Label 1337 if (plugins.rdInputLabel.length) { 1338 plugins.rdInputLabel.RDInputLabel(); 1339 } 1340 1341 // Regula 1342 if (plugins.regula.length) { 1343 attachFormValidator(plugins.regula); 1344 } 1345 1346 // MailChimp Ajax subscription 1347 if (plugins.mailchimp.length) { 1348 for (i = 0; i < plugins.mailchimp.length; i++) { 1349 var $mailchimpItem = $(plugins.mailchimp[i]), 1350 $email = $mailchimpItem.find('input[type="email"]'); 1351 1352 // Required by MailChimp 1353 $mailchimpItem.attr('novalidate', 'true'); 1354 $email.attr('name', 'EMAIL'); 1355 1356 $mailchimpItem.on('submit', $.proxy(function ($email, event) { 1357 event.preventDefault(); 1358 1359 var $this = this; 1360 1361 var data = {}, 1362 url = $this.attr('action').replace('/post?', '/post-json?').concat('&c=?'), 1363 dataArray = $this.serializeArray(), 1364 $output = $("#" + $this.attr("data-form-output")); 1365 1366 for (i = 0; i < dataArray.length; i++) { 1367 data[dataArray[i].name] = dataArray[i].value; 1368 } 1369 1370 $.ajax({
1371 data: data, 1372 url: url, 1373 dataType: 'jsonp', 1374 error: function (resp, text) { 1375 $output.html('Server error: ' + text); 1376 1377 setTimeout(function () { 1378 $output.removeClass("active"); 1379 }, 4000); 1380 }, 1381 success: function (resp) { 1382 $output.html(resp.msg).addClass('active'); 1383 $email[0].value = ''; 1384 var $label = $('[for="' + $email.attr('id') + '"]'); 1385 if ($label.length) $label.removeClass('focus not-empty'); 1386 1387 setTimeout(function () { 1388 $output.removeClass("active"); 1389 }, 6000); 1390 }, 1391 beforeSend: function (data) { 1392 var isNoviBuilder = window.xMode; 1393 1394 var isValidated = (function () { 1395 var results, errors = 0; 1396 var elements = $this.find('[data-constraints]'); 1397 var captcha = null; 1398 if (elements.length) { 1399 for (var j = 0; j < elements.length; j++) { 1400 1401 var $input = $(elements[j]); 1402 if ((results = $input.regula('validate')).length) { 1403 for (var k = 0; k < results.length; k++) { 1404 errors++; 1405 $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error"); 1406 } 1407 } else { 1408 $input.siblings(".form-validation").text("").parent().removeClass("has-error") 1409 } 1410 } 1411 1412 if (captcha) { 1413 if (captcha.length) { 1414 return validateReCaptcha(captcha) && errors === 0 1415 } 1416 } 1417 1418 return errors === 0; 1419 } 1420 return true; 1421 })(); 1422 1423 // Stop request if builder or inputs are invalide 1424 if (isNoviBuilder || !isValidated) 1425 return false; 1426 1427 $output.html('Submitting...').addClass('active'); 1428 } 1429 }); 1430 1431 return false; 1432 }, $mailchimpItem, $email)); 1433 } 1434 } 1435 1436 // Campaign Monitor ajax subscription 1437 if (plugins.campaignMonitor.length) { 1438 for (i = 0; i < plugins.campaignMonitor.length; i++) { 1439 var $campaignItem = $(plugins.campaignMonitor[i]); 1440 1441 $campaignItem.on('submit', $.proxy(function (e) { 1442 var data = {}, 1443 url = this.attr('action'), 1444 dataArray = this.serializeArray(), 1445 $output = $("#" + plugins.campaignMonitor.attr("data-form-output")), 1446 $this = $(this); 1447 1448 for (i = 0; i < dataArray.length; i++) { 1449 data[dataArray[i].name] = dataArray[i].value; 1450 } 1451 1452 $.ajax({
1453 data: data, 1454 url: url, 1455 dataType: 'jsonp', 1456 error: function (resp, text) { 1457 $output.html('Server error: ' + text); 1458 1459 setTimeout(function () { 1460 $output.removeClass("active"); 1461 }, 4000); 1462 }, 1463 success: function (resp) { 1464 $output.html(resp.Message).addClass('active'); 1465 1466 setTimeout(function () { 1467 $output.removeClass("active"); 1468 }, 6000); 1469 }, 1470 beforeSend: function (data) { 1471 // Stop request if builder or inputs are invalide 1472 if (isNoviBuilder || !isValidated($this.find('[data-constraints]'))) 1473 return false; 1474 1475 $output.html('Submitting...').addClass('active'); 1476 } 1477 }); 1478 1479 // Clear inputs after submit 1480 var inputs = $this[0].getElementsByTagName('input'); 1481 for (var i = 0; i < inputs.length; i++) { 1482 inputs[i].value = ''; 1483 var label = document.querySelector('[for="' + inputs[i].getAttribute('id') + '"]'); 1484 if (label) label.classList.remove('focus', 'not-empty'); 1485 } 1486 1487 return false; 1488 }, $campaignItem)); 1489 } 1490 } 1491 1492 // RD Mailform 1493 if (plugins.rdMailForm.length) { 1494 var i, j, k, 1495 msg = { 1496 'MF000': 'Successfully sent!', 1497 'MF001': 'Recipients are not set!', 1498 'MF002': 'Form will not work locally!', 1499 'MF003': 'Please, define email field in your form!', 1500 'MF004': 'Please, define type of your form!', 1501 'MF254': 'Something went wrong with PHPMailer!', 1502 'MF255': 'Aw, snap! Something went wrong.' 1503 }; 1504 1505 for (i = 0; i < plugins.rdMailForm.length; i++) { 1506 var $form = $(plugins.rdMailForm[i]), 1507 formHasCaptcha = false; 1508 1509 $form.attr('novalidate', 'novalidate').ajaxForm({ 1510 data: { 1511 "form-type": $form.attr("data-form-type") || "contact", 1512 "counter": i 1513 }, 1514 beforeSubmit: function (arr, $form, options) { 1515 if (isNoviBuilder) 1516 return; 1517 1518 var form = $(plugins.rdMailForm[this.extraData.counter]), 1519 inputs = form.find("[data-constraints]"), 1520 output = $("#" + form.attr("data-form-output")), 1521 captcha = form.find('.recaptcha'), 1522 captchaFlag = true; 1523 1524 output.removeClass("active error success"); 1525 1526 if (isValidated(inputs, captcha)) { 1527 1528 // veify reCaptcha 1529 if (captcha.length) { 1530 var captchaToken = captcha.find('.g-recaptcha-response').val(), 1531 captchaMsg = { 1532 'CPT001': 'Please, setup you "site key" and "secret key" of reCaptcha', 1533 'CPT002': 'Something wrong with google reCaptcha' 1534 }; 1535 1536 formHasCaptcha = true; 1537 1538 $.ajax({
1539 method: "POST", 1540 url: "bat/reCaptcha.php", 1541 data: {'g-recaptcha-response': captchaToken}, 1542 async: false 1543 }) 1544 .done(function (responceCode) { 1545 if (responceCode !== 'CPT000') { 1546 if (output.hasClass("snackbars")) { 1547 output.html('<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + captchaMsg[responceCode] + '</span></p>') 1548 1549 setTimeout(function () { 1550 output.removeClass("active"); 1551 }, 3500); 1552 1553 captchaFlag = false; 1554 } else { 1555 output.html(captchaMsg[responceCode]); 1556 } 1557 1558 output.addClass("active"); 1559 } 1560 }); 1561 } 1562 1563 if (!captchaFlag) { 1564 return false; 1565 } 1566 1567 form.addClass('form-in-process'); 1568 1569 if (output.hasClass("snackbars")) { 1570 output.html('<p><span class="icon text-middle fa fa-circle-o-notch fa-spin icon-xxs"></span><span>Sending</span></p>'); 1571 output.addClass("active"); 1572 } 1573 } else { 1574 return false; 1575 } 1576 }, 1577 error: function (result) { 1578 if (isNoviBuilder) 1579 return; 1580 1581 var output = $("#" + $(plugins.rdMailForm[this.extraData.counter]).attr("data-form-output")), 1582 form = $(plugins.rdMailForm[this.extraData.counter]); 1583 1584 output.text(msg[result]); 1585 form.removeClass('form-in-process'); 1586 1587 if (formHasCaptcha) { 1588 grecaptcha.reset(); 1589 } 1590 }, 1591 success: function (result) { 1592 if (isNoviBuilder) 1593 return; 1594 1595 var form = $(plugins.rdMailForm[this.extraData.counter]), 1596 output = $("#" + form.attr("data-form-output")), 1597 select = form.find('select'); 1598 1599 form 1600 .addClass('success') 1601 .removeClass('form-in-process'); 1602 1603 if (formHasCaptcha) { 1604 grecaptcha.reset(); 1605 } 1606 1607 result = result.length === 5 ? result : 'MF255'; 1608 output.text(msg[result]); 1609 1610 if (result === "MF000") { 1611 if (output.hasClass("snackbars")) { 1612 output.html('<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + msg[result] + '</span></p>'); 1613 } else { 1614 output.addClass("active success"); 1615 } 1616 } else { 1617 if (output.hasClass("snackbars")) { 1618 output.html(' <p class="snackbars-left"><span class="icon icon-xxs mdi mdi-alert-outline text-middle"></span><span>' + msg[result] + '</span></p>'); 1619 } else { 1620 output.addClass("active error"); 1621 } 1622 } 1623 1624 form.clearForm(); 1625 1626 if (select.length) { 1627 select.select2("val", ""); 1628 } 1629 1630 form.find('input, textarea').trigger('blur'); 1631 1632 setTimeout(function () { 1633 output.removeClass("active error success"); 1634 form.removeClass('success'); 1635 }, 3500); 1636 } 1637 }); 1638 } 1639 } 1640 1641 // lightGallery 1642 if (plugins.lightGallery.length) { 1643 for (var i = 0; i < plugins.lightGallery.length; i++) { 1644 initLightGallery(plugins.lightGallery[i]); 1645 } 1646 } 1647 1648 // lightGallery item 1649 if (plugins.lightGalleryItem.length) { 1650 // Filter carousel items 1651 var notCarouselItems = []; 1652 1653 for (var z = 0; z < plugins.lightGalleryItem.length; z++) { 1654 if (!$(plugins.lightGalleryItem[z]).parents('.owl-carousel').length && 1655 !$(plugins.lightGalleryItem[z]).parents('.swiper-slider').length && 1656 !$(plugins.lightGalleryItem[z]).parents('.slick-slider').length) { 1657 notCarouselItems.push(plugins.lightGalleryItem[z]); 1658 } 1659 } 1660 1661 plugins.lightGalleryItem = notCarouselItems; 1662 1663 for (var i = 0; i < plugins.lightGalleryItem.length; i++) { 1664 initLightGalleryItem(plugins.lightGalleryItem[i]); 1665 } 1666 } 1667 1668 // Dynamic lightGallery 1669 if (plugins.lightDynamicGalleryItem.length) { 1670 for (var i = 0; i < plugins.lightDynamicGalleryItem.length; i++) { 1671 initDynamicLightGallery(plugins.lightDynamicGalleryItem[i]); 1672 } 1673 } 1674 1675 // Custom Toggles 1676 if (plugins.customToggle.length) { 1677 for (var i = 0; i < plugins.customToggle.length; i++) { 1678 var $this = $(plugins.customToggle[i]); 1679 1680 $this.on('click', $.proxy(function (event) { 1681 event.preventDefault(); 1682 1683 var $ctx = $(this); 1684 $($ctx.attr('data-custom-toggle')).add(this).toggleClass('active'); 1685 }, $this)); 1686
1687 if ($this.attr("data-custom-toggle-hide-on-blur") === "true") { 1688 $body.on("click", $this, function (e) { 1689 if (e.target !== e.data[0] 1690 && $(e.data.attr('data-custom-toggle')).find($(e.target)).length 1691 && e.data.find($(e.target)).length === 0) { 1692 $(e.data.attr('data-custom-toggle')).add(e.data[0]).removeClass('active'); 1693 } 1694 }) 1695 } 1696 1697 if ($this.attr("data-custom-toggle-disable-on-blur") === "true") { 1698 $body.on("click", $this, function (e) { 1699 if (e.target !== e.data[0] && $(e.data.attr('data-custom-toggle')).find($(e.target)).length === 0 && e.data.find($(e.target)).length === 0) { 1700 $(e.data.attr('data-custom-toggle')).add(e.data[0]).removeClass('active'); 1701 } 1702 }) 1703 } 1704 } 1705 } 1706 1707 // Countdown 1708 if (plugins.countdown.length) { 1709 for (var i = 0; i < plugins.countdown.length; i++) { 1710 var 1711 node = plugins.countdown[i], 1712 countdown = aCountdown({ 1713 node: node, 1714 from: node.getAttribute('data-from'), 1715 to: node.getAttribute('data-to'), 1716 count: node.getAttribute('data-count'), 1717 tick: 100, 1718 }); 1719 } 1720 } 1721 1722 // Material Parallax 1723 if (plugins.materialParallax.length) { 1724 if (!isNoviBuilder && !isIE && !isMobile) { 1725 plugins.materialParallax.parallax(); 1726 1727 // heavy pages fix 1728 $window.on('load', function () { 1729 setTimeout(function () { 1730 $window.scroll(); 1731 }, 500); 1732 }); 1733 } else { 1734 for (var i = 0; i < plugins.materialParallax.length; i++) { 1735 var parallax = $(plugins.materialParallax[i]), 1736 imgPath = parallax.data("parallax-img"); 1737 1738 parallax.css({ 1739 "background-image": 'url(' + imgPath + ')', 1740 "background-size": "cover" 1741 }); 1742 } 1743 } 1744 } 1745 1746 // Winona buttons 1747 if (plugins.buttonWinona.length && !isNoviBuilder) { 1748 initWinonaButtons(plugins.buttonWinona); 1749 } 1750 1751 function initWinonaButtons(buttons) { 1752 for (var i = 0; i < buttons.length; i++) { 1753 var $button = $(buttons[i]), 1754 innerContent = $button.html(); 1755 1756 $button.html(''); 1757 $button.append('<div class="content-original">' + innerContent + '</div>'); 1758 $button.append('<div class="content-dubbed">' + innerContent + '</div>'); 1759 } 1760 } 1761 1762 // Select2 1763 if (plugins.selectFilter.length) { 1764 var i; 1765 for (i = 0; i < plugins.selectFilter.length; i++) { 1766 var select = $(plugins.selectFilter[i]), 1767 selectStyle = 'html-' + select.attr('data-style') + '-select'; 1768 $html.addClass(selectStyle); 1769 var parent = select.closest('div'); 1770 select.select2({ 1771 dropdownParent: parent, 1772 placeholder: select.attr("data-placeholder") ? select.attr("data-placeholder") : false, 1773 minimumResultsForSearch: select.attr("data-minimum-results-search") ? select.attr("data-minimum-results-search") : -1, 1774 maximumSelectionSize: 3 1775 }); 1776 } 1777 } 1778 1779 // Stepper 1780 if (plugins.stepper.length) { 1781 plugins.stepper.stepper({ 1782 labels: { 1783 up: "", 1784 down: "" 1785 } 1786 }); 1787 } 1788 1789 //RD Range 1790 if (plugins.rdRange.length && !isNoviBuilder) { 1791 plugins.rdRange.RDRange({ 1792 callbacks: { 1793 onChange: function () { 1794 var $inputs = $('.rd-range-input-value-1, .rd-range-input-value-2'); 1795 1796 for (var z = 0; z < $inputs.length; z++) { 1797 1798 if (isDesktop) { 1799 $inputs[z].style.width = ($inputs[z].value.length + 1) * 1.15 + 'ch'; 1800 } 1801 } 1802 }, 1803 } 1804 }); 1805 } 1806 1807 // Slick carousel 1808 if (plugins.slick.length) { 1809 for (var i = 0; i < plugins.slick.length; i++) { 1810 var $slickItem = $(plugins.slick[i]); 1811 1812 $slickItem.on('init', function (slick) { 1813 initLightGallery($('[data-lightgallery="group-slick"]'), 'lightGallery-in-carousel'); 1814 initLightGallery($('[data-lightgallery="item-slick"]'), 'lightGallery-in-carousel'); 1815 }); 1816 1817 $slickItem.slick({ 1818 slidesToScroll: parseInt($slickItem.attr('data-slide-to-scroll'), 10) || 1, 1819 asNavFor: $slickItem.attr('data-for') || false, 1820 dots: $slickItem.attr("data-dots") === "true", 1821 infinite: isNoviBuilder ? false : $slickItem.attr("data-loop") === "true", 1822 focusOnSelect: true, 1823 arrows: $slickItem.attr("data-arrows") === "true", 1824 swipe: $slickItem.attr("data-swipe") === "true", 1825 autoplay: $slickItem.attr("data-autoplay") === "true", 1826 centerMode: $slickItem.attr("data-center-mode") === "true",
1827 fade: $slickItem.attr("data-slide-effect") === "true", 1828 centerPadding: $slickItem.attr("data-center-padding") ? $slickItem.attr("data-center-padding") : '0.50', 1829 mobileFirst: true, 1830 appendArrows: $slickItem.attr("data-arrows-class") || $slickItem, 1831 nextArrow: $slickItem.attr('data-custom-arrows') === "true" ? '<button type="button" class="slick-next">' + 1832 ' <svg width="100%" height="100%" viewbox="0 0 78 78">' + 1833 ' <circle class="slick-button-line" cx="39" cy="39" r="36"></circle>' + 1834 ' <circle class="slick-button-line-2" cx="39" cy="39" r="36"></circle>' + 1835 ' </svg>' + 1836 '</button>' : '<button type="button" class="slick-next"></button>', 1837 prevArrow: $slickItem.attr('data-custom-arrows') === "true" ? '<button type="button" class="slick-prev">' + 1838 ' <svg width="100%" height="100%" viewbox="0 0 78 78">' + 1839 ' <circle class="slick-button-line" cx="39" cy="39" r="36"></circle>' + 1840 ' <circle class="slick-button-line-2" cx="39" cy="39" r="36"></circle>' + 1841 ' </svg>' + 1842 '</button>' : '<button type="button" class="slick-prev"></button>', 1843 responsive: [ 1844 { 1845 breakpoint: 0, 1846 settings: { 1847 slidesToShow: parseInt($slickItem.attr('data-items'), 10) || 1, 1848 vertical: $slickItem.attr('data-vertical') === 'true' || false 1849 } 1850 }, 1851 { 1852 breakpoint: 575, 1853 settings: { 1854 slidesToShow: parseInt($slickItem.attr('data-sm-items'), 10) || 1, 1855 vertical: $slickItem.attr('data-sm-vertical') === 'true' || false 1856 } 1857 }, 1858 { 1859 breakpoint: 767, 1860 settings: { 1861 slidesToShow: parseInt($slickItem.attr('data-md-items'), 10) || 1, 1862 vertical: $slickItem.attr('data-md-vertical') === 'true' || false 1863 } 1864 }, 1865 { 1866 breakpoint: 991, 1867 settings: { 1868 slidesToShow: parseInt($slickItem.attr('data-lg-items'), 10) || 1, 1869 vertical: $slickItem.attr('data-lg-vertical') === 'true' || false 1870 } 1871 }, 1872 { 1873 breakpoint: 1199, 1874 settings: { 1875 slidesToShow: parseInt($slickItem.attr('data-xl-items'), 10) || 1, 1876 vertical: $slickItem.attr('data-xl-vertical') === 'true' || false 1877 } 1878 } 1879 ] 1880 }) 1881 1882 .on('afterChange', function (event, slick, currentSlide, nextSlide) { 1883 var $this = $(this), 1884 childCarousel = $this.attr('data-child'); 1885 1886 if (childCarousel) { 1887 $(childCarousel + ' .slick-slide').removeClass('slick-current'); 1888 $(childCarousel + ' .slick-slide').eq(currentSlide).addClass('slick-current'); 1889 } 1890 }); 1891 1892 if ($slickItem.attr('data-fraction')) { 1893 (function () { 1894 var fractionElement = document.querySelectorAll($slickItem.attr('data-fraction'))[0], 1895 fractionCurrent = fractionElement.querySelectorAll('.slick-fraction-current')[0], 1896 fractionAll = fractionElement.querySelectorAll('.slick-fraction-all')[0]; 1897 1898 $slickItem.on('afterChange', function (slick) { 1899 fractionCurrent.innerText = leadingZero(this.slick.currentSlide + 1); 1900 fractionAll.innerText = leadingZero(this.slick.slideCount); 1901 }); 1902 1903 $slickItem.trigger('afterChange'); 1904 })(); 1905 } 1906 } 1907 } 1908 1909 function leadingZero(decimal) { 1910 return decimal < 10 && decimal > 0 ? '0' + decimal : decimal; 1911 } 1912 1913 // Radio Panel 1914 if (plugins.radioPanel) { 1915 for (var i = 0; i < plugins.radioPanel.length; i++) { 1916 var $element = $(plugins.radioPanel[i]); 1917 $element.on('click', function () { 1918 plugins.radioPanel.removeClass('active'); 1919 $(this).addClass('active'); 1920 }) 1921 } 1922 } 1923 1924 // Hoverdir plugin 1925 if (plugins.hoverdir.length) { 1926 initHoverDir(plugins.hoverdir); 1927 } 1928 }); 1929}());
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.