PageSourceSearch

https://www.yrkesforarcentrum.se/wp-content/themes/enfold/config-t…/slideshow/slideshow-video.js?ver=5.6.21

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

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.