Pecetowicz

#99318 - licznik JS

Aug 20th, 2024
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 65.66 KB | None | 0 0
  1. "use strict";
  2. (function () {
  3.     // Global variables
  4.     var
  5.         userAgent = navigator.userAgent.toLowerCase(),
  6.         initialDate = new Date(),
  7.  
  8.         $document = $(document),
  9.         $window = $(window),
  10.         $html = $("html"),
  11.         $body = $("body"),
  12.  
  13.         isDesktop = $html.hasClass("desktop"),
  14.         isIE = userAgent.indexOf("msie") !== -1 ? parseInt(userAgent.split("msie")[1], 10) : userAgent.indexOf("trident") !== -1 ? 11 : userAgent.indexOf("edge") !== -1 ? 12 : false,
  15.         isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
  16.         windowReady = false,
  17.         isNoviBuilder = false,
  18.         livedemo = true,
  19.  
  20.         plugins = {
  21.             bootstrapTooltip:        $( '[data-toggle="tooltip"]' ),
  22.             bootstrapModalDialog:    $( '.modal' ),
  23.             customToggle:            $( '[data-custom-toggle]' ),
  24.             counter:                 $( '.counter' ),
  25.             circleProgress:          $( '.progress-bar-circle' ),
  26.             captcha:                 $( '.recaptcha' ),
  27.             campaignMonitor:         $( '.campaign-mailform' ),
  28.             copyrightYear:           $( '.copyright-year' ),
  29.             checkbox:                $( 'input[type="checkbox"]' ),
  30.             dateCountdown:           $( '.DateCountdown' ),
  31.             isotope:                 $( '.isotope-wrap' ),
  32.             lightGallery:            $( '[data-lightgallery="group"]' ),
  33.             lightGalleryItem:        $( '[data-lightgallery="item"]' ),
  34.             lightDynamicGalleryItem: $( '[data-lightgallery="dynamic"]' ),
  35.             materialParallax:        $( '.parallax-container' ),
  36.             mailchimp:               $( '.mailchimp-mailform' ),
  37.             owl:                     $( '.owl-carousel' ),
  38.             popover:                 $( '[data-toggle="popover"]' ),
  39.             progressLinear:          $( '.progress-linear' ),
  40.             preloader:               $( '.preloader' ),
  41.             rdNavbar:                $( '.rd-navbar' ),
  42.             rdMailForm:              $( '.rd-mailform' ),
  43.             rdInputLabel:            $( '.form-label' ),
  44.             regula:                  $( '[data-constraints]' ),
  45.             radio:                   $( 'input[type="radio"]' ),
  46.             swiper:                  $( '.swiper-container' ),
  47.             search:                  $( '.rd-search' ),
  48.             searchResults:           $( '.rd-search-results' ),
  49.             statefulButton:          $( '.btn-stateful' ),
  50.             viewAnimate:             $( '.view-animate' ),
  51.             wow:                     $( '.wow' ),
  52.             maps:                    $( '.google-map-container' ),
  53.             scroller:                $( '.scroll-wrap' ),
  54.             jPlayerInit:             $( '.jp-player-init' ),
  55.             circleJPlayer:           $( '.jp-player-circle-init' ),
  56.             jPlayerVideo:            $( '.jp-video-init' ),
  57.             countDown:               $( '.countdown' ),
  58.             stepper:                 $( 'input[type="number"]' ),
  59.             slick:                   $( '.slick-slider' ),
  60.             vide:                    $( '.bg-vide' ),
  61.             customWaypoints:         $('[data-custom-scroll-to]'),
  62.  
  63.         };
  64.  
  65.     /**
  66.      * @desc Check the element was been scrolled into the view
  67.      * @param {object} elem - jQuery object
  68.      * @return {boolean}
  69.      */
  70.     function isScrolledIntoView ( elem ) {
  71.         if ( isNoviBuilder ) return true;
  72.         return elem.offset().top + elem.outerHeight() >= $window.scrollTop() && elem.offset().top <= $window.scrollTop() + $window.height();
  73.     }
  74.  
  75.     /**
  76.      * @desc Calls a function when element has been scrolled into the view
  77.      * @param {object} element - jQuery object
  78.      * @param {function} func - init function
  79.      */
  80.     function lazyInit( element, func ) {
  81.         var scrollHandler = function () {
  82.             if ( ( !element.hasClass( 'lazy-loaded' ) && ( isScrolledIntoView( element ) ) ) ) {
  83.                 func.call();
  84.                 element.addClass( 'lazy-loaded' );
  85.             }
  86.         };
  87.  
  88.         scrollHandler();
  89.         $window.on( 'scroll', scrollHandler );
  90.     }
  91.  
  92.     // Initialize scripts that require a loaded window
  93.     $window.on('load', function () {
  94.         // Page loader & Page transition
  95.         if (plugins.preloader.length && !isNoviBuilder) {
  96.             pageTransition({
  97.                 target: document.querySelector( '.page' ),
  98.                 delay: 0,
  99.                 duration: 500,
  100.                 classIn: 'fadeIn',
  101.                 classOut: 'fadeOut',
  102.                 classActive: 'animated',
  103.                 conditions: function (event, link) {
  104.                     return link && !/(\#|javascript:void\(0\)|javascript:;|callto:|tel:|mailto:|:\/\/)/.test(link) && !event.currentTarget.hasAttribute('data-lightgallery');
  105.                 },
  106.                 onTransitionStart: function ( options ) {
  107.                     setTimeout( function () {
  108.                         plugins.preloader.removeClass('loaded');
  109.                     }, options.duration * .75 );
  110.                 },
  111.                 onReady: function () {
  112.                     plugins.preloader.addClass('loaded');
  113.                     windowReady = true;
  114.                 }
  115.             });
  116.         }
  117.  
  118.         // jQuery Count To
  119.         if ( plugins.counter.length ) {
  120.             for ( var i = 0; i < plugins.counter.length; i++ ) {
  121.                 var
  122.                     counter = $(plugins.counter[i]),
  123.                     initCount = function () {
  124.                         var counter = $(this);
  125.                         if ( !counter.hasClass( "animated-first" ) && isScrolledIntoView( counter ) ) {
  126.                             counter.countTo({
  127.                                 refreshInterval: 40,
  128.                                 speed: counter.attr("data-speed") || 1000,
  129.                                 from: 0,
  130.                                 to: parseInt( counter.text(), 10 )
  131.                             });
  132.                             counter.addClass('animated-first');
  133.                         }
  134.                     };
  135.  
  136.                 $.proxy( initCount, counter )();
  137.                 $window.on( "scroll", $.proxy( initCount, counter ) );
  138.             }
  139.         }
  140.  
  141.         // Progress bar
  142.         if ( plugins.progressLinear.length ) {
  143.             for ( var i = 0; i < plugins.progressLinear.length; i++) {
  144.                 var
  145.                     bar = $(plugins.progressLinear[i]),
  146.                     initProgress = function() {
  147.                         var
  148.                             bar = $(this),
  149.                             end = parseInt($(this).find('.progress-value').text(), 10);
  150.  
  151.                         if ( !bar.hasClass( "animated-first" ) && isScrolledIntoView( bar ) ) {
  152.                             bar.find('.progress-bar-linear').css({width: end + '%'});
  153.                             bar.find('.progress-value').countTo({
  154.                                 refreshInterval: 40,
  155.                                 from: 0,
  156.                                 to: end,
  157.                                 speed: 1000
  158.                             });
  159.                             bar.addClass('animated-first');
  160.                         }
  161.                     };
  162.  
  163.                 $.proxy( initProgress, bar )();
  164.                 $window.on( "scroll", $.proxy( initProgress, bar ) );
  165.             }
  166.         }
  167.  
  168.         // Circle Progress
  169.         if ( plugins.circleProgress.length ) {
  170.             for ( var i = 0; i < plugins.circleProgress.length; i++ ) {
  171.                 var circle = $(plugins.circleProgress[i]);
  172.  
  173.                 circle.circleProgress({
  174.                     value: circle.attr('data-value'),
  175.                     size: circle.attr('data-size') ? circle.attr('data-size') : 175,
  176.                     fill: {
  177.                         gradient: circle.attr('data-gradient').split(","),
  178.                         gradientAngle: Math.PI / 4
  179.                     },
  180.                     startAngle: -Math.PI / 4 * 2,
  181.                     emptyFill: circle.attr('data-empty-fill') ? circle.attr('data-empty-fill') : "rgb(245,245,245)"
  182.                 }).on('circle-animation-progress', function (event, progress, stepValue) {
  183.                     $(this).find('span').text( String(stepValue.toFixed(2)).replace('0.', '').replace('1.', '1') );
  184.                 });
  185.  
  186.                 if ( isScrolledIntoView( circle ) ) circle.addClass('animated-first');
  187.  
  188.                 $window.on( 'scroll', $.proxy( function() {
  189.                     var circle = $(this);
  190.                     if ( !circle.hasClass( "animated-first" ) && isScrolledIntoView( circle ) ) {
  191.                         circle.circleProgress( 'redraw' );
  192.                         circle.addClass( 'animated-first' );
  193.                     }
  194.                 }, circle ) );
  195.             }
  196.         }
  197.  
  198.         // Isotope
  199.         if ( plugins.isotope.length ) {
  200.             for ( var i = 0; i < plugins.isotope.length; i++ ) {
  201.                 var
  202.                     wrap = plugins.isotope[ i ],
  203.                     filterHandler = function ( event ) {
  204.                         event.preventDefault();
  205.                         for ( var n = 0; n < this.isoGroup.filters.length; n++ ) this.isoGroup.filters[ n ].classList.remove( 'active' );
  206.                         this.classList.add( 'active' );
  207.                         this.isoGroup.isotope.arrange( { filter: this.getAttribute( "data-isotope-filter" ) !== '*' ? '[data-filter*="' + this.getAttribute( "data-isotope-filter" ) + '"]' : '*' } );
  208.                     },
  209.                     resizeHandler = function () {
  210.                         this.isoGroup.isotope.layout();
  211.                     };
  212.  
  213.                 wrap.isoGroup = {};
  214.                 wrap.isoGroup.filters = wrap.querySelectorAll( '[data-isotope-filter]' );
  215.                 wrap.isoGroup.node = wrap.querySelector( '.isotope' );
  216.                 wrap.isoGroup.layout = wrap.isoGroup.node.getAttribute( 'data-isotope-layout' ) ? wrap.isoGroup.node.getAttribute( 'data-isotope-layout' ) : 'masonry';
  217.                 wrap.isoGroup.isotope = new Isotope( wrap.isoGroup.node, {
  218.                     itemSelector: '.isotope-item',
  219.                     layoutMode: wrap.isoGroup.layout,
  220.                     filter: '*',
  221.                     columnWidth: ( function() {
  222.                         if ( wrap.isoGroup.node.hasAttribute('data-column-class') ) return wrap.isoGroup.node.getAttribute('data-column-class');
  223.                         if ( wrap.isoGroup.node.hasAttribute('data-column-width') ) return parseFloat( wrap.isoGroup.node.getAttribute('data-column-width') );
  224.                     }() )
  225.                 } );
  226.  
  227.                 for ( var n = 0; n < wrap.isoGroup.filters.length; n++ ) {
  228.                     var filter = wrap.isoGroup.filters[ n ];
  229.                     filter.isoGroup = wrap.isoGroup;
  230.                     filter.addEventListener( 'click', filterHandler );
  231.                 }
  232.  
  233.                 window.addEventListener( 'resize', resizeHandler.bind( wrap ) );
  234.             }
  235.         }
  236.  
  237.         // Material Parallax
  238.         if ( plugins.materialParallax.length ) {
  239.             if ( !isNoviBuilder && !isIE && !isMobile) {
  240.                 plugins.materialParallax.parallax();
  241.             } else {
  242.                 for ( var i = 0; i < plugins.materialParallax.length; i++ ) {
  243.                     var $parallax = $(plugins.materialParallax[i]);
  244.  
  245.                     $parallax.addClass( 'parallax-disabled' );
  246.                     $parallax.css({ "background-image": 'url('+ $parallax.data("parallax-img") +')' });
  247.                 }
  248.             }
  249.         }
  250.     });
  251.  
  252.     // Initialize scripts that require a finished document
  253.     $(function () {
  254.         isNoviBuilder = window.xMode;
  255.  
  256.         /**
  257.          * jpFormatePlaylistObj
  258.          * @description  format dynamic playlist object for jPlayer init
  259.          */
  260.         function jpFormatePlaylistObj(playlistHtml) {
  261.             var playlistObj = [];
  262.  
  263.             // Format object with audio
  264.             for (var i = 0; i < playlistHtml.length; i++) {
  265.                 var playlistItem = playlistHtml[i],
  266.                         itemData = $(playlistItem).data();
  267.                 playlistObj[i] = {};
  268.  
  269.                 for (var key in itemData) {
  270.                     playlistObj[i][key.replace('jp', '').toLowerCase()] = itemData[key];
  271.                 }
  272.             }
  273.  
  274.             return playlistObj;
  275.         }
  276.  
  277.         /**
  278.          * initJplayerBase
  279.          * @description Base jPlayer init
  280.          */
  281.         function initJplayerBase(index, item, mediaObj) {
  282.             return new jPlayerPlaylist({
  283.                 jPlayer: item.getElementsByClassName("jp-jplayer")[0],
  284.                 cssSelectorAncestor: ".jp-audio-" + index // Need too bee a selector not HTMLElement or Jq object, so we make it unique
  285.             }, mediaObj, {
  286.                 playlistOptions: {
  287.                     enableRemoveControls: false
  288.                 },
  289.                 supplied: "ogv, m4v, oga, mp3",
  290.                 useStateClassSkin: true,
  291.                 volume: 0.4
  292.             });
  293.         }
  294.  
  295.         /**
  296.          * @desc Toggle swiper videos on active slides
  297.          * @param {object} swiper - swiper slider
  298.          */
  299.         function toggleSwiperInnerVideos(swiper) {
  300.             var prevSlide = $(swiper.slides[swiper.previousIndex]),
  301.                 nextSlide = $(swiper.slides[swiper.activeIndex]),
  302.                 videos,
  303.                 videoItems = prevSlide.find("video");
  304.  
  305.             for (var i = 0; i < videoItems.length; i++) {
  306.                 videoItems[i].pause();
  307.             }
  308.  
  309.             videos = nextSlide.find("video");
  310.             if (videos.length) {
  311.                 videos.get(0).play();
  312.             }
  313.         }
  314.  
  315.         /**
  316.          * @desc Toggle swiper animations on active slides
  317.          * @param {object} swiper - swiper slider
  318.          */
  319.         function toggleSwiperCaptionAnimation(swiper) {
  320.             var prevSlide = $(swiper.container).find("[data-caption-animate]"),
  321.                 nextSlide = $(swiper.slides[swiper.activeIndex]).find("[data-caption-animate]"),
  322.                 delay,
  323.                 duration,
  324.                 nextSlideItem,
  325.                 prevSlideItem;
  326.  
  327.             for (var i = 0; i < prevSlide.length; i++) {
  328.                 prevSlideItem = $(prevSlide[i]);
  329.  
  330.                 prevSlideItem.removeClass("animated")
  331.                     .removeClass(prevSlideItem.attr("data-caption-animate"))
  332.                     .addClass("not-animated");
  333.             }
  334.  
  335.  
  336.             var tempFunction = function (nextSlideItem, duration) {
  337.                 return function () {
  338.                     nextSlideItem
  339.                         .removeClass("not-animated")
  340.                         .addClass(nextSlideItem.attr("data-caption-animate"))
  341.                         .addClass("animated");
  342.                     if (duration) {
  343.                         nextSlideItem.css('animation-duration', duration + 'ms');
  344.                     }
  345.                 };
  346.             };
  347.  
  348.             for (var i = 0; i < nextSlide.length; i++) {
  349.                 nextSlideItem = $(nextSlide[i]);
  350.                 delay = nextSlideItem.attr("data-caption-delay");
  351.                 duration = nextSlideItem.attr('data-caption-duration');
  352.                 if (!isNoviBuilder) {
  353.                     if (delay) {
  354.                         setTimeout(tempFunction(nextSlideItem, duration), parseInt(delay, 10));
  355.                     } else {
  356.                         tempFunction(nextSlideItem, duration);
  357.                     }
  358.  
  359.                 } else {
  360.                     nextSlideItem.removeClass("not-animated")
  361.                 }
  362.             }
  363.         }
  364.  
  365.         /**
  366.          * @desc Initialize owl carousel plugin
  367.          * @param {object} carousel - carousel jQuery object
  368.          */
  369.         function initOwlCarousel ( carousel ) {
  370.             var
  371.                 aliaces = [ '-', '-sm-', '-md-', '-lg-', '-xl-', '-xxl-' ],
  372.                 values = [ 0, 576, 768, 992, 1200, 1600 ],
  373.                 responsive = {};
  374.  
  375.             for ( var j = 0; j < values.length; j++ ) {
  376.                 responsive[ values[ j ] ] = {};
  377.                 for ( var k = j; k >= -1; k-- ) {
  378.                     if ( !responsive[ values[ j ] ][ 'items' ] && carousel.attr( 'data' + aliaces[ k ] + 'items' ) ) {
  379.                         responsive[ values[ j ] ][ 'items' ] = k < 0 ? 1 : parseInt( carousel.attr( 'data' + aliaces[ k ] + 'items' ), 10 );
  380.                     }
  381.                     if ( !responsive[ values[ j ] ][ 'stagePadding' ] && responsive[ values[ j ] ][ 'stagePadding' ] !== 0 && carousel.attr( 'data' + aliaces[ k ] + 'stage-padding' ) ) {
  382.                         responsive[ values[ j ] ][ 'stagePadding' ] = k < 0 ? 0 : parseInt( carousel.attr( 'data' + aliaces[ k ] + 'stage-padding' ), 10 );
  383.                     }
  384.                     if ( !responsive[ values[ j ] ][ 'margin' ] && responsive[ values[ j ] ][ 'margin' ] !== 0 && carousel.attr( 'data' + aliaces[ k ] + 'margin' ) ) {
  385.                         responsive[ values[ j ] ][ 'margin' ] = k < 0 ? 30 : parseInt( carousel.attr( 'data' + aliaces[ k ] + 'margin' ), 10 );
  386.                     }
  387.                 }
  388.             }
  389.  
  390.             // Enable custom pagination
  391.             if ( carousel.attr( 'data-dots-custom' ) ) {
  392.                 carousel.on( 'initialized.owl.carousel', function ( event ) {
  393.                     var
  394.                         carousel = $( event.currentTarget ),
  395.                         customPag = $( carousel.attr( 'data-dots-custom' ) ),
  396.                         active = 0;
  397.  
  398.                     if ( carousel.attr( 'data-active' ) ) {
  399.                         active = parseInt( carousel.attr( 'data-active' ), 10 );
  400.                     }
  401.  
  402.                     carousel.trigger( 'to.owl.carousel', [ active, 300, true ] );
  403.                     customPag.find( '[data-owl-item="' + active + '"]' ).addClass( 'active' );
  404.  
  405.                     customPag.find( '[data-owl-item]' ).on( 'click', function ( event ) {
  406.                         event.preventDefault();
  407.                         carousel.trigger( 'to.owl.carousel', [ parseInt( this.getAttribute( 'data-owl-item' ), 10 ), 300, true ] );
  408.                     } );
  409.  
  410.                     carousel.on( 'translate.owl.carousel', function ( event ) {
  411.                         customPag.find( '.active' ).removeClass( 'active' );
  412.                         customPag.find( '[data-owl-item="' + event.item.index + '"]' ).addClass( 'active' )
  413.                     } );
  414.                 } );
  415.             }
  416.  
  417.             // Initialize lightgallery items in cloned owl items
  418.             carousel.on( 'initialized.owl.carousel', function () {
  419.                 initLightGalleryItem( carousel.find( '[data-lightgallery="item"]' ), 'lightGallery-in-carousel' );
  420.             } );
  421.  
  422.             carousel.owlCarousel( {
  423.                 autoplay:           isNoviBuilder ? false : carousel.attr( 'data-autoplay' ) !== 'false',
  424.                 autoplayTimeout:    carousel.attr( "data-autoplay" ) ? Number( carousel.attr( "data-autoplay" ) ) : 3000,
  425.                 autoplayHoverPause: true,
  426.                 loop:               isNoviBuilder ? false : carousel.attr( 'data-loop' ) !== 'false',
  427.                 items:              1,
  428.                 center:             carousel.attr( 'data-center' ) === 'true',
  429.                 dotsContainer:      carousel.attr( 'data-pagination-class' ) || false,
  430.                 navContainer:       carousel.attr( 'data-navigation-class' ) || false,
  431.                 mouseDrag:          isNoviBuilder ? false : carousel.attr( 'data-mouse-drag' ) !== 'false',
  432.                 nav:                carousel.attr( 'data-nav' ) === 'true',
  433.                 dots:               carousel.attr( 'data-dots' ) === 'true',
  434.                 dotsEach:           carousel.attr( 'data-dots-each' ) ? parseInt( carousel.attr( 'data-dots-each' ), 10 ) : false,
  435.                 animateIn:          carousel.attr( 'data-animation-in' ) ? carousel.attr( 'data-animation-in' ) : false,
  436.                 animateOut:         carousel.attr( 'data-animation-out' ) ? carousel.attr( 'data-animation-out' ) : false,
  437.                 responsive:         responsive,
  438.                 navText:            carousel.attr( 'data-nav-text' ) ? $.parseJSON( carousel.attr( 'data-nav-text' ) ) : [],
  439.                 navClass:           carousel.attr( 'data-nav-class' ) ? $.parseJSON( carousel.attr( 'data-nav-class' ) ) : [ 'owl-prev', 'owl-next' ]
  440.             } );
  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" ) !== "false",
  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 head = document.getElementsByTagName('head')[0],
  756.                     insertBefore = head.insertBefore;
  757.  
  758.                 head.insertBefore = function (newElement, referenceElement) {
  759.                     if (newElement.href && newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') !== -1 || newElement.innerHTML.indexOf('gm-style') !== -1) {
  760.                         return;
  761.                     }
  762.                     insertBefore.call(head, newElement, referenceElement);
  763.                 };
  764.                 var geocoder = new google.maps.Geocoder;
  765.                 for (var i = 0; i < plugins.maps.length; i++) {
  766.                     var zoom = parseInt(plugins.maps[i].getAttribute("data-zoom"), 10) || 11;
  767.                     var styles = plugins.maps[i].hasAttribute('data-styles') ? JSON.parse(plugins.maps[i].getAttribute("data-styles")) : [];
  768.                     var center = plugins.maps[i].getAttribute("data-center") || "New York";
  769.  
  770.                     // Initialize map
  771.                     var map = new google.maps.Map(plugins.maps[i].querySelectorAll(".google-map")[0], {
  772.                         zoom: zoom,
  773.                         styles: styles,
  774.                         scrollwheel: false,
  775.                         center: {lat: 0, lng: 0}
  776.                     });
  777.  
  778.                     // Add map object to map node
  779.                     plugins.maps[i].map = map;
  780.                     plugins.maps[i].geocoder = geocoder;
  781.                     plugins.maps[i].keySupported = true;
  782.                     plugins.maps[i].google = google;
  783.  
  784.                     // Get Center coordinates from attribute
  785.                     getLatLngObject(center, null, plugins.maps[i], function (location, markerElement, mapElement) {
  786.                         mapElement.map.setCenter(location);
  787.                     });
  788.  
  789.                     // Add markers from google-map-markers array
  790.                     var markerItems = plugins.maps[i].querySelectorAll(".google-map-markers li");
  791.  
  792.                     if (markerItems.length){
  793.                         var markers = [];
  794.                         for (var j = 0; j < markerItems.length; j++){
  795.                             var markerElement = markerItems[j];
  796.                             getLatLngObject(markerElement.getAttribute("data-location"), markerElement, plugins.maps[i], function(location, markerElement, mapElement){
  797.                                 var icon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon");
  798.                                 var activeIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active");
  799.                                 var info = markerElement.getAttribute("data-description") || "";
  800.                                 var infoWindow = new google.maps.InfoWindow({
  801.                                     content: info
  802.                                 });
  803.                                 markerElement.infoWindow = infoWindow;
  804.                                 var markerData = {
  805.                                     position: location,
  806.                                     map: mapElement.map
  807.                                 }
  808.                                 if (icon){
  809.                                     markerData.icon = icon;
  810.                                 }
  811.                                 var marker = new google.maps.Marker(markerData);
  812.                                 markerElement.gmarker = marker;
  813.                                 markers.push({markerElement: markerElement, infoWindow: infoWindow});
  814.                                 marker.isActive = false;
  815.                                 // Handle infoWindow close click
  816.                                 google.maps.event.addListener(infoWindow,'closeclick',(function(markerElement, mapElement){
  817.                                     var markerIcon = null;
  818.                                     markerElement.gmarker.isActive = false;
  819.                                     markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon");
  820.                                     markerElement.gmarker.setIcon(markerIcon);
  821.                                 }).bind(this, markerElement, mapElement));
  822.  
  823.  
  824.                                 // Set marker active on Click and open infoWindow
  825.                                 google.maps.event.addListener(marker, 'click', (function(markerElement, mapElement) {
  826.                                     if (markerElement.infoWindow.getContent().length === 0) return;
  827.                                     var gMarker, currentMarker = markerElement.gmarker, currentInfoWindow;
  828.                                     for (var k =0; k < markers.length; k++){
  829.                                         var markerIcon;
  830.                                         if (markers[k].markerElement === markerElement){
  831.                                             currentInfoWindow = markers[k].infoWindow;
  832.                                         }
  833.                                         gMarker = markers[k].markerElement.gmarker;
  834.                                         if (gMarker.isActive && markers[k].markerElement !== markerElement){
  835.                                             gMarker.isActive = false;
  836.                                             markerIcon = markers[k].markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon")
  837.                                             gMarker.setIcon(markerIcon);
  838.                                             markers[k].infoWindow.close();
  839.                                         }
  840.                                     }
  841.  
  842.                                     currentMarker.isActive = !currentMarker.isActive;
  843.                                     if (currentMarker.isActive) {
  844.                                         if (markerIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active")){
  845.                                             currentMarker.setIcon(markerIcon);
  846.                                         }
  847.  
  848.                                         currentInfoWindow.open(map, marker);
  849.                                     }else{
  850.                                         if (markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon")){
  851.                                             currentMarker.setIcon(markerIcon);
  852.                                         }
  853.                                         currentInfoWindow.close();
  854.                                     }
  855.                                 }).bind(this, markerElement, mapElement))
  856.                             })
  857.                         }
  858.                     }
  859.                 }
  860.             });
  861.         }
  862.  
  863.         // Google ReCaptcha
  864.         if (plugins.captcha.length) {
  865.             $.getScript("//www.google.com/recaptcha/api.js?onload=onloadCaptchaCallback&render=explicit&hl=en");
  866.         }
  867.  
  868.         // Additional class on html if mac os.
  869.         if (navigator.platform.match(/(Mac)/i)) {
  870.             $html.addClass("mac-os");
  871.         }
  872.  
  873.         // Adds some loosing functionality to IE browsers (IE Polyfills)
  874.         if (isIE) {
  875.             if (isIE === 12) $html.addClass("ie-edge");
  876.             if (isIE === 11) $html.addClass("ie-11");
  877.             if (isIE < 10) $html.addClass("lt-ie-10");
  878.             if (isIE < 11) $html.addClass("ie-10");
  879.         }
  880.  
  881.         // Bootstrap Tooltips
  882.         if (plugins.bootstrapTooltip.length) {
  883.             var tooltipPlacement = plugins.bootstrapTooltip.attr('data-placement');
  884.             initBootstrapTooltip(tooltipPlacement);
  885.  
  886.             $window.on('resize orientationchange', function () {
  887.                 initBootstrapTooltip(tooltipPlacement);
  888.             })
  889.         }
  890.  
  891.         // Stop vioeo in bootstrapModalDialog
  892.         if (plugins.bootstrapModalDialog.length) {
  893.             for (var i = 0; i < plugins.bootstrapModalDialog.length; i++) {
  894.                 var modalItem = $(plugins.bootstrapModalDialog[i]);
  895.  
  896.                 modalItem.on('hidden.bs.modal', $.proxy(function () {
  897.                     var activeModal = $(this),
  898.                         rdVideoInside = activeModal.find('video'),
  899.                         youTubeVideoInside = activeModal.find('iframe');
  900.  
  901.                     if (rdVideoInside.length) {
  902.                         rdVideoInside[0].pause();
  903.                     }
  904.  
  905.                     if (youTubeVideoInside.length) {
  906.                         var videoUrl = youTubeVideoInside.attr('src');
  907.  
  908.                         youTubeVideoInside
  909.                             .attr('src', '')
  910.                             .attr('src', videoUrl);
  911.                     }
  912.                 }, modalItem))
  913.             }
  914.         }
  915.  
  916.         // Popovers
  917.         if (plugins.popover.length) {
  918.             if (window.innerWidth < 767) {
  919.                 plugins.popover.attr('data-placement', 'bottom');
  920.                 plugins.popover.popover();
  921.             }
  922.             else {
  923.                 plugins.popover.popover();
  924.             }
  925.         }
  926.  
  927.         // Bootstrap Buttons
  928.         if (plugins.statefulButton.length) {
  929.             $(plugins.statefulButton).on('click', function () {
  930.                 var statefulButtonLoading = $(this).button('loading');
  931.  
  932.                 setTimeout(function () {
  933.                     statefulButtonLoading.button('reset')
  934.                 }, 2000);
  935.             })
  936.         }
  937.  
  938.         // Copyright Year (Evaluates correct copyright year)
  939.         if (plugins.copyrightYear.length) {
  940.             plugins.copyrightYear.text(initialDate.getFullYear());
  941.         }
  942.  
  943.         // Google maps
  944.         if( plugins.maps.length ) {
  945.             lazyInit( plugins.maps, initMaps );
  946.         }
  947.  
  948.         // Add custom styling options for input[type="radio"]
  949.         if (plugins.radio.length) {
  950.             for (var i = 0; i < plugins.radio.length; i++) {
  951.                 $(plugins.radio[i]).addClass("radio-custom").after("<span class='radio-custom-dummy'></span>")
  952.             }
  953.         }
  954.  
  955.         // Add custom styling options for input[type="checkbox"]
  956.         if (plugins.checkbox.length) {
  957.             for (var i = 0; i < plugins.checkbox.length; i++) {
  958.                 $(plugins.checkbox[i]).addClass("checkbox-custom").after("<span class='checkbox-custom-dummy'></span>")
  959.             }
  960.         }
  961.  
  962.         // UI To Top
  963.         if (isDesktop && !isNoviBuilder) {
  964.             $().UItoTop({
  965.                 easingType: 'easeOutQuad',
  966.                 containerClass: 'ui-to-top fa fa-angle-up'
  967.             });
  968.         }
  969.  
  970.         // RD Navbar
  971.         if (plugins.rdNavbar.length) {
  972.             var aliaces, i, j, len, value, values, responsiveNavbar;
  973.  
  974.             aliaces = ["-", "-sm-", "-md-", "-lg-", "-xl-", "-xxl-"];
  975.             values = [0, 576, 768, 992, 1200, 1600];
  976.             responsiveNavbar = {};
  977.  
  978.             for (i = j = 0, len = values.length; j < len; i = ++j) {
  979.                 value = values[i];
  980.                 if (!responsiveNavbar[values[i]]) {
  981.                     responsiveNavbar[values[i]] = {};
  982.                 }
  983.                 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'layout')) {
  984.                     responsiveNavbar[values[i]].layout = plugins.rdNavbar.attr('data' + aliaces[i] + 'layout');
  985.                 }
  986.                 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'device-layout')) {
  987.                     responsiveNavbar[values[i]]['deviceLayout'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'device-layout');
  988.                 }
  989.                 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'hover-on')) {
  990.                     responsiveNavbar[values[i]]['focusOnHover'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'hover-on') === 'true';
  991.                 }
  992.                 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'auto-height')) {
  993.                     responsiveNavbar[values[i]]['autoHeight'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'auto-height') === 'true';
  994.                 }
  995.  
  996.                 if (isNoviBuilder) {
  997.                     responsiveNavbar[values[i]]['stickUp'] = false;
  998.                 } else if (plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up')) {
  999.                     responsiveNavbar[values[i]]['stickUp'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up') === 'true';
  1000.                 }
  1001.  
  1002.                 if (plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up-offset')) {
  1003.                     responsiveNavbar[values[i]]['stickUpOffset'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up-offset');
  1004.                 }
  1005.             }
  1006.  
  1007.  
  1008.             plugins.rdNavbar.RDNavbar({
  1009.                 anchorNav: !isNoviBuilder,
  1010.                 stickUpClone: (plugins.rdNavbar.attr("data-stick-up-clone") && !isNoviBuilder) ? plugins.rdNavbar.attr("data-stick-up-clone") === 'true' : false,
  1011.                 responsive: responsiveNavbar,
  1012.                 callbacks: {
  1013.                     onStuck: function () {
  1014.                         var navbarSearch = this.$element.find('.rd-search input');
  1015.  
  1016.                         if (navbarSearch) {
  1017.                             navbarSearch.val('').trigger('propertychange');
  1018.                         }
  1019.                     },
  1020.                     onDropdownOver: function () {
  1021.                         return !isNoviBuilder;
  1022.                     },
  1023.                     onUnstuck: function () {
  1024.                         if (this.$clone === null)
  1025.                             return;
  1026.  
  1027.                         var navbarSearch = this.$clone.find('.rd-search input');
  1028.  
  1029.                         if (navbarSearch) {
  1030.                             navbarSearch.val('').trigger('propertychange');
  1031.                             navbarSearch.trigger('blur');
  1032.                         }
  1033.  
  1034.                     }
  1035.                 }
  1036.             });
  1037.  
  1038.  
  1039.             if (plugins.rdNavbar.attr("data-body-class")) {
  1040.                 document.body.className += ' ' + plugins.rdNavbar.attr("data-body-class");
  1041.             }
  1042.         }
  1043.  
  1044.         // RD Search
  1045.         if (plugins.search.length || plugins.searchResults) {
  1046.             var handler = "bat/rd-search.php";
  1047.             var defaultTemplate = '<h5 class="search-title"><a target="_top" href="#{href}" class="search-link">#{title}</a></h5>' +
  1048.                 '<p>...#{token}...</p>' +
  1049.                 '<p class="match"><em>Terms matched: #{count} - URL: #{href}</em></p>';
  1050.             var defaultFilter = '*.html';
  1051.  
  1052.             if (plugins.search.length) {
  1053.                 for (var i = 0; i < plugins.search.length; i++) {
  1054.                     var searchItem = $(plugins.search[i]),
  1055.                         options = {
  1056.                             element: searchItem,
  1057.                             filter: (searchItem.attr('data-search-filter')) ? searchItem.attr('data-search-filter') : defaultFilter,
  1058.                             template: (searchItem.attr('data-search-template')) ? searchItem.attr('data-search-template') : defaultTemplate,
  1059.                             live: (searchItem.attr('data-search-live')) ? searchItem.attr('data-search-live') : false,
  1060.                             liveCount: (searchItem.attr('data-search-live-count')) ? parseInt(searchItem.attr('data-search-live'), 10) : 4,
  1061.                             current: 0, processed: 0, timer: {}
  1062.                         };
  1063.  
  1064.                     var $toggle = $('.rd-navbar-search-toggle');
  1065.                     if ($toggle.length) {
  1066.                         $toggle.on('click', (function (searchItem) {
  1067.                             return function () {
  1068.                                 if (!($(this).hasClass('active'))) {
  1069.                                     searchItem.find('input').val('').trigger('propertychange');
  1070.                                 }
  1071.                             }
  1072.                         })(searchItem));
  1073.                     }
  1074.  
  1075.                     if (options.live) {
  1076.                         var clearHandler = false;
  1077.  
  1078.                         searchItem.find('input').on("input propertychange", $.proxy(function () {
  1079.                             this.term = this.element.find('input').val().trim();
  1080.                             this.spin = this.element.find('.input-group-addon');
  1081.  
  1082.                             clearTimeout(this.timer);
  1083.  
  1084.                             if (this.term.length > 2) {
  1085.                                 this.timer = setTimeout(liveSearch(this), 200);
  1086.  
  1087.                                 if (clearHandler === false) {
  1088.                                     clearHandler = true;
  1089.  
  1090.                                     $body.on("click", function (e) {
  1091.                                         if ($(e.toElement).parents('.rd-search').length === 0) {
  1092.                                             $('#rd-search-results-live').addClass('cleared').html('');
  1093.                                         }
  1094.                                     })
  1095.                                 }
  1096.  
  1097.                             } else if (this.term.length === 0) {
  1098.                                 $('#' + this.live).addClass('cleared').html('');
  1099.                             }
  1100.                         }, options, this));
  1101.                     }
  1102.  
  1103.                     searchItem.submit($.proxy(function () {
  1104.                         $('<input />').attr('type', 'hidden')
  1105.                             .attr('name', "filter")
  1106.                             .attr('value', this.filter)
  1107.                             .appendTo(this.element);
  1108.                         return true;
  1109.                     }, options, this))
  1110.                 }
  1111.             }
  1112.  
  1113.             if (plugins.searchResults.length) {
  1114.                 var regExp = /\?.*s=([^&]+)\&filter=([^&]+)/g;
  1115.                 var match = regExp.exec(location.search);
  1116.  
  1117.                 if (match !== null) {
  1118.                     $.get(handler, {
  1119.                         s: decodeURI(match[1]),
  1120.                         dataType: "html",
  1121.                         filter: match[2],
  1122.                         template: defaultTemplate,
  1123.                         live: ''
  1124.                     }, function (data) {
  1125.                         plugins.searchResults.html(data);
  1126.                     })
  1127.                 }
  1128.             }
  1129.         }
  1130.  
  1131.         // Add class in viewport
  1132.         if (plugins.viewAnimate.length) {
  1133.             for (var i = 0; i < plugins.viewAnimate.length; i++) {
  1134.                 var $view = $(plugins.viewAnimate[i]).not('.active');
  1135.                 $document.on("scroll", $.proxy(function () {
  1136.                     if (isScrolledIntoView(this)) {
  1137.                         this.addClass("active");
  1138.                     }
  1139.                 }, $view))
  1140.                     .trigger("scroll");
  1141.             }
  1142.         }
  1143.  
  1144.         // Swiper
  1145.         if (plugins.swiper.length) {
  1146.             for (var i = 0; i < plugins.swiper.length; i++) {
  1147.                 var s = $(plugins.swiper[i]);
  1148.                 var pag = s.find(".swiper-pagination"),
  1149.                     next = s.find(".swiper-button-next"),
  1150.                     prev = s.find(".swiper-button-prev"),
  1151.                     bar = s.find(".swiper-scrollbar"),
  1152.                     swiperSlide = s.find(".swiper-slide"),
  1153.                     autoplay = false;
  1154.  
  1155.                 for (var j = 0; j < swiperSlide.length; j++) {
  1156.                     var $this = $(swiperSlide[j]),
  1157.                         url;
  1158.  
  1159.                     if (url = $this.attr("data-slide-bg")) {
  1160.                         $this.css({
  1161.                             "background-image": "url(" + url + ")",
  1162.                             "background-size": "cover"
  1163.                         })
  1164.                     }
  1165.                 }
  1166.  
  1167.                 swiperSlide.end()
  1168.                     .find("[data-caption-animate]")
  1169.                     .addClass("not-animated")
  1170.                     .end();
  1171.  
  1172.                 s.swiper({
  1173.                     autoplay: !isNoviBuilder && $.isNumeric( s.attr('data-autoplay') ) ? s.attr('data-autoplay') : false,
  1174.                     direction: s.attr('data-direction') ? s.attr('data-direction') : "horizontal",
  1175.                     effect: s.attr('data-slide-effect') ? s.attr('data-slide-effect') : "slide",
  1176.                     speed: s.attr('data-slide-speed') ? s.attr('data-slide-speed') : 600,
  1177.                     keyboardControl: s.attr('data-keyboard') === "true",
  1178.                     mousewheelControl: s.attr('data-mousewheel') === "true",
  1179.                     mousewheelReleaseOnEdges: s.attr('data-mousewheel-release') === "true",
  1180.                     nextButton: next.length ? next.get(0) : null,
  1181.                     prevButton: prev.length ? prev.get(0) : null,
  1182.                     pagination: pag.length ? pag.get(0) : null,
  1183.                     paginationClickable: pag.length ? pag.attr("data-clickable") !== "false" : false,
  1184.                     paginationBulletRender: pag.length ? pag.attr("data-index-bullet") === "true" ? function (swiper, index, className) {
  1185.                         return '<span class="' + className + '">' + (index + 1) + '</span>';
  1186.                     } : null : null,
  1187.                     scrollbar: bar.length ? bar.get(0) : null,
  1188.                     scrollbarDraggable: bar.length ? bar.attr("data-draggable") !== "false" : true,
  1189.                     scrollbarHide: bar.length ? bar.attr("data-draggable") === "false" : false,
  1190.                     loop: isNoviBuilder ? false : s.attr('data-loop') !== "false",
  1191.                     simulateTouch: s.attr('data-simulate-touch') && !isNoviBuilder ? s.attr('data-simulate-touch') === "true" : false,
  1192.                     onTransitionStart: function (swiper) {
  1193.                         toggleSwiperInnerVideos(swiper);
  1194.                     },
  1195.                     onTransitionEnd: function (swiper) {
  1196.                         toggleSwiperCaptionAnimation(swiper);
  1197.                     },
  1198.                     onInit: function (swiper) {
  1199.                         toggleSwiperInnerVideos(swiper);
  1200.                         toggleSwiperCaptionAnimation(swiper);
  1201.                         initLightGalleryItem(s.find('[data-lightgallery="item"]'), 'lightGallery-in-carousel');
  1202.                     }
  1203.                 });
  1204.             }
  1205.         }
  1206.  
  1207.         // Owl carousel
  1208.         if ( plugins.owl.length ) {
  1209.             for ( var i = 0; i < plugins.owl.length; i++ ) {
  1210.                 var carousel = $( plugins.owl[ i ] );
  1211.                 plugins.owl[ i ].owl = carousel;
  1212.                 initOwlCarousel( carousel );
  1213.             }
  1214.         }
  1215.  
  1216.         // WOW
  1217.         if ($html.hasClass("wow-animation") && plugins.wow.length && !isNoviBuilder && isDesktop) {
  1218.             new WOW().init();
  1219.         }
  1220.  
  1221.         // RD Input Label
  1222.         if (plugins.rdInputLabel.length) {
  1223.             plugins.rdInputLabel.RDInputLabel();
  1224.         }
  1225.  
  1226.         // Regula
  1227.         if (plugins.regula.length) {
  1228.             attachFormValidator(plugins.regula);
  1229.         }
  1230.  
  1231.         // MailChimp Ajax subscription
  1232.         if (plugins.mailchimp.length) {
  1233.             for (i = 0; i < plugins.mailchimp.length; i++) {
  1234.                 var $mailchimpItem = $(plugins.mailchimp[i]),
  1235.                     $email = $mailchimpItem.find('input[type="email"]');
  1236.  
  1237.                 // Required by MailChimp
  1238.                 $mailchimpItem.attr('novalidate', 'true');
  1239.                 $email.attr('name', 'EMAIL');
  1240.  
  1241.                 $mailchimpItem.on('submit', $.proxy( function ( $email, event ) {
  1242.                     event.preventDefault();
  1243.  
  1244.                     var $this = this;
  1245.  
  1246.                     var data = {},
  1247.                         url = $this.attr('action').replace('/post?', '/post-json?').concat('&c=?'),
  1248.                         dataArray = $this.serializeArray(),
  1249.                         $output = $("#" + $this.attr("data-form-output"));
  1250.  
  1251.                     for (i = 0; i < dataArray.length; i++) {
  1252.                         data[dataArray[i].name] = dataArray[i].value;
  1253.                     }
  1254.  
  1255.                     $.ajax({
  1256.                         data: data,
  1257.                         url: url,
  1258.                         dataType: 'jsonp',
  1259.                         error: function (resp, text) {
  1260.                             $output.html('Server error: ' + text);
  1261.  
  1262.                             setTimeout(function () {
  1263.                                 $output.removeClass("active");
  1264.                             }, 4000);
  1265.                         },
  1266.                         success: function (resp) {
  1267.                             $output.html(resp.msg).addClass('active');
  1268.                             $email[0].value = '';
  1269.                             var $label = $('[for="'+ $email.attr( 'id' ) +'"]');
  1270.                             if ( $label.length ) $label.removeClass( 'focus not-empty' );
  1271.  
  1272.                             setTimeout(function () {
  1273.                                 $output.removeClass("active");
  1274.                             }, 6000);
  1275.                         },
  1276.                         beforeSend: function (data) {
  1277.                             var isNoviBuilder = window.xMode;
  1278.  
  1279.                             var isValidated = (function () {
  1280.                                 var results, errors = 0;
  1281.                                 var elements = $this.find('[data-constraints]');
  1282.                                 var captcha = null;
  1283.                                 if (elements.length) {
  1284.                                     for (var j = 0; j < elements.length; j++) {
  1285.  
  1286.                                         var $input = $(elements[j]);
  1287.                                         if ((results = $input.regula('validate')).length) {
  1288.                                             for (var k = 0; k < results.length; k++) {
  1289.                                                 errors++;
  1290.                                                 $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error");
  1291.                                             }
  1292.                                         } else {
  1293.                                             $input.siblings(".form-validation").text("").parent().removeClass("has-error")
  1294.                                         }
  1295.                                     }
  1296.  
  1297.                                     if (captcha) {
  1298.                                         if (captcha.length) {
  1299.                                             return validateReCaptcha(captcha) && errors === 0
  1300.                                         }
  1301.                                     }
  1302.  
  1303.                                     return errors === 0;
  1304.                                 }
  1305.                                 return true;
  1306.                             })();
  1307.  
  1308.                             // Stop request if builder or inputs are invalide
  1309.                             if (isNoviBuilder || !isValidated)
  1310.                                 return false;
  1311.  
  1312.                             $output.html('Submitting...').addClass('active');
  1313.                         }
  1314.                     });
  1315.  
  1316.                     return false;
  1317.                 }, $mailchimpItem, $email ));
  1318.             }
  1319.         }
  1320.  
  1321.         // Campaign Monitor ajax subscription
  1322.         if (plugins.campaignMonitor.length) {
  1323.             for (i = 0; i < plugins.campaignMonitor.length; i++) {
  1324.                 var $campaignItem = $(plugins.campaignMonitor[i]);
  1325.  
  1326.                 $campaignItem.on('submit', $.proxy(function (e) {
  1327.                     var data = {},
  1328.                         url = this.attr('action'),
  1329.                         dataArray = this.serializeArray(),
  1330.                         $output = $("#" + plugins.campaignMonitor.attr("data-form-output")),
  1331.                         $this = $(this);
  1332.  
  1333.                     for (i = 0; i < dataArray.length; i++) {
  1334.                         data[dataArray[i].name] = dataArray[i].value;
  1335.                     }
  1336.  
  1337.                     $.ajax({
  1338.                         data: data,
  1339.                         url: url,
  1340.                         dataType: 'jsonp',
  1341.                         error: function (resp, text) {
  1342.                             $output.html('Server error: ' + text);
  1343.  
  1344.                             setTimeout(function () {
  1345.                                 $output.removeClass("active");
  1346.                             }, 4000);
  1347.                         },
  1348.                         success: function (resp) {
  1349.                             $output.html(resp.Message).addClass('active');
  1350.  
  1351.                             setTimeout(function () {
  1352.                                 $output.removeClass("active");
  1353.                             }, 6000);
  1354.                         },
  1355.                         beforeSend: function (data) {
  1356.                             // Stop request if builder or inputs are invalide
  1357.                             if (isNoviBuilder || !isValidated($this.find('[data-constraints]')))
  1358.                                 return false;
  1359.  
  1360.                             $output.html('Submitting...').addClass('active');
  1361.                         }
  1362.                     });
  1363.  
  1364.                     // Clear inputs after submit
  1365.                     var inputs = $this[0].getElementsByTagName('input');
  1366.                     for (var i = 0; i < inputs.length; i++) {
  1367.                         inputs[i].value = '';
  1368.                         var label = document.querySelector( '[for="'+ inputs[i].getAttribute( 'id' ) +'"]' );
  1369.                         if( label ) label.classList.remove( 'focus', 'not-empty' );
  1370.                     }
  1371.  
  1372.                     return false;
  1373.                 }, $campaignItem));
  1374.             }
  1375.         }
  1376.  
  1377.         // RD Mailform
  1378.         if (plugins.rdMailForm.length) {
  1379.             var i, j, k,
  1380.                 msg = {
  1381.                     'MF000': 'Successfully sent!',
  1382.                     'MF001': 'Recipients are not set!',
  1383.                     'MF002': 'Form will not work locally!',
  1384.                     'MF003': 'Please, define email field in your form!',
  1385.                     'MF004': 'Please, define type of your form!',
  1386.                     'MF254': 'Something went wrong with PHPMailer!',
  1387.                     'MF255': 'Aw, snap! Something went wrong.'
  1388.                 };
  1389.  
  1390.             for (i = 0; i < plugins.rdMailForm.length; i++) {
  1391.                 var $form = $(plugins.rdMailForm[i]),
  1392.                     formHasCaptcha = false;
  1393.  
  1394.                 $form.attr('novalidate', 'novalidate').ajaxForm({
  1395.                     data: {
  1396.                         "form-type": $form.attr("data-form-type") || "contact",
  1397.                         "counter": i
  1398.                     },
  1399.                     beforeSubmit: function (arr, $form, options) {
  1400.                         if (isNoviBuilder)
  1401.                             return;
  1402.  
  1403.                         var form = $(plugins.rdMailForm[this.extraData.counter]),
  1404.                             inputs = form.find("[data-constraints]"),
  1405.                             output = $("#" + form.attr("data-form-output")),
  1406.                             captcha = form.find('.recaptcha'),
  1407.                             captchaFlag = true;
  1408.  
  1409.                         output.removeClass("active error success");
  1410.  
  1411.                         if (isValidated(inputs, captcha)) {
  1412.  
  1413.                             // veify reCaptcha
  1414.                             if (captcha.length) {
  1415.                                 var captchaToken = captcha.find('.g-recaptcha-response').val(),
  1416.                                     captchaMsg = {
  1417.                                         'CPT001': 'Please, setup you "site key" and "secret key" of reCaptcha',
  1418.                                         'CPT002': 'Something wrong with google reCaptcha'
  1419.                                     };
  1420.  
  1421.                                 formHasCaptcha = true;
  1422.  
  1423.                                 $.ajax({
  1424.                                     method: "POST",
  1425.                                     url: "bat/reCaptcha.php",
  1426.                                     data: {'g-recaptcha-response': captchaToken},
  1427.                                     async: false
  1428.                                 })
  1429.                                     .done(function (responceCode) {
  1430.                                         if (responceCode !== 'CPT000') {
  1431.                                             if (output.hasClass("snackbars")) {
  1432.                                                 output.html('<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + captchaMsg[responceCode] + '</span></p>')
  1433.  
  1434.                                                 setTimeout(function () {
  1435.                                                     output.removeClass("active");
  1436.                                                 }, 3500);
  1437.  
  1438.                                                 captchaFlag = false;
  1439.                                             } else {
  1440.                                                 output.html(captchaMsg[responceCode]);
  1441.                                             }
  1442.  
  1443.                                             output.addClass("active");
  1444.                                         }
  1445.                                     });
  1446.                             }
  1447.  
  1448.                             if (!captchaFlag) {
  1449.                                 return false;
  1450.                             }
  1451.  
  1452.                             form.addClass('form-in-process');
  1453.  
  1454.                             if (output.hasClass("snackbars")) {
  1455.                                 output.html('<p><span class="icon text-middle fa fa-circle-o-notch fa-spin icon-xxs"></span><span>Sending</span></p>');
  1456.                                 output.addClass("active");
  1457.                             }
  1458.                         } else {
  1459.                             return false;
  1460.                         }
  1461.                     },
  1462.                     error: function (result) {
  1463.                         if (isNoviBuilder)
  1464.                             return;
  1465.  
  1466.                         var output = $("#" + $(plugins.rdMailForm[this.extraData.counter]).attr("data-form-output")),
  1467.                             form = $(plugins.rdMailForm[this.extraData.counter]);
  1468.  
  1469.                         output.text(msg[result]);
  1470.                         form.removeClass('form-in-process');
  1471.  
  1472.                         if (formHasCaptcha) {
  1473.                             grecaptcha.reset();
  1474.                         }
  1475.                     },
  1476.                     success: function (result) {
  1477.                         if (isNoviBuilder)
  1478.                             return;
  1479.  
  1480.                         var form = $(plugins.rdMailForm[this.extraData.counter]),
  1481.                             output = $("#" + form.attr("data-form-output")),
  1482.                             select = form.find('select');
  1483.  
  1484.                         form
  1485.                             .addClass('success')
  1486.                             .removeClass('form-in-process');
  1487.  
  1488.                         if (formHasCaptcha) {
  1489.                             grecaptcha.reset();
  1490.                         }
  1491.  
  1492.                         result = result.length === 5 ? result : 'MF255';
  1493.                         output.text(msg[result]);
  1494.  
  1495.                         if (result === "MF000") {
  1496.                             if (output.hasClass("snackbars")) {
  1497.                                 output.html('<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + msg[result] + '</span></p>');
  1498.                             } else {
  1499.                                 output.addClass("active success");
  1500.                             }
  1501.                         } else {
  1502.                             if (output.hasClass("snackbars")) {
  1503.                                 output.html(' <p class="snackbars-left"><span class="icon icon-xxs mdi mdi-alert-outline text-middle"></span><span>' + msg[result] + '</span></p>');
  1504.                             } else {
  1505.                                 output.addClass("active error");
  1506.                             }
  1507.                         }
  1508.  
  1509.                         form.clearForm();
  1510.  
  1511.                         if (select.length) {
  1512.                             select.select2("val", "");
  1513.                         }
  1514.  
  1515.                         form.find('input, textarea').trigger('blur');
  1516.  
  1517.                         setTimeout(function () {
  1518.                             output.removeClass("active error success");
  1519.                             form.removeClass('success');
  1520.                         }, 3500);
  1521.                     }
  1522.                 });
  1523.             }
  1524.         }
  1525.  
  1526.         // lightGallery
  1527.         if (plugins.lightGallery.length) {
  1528.             for (var i = 0; i < plugins.lightGallery.length; i++) {
  1529.                 initLightGallery(plugins.lightGallery[i]);
  1530.             }
  1531.         }
  1532.  
  1533.         // lightGallery item
  1534.         if (plugins.lightGalleryItem.length) {
  1535.             // Filter carousel items
  1536.             var notCarouselItems = [];
  1537.  
  1538.             for (var z = 0; z < plugins.lightGalleryItem.length; z++) {
  1539.                 if (!$(plugins.lightGalleryItem[z]).parents('.owl-carousel').length &&
  1540.                     !$(plugins.lightGalleryItem[z]).parents('.swiper-slider').length &&
  1541.                     !$(plugins.lightGalleryItem[z]).parents('.slick-slider').length) {
  1542.                     notCarouselItems.push(plugins.lightGalleryItem[z]);
  1543.                 }
  1544.             }
  1545.  
  1546.             plugins.lightGalleryItem = notCarouselItems;
  1547.  
  1548.             for (var i = 0; i < plugins.lightGalleryItem.length; i++) {
  1549.                 initLightGalleryItem(plugins.lightGalleryItem[i]);
  1550.             }
  1551.         }
  1552.  
  1553.         // Dynamic lightGallery
  1554.         if (plugins.lightDynamicGalleryItem.length) {
  1555.             for (var i = 0; i < plugins.lightDynamicGalleryItem.length; i++) {
  1556.                 initDynamicLightGallery(plugins.lightDynamicGalleryItem[i]);
  1557.             }
  1558.         }
  1559.  
  1560.         // Custom Toggles
  1561.         if (plugins.customToggle.length) {
  1562.             for (var i = 0; i < plugins.customToggle.length; i++) {
  1563.                 var $this = $(plugins.customToggle[i]);
  1564.  
  1565.                 $this.on('click', $.proxy(function (event) {
  1566.                     event.preventDefault();
  1567.  
  1568.                     var $ctx = $(this);
  1569.                     $($ctx.attr('data-custom-toggle')).add(this).toggleClass('active');
  1570.                 }, $this));
  1571.  
  1572.                 if ($this.attr("data-custom-toggle-hide-on-blur") === "true") {
  1573.                     $body.on("click", $this, function (e) {
  1574.                         if (e.target !== e.data[0]
  1575.                             && $(e.data.attr('data-custom-toggle')).find($(e.target)).length
  1576.                             && e.data.find($(e.target)).length === 0) {
  1577.                             $(e.data.attr('data-custom-toggle')).add(e.data[0]).removeClass('active');
  1578.                         }
  1579.                     })
  1580.                 }
  1581.  
  1582.                 if ($this.attr("data-custom-toggle-disable-on-blur") === "true") {
  1583.                     $body.on("click", $this, function (e) {
  1584.                         if (e.target !== e.data[0] && $(e.data.attr('data-custom-toggle')).find($(e.target)).length === 0 && e.data.find($(e.target)).length === 0) {
  1585.                             $(e.data.attr('data-custom-toggle')).add(e.data[0]).removeClass('active');
  1586.                         }
  1587.                     })
  1588.                 }
  1589.             }
  1590.         }
  1591.  
  1592.         // TimeCircles
  1593.         if (plugins.dateCountdown.length) {
  1594.             for ( var i = 0; i < plugins.dateCountdown.length; i++ ) {
  1595.                 var
  1596.                     dateCountdownItem = $( plugins.dateCountdown[ i ] ),
  1597.                     countdownRender = function () {
  1598.                         dateCountdownItem.TimeCircles( {
  1599.                             time: { Seconds: { show: !( window.innerWidth < 768 ), } }
  1600.                         } ).rebuild();
  1601.                     };
  1602.  
  1603.                 dateCountdownItem.TimeCircles( {
  1604.                     color: dateCountdownItem.attr( "data-color" ) ? dateCountdownItem.attr( "data-color" ) : "rgba(247, 247, 247, 1)",
  1605.                     animation: "smooth",
  1606.                     bg_width: dateCountdownItem.attr( "data-bg-width" ) ? dateCountdownItem.attr( "data-bg-width" ) : 0.6,
  1607.                     circle_bg_color: dateCountdownItem.attr( "data-bg" ) ? dateCountdownItem.attr( "data-bg" ) : "rgba(0, 0, 0, 1)",
  1608.                     fg_width: dateCountdownItem.attr( "data-width" ) ? dateCountdownItem.attr( "data-width" ) : 0.03,
  1609.                     time: {
  1610.                         Days: {
  1611.                             text: "Days",
  1612.                             show: true,
  1613.                             color: dateCountdownItem.attr( "data-color" ) ? dateCountdownItem.attr( "data-color" ) : "#f9f9f9"
  1614.                         },
  1615.                         Hours: {
  1616.                             text: "Hours",
  1617.                             show: true,
  1618.                             color: dateCountdownItem.attr( "data-color" ) ? dateCountdownItem.attr( "data-color" ) : "#f9f9f9"
  1619.                         },
  1620.                         Minutes: {
  1621.                             text: "Minutes",
  1622.                             show: true,
  1623.                             color: dateCountdownItem.attr( "data-color" ) ? dateCountdownItem.attr( "data-color" ) : "#f9f9f9"
  1624.                         },
  1625.                         Seconds: {
  1626.                             text: "Seconds",
  1627.                             show: false,
  1628.                             color: dateCountdownItem.attr( "data-color" ) ? dateCountdownItem.attr( "data-color" ) : "#f9f9f9"
  1629.                         }
  1630.                     }
  1631.                 } );
  1632.  
  1633.                 countdownRender();
  1634.                 window.addEventListener( 'resize', countdownRender );
  1635.             }
  1636.         }
  1637.  
  1638.         // JQuery mousewheel plugin
  1639.         if (plugins.scroller.length) {
  1640.             for (var i = 0; i < plugins.scroller.length; i++) {
  1641.                 var scrollerItem = $(plugins.scroller[i]);
  1642.  
  1643.                 scrollerItem.mCustomScrollbar({
  1644.                     theme: scrollerItem.attr('data-theme') ? scrollerItem.attr('data-theme') : 'minimal',
  1645.                     scrollInertia: 100,
  1646.                     scrollButtons: {enable: false}
  1647.                 });
  1648.             }
  1649.         }
  1650.  
  1651.         /**
  1652.          * Jp Audio player
  1653.          * @description  Custom jPlayer script
  1654.          */
  1655.         if (plugins.jPlayerInit.length) {
  1656.  
  1657.             var artist = $('.jp-artist');
  1658.  
  1659.             // artist[0].innerText = artist[0].innerText.replace('by', 'from');
  1660.  
  1661.             $html.addClass('ontouchstart' in window || 'onmsgesturechange' in window ? 'touch' : 'no-touch');
  1662.  
  1663.             $.each(plugins.jPlayerInit, function (index, item) {
  1664.                 var player = item.querySelector('.jp-jplayer');
  1665.  
  1666.                 $(item).addClass('jp-audio-' + index);
  1667.  
  1668.                 var mediaObj = jpFormatePlaylistObj($(item).find('.jp-player-list .jp-player-list-item')),
  1669.                         playerInstance = initJplayerBase(index, item, mediaObj);
  1670.  
  1671.                 if ($(item).data('jp-player-name')) {
  1672.                     var customJpPlaylists = $('[data-jp-playlist-relative-to="' + $(item).data('jp-player-name') + '"]'),
  1673.                             playlistItems = customJpPlaylists.find("[data-jp-playlist-item]");
  1674.  
  1675.                     // Toggle audio play on custom playlist play button click
  1676.                     playlistItems.on('click', customJpPlaylists.data('jp-playlist-play-on'), function (e) {
  1677.                         var mediaObj = jpFormatePlaylistObj(playlistItems),
  1678.                                 $clickedItem = $(e.delegateTarget);
  1679.  
  1680.                         if (!JSON.stringify(playerInstance.playlist) === JSON.stringify(mediaObj) || !playerInstance.playlist.length) {
  1681.                             playerInstance.setPlaylist(mediaObj);
  1682.                         }
  1683.  
  1684.                         if (!$clickedItem.hasClass('playing')) {
  1685.                             playerInstance.pause();
  1686.  
  1687.                             if ($clickedItem.hasClass('last-played')) {
  1688.                                 playerInstance.play();
  1689.                             } else {
  1690.                                 playerInstance.play(playlistItems.index($clickedItem));
  1691.                             }
  1692.  
  1693.                             playlistItems.removeClass('playing last-played');
  1694.                             $clickedItem.addClass('playing');
  1695.                         } else {
  1696.                             playlistItems.removeClass('playing last-played');
  1697.                             $clickedItem.addClass('last-played');
  1698.                             playerInstance.pause();
  1699.                         }
  1700.  
  1701.                     });
  1702.  
  1703.  
  1704.                     // Callback for custom playlist
  1705.                     $(playerInstance.cssSelector.jPlayer).bind($.jPlayer.event.play, function (e) {
  1706.  
  1707.                         var toggleState = function (elemClass, index) {
  1708.                             var activeIndex = playlistItems.index(playlistItems.filter(elemClass));
  1709.  
  1710.                             if (activeIndex !== -1) {
  1711.                                 if (playlistItems.eq(activeIndex + index).length !== 0) {
  1712.                                     playlistItems.eq(activeIndex)
  1713.                                     .removeClass('play-next play-prev playing last-played')
  1714.                                     .end()
  1715.                                     .eq(activeIndex + index)
  1716.                                     .addClass('playing');
  1717.                                 }
  1718.                             }
  1719.                         };
  1720.  
  1721.                         // Check if user select next or prev track
  1722.                         toggleState('.play-next', +1);
  1723.                         toggleState('.play-prev', -1);
  1724.  
  1725.                         var lastPlayed = playlistItems.filter('.last-played');
  1726.  
  1727.                         // If user just press pause and than play on same track
  1728.                         if (lastPlayed.length) {
  1729.                             lastPlayed.addClass('playing').removeClass('last-played play-next');
  1730.                         }
  1731.                     });
  1732.  
  1733.  
  1734.                     // Add temp marker of last played audio
  1735.                     $(playerInstance.cssSelector.jPlayer).bind($.jPlayer.event.pause, function (e) {
  1736.                         playlistItems.filter('.playing').addClass('last-played').removeClass('playing');
  1737.  
  1738.                         $(playerInstance.cssSelector.cssSelectorAncestor).addClass('jp-state-visible');
  1739.                     });
  1740.  
  1741.                     // Add temp marker that user want to play next audio
  1742.                     $(item).find('.jp-next')
  1743.                     .on('click', function (e) {
  1744.                         playlistItems.filter('.playing, .last-played').addClass('play-next');
  1745.                     });
  1746.  
  1747.                     // Add temp marker that user want to play prev audio
  1748.                     $(item).find('.jp-previous')
  1749.                     .on('click', function (e) {
  1750.                         playlistItems.filter('.playing, .last-played').addClass('play-prev');
  1751.                     });
  1752.                 }
  1753.             });
  1754.  
  1755.         }
  1756.  
  1757.         /**
  1758.          * Instance CirclePlayer
  1759.          *
  1760.          * CirclePlayer(jPlayerSelector, media, options)
  1761.          *   jPlayerSelector: String - The css selector of the jPlayer div.
  1762.          *   media: Object - The media object used in jPlayer("setMedia",media).
  1763.          *   options: Object - The jPlayer options.
  1764.          *
  1765.          * @description  Multiple instances must set the cssSelectorAncestor in the jPlayer options.
  1766.          */
  1767.         if (plugins.circleJPlayer.length) {
  1768.             $.each(plugins.circleJPlayer, function (index, item) {
  1769.                 $(item).find('.cp-jplayer').addClass('cp-jplayer-' + index);
  1770.                 $(item).find('.cp-container').addClass('cp-container-' + index);
  1771.  
  1772.                 new CirclePlayer(".cp-jplayer-" + index,
  1773.                         {
  1774.                             oga: $(item).data('jp-oga'),
  1775.                             m4a: $(item).data('jp-m4a'),
  1776.                             mp3: $(item).data('jp-mp3')
  1777.                         }, {
  1778.                             cssSelectorAncestor: ".cp-container-" + index,
  1779.                             supplied: "mp3, m4a",
  1780.                             volume: 0.4
  1781.                         });
  1782.             });
  1783.         }
  1784.  
  1785.         /**
  1786.          * Jp Video player
  1787.          * @description  Custom jPlayer video initialization
  1788.          */
  1789.         if (plugins.jPlayerVideo.length) {
  1790.             $.each(plugins.jPlayerVideo, function (index, item) {
  1791.                 var $item = $(item);
  1792.  
  1793.                 $item.find('.jp-video').addClass('jp-video-' + index);
  1794.  
  1795.                 new jPlayerPlaylist({
  1796.                     jPlayer: item.getElementsByClassName("jp-jplayer")[0],
  1797.                     cssSelectorAncestor: ".jp-video-" + index // Need too bee a selector not HTMLElement or Jq object, so we make it unique
  1798.                 }, jpFormatePlaylistObj($(item).find('.jp-player-list .jp-player-list-item')), {
  1799.                     playlistOptions: {
  1800.                         enableRemoveControls: false
  1801.                     },
  1802.                     size: {
  1803.                         width: "100%",
  1804.                         height: "auto",
  1805.                     },
  1806.                     supplied: "webmv, ogv, m4v",
  1807.                     useStateClassSkin: true,
  1808.                     volume: 0.4
  1809.                 });
  1810.  
  1811.                 $(item).find(".jp-jplayer").on('click', function (e) {
  1812.                     var $this = $(this);
  1813.                     if ($('.jp-video-' + index).hasClass('jp-state-playing')) {
  1814.                         $this.jPlayer("pause");
  1815.                     } else {
  1816.                         $this.jPlayer("play");
  1817.                     }
  1818.                 });
  1819.  
  1820.                 var initialContainerWidth = $item.width();
  1821.                 // this is the overall page container, so whatever is relevant to your page
  1822.  
  1823.                 $window.resize(function () {
  1824.                     if ($item.width() !== initialContainerWidth) {
  1825.                         // checks current container size against it's rendered size on every resize.
  1826.                         initialContainerWidth = $item.width();
  1827.                         $item.trigger('resize', $item);
  1828.                         //pass off to resize listener for performance
  1829.                     }
  1830.                 });
  1831.             });
  1832.             $window.on('resize', function (e) {
  1833.                 $('.jp-video').each(function (index) {
  1834.                     // find every instance of jplayer using a class in their default markup
  1835.                     var $parentContainer = $(this).closest('.jp-video-init'),
  1836.                             // finds jplayers closest parent element from the ones you give it (can chain as many as you want)
  1837.                             containerWidth = $parentContainer.width(),
  1838.                             //takes the closest elements width
  1839.                             ARWidth = 1280,
  1840.                             ARHeight = 720;
  1841.                     // Width and height figures used to calculate the aspect ratio (will not restrict your players to this size)
  1842.                     var aspectRatio = ARHeight / ARWidth;
  1843.                     var videoHeight = Math.round(aspectRatio * containerWidth);
  1844.                     // calculates the appropriate height in rounded pixels using the aspect ratio
  1845.                     $(this).find('.jp-jplayer').width(containerWidth).height(videoHeight);
  1846.                     // and then apply the width and height!
  1847.                 });
  1848.             })
  1849.             .trigger('resize');
  1850.         }
  1851.         // jQuery Countdown
  1852.         if ( plugins.countDown.length ) {
  1853.             for ( var i = 0; i < plugins.countDown.length; i++) {
  1854.                 var $countDownItem = $( plugins.countDown[i] ),
  1855.                         settings = {
  1856.                             format: $countDownItem.attr('data-format'),
  1857.                             layout: $countDownItem.attr('data-layout')
  1858.                         };
  1859.                 if ( livedemo ) {
  1860.                     var d = new Date();
  1861.                     d.setDate(d.getDate() + 42);
  1862.                     settings[ $countDownItem.attr('data-type') ] = d;
  1863.                 } else {
  1864.                     settings[ $countDownItem.attr('data-type') ] = new Date( $countDownItem.attr( 'data-time' ) );
  1865.                 }
  1866.                 $countDownItem.countdown( settings );
  1867.             }
  1868.         }
  1869.         // Stepper
  1870.         if (plugins.stepper.length) {
  1871.             plugins.stepper.stepper({
  1872.                 labels: {
  1873.                     up: "",
  1874.                     down: ""
  1875.                 }
  1876.             });
  1877.         }
  1878.         // Slick carousel
  1879.         if (plugins.slick.length) {
  1880.             for (var i = 0; i < plugins.slick.length; i++) {
  1881.                 var $slickItem = $(plugins.slick[i]);
  1882.                 $slickItem.on('init', function (slick) {
  1883.                     initLightGallery($('[data-lightgallery="group-slick"]'), 'lightGallery-in-carousel');
  1884.                     initLightGallery($('[data-lightgallery="item-slick"]'), 'lightGallery-in-carousel');
  1885.                 });
  1886.                 $slickItem.slick({
  1887.                     slidesToScroll: parseInt($slickItem.attr('data-slide-to-scroll'), 10) || 1,
  1888.                     asNavFor: $slickItem.attr('data-for') || false,
  1889.                     dots: $slickItem.attr("data-dots") === "true",
  1890.                     infinite: isNoviBuilder ? false : $slickItem.attr("data-loop") === "true",
  1891.                     focusOnSelect: true,
  1892.                     arrows: $slickItem.attr("data-arrows") === "true",
  1893.                     swipe: $slickItem.attr("data-swipe") === "true",
  1894.                     autoplay: $slickItem.attr("data-autoplay") === "true",
  1895.                     vertical: $slickItem.attr("data-vertical") === "true",
  1896.                     centerMode: $slickItem.attr("data-center-mode") === "true",
  1897.                     centerPadding: $slickItem.attr("data-center-padding") ? $slickItem.attr("data-center-padding") : '0.50',
  1898.                     mobileFirst: true,
  1899.                     responsive: [
  1900.                         {
  1901.                             breakpoint: 0,
  1902.                             settings: {
  1903.                                 slidesToShow: parseInt($slickItem.attr('data-items'), 10) || 1
  1904.                             }
  1905.                         },
  1906.                         {
  1907.                             breakpoint: 575,
  1908.                             settings: {
  1909.                                 slidesToShow: parseInt($slickItem.attr('data-sm-items'), 10) || 1
  1910.                             }
  1911.                         },
  1912.                         {
  1913.                             breakpoint: 767,
  1914.                             settings: {
  1915.                                 slidesToShow: parseInt($slickItem.attr('data-md-items'), 10) || 1
  1916.                             }
  1917.                         },
  1918.                         {
  1919.                             breakpoint: 991,
  1920.                             settings: {
  1921.                                 slidesToShow: parseInt($slickItem.attr('data-lg-items'), 10) || 1
  1922.                             }
  1923.                         },
  1924.                         {
  1925.                             breakpoint: 1199,
  1926.                             settings: {
  1927.                                 slidesToShow: parseInt($slickItem.attr('data-xl-items'), 10) || 1
  1928.                             }
  1929.                         }
  1930.                     ]
  1931.                 })
  1932.                 .on('afterChange', function (event, slick, currentSlide, nextSlide) {
  1933.                     var $this = $(this),
  1934.                             childCarousel = $this.attr('data-child');
  1935.                     if (childCarousel) {
  1936.                         $(childCarousel + ' .slick-slide').removeClass('slick-current');
  1937.                         $(childCarousel + ' .slick-slide').eq(currentSlide).addClass('slick-current');
  1938.                     }
  1939.                 });
  1940.             }
  1941.         }
  1942.         // Vide
  1943.         if ( plugins.vide.length ) {
  1944.             for ( var i = 0; i < plugins.vide.length; i++ ) {
  1945.                 var $element = $(plugins.vide[i]),
  1946.                         options = $element.data('vide-options'),
  1947.                         path = $element.data('vide-bg');
  1948.                 $element.vide( path, options );
  1949.                 var
  1950.                         videObj = $element.data('vide').getVideoObject(),
  1951.                         scrollHandler = (function( $element ) {
  1952.                             if ( isScrolledIntoView( $element ) ) this.play();
  1953.                             else this.pause();
  1954.                         }).bind( videObj, $element );
  1955.                 scrollHandler();
  1956.                 if ( isNoviBuilder ) videObj.pause();
  1957.                 else document.addEventListener( 'scroll', scrollHandler );
  1958.             }
  1959.         }
  1960.         // Custom Waypoints
  1961.         if (plugins.customWaypoints.length && !isNoviBuilder) {
  1962.             var i;
  1963.             for (i = 0; i < plugins.customWaypoints.length; i++) {
  1964.                 var $this = $(plugins.customWaypoints[i]);
  1965.                 $this.on('click', function (e) {
  1966.                     e.preventDefault();
  1967.                     $("body, html").stop().animate({
  1968.                         scrollTop: $("#" + $(this).attr('data-custom-scroll-to')).offset().top
  1969.                     }, 1000, function () {
  1970.                         $window.trigger("resize");
  1971.                     });
  1972.                 });
  1973.             }
  1974.         }
  1975.     });
  1976. }());
Advertisement
Add Comment
Please, Sign In to add comment