Clicking on an image not working as intended - javascript

I made a game where you need to click the image on the left side of the screen that you do not see on the opposite side to get to the next level. For some reason, when you click any image on the left side you still go to the next level. When you click the wrong image it should say game over. Right now it only does that when the whitespace is clicked. Any tips?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Matching Game</title>
<style>
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 1px solid;
}
</style>
</head>
<body onload="generateFaces()">
<h1>Matching Game</h1>
<p>Click on the extra smiling face on the left.</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
<script >
let numberOfFaces = 5;
const theLeftSide = document.querySelector("#leftSide");
const theRightSide = document.querySelector("#rightSide");
function generateFaces() {
for (let i = 0; i < numberOfFaces; i++) {
let face = document.createElement("img");
face.src = 'images/smile.png';
const randomTop = Math.floor(Math.random() * 400) + 1;
const randomLeft = Math.floor(Math.random() * 400) + 1;
face.style.top = randomTop + 'px';
face.style.left = randomLeft + 'px';
theLeftSide.appendChild(face);
theLeftSide.lastChild.addEventListener('click', nextLevel);
document.body.addEventListener('click', gameOver);
}
const leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
theRightSide.appendChild(leftSideImages);
function nextLevel(event) {
event.stopPropagation();
numberOfFaces += 5;
while (theLeftSide.firstChild) {
theLeftSide.removeChild(theLeftSide.firstChild);
}
while (theRightSide.firstChild) {
theRightSide.removeChild(theRightSide.firstChild);
}
generateFaces();
}
function gameOver() {
alert('Game Over!');
document.body.removeEventListener('click', gameOver);
theLeftSide.lastChild.removeEventListener('click', nextLevel);
}
}
</script>
</body>
</html>

notice
for (let i = 0; i < numberOfFaces; i++) {
let face = document.createElement("img");
...
theLeftSide.appendChild(face);
// you do this in every loop
theLeftSide.lastChild.addEventListener('click', nextLevel);
}
put the theLeftSide.lastChild.addEventListener('click', nextLevel); outside loop for it to work

Related

Dom html javascript about onclick

I want to generate five image imgs first in left side, then remove the lastchild of it and copy the rest to the right side. If user clicks the extra img in left side, then clear all and generate more 5(10) img in left and copy 9 to the right side, and so on. If user clicks the wrong place, alert ("game over").Here is my code:
<html>
<head>
<style>
img{
position: absolute;
}
div{
position: absolute;
width: 500px;
height: 500px;
}
#rightSide { left: 500px;
border-left: 1px solid black;
}
</style>
<script>
var numberOfFaces = 5;
function generateFaces(){
var theLeftSide = document.getElementById("leftSide");
for (var i = 0; i < numberOfFaces; i++){
var img = document.createElement("img");
img.src = "smile.png";
var randomTop = Math.random() * 400;
var randomLeft = Math.random() * 400;
img.style.top = randomTop + "px";
img.style.left = randomLeft + "px";
theLeftSide.appendChild(img);
}
var theRightSide = document.getElementById("rightSide");
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
document.getElementById("rightSide").appendChild(leftSideImages);
var theBody = document.getElementByTagName("body")[0];
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
while (theBody.firstChild){
theBody.removeChild(theBody.firstChild);
}
numberOfFaces += 5;
generateFaces();
}
theBody.onclick = function gameover(){
alert("Game Over");
thBody.onclick = null;
theLeftSide.lastChild.onclick = null;
}
}
window.onload = generateFaces;
</script>
</head>
<body>
<h1>Matching Game</h1>
<p>click on the extra smiling face on the left</p>
<div id = "leftSide">
</div>
<div id = "rightSide">
</div>
</body>
</html>
I could generate and clone at first time, but when I click, nothing happens, so what is the problem?
This may be a typing error.
var theBody = document.getElementsByTagName("body")[0];
your code: var theBody = document.getElementByTagName("body")[0];
I suggest to use a good editor for html. I fixed the error with Jetbrain phpStorm but better ones may exist.
Bellow is a modified version that worked for me. Notice that in this version I added the events on all children instead of the whole document body. I don't know but for me it feels more accurate not to end the game on a user clicks on a white space for example.
<html>
<head>
<style>
img{
position: absolute;
}
div{
position: absolute;
width: 500px;
height: 500px;
}
#rightSide { left: 500px;
border-left: 1px solid black;
}
</style>
<script>
var numberOfFaces = 5;
var theBody;
var theLeftSide;
var theRightSide;
function generateFaces(){
theBody = document.getElementsByTagName("body")[0];
theLeftSide = document.getElementById("leftSide");
theRightSide = document.getElementById("rightSide");
for (var i = 0; i < numberOfFaces; i++){
var img = document.createElement("img");
img.src = "smile.png";
var randomTop = Math.random() * 400;
var randomLeft = Math.random() * 400;
img.style.top = randomTop + "px";
img.style.left = randomLeft + "px";
if(theLeftSide != null)
theLeftSide.appendChild(img);
else
{
alert("Game Over");
return;
}
}
var leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
document.getElementById("rightSide").appendChild(leftSideImages);
addEvents();
}
function addEvents(){
for(var i=0; i < theLeftSide.childNodes.length; i++){
theLeftSide.childNodes[i].onclick = nextLevel;
}
}
function removeEvents(){
for(var i=0; i < theLeftSide.childNodes.length; i++){
theLeftSide.childNodes[i].onclick = null;
}
}
function nextLevel(event){
if(this == theLeftSide.lastChild){
event.stopPropagation();
theLeftSide.innerHTML = "";
theRightSide.innerHTML = "";
numberOfFaces += 5;
generateFaces();
}
else
{
alert("Game Over");
removeEvents();
}
}
window.onload = generateFaces;
</script>
</head>
<body>
<h1>Matching Game</h1>
<p>click on the extra smiling face on the left</p>
<div id = "leftSide">
</div>
<div id = "rightSide">
</div>
</body>
</html>

