Javascript move multiple elements to separate div's and back - javascript

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

Related

Link or button sets a variable, then calls the script

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>

Calling src from nearest audio tag to JavaScript function without ID

I'm attempting to play multiple locally stored mp3 files on a single html page. I want a single JavaScript function in a separate js file triggered onclick that will play the correct file referenced in the adjacent audio tag. The audio just needs to play through once every time it is tapped/clicked.
I've tried using querySelector and various other techniques to find the nearest audio tag, but it always defaults to the audio tag at the top of the page. How can I limit the scope of querySelect, or is there another method of doing what I want? I don't want to have to create a unique ID for every audio tag because there are dozens of pages like this I am making.
function PlaySound() {
var sound = document.querySelector(".audio");
sound.play()
}
<audio class="audio" src="../../audio/na.mp3" autostart="false"></audio><a onclick="PlaySound()">나</a>
<audio class="audio" src="../../audio/gak.mp3" autostart="false"></audio><a onclick="PlaySound()">각</a>
First of all, you should use a button, not an anchor tag for these. They are buttons, since they only do an action on the page. Links are something that takes you to another page.
Now for your issue: when an event listener is invoked, such as your PlaySound when onclick happens, you can give it a this argument, which is the DOM instance of the button clicked.
Now your audio is a simple previousElementSibling away from grabbing, meaning and you can easily invoke audio.play() on it.
function play (button) {
console.log('Button:', button.innerText)
const audio = button.previousElementSibling
console.log('Audio', audio)
}
<audio src="1"></audio>
<button onclick="play(this)">1</button>
<audio src="2"></audio>
<button onclick="play(this)">2</button>
What you could do is store the information that are held by the audio tags inside a JavaScript array and dynamically create the list of audio and the respective buttons.
var audioList = [{
src: "../../audio/na.mp3",
text: "나"
}, {
src: "../../audio/gak.mp3",
text: "각"
}];
var container = document.querySelector("#container");
audioList.forEach(function(audio) {
var audioElem = document.createElement("audio");
var button = document.createElement("button");
audioElem.setAttribute("autostart", false);
audioElem.setAttribute("src", audio.src);
button.textContent = audio.text;
audioElem.className = "audio";
button.addEventListener("click", getButtonListener(audioElem));
container.appendChild(audioElem);
container.appendChild(button);
});
function getButtonListener(audioElem) {
return function() {
audioElem.play();
console.log("Playing:" + audioElem.src);
};
}
<div id="container"></div>
Or you could just do:
var audioList = {
"나": "../../audio/na.mp3",
"각": "../../audio/gak.mp3"
};
function openAudio(target){
document.querySelector("audio[src='" + audioList[target.textContent] + "']").play();
console.log("Playing: " + audioList[target.textContent]);
}
<audio class="audio" src="../../audio/na.mp3" autostart="false"></audio>
<button onclick="openAudio(this)">나</button>
<audio class="audio" src="../../audio/gak.mp3" autostart="false"></audio>
<button onclick="openAudio(this)">각</button>

How to randomize in pairs?

I'm trying to randomize some videos that are both .webm and .mp4.
I have a two of each video for instance vid1.webm and vid1.mp4
I'd like to have the videos randomize and pull both at the same time into the video tag.
safari doesn't support .webm so that's why i would like to have .mp4 as a backup and need both to randomize into the browser on click.
I am loading them from an array and also can't figure out how the folder structure should be listed out, I would really like to keep them in an array as I am loading in several hundred
var randomImage = new Array();
randomVideo[0] = "videos/1.webm/ or mp4"; //not sure how to do the file structure
randomVideo[1] = "videos/2.webm/ or mp4"; //
randomVideo[2] = "videos/3.webm/ or mp4"; //
//trying to figure out this part
$(function() {
$('a.click').click(function(e) {
e.preventDefault();
var number = Math.floor(Math.random()*randomVideo.length);
$(this).html('<source src="'+randomVideo[number]+'" />');
});
});
$(function() {
$('a.click').click(function(e) {
e.preventDefault();
var number = Math.floor(Math.random()*randomVideo.length);
$(this).html('<source src="'+randomVideo[number]+'" type="video/mp4" /> )
}
})
html
<a href="#" class="click">
<section>
<video controls autoplay>
<script>
randomVideo()
</script>
</video>
</section>
</a>
If anyone can help me figure this out it would be greatly appreciated!
Can't figure it out, still learning.
You have multiple issues. Firstly your array name doesn't match (randomImage and randomVideo). Not sure why you are hooking the click event twice. One approach is to store the common parts of the path in the array and then concatenate the file ending. Also, I have no idea what you were trying to do with the img tag...
Anyway, the code below should help you, if I have understood what you are trying to do correctly.
var randomVideo = new Array();
// define your common video paths here
randomVideo[0] = "videos/1";
randomVideo[1] = "videos/2";
randomVideo[2] = "videos/3";
function randomiseVideos() {
var number = Math.floor(Math.random() * randomVideo.length);
$('#myvid').empty(); // clean up from last time
// now add 2 sources (will fall back appropriately depending on client support)
$('#myvid').append('<source src="' + randomVideo[number] + '.webm" type="video/webm">');
$('#myvid').append('<source src="' + randomVideo[number] + '.mp4" type="video/mp4">');
}
$(function () {
// Randomise on page load
randomiseVideos();
// handle click on test link
$('a.click').click(function (e) {
e.preventDefault();
randomiseVideos();
});
});
HTML:
Test Link
<section>
<video id="myvid" width="320" height="240" controls autoplay></video>
</section>
JS fiddle demo
The video element supports multiple sources https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_HTML5_audio_and_video
A very simple solution would be to store a list of video objects in your array:
var videos = [
[{type:'mpg', 'src':'blah.mpg'}, {type:'webm', 'src':'blah.webm'}],
[{type:'mpg', 'src':'blah2.mpg'}, {type:'webm', 'src':'blah2.webm'}],
];
...
var video = videos[randomIndex];
And use that to output sources like:
<video controls>
<source src="blah.mpg" type="video/ogg">
<source src="blah.webm" type="video/mp4">
Your browser does not support the <code>video</code> element.
</video>

How to randomize video on click and on page load

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

HTML5 Audio Tag Changing Src when finished. jQuery

I have created a audio element with a ul. In the ul is list items which are linked to different songs. I have gotten the song to change when the item is clicked and it all works however i would like the song to also change when the current playing song finishes. Below is my html and js.
HTML:
<div id="mp3_player">
<div id="audio_box">
<audio id="audioPlayer" preload="auto" src="" controls="controls"></audio>
</div>
</div>
<ul id="songSelector">
<li>song1</li>
<li>song2</li>
<li>song3</li>
<li>song4</li>
</ul>
The source doesn't have a value becasuse it is added in another part of my script.
JS:
$(audio).bind('ended', function() {
var testing = $('#songSelector').next().attr('href');
alert(testing);
})
The alert returns undefined when the song finished when it should return the link on the next li element. I just cant figure out what i am doing wrong.
Thanks in advanced.
Right now, $('#songSelector').next() is going to whatever is after #songSelector in the dom. You probably need to keep track of which one is "current" in another variable.
var currentSong = $('#songSelector').find('a:first');
$(audio).bind('ended', function() {
var next = currentSong.next();
if ( next.length ) {
currentSong = next;
} else {
/* uncomment this if you want it to loop back to the beginning */
// currentSong = $('#songSelector').find('a:first');
}
var testing = currentSong.attr('href');
alert(testing);
});
Then you just need to update currentSong in your click handler as well.

Categories

Resources