I have trouble hiding elements in my game if they don't match - javascript

I am working on a memory game and I asked a previous question earlier which was answered. I've had this problem and I haven't been able to find a solution with effort. So it's a memory game and when the cards are clicked, they are pushed into an array which can hold two elements at max (you can only click two cards) and then the two elements' frontSrc is checked if they are the same. I set that using an expando property. If so, have them visible and then clear the array so I can do more comparisons. However, it doesn't seem to be working as intended. I'll attach a video below. I've tried using timeout to set the length again, but that didn't work. It works for the first cards, but the other ones after that, it doesn't work.
Here is my code.
<!DOCTYPE html>
<!--
Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template
-->
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.card{
width: 35%;
}
#cards{
display: grid;
grid-template-columns:25% 25% 25% 25%;
row-gap: 25px;
}
</style>
</head>
<body onload="init()">
<section id="cards">
</section>
<script>
var arrCards = [];
var arrShowedCards = [];
//appendElements();
function init(){
createCards();
shuffleCards();
appendElements();
}
function createCards(){
var arrCardNames = ["Mouse","Penguin","Pop","Mouse","Penguin","Pop"];
for(var i = 0; i<6; i++){
var card = document.createElement("IMG");
card.src = "Images/red_back.png";
card.className = "card";
card.frontSrc = "Images/" + arrCardNames[i] + ".png";
card.id = "card" + i;
card.addEventListener("click", showCard);
document.getElementById("cards").appendChild(card);
arrCards.push(card);
}
}
function shuffleCards(){
for (let i = arrCards.length-1; i > 0; i--)
{
const j = Math.floor(Math.random() * (i + 1));
const temp = arrCards[i];
arrCards[i] = arrCards[j];
arrCards[j] = temp;
}
return arrCards;
}
function appendElements(){
for(var i = 0; i<arrCards.length; i++){
document.getElementById("cards").appendChild(arrCards[i]);
}
}
function showCard(){
var sourceString = "Images/red_back.png";
this.src = this.frontSrc;
arrShowedCards.push(this);
if(arrShowedCards.length === 2){
if(arrShowedCards[0].frontSrc === arrShowedCards[1].frontSrc){
console.log("Match!");
arrShowedCards = [];
}
else{
console.log("No match!");
setTimeout(function(){
arrShowedCards[0].src = sourceString;
arrShowedCards[1].src = sourceString;
}, 1000);
}
}
}
</script>
</body>
</html>
I am not sure how come it doesn't work for it for the other cards.
Here is the video.
https://drive.google.com/file/d/1aRPfLALHvTKjawGaiRgD1d0hWQT3BPDQ/view
If anyone finds a better way to approach this, let me know.
Thanks!

I think when not match, you need to reset arrShowedCards otherwise its length will be greater than 2 forever.
function showCard() {
var sourceString = "Images/red_back.png";
this.src = this.frontSrc;
arrShowedCards.push(this);
if (arrShowedCards.length === 2) {
var a = arrShowedCards[0], b = arrShowedCards[1];
arrShowedCards.length = 0;
if (a.frontSrc === b.frontSrc) {
console.log("Match!");
} else {
console.log("No match!");
setTimeout(function () {
a.src = sourceString;
b.src = sourceString;
}, 1000);
}
}
}

Related

How can I use JavaScript to grab a random div?