update .style attributes with setInterval

I'm trying to move the position of a div element at set intervals however the setInterval method executes once and then stops. setInterval() doesn't update .style.transform repeatedly every 200 milliseconds as intended.
<!DOCTYPE html>
<html>
<head>
<title>Snake game</title>
<style type="text/css">
.container {
width: 500px;
height: 500px;
border: 2px solid black;
}
#snakehead {
width: 5px;
height: 5px;
background: pink;
position: relative;
left: 0px;
}
</style>
<script type="text/javascript" src="snake.js"></script>
</head>
<body>
<div class="container">
<div id="snakehead"></div>
</div>
</body>
</html>
Javascript: Ideally I'd also like to be able to move the snakehead in any direction with vx and vy. Anyway to put those values into .style.transform = translateX()?
function snakepos() {
var x = 0;
var y = 0;
var vx = 1;
var vy = 0;
return {
move: function() {
x += vx;
y += vy;
var snakehead = document.querySelector("#snakehead");
snakedhead.style.left = "5px";
}
};
}
window.onload = function() {
console.log("hi");
var container = document.querySelector(".container");
var snake = snakepos();
setInterval(function() {
snake.move();
}, 200);
}
I know this can be done much easier in jQuery with .css but I'd to how this can be done in vanilla javascript. Thank you in advance.
snakehead.style.left = (snakedhead.style.left + "5px");
or
snakehead.style.left = (snakedhead.style.left - "5px");
I'd recommend something in a style a bit more familiar to me:
function snakepos() {
this.x = 0;
this.y = 0;
this.vx = 1;
this.vy = 1;
this.snakehead = document.querySelector("#snakehead");
var me = this;
this.move = function() {
me.x += me.vx;
me.y += me.vy;
me.snakehead.style.top = me.y + "px";
me.snakehead.style.left = me.x + "px";
};
return this;
}
console.log("hi");
var container = document.querySelector(".container");
var snake = new snakepos();
setInterval(function() {
snake.move();
}, 200);
See fiddle: https://jsfiddle.net/theredhead/td8opb0b/1/

How can I generate new set of smiling faces at random position after user click on extra smiling face?

