Using jQuery to play/stop YouTube multiple iframe players - javascript

I am trying to play/stop multiple YouTube iframe players on a single page. I can start the players automatically (i.e. through a custom method called loadYouTubeVideo(playerID)) upon clicking, but I am not sure how I can get access to the player objects again from another function call (i.e. through a custom method called unloadYouTubeVideo(playerID))
Here is the jsfiddle with what I am talking about: http://jsfiddle.net/iwasrobbed/9Dj8c/3/
So each player starts, but it continues to play even after the div containing it is hidden.
By the way, I am using the iframe version of the player for a reason, so answers telling me to 'just use the flash object embed version' of the player are not acceptable for this question.
Code here in case jsfiddle is not available:
<html>
<body>
<script>
$(document).ready(function(){
// YouTube Player API adapter
$.getScript('http://www.youtube.com/player_api');
loadYouTubePlayer = function(playerID) {
the_player = new YT.Player(playerID, {
events: { 'onReady': playYouTubeVideo }
});
};
unloadYouTubePlayer = function(playerID) {
// This is the part that's broken
$(playerID).stopVideo();
};
function playYouTubeVideo(event) {
event.target.playVideo();
}
$('.show_player').click(function() {
var idType = 'data-video-id';
var id = $(this).attr(idType);
$(this).fadeOut('fast', function() {
$('.hidden_player['+idType+'='+id+']').fadeIn('fast', function() {
loadYouTubePlayer('the_player'+id);
$('.stop_player['+idType+'='+id+']').fadeIn('fast');
});
});
});
$('.stop_player').click(function() {
var idType = 'data-video-id';
var id = $(this).attr(idType);
$(this).fadeOut('fast', function() {
$('.hidden_player['+idType+'='+id+']').fadeOut('fast', function() {
unloadYouTubePlayer('the_player'+id);
$('.show_player['+idType+'='+id+']').fadeIn('fast');
});
});
});
});
</script>
<div class="hidden_player" data-video-id="0" style="display:none">
<iframe id="the_player0" width="640" height="360" frameborder="0" src="http://www.youtube.com/embed/2ktsHhz_n2A" type="text/html"></iframe>
</div>
<p>Show video 0 and start playing automatically</p>
<p>Stop video 0 from playing</p>
<br/><br/>
<div class="hidden_player" data-video-id="1" style="display:none">
<iframe id="the_player1" width="640" height="360" frameborder="0" src="http://www.youtube.com/embed/2ktsHhz_n2A" type="text/html"></iframe>
</div>
<p>Show video 1 and start playing automatically</p>
<p>Stop video 1 from playing</p>
</body>
</html>

I have created a function which access framed YouTube videos through the ID of the parent of the iframe (as specified in the YT Frame API), and executes the functions defined at the JS API.
See this answer for the code and a detailled Q&A section.
My code would be implemented in this way:
callPlayer(playerID, "stopVideo");

Related

Resolving the error of "SC.Widget function should be given either iframe element or a string specifying id attribute of iframe element"?

