Reset Vimeo player when finished - javascript

How can I reset an embed Vimeo video to how it was onload after it's done playing?
The Vimeo API offers an unload method
player.api("unload")
But it isn't working for non-flash players.

Using the Vimeo API, you can add an event for finish to trigger the reload. The Vimeo API includes a method unload(), but it isn't supported in HTML players. Instead, reset the URL in the iframe to return the video to it's original state.
HTML
<iframe src="//player.vimeo.com/video/77984632?api=1" id="video"></iframe>
JS
var iframe = document.getElementById("video"),
player = $f(iframe);
player.addEvent("ready", function() {
player.addEvent('finish', function() {
player.element.src = player.element.src;
});
});

unload() should now work properly across all players.

Variation of Steve Robbins solution, with Vimeo specific solution. You don't have to reach the end of the video, but anytime the user bails out, including clicking on a button:
Simple Javascript solution with Vimeo Library loaded:
https://player.vimeo.com/api/player.js
function ResetVideo()
{
var Field = "iframe-video"; // <iframe id=iframe-video
var iframe = document.getElementById(Field);
var bLoad = LoadVimeoLib(); // Is the Vimeo lib loaded
if(bLoad > 0)
{
var Videoplayer = new Vimeo.Player(iframe);
Videoplayer.pause(); // Pause the video and audio
Videoplayer.setCurrentTime(0); // Reset the video position
// Reset the video back to the iframe
VideoSrc = Videoplayer.element.src; // Save the video source
Videoplayer.element.src = ""; // Empty the source
Videoplayer.element.src = VideoSrc; // Reset the video source
}
}
function LoadVimeoLib()
{
if (typeof jQuery === 'undefined')
{
alert('no jquery installed');
return 0;
}
var scriptlen = jQuery('script[src="https://player.vimeo.com/api/player.js"]').length;
if (scriptlen == 0)
{
jQuery.ajax({
type: "GET",
url: "https://player.vimeo.com/api/player.js",
dataType: "script"
});
}
return 1;
}

Related

Generate new iframe YouTube player for multiple instances on a page

