PageSourceSearch

https://congresoneurologia.com.ar/js/theme.js

js congresoneurologia.com.ar collected 2026-10-08 21:15:04 UTC 98,657 bytes, 4,695 lines download raw bytes

1// Theme
2(function( $ ) {
3
4	'use strict';
5
6	window.theme = {};
7
8	// Theme Common Functions
9	window.theme.fn = {
10
11		getOptions: function(opts) {
12
13			if (typeof(opts) == 'object') {
14
15				return opts;
16
17			} else if (typeof(opts) == 'string') {
18
19				try {
20					return JSON.parse(opts.replace(/'/g,'"').replace(';',''));
21				} catch(e) {
22					return {};
23				}
24
25			} else {
26
27				return {};
28
29			}
30
31		},
32
33		getOptionsSemicolon: function(opts) {
34
35			if (typeof(opts) == 'object') {
36
37				return opts;
38
39			} else if (typeof(opts) == 'string') {
40
41				try {
42					return JSON.parse(opts.replace(/'/g,'"'));
43				} catch(e) {
44					return {};
45				}
46
47			} else {
48
49				return {};
50
51			}
52
53		}
54
55	};
56
57}).apply( this, [ jQuery ]);
58
59// Animate
60(function(theme, $) {
61
62	'use strict';
63
64	theme = theme || {};
65
66	var instanceName = '__animate';
67
68	var PluginAnimate = function($el, opts) {
69		return this.initialize($el, opts);
70	};
71
72	PluginAnimate.defaults = {
73		accX: 0,
74		accY: -80,
75		delay: 100,
76		duration: '750ms'
77	};
78
79	PluginAnimate.prototype = {
80		initialize: function($el, opts) {
81			if ($el.data(instanceName)) {
82				return this;
83			}
84
85			this.$el = $el;
86
87			this
88				.setData()
89				.setOptions(opts)
90				.build();
91
92			return this;
93		},
94
95		setData: function() {
96			this.$el.data(instanceName, this);
97
98			return this;
99		},
100
101		setOptions: function(opts) {
102			this.options = $.extend(true, {}, PluginAnimate.defaults, opts, {
103				wrapper: this.$el
104			});
105
106			return this;
107		},
108
109		build: function() {
110			var self = this,
111				$el = this.options.wrapper,
112				delay = 0,
113				duration = this.options.duration,
114				elTopDistance = $el.offset().top + 100,
115				windowTopDistance = $(window).scrollTop();
116
117			$el.addClass('appear-animation animated');
118
119			if (!$('html').hasClass('no-csstransitions') && $(window).width() > 767 && elTopDistance >= windowTopDistance) {
120
121				$el.appear(function() {
122
123					$el.one('animation:show', function(ev) {
124						delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay);
125						duration = ($el.attr('data-appear-animation-duration') ? $el.attr('data-appear-animation-duration') : self.options.duration);
126
127						if (duration != '750ms') {
128							$el.css('animation-duration', duration);
129						}
130
131						$el.css('animation-delay', delay + 'ms');
132
133						$el.addClass($el.attr('data-appear-animation') + ' appear-animation-visible');
134					});
135
136					$el.trigger('animation:show');
137
138				}, {
139					accX: self.options.accX,
140					accY: self.options.accY
141				});
142
143			} else {
144
145				$el.addClass('appear-animation-visible');
146
147			}
148
149			return this;
150		}
151	};
152
153	// expose to scope
154	$.extend(theme, {
155		PluginAnimate: PluginAnimate
156	});
157
158	// jquery plugin
159	$.fn.themePluginAnimate = function(opts) {
160		return this.map(function() {
161			var $this = $(this);
162
163			if ($this.data(instanceName)) {
164				return $this.data(instanceName);
165			} else {
166				return new PluginAnimate($this, opts);
167			}
168
169		});
170	};
171
172}).apply(this, [window.theme, jQuery]);
173
174// Carousel
175(function(theme, $) {
176
177	'use strict';
178
179	theme = theme || {};
180
181	var instanceName = '__carousel';
182
183	var PluginCarousel = function($el, opts) {
184		return this.initialize($el, opts);
185	};
186
187	PluginCarousel.defaults = {
188		loop: true,
189		responsive: {
190			0: {
191				items: 1
192			},
193			575: {
194				items: 1
195			},
196			767: {
197				items: 2
198			},
199			991: {
200				items: 3
201			},
202			1199: {
203				items: 4
204			}
205		},
206		navText: [],
207		clonePrevNext: false,
208		vertical: false,
209		rewind: false
210	};
211
212	PluginCarousel.prototype = {
213		initialize: function($el, opts) {
214			if ($el.data(instanceName)) {
215				return this;
216			}
217
218			this.$el = $el;
219
220			this
221				.setData()
222				.setOptions(opts)
223				.build();
224
225			return this;
226		},
227
228		setData: function() {
229			this.$el.data(instanceName, this);
230
231			return this;
232		},
233
234		setOptions: function(opts) {
235			this.options = $.extend(true, {}, PluginCarousel.defaults, opts, {
236				wrapper: this.$el
237			});
238
239			return this;
240		},
241
242		build: function() {
243			if (!($.isFunction($.fn.owlCarousel))) {
244				return this;
245			}
246
247			var self = this,
248				$el = this.options.wrapper;
249
250			// Add Theme Class
251			$el.addClass('owl-theme');
252
253			// Force RTL according to HTML dir attribute
254			if ($('html').attr('dir') == 'rtl') {
255				this.options = $.extend(true, {}, this.options, {
256					rtl: true
257				});
258			}
259
260			if (this.options.items == 1) {
261				this.options.responsive = {}
262			}
263
264			// Auto Height Fixes
265			if (this.options.autoHeight) {
266				var itemsHeight = [];
267
268				$el.find('.owl-item').each(function(){
269					if( $(this).hasClass('active') ) {
270						itemsHeight.push( $(this).height() );
271					}
272				});
273
274				$(window).afterResize(function() {
275					$el.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) );
276				});
277
278				$(window).on('load', function() {
279					$el.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) );
280				});
281			}
282
283			// Initialize OwlCarousel
284			$el.owlCarousel(this.options).addClass('owl-carousel-init');
285
286			// Carousel Corner Left Bottom Style
287			if( $('.carousel-corner-left-bottom').get(0) ) {
288				$('.carousel-corner-left-bottom').on('drag.owl.carousel change.owl.carousel', function(e){
289					$(this).find('.owl-item').addClass('changing');
290				});
291
292				$('.carousel-corner-left-bottom').on('changed.owl.carousel', function(e){
293					setTimeout(function(){
294						$('.carousel-corner-left-bottom').find('.owl-item').removeClass('changing');
295					}, 500);
296				});
297			}
298
299			// Carousel Center Active Items Style
300			if( $el.hasClass('carousel-center-active-items') ) {
301				var itemsActive    = $el.find('.owl-item.active'),
302					indexCenter    = Math.floor( ($el.find('.owl-item.active').length - 1) / 2 ),
303					itemCenter     = itemsActive.eq(indexCenter),
304					itemCenterPrev = itemCenter.prev(),
305					itemCenterNext = itemCenter.next();
306
307				itemCenter.addClass('current');
308				itemCenterPrev.addClass('remove-blur');
309				itemCenterNext.addClass('remove-blur');
310
311				$el.on('change.owl.carousel', function(event) {
312				  	$el.find('.owl-item').removeClass('current');
313					
314					setTimeout(function(){
315					  	var itemsActive    = $el.find('.owl-item.active'),
316					  		itemCenter     = itemsActive.eq(indexCenter);
317
318					  	itemCenter.addClass('current');
319
320						// Add blur effect for first and last active items
321					  	itemsActive.first().removeClass('remove-blur');
322						itemsActive.last().removeClass('remove-blur');
323
324					  	// Remove blur effect for elements at right and left of current item
325					  	itemCenter.prev().addClass('remove-blur');
326						itemCenter.next().addClass('remove-blur');
327
328					}, 100);
329				});
330
331				$el.on('resized.owl.carousel', function(event) {
332					if( $el.find('.owl-item.active').length == 1 ) {
333						$el
334							.css({
335								width: '100%'
336							})
337							.addClass('rm-degrade-now');
338					} else {
339						$el
340							.css({
341								width: ''
342							})
343							.removeClass('rm-degrade-now');
344					}
345
346					$el.trigger('refresh.owl.carousel');
347				});
348
349				// Refresh
350				$el.trigger('refresh.owl.carousel');
351			}
352
353			// Clone Prev Next
354			if (this.options.clonePrevNext) {
355				$el.find('.owl-item').each(function() {
356					$(this).prev().find('div:not(.clone-inside)').clone().addClass('clone-inside prev').prependTo($(this));
357					$(this).next().find('div:not(.clone-inside)').clone().addClass('clone-inside next').appendTo($(this));
358				});
359
360				$el.on('change.owl.carousel', function(){
361					$el.find('.owl-item.active div:not(.prev)').css('opacity', 0);
362				});
363
364				$el.on('changed.owl.carousel', function(){
365					$el.find('.owl-item').one('animationend', function(){
366						$el.find('.owl-item div:not(.prev)').css('opacity', 1);
367						$el.find('.owl-item.cloned div:not(.prev)').css('opacity', 0);
368						$el.find('.owl-item.active div:not(.prev)').css('opacity', 1);
369					});
370						
371				});
372
373				$el.on('drag.owl.carousel', function(){
374					$el.find('.owl-item div:not(.prev)').css('opacity', 1);
375				});
376			}
377
378			return this;
379		}
380	};
381
382	// expose to scope
383	$.extend(theme, {
384		PluginCarousel: PluginCarousel
385	});
386
387	// jquery plugin
388	$.fn.themePluginCarousel = function(opts) {
389		return this.map(function() {
390			var $this = $(this);
391
392			if ($this.data(instanceName)) {
393				return $this.data(instanceName);
394			} else {
395				return new PluginCarousel($this, opts);
396			}
397
398		});
399	}
400
401}).apply(this, [window.theme, jQuery]);
402
403// Chart Circular
404(function(theme, $) {
405
406	'use strict';
407
408	theme = theme || {};
409
410	var instanceName = '__chartCircular';
411
412	var PluginChartCircular = function($el, opts) {
413		return this.initialize($el, opts);
414	};
415
416	PluginChartCircular.defaults = {
417		accX: 0,
418		accY: -150,
419		delay: 1,
420		barColor: '#2388ed',
421		trackColor: '#F1F3F7',
422		scaleColor: false,
423		scaleLength: 5,
424		lineCap: 'square',
425		lineWidth: 3,
426		size: 150,
427		rotate: 0,
428		animate: ({
429			duration: 2500,
430			enabled: true
431		})
432	};
433
434	PluginChartCircular.prototype = {
435		initialize: function($el, opts) {
436			if ($el.data(instanceName)) {
437				return this;
438			}
439
440			this.$el = $el;
441
442			this
443				.setData()
444				.setOptions(opts)
445				.build();
446
447			return this;
448		},
449
450		setData: function() {
451			this.$el.data(instanceName, this);
452
453			return this;
454		},
455
456		setOptions: function(opts) {
457			this.options = $.extend(true, {}, PluginChartCircular.defaults, opts, {
458				wrapper: this.$el
459			});
460
461			return this;
462		},
463
464		build: function() {
465			if (!($.isFunction($.fn.appear)) || !($.isFunction($.fn.easyPieChart))) {
466				return this;
467			}
468
469			var self = this,
470				$el = this.options.wrapper,
471				value = ($el.attr('data-percent') ? $el.attr('data-percent') : 0),
472				percentEl = $el.find('.percent');
473
474			$.extend(true, self.options, {
475				onStep: function(from, to, currentValue) {
476					percentEl.html(parseInt(currentValue));
477				}
478			});
479
480			$el.attr('data-percent', 0);
481
482			$el.appear(function() {
483
484				$el.easyPieChart(self.options);
485
486				setTimeout(function() {
487
488					$el.data('easyPieChart').update(value);
489					$el.attr('data-percent', value);
490
491				}, self.options.delay);
492
493			}, {
494				accX: self.options.accX,
495				accY: self.options.accY
496			});
497
498			return this;
499		}
500	};
501
502	// expose to scope
503	$.extend(theme, {
504		PluginChartCircular: PluginChartCircular
505	});
506
507	// jquery plugin
508	$.fn.themePluginChartCircular = function(opts) {
509		return this.map(function() {
510			var $this = $(this);
511
512			if ($this.data(instanceName)) {
513				return $this.data(instanceName);
514			} else {
515				return new PluginChartCircular($this, opts);
516			}
517
518		});
519	}
520
521}).apply(this, [window.theme, jQuery]);
522
523// Counter
524(function(theme, $) {
525
526	'use strict';
527
528	theme = theme || {};
529
530	var instanceName = '__counter';
531
532	var PluginCounter = function($el, opts) {
533		return this.initialize($el, opts);
534	};
535
536	PluginCounter.defaults = {
537		accX: 0,
538		accY: 0,
539		speed: 3000,
540		refreshInterval: 100,
541		decimals: 0,
542		onUpdate: null,
543		onComplete: null
544	};
545
546	PluginCounter.prototype = {
547		initialize: function($el, opts) {
548			if ($el.data(instanceName)) {
549				return this;
550			}
551
552			this.$el = $el;
553
554			this
555				.setData()
556				.setOptions(opts)
557				.build();
558
559			return this;
560		},
561
562		setData: function() {
563			this.$el.data(instanceName, this);
564
565			return this;
566		},
567
568		setOptions: function(opts) {
569			this.options = $.extend(true, {}, PluginCounter.defaults, opts, {
570				wrapper: this.$el
571			});
572
573			return this;
574		},
575
576		build: function() {
577			if (!($.isFunction($.fn.countTo))) {
578				return this;
579			}
580
581			var self = this,
582				$el = this.options.wrapper;
583
584			$.extend(self.options, {
585				onComplete: function() {
586					if ($el.data('append')) {
587						$el.html($el.html() + $el.data('append'));
588					}
589
590					if ($el.data('prepend')) {
591						$el.html($el.data('prepend') + $el.html());
592					}
593				}
594			});
595
596			$el.appear(function() {
597
598				$el.countTo(self.options);
599
600			}, {
601				accX: self.options.accX,
602				accY: self.options.accY
603			});
604
605			return this;
606		}
607	};
608
609	// expose to scope
610	$.extend(theme, {
611		PluginCounter: PluginCounter
612	});
613
614	// jquery plugin
615	$.fn.themePluginCounter = function(opts) {
616		return this.map(function() {
617			var $this = $(this);
618
619			if ($this.data(instanceName)) {
620				return $this.data(instanceName);
621			} else {
622				return new PluginCounter($this, opts);
623			}
624
625		});
626	}
627
628}).apply(this, [window.theme, jQuery]);
629
630// Double Carousel
631(function(theme, $) {
632
633	'use strict';
634
635	theme = theme || {};
636
637	var instanceName = '__doubleCarousel';
638
639	var PluginDoubleCarousel = function($el, opts) {
640		return this.initialize($el, opts);
641	};
642
643	PluginDoubleCarousel.defaults = {
644		loop: true,
645		responsive: {
646			0: {
647				items: 1
648			},
649			479: {
650				items: 1
651			},
652			768: {
653				items: 1
654			},
655			979: {
656				items: 2
657			},
658			1199: {
659				items: 3
660			}
661		},
662		margin: 20,
663		mouseDrag: false,
664		navText: [],
665		autoplay: true,
666		autoplayTimeout: 5000,
667		rewind: false
668	};
669
670	PluginDoubleCarousel.prototype = {
671		initialize: function($el, opts) {
672			if ($el.data(instanceName)) {
673				return this;
674			}
675
676			this.$el = $el;
677			this.$carousels = $el.find('.owl-carousel');
678			this.$mainCarousel = $el.find('.wrapper-right .owl-carousel');
679			this.$mirrorCarousel = $el.find('.wrapper-left .owl-carousel');
680
681			this
682				.setData()
683				.setOptions(opts)
684				.build()
685				.navigation();
686
687			return this;
688		},
689
690		setData: function() {
691			this.$el.data(instanceName, this);
692
693			return this;
694		},
695
696		setOptions: function(opts) {
697			this.options = $.extend(true, {}, PluginDoubleCarousel.defaults, opts, {
698				wrapper: this.$el
699			});
700
701			return this;
702		},
703
704		build: function() {
705			if (!($.isFunction($.fn.owlCarousel))) {
706				return this;
707			}
708
709			var self 	  = this,
710				$el 	  = this.options.wrapper,
711				firstLoad = true;
712
713			// Add Theme Class
714			self.$carousels.addClass('owl-theme');
715
716			if (this.options.items == 1) {
717				this.options.responsive = {}
718			}
719
720			// Auto Height Fixes
721			if (this.options.autoHeight) {
722				var itemsHeight = [];
723
724				self.$carousels.find('.owl-item').each(function(){
725					if( $(this).hasClass('active') ) {
726						itemsHeight.push( $(this).height() );
727					}
728				});
729
730				$(window).afterResize(function() {
731					self.$carousels.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) );
732				});
733
734				$(window).on('load', function() {
735					self.$carousels.find('.owl-stage-outer').height( Math.max.apply(null, itemsHeight) );
736				});
737			}
738
739			// If Mobile
740			if ($.browser.mobile) {
741				this.options = $.extend(true, {}, this.options, {
742					mouseDrag: true,
743					margin: 0
744				});
745			}
746
747			// Initialize Main Carousel
748			self.$mainCarousel.owlCarousel(this.options).addClass('owl-carousel-init mirrored');
749
750			// Remove autoplay from Mirror Carousel
751			if( this.options.autoplay ) {
752				this.options = $.extend(true, {}, this.options, {
753					autoplay: false
754				});
755			}
756
757			// Initialize Mirror Carousel
758			self.$mirrorCarousel.owlCarousel(this.options).addClass('owl-carousel-init mirrored');			
759
760			// Set the first item position of Mirror Carousel
761			for( var i=1; i <= self.$mirrorCarousel.find('.owl-item.active').length - 1; i++ ) {
762				self.$mirrorCarousel.trigger('prev.owl.carousel');
763			}
764			
765			self.events();
766			self.recalcCarouselsWidth();
767
768			if( firstLoad == true ) {
769				firstLoad = false;
770				self.recalcCarouselsWidth();
771
772				setTimeout(function(){
773	        		self.$mirrorCarousel.addClass('show-carousel');
774	        		self.$mainCarousel.addClass('show-carousel');
775
776	        		self.refreshOnResize();
777        		}, 500);
778    		}
779
780    		if( firstLoad == false ) {
781    			self.setCurrentItem();
782    		}
783
784			return this;
785		},
786
787		setCurrentItem: function() {
788			var self = this,
789				flag = false;
790
791			self.$mainCarousel.on('change.owl.carousel', function(event) {
792			  	if (event.namespace && event.property.name === 'position' && flag == false) {
793				    var target = event.relatedTarget.relative(event.property.value, true);
794				    flag = true;
795
796				    self.$mirrorCarousel.owlCarousel('to', target - (self.$mirrorCarousel.find('.owl-item.active').length - 1), 300, true);
797				    self.$mirrorCarousel.find('.owl-item').removeClass('current');
798			        self.$mainCarousel.find('.owl-item').removeClass('current');
799			        
800			        setTimeout(function(){
801			        	self.$mirrorCarousel.find('.owl-item.active').eq( self.$mirrorCarousel.find('.owl-item.active').length - 1 ).addClass('current');
802			        	self.$mainCarousel.find('.owl-item.active').eq(0).addClass('current');
803			        }, 10);
804
805			        flag = false;
806			  	}
807			});
808
809			if( $.browser.mobile ) {
810				self.$mirrorCarousel.on('change.owl.carousel', function(event) {
811				  	if (event.namespace && event.property.name === 'position' && flag == false) {
812					    var target = event.relatedTarget.relative(event.property.value, true);
813					    flag = true;
814
815					    self.$mainCarousel.owlCarousel('to', target - (self.$mainCarousel.find('.owl-item.active').length - 1), 300, true);
816					    self.$mainCarousel.find('.owl-item').removeClass('current');
817				        self.$mirrorCarousel.find('.owl-item').removeClass('current');
818				        
819				        setTimeout(function(){
820				        	self.$mainCarousel.find('.owl-item.active').eq( self.$mainCarousel.find('.owl-item.active').length - 1 ).addClass('current');
821				        	self.$mirrorCarousel.find('.owl-item.active').eq(0).addClass('current');
822				        }, 10);
823
824				     	flag = false;
825				  	}
826				});
827			}
828		},
829		
830		recalcCarouselsWidth: function() {
831			var self 		     = this,
832				$el 		     = this.options.wrapper,
833				itemSize         = self.$mirrorCarousel.find('.owl-item').outerWidth(true),
834				dividedItemSize  = itemSize / 2,
835				totalActiveItems = self.$mirrorCarousel.find('.owl-item.active').length;
836
837			if( totalActiveItems > 1 ) {
838				
839				self.$mirrorCarousel.width( $el.find('.wrapper-left').width() + divi
839dedItemSize );
840				setTimeout(function(){
841					self.$mirrorCarousel.css({
842						right: dividedItemSize
843					});
844				}, 500);
845				
846				self.$mainCarousel.width( $el.find('.wrapper-right').width() + dividedItemSize );
847
848			} else {
849				
850				self.$mirrorCarousel.width( $el.find('.wrapper-left').width() );
851				setTimeout(function(){
852					self.$mirrorCarousel.css({
853						right: 0
854					});
855				}, 500);
856				
857				self.$mainCarousel.width( $el.find('.wrapper-right').width() );
858
859			}
860
861			$(document).trigger('double.carousel.recalc.width');
862		},
863
864		refreshOnResize: function() {
865			var self = this;
866
867			$(document).ready(function(){
868				$(window).afterResize(function(){
869					
870					// First - Refresh both carousels to set new sizes
871					self.$mirrorCarousel.trigger('refresh.owl.carousel');
872					self.$mainCarousel.trigger('refresh.owl.carousel');
873
874					// Second - Recalc Carousels width based on new sizes
875					setTimeout(function(){
876						self.recalcCarouselsWidth();
877					}, 600);
878
879				}, false, 300);
880			});
881		},
882
883		navigation: function() {
884			var self       = this,
885				$el        = this.options.wrapper,
886				$leftArrow  = $el.find('.arrow-left'),
887				$rightArrow = $el.find('.arrow-right');
888
889			$leftArrow.on('click', function(e){
890				self.$mainCarousel.trigger('prev.owl.carousel');
891			});
892
893			$rightArrow.on('click', function(e){
894				self.$mainCarousel.trigger('next.owl.carousel');
895			});
896		},
897
898		events: function() {
899			var self = this;
900
901			$(window).on('double.carousel.recalc.width', function(e){
902					
903				// Refresh carousels to set new sizes
904				self.$mirrorCarousel.trigger('refresh.owl.carousel');
905				self.$mainCarousel.trigger('refresh.owl.carousel');
906				
907				// Set current item
908				self.$mirrorCarousel.find('.owl-item.active').eq( self.$mirrorCarousel.find('.owl-item.active').length - 1 ).addClass('current');
909	        	self.$mainCarousel.find('.owl-item.active').eq(0).addClass('current');
910
911				// Position the first item
912				self.$mainCarousel.trigger('prev.owl.carousel').trigger('next.owl.carousel');
913        		
914			});
915		}
916	};
917
918	// expose to scope
919	$.extend(theme, {
920		PluginDoubleCarousel: PluginDoubleCarousel
921	});
922
923	// jquery plugin
924	$.fn.themePluginDoubleCarousel = function(opts) {
925		return this.map(function() {
926			var $this = $(this);
927
928			if ($this.data(instanceName)) {
929				return $this.data(instanceName);
930			} else {
931				return new PluginDoubleCarousel($this, opts);
932			}
933
934		});
935	}
936
937}).apply(this, [window.theme, jQuery]);
938
939// Float Element
940(function(theme, $) {
941
942	'use strict';
943
944	theme = theme || {};
945
946	var instanceName = '__floatElement';
947
948	var PluginFloatElement = function($el, opts) {
949		return this.initialize($el, opts);
950	};
951
952	PluginFloatElement.defaults = {
953		startPos: 'top',
954		speed: 3,
955		horizontal: false,
956		transition: false
957	};
958
959	PluginFloatElement.prototype = {
960		initialize: function($el, opts) {
961			if ($el.data(instanceName)) {
962				return this;
963			}
964
965			this.$el = $el;
966
967			this
968				.setData()
969				.setOptions(opts)
970				.build();
971
972			return this;
973		},
974
975		setData: function() {
976			this.$el.data(instanceName, this);
977
978			return this;
979		},
980
981		setOptions: function(opts) {
982			this.options = $.extend(true, {}, PluginFloatElement.defaults, opts, {
983				wrapper: this.$el
984			});
985
986			return this;
987		},
988
989		build: function() {
990			var self = this,
991				$el = this.options.wrapper,
992				$window = $(window),
993				minus;
994
995			if( self.options.style ) {
996				console.log(self.options.style);
997				$el.attr('style', self.options.style);
998			}
999
1000			if( $window.width() > 767 ) {
1001
1002				// Set Start Position
1003				if( self.options.startPos == 'none' ) {
1004					minus = '';
1005				} else if( self.options.startPos == 'top' ) {
1006					$el.css({
1007						top: 0
1008					});
1009					minus = '';
1010				} else {
1011					$el.css({
1012						bottom: 0
1013					});
1014					minus = '-';
1015				}
1016
1017				// Set Transition
1018				if( self.options.transition ) {
1019					$el.css({
1020						transition: 'ease transform 500ms'
1021					});
1022				}
1023
1024				// First Load
1025				self.movement(minus);	
1026
1027				// Scroll
1028				$window.on('scroll', function(){
1029					self.movement(minus);				   
1030				});
1031
1032			}
1033
1034			return this;
1035		},
1036
1037		movement: function(minus) {
1038			var self = this,
1039				$el = this.options.wrapper,
1040				$window = $(window),
1041				scrollTop = $window.scrollTop(),
1042		    	elementOffset = $el.offset().top,
1043		     	currentElementOffset = (elementOffset - scrollTop);
1044
1045		   	var scrollPercent = 100 * currentElementOffset / ($window.height());
1046
1047		   	if( $el.visible( true ) ) {
1048
1049		   		if( !self.options.horizontal ) {
1050
1051		   			$el.css({
1052			   			transform: 'translate3d(0, '+ minus + scrollPercent / self.options.speed +'%, 0)'
1053			   		});
1054
1055		   		} else {
1056
1057		   			$el.css({
1058			   			transform: 'translate3d('+ minus + scrollPercent / self.options.speed +'%, '+ minus + scrollPercent / self.options.speed +'%, 0)'
1059			   		});
1060
1061		   		}
1062		   		
1063		   	}
1064		}
1065	};
1066
1067	// expose to scope
1068	$.extend(theme, {
1069		PluginFloatElement: PluginFloatElement
1070	});
1071
1072	// jquery plugin
1073	$.fn.themePluginFloatElement = function(opts) {
1074		return this.map(function() {
1075			var $this = $(this);
1076
1077			if ($this.data(instanceName)) {
1078				return $this.data(instanceName);
1079			} else {
1080				return new PluginFloatElement($this, opts);
1081			}
1082
1083		});
1084	}
1085
1086}).apply(this, [window.theme, jQuery]);
1087
1088// Icon
1089(function(theme, $) {
1090
1091	'use strict';
1092
1093	theme = theme || {};
1094
1095	var instanceName = '__icon';
1096
1097	var PluginIcon = function($el, opts) {
1098		return this.initialize($el, opts);
1099	};
1100
1101	PluginIcon.defaults = {
1102		color: '#2388ED',
1103		animated: false,
1104		delay: 300
1105	};
1106
1107	PluginIcon.prototype = {
1108		initialize: function($el, opts) {
1109			if ($el.data(instanceName)) {
1110				return this;
1111			}
1112
1113			this.$el = $el;
1114
1115			this
1116				.setData()
1117				.setOptions(opts)
1118				.build();
1119
1120			return this;
1121		},
1122
1123		setData: function() {
1124			this.$el.data(instanceName, this);
1125
1126			return this;
1127		},
1128
1129		setOptions: function(opts) {
1130			this.options = $.extend(true, {}, PluginIcon.defaults, opts, {
1131				wrapper: this.$el
1132			});
1133
1134			return this;
1135		},
1136
1137		build: function() {
1138			var self  	 = this,
1139				$el   	 = this.options.wrapper,
1140				color 	 = self.options.color,
1141				elTopDistance = $el.offset().top,
1142				windowTopDistance = $(window).scrollTop(),
1143				duration = ( self.options.animated && !self.options.strokeBased ) ? 200 : 100;
1144
1145			// Check origin
1146			if( window.location.origin === 'file://' ) {
1147				$el.css('opacity', 1);
1148				return;
1149			}
1150
1151			// Duration
1152			if( self.options.duration ) {
1153				duration = self.options.duration;
1154			}
1155
1156			// Icon Wrapper
1157			var iconWrapper = $('<object class="animated-icon" type="image/svg+xml" data="'+ $el.attr('src') +'"></object>');
1158
1159			if( $el.attr('style') ) {
1160				iconWrapper.attr('style', $el.attr('style'));
1161			}
1162
1163			if( $el.attr('width') ) {
1164				iconWrapper.attr('width', $el.attr('width'));
1165			}
1166
1167			iconWrapper.css('height', $el.height());
1168
1169			$el.replaceWith(iconWrapper);
1170
1171			$el = iconWrapper;
1172
1173			var icon = new Vivus($($el)[0], {start: 'manual', type: 'sync', selfDestroy: true, duration: duration, onReady: function(obj){
1174				var styleElement = document.createElementNS("http://www.w3.org/2000/svg", "style"),
1175					animateStyle = '';
1176
1177				// SVG Fill Based
1178				if( self.options.animated && !self.options.strokeBased || !self.options.animated && color && !self.options.strokeBased ) {
1179					animateStyle = 'stroke-width: 0.1px; fill-opacity: 0; transition: ease fill-opacity 300ms;';
1180					
1181					// Set Style on SVG inside object
1182					styleElement.textContent = 'path, line, rect, circle, line, polyline { fill: '+ color +'; stroke: '+ color +'; '+ animateStyle + (self.options.svgStyle ? self.options.svgStyle : "") + ' } .finished path { fill-opacity: 1; }';
1183					obj.el.appendChild(styleElement);
1184				}
1185
1186				// SVG Stroke Based
1187				if( self.options.animated && self.options.strokeBased || !self.options.animated && color && self.options.strokeBased ) {
1188
1189					// Set Style on SVG inside object
1190					styleElement.textContent = 'path, line, rect, circle, line, polyline { stroke: '+ color +'; ' + (self.options.svgStyle ? self.options.svgStyle : "") + '}';
1191					obj.el.appendChild(styleElement);
1192				}
1193
1194				// devcode: !production
1195				$(window).on('styleSwitcher.modifyVars', function(e){
1196					if( self.options.color.toUpperCase() != '#FFF' ) {
1197						if( e.options.colorPrimary.toUpperCase() != self.options.color.toUpperCase() ) {
1198							
1199							var	styleElement = document.createElementNS("http://www.w3.org/2000/svg", "style"),
1200								svg          = obj.el;
1201
1202							if( self.options.strokeBased ) {
1203								styleElement.textContent = 'path, line, rect, circle, line, polyline { stroke: '+ e.options.colorPrimary +'; }';
1204							} else {
1205								styleElement.textContent = 'path, line, rect, circle, line, polyline { fill: '+ e.options.colorPrimary +'; stroke: '+ e.options.colorPrimary +'; }';
1206							}
1207							svg.appendChild(styleElement);
1208						
1209						}
1210					}
1211				});
1212				// endcode
1213
1214				$.event.trigger('theme.plugin.icon.svg.ready');
1215			}});
1216
1217			// Isn't animated
1218			if( !self.options.animated ) {
1219				setTimeout(function(){
1220					icon.finish();
1221				}, 10);
1222				$el.css({ opacity: 1 });
1223			}
1224
1225			// Animated
1226			if( self.options.animated && $(window).width() > 767 ) {
1227				
1228				// First Load
1229				if( $el.visible( true ) ) {
1230					self.startIconAnimation( icon, $el );
1231				} else if( elTopDistance < windowTopDistance ) {
1232					self.startIconAnimation( icon, $el );
1233				}
1234
1235				// On Scroll
1236				$(window).on('scroll', function(){
1237					if( $el.visible( true ) ) {
1238						self.startIconAnimation( icon, $el );
1239					}
1240				});
1241
1242			} else {
1243				
1244				$el.css({ opacity: 1 });
1245
1246				$(window).on('theme.plugin.icon.svg.ready', function(){
1247					setTimeout(function(){
1248						icon.el.setAttribute('class', 'finished');
1249					}, 300);
1250				});
1251				
1252			}
1253
1254			return this;
1255		},
1256		startIconAnimation: function(icon, $el) {
1257			var self = this;
1258
1259			// Animate for better performance
1260			$({to:0}).animate({to:1}, ((self.options.strokeBased) ? self.options.delay : self.options.delay + 300 ), function() {
1261				$el.css({ opacity: 1 });
1262			});
1263
1264			$({to:0}).animate({to:1}, self.options.delay, function() {
1265				icon.play(1);
1266
1267				setTimeout(function(){
1268					icon.el.setAttribute('class', 'finished');
1269				}, icon.duration * 5 );
1270			});
1271		}
1272	};
1273
1274	// expose to scope
1275	$.extend(theme, {
1276		PluginIcon: PluginIcon
1277	});
1278
1279	// jquery plugin
1280	$.fn.themePluginIcon = function(opts) {
1281		return this.map(function() {
1282			var $this = $(this);
1283
1284			if ($this.data(instanceName)) {
1285				return $this.data(instanceName);
1286			} else {
1287				return new PluginIcon($this, opts);
1288			}
1289
1290		});
1291	};
1292
1293}).apply(this, [window.theme, jQuery]);
1294
1295// Image Background
1296(function(theme, $) {
1297
1298	'use strict';
1299
1300	theme = theme || {};
1301
1302	var instanceName = '__imageBackground';
1303
1304	var PluginImageBackground = function($el, opts) {
1305		return this.initialize($el, opts);
1306	};
1307
1308	PluginImageBackground.defaults = {
1309		bgSize: 'cover',
1310		bgPosition: 'center'
1311	};
1312
1313	PluginImageBackground.prototype = {
1314		initialize: function($el, opts) {
1315			if ($el.data(instanceName)) {
1316				return this;
1317			}
1318
1319			this.$el = $el;
1320
1321			this
1322				.setData()
1323				.setOptions(opts)
1324				.build();
1325
1326			return this;
1327		},
1328
1329		setData: function() {
1330			this.$el.data(instanceName, this);
1331
1332			return this;
1333		},
1334
1335		setOptions: function(opts) {
1336			this.options = $.extend(true, {}, PluginImageBackground.defaults, opts, {
1337				wrapper: this.$el
1338			});
1339
1340			return this;
1341		},
1342
1343		build: function() {
1344			var self = this,
1345				$el = self.options.wrapper,
1346				important;
1347
1348			if( !self.options.imageUrl ) {
1349				return;
1350			}
1351
1352			$el.css({
1353				'background-image': 'url(' + self.options.imageUrl + ')',
1354				'background-size' : self.options.bgSize,
1355				'background-position': self.options.bgPosition,
1356				'background-repeat': 'no-repeat'
1357			});
1358
1359			return this;
1360		}
1361	};
1362
1363	// expose to scope
1364	$.extend(theme, {
1365		PluginImageBackground: PluginImageBackground
1366	});
1367
1368	// jquery plugin
1369	$.fn.themePluginImageBackground = function(opts) {
1370		return this.map(function() {
1371			var $this = $(this);
1372
1373			if ($this.data(instanceName)) {
1374				return $this.data(instanceName);
1375			} else {
1376				return new PluginImageBackground($this, opts);
1377			}
1378
1379		});
1380	}
1381
1382}).apply(this, [window.theme, jQuery]);
1383
1384// Lazy Load
1385(function(theme, $) {
1386
1387	'use strict';
1388
1389	theme = theme || {};
1390
1391	var instanceName = '__lazyload';
1392
1393	var PluginLazyLoad = function($el, opts) {
1394		return this.initialize($el, opts);
1395	};
1396
1397	PluginLazyLoad.defaults = {
1398		effect: 'show',
1399		appearEffect: '',
1400		appear: function(elements_left, settings) {
1401			
1402		},
1403		load: function(elements_left, settings) {
1404			$(this).addClass($.trim('lazy-load-loaded ' + settings.appearEffect));
1405		}
1406	};
1407
1408	PluginLazyLoad.prototype = {
1409		initialize: function($el, opts) {
1410			if ($el.data(instanceName)) {
1411				return this;
1412			}
1413
1414			this.$el = $el;
1415
1416			this
1417				.setData()
1418				.setOptions(opts)
1419				.build();
1420
1421			return this;
1422		},
1423
1424		setData: function() {
1425			this.$el.data(instanceName, this);
1426
1427			return this;
1428		},
1429
1430		setOptions: function(opts) {
1431			this.options = $.extend(true, {}, PluginLazyLoad.defaults, opts, {
1432				wrapper: this.$el
1433			});
1434
1435			return this;
1436		},
1437
1438		build: function() {
1439			if (!($.isFunction($.fn.lazyload))) {
1440				return this;
1441			}
1442
1443			var self = this;
1444
1445			self.options.wrapper.lazyload(this.options);
1446
1447			return this;
1448		}
1449	};
1450
1451	// expose to scope
1452	$.extend(theme, {
1453		PluginLazyLoad: PluginLazyLoad
1454	});
1455
1456	// jquery plugin
1457	$.fn.themePluginLazyLoad = function(opts) {
1458		return this.map(function() {
1459			var $this = $(this);
1460
1461			if ($this.data(instanceName)) {
1462				return $this.data(instanceName);
1463			} else {
1464				return new PluginLazyLoad($this, opts);
1465			}
1466
1467		});
1468	}
1469
1470}).apply(this, [window.theme, jQuery]);
1471
1472// Lightbox
1473(function(theme, $) {
1474
1475	'use strict';
1476
1477	theme = theme || {};
1478
1479	var instanceName = '__lightbox';
1480
1481	var PluginLightbox = function($el, opts) {
1482		return this.initialize($el, opts);
1483	};
1484
1485	PluginLightbox.defaults = {
1486		tClose: 'Close (Esc)', // Alt text on close button
1487		tLoading: 'Loading...', // Text that is displayed during loading. Can contain %curr% and %total% keys
1488		gallery: {
1489			tPrev: 'Previous (Left arrow key)', // Alt text on left arrow
1490			tNext: 'Next (Right arrow key)', // Alt text on right arrow
1491			tCounter: '%curr% of %total%' // Markup for "1 of 7" counter
1492		},
1493		image: {
1494			tError: '<a href="%url%">The image</a> could not be loaded.' // Error message when image could not be loaded
1495		},
1496		ajax: {
1497			tError: '<a href="%url%">The content</a> could not be loaded.' // Error message when ajax request failed
1498		},
1499		callbacks: {
1500			open: function() {
1501				$('html').addClass('lightbox-open');
1502			},
1503			close: function() {
1504				$('html').removeClass('lightbox-open');
1505			}
1506		}
1507	};
1508
1509	PluginLightbox.prototype = {
1510		initialize: function($el, opts) {
1511			if ($el.data(instanceName)) {
1512				return this;
1513			}
1514
1515			this.$el = $el;
1516
1517			this
1518				.setData()
1519				.setOptions(opts)
1520				.build();
1521
1522			return this;
1523		},
1524
1525		setData: function() {
1526			this.$el.data(instanceName, this);
1527
1528			return this;
1529		},
1530
1531		setOptions: function(opts) {
1532			this.options = $.extend(true, {}, PluginLightbox.defaults, opts, {
1533				wrapper: this.$el
1534			});
1535
1536			return this;
1537		},
1538
1539		build: function() {
1540			if (!($.isFunction($.fn.magnificPopup))) {
1541				return this;
1542			}
1543
1544			this.options.wrapper.magnificPopup(this.options);
1545
1546			return this;
1547		}
1548	};
1549
1550	// expose to scope
1551	$.extend(theme, {
1552		PluginLightbox: PluginLightbox
1553	});
1554
1555	// jquery plugin
1556	$.fn.themePluginLightbox = function(opts) {
1557		return this.map(function() {
1558			var $this = $(this);
1559
1560			if ($this.data(instanceName)) {
1561				return $this.data(instanceName);
1562			} else {
1563				return new PluginLightbox($this, opts);
1564			}
1565
1566		});
1567	}
1568
1569}).apply(this, [window.theme, jQuery]);
1570
1571// Loading Overlay
1572(function(theme, $) {
1573
1574	'use strict';
1575
1576	theme = theme || {};
1577
1578	var loadingOverlayTemplate = [
1579		'<div class="loading-overlay">',
1580			'<div class="bounce-loader"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>',
1581		'</div>'
1582	].join('');
1583
1584	var LoadingOverlay = function( $wrapper, options ) {
1585		return this.initialize( $wrapper, options );
1586	};
1587
1588	LoadingOverlay.prototype = {
1589
1590		options: {
1591			css: {}
1592		},
1593
1594		initialize: function( $wrapper, options ) {
1595			this.$wrapper = $wrapper;
1596
1597			this
1598				.setVars()
1599				.setOptions( options )
1600				.build()
1601				.events();
1602
1603			this.$wrapper.data( 'loadingOverlay', this );
1604		},
1605
1606		setVars: function() {
1607			this.$overlay = this.$wrapper.find('.loading-overlay');
1608
1609			return this;
1610		},
1611
1612		setOptions: function( options ) {
1613			if ( !this.$overlay.get(0) ) {
1614				this.matchProperties();
1615			}
1616			this.options     = $.extend( true, {}, this.options, options );
1617			this.loaderClass = this.getLoaderClass( this.options.css.backgroundColor );
1618
1619			return this;
1620		},
1621
1622		build: function() {
1623			if ( !this.$overlay.closest(document.documentElement).get(0) ) {
1624				if ( !this.$cachedOverlay ) {
1625					this.$overlay = $( loadingOverlayTemplate ).clone();
1626
1627					if ( this.options.css ) {
1628						this.$overlay.css( this.options.css );
1629						this.$overlay.find( '.loader' ).addClass( this.loaderClass );
1630					}
1631				} else {
1632					this.$overlay = this.$cachedOverlay.clone();
1633				}
1634
1635				this.$wrapper.append( this.$overlay );
1636			}
1637
1638			if ( !this.$cachedOverlay ) {
1639				this.$cachedOverlay = this.$overlay.clone();
1640			}
1641
1642			return this;
1643		},
1644
1645		events: function() {
1646			var _self = this;
1647
1648			if ( this.options.startShowing ) {
1649				_self.show();
1650			}
1651
1652			if ( this.$wrapper.is('body') || this.options.hideOnWindowLoad ) {
1653				$( window ).on( 'load error', function() {
1654					_self.hide();
1655				});
1656			}
1657
1658			if ( this.options.listenOn ) {
1659				$( this.options.listenOn )
1660					.on( 'loading-overlay:show beforeSend.ic', function( e ) {
1661						e.stopPropagation();
1662						_self.show();
1663					})
1664					.on( 'loading-overlay:hide complete.ic', function( e ) {
1665						e.stopPropagation();
1666						_self.hide();
1667					});
1668			}
1669
1670			this.$wrapper
1671				.on( 'loading-overlay:show beforeSend.ic', function( e ) {
1672					if ( e.target === _self.$wrapper.get(0) ) {
1673						e.stopPropagation();
1674						_self.show();
1675						return true;
1676					}
1677					return false;
1678				})
1679				.on( 'loading-overlay:hide complete.ic', function( e ) {
1680					if ( e.target === _self.$wrapper.get(0) ) {
1681						e.stopPropagation();
1682						_self.hide();
1683						return true;
1684					}
1685					return false;
1686				});
1687
1688			return this;
1689		},
1690
1691		show: function() {
1692			this.build();
1693
1694			this.position = this.$wrapper.css( 'position' ).toLowerCase();
1695			if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) {
1696				this.$wrapper.css({
1697					position: 'relative'
1698				});
1699			}
1700			this.$wrapper.addClass( 'loading-overlay-showing' );
1701		},
1702
1703		hide: function() {
1704			var _self = this;
1705
1706			this.$wrapper.removeClass( 'loading-overlay-showing' );
1707			setTimeout(function() {
1708				if ( this.position != 'relative' || this.position != 'absolute' || this.position != 'fixed' ) {
1709					_self.$wrapper.css({ position: '' });
1710				}
1711			}, 500);
1712		},
1713
1714		matchProperties: function() {
1715			var i,
1716				l,
1717				properties;
1718
1719			properties = [
1720				'backgroundColor',
1721				'borderRadius'
1722			];
1723
1724			l = properties.length;
1725
1726			for( i = 0; i < l; i++ ) {
1727				var obj = {};
1728				obj[ properties[ i ] ] = this.$wrapper.css( properties[ i ] );
1729
1730				$.extend( this.options.css, obj );
1731			}
1732		},
1733
1734		getLoaderClass: function( backgroundColor ) {
1735			if ( !backgroundColor || backgroundColor === 'transparent' || backgroundColor === 'inherit' ) {
1736				return 'black';
1737			}
1738
1739			var hexColor,
1740				r,
1741				g,
1742				b,
1743				yiq;
1744
1745			var colorToHex = function( color ){
1746				var hex,
1747					rgb;
1748
1749				if( color.indexOf('#') >- 1 ){
1750					hex = color.replace('#', '');
1751				} else {
1752					rgb = color.match(/\d+/g);
1753					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);
1754				}
1755
1756				if ( hex.length === 3 ) {
1757					hex = hex + hex;
1758				}
1759
1760				return hex;
1761			};
1762
1763			hexColor = colorToHex( backgroundColor );
1764
1765			r = parseInt( hexColor.substr( 0, 2), 16 );
1766			g = parseInt( hexColor.substr( 2, 2), 16 );
1767			b = parseInt( hexColor.substr( 4, 2), 16 );
1768			yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
1769
1770			return ( yiq >= 128 ) ? 'black' : 'white';
1771		}
1772
1773	};
1774
1775	// expose to scope
1776	$.extend(theme, {
1777		LoadingOverlay: LoadingOverlay
1778	});
1779
1780	// expose as a jquery plugin
1781	$.fn.loadingOverlay = function( opts ) {
1782		return this.each(function() {
1783			var $this = $( this );
1784
1785			var loadingOverlay = $this.data( 'loadingOverlay' );
1786			if ( loadingOverlay ) {
1787				return loadingOverlay;
1788			} else {
1789				var options = opts || $this.data( 'loading-overlay-options' ) || {};
1790				return new LoadingOverlay( $this, options );
1791			}
1792		});
1793	}
1794
1795	// auto init
1796	$('[data-loading-overlay]').loadingOverlay();
1797
1798}).apply(this, [window.theme, jQuery]);
1799
1800// Masonry
1801(function(theme, $) {
1802
1803	'use strict';
1804
1805	theme = theme || {};
1806
1807	var instanceName = '__masonry';
1808
1809	var PluginMasonry = function($el, opts) {
1810		return this.initialize($el, opts);
1811	};
1812
1813	PluginMasonry.defaults = {
1814		itemSelector: '.isotope-item'
1815	};
1816
1817	PluginMasonry.prototype = {
1818		initialize: function($el, opts) {
1819			if ($el.data(instanceName)) {
1820				return this;
1821			}
1822
1823			this.$el = $el;
1824
1825			this
1826				.setData()
1827				.setOptions(opts)
1828				.build();
1829
1830			return this;
1831		},
1832
1833		setData: function() {
1834			this.$el.data(instanceName, this);
1835
1836			return this;
1837		},
1838
1839		setOptions: function(opts) {
1840			this.options = $.extend(true, {}, PluginMasonry.defaults, opts, {
1841				wrapper: this.$el
1842			});
1843
1844			return this;
1845		},
1846
1847		build: function() {
1848			if (!($.isFunction($.fn.isotope))) {
1849				return this;
1850			}
1851
1852			var self = this,
1853				$window = $(window);
1854
1855			self.$loader = false;
1856
1857			if (self.options.wrapper.closest('.masonry-loader').get(0)) {
1858				self.$loader = self.options.wrapper.closest('.masonry-loader');
1859				self.createLoader();
1860			}
1861
1862			self.options.wrapper.one('layoutComplete', function(event, laidOutItems) {
1863				self.removeLoader();
1864			});
1865
1866			self.options.wrapper.waitForImages(function() {
1867				self.options.wrapper.isotope(self.options);
1868			});
1869
1870			setTimeout(function() {
1871				self.removeLoader();
1872			}, 3000);
1873
1874			$window.afterResize(function(){
1875				self.options.wrapper.isotope('layout');
1876			});
1877
1878			return this;
1879		},
1880
1881		createLoader: function() {
1882			var self = this;
1883
1884			var loaderTemplate = [
1885				'<div class="bounce-loader">',
1886					'<div class="bounce1"></div>',
1887					'<div class="bounce2"></div>',
1888					'<div class="bounce3"></div>',
1889				'</div>'
1890			].join('');
1891
1892			self.$loader.append(loaderTemplate);
1893
1894			return this;
1895		},
1896
1897		removeLoader: function() {
1898
1899			var self = this;
1900
1901			if (self.$loader) {
1902
1903				self.$loader.removeClass('masonry-loader-showing');
1904
1905				setTimeout(function() {
1906					self.$loader.addClass('masonry-loader-loaded');
1907				}, 300);
1908
1909			}
1910
1911		}
1912	};
1913
1914	// expose to scope
1915	$.extend(theme, {
1916		PluginMasonry: PluginMasonry
1917	});
1918
1919	// jquery plugin
1920	$.fn.themePluginMasonry = function(opts) {
1921		return this.map(function() {
1922			var $this = $(this);
1923
1924			if ($this.data(instanceName)) {
1925				return $this.data(instanceName);
1926			} else {
1927				return new PluginMasonry($this, opts);
1928			}
1929
1930		});
1931	}
1932
1933}).apply(this, [window.theme, jQuery]);
1934
1935// Match Height
1936(function(theme, $) {
1937
1938	'use strict';
1939
1940	theme = theme || {};
1941
1942	var instanceName = '__matchHeight';
1943
1944	var PluginMatchHeight = function($el, opts) {
1945		return this.initialize($el, opts);
1946	};
1947
1948	PluginMatchHeight.defaults = {
1949		byRow: true,
1950		property: 'height',
1951		target: null,
1952		remove: false
1953	};
1954
1955	PluginMatchHeight.prototype = {
1956		initialize: function($el, opts) {
1957			if ($el.data(instanceName)) {
1958				return this;
1959			}
1960
1961			this.$el = $el;
1962
1963			this
1964				.setData()
1965				.setOptions(opts)
1966				.build();
1967
1968			return this;
1969		},
1970
1971		setData: function() {
1972			this.$el.data(instanceName, this);
1973
1974			return this;
1975		},
1976
1977		setOptions: function(opts) {
1978			this.options = $.extend(true, {}, PluginMatchHeight.defaults, opts, {
1979				wrapper: this.$el
1980			});
1981
1982			return this;
1983		},
1984
1985		build: function() {
1986			if (!($.isFunction($.fn.matchHeight))) {
1987				return this;
1988			}
1989
1990			var self = this;
1991
1992			self.options.wrapper.matchHeight(self.options);
1993
1994			return this;
1995		}
1996
1997	};
1998
1999	// expose to scope
2000	$.extend(theme, {
2001		PluginMatchHeight: PluginMatchHeight
2002	});
2003
2004	// jquery plugin
2005	$.fn.themePluginMatchHeight = function(opts) {
2006		return this.map(function() {
2007			var $this = $(this);
2008
2009			if ($this.data(instanceName)) {
2010				return $this.data(instanceName);
2011			} else {
2012				return new PluginMatchHeight($this, opts);
2013			}
2014
2015		});
2016	}
2017
2018}).apply(this, [window.theme, jQuery]);
2019
2020// Parallax
2021(function(theme, $) {
2022
2023	'use strict';
2024
2025	theme = theme || {};
2026
2027	var instanceName = '__parallax';
2028
2029	var PluginParallax = function($el, opts) {
2030		return this.initialize($el, opts);
2031	};
2032
2033	PluginParallax.defaults = {
2034		speed: 1.5,
2035		horizontalPosition: '50%',
2036		offset: 0,
2037		responsiveOffset: false,
2038		parallaxHeight: '180%'
2039	};
2040
2041	PluginParallax.prototype = {
2042		initialize: function($el, opts) {
2043			if ($el.data(instanceName)) {
2044				return this;
2045			}
2046
2047			this.$el = $el;
2048
2049			this
2050				.setData()
2051				.setOptions(opts)
2052				.build();
2053
2054			return this;
2055		},
2056
2057		setData: function() {
2058			this.$el.data(instanceName, this);
2059
2060			return this;
2061		},
2062
2063		setOptions: function(opts) {
2064			this.options = $.extend(true, {}, PluginParallax.defaults, opts, {
2065				wrapper: this.$el
2066			});
2067
2068			return this;
2069		},
2070
2071		build: function() {
2072			var self = this,
2073				$window = $(window),
2074				offset,
2075				optOffset,
2076				yPos,
2077				plxPos,
2078				bgpos,
2079				background;
2080
2081			// Create Parallax Element
2082			background = $('<div class="parallax-background"></div>');
2083
2084			// Set Style for Parallax Element
2085			background.css({
2086				'background-image' : 'url(' + self.options.wrapper.data('image-src') + ')',
2087				'background-size' : 'cover',
2088				'background-position' : 'center',
2089				'position' : 'absolute',
2090				'top' : 0,
2091				'left' : 0,
2092				'width' : '100%',
2093				'height' : (!$.browser.mobile) ? self.options.parallaxHeight : '100%'
2094			});
2095
2096			// Add Parallax Element on DOM
2097			self.options.wrapper.prepend(background);
2098
2099			// Set Overlfow Hidden / Position Relative / Min height to Parallax Wrapper
2100			self.options.wrapper.css({
2101				'position' : 'relative',
2102				'overflow' : 'hidden',
2103				'min-height': (self.options.minHeight) ? self.options.minHeight : ''
2104			});
2105
2106			// Parallax Effect on Scroll & Resize
2107			var parallaxEffectOnScrolResize = function() {
2108				// Offset
2109				optOffset = self.options.offset;
2110
2111				$window.on('scroll resize', function() {
2112					
2113					// Responsive Offset
2114					if( self.options.responsiveOffset ) {
2115						var window_w = $window.width(),
2116							responsiveOffset = self.options.responsiveOffset;
2117
2118						if( responsiveOffset.constructor === Array ) {
2119							if( window_w > 1199 ) {
2120								optOffset = responsiveOffset[2];
2121							} else if( window_w > 991 ) {
2122								optOffset = responsiveOffset[1];
2123							} else if( window_w > 767 ) {
2124								optOffset = responsiveOffset[0];
2125							}
2126						}
2127					}
2128
2129					offset  = self.options.wrapper.offset();
2130					yPos    = -($window.scrollTop() - (offset.top - 100)) / ((self.options.speed + 2 ));
2131					plxPos  = (yPos < 0) ? Math.abs(yPos) : -Math.abs(yPos);
2132					background.css({
2133						'transform' : 'translate3d(0, '+ ( (plxPos - 50) + (optOffset) ) +'px, 0)',
2134						'background-position-x' : self.options.horizontalPosition
2135					});
2136					
2137				});
2138
2139				$window.trigger('scroll');
2140			}
2141
2142			if (!$.browser.mobile) {
2143				parallaxEffectOnScrolResize();
2144			} else {
2145				if( self.options.enableOnMobile == true ) {
2146					parallaxEffectOnScrolResize();
2147				} else {
2148					self.options.wrapper.addClass('parallax-disabled');
2149				}
2150			}
2151
2152			return this;
2153		}
2154	};
2155
2156	// expose to scope
2157	$.extend(theme, {
2158		PluginParallax: PluginParallax
2159	});
2160
2161	// jquery plugin
2162	$.fn.themePluginParallax = function(opts) {
2163		return this.map(function() {
2164			var $this = $(this);
2165
2166			if ($this.data(instanceName)) {
2167				return $this.data(instanceName);
2168			} else {
2169				return new PluginParallax($this, opts);
2170			}
2171
2172		});
2173	}
2174
2175}).apply(this, [window.theme, jQuery]);
2176
2177// Progress Bar
2178(function(theme, $) {
2179
2180	'use strict';
2181
2182	theme = theme || {};
2183
2184	var instanceName = '__progressBar';
2185
2186	var PluginProgressBar = function($el, opts) {
2187		return this.initialize($el, opts);
2188	};
2189
2190	PluginProgressBar.defaults = {
2191		accX: 0,
2192		accY: -50,
2193		delay: 1
2194	};
2195
2196	PluginProgressBar.prototype = {
2197		initialize: function($el, opts) {
2198			if ($el.data(instanceName)) {
2199				return this;
2200			}
2201
2202			this.$el = $el;
2203
2204			this
2205				.setData()
2206				.setOptions(opts)
2207				.build();
2208
2209			return this;
2210		},
2211
2212		setData: function() {
2213			this.$el.data(instanceName, this);
2214
2215			return this;
2216		},
2217
2218		setOptions: function(opts) {
2219			this.options = $.extend(true, {}, PluginProgressBar.defaults, opts, {
2220				wrapper: this.$el
2221			});
2222
2223			return this;
2224		},
2225
2226		build: function() {
2227			if (!($.isFunction($.fn.appear))) {
2228				return this;
2229			}
2230
2231			var self = this,
2232				$el = this.options.wrapper,
2233				delay = 1;
2234
2235			$el.appear(function() {
2236
2237				delay = ($el.attr('data-appear-animation-delay') ? $el.attr('data-appear-animation-delay') : self.options.delay);
2238
2239				$el.addClass($el.attr('data-appear-animation'));
2240
2241				setTimeout(function() {
2242
2243					$el.animate({
2244						width: $el.attr('data-appear-progress-animation')
2245					}, 1500, 'easeOutQuad', function() {
2246						$el.find('.progress-bar-tooltip').animate({
2247							opacity: 1
2248						}, 500, 'easeOutQuad');
2249					});
2250
2251				}, delay);
2252
2253			}, {
2254				accX: self.options.accX,
2255				accY: self.options.accY
2256			});
2257
2258			return this;
2259		}
2260	};
2261
2262	// expose to scope
2263	$.extend(theme, {
2264		PluginProgressBar: PluginProgressBar
2265	});
2266
2267	// jquery plugin
2268	$.fn.themePluginProgressBar = function(opts) {
2269		return this.map(function() {
2270			var $this = $(this);
2271
2272			if ($this.data(instanceName)) {
2273				return $this.data(instanceName);
2274			} else {
2275				return new PluginProgressBar($this, opts);
2276			}
2277
2278		});
2279	}
2280
2281}).apply(this, [window.theme, jQuery]);
2282
2283// Rmove Min Height Adter Load
2284(function(theme, $) {
2285
2286	'use strict';
2287
2288	theme = theme || {};
2289
2290	var instanceName = '__removeMinHeight';
2291
2292	var PluginRemoveMinHeight = function($el, opts) {
2293		return this.initialize($el, opts);
2294	};
2295
2296	PluginRemoveMinHeight.prototype = {
2297		initialize: function($el, opts) {
2298			if ($el.data(instanceName)) {
2299				return this;
2300			}
2301
2302			this.$el = $el;
2303
2304			this
2305				.setData()
2306				.build();
2307
2308			return this;
2309		},
2310
2311		setData: function() {
2312			this.$el.data(instanceName, this);
2313
2314			return this;
2315		},
2316
2317		build: function() {
2318			var self = this;
2319
2320			$(window).on('load', function(){
2321				self.$el.css('min-height', 0);
2322			});
2323
2324			return this;
2325		}
2326	};
2327
2328	// expose to scope
2329	$.extend(theme, {
2330		PluginRemoveMinHeight: PluginRemoveMinHeight
2331	});
2332
2333	// jquery plugin
2334	$.fn.themePluginRemoveMinHeight = function(opts) {
2335		return this.map(function() {
2336			var $this = $(this);
2337
2338			if ($this.data(instanceName)) {
2339				return $this.data(instanceName);
2340			} else {
2341				return new PluginRemoveMinHeight($this, opts);
2342			}
2343
2344		});
2345	}
2346
2347}).apply(this, [window.theme, jQuery]);
2348
2349// Revolution Slider
2350(function(theme, $) {
2351
2352	'use strict';
2353
2354	theme = theme || {};
2355
2356	var instanceName = '__revolution';
2357
2358	var PluginRevolutionSlider = function($el, opts) {
2359		return this.initialize($el, opts);
2360	};
2361
2362	PluginRevolutionSlider.defaults = {
2363		sliderType: 'standard',
2364		sliderLayout: 'fullwidth',
2365		delay: 9000,
2366		gridwidth: 1170,
2367		gridheight: 500,
2368		spinner: 'spinner3',
2369		disableProgressBar: 'on',
2370		parallax: {
2371			type: 'off',
2372			bgparallax: 'off'
2373		},
2374		navigation: {
2375			keyboardNavigation: 'off',
2376			keyboard_direction: 'horizontal',
2377			mouseScrollNavigation: 'off',
2378			onHoverStop: 'off',
2379			touch: {
2380				touchenabled: 'on',
2381				swipe_threshold: 75,
2382				swipe_min_touches: 1,
2383				swipe_direction: 'horizontal',
2384				drag_block_vertical: false
2385			},
2386			arrows: {
2387				enable: true,
2388				hide_onmobile: false,
2389				hide_under: 0,
2390				hide_onleave: true,
2391				hide_delay: 200,
2392				hide_delay_mobile: 1200,
2393				left: {
2394					h_align: 'left',
2395					v_align: 'center',
2396					h_offset: 30,
2397					v_offset: 0
2398				},
2399				right: {
2400					h_align: 'right',
2401					v_align: 'center',
2402					h_offset: 30,
2403					v_offset: 0
2404				}
2405			}
2406		}
2407	};
2408
2409	PluginRevolutionSlider.prototype = {
2410		initialize: function($el, opts) {
2411			if ($el.data(instanceName)) {
2412				return this;
2413			}
2414
2415			this.$el = $el;
2416
2417			this
2418				.setData()
2419				.setOptions(opts)
2420				.build()
2421				.events();
2422
2423			return this;
2424		},
2425
2426		setData: function() {
2427			this.$el.data(instanceName, this);
2428
2429			return this;
2430		},
2431
2432		setOptions: function(opts) {
2433			this.options = $.extend(true, {}, PluginRevolutionSlider.defaults, opts, {
2434				wrapper: this.$el
2435			});
2436
2437			return this;
2438		},
2439
2440		build: function() {
2441			if (!($.isFunction($.fn.revolution))) {
2442				return this;
2443			}
2444
2445			// Single Slider Class
2446			if(this.options.wrapper.find('> ul > li').length == 1) {
2447				this.options.wrapper.addClass('slider-single-slide');
2448			}
2449
2450			this.options.wrapper.revolution(this.options);
2451
2452			return this;
2453		},
2454
2455		events: function() {
2456
2457			return this;
2458		}
2459	};
2460
2461	// expose to scope
2462	$.extend(theme, {
2463		PluginRevolutionSlider: PluginRevolutionSlider
2464	});
2465
2466	// jquery plugin
2467	$.fn.themePluginRevolutionSlider = function(opts) {
2468		return this.map(function() {
2469			var $this = $(this);
2470
2471			if ($this.data(instanceName)) {
2472				return $this.data(instanceName);
2473			} else {
2474				return new PluginRevolutionSlider($this, opts);
2475			}
2476
2477		});
2478	}
2479
2480}).apply(this, [window.theme, jQuery]);
2481
2482// Scroll to Top
2483(function(theme, $) {
2484
2485	'use strict';
2486
2487	theme = theme || {};
2488
2489	var initialized = false;
2490
2491	$.extend(theme, {
2492
2493		PluginScrollToTop: {
2494
2495			defaults: {
2496				wrapper: $('body'),
2497				offset: 150,
2498				buttonClass: 'scroll-to-top',
2499				iconClass: 'fas fa-chevron-up',
2500				delay: 1000,
2501				visibleMobile: false,
2502				label: false,
2503				easing: 'easeOutBack'
2504			},
2505
2506			initialize: function(opts) {
2507				initialized = true;
2508
2509				this
2510					.setOptions(opts)
2511					.build()
2512					.events();
2513
2514				return this;
2515			},
2516
2517			setOptions: function(opts) {
2518				this.options = $.extend(true, {}, this.defaults, opts);
2519
2520				return this;
2521			},
2522
2523			build: function() {
2524				var self = this,
2525					$el;
2526
2527				// Base HTML Markup
2528				$el = $('<a />')
2529					.addClass(self.options.buttonClass)
2530					.attr({
2531						'href': '#',
2532					})
2533					.append(
2534						$('<i />')
2535						.addClass(self.options.iconClass)
2536				);
2537
2538				// Visible Mobile
2539				if (!self.options.visibleMobile) {
2540					$el.addClass('hidden-mobile');
2541				}
2542
2543				// Label
2544				if (self.options.label) {
2545					$el.append(
2546						$('<span />').html(self.options.label)
2547					);
2548				}
2549
2550				this.options.wrapper.append($el);
2551
2552				this.$el = $el;
2553
2554				return this;
2555			},
2556
2557			events: function() {
2558				var self = this,
2559					_isScrolling = false;
2560
2561				// Click Element Action
2562				self.$el.on('click', function(e) {
2563					e.preventDefault();
2564					$('body, html').animate({
2565						scrollTop: 0
2566					}, self.options.delay, self.options.easing);
2567					return false;
2568				});
2569
2570				// Show/Hide Button on Window Scroll event.
2571				$(window).scroll(function() {
2572
2573					if (!_isScrolling) {
2574
2575						_isScrolling = true;
2576
2577						if ($(window).scrollTop() > self.options.offset) {
2578
2579							self.$el.stop(true, true).addClass('visible');
2580							_isScrolling = false;
2581
2582						} else {
2583
2584							self.$el.stop(true, true).removeClass('visible');
2585							_isScrolling = false;
2586
2587						}
2588
2589					}
2590
2591				});
2592
2593				return this;
2594			}
2595
2596		}
2597
2598	});
2599
2600}).apply(this, [window.theme, jQuery]);
2601
2602// Counter
2603(function(theme, $) {
2604
2605	'use strict';
2606
2607	theme = theme || {};
2608
2609	var instanceName = '__sliderRange';
2610
2611	var PluginSliderRange = function($el, opts) {
2612		return this.initialize($el, opts);
2613	};
2614
2615	PluginSliderRange.defaults = {
2616		start: [ 50, 250 ],
2617		connect: true,
2618		step: 1,
2619		range: {
2620			min: 0,
2621			max: 300
2622		}
2623	};
2624
2625	PluginSliderRange.prototype = {
2626		initialize: function($el, opts) {
2627			if ($el.data(instanceName)) {
2628				return this;
2629			}
2630
2631			this.$el = $el;
2632
2633			this
2634				.setData()
2635				.setOptions(opts)
2636				.build();
2637
2638			return this;
2639		},
2640
2641		setData: function() {
2642			this.$el.data(instanceName, this);
2643
2644			return this;
2645		},
2646
2647		setOptions: function(opts) {
2648			this.options = $.extend(true, {}, PluginSliderRange.defaults, opts, {
2649				wrapper: this.$el
2650			});
2651
2652			return this;
2653		},
2654
2655		build: function() {
2656			if (!($.isFunction($.fn.countTo))) {
2657				return this;
2658			}
2659
2660			var self = this,
2661				$el = this.options.wrapper,
2662				priceLow = $('.price-range-low'),
2663				priceHigh = $('.price-range-high'),
2664				hiddenPriceLow = $('.hidden-price-range-low'),
2665				hiddenPriceHigh = $('.hidden-price-range-high');
2666
2667			// Create Slider
2668			noUiSlider.create($el[0], {
2669				start: [ 50, 250 ],
2670				connect: true,
2671				step: 1,
2672				range: {
2673					'min': 0,
2674					'max': 300
2675				}
2676			});
2677
2678			// Update Input values
2679			$el[0].noUiSlider.on('update', function( values, handle ) {
2680				var value = values[handle];
2681
2682				if ( handle ) {
2683					priceHigh.text(Math.round(value));
2684					hiddenPriceHigh.val(Math.round(value));
2685				} else {
2686					priceLow.text(Math.round(value));
2687					hiddenPriceLow.val(Math.round(value));
2688				}
2689			});
2690
2691			return this;
2692		}
2693	};
2694
2695	// expose to scope
2696	$.extend(theme, {
2697		PluginSliderRange: PluginSliderRange
2698	});
2699
2700	// jquery plugin
2701	$.fn.themePluginSliderRange = function(opts) {
2702		return this.map(function() {
2703			var $this = $(this);
2704
2705			if ($this.data(instanceName)) {
2706				return $this.data(instanceName);
2707			} else {
2708				return new PluginSliderRange($this, opts);
2709			}
2710
2711		});
2712	}
2713
2714}).apply(this, [window.theme, jQuery]);
2715
2716// Sort
2717(function(theme, $) {
2718
2719	'use strict';
2720
2721	theme = theme || {};
2722
2723	var instanceName = '__sort';
2724
2725	var PluginSort = function($el, opts) {
2726		return this.initialize($el, opts);
2727	};
2728
2729	PluginSort.defaults = {
2730		useHash: true,
2731		itemSelector: '.isotope-item',
2732		layoutMode: 'masonry',
2733		filter: '*',
2734		hiddenStyle: {
2735			opacity: 0
2736		},
2737		visibleStyle: {
2738			opacity: 1
2739		},
2740		stagger: 30,
2741		isOriginLeft: ($('html').attr('dir') == 'rtl' ? false : true)
2742	};
2743
2744	PluginSort.prototype = {
2745		initialize: function($el, opts) {
2746			if ($el.data(instanceName)) {
2747				return this;
2748			}
2749
2750			this.$el = $el;
2751
2752			this
2753				.setData()
2754				.setOptions(opts)
2755				.build();
2756
2757			return this;
2758		},
2759
2760		setData: function() {
2761			this.$el.data(instanceName, this);
2762
2763			return this;
2764		},
2765
2766		setOptions: function(opts) {
2767			this.options = $.extend(true, {}, PluginSort.defaults, opts, {
2768				wrapper: this.$el
2769			});
2770
2771			return this;
2772		},
2773
2774		build: function() {
2775			if (!($.isFunction($.fn.isotope))) {
2776				return this;
2777			}
2778
2779			var self = this,
2780				$source = this.options.wrapper,
2781				$destination = $('.sort-destination[data-sort-id="' + $source.attr('data-sort-id') + '"]'),
2782				$window = $(window);
2783
2784			if ($destination.get(0)) {
2785
2786				self.$source = $source;
2787				self.$destination = $destination;
2788				self.$loader = false;
2789
2790				self.setParagraphHeight($destination);
2791
2792				if (self.$destination.parents('.sort-destination-loader').get(0)) {
2793					self.$loader = self.$destination.parents('.sort-destination-loader');
2794					self.createLoader();
2795				}
2796
2797				$destination.attr('data-filter', '*');
2798
2799				$destination.one('layoutComplete', function(event, laidOutItems) {
2800					self.removeLoader();
2801				});
2802
2803				$destination.waitForImages(function() {
2804					$destination.isotope(self.options);
2805					self.events();
2806				});
2807
2808				setTimeout(function() {
2809					self.removeLoader();
2810				}, 3000);
2811
2812			}
2813
2814			return this;
2815		},
2816
2817		events: function() {
2818			var self = this,
2819				filter = null,
2820				$window = $(window);
2821
2822			self.$source.find('a').on('click', function(e) {
2823				e.preventDefault();
2824
2825				filter = $(this).parent().data('option-value');
2826
2827				self.setFilter(filter);
2828
2829				if (e.originalEvent) {
2830					self.$source.trigger('filtered');
2831				}
2832
2833				return this;
2834			});
2835
2836			self.$destination.trigger('filtered');
2837			self.$source.trigger('filtered');
2838
2839			if (self.options.useHash) {
2840				self.hashEvents();
2841			}
2842
2843			$window.on('resize', function() {
2844				setTimeout(function() {
2845					self.$destination.isotope('layout');
2846				}, 300);
2847			});
2848
2849			setTimeout(function() {
2850				$window.trigger('resize');
2851			}, 300);
2852
2853			return this;
2854		},
2855
2856		setFilter: function(filter) {
2857			var self = this,
2858				page = false,
2859				currentFilter = filter;
2860
2861			self.$source.find('.nav-link.active').removeClass('active');
2862			self.$source.find('li[data-option-value="' + filter + '"] .nav-link').addClass('active');
2863
2864			self.options.filter = currentFilter;
2865
2866			if (self.$destination.attr('data-current-page')) {
2867				currentFilter = currentFilter + '[data-page-rel=' + self.$destination.attr('data-current-page') + ']';
2868			}
2869
2870			self.$destination.attr('data-filter', filter).isotope({
2871				filter: currentFilter
2872			}).one('arrangeComplete', function( event, filteredItems ) {
2873				
2874				if (self.options.useHash) {
2875					if (window.location.hash != '' || self.options.filter.replace('.', '') != '*') {
2876						window.location.hash = self.options.filter.replace('.', '');
2877					}
2878				}
2879				
2880				$(window).trigger('scroll');
2881
2882			}).trigger('filtered');
2883
2884			return this;
2885		},
2886
2887		hashEvents: function() {
2888			var self = this,
2889				hash = null,
2890				hashFilter = null,
2891				initHashFilter = '.' + location.hash.replace('#', '');
2892
2893			if (initHashFilter != '.' && initHashFilter != '.*') {
2894				self.setFilter(initHashFilter);
2895			}
2896
2897			$(window).on('hashchange', function(e) {
2898
2899				hashFilter = '.' + location.hash.replace('#', '');
2900				hash = (hashFilter == '.' || hashFilter == '.*' ? '*' : hashFilter);
2901
2902				self.setFilter(hash);
2903
2904			});
2905
2906			return this;
2907		},
2908
2909		setParagraphHeight: function() {
2910			var self = this,
2911				minParagraphHeight = 0,
2912				paragraphs = $('span.image-frame-caption p', self.$destination);
2913
2914			paragraphs.each(function() {
2915				if ($(this).height() > minParagraphHeight) {
2916					minParagraphHeight = ($(this).height() + 10);
2917				}
2918			});
2919
2920			paragraphs.height(minParagraphHeight);
2921
2922			return this;
2923		},
2924
2925		createLoader: function() {
2926			var self = this;
2927
2928			var loaderTemplate = [
2929				'<div class="bounce-loader">',
2930					'<div class="bounce1"></div>',
2931					'<div class="bounce2"></div>',
2932					'<div class="bounce3"></div>',
2933				'</div>'
2934			].join('');
2935
2936			self.$loader.append(loaderTemplate);
2937
2938			return this;
2939		},
2940
2941		removeLoader: function() {
2942
2943			var self = this;
2944
2945			if (self.$loader) {
2946
2947				self.$loader.removeClass('sort-destination-loader-showing');
2948
2949				setTimeout(function() {
2950					self.$loader.addClass('sort-destination-loader-loaded');
2951				}, 300);
2952
2953			}
2954
2955		}
2956
2957	};
2958
2959	// expose to scope
2960	$.extend(theme, {
2961		PluginSort: PluginSort
2962	});
2963
2964	// jquery plugin
2965	$.fn.themePluginSort = function(opts) {
2966		return this.map(function() {
2967			var $this = $(this);
2968
2969			if ($this.data(instanceName)) {
2970				return $this.data(instanceName);
2971			} else {
2972				return new PluginSort($this, opts);
2973			}
2974
2975		});
2976	}
2977
2978}).apply(this, [window.theme, jQuery]);
2979
2980// Steps
2981(function(theme, $) {
2982	
2983	'use strict';
2984	
2985	theme = theme || {};
2986	
2987	var instanceName = '__steps';
2988
2989	var PluginSteps = function($el, opts) {
2990		return this.initialize($el, opts);
2991	};
2992
2993	PluginSteps.defaults = {
2994		delay: 7000,
2995		animDelay: 300,
2996		hideDotsOnBack: true
2997	};
2998
2999	PluginSteps.prototype = {
3000		initialize: function($el, opts) {
3001			if ( $el.data( instanceName ) ) {
3002				return this;
3003			}
3004
3005			this.$el = $el;
3006
3007			this
3008				.setData()
3009				.setOptions(opts)
3010				.build();
3011
3012			return this;
3013		},
3014
3015		setData: function() {
3016			this.$el.data(instanceName, this);
3017
3018			return this;
3019		},
3020
3021		setOptions: function(opts) {
3022			this.options = $.extend(true, {}, PluginSteps.defaults, opts, {
3023				wrapper: this.$el
3024			});
3025
3026			return this;
3027		},
3028
3029		build: function() {
3030			var self = this,
3031				$el = this.options.wrapper,
3032				$item = $el.find('.item'),
3033				$window = $(window);
3034
3035			// Set first item active class on page load
3036			if( !$el.find('.item.active').get(0) ) {
3037				$el.find('.item').eq(0).addClass('active');
3038			}
3039
3040			var start = function(firstTime) {				
3041				var activeItem = $el.find('.item.active'),
3042					firstItem  = $el.find('.item').eq(0),
3043					nextItem   = ( activeItem.next().length == 0 ) ? firstItem : activeItem.next(),
3044					nextItem2  = ( nextItem.next().length == 0 ) ? firstItem : nextItem.next(),
3045					isLastItem = $el.find('.item').length - 1 == activeItem.index(),
3046					darkDots   = $el.find('.dots-color-dark'),
3047					darkDotsLeft = ( !firstTime ) ? parseFloat( nextItem2.css('left') ) / nextItem2.parent().width() * 100 : parseFloat( nextItem.css('left') ) / nextItem.parent().width() * 100,
3048					darkDotsWidth = 140,
3049					darkDotsTransitionDuration = self.options.delay - 1000;
3050
3051				// If mobile
3052				if( $window.width() < 992 ) {
3053					darkDotsLeft = ( !firstTime ) ? parseFloat( nextItem2.css('top') ) / nextItem2.parent().height() * 100 : parseFloat( nextItem.css('top') ) / nextItem.parent().height() * 100;
3054				}
3055
3056				// If not is the first time
3057				if( !firstTime ) {
3058					$('.item').removeClass('active');
3059					nextItem.addClass('active');
3060				}
3061
3062				// Set dark dots transition duration
3063				darkDots.css({
3064					transition: 'linear left '+ darkDotsTransitionDuration +'ms'
3065				});
3066
3067				// Check and set the value of left position for dark dots
3068				if( darkDotsLeft == 50 ) {
3069					darkDotsLeft = 50+'%';
3070				} else if( darkDotsLeft > 50 ) {
3071					darkDotsLeft = (darkDotsLeft + 20)+'%';
3072				} else {
3073					darkDotsLeft = (darkDotsLeft - 20)+'%';
3074				}
3075
3076				// Set width and left position for dark dots
3077				darkDots.css({
3078					width: darkDotsWidth,
3079					left: darkDotsLeft,
3080					opacity: 1
3081				});
3082
3083				// Hide dots when back
3084				if( isLastItem && self.options.hideDotsOnBack ) {
3085					darkDots.css({
3086						opacity: 0
3087					});
3088				}
3089
3090				// Remove active border color from current item
3091				setTimeout(function(){
3092					nextItem.css({
3093						'border-color': $el.find('.dots-color').css('background-color')
3094					});
3095				}, (isLastItem) ? self.options.delay : self.options.delay );
3096
3097				// Check if is first time
3098				if( !firstTime ) {
3099					
3100					// Set active border color for next item
3101					setTimeout(function(){
3102						nextItem2.css({
3103							'border-color': $el.find('.dots-color-dark').css('background-color')
3104						});
3105					}, self.options.delay);
3106
3107					// Link Elements
3108					if( nextItem.data('link-to') ) {
3109						var link_to = nextItem.data('link-to');
3110
3111						$('[data-link-id]').addClass('steps-shadow active');
3112						$('[data-link-id="'+ link_to +'"]').removeClass('active');
3113					}
3114
3115				} else {
3116					
3117					// Remove active border color from first item
3118					setTimeout(function(){
3119						firstItem.css({
3120							'border-color': $el.find('.dots-color').css('background-color')
3121						});
3122					}, self.options.delay );
3123
3124					// Set active border color for next item
3125					setTimeout(function(){
3126						nextItem.css({
3127							'border-color': $el.find('.dots-color-dark').css('background-color')
3128						});
3129					}, self.options.delay);
3130
3131					// Link Elements
3132					if( firstItem.data('link-to') ) {
3133						var link_to = firstItem.data('link-to');
3134
3135						$('[data-link-id]').addClass('steps-shadow active');
3136						$('[data-link-id="'+ link_to +'"]').removeClass('active');
3137					}
3138				
3139				}
3140
3141							
3142			}
3143
3144			var initialized = false;
3145			$window.on('scroll', function(){
3146				if( $el.visible( true ) && initialized == false ) {
3147					// Pevent to initialize again
3148					initialized = true;
3149
3150					// Execute start() only one time (first time)
3151					start(true);
3152
3153					// Execute start() every defined delay time
3154					setInterval(function(){
3155						start();
3156					}, self.options.delay);
3157				}
3158			});
3159			
3160			return this;
3161		}
3162	};
3163
3164	// expose to scope
3165	$.extend(theme, {
3166		PluginSteps: PluginSteps
3167	});
3168
3169	// jquery plugin
3170	$.fn.themePluginSteps = function(opts) {
3171		return this.map(function() {
3172			var $this = $(this);
3173
3174			if ($this.data(instanceName)) {
3175				return $this.data(instanceName);
3176			} else {
3177				return new PluginSteps($this, opts);
3178			}
3179			
3180		});
3181	}
3182
3183}).apply(this, [ window.theme, jQuery ]);
3184
3185// Sticky
3186(function(theme, $) {
3187	
3188	'use strict';
3189	
3190	theme = theme || {};
3191	
3192	var instanceName = '__sticky';
3193
3194	var PluginSticky = function($el, opts) {
3195		return this.initialize($el, opts);
3196	};
3197
3198	PluginSticky.defaults = {
3199		
3200	};
3201
3202	PluginSticky.prototype = {
3203		initialize: function($el, opts) {
3204			if ( $el.data( instanceName ) ) {
3205				return this;
3206			}
3207
3208			this.$el = $el;
3209
3210			this
3211				.setData()
3212				.setOptions(opts)
3213				.build()
3214				.events();
3215
3216			return this;
3217		},
3218
3219		setData: function() {
3220			this.$el.data(instanceName, this);
3221
3222			return this;
3223		},
3224
3225		setOptions: function(opts) {
3226			this.options = $.extend(true, {}, PluginSticky.defaults, opts, {
3227				wrapper: this.$el
3228			});
3229
3230			return this;
3231		},
3232
3233		build: function() {
3234			var self = this,
3235				$window = $(window),
3236				$html = $('html');
3237			
3238			if( !$.browser.mobile && !self.options.stickyStartAt ) {
3239				self.options.wrapper.stick_in_parent(self.options);
3240			}
3241
3242			if( self.options.stickyStartAt ) {
3243				var $stickyWrapper = self.options.wrapper,
3244					$stickyBody     = self.options.wrapper.find('.sticky-body');
3245
3246				// Set Sticky Wrapper Height
3247				$stickyWrapper.css({
3248					height: $stickyWrapper.outerHeight()
3249				});
3250
3251				// Change Logo Src
3252				if( $stickyWrapper.find('img').attr('data-change-src') ) {
3253					var $logo      = $stickyWrapper.find('img'),
3254						logoSrc    = $logo.attr('src'),
3255						logoNewSrc = $logo.attr('data-change-src');
3256
3257					self.changeLogoSrc = function(activate) {
3258						if(activate) {
3259							$logo.attr('src', logoNewSrc);
3260						} else {
3261							$logo.attr('src', logoSrc);
3262						}
3263					}
3264				}
3265			}
3266			
3267			return this;
3268		},
3269		events: function() {
3270			var self = this,
3271				$window = $(window),
3272				$html = $('html'),
3273				$logo = self.options.wrapper.find('img');
3274
3275			$window.on('scroll', function(){
3276
3277				if( self.options.stickyStartAt < $window.scrollTop() ) {
3278					$html.addClass('sticky-wrapper-active');
3279					
3280					if( $logo.attr('data-change-src') ) {
3281						self.changeLogoSrc(true);
3282					}
3283				} else {
3284					$html.removeClass('sticky-wrapper-active');
3285					
3286					if( $logo.attr('data-change-src') ) {
3287						self.changeLogoSrc(false);
3288					}
3289				}
3290
3291			});
3292		}
3293	};
3294
3295	// expose to scope
3296	$.extend(theme, {
3297		PluginSticky: PluginSticky
3298	});
3299
3300	// jquery plugin
3301	$.fn.themePluginSticky = function(opts) {
3302		return this.map(function() {
3303			var $this = $(this);
3304
3305			if ($this.data(instanceName)) {
3306				return $this.data(instanceName);
3307			} else {
3308				return new PluginSticky($this, opts);
3309			}
3310			
3311		});
3312	}
3313
3314}).apply(this, [ window.theme, jQuery ]);
3315
3316// Toggle
3317(function(theme, $) {
3318
3319	'use strict';
3320
3321	theme = theme || {};
3322
3323	var instanceName = '__toggle';
3324
3325	var PluginToggle = function($el, opts) {
3326		return this.initialize($el, opts);
3327	};
3328
3329	PluginToggle.defaults = {
3330		duration: 350,
3331		isAccordion: false
3332	};
3333
3334	PluginToggle.prototype = {
3335		initialize: function($el, opts) {
3336			if ($el.data(instanceName)) {
3337				return this;
3338			}
3339
3340			this.$el = $el;
3341
3342			this
3343				.setData()
3344				.setOptions(opts)
3345				.build();
3346
3347			return this;
3348		},
3349
3350		setData: function() {
3351			this.$el.data(instanceName, this);
3352
3353			return this;
3354		},
3355
3356		setOptions: function(opts) {
3357			this.options = $.extend(true, {}, PluginToggle.defaults, opts, {
3358				wrapper: this.$el
3359			});
3360
3361			return this;
3362		},
3363
3364		build: function() {
3365			var self = this,
3366				$wrapper = this.options.wrapper,
3367				$items = $wrapper.find('.toggle'),
3368				$el = null;
3369
3370			$items.each(function() {
3371				$el = $(this);
3372
3373				if ($el.hasClass('active')) {
3374					$el.find('> p').addClass('preview-active');
3375					$el.find('> .toggle-content').slideDown(self.options.duration);
3376				}
3377
3378				self.events($el);
3379			});
3380
3381			if (self.options.isAccordion) {
3382				self.options.duration = self.options.duration / 2;
3383			}
3384
3385			return this;
3386		},
3387
3388		events: function($el) {
3389			var self = this,
3390				previewParCurrentHeight = 0,
3391				previewParAnimateHeight = 0,
3392				toggleContent = null;
3393
3394			$el.find('> label').on('click', function(e) {
3395
3396				var $this = $(this),
3397					parentSection = $this.parent(),
3398					parentWrapper = $this.parents('.toggle'),
3399					previewPar = null,
3400					closeElement = null;
3401
3402				if (self.options.isAccordion && typeof(e.originalEvent) != 'undefined') {
3403					closeElement = parentWrapper.find('.toggle.active > label');
3404
3405					if (closeElement[0] == $this[0]) {
3406						return;
3407					}
3408				}
3409
3410				parentSection.toggleClass('active');
3411
3412				// Preview Paragraph
3413				if (parentSection.find('> p').get(0)) {
3414
3415					previewPar = parentSection.find('> p');
3416					previewParCurrentHeight = previewPar.css('height');
3417					previewPar.css('height', 'auto');
3418					previewParAnimateHeight = previewPar.css('height');
3419					previewPar.css('height', previewParCurrentHeight);
3420
3421				}
3422
3423				// Content
3424				toggleContent = parentSection.find('> .toggle-content');
3425
3426				if (parentSection.hasClass('active')) {
3427
3428					$(previewPar).animate({
3429						height: previewParAnimateHeight
3430					}, self.options.duration, function() {
3431						$(this).addClass('preview-active');
3432					});
3433
3434					toggleContent.slideDown(self.options.duration, function() {
3435						if (closeElement) {
3436							closeElement.trigger('click');
3437						}
3438					});
3439
3440				} else {
3441
3442					$(previewPar).animate({
3443						height: 0
3444					}, self.options.duration, function() {
3445						$(this).removeClass('preview-active');
3446					});
3447
3448					toggleContent.slideUp(self.options.duration);
3449
3450				}
3451
3452			});
3453		}
3454	};
3455
3456	// expose to scope
3457	$.extend(theme, {
3458		PluginToggle: PluginToggle
3459	});
3460
3461	// jquery plugin
3462	$.fn.themePluginToggle = function(opts) {
3463		return this.map(function() {
3464			var $this = $(this);
3465
3466			if ($this.data(instanceName)) {
3467				return $this.data(instanceName);
3468			} else {
3469				return new PluginToggle($this, opts);
3470			}
3471
3472		});
3473	}
3474
3475}).apply(this, [window.theme, jQuery]);
3476
3477// Tweets
3478(function(theme, $) {
3479
3480	'use strict';
3481
3482	theme = theme || {};
3483
3484	var instanceName = '__tweets';
3485
3486	var PluginTweets = function($el, opts) {
3487		return this.initialize($el, opts);
3488	};
3489
3490	PluginTweets.defaults = {
3491		username: null,
3492		count: 2,
3493		URL: 'php/twitter-feed.php'
3494	};
3495
3496	PluginTweets.prototype = {
3497		initialize: function($el, opts) {
3498			if ($el.data(instanceName)) {
3499				return this;
3500			}
3501
3502			this.$el = $el;
3503
3504			this
3505				.setData()
3506				.setOptions(opts)
3507				.build();
3508
3509			return this;
3510		},
3511
3512		setData: function() {
3513			this.$el.data(instanceName, this);
3514
3515			return this;
3516		},
3517
3518		setOptions: function(opts) {
3519			this.options = $.extend(true, {}, PluginTweets.defaults, opts, {
3520				wrapper: this.$el
3521			});
3522
3523			return this;
3524		},
3525
3526		build: function() {
3527			if (this.options.username == null || this.options.username == '') {
3528				return this;
3529			}
3530
3531			var self = this,
3532				$wrapper = this.options.wrapper;
3533
3534			$.ajax({
3535				type: 'GET',
3536				data: {
3537					twitter_screen_name: self.options.username,
3538					tweets_to_display: self.options.count
3539				},
3540				url: self.options.URL,
3541			}).done(function(html) {
3542				$wrapper.html(html).find('a').attr('target','_blank');
3543			});
3544
3545			return this;
3546		}
3547	};
3548
3549	// expose to scope
3550	$.extend(theme, {
3551		PluginTweets: PluginTweets
3552	});
3553
3554	// jquery plugin
3555	$.fn.themePluginTweets = function(opts) {
3556		return this.map(function() {
3557			var $this = $(this);
3558
3559			if ($this.data(instanceName)) {
3560				return $this.data(instanceName);
3561			} else {
3562				return new PluginTweets($this, opts);
3563			}
3564
3565		});
3566	}
3567
3568}).apply(this, [window.theme, jQuery]);
3569
3570// Validation
3571(function(theme, $) {
3572
3573	'use strict';
3574
3575	theme = theme || {};
3576
3577	var initialized = false;
3578
3579	$.extend(theme, {
3580
3581		PluginValidation: {
3582
3583			defaults: {
3584				validator: {
3585					highlight: function(element) {
3586						$(element)
3587							.parent()
3588							.removeClass('has-success')
3589							.addClass('has-error');
3590					},
3591					success: function(element) {
3592						$(element)
3593							.parent()
3594							.removeClass('has-error')
3595							.addClass('has-success')
3596							.find('label.error')
3597							.remove();
3598					},
3599					errorPlacement: function(error, element) {
3600						if (element.attr('type') == 'radio' || element.attr('type') == 'checkbox') {
3601							error.appendTo(element.parent().parent());
3602						} else {
3603							error.insertAfter(element);
3604						}
3605					}
3606				},
3607				validateCaptchaURL: 'php/contact-form-verify-captcha.php',
3608				refreshCaptchaURL: 'php/contact-form-refresh-captcha.php'
3609			},
3610
3611			initialize: function(opts) {
3612				initialized = true;
3613
3614				this
3615					.setOptions(opts)
3616					.build();
3617
3618				return this;
3619			},
3620
3621			setOptions: function(opts) {
3622				this.options = $.extend(true, {}, this.defaults, opts);
3623
3624				return this;
3625			},
3626
3627			build: function() {
3628				var self = this;
3629
3630				if (!($.isFunction($.validator))) {
3631					return this;
3632				}
3633
3634				self.addMethods();
3635				self.setMessageGroups();
3636
3637				$.validator.setDefaults(self.options.validator);
3638
3639				return this;
3640			},
3641
3642			addMethods: function() {
3643				var self = this;
3644
3645				$.validator.addMethod('captcha', function(value, element, params) {
3646					var captchaValid = false;
3647
3648					$.ajax({
3649						url: self.options.validateCaptchaURL,
3650						type: 'POST',
3651						async: false,
3652						dataType: 'json',
3653						data: {
3654							captcha: $.trim(value)
3655						},
3656						success: function(data) {
3657							if (data.response == 'success') {
3658								captchaValid = true;
3659							}
3660						}
3661					});
3662
3663					if (captchaValid) {
3664						return true;
3665					}
3666
3667				}, '');
3668
3669				// Refresh Captcha
3670				$('#refreshCaptcha').on('click', function(e) {
3671					e.preventDefault();
3672					$.get(self.options.refreshCaptchaURL, function(url) {
3673						$('#captcha-image').attr('src', url);
3674					});					
3675				});
3676
3677			},
3678
3679			setMessageGroups: function() {
3680
3681				$('.checkbox-group[data-msg-required], .radio-group[data-msg-required]').each(function() {
3682					var message = $(this).data('msg-required');
3683					$(this).find('input').attr('data-msg-required', message);
3684				});
3685
3686			}
3687
3688		}
3689
3690	});
3691
3692}).apply(this, [window.theme, jQuery]);
3693
3694// Video Background
3695(function(theme, $) {
3696
3697	'use strict';
3698
3699	theme = theme || {};
3700
3701	var instanceName = '__videobackground';
3702
3703	var PluginVideoBackground = function($el, opts) {
3704		return this.initialize($el, opts);
3705	};
3706
3707	PluginVideoBackground.defaults = {
3708		overlay: true,
3709		volume: 1,
3710		playbackRate: 1,
3711		muted: true,
3712		loop: true,
3713		autoplay: true,
3714		position: '50% 50%',
3715		posterType: 'detect',
3716		className: 'z-index-0'
3717	};
3718
3719	PluginVideoBackground.prototype = {
3720		initialize: function($el, opts) {
3721			this.$el = $el;
3722
3723			this
3724				.setData()
3725				.setOptions(opts)
3726				.build();
3727
3728			return this;
3729		},
3730
3731		setData: function() {
3732			this.$el.data(instanceName, this);
3733
3734			return this;
3735		},
3736
3737		setOptions: function(opts) {
3738			this.options = $.extend(true, {}, PluginVideoBackground.defaults, opts, {
3739				path: this.$el.data('video-path'),
3740				wrapper: this.$el
3741			});
3742
3743			return this;
3744		},
3745
3746		build: function() {
3747
3748			if (!($.isFunction($.fn.vide)) || (!this.options.path)) {
3749				return this;
3750			}
3751
3752			if (this.options.overlay) {
3753				this.options.wrapper.prepend(
3754					$('<div />').addClass('video-overlay')
3755				);
3756			}
3757
3758			this.options.wrapper.vide(this.options.path, this.options);
3759
3760			return this;
3761		}
3762	};
3763
3764	// expose to scope
3765	$.extend(theme, {
3766		PluginVideoBackground: PluginVideoBackground
3767	});
3768
3769	// jquery plugin
3770	$.fn.themePluginVideoBackground = function(opts) {
3771		return this.map(function() {
3772			var $this = $(this);
3773
3774			if ($this.data(instanceName)) {
3775				return $this.data(instanceName);
3776			} else {
3777				return new PluginVideoBackground($this, opts);
3778			}
3779
3780		});
3781	}
3782
3783}).apply(this, [window.theme, jQuery]);
3784
3785// Account
3786(function(theme, $) {
3787
3788	theme = theme || {};
3789
3790	var initialized = false;
3791
3792	$.extend(theme, {
3793
3794		Account: {
3795
3796			defaults: {
3797				wrapper: $('#headerAccount')
3798			},
3799
3800			initialize: function($wrapper, opts) {
3801				if (initialized) {
3802					return this;
3803				}
3804
3805				initialized = true;
3806				this.$wrapper = ($wrapper || this.defaults.wrapper);
3807
3808				this
3809					.setOptions(opts)
3810					.events();
3811
3812				return this;
3813			},
3814
3815			setOptions: function(opts) {
3816				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
3817
3818				return this;
3819			},
3820
3821			events: function() {
3822				var self = this;
3823
3824				self.$wrapper.find('input').on('focus', function() {
3825					self.$wrapper.addClass('open');
3826
3827					$(document).mouseup(function(e) {
3828						if (!self.$wrapper.is(e.target) && self.$wrapper.has(e.target).length === 0) {
3829							self.$wrapper.removeClass('open');
3830						}
3831					});
3832				});
3833
3834				$('#headerSignUp').on('click', function(e) {
3835					e.preventDefault();
3836					self.$wrapper.addClass('signup').removeClass('signin').removeClass('recover');
3837					self.$wrapper.find('.signup-form input:first').focus();
3838				});
3839
3840				$('#headerSignIn').on('click', function(e) {
3841					e.preventDefault();
3842					self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover');
3843					self.$wrapper.find('.signin-form input:first').focus();
3844				});
3845
3846				$('#headerRecover').on('click', function(e) {
3847					e.preventDefault();
3848					self.$wrapper.addClass('recover').removeClass('signup').removeClass('signin');
3849					self.$wrapper.find('.recover-form input:first').focus();
3850				});
3851
3852				$('#headerRecoverCancel').on('click', function(e) {
3853					e.preventDefault();
3854					self.$wrapper.addClass('signin').removeClass('signup').removeClass('recover');
3855					self.$wrapper.find('.signin-form input:first').focus();
3856				});
3857			}
3858
3859		}
3860
3861	});
3862
3863}).apply(this, [window.theme, jQuery]);
3864
3865// Nav
3866(function(theme, $) {
3867
3868	theme = theme || {};
3869
3870	var initialized = false;
3871
3872	$.extend(theme, {
3873
3874		Nav: {
3875
3876			defaults: {
3877				wrapper: $('#mainNav'),
3878				scrollDelay: 600,
3879				scrollAnimation: 'easeOutQuad'
3880			},
3881
3882			initialize: function($wrapper, opts) {
3883				if (initialized) {
3884					return this;
3885				}
3886
3887				initialized = true;
3888				this.$wrapper = ($wrapper || this.defaults.wrapper);
3889
3890				this
3891					.setOptions(opts)
3892					.build()
3893					.events();
3894
3895				return this;
3896			},
3897
3898			setOptions: function(opts) {
3899				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
3900
3901				return this;
3902			},
3903
3904			build: function() {
3905				var self = this,
3906					$html = $('html'),
3907					$header = $('#header'),
3908					thumbInfoPreview;
3909
3910				// Add Arrows
3911				$header.find('.dropdown-toggle, .dropdown-submenu > a').append($('<i />').addClass('menu-arrow'));
3912
3913				// Side Header
3914				if( $html.hasClass('side-header') || $html.hasClass('side-header-overlay-full-screen') ) {
3915					
3916					// Nano Scroll
3917					$('.nano').nanoScroller({
3918						alwaysVisible: true
3919					});
3920				}
3921
3922				// Reverse
3923				self.checkReverse = function() {
3924
3925					self.$wrapper.find('.dropdown-submenu').removeClass('dropdown-reverse');
3926
3927					self.$wrapper.find('.dropdown-submenu:not(.manual)').each(function() {
3928						if(!$(this).find('.dropdown-menu').visible( false, true, 'horizontal' )  ) {
3929							$(this).addClass('dropdown-reverse');
3930						}
3931					});
3932				}
3933
3934				if( !$html.hasClass('side-header') && !$html.hasClass('side-header-overlay-full-screen') ) {
3935					self.checkReverse();
3936
3937	 				$(window).on('resize', function() {
3938						self.checkReverse();
3939	 				});
3940				}
3941
3942				return this;
3943			},
3944
3945			events: function() {
3946				var self    = this,
3947					$html   = $('html'),
3948					$header = $('#header'),
3949					$window = $(window),
3950					headerBodyHeight = $('.header-body').outerHeight();
3951
3952				$header.find('a[href="#"]').on('click', function(e) {
3953					e.preventDefault();
3954				});
3955
3956				// Mobile Arrows
3957				$header.find('.dropdown-toggle[href="#"], .dropdown-submenu a[href="#"], .dropdown-toggle[href!="#"] .menu-arrow, .dropdown-submenu a[href!="#"] .menu-arrow').on('click', function(e) {
3958					e.preventDefault();
3959					if ($window.width() < 992 || $html.hasClass('side-header') || $html.hasClass('side-header-overlay-full-screen')) {
3960						if( $(this).closest('li').hasClass('opened') ) {
3961							$(this).closest('li').find('> .dropdown-menu').slideUp(600, function(){
3962								$(this).closest('li').removeClass('opened');
3963
3964								// Refresh Nano Scroll
3965								if( $html.hasClass('side-header') || $html.hasClass('side-header-overlay-full-screen') ) {
3966									$('.nano').nanoScroller();
3967								}
3968								
3969							});
3970						} else {
3971							$(this).closest('li').addClass('opened');
3972							$(this).closest('li').find('> .dropdown-menu').slideDown(600, function(){
3973								
3974								// Refresh Nano Scroll
3975								if( $html.hasClass('side-header') || $html.hasClass('side-header-overlay-full-screen') ) {
3976									$('.nano').nanoScroller();
3977								}
3978								
3979							});
3980						}
3981					}
3982				});
3983
3984				// Touch Devices with normal resolutions
3985				if('ontouchstart' in document.documentElement) {
3986					$header.find('.dropdown-toggle:not([href="#"]), .dropdown-submenu > a:not([href="#"])')
3987						.on('touchstart click', function(e) {
3988							if($window.width() > 991) {
3989
3990								e.stopPropagation();
3991								e.preventDefault();
3992
3993								if(e.handled !== true) {
3994
3995									var li = $(this).closest('li');
3996
3997									if(li.hasClass('tapped')) {
3998										location.href = $(this).attr('href');
3999									}
4000
4001									li.addClass('tapped');
4002
4003									e.handled = true;
4004								} else {
4005									return false;
4006								}
4007
4008								return false;
4009
4010							}
4011						})
4012						.on('blur', function(e) {
4013							$(this).closest('li').removeClass('tapped');
4014						});
4015
4016				}
4017
4018				// Collapse Nav
4019				$header.find('[data-collapse-nav]').on('click', function(e) {
4020					$(this).parents('.collapse').removeClass('in');
4021				});
4022
4023				// Mobile Menu Button
4024				var mobileMenuBtn = $('.header-btn-collapse-nav'),
4025					flagMenu = true;
4026				
4027				mobileMenuBtn.on('click', function(){
4028					if( flagMenu ) {
4029						$(this).toggleClass('active');
4030						$html.addClass('mobile-menu-opened');
4031					}
4032					flagMenu = false;
4033				});
4034
4035				$('.header-nav-main nav').on('show.bs.collapse hide.bs.collapse', function (e) {
4036				    if( e.type == 'hide' ) {
4037					    $html.removeClass('mobile-menu-opened');
4038					    $(this).addClass('closed');
4039				    }
4040				    if( e.type == 'show' ) {
4041					    $(this).removeClass('closed');
4042				    }
4043				    flagMenu = true;
4044				});
4045
4046				// Anchors Position
4047				$('[data-hash]').each(function() {
4048
4049					var target    = ($(this).attr('href') != '#') ? $(this).attr('href') : '',
4050						offset    = ($(this).is("[data-hash-offset]") ? $(this).data('hash-offset') : 0),
4051						highlight = ($(this).is("[data-hash-highlight]") ? true : false);
4052
4053					if($(target).get(0)) {
4054						$(this).on('click', function(e) {
4055							e.preventDefault();
4056
4057							if( $window.width() < 992 ) {
4058								if( !$(e.target).is('i') ) {
4059
4060									// Close Collapse if Opened
4061									$(this).parents('.collapse.show').collapse('hide');
4062
4063									// Change state of mobile menu button
4064									$('.header-btn-collapse-nav').removeClass('active')
4065
4066									// Scroll to target
4067									self.scrollToTarget(target, offset, highlight);
4068									
4069								}
4070							} else {
4071								// Scroll to target
4072								self.scrollToTarget(target, offset, highlight);
4073							}
4074
4075							return;
4076						});
4077					}
4078
4079				});
4080
4081				// Side Header Nano Scroll On Resize
4082				if( $html.hasClass('side-header') ) {
4083					$window.on('resize', function(){
4084						if( $window.width() < 992 ) {
4085							$('.nano').nanoScroller({ destroy: true });
4086							$header.find('.header-nav').removeClass('nano');
4087						} else {
4088							$header.find('.header-nav').addClass('nano');
4089							$('.nano').nanoScroller();
4090						}
4091					});
4092				}
4093
4094				// Side Header Toggle
4095				if( $html.hasClass('side-header-from-out') || $html.hasClass('side-header-overlay-full-screen') ) {
4096					$('.side-header-btn-toggle').on('click', function(){
4097						$header.toggleClass('side-header-show');
4098						
4099						if( $html.hasClass('side-header-overlay-full-screen') ) {
4100							$html.find('body').addClass('no-vertical-scroll');
4101						}
4102						return false;
4103					});
4104
4105					$('.side-header-btn-close').on('click', function(){
4106						$header.removeClass('side-header-show');
4107						
4108						if( $html.hasClass('side-header-overlay-full-screen') ) {
4109							$html.find('body').removeClass('no-vertical-scroll');
4110						}
4111						return false;
4112					});
4113				}
4114
4115				// Header Search Expanded
4116				var searchBtn  = $header.find('.header-search-button'),
4117					searchExpanded = $header.find('.header-search-expanded');
4118				
4119				if( searchExpanded ) {
4120					searchBtn.on('click', function(){
4121						$html.toggleClass('header-search-expanded-active');
4122					});
4123					
4124					$(document).mouseup(function(e) {
4125						if (!searchExpanded.is(e.target) && searchExpanded.has(e.target).length === 0) {
4126							$html.removeClass('header-search-expanded-active');
4127						}
4128					});
4129				}
4130
4131				return this;
4132			},
4133
4134			scrollToTarget: function(target, offset, highlight) {
4135				var self = this;
4136
4137				$('body').addClass('scrolling');
4138
4139				$('html, body').animate({
4140					scrollTop: $(target).offset().top - offset
4141				}, self.options.scrollDelay, self.options.scrollAnimation, function() {
4142					
4143					if( highlight ) {
4144						$(target).addClass('highlight-anim');
4145
4146						setTimeout(function(){
4147							$(target).removeClass('highlight-anim');
4148						}, 1200);
4149					}
4150
4151					$('body').removeClass('scrolling');
4152				});
4153
4154				return this;
4155
4156			}
4157
4158		}
4159
4160	});
4161
4162}).apply(this, [window.theme, jQuery]);
4163
4164
4165// Newsletter
4166(function(theme, $) {
4167
4168	theme = theme || {};
4169
4170	var initialized = false;
4171
4172	$.extend(theme, {
4173
4174		Newsletter: {
4175
4176			defaults: {
4177				wrapper: $('.newsletter-form')
4178			},
4179
4180			initialize: function($wrapper, opts) {
4181				if (initialized) {
4182					return this;
4183				}
4184
4185				initialized = true;
4186				this.$wrapper = ($wrapper || this.defaults.wrapper);
4187
4188				this
4189					.setOptions(opts)
4190					.build();
4191
4192				return this;
4193			},
4194
4195			setOptions: function(opts) {
4196				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
4197
4198				return this;
4199			},
4200
4201			build: function() {
4202				if (!($.isFunction($.fn.validate))) {
4203					return this;
4204				}
4205
4206				var self = this;
4207
4208				self.$wrapper.each(function(){
4209
4210					var $wrapper = $(this),
4211					    $email = $wrapper.find('.newsletter-email'),
4212						$success = $wrapper.find('.newsletter-form-success'),
4213						$error = $wrapper.find('.newsletter-form-error');
4214
4215					$wrapper.validate({
4216						submitHandler: function(form) {
4217
4218							$.ajax({
4219								type: 'POST',
4220								url: $wrapper.attr('action'),
4221								data: {
4222									'email': $email.val()
4223								},
4224								dataType: 'json'
4225							}).always(function(data, textStatus, jqXHR) {
4226
4227								if (data.response == 'success') {
4228									$success.removeClass('d-none');
4229									$error.addClass('d-none');
4230
4231									$email
4232										.val('')
4233										.blur();
4234
4235									$wrapper.find('label.error').remove();
4236
4237									// Uncomment the code below if want hide the Success message after a time
4238									// setTimeout(function(){
4239									// 	$success.addClass('d-none');
4240									// }, 5000);
4241
4242									return;
4243
4244								} else {
4245									$error.html(data.message);
4246									$error.removeClass('d-none');
4247									$success.addClass('d-none');
4248
4249									$email
4250										.blur();
4251
4252									$wrapper.find('label.error').remove();
4253
4254									return;
4255								}
4256
4257								$error.removeClass('d-none');
4258								$success.addClass('d-none');
4259
4260								$wrapper.find('.has-success')
4261									.removeClass('has-success');
4262									
4263							});
4264
4265						},
4266						rules: {
4267							newsletterEmail: {
4268								required: true,
4269								email: true
4270							}
4271						},
4272						errorPlacement: function(error, element) {
4273							if( !element.next().hasClass('input-group') ) {
4274								element.closest('.newsletter-form').append(error);
4275							} else {
4276								error.insertAfter(element.parent());
4277							}
4278						}
4279					});
4280
4281				});
4282
4283				return this;
4284			}
4285
4286		}
4287
4288	});
4289
4290}).apply(this, [window.theme, jQuery]);
4291
4292// Search
4293(function(theme, $) {
4294
4295	theme = theme || {};
4296
4297	var initialized = false;
4298
4299	$.extend(theme, {
4300
4301		Search: {
4302
4303			defaults: {
4304				wrapper: $('#searchForm')
4305			},
4306
4307			initialize: function($wrapper, opts) {
4308				if (initialized) {
4309					return this;
4310				}
4311
4312				initialized = true;
4313				this.$wrapper = ($wrapper || this.defaults.wrapper);
4314
4315				this
4316					.setOptions(opts)
4317					.build();
4318
4319				return this;
4320			},
4321
4322			setOptions: function(opts) {
4323				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
4324
4325				return this;
4326			},
4327
4328			build: function() {
4329				if (!($.isFunction($.fn.validate))) {
4330					return this;
4331				}
4332
4333				this.$wrapper.validate({
4334					errorPlacement: function(error, element) {}
4335				});
4336
4337				return this;
4338			}
4339
4340		}
4341
4342	});
4343
4344}).apply(this, [window.theme, jQuery]);
4345
4346// Sticky Header
4347(function(theme, $) {
4348
4349	theme = theme || {};
4350
4351	var initialized = false;
4352
4353	$.extend(theme, {
4354
4355		StickyHeader: {
4356
4357			defaults: {
4358				wrapper: $('#header'),
4359				headerBody: $('#header .header-body'),
4360				stickyEnabled: true,
4361				stickyEnableOnBoxed: true,
4362				stickyEnableOnMobile: true,
4363				stickyStartAt: 0,
4364				stickyStartAtElement: false,
4365				stickySetTop: 0,
4366				stickyHeaderContainerHeight: false,
4367				stickyChangeLogo: false
4368			},
4369
4370			initialize: function($wrapper, opts) {
4371				if (initialized) {
4372					return this;
4373				}
4374
4375				initialized = true;
4376				this.$wrapper = ($wrapper || this.defaults.wrapper);
4377
4378				this
4379					.setOptions(opts)
4380					.build()
4381					.events();
4382
4383				return this;
4384			},
4385
4386			setOptions: function(opts) {
4387				this.options = $.extend(true, {}, this.defaults, opts, theme.fn.getOptions(this.$wrapper.data('plugin-options')));
4388
4389				return this;
4390			},
4391
4392			build: function() {
4393				if (!this.options.stickyEnableOnBoxed && $('html').hasClass('boxed') || !this.options.stickyEnabled) {
4394					return this;
4395				}
4396
4397				var self = this,
4398					$html = $('html'),
4399					$window = $(window),
4400					sideHeader = $html.hasClass('side-header'),
4401					initialHeaderTopHeight = self.options.wrapper.find('.header-top').outerHeight(),
4402					initialHeaderContainerHeight = self.options.wrapper.find('.header-container').outerHeight(),
4403					minHeight;
4404
4405				// HTML Classes
4406				$html.addClass('sticky-header-enabled');
4407
4408				if (parseInt(self.options.stickySetTop) < 0) {
4409					$html.addClass('sticky-header-negative');
4410				}
4411
4412				// Set Start At
4413				if(self.options.stickyStartAtElement) {
4414
4415					var $stickyStartAtElement = $(self.options.stickyStartAtElement);
4416
4417					$(window).on('scroll resize', function() {
4418						self.options.stickyStartAt = $stickyStartAtElement.offset().top;
4419					});
4420
4421					$(window).trigger('resize');
4422				}
4423
4424				// Boxed
4425				if($html.hasClass('boxed') && (parseInt(self.options.stickyStartAt) == 0) && $window.width() > 991) {
4426					self.options.stickyStartAt = 30;
4427				}
4428
4429				// Define Min Height value
4430				if( self.options.wrapper.find('.header-top').get(0) ) {
4431					minHeight = ( initialHeaderTopHeight + initialHeaderContainerHeight );
4432				} else {
4433					minHeight = initialHeaderContainerHeight;
4434				}
4435
4436				// Set header Body Position When Always Sticky
4437				if( self.options.stickyStartAt == 0 ) {
4438					self.options.headerBody.css('position','fixed');
4439				}
4440
4441				// Two Logos Effect
4442				if( self.options.wrapper.find('.header-logo img').length > 1 ) {
4443					self.options.wrapper.find('.header-logo .logo-2').removeClass('d-none');
4444				}
4445
4446				// Set Wrapper Min Height
4447				$window.on('stickyHeader.activate stickyHeader.deactivate', function(){
4448					self.options.wrapper.css('min-height', minHeight);
4449				});
4450
4451				// Sticky Header Container Height
4452				if( self.options.stickyHeaderContainerHeight ) {
4453					self.options.wrapper.find('.header-container').css('height', self.options.wrapper.find('.header-container').outerHeight());
4454				}
4455
4456				// Check Sticky Header
4457				self.checkStickyHeader = function() {
4458					if ($window.scrollTop() >= parseInt(self.options.stickyStartAt)) {
4459						self.activateStickyHeader();
4460					} else {
4461						self.deactivateStickyHeader();
4462					}
4463				};
4464				
4465				// Activate Sticky Header
4466				self.activateStickyHeader = function() {
4467
4468					if ($window.width() < 992) {
4469						if (!self.options.stickyEnableOnMobile) {
4470							self.deactivateStickyHeader();
4471							return;
4472						}
4473					} else {
4474						if (sideHeader) {
4475							self.deactivateStickyHeader();
4476							return;
4477						}
4478					}
4479
4480					$html.addClass('sticky-header-active');
4481
4482					// Set Header Body Position Fixed and top value
4483					if( self.options.stickyStartAt ) {
4484						self.options.headerBody.css('position','fixed');
4485						self.options.headerBody.css('top', self.options.stickySetTop);	
4486					}
4487
4488					// Sticky Effect - Shrink
4489					if( self.options.wrapper.hasClass('header-effect-shrink') ) {
4490
4491						// If Header Top
4492						if( self.options.wrapper.find('.header-top').get(0) ) {
4493							self.options.wrapper.find('.header-top').css({
4494								height: 0,
4495								'min-height': 0,
4496								overflow: 'hidden'
4497							});
4498						}
4499
4500						// Header Container
4501						if( self.options.stickyHeaderContainerHeight ) {
4502							self.options.wrapper.find('.header-container').css({
4503								height: self.options.stickyHeaderContainerHeight,
4504								'min-height': 0
4505							});
4506						} else {
4507							self.options.wrapper.find('.header-container').css({
4508								height: (initialHeaderContainerHeight / 3) * 2, // one third of container height
4509								'min-height': 0
4510							});
4511						}
4512
4513					}
4514
4515					// Two Logos Effect
4516					if( self.options.wrapper.find('.header-logo img').length > 1 ) {
4517						var logo1 = $('#header .header-logo .logo-1'),
4518							logo2 = $('#header .header-logo .logo-2');
4519
4520						// First Logo
4521						logo1.parent().css('pointer-events','none');
4522						logo1.removeClass('active');
4523
4524						// Second Logo
4525						logo2.addClass('active');
4526
4527					}
4528
4529					// Set Logo Size and Position
4530					if (self.options.stickyChangeLogo) {
4531						self.changeLogo(true);
4532					}
4533
4534					// Change Logo Src
4535					if( self.options.wrapper.find('.header-logo img').attr('data-change-src') ) {
4536						self.changeLogoSrc(true);
4537					}
4538
4539					$.event.trigger({
4540						type: 'stickyHeader.activate'
4541					});
4542				};
4543
4544				// Deactivate Sticky Header
4545				self.deactivateStickyHeader = function() {
4546
4547					$html.removeClass('sticky-header-active');
4548
4549					self.options.headerBody.css('top', 0);
4550
4551					// Set Logo Size and Position
4552					if (self.options.stickyChangeLogo) {
4553						self.changeLogo(false);
4554					}
4555
4556					// Change Logo Src
4557					if( self.options.wrapper.find('.header-logo img').attr('data-change-src') ) {
4558						self.changeLogoSrc(false);
4559					}
4560
4561					// Reset Header Body Position
4562					self.options.headerBody.css('position', 'static');
4563
4564					// Sticky Effect - Shrink
4565					if( self.options.wrapper.hasClass('header-effect-shrink') ) {
4566
4567						// Boxed Layout
4568						if( $html.hasClass('boxed') ) {
4569
4570							// Set Header Body Position Absolute
4571							self.options.headerBody.css('position','absolute');
4572
4573							if( $window.scrollTop() > $('.body').offset().top ) {
4574								// Set Header Body Position Fixed
4575								self.options.headerBody.css('position','fixed');								
4576							}
4577
4578						} else {
4579							// Set Header Body Position Fixed
4580							self.options.headerBody.css('position','fixed');
4581						}
4582
4583						// If Header Top
4584						if( self.options.wrapper.find('.header-top').get(0) ) {
4585							self.options.wrapper.find('.header-top').css({
4586								height: initialHeaderTopHeight,
4587								overflow: 'visible'
4588							});
4589						}
4590
4591						// Header Container
4592						self.options.wrapper.find('.header-container').css({
4593							height: initialHeaderContainerHeight
4594						});
4595
4596					}
4597
4598					// Two Logos Effect
4599					if( self.options.wrapper.find('.header-logo img').length > 1 ) {
4600						var logo1 = $('#header .header-logo .logo-1'),
4601							logo2 = $('#header .header-logo .logo-2');
4602
4603						// First Logo
4604						logo1.parent().css('pointer-events','auto');
4605						logo1.addClass('active');
4606
4607						// Second Logo
4608						logo2.removeClass('active');
4609
4610					}
4611
4612					$.event.trigger({
4613						type: 'stickyHeader.deactivate'
4614					});
4615				};
4616
4617				// Always Sticky
4618				if (parseInt(self.options.stickyStartAt) <= 0) {
4619					self.activateStickyHeader();
4620				}
4621
4622				// Set Logo Size and Position
4623				if (self.options.stickyChangeLogo) {
4624
4625					var $logoWrapper = self.options.wrapper.find('.header-logo'),
4626						$logo = $logoWrapper.find('img'),
4627						logoWidth = $logo.attr('width'),
4628						logoHeight = $logo.attr('height'),
4629						logoSmallTop = parseInt($logo.attr('data-sticky-top') ? $logo.attr('data-sticky-top') : 0),
4630						logoSmallWidth = parseInt($logo.attr('data-sticky-width') ? $logo.attr('data-sticky-width') : 'auto'),
4631						logoSmallHeight = parseInt($logo.attr('data-sticky-height') ? $logo.attr('data-sticky-height') : 'auto');
4632
4633					self.changeLogo = function(activate) {
4634						if(activate) {
4635							
4636							$logo.css({
4637								'top': logoSmallTop,
4638								'width': logoSmallWidth,
4639								'height': logoSmallHeight
4640							});
4641
4642						} else {
4643							
4644							$logo.css({
4645								'top': 0,
4646								'width': logoWidth,
4647								'height': logoHeight
4648							});
4649
4650						}
4651					}
4652
4653				}
4654
4655				// Change Logo Src
4656				if( self.options.wrapper.find('.header-logo img').attr('data-change-src') ) {
4657					var $logo = self.options.wrapper.find('.header-logo img'),
4658						logoSrc = $logo.attr('src'),
4659						logoNewSrc = $logo.attr('data-change-src');
4660
4661					self.changeLogoSrc = function(activate) {
4662						if(activate) {
4663							$logo.attr('src', logoNewSrc);
4664						} else {
4665							$logo.attr('src', logoSrc);
4666						}
4667					}
4668				}
4669
4670				return this;
4671			},
4672
4673			events: function() {
4674				var self = this;
4675
4676				if (!this.options.stickyEnableOnBoxed && $('body').hasClass('boxed') || !this.options.stickyEnabled) {
4677					return this;
4678				}
4679
4680				if (!self.options.alwaysStickyEnabled) {
4681					$(window).on('scroll resize', function() {
4682						self.checkStickyHeader();
4683					});
4684				} else {
4685					self.activateStickyHeader();
4686				}
4687
4688				return this;
4689			}
4690
4691		}
4692
4693	});
4694
4695}).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.