trying to change cell image once clicked, doesnt change upon click - javascript

I m trying to change the img on the cell once i click on it, however that does not happen, an explanation and a solution would be nice.
I am manually setting gBoard[0][0].isFlagged to true, and then clicking the cell, the img does not change.
html
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="ie=edge" http-equiv="X-UA-Compatible">
<title>Document</title>
<link href="css/game.css" rel="stylesheet">
</head>
<body onload="init()">
<h1>Welcome to minesweeper</h1>
<div class="board-container"></div><button class="restart-Btn" onclick="restartGame(this)">restartGame</button>
<script src="js/utils.js">
</script>
<script src="js/game.js">
</script>
</body>
</html>
script
const TILE = '<img src="/img/tile.png" >'
const TWO = '<img src="/img/2.png" >'
function printMat(mat, selector) {
var strHTML = '<table border="1"><tbody>';
for (var i = 0; i < mat.length; i++) {
strHTML += '<tr>';
for (var j = 0; j < mat[0].length; j++) {
var className = `cell-${i}-${j}`
strHTML +=
`<td class="${className}"
onclick="cellClicked(this, ${i}, ${j})">
<img src="${mat[i][j].image}" >
</td>`
}
strHTML += '</tr>'
}
strHTML += '</tbody></table>';
var elContainer = document.querySelector(selector);
elContainer.innerHTML = strHTML;
}
function createBoard(size) {
var board = []
for (var i = 0; i < size; i++) {
board[i] = []
for (var j = 0; j < size; j++) {
board[i][j] = creatCell()
}
}
return board
}
function creatCell() {
return {
isBomb: false,
isFlagged: false,
isClicked: false,
isOpen: false,
image: "/img/tile.png"
}
}
function cellClicked(elCell, i, j) {
if (gBoard[i][j].image === TILE && gBoard[i][j].isFlagged === true) {
elCell.innerHTML = TWO
}
}

If you check out the cellClicked() function, the first comparison is not right. TILE holds a string with the entire <img>element but gBoard[i][j].image is just the value of the src attribute, so this comparison:
gBoard[i][j].image === TILE
Is really comparing:
'<img src="/img/tile.png" >' === '/img/tile.png'
Which won't ever be true.
I got it to work by setting up a new variable, tileSrc:
const TILE = '<img src="/img/tile.png" >'
const tileSrc = '/img/tile.png';
Then in the conditional in cellClicked(), test against that:
if (gBoard[i][j].image === tileSrc && gBoard[i][j].isFlagged === true)
You can see it working here: Tiles App

Make sure the function is being called in the console.
Without the HTML I can't know for sure this is the issue but I had an issue of images not updating, but then I found out I had to 'force refresh' the image by adding a time stamp.
Maybe try:
function cellClicked(elCell, i, j) {
if (gBoard[i][j].image === TILE && gBoard[i][j].isFlagged === true) {
var timestamp = new Date().getTime();
elCell.innerHTML = TWO + '?' + timestamp
}
}

Related

JS Modules Error: "Uncaught ReferenceError: getActualGrid is not defined at <anonymous>:1:1"

I'm trying to make a 2D Array for Conway's Game of Life, but when I try to use the functions in the console for testing I get this error:
Uncaught ReferenceError: getActualGrid is not defined at <anonymous>:1:1
I don't understand where is it coming from. The functions are in global scope, yet it's like they weren't. When I use my code to run them it works fine (I add the commands that I want to use in the console at the end of the file), but I'm not being able to use them in my web browser. I assume It's because of modules usage...
Is there any way to solve this??
My HTML and JS code:
let rows = 9;
let columns = 9;
const width = 20;
export const generateGrid = () => {
let grid = "<table cellpadding=0 cellspacing=0 class='grid__container'>";
for (let y = 0; y < rows; y++) {
grid += "<tr>";
for (let x = 0; x < columns; x++) {
grid += `<td id="cell-${x + "-" + y}">`;
grid += "</td>";
}
grid += "</tr>";
}
grid += "</table>";
let table = document.querySelector("#grid");
table.innerHTML = grid;
let gridContainer = document.querySelector(".grid__container");
gridContainer.style.height = width * rows + "px";
gridContainer.style.width = width * columns + "px";
let cells = document.querySelectorAll("td");
cells.forEach((cell) => {
cell.addEventListener("mouseup", function (event) {
let cell = event.target;
changeStatus(cell);
});
});
};
export const changeStatus = (cell) => {
if (cell.style.background != "gray") {
cell.style.background = "gray";
} else {
cell.style.background = "";
}
};
let actualGrid = [];
export const getActualGrid = () => {
actualGrid = [];
for (let y = 0; y < rows; y++) {
actualGrid.push([]);
for (let x = 0; x < columns; x++) {
let cell = document.querySelector(`#cell-${x + "-" + y}`);
actualGrid[y][x] = cell.style.background == "gray";
}
}
};
generateGrid();
<!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">
<link rel="shortcut icon" href="./src/assets/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="./src/css/style.css">
<link rel="stylesheet" href="./src/css/table.css">
<title>The Game of Life</title>
</head>
<body>
<div id="grid" class="grid"></div>
<script type="module" src="./src/js/index.js"></script>
<script>
</script>
</body>
</html>
Everything work fine when I run it, I mean I got the