The following JavaScript works great when I have only one instance of a YouTube video on a page:
function createVideo(playerElement, videoID, autoplay=false) {
const youtubeScriptId = 'youtube-api';
const youtubeScript = document.getElementById(youtubeScriptId);
if (youtubeScript === null) {
const tag = document.createElement('script');
const firstScript = document.getElementsByTagName('script')[0];
tag.src = 'https://www.youtube.com/iframe_api';
tag.id = youtubeScriptId;
firstScript.parentNode.insertBefore(tag, firstScript);
}
window.onYouTubeIframeAPIReady = function() {
return new window.YT.Player(playerElement, {
videoId: videoID,
playerVars: {
autoplay: autoplay,
modestbranding: 1,
rel: 0
}
});
}
}
But when I try to call this again, the video doesn't load. Only the first video. This method is called via a click event after the page has loaded, and I pass in a videoID data attribute and build my new YouTube video to show on the page.
I assume because my JavaScript is creating only one instance on the window object, and not separate multiple instances. After further research I can see that the onYouTubeIframeAPIReady() method only fires once on a page, so that explains why the subsequent calls when the click event fires this method fails. Since it is impossible for me to know how many exact instances to load on a page, how would I refactor this code to make it dynamic, so that unlimited instances can be created and played on a page via click events only? I've seen countless tutorials of building YouTube videos when you know the elements on a page. But in this scenario either I do not know what is on the DOM, or want to slow the site down on page load by building unlimited YT videos to be inserted into the DOM only to probably not be clicked to play by the user.
Is it even possible to dynamically create a new YouTube video on a page using their YT API bound to a click event? From what I am reading online, it looks like a person has to load all videos at once when onYouTubeIframeAPIReady() is first loaded on the page after the YT API loads, and I have to add extra logic in place to play/stop each and then bind additional click events per each video to show/hide/play/stop. This is going to increase my page load dramatically, and add a bunch of JS overhang to my page. I simply want to create a new video on a click event.
I hope you're not using the same videoID every time, because for multiple instances of anything you need to have some kind of sequential ID management, like this...
var ID=[], Vid;
for(var i=0; i<20; i++){ // create 20 video players
ID.push('V'+i);
Vid=document.createElement('video');
Vid.id=ID[i];
document.body.appendChild(Vid);
createVideo(e, ID[i], false); // Your function
}
You get the drift...
The core issue that you're experiencing is the YT.Player can only be initalized once on the page - and if you have multiple videos to be handled via the YT.Player you'd have to iterate over the videos one by one with the same YT.Player instance. It's a little weird at first, but can work - especially if you need to handle the videos via popup modals, etc.
Here's an example that I've used to iterate over a page that has multiple hidden modals with videos, and then handle the click events and playing the videos:
jQuery(document).ready(function ($) {
let modalTriggerElements = $('.video_play_icon'),
playerInfoList = [],
players = []
if (typeof (YT) == 'undefined' || typeof (YT.Player) == 'undefined') {
let tag = document.createElement('script'),
firstScript = document.getElementsByTagName('script')[0]
tag.src = 'https://www.youtube.com/iframe_api';
tag.id = 'youtube-api';
firstScript.parentNode.insertBefore(tag, firstScript)
}
if (modalTriggerElements.length > 0) {
$.each(modalTriggerElements, (index, element) => {
buildPlayersList(element)
modalTriggerClickEvent(element)
})
}
window.onYouTubePlayerAPIReady = function () {
if (typeof playerInfoList === 'undefined') return;
for (let i = 0; i < playerInfoList.length; i++) {
players[i] = createPlayer(playerInfoList[i]);
}
}
function createPlayer(playerInfo) {
return new YT.Player(playerInfo.playerId, {
videoId: playerInfo.videoId,
playerVars: {
showinfo: 0,
}
});
}
function buildPlayersList(element) {
let $modelDiv = $(element).closest('.hc_module').next('.video_model'),
$playerDiv = $($modelDiv).find('#video-player');
playerInfoList.push({
'videoId': $($modelDiv).data('video-id'),
'playerId': $($playerDiv)[0],
});
}
function modalTriggerClickEvent(element) {
$(element).on('click', () => {
let $parentDiv = $(element).closest('.hc_module'),
$nearestVideoDiv = $parentDiv.next('.video_model'),
$closeDiv = $nearestVideoDiv.find('.close_modal')
$nearestVideoDiv.css('display', 'block')
$nearestVideoDiv.attr('aria-hidden', 'false')
$closeDiv.on('click', () => {
$nearestVideoDiv.css('display', 'none')
$nearestVideoDiv.attr('aria-hidden', 'true')
players.forEach((el) => {
el.stopVideo();
});
})
})
}
});
When you don't know how many players you can use random numbers to avoid conflicts...
var ID=[]; // Global array
function AddVideoPlayer(){
var Vid, i=ID.length-1;
ID.push('V'+RandomNumber(99999999));
Vid=document.createElement('video');
Vid.id=ID[i];
document.body.appendChild(Vid);
createVideo(e, ID[i], false); // Your function
}

Firefox: ReferenceError: event is not defined

