PageSourceSearch

https://sebacs.com/js/script.js

js sebacs.com collected 2026-10-05 22:02:12 UTC 27,598 bytes, 850 lines download raw bytes

1/**
2 * Global variables
3 */
4"use strict";
5
6var userAgent = navigator.userAgent.toLowerCase(),
7	initialDate = new Date(),
8
9	$document = $( document ),
10	$window = $(window),
11	$html = $( "html" ),
12
13	isDesktop = $html.hasClass( "desktop" ),
14	isIE = userAgent.indexOf( "msie" ) != -1 ? parseInt( userAgent.split( "msie" )[ 1 ] ) : 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,
17
18	plugins = {
19		responsiveTabs: $( ".responsive-tabs" ),
20		rdInputLabel: $( ".form-label" ),
21		rdNavbar: $( ".rd-navbar" ),
22		regula: $( "[data-constraints]" ),
23		photoSwipeGallery: $( "[data-photo-swipe-item]" ),
24		isotope: $( ".isotope" ),
25		customToggle: $( "[data-custom-toggle]" ),
26		search: $( ".rd-search" ),
27		searchResults: $( '.rd-search-results' ),
28		rdMailForm: $( ".rd-mailform" ),
29		copyrightYear: $( "#copyright-year" ),
30		materialParallax: $( ".parallax-container" ),
31		maps: $( ".google-map-container" ),
32		lightGallery: $( "[data-lightgallery='group']" ),
33		lightGalleryItem: $( "[data-lightgallery='item']" ),
34		lightDynamicGalleryItem: $( "[data-lightgallery='dynamic']" )
35	};
36
37
38/**
39 * @desc Check the element was been scrolled into the view
40 * @param {object} elem - jQuery object
41 * @return {boolean}
42 */
43function isScrolledIntoView ( elem ) {
44	if ( isNoviBuilder ) return true;
45	return elem.offset().top + elem.outerHeight() >= $window.scrollTop() && elem.offset().top <= $window.scrollTop() + $window.height();
46}
47
48/**
49 * @desc Calls a function when element has been scrolled into the view
50 * @param {object} element - jQuery object
51 * @param {function} func - init function
52 */
53function lazyInit( element, func ) {
54	var scrollHandler = function () {
55		if ( ( !element.hasClass( 'lazy-loaded' ) && ( isScrolledIntoView( element ) ) ) ) {
56			func.call();
57			element.addClass( 'lazy-loaded' );
58		}
59	};
60
61	scrollHandler();
62	$window.on( 'scroll', scrollHandler );
63}
64/**
65 * Initialize All Scripts
66 */
67$document.ready( function () {
68	isNoviBuilder = window.xMode;
69
70	
71	
72	/**
73	 * Google map function for getting latitude and longitude
74	 */
75	function getLatLngObject(str, marker, map, callback) {
76		var coordinates = {};
77		try {
78			coordinates = JSON.parse(str);
79			callback(new google.maps.LatLng(
80				coordinates.lat,
81				coordinates.lng
82			), marker, map)
83		} catch (e) {
84			map.geocoder.geocode({'address': str}, function (results, status) {
85				if (status === google.maps.GeocoderStatus.OK) {
86					var latitude = results[0].geometry.location.lat();
87					var longitude = results[0].geometry.location.lng();
88
89					callback(new google.maps.LatLng(
90						parseFloat(latitude),
91						parseFloat(longitude)
92					), marker, map)
93				}
94			})
95		}
96	}
97
98	function initMaps() {
99		var key;
100
101		for ( var i = 0; i < plugins.maps.length; i++ ) {
102			if ( plugins.maps[i].hasAttribute( "data-key" ) ) {
103				key = plugins.maps[i].getAttribute( "data-key" );
104				break;
105			}
106		}
107
108		$.getScript('//maps.google.com/maps/api/js?'+ ( key ? 'key='+ key + '&' : '' ) +'sensor=false&libraries=geometry,places&v=quarterly', function () {
109			var head = document.getElementsByTagName('head')[0],
110				insertBefore = head.insertBefore;
111
112			head.insertBefore = function (newElement, referenceElement) {
113				if (newElement.href && newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') !== -1 || newElement.innerHTML.indexOf('gm-style') !== -1) {
114					return;
115				}
116				insertBefore.call(head, newElement, referenceElement);
117			};
118			var geocoder = new google.maps.Geocoder;
119			for (var i = 0; i < plugins.maps.length; i++) {
120				var zoom = parseInt(plugins.maps[i].getAttribute("data-zoom"), 10) || 11;
121				var styles = plugins.maps[i].hasAttribute('data-styles') ? JSON.parse(plugins.maps[i].getAttribute("data-styles")) : [];
122				var center = plugins.maps[i].getAttribute("data-center") || "New York";
123
124				// Initialize map
125				var map = new google.maps.Map(plugins.maps[i].querySelectorAll(".google-map")[0], {
126					zoom: zoom,
127					styles: styles,
128					scrollwheel: false,
129					center: {lat: 0, lng: 0}
130				});
131
132				// Add map object to map node
133				plugins.maps[i].map = map;
134				plugins.maps[i].geocoder = geocoder;
135				plugins.maps[i].keySupported = true;
136				plugins.maps[i].google = google;
137
138				// Get Center coordinates from attribute
139				getLatLngObject(center, null, plugins.maps[i], function (location, markerElement, mapElement) {
140					mapElement.map.setCenter(location);
141				});
142
143				// Add markers from google-map-markers array
144				var markerItems = plugins.maps[i].querySelectorAll(".google-map-markers li");
145
146				if (markerItems.length){
147					var markers = [];
148					for (var j = 0; j < markerItems.length; j++){
149						var markerElement = markerItems[j];
150						getLatLngObject(markerElement.getAttribute("data-location"), markerElement, plugins.maps[i], function(location, markerElement, mapElement){
151							var icon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon");
152							var activeIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active");
153							var info = markerElement.getAttribute("data-description") || "";
154							var infoWindow = new google.maps.InfoWindow({
155								content: info
156							});
157							markerElement.infoWindow = infoWindow;
158							var markerData = {
159								position: location,
160								map: mapElement.map
161							}
162							if (icon){
163								markerData.icon = icon;
164							}
165							var marker = new google.maps.Marker(markerData);
166							markerElement.gmarker = marker;
167							markers.push({markerElement: markerElement, infoWindow: infoWindow});
168							marker.isActive = false;
169							// Handle infoWindow close click
170							google.maps.event.addListener(infoWindow,'closeclick',(function(markerElement, mapElement){
171								var markerIcon = null;
172								markerElement.gmarker.isActive = false;
173								markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon");
174								markerElement.gmarker.setIcon(markerIcon);
175							}).bind(this, markerElement, mapElement));
176
177
178							// Set marker active on Click and open infoWindow
179							google.maps.event.addListener(marker, 'click', (function(markerElement, mapElement) {
180								if (markerElement.infoWindow.getContent().length === 0) return;
181								var gMarker, currentMarker = markerElement.gmarker, currentInfoWindow;
182								for (var k =0; k < markers.length; k++){
183									var markerIcon;
184									if (markers[k].markerElement === markerElement){
185										currentInfoWindow = markers[k].infoWindow;
186									}
187									gMarker = markers[k].markerElement.gmarker;
188									if (gMarker.isActive && markers[k].markerElement !== markerElement){
189										gMarker.isActive = false;
190										markerIcon = markers[k].markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon")
191										gMarker.setIcon(markerIcon);
192										markers[k].infoWindow.close();
193									}
194								}
195
196								currentMarker.isActive = !currentMarker.isActive;
197								if (currentMarker.isActive) {
198									if (markerIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active")){
199										currentMarker.setIcon(markerIcon);
200									}
201
202									currentInfoWindow.open(map, marker);
203								}else{
204									if (markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon")){
205										currentMarker.setIcon(markerIcon);
206									}
207									currentInfoWindow.close();
208								}
209							}).bind(this, markerElement, mapElement))
210						})
211					}
212				}
213			}
214		});
215	}
216
217
218	// Google maps
219	if( plugins.maps.length ) {
220		lazyInit( plugins.maps, initMaps ); 
221	}
222	/**
223	 * Live Search
224	 * @description  create live search results
225	 */
226	function liveSearch ( options ) {
227		$( '#' + options.live ).removeClass( 'cleared' ).html();
228		options.current++;
229		options.spin.addClass( 'loading' );
230		$.get( handler, {
231			s: decodeURI( options.term ),
232			liveSearch: options.live,
233			dataType: "html",
234			liveCount: options.liveCount,
235			filter: options.filter,
236			template: options.template
237		}, function ( data ) {
238			options.processed++;
239			var live = $( '#' + options.live );
240			if ( options.processed == options.current && !live.hasClass( 'cleared' ) ) {
241				live.find( '> #search-results' ).removeClass( 'active' );
242				live.html( data );
243				setTimeout( function () {
244					live.find( '> #search-results' ).addClass( 'active' );
245				}, 50 );
246			}
247			options.spin.parents( '.rd-search' ).find( '.input-group-addon' ).removeClass( 'loading' );
248		} )
249	}
250
251	/**
252	 * attachFormValidator
253	 * @description  attach form validation to elements
254	 */
255	function attachFormValidator ( elements ) {
256		for ( var i = 0; i < elements.length; i++ ) {
257			var o = $( elements[ i ] ), v;
258			o.addClass( "form-control-has-validation" ).after( "<span class='form-validation'></span>" );
259			v = o.parent().find( ".form-validation" );
260			if ( v.is( ":last-child" ) ) {
261				o.addClass( "form-control-last-child" );
262			}
263		}
264
265		elements
266			.on( 'input change propertychange blur', function ( e ) {
267				var $this = $( this ), results;
268
269				if ( e.type !== "blur" ) {
270					if ( !$this.parent().hasClass( "has-error" ) ) {
271						return;
272					}
273				}
274
275				if ( $this.parents( '.rd-mailform' ).hasClass( 'success' ) ) {
276					return;
277				}
278
279				if ( (results = $this.regula( 'validate' )).length ) {
280					for ( i = 0; i < results.length; i++ ) {
281						$this.siblings( ".form-validation" ).text( results[ i ].message ).parent().addClass( "has-error" )
282					}
283				} else {
284					$this.siblings( ".form-validation" ).text( "" ).parent().removeClass( "has-error" )
285				}
286			} )
287			.regula( 'bind' );
288
289		var regularConstraintsMessages = [
290			{
291				type: regula.Constraint.Required,
292				newMessage: "The text field is required."
293			},
294			{
295				type: regula.Constraint.Email,
296				newMessage: "The email is not a valid email."
297			},
298			{
299				type: regula.Constraint.Numeric,
300				newMessage: "Only numbers are required"
301			},
302			{
303				type: regula.Constraint.Selected,
304				newMessage: "Please choose an option."
305			}
306		];
307
308		for ( var i = 0; i < regularConstraintsMessages.length; i++ ) {
309			var regularConstraint = regularConstraintsMessages[ i ];
310
311			regula.override( {
312				constraintType: regularConstraint.type,
313				defaultMessage: regularConstraint.newMessage
314			} );
315		}
316	}
317
318	/**
319	 * isValidated
320	 * @description  check if all elemnts pass validation
321	 */
322	function isValidated ( elements, captcha ) {
323		var results, errors = 0;
324
325		if ( elements.length ) {
326			for ( j = 0; j < elements.length; j++ ) {
327
328				var $input = $( elements[ j ] );
329				if ( (results = $input.regula( 'validate' )).length ) {
330					for ( k = 0; k < results.length; k++ ) {
331						errors++;
332						$input.siblings( ".form-validation" ).text( results[ k ].message ).parent().addClass( "has-error" );
333					}
334				} else {
335					$input.siblings( ".form-validation" ).text( "" ).parent().removeClass( "has-error" )
336				}
337			}
338
339			if ( captcha ) {
340				if ( captcha.length ) {
341					return validateReCaptcha( captcha ) && errors == 0
342				}
343			}
344
345			return errors == 0;
346		}
347		return true;
348	}
349
350	/**
351	 * validateReCaptcha
352	 * @description  validate google reCaptcha
353	 */
354	function validateReCaptcha ( captcha ) {
355		var captchaToken = captcha.find( '.g-recaptcha-response' ).val();
356
357		if ( captchaToken.length === 0 ) {
358			captcha
359				.siblings( '.form-validation' )
360				.html( 'Please, prove that you are not robot.' )
361				.addClass( 'active' );
362			captcha
363				.closest( '.form-group' )
364				.addClass( 'has-error' );
365
366			captcha.on( 'propertychange', function () {
367				var $this = $( this ),
368					captchaToken = $this.find( '.g-recaptcha-response' ).val();
369
370				if ( captchaToken.length > 0 ) {
371					$this
372						.closest( '.form-group' )
373						.removeClass( 'has-error' );
374					$this
375						.siblings( '.form-validation' )
376						.removeClass( 'active' )
377						.html( '' );
378					$this.off( 'propertychange' );
379				}
380			} );
381
382			return false;
383		}
384
385		return true;
386	}
387
388	/**
389	 * onloadCaptchaCallback
390	 * @description  init google reCaptcha
391	 */
392	window.onloadCaptchaCallback = function () {
393		for ( i = 0; i < plugins.captcha.length; i++ ) {
394			var $capthcaItem = $( plugins.captcha[ i ] );
395
396			grecaptcha.render(
397				$capthcaItem.attr( 'id' ),
398				{
399					sitekey: $capthcaItem.attr( 'data-sitekey' ),
400					size: $capthcaItem.attr( 'data-size' ) ? $capthcaItem.attr( 'data-size' ) : 'normal',
401					theme: $capthcaItem.attr( 'data-theme' ) ? $capthcaItem.attr( 'data-theme' ) : 'light',
402					callback: function ( e ) {
403						$( '.recaptcha' ).trigger( 'propertychange' );
404					}
405				}
406			);
407			$capthcaItem.after( "<span class='form-validation'></span>" );
408		}
409	};
410
411	// IE Classes
412	if ( isIE ) {
413		if ( isIE < 10 ) $html.addClass( "lt-ie-10" );
414		if ( isIE < 11 ) $html.addClass( "ie-10" );
415		if ( isIE === 11 ) $( "html" ).addClass( "ie-11" );
416		if ( isIE >= 12 ) $( "html" ).addClass( "ie-edge" );
417	}
418
419	// Copyright Year
420	if ( plugins.copyrightYear.length ) {
421		plugins.copyrightYear.text( initialDate.getFullYear() );
422	}
423
424	// Responsive Tabs
425	if ( plugins.responsiveTabs.length ) {
426		var i = 0;
427		for ( i = 0; i < plugins.responsiveTabs.length; i++ ) {
428			var $this = $( plugins.responsiveTabs[ i ] );
429			$this.easyResponsiveTabs( {
430				type: $this.attr( "data-type" ),
431				tabidentify: $this.find( ".resp-tabs-list" ).attr( "data-group" ) || "tab"
432			} );
433		}
434	}
435
436	// RD Input Label
437	if ( plugins.rdInputLabel.length ) {
438		plugins.rdInputLabel.RDInputLabel();
439	}
440
441	// Regula
442	if ( plugins.regula.length ) {
443		attachFormValidator( plugins.regula );
444	}
445
446	// WOW
447	if ( !isNoviBuilder && $html.hasClass( 'desktop' ) && $html.hasClass( "wow-animation" ) && $( ".wow" ).length ) {
448		new WOW().init();
449	}
450
451	// Isotope
452	if ( plugins.isotope.length ) {
453		var i, isogroup = [];
454		for ( i = 0; i < plugins.isotope.length; i++ ) {
455			var
456				isotopeItem = plugins.isotope[ i ],
457				iso = new Isotope( isotopeItem, {
458					itemSelector: '.isotope-item',
459					layoutMode: isotopeItem.getAttribute( 'data-isotope-layout' ) ? isotopeItem.getAttribute( 'data-isotope-layout' ) : 'masonry',
460					filter: '*'
461				} );
462
463			isogroup.push( iso );
464		}
465
466		setTimeout( function () {
467			for ( var i = 0; i < isogroup.length; i++ ) {
468				var isotope = isogroup[ i ];
469				isotope.element.className += " isotope--loaded";
470				isotope.layout();
471				window.addEventListener( 'resize', (function () {
472					this.layout();
473				}).bind( isotope ) );
474			}
475		}, 600 );
476
477		$( "[data-isotope-filter]" ).on( "click", function ( e ) {
478			e.preventDefault();
479			var filter = $( this );
480			filter.parents( ".isotope-filters" ).find( '.active' ).removeClass( "active" );
481			filter.addClass( "active" );
482			var iso = $( '.isotope[data-isotope-group="' + this.getAttribute( "data-isotope-group" ) + '"]' );
483			iso.isotope( {
484				itemSelector: '.isotope-item',
485				layoutMode: iso.attr( 'data-isotope-layout' ) ? iso.attr( 'data-isotope-layout' ) : 'masonry',
486				filter: this.getAttribute( "data-isotope-filter" ) == '*' ? '*' : '[data-filter*="' + this.getAttribute( "data-isotope-filter" ) + '"]'
487			} );
488		} ).eq( 0 ).trigger( "click" );
489
490
491	}
492
493	// RD Navbar
494	if ( plugins.rdNavbar.length ) {
495		var navbar = plugins.rdNavbar,
496			aliases = { '0': '-', '480': '-xs-', '768': '-sm-', '992': '-md-', '1200': '-lg-' },
497			responsiveNavbar = {};
498
499		for ( var alias in aliases ) {
500			responsiveNavbar[ alias ] = {};
501			if ( navbar.attr( 'data' + aliases[ alias ] + 'layout' ) ) responsiveNavbar[ alias ].layout = navbar.attr( 'data' + aliases[ alias ] + 'layout' );
502			else responsiveNavbar[ alias ].layout = 'rd-navbar-fixed';
503			if ( navbar.attr( 'data' + aliases[ alias ] + 'device-layout' ) ) responsiveNavbar[ alias ].deviceLayout = navbar.attr( 'data' + aliases[ alias ] + 'device-layout' );
504			else responsiveNavbar[ alias ].deviceLayout = 'rd-navbar-fixed';
505			if ( navbar.attr( 'data' + aliases[ alias ] + 'hover-on' ) ) responsiveNavbar[ alias ].focusOnHover = navbar.attr( 'data' + aliases[ alias ] + 'hover-on' ) === 'true';
506			if ( navbar.attr( 'data' + aliases[ alias ] + 'auto-height' ) ) responsiveNavbar[ alias ].autoHeight = navbar.attr( 'data' + aliases[ alias ] + 'auto-height' ) === 'true';
507			if ( navbar.attr( 'data' + aliases[ alias ] + 'stick-up-offset' ) ) responsiveNavbar[ alias ].stickUpOffset = navbar.attr( 'data' + aliases[ alias ] + 'stick-up-offset' );
508			if ( navbar.attr( 'data' + aliases[ alias ] + 'stick-up' ) && !isNoviBuilder ) responsiveNavbar[ alias ].stickUp = navbar.attr( 'data' + aliases[ alias ] + 'stick-up' ) === 'true';
509			else responsiveNavbar[ alias ].stickUp = false;
510
511			if ( $.isEmptyObject( responsiveNavbar[ alias ] ) ) delete responsiveNavbar[ alias ];
512		}
513
514		navbar.RDNavbar( {
515			stickUpClone: ( !isNoviBuilder && navbar.attr( "data-stick-up-clone" ) ) ? navbar.attr( "data-stick-up-clone" ) === 'true' : false,
516			stickUpOffset: ( navbar.attr( "data-stick-up-offset" ) ) ? navbar.attr( "data-stick-up-offset" ) : 1,
517			anchorNavOffset: -78,
518			anchorNav: !isNoviBuilder,
519			anchorNavEasing: 'linear',
520			focusOnHover: !isNoviBuilder,
521			responsive: responsiveNavbar,
522			onDropdownOver: function () {
523				return !isNoviBuilder;
524			}
525		} );
526
527		if ( navbar.attr( "data-body-class" ) ) {
528			document.body.className += ' ' + navbar.attr( "data-body-class" );
529		}
530	}
531
532	// RD Search
533	if ( plugins.search.length || plugins.searchResults ) {
534		var handler = "bat/rd-search.php";
535		var defaultTemplate = '<h5 class="search_title"><a target="_top" href="#{href}" class="search_link">#{title}</a></h5>' +
536			'<p>...#{token}...</p>' +
537			'<p class="match"><em>Terms matched: #{count} - URL: #{href}</em></p>';
538		var defaultFilter = '*.html';
539
540		if ( plugins.search.length ) {
541
542			for ( i = 0; i < plugins.search.length; i++ ) {
543				var searchItem = $( plugins.search[ i ] ),
544					options = {
545						element: searchItem,
546						filter: (searchItem.attr( 'data-search-filter' )) ? searchItem.attr( 'data-search-filter' ) : defaultFilter,
547						template: (searchItem.attr( 'data-search-template' )) ? searchItem.attr( 'data-search-template' ) : defaultTemplate,
548						live: (searchItem.attr( 'data-search-live' )) ? searchItem.attr( 'data-search-live' ) : false,
549						liveCount: (searchItem.attr( 'data-search-live-count' )) ? parseInt( searchItem.attr( 'data-search-live' ) ) : 4,
550						current: 0, processed: 0, timer: {}
551					};
552
553				if ( $( '.rd-navbar-search-toggle' ).length ) {
554					var toggle = $( '.rd-navbar-search-toggle' );
555					toggle.on( 'click', function () {
556						if ( !($( this ).hasClass( 'active' )) ) {
557							searchItem.find( 'input' ).val( '' ).trigger( 'propertychange' );
558						}
559					} );
560				}
561
562				if ( options.live ) {
563					searchItem.find( 'input' ).on( "keyup input propertychange", $.proxy( function () {
564						this.term = this.element.find( 'input' ).val().trim();
565						this.spin = this.element.find( '.input-group-addon' );
566						clearTimeout( this.timer );
567
568						if ( this.term.length > 2 ) {
569							this.timer = setTimeout( liveSearch( this ), 200 );
570						} else if ( this.term.length == 0 ) {
571							$( '#' + this.live ).addClass( 'cleared' ).html( '' );
572						}
573					}, options, this ) );
574				}
575
576				searchItem.submit( $.proxy( function () {
577					$( '<input />' ).attr( 'type', 'hidden' )
578						.attr( 'name', "filter" )
579						.attr( 'value', this.filter )
580						.appendTo( this.element );
581					return true;
582				}, options, this ) )
583			}
584		}
585
586		if ( plugins.searchResults.length ) {
587			var regExp = /\?.*s=([^&]+)\&filter=([^&]+)/g;
588			var match = regExp.exec( location.search );
589
590			if ( match != null ) {
591				$.get( handler, {
592					s: decodeURI( match[ 1 ] ),
593					dataType: "html",
594					filter: match[ 2 ],
595					template: defaultTemplate,
596					live: ''
597				}, function ( data ) {
598					plugins.searchResults.html( data );
599				} )
600			}
601		}
602	}
603
604	// UI To Top
605	if ( !isNoviBuilder && isDesktop ) {
606		$().UItoTop( {
607			easingType: 'easeOutQuart',
608			containerClass: 'ui-to-top icon icon-xs icon-circle icon-darker-filled mdi mdi-chevron-up'
609		} );
610	}
611
612	// RD Mailform
613	if ( plugins.rdMailForm.length ) {
614		var i, j, k,
615			msg = {
616				'MF000': 'Successfully sent!',
617				'MF001': 'Recipients are not set!',
618				'MF002': 'Form will not work locally!',
619				'MF003': 'Please, define email field in your form!',
620				'MF004': 'Please, define type of your form!',
621				'MF254': 'Something went wrong with PHPMailer!',
622				'MF255': 'Aw, snap! Something went wrong.'
623			};
624
625		for ( i = 0; i < plugins.rdMailForm.length; i++ ) {
626			var $form = $( plugins.rdMailForm[ i ] ),
627				formHasCaptcha = false;
628
629			$form.attr( 'novalidate', 'novalidate' ).ajaxForm( {
630				data: {
631					"form-type": $form.attr( "data-form-type" ) || "contact",
632					"counter": i
633				},
634				beforeSubmit: function ( arr, $form, options ) {
635
636					var form = $( plugins.rdMailForm[ this.extraData.counter ] ),
637						inputs = form.find( "[data-constraints]" ),
638						output = $( "#" + form.attr( "data-form-output" ) ),
639						captcha = form.find( '.recaptcha' ),
640						captchaFlag = true;
641
642					output.removeClass( "active error success" );
643
644					if ( isValidated( inputs, captcha ) ) {
645
646						// veify reCaptcha
647						if ( captcha.length ) {
648							var captchaToken = captcha.find( '.g-recaptcha-response' ).val(),
649								captchaMsg = {
650									'CPT001': 'Please, setup you "site key" and "secret key" of reCaptcha',
651									'CPT002': 'Something wrong with google reCaptcha'
652								};
653
654							formHasCaptcha = true;
655
656							$.ajax( {
657								method: "POST",
658								url: "bat/reCaptcha.php",
659								data: { 'g-recaptcha-response': captchaToken },
660								async: false
661							} )
662								.done( function ( responceCode ) {
663									if ( responceCode !== 'CPT000' ) {
664										if ( output.hasClass( "snackbars" ) ) {
665											output.html( '<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + captchaMsg[ responceCode ] + '</span></p>' )
666
667											setTimeout( function () {
668												output.removeClass( "active" );
669											}, 3500 );
670
671											captchaFlag = false;
672										} else {
673											output.html( captchaMsg[ responceCode ] );
674										}
675
676										output.addClass( "active" );
677									}
678								} );
679						}
680
681						if ( !captchaFlag ) {
682							return false;
683						}
684
685						form.addClass( 'form-in-process' );
686
687						if ( output.hasClass( "snackbars" ) ) {
688							output.html( '<p><span class="icon text-middle fa fa-circle-o-notch fa-spin icon-xxs"></span><span>Sending</span></p>' );
689							output.addClass( "active" );
690						}
691					} else {
692						return false;
693					}
694				},
695				error: function ( result ) {
696
697					var output = $( "#" + $( plugins.rdMailForm[ this.extraData.counter ] ).attr( "data-form-output" ) ),
698						form = $( plugins.rdMailForm[ this.extraData.counter ] );
699
700					output.text( msg[ result ] );
701					form.removeClass( 'form-in-process' );
702
703					if ( formHasCaptcha ) {
704						grecaptcha.reset();
705					}
706				},
707				success: function ( result ) {
708
709					var form = $( plugins.rdMailForm[ this.extraData.counter ] ),
710						output = $( "#" + form.attr( "data-form-output" ) ),
711						select = form.find( 'select' );
712
713					form
714						.addClass( 'success' )
715						.removeClass( 'form-in-process' );
716
717					if ( formHasCaptcha ) {
718						grecaptcha.reset();
719					}
720
721					result = result.length === 5 ? result : 'MF255';
722					output.text( msg[ result ] );
723
724					if ( result === "MF000" ) {
725						if ( output.hasClass( "snackbars" ) ) {
726							output.html( '<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + msg[ result ] + '</span></p>' );
727						} else {
728							output.addClass( "active success" );
729						}
730					} else {
731						if ( output.hasClass( "snackbars" ) ) {
732							output.html( ' <p class="snackbars-left"><span class="icon icon-xxs mdi mdi-alert-outline text-middle"></span><span>' + msg[ result ] + '</span></p>' );
733						} else {
734							output.addClass( "active error" );
735						}
736					}
737
738					form.clearForm();
739
740					if ( select.length ) {
741						select.select2( "val", "" );
742					}
743
744					form.find( 'input, textarea' ).trigger( 'blur' );
745
746					setTimeout( function () {
747						output.removeClass( "active error success" );
748						form.removeClass( 'success' );
749					}, 3500 );
750				}
751			} );
752		}
753	}
754
755	// Custom Toggles
756	if ( plugins.customToggle.length ) {
757		var i;
758		for ( i = 0; i < plugins.customToggle.length; i++ ) {
759			var $this = $( plugins.customToggle[ i ] );
760			$this.on( 'click', function ( e ) {
761				e.preventDefault();
762				$( "#" + $( this ).attr( 'data-custom-toggle' ) ).add( this ).toggleClass( 'active' );
763			} );
764
765			if ( $this.attr( "data-custom-toggle-disable-on-blur" ) === "true" ) {
766				$( "body" ).on( "click", $this, function ( e ) {
767					if ( e.target !== e.data[ 0 ] && $( "#" + e.data.attr( 'data-custom-toggle' ) ).find( $( e.target ) ).length == 0 && e.data.find( $( e.target ) ).length == 0 ) {
768						$( "#" + e.data.attr( 'data-custom-toggle' ) ).add( e.data[ 0 ] ).removeClass( 'active' );
769					}
770				} )
771			}
772		}
773	}
774
775	// Material Parallax
776	if ( plugins.materialParallax.length ) {
777		if ( !isNoviBuilder && !isIE && !isMobile ) {
778			plugins.materialParallax.parallax();
779		} else {
780			for ( var i = 0; i < plugins.materialParallax.length; i++ ) {
781				var $parallax = $( plugins.materialParallax[ i ] );
782
783				$parallax.addClass( 'parallax-disabled' );
784				$parallax.css( { "background-image": 'url(' + $parallax.data( "parallax-img" ) + ')' } );
785			}
786		}
787	}
788
789	
790
791	// lightGallery
792	function initLightGallery ( itemsToInit, addClass ) {
793		$( itemsToInit ).lightGallery( {
794			thumbnail: $( itemsToInit ).attr( "data-lg-thumbnail" ) !== "false",
795			selector: "[data-lightgallery='item']",
796			autoplay: $( itemsToInit ).attr( "data-lg-autoplay" ) === "true",
797			pause: parseInt( $( itemsToInit ).attr( "data-lg-autoplay-delay" ) ) || 5000,
798			addClass: addClass,
799			mode: $( itemsToInit ).attr( "data-lg-animation" ) || "lg-slide",
800			loop: $( itemsToInit ).attr( "data-lg-loop" ) !== "false"
801		} );
802	}
803
804	function initDynamicLightGallery ( itemsToInit, addClass ) {
805		$( itemsToInit ).on( "click", function () {
806			$( itemsToInit ).lightGallery( {
807				thumbnail: $( itemsToInit ).attr( "data-lg-thumbnail" ) !== "false",
808				selector: "[data-lightgallery='item']",
809				autoplay: $( itemsToInit ).attr( "data-lg-autoplay" ) === "true",
810				pause: parseInt( $( itemsToInit ).attr( "data-lg-autoplay-delay" ) ) || 5000,
811				addClass: addClass,
812				mode: $( itemsToInit ).attr( "data-lg-animation" ) || "lg-slide",
813				loop: $( itemsToInit ).attr( "data-lg-loop" ) !== "false",
814				dynamic: true,
815				dynamicEl:
816				JSON.parse( $( itemsToInit ).attr( "data-lg-dynamic-elements" ) ) || []
817			} );
818		} );
819	}
820
821	function initLightGalleryItem ( itemToInit, addClass ) {
822		$( itemToInit ).lightGallery( {
823			selector: "this",
824			addClass: addClass,
825			counter: false,
826			youtubePlayerParams: {
827				modestbranding: 1,
828				showinfo: 0,
829				rel: 0,
830				controls: 0
831			},
832			vimeoPlayerParams: {
833				byline: 0,
834				portrait: 0
835			}
836		} );
837	}
838
839	if ( !isNoviBuilder && plugins.lightGallery.length ) {
840		for ( var i = 0; i < plugins.lightGallery.length; i++ ) initLightGallery( plugins.lightGallery[ i ] );
841	}
842
843	if ( !isNoviBuilder && plugins.lightGalleryItem.length ) {
844		for ( var i = 0; i < plugins.lightGalleryItem.length; i++ ) initLightGalleryItem( plugins.lightGalleryItem[ i ] );
845	}
846
847	if ( !isNoviBuilder && plugins.lightDynamicGalleryItem.length ) {
848		for ( var i = 0; i < plugins.lightDynamicGalleryItem.length; i++ ) initDynamicLightGallery( plugins.lightDynamicGalleryItem[ i ] );
849	}
850} );

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.