I'm loading YouTube videos using JS API. I can play, pause and go fullscreen with external controls but I can't exit fullscreen with double click on the video.
Using the code below try this:
load the video with button
go fullscreen using internal iframe button
double click on video (you will exit fullscreen)
Now my problem:
load the video with button
go fullscreen using external button
double click on video (nothing happens unless you press ESC key)
How can I do this? I need to exit fullscreen by double click (besides using ESC key)
fiddle: https://jsfiddle.net/cs8tnvkh/
HTML
<button id="btn_load">load video</button>
<button id="btn_play">play</button>
<button id="btn_pause">pause</button>
<button id="btn_fullscreen">fullscreen</button>
<div id="video_player">
<div id="video"></div>
</div>
JS
const YOUTUBE_LINK = "https://www.youtube.com/embed/#VIDEO?wmode=transparent&autoplay=1&rel=0&controls=1&enablejsapi=1&html5=1";
const YOUTUBE_VIDEO_ID = "mPyLF7NxZyY";
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('video', {
height: '480',
width: '720',
events: {
// call this function when player is ready to use
'onReady': onPlayerReady
}
});
}
function onPlayerReady(event) {
$("#btn_play").click(function() {
player.playVideo();
});
$("#btn_pause").click(function() {
player.pauseVideo();
});
$("#btn_fullscreen").click(function() {
var iframe = $('#video')[0];
var requestFullScreen = iframe.requestFullScreen || iframe.mozRequestFullScreen || iframe.webkitRequestFullScreen;
if (requestFullScreen) {
requestFullScreen.bind(video)();
}
});
}
var tag = document.createElement('script');
tag.src = "//www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
$(document).ready(function() {
$("#btn_load").click(function() {
var video_src = YOUTUBE_LINK.replace("#VIDEO", YOUTUBE_VIDEO_ID);
$("#video_player iframe").attr("src", video_src);
});
});
Related
I'm trying to make a project where a user can load multiple files at once and play them simultaneously. I want to give the options of uploading a video file, uploading an audio file, and/or entering a YouTube link. The difficulty I'm having is creating a custom play button for the case where they enter a YouTube link, as the play button will need to trigger multiple elements.
I found this codepen for custom play buttons: https://codepen.io/AmrSubZero/pen/oLOYMr
On its own, my code to set an iframe's source based on the url entered works fine, but when I attempt to integrate it here the custom play button ceases working. I think this is the result of onPlayerReady being loaded prior to the source being set. I've made an effort to resolve this based on that premise (calling on player ready after the button to enter the link is clicked) but no luck.
Codepen with the relevant bit of my project added: https://codepen.io/Carousel_/pen/zYpBZvR
HTML
<div class="buttons">
<button class="button" id="play-button">PLAY</button>
<button class="button" id="pause-button">PAUSE</button>
<button class="button" id="stop-button">STOP</button>
</div>
<p class="hideEngine">
YouTube Link:<br>
<input class="hideEngine" id="url" type="url" />
</p>
<iframe id="video" frameborder="0" allowfullscreen></iframe>
<button type="button" class="mybutton" id="mybutton" onclick="return embed();" >Initialize</button>
JS
var init = document.getElementById('mybutton');
init.addEventListener("click", function(){
onYouTubePlayerAPIReady();
onPlayerReady();
});
var embed = function(url) {
var url = document.getElementById('url').value
var id = url.split("?v=")[1];
var embedlink = "https://www.youtube.com/embed/" + id + "?enablesjsapi=1";
document.getElementById("video").src = embedlink;
}
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('video', {
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady(event) {
var playButton = document.getElementById("play-button");
playButton.addEventListener("click", function() {
player.playVideo();
});
var pauseButton = document.getElementById("pause-button");
pauseButton.addEventListener("click", function() {
player.pauseVideo();
});
var stopButton = document.getElementById("stop-button");
stopButton.addEventListener("click", function() {
player.stopVideo();
});
}
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
Any suggestions would be appreciated! Thanks.
Currently, the video does not player.stopVideo(); in the code.
To reproduce: Click 1 svg play button, then click the X and you will see that.
How is that fixed in the code so that the same video stops after clicking the X?
Updated Codes:
Click Run, not update to test JSitor code:
Also, autoplay works inside JSitor: https://jsitor.com/qYKcpdB0tj
Backup copy: https://jsfiddle.net/0q63tr2m/
const videoPlayer = (function makeVideoPlayer() {
const players = [];
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/player_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onPlayerReady(event) {
const player = event.target;
player.setVolume(100);
}
function addPlayer(video, settings) {
const defaults = {
height: 360,
host: "https://www.youtube-nocookie.com",
videoId: video.dataset.id,
width: 640
};
defaults.events = {
"onReady": onPlayerReady
};
You can see the video still playing here:
What you have to do is as follow:
Add an id to your iframe element like so: id="iframe"
Remove player.stopVideo(); from createStopHandler function
On your createStopHandler function, add following code(if you want your video to stop and not pause, then change the func snippet "func":"pauseVideo" into "func":"stopVideo"):
var frame = document.getElementById("iframe");
frame.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
This should do it. Here you can see it working: https://jsfiddle.net/vjbex6t1/8/
function addClickToHome(goHome) {
goHome.forEach(function addEventHandler(goHome) {
goHome.addEventListener("click", homeClickHandler);
//STOP PLAYER AFTER HOME IS CLICKED
});
}
Initialize some variable with player globally and stop it when button is pressed to home
You can try this out,
var videoURL = $('#playerID').prop('src');
videoURL = videoURL.replace("&autoplay=1", "");
$('#playerID').prop('src','');
$('#playerID').prop('src',videoURL);
I have embedded a YouTube video on my Shopify store, but as we know it doesn't auto play on mobiles and tabs so I have used YouTube API to play it on external click as I don't like the big red button
But cant make it disappear, issue is I already have text positioned over the video so cant use an overlay image like most of solutions.
My code:
<div class="video-wrapper">
<div id="bucklesburyVideo"></div>
</div>
<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('bucklesburyVideo', {
playerVars: {
'playlist': 'f8BxdOvj1Ho',
'loop': 1,
'autoplay': 1,
'controls': 0,
'showinfo': 0,
'wmode': 'opaque'
},
videoId: 'f8BxdOvj1Ho',
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady(event) {
event.target.mute();
var playButton = document.getElementById("play-button");
playButton.addEventListener("click", function() {
player.playVideo();
});
var pauseButton = document.getElementById("pause-button");
pauseButton.addEventListener("click", function() {
player.pauseVideo();
});
}
</script>
If you check the IFrame API and its player parameter, there is no instruction or method there that can show you on how to hide the big red play button of the YouTube. So what can I suggest you is to use a custom CSS to hide or adjust the location of the Play button.
Check this thread if it can help you.
For more information, check the other solution in this SO question.
I would like to pause the video when the user click on another tab in their browser. I have tried to do this with Youtube and Vimeo.
This is the basic idea behind the javascript:
For Youtube:
//YouTube
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var youtubePlayer;
var onYouTubeIframeAPIReady = function() {
youtubePlayer = new YT.Player('youtube', {
height: '390',
width: '640',
videoId: 'sXtekwuT8R0',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
};
var onPlayerReady = function(event) {
event.target.playVideo();
};
var onPlayerStateChange = function(event) {
if (event.data == YT.PlayerState.PLAYING) {
parent.focus();
window.onblur = function() {
status.text("You went away!");
youtubePlayer.stopVideo();
};
}
};
For Vimeo (using their Froogaloop library):
$(function() {
//Vimeo
var iframe = $('#vimeo');
var vimeoPlayer = $f(iframe[0]);
var status = $('#status');
vimeoPlayer.addEvent('ready', function() {
vimeoPlayer.addEvent('play', function(){
status.text("Playing!");
parent.focus();
window.onblur = function() {
status.text("You went away!");
vimeoPlayer.api("pause");
};
});
});
});
Here are some codepen examples of these attempts:
Youtube:
http://codepen.io/earlonrails/pen/jugAm
Vimeo:
http://codepen.io/earlonrails/pen/KBAmd
Both examples will work if after I click the play button, I click on the parent document of the iframe then click a different window or tab. The Youtube example will also work when it is first loaded, but not if you click the play then pause then play. I believe both of these problems are due to the fact that you are clicking the iframe, therefore the event either is trigger at the same time or cannot be triggered because the event can't be captured there. I thought using the postMessages sent through the iframes along with callbacks would make this work, but alas I have not been able to figure this out.
Need to set the current window before adding the event callback and use this window variable in the callback function. IE
var myWindow = window;
vimeoPlayer.addEvent('play', function(){
status.text("Playing!");
myWindow.focus();
myWindow.onblur = function() {
status.text("You went away!");
vimeoPlayer.api("pause");
};
});
These can be confirmed and tested at the previously linked codepen examples:
Youtube: http://codepen.io/earlonrails/pen/jugAm
Vimeo: http://codepen.io/earlonrails/pen/KBAmd
I guess the window when clicked in the iframe would be setting onblur on the iframe window, which would then never get called, but I still can't explain why when you click play on the iframe, then click the body of the page, then click a different tab then it works. Perhaps the callback is being fired more than once from the iframe or the postMessage is being fired or still in some buffer.
I'm currently loading a YouTube video inside a -UIwebView, this is working perfectly and the video starts playing automatically. but the problem is that once the video finishes inside the -UIwebViewit just stops and shows the play button. I would however want the video player to close so the users wouldn't have to manually hit the "Done" button every time.
Image of the screen when the video doesn't close.
Here's the link I launch the video inside the -UIwebview
NSString *youTubeVideoHTML = [NSString stringWithFormat:#"<!DOCTYPE html><html><head>
<style>body{margin:0px 0px 0px 0px;}</style></head> <body> <div id=\"player\"></div> <script>
var tag = document.createElement('script'); tag.src = \"http://www.youtube.com/player_api\";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
width:'320',
height:'200',
videoId:'%#',
events: {
'onReady': onPlayerReady,
}
});
}
function onPlayerReady(event) {
event.target.playVideo();
}
</script> </body> </html>", [[NSUserDefaults standardUserDefaults]
objectForKey:#"detailVideoURL"]];
EDIT:
I tried implementing the first answer into my code and this is how it ended up like. I'm still unsure what I should add into the callback ?
NSString *youTubeVideoHTML = [NSString stringWithFormat:#"<!DOCTYPE html><html><head><style>body{margin:0px 0px 0px 0px;}</style></head> <body> <div id=\"player\"></div> <script>
var tag = document.createElement('script'); tag.src = \"http://www.youtube.com/player_api\";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
width:'320',
height:'200',
videoId:'%#',
events: {
'onReady': onPlayerReady,
}
});
}
function onPlayerReady(event) {
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000); done = true;
}
if (event.data == YT.PlayerState.ENDED) {
window.location = "callback:nil"; }; }
function stopVideo() {
player.stopVideo();
}
</script> </body> </html>", [[NSUserDefaults standardUserDefaults] objectForKey:#"detailVideoURL"];
Image of the error : http://gyazo.com/31da955d8af98f40b82789a7f60c1edb
You can do it by calling your objective function from javascript using youtube api.
On the HTML/Javascript Side
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '300',
width: '250',
videoId: 'GUdYebAN-Fs',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
event.target.destroy();
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 60000);
done = true;
}
if (event.data == YT.PlayerState.ENDED) {
event.target.destroy();//to close the video
window.location = "callback:anything"; //here's the key
};
}
function stopVideo() {
player.stopVideo();
}
</script>
</body>
</html>
onStateChange- From the google's API reference page
This event fires whenever the player's state changes. The data property of the event object that the API passes to your event listener function will specify an integer that corresponds to the new player state.
So in the javascript function you would be able to trace the End of the video time.Then just
add event.target.destroy() on entering the state end condition.
On the native/iOS side:
And even you can do the native stuff here by catching up the call back method using the webview delegate method.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ( [[[request URL] scheme] isEqualToString:#"callback"] ) {
//Video has ended up playing,you can perform native stuff here...
return NO;
}
return YES;
}
Note: Please make sure to test this code in your device,because sometimes the simulators won't be supporting.
Good Luck...Hope it helps...
This is how you can apply Puneeth's solution to Google's YTPlayerView so the player hides after the video finishes:
- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state
{
if(state == kYTPlayerStateEnded) {
[self.youTubePlayer.webView stringByEvaluatingJavaScriptFromString:#"player.destroy();"];
// you'll have to recreate the player again since it's now destroyed
[self.youTubePlayer removeFromSuperview];
self.youTubePlayer = nil;
}
}