I'm trying to loop over every YouTube video in a page (using the iframe embed method) and append to each the title of the video, using jQuery. My HTML looks something like this:
<div class="video-wrapper">
<div class="video-container">
<iframe src="http://www.youtube.com/embed/qzNSsDD_LzE" frameborder="0" allowfullscreen></iframe>
</div>
</div>
<div class="video-wrapper">
<div class="video-container">
<iframe src="http://www.youtube.com/embed/9bZkp7q19f0" frameborder="0" allowfullscreen></iframe>
</div>
</div>
And the jQuery looks like this:
var video = $('.video-container');
video.each(function() {
var youTuberegex = /(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com(?:\/embed\/|\/v\/|\/watch\?v=))([\w-]{10,12})/g,
videoID = youTuberegex.exec($(this).find('iframe').attr('src'))[1];
$.getJSON('http://gdata.youtube.com/feeds/api/videos/'+videoID+'?v=2&alt=jsonc', function(data){
var videoTitle = data.data.title;
video.after('<figcaption>'+videoTitle+'</figcaption>');
});
});
So, I am (trying to) take each video and use a regex to extract the ID. I then use the video feed to retrieve the title, and append it to the video-container.
This is in a jsFiddle. As you can see, the problem is that the title of each video is appended every time. Where am I going wrong, and is this an efficient way to achieve what I am after?
The video variable refers to the entire set of objects that match the selector ".video-container" so when you are doing
video.after('<figcaption>'+videoTitle+'</figcaption>');
It is doing that on each one.
What you need to do is something like:
video.each(function() {
var videoBox = $(this)
var youTuberegex = /(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com(?:\/embed\/|\/v\/|\/watch\?v=))([\w-]{10,12})/g,
videoID = youTuberegex.exec($(this).find('iframe').attr('src'))[1];
$.getJSON('http://gdata.youtube.com/feeds/api/videos/'+videoID+'?v=2&alt=jsonc', function(data){
var videoTitle = data.data.title;
videoBox.after('<figcaption>'+videoTitle+'</figcaption>');
});
});
The videoBox variable points to the specifc div for that video.
Related
I'm trying to create a function that shows a different ID, on load or refresh/ A different video on load.
My main goal is to create a splash intro popup that shows a <section> with youtube video in full screen, As a Section with a video background.
I have 6 different videos and I want each time to load a different video.
So I'm doing this with Elementor.
adding 6 sections, giving each section an ID and inserting a different youtube video background.
I need to do something like document.getElementById('vidz')[0].className+=' add-' + Math.floor((Math.random() * 10) + 1);
I'm bad at JS Please help me.
I have this I want to add a function that shows each time a different ID: section#vidz1/#vidz2/#vidz3/.../#vidz6
and disables the other youtube videos to not load everything at once
function getRandomArrayItem(arr){
var randomKey = Math.floor(Math.random() * arr.length);
var item = arr[randomKey];
return(item);
}
function showRandomString(){
var arrKeys = ["first","second","third","four","five"];
var strItem = getRandomArrayItem(arrKeys);
document.getElementById("output").innerHTML = strItem;
}
window.onload = showRandomString;
If you have a better solution let me know each section loads the youtube
<iframe class="elementor-background-video-embed" frameborder="0" allowfullscreen="1" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" title="YouTube video player" width="640" height="360" src="https://www.youtube.com/embed/qoXa-tTkitg" (more)></iframe>
So one section with a different youtube ID can be faster no?
Thanks
Any HTML in a <template> element is not rendered right away, so you could use that to avoid loading the videos. To keep this simple, you could just put the static content for a single <iframe> into the template and change it depending on the video data selected. For an example, see the snippet I've included below.
The following snippet doesn't run properly on this site, for some reason (assuming sandboxing). But, you can run the same code on jsfiddle and it does actually work.
// Interface w/ HTML
var SELECTORS = {
VIDEO_CONTAINER: '.js-video-container',
VIDEO_TEMPLATE: '.js-video-template',
VIDEO: '.js-video'
};
var VIDEO_DATA_LIST = [
{ src: 'https://www.youtube.com/embed/qoXa-tTkitg' },
{ src: 'https://www.youtube.com/embed/iphcyNWFD10' },
{ src: 'https://www.youtube.com/embed/IvUU8joBb1Q' },
{ src: 'https://www.youtube.com/embed/zGxwbhkDjZM' }
];
function getRandomArrayItem(array) {
return array[Math.floor(Math.random() * array.length)];
}
function insertRandomVideo(templateElement, parentElement, videoSelector, videoDataList) {
var videoData = getRandomArrayItem(videoDataList);
// Create a videoElement from the template
var videoElement = templateElement.content.cloneNode(true).querySelector(videoSelector);
// Add dynamic data to the cloned element
videoElement.src = videoData.src; // NOTE: videoData gets repeated if you use more properties
// Add the cloned element to the parent/container
parentElement.appendChild(videoElement);
}
window.addEventListener('DOMContentLoaded', function(event) {
// Run the function
insertRandomVideo(
document.querySelector(SELECTORS.VIDEO_TEMPLATE),
document.querySelector(SELECTORS.VIDEO_CONTAINER),
SELECTORS.VIDEO,
VIDEO_DATA_LIST
);
});
<div class="js-video-container"></div>
<template class="js-video-template">
<iframe class="js-video elementor-background-video-embed" frameborder="0" allowfullscreen="1" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" title="YouTube video player" width="640" height="360"></iframe>
</template>
Also, here's an alternative version, which I like better. But, before you jump in, let me explain a few things I used, just in case you don't follow...
const is basically var (with different scoping but prevents re-assignment, so I like it for readability)
I used const with functions just to prevent them from being changed in later code.
I used arrow functions in place of "regular" functions - they prevent odd usage of this (when you don't actually NEED to use it in most cases) and I just personally like them because they're shorter.
I put all the selectors at top and made them include a js- prefix so it's easy to follow the hooks from HTML -> JS (also used this above, but added Object.freeze() to, again, prevent changes)
I used object destructuring just to keep things DRY when you add more properties to the video data objects.
Finally, I prefer to inject instead of directly using constants and elements inside a function
First, the jsfiddle, and here's the snippet:
// Interface w/ HTML
const SELECTORS = Object.freeze({
VIDEO_CONTAINER: '.js-video-container',
VIDEO_TEMPLATE: '.js-video-template',
VIDEO: '.js-video',
})
const VIDEO_DATA_LIST = [
{ src: 'https://www.youtube.com/embed/qoXa-tTkitg' },
{ src: 'https://www.youtube.com/embed/iphcyNWFD10' },
{ src: 'https://www.youtube.com/embed/IvUU8joBb1Q' },
{ src: 'https://www.youtube.com/embed/zGxwbhkDjZM' },
]
// (Just shortened this using arrow functions)
const getRandomArrayItem = array =>
array[Math.floor(Math.random() * array.length)]
const insertRandomVideo = (templateElement, parentElement, videoSelector, videoDataList) => {
const { src } = getRandomArrayItem(videoDataList)
// Create a videoElement from the template
const videoElement = templateElement.content.cloneNode(true).querySelector(videoSelector)
videoElement.src = src
// (Can also set other values if you include them in the data list)
parentElement.appendChild(videoElement)
}
window.addEventListener('DOMContentLoaded', event => {
// Run the function
insertRandomVideo(
document.querySelector(SELECTORS.VIDEO_TEMPLATE),
document.querySelector(SELECTORS.VIDEO_CONTAINER),
SELECTORS.VIDEO,
VIDEO_DATA_LIST,
)
})
<div class="js-video-container"></div>
<template class="js-video-template">
<iframe class="js-video elementor-background-video-embed" frameborder="0" allowfullscreen="1" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" title="YouTube video player" width="640" height="360"></iframe>
</template>
I have a script that plays a video in a Modal when a thumbnail gets clicked. This only works with the first video mentioned in the html, so I'm trying to use js to grab the particular video whos thumbnail is clicked on.
I have set up a variable in the js called vidcode, and gave it a value of the first video's address (rLdpnu2dDUY) or whatever it's called. I then set up a value 'start' for the link part before, and 'end' for the link part after. Now I have "showVideo = start + vidcode + end" and then innerHTML = showVideo, which works no problems.
So far the injection part works. My problem now is passing the address of the clicked thumbnail into the vidcode variable to play the corresponding video. I have looked on SO, w3, and Google. I have 6 different tries and none work fully.
I can create a link which
- Sets the variable, but then does not call the script.
- Calls the script but does not pass on the variable.
- Click one thumb to set the variable then another thumb to call the script. That one will then work but it's an extra step. At least with this one I know that the variable is being set..
<!--== Standard button but requires var vidcode to be preset in the Modal script ==-->
<img src="https://img.youtube.com/vi/rLdpnu2dDUY/hqdefault.jpg">
<!--== Add onClick to trigger a mini-script which sets the var vidcode early ==-->
<script>function hDSansxhArU(){var vidcode = 'hDSansxhArU';}</script>
<!--== Adding the javascript directly to the link code, yet it does not trigger the Modal script ===-->
<!--== Adding the javascript directly to the link code, to trigger a mini-script, to then call the modal ===-->
<script>function buttt(){var vidcode = 'duBjWlIzpzQ'; modalviewer();}</script>
<!--== Use the video's code as an id, then calling that id immediately and setting it to var vidcode ==-->
<script>
document.getElementById('hDSansxhArU').onclick = function() {
var vidcode = 'hDSansxhArU';
modalviewer()
};
</script>
Spots are commented out when trying something else
function modalviewer(){ //This function usually isn't here
var start = '<iframe width="840" height="472" src="https://www.youtube.com/embed/';
var end = '" frameborder="0" encrypted-media></iframe>';
//var showVideo = start + vidcode + end;
// This part works fine when vidcode gets a value
document.getElementById("button").addEventListener("click", function() {
document.querySelector(".theVideo").innerHTML = showVideo;
document.querySelector(".bg-modal").style.display = "flex";
});
document.querySelector(".bg-modal").addEventListener("click", function() { //.bg-modal to make the surrounding clickable
document.querySelector(".bg-modal").style.display = "none";
document.querySelector(".theVideo").innerHTML = "";
});
};
Expected results:
Click a link and have either
- set that address to variable 'vidcode', or
- set the address gobbledegook to 'vidcode' from here
and either have the modal script in a separate js file or at the bottom of the page.
As a code-newbie, I'm proud to have figured it out so far (with previous help from SO), it just frustrates me that I can only get half of this to work at a time :/.
#CTOverton provided what was needed, although everyone else and in Stop/Pause video when Modal is closed (not using $ sign) contributed with everything that they got me to look up as well. #Phoenix1355 actually started me on the right path despite me not posting any code at all, in turn leading me to learn so much in very little about Javascript and HTML.
This has been plaguing me for at least a week (I've lost track of time making this website), researching, getting other setups, trying overly-complicated setups, being told it can only be done by paying for a hosting plan or having to use Wordpress.. And this Console.log output, sooo helpful omg. Thank you everyone who contributed!
Here is the finished code:
<html>
<head>
<link href="http://www.jolanxbl.ca/snips/modal.css" rel="stylesheet" />
</head>
<body>
<center>
<br><br><br><br><br>
<!--List of videos-->
<img data-vidcode="rLdpnu2dDUY" src="https://img.youtube.com/vi/rLdpnu2dDUY/hqdefault.jpg" width="200px">
<img data-vidcode="hDSansxhArU" src="https://img.youtube.com/vi/hDSansxhArU/hqdefault.jpg" width="200px">
<img data-vidcode="duBjWlIzpzQ" src="https://img.youtube.com/vi/duBjWlIzpzQ/hqdefault.jpg" width="200px">
</center>
<!-- Modal Section 1 -->
<div class="bg-modal">
<div class="modal-content">
<div class="close">+</div>
<div class="theVideo">
<iframe width="840" height="472" src="https://www.youtube.com/embed/rLdpnu2dDUY" frameborder="0" encrypted-media; picture-in-picture allowfullscreen></iframe>
</div>
</div>
</div>
<script>
let vidcode = 'rLdpnu2dDUY';
// Get all elements with classname 'thumbnail'
let thumbnails = document.getElementsByClassName('thumbnail');
// Loop for every element with class
Array.from(thumbnails).forEach(function(element) {
element.addEventListener('click', thumbnailClicked);
});
function thumbnailClicked(event) {
// Event is mouse click event
// target is the img (as that is what you click on)
// dataset is the data attributes of img
vidcode = event.target.dataset.vidcode;
console.log('vidcode: ', vidcode)
//document.querySelector(".gridContainer").addEventListener("click", function() {
document.querySelector(".theVideo").innerHTML = '<iframe width="840" height="472" src="https://www.youtube.com/embed/' + vidcode + '" frameborder="0" encrypted-media></iframe>';
document.querySelector(".bg-modal").style.display = "flex";
}
document.querySelector(".bg-modal").addEventListener("click", function() { //.bg-modal to make the surrounding clickable
document.querySelector(".bg-modal").style.display = "none";
document.querySelector(".theVideo").innerHTML = "";
});
</script>
</body>
</html>
Based on your description I think you are looking for something along the lines of the "data attribute". Data attributes are custom attributes you can assign to any DOM element that contain essentially whatever you want.
In you case if you have a page with lots of thumbnails and you want a specific action to happen when you click on a specific thumbnail, your best bet is if you store that unique identifier (the video id, or are you put it vidcode) on the element you are clicking on.
This can be done like this:
<body>
<!--List of videos-->
<img data-vidcode="rLdpnu2dDUY" src="https://img.youtube.com/vi/rLdpnu2dDUY/hqdefault.jpg">
<img data-vidcode="example2" src="img2.jpg">
<img data-vidcode="example3" src="img3.jpg">
<script>
let vidcode = 'rLdpnu2dDUY';
// Get all elements with classname 'thumbnail'
let thumbnails = document.getElementsByClassName('thumbnail');
// Loop for every element with class
Array.from(thumbnails).forEach(function(element) {
element.addEventListener('click', thumbnailClicked);
});
function thumbnailClicked(event) {
// Event is mouse click event
// target is the img (as that is what you click on)
// dataset is the data attributes of img
vidcode = event.target.dataset.vidcode;
console.log('vidcode: ', vidcode)
}
</script>
</body>
Try passing the vidcode as an parameter for modalviewer function and then use the value.
function modalviewer(vidcode){
var start = '<iframe width="840" height="472" src="https://www.youtube.com/embed/';
var end = '" frameborder="0" encrypted-media></iframe>';
var showVideo = start + vidcode + end;
document.querySelector(".theVideo").innerHTML = showVideo;
};
<div class="theVideo"></div>
Click
<script>
document.getElementById('hDSansxhArU').onclick = function() {
var vidcode = 'hDSansxhArU';
modalviewer(vidcode)
};
</script>
I was wondering if it is possible to create dynamically multiple YouTube embeds on a page. YouTube video id's where stored in a JSON object.
I was hoping something like this can be created dynamically by the script:
<iframe id="koW2Clc0xEA" frameborder="0" allowfullscreen="1" title="YouTube video player" width="640" height="390" src="https://www.youtube.com/embed/koW2Clc0xEA?enablejsapi=1"></iframe>
I already use the YouTube JavaScript API to load one hero video, I can imagine that I may can use that code as the basic, but it belongs to another part of the site then the hero video.
I prepared a little JsFiddle for you: https://jsfiddle.net/v879x7bm/3/
Create a container in your HTML:
<div id="ytContainer"></div>
JavaScript with jQuery:
var yourJsonAsString = '{"videos":[{"title":"bla bla","id":"no3unQcv_vg"},{"title":"blub","id":"3IHrNcJdP8s"},{"title":"abc","id":"-6v-rwoRv_4"}]}';
var ytVideos = JSON.parse(yourJsonAsString);
for (var i in ytVideos.videos) {
var ytVideo = $("<iframe/>");
ytVideo.attr({
width: 560,
height: 315,
src: 'https://www.youtube.com/embed/' + ytVideos.videos[i].id,
frameborder: 0
});
$("#ytContainer").append(ytVideo);
}
In this example I expected your unserialized object structure is looking like this:
{
"videos":[
{
"title":"bla bla",
"id":"no3unQcv_vg"
},
{
"title":"blub",
"id":"3IHrNcJdP8s"
},
{
"title":"abc",
"id":"-6v-rwoRv_4"
}
]
}
But you can adapt to your needs :)
Imagine that your JSON string that contains the video urls. Here is some code that will work with jQuery. By changing the json_string variable, it will change which videos get loaded to the screen.
<html>
<div id="content_div"></div>
</html>
<script type="text/javascript">
jQuery(function () {
var json_string = '{ "vid1" : "www.vid1.url", "vid2" : "www.vid2.url"}';
//make the string into an object
var json_object = JSON.parse(json_string);
//loop through the json_object and add the new video each time through
for (i in json_object) {
jQuery("#content_div").append('<p><iframe width="420" height="315" src="' + json_object[i] + '"></iframe></p>');
}
});
</script>
JSfiddle here showing the code working, but using a <p> tag instead of the iframe.
I have been scratching my head for a few days now with this one. Just trying to get better at javascript but no one seems to be able to figure out what I am doing wrong here.
What I want is to create a data structure or array containing videos
On page load I would like a random video to be loaded and begin playing
After this I would like the user to be able to click the video to initiate the math.random and generate a new video in its place.
Issues -
1 - With the code I have whenever I click to randomize the video just disappears no console errors or anything.
2 - The page doesn't randomize on load
3 - I am not sure if this is the best way to go about as far as data structure is concerned?
This doesn't seem logically like a hard problem to solve but for me its been a real head scratcher.
Any help is greatly appreciated!!
HTML
<a href="#" class="click">
<section>
<div>
<video loop autoplay>
<source src="videos/1.webm" type="video/ogg">
<source src="videos/1.mp4" type="video/mp4">
Your browser does not support the <code>video</code> element.
</video>
</div>
</section>
</a>
JavaScript
//Array of Videos
var videos = [
[{type:'mp4', 'src':'videos/1.mp4'}, {type:'webm', 'src':'videos/1.webm'}],
[{type:'mp4', 'src':'videos/2.mp4'}, {type:'webm', 'src':'videos/2.webm'}],
];
//onClick + Action
$(function() {
$('a.click').click(function(e) {
e.preventDefault();
var randomIndex = parseInt(Math.random()*videos.length);
$(this).find('videos').append('<source src="'+videos[randomIndex]+'" />');
});
});
//onLoad Randomize
function getRandomVideo() {
var number = Math.floor(Math.random()*video.length);
document.write('<source src="'+videos[number]+'" />');
}
$(function() {
$('a.click').click(function(e) {
e.preventDefault();
console.log("hello world");
var number = Math.floor(Math.random()*videos.length);
$(this).html('<source src="'+videos[number]+'" />');
});
});
Here is working pen http://codepen.io/easingthemes/pen/PwWRdx
<a> tag will break on some browsers around block elements. You don't need <a>.
You need videos[number][index].src because videos[number] is an object.
Also you need to reload video when you change src
$('video').load();
$('video').play();
HTML
<section>
<div>
<video loop autoplay>
<source src="http://html5demos.com/assets/dizzy.mp4" type="video/mp4">
<source src="http://techslides.com/demos/sample-videos/small.webm" type="video/ogg">
Your browser does not support the <code>video</code> element.
</video>
</div>
</section>
JS
var videos = [
[{type:'mp4', 'src':'http://techslides.com/demos/sample-videos/small.mp4'}, {type:'webm', 'src':'http://techslides.com/demos/sample-videos/small.webm'}],
[{type:'mp4', 'src':'http://html5demos.com/assets/dizzy.mp4'}, {type:'webm', 'src':'http://html5demos.com/assets/dizzy.webm'}],
];
$(function() {
$('section').on('click', 'div', function(e) {
var number = Math.floor(Math.random()*videos.length);
$(this).find('source').each(function(index){
videoSrc = videos[number][index].src;
$(this).attr('src', videoSrc);
$('video').load();
$('video').play();
});
});
});
Ok this is an array of array of objects this is a function to change the 1st and second src and type
function getRandomVideo(videos) {
var number = Math.floor(Math.random()*videos.length);
$('.click video source').eq(0).attr('type',videos[number][0].type).attr('src',videos[number][0].src);
$('.click video source').eq(1).attr('type',videos[number][1].type).attr('src',videos[number][1].src);
$('.click video').load();
$('.click video').play();
}
DEMO use this function in any event you want
There are 3 videos, placed in 3 separate div's.
There also are 3 separate div's, but in other position of a page (lets say contA and contB and contC).
I want that if I click on the video1, then video2 and video3 goes to contA and contB, and video1 goes to contC.
If I click video1 again, all videos go back to their original position.
If I click on video2 (while its in contA), then video1 goes to contA, video3 goes to contB, video2 goes to contC.
I have prepared a jsbin demo:
Jsbin DEMO
Anyone could help? Appreciated!
EDIT: (Added a code as requested)
HTML:
<div id="vid1">
<video id="Video1" class="videos">
<source src="http://www.craftymind.com/factory/html5video/BigBuckBunny_640x360.mp4" type="video/mp4"></source>
HTML5 Video is required for this example.
</video>
</div>
<div id="vid2">
<video id="Video2" class="videos">
<source src="http://www.craftymind.com/factory/html5video/BigBuckBunny_640x360.mp4" type="video/mp4"></source>
HTML5 Video is required for this example.
</video>
</div>
<div id="vid3">
<video id="Video3" class="videos">
<source src="http://www.craftymind.com/factory/html5video/BigBuckBunny_640x360.mp4" type="video/mp4"></source>
HTML5 Video is required for this example.
</video>
</div>
<div id="contA"><br>first container<br></div>
<div id="contB"><br>second container<br></div>
<div id="contC"><br>third container<br></div>
JavaScript:
$(window).load(function()
{
//add event for all videos
$('.videos').click(videoClicked);
function videoClicked(e)
{
//get a referance to the video clicked
var sender = e.target;
//get all the videos
var $videos = $('.videos');
$videos.appendTo('#contA');
$videos.appendTo('#contB'); //but I need each video to be put to different div: #contA, #contB...
$videos.not(sender).appendTo('#contC'); //if I put the clicked video into this container, it does not go back to original one.
}
});
Think this is what you're looking for, but it's based on the naming convention used in the example. I also took the liberty of renaming contA/contB and contC to cont1, cont2 and cont3, because it's easier to manipulate.
JSBin demo
//remember last video clicked (you could check last container instead)
var lastclicked;
function videoClicked(e)
{
//get a reference to the video clicked
var sender = e.target;
//get all the videos
var $videos = $('.videos');
if(sender==lastclicked){
//reset to original positions
$.each($videos,function(){
var ind = this.id.substring(this.id.length-1); //based on the video + number naming convention
$(this).appendTo('#vid' + ind);
});
lastclicked = null;
return;
}
lastclicked= sender;
var i = 1;
//place all non clicked videos in cont1/cont2/etc
$.each($videos.not(sender),function()
{
$(this).appendTo('#cont' + i++ );
});
//place the clicked video in the last container
$(sender).appendTo('#cont' + i ); //always cont3 with fixed divs, but this is dynamic in case you add more
}
});
I will edit this answer as the desired results become more clear but i think i can give you some info to get you going in the right direction.
the section of code "but i need each video to be put to a diff cont"
I would leverage a data attribute and let each control keep track of itself.
$video.each(function()
{
var targetdiv = $(this).data('origonal-div');
$(targetdiv.ToString()).append(this);
//optionally update the data value to keep track of the next location to append to.
}
if you need more info post some questions with an update on the jsbin so i can see where you are having trouble.
Cheers