playing sound on if statement - javascript

I am looking for a way to play a sound on an if-statement.
To be exact. I want a sound to be automatically played, when the amount of attempts have reached 3.
Is there a way to get this to work?
// guesses
function testbutton() {
attempt++;
document.getElementById("alarm").innerHTML = "guess" + attempt;
}
// guess set to zero
var attempt = 0;
// sound functions
if (attempt == 3) {
var sound20 = new Audio('http://commondatastorage.googleapis.com/codeskulptor-assets/Collision8-Bit.ogg');
var playSound = function() {
sound20.play();
}
};
playSound();
<button onclick="testbutton();">Test</button>
<p id="alarm"></p>

Put the if statement inside the function, after you increment attempt.
// guesses
function testbutton() {
attempt++;
document.getElementById("alarm").innerHTML = "guess" + attempt;
if (attempt == 3) {
playSound();
};
}
// guess set to zero
var attempt = 0;
// sound functions
var playSound = function() {
var sound20 = new Audio('http://commondatastorage.googleapis.com/codeskulptor-assets/Collision8-Bit.ogg');
sound20.play();
}
<button onclick="testbutton();">Test</button>
<p id="alarm"></p>

Related

JS: setInterval running as if there were multiple intervals set

So, I've been trying to figure out JS, and what better way to do so than to make a small project. It's a small trivia game, and it has a question timer I've made using setInterval. Unfortunately, after answering multiple questions, the interval's behaviour gets very weird - it runs the command twice every time. I guess it's my faulty implementation of buttonclicks?
By the way, if my code is awful I am sorry, I've been desperate to fix the issue and messed with it a lot.
function startGame(){
if (clicked === true){
return;
}
else{
$("#textPresented").html("Which anthem is this?");
$("#button").css("display", "none");
currentCountry = getRndInteger(0,8);
console.log(currentCountry);
var generatedURL = anthemnflags[currentCountry];
console.log(generatedURL);
audios.setAttribute("src", generatedURL);
audios.play();
$("#button").html("I know!");
$("#button").css("display", "block");
$("#button").click(function () {
continueManager();
});
y=10;
console.log("cleared y" + y);
x = setInterval(function(){
y = y - 1;
console.log("Counting down..." + y)
}, 1000);
console.log("INTERVAL SET");
}
}
Here is the console output:
cleared y10 flaggame.js:59:17
INTERVAL SET flaggame.js:64:17
AbortError: The fetching process for the media resource was aborted by the user agent at the user's request. flaggame.js:49
Counting down...9 flaggame.js:62:20 ---- THESE TWO ARE BEING PRINTED AT THE SAME TIME
Counting down...8 flaggame.js:62:20 ---- THESE TWO ARE BEING PRINTED AT THE SAME TIME
Counting down...7 flaggame.js:62:20
Counting down...6 flaggame.js:62:20
Counting down...5 flaggame.js:62:20
Counting down...4 flaggame.js:62:20
Counting down...3 flaggame.js:62:20
Counting down...2 flaggame.js:62:20
Counting down...1 flaggame.js:62:20
Counting down...0
THE REST OF MY CODE:
function middleGame(){
$("#button").css("display", "none");
var n = document.querySelectorAll(".flagc").length;
correctIMG = getRndInteger(0,n-1);
showFlags();
var taken = new Array();
for (var i = 0; i < n; ++i){
if (i === correctIMG){
images[i].attr("src", "res/" + flagsfiles[currentCountry]);
taken[currentCountry] = true;
}
else{
var randomFlag = getRndInteger(0, flagsfiles.length);
if (randomFlag !== currentCountry && taken[randomFlag] !== true){
images[i].attr("src", "res/" + flagsfiles[randomFlag]);
taken[randomFlag] = true;
}
}
}
$(".flagc").click(function(){
clickregister(this);
});
}
function continueManager(){
if (!clicked){
audios.pause()
clearInterval(x);
x = 0;
clicked = true;
middleGame();
return;
}
}
function clickregister(buttonClicked){
if ($(buttonClicked).attr("id") != correctIMG){
points = points - 1;
flagARR[$(buttonClicked).attr("id")].css("display", "none");
console.log("INCORRECT");
}
else{
if (y >= 0) {
var addedPoints = 1 + y;
points = points + addedPoints;
$("#points").html(points);
}
else{
points = points + 1;
}
hideFlags();
clicked = false;
startGame();
}
}
$(function(){
hideFlags();
$("#textPresented").html("When you're ready, click the button below!");
$("#button").html("I am ready!");
$("#button").click(function () {
if (!gameStarted){
gameStarted = true;
alert("STARTING GAME");
startGame();
}
});
});
Basically this is how it works:
When the "I am ready" button is clicked, startGame() is called. It plays a random tune and counts down, until the player hits the "I know" button. That button SHOULD stop the interval and start the middleGame() function, which shows 4 images, generates a random correct image and awaits input, checks if it's true, then launches startGame() again.
The first and second cycles are perfect - after the third one things get messy.
I also noticed that the "INCORRECT" log gets printed twice, why?
EDIT: here is the minimized code that has the same issue:
var x;
var gameStarted = false;
var y;
var clicked;
$(function(){
$("#button").click(function () {
if (!gameStarted){
gameStarted = true;
startGame();
}
});
});
function startGame(){
console.log("startgame()");
if (clicked === true){
return;
}
else{
console.log("!true");
$("#button").css("display", "block");
$("#button").click(function () {
continueManager();
});
y=10;
x = setInterval(function(){
y = y - 1;
console.log(y);
}, 1000);
}
}
function continueManager(){
if (!clicked){
clearInterval(x);
x = 0;
clicked = true;
middleGame();
return;
}
}
function middleGame(){
$("#button").css("display", "none");
var taken = new Array();
$(".flagc").click(function(){
clickregister(this);
});
}
function clickregister(buttonClicked){
console.log("clickgregister");
//Irrelevant code that checks the answers
clicked = false;
startGame();
}
EDIT2: It appears that my clickregister() function gets called twice, and that function then calls startGame() twice.
EDIT3: I have found the culprit! It's these lines of code:
$(".flagc").click(function(){
console.log("button" + $(this).attr("id") + "is clicked");
clickregister(this);
});
They get called twice, for the same button
I fixed it!
It turns out all I had to do was to add
$(".flagc").unbind('click');
Before the .click() function!
You need to clear the interval first then call it again. You can do that by creating a variable outside of the event listener scope and in the event listener check if the variable contains anything if yes then clear the interval of x. After clearing the interval you can reset it.
Something like this:
<button class="first" type="submit">Button</button>
const btn = document.querySelector('.first');
let x;
btn.addEventListener("click", () => {
x && clearInterval(x)
x = setInterval(() => console.log("yoo"), 500)
})
This is because if you don't clear the interval of x it will create a new one on every button press.

