play through an array of audio files onclick - javascript

I have an array of audio files that I want to play through whenever I click a button. If I click said button, it will play the next audio file in the array. Also, if audio is currently playing when the user clicks again, the current track is reset and the next song plays.
Trying to figure out why I can't cycle through the array I currently have.
var song1 = $("#sound-1");
var song2 = $("#sound-2");
var song3 = $("#sound-3");
var song4 = $("#sound-4");
var song5 = $("#sound-5");
var song6 = $("#sound-6");
var song7 = $("#sound-7");
var song8 = $("#sound-8");
var audioArray = [ song1, song2, song3, song4, song5, song6, song7, song8 ];
$(".click").click(function(){
var i=0;
if (i< audioArray.length){
audioArray[i].trigger('play');
i++;
} else if ( i>audioArray.length){
i = 0;
audioArray[i].trigger('play');
};
});

Updated answer:
Since you are using the native HTML5 interface, there is a pause event that can be triggered as well. Unfortunately, there is no stop event that would reset the time, however we can set it to 0 manually using the currentTime property.
var i=0;
var lastPlayedFile = null;
$(".click").click(function(){
if(lastPlayedFile !== null) {
lastPlayedFile[0].currentTime = 0; // [0] because we need a native DOM element, not a jQuery-wrapped one
lastPlayedFile.trigger('pause');
}
if (i< audioArray.length){
lastPlayedFile = audioArray[i];
audioArray[i].trigger('play');
i++;
} else if (i>=audioArray.length){ // there was a missing '=' in this condition to work properly
i = 0;
lastPlayedFile = audioArray[0];
audioArray[i].trigger('play');
};
});
Here is a fiddle I created. I've tested it in Chrome and it works flawlessly.
I suggest looking at the audio tag reference to see what more you can achieve by manipulating the native DOM audio element.
Original answer:
Move declaration of i outside the click handler.
var i=0;
$(".click").click(function(){
if (i< audioArray.length){
audioArray[i].trigger('play');
i++;
} else if ( i>audioArray.length){
i = 0;
audioArray[i].trigger('play');
};
});
You were resetting it's value to 0 each time user clicked the button.

Related

How can I put off everything in my code until a button is clicked?

Working on a JavaScript program, and the first thing that happens when run is asking the user whether they want to enter something using prompt()s, or using a textarea. The textarea option comes with a clickable button element to press once the user has entered everything they want into the textarea.
If this option is chosen, I want the rest of my program to not run until this button is clicked, and the user is confirming that they are finished with their input. Currently I have the button code within the selection part (where the user has chosen to use a textarea), as below:
if (trimmedResponse == 'manual') {
... (irrelevant code)
} else { //if paste is chosen
var createArray = function(howMany){
var pasteInput = document.createElement("TEXTAREA");
var makingArray = [];
document.body.appendChild(pasteInput);
pasteInput.rows = howMany;
let done = document.createElement("button");
done.innerHTML = 'Enter terms';
done.onclick = function(){
for (var j = 0; j < howMany; j++){
makingArray[j] = String((pasteInput.value).replace(/ /g,'').split('-')).split('\n');
}
pasteInput.style.display = 'none';
done.style.display = 'none';
}
document.body.appendChild(done);
return makingArray;
}
termArray = window.createArray(numOfTerms); //getting a variable holding the array from the prior function, to access later
}
The rest of the script.js file is made up of the regular subroutines - preload, setup, draw, and some initialisation and other small methods in the open scope before preload(), as below in a greatly reduced format:
let BG;
let translateEdit = document.createElement("button");
translateEdit.innerHTML = "Edit a translation";
translateEdit.style.position = 'absolute';
translateEdit.style.left = '50px';
translateEdit.style.top = '130px';
let list = "";
translateEdit.onclick = function () {
this.blur();
do {
replaceChoice = prompt("Which translation do you want to edit? (1-"+numOfTerms+") \n"+list+" \nOr enter any letter to leave this screen.");
} while (replaceChoice < 1 || replaceChoice > termArray.length)
termArray[replaceChoice-1][1] = prompt("What is the new translation for the term "+termArray[replaceChoice-1][0]+"?");
list = "";
for (let i = 0; i < numOfTerms ; i++){
list += ((i+1)+". ["+termArray[i][0] + "] - [" + termArray[i][1] + "]\n") //adds each term and translation in a user-friendly / clear display to the list variable for later display
}
alert("The term list currently looks as follows: \n"+list);
};
document.body.appendChild(translateEdit);
let temp1;
let temp2;
let temp3;
var performanceDisplay = "";
function preload() { //function loading image from file into variable
Helvetica = loadFont('Helvetica-Bold.ttf');
BG = loadImage('images/background.png');
}
function setup() { //function to create display/background using image file and dimensions and instantiate objects (character,terms,counters) as well as slider and icon to be displayed for it
alert("Below are the terms you have entered: \n" + list + "If any of the above are incorrect, use the edit buttons on the next screen to adjust terms or translations.");
speakericon = loadImage('images/speaker.png');
createCanvas(width, height);
... (further code in setup())
}
function draw() { //make background + objects visible on screen, allow them to act as they must, creating new terms when necessary, calling functions in class files such as player movement (calls all functions in classes throughout function) - all run every tick
image(BG, 0, 0, width, height); //set the display to the background image from BG variable in preload()
... (further code in draw())
}
In essence, I need to stop everything else from running until the button 'done' is clicked, and would appreciate any help with anything to achieve this.

