I've been struggling with this for a while now and I've tried a number of solutions but I'm totally stuck on this:
I have a number of embedded videos from YouTube on my Site and I have navigation buttons. I want the videos to be paused as soon as any of the buttons are clicked, no matter how many of them are playing at that time. I embedded them the classic way by using the iframe code that YouTube gives you when clicking "embed" and gave them the ".yt" class.
My function currently looks like this:
$(function () {
$('#shadingleft').on('click', function () {
rotateLeft();
reset();
selector = selector - 1;
if (selector <= -1) {
selector = 9;
}
$('.clicked').toggleClass('clicked');
})
$('#shadingright').on('click', function () {
rotateRight();
reset();
selector = selector + 1;
if (selector >= 10) {
selector = 0;
}
$('.clicked').toggleClass('clicked');
})
$('#shadingtop').on('click', function () {
rotateUp();
$('.clicked').toggleClass('clicked');
})
$('#shadingbottom').on('click', function () {
rotateDown();
$('.clicked').toggleClass('clicked');
})
$('.art').on('click', function () {
$(this).toggleClass('clicked');
})
});
As you can see I already managed to toggle the highlighted ".art" elements in my gallery using toggleClass. Unfortunately it doesn't seem to work for playing and pausing videos.
Whenever one of the four "shading..." elements is clicked I want my ".yt" elements to stop playing the embedded video.
Thanks for helping!
This is a actually a big limitation with iframes. Most browsers won't allow a page's scripts to interact with the content of its iframes for security reasons. So chances are that there is no way at all to do that.
One way you could stop videos would be to reload the youtube iframe entierly, but that would put it back to 00:00 as if it was never played.
Another would be to try and fetch the video stream from youtube on your server and then displaying it in a player of your own on your page. (Which is obviously way more complicated than using an iframe)
Related
The problem I'm trying to solve:
On my website I'm trying to build a way for the user to change the volume to on/off and save it across different pages. So when the user goes to index.html and about.html, I want the setting saved.
My thinking:
I am currently trying to solve this by saving the class active to localstorage and adding that to the button #MyElement that I use to toggle the audio. Then the .active class on the #MyElement button determines if audio will be played or not.
Furthermore I have javascript to play the audio file when I hover over the .box divs (1 and 2 in the codepen). This part seems to be working as I want it, however: when the page loads (I refresh the page and the previous setting was .active, the audio doesn't play! Then I need to toggle it again to .active and only then will it play. It seems like this piece of code doesn't recognise the other part.
How do I make sure the audio part listens to the localstorage class that is saved? I believe my code also uses part jQuery and part native javascript. I am quite new to this and mostly try to learn from other code snippets and slowly implementing things, however I'm stuck on this now for some time.
// Playing audio based on .active
document.querySelectorAll("[data-sound]").forEach(function (element) {
// Play associated audio
element.addEventListener("mouseenter", function (event) {
// element = $("body");'
if ($("#MyElement").is(".active")) var soundKey = element.dataset.sound;
var audioElement = document.querySelector("#" + soundKey);
if (!audioElement) return;
audioElement.currentTime = 0;
audioElement.play();
});
});
// Saving classes to localstorage
$("#MyElement").addClass(localStorage.getItem("ClassName"));
$("#MyElement").on("click", function () {
if ($(this).hasClass("active")) {
$(this).removeClass("active").addClass("inactive");
localStorage.setItem("ClassName", "inactive");
} else {
$(this).removeClass("inactive").addClass("active");
localStorage.setItem("ClassName", "active");
}
});
https://codepen.io/lucvanloon/pen/LYNLeEw
Thank you for taking a look!
Luc
Create a sessionStorage as follows:
sessionStorage.setItem("audio", "active");
document.getElementById("result").innerHTML = sessionStorage.getItem("audio");
I found out that the codepen isn't working because of policy in Google Chrome: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
It's not allowed to autoplay audio. Regardless if I save a previous user setting or not, it's always reset when the page refreshes.
What I'm trying to do: Create a list of items which contains a link to play audio from a youtube video beside each item
What I'm currently doing: I'm able to do this for a single item using the below:
<div data-video="VIDEO_ID"
data-autoplay="0"
data-loop="1"
id="youtube-audio">
</div>
<script src="https://www.youtube.com/iframe_api"></script>
<script src="https://cdn.rawgit.com/labnol/files/master/yt.js"></script>
This creates a play button and works perfectly on a single item, however will not work with multiple items on the same page presumably since they all use the same ID. Creating a different ID causes the player to not function. Creating two different data-video's with the same ID will only allow the first one to play, the other will appear correctly but not operate when pressing play.
Looking for solution: Preferably how to use the existing script for multiple videos on the same page. Otherwise an alternative solution for playing audio only on youtube videos with a custom play button would be great.
Thanks!
If you want you can just copy paste your code like this
https://jsfiddle.net/8wkjqf3m/
and it works, I'm not sure if you were having a problem doing that or if your problem was elsewhere. It is of course very sloppy looking and the code should be reworked so that you don't have to hard code every function for every video.
I tried to do everything dynamically and failed. I'm not sure if it is possible to dynamically make a function that makes a "new YT.player" for every video id you have and also have the onPlayerReady and onPlayerStateChange functions dynamically made to go with it. I'm sure there is some way but I couldn't figure it out.
The idea though is to make multiple "youtube-audio" divs with different ids for however many youtube players you want to have and have matching multiple "youtube-player" divs for the iframe to function. You can generate that part with javascript if you want so that you don't have to pollute your code with a bunch of repetitive html.
You can make all of your ids dynamically too.
var array = ['put a video id here','put a video id here','put a video id here'];
array = array.map(function(element,index) {
var div = document.createElement('div');
div.setAttribute('id', 'youtube-audio-' + index);
return {'videoId': element, 'div': div };
}
You can just have an array holding the youtube video ids and then initialize all of the divs data-video attributes using
document.getElementById("youtube-audio-1").dataset.video = //youtube video id
I don't see the point in doing all of that dynamically though if there is no way to get around copy pasting x number of "new YT.player"s and "onPlayerReady"s etc...
Good Luck, let me know if I was in the right area or if that was not what you wanted
I have modified the second script so it works as you (or I) want.
To use it use classes instead of IDs. Like the following:
<div data-video="NQKC24th90U" data-autoplay="0" data-loop="1" class="youtube-audio"></div>
<div data-video="KK2smasHg6w" data-autoplay="0" data-loop="1" class="youtube-audio"></div>
Here is the script:
/*
YouTube Audio Embed
--------------------
Author: Amit Agarwal
Web: http://www.labnol.org/?p=26740
edited by Anton Chinaev
*/
function onYouTubeIframeAPIReady()
{
var o= function(e, t)
// This function switches the imgs, you may want to change it
{
var a=e?"IDzX9gL.png":"quyUPXN.png";
//IDzX9gL is the stopped img and quyUPXN the playing img
t.setAttribute("src","https://i.imgur.com/"+a)
// folder or web direction the img is in. it can be "./"+a
};
var counter = 0;
var bigE = document.querySelectorAll(".youtube-audio");
bigE.forEach(function(e)
{
var t=document.createElement("img");
t.setAttribute("id","youtube-icon-"+counter),
t.style.cssText="cursor:pointer;cursor:hand",
e.appendChild(t);
var a=document.createElement("div");
a.setAttribute("id","youtube-player-"+counter),
e.appendChild(a);
t.setAttribute("src","https://i.imgur.com/quyUPXN.png");
e.onclick=function()
{
r.getPlayerState()===YT.PlayerState.PLAYING||r.getPlayerState()===YT.PlayerState.BUFFERING?(r.pauseVideo(),
o(!1, t)):(r.playVideo(),
o(!0, t))
};
var r= new YT.Player("youtube-player-"+counter,
{
height:"0",
width:"0",
videoId:e.dataset.video,
playerVars:
{
autoplay:e.dataset.autoplay,loop:e.dataset.loop
},
events:
{
onReady:function(e)
{
r.setPlaybackQuality("small"),
o(r.getPlayerState()!==YT.PlayerState.CUED, t)
},
onStateChange:function(e)
{
e.data===YT.PlayerState.ENDED&&o(!1, t)
}
}
})
counter++;
});
}
Trying to call the vimeo api to pause video on a click event to hide it. And, on clicking to reveal the video again, play the video from its paused position.
There are various related questions on here, I can't find an answer to the simple "how to pause". I'm a jquery novice and can't make heads or tails of the froogaloop documentation.
Here's a FIDDLE, and my current jquery script to hide the video
$(document).click(function (event) {
if (!$(event.target).hasClass('click')) {
$('#video').hide();
}
});
which hides it when an element without the "click" class is clicked. But the video plays on in the background. Froogaloop is loaded in the fiddle. Thanks everyone
Here's an updated FIDDLE that makes pause/play work as I'd imagined. Click the image to play the video; click outside or on empty space (you control this with classes) to pause it; click image again to play from paused position. Simple, no buttons, no excess jquery or froogaloop code.
Putting this here for those who might benefit from it. And a +1 to mbrrw for getting me started.
var iframe = $('#video iframe')[0];
var player = $f(iframe);
$('.showvideo').on('click', function(){
$('#video').show();
$('.image').hide();
player.api('play');
});
$(document).click(function (event) {
if (!$(event.target).hasClass('click')) { //if what was clicked does not have the class 'click' (ie. any empty space)
$('#video').hide();
$('.image').show();
player.api('pause');
}
});
Remember to append api=1 to the vimeo link. And the url must be https, not http.
froogaloop can be a pain in the arse.
The code to get you started is here:
https://developer.vimeo.com/player/js-api#universal-with-froogaloop
I've adapted that to get it working i think how you expect here:
https://jsfiddle.net/fLe5xs4v/
Setting it up like so:
var iframe = $('#video iframe')[0];
var player = $f(iframe);
Note that if you change the text in the play and pause buttons you will break this code:
$('button').bind('click', function() {
player.api($(this).text().toLowerCase());
});
Give it a shot it should get you going in the right direction at least. Good luck!
I've got this plugin which applies different style to html5 <audio> element and provides flash fallback to browsers that don't support .mp3 file format. Problem I encountered is that once you start playing one song, and then click play on any other song, all of them will play at the same time, which is bad user experience.
I was trying to figure out how to edit plugin to make it only play one song at a time, so say if user listens to one song and then click play on other, first one should pause, and so on.
I'm not entirely sure, but I think something need's to be edited along these lines:
playPause: function() {
if (this.playing) this.pause();
else this.play();
},
However, there are various places in the plugin which seem to deal with playing and pausing song, so I'm not sure that this is exact correct line for this. I'm still very new to jQuery, and can't entirely figure out how this big audio library works, I've been reading through code comment's , but still am unable to figure this out.
Full code of the plugin is available here: http://freshbeer.lv/mg/js/audio.min.js Official plugin website: http://kolber.github.io/audiojs/
You can visit my demo page to see the issue, just click play on several players and you will see that they all play at the same time: http://freshbeer.lv/mg/index.html
Use the addEventListener and the play event. This pauses all players except the one that the play button has been pressed on.
audiojs.events.ready(function () {
var as = audiojs.createAll();
$('audio').each(function () {
var myAudio = this;
this.addEventListener('play', function () {
$('audio').each(function () {
if (!(this === myAudio)) {
this.pause();
}
});
});
});
});
I have put my own custom title absolutely positioned over the top of an Vimeo video embed (you can see the dev site here http://ourcityourstory.com/dev/). When I click on the Vimeo video I want the title absolutely positioned over it to hide.
How do I accomplish this? None of the JS I'm writing is working.
Here is my non-working code:
$(document).click({namespace: this}, function (e) {
var t = e.data.namespace;
if ($(e.target).parents("#video-slider-wrapper iframe").length > 0 || $(e.target).is($("#video-slider-wrapper iframe"))) {
$("#episode h1").hide();
}
});
UPDATE: pimvdb's example listed below does exactly what I need my page to do — however, I keep getting the error "$f is not defined" on my page.
Your click handler does not work because the iframe is cross-domain. However, you can use the dedicated Vimeo API to add a listener when the play event is fired:
var player = $f( $('#player1').get(0) );
player.addEvent('play', function() {
$("h1").hide();
});