I have an iFrame that displays an embedded youtube video.
<iframe width="560" height="315" src="http://www.youtube.com/embed/xxx" frameborder="0" allowfullscreen></iframe>
What I would like to do is somehow capture the click event when the user clicks the you tube video so that I can call an http://myserver.com/dostuff rest api to update an external server counter tracking the number of clicks and of course allow the video to play as expected.
Any information would be greatly appreciated.
You can't, I believe. That would be a security risk. If you mainly want to do tracking and whatnot, you would probably be best off doing something like adding an image/button in the place of the video that the user clicks, causing the video to appear.
Edit: This solution may work too; I'm not sure if it'll work for iframes that aren't on the same domain.
window.postMessage could help. But you should have an access to source code of the page you're rendering in iframe.
So in case of embedding of youtube video, you probably can't deal with this.
Everybody had great feedback. Thanks for all who posted. After trying some hacks the bottom line is that trapping the click event is not natively supported via html or javascript.
The best artifact and cleanest solution that I have found is here.
//Its possible by recording the stateChange in the video.
//HTML code----
<!DOCTYPE html>
<html>
<body>
<div id='vidWrapper'>
//your iframe tag goes here.
<iframe id="video-id-first" src="https://www.youtube.com/embed/nNlEiuqiKAk?enablejsapi=1&origin=http%3A%2F%2F3.7.232.244" gesture="media" allow="encrypted-media" allowfullscreen="" data-gtm-yt-inspected-53610233_3="true" width="560" height="400" frameborder="0"></iframe>
</div>
</body>
</html>
//JS code ----
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 player;
var width = document.getElementById("video-id-first").getAttribute("width");
var height = document.getElementById("video-id-first").getAttribute("height");
var src = document.getElementById("video-id-first").getAttribute("src");
//splitting to get the videoId from src.
var partsArr = src.split("/");
var videoSource = partsArr[partsArr.length -1 ].split("?");
var videoId = videoSource[videoSource.length -2 ];
function onYouTubeIframeAPIReady() {
player = new YT.Player('vidWrapper', {
height:height,
width: width,
videoId: videoId,
events: {
'onStateChange': function(event) {
if (event.data == YT.PlayerState.PLAYING) {
startVideo();
}
if (event.data == YT.PlayerState.PAUSED) {
stopVideo();
}
}
}
});
}
function startVideo() {
//write your functionality here.
alert('Video Started');
}
function stopVideo() {
//write your functionality here.
alert('Video Paused');
}
Related
I'm working on a website, and i'm trying to get an youtube video in an <iframe> tag to play and pause with one button. I can get it to play or pause with separate buttons, but I can't seem to get the if statement to work in order to control the video with just one button.
I'm still relatively new to JavaScript, so it may just bee something simple I missed, but I'v searched online for a while now, and could not find anything that solved my problem.
Below is the code I use right now. The first time I click the button the YouTube video play's, but the second time nothing happens.
I also tried turning autoplay on for the embedded video, but then when I press the button, nothing happens at all.
This is the code I'm currently using:
HTML
<div class="iframe">
<iframe id="iframe1" width="360" height="203" src="https://www.youtube-nocookie.com/embed/videoseries?list=PLb-Mg8r29XuOV9CbkXVDQ5NdQG__WbJqI&controls=0&showinfo=0&enablejsapi=1" frameborder="0" allowfullscreen></iframe>
<a href="#" onclick="iframe1play();return false;">
<div id="iframe1play">
</div>
</a>
</div>
JavaScript
function onYouTubePlayerAPIReady() {
iframe1 = new YT.Player('iframe1');
}
function iframe1play() {
if (event.data == YT.PlayerState.PLAYING && !done) {
iframe1.pauseVideo();
document.getElementById("iframe1").style.opacity = "0";
} else {
iframe1.playVideo();
document.getElementById("iframe1").style.opacity = "1";
}
}
var tag = document.createElement('script');
tag.src = "//www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
Any suggestions are appreciated!
Ok so the main problem was that you didn't have event object in your function.
this should do the trick
if (player.getPlayerState() == YT.PlayerState.PLAYING) {
player.pauseVideo();
document.getElementById("iframe").style.opacity = "0";
} else {
player.playVideo();
document.getElementById("iframe").style.opacity = "1";
}
Use jQuery or other framework, if you can,for injecting functions to elements.
Maybe I don't understand your question. Because I tried your code and it works.
I can see a page with a youtube video. On clicking play button the video starts and when I click again on the video in pauses. So what is your problem. I'm sorry if I don't use comments but I can't yet.
Well, I think this is a major Youtube bug but I don't find any report about it.
I have a web app which is displayed in full screen browser using the JavaScript Fullscreen API.
In the web app there is an embedded Youtube player. When you open the Youtube player in fullscreen, then clicks the Youtube's fullscreen button again to exit the player's fullscreen, it doesn't respond!
I am sure it is related to the fact that the browser is already in full screen mode so there is some kind of conflict.
I have created a simplified example which can be viewed here:
http://run.plnkr.co/CjrrBGBvrSspfa92/
Click the "GO FULLSCREEN" button.
Play the video and click the
fullscreen button. The video will go fullscreen.
Click the
fullscreen button again. It won't exit.
EDIT:
The code for the html file above is here:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<iframe width="560" height="315" src="https://www.youtube.com/embed/b-6B2zyoFsI" frameborder="0" allowfullscreen></iframe>
<button id="btn">GO FULLSCREEN</button>
<script type="text/javascript">
document.getElementById("btn").addEventListener("click", function() {
var elem = document.documentElement;
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen();
} else if (elem.mozRequestFullScreen) {
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen();
}
});
</script>
</body>
</html>
The thing is I did some searching and it seams Youtube doesn't know if the video is in fullscreen or not when using the JavaScript Fullscreen API nor does Google provide an API call to fo in or out of fullscreen. So, When you click the button and it goes in fullscreen, you'll see the player's fullscreen button not pressed. So, in order to get back to the window view, the user has two options:
1) click on the button 2 times (the first time, the player tries to go in fullscreen and the button changes state, the second time, the player goes in window mode) - this is the solution
2) click Esc on the keyboard.
I checked with the HTML5 player.
Furthermore, I tried injecting a button inside YouTube's iframe so I can select it in order to exit fullscreen, but it didn't work... would have been silly to actually.
This should work:
<div id="videoplayer"></div>
<p><button id="btn">GO FULLSCREEN</button></p>
<script type="text/javascript">
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('videoplayer', {
height: '380',
width: '500',
videoId: 'h7ArUgxtlJs',
fs: 1
});
}
document.getElementById("btn").addEventListener("click", function() {
var elem = document.getElementById('videoplayer');
var requestFullScreen = elem.requestFullscreen || elem.msRequestFullscreen || elem.mozRequestFullScreen || elem.webkitRequestFullscreen;
if (requestFullScreen) {
requestFullScreen.bind(elem)();
}
});
</script>
You can use the classic embed, I belive.
Working demo
This may help: "Exiting Fullscreen Mode":
// Whack fullscreen
function exitFullscreen() {
if(document.exitFullscreen) {
document.exitFullscreen();
} else if(document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if(document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
// Cancel fullscreen for browsers that support it!
exitFullscreen();
Source.
Side note: Youtube's API is still pretty scarce in terms of what you can customize even in 2015 (due to how it relies on so much iFrame, and they don't want you to reskin their player). You'll likely get to a point where your using a bunch of funky JavaScript hacks to get what you want, which can get messy and unstable. It would be better practice to utilize one of many customizable video players where you can have more control with JS; like JW player, Video.js, Flow player, popcorn.js etc.
Strange one: embedded YouTube videos, once played (either by clicking 'play' or autoplaying on page load) will not play again.
I'm using the standard iFrame embed copied straight from YouTube. This happens with several different short videos and across all browser/OS combinations I've tested (Chrome/Safari/Firefox/IE on Windows/Mac).
Here's the code:
<iframe width="420" height="315" src="//www.youtube.com/embed/OuSdU8tbcHY" frameborder="0" allowfullscreen></iframe>
and you can see it in action at this fiddle.
So it appears that the issue is NOT related to video length; it's a problem with the flash player. If the flash player is loaded, and there is no user interaction with the controls at all, then when the player finishes it will not reload the iframe (despite the fact that it raises the 'video ended' event ... when you try to reload it won't issue the right call to reload the video and hence can never restart playback). You can test longer videos as well; if you start watching them and don't use the scrub bar, they'll exhibit the same behavior. Likewise, on your very short video, if you start playback and then scrub a bit (even backwards in time), that will trigger an iframe reload (akin to what #SuperMan noted), and so when the video finishes, then the reload will work just fine.
This is most likely a recently introduced bug in the Flash player, and it is not present in the HTML5 player; so if your use case allows it, the simplest solution would be to force the HTML5 player by appending ?html5=1 to the source of your iframe.
However, if having the flash player as a possibility is an iron clad requirement, then you can hack your code to force it to reload itself when finished (rather than waiting for a user to hit the reload or replay button).
<html>
<body>
<script>
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 player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
events: {
onStateChange: 'onPlayerStateChange'
}
});
}
function onPlayerStateChange(event) {
if (event.data===YT.PlayerState.ENDED) {
event.target.cueVideoById(event.target.getVideoData().video_id);
}
}
</script>
<iframe width="420" height="315" src="//www.youtube.com/embed/OuSdU8tbcHY" frameborder="0" allowfullscreen id="player"></iframe>
</body>
</html>
Note that this requires giving your iframe an id attribute, so that you can bind to it with the iframe API.
This also avoids having to overlay any DOM elements over the video (which is not in any way a bad solution as long as you don't have any odd wmode requirements; a very strict reading of the YouTube TOS might also lead to the conclusion that you can't overlay anything over any portion of the player even if it's transparent...).
One drawback of my solution is that it won't display the 'related videos' at the end of the video, so if that's a deal breaker then this is a no-go (in other words, my solution is more akin to adding the rel=0 attribute to your iframe source).
Okay, I don't know how to fix the problem but here's a work around.
The general idea is to place a div over the reload button when the video finishes, and when the div is clicked the video reloads, since the normal method doesn't work.
Here's the code I used, in the code the div is blue for visualization purposes
<!DOCTYPE html>
<html>
<body>
<div id="player_prop" style="position:relative;"><iframe id="player" type="text/html" width="640" height="390"
src="http://www.youtube.com/embed/OuSdU8tbcHY?enablejsapi=1"
frameborder="0"></iframe></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_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 onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
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.
//from mantish http://stackoverflow.com/questions/3452546/javascript-regex-how-to-get-youtube-video-id-from-url
function youtube_parser(url){
var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var match = url.match(regExp);
if (match&&match[2].length==11){
return match[2];
}else{
//error
}
}
//end of Lasnvs code
function restart_vid()
{
el = document.getElementById("fake_replay_button");
vid_id = youtube_parser(document.getElementById('player').src);
player.loadVideoById(vid_id);
el.parentNode.removeChild(el);
}
function fakeplay()
{
el = document.getElementById("player_prop");
var xPos = el.offsetLeft
var yPos = el.offsetHeight - 30;
var pseudoPlay = document.createElement('div');
pseudoPlay.setAttribute('style', 'background-color:blue; cursor:pointer; display:block; width:55px; height:25px; position:absolute; top:'+yPos+'px;');
pseudoPlay.setAttribute('onclick','restart_vid()');
pseudoPlay.setAttribute('id','fake_replay_button');
el.appendChild(pseudoPlay);
}
function onPlayerStateChange(event)
{
if(event.data==YT.PlayerState.ENDED)
{
fakeplay();
}
}
</script>
</body>
</html>
To use this code all you have to do is copy and paste the script portion, and instead of only using this
<iframe width="420" height="315" src="//www.youtube.com/embed/OuSdU8tbcHY" frameborder="0" allowfullscreen></iframe>
give it an id=player, enable jsapi by adding ?enablejsapi=1 at the end of the src and enclose the iframe in a div with id = player_prop, make sure the div has property position:relative, or else the alignment of the button would be off, it should look like this
<div id="player_prop" style="position:relative;">
<iframe id="player" type="text/html" width="640" height="390" src="http://www.youtube.com/embed/OuSdU8tbcHY?enablejsapi=1" frameborder="0"></iframe>
</div>
And of course here's a link to the Fiddle
In simple and fine way is that you have to add two addition parameter in youtube url first one is loop=1 and second is playlist=videoid
However, you can extract videoid from the url. It will be after embed slash
<iframe src="https://www.youtube.com/embed/J3jB4CS0x34?autoplay=1&mute=1&loop=1;playlist=J3jB4CS0x34" width="100%" height="100%" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="">
</iframe>
Maybe something like this:
JsFiddle
It's not a perfect solution, cause you interect with video outside of iframe, but maybe it will get you going(changing src will always reload the video).
$('iframe').attr("src", "//www.youtube.com/embed/OuSdU8tbcHY?autoplay=1"); // restarts the video
I have some videos which are embedded from YouTube in my "index.php". I am able to watch several videos at the same time by clicking them repeatedly. So, as usual it can be done. But I want to block this somehow.
For example, I'm watching X video and I clicked play to watch Y video. The X video should stop when I do it. Then I should be able to continue watching the Y video. I saw this feature in a website which I don't remember the name of it. And I don't know how to do and have an idea.
What I can guess is that it can be done by using some JavaScript or jQuery.
Here is an example for YouTube video code:
<iframe width="426" height="240" src="//www.youtube.com/embed/lWA2pjMjpBs?rel=0" frameborder="0" allowfullscreen></iframe>
Here is my JavaScript (without jQuery) solution to allow only one YouTube video to play at the time.
DEMO.
First you need to add a Youtube API by simply adding the script to your HTML page:
<script src="https://www.youtube.com/iframe_api"></script>
Then paste as many embed videos as you need. Keep in mind that
?enablejsapi=1&version=3&wmode=transparent
needs to be added to each link in order to access API. I wrapped the videos in div with yt_videos class.
<div class="yt_videos">
<iframe class="video_groups" src="https://www.youtube.com/embed/r4CH0al0ucs?enablejsapi=1&version=3&wmode=transparent" frameborder="0" allowfullscreen></iframe>
<iframe class="video_groups" src="https://www.youtube.com/embed/lL9Zoc46ZG0?enablejsapi=1&version=3&wmode=transparent" frameborder="0" allowfullscreen></iframe>
<iframe class="video_groups" src="https://www.youtube.com/embed/s1NZ2mkW0hM?enablejsapi=1&version=3&wmode=transparent" frameborder="0" allowfullscreen></iframe>
</div>
Then in javascript I access onYouTubeIframeAPIReady() so I can control players behaviour. I loop through the iframes and assign unique id's:
var players = [];
function onYouTubeIframeAPIReady() {
var predefined_players = document.getElementsByClassName("yt_videos")[0].getElementsByTagName('iframe');
for(var i = 0; i < predefined_players.length; i++){
predefined_players[i].id = "player" + i;
players[i] = new YT.Player("player" + i, {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
}
function onPlayerStateChange(event) {
var link = event.target.a.id;
var newstate = event.data;
if (newstate == YT.PlayerState.PLAYING) {
players.forEach(function(item, i) {
if (item.a.id != link) item.pauseVideo();
});
}
}
See the DEMO.
You can use the Youtube JS API
https://developers.google.com/youtube/js_api_reference
With it you can handle youtube player events...
If you're using only 1 iframe and just have several links on the sides that would contain the src destination of the iframe you could change the src attribute of the iframe like this:
$('.YoutubeLink').click(function(event){
$('#myIframe').attr('src',$(this).attr('href'));
});
I have an embedded youtube video with hidden controls:
<iframe id="ytplayer" type="text/html" width="400" height="225"
src="http://www.youtube.com/embed/dMH0bHeiRNg?rel=0&controls=0&showinfo=0
&loop=1&hd=1&modestbranding=1&enablejsapi=1&playerapiid=ytplayer"
frameborder="0" allowfullscreen></iframe>
I can control it with the youtube Javascript API.
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('ytplayer', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
Things like player.playVideo() and so on work perfectly. Now I am looking for a way to make the video play in fullscreen mode with a Javascript call but I couldn't find any method in the API.
Is it even possible (without the controls) and if so - how?
This worked perfect in my case. You can find more details on this link: demo on CodePen
var player, iframe;
var $ = document.querySelector.bind(document);
// init player
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '200',
width: '300',
videoId: 'dQw4w9WgXcQ',
events: {
'onReady': onPlayerReady
}
});
}
// when ready, wait for clicks
function onPlayerReady(event) {
var player = event.target;
iframe = $('#player');
setupListener();
}
function setupListener (){
$('button').addEventListener('click', playFullscreen);
}
function playFullscreen (){
player.playVideo();//won't work on mobile
var requestFullScreen = iframe.requestFullScreen || iframe.mozRequestFullScreen || iframe.webkitRequestFullScreen;
if (requestFullScreen) {
requestFullScreen.bind(iframe)();
}
}
You can use html5 fullscreen api:
node.requestFullScreen();
document.cancelFullScreen();
document.fullScreen; // bool
But note that:
this usually requires vendor specific prefix like mozRequestFullScreen() or webkitRequestFullScreen
requestFullScreen has to be called on user events (like onclick)
in firefox the fullscreen will be black until "Allow" is clicked by user
I've added code to do fullscreen (real full screen, not full window) to my answer on Auto-Full Screen for a Youtube embed.
YouTube don't expose fullscreen in their API, but you can call the native browser requestFullScreen() function from the playerStateChange() event from the YouTube API or make your own custom play button like I have.
Looking at the API reference for the iframe player, I don't think it's possible to set it to fullscreen (with the iframe API alone)- ctrl f didn't find fullscreen, so either it's a secret method hidden inside the API or it doesn't exist. However, as you probably know, you can set the size of the player player.setSize(width:Number, height:Number):Object, then make the window fullscreen.
Maybe have a look at this similar question. It looks as though this might work for you (using the javascript fullscreen api rather than the Youtube API):
Full Screen Option in Chromeless player using Javascript?
You can try setting the iframe dimension to the window dimension through javascript.
Something like this (using jQuery):
$('ytplayer').attr('width', $(window).width());
$('ytplayer').attr('height', $(window).height());
I hope this can help you.