I'm using JavaScript to create a grid. What I'm trying to do is have a random box that is created change colors when I click on the "Play" button but I cannot seem to get it figured out.
I've tried using various amounts of Math.random(), this might be where my problem is.
const container = document.getElementById('container');
const gameButton = document.createElement('button');
// This is the button I'm trying to use for this.
gameButton.addEventListener('click', function (event) {
let getRandom = document.getElementsByTagName('div');
});
let userInput = prompt('Enter a number between 10-20: ');
if (isNaN(userInput)) {
alert('Numbers only.');
location.reload();
} else if (userInput < 10) {
alert('That\'s less than 10');
location.reload();
} else if (userInput > 20) {
alert('That\'s greater than 20');
location.reload();
} else {
gameButton.textContent = 'Play';
gameButton.style.height = '25px';
gameButton.style.width = '50px';
gameButton.style.borderRadius = '7px';
gameButton.style.marginBottom = '15px';
container.appendChild(gameButton);
}
for (let index = 1; index <= userInput; index++) {
let gameBoard = document.createElement('div');
gameBoard.setAttribute('class', 'game-board');
container.appendChild(gameBoard);
for (let j = 0; j < userInput; j++) {
const square = document.createElement('div');
square.setAttribute('class', 'square');
gameBoard.appendChild(square);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="./style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="container">
</div>
<!---<script src="./app.js"></script>--->
</body>
</html>
Expected result is one of the 'divs' changes color when the button is clicked on.
Between your question and your code, it's a little confusing. But just going off what you said, here's a way to choose a random element from a list of elements, provided you give it a class name (feel free to tweak this):
// Function to get a random number, taking in min and max values.
const randomNum = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)
// Function that takes in a class name to select all those elements
// on the page, and returns a random one from the list.
const getRandomElement = className => {
const elements = document.querySelectorAll(`.${className}`)
const num = randomNum(0, elements.length - 1)
return elements[num]
}
You could change the code in your event listener like this:
gameButton.addEventListener('click', function (event) {
let divs = document.getElementsByClassName('game-board');
let random_div = divs[Math.floor(Math.random()*divs.length)];
random_div.style.backgroundColor = 'red';
});
Or if you want only one square to change color, use document.getElementsByClassName('square') instead.
Relevante part o the code. You can make it better checking the elements, the styles, etc. But essentially it is:
gameButton.addEventListener('click', function (event) {
let getRandom = document.getElementsByTagName('div');
var a = Math.random()
let b = a.toString().substr(2, 1)
getRandom[b].style = 'background-color: ' + (parseInt(b) % 2 == 0 ? 'yellow' : 'red')
});
So you use Math.Random to get some random number after the dot(.) and use it to read some index from the collection you get for the getRandom.
Then you just set element style or whatever you want.
The fiddle: https://jsfiddle.net/cm5kyrdj/

How should I refer back to the an element before (in a different function), and modify it in a new function?

How do I make reference to the specific dashes I created, and add a
specific letter to them. Read the comments and code to get a better
context. Thanks for any help in advance!!
<!Doctype html>
<html lang="en">
<head>
<style>
ul {
display: inline;
list-style-type: none;
}
.boxes {
font-size:1.6em;
text-align:center;
width: 10px;
border-bottom: 3px solid black;
margin: 5px;
padding: 10px;
display: inline;
}
.hidden {
visibility: hidden;
}
.visible {
visibility: visible;
}
</style>
</head>
<body>
<script>
var possibleWord = ["COW", "BETTER", "HARDER", "JUSTIFY", "CONDEMN",
"CONTROL", "HELLO", "UNDERSTAND", "LIFE", "INSIGHT","DATE",
"RIGHTEOUSNESS"];
var hangmanWord = possibleWord[Math.floor(Math.random() *
possibleWord.length)];
var underlineHelp;
var space;
var guess;
var guesses = [];
var placement;
var underscores = [];
var character = [];
var textNodes = [];
window.onload = function () {
placement = document.getElementById('hold');
underlineHelp = document.createElement('ul');
placement.appendChild(underlineHelp);
for (i = 0; i < hangmanWord.length; i++) {
underscores = document.createElement('li');
underscores.setAttribute('class', 'boxes');
guesses.push(underscores);
underlineHelp.appendChild(underscores);
character = document.createElement('span');
character.appendChild(document.createTextNode(hangmanWord[i]));
character.classList.add('hidden');
underscores.appendChild(character);
}
This is the area I want to refer to later.
for(x=1;x<=26;x++){
document.getElementById("test").innerHTML = hangmanWord;
var btn = document.createElement("BUTTON");
var myP = document.createElement("br");
var letter = String.fromCharCode(x+64);
var t = document.createTextNode(letter);
btn.appendChild(t);
btn.id = letter;
Just creating buttons. This is important when I say 'this.id' down below.
btn.addEventListener("click", checkLetter);
document.body.appendChild(btn);
//add a line break 'myP' after 3 buttons
if (x%10==0) {
document.body.appendChild(myP);
}
}
}
function checkLetter(){
//this refers to the object that called this function
document.getElementById("p1").innerHTML += this.id;
for (i = 0; i < hangmanWord.length; i++) {
guess = hangmanWord[i];
if (this.id == guess) {
character[i] = hangmanWord[i];
character.appendChild(document.createTextNode(hangmanWord[i]));
character.classList.add('visible');
}
}
}
Here is where I am in trouble. If I do this (the code I wrote after the if statement) the letters will be added on the end of the string. I Want to have it on the specific dashes that I created earlier. How can I manage to do that? Do I have to do something called "object passing." I am relatively new to js (high school student) and I am keen on any insight! Once again thanks for the help in advance!
</script>
</head>
<body>
<p>Click the button to make a BUTTON element with text.</p>
<div id = "contents">
<div id = "hold"></div>
</div>
<p id ="p1"> Letters picked: </p>
<div id= "picBox"></div>
<div id = "test"></div>
</div>
</body>
You could store the guessing word and the guessed characters in an object and just output the replaced result of such instead. Seems easier to me.
<html>
<head>
<script>
//The hangman object
var Hangman = {
wordToGuess: 'RIGHTEOUSNESS', //The word to guess. Just one for my example
guessedLetters: [] //The guessed characters
};
window.onload = function(){
//Creating the buttons
for(var tF=document.createDocumentFragment(), x=1; x<=26; x++){
var tLetter = String.fromCharCode(x+64),
tButton = tF.appendChild(document.createElement("button"));
tButton.id = tLetter;
tButton.addEventListener("click", checkLetter);
tButton.appendChild(document.createTextNode(tLetter));
(x%10 === 0) && tF.appendChild(document.createElement('br'))
};
document.body.appendChild(tF);
startTheGame()
};
//Starts a game of hangman
function startTheGame(){
var tWord = Hangman.wordToGuess,
tPlacement = document.getElementById('hold');
document.getElementById('test').innerHTML = tWord;
//Resetting the guesses
Hangman.guessedLetters = [];
//Creating dashes for all letters in our word
for(var i=0, j=tWord.length; i<j; i++){
tPlacement.appendChild(document.createTextNode('_'))
}
}
function checkLetter(){
var tButton = this,
tLetter = tButton.id,
tWord = Hangman.wordToGuess,
tPlacement = document.getElementById('hold');
//Make a guess
document.getElementById('p1').innerHTML += tLetter;
(Hangman.guessedLetters.indexOf(tLetter) === -1) && Hangman.guessedLetters.push(tLetter.toLowerCase());
//Clear the current word
while(tPlacement.firstChild) tPlacement.removeChild(tPlacement.firstChild);
//Now we reverse replace the hangman word by the guessed characters
for(var i=0, j=tWord.length; i<j; i++){
tPlacement.appendChild(document.createTextNode(
(Hangman.guessedLetters.indexOf(tWord[i].toLowerCase()) === -1) ? '_' : tWord[i]
))
}
}
</script>
</head>
<body>
<p>Click the button to make a BUTTON element with text.</p>
<div id = 'contents'>
<div id = 'hold'></div>
</div>
<p id = 'p1'> Letters picked: </p>
<div id= "picBox"></div>
<div id = "test"></div>
<!-- This one seems to be too much
</div>
-->
</body>
</html>
https://jsfiddle.net/zk0uhetz/
Update
Made a version with propert object handling, separating the actual hangman logic from the interface.
<html>
<head>
<style>
button{
margin: 1px;
min-width: 30px
}
button[disabled]{
background: #777;
color: #fff
}
</style>
<script>
//Handles the hangman game itself
;(function(ns){
'use strict';
var _listOfWord = ['COW', 'BETTER', 'HARDER', 'JUSTIFY', 'CONDEMN', 'CONTROL', 'HELLO', 'UNDERSTAND', 'LIFE', 'INSIGHT','DATE', 'RIGHTEOUSNESS'],
_wordToGuess = null, //The word to guess. Just one for my example
_guessedLetters = [] //The guessed characters
ns.Hangman = {
//Returns the current obstructed word
getCurrentObstructedWord: function(){
var tWord = []; //The current state of the game
if(_wordToGuess){
//Now we reverse replace the hangman word by the guessed characters
for(var i=0, j=_wordToGuess.length; i<j; i++){
tWord.push(
(_guessedLetters.indexOf(_wordToGuess[i].toLowerCase()) === -1) ? '_' : _wordToGuess[i]
)
}
};
return tWord
},
//Make a guess at the current game
Guess: function(letter){
//Add the guess to the list of guesses, unless already guessed
(_guessedLetters.indexOf(letter) === -1) && _guessedLetters.push(letter.toLowerCase());
return this.getCurrentObstructedWord()
},
isComplete: function(){
return !!(this.getCurrentObstructedWord().indexOf('_') === -1)
},
//Starts a new game
Start: function(){
_guessedLetters = []; //Resetting the guesses
_wordToGuess = _listOfWord[Math.floor(Math.random() * _listOfWord.length)];
return _wordToGuess
}
}
}(window._ = window._ || {}));
//Creates the buttons for hangman
function createButtons(){
var tContainer = document.querySelector('#buttons');
while(tContainer.firstChild) tContainer.removeChild(tContainer.firstChild);
//Creating the buttons
for(var tF=document.createDocumentFragment(), x=1; x<=26; x++){
var tLetter = String.fromCharCode(x+64),
tButton = tF.appendChild(document.createElement('button'));
tButton.id = tLetter;
tButton.addEventListener('click', makeAGuess);
tButton.appendChild(document.createTextNode(tLetter));
(x%10 === 0) && tF.appendChild(document.createElement('br'))
};
tContainer.appendChild(tF)
};
//Makes a guess
function makeAGuess(){
var tButton = this,
tLetter = tButton.id;
//Disable the button
tButton.setAttribute('disabled', 'disabled');
//Make a guess
var tElement = document.getElementById('hold');
tElement.textContent = _.Hangman.Guess(tLetter).join('');
//Check if finished
if(_.Hangman.isComplete()){
tElement.style.color = 'limegreen'
}
};
//Starts a new game of hangman
function Reset(){
createButtons(); //Recreated the buttons
_.Hangman.Start(); //Starting a game of hangman
var tElement = document.getElementById('hold');
tElement.textContent = _.Hangman.getCurrentObstructedWord().join('');
tElement.style.color = ''
};
window.onload = function(){
Reset()
};
</script>
</head>
<body>
<div id = 'hold'></div>
<p id = 'p1'>Make a guess:</p>
<div id = 'buttons'></div>
<br /><br />
<button onclick = 'Reset()'>Start a new game</button>
</body>
</html>
https://jsfiddle.net/mm6pLfze/

Java Script Slide Show (add slide effect)

I have a problem
this are my first steps in javascript and I'm trying to make a Javascript slide show.
I try to add a "slide in" "slide out" effect
But I don't know how I can do this.
I google about 2-3 hours but still no solution.
Please help me and give me some feedback please
Here is my code
<head>
<title>Test Slider</title>
</head>
<body>
<div id="slider" style="width: 400px; height: 200px;color: orange; font-weight: bold; font-size: 30px;font-family: sans-serif" onclick="javascript:superlink()" style="cursor:pointer;"></div>
<script type="text/javascript">
//Init//
var SlideDauer = 2000;
var ImgInX = 0;
var ImgInXposition = 0;
var background = 'url(http://www.flashforum.de/forum/customavatars/avatar47196_1.gif)';
var SldInX = 0;
var LinkInX = 0;
function superlink() {
if (!SliderKannEsLosGehen()) return false;
if (LinkInX >= SliderBilder.length) {
LinkInX = 0;
}
var Ziel = window.location.href = SliderLink[LinkInX];
++LinkInX;
}
var SliderBilder = new Array();
SliderBilder.push("http://ds.serving-sys.com/BurstingRes//Site-80313/Type-0/721dbabb-2dd5-4d92-9754-7db9c5888f48.jpg");
SliderBilder.push("http://bytes.com/images/bytes_logo_a4k80.gif");
SliderBilder.push("http://cdn.qservz.com/file/df8e9dcf202cfddedf6f2d4d77fcf07b.gif");
SliderBilder.push("http://ds.serving-sys.com/BurstingRes//Site-80313/Type-0/721dbabb-2dd5-4d92-9754-7db9c5888f48.jpg");
//SliderBilder.push("http://www.flashforum.de/forum/customavatars/avatar47196_1.gif");
var SliderTitle = new Array();
SliderTitle.push("");
SliderTitle.push("Title 1");
SliderTitle.push("Title 3");
SliderTitle.push("Title 4");
//SliderTitle.push("Title 5");
var SliderLink = new Array();
SliderLink.push("http://www.google.de");
SliderLink.push("http://spiegel.de");
SliderLink.push("http://bing.com");
SliderLink.push("http://youtube.com");
//SliderLink.push ("http://www.flashforum.de/forum/customavatars/avatar47196_1.gif");
function SliderKannEsLosGehen() {
if (SliderBilder.length < 2) return false;
return true;
if (SliderTitle.length < 2) return false;
return true;
}
//Run//
function SliderRun() {
if (!SliderKannEsLosGehen()) return false;
if (ImgInX >= SliderBilder.length) {
ImgInX = ImgInXposition;
}
if (SldInX >= SliderBilder.length) {
SldInX = 0;
}
document.getElementById("slider").style.backgroundImage = 'url(' + SliderBilder[ImgInX] + ')';
++ImgInX;
document.getElementById("slider").innerHTML = SliderTitle[SldInX];
++SldInX;
window.setTimeout("SliderRun()", SlideDauer);
}
window.setTimeout("SliderRun()", SlideDauer);
</script>
</body>
</html>
For effects i would look into JQuery and use the animate function. There is loads of fun to be had with this as long as you have an understanding of css.

Clone HTML elements with JS

Trying to set up a Tic-Tac-Toe board based on JS input with an alert. The alert never shows up, and the HTML is never rendered... what am I missing?
ALL HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tic Tac Toe! (and more...)</title>
<meta name="description" content="Tic Tac Toe">
<meta name="author" content="SinSysOnline">
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="js.js"></script>
<style>
body{
font-family:"Lucida Console", Monaco, monospace;
}
td{
border-right:1px solid #000;
border-bottom:1px solid #000;
width:100px;
height:100px;
text-align:center;
font-size:72px;
}
td:last-child{
border-right:none;
border-bottom:1px solid #000;
}
tr:last-child td{
border-bottom:none;
}
</style>
</head>
<body>
<div id="dashboard">
<input type="text" value="How large is your grid? (default 3)" size="35" />
</div>
<table id="board">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</body>
</html>
ALL JS (minus jQuery)
/* Sadly, there is a very well known algorithm to ensure one NEVER loses at
tic-tac-toe. Ties, perhaps, but if you play right you can NEVER LOSE.
I will not institue this cheap shot into my program, and this will be
a computer vs you. I will add in potential moves :-) */
(function($) {
function create(x){
var board = [];
for(var i=0;i<x;i++){
var tempArr = [];
for(var j=0;j<x;j++){ tempArr[j] = ""; }
board.push(tempArr);
}
$('#board tr').clone(x);
return board;
}
var x = prompt("How large would you like your grid? (3-10)");
var board = create(x);
})(jQuery);
I've tried adding the JS to the bottom of my body... just kind of confused here. I know JS inside and out... except for DOM manipulation...
you didn't do any thing with your cloned element!
if you want to dynamically generate a table
the code should be like this
var $board = $('#board');
var td = "<td></td>", $tr = $("<tr></tr>");
function create(x) {
$board.empty();
var arr = [];
for(var i = 0; i < x; i++) {
arr.push(td);
}
var $trCloned = $tr.clone().append(arr.join(''));
for(var j = 0; j < x; j++) {
$board.append($trCloned);
}
}
Here is the fiddle
// JQuery
function create(board, x)
{
var row = $("<tr></tr>");
var i;
for (i = 0; i != x; i++) row.append ($("<td>x</td>")); // create a row
for (i = 0; i != x; i++) $('#'+board).append(row.clone()); // then the board
}
// sample use
var x = window.prompt ("How much, boss?");
create('board', x);
// html
<table id='board' />
I've put an 'x' inside the cells so that the board is visible
As Fiddle works, this No-Prompt problem is more like an environment/compatibility/typo issue. The problem can be solved progressively.
There is a misuse of jQuery's clone() function, the clone() function accepts boolean type (http://api.jquery.com/clone/) , which means whether or not event handlers will be copied. From the code I guess this is not what you want. Please correct it and try again.
On which browser did you test? Does this issue happen on one specific browser, or happens on all browsers in your computer? If it is the latter one, then copy your code (copy the files, not re-type) to someone else' computer and try again.
Simplify the JS code and test step by step. First, just leave the prompt() line and delete all else, will it work? Then, add an empty create() function and try again. Then, add something more. Sooner or later, you will find the line which causes the problem.
Please let us know if you deliver the above experiment and find something new.
EDITS
I'll never stop if I don't stop now. I'm stuck anyway. Hope this helps you on your way. Still needs some work (undefined references) but is functional if my fanciness didn't distract me so much:
JS Fiddle Demo (not working)
Javascript:
(function (window, document, $) {
var $board = $('#board');
var x = parseInt(prompt("How large would you like your grid? (3-10)"), 10);
var taken = [];
create(x);
function create(x) {
var tmp;
var $tr = $('<tr/>');
var $td = $('<td/><td/><td/>');
if (x <= 10 && x >= 3 && typeof x === 'number') {
for (var i = 0; i < x; i++) {
tmp = $tr.append($td);
tmp.clone().appendTo($board);
}
$('#board').on('click', 'td', function (evt) {
var e = evt || window.event;
var y = $(this).index();
var z = $(this).parent('tr').index();
taken = (!taken) ? [y, z] : taken;
userChoice(y, z, x, this);
});
} else {
alert('You entered an incorrect value. Try again!');
return false;
}
}
function userChoice(y, z, x, el) {
//if($(el).text() !== "") {
console.log(taken);
for (var d = 0; d < (x - 1); d++) {
for (var o = 0, n = 0; o < 3; o++) {
if ((taken[n].indexOf(y) && taken[n].indexOf(z)) || (taken[n].indexOf(y) && taken[n].indexOf(z))) {
alert('Already played that spot. Nice try.');
return false;
}
n++;
}
}
taken.push([y, z]);
$(el).text('O');
console.log(taken);
if ((taken.length * taken[taken.length].length) / (x - 1) === 3) {
alert('No more spaces! Game over!');
return false;
}
compChoice(x);
}
function compChoice(x) {
console.log(taken);
var a = Math.floor(Math.random(10) * x);
var b = Math.floor(Math.random(10) * x);
for (var d = 0; d < (x-1); d++) {
for (var o = 0, n = 0; o < 3; o++) {
if ((taken[n].indexOf(a) && taken[n].indexOf(b)) || (taken[n].indexOf(a) && taken[n].indexOf(b))) {
compChoice(x);
}
n++;
}
}
taken.push([a,b]);
console.log(taken);
$board.find('tr:nth-of-type(' + a + ')').find('td:nth-of-type(' + b + ')').text('X');
if ((taken.length * taken[taken.length].length) === x) {
alert('No more spaces! Game over!');
return false;
}
}
})(this, this.document, jQuery, undefined);
HTML:
<div id="dashboard">
<noscript>
<input type="text" value="How large is your grid? (default 3)" size="35" />
</noscript>
</div>
<table id="board"></table>

Javascript run a function at the same time with different vars

Sorry about the confusing title, I'll explain better.
I have a 20x20 grid of div's, so its 400 of them each with an id, going from 0 to 399.
Each div is given one of three random values - red, green or blue - and when a div is clicked, a function is run to check if the div to the left, right, over and under are of the same value, if it is of the same value it will be simulated a click and the same function will run again.
The problem, is that the function sets vars, so if it finds that the div below has the same value, it will overwrite the vars set by the first click, hence never click any of the others.
JSfiddle - http://jsfiddle.net/5e52s/
Here is what I've got:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>untiteled</title>
<style>
body {
width: 420px;
}
.box {
width: 19px;
height: 19px;
border: 1px solid #fafafa;
float: left;
}
.box:hover {
border: 1px solid #333;
}
.clicked {
background: #bada55 !important;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$().ready(function(){
var colors = ['red', 'green', 'blue'];
var i = 0;
while(i<400){
var color = colors[Math.floor(Math.random() * colors.length)];
$('.test').append('<div class="box" id="'+i+'" value="'+color+'" style="background:'+color+';">'+i+'</div>');
i++;
}
$('.box').click(function(){
var t = $(this);
t.addClass('clicked');
id = t.attr('id');
val = t.attr('value');
//Set color
up = parseInt(id) - 20;
right = parseInt(id) + 1;
down = parseInt(id) + 20;
left = parseInt(id) - 1;
clickup = false;
clickdown = false;
if($('#'+down).attr('value') === val){
clickdown = true;
}
if(up > -1 && ($('#'+up).attr('value') === val)){
clickup = true;
}
if(clickdown == true){
$('#'+down).click();
}
if(clickup == true){
$('#'+up).click();
}
});
});
</script>
</head>
<body>
<div class="test">
</div>
</body>
I think the biggest root cause of your problem is you don't check if it already has class 'clicked' or not. That could make the infinite recursive. For example, if you click on the div#2 then the div#1 receives a simulated click, and div#2 receives a simulated click from div#1.
$('.box').click(function(){
var t = $(this);
if(t.hasClass('clicked')) {
return;
}
t.addClass('clicked');
var id = t.attr('id');
var val = t.attr('value');
//Set color
var up = parseInt(id) - 20;
var right = (id%20 != 19) ? ((0|id) + 1) : 'nothing' ;
var down = parseInt(id) + 20;
var left = (id%20 != 0) ? ((0|id) - 1) : 'nothing';
console.log(up, right, down, left);
if($('#'+down).attr('value') === val) {
$('#'+down).click();
}
if($('#'+right).attr('value') === val) {
$('#'+right).click();
}
if($('#'+up).attr('value') === val) {
$('#'+up).click();
}
if($('#'+left).attr('value') === val) {
$('#'+left).click();
}
});
You can schedule the clicks onto the event loop instead of calling them directly, eg:
if(clickdown == true){
setTimeout(function () {
$('#'+down).click();
});
}
I don't think that's your root cause though, it's probably a combination of global vars and scope issues. Try reformatting as such:
$('.box').click(function (event){
var t = $(this), id, val, up, right, down, left, clickup, clickdown;
//...
Your variables id and val are not in a var statement, thus are implicitly created as members of the window object instead of being scoped to the local function. Change the semicolon on the line before each to a comma so that they become part of the var statement, and your code should begin working.

Categories