PageSourceSearch

https://www.ottawa-translations.com/js/script.js

js ottawa-translations.com collected 2026-10-04 03:14:42 UTC 64,036 bytes, 1,765 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.