I created a whack a mole game. However, I am trying to add the Price is Right theme to the background as the user plays the game. Is there anything I need to add to the javascript to make this happen? I have the mp3 file saved inside of a sounds folder.
Here is the index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Whack A Mole</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>Whack a Skeletor!</h1>
<h2>Your Score:</h2>
<h2 id="score">0</h2>
<h2>Seconds Left:</h2>
<h2 id="time-left">60</h2>
<div class="grid">
<div class="square" id="1"></div>
<div class="square" id="2"></div>
<div class="square" id="3"></div>
<div class="square" id="4"></div>
<div class="square" id="5"></div>
<div class="square" id="6"></div>
<div class="square" id="7"></div>
<div class="square" id="8"></div>
<div class="square" id="9"></div>
</div>
<script src="app.js"></script>
</body>
</html>
Here is the JavaScript file
const squares = document.querySelectorAll('.square');
const mole = document.querySelector('.mole');
const timeLeft = document.querySelector('#time-left');
const score = document.querySelector('#score');
let result = 0;
let hitPosition;
let currentTime = 60;
let timerId = null;
let evilLaugh = new Audio('sounds/laugh.mp3');
evilLaugh.volume = 0.3;
function randomSquare() {
squares.forEach((square) => {
square.classList.remove('mole');
});
let randomSquare = squares[Math.floor(Math.random() * 9)];
randomSquare.classList.add('mole');
hitPosition = randomSquare.id;
}
squares.forEach((square) => {
square.addEventListener('mousedown', () => {
if (square.id == hitPosition) {
result++;
score.textContent = result;
hitPosition = null;
}
});
});
function moveMole() {
timerId = setInterval(randomSquare, 500);
}
moveMole();
function countDown() {
currentTime--;
timeLeft.textContent = currentTime;
if (currentTime == 0) {
clearInterval(countDownTimerId);
clearInterval(timerId);
alert('GAME OVER! Your final score is ' + result);
evilLaugh.play();
}
}
let countDownTimerId = setInterval(countDown, 1000);
Here is the CSS file
* {
background-color: black;
color: red;
}
.square {
width: 200px;
height: 200px;
border-style: solid;
border-color: lime;
}
.grid {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-content: center;
width: 618px;
height: 618px;
}
.mole {
background-image: url(skeletor.jpeg);
background-size: cover;
}
What you're doing with evilLaugh is the same thing that you would do with your Price is Right sound. The only addition would be that we would need some way to repeat the song each time it ends, which is well covered in this Stack Overflow question. So you could do:
let myPriceAudio = new Audio('sounds/nameOfFile.mp3');
myPriceAudio.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
myPriceAudio.play();
The linked Stack Overflow question does say that all major browsers support myPriceAudio.loop = true;, so you could also do that instead of the .addEventListener() functionality.
Related
let doorLeft = document.getElementById("left");
let doorMiddle = document.getElementById("middle");
let doorRight = document.getElementById("right");
let resetButton = document.getElementById("reset");
let numberOfClicks = 0;
function incrementClicks() {
numberOfClicks++;
console.log('Number of clicks: ' + numberOfClicks)
}
/* -------------------------------------------------------------------------- */
/* handle click door only once */
/* -------------------------------------------------------------------------- */
const revealDoorColour = () => {
doorLeft.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorMiddle.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorRight.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
};
/* -------------------------------------------------------------------------- */
const reset = () => {
doorLeft.style.backgroundColor = "paleturquoise";
doorRight.style.backgroundColor = "paleturquoise";
doorMiddle.style.backgroundColor = "paleturquoise";
revealDoorColour();
resetButton.innerHTML = "Let's play";
};
resetButton.addEventListener("click", function() {
reset();
numberOfClicks = 0;
});
.container.main {
display: flex;
justify-content: space-around;
padding: 0 20%;
}
.door {
height: 500px;
width: 300px;
margin: 10px;
}
#left {
background-color: paleturquoise;
}
#middle {
background-color: paleturquoise;
}
#right {
background-color: paleturquoise;
}
.score {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<title>Door guesser</title>
<script src="./js/main.js" async></script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container main">
<div class="door" id="left">
</div>
<div class="door" id="middle">
</div>
<div class="door" id="right">
</div>
</div>
<div class="container score">
<div class="currentScoreGroup">
<div>Current score: </div>
<div id="currentScore">0</div>
</div>
<div class="bestScoreGroup">
<div>Best score: </div>
<div id="bestScore">0</div>
</div>
<button class="reset" id='reset'>Let's play </button>
</div>
</body>
</html>
Following Extract function from addEventListener I've added the {once:true} parameter which seems to work fine most of the time. However, when clicking on the div in question, it randomly gets fired multiple times (at the same x/y coordinates). How is this possible? I set a breakpoint in the anonymous function and it runs through it multiple times. Any ideas?
To replicate the issue
Click Let's play
Click any card
click Let's play once again
Click a different card
Now you should see 2 entries (clicks) in the console
The once option of addEventListener work like this:
once
A Boolean indicating that the listener should be invoked at most once after being added.
If true, the listener would be automatically removed when invoked.
So if a div is not clicked, its handler still stay there. When you click play again, you basically add more event listener to the div. What why it randomly gets fired multiple times (at the same x/y coordinates)
To fix that, just remove the event listener in reset
let doorLeft = document.getElementById("left");
let doorMiddle = document.getElementById("middle");
let doorRight = document.getElementById("right");
let resetButton = document.getElementById("reset");
let numberOfClicks = 0;
function incrementClicks() {
numberOfClicks++;
console.log('Number of clicks: ' + numberOfClicks)
}
/* -------------------------------------------------------------------------- */
/* handle click door only once */
/* -------------------------------------------------------------------------- */
const revealDoorColour = () => {
doorLeft.removeEventListener("click", incrementClicks);
doorMiddle.removeEventListener("click", incrementClicks);
doorRight.removeEventListener("click", incrementClicks);
//
doorLeft.addEventListener("click", incrementClicks, { once: true });
doorMiddle.addEventListener("click", incrementClicks, { once: true });
doorRight.addEventListener("click", incrementClicks, { once: true });
};
/* -------------------------------------------------------------------------- */
const reset = () => {
doorLeft.style.backgroundColor = "paleturquoise";
doorRight.style.backgroundColor = "paleturquoise";
doorMiddle.style.backgroundColor = "paleturquoise";
revealDoorColour();
resetButton.innerHTML = "Let's play";
};
resetButton.addEventListener("click", function() {
reset();
numberOfClicks = 0;
});
.container.main {
display: flex;
justify-content: space-around;
padding: 0 20%;
}
.door {
height: 500px;
width: 300px;
margin: 10px;
}
#left {
background-color: paleturquoise;
}
#middle {
background-color: paleturquoise;
}
#right {
background-color: paleturquoise;
}
.score {
text-align: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<title>Door guesser</title>
<script src="./js/main.js" async></script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container main">
<div class="door" id="left">
</div>
<div class="door" id="middle">
</div>
<div class="door" id="right">
</div>
</div>
<div class="container score">
<div class="currentScoreGroup">
<div>Current score: </div>
<div id="currentScore">0</div>
</div>
<div class="bestScoreGroup">
<div>Best score: </div>
<div id="bestScore">0</div>
</div>
<button class="reset" id='reset'>Let's play </button>
</div>
</body>
</html>
I have a few URLs that each show the status of some industrial equipment. I'm trying to create an HTML/Javascript solution that, on load, cycles through each of the websites at a set interval, with two buttons to stop the cycle (to take a closer look at something) and restart the cycle (either from the beginning or where it left off, I'm not picky). I'm REALLY rusty, but I got what I think is a good start. Unfortunately, it doesn't work. Here are the CSS and HTML:
html,
body {
height: 100vh;
width: 100vw;
}
#btStart {
position: absolute;
width: 50px;
height: 40px;
left: 20px;
top: 50px;
}
#btStop {
position: absolute;
width: 50px;
height: 40px;
left: 20px;
top: 120px;
}
#infoFrame {
width: 100%;
height: 100%;
}
.holder {
width: 100%;
height: 100%;
position: relative;
}
<!DOCTYPE HTML>
<html>
<head>
<title>Info Cycle</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="main.css" rel="stylesheet">
</head>
<body>
<div class="holder">
<iframe src="" id="infoFrame" frameborder="0" allowfullscreen>
<script type="text/javascript">
var urlArray = ['url1.com',
'url2.com',
'url3.com',
'url4.com',
'url5.com'];
var count = 0;
var i = document.getElementById('infoFrame');
var u = document.getElementById('url');
var timer = setInterval(cycleTimer, 5000);
function nextUrl() {
url = urlArray[++count];
count = (count >= urlArray.length - 1)? -1 : count;
return url;
}
function cycleTimer() {
u.innerHTML = '';
i.src = nextUrl();
i.onload = function(){
u.innerHTML = i.src;
}
}
</script>
</iframe>
<button type="button" id="btStart" onclick="var timer = setInterval(cycleTimer, 5000);">Start</button>
<button type="button" id="btStop" onclick="clearInterval(timer)";>Stop</button>
</div>
</body>
<footer>
</footer>
</html>
Before I added the buttons it would load, then 5 seconds later it would cycle correctly, and so on. Now it only shows the buttons. Looking at the requests, I believe what's happening in my CSS and structure is trash, and it's loading the appropriate URL, but not displaying. I should add, prior to the buttons I only had the iframe with the script in it as a proof of concept. I div'd it, added the stylesheet, and added the buttons, and now here we are.
This may be a rookie mistake, or something more complicated. I haven't done development in a long time, and I'm just trying to solve a little problem at work. If you could spare a minute, I'd be happy to know how to fix this, and also any feedback on what I could be doing better. I'd love to get back into doing more of this, so I'm interested to learn anything the community can share. I've searched the site and the internet, and I've found a couple of related solutions but nothing for this in particular.
Thanks!
EDIT:
In case it helps, below is the HTML before the buttons and stylesheet, which worked (it rotated between webpages every 7 seconds):
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Info Cycle</title>
</head>
<body>
<iframe id="frame" src=""
style="
position: fixed;
top: 0px;
bottom: 0px;
right: 0px;
width: 100%;
border: none;
margin: 0;
padding: 0;
overflow: hidden;
z-index: 999999;
height: 100%;
"></iframe>
<script type="text/javascript">
var urlArray = ['url1.com',
'url2.com',
'url3.com',
'url4.com',
'url5.com'];
var count = 0;
var i = document.getElementById('frame');
var u = document.getElementById('url');
var timer = setInterval(cycleTimer, 7000);
function nextUrl() {
url = urlArray[++count];
count = (count >= urlArray.length - 1)? -1 : count;
return url;
}
function cycleTimer() {
u.innerHTML = '';
i.src = nextUrl();
i.onload = function(){
u.innerHTML = i.src;
}
}
</script>
</body>
</html>
The iframe style was something I found in an old file I'd written (probably copied and pasted from Stack Overflow to just get a thing to work).
The problem here is having the script inside the iframe. If you move your script out of the iframe and put it under body or head then it will work.
<!DOCTYPE HTML>
<html>
<head>
<title>Info Cycle</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="main.css" rel="stylesheet">
<script type="text/javascript">
var urlArray = ['url1.com',
'url2.com',
'url3.com',
'url4.com',
'url5.com'];
var count = 0;
var timer = setInterval(cycleTimer, 5000);
function nextUrl() {
url = urlArray[++count];
count = (count >= urlArray.length - 1) ? -1 : count;
return url;
}
function cycleTimer() {
var i = document.getElementById('infoFrame');
var u = document.getElementById('url');
u.innerHTML = '';
i.src = nextUrl();
i.onload = function () {
u.innerHTML = i.src;
}
}
</script>
</head>
<body>
<div class="holder">
<iframe src="" id="infoFrame" frameborder="0" allowfullscreen>
</iframe>
<button type="button" id="btStart" onclick="var timer = setInterval(cycleTimer, 5000);">Start</button>
<button type="button" id="btStop" onclick="clearInterval(timer)" ;>Stop</button>
</div>
</body>
<footer>
</footer>
</html>
I'm trying to get the two players to take turns in my tic-tac-toe project. In my playerContols function I've tried to put each player in a "current PLayer" housing variable that will switch out depending if one player went already but it just gets stuck on player 2 and just mark every cell with O's. I'm not entirely sure what's wrong with it
my code
const playgame = (() => {
const playerOne = {
Name: 'playerOne',
Marking: 'X'
};
const playerTwo = {
Name: 'PlayerTwo',
Marking: 'O'
};
function playerControls(e) {
let currentPlayer;
currentPlayer = playerOne;
e.target.textContent = currentPlayer.Marking;
if (currentPlayer === playerOne) {
currentPlayer = playerTwo;
e.target.textContent = currentPlayer.Marking;
} else {
currentPlayer = playerOne;
e.target.textContent = currentPlayer.Marking;
}
}
return {
playerControls
}
})();
const gameBoard = (() => {
const makeBoard = (rows, cols) => {
const theBoard = document.getElementById("GameBoard");
theBoard.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
theBoard.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
for (i = 0; i < (rows * cols); i++) {
let gameDivs = document.createElement("div");
gameDivs.addEventListener("click", playgame.playerControls)
theBoard.appendChild(gameDivs).classList.add("newdivgrid");
}
};
makeBoard(3, 3);
})();
#GameBoard {
width: 600px;
height: 350px;
border: 1px solid darkblue;
margin-left: 27%;
text-align: center;
font-size: 500%;
font-family: cursive, sans-serif;
display: grid;
}
.newdivgrid {
border: 1px solid black;
grid-row-gap: 50px;
}
.newdivgrid:hover {
background-color: aqua;
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic-Tac-Toe game</title>
<link rel="stylesheet" href="Tic-Tac-Toe.css">
</head>
<h1>Tic-Tac-Toe Project</h1>
<div id="PlayerSelectionContainer">
<h2>Select Players</h2>
<div class="Player1">
<h3>Player 1</h3>
<div class="playerSelectionButtons" data-player="playerOne">
<button data-player="human">Human</button>
<button data-player="computer">Computer</button>
</div>
</div>
<div class="Player2">
<h3>Player 2</h3>
<div class="playerSelectionButtons" data-player="playerTwo">
<button data-human-player="human">Human</button>
<button data-computer-player="computer">Computer</button>
</div>
</div>
</div>
<div id="GameBoard">
</div>
<div id="resultContainer">
<h3>Results</h3>
<div class="player1Results">
<h3>Player 1 Results</h3>
<textarea placeholder="0" disabled></textarea>
</div>
<div class="Player2Results">
<h3>Player 2 Results</h3>
<textarea placeholder="0" disabled></textarea>
</div>
</div>
<body>
<script src="Tic-Tac-Toe.js"></script>
</body>
</html>
The issue is that your currentPlayer variable declaration and initialization needs to live outside the playerControls function or else you're just resetting it to playerOne each time.
let currentPlayer;
currentPlayer = playerOne;
function playerControls(e){...}
Here is the fix in action:
const playgame = (()=> {
const playerOne = {
Name: 'playerOne',
Marking: 'X'
};
const playerTwo = {
Name: 'PlayerTwo',
Marking: 'O'
};
let currentPlayer;
currentPlayer = playerOne;
function playerControls(e){
e.target.textContent = currentPlayer.Marking;
if(currentPlayer === playerOne)
{
currentPlayer = playerTwo;
e.target.textContent = currentPlayer.Marking;
}else{
currentPlayer = playerOne;
e.target.textContent = currentPlayer.Marking;
}
}
return{playerControls}
})();
const gameBoard = (() => {
const makeBoard = (rows, cols) => {
const theBoard = document.getElementById("GameBoard");
theBoard.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
theBoard.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
for (i=0; i<(rows * cols); i++){
let gameDivs = document.createElement("div");
gameDivs.addEventListener("click", playgame.playerControls)
theBoard.appendChild(gameDivs).classList.add("newdivgrid");
}
};
makeBoard(3,3);
})();
#GameBoard{
width: 600px;
height: 350px;
border: 1px solid darkblue;
margin-left: 27%;
text-align: center;
font-size: 500%;
font-family: cursive, sans-serif;
display: grid;
}
.newdivgrid{
border: 1px solid black;
grid-row-gap: 50px;
}
.newdivgrid:hover{
background-color: aqua;
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic-Tac-Toe game</title>
<link rel="stylesheet" href="Tic-Tac-Toe.css">
</head>
<h1>Tic-Tac-Toe Project</h1>
<div id="PlayerSelectionContainer">
<h2>Select Players</h2>
<div class="Player1">
<h3>Player 1</h3>
<div class="playerSelectionButtons" data-player="playerOne">
<button data-player="human">Human</button>
<button data-player="computer">Computer</button>
</div>
</div>
<div class="Player2">
<h3>Player 2</h3>
<div class="playerSelectionButtons" data-player="playerTwo">
<button data-human-player="human">Human</button>
<button data-computer-player="computer">Computer</button>
</div>
</div>
</div>
<div id="GameBoard">
</div>
<div id="resultContainer">
<h3>Results</h3>
<div class="player1Results">
<h3>Player 1 Results</h3>
<textarea placeholder="0" disabled ></textarea>
</div>
<div class="Player2Results">
<h3>Player 2 Results</h3>
<textarea placeholder="0" disabled ></textarea>
</div>
</div>
<body>
<script src="Tic-Tac-Toe.js"></script>
</body>
</html>
I tried searching for "file name changes to 0 in browser" both in Google and here, but got nowhere. This is a simple file which suddenly stopped opening. I can't even get at the inspector to troubleshoot it. Undo/redo history is lost, so that will not help. I'm guessing it's a simple mistake, but I have NEVER seen this before.
<!doctype html>
<html lang="en">
<head>
<title>JS Animated Navigation Test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
<!--
var location = 0;
var bar = document.getElementById("bar1");
function myMove()
{
// if (id != 0) clearInterval(id);
location = -144;
// if (location != -144) return; // don't execute onmouseover while previous onmouseover is still running.
id = setInterval(move, 1);
}
function move()
{
location++;
bar.style.left = location + 'px';
if (location == 300)
{
clearInterval(id);
id = setInterval(moveback, 1);
}
}
function moveback()
{
location--;
bar.style.left = location + 'px';
if (location == -144)
{
clearInterval(id);
// id = setInterval(move, 1);
}
}
-->
</script>
<style>
#container
{
width: 600px;
height: 100px;
position: relative;
background: white;
}
#bar1
{
width: 150px;
height: 30px;
position: absolute;
left: -144px;
background-color: white;
}
</style>
</head>
<body>
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id ="container">
<div id ="animate"><img src="imageGalleryBar.png" alt="Image Gallery" width="150" height="30" id="bar1" onmouseover="myMove()" /></div>
</div>
</body>
</html>
Thank you
You can't use the variable name location as it is a reserved word; what you're actually doing is setting the window.location variable to 0.
Rename it, or put it in a namespace or object.
I'm trying to implement a timer that will swap the larger image with the next image in line, I feel like I'm on the right track, but I'm not getting there. I can't use Jquery or (event.target), (event.srcElement) or appendChild. Any ideas? I don't think my function is doing anything right now. Current code below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Photo Gallery</title>
<script>
var aryImages[] = {"1.jpg", "2.jpg", "3.jpg"}
function changeImage(varImage) {
document.getElementById('bigImage').src='images/1.jpg';
for (var i = 1; i < 4; i ++)
index.html = "images/1.jpg" + photoOrder[i] +"sm.jpg";
}
</script>
/* styling elements */
<style>
img
{
width: 300px;
height: 290px;
padding: 2px;
}
body
{
text-align: center;
background-color: black;
}
</style>
</head>
<body>
<div>
<img src="images/1.jpg" id="bigImage" />
</div>
<img src='images/1.jpg' id='image1' onclick="changeImage(image1)" />
<img src='images/2.jpg' id='image2' onclick="changeImage(image2)"/>
<img src='images/3.jpg' id='image3' onclick="changeImage(image3)"/>
</body>
</html>
This should be what you're looking for. I set an interval that will rotate through your images. If the user clicks an image, that will change the image and reset the interval.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Photo Gallery</title>
<script>
var i = 1;
function changeImage(event, varImage) {
document.getElementById('bigImage').src='images/' + varImage + '.jpg';
// use this so the image interval doesnt
// interfere with user's click
if (event !== null) {
clearInterval(newInt);
newInt = setInterval(() => {
changeImage(null, i++);
if (i === 4) i = 1;
}, 500);
}
}
var newInt = setInterval(() => {
changeImage(null, i++);
if (i === 4) i = 1;
}, 500)
</script>
/* styling elements */
<style>
img
{
width: 300px;
height: 290px;
padding: 2px;
}
body
{
text-align: center;
background-color: black;
}
</style>
</head>
<body>
<div>
<img src="images/1.jpg" id="bigImage" />
</div>
<img src='images/1.jpg' id='1' onclick="changeImage(event, 1)" />
<img src='images/2.jpg' id='2' onclick="changeImage(event, 2)"/>
<img src='images/3.jpg' id='3' onclick="changeImage(event, 3)"/>
</body>
</html>
first of all you are not changing anything
you dont have a timer at all :)
here how to implement one:
setInterval(function(){
// do something;
}, 3000);
now inside the timer you should change images
for example
you should run inspect element on image to see changes because there is no images at these sources
var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var currentImage = 0;
// assuming that image is the image index in the array.
var changeImage = function (image) {
document.getElementById('bigImage').src = 'images/' + images[image];
};
// now we can use setInterval function
setInterval(function(){
// check if we reached the last image
if(currentImage >= images.length -1) {
// if last image go back to first one
currentImage = 0;
} else {
// if not last image so give me the next
currentImage ++;
}
// do the image change
changeImage(currentImage);
}, 3000);
<img src="images/image1.jpg" id="bigImage" />
<button onclick="changeImage(0)" > image1 </button>
<button onclick="changeImage(1)" > image2 </button>
<button onclick="changeImage(2)" > image3 </button>