PageSourceSearch

https://meridiansolutions.com.sg/js/theme.js

js meridiansolutions.com.sg collected 2026-09-26 08:14:24 UTC 59,413 bytes, 2,906 lines download raw bytes

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