Firefox displays the following error in the console:
ReferenceError: event is not defined
In refence to my code which allows me to open embedded youtube videos in fullscreen modals.
$(document).ready(function () {
$(".vma_overlay").click(function () {
var $videoSrcOriginal = $(event.target).siblings('.vma_iFramePopup').attr("src");
// Check if the embedded youtube url has any attributes appended
// by looking for a '?' in the url.
// If one is found, append our autoplay attribute using '&',
// else append it with '?'.
if ($videoSrcOriginal.indexOf('?') > -1) {
var $videoSrc = $videoSrcOriginal
// when the modal is opened autoplay it
$('#vma_ModalBox').on('shown.bs.modal', function (e) {
// set the video src to autoplay
var $videoSrcAuto = $videoSrc + "&autoplay=1&mute=1";
$("#vma_video").attr('src', $videoSrcAuto);
$('body').addClass("modalyt");
})
} else {
var $videoSrc = $(".vma_iFramePopup").attr("src");
// when the modal is opened autoplay it
$('#vma_ModalBox').on('shown.bs.modal', function (e) {
// set the video src to autoplay
var $videoSrcAuto = $videoSrc + "?autoplay=1&mute=1";
$("#vma_video").attr('src', $videoSrcAuto);
$('body').addClass("modalyt");
})
}
// stop playing the youtube video when modal is closed
$('#vma_ModalBox').on('hide.bs.modal', function (e) {
$("#vma_video").attr('src', $videoSrc);
$('body').removeClass("modalyt");
})
});
});
Firefox is highlighting the following line of code as being the culprit:
var $videoSrcOriginal = $(event.target).siblings('.vma_iFramePopup').attr("src");
I don't seem to be having this issue in Chrome, IE or Edge.
I have tried to put it all together in a CodePen here: https://codepen.io/CodeChaos/pen/ZPgbJe
add event to function argument
$(".vma_overlay").click(function (event) {
var $videoSrcOriginal = $(event.target).

Generating YouTube Custom PlayList issue

I want to build a custom youtube playlist from this tutorial using the YouTube API and I got stuck at a certain point.
I basically embedded the client.js script and execute it's function on loading and after that i embedded also the YouTubePlayList.js file as stated in the tutorial.
Here is a fiddle of what i'm trying to do. I do receive the YouTubePlayList object in console but it doesn't seem to give any proper data. I need a working script example or guidance on how to achieve it to work and have the playlist rendered in my client. Thanks in advance, any help appreciated!
JS:
<pre>
function YouTubePlayList (id, entries) {
this.id = id;
this.entries = entries;
this.currently_playing = 0;
this.randomizer = false;
}
var requestOptions = {
playlistId: 'PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe',
part: 'contentDetails, snippet',
execute: function(response) {
var entries = [];
$.each(response.items, function(key, val){
var entry = {};
entry.video_id = val.snippet.resourceId.videoId;
entry.image_src = val.snippet.thumbnails.medium.url;
entry.title = val.snippet.title;
entry.note = val.contentDetails.note;
entries.push(entry);
});
}
};
window['PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe'] = new YouTubePlayList('PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe', 1);
console.log(window['PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe']);
</pre>
You can visit Playlists: insert
This will help you create a new playlist in your channel. The page is jam packed of ideas that will help you to start. There are also example such as the .js code below.
// Define some variables used to remember state.
var playlistId, channelId;
// After the API loads, call a function to enable the playlist creation form.
function handleAPILoaded() {
enableForm();
}
// Enable the form for creating a playlist.
function enableForm() {
$('#playlist-button').attr('disabled', false);
}
// Create a private playlist.
function createPlaylist() {
var request = gapi.client.youtube.playlists.insert({
part: 'snippet,status',
resource: {
snippet: {
title: 'Test Playlist',
description: 'A private playlist created with the YouTube API'
},
status: {
privacyStatus: 'private'
}
}
});
request.execute(function(response) {
var result = response.result;
if (result) {
playlistId = result.id;
$('#playlist-id').val(playlistId);
$('#playlist-title').html(result.snippet.title);
$('#playlist-description').html(result.snippet.description);
} else {
$('#status').html('Could not create playlist');
}
});
}
// Add a video ID specified in the form to the playlist.
function addVideoToPlaylist() {
addToPlaylist($('#video-id').val());
}
// Add a video to a playlist. The "startPos" and "endPos" values let you
// start and stop the video at specific times when the video is played as
// part of the playlist. However, these values are not set in this example.
function addToPlaylist(id, startPos, endPos) {
var details = {
videoId: id,
kind: 'youtube#video'
}
if (startPos != undefined) {
details['startAt'] = startPos;
}
if (endPos != undefined) {
details['endAt'] = endPos;
}
var request = gapi.client.youtube.playlistItems.insert({
part: 'snippet',
resource: {
snippet: {
playlistId: playlistId,
resourceId: details
}
}
});
request.execute(function(response) {
$('#status').html('<pre>' + JSON.stringify(response.result) + '</pre>');
});
}
Try to explore YouTube Player API Reference for iframe Embeds.
The IFrame player API lets you embed a YouTube video player on your
website and control the player using JavaScript.
Using the API's JavaScript functions, you can queue videos for
playback; play, pause, or stop those videos; adjust the player volume;
or retrieve information about the video being played. You can also add
event listeners that will execute in response to certain player
events, such as a player state change or a video playback quality
change.
This guide explains how to use the IFrame API. It identifies the
different types of events that the API can send and explains how to
write event listeners to respond to those events. It also details the
different JavaScript functions that you can call to control the video
player as well as the player parameters you can use to further
customize the player.

Ajax request to pre-download video(s)

I have been trying to download a video (which will ultimately be from my own resource) and while the video is downloading I want to show a loading message.
Once it is fully downloaded I want to hide the loading icon and have the video ready to be played.
I am having trouble getting the video file and setting it to the video attribute in the HTML. Here is the code I am using...
JS:
var root = 'https://crossorigin.me/http://techslides.com/demos/sample-videos/small.mp4';
function loadVideo() {
$('.loading').show();
$.ajax({
url: root,
method: 'GET'
}).then(function(data) {
$('.loading').hide();
console.log("done");
$('video').attr('src', data);
$("video")[0].load();
//console.log(data);
});
}
HTML:
<div class="loading animated bounce infinite">
Loading
</div>
<video width="320" height="240" controls>
</video>
You don't need an ajax request for this. You could simply set the source of the video element, and then listen to loadeddata. There are 4 different readyStates you can check for. HAVE_ENOUGH_DATA (readyState 4) stands for:
Enough data is available—and the download rate is high enough—that the media can be played through to the end without interruption.
An implementation for this could look like this:
function loadVideo(videoURL, $player) {
$player = $videoObj || $('video');
$('.loading').show();
$player.attr('src', videoURL);
var player = $player[0];
player.addEventListener('loadeddata', function() {
if(player.readyState == 4) {
// or whatever you want to do
// in case the video has enough data
$('.loading').hide();
}
});
}
In case you really need the "complete" state (the 100%), you could use the progress event to determine how much of the video has been buffered, in case the buffer is 100%, the video should be completely loaded.
function loadVideoCompleted(videoURL, $player) {
$player = $videoObj || $('video');
$('.loading').show();
$player.attr('src', videoURL);
var player = $player[0];
player.addEventListener('loadeddata', function() {
var percentageBuffered = 0;
if (player.buffered.length > 0
&& player.buffered.end && player.duration) {
percentageBuffered = player.buffered.end(0) / player.duration;
} else if (player.bytesTotal != undefined &&
player.bytesTotal > 0 && player.bufferedBytes != undefined) {
percentageBuffered = player.bufferedBytes / player.bytesTotal;
}
if (percentageBuffered == 1) {
// or whatever you want to do in case
// 100% of the video has been buffered
$('.loading').hide();
}
});
}

how to jump to the next video when current video file is not available?

I am trying to play list of video files stored in a folder one by one but if any of the file is missing or deleted the program will stop but i want it jump to the next video and continue its execution is there any way to catch this error and jump to the next one?
function advanceVideo()
{
video_count++;
if (video_count > num_files) video_count = 1;
videoPlayer.setAttribute("src","video/video"+video_count+".ogg");
video.load();
video.play();
}
I am using the above function for accessing the video file in the folder.
Make use of the various events the <video /> element offers
// function to load the next video (without .play())
function advanceVideo() {
video_count = (video_count + 1) % num_files;
this.setAttribute("src", "video/video" + video_count + ".ogg");
this.load();
}
// if the current video has reached the end, load the next
videoPlayer.addEventListener("ended", advanceVideo);
// if the browser fetched enough data to play the video start playing
videoPlayer.addEventListener("canplay", function() {
this.play();
});
// if an error occured load the next video
videoPlayer.addEventListener("error", advanceVideo);
Update
This should do what you've requested in your comment
var num_files = 2,
playedVideos = 0;
// load next video
function advanceVideo() {
// current video id or -1 if not found
var curId = parseInt((/video(\d+)\.ogg$/.exec(this.src) || [, -1])[1], 10);
// reset if all videos have been played
if (playedVideos == num_files) {
playedVideos = 0;
curId = -1;
}
this.src = "video/video" + (curId + 1) + ".ogg";
this.load();
}
// if the current video has reached the end, load the next
videoPlayer.addEventListener("ended", function() {
playedVideos++;
advanceVideo();
});
// if the browser fetched enough data to play the video start playing
videoPlayer.addEventListener("canplay", function() {
this.play();
});
// if an error occured load the next video
videoPlayer.addEventListener("error", advanceVideo);
If there are less videos to play than num_files indicates, this will end in an "infinite loop" as it will try all videos until curId reaches the value Infinity!
Try using try-catch block:
function advanceVideo()
{
video_count++;
if (video_count > num_files) video_count = 1;
videoPlayer.setAttribute("src","video/video"+video_count+".ogg");
try {
video.load();
video.play();
} catch (e) { }
}

Categories

Resources