PageSourceSearch

https://extension.org/wp-content/themes/enfold/config-templatebuil…/slideshow/slideshow-video.js?ver=5.7

js extension.org collected 2026-09-24 08:26:36 UTC 23,991 bytes, 910 lines download raw bytes

1// -------------------------------------------------------------------------------------------
2//
3// AVIA VIDEO API - make sure that youtube, vimeo and html 5 use the same interface
4//
5// requires froogaloop vimeo library and youtube iframe api (yt can be loaded async)
6//
7// -------------------------------------------------------------------------------------------
8
9
10(function($)
11{
12    "use strict";
13
14	$.AviaVideoAPI  =  function(options, video, option_container)
15	{
16		this.videoElement = video;
17
18		// actual video element. either iframe or video
19		this.$video	= $( video );
20
21		// container where the AviaVideoAPI object will be stored as data, and that can receive events like play, pause etc
22		// also the container that allows to overwrite javacript options by adding html data- attributes
23		this.$option_container = option_container ? $( option_container ) : this.$video;
24
25		// button to click to actually start the loading process of the video
26		this.load_btn = this.$option_container.find('.av-click-to-play-overlay');
27
28		// contains video list
29		this.video_wrapper = this.$video.parents('ul').eq(0);
30
31		//check if we should load immediately or on click
32		this.lazy_load = this.video_wrapper.hasClass('av-show-video-on-click') ? true : false;
33
34		//mobile device?
35		this.isMobile = $.avia_utilities.isMobile;
36
37		//iamge fallback use
38		this.fallback = this.isMobile ? this.$option_container.is('.av-mobile-fallback-image') : false;
39
40		if( this.fallback )
41		{
42			return;
43		}
44
45		// set up the whole api object
46		this._init( options );
47	};
48
49	$.AviaVideoAPI.defaults  = {
50
51		loop: false,
52		mute: false,
53		controls: false,
54		events: 'play pause mute unmute loop toggle reset unload'
55
56	};
57
58	$.AviaVideoAPI.apiFiles =
59    {
60    	youtube : {loaded: false, src: 'https://www.youtube.com/iframe_api' }
61    };
62
63    $.AviaVideoAPI.players =
64    {
65
66    };
67
68  	$.AviaVideoAPI.prototype =
69    {
70    	_init: function( options )
71    	{
72			// set slider options
73			this.options = this._setOptions(options);
74
75			// info which video service we are using: html5, vimeo or youtube
76			this.type = this._getPlayerType();
77
78			this.player = false;
79
80			// store the player object to the this.player variable created by one of the APIs (mediaelement, youtube, vimeo)
81			this._bind_player();
82
83			// set to true once the events are bound so it doesnt happen a second time by accident or racing condition
84			this.eventsBound = false;
85
86			// info if the video is playing
87			this.playing = false;
88
89			//set css class that video is currently not playing
90			this.$option_container.addClass('av-video-paused');
91
92			//play pause indicator
93			this.pp = $.avia_utilities.playpause(this.$option_container);
94    	},
95
96
97    	//set the video options by first merging the default options and the passed options, then checking the video element if any data attributes overwrite the option set
98    	_setOptions: function(options)
99		{
100			var newOptions 	= $.extend( true, {}, $.AviaVideoAPI.defaults, options ),
101				htmlData 	= this.$option_container.data(),
102				i 			= "";
103
104			//overwritte passed option set with any data properties on the html element
105			for( i in htmlData )
106			{
107				if( htmlData.hasOwnProperty(i) && (typeof htmlData[i] === "string" || typeof htmlData[i] === "number" || typeof htmlData[i] === "boolean") )
108				{
109					newOptions[i] = htmlData[i];
110				}
111			}
112
113			return newOptions;
114		},
115
116		//get the player type
117		_getPlayerType: function()
118		{
119			var vid_src = this.$video.get(0).src || this.$video.data('src');
120
121			if( this.$video.is('video') )
122			{
123				return 'html5';
124			}
125
126			if( this.$video.is('.av_youtube_frame') )
127			{
128				return 'youtube';
129			}
130
131			if( vid_src.indexOf('vimeo.com') != -1 )
132			{
133				return 'vimeo';
134			}
135			if( vid_src.indexOf('youtube.com') != -1)
136			{
137				return 'youtube';
138			}
139		},
140
141		_bind_player: function()
142		{
143			var _self = this;
144
145			//	check if videos are disabled by user setting via cookie - or user must opt in.
146			var cookie_check = $('html').hasClass('av-cookies-needs-opt-in') || $('html').hasClass('av-cookies-can-opt-out');
147			var allow_continue = true;
148			var silent_accept_cookie = $('html').hasClass('av-cookies-user-silent-accept');
149			var self_hosted = 'html5' == this.type;
150
151			if( cookie_check && ! silent_accept_cookie && ! self_hosted )
152			{
153				if( ! document.cookie.match(/aviaCookieConsent/) || $('html').hasClass('av-cookies-session-refused') )
154				{
155					allow_continue = false;
156				}
157				else
158				{
159					if( ! document.cookie.match(/aviaPrivacyRefuseCookiesHideBar/) )
160					{
161						allow_continue = false;
162					}
163					else if( ! document.cookie.match(/aviaPrivacyEssentialCookiesEnabled/) )
164					{
165						allow_continue = false;
166					}
167					else if( document.cookie.match(/aviaPrivacyVideoEmbedsDisabled/) )
168					{
169						allow_continue = false;
170					}
171				}
172			}
173
174			//	allow 3-rd party plugins to hook (see enfold\config-cookiebot\cookiebot.js)
175			if( window['wp'] && wp.hooks )
176			{
177				allow_continue = wp.hooks.applyFilters( 'aviaCookieConsent_allow_continue', allow_continue );
178			}
179
180			if( ! allow_continue )
181			{
182				this._use_external_link();
183				return;
184			}
185
186			if(this.lazy_load && this.load_btn.length && this.type != "html5")
187			{
188				this.$option_container.addClass('av-video-lazyload');
189
190				this.load_btn.on('click', function()
191				{
192					_self.load_btn.remove();
193					_self._setPlayer();
194				});
195			}
196			else
197			{
198				this.lazy_load = false;
199				this._setPlayer();
200			}
201		},
202
203		//if the user has disabled video slides via cookie a click event will open the video externally
204		_use_external_link: function()
205		{
206			//display the play button no matter what
207			this.$option_container.addClass('av-video-lazyload');
208
209			this.load_btn.on('click', function(e)
210			{
211				if (e.originalEvent === undefined) return; //human click only
212
213				var src_url = $(this).parents('.avia-slide-wrap').find('div[data-original_url]').data('original_url');
214				if( src_url ) window.open(src_url , '_blank');
215			});
216		},
217
218		//get the player object
219		_setPlayer: function()
220		{
221			var _self = this;
222
223			switch( this.type )
224			{
225				case "html5":
226
227					this.player = this.$video.data('mediaelementplayer');
228
229					//apply fallback. sometimes needed for safari
230					if( ! this.player )
231					{
232						this.$video.data('mediaelementplayer', $.AviaVideoAPI.players[ this.$video.attr('id').replace(/_html5/,'') ] );
233						this.player = this.$video.data('mediaelementplayer');
234					}
235
236					this._playerReady();
237					break;
238
239				case "vimeo":
240
241					//we need to create an iframe and append it to the html first
242					var ifrm 	= document.createElement("iframe");
243					var $ifrm	= $( ifrm );
244
245					//note: unmuted vimeo videos in chrome do often times not work due to chrome blocking them
246					ifrm.onload = function()
247					{
248						_self.player = Froogaloop( ifrm );
249						_self._playerReady();
250						_self.$option_container.trigger('av-video-loaded');
251					};
252
253					ifrm.setAttribute("src", this.$video.data('src') );
254
255					//we replace the old html structure with the iframe
256					$ifrm.insertAfter( this.$video );
257					this.$video.remove();
258					this.$video = ifrm;
259					break;
260
261				case "youtube":
262
263					this._getAPI(this.type);
264					$('body').on('av-youtube-iframe-api-loaded', function(){ _self._playerReady(); });
265					break;
266			}
267		},
268
269		_getAPI: function( api )
270		{
271			//make sure the api file is loaded only once
272			if($.AviaVideoAPI.apiFiles[api].loaded === false)
273			{
274				$.AviaVideoAPI.apiFiles[api].loaded = true;
275				//load the file async
276				var tag		= document.createElement('script'),
277					first	= document.getElementsByTagName('script')[0];
278
279				tag.src = $.AviaVideoAPI.apiFiles[api].src;
280      			first.parentNode.insertBefore(tag, first);
281			}
282		},
283
284		//wait for player to be ready, then bind events
285		_playerReady: function()
286		{
287			var _self = this;
288
289			this.$option_container.on('av-video-loaded', function(){ _self._bindEvents(); });
290
291			switch(this.type)
292			{
293				case "html5":
294					this.$video.on( 'av-mediajs-loaded', function(){ _self.$option_container.trigger('av-video-loaded'); } );
295					this.$video.on( 'av-mediajs-ended' , function(){ _self.$option_container.trigger('av-video-ended');  } );
296					break;
297				case "vimeo":
298					//finish event must be applied after ready event for firefox
299					_self.player.addEvent('ready',  function()
300					{
301						_self.$option_container.trigger('av-video-loaded');
302						_self.player.addEvent('finish', function(){ _self.$option_container.trigger('av-video-ended');  });
303					});
304					break;
305
306				case "youtube":
307
308					var params = _self.$video.data();
309
310					if( _self._supports_video() )
311					{
312						params.html5 = 1;
313					}
314
315					_self.player = new YT.Player(_self.$video.attr('id'),
316					{
317						videoId: params.videoid,
318						height: _self.$video.attr('height'),
319						width: _self.$video.attr('width'),
320						playerVars: params,
321						events: {
322						'onReady': function(){ _self.$option_container.trigger('av-video-loaded'); },
323						'onError': function(player){ $.avia_utilities.log('YOUTUBE ERROR:', 'error', player); },
324						'onStateChange': function(event){
325							if (event.data === YT.PlayerState.ENDED)
326							{
327								var command = _self.options.loop != false ? 'loop' : 'av-video-ended';
328								_self.$option_container.trigger(command);
329							}
330						  }
331						}
332					});
333					break;
334			}
335
336			//fallback always trigger after 2 seconds
337			setTimeout(function()
338			{
339				if(_self.eventsBound == true || typeof _self.eventsBound == 'undefined' || _self.type == 'youtube' )
340				{
341					return;
342				}
343
344				$.avia_utilities.log('Fallback Video Trigger "' + _self.type + '":', 'log', _self );
345
346				_self.$option_container.trigger('av-video-loaded');
347
348			}, 2000 );
349		},
350
351		//bind events we should listen to, to the player
352		_bindEvents: function()
353		{
354			if( this.eventsBound == true || typeof this.eventsBound == 'undefined')
355			{
356				return;
357			}
358
359			var _self = this, volume = 'unmute';
360
361			this.eventsBound = true;
362
363			this.$option_container.on(this.options.events, function(e)
364			{
365				_self.api(e.type);
366			});
367
368			if( !_self.isMobile )
369			{
370				//set up initial options
371				if( this.options.mute != false )
372				{
373					volume = "mute";
374				}
375
376				if( this.options.loop != false )
377				{
378					_self.api('loop');
379				}
380
381				_self.api(volume);
382			}
383
384			//set timeout to prevent racing conditions with other scripts
385			setTimeout( function()
386			{
387				_self.$option_container.trigger('av-video-events-bound').addClass('av-video-events-bound');
388			}, 50 );
389		},
390
391
392		_supports_video: function()
393		{
394		  return !!document.createElement('video').canPlayType;
395		},
396
397
398		/************************************************************************
399		PUBLIC Methods
400		*************************************************************************/
401
402
403		api: function( action )
404		{
405			//commands on mobile can not be executed if the player was not started manually
406			if(this.isMobile && !this.was_started()) return;
407
408			// prevent calling of unbound function
409			if(this.options.events.indexOf(action) === -1) return;
410
411			// broadcast that the command was executed
412			this.$option_container.trigger('av-video-'+action+'-executed');
413
414			// console.log("video player api action: " + action);
415
416			// calls the function based on action. eg: _html5_play()
417			if(typeof this[ '_' + this.type + '_' + action] == 'function')
418			{
419				this[ '_' + this.type + '_' + action].call(this);
420			}
421
422			//call generic function eg: _toggle() or _play()
423			if(typeof this[ '_' + action] == 'function')
424			{
425				this[ '_' + action].call(this);
426			}
427		},
428
429		was_started: function()
430		{
431			if(!this.player) return false;
432
433			switch(this.type)
434			{
435				case "html5":
436					if( this.player.getCurrentTime() > 0 )
437					{
438						return true;
439					}
440					break;
441
442				case "vimeo":
443					if( this.player.api('getCurrentTime') > 0 )
444					{
445						return true;
446					}
447					break;
448
449				case "youtube":
450					if( this.player.getPlayerState() !== -1 )
451					{
452						return true;
453					}
454					break;
455			}
456
457			return false;
458		},
459
460		/************************************************************************
461		Generic Methods, are always executed and usually set variables
462		*************************************************************************/
463		_play: function()
464		{
465			this.playing = true;
466			this.$option_container.addClass('av-video-playing').removeClass('av-video-paused');
467		},
468
469		_pause: function()
470		{
471			this.playing = false;
472			this.$option_container.removeClass('av-video-playing').addClass('av-video-paused');
473		},
474
475		_loop: function()
476		{
477			this.options.loop = true;
478		},
479
480		_toggle: function( )
481		{
482			var command = this.playing == true ? 'pause' : 'play';
483
484			this.api(command);
485			this.pp.set(command);
486		},
487
488
489		/************************************************************************
490		VIMEO Methods
491		*************************************************************************/
492
493		_vimeo_play: function( )
494		{
495			this.player.api('play');
496		},
497
498		_vimeo_pause: function( )
499		{
500			this.player.api('pause');
501		},
502
503		_vimeo_mute: function( )
504		{
505			this.player.api('setVolume', 0);
506		},
507
508		_vimeo_unmute: function( )
509		{
510			this.player.api('setVolume', 0.7);
511		},
512
513		_vimeo_loop: function( )
514		{
515			// currently throws error, must be set in iframe
516			// this.player.api('setLoop', true);
517		},
518
519		_vimeo_reset: function( )
520		{
521			this.player.api('seekTo',0);
522		},
523
524		_vimeo_unload: function()
525		{
526			this.player.api('unload');
527		},
528
529		/************************************************************************
530		YOUTUBE Methods
531		*************************************************************************/
532
533		_youtube_play: function( )
534		{
535			this.player.playVideo();
536		},
537
538		_youtube_pause: function( )
539		{
540			this.player.pauseVideo();
541		},
542
543		_youtube_mute: function( )
544		{
545			this.player.mute();
546		},
547
548		_youtube_unmute: function( )
549		{
550			this.player.unMute();
551		},
552
553		_youtube_loop: function( )
554		{
555			// does not work properly with iframe api. needs to manual loop on "end" event
556			// this.player.setLoop(true);
557			if(this.playing == true) this.player.seekTo(0);
558		},
559
560		_youtube_reset: function( )
561		{
562			this.player.stopVideo();
563		},
564
565		_youtube_unload: function()
566		{
567			this.player.clearVideo();
568		},
569
570		/************************************************************************
571		HTML5 Methods
572		*************************************************************************/
573
574		_html5_play: function( )
575		{
576			//disable stoping of other videos in case the user wants to run section bgs
577			if(this.player)
578			{
579				this.player.options.pauseOtherPlayers = false;
580				this.player.play();
581			}
582
583		},
584
585		_html5_pause: function( )
586		{
587			if(this.player) this.player.pause();
588		},
589
590		_html5_mute: function( )
591		{
592			if(this.player) this.player.setMuted(true);
593		},
594
595		_html5_unmute: function( )
596		{
597			if(this.player) this.player.setVolume(0.7);
598		},
599
600		_html5_loop: function( )
601		{
602			if(this.player) this.player.options.loop = true;
603		},
604
605		_html5_reset: function( )
606		{
607			if(this.player) this.player.setCurrentTime(0);
608		},
609
610		_html5_unload: function()
611		{
612			this._html5_pause();
613			this._html5_reset();
614		}
615    };
616
617    //simple wrapper to call the api. makes sure that the api data is not applied twice
618    $.fn.aviaVideoApi = function( options , apply_to_parent)
619    {
620    	return this.each( function()
621    	{
622    		// by default save the object as data to the initial video.
623    		// in the case of slideshows its more benefitial to save it to a parent element (eg: the slide)
624    		var applyTo = this;
625
626    		if( apply_to_parent )
627    		{
628    			applyTo = $(this).parents(apply_to_parent).get(0);
629    		}
630
631    		var self = $.data( applyTo, 'aviaVideoApi' );
632
633    		if( ! self )
634    		{
635    			self = $.data( applyTo, 'aviaVideoApi', new $.AviaVideoAPI( options, this, applyTo ) );
636    		}
637    	});
638    };
639
640})( jQuery );
641
642window.onYouTubeIframeAPIReady = function(){ jQuery('body').trigger('av-youtube-iframe-api-loaded'); };
643
644
645// Init style shamelessly stolen from jQuery http://jquery.com
646// min version: https://f.vimeocdn.com/js/froogaloop2.min.js
647var Froogaloop = (function(){
648    // Define a local copy of Froogaloop
649    function Froogaloop(iframe) {
650        // The Froogaloop object is actually just the init constructor
651        return new Froogaloop.fn.init(iframe);
652    }
653
654    var eventCallbacks = {},
655        hasWindowEvent = false,
656        isReady = false,
657        slice = Array.prototype.slice,
658        playerOrigin = '*';
659
660    Froogaloop.fn = Froogaloop.prototype = {
661        element: null,
662
663        init: function(iframe) {
664            if (typeof iframe === "string") {
665                iframe = document.getElementById(iframe);
666            }
667
668            this.element = iframe;
669
670            return this;
671        },
672
673        /*
674         * Calls a function to act upon the player.
675         *
676         * @param {string} method The name of the Javascript API method to call. Eg: 'play'.
677         * @param {Array|Function} valueOrCallback params Array of parameters to pass when calling an API method
678         *                                or callback function when the method returns a value.
679         */
680        api: function(method, valueOrCallback) {
681            if (!this.element || !method) {
682                return false;
683            }
684
685            var self = this,
686                element = self.element,
687                target_id = element.id !== '' ? element.id : null,
688                params = !isFunction(valueOrCallback) ? valueOrCallback : null,
689                callback = isFunction(valueOrCallback) ? valueOrCallback : null;
690
691            // Store the callback for get functions
692            if (callback) {
693                storeCallback(method, callback, target_id);
694            }
695
696            postMessage(method, params, element);
697            return self;
698        },
699
700        /*
701         * Registers an event listener and a callback function that gets called when the event fires.
702         *
703         * @param eventName (String): Name of the event to listen for.
704         * @param callback (Function): Function that should be called when the event fires.
705         */
706        addEvent: function(eventName, callback) {
707            if (!this.element) {
708                return false;
709            }
710
711            var self = this,
712                element = self.element,
713                target_id = element.id !== '' ? element.id : null;
714
715
716            storeCallback(eventName, callback, target_id);
717
718            // The ready event is not registered via postMessage. It fires regardless.
719            if (eventName != 'ready') {
720                postMessage('addEventListener', eventName, element);
721            }
722            else if (eventName == 'ready' && isReady) {
723                callback.call(null, target_id);
724            }
725
726            return self;
727        },
728
729        /*
730         * Unregisters an event listener that gets called when the event fires.
731         *
732         * @param eventName (String): Name of the event to stop listening for.
733         */
734        removeEvent: function(eventName) {
735            if (!this.element) {
736                return false;
737            }
738
739            var self = this,
740                element = self.element,
741                target_id = element.id !== '' ? element.id : null,
742                removed = removeCallback(eventName, target_id);
743
744            // The ready event is not registered
745            if (eventName != 'ready' && removed) {
746                postMessage('removeEventListener', eventName, element);
747            }
748        }
749    };
750
751    /**
752     * Handles posting a message to the parent window.
753     *
754     * @param method (String): name of the method to call inside the player. For api calls
755     * this is the name of the api method (api_play or api_pause) while for events this method
756     * is api_addEventListener.
757     * @param params (Object or Array): List of parameters to submit to the method. Can be either
758     * a single param or an array list of parameters.
759     * @param target (HTMLElement): Target iframe to post the message to.
760     */
761    function postMessage(method, params, target) {
762        if (!target.contentWindow.postMessage) {
763            return false;
764        }
765
766        var data = JSON.stringify({
767            method: method,
768            value: params
769        });
770
771        target.contentWindow.postMessage(data, playerOrigin);
772    }
773
774    /**
775     * Event that fires whenever the window receives a message from its parent
776     * via window.postMessage.
777     */
778    function onMessageReceived(event)
779	{
780
781        var data, method;
782
783        try {
784            data = JSON.parse(event.data);
785            method = data.event || data.method;
786        }
787        catch(e)  {
788            //fail silently... like a ninja!
789        }
790
791        if (method == 'ready' && !isReady) {
792            isReady = true;
793        }
794
795        // Handles messages from the vimeo player only
796        if (!(/^https?:\/\/player.vimeo.com/).test(event.origin)) {
797            return false;
798        }
799
800        if (playerOrigin === '*') {
801            playerOrigin = event.origin;
802        }
803        var value = data.value,
804            eventData = data.data,
805            target_id = target_id === '' ? null : data.player_id,
806
807            callback = getCallback(method, target_id),
808            params = [];
809
810        if (!callback) {
811            return false;
812        }
813
814        if (value !== undefined) {
815            params.push(value);
816        }
817
818        if (eventData) {
819            params.push(eventData);
820        }
821
822        if (target_id) {
823            params.push(target_id);
824        }
825
826        return params.length > 0 ? callback.apply(null, params) : callback.call();
827    }
828
829
830    /**
831     * Stores submitted callbacks for each iframe being tracked and each
832     * event for that iframe.
833     *
834     * @param eventName (String): Name of the event. Eg. api_onPlay
835     * @param callback (Function): Function that should get executed when the
836     * event is fired.
837     * @param target_id (String) [Optional]: If handling more than one iframe then
838     * it stores the different callbacks for different iframes based on the iframe's
839     * id.
840     */
841    function storeCallback(eventName, callback, target_id) {
842        if (target_id) {
843            if (!eventCallbacks[target_id]) {
844                eventCallbacks[target_id] = {};
845            }
846            eventCallbacks[target_id][eventName] = callback;
847        }
848        else {
849            eventCallbacks[eventName] = callback;
850        }
851    }
852
853    /**
854     * Retrieves stored callbacks.
855     */
856    function getCallback(eventName, target_id) {
857
858	    /*modified by kriesi - removing this will result in a js error. */
859        if (target_id && eventCallbacks[target_id] && eventCallbacks[target_id][eventName])
860		{
861            return eventCallbacks[target_id][eventName];
862        }
863        else
864		{
865            return eventCallbacks[eventName];
866        }
867    }
868
869    function removeCallback(eventName, target_id) {
870        if (target_id && eventCallbacks[target_id]) {
871            if (!eventCallbacks[target_id][eventName]) {
872                return false;
873            }
874            eventCallbacks[target_id][eventName] = null;
875        }
876        else {
877            if (!eventCallbacks[eventName]) {
878                return false;
879            }
880            eventCallbacks[eventName] = null;
881        }
882
883        return true;
884    }
885
886    function isFunction(obj) {
887        return !!(obj && obj.constructor && obj.call && obj.apply);
888    }
889
890    function isArray(obj) {
891        return toString.call(obj) === '[object Array]';
892    }
893
894    // Give the init function the Froogaloop prototype for later instantiation
895    Froogaloop.fn.init.prototype = Froogaloop.fn;
896
897    // Listens for the message event.
898    // W3C
899    if (window.addEventListener) {
900        window.addEventListener('message', onMessageReceived, false);
901    }
902    // IE
903    else {
904        window.attachEvent('onmessage', onMessageReceived);
905    }
906
907    // Expose froogaloop to the global object
908    return (window.Froogaloop = window.$f = Froogaloop);
909
910})();

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.