javascript change background and play sound with one button

I'm building a clock inspired from the link below with added features like the single party button will play a music and change the BodyBGcolor per second.
https://codepen.io/codifiedconcepts/pen/bwgxRq
The music plays and pauses fine, but the BG starts changing but doesn't stop if I click to pause, and starts flickering and gets faster if I click the button again.
var partyTime = false;
var catMusic = new Audio("media/party.mp3");
function partyEvent() {
// partyTime and catMusic are defined outside
// otherwise they get re-defined without changing the old definition
if (partyTime === false) {
partyTime = true;
catMusic.play();
partyBtn.innerHTML = "PARTY OVER";
} else {
partyTime = false;
catMusic.pause();
partyBtn.innerHTML = "PARTY TIME";
}
}
var i = 0;
function changeBG() {
var color = ["red", "blue", "brown", "green"];
document.body.style.backgroundColor = color[i];
i = (i + 1) % color.length;
if (partyTime === true) {
var initBG = setInterval(changeBG, 1000);
} else {
clearInterval(initBG);
}
}
I have another function which changes the BGcolor 5 times in a day, for morning, noon, evening etc.. as a switch statement, I'm showing one case here..
switch (true) {
case hour <= 5:
imgTxt.innerHTML = "GET SOME SLEEPZ BRO";
catImg.style.background = "url('img/earlyMorning.jpg')";
catImg.style.backgroundSize = "cover";
document.body.style.backgroundColor= "#2d3037";
clockBody.style.color = "#99ffcc";
break;
please help this noob, and sorry for the indentation, it gets all same after pasting here..
if (partyTime === true) {
var initBG = setInterval(changeBG, 1000);
} else {
clearInterval(initBG);
}
Here you are creating initBG local to if block. In the else block initBG is undefined so it does not stop the interval process.
Solution: Define initBG outside the partyEvent function.
var initBG;
if (partyTime === true) {
initBG = setInterval(changeBG, 1000);
} else {
clearInterval(initBG);
}

Javascript Closure functions

So I'm new to javascript and I am looking for a way to count how many times a function is executed. The code randomly generates a square or circle and displays from the shape is shown to when you click it (reactionTime). That works fine and dandy.
But I'm looking for a way to keep track of the number of times a shape is clicked and then eventually the cumulative time to calculate average time per click. If it helps, I come from a pretty good C++ background.
To count number of clicks, I was thinking of adding a closure function.
From here: How do I find out how many times a function is called with javascript/jquery?
myFunction = (function(){
var count = 0;
return function(){
count++
alert( "I have been called " + count + " times");
}
})();
And from here: Function count calls
var increment = function() {
var i = 0;
return function() { return i += 1; };
};
var ob = increment();
But I tried a global variable and several variations of closure functions to no avail (look for the comments). I tried putting the closure function in other functions. And I also tried something like:
var increment = makeBox();
I'm wondering if anyone can guide me in the right direction. It would be much appreciated!
var clickedTime; var createdTime; var reactionTime;
var clicked; var avg = 0;
avg = (avg + reactionTime) / clicked;
document.getElementById("clicked").innerHTML = clicked;
document.getElementById("avg").innerHTML = avg;
function getRandomColor() {
....
}
function makeBox() { // This is the long function that makes box
createdTime = Date.now();
var time = Math.random();
time = time * 3000;
///////// var increment = function () {
var i = 0;
//return function() { return i += 1; };
i++;
return i;
///////// };
// clicked++; /////////// global variable returns NaN
// console.log(clicked);
// alert("Clicked: "+clicked);
setTimeout(function() {
if (Math.random() > 0.5) {
document.getElementById("box").style.borderRadius="75px"; }
else {
document.getElementById("box").style.borderRadius="0px"; }
var top = Math.random(); top = top * 300;
var left = Math.random(); left = left * 500;
document.getElementById("box").style.top = top+"px";
document.getElementById("box").style.left = left+"px";
document.getElementById("box").style.backgroundColor = getRandomColor();
document.getElementById("box").style.display = "block";
createdTime = Date.now();
}, time);
}
ob = increment(); //////////////////////// I think this gives me 1 every time
alert("Increment: "+ob); //////////////////
document.getElementById("box").onclick = function() {
clickedTime = Date.now();
reactionTime= (clickedTime - createdTime)/1000;
document.getElementById("time").innerHTML = reactionTime;
this.style.display = "none";
makeBox();
}
makeBox();
You have a few problems but to answer your question:
You're not defining clicked as a number (or any other type) so trying to perform an operation on undefined returns NaN...because well, it's not a number.
Your second attempt var i = 0; won't work because i is re-defined on each function call.
You should be able to use your gobal variable clicked as long as you set it to zero.
Here is an example that shows how a closure can count calls to a function:
function add5(y) {
//A totally normal function
return y + 5;
}
var counter = 0, /*a counter scoped outside of the function counter function*/
trackedAdd5 = (function (func) {
/*This anonymous function is incrementing a counter and then calling the function it is passed*/
return function () {
counter++;
/*The trick is this function returns the output of calling the passed in function (not that it is applying it by passing in the arguments)*/
return func.apply(this, arguments);
}
})(add5); /*calling this tracking function by passing the function to track*/
document.getElementById('run').addEventListener('click', function () {
/*Here we are treating this new trackedAdd5 as a normal function*/
var y = document.getElementById('y');
y.value = trackedAdd5(parseInt(y.value, 10));
/*Except the outer counter variable now represents the number of times this function has been called*/
document.getElementById('counter').value = counter;
});
<label> <code>y = </code>
<input id='y' value='0' />
<button id='run'>add5</button>
</label>
<br/>
<label><code>add5()</code> was called
<input readonly id='counter' value='0' />times</label>
makeBox.click = 0; // define the function's counter outside the function
makeBox.click++; // replace the `i` usage with this inside the function
About ob = increment();: it is used erroneously (redefines ob many times);
var ob = increment(); // define it once
ob(); // increments the counter
// another way to define `increment`:
var increment = (function () {
var i = 0;
return function () {
return i += 1;
};
})();
ob = increment(); // ob becomes 1 initially
ob = increment(); // ob becomes 2, etc.

Countdown timer that refreshes depending on the data I receive by a WebSocket

I want to build a 10-seconds JQuery Countdown-Timer with a WebSocket that refreshes every second. It should reset the timer at x seconds (depending on the data I get from the WebSocket). If I get data for a specific timer, it should start over and counting down from 10s again, but only for this specific timer.
If one of these timers drops to 0, the countdown should stop completely.
At the moment I use setInterval for demonstration reasons, but I want to implement this timers to the WebSocket as mentioned: http://jsfiddle.net/alexiovay/azkdry0w/5/
JavaScript:
var setup = function(){
$('.count').each(eachSetup);
};
var eachSetup = function(){
var count = $(this);
var sec = count.data('seconds') ;
count.data('count', sec);
};
var everySecond = function(){
$('.count').each(eachCount);
};
var eachCount = function(){
var count = $(this);
var s = count.data('count');
count.text(s);
s--;
if(s < 0) {
s = 0;
}
count.data('count', s);
};
setup();
setInterval(everySecond, 1000);
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p class="count" data-seconds="5"></p>
<p class="count" data-seconds="10"></p>
<p class="count" data-seconds="15"></p>
My WebSocket starts like this and refreshes every second:
var socket = io.connect('http://localhost:8000');
socket.on('notification', function (data) {
$.each(data.rows,function(index,row){
...
If you're getting, say, data.user and data.seconds from the socket, you could do the following:
var timers = []; // Creates an array to store your timers
socket.on('notification', function(data) { // Listen for 'notification' from socket
if(timers.length > 0) {
for(i in timers) {
if(timers[i][0] === data.timer) {
timers[i][1] = 10; // If timer for data.user already exists, set it to 10 seconds again.
} else {
timers.push([data.timer, data.seconds]); // Else, create it with data.seconds seconds
}
}
} else {
timers.push([data.timer, data.seconds]);
}
}
function timerCount() {
for(i in timers) {
if(timers[i][1] <= 0) {
delete timers[i]; // If timer seconds is less than 0, delete it.
} else {
timers[i][1]--; // Else, decrease it by 1 second.
}
}
}
setInterval(timerCount, 1000); // Runs the timerCount() function every second.

Javascript game - increment fires more than once

I am building simple "Spot the difference" game in jQuery/HTML. There are 5 rounds/stages, each with different pictures and user needs to go through all of them starting from round 1.
I am having this issue with increment firing twice when I am in 2nd round, and then triple times when I am in 3rd round and so on. This cause points to jump up double/triple/... instead of just jump up by 1.
The code is on baby level. I did not make any stuff to refactor it and improve.
I think I don't need to provide HTML for this, as simply looking at logic in JS file should be enough.
For those who prefer pastebin version is here (http://pastebin.com/ACqafZ5G). Full code:
(function(){
var round = 1;
var points = 0;
var pointsTotal = 0;
var pointsDisplay = $(".js-calc");
var pointsTotalDisplay = $(".js-calc-total");
var counterDisplay = $(".js-counter");
var entryPage = $(".entry-page");
var mainMenu = $(".main-menu");
var submitNow = $(".js-now");
var submitResultsFinalBtn = $(".js-submit-results-final");
// rounds-categories
var allRounds = $(".round");
var divRound1 = $(".round1"),
divRound2 = $(".round2"),
divRound3 = $(".round3"),
divRound4 = $(".round4"),
divRound5 = $(".round5");
var allPic = $(".js-pic");
var pic1 = $(".js-pic1"),
pic2 = $(".js-pic2"),
pic3 = $(".js-pic3"),
pic4 = $(".js-pic4"),
picFinish = $(".js-finish");
// on the beginning hide all and leave only entry page
mainMenu.hide();
allRounds.hide();
submitResultsFinalBtn.hide();
// countdown (SEE THE FUNCTION ON THE END)
var myCounter = new Countdown({
seconds: 60, // number of seconds to count down
onUpdateStatus: function(sec){
counterDisplay.html(sec); // display seconds in html
}, // callback for each second
onCounterEnd: function(){
console.log('TIME IS OVER!');
// THIS SHOULD NOT BE HERE, I WOULD PREFER TO MOVE IT SOMEWHERE TO GAME ITSELF
pointsTotalDisplay.html(pointsTotal);
round++; // update to next round
allRounds.hide(); // hide window
mainMenu.show(); // show back again main menu
} // final action
});
var initiateRound = $(".js-initiate");
initiateRound.on("click", function(){ // START GAME
console.log("ROUND " + round + " INITIATED");
points = 0; // reset the points for this round to 0 - not sure this is the way to do it...
console.log(points + " points for this round, " + pointsTotal + " in TOTAL"); // say how many points so far
entryPage.hide();
mainMenu.hide();
allPic.hide();
if( round === 1){
divRound1.show();
pic1.show();
}else if( round === 2){
divRound2.show();
pic2.show();
}else if( round === 3){
divRound3.show();
pic3.show();
}else if( round === 4){
divRound4.show();
pic4.show();
}else if( round === 5){
divRound5.show();
picFinish.show();
initiateRound.hide();
submitNow.hide();
submitResultsFinalBtn.show();
}
counterDisplay.html("60"); //display 60sec on the beginning
myCounter.start(); // and start play time (countdown)
// pointsDisplay.html(points); // display in HTML amount of points for particular round
// if user start collecting points, add them
var mapImage = $('.transparent AREA');
mapImage.each(function(index) {
// When clicked, reveal red circle with missing element
$(this).one("click", function(e) { // YOU CAN CLICK ONLY ONCE!! Using .one() to prevent multiple clicks and eventually scoring more points
e.stopPropagation();
console.log("FIRED");
var theDifference = '#'+$(this).attr('id')+'-diff';
$(theDifference).css('display', 'inline');
if ($(theDifference).data('clicked', true)){ // found circle
// points++;
points += 1;
pointsTotal++;
console.log(points + " points for this round, " + pointsTotal + " in TOTAL");
pointsDisplay.html(points); // display in html amount of points
}
if (points === 6){ // if all points collected (max 6) for this round
myCounter.stop(); // stop countdown
console.log("time stopped, you found all");
setTimeout(function(){ // give him 2sec delay to see last circle marked
allRounds.hide(); // hide window
mainMenu.show(); // show back again main menu
console.log("round " + round + " is finished");
round++; // update to next round
console.log("round " + round + " is activated");
pointsTotalDisplay.html(pointsTotal); // display in HTML total amount of pints
}, 2000);
};
});
});
});
})();
function Countdown(options) {
var timer,
instance = this,
seconds = options.seconds || 10,
updateStatus = options.onUpdateStatus || function () {},
counterEnd = options.onCounterEnd || function () {};
function decrementCounter() {
updateStatus(seconds);
if (seconds === 0) {
counterEnd();
instance.stop();
}
seconds--;
}
this.start = function () {
clearInterval(timer);
timer = 0;
seconds = options.seconds;
timer = setInterval(decrementCounter, 1000);
};
this.stop = function () {
clearInterval(timer);
};
}
Are you sure you're not stacking the $('.transparent AREA') from a round to another ?
This would explain why you score multiple times:
var mapImage = $('.transparent AREA');
mapImage.each(function(index) {
// ...
points++;
// ...
});
Solved!
mapImage.each should be outside of initiateRound

Categories

Resources