I'm currently working on a project which includes when the user hovers over a certain div then it will play the associated audio file and stop all other audio elements on the page that contain the class 'stoppable' in them.
I've got the code working but now I'm having that page as an iFrame on another page which can insert elements into the iframe, so I have to keep adding iframe.contents on elements to make them work.
On the code below it detects when the user has entered the div and plays the correct audio however it does not stop all the other audio elements.
I believe I have the incorrect syntax on the
$('.stoppable:not($("#new-audio-476333", iframe.contents()))
section, and I'm not sure what the correct syntax would be.
var iframe = $('#clientframe');
$('#476333',iframe.contents()).mouseenter(function() {
$('.stoppable:not($("#new-audio-476333", iframe.contents()))').each(function(){
this.pause(); this.currentTime = 0;
});
var audio = $('#new-audio-476333', iframe.contents())[0];audio.pause();audio.play(); });
Any help would be greatly appreciated.
Thanks!
-Hopeless
$('.stoppable:not(#new-audio-476333)', iframe.contents())
This means that elements with class name stoppable which its id is not new-audio-476333.
Related
I am creating a chrome extension that adds a button to the youtube player HUD (to the left of the watch later button). This works fine, but the only problem is that when the HUD autofades after a few seconds of inactivity, this button element doesn't.
I've added the button to the following div using javascript:
<div class="ytp-chrome-top-buttons"> </div>
and my button looks like this:
<button class="customClass" id="customID" title="custom title"><svg class="customClass"></svg></button>
I've looked through the source of the page to try and see how exactly youtube makes the other icons disappear, and whether I can copy a class to my svg to make it disappear, but I haven't been able to find it.
I've looked at using a timer and javascript to make the element disappear, but I figured if the functionality is already there, why complicate it.
As a last resort I will be resorting to using the timer method, but I'd much prefer using CSS classes.
I have had a cursory glance into the Youtube Player API, but to be frank, I'm having a hard time understanding how it works (While I have a few years of programming experience, I only started learning javascript, HTML, and CSS yesterday). I also understand that this API is only for embedded youtube videos?
To clarify, I DO know how to use API's in javascript, just not this particular one. I have used the youtube data API to implement the button's functionality successfully.
Any help is appreciated.
Thanks.
If you examine the element changes, you can see that the class list of the video has changed with the change of the bottom bar. When the bottom bar is hidden, the ytp-autohide class is added. Keeping this in mind, after scanning the class changes with the mutation observer, you will reach the desired result when the ytp-autohide class's existence status changes.
var video = document.querySelector("#movie_player");
var lastState = video.classList.contains('ytp-autohide');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if(mutation.attributeName == "class"){
var currentState = mutation.target.classList.contains('ytp-autohide');
if(lastState !== currentState) {
lastState = currentState;
if(currentState)
console.log("Hided");
else
console.log("Shown");
}
}
});
});
observer.observe(video, {attributes: true});
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++;
});
}
So, I'm still new to javascript and everything. What I'm trying to do is when a small video is clicked, display it on the main big video above. This is the script so far, but I'm not sure what I need to add.
<script type="text/javascript">
$(document).ready(function() {
$(".littlevideo").click(function() {
var video = $(this).closest("div").find("video").attr("src")
$('#displayvideo').attr("src",video);
});
});
</script>
you want to do something like:
<script type="text/javascript">
$(document).ready(function() {
$(".littlevideo").click(function() {
var video = $(this).closest("div").find("video").attr("src")
$('#displayvideo').append("<iframesrc="+video+"></iframe>");
});
});
The append basically adds that HTML to the container. you do the +video+ because it adds whatever that value is, to the existing string. This is how you make it dynamic.
We need the rest of the page (preferably), but that piece of code should do what you are wanting. Basically, the code just takes the attributes of the element being clicked on (as long as it has a class of "littlevideo") and transfers it to the #displayvideo element (I'm guessing the "big video" you're talking about). Make sure the little video's elements/tags all have class="littlevideo", and the big video player element/tag has an attribute of id="displayvideo".
i'm working on adding a video to the home page of a site i'm working on. ideally, i'd like to show the youtube version by default, and add a button underneath that says something like "don't have access to youtube? click here to watch an alternate version".
once clicked, a different player will load into the same video div and replace the youtube version.
we have the video uploaded to youtube, and also have an html5 version on the site that is played via the video.js plugin for wordpress.
how can i load the alternate html5 video player into the div via a button click (without refreshing the page if possible)? i'm assuming this can be done via javascript / jquery / ajax somehow, but I'm not sure how to do this (my js level is novice).
thanks!!
You can clear the div out with:
$("#yourDivID").empty()
Then populate the div with new content
var newHtml = "Whatever you want!"
$("#yourDivID").append(newHtml);
Or
$("#yourDivID").html(newHtml);
Here's a very primitive example of replacing content in a Div: http://jsfiddle.net/FJuwd/
Html
<div id="myvideodiv"> </div>
In script
mybutton.click(function(){
playerMethod("myvideodiv").setup({ //here player intializations based on sepecific type
file: "/uploads/example.mp4",
height: 360,
image: "/uploads/example.jpg",
width: 640
});
})
see example here.
jQuery solution: Just create div and populate with video on button click. Many ways to do this. The check for length is only there to eliminate putting another video up.
<div id="player"><div>
<button id="clickme">Click to play video</button>
$("#clickme").on("click", function(e) {
if($('#myfileplayer').length == 0) {
var mydiv = $("#player");
var myvideo = $("<video id='myfileplayer' src='http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv' width='320' height='240' controls></video>");
mydiv.append(myvideo);
}
});
See example
thanks so much everyone for all of the help. love this place.
i was actually able to work this out more easily by just toggling divs that contain the two different videos. not sure why i didn't think of this initially. doesn't actually remove the content, just hides it, but i think it will work for me.
html
<div id="youtube">my youtube vid</div>
<div id="html5" style="display:none;">my alternate vid</div>
<input type="button" value="switch video" id="click"/>
jquery
$(function(){
$('#click').click(function(){
$('#youtube').toggle();
$('#html5').toggle();
});
});
i also tried this with the js, so the youtube video would be removed & stop playing when the divs are toggled
$(function(){
$('#click').click(function(){
$('#youtube').toggle();
$('#html5').toggle();
$('#youtube').empty();
});
});
this works, but i wasn't sure how to add the youtube video back when toggling back. not really a big deal - just something i was curious about. i'm assuming it can be done with .append.
problem with this is that both of the vids exist in the wordpress page as shortcodes, so it complicates things a bit. i just wrapped the shortdoces in divs with these ids in the wordpress page to get the toggle working, and added the js to my page template. thx again!