PageSourceSearch

https://www.taylormccaslin.com/wp-content/themes/one/framework/assets/frontend/js/frontend.js?ver=7.0.3

js taylormccaslin.com collected 2026-10-04 00:16:32 UTC 21,005 bytes, 833 lines download raw bytes

1/**
2 * Frontend controller.
3 *
4 * This file is entitled to manage all the interactions in the frontend.
5 *
6 * ---
7 *
8 * The Happy Framework: WordPress Development Framework
9 * Copyright 2014, Andrea Gandino & Simone Maranzana
10 *
11 * Licensed under The MIT License
12 * Redistribuitions of files must retain the above copyright notice.
13 *
14 * @package Assets\Frontend\JS
15 * @author The Happy Bit <[email protected]>
16 * @copyright Copyright 2014, Andrea Gandino & Simone Maranzana
17 * @link http://
18 * @since The Happy Framework v 2.0
19 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
20 */
21
22/**
23 * Video shortcodes
24 * -----------------------------------------------------------------------------
25 */
26 window.thb_loaded_videos = 0;
27
28(function($) {
29	"use strict";
30
31	window.thb_video_holder = function( holder ) {
32		var context = holder.parent(),
33			context_height = context.outerHeight(),
34			context_width = context.outerWidth(),
35			ratio_x = holder.data( "ratio-x" ) !== undefined ? holder.data( "ratio-x" ) : 16,
36			ratio_y = holder.data( "ratio-y" ) !== undefined ? holder.data( "ratio-y" ) : 9,
37			y_alignment = holder.data( "y-alignment" ) !== undefined ? holder.data( "y-alignment" ) : "middle",
38			projected_width = 0,
39			projected_height = 0;
40
41		if ( context_height < ( context_width * ratio_y / ratio_x ) ) {
42			projected_height = context_width * ratio_y / ratio_x;
43
44			holder.css( "width", context_width );
45			holder.css( "height", projected_height );
46			holder.css( "margin-left", 0 );
47			holder.css( "margin-top", 0 );
48
49			if ( y_alignment == "middle" ) {
50				holder.css( "margin-top", ( context_height - projected_height ) / 2 );
51			}
52		}
53		else {
54			projected_width = context_height * ratio_x / ratio_y;
55
56			holder.css( "width", projected_width );
57			holder.css( "height", context_height );
58			holder.css( "margin-top", 0 );
59			holder.css( "margin-left", ( context_width - projected_width ) / 2 );
60		}
61	};
62
63	window.thb_video_holders = function( context, holder_selector ) {
64		if ( holder_selector === undefined ) {
65			holder_selector = '.thb-video-holder[data-fill="1"]';
66		}
67
68		$( holder_selector, context ).each(function(){
69			thb_video_holder( $( this ) );
70		});
71
72		$(window).on( "resize.thb_video_holders", function() {
73			$( holder_selector, context ).each(function(){
74				thb_video_holder( $( this ) );
75			});
76		}.debounce(200) );
77	};
78
79	window.thb_video_holders_off = function( context, holder_selector ) {
80		if ( holder_selector === undefined ) {
81			holder_selector = '.thb-video-holder[data-fill="1"]';
82		}
83
84		$( window ).off( ".thb_video_holders" );
85
86		$( holder_selector, context ).each(function(){
87			$( this ).removeAttr( "style" );
88		});
89	};
90
91	window.THB_Video = function( id, obj, type ) {
92		var self = this;
93
94		this.id = id;
95		this.obj = obj;
96		this.type = type;
97
98		/**
99		 * State
100		 */
101		this.state = function( code ) {
102			var state = "";
103
104			switch( code ) {
105				case 0:
106					state = "finished";
107					break;
108				case 1:
109					state = "playing";
110					break;
111				default:
112					state = "paused";
113					break;
114			}
115
116			return state;
117		};
118
119		/**
120		 * Videos loaded callback
121		 */
122		this.callbackCheck = function() {
123			window.thb_loaded_videos++;
124
125			this.obj.addClass("thb-video-loaded");
126			self.obj.trigger( "thb-video-loaded" );
127
128			if ( window.thb_loaded_videos === window.thb_total_videos ) {
129				$(window).trigger("thb-loaded-videos");
130			}
131		};
132
133		/**
134		 * Init
135		 */
136		this.init = function() {
137			var self = this;
138
139			switch( this.type ) {
140				case "youtube":
141					this.api = new YT.Player("youtube-" + this.id, {
142						events: {
143							onStateChange: function(state) {
144								self.obj.trigger( "change", [ self.state(state.data) ] );
145							},
146							onReady: function() {
147								self.callbackCheck();
148							}
149						}
150					});
151
152					this.play = function() { this.api.playVideo(); };
153					this.pause = function() { this.api.pauseVideo(); };
154					this.stop = function() { this.api.stopVideo(); };
155					this.isMuted = function() { return this.api.isMuted(); };
156					this.mute = function() { this.api.mute(); };
157					this.unMute = function() { this.api.unMute(); };
158					this.toggleVolume = function() {
159						if ( this.isMuted() ) {
160							this.unMute();
161						}
162						else {
163							this.mute();
164						}
165					};
166
167					break;
168				case "vimeo":
169					this.api = new Froogaloop(this.obj.get(0));
170
171					this.api.addEvent("ready", function(player_id) {
172						self.api.addEvent("play", function() {
173							self.obj.trigger("change", [self.state(1)]);
174						});
175						self.api.addEvent("pause", function() {
176							self.obj.trigger("change", [self.state(2)]);
177						});
178						self.api.addEvent("finish", function() {
179							self.obj.trigger("change", [self.state(0)]);
180						});
181
182						self.callbackCheck();
183					});
184
185					this.play = function() { this.api.api("play"); };
186					this.pause = function() { this.api.api("pause"); };
187					this.stop = function() { this.api.api("pause"); };
188					this.isMuted = function() {
189						var muted = false;
190
191						this.api.api( "getVolume", function( vol ) {
192							if ( vol == 0 ) {
193								muted = true;
194							}
195						} );
196
197						return muted;
198					};
199					this.mute = function() { self.api.api( "setVolume", 0 ); };
200					this.unMute = function() { self.api.api( "setVolume", 1 ); };
201					this.toggleVolume = function() {
202						var self = this;
203
204						this.api.api( "getVolume", function( vol ) {
205							if ( vol == 0 ) {
206								self.unMute();
207							}
208							else {
209								self.mute();
210							}
211						} );
212					};
213
214					break;
215				default:
216					this.api = this.obj.get(0);
217
218					this.api.addEventListener("loadedmetadata", function() {
219						self.obj.data('width', self.obj.get(0).videoWidth);
220						self.obj.data('height', self.obj.get(0).videoHeight);
221
222						if( self.obj.attr("autoplay") ) {
223							self.play();
224						}
225
226						self.callbackCheck();
227					}, false);
228					this.api.addEventListener("play", function() {
229						self.obj.trigger("change", [self.state(1)]);
230					}, false);
231					this.api.addEventListener("pause", function() {
232						self.obj.trigger("change", [self.state(2)]);
233					}, false);
234					this.api.addEventListener("ended", function() {
235						self.obj.trigger("change", [self.state(0)]);
236					}, false);
237
238					this.play = function() { this.api.play(); };
239					this.pause = function() { this.api.pause(); };
240					this.stop = function() { this.api.pause(); };
241					this.isMuted = function() { return self.obj.get( 0 ).muted; };
242					this.mute = function() { self.obj.get( 0 ).muted = true; };
243					this.unMute = function() { self.obj.get( 0 ).muted = false; };
244					this.toggleVolume = function() {
245						self.obj.get( 0 ).muted = ! self.obj.get( 0 ).muted;
246					};
247
248					break;
249			}
250		};
251
252		/**
253		 * Change
254		 */
255		this.change = function(state) {};
256
257		this.init();
258	};
259
260	window.thb_total_videos = 0;
261	window.thb_video_ids = 0;
262	window.thb_youtube_ready = false;
263
264	$(document).ready(function() {
265		window.thb_total_videos = $("iframe.thb-video-api, video.wp-video-shortcode").length;
266
267		if ( window.thb_total_videos == 0 ) {
268			$( window ).trigger( "thb-loaded-videos" );
269		}
270
271		$("iframe[src^='//player.vimeo'].thb-video-api").each(function() {
272			// window.thb_boot_iframe_video( $( this ) );
273			$(this).data( "player", new THB_Video( window.thb_video_ids++, $(this), 'vimeo' ) );
274		});
275
276		if( $("iframe[src*='youtu'].thb-video-api").length ) {
277			window.thb_load_youtube();
278		}
279
280		// $("iframe[src*='youtu'].thb-video-api").each(function() {
281		// 	window.thb_boot_iframe_video( $( this ) );
282		// 	// $(this).data( "player", new THB_Video( window.thb_video_ids++, $(this), 'youtube' ) );
283		// });
284
285		$("video.wp-video-shortcode").each(function() {
286			$(this).data( "player", new THB_Video( window.thb_video_ids++, $(this), 'selfhosted' ) );
287		});
288	});
289
290	window.thb_load_youtube = function() {
291		var tag = document.createElement("script");
292		tag.src = "//www.youtube.com/iframe_api";
293		var firstScriptTag = document.getElementsByTagName('script')[0];
294		firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
295	};
296
297	window.thb_boot_iframe_video = function( iframe ) {
298		var src = iframe.attr( "src" );
299
300		if ( ! src ) {
301			return;
302		}
303
304		if ( src.indexOf( "youtu" ) > -1 ) {
305			if ( window.thb_youtube_ready ) {
306				var id = window.thb_video_ids++;
307				iframe.attr( "id", "youtube-" + id );
308				iframe.data( "player", new THB_Video( id, iframe, 'youtube' ) );
309			}
310			else {
311				$( window ).on( "thb-youtube-ready", function() {
312					var id = window.thb_video_ids++;
313					iframe.attr( "id", "youtube-" + id );
314					iframe.data( "player", new THB_Video( id, iframe, 'youtube' ) );
315				} );
316
317				window.thb_load_youtube();
318			}
319		}
320		else if ( src.indexOf( "//player.vimeo" ) > -1 ) {
321			iframe.data( "player", new THB_Video( window.thb_video_ids++, iframe, 'vimeo' ) );
322		}
323	};
324
325	window.onYouTubeIframeAPIReady = function() {
326		window.thb_youtube_ready = true;
327		$( window ).trigger( "thb-youtube-ready" );
328
329		$("iframe[src*='youtu'].thb-video-api").each(function() {
330			// window.thb_boot_iframe_video( $( this ) );
331			var id = window.thb_video_ids++;
332
333			$(this).attr( "id", "youtube-" + id );
334			$(this).data( "player", new THB_Video( id, $(this), 'youtube' ) );
335		});
336	};
337})(jQuery);
338
339/**
340 * Translations
341 * -----------------------------------------------------------------------------
342 */
343(function($) {
344	"use strict";
345
346	$.thb.translate = function( key ) {
347		if( $.thb.translations[key] ) {
348			return $.thb.translations[key];
349		}
350
351		return key;
352	};
353})(jQuery);
354
355/**
356 * Remove empty paragraphs
357 * -----------------------------------------------------------------------------
358 */
359(function($) {
360	"use strict";
361
362	$( document ).ready( function() {
363		$('p')
364			.filter(function() {
365				return $.trim($(this).html()) === '';
366			})
367			.remove();
368	} );
369})(jQuery);
370
371/**
372 * ****************************************************************************
373 * THB menu
374 *
375 * $("#menu-container").menu();
376 * ****************************************************************************
377 */
378(function($) {
379	"use strict";
380
381	$.fn.menu = function(params) {
382
383		// Parameters
384		// --------------------------------------------------------------------
385		var settings = {
386			animate: true,
387			speed: 350,
388			display: 'block',
389			easing: 'linear',
390			openClass: 'current-menu-item',
391			megaMenu: {
392				fixed: true,
393				sentinel: null
394			},
395			availableRightSpaceClass: 'available-space-right',
396			availableLeftSpaceClass: 'available-space-left',
397			'showCallback': function() {},
398			'hideCallback': function() {}
399		};
400
401		// Parameters
402		$.extend(settings, params);
403
404		// Menu instance
405		// --------------------------------------------------------------------
406		var instance = {
407			el: null,
408
409			destroy: function() {
410				$( instance.el ).find( "*" ).off( ".thb_menu" );
411				$( instance.el ).find( "ul.sub-menu" ).removeAttr( "style" );
412				$( window ).off( ".thb_menu" );
413			},
414
415			init: function( subMenu, item, root ) {
416				instance.el = root;
417
418				item.removeClass( settings.availableRightSpaceClass );
419				item.removeClass( settings.availableLeftSpaceClass );
420
421				// if ( item.is( ".thb-is-mega" ) ) {
422				// 	return;
423				// }
424
425				var itemOffset = item.offset().left;
426
427				if ( item.parent().hasClass( "sub-menu" ) ) {
428					itemOffset += item.outerWidth();
429				}
430
431				var subMenuWidth = subMenu.outerWidth(),
432					availableRightSpace = $( window ).width() - itemOffset,
433					availableLeftSpace = itemOffset;
434
435				if ( availableRightSpace > subMenuWidth ) {
436					item.addClass( settings.availableRightSpaceClass );
437				}
438
439				if ( availableLeftSpace > subMenuWidth ) {
440					item.addClass( settings.availableLeftSpaceClass );
441				}
442			},
443
444			showMegaSubMenu: function( subMenu, item ) {
445				if ( settings.megaMenu && settings.megaMenu.fixed ) {
446					subMenu
447						.css({
448							'top': item.offset().top + item.outerHeight()
449						});
450				}
451
452				this.showSubMenu( subMenu, item );
453			},
454
455			showSubMenu: function( subMenu, item ) {
456				item.addClass( settings.openClass );
457
458				instance.init( subMenu, item, instance.el );
459
460				var css_start = {
461						opacity: 0,
462						display: settings.display
463					},
464					css_end = {
465						opacity: 1
466					};
467
468				if ( settings.animate ) {
469					subMenu
470						.stop(true, true)
471						.css( css_start )
472						.animate( css_end, settings.speed, settings.easing, function() {
473							settings.showCallback();
474						});
475				}
476				else {
477					subMenu.css( "display", settings.display );
478					settings.showCallback();
479				}
480			},
481
482			hideSubMenu: function( subMenu, item ) {
483				item.removeClass( settings.openClass );
484
485				var css_end = {
486						opacity: 0
487					};
488
489				if ( settings.animate ) {
490					subMenu
491						.stop(true, true)
492						.animate( css_end, settings.speed / 2, settings.easing, function() {
493							$(this).hide();
494							settings.hideCallback();
495						} );
496				}
497				else {
498					subMenu.hide();
499					settings.hideCallback();
500				}
501			}
502		};
503
504		return this.each(function() {
505			var self = this,
506				menuContainer = $(this),
507				menu = menuContainer.find("> ul"),
508				menuItems = menu.find("> li"),
509				subMenuItems = menuItems.find('li').andSelf();
510
511			$( this ).data( "thb-menu", instance );
512
513			menuItems.each(function() {
514				if ( $( this ).parents( '.thb-is-mega' ).length ) {
515				// if ( $( this ).is( '.thb-is-mega' ) || $( this ).parents( '.thb-is-mega' ).length ) {
516					return;
517				}
518
519				if ( settings.megaMenu && settings.megaMenu.fixed && $( this ).hasClass( "thb-is-mega" ) ) {
520					$( this ).addClass( 'thb-megamenu-fixed' );
521				}
522
523				$(this).find('> a').addClass('needsclick');
524
525				var subMenu = $(this).find('> ul');
526
527				if( subMenu.length ) {
528					subMenu.css({
529						display: 'none'
530					});
531				}
532			});
533
534			// Binding events
535			subMenuItems.each(function() {
536				var item = $(this),
537					subMenu = item.find("> ul");
538
539				if ( item.parents( '.thb-is-mega' ).length ) {
540					return;
541				}
542
543				if( subMenu.length ) {
544					item
545						.find('> a')
546						.addClass('w-sub needsclick');
547
548					instance.init( subMenu, item, self );
549
550					item
551						.on( "mouseenter.thb_menu", function() {
552							if ( item.hasClass( "thb-is-mega" ) ) {
553								instance.showMegaSubMenu( subMenu, $(this) );
554							}
555							else {
556								instance.showSubMenu( subMenu, $(this) );
557							}
558						})
559						.on( "mouseleave.thb_menu", function() {
560							instance.hideSubMenu( subMenu, $(this) );
561						});
562
563					$( window ).on( "resize.thb_menu", function() {
564						instance.init( subMenu, item, self );
565					} );
566				}
567			});
568		});
569
570	};
571
572})(jQuery);
573
574/**
575 * Scroll in page.
576 */
577;( function( $ ) {
578	window.thb_scroll_in_page = function( smoothScrollSelectors, scrollOptions, offset, preScrollCallback ) {
579		if ( offset === undefined ) {
580			offset = 0;
581		}
582
583		scrollOptions = $.extend( {
584			speed: 350,
585			easing: "easeInOutCubic"
586		}, scrollOptions );
587
588		$( document ).on( "click", smoothScrollSelectors, function() {
589			var href = $( this ).attr( "href" ),
590				target = $( this ).attr( "target" );
591
592			if ( href.indexOf( "#" ) > -1 ) {
593				var url = href.split("#"),
594					current_url = window.location.href.split("#"),
595					is_same_page = url[0] == "" || ( url[0] != "" && url[0] == current_url[0] ),
596					href = "#" + url[1];
597
598				if ( is_same_page ) {
599					if ( ! $( href ).length ) {
600						return false;
601					}
602
603					if ( preScrollCallback !== undefined ) {
604						preScrollCallback();
605					}
606
607					$.scrollTo( $( href ), scrollOptions.speed, {
608						easing: scrollOptions.easing,
609						offset: ( offset ) * -1
610					} );
611
612					return false;
613				}
614				else {
615					return true;
616				}
617			}
618		} );
619	}
620} )( jQuery );
621
622/**
623 * Fullscreen.
624 */
625;( function( $ ) {
626	window.thb_fullscreen_check = function() {
627		return document.documentElement.requestFullscreen || document.documentElement.mozRequestFullScreen || document.documentElement.webkitRequestFullScreen || document.documentElement.msRequestFullscreen;
628	};
629
630	window.thb_is_fullscreen = function() {
631		return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement;
632	};
633
634	window.thb_exit_fullscreen = function() {
635		if ( document.exitFullscreen ) {
636			document.exitFullscreen();
637		}
638		else if ( document.msExitFullscreen ) {
639			document.msExitFullscreen();
640		}
641		else if ( document.mozCancelFullScreen ) {
642			document.mozCancelFullScreen();
643		}
644		else if ( document.webkitExitFullscreen ) {
645			document.webkitExitFullscreen();
646		}
647	};
648
649	window.thb_go_fullscreen = function( elem ) {
650		elem = $( elem ).get( 0 );
651
652		if ( elem.requestFullscreen ) {
653			elem.requestFullscreen();
654		}
655		else if ( elem.msRequestFullscreen ) {
656			elem.msRequestFullscreen();
657		}
658		else if ( elem.mozRequestFullScreen ) {
659			elem.mozRequestFullScreen();
660		}
661		else if ( elem.webkitRequestFullscreen ) {
662			elem.webkitRequestFullscreen();
663		}
664	};
665
666	window.thb_fullscreen_transition = function( on ) {
667		if ( on ) {
668			$( "html" ).addClass( "thb-full-screen" );
669		}
670		else {
671			$( "html" ).removeClass( "thb-full-screen" );
672		}
673	};
674
675	if ( document.addEventListener ) {
676		document.addEventListener( "fullscreenchange", function () {
677			thb_fullscreen_transition( document.fullscreen );
678		}, false );
679
680		document.addEventListener( "mozfullscreenchange", function () {
681			thb_fullscreen_transition( document.mozFullScreen );
682		}, false );
683
684		document.addEventListener( "webkitfullscreenchange", function () {
685			thb_fullscreen_transition( document.webkitIsFullScreen );
686		}, false );
687
688		document.addEventListener( "msfullscreenchange", function () {
689			thb_fullscreen_transition( document.msFullscreenElement );
690		}, false );
691	}
692	else {
693		document.attachEvent( "fullscreenchange", function () {
694			thb_fullscreen_transition( document.fullscreen );
695		} );
696
697		document.attachEvent( "mozfullscreenchange", function () {
698			thb_fullscreen_transition( document.mozFullScreen );
699		} );
700
701		document.attachEvent( "webkitfullscreenchange", function () {
702			thb_fullscreen_transition( document.webkitIsFullScreen );
703		} );
704
705		document.attachEvent( "msfullscreenchange", function () {
706			thb_fullscreen_transition( document.msFullscreenElement );
707		} );
708	}
709} )( jQuery );
710
711/**
712 * Parallax.
713 */
714;( function( $ ) {
715	var $window = $( window ),
716		windowHeight = $window.height();
717
718	var THB_Parallax = function( $el, options ) {
719		var parallax = this;
720
721		options = $.extend( {}, {
722			speed: 0.6,
723			xpos: "50%"
724		}, options );
725
726		this.update = function() {
727			var offset = $el.offset().top,
728				pos = $window.scrollTop(),
729				height = $el.outerHeight();
730
731			if ( offset + height < pos || offset > pos + windowHeight ) {
732				return;
733			}
734
735			$el.css( "backgroundPosition", options.xpos + " " + Math.round( ( offset - pos ) * options.speed ) + "px" );
736		};
737
738		$window.on( "scroll", this.update );
739		$window.on( "resize", function() {
740			windowHeight = $window.height();
741			parallax.update();
742		} );
743
744		this.update();
745	};
746
747	$.fn.thbParallax = function( options ) {
748		return this.each( function() {
749			if ( ! $( this ).data( "thbParallax" ) ) {
750				$( this ).data( "thbParallax", new THB_Parallax( $( this ), options ) );
751			}
752		} );
753	};
754} )( jQuery );
755
756/**
757 * Scroll to include.
758 */
759;( function( $ ) {
760	$.scrollToInclude = function( element, options ) {
761		element = $( element );
762
763		options = $.extend( {
764			speed: 350,
765			easing: "easeInOutCubic",
766			offset: 0
767		}, options );
768
769		var element_height = element.outerHeight(),
770			element_offset = element.position().top,
771			endOfScroll = parseInt( element_offset + element_height + options.offset, 10 );
772
773		endOfScroll -= $( window ).height();
774
775		$.scrollTo( endOfScroll, options.speed, {
776			easing: options.easing,
777			offset: ( options.offset ) * -1
778		} );
779	};
780} )( jQuery );
781
782/**
783 * Frontend conditional controller.
784 */
785;( function( $ ) {
786	if( ! $.thb ) {
787		$.thb = {};
788	}
789
790	$.thb.wp = {
791		is_body_class: function( classname ) {
792			return $( "body" ).hasClass( classname );
793		},
794		is_post_type: function( post_type ) {
795			return $( "body" ).hasClass( "single-" + post_type );
796		},
797		is_single_post: function() {
798			return $.thb.wp.is_post_type( "post" );
799		},
800		is_page: function( arg ) {
801			if ( $( "body" ).hasClass( "page" ) ) {
802				if ( typeof arg === 'string' ) {
803					// Template
804					arg = arg.replace( /./g, '-' );
805					return $( "body" ).hasClass( "page-template-" + arg );
806				}
807				else if ( typeof arg === 'number' ) {
808					// Page ID
809					return $( "body" ).hasClass( "page-id-" + arg );
810				}
811			}
812
813			return false;
814		},
815		is_mobile: function() {
816			return $( "body" ).hasClass( "thb-mobile" );
817		},
818		is_desktop: function() {
819			return $( "body" ).hasClass( "thb-desktop" );
820		},
821		is_larger_than: function( width ) {
822			return Math.max(document.documentElement.clientWidth, window.innerWidth || 0) >= width;
823		},
824		is_smaller_than: function( width ) {
825			return Math.max(document.documentElement.clientWidth, window.innerWidth || 0) <= width;
826		},
827		is_between: function( min, max ) {
828			var viewport = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
829
830			return viewport >= min && viewport <= max;
831		}
832	}
833} )( 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.