Javascript: Compare value of an input text box to the values of ul li elements

I am trying to compare the elements inside my unordered list to the value in the input textbox. If the value in the input text box matches a word in the unordered list I want to do something with that word in the unordered list.
Here is my JavaScript code:
function CheckWordMatch() {
var wordList = document.getElementById("wordSearchTable");
var wordListLi = wordList.getElementsByTagName("li");
var inputBoxText = document.getElementById("pickedLetters");
for (var i = 0; i < wordListLi.length; i++) {
if (inputBoxText.value === wordListLi[i].value) {
wordArray.style.textDecoration = "line-through";
console.log("IT WORKS");
}
}
}
#wordSearchTable is the ID of the unordered list.
#pickedLetters is the ID of the input text box.
Here is the entire javascript code and html code:
var allCells;
var found = false;
window.onload = init;
function init() {
document.querySelectorAll("aside h1")[0].innerHTML = wordSearchTitle;
document.getElementById("wordTable").innerHTML = drawWordSearch(letterGrid, wordGrid);
document.getElementById("wordList").innerHTML = showList(wordArray);
allCells = document.querySelectorAll("table#wordSearchTable td");
for (var i = 0; i < allCells.length; i++) {
allCells[i].addEventListener("mousedown", highlightLetters)
allCells[i].style.cursor = "pointer";
allCells[i].addEventListener("mouseup", removeMouseDown)
}
document.getElementById("pickedLetters").addEventListener('keyup', CheckWordMatch);
//document.getElementById("wordTable").addEventListener("mouseup", CheckWordMatch);
console.log("Hello");
}
/*============================================================*/
function drawWordSearch(letters, words) {
var rowSize = letters.length;
var colSize = letters[0].length;
var htmlCode = "<table id='wordSearchTable'>";
htmlCode += "<caption>Word Search</caption>";
for (var i = 0; i < rowSize; i++) {
htmlCode += "<tr>";
for (var j = 0; j < colSize; j++) {
if (words[i][j] == " ") {
htmlCode += "<td>";
} else {
htmlCode += "<td class='wordCell'>";
}
htmlCode += letters[i][j];
htmlCode += "</td>";
}
htmlCode += "</tr>";
}
htmlCode += "</table>";
return htmlCode;
}
function showList(list) {
var htmlCode = "<ul id='wordSearchList'>";
for (var i = 0; i < list.length; i++) {
htmlCode += "<li>" + list[i] + "</li>";
}
htmlCode += "</ul>";
return htmlCode;
}
function removeMouseDown(e) {
for (var i = 0; i < allCells.length; i++) {
allCells[i].removeEventListener("mouseenter", highlightLetters2)
}
CheckWordMatch();
}
function highlightLetters2(e) {
var inputBoxValue = document.getElementById("pickedLetters");
e.target.style.backgroundColor = "pink";
inputBoxValue.value = inputBoxValue.value + e.target.textContent;
for (var i = 0; i < allCells.length; i++) {
allCells[i].addEventListener("mouseup", removeMouseDown)
}
}
function highlightLetters(e) {
var inputBoxValue = document.getElementById("pickedLetters");
e.target.style.backgroundColor = "pink";
inputBoxValue.value = e.target.textContent;
for (var i = 0; i < allCells.length; i++) {
allCells[i].addEventListener("mouseenter", highlightLetters2)
}
}
function CheckWordMatch(event) {
var inputBoxText = event.target.value;
var wordList = document.getElementById("wordSearchTable");
var wordListLi = wordList.getElementsByTagName("li");
var inputBoxText = document.getElementById("pickedLetters");
for (var i = 0; i < wordListLi.length; i++) {
if (inputBoxText.value === wordListLi[i].textContent) {
wordArray.style.textDecoration = "line-through";
console.log("IT WORKS");
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Word Search</title>
<meta charset="utf-8" />
<link href="p2-layout.css" rel="stylesheet" />
<script src="p2-makeTable.js" async></script>
<script src="p2-wordSearch.js" async></script>
</head>
<body>
<section id="main">
<header><br></header>
<article>
<figure id="wordTable"></figure>
<input type="button" value="Show Solution" id="showSolution" />
</article>
<aside>
<h1 id="wordSearchTitle"></h1>
<input type="text" id="pickedLetters" readonly />
<figure id="wordList"></figure>
</aside>
</section>
</body>
</html>
First you'll need to attach an event listener to the input element #pickedLetters. I used keyup in this example but feel free to pick what suits your use-case best.
document.getElementById("pickedLetters").addEventListener('keyup', CheckWordMatch);
I also fixed some of your sample code. See below with comments:
function CheckWordMatch(event) {
// get the value of the target which is the value of the input element.
var inputBoxText = event.target.value;
var wordList = document.getElementById("wordSearchTable");
var wordListLi = wordList.getElementsByTagName("li");
for (var i = 0; i < wordListLi.length; i++) {
// since you want to compare the value of the input
// element with the value (or text) of the li element,
//you should use textContent or innerText.
if (inputBoxText === wordListLi[i].textContent) {
wordListLi[i].style.textDecoration = "line-through";
console.log("IT WORKS");
}
}
}
// attach an event listener to the input element to trigger your function.
document.getElementById("pickedLetters").addEventListener('keyup', CheckWordMatch);

Bind JS Pyramid in HTML

I created a pyramid using JavaScript and below is the code that I tried so far using for loop:
function showPyramid() {
var rows = 5;
var output = '';
for (var i = 1; i <= rows; i++) { //Outer loop
for (var j = 1; j <= i; j++) { //Inner loop
output += '* ';
}
console.log(output);
document.getElementById('result').innerHTML = output;
output = '';
}
}
Pretty basic! But I am trying to bind the result with HTML element, say with div as follows:
document.getElementById('result').innerHTML = output;
Instead it shows five stars in a row rather than the format in JS seeing in the console. Anything that I am missing here?
Full Code:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pyramid</title>
<script>
function showPyramid() {
var rows = 5;
var output = '';
for (var i = 1; i <= rows; i++) {
for (var j = 1; j <= i; j++) {
output += '* ';
}
console.log(output);
document.getElementById('result').innerHTML = output;
output = '';
}
}
</script>
</head>
<body onload="showPyramid();">
<h1>Pyramid</h1>
<div id="result"></div>
</body>
Currently, you are resetting the innerHTML at the end of each loop iteration; either use += to append HTML or append all the output together first, then set the innerHTML. Also, you will need to use the <br> tag to create line breaks in HTML.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pyramid</title>
<script>
function showPyramid() {
var rows = 5;
var output = '';
for (var i = 1; i <= rows; i++) {
for (var j = 1; j <= i; j++) {
output += '* ';
}
output += "<br/>";
}
document.getElementById('result').innerHTML += output;
}
</script>
</head>
<body onload="showPyramid();">
<h1>Pyramid</h1>
<div id = "result"></div>
</body>
</html>
const result = document.querySelector("#result");
function generatePyramid(max = 5) {
result.innerHTML = "";
const length = 2 * max - 1;
for (let i = 1; i <= max; i++) {
let s = "*".repeat(i).split("").join(" ");
s = s.padStart(
s.length + Math.floor((length - s.length) / 2)
).padEnd(length);
const div = document.createElement("div");
div.innerHTML = s.replace(/\s/g, " ");
result.appendChild(div);
}
}
// generatePyramid(); // base 5 stars
generatePyramid(11); // base 11 stars
// generatePyramid(21); // base 21 stars
<h1>Pyramid</h1>
<div id="result"></div>

Javascript: why is the alert saying undefined and not the letter "k"

I can get my array to work and display perfectly as a 2d array but the second I attempt to add another element it never shows it always stays undefined. I tried many different methods, in this version I attempted to duplicate the way that I add the 2d elements.
Ultimately I want to save data to the array to make the walls "#" that are displaying correctly to have further data stating "solid" and then I would be able to test for that before moving the "#"
I actually have a working version of this but using a second array which would get very cumbersome if I add further data.
Also as it is right now I am surprised the entire map is not getting overwritten with the letter k
function gameloop(){
var mainArray = [];
var mapSizeX = 32;
var mapSizeY = 128;
var arrayDepth = 10;
var idPos = {x:0, y:0};
function initMap(mainArray, mapSizeX, mapSizeY){
for (var i = 0; i < mapSizeX; i++) {
mainArray.push([0])
for (var j = 0; j < mapSizeY; j++) {
mainArray[i][j] = ".";
if(j == 0){mainArray[i][j] = "#";}
if(j == mapSizeY-1){mainArray[i][j] = "#";}
if(i == 0){mainArray[i][j] = "#";}
if(i == mapSizeX-1){mainArray[i][j] = "#";}
for (var k = 0; k < arrayDepth; k++) {
mainArray[i][j][k] = "k";
}
}
}
}
function nl(){GameScreen.innerText += "\n";}
function render() {GameScreen.innerText = mainArray.map(arr => arr.join("")).join("\n");
nl(); nl();}
function reposition(xChange,yChange,strA){
//mainArray[idPos.x][idPos.y] = ".";
//idPos.x = idPos.x + xChange;
//idPos.y = idPos.y + yChange;
//mainArray[idPos.x][idPos.y] = "#";
if(mainArray[idPos.x+xChange][idPos.y+yChange][1] === "Solid"){GameLog.innerText ="You can not travel in that direction"}
else{
mainArray[idPos.x][idPos.y] = ".";
idPos.x = idPos.x + xChange;
idPos.y = idPos.y + yChange;
mainArray[idPos.x][idPos.y] = "#";
GameLog.innerText = "You take a step to the " + strA
alert(mainArray[0][0][1]);
}
render();
}
//Startup
initMap(mainArray, mapSizeX, mapSizeY);
idPos.x = mapSizeX/2; idPos.y = mapSizeY/2;
mainArray[idPos.x][idPos.y] = "#";
//First Render
render();
document.addEventListener('keydown', function(event) {
if(event.keyCode === 38 ){reposition(-1,0,"North");}
if(event.keyCode === 40 ){reposition(1,0,"South");}
if(event.keyCode === 37 ){reposition(0,-1,"West");}
if(event.keyCode === 39 ){reposition(0,1,"East");}
//alert(event.keyCode);
});
}
gameloop();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<br>
<p style="color:#7d7d7d;font-family:Lucida Console;">Dungeon Valley.<br>
<font style="color:#ABABAB;font-family:Lucida Console;font-size:0.5em";>
Taming the Borderlands.<br>
v0.005 By heromedel. </P></font>
<P>
<section id="GameScreen" style="color:#000000;font-family:Lucida Console;"></section>
<P>
<section id="GameLog" style="color:#000000;font-family:Lucida Console;">Arrow Keys to move.<br></section>
<script src="main.js"></script>
</body>
</html>
If I'm understanding what you're trying to do, this is wrong:
for (var k = 0; k < arrayDepth; k++) {
mainArray[i][j][k] = "k";
}
mainArray is supposed to be a 2d array of strings, right? So why are you using var k to add a 3rd dimension to it? Unless you're trying to append to the string? In Javascript you append to strings with +, not with [].
By the way, this is also wrong:
mainArray.push([0])
You want to push an empty array [], not an array with a 0 in it [0].

how to display information underneath a specific button using javascript

I have the following piece of code I am working on. My purpose is to be able to grab information about different users from a specific website, display the name and other info and then have a button that when clicked, prints more information. I am able to get the information and display the name and picture, but when I click the button the information is displayed at the top of the page, not under the specific button that was clicked. I want for the information to be display under each user... I am new to Javascript and learning on my own, any help is appreciated!
function getUsers(user) {
var out = "";
var i;
for (i = 0; i < user.length; i++) {
out += '' + user[i].login + '<br>'+'</br> <img src="'+user[i].avatar_url+
'" alt="Image" style="width:304px;height:228px"</br></br>'+
'<button onclick=printRepos("'+user[i].repos_url+'")>Repositories</button></br>'+'<div id="id"></div>';
}
document.getElementById("id01").innerHTML = out;
}
Printing Function
function printF(array) {
var out = "";
var i;
for (i = 0; i < array.length; i++) {
out += array[i].id+'</br>';
}
document.getElementById("id").innerHTML = out;
}
This works fine. I just made div with dynamic ids and passed it to the function
function getUsers(user) {
var out = "";
var i;
for (i = 0; i < user.length; i++) {
out += '' + user[i].login + ' <br>'+'</br> <img src="'+user[i].avatar_url+
'" alt="Image" style="width:304px;height:228px"</br></br>'+
'<button onclick=printRepos("'+user[i].repos_url+'","'+i+'")>Repositories</button></br>'+'<div id="'+ 'id' + i +'"></div>';
}
document.getElementById("id01").innerHTML = out;
}
function printRepos(array, id) {
var out = "";
var i;
for (i = 0; i < array.length; i++) {
out += array[i].id+'</br>';
}
console.log('id' + id);
document.getElementById('id' + id).innerHTML = out;
}
Add the "this" keyword as a parameter to your onclicks, to pass in the button that was clicked:
<button onclick=printRepos(this,"'+user[i].repos_url+'")>Repositories</button>
Then locate the next div after that button in your event handler:
function printF(btn, array) {
var out = "";
var i;
for (i = 0; i < array.length; i++) {
out += array[i].id+'</br>';
}
// find the div
var d = btn; // start with the button
while (d.tagName != "DIV") d = d.nextSibling; // look for the next div
d.innerHTML = out;
}

Categories

Resources