PageSourceSearch

https://www.takwene.com/assets/js/theme.js

js takwene.com collected 2026-09-24 19:21:11 UTC 65,296 bytes, 3,196 lines download raw bytes

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