I have been trying to get the smiley faces to generate in new random position by putting the function delete_all_children() at appropriate locations, but everytime, it won't run properly. Instead, if I ignore the randomized location after finding the extra picture, the game runs properly but it is a build up from existing smiley faces, which makes the game easier.
I want the new faces to generate in random location.
Please help!
<DOCTYPE! html>
<html>
<head>
<title>Matching Game - Smiling :)</title>
<style>
div, img {position: absolute;}
div {width: 500px; height: 500px;}
#rightSide {left: 500px; border-left: 1px solid black}
</style>
<script type="text/javascript">
var numberOfFace = 5;
var count = 0;
var theBody = document.getElementsByTagName("body")[0];
function generateFaces() {
var theLeftSide = document.getElementById('leftSide');
var theRightSide = document.getElementById('rightSide');
while (count < numberOfFace) {
var top_random = (Math.random() * 400);
var left_random = (Math.random() * 400);
var smiling_face = document.createElement("img");
smiling_face.src = "http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png";
smiling_face.style.top = Math.floor(top_random) + "px";
smiling_face.style.left = Math.floor(left_random) + "px";
theLeftSide.appendChild(smiling_face);
count ++;
};
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
theRightSide.appendChild(leftSideImages);
theLeftSide.lastChild.onclick = function nextLevel(event) {
event.stopPropagation();
numberOfFace += 5;
generateFaces();
};
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
function delete_all_children() {
var theNode = document.getElementById("theBody");
while (theNode.firstChild) {
theNode.removeChild(theNode.firstChild);
};
};
};
</script>
</head>
<body onload="generateFaces()">
<h1>Matching Game</h1>
<p>Click on the extra smiling face on the left!</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
</body>
</html>

Why do the elements not appear in random places but they are staying aligned on top of the div?

