Wondering what I'm doing wrong here - the function is supposed to look at all the cells in a table, add their default background color, font color and border color and then add an Event Listener to each that executes the anonymouse function to change a cells formatting depending on what key is held down onmousedown. It does the initial styling of all the cells correctly but that's it.
function setupPuzzle() {
allCells = document.querySelectorAll("table#hitoriGrid td");
for (var i = 0; i < allCells.length; i++) {
allCells[i].style.backgroundColor = "rgb(255,255,255)";
allCells[i].style.color = "rgb(0,0,0)";
allCells[i].style.borderRadius = "0px";
allCells[i].addEventListener("onmousedown", function(e) {
e.preventDefault();
if (e.shiftKey) {
allCells[i].style.backgroundColor = "rgb(255,255,255)";
allCells[i].style.color = "rgb(0,0,0)";
allCells[i].style.borderRadius = "0px";
} else if (e.altKey) {
allCells[i].style.backgroundColor = "rgb(0,0,0)";
allCells[i].style.color = "rgb(255,255,255)";
allCells[i].style.borderRadius = "0px";
} else {
allCells[i].style.backgroundColor = "rgb(101,101,101)";
allCells[i].style.color = "rgb(255,255,255)";
allCells[i].style.borderRadius = "50%";
}
});
}
}
Short answer is that you are listening for an onmousedown event so e.altKey and e.shiftKey is always false because the event passed to your callback function is an onmousedown event. I am not sure if you can actually read if a key is already pressed but one of solutions that come to my mind is to listen on events for keydown and store something like:
var keyPressed = [];
window.onkeyup = function(e) {keys[e.keyCode]=false;}
window.onkeydown = function(e) {keys[e.keyCode]=true;}
Then on mouse down event you can check in an array if key is pressed.
Edit: use mousedown
instead of onmousedown
for the event name as pointed out by the other answers. This edit has been made in the below code:
The issue is that i
does not point to the value that you expect it to. The scope of i
is not confined to the block that it is contained in, so all of your onmousedown
callbacks are going to reference an i
that is equal to allCells.length + 1
i
is incremented by 1 on each iteration of the for-loop, and this i
value is shared by all of your onmousedown
handlers, so by the time your for-loop finishes running, your handlers will all refer to i
, which will be allCells.length + 1
as that is the last value i
takes before the for-loop exits.
If you are using ES6, you can use let
instead of var
in your for-loop to fix the issue:
function setupPuzzle() {
allCells = document.querySelectorAll("table#hitoriGrid td");
for (let i = 0; i < allCells.length; i++) { // uset let instead of var
allCells[i].style.backgroundColor = "rgb(255,255,255)";
allCells[i].style.color = "rgb(0,0,0)";
allCells[i].style.borderRadius = "0px";
allCells[i].addEventListener("mousedown", function(e) {
e.preventDefault();
if (e.shiftKey) {
allCells[i].style.backgroundColor = "rgb(255,255,255)";
allCells[i].style.color = "rgb(0,0,0)";
allCells[i].style.borderRadius = "0px";
} else if (e.altKey) {
allCells[i].style.backgroundColor = "rgb(0,0,0)";
allCells[i].style.color = "rgb(255,255,255)";
allCells[i].style.borderRadius = "0px";
} else {
allCells[i].style.backgroundColor = "rgb(101,101,101)";
allCells[i].style.color = "rgb(255,255,255)";
allCells[i].style.borderRadius = "50%";
}
});
}
}
If you are not using ES6, you can use a closure to make sure that i
is scoped at the block-level (and therefore all of your event handlers will have their own reference of i
):
function setupPuzzle() {
allCells = document.querySelectorAll("table#hitoriGrid td");
for (var i = 0; i < allCells.length; i++) {
(function(i) { // closure
allCells[i].style.backgroundColor = "rgb(255,255,255)";
allCells[i].style.color = "rgb(0,0,0)";
allCells[i].style.borderRadius = "0px";
allCells[i].addEventListener("mousedown", function(e) {
e.preventDefault();
if (e.shiftKey) {
allCells[i].style.backgroundColor = "rgb(255,255,255)";
allCells[i].style.color = "rgb(0,0,0)";
allCells[i].style.borderRadius = "0px";
} else if (e.altKey) {
allCells[i].style.backgroundColor = "rgb(0,0,0)";
allCells[i].style.color = "rgb(255,255,255)";
allCells[i].style.borderRadius = "0px";
} else {
allCells[i].style.backgroundColor = "rgb(101,101,101)";
allCells[i].style.color = "rgb(255,255,255)";
allCells[i].style.borderRadius = "50%";
}
});
})(i); // captures surrounding value of i
}
}
mousedown
instead of onmousedown
i
value will be the last value of i
. so you need to use this
instead of allCells[i]
. function setupPuzzle() { allCells = document.querySelectorAll("table#hitoriGrid td"); for (var i = 0; i < allCells.length; i++) { allCells[i].style.backgroundColor = "rgb(255,255,255)"; allCells[i].style.color = "rgb(0,0,0)"; allCells[i].style.borderRadius = "0px"; allCells[i].addEventListener("mousedown", function(e) { e.preventDefault(); if (e.shiftKey) { this.style.backgroundColor = "rgb(255,255,255)"; this.style.color = "rgb(0,0,0)"; this.style.borderRadius = "0px"; } else if (e.altKey) { this.style.backgroundColor = "rgb(0,0,0)"; this.style.color = "rgb(255,255,255)"; this.style.borderRadius = "0px"; } else { this.style.backgroundColor = "rgb(101,101,101)"; this.style.color = "rgb(255,255,255)"; this.style.borderRadius = "50%"; } }); } } setupPuzzle();
<table id="hitoriGrid" border="2"> <tr> <td>Test</td> <td>Test</td> </tr> </table>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.