PageSourceSearch

https://forum-game.com/themes/jiu-you-hui-jiao-liu-lun-tan-you-xi-wan-jia-ju-le-bu/static/js/script.js

js forum-game.com collected 2026-10-08 02:10:18 UTC 64,638 bytes, 1,929 lines download raw bytes

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

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