The code is supposed to generate 5 elements one by one so that when the page is downloaded all we`ll see 5 elements (newFace) in random places.
This code generates all 5 elements but they are staying aligned one by one instead of appearing in random position as wished
function generate_faces() {
var theLeftSide = document.getElementById("leftSide");
var number_of_faces = 0;
while (number_of_faces < 5){
var top_position = Math.floor(Math.random()*300);
var left_position = Math.floor(Math.random()*300);
newFace = document.createElement("img");
newFace.setAttribute(
"src",
"http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png"
);
newFace.style.top = top_position+"px";
newFace.style.left = left_position+"px";
theLeftSide.appendChild(newFace);
number_of_faces = number_of_faces + 1;
}
}
Try this.
<!DOCTYPE html>
<html>
<head></head>
<style>
html, body, leftSide {
width: 100%;
height: 100%;
position: relative;
}
#leftSide {
position: relative;
}
#leftSide img {
position: absolute;
}
</style>
<body onclick="generate_faces()">
<div id="leftSide">
</div>
</body>
</html>
<script>
function generate_faces() {
var theLeftSide = document.getElementById("leftSide");
var number_of_faces = 0;
while (number_of_faces < 5){
var top_position = Math.floor(Math.random()*300);
var left_position = Math.floor(Math.random()*300);
newFace = document.createElement("img");
newFace.setAttribute(
"src",
"http://home.cse.ust.hk/~rossiter/mooc/matching_game/smile.png"
);
newFace.style.top = top_position+"px";
newFace.style.left = left_position+"px";
theLeftSide.appendChild(newFace);
number_of_faces = number_of_faces + 1;
}
}
</script>

Why does the onclick event listener gets removed?

I am making a small matching game in javascript. Why does the onclick listener stop working after the first successful attempt. How do I rectify this issue.
I am expecting the listener to be attached to the last child element of the div with id "leftSide" even after I refresh all nodes by removing old nodes first.
<!DOCTYPE html>
<html>
<head>
<title>Matching Game</title>
<style>
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 1px solid black;
}
</style>
</head>
<body>
<h2>Matching Game</h2>
<p>Click on the extra smile on the left</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
<script>
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
var theRightSide = document.getElementById("rightSide");
function generateFaces() {
for (var i=0; i<=numberOfFaces; i++) {
new_img = document.createElement("img");
new_img.src="smile.png";
new_img.style.top=String(Math.floor(Math.random()*400))+"px";
new_img.style.left=String(Math.floor(Math.random()*400))+"px";
theLeftSide.appendChild(new_img);
}
// Clone all images to right side
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
theRightSide.appendChild(leftSideImages);
}
generateFaces()
var theBody = document.getElementsByTagName("body")[0];
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
theLeftSide.lastChild.onclick = function nextLevel(event) {
// remove child nodes
while (theLeftSide.firstChild) {
theLeftSide.removeChild(theLeftSide.firstChild);
}
while (theRightSide.firstChild) {
theRightSide.removeChild(theRightSide.firstChild);
}
// new nodes
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
};
</script>
</body>
</html>
The problem is when you attach an event handler to an element, when that element is destroyed, the event is gone too (when the GC cleans). The theLeftSide.lastChild doesn't creates a reference to whatever last child element of theLeftSide is. It creates a reference to the current last child.
You must change the place you add the event handler to inside your generateFaces function, so everytime you change the theLeftSide children, you get again the last child, and add the event.
Take a look at the example below:
<!DOCTYPE html>
<html>
<head>
<title>Matching Game</title>
<style>
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 1px solid black;
}
</style>
</head>
<body>
<h2>Matching Game</h2>
<p>Click on the extra smile on the left</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
<script>
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
var theRightSide = document.getElementById("rightSide");
function generateFaces() {
for (var i = 0; i <= numberOfFaces; i++) {
new_img = document.createElement("img");
new_img.src = "http://www.webgranth.com/wp-content/uploads/2012/03/smile.png";
new_img.style.top = String(Math.floor(Math.random() * 400)) + "px";
new_img.style.left = String(Math.floor(Math.random() * 400)) + "px";
theLeftSide.appendChild(new_img);
}
// Clone all images to right side
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
theRightSide.appendChild(leftSideImages);
theLeftSide.lastChild.onclick = nextLevel;
}
generateFaces()
var theBody = document.getElementsByTagName("body")[0];
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
function nextLevel(event) {
// remove child nodes
while (theLeftSide.firstChild) {
theLeftSide.removeChild(theLeftSide.firstChild);
}
while (theRightSide.firstChild) {
theRightSide.removeChild(theRightSide.firstChild);
}
// new nodes
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
};
</script>
</body>
</html>
Note: I've simpled changed the theLeftSide.lastChild.onclick = function nextLevel(event) {, to a simple function declaration: function nextLevel(event) {, and then added the event handler inside the generateFaces function: theLeftSide.lastChild.onclick = nextLevel;.
you could try something like this:
<!DOCTYPE html>
<html>
<head>
<title>Matching Game</title>
<style>
img {
position: absolute;
}
div {
position: absolute;
width: 500px;
height: 500px;
}
#rightSide {
left: 500px;
border-left: 1px solid black;
}
</style>
</head>
<body>
<h2>Matching Game</h2>
<p>Click on the extra smile on the left</p>
<div id="leftSide"></div>
<div id="rightSide"></div>
<script>
var numberOfFaces = 5;
var theLeftSide = document.getElementById("leftSide");
var theRightSide = document.getElementById("rightSide");
var clickLastChild = function clickLastChild() {
// remove child nodes
theLeftSide.lastChild.onclick = function (event) {
while (theLeftSide.firstChild) {
theLeftSide.removeChild(theLeftSide.firstChild);
}
while (theRightSide.firstChild) {
theRightSide.removeChild(theRightSide.firstChild);
}
// new nodes
event.stopPropagation();
numberOfFaces += 5;
generateFaces();
};
};
function generateFaces() {
for (var i = 0; i <= numberOfFaces; i++) {
new_img = document.createElement("img");
new_img.src = "smile.png";
new_img.style.top = String(Math.floor(Math.random() * 400)) + "px";
new_img.style.left = String(Math.floor(Math.random() * 400)) + "px";
theLeftSide.appendChild(new_img);
}
// Clone all images to right side
leftSideImages = theLeftSide.cloneNode(true);
leftSideImages.removeChild(leftSideImages.lastChild);
theRightSide.appendChild(leftSideImages);
clickLastChild();
}
generateFaces();
var theBody = document.getElementsByTagName("body")[0];
theBody.onclick = function gameOver() {
alert("Game Over!");
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
clickLastChild();
</script>
</body>
</html>
Here i made fully working jsfiddle
You have to call generateFaces() from game over scenario also.
And yes as #epascarello mentioned, you are losing click events as you are setting them to null.
Because you set the onclick to false
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
when you click the tbody.

Categories