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'));
});
Related
I am trying to embed a vimeo video using iframe in my Qualtrics survey. When this video ends, I want to automatically advance to the next page (i.e., automatically press the "next button"). Before using vimeo, my videos were stored on dropbox and I used the following code for this (the url is not the real one):
<video autoplay="" id="video1" height="580" width="740"><source src="https://dl.dropboxusercontent.com/u/6339921/att/fam.mp4" type="video/mp4"></video>
Qualtrics.SurveyEngine.addOnload(function() {
that = this;
document.getElementById('video1').addEventListener('ended',myHandler,false);
function myHandler(e) {
if(!e) {
e = window.event;
}
that.clickNextButton();
}
});
However, it seems that I have to use iframe with vimeo, but I am unable to make the auto-advance work (the video will play but the page will not advance). Maybe it is because I am assigning the "ID" the wrong way. Here is the code:
<iframe id="player1" src="https://player.vimeo.com/video/20708824?autoplay=1api=1&player_id=player1&title=0&byline=0&portrait=0&background=1&mute=0&loop=0" width="600" height="400" frameborder="0"></iframe>
Qualtrics.SurveyEngine.addOnload(function() {
that = this;
var idPlayer = new Vimeo.Player('player1');
document.getElementByID('player1').addEventListener('ended',myHandler,false);
function myHandler(e) {
if(!e) { e = window.event; }
that.clickNextButton();
}
});
I am looking for a) an option to fix the iframe code, or b) an option to embed a vimeo video using the old code that I had used with dropbox videos.
Thanks so much and I apologize if this all sounds naive, I am not a programmer :-(
You can't add an event listener to an iframe from a different domain. It is called cross-domain scripting and for security reasons isn't allowed by the browser.
You have to use postMessage. There is a JavaScript class already written, but you would have figure out how to integrate it into Qualtrics:
https://github.com/vimeo/player.js
I have a site with a list of many embedded youtube videos like this
<div class="thumbnail">
<iframe width="560" height="315" src="https://www.youtube.com/embed/2sZAeXBP0NE" frameborder="0" allowfullscreen></iframe> </div>
the video list is big and changing daily.
im looking for a way to capture the start video event, so i can force the user to accept the TOS (using popup) before seeing the videos.
I tried to place a div with higher z-index and put an onclick event there ,but its not working/preventing the user to watch the video.
So I ended up using YouTube API
few things to mention
You must use a div as a placeholder for the video like this
<div id="video3" class="video3"></div>
and then you may declare callback function that fires once the video is clicked
function onYouTubeIframeAPIReady() {
video1 = new YT.Player('video1', {
height: '315',
width: '560',
videoId: 'youtubeId',
events: {
'onStateChange': onPlayerStateChange
}
});
note that all videos must be loaded inside the onYouTubeIFrameReady and they all may point to the same callback function or different ones
hope it helps
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 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.
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');
}