Play a random video on button click - javascript

I should start by saying I'm not good with JS and I'm still trying to learn it.
I have 10 mp4s and I need to play one at random on a button click. I'm having trouble making it happen and I've searched around for a solution but to no avail.
Here's what I have so far:
HTML
<div class="videoHolder">
<video id="video" autoplay muted>
Your browser does not support the video tag.
</video>
</div>
<button type="button" name="button">Push to Play</button>
JS
var videos = [
"mp4s/video1.mp4",
"mp4s/video2.mp4",
"mp4s/video3.mp4",
"mp4s/video4.mp4",
"mp4s/video5.mp4",
"mp4s/video6.mp4",
"mp4s/video7.mp4",
"mp4s/video8.mp4",
"mp4s/video9.mp4",
"mp4s/video10.mp4",
];
var videoId = 0;
var elemVideo = document.getElementById('video');
var elemSource = document.createElement('source');
elemVideo.appendChild(elemSource);
elemVideo.addEventListener('ended', play_next, false);
function play_next() {
if (videoId == 10) {
elemVideo.stop();
} else {
video.pause();
elemSource.setAttribute('src', videos[videoId]);
videoId++;
elemVideo.load();
elemVideo.play();
}
}
play_next();
</script>
This unfortunately doesn't do what I need. This code will play all 10 videos one after the other on page load, then stop. I need it to only play one of the random 10 videos when someone pushes the "Push to Play" button. And I need it to keep going after 10.
Like I said I'm not good with JS at all and I was able to find this code from browsing around and modifying it a bit.

This should work for you.
<div class="videoHolder">
<video id="video" autoplay muted src="">
</video>
</div>
<button id='playRandom' type="button" name="button">Push to Play</button>
This is a really basic implementation of what you want
var videos = [
"mp4s/video1.mp4",
"mp4s/video2.mp4",
"mp4s/video3.mp4",
"mp4s/video4.mp4",
"mp4s/video5.mp4",
"mp4s/video6.mp4",
"mp4s/video7.mp4",
"mp4s/video8.mp4",
"mp4s/video9.mp4",
"mp4s/video10.mp4"
];
var videoId = getRandomInt(0, 9);
var elemVideo = document.getElementById('video');
elemVideo.setAttribute('src', '/' + videos[videoId]);
var btn = document.getElementById('playRandom');
btn.addEventListener('click', function (e) {
var nextId = getRandomInt(0, 9);
if (nextId != videoId) {
playNext(nextId);
} else {
while (nextId == videoId) {
nextId = getRandomInt(0, 9);
}
playNext(nextId);
}
});
/* gets random whole number between 0 and 9 */
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function playNext(id) {
elemVideo.setAttribute('src', '/' + videos[id]);
elemVideo.play();
}
This is a more robust implementation that includes a history of previously played videos so you don't play the same videos over again.
var videos = [
"mp4s/video1.mp4",
"mp4s/video2.mp4",
"mp4s/video3.mp4",
"mp4s/video4.mp4",
"mp4s/video5.mp4",
"mp4s/video6.mp4",
"mp4s/video7.mp4",
"mp4s/video8.mp4",
"mp4s/video9.mp4",
"mp4s/video10.mp4"
];
var playedVideos = [];
var videoId = getRandomInt(0, 9);
var elemVideo = document.getElementById('video');
elemVideo.setAttribute('src', '/' + videos[videoId]);
var btn = document.getElementById('playRandom');
btn.addEventListener('click', playRandom);
function playRandom(e) {
var nextId = getRandomInt(0, 9);
if (nextId != videoId) {
if (!playNext(nextId)) {
playRandom(e);
}
} else {
while (nextId == videoId) {
nextId = getRandomInt(0, 9);
}
if (!playNext(nextId)) {
playRandom(e);
}
}
}
/* gets random whole number between 0 and 9 */
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function playNext(id) {
// checks if the video has already been played
for (var src in playedVideos) {
if (src == videos[id]) {
return false;
}
}
elemVideo.setAttribute('src', '/' + videos[id]);
elemVideo.play();
// adds src to arr of played videos
playedVideos.push(videos[id]);
/*
* Everything from here on is optional depending on whether you want to
* - iterate over the arr of videos and play each videos at least once before starting over or
* - you want to stop playing videos after playing each at least once
*/
// empties the played videos arr and allows you to start playing a new set of random videos
if (playedVideos.length() == 10) {
playedVideos = [];
// if you'd like to stop playing videos altogether at this, point delete the previous statement and display a prompt saying the playlist is over
// or if you'd like to reset the playlist, then remove the event listener ('playRandom') and display a reset button that starts everything over from the beginning.
}
return true;
}

Related

JS random order showing divs delay issue

I got function within JS which is supposed to show random order divs on btn click.
However once the btn is clicked user got to wait for initial 10 seconds ( which is set by: setInterval(showQuotes, 10000) ) for divs to start showing in random order which is not ideal for me.
JS:
var todo = null;
var div_number;
var used_numbers;
function showrandomdivsevery10seconds() {
div_number = 1;
used_numbers = new Array();
if (todo == null) {
todo = setInterval(showQuotes, 10000);
$('#stop-showing-divs').css("display", "block");
}
}
function showQuotes() {
used_numbers.splice(0, used_numbers.length);
$('.container').hide();
for (var inc = 0; inc < div_number; inc++) {
var random = get_random_number();
$('.container:eq(' + random + ')').show();
}
$('.container').delay(9500).fadeOut(2000);
}
function get_random_number() {
var number = randomFromTo(0, 100);
if ($.inArray(number, used_numbers) != -1) {
return get_random_number();
} else {
used_numbers.push(number);
return number;
}
}
function randomFromTo(from, to) {
return Math.floor(Math.random() * (to - from + 1) + from);
}
Question: How to alter the code so upon the btn click divs will start showing right away without initial waiting for 10 seconds? (take in mind I want to keep any further delay of 10 seconds in between of each div being shown)
Thank you.
Call it when you begin the interval
todo = setInterval((showQuotes(),showQuotes), 10000);

Audio on JavsScript when a certain condition is met

I am making a blackjacks game right now and I am having trouble on getting audio in the code, I want it to play audio when a certain condition is met, I want it to pick up an audio file from a local file, and I also want it to autoplay, how can I achieve this? Thanks.
Here is my javascript code:
//adding the cards together, with parameter passing
function cardNumber(one, two) {
var cardTotal = one + two;
alert(`Your card numbers are ${one} and ${two}!`);
return cardTotal;
}
var cardRange = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var cardOne = cardRange[Math.floor(Math.random() * cardRange.length)];
var cardTwo = cardRange[Math.floor(Math.random() * cardRange.length)];
//calling the cardNumber function (parameter passing shown)
var cardSum = cardNumber(cardOne, cardTwo);
//adding the cards together if the user wants an extra card, with parameter passing
function moreCards(nextCard, total) {
alert(`Your extra card is ${nextCard}!`);
var cardTotal = nextCard + total;
return cardTotal;
}
function inputValidation() {
var i;
for (i = 0; i < 3;) {
//Asks the user if they want another card, they can do this up to three times, depending on their choice and card sum.
var input = prompt(`Which makes your card total ${cardSum}. Would you like to draw another card? (Type in 1 for yes, 0 for no, or select cancel to return to home.)`);
if (input === null) {
//takes you back to pontoonhome.html
window.location.replace("pontoonhome.html").src = "homepage";
i += 3;
}
//Random number doesn't change
else if (input === "1") {
i++;
var extraCard = cardRange[Math.floor(Math.random() * cardRange.length)];
//calling the moreCards function
cardSum = moreCards(extraCard, cardSum);
}
else if (input === "0") {
//If the user declines to another card
i += 3;
}
else {
//If the user puts in an invalid input
alert("Wrong input, enter 1 or 0 on your keyboard!");
}
if (cardSum >= 22) {
//If the user gets above 22 (bust)
i += 3;
}
}
}
function pontoonDecision() {
var comScore = 18;
if (cardSum >= 22) {
alert("BUST!");
document.write(`You got ${cardSum}, which is above 21, that means you got a bust! Therefore, you lose!`);
document.getElementById("loss").src = "images/dislike-157252_640.png";
}
else if (cardSum > comScore && cardSum < 22) {
document.write(`You got ${cardSum}, and the AI player got ${comScore}, which means you win! <br>`);
document.getElementById("victory").src = "images/hand-157251_640.png";
//where I want the audio to play.
let audio = document.getElementById("winner").src = "audio/winner.wav";
audio.autoplay();
//not sure how to do it right
}
else if (cardSum === comScore) {
document.write(`You got ${cardSum}, and the AI player got ${comScore}. Which means it is a tie!`);
document.getElementById("draw").src = "images/questions-3409194_640.png"
}
else {
document.write(`You got ${cardSum}, and the AI player got ${comScore}. You got a value lower than the computer's score, meaning you lose!`);
document.getElementById("loss").src = "images/dislike-157252_640.png";
}
}
inputValidation();
pontoonDecision();
Here is my HTML code:
<!DOCTYPE html>
<html>
<head>
<title>Game</title>
<link rel = "stylesheet" href = "css/styles.css">
<body>
<div class ="title">
<h1>Pontoon</h1>
</div>
<div class ="hyperlinks">
Home
Rules
Start
Contact Us
</div>
<div class="header">
<h2>Game</h2>
</div>
<img id = "victory"></img>
<img id = "loss"></img>
<img id = "draw"></img>
<audio controls autoplay>
<audio id = "winner"></audio>
<!--The audio I want to play^^^-->
</audio>
<a href id = "homepage"></a>
<br>
<script src = "js/pontoonGame3.js">
</script>
<div class = "wrapper">
Exit
Play Again
</div>
</body>
</head>
</html>
let audio = document.getElementById("winner").src = "audio/winner.wav";
You're assigning audio to the contents of src, which is "audio/winner.wav".
Make this two separate statements.
let audio = document.getElementById("winner");
audio.src = "audio/winner.wav";
autoplay is a property of an Audio object, not a function. So calling audio.autoplay() is invalid. You should call play() instead.
let audio = document.getElementById("winner");
audio.src = "audio/winner.wav";
audio.play();
First of all, create a folder audio in the same place as your code (recommended), then include all of the audios you need here
In your HTML, using <audio> tag for each of the audio file, make sure to give them unique IDs to query later:
<audio src="link-to-your-audio.mp3" id="your-audio"></audio>
In your script, just like any other elements, query all the audio tags
const yourAudio = document.getElementById('your-audio');
To play the audio, use .play() or .pause() to stop it, like so:
yourAudio.play();
yourAudio.pause();

Loading/Buffering text while loading audio in html5 custom player with JavaScript

I found a custom html5 audio player and successfully redesigned it, now I want to add a "loading/buffering" text while player is loading audio (otherwise users may freak out because nothing happening after they hit play).
Here is the code to explain:
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.substr(0, 2),
time = minutes + ':' + seconds
return time;
}
function calculateCurrentValue(currentTime) {
var current_hour = parseInt(currentTime / 3600) % 24,
current_minute = parseInt(currentTime / 60) % 60,
current_seconds_long = currentTime % 60,
current_seconds = current_seconds_long.toFixed(),
current_time = (current_minute < 10 ? "0" + current_minute : current_minute) + ":" + (current_seconds < 10 ? "0" + current_seconds : current_seconds);
return current_time;
}
function initProgressBar() {
var player = document.getElementById('player');
var length = player.duration
var current_time = player.currentTime;
// calculate total length of value
var totalLength = calculateTotalValue(length)
jQuery(".end-time").html(totalLength);
// calculate current value time
var currentTime = calculateCurrentValue(current_time);
jQuery(".start-time").html(currentTime);
var progressbar = document.getElementById('seekObj');
progressbar.value = (player.currentTime / player.duration);
progressbar.addEventListener("click", seek);
if (player.currentTime == player.duration) {
$('#play-btn').removeClass('pause');
}
function seek(evt) {
var percent = evt.offsetX / this.offsetWidth;
player.currentTime = percent * player.duration;
progressbar.value = percent / 100;
}
};
function initPlayers(num) {
// pass num in if there are multiple audio players e.g 'player' + i
for (var i = 0; i < num; i++) {
(function() {
// Variables
// ----------------------------------------------------------
// audio embed object
var playerContainer = document.getElementById('player-container'),
player = document.getElementById('player'),
isPlaying = false,
playBtn = document.getElementById('play-btn');
// Controls Listeners
// ----------------------------------------------------------
if (playBtn != null) {
playBtn.addEventListener('click', function() {
togglePlay()
});
}
// Controls & Sounds Methods
// ----------------------------------------------------------
function togglePlay() {
if (player.paused === false) {
player.pause();
isPlaying = false;
$('#play-btn').removeClass('pause');
} else {
player.play();
$('#play-btn').addClass('pause');
isPlaying = true;
}
}
}());
}
}
initPlayers(jQuery('#player-container').length);
Player code (source) on CodePen
I want some text will be shown in the same "span" that shows
"start time" (please see CodePen) while media is loading;
The text " 'loading.' 'loading..' 'loading...' " must changing on
loop while media is loading;
When it is loaded the "loading" text must be changing on "start
time" as it is now.
So basically I wat to put some text in start time while it is not shows anything but zeroes
I'm new to JS
Thats why I need some help or point to right direction
You can use the "readyState" event of the audio player to show hide loading.
There is already a "SetInterval" even which is getting fired so in that we can add this code to show/hide the "Loading"
1st add the loading element(You can put it where ever you want"
<h3 id="loading" style="display:none;">Loading</h3>
Now let's add the code to check "readystate" inside "SetInterval"
if(player.readyState>0&&player.readyState<4){
$("#loading").show();
}
else{
$("#loading").hide();
}
You can read more about "readystate" here
/As per the request I have changed the code to use the start time as loading, to make it work we don't have to add anything inside html but need to do some changes in JS
First, add this inside "togglePlay" functions pay condition in the "else" block.
$(".start-time").html("Loading...");
After this inside "initProgressBar()" function replace the "jQuery(".start-time").html(currentTime);" with the below code
if (player.readyState === 4) {
jQuery(".start-time").html(currentTime);
}
so how it will work, When you click play button the start time text will show as "Loading" but once the file is loaded and the player is ready to play the text will be changed to "start time", Hope it works. Also updated the CodePen for better understanding
You can find the full code in the CodePen
You could use setInterval to cycle through the different 'loading' text and clearInterval when the player's play promise is done.
Here's a basic example:
var dots = 1;
var loading = setInterval(function(){
dots = (dots % 3) + 1;
$(".start-time").text("Loading" + Array(dots + 1).join("."));
console.log($(".start-time").text());
}, 250);
player.play().then(function() {
clearInterval(loading);
}).catch((error) => {
$(".start-time").text("Error loading");
});

inner html in javascript not working

I have an audio file and a javascript for it.
The javascript displays percentage of the audio buffered, if no buffered occurs it displays loading...
function loop2() {
var audio2 = document.getElementById("atwo1");
var percentages = document.getElementsByClassName("atwo1l")
var buffered = audio2.buffered;
var loaded;
if (buffered.length) {
loaded = 100 * buffered.end(0) / audio2.duration;
if (loaded.toFixed(2) != '0') {
percentages[0].innerHTML = 'Loading: ' + loaded.toFixed(2) + '%';
} else {
percentages[0].innerHTML = 'Loading....';
}
}
setTimeout(loop2, 50);
}
loop2();
<audio id="atwo1" controls="controls">
<source src="https://docs.google.com/uc?export=download&id=19gLpR7J8TVHmooVbM23eK5Xq0f9YXNZf">
</audio>
<p><span class="atwo1l"></span></p>
But for the above code, it does not displays loading...
When we place small audio file it will display. So why not for large files?
Update:
Found a partial answer (updated codes)
Why a partial answer?
All comments together in an answer
function loop2() {
var audio2 = document.getElementById("aone1"),
percentages = document.getElementsByClassName("aone1l"),
buffered,
loaded;
if (audio2 && percentages) { // if both elements are found in the DOM
buffered = audio2.buffered;
if (buffered.length) {
loaded = 100 * buffered.end(0) / audio2.duration;
if (loaded.toFixed(2) != '0') {
percentages[0].innerHTML = 'Loading: ' + loaded.toFixed(2) + '%';
}
if(loaded >= 1){
audio2.classList.remove('un-buffered');
}
} else { // handle the case where the buffered.length is 0 or undefined
percentages[0].innerHTML = 'Loading....';
}
}
setTimeout(loop2, 50);
}

HTML5 Audio Tag - Start and end at position

I have a number of <audio> tags in my code and I would like to know if there is a way that I can set each one to have a custom start and end position as they all load the same file.
This should happen without user interaction. effectively I need to deploy and <audio> tag and have something like data-start="04.22" data-end="09.45"
There is a timerange parameter available in MediaElement's src attribute which does exactly this.
://url/to/media.ext#t=[starttime][,endtime]
Note that if you enable the controls on these elements, then the user will be able to seek to different positions.
Example :
var url = 'https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg';
var slice_length = 12;
var audio, start, end;
for (var i = 0; i < 10; i++) {
start = slice_length * i; // set the start
end = slice_length * (i + 1); // set the end
// simply append our timerange param
audio = new Audio(url + '#t=' + start + ',' + end);
audio.controls = true; // beware this allows the user to change the range
document.body.appendChild(document.createTextNode(start + 's ~ ' + end + 's'));
document.body.appendChild(document.createElement('br'));
document.body.appendChild(audio);
document.body.appendChild(document.createElement('br'));
}
The following is what your looking for. I have four options from which you can choose from each with a bit less difficulty than the one before. I recommend the last one based on what you needed.
The start time is in seconds and in this example it is 12 seconds. Instead of a end time you have a play time and this is in milliseconds.
myAudio=document.getElementById('audio2');
myAudio.addEventListener('canplaythrough', function() {
if(this.currentTime < 72){this.currentTime = 72;}
this.play();
setTimeout(function(){
document.getElementById('audio2').pause();
}, 3000);
});
<audio id="audio2"
preload="auto"
src="https://upload.wikimedia.org/wikipedia/commons/f/f0/Drum.ogg" >
<p>Your browser does not support the audio element</p>
</audio>
If you really want to have an end time you can write a function that will take your input and subtract it from start time and convert it into millisecond.
An example of that is seen below:
var startTime = 72;
var endTime = 75;
var delaySec = endTime - startTime;
var delayMillis = delaySec * 1000;
myAudio=document.getElementById('audio2');
myAudio.addEventListener('canplaythrough', function() {
if(this.currentTime < startTime){this.currentTime = startTime;}
this.play();
setTimeout(function(){
document.getElementById('audio2').pause();
}, delayMillis);
});
<audio id="audio2"
preload="auto"
src="https://upload.wikimedia.org/wikipedia/commons/f/f0/Drum.ogg" >
<p>Your browser does not support the audio element</p>
</audio>
In this one you can set both the start time and end time in seconds.
Or you could do this with the start time in minutes and seconds.
var startMinute = 1;
var startSecond = 12;
var endMinute = 1;
var endSecond = 15;
var startinsec = startMinute * 60;
var startTime = startinsec + startSecond;
var endinsec = endMinute * 60;
var endTime = endinsec + endSecond;;
var delaySec = endTime - startTime;
var delayMillis = delaySec * 1000;
myAudio=document.getElementById('audio2');
myAudio.addEventListener('canplaythrough', function() {
if(this.currentTime < startTime){this.currentTime = startTime;}
this.play();
setTimeout(function(){
document.getElementById('audio2').pause();
}, delayMillis);
});
<audio id="audio2"
preload="auto"
src="https://upload.wikimedia.org/wikipedia/commons/f/f0/Drum.ogg" >
<p>Your browser does not support the audio element</p>
</audio>
Here is another one which should actually be easier for you to do since you have multiple files:
audioControl('audio2', 1, 12, 1, 15);
function audioControl(elemID,sM, sS, eM, eS) {
var startinsec = sM * 60;
var startTime = startinsec + sS;
var endinsec = eM * 60;
var endTime = endinsec + eS;;
var delaySec = endTime - startTime;
var delayMillis = delaySec * 1000;
myAudio=document.getElementById(elemID);
myAudio.addEventListener('canplaythrough', function() {
if(this.currentTime < startTime){this.currentTime = startTime;}
this.play();
setTimeout(function(){
document.getElementById(elemID).pause();
}, delayMillis);
});
}
<audio id="audio2"
preload="auto"
src="https://upload.wikimedia.org/wikipedia/commons/f/f0/Drum.ogg" >
<p>Your browser does not support the audio element</p>
</audio>
Anytime you want to do it you just run the following:
audioControl(ElementID, StartMinute, StartSecond, EndMinute, EndSecond);
See this answer for how to play an audio file at a certain time:
HTML 5 <audio> - Play file at certain time point

Categories