Context: This is a Soundcloud API javascript and iframe that is suppose to play the correct sound of the soundcloud link when you hover over the link.
Problem: The problem is that I get an error saying "SC.Widget function should be given either iframe element or a string specifying id attribute of iframe element" when I hover over a link. The error occurs at this line of code:
widget = SC.Widget(event.currentTarget.childNodes[1]);
HTML (Iframe the src is customized to play that particular link):
<div class="clickme">
<iframe src="https://w.soundcloud.com/player/?url=https://soundcloud.com{{-list2[1]-}}&show_artwork=true"
"width=300" height="200" scrolling="no" frameborder="0" style="display: none" allow="autoplay">
</iframe>
</div>
Javascript(Soundcloud API):
<script type="text/javascript">
let widget;
let currentWidget;
$(document).ready(function () {
console.log("ready!");
var menu = document.getElementsByClassName("clickme");
for (i = 0; i < menu.length; i++) {
var list = menu[i];
var link = String(list.outerHTML);
if (link.includes('soundcloud')) {
list.addEventListener("mouseenter", function (event) {
if (event.currentTarget.childNodes[1] == currentWidget) {
widget.play();
} else {
if (widget) {
widget.unbind(SC.Widget.Events.PLAY);
widget.unbind(SC.Widget.Events.READY);
widget.unbind(SC.Widget.Events.FINISH);
}
widget = SC.Widget(event.currentTarget.childNodes[1]);
/*<!--widget = SC.Widget(idIndex);-->*/
widget.bind(SC.Widget.Events.READY, function () {
widget.bind(SC.Widget.Events.PLAY, function () {
// get information about currently playing sound
console.log('sound is beginning to play');
});
// get current level of volume
widget.getVolume(function (volume) {
console.log('current volume value is ' + volume);
});
// set new volume level
widget.setVolume(50);
// get the value of the current position
widget.bind(SC.Widget.Events.FINISH, function () {
// get information about currently playing sound
console.log('replaying sound');
widget.seekTo(0);
widget.play();
});
});
widget.play();
}
currentWidget = event.currentTarget.childNodes[1];
});
list.addEventListener("mouseleave", function (event) {
console.log('pause soundcloud ');
if (widget) {
widget.pause();
}
});
}
}
});
</script>
As the error message states, you have to pass either an <iframe /> or an ID to an <iframe />. It means that event.currentTarget.childNodes[1] is probably NOT an <iframe /> (even less a string representing an DOM's element id).
I suggest you console.log() the entire event if you want to use mouse events to get corresponding <iframe />, or you make a clever use of id. Otherwise I'd recommend using a more robust method to get the iframe HTMLElement to pass to the SoundCloud Widget.
In the following snippet, Element.querySelector() is used to find iframes, but jQuery can do the same. Pass your mouse over one of the list elements and you should see the widget's methods logged in the Console.
// Run when DOM is ready
(function() {
// Make sure the SoundCloud Widget API is loaded in DOM
if (!(window.SC && window.SC.Widget)) {
return;
}
let currentWidget = null;
const listItems = document.getElementsByTagName('li');
for (const listItem of listItems) {
listItem.addEventListener('mouseover', event => {
// Get the <iframe /> HTMLElement
const iframe = listItem.querySelector('iframe');
const widget = SC.Widget(iframe);
// Set the current widget
currentWidget = widget;
// The logged object should have the "load", "bind", ... methods
for (const properties in currentWidget) {
console.log(properties);
}
// Unbind, set volume, ...
// ...
});
}
})()
<html>
<head>
<script src="https://w.soundcloud.com/player/api.js" charset="utf-8"></script>
</head>
<body>
<ul>
<li>
<iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177612306&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
</li>
<li>
<iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177613530&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
</li>
<li>
<iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177615096&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
</li>
<li>
<iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177644181&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
</li>
<li>
<iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177647310&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
</li>
</ul>
</body>
</html>

Embedded Vimeo Timestamp Link Not Working

I used to be able to get this to work where I press the link of the song, and it will jump to the time of the embedded Vimeo video in my site(Wordpress). The codes are as below:
HTML
<div class="wpb_video_widget wpb_content_element vc_clearfix vc_video-aspect-ratio-169 vc_video-el-width-100 vc_video-align-center">
<iframe id="player_1" src="https://player.vimeo.com/video/xxxxxxx?dnt=1&app_id=122963?api=1&player_id=player_1" width="1080" height="720" frameborder="0" allow="autoplay; fullscreen" allowfullscreen=""></iframe>
</div>
<div class="links">
<a class="link_1" href="javascript:void(0);" target="_self">Track 1 “Song Name”</a><br/>
<a class="link_2" href="javascript:void(0);" target="_self">Track 2 "Name of song"</a><br/>
JS Script
<script type="text/javascript">
// Set lesson times (in seconds)
var link_1_track = 000;
var link_2_track = 323;
// Function to hide all status messages
hidePlayNoticeAll = function() {
jQuery(".link_1_status").html("");
jQuery(".link_2_status").html("");
// Load Vimeo API for the embedded video
var iframe_player = jQuery('#player_1')[0];
var player_1 = $f(iframe_player);
// Function to control what happens when each lesson link is clicked
function setupLinks() {
jQuery(".link_1").click(function () {
player_1.api('play'); //Play the video
player_1.api('seekTo', link_1_track); //Seek to the number of seconds in the variable link_1_track
hidePlayNoticeAll(); // Hide all status messages before displaying (to prevent them from sticking)
jQuery(".link_1_status").html(playNotice); //Display status message (playNotice) within span with class link_1_status
});
jQuery(".link_2").click(function () {
player_1.api('play');
player_1.api('seekTo', link_2_track);
hidePlayNoticeAll();
jQuery(".link_2_status").html(playNotice);
});
}
setupLinks();
</script>
Is there anything wrong with the code? Or do I need an API from vimeo or jquery? I cant remember what I did to make it work before. Thank you in advance.
I have found the API that I needed to get this working. So I will be closing my own question haha.
The script made it worked like a charm, in case anyone wants to use the code, this is the script below. Cheers.
<script src="https://f.vimeocdn.com/js/froogaloop2.min.js"></script>

JavaScript play videos with same class control by play buttons with same class

I'm trying to make 3 play/pause buttons for 3 videos. Each play/pause button controls the closest video.
(function () {
var play = document.querySelectorAll('.video_play_button'),
video = document.querySelectorAll('.timeline_video');
function videoPlay() {
video.forEach(function (videoItem) {
if (videoItem.paused) {
videoItem.play();
} else {
videoItem.pause();
}
});
}
play.forEach(function (playItem) {
playItem.addEventListener('click', videoPlay, false);
})
})();
<section>
<video class="timeline_video"></video>
<h3><span class="video_play_button"></span></h3>
</section>
<section>
<video class="timeline_video"></video>
<h3><span class="video_play_button"></span></h3>
</section>
<section>
<video class="timeline_video"></video>
<h3><span class="video_play_button"></span></h3>
</section>
When I hit the play button now, it will play all the videos. How do I make it only plays the closest video?
Thanks :)
When I hit the play button now, it will play all the videos. How do I
make it only plays the closest video?
You can use parentNode to get to h3 and previousElementSibling to get to the video tag
You can modify videoPlay method to
function videoPlay( event )
{
var videoItem = event.currentTarget.parentNode.previousElementSibling;
videoItem.paused ? videoItem.play() : videoItem.pause();
}

Remove a dynamically added iframe

Hi so I have a parent div that in any given time an iframe with an embed youtube video is added. This par works great but I want to remove the iframe once the video is done. I've tried using an EvenListener then tried a bind, both of which did not work.
function play_vid(id, par){
// id: youtube video id par: id of parent div
var obj = {"video": {
"value": '<iframe id="ytb-player" width="100%" height="100%" src="http://www.youtube.com/embed/' +id+'" frameborder="0" '+
'allowFullScreen></iframe>'
}}
$(par).html(obj.video.value);
$('#ytb-player').bind('onStateChange', function(e) {
if (e.data === 0) {
$(par).remove('#ytb-player');
}
});
}
Any help is appreciated!
Yep! Using the YT API works with the code above!

Change youtube video on image on stop state

I made the code like this which changes an image on the web-site on Youtube video.
<script type="text/javascript">
$(window).load(function(){
$('img.demovideo').click(function(){
video = '<iframe class="demovideo" width="100%" height="551px" src="'+ $(this).attr('data-video') +'"></iframe>';
$(this).replaceWith(video);
});
$('img.demovideo').css('cursor', 'pointer');
});
</script>
How can I change the Youtube video back on image on player state 0?
I made a code like this, but it doesn't work:
<script type="text/javascript">
raketaplayer.onStateChange () {
b = raketaplayer.getPlayerState();
if (b=0) {
image = '<img class="demovideo" src="http://raketa.pro/wp-content/uploads/2013/03/image_header_2.png" data-video="http://www.youtube.com/embed/7hoqO36CVRM?&rel=0&theme=light&showinfo=0&hd=1&autohide=1&color=white&autoplay=1&enablejsapi=1&playerapiid=raketaplayer" style="cursor: pointer;">';
$(iframe.demovideo).replaceWith(image);
});
$('img.demovideo').css('cursor', 'pointer');
});
}
}
</script>
What's wrong with it? Please, help :)
Image code as follows:
<img class="demovideo" src="http://raketa.pro/wp-content/uploads/2013/03/image_header.png" data-video="http://www.youtube.com/embed/7hoqO36CVRM?&rel=0&theme=light&showinfo=0&hd=1&autohide=1&color=white&autoplay=1&enablejsapi=1&playerapiid=raketaplayer">
A couple of issues that you might want to address. First of all, your conditional statement uses a single equal sign instead of a double. More importantly, though, when you execute the onStateChange function, it can take an argument that represents the event, which will report the state change without you having to query for it, like this:
raketaplayer.onStateChange (event) {
if (event.data==0) {
image = '<img class="demovideo" src="http://raketa.pro/wp-content/uploads/2013/03/image_header_2.png" data-video="http://www.youtube.com/embed/7hoqO36CVRM?&rel=0&theme=light&showinfo=0&hd=1&autohide=1&color=white&autoplay=1&enablejsapi=1&playerapiid=raketaplayer" style="cursor: pointer;">';
$(iframe.demovideo).replaceWith(image);
});
$('img.demovideo').css('cursor', 'pointer');
});
}
}
Finally, make sure you've bound your onStateChange function to the state change event of the YT.Player object that you create elsewhere in your code.

Categories