PageSourceSearch

https://l2top.co/js/theme.js

js l2top.co collected 2026-09-24 09:24:02 UTC 57,245 bytes, 2,992 lines download raw bytes

1// Theme
2window.theme = {};
3
4// Animate
5(function(theme, $) {
6
7	theme = theme || {};
8
9	var instanceName = '__animate';
10
11	var PluginAnimate = function($el, opts) {
12		return this.initialize($el, opts);
13	};
14
15	PluginAnimate.defaults = {
16		accX: 0,
17		accY: -150,
18		delay: 1
19	};
20
21	PluginAnimate.prototype = {
22		initialize: function($el, opts) {
23			if ($el.data(instanceName)) {
24				return this;
25			}
26
27			this.$el = $el;
28
29			this
30				.setData()
31				.setOptions(opts)
32				.build();
33
34			return this;
35		},
36
37		setData: function() {
38			this.$el.data(instanceName, this);
39
40			return this;
41		},
42
43		setOptions: function(opts) {
44			this.options = $.extend(true, {}, PluginAnimate.defaults, opts, {
45				wrapper: this.$el
46			});
47
48			return this;
49		},
50
51		build: function() {
52			var self = this,
53				$el = this.options.wrapper,
54				delay = 0;
55
56			$el.addClass('appear-animation');
57
58			if (!$('html').hasClass('no-csstransitions') && $(window).width() > 767) {
59
60				$el.appear(function() {
61
62					delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay);
63
64					if (delay > 1) {
65						$el.css('animation-delay', delay + 'ms');
66					}
67
68					$el.addClass($el.attr('data-appear-animation'));
69
70					setTimeout(function() {
71						$el.addClass('appear-animation-visible');
72					}, delay);
73
74				}, {
75					accX: self.options.accX,
76					accY: self.options.accY
77				});
78
79			} else {
80
81				$el.addClass('appear-animation-visible');
82
83			}
84
85			return this;
86		}
87	};
88
89	// expose to scope
90	$.extend(theme, {
91		PluginAnimate: PluginAnimate
92	});
93
94	// jquery plugin
95	$.fn.themePluginAnimate = function(opts) {
96		return this.map(function() {
97			var $this = $(this);
98
99			if ($this.data(instanceName)) {
100				return $this.data(instanceName);
101			} else {
102				return new PluginAnimate($this, opts);
103			}
104
105		});
106	};
107
108}).apply(this, [window.theme, jQuery]);
109
110// Carousel
111(function(theme, $) {
112
113	theme = theme || {};
114
115	var instanceName = '__carousel';
116
117	var PluginCarousel = function($el, opts) {
118		return this.initialize($el, opts);
119	};
120
121	PluginCarousel.defaults = {
122		loop: true,
123		responsive: {
124			0: {
125				items: 1
126			},
127			479: {
128				items: 1
129			},
130			768: {
131				items: 2
132			},
133			979: {
134				items: 3
135			},
136			1199: {
137				items: 4
138			}
139		},
140		navText: []
141	};
142
143	PluginCarousel.prototype = {
144		initialize: function($el, opts) {
145			if ($el.data(instanceName)) {
146				return this;
147			}
148
149			this.$el = $el;
150
151			this
152				.setData()
153				.setOptions(opts)
154				.build();
155
156			return this;
157		},
158
159		setData: function() {
160			this.$el.data(instanceName, this);
161
162			return this;
163		},
164
165		setOptions: function(opts) {
166			this.options = $.extend(true, {}, PluginCarousel.defaults, opts, {
167				wrapper: this.$el
168			});
169
170			return this;
171		},
172
173		build: function() {
174			if (!($.isFunction($.fn.owlCarousel))) {
175				return this;
176			}
177
178			var self = this,
179				$el = this.options.wrapper;
180
181			// Add Theme Class
182			$el.addClass('owl-theme');
183
184			// Force RTL according to HTML dir attribute
185			if ($('html').attr('dir') == 'rtl') {
186				this.options = $.extend(true, {}, this.options, {
187					rtl: true
188				});
189			}
190
191			if (this.options.items == 1) {
192				this.options.responsive = {}
193			}
194
195			if (this.options.items > 4) {
196				this.options = $.extend(true, {}, this.options, {
197					responsive: {
198						1199: {
199							items: this.options.items
200						}
201					}
202				});
203			}
204
205			// Auto Height Fixes
206			if (this.options.autoHeight) {
207				$(window).afterResize(function() {
208					$el.find('.owl-stage-outer').height( $el.find('.owl-item.active').height() );
209				});
210
211				$(window).on('load', function() {
212					$el.find('.owl-stage-outer').height( $el.find('.owl-item.active').height() );
213				});
214			}
215
216			// Initialize OwlCarousel
217			$el.owlCarousel(this.options).addClass('owl-carousel-init');
218
219			return this;
220		}
221	};
222
223	// expose to scope
224	$.extend(theme, {
225		PluginCarousel: PluginCarousel
226	});
227
228	// jquery plugin
229	$.fn.themePluginCarousel = function(opts) {
230		return this.map(function() {
231			var $this = $(this);
232
233			if ($this.data(instanceName)) {
234				return $this.data(instanceName);
235			} else {
236				return new PluginCarousel($this, opts);
237			}
238
239		});
240	}
241
242}).apply(this, [window.theme, jQuery]);
243
244// Chart Circular
245(function(theme, $) {
246
247	theme = theme || {};
248
249	var instanceName = '__chartCircular';
250
251	var PluginChartCircular = function($el, opts) {
252		return this.initialize($el, opts);
253	};
254
255	PluginChartCircular.defaults = {
256		accX: 0,
257		accY: -150,
258		delay: 1,
259		barColor: '#0088CC',
260		trackColor: '#f2f2f2',
261		scaleColor: false,
262		scaleLength: 5,
263		lineCap: 'round',
264		lineWidth: 13,
265		size: 175,
266		rotate: 0,
267		animate: ({
268			duration: 2500,
269			enabled: true
270		})
271	};
272
273	PluginChartCircular.prototype = {
274		initialize: function($el, opts) {
275			if ($el.data(instanceName)) {
276				return this;
277			}
278
279			this.$el = $el;
280
281			this
282				.setData()
283				.setOptions(opts)
284				.build();
285
286			return this;
287		},
288
289		setData: function() {
290			this.$el.data(instanceName, this);
291
292			return this;
293		},
294
295		setOptions: function(opts) {
296			this.options = $.extend(true, {}, PluginChartCircular.defaults, opts, {
297				wrapper: this.$el
298			});
299
300			return this;
301		},
302
303		build: function() {
304			if (!($.isFunction($.fn.appear)) || !($.isFunction($.fn.easyPieChart))) {
305				return this;
306			}
307
308			var self = this,
309				$el = this.options.wrapper,
310				value = ($el.attr('data-percent') ? $el.attr('data-percent') : 0),
311				percentEl = $el.find('.percent');
312
313			$.extend(true, self.options, {
314				onStep: function(from, to, currentValue) {
315					percentEl.html(parseInt(currentValue));
316				}
317			});
318
319			$el.attr('data-percent', 0);
320
321			$el.appear(function() {
322
323				$el.easyPieChart(self.options);
324
325				setTimeout(function() {
326
327					$el.data('easyPieChart').update(value);
328					$el.attr('data-percent', value);
329
330				}, self.options.delay);
331
332			}, {
333				accX: self.options.accX,
334				accY: self.options.accY
335			});
336
337			return this;
338		}
339	};
340
341	// expose to scope
342	$.extend(theme, {
343		PluginChartCircular: PluginChartCircular
344	});
345
346	// jquery plugin
347	$.fn.themePluginChartCircular = function(opts) {
348		return this.map(function() {
349			var $this = $(this);
350
351			if ($this.data(instanceName)) {
352				return $this.data(instanceName);
353			} else {
354				return new PluginChartCircular($this, opts);
355			}
356
357		});
358	}
359
360}).apply(this, [window.theme, jQuery]);
361
362// Counter
363(function(theme, $) {
364
365	theme = theme || {};
366
367	var instanceName = '__counter';
368
369	var PluginCounter = function($el, opts) {
370		return this.initialize($el, opts);
371	};
372
373	PluginCounter.defaults = {
374		accX: 0,
375		accY: 0,
376		speed: 3000,
377		refreshInterval: 100,
378		decimals: 0,
379		onUpdate: null,
380		onComplete: null
381	};
382
383	PluginCounter.prototype = {
384		initialize: function($el, opts) {
385			if ($el.data(instanceName)) {
386				return this;
387			}
388
389			this.$el = $el;
390
391			this
392				.setData()
393				.setOptions(opts)
394				.build();
395
396			return this;
397		},
398
399		setData: function() {
400			this.$el.data(instanceName, this);
401
402			return this;
403		},
404
405		setOptions: function(opts) {
406			this.options = $.extend(true, {}, PluginCounter.defaults, opts, {
407				wrapper: this.$el
408			});
409
410			return this;
411		},
412
413		build: function() {
414			if (!($.isFunction($.fn.countTo))) {
415				return this;
416			}
417
418			var self = this,
419				$el = this.options.wrapper;
420
421			$.extend(self.options, {
422				onComplete: function() {
423					if ($el.data('append')) {
424						$el.html($el.html() + $el.data('append'));
425					}
426
427					if ($el.data('prepend')) {
428						$el.html($el.data('prepend') + $el.html());
429					}
430				}
431			});
432
433			$el.appear(function() {
434
435				$el.countTo(self.options);
436
437			}, {
438				accX: self.options.accX,
439				accY: self.options.accY
440			});
441
442			return this;
443		}
444	};
445
446	// expose to scope
447	$.extend(theme, {
448		PluginCounter: PluginCounter
449	});
450
451	// jquery plugin
452	$.fn.themePluginCounter = function(opts) {
453		return this.map(function() {
454			var $this = $(this);
455
456			if ($this.data(instanceName)) {
457				return $this.data(instanceName);
458			} else {
459				return new PluginCounter($this, opts);
460			}
461
462		});
463	}
464
465}).apply(this, [window.theme, jQuery]);
466
467// Lazy Load
468(function(theme, $) {
469
470	theme = theme || {};
471
472	var instanceName = '__lazyload';
473
474	var PluginLazyLoad = function($el, opts) {
475		return this.initialize($el, opts);
476	};
477
478	PluginLazyLoad.defaults = {
479		effect : 'fadeIn'
480	};
481
482	PluginLazyLoad.prototype = {
483		initialize: function($el, opts) {
484			if ($el.data(instanceName)) {
485				return this;
486			}
487
488			this.$el = $el;
489
490			this
491				.setData()
492				.setOptions(opts)
493				.build();
494
495			return this;
496		},
497
498		setData: function() {
499			this.$el.data(instanceName, this);
500
501			return this;
502		},
503
504		setOptions: function(opts) {
505			this.options = $.extend(true, {}, PluginLazyLoad.defaults, opts, {
506				wrapper: this.$el
507			});
508
509			return this;
510		},
511
512		build: function() {
513			if (!($.isFunction($.fn.lazyload))) {
514				return this;
515			}
516
517			var self = this;
518
519			self.options.wrapper.lazyload(this.options);
520
521			return this;
522		}
523	};
524
525	// expose to scope
526	$.extend(theme, {
527		PluginLazyLoad: PluginLazyLoad
528	});
529
530	// jquery plugin
531	$.fn.themePluginLazyLoad = function(opts) {
532		return this.map(function() {
533			var $this = $(this);
534
535			if ($this.data(instanceName)) {
536				return $this.data(instanceName);
537			} else {
538				return new PluginLazyLoad($this, opts);
539			}
540
541		});
542	}
543
544}).apply(this, [window.theme, jQuery]);
545
546// Lightbox
547(function(theme, $) {
548
549	theme = theme || {};
550
551	var instanceName = '__lightbox';
552
553	var PluginLightbox = function($el, opts) {
554		return this.initialize($el, opts);
555	};
556
557	PluginLightbox.defaults = {
558		tClose: 'Close (Esc)', // Alt text on close button
559		tLoading: 'Loading...', // Text that is displayed during loading. Can contain %curr% and %total% keys
560		gallery: {
561			tPrev: 'Previous (Left arrow key)', // Alt text on left arrow
562			tNext: 'Next (Right arrow key)', // Alt text on right arrow
563			tCounter: '%curr% of %total%' // Markup for "1 of 7" counter
564		},
565		image: {
566			tError: '<a href="%url%">The image</a> could not be loaded.' // Error message when image could not be loaded
567		},
568		ajax: {
569			tError: '<a href="%url%">The content</a> could not be loaded.' // Error message when ajax request failed
570		},
571		callbacks: {
572			open: function() {
573				$('html').addClass('lightbox-opened');
574			},
575			close: function() {
576				$('html').removeClass('lightbox-opened');
577			}
578		}
579	};
580
581	PluginLightbox.prototype = {
582		initialize: function($el, opts) {
583			if ($el.data(instanceName)) {
584				return this;
585			}
586
587			this.$el = $el;
588
589			this
590				.setData()
591				.setOptions(opts)
592				.build();
593
594			return this;
595		},
596
597		setData: function() {
598			this.$el.data(instanceName, this);
599
600			return this;
601		},
602
603		setOptions: function(opts) {
604			this.options = $.extend(true, {}, PluginLightbox.defaults, opts, {
605				wrapper: this.$el
606			});
607
608			return this;
609		},
610
611		build: function() {
612			if (!($.isFunction($.fn.magnificPopup))) {
613				return this;
614			}
615
616			this.options.wrapper.magnificPopup(this.options);
617
618			return this;
619		}
620	};
621
622	// expose to scope
623	$.extend(theme, {
624		PluginLightbox: PluginLightbox
625	});
626
627	// jquery plugin
628	$.fn.themePluginLightbox = function(opts) {
629		return this.map(function() {
630			var $this = $(this);
631
632			if ($this.data(instanceName)) {
633				return $this.data(instanceName);
634			} else {
635				return new PluginLightbox($this, opts);
636			}
637
638		});
639	}
640
641}).apply(this, [window.theme, jQuery]);
642
643// Loading Overlay
644(function(theme, $) {
645
646	'use strict';
647
648	theme = theme || {};
649
650	var loadingOverlayTemplate = [
651		'<div class="loading-overlay">',
652			'<div class="bounce-loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>',
653		'</div>'
654	].join('');
655
656	var LoadingOverlay = function( $wrapper, options ) {
657		return this.initialize( $wrapper, options );
658	};
659
660	LoadingOverlay.prototype = {
661
662		options: {
663			css: {}
664		},
665
666		initialize: function( $wrapper, options ) {
667			this.$wrapper = $wrapper;
668
669			this
670				.setVars()
671				.setOptions( options )
672				.build()
673				.events();
674
675			this.$wrapper.data( 'loadingOverlay', this );
676		},
677
678		setVars: function() {
679			this.$overlay = this.$wrapper.find('.loading-overlay');
680
681			return this;
682		},
683
684		setOptions: function( options ) {
685			if ( !this.$overlay.get(0) ) {
686				this.matchProperties();
687			}
688			this.options     = $.extend( true, {}, this.options, options );
689			this.loaderClass = this.getLoaderClass( this.options.css.backgroundColor );
690
691			return this;
692		},
693
694		build: function() {
695			if ( !this.$overlay.closest(document.documentElement).get(0) ) {
696				if ( !this.$cachedOverlay ) {
697					this.$overlay = $( loadingOverlayTemplate ).clone();
698
699					if ( this.options.css ) {
700						this.$overlay.css( this.options.css );
701						this.$overlay.find( '.loader' ).addClass( this.loaderClass );
702					}
703				} else {
704					this.$overlay = this.$cachedOverlay.clone();
705				}
706
707				this.$wrapper.append( this.$overlay );
708			}
709
710			if ( !this.$cachedOverlay ) {
711				this.$cachedOverlay = this.$overlay.clone();
712			}
713
714			return this;
715		},
716
717		events: function() {
718			var _self = this;
719
720			if ( this.options.startShowing ) {
721				_self.show();
722			}
723
724			if ( this.$wrapper.is('body') || this.options.hideOnWindowLoad ) {
725				$( window ).on( 'load error', function() {
726					_self.hide();
727				});
728			}
729
730			if ( this.options.listenOn ) {
731				$( this.options.listenOn )
732					.on( 'loading-overlay:show beforeSend.ic', function( e ) {
733						e.stopPropagation();
734						_self.show();
735					})
736					.on( 'loading-overlay:hide complete.ic', function( e ) {
737						e.stopPropagation();
738						_self.hide();
739					});
740			}
741
742			this.$wrapper
743				.on( 'loading-overlay:show beforeSend.ic', function( e ) {
744					if ( e.target === _self.$wrapper.get(0) ) {
745						e.stopPropagation();
746						_self.show();
747						return true;
748					}
749					return false;
750				})
751				.on( 'loading-overlay:hide complete.ic', function( e ) {
752					if ( e.target === _self.$wrapper.get(0) ) {
753						e.stopPropagation();
754						_self.hide();
755						return true;
756					}
757					return false;
758				});
759
760			return this;
761		},
762
763		show: function() {
764			this.build();
765
766			this.position = this.$wrapper.css( 'position' ).toLowerCase();
767			if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) {
768				this.$wrapper.css({
769					position: 'relative'
770				});
771			}
772			this.$wrapper.addClass( 'loading-overlay-showing' );
773		},
774
775		hide: function() {
776			var _self = this;
777
778			this.$wrapper.removeClass( 'loading-overlay-showing' );
779			setTimeout(function() {
780				if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) {
781					_self.$wrapper.css({ position: '' });
782				}
783			}, 500);
784		},
785
786		matchProperties: function() {
787			var i,
788				l,
789				properties;
790
791			properties = [
792				'backgroundColor',
793				'borderRadius'
794			];
795
796			l = properties.length;
797
798			for( i = 0; i < l; i++ ) {
799				var obj = {};
800				obj[ properties[ i ] ] = this.$wrapper.css( properties[ i ] );
801
802				$.extend( this.options.css, obj );
803			}
804		},
805
806		getLoaderClass: function( backgroundColor ) {
807			if ( !backgroundColor || backgroundColor === 'transparent' || backgroundColor === 'inherit' ) {
808				return 'black';
809			}
810
811			var hexColor,
812				r,
813				g,
814				b,
815				yiq;
816
817			var colorToHex = function( color ){
818				var hex,
819					rgb;
820
821				if( color.indexOf('#') >- 1 ){
822					hex = color.replace('#', '');
823				} else {
824					rgb = color.match(/\d+/g);
825					hex = ('0' + parseInt(rgb[0], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2);
826				}
827
828				if ( hex.length === 3 ) {
829					hex = hex + hex;
830				}
831
832				return hex;
833			};
834
835			hexColor = colorToHex( backgroundColor );
836
837			r = parseInt( hexColor.substr( 0, 2), 16 );
838			g = parseInt( hexColor.substr( 2, 2), 16 );
839			b = parseInt( hexColor.substr( 4, 2), 16 );
840			yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
841
842			return ( yiq >= 128 ) ? 'black' : 'white';
843		}
844
845	};
846
847	// expose to scope
848	$.extend(theme, {
849		LoadingOverlay: LoadingOverlay
850	});
851
852	// expose as a jquery plugin
853	$.fn.loadingOverlay = function( opts ) {
854		return this.each(function() {
855			var $this = $( this );
856
857			var loadingOverlay = $this.data( 'loadingOverlay' );
858			if ( loadingOverlay ) {
859				return loadingOverlay;
860			} else {
861				var options = opts || $this.data( 'loading-overlay-options' ) || {};
862				return new LoadingOverlay( $this, options );
863			}
864		});
865	}
866
867	// auto init
868	$('[data-loading-overlay]').loadingOverlay();
869
870}).apply(this, [window.theme, jQuery]);
871
872// Masonry
873(function(theme, $) {
874
875	theme = theme || {};
876
877	var instanceName = '__masonry';
878
879	var PluginMasonry = function($el, opts) {
880		return this.initialize($el, opts);
881	};
882
883	PluginMasonry.defaults = {
884		itemSelector: 'li'
885	};
886
887	PluginMasonry.prototype = {
888		initialize: function($el, opts) {
889			if ($el.data(instanceName)) {
890				return this;
891			}
892
893			this.$el = $el;
894
895			this
896				.setData()
897				.setOptions(opts)
898				.build();
899
900			return this;
901		},
902
903		setData: function() {
904			this.$el.data(instanceName, this);
905
906			return this;
907		},
908
909		setOptions: function(opts) {
910			this.options = $.extend(true, {}, PluginMasonry.defaults, opts, {
911				wrapper: this.$el
912			});
913
914			return this;
915		},
916
917		build: function() {
918			if (!($.isFunction($.fn.isotope))) {
919				return this;
920			}
921
922			this.options.wrapper.isotope(this.options);
923
924			return this;
925		}
926	};
927
928	// expose to scope
929	$.extend(theme, {
930		PluginMasonry: PluginMasonry
931	});
932
933	// jquery plugin
934	$.fn.themePluginMasonry = function(opts) {
935		return this.map(function() {
936			var $this = $(this);
937
938			$this.waitForImages(function() {
939				if ($this.data(instanceName)) {
940					return $this.data(instanceName);
941				} else {
942					return new PluginMasonry($this, opts);
943				}
944			});
945
946		});
947	}
948
949}).apply(this, [window.theme, jQuery]);
950
951// Match Height
952(function(theme, $) {
953
954	theme = theme || {};
955
956	var instanceName = '__matchHeight';
957
958	var PluginMatchHeight = function($el, opts) {
959		return this.initialize($el, opts);
960	};
961
962	PluginMatchHeight.defaults = {
963		byRow: true,
964		property: 'height',
965		target: null,
966		remove: false
967	};
968
969	PluginMatchHeight.prototype = {
970		initialize: function($el, opts) {
971			if ($el.data(instanceName)) {
972				return this;
973			}
974
975			this.$el = $el;
976
977			this
978				.setData()
979				.setOptions(opts)
980				.build();
981
982			return this;
983		},
984
985		setData: function() {
986			this.$el.data(instanceName, this);
987
988			return this;
989		},
990
991		setOptions: function(opts) {
992			this.options = $.extend(true, {}, PluginMatchHeight.defaults, opts, {
993				wrapper: this.$el
994			});
995
996			return this;
997		},
998
999		build: function() {
1000			if (!($.isFunction($.fn.matchHeight))) {
1001				return this;
1002			}
1003
1004			var self = this;
1005
1006			self.options.wrapper.matchHeight(self.options);
1007
1008			return this;
1009		}
1010
1011	};
1012
1013	// expose to scope
1014	$.extend(theme, {
1015		PluginMatchHeight: PluginMatchHeight
1016	});
1017
1018	// jquery plugin
1019	$.fn.themePluginMatchHeight = function(opts) {
1020		return this.map(function() {
1021			var $this = $(this);
1022
1023			if ($this.data(instanceName)) {
1024				return $this.data(instanceName);
1025			} else {
1026				return new PluginMatchHeight($this, opts);
1027			}
1028
1029		});
1030	}
1031
1032}).apply(this, [window.theme, jQuery]);
1033
1034// Parallax
1035(function(theme, $) {
1036
1037	theme = theme || {};
1038
1039	var instanceName = '__parallax';
1040
1041	var PluginParallax = function($el, opts) {
1042		return this.initialize($el, opts);
1043	};
1044
1045	PluginParallax.defaults = {
1046		speed: 1.5,
1047		horizontalPosition: '50%',
1048		offset: 0
1049	};
1050
1051	PluginParallax.prototype = {
1052		initialize: function($el, opts) {
1053			if ($el.data(instanceName)) {
1054				return this;
1055			}
1056
1057			this.$el = $el;
1058
1059			this
1060				.setData()
1061				.setOptions(opts)
1062				.build();
1063
1064			return this;
1065		},
1066
1067		setData: function() {
1068			this.$el.data(instanceName, this);
1069
1070			return this;
1071		},
1072
1073		setOptions: function(opts) {
1074			this.options = $.extend(true, {}, PluginParallax.defaults, opts, {
1075				wrapper: this.$el
1076			});
1077
1078			return this;
1079		},
1080
1081		build: function() {
1082			var self = this,
1083				$window = $(window),
1084				offset,
1085				yPos,
1086				bgpos;
1087
1088			self.options.wrapper.css('background-image', 'url(' + self.options.wrapper.data('image-src') + ')');
1089
1090			if (!$.browser.mobile) {
1091
1092				$window.on('scroll resize', function() {
1093					offset = self.options.wrapper.offset();
1094					yPos = -($window.scrollTop() - offset.top) / self.options.speed + (self.options.offset);
1095					bgpos = self.options.horizontalPosition + ' ' + yPos + 'px';
1096					self.options.wrapper.css('background-position', bgpos);
1097				});
1098
1099				$window.trigger('scroll');
1100
1101			} else {
1102				self.options.wrapper.addClass('parallax-disabled');
1103			}
1104
1105			return this;
1106		}
1107	};
1108
1109	// expose to scope
1110	$.extend(theme, {
1111		PluginParallax: PluginParallax
1112	});
1113
1114	// jquery plugin
1115	$.fn.themePluginParallax = function(opts) {
1116		return this.map(function() {
1117			var $this = $(this);
1118
1119			if ($this.data(instanceName)) {
1120				return $this.data(instanceName);
1121			} else {
1122				return new PluginParallax($this, opts);
1123			}
1124
1125		});
1126	}
1127
1128}).apply(this, [window.theme, jQuery]);
1129
1130// Progress Bar
1131(function(theme, $) {
1132
1133	theme = theme || {};
1134
1135	var instanceName = '__progressBar';
1136
1137	var PluginProgressBar = function($el, opts) {
1138		return this.initialize($el, opts);
1139	};
1140
1141	PluginProgressBar.defaults = {
1142		accX: 0,
1143		accY: -50,
1144		delay: 1
1145	};
1146
1147	PluginProgressBar.prototype = {
1148		initialize: function($el, opts) {
1149			if ($el.data(instanceName)) {
1150				return this;
1151			}
1152
1153			this.$el = $el;
1154
1155			this
1156				.setData()
1157				.setOptions(opts)
1158				.build();
1159
1160			return this;
1161		},
1162
1163		setData: function() {
1164			this.$el.data(instanceName, this);
1165
1166			return this;
1167		},
1168
1169		setOptions: function(opts) {
1170			this.options = $.extend(true, {}, PluginProgressBar.defaults, opts, {
1171				wrapper: this.$el
1172			});
1173
1174			return this;
1175		},
1176
1177		build: function() {
1178			if (!($.isFunction($.fn.appear))) {
1179				return this;
1180			}
1181
1182			var self = this,
1183				$el = this.options.wrapper,
1184				delay = 1;
1185
1186			$el.appear(function() {
1187
1188				delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay);
1189
1190				$el.addClass($el.attr('data-appear-animation'));
1191
1192				setTimeout(function() {
1193
1194					$el.animate({
1195						width: $el.attr('data-appear-progress-animation')
1196					}, 1500, 'easeOutQuad', function() {
1197						$el.find('.progress-bar-tooltip').animate({
1198							opacity: 1
1199						}, 500, 'easeOutQuad');
1200					});
1201
1202				}, delay);
1203
1204			}, {
1205				accX: self.options.accX,
1206				accY: self.options.accY
1207			});
1208
1209			return this;
1210		}
1211	};
1212
1213	// expose to scope
1214	$.extend(theme, {
1215		PluginProgressBar: PluginProgressBar
1216	});
1217
1218	// jquery plugin
1219	$.fn.themePluginProgressBar = function(opts) {
1220		return this.map(function() {
1221			var $this = $(this);
1222
1223			if ($this.data(instanceName)) {
1224				return $this.data(instanceName);
1225			} else {
1226				return new PluginProgressBar($this, opts);
1227			}
1228
1229		});
1230	}
1231
1232}).apply(this, [window.theme, jQuery]);
1233
1234// Revolution Slider
1235(function(theme, $) {
1236
1237	theme = theme || {};
1238
1239	var instanceName = '__revolution';
1240
1241	var PluginRevolutionSlider = function($el, opts) {
1242		return this.initialize($el, opts);
1243	};
1244
1245	PluginRevolutionSlider.defaults = {
1246		sliderType: 'standard',
1247		sliderLayout: 'fullwidth',
1248		delay: 9000,
1249		gridwidth: 1170,
1250		gridheight: 500,
1251		spinner: 'spinner3',
1252		parallax: {
1253			type: 'off',
1254			bgparallax: 'off'
1255		},
1256		navigation: {
1257			keyboardNavigation: 'off',
1258			keyboard_direction: 'horizontal',
1259			mouseScrollNavigation: 'off',
1260			onHoverStop: 'off',
1261			touch: {
1262				touchenabled: 'on',
1263				swipe_threshold: 75,
1264				swipe_min_touches: 1,
1265				swipe_direction: 'horizontal',
1266				drag_block_vertical: false
1267			},
1268			arrows: {
1269				enable: true,
1270				hide_onmobile: false,
1271				hide_under: 0,
1272				hide_onleave: true,
1273				hide_delay: 200,
1274				hide_delay_mobile: 1200,
1275				left: {
1276					h_align: 'left',
1277					v_align: 'center',
1278					h_offset: 30,
1279					v_offset: 0
1280				},
1281				right: {
1282					h_align: 'right',
1283					v_align: 'center',
1284					h_offset: 30,
1285					v_offset: 0
1286				}
1287			}
1288		}
1289	};
1290
1291	PluginRevolutionSlider.prototype = {
1292		initialize: function($el, opts) {
1293			if ($el.data(instanceName)) {
1294				return this;
1295			}
1296
1297			this.$el = $el;
1298
1299			this
1300				.setData()
1301				.setOptions(opts)
1302				.build()
1303				.events();
1304
1305			return this;
1306		},
1307
1308		setData: function() {
1309			this.$el.data(instanceName, this);
1310
1311			return this;
1312		},
1313
1314		setOptions: function(opts) {
1315			this.options = $.extend(true, {}, PluginRevolutionSlider.defaults, opts, {
1316				wrapper: this.$el
1317			});
1318
1319			return this;
1320		},
1321
1322		build: function() {
1323			if (!($.isFunction($.fn.revolution))) {
1324				return this;
1325			}
1326
1327			// Single Slider Class
1328			if(this.options.wrapper.find('> ul > li').length == 1) {
1329				this.options.wrapper.addClass('slider-single-slide');
1330			}
1331
1332			this.options.wrapper.revolution(this.options);
1333
1334			return this;
1335		},
1336
1337		events: function() {
1338
1339			return this;
1340		}
1341	};
1342
1343	// expose to scope
1344	$.extend(theme, {
1345		PluginRevolutionSlider: PluginRevolutionSlider
1346	});
1347
1348	// jquery plugin
1349	$.fn.themePluginRevolutionSlider = function(opts) {
1350		return this.map(function() {
1351			var $this = $(this);
1352
1353			if ($this.data(instanceName)) {
1354				return $this.data(instanceName);
1355			} else {
1356				return new PluginRevolutionSlider($this, opts);
1357			}
1358
1359		});
1360	}
1361
1362}).apply(this, [window.theme, jQuery]);
1363
1364// Scroll to Top
1365(function(theme, $) {
1366
1367	theme = theme || {};
1368
1369	$.extend(theme, {
1370
1371		PluginScrollToTop: {
1372
1373			defaults: {
1374				wrapper: $('body'),
1375				offset: 150,
1376				buttonClass: 'scroll-to-top',
1377				iconClass: 'fa fa-chevron-up',
1378				delay: 1000,
1379				visibleMobile: false,
1380				label: false,
1381				easing: 'easeOutBack'
1382			},
1383
1384			initialize: function(opts) {
1385				initialized = true;
1386
1387				this
1388					.setOptions(opts)
1389					.build()
1390					.events();
1391
1392				return this;
1393			},
1394
1395			setOptions: function(opts) {
1396				this.options = $.extend(true, {}, this.defaults, opts);
1397
1398				return this;
1399			},
1400
1401			build: function() {
1402				var self = this,
1403					$el;
1404
1405				// Base HTML Markup
1406				$el = $('<a />')
1407					.addClass(self.options.buttonClass)
1408					.attr({
1409						'href': '#',
1410					})
1411					.append(
1412						$('<i />')
1413						.addClass(self.options.iconClass)
1414				);
1415
1416				// Visible Mobile
1417				if (!self.options.visibleMobile) {
1418					$el.addClass('hidden-mobile');
1419				}
1420
1421				// Label
1422				if (self.options.label) {
1423					$el.append(
1424						$('<span />').html(self.options.label)
1425					);
1426				}
1427
1428				this.options.wrapper.append($el);
1429
1430				this.$el = $el;
1431
1432				return this;
1433			},
1434
1435			events: function() {
1436				var self = this,
1437					_isScrolling = false;
1438
1439				// Click Element Action
1440				self.$el.on('click', function(e) {
1441					e.preventDefault();
1442					$('body, html').animate({
1443						scrollTop: 0
1444					}, self.options.delay, self.options.easing);
1445					return false;
1446				});
1447
1448				// Show/Hide Button on Window Scroll event.
1449				$(window).scroll(function() {
1450
1451					if (!_isScrolling) {
1452
1453						_isScrolling = true;
1454
1455						if ($(window).scrollTop() > self.options.offset) {
1456
1457							self.$el.stop(true, true).addClass('visible');
1458							_isScrolling = false;
1459
1460						} else {
1461
1462							self.$el.stop(true, true).removeClass('visible');
1463							_isScrolling = false;
1464
1465						}
1466
1467					}
1468
1469				});
1470
1471				return this;
1472			}
1473
1474		}
1475
1476	});
1477
1478}).apply(this, [window.theme, jQuery]);
1479
1480// Sort
1481(function(theme, $) {
1482
1483	theme = theme || {};
1484
1485	var instanceName = '__sort';
1486
1487	var PluginSort = function($el, opts) {
1488		return this.initialize($el, opts);
1489	};
1490
1491	PluginSort.defaults = {
1492		useHash: true,
1493		itemSelector: '.isotope-item',
1494		layoutMode: 'masonry',
1495		filter: '*',
1496		hiddenStyle: {
1497			opacity: 0
1498		},
1499		visibleStyle: {
1500			opacity: 1
1501		},
1502		stagger: 30,
1503		isOriginLeft: ($('html').attr('dir') == 'rtl' ? false : true)
1504	};
1505
1506	PluginSort.prototype = {
1507		initialize: function($el, opts) {
1508			if ($el.data(instanceName)) {
1509				return this;
1510			}
1511
1512			this.$el = $el;
1513
1514			this
1515				.setData()
1516				.setOptions(opts)
1517				.build();
1518
1519			return this;
1520		},
1521
1522		setData: function() {
1523			this.$el.data(instanceName, this);
1524
1525			return this;
1526		},
1527
1528		setOptions: function(opts) {
1529			this.options = $.extend(true, {}, PluginSort.defaults, opts, {
1530				wrapper: this.$el
1531			});
1532
1533			return this;
1534		},
1535
1536		build: function() {
1537			if (!($.isFunction($.fn.isotope))) {
1538				return this;
1539			}
1540
1541			var self = this,
1542				$source = this.options.wrapper,
1543				$destination = $('.sort-destination[data-sort-id="' + $source.attr('data-sort-id') + '"]'),
1544				$window = $(window);
1545
1546			if ($destination.get(0)) {
1547
1548				self.$source = $source;
1549				self.$destination = $destination;
1550				self.$loader = false;
1551
1552				self.setParagraphHeight($destination);
1553
1554				if (self.$destination.parents('.sort-destination-loader').get(0)) {
1555					self.$loader = self.$destination.parents('.sort-destination-loader');
1556					self.createLoader();
1557				}
1558
1559				self.$destination.waitForImages(function() {
1560
1561					$destination.attr('data-filter', '*').isotope(self.options).isotope('layout').trigger('filtered');
1562
1563					self.$destination.isotope('on', 'layoutComplete', function(event, laidOutItems) {
1564						if (self.options.useHash) {
1565							if (window.location.hash != '' || self.options.filter.replace('.', '') != '*') {
1566								window.location.hash = self.options.filter.replace('.', '');
1567							}
1568						}
1569					});
1570
1571					self.events();
1572
1573					$source.trigger('filtered');
1574
1575					if (self.$loader) {
1576						self.$loader.removeClass('sort-destination-loader-showing');
1577
1578						setTimeout(function() {
1579							self.$loader.addClass('sort-destination-loader-loaded');
1580						}, 500);
1581					}
1582
1583				});
1584
1585				$window.on('resize', function() {
1586					setTimeout(function() {
1587						self.$destination.isotope('layout');
1588					}, 300);
1589				});
1590
1591				setTimeout(function() {
1592					if (self.$loader) {
1593						self.$loader.removeClass('sort-destination-loader-showing');
1594
1595						setTimeout(function() {
1596							self.$loader.addClass('sort-destination-loader-loaded');
1597						}, 500);
1598					}
1599				}, 3000);
1600
1601			}
1602
1603			return this;
1604		},
1605
1606		events: function() {
1607			var self = this,
1608				filter = null;
1609
1610			self.$source.find('a').click(function(e) {
1611				e.preventDefault();
1612
1613				filter = $(this).parent().data('option-value');
1614
1615				self.setFilter(filter);
1616
1617				if (e.originalEvent) {
1618					self.$source.trigger('filtered');
1619				}
1620
1621				return this;
1622			});
1623
1624			if (self.options.useHash) {
1625				self.hashEvents();
1626			}
1627
1628			return this;
1629		},
1630
1631		setFilter: function(filter) {
1632			var self = this,
1633				page = false,
1634				currentFilter = filter;
1635
1636			self.$source.find('li.active').removeClass('active');
1637			self.$source.find('li[data-option-value="' + filter + '"]').addClass('active');
1638
1639			self.options.filter = currentFilter;
1640
1641			if (self.$destination.attr('data-current-page')) {
1642				currentFilter = currentFilter + '[data-page-rel=' + self.$destination.attr('data-current-page') + ']';
1643			}
1644
1645			self.$destination.attr('data-filter', filter).isotope({
1646				filter: currentFilter
1647			}).on('arrangeComplete', function( event, filteredItems ) {
1648				$(window).trigger('scroll');
1649			}).trigger('filtered');
1650
1651			return this;
1652		},
1653
1654		hashEvents: function() {
1655			var self = this,
1656				hash = null,
1657				hashFilter = null,
1658				initHashFilter = '.' + location.hash.replace('#', '');
1659
1660			if (initHashFilter != '.' && initHashFilter != '.*') {
1661				self.setFilter(initHashFilter);
1662			}
1663
1664			$(window).bind('hashchange', function(e) {
1665
1666				hashFilter = '.' + location.hash.replace('#', '');
1667				hash = (hashFilter == '.' || hashFilter == '.*' ? '*' : hashFilter);
1668
1669				self.setFilter(hash);
1670
1671			});
1672
1673			return this;
1674		},
1675
1676		setParagraphHeight: function() {
1677			var self = this,
1678				minParagraphHeight = 0,
1679				paragraphs = $('span.thumb-info-caption p', self.$destination);
1680
1681			paragraphs.each(function() {
1682				if ($(this).height() > minParagraphHeight) {
1683					minParagraphHeight = ($(this).height() + 10);
1684				}
1685			});
1686
1687			paragraphs.height(minParagraphHeight);
1688
1689			return this;
1690		},
1691
1692		createLoader: function() {
1693			var self = this;
1694
1695			var loaderTemplate = [
1696				'<div class="bounce-loader">',
1697					'<div class="bounce1"></div>',
1698					'<div class="bounce2"></div>',
1699					'<div class="bounce3"></div>',
1700				'</div>'
1701			].join('');
1702
1703			self.$loader.append(loaderTemplate);
1704
1705			return this;
1706		}
1707
1708	};
1709
1710	// expose to scope
1711	$.extend(theme, {
1712		PluginSort: PluginSort
1713	});
1714
1715	// jquery plugin
1716	$.fn.themePluginSort = function(opts) {
1717		return this.map(function() {
1718			var $this = $(this);
1719
1720			if ($this.data(instanceName)) {
1721				return $this.data(instanceName);
1722			} else {
1723				return new PluginSort($this, opts);
1724			}
1725
1726		});
1727	}
1728
1729}).apply(this, [window.theme, jQuery]);
1730
1731// Sticky
1732(function(theme, $) {
1733	
1734	theme = theme || {};
1735	
1736	var instanceName = '__sticky';
1737
1738	var PluginSticky = function($el, opts) {
1739		return this.initialize($el, opts);
1740	};
1741
1742	PluginSticky.defaults = {
1743		minWidth: 991,
1744		activeClass: 'sticky-active'
1745	};
1746
1747	PluginSticky.prototype = {
1748		initialize: function($el, opts) {
1749			if ( $el.data( instanceName ) ) {
1750				return this;
1751			}
1752
1753			this.$el = $el;
1754
1755			this
1756				.setData()
1757				.setOptions(opts)
1758				.build();
1759
1760			return this;
1761		},
1762
1763		setData: function() {
1764			this.$el.data(instanceName, this);
1765
1766			return this;
1767		},
1768
1769		setOptions: function(opts) {
1770			this.options = $.extend(true, {}, PluginSticky.defaults, opts, {
1771				wrapper: this.$el
1772			});
1773
1774			return this;
1775		},
1776
1777		build: function() {
1778			if (!($.isFunction($.fn.pin))) {
1779				return this;
1780			}
1781
1782			var self = this,
1783				$window = $(window);
1784			
1785			self.options.wrapper.pin(self.options);
1786
1787			$window.afterResize(function() {
1788				self.options.wrapper.removeAttr('style').removeData('pin');
1789				self.options.wrapper.pin(self.options);
1790				$window.trigger('scroll');
1791			});
1792			
1793			return this;
1794		}
1795	};
1796
1797	// expose to scope
1798	$.extend(theme, {
1799		PluginSticky: PluginSticky
1800	});
1801
1802	// jquery plugin
1803	$.fn.themePluginSticky = function(opts) {
1804		return this.map(function() {
1805			var $this = $(this);
1806
1807			if ($this.data(instanceName)) {
1808				return $this.data(instanceName);
1809			} else {
1810				return new PluginSticky($this, opts);
1811			}
1812			
1813		});
1814	}
1815
1816}).apply(this, [ window.theme, jQuery ]);
1817
1818// Toggle
1819(function(theme, $) {
1820
1821	theme = theme || {};
1822
1823	var instanceName = '__toggle';
1824
1825	var PluginToggle = function($el, opts) {
1826		return this.initialize($el, opts);
1827	};
1828
1829	PluginToggle.defaults = {
1830		duration: 350,
1831		isAccordion: false
1832	};
1833
1834	PluginToggle.prototype = {
1835		initialize: function($el, opts) {
1836			if ($el.data(instanceName)) {
1837				return this;
1838			}
1839
1840			this.$el = $el;
1841
1842			this
1843				.setData()
1844				.setOptions(opts)
1845				.build();
1846
1847			return this;
1848		},
1849
1850		setData: function() {
1851			this.$el.data(instanceName, this);
1852
1853			return this;
1854		},
1855
1856		setOptions: function(opts) {
1857			this.options = $.extend(true, {}, PluginToggle.defaults, opts, {
1858				wrapper: this.$el
1859			});
1860
1861			return this;
1862		},
1863
1864		build: function() {
1865			var self = this,
1866				$wrapper = this.options.wrapper,
1867				$items = $wrapper.find('.toggle'),
1868				$el = null;
1869
1870			$items.each(function() {
1871				$el = $(this);
1872
1873				if ($el.hasClass('active')) {
1874					$el.find('> p').addClass('preview-active');
1875					$el.find('> .toggle-content').slideDown(self.options.duration);
1876				}
1877
1878				self.events($el);
1879			});
1880
1881			if (self.options.isAccordion) {
1882				self.options.duration = self.options.duration / 2;
1883			}
1884
1885			return this;
1886		},
1887
1888		events: function($el) {
1889			var self = this,
1890				previewParCurrentHeight = 0,
1891				previewParAnimateHeight = 0,
1892				toggleContent = null;
1893
1894			$el.find('> label').click(function(e) {
1895
1896				var $this = $(this),
1897					parentSection = $this.parent(),
1898					parentWrapper = $this.parents('.toggle'),
1899					previewPar = null,
1900					closeElement = null;
1901
1902				if (self.options.isAccordion && typeof(e.originalEvent) != 'undefined') {
1903					closeElement = parentWrapper.find('.toggle.active > label');
1904
1905					if (closeElement[0] == $this[0]) {
1906						return;
1907					}
1908				}
1909
1910				parentSection.toggleClass('active');
1911
1912				// Preview Paragraph
1913				if (parentSection.find('> p').get(0)) {
1914
1915					previewPar = parentSection.find('> p');
1916					previewParCurrentHeight = previewPar.css('height');
1917					previewPar.css('height', 'auto');
1918					previewParAnimateHeight = previewPar.css('height');
1919					previewPar.css('height', previewParCurrentHeight);
1920
1921				}
1922
1923				// Content
1924				toggleContent = parentSection.find('> .toggle-content');
1925
1926				if (parentSection.hasClass('active')) {
1927
1928					$(previewPar).animate({
1929						height: previewParAnimateHeight
1930					}, self.options.duration, function() {
1931						$(this).addClass('preview-active');
1932					});
1933
1934					toggleContent.slideDown(self.options.duration, function() {
1935						if (closeElement) {
1936							closeElement.trigger('click');
1937						}
1938					});
1939
1940				} else {
1941
1942					$(previewPar).animate({
1943						height: 0
1944					}, self.options.duration, function() {
1945						$(this).removeClass('preview-active');
1946					});
1947
1948					toggleContent.slideUp(self.options.duration);
1949
1950				}
1951
1952			});
1953		}
1954	};
1955
1956	// expose to scope
1957	$.extend(theme, {
1958		PluginToggle: PluginToggle
1959	});
1960
1961	// jquery plugin
1962	$.fn.themePluginToggle = function(opts) {
1963		return this.map(function() {
1964			var $this = $(this);
1965
1966			if ($this.data(instanceName)) {
1967				return $this.data(instanceName);
1968			} else {
1969				return new PluginToggle($this, opts);
1970			}
1971
1972		});
1973	}
1974
1975}).apply(this, [window.theme, jQuery]);
1976
1977// Tweets
1978(function(theme, $) {
1979
1980	theme = theme || {};
1981
1982	var instanceName = '__tweets';
1983
1984	var PluginTweets = function($el, opts) {
1985		return this.initialize($el, opts);
1986	};
1987
1988	PluginTweets.defaults = {
1989		username: null,
1990		count: 2,
1991		URL: 'php/twitter-feed.php'
1992	};
1993
1994	PluginTweets.prototype = {
1995		initialize: function($el, opts) {
1996			if ($el.data(instanceName)) {
1997				return this;
1998			}
1999
2000			this.$el = $el;
2001
2002			this
2003				.setData()
2004				.setOptions(opts)
2005				.build();
2006
2007			return this;
2008		},
2009
2010		setData: function() {
2011			this.$el.data(instanceName, this);
2012
2013			return this;
2014		},
2015
2016		setOptions: function(opts) {
2017			this.options = $.extend(true, {}, PluginTweets.defaults, opts, {
2018				wrapper: this.$el
2019			});
2020
2021			return this;
2022		},
2023
2024		build: function() {
2025			if (this.options.username == null || this.options.username == '') {
2026				return this;
2027			}
2028
2029			var self = this,
2030				$wrapper = this.options.wrapper;
2031
2032			$.ajax({
2033				type: 'GET',
2034				data: {
2035					twitter_screen_name: self.options.username,
2036					tweets_to_display: self.options.count
2037				},
2038				url: self.options.URL,
2039			}).done(function(html) {
2040				$wrapper.html(html).find('a').attr('target','_blank');
2041			});
2042
2043			return this;
2044		}
2045	};
2046
2047	// expose to scope
2048	$.extend(theme, {
2049		PluginTweets: PluginTweets
2050	});
2051
2052	// jquery plugin
2053	$.fn.themePluginTweets = function(opts) {
2054		return this.map(function() {
2055			var $this = $(this);
2056
2057			if ($this.data(instanceName)) {
2058				return $this.data(instanceName);
2059			} else {
2060				return new PluginTweets($this, opts);
2061			}
2062
2063		});
2064	}
2065
2066}).apply(this, [window.theme, jQuery]);
2067
2068// Validation
2069(function(theme, $) {
2070
2071	theme = theme || {};
2072
2073	$.extend(theme, {
2074
2075		PluginValidation: {
2076
2077			defaults: {
2078				validator: {
2079					highlight: function(element) {
2080						$(element)
2081							.parent()
2082							.removeClass('has-success')
2083							.addClass('has-error');
2084					},
2085					success: function(element) {
2086						$(element)
2087							.parent()
2088							.removeClass('has-error')
2089							.addClass('has-success')
2090							.find('label.error')
2091							.remove();
2092					},
2093					errorPlacement: function(error, element) {
2094						if (element.attr('type') == 'radio' || element.attr('type') == 'checkbox') {
2095							error.appendTo(element.parent().parent());
2096						} else {
2097							error.insertAfter(element);
2098						}
2099					}
2100				},
2101			},
2102
2103			initialize: function(opts) {
2104				initialized = true;
2105
2106				this
2107					.setOptions(opts)
2108					.build();
2109
2110				return this;
2111			},
2112
2113			setOptions: function(opts) {
2114				this.options = $.extend(true, {}, this.defaults, opts);
2115
2116				return this;
2117			},
2118
2119			build: function() {
2120				var self = this;
2121
2122				if (!($.isFunction($.validator))) {
2123					return this;
2124				}
2125
2126				self.addMethods();
2127				self.setMessageGroups();
2128
2129				$.validator.setDefaults(self.options.validator);
2130
2131				return this;
2132			},
2133
2134			addMethods: function() {
2135				var self = this;
2136
2137				$.validator.addMethod('captcha', function(value, element, params) {
2138					var captchaValid = false;
2139
2140					$.ajax({
2141						type: 'POST',
2142						async: false,
2143						dataType: 'json',
2144						data: {
2145							captcha: $.trim(value)
2146						},
2147						success: function(data) {
2148							if (data.response == 'success') {
2149								captchaValid = true;
2150							}
2151						}
2152					});
2153
2154					if (captchaValid) {
2155						return true;
2156					}
2157
2158				}, '');
2159			},
2160
2161			setMessageGroups: function() {
2162
2163				$('.checkbox-group[data-msg-required], .radio-group[data-msg-required]').each(function() {
2164					var message = $(this).data('msg-required');
2165					$(this).find('input').attr('data-msg-required', message);
2166				});
2167
2168			}
2169
2170		}
2171
2172	});
2173
2174}).apply(this, [window.theme, jQuery]);
2175
2176// Video Background
2177(function(theme, $) {
2178
2179	theme = theme || {};
2180
2181	var instanceName = '__videobackground';
2182
2183	var PluginVideoBackground = function($el, opts) {
2184		return this.initialize($el, opts);
2185	};
2186
2187	PluginVideoBackground.defaults = {
2188		overlay: true,
2189		volume: 1,
2190		playbackRate: 1,
2191		muted: true,
2192		loop: true,
2193		autoplay: true,
2194		position: '50% 50%',
2195		posterType: 'detect'
2196	};
2197
2198	PluginVideoBackground.prototype = {
2199		initialize: function($el, opts) {
2200			this.$el = $el;
2201
2202			this
2203				.setData()
2204				.setOptions(opts)
2205				.build();
2206
2207			return this;
2208		},
2209
2210		setData: function() {
2211			this.$el.data(instanceName, this);
2212
2213			return this;
2214		},
2215
2216		setOptions: function(opts) {
2217			this.options = $.extend(true, {}, PluginVideoBackground.defaults, opts, {
2218				path: this.$el.data('video-path'),
2219				wrapper: this.$el
2220			});
2221
2222			return this;
2223		},
2224
2225		build: function() {
2226
2227			if (!($.isFunction($.fn.vide)) || (!this.options.path)) {
2228				return this;
2229			}
2230
2231			if (this.options.overlay) {
2232				this.options.wrapper.prepend(
2233					$('<div />').addClass('video-overlay')
2234				);
2235			}
2236
2237			this.options.wrapper.vide(this.options.path, this.options);
2238
2239			return this;
2240		}
2241	};
2242
2243	// expose to scope
2244	$.extend(theme, {
2245		PluginVideoBackground: PluginVideoBackground
2246	});
2247
2248	// jquery plugin
2249	$.fn.themePluginVideoBackground = function(opts) {
2250		return this.map(function() {
2251			var $this = $(this);
2252
2253			if ($this.data(instanceName)) {
2254				return $this.data(instanceName);
2255			} else {
2256				return new PluginVideoBackground($this, opts);
2257			}
2258
2259		});
2260	}
2261
2262}).apply(this, [window.theme, jQuery]);
2263
2264// Word Rotate
2265(function(theme, $) {
2266	
2267	theme = theme || {};
2268	
2269	var instanceName = '__wordRotate';
2270
2271	var PluginWordRotate = function($el, opts) {
2272		return this.initialize($el, opts);
2273	};
2274
2275	PluginWordRotate.defaults = {
2276		delay: 2000,
2277		animDelay: 300
2278	};
2279
2280	PluginWordRotate.prototype = {
2281		initialize: function($el, opts) {
2282			if ( $el.data( instanceName ) ) {
2283				return this;
2284			}
2285
2286			this.$el = $el;
2287
2288			this
2289				.setData()
2290				.setOptions(opts)
2291				.build();
2292
2293			return this;
2294		},
2295
2296		setData: function() {
2297			this.$el.data(instanceName, this);
2298
2299			return this;
2300		},
2301
2302		setOptions: function(opts) {
2303			this.options = $.extend(true, {}, PluginWordRotate.defaults, opts, {
2304				wrapper: this.$el
2305			});
2306
2307			return this;
2308		},
2309
2310		build: function() {
2311			var self = this,
2312				$el = this.options.wrapper,
2313				itemsWrapper = $el.find(".word-rotate-items"),
2314				items = itemsWrapper.find("> span"),
2315				firstItem = items.eq(0),
2316				firstItemClone = firstItem.clone(),
2317				currentItem = 1,
2318				currentTop = 0,
2319				itemWidth = 0;
2320
2321			itemsWrapper
2322				.width(firstItem.width() + "px")
2323				.append(firstItemClone);
2324
2325			$el				
2326				.addClass("active");
2327
2328			setInterval(function() {
2329
2330				currentTop = (currentItem * $el.height());
2331				currentItem++;
2332
2333				if(currentItem <= items.length) {
2334					itemWidth = items.eq(currentItem-1).width();
2335				} else {
2336					itemWidth = items.eq(0).width();
2337				}
2338
2339				itemsWrapper.animate({
2340					top: -(currentTop) + "px",
2341					width: itemWidth + "px"
2342				}, self.options.animDelay, "easeOutQuad", function() {
2343
2344					if(currentItem > items.length) {
2345
2346						itemsWrapper.css("top", 0);
2347						currentItem = 1;
2348
2349					}
2350
2351				});
2352
2353			}, self.options.delay);
2354
2355			return this;
2356		}
2357	};
2358
2359	// expose to scope
2360	$.extend(theme, {
2361		PluginWordRotate: PluginWordRotate
2362	});
2363
2364	// jquery plugin
2365	$.fn.themePluginWordRotate = function(opts) {
2366		return this.map(function() {
2367			var $this = $(this);
2368
2369			if ($this.data(instanceName)) {
2370				return $this.data(instanceName);
2371			} else {
2372				return new PluginWordRotate($this, opts);
2373			}
2374			
2375		});
2376	}
2377
2378}).apply(this, [ window.theme, jQuery ]);
2379
2380// Account
2381(function(theme, $) {
2382
2383	theme = theme || {};
2384
2385	var initialized = false;
2386
2387	$.extend(theme, {
2388
2389		Account: {
2390
2391			defaults: {
2392				wrapper: $('#headerAccount')
2393			},
2394
2395			initialize: function($wrapper, opts) {
2396				if (initialized) {
2397					return this;
2398				}
2399
2400				initialized = true;
2401				this.$wrapper = ($wrapper || this.defaults.wrapper);
2402
2403				this
2404					.setOptions(opts)
2405					.events();
2406
2407				return this;
2408			},
2409
2410			setOptions: function(opts) {
2411				this.options = $.extend(true, {}, this.defaults, opts, this.$wrapper.data('plugin-options'));
2412
2413				return this;
2414			},
2415
2416			events: function() {
2417				var self = this;
2418
2419				self.$wrapper.find('input').on('focus', function() {
2420					self.$wrapper.addClass('open');
2421
2422					$(document).mouseup(function(e) {
2423						if (!self.$wrapper.is(e.target) && self.$wrapper.has(e.target).length === 0) {
2424							self.$wrapper.removeClass('open');
2425						}
2426					});
2427				});
2428
2429				$('#headerSignUp').on('click', function(e) {
2430					e.preventDefault();
2431					self.$wrapper.addClass('signup').removeClass('signin').removeClass('recover');
2432					self.$wrapper.find('.signup-form input:first').focus();
2433				});
2434
2435				$('#headerSignIn').on('click', function(e) {
2436					e.preventDefault();
2437					self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover');
2438					self.$wrapper.find('.signin-form input:first').focus();
2439				});
2440
2441				$('#headerRecover').on('click', function(e) {
2442					e.preventDefault();
2443					self.$wrapper.addClass('recover').removeClass('signup').removeClass('signin');
2444					self.$wrapper.find('.recover-form input:first').focus();
2445				});
2446
2447				$('#headerRecoverCancel').on('click', function(e) {
2448					e.preventDefault();
2449					self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover');
2450					self.$wrapper.find('.signin-form input:first').focus();
2451				});
2452			}
2453
2454		}
2455
2456	});
2457
2458}).apply(this, [window.theme, jQuery]);
2459
2460// Nav
2461(function(theme, $) {
2462
2463	theme = theme || {};
2464
2465	var initialized = false;
2466
2467	$.extend(theme, {
2468
2469		Nav: {
2470
2471			defaults: {
2472				wrapper: $('#mainNav'),
2473				scrollDelay: 600,
2474				scrollAnimation: 'easeOutQuad'
2475			},
2476
2477			initialize: function($wrapper, opts) {
2478				if (initialized) {
2479					return this;
2480				}
2481
2482				initialized = true;
2483				this.$wrapper = ($wrapper || this.defaults.wrapper);
2484
2485				this
2486					.setOptions(opts)
2487					.build()
2488					.events();
2489
2490				return this;
2491			},
2492
2493			setOptions: function(opts) {
2494				this.options = $.extend(true, {}, this.defaults, opts, this.$wrapper.data('plugin-options'));
2495
2496				return this;
2497			},
2498
2499			build: function() {
2500				var self = this,
2501					$html = $('html'),
2502					$header = $('#header'),
2503					thumbInfoPreview;
2504
2505				// Add Arrows
2506				$header.find('.dropdown-toggle, .dropdown-submenu > a').append($('<i />').addClass('fa fa-caret-down'));
2507
2508				// Preview Thumbs
2509				self.$wrapper.find('a[data-thumb-preview]').each(function() {
2510					thumbInfoPreview = $('<span />').addClass('thumb-info thumb-info-preview')
2511											.append($('<span />').addClass('thumb-info-wrapper')
2512												.append($('<span />').addClass('thumb-info-image').css('background-image', 'url(' + $(this).data('thumb-preview') + ')')
2513										   )
2514									   );
2515
2516					$(this).append(thumbInfoPreview);
2517				});
2518
2519				// Side Header Right (Reverse Dropdown)
2520				if($html.hasClass('side-header-right')) {
2521					$header.find('.dropdown').addClass('dropdown-reverse');
2522				}
2523
2524				return this;
2525			},
2526
2527			events: function() {
2528				var self = this,
2529					$header = $('#header'),
2530					$window = $(window);
2531
2532				$header.find('a[href="#"]').on('click', function(e) {
2533					e.preventDefault();
2534				});
2535
2536				// Mobile Arrows
2537				$header.find('.dropdown-toggle[href="#"], .dropdown-submenu a[href="#"], .dropdown-toggle[href!="#"] .fa-caret-down, .dropdown-submenu a[href!="#"] .fa-caret-down').on('click', function(e) {
2538					e.preventDefault();
2539					if ($window.width() < 992) {
2540						$(this).closest('li').toggleClass('opened');
2541					}
2542				});
2543
2544				// Touch Devices with normal resolutions
2545				if('ontouchstart' in document.documentElement) {
2546					$header.find('.dropdown-toggle:not([href="#"]), .dropdown-submenu > a:not([href="#"])')
2547						.on('touchstart click', function(e) {
2548							if($window.width() > 991) {
2549
2550								e.stopPropagation();
2551								e.preventDefault();
2552
2553								if(e.handled !== true) {
2554
2555									var li = $(this).closest('li');
2556
2557									if(li.hasClass('tapped')) {
2558										location.href = $(this).attr('href');
2559									}
2560
2561									li.addClass('tapped');
2562
2563									e.handled = true;
2564								} else {
2565									return false;
2566								}
2567
2568								return false;
2569
2570							}
2571						})
2572						.on('blur', function(e) {
2573							$(this).closest('li').removeClass('tapped');
2574						});
2575
2576				}
2577
2578				// Anchors Position
2579				$('[data-hash]').each(function() {
2580
2581					var target = $(this).attr('href'),
2582						offset = ($(this).is("[data-hash-offset]") ? $(this).data('hash-offset') : 0);
2583
2584					if($(target).get(0)) {
2585						$(this).on('click', function(e) {
2586							e.preventDefault();
2587
2588							// Close Collapse if Opened
2589							$(this).parents('.collapse.in').removeClass('in');
2590
2591							self.scrollToTarget(target, offset);
2592
2593							return;
2594						});
2595					}
2596
2597				});
2598
2599				// Mobile Redirect - (Ignores the Dropdown from Bootstrap)
2600				$('.mobile-redirect').on('click', function() {
2601					if ($window.width() < 992) {
2602						self.location = $(this).attr('href');
2603					}
2604				});
2605
2606				return this;
2607			},
2608
2609			scrollToTarget: function(target, offset) {
2610				var self = this;
2611
2612				$('body').addClass('scrolling');
2613
2614				$('html, body').animate({
2615					scrollTop: $(target).offset().top - offset
2616				}, self.options.scrollDelay, self.options.scrollAnimation, function() {
2617					$('body').removeClass('scrolling');
2618				});
2619
2620				return this;
2621
2622			}
2623
2624		}
2625
2626	});
2627
2628}).apply(this, [window.theme, jQuery]);
2629
2630// Newsletter
2631(function(theme, $) {
2632
2633	theme = theme || {};
2634
2635	var initialized = false;
2636
2637	$.extend(theme, {
2638
2639		Newsletter: {
2640
2641			defaults: {
2642				wrapper: $('#newsletterForm')
2643			},
2644
2645			initialize: function($wrapper, opts) {
2646				if (initialized) {
2647					return this;
2648				}
2649
2650				initialized = true;
2651				this.$wrapper = ($wrapper || this.defaults.wrapper);
2652
2653				this
2654					.setOptions(opts)
2655					.build();
2656
2657				return this;
2658			},
2659
2660			setOptions: function(opts) {
2661				this.options = $.extend(true, {}, this.defaults, opts, this.$wrapper.data('plugin-options'));
2662
2663				return this;
2664			},
2665
2666			build: function() {
2667				if (!($.isFunction($.fn.validate))) {
2668					return this;
2669				}
2670
2671				var self = this,
2672					$email = self.$wrapper.find('#newsletterEmail'),
2673					$success = $('#newsletterSuccess'),
2674					$error = $('#newsletterError');
2675
2676				self.$wrapper.validate({
2677					submitHandler: function(form) {
2678
2679						$.ajax({
2680							type: 'POST',
2681							url: self.$wrapper.attr('action'),
2682							data: {
2683								'email': $email.val()
2684							},
2685							dataType: 'json',
2686							success: function(data) {
2687								if (data.response == 'success') {
2688
2689									$success.removeClass('hidden');
2690									$error.addClass('hidden');
2691
2692									$email
2693										.val('')
2694										.blur()
2695										.closest('.control-group')
2696										.removeClass('success')
2697										.removeClass('error');
2698
2699								} else {
2700
2701									$error.html(data.message);
2702									$error.removeClass('hidden');
2703									$success.addClass('hidden');
2704
2705									$email
2706										.blur()
2707										.closest('.control-group')
2708										.removeClass('success')
2709										.addClass('error');
2710
2711								}
2712							}
2713						});
2714
2715					},
2716					rules: {
2717						newsletterEmail: {
2718							required: true,
2719							email: true
2720						}
2721					},
2722					errorPlacement: function(error, element) {
2723
2724					}
2725				});
2726
2727				return this;
2728			}
2729
2730		}
2731
2732	});
2733
2734}).apply(this, [window.theme, jQuery]);
2735
2736// Search
2737(function(theme, $) {
2738
2739	theme = theme || {};
2740
2741	var initialized = false;
2742
2743	$.extend(theme, {
2744
2745		Search: {
2746
2747			defaults: {
2748				wrapper: $('#searchForm')
2749			},
2750
2751			initialize: function($wrapper, opts) {
2752				if (initialized) {
2753					return this;
2754				}
2755
2756				initialized = true;
2757				this.$wrapper = ($wrapper || this.defaults.wrapper);
2758
2759				this
2760					.setOptions(opts)
2761					.build();
2762
2763				return this;
2764			},
2765
2766			setOptions: function(opts) {
2767				this.options = $.extend(true, {}, this.defaults, opts, this.$wrapper.data('plugin-options'));
2768
2769				return this;
2770			},
2771
2772			build: function() {
2773				if (!($.isFunction($.fn.validate))) {
2774					return this;
2775				}
2776
2777				this.$wrapper.validate({
2778					errorPlacement: function(error, element) {}
2779				});
2780
2781				return this;
2782			}
2783
2784		}
2785
2786	});
2787
2788}).apply(this, [window.theme, jQuery]);
2789
2790// Sticky Header
2791(function(theme, $) {
2792
2793	theme = theme || {};
2794
2795	var initialized = false;
2796
2797	$.extend(theme, {
2798
2799		StickyHeader: {
2800
2801			defaults: {
2802				wrapper: $('#header'),
2803				headerBody: $('#header .header-body'),
2804				stickyEnabled: true,
2805				stickyEnableOnBoxed: true,
2806				stickyEnableOnMobile: true,
2807				stickyStartAt: 0,
2808				stickyStartAtElement: false,
2809				stickySetTop: 0,
2810				stickyChangeLogo: false,
2811				stickyChangeLogoWrapper: true
2812			},
2813
2814			initialize: function($wrapper, opts) {
2815				if (initialized) {
2816					return this;
2817				}
2818
2819				initialized = true;
2820				this.$wrapper = ($wrapper || this.defaults.wrapper);
2821
2822				this
2823					.setOptions(opts)
2824					.build()
2825					.events();
2826
2827				return this;
2828			},
2829
2830			setOptions: function(opts) {
2831				this.options = $.extend(true, {}, this.defaults, opts, this.$wrapper.data('plugin-options'));
2832
2833				return this;
2834			},
2835
2836			build: function() {
2837				if (!this.options.stickyEnableOnBoxed && $('html').hasClass('boxed') || !this.options.stickyEnabled) {
2838					return this;
2839				}
2840
2841				var self = this,
2842					$html = $('html'),
2843					$window = $(window),
2844					sideHeader = $html.hasClass('side-header');
2845
2846				// HTML Classes
2847				$html.addClass('sticky-header-enabled');
2848
2849				if (parseInt(self.options.stickySetTop) < 0) {
2850					$html.addClass('sticky-header-negative');
2851				}
2852
2853				// Set Start At
2854				if(self.options.stickyStartAtElement) {
2855
2856					var $stickyStartAtElement = $(self.options.stickyStartAtElement);
2857
2858					$(window).on('scroll resize', function() {
2859						self.options.stickyStartAt = $stickyStartAtElement.offset().top;
2860					});
2861
2862					$(window).trigger('resize');
2863				}
2864
2865				// Boxed
2866				if($html.hasClass('boxed') && (parseInt(self.options.stickyStartAt) == 0) && $window.width() > 991) {
2867					self.options.stickyStartAt = 30;
2868				}
2869
2870				// Set Wrapper Min-Height
2871				self.options.wrapper.css('min-height', self.options.wrapper.height());
2872
2873				// Check Sticky Header
2874				self.checkStickyHeader = function() {
2875					if ($window.scrollTop() >= parseInt(self.options.stickyStartAt)) {
2876						self.activateStickyHeader();
2877					} else {
2878						self.deactivateStickyHeader();
2879					}
2880				};
2881				
2882				// Activate Sticky Header
2883				self.activateStickyHeader = function() {
2884
2885					if ($window.width() < 992) {
2886						if (!self.options.stickyEnableOnMobile) {
2887							self.deactivateStickyHeader();
2888							return;
2889						}
2890					} else {
2891						if (sideHeader) {
2892							self.deactivateStickyHeader();
2893							return;
2894						}
2895					}
2896
2897					$html.addClass('sticky-header-active');
2898
2899					self.options.headerBody.css('top', self.options.stickySetTop);
2900
2901					if (self.options.stickyChangeLogo) {
2902						self.changeLogo(true);
2903					}
2904
2905					$.event.trigger({
2906						type: 'stickyHeader.activate'
2907					});
2908				};
2909
2910				// Deactivate Sticky Header
2911				self.deactivateStickyHeader = function() {
2912
2913					$html.removeClass('sticky-header-active');
2914
2915					self.options.headerBody.css('top', 0);
2916
2917					if (self.options.stickyChangeLogo) {
2918						self.changeLogo(false);
2919					}
2920
2921					$.event.trigger({
2922						type: 'stickyHeader.deactivate'
2923					});
2924				};
2925
2926				// Always Sticky
2927				if (parseInt(self.options.stickyStartAt) <= 0) {
2928					self.activateStickyHeader();
2929				}
2930
2931				// Set Logo
2932				if (self.options.stickyChangeLogo) {
2933
2934					var $logoWrapper = self.options.wrapper.find('.header-logo'),
2935						$logo = $logoWrapper.find('img'),
2936						logoWidth = $logo.attr('width'),
2937						logoHeight = $logo.attr('height'),
2938						logoSmallTop = parseInt($logo.attr('data-sticky-top') ? $logo.attr('data-sticky-top') : 0),
2939						logoSmallWidth = parseInt($logo.attr('data-sticky-width') ? $logo.attr('data-sticky-width') : 'auto'),
2940						logoSmallHeight = parseInt($logo.attr('data-sticky-height') ? $logo.attr('data-sticky-height') : 'auto');
2941
2942					if (self.options.stickyChangeLogoWrapper) {
2943						$logoWrapper.css({
2944							'width': $logo.outerWidth(true),
2945							'height': $logo.outerHeight(true)
2946						});
2947					}
2948
2949					self.changeLogo = function(activate) {
2950						if(activate) {
2951							$logo.css({
2952								'top': logoSmallTop,
2953								'width': logoSmallWidth,
2954								'height': logoSmallHeight
2955							});
2956						} else {
2957							$logo.css({
2958								'top': 0,
2959								'width': logoWidth,
2960								'height': logoHeight
2961							});
2962						}
2963					}
2964
2965				}
2966
2967				return this;
2968			},
2969
2970			events: function() {
2971				var self = this;
2972
2973				if (!this.options.stickyEnableOnBoxed && $('body').hasClass('boxed') || !this.options.stickyEnabled) {
2974					return this;
2975				}
2976
2977				if (!self.options.alwaysStickyEnabled) {
2978					$(window).on('scroll resize', function() {
2979						self.checkStickyHeader();
2980					});
2981				} else {
2982					self.activateStickyHeader();
2983				}
2984
2985				return this;
2986			}
2987
2988		}
2989
2990	});
2991
2992}).apply(this, [window.theme, jQuery]);

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.