Browser Extension's creating dynamic buttons with dynamic links

I'm trying to create a browser extension popup (in JS) that creates a number of buttons with links that open up different webpages. The function takes a number of parameters, the main one being b_link which is an array of URL's to the website. For some reason, only the last URL in array is applied to all of the buttons that are created.
I'm not entirely sure what the problem is, I could speculate but I don't think that would be productive. One thing I did notice and had to compensate for was using b_link in the lambda function. Just using b_link[i], the lambda function only saw undefined so no webpage opened, but using var tmpLink = b_link[i]; at least gets the link into the function and allows a webpage to open.
How should I make these buttons so that they all have their own links, rather than only the last one in the array?
The function in question:
function createSiteButton(numBtns, b_id, b_class, b_text, b_link, b_bg)
{
// check if the input text is an array
if (Array.isArray(b_text))
{
// create the new set of buttons
for (i= 0; i < numBtns; i++)
{
var newButton = document.createElement('button');
var tmpLink = b_link[i];
newButton.id = b_id;
newButton.class = b_class;
newButton.innerHTML = b_text[i];
newButton.style.background = b_bg;
newButton.addEventListener("click", function()
{
if (tmpLink)
{
window.open(tmpLink, "_blank");
}
});
button_array[i] = newButton;
}
// add the new buttons the screen
for (i= 0; i < numBtns; i++)
{
divID.appendChild(button_array[i]);
}
}
}
I found a way to do this via creating an a element, setting href via a.href = tmpLink and appending the button to the a element as a child. The final function is:
function createSiteButton(numBtns, b_id, b_class, b_text, b_link, b_bg)
{
var outputElem = document.getElementById('output');
// check if the input text is an array
if (Array.isArray(b_text))
{
//var tmpLink = null;
// create the new set of buttons
for (i= 0; i < numBtns; i++)
{
var a = document.createElement('a');
var newButton = document.createElement('button');
var tmpLink = b_link[i];
newButton.id = b_id;
newButton.class = b_class;
newButton.innerHTML = b_text[i];
newButton.style.background = b_bg;
a.href = tmpLink;
a.appendChild(newButton);
divID.appendChild(a);
button_array[i] = newButton;
}
}
}

how to exit from a function in javascript?

I am using this codepen template
https://codepen.io/stevethorson/pen/nisBh for quiz competition. I have 10 div elements all are set to display none except the first div, when this timer gets reset, it will change my next div display and hide the previous div display.
how to stop that timer resetting when it complete 10 resets and make my 10th div not to hide? all the id of div are in array.
the changes i made at the bottom of js code in that template is,
var Timer;
let ids=["aq","bq","cq","dq","eq","fq","gq","hq","iq","jq"];
var i=0;
var j=1;
$(document).ready(function() {
var callbackFunction = function(){
Timer.reset(2);
i+=1;
j+=1;
$('h3').html('Question Number:'+j+'');
document.getElementById(ids[i-1]).style.display = "none";
document.getElementById(ids[i]).style.display = "";
};
Timer = new radialTimer(callbackFunction);
Timer.init("timer", 2);
});
so i want my last div to appear permanently
Timer.start(t);
while (j >2) {
timer.stop(a); // name that callback function as a and if it gets incremented i,e resetted untill some reseets, just use while loop and stop that funcion a.
}
}
}
var Timer;
let ids=["aq","bq","cq"];
var i=0;
var j=1;
$(document).ready(function() {
var callbackFunction = function(a){ //function a
Timer.reset(2);
i+=1;
j+=1;
$('h3').html('Question:'+j+'');
document.getElementById(ids[i-1]).style.display = "none";
document.getElementById(ids[i]).style.display = "";
};
Timer = new radialTimer(callbackFunction);
Timer.init("timer", 2);
});

How do I make an Array of Buttons out of this in JS? And How do I set Random Images with this?

So I`m trying to make a Memory Game. At the moment I´m trying to set the Image of the card randomly but my code just changes to top Image.
var images = ["url(IMG1.jpg)","url(IMG2.jpg)"...];
var randomIMG =0;
var card = "<div class='flip-card'><div class='flip-card-inner'><div class='flip-card-front'><button id='button'onclick='Flipfront(this)'style='width:300px;height:300px; marign:50px; background-image:url(Frontpage.jpg);'></button></div><div class='flip-card-back'><button id='button2'onclick='Flipback(this)'style='width:300px;height:300px; marign:50px; background-image:images[randomIMG];background-repeat:no-repeat;background-size:contain;'></button></div></div></div>"
for (let i = 0; i < level; i++) {
document.querySelector("#container").innerHTML +=card;
}
function RandomBG(){
for (let i = 0; i<level;i++){
randomIMG = Math.floor(Math.random()*9)+0;
document.getElementById("button2").style.backgroundImage = images[randomIMG];
}
}
function Flipfront(el){
RandomBG();
el.closest('.flip-card').classList.add('flipped');
flipped++;
}
And Also for later on, how do I put all my Buttons into an array?
In this line
document.getElementById("button2").style.backgroundImage = images[randomIMG];
you are setting the background of button2. You need to ensure that you get the correct element:
function RandomBG(el){
for (let i = 0; i<level;i++){
randomIMG = Math.floor(Math.random()*9)+0;
el.style.backgroundImage = images[randomIMG];
}
}
and that you pass it:
function Flipfront(el){
RandomBG();
el.closest('.flip-card').classList.add('flipped');
flipped++;
}
If all you are trying to do is get all the buttons in the page:
let btns = document.querySelectorAll("button");
And if you want a few specific ones, change the css selector.

Event handler causes many alerts

I am working on a Phonegap app, in which I access device's contacts. I then store upto 10 contacts in window.localStorage. To do so, when the user select a button, I create a div which has three elements.
An image (contact icon that represents male/female contact)
The name of the contact
Another image (represents 'add' sign to add it to window.localStorage)
I then associate an event handler, which will first check if the contact already exists in the localStorage and then proceed to add the contact. Here is the code
function checkDuplicate(somevalue)
{
for(var i=0;i<10;i++) {
if(window.localStorage.getItem(i)!=null) {
if(window.localStorage.getItem(i)==somevalue) {
navigator.notification.alert('Entry exists at Button:'+i);
return false;
}
}
}
//chosenButton is a global variable
window.localStorage.setItem(chosenButton,somevalue);
document.getElementById('contactNumberField').textContent=somevalue;
}
//Problem is with the event listener attached to span2. Please read below
function addContact(item)
{
var parentDiv = document.getElementById('thelist');
var childDiv = document.createElement('li');
var span1 = document.createElement('span');
span1.style.float='left';
span1.innerHTML = "<img src='keypad-contact.png'/>";
var span2 = document.createElement('span');
span2.style.float='right';
span2.innerHTML="<img src='keypad-addcontact.png'/>";
span2.addEventListener('click',function({checkDuplicate(item.number);},false);
childDiv.textContent=item.name;
childDiv.style.color='white';
childDiv.appendChild(span1);
childDiv.appendChild(span2);
parentDiv.appendChild(childDiv);
}
function onSuccess(contacts)
{
var objArray = new Array();
for(var i=0; i<contacts.length;i++) {
var tempObj = new Object();
tempObj['name']=contacts[i].displayName;
tempObj['number']=contacts[i].phoneNumbers[0].value;
objArray.push(tempObj);
}
objArray.sort(
function(a,b){
var nameA = a.name.toLowerCase(),nameB=b.name.toLowerCase();
if(nameA < nameB) return -1;
else if(nameA > nameB) return 1;
return 0;
});
for(var i=0; i<objArray.length;i++) addContact(objArray[i]);
}
function onDeviceReady()
{
var options = new ContactFindOptions();
options.multiple=true;
var field = ["displayName","phoneNumbers"];
navigator.contacts.find(field, onSuccess, function(){alert('NA');}, options);
}
Problem
When I try to add a contact which is already present in window.localStorage, for my first touch on span2, I get one alert. If I try to add again by touching it for the second time, I get two alerts.. and this goes on. The trouble is with the event handler associated with span2. However, I don't know how to over come this situation. How can I ensure that irrespective of how many times I press span2, I get alert only once. How to remove the event handler as soon as it is fired?
Please help.
Fixed:
The issue was not with adding event handlers dynamically. I happen to use iScroll (cubiq) for my project and that caused the trouble. Now I am not receiving multiple alerts. The trick is to declare the globlal scroller variable only once.
var scroller = null;
and then in the function
if(!scroller) scroller = new iScroll('scrollableDiv');
I hope this could be a useful tip for people who are using iScroll and struggling with multiple alerts like me.

Categories