Reputation:
I'm making a connect four game and right now I just want the console log the div that's being clicked on the board. But for some reason the div that's being logged isn't the one that's clicked on.The div that's logged is always at the bottom of the board? Can someone please help me understand why this is happening. Thanks:)
const board = document.querySelectorAll(".slot");
for(let i = 0; i < board.length; i++) {
board[i].addEventListener('click', dropChip);
}
function dropChip() {
console.log(this);
}
/** {
border: 1px solid red;
}*/
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
body {
display: flex;
justify-content: flex-end;
min-height: 100vh;
background-color: #e6e9ef;
flex-direction: column;
}
.board-wrapper {
/*display: flex;*/
margin: 0 auto;
padding-top: 100px;
position: relative;
overflow: hidden;
}
.board {
display: flex;
background-color: #00c;
flex-wrap: wrap;
max-width: 706px;
padding: 3px;
/*margin: auto;*/
}
.board>div {
width: 100px;
height: 100px;
background-color: blue;
border: 3px solid #00c;
cursor: pointer;
position: relative;
}
.board>div:after {
content: "";
position: absolute;
z-index: 99;
left: 0;
right: 0;
top: -999em;
bottom: -999em;
transition: all .5s ease;
background-color: transparent;
}
.board>div:hover:after {
background-color: #00c;
}
.board>div.counter {
/*display: block;
padding: 0;*/
position: absolute;
top: 0;
left: 0;
right: 0;
width: auto;
height: 100px;
border: none;
background-color: #e6e9ef;
z-index: 100;
}
.board>div.counter:after {
/*content: "";*/
/*display: block;*/
/*padding: 0;*/
height: 80px;
width: 80px;
background-color: red;
top: 0;
/*left: 0;
right: auto;*/
border-radius: 50%;
transition: transform .5s ease, opacity .2s ease;
/*transform: translateX(0);*/
z-index: 100;
opacity: 0;
}
.board>div.counter:before {
content: "";
display: block;
padding: 0;
position: absolute;
top: 15px;
left: 15px;
right: auto;
height: 50px;
width: 50px;
border-radius: 50%;
background-color: red;
box-shadow: inset 0px 0px 25px #cc0000;
z-index: 101;
transition: transform .5s ease, opacity .2s ease;
/*transform: translateX(0);*/
opacity: 0;
}
.board>div:nth-of-type(7n+1):hover~.counter:after {
transform: translateX(14px);
opacity: 1;
}
.board>div:nth-of-type(7n+2):hover~.counter:after {
transform: translateX(114px);
opacity: 1;
}
.board>div:nth-of-type(7n+3):hover~.counter:after {
transform: translateX(214px);
opacity: 1;
}
.board>div:nth-of-type(7n+4):hover~.counter:after {
transform: translateX(314px);
opacity: 1;
}
.board>div:nth-of-type(7n+5):hover~.counter:after {
transform: translateX(414px);
opacity: 1;
}
.board>div:nth-of-type(7n+6):hover~.counter:after {
transform: translateX(514px);
opacity: 1;
}
.board>div:nth-of-type(7n+7):hover~.counter:after {
transform: translateX(614px);
opacity: 1;
}
.board>div:nth-of-type(7n+1):hover~.counter:before {
transform: translateX(14px);
opacity: 1;
}
.board>div:nth-of-type(7n+2):hover~.counter:before {
transform: translateX(114px);
opacity: 1;
}
.board>div:nth-of-type(7n+3):hover~.counter:before {
transform: translateX(214px);
opacity: 1;
}
.board>div:nth-of-type(7n+4):hover~.counter:before {
transform: translateX(314px);
opacity: 1;
}
.board>div:nth-of-type(7n+5):hover~.counter:before {
transform: translateX(414px);
opacity: 1;
}
.board>div:nth-of-type(7n+6):hover~.counter:before {
transform: translateX(514px);
opacity: 1;
}
.board>div:nth-of-type(7n+7):hover~.counter:before {
transform: translateX(614px);
opacity: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Connect Four</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="board-wrapper">
<div class="board">
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="counter"></div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Upvotes: 1
Views: 956
Reputation: 19967
Normally I don't use this
in event listener. I find it very confusing, should be considered an antipattern. You can use evt.target
, way more clear.
const board = document.querySelectorAll(".slot");
for(let i = 0; i < board.length; i++) {
board[i].addEventListener('click', dropChip);
}
function dropChip(evt) {
console.log(evt.target);
}
As to an explanation, I'm confused too. I think your code should work...
Edit: So it turns out to be a css problem (see Maaz's answer), I didn't look into the stylesheet, miss that part. OP's script is valid, it does work.
Upvotes: 1
Reputation: 4650
It's been found out that the issue is actually the CSS, but I'm leaving this here for extra infomation.
The common approach would be to pass the event.target
as an argument on the dropChip
function
const board = document.querySelectorAll(".slot");
for(let i = 0; i < board.length; i++) {
board[i].addEventListener('click', function(evt){ dropChip(evt.target) });
}
function dropChip(div) {
console.log(div);
}
Event listeners will always automatically supply an event
object when executing the callback, which is why we added an evt
parameter on our anonymous function.
You can also omit the anonymous function if you want to be straightforward
for(let i = 0; i < board.length; i++) {
board[i].addEventListener('click', dropChip);
}
function dropChip(evt) {
console.log(evt.target);
}
You can also pass the iterated item instead during the loop
for(let i = 0; i < board.length; i++) {
board[i].addEventListener('click', function(evt){ dropChip(board[i]) });
}
Upvotes: 4
Reputation: 6112
Commenting out .board>div:after
CSS rule solves the problem of the right this
context. It's because all your slot div
s are the same height. So the lower most div
s in the DOM are positioned above the rest. Your JS is actually fine, it's the CSS that makes the div
s so large that it looks like you're clicking on one, but the click is registered on something else much lower in the DOM.
const board = document.querySelectorAll(".slot");
for(let i = 0; i < board.length; i++) {
board[i].addEventListener('click', dropChip);
}
function dropChip() {
console.log(this);
}
/** {
border: 1px solid red;
}*/
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
body {
display: flex;
justify-content: flex-end;
min-height: 100vh;
background-color: #e6e9ef;
flex-direction: column;
}
.board-wrapper {
/*display: flex;*/
margin: 0 auto;
padding-top: 100px;
position: relative;
overflow: hidden;
}
.board {
display: flex;
background-color: #00c;
flex-wrap: wrap;
max-width: 706px;
padding: 3px;
/*margin: auto;*/
}
.board>div {
width: 100px;
height: 100px;
background-color: blue;
border: 3px solid #00c;
cursor: pointer;
position: relative;
}
/* Commented out.
.board>div:after {
content: "";
position: absolute;
z-index: 99;
left: 0;
right: 0;
top: -999em;
bottom: -999em;
transition: all .5s ease;
background-color: transparent;
}*/
.board>div:hover:after {
background-color: #00c;
}
.board>div.counter {
/*display: block;
padding: 0;*/
position: absolute;
top: 0;
left: 0;
right: 0;
width: auto;
height: 100px;
border: none;
background-color: #e6e9ef;
z-index: 100;
}
.board>div.counter:after {
/*content: "";*/
/*display: block;*/
/*padding: 0;*/
height: 80px;
width: 80px;
background-color: red;
top: 0;
/*left: 0;
right: auto;*/
border-radius: 50%;
transition: transform .5s ease, opacity .2s ease;
/*transform: translateX(0);*/
z-index: 100;
opacity: 0;
}
.board>div.counter:before {
content: "";
display: block;
padding: 0;
position: absolute;
top: 15px;
left: 15px;
right: auto;
height: 50px;
width: 50px;
border-radius: 50%;
background-color: red;
box-shadow: inset 0px 0px 25px #cc0000;
z-index: 101;
transition: transform .5s ease, opacity .2s ease;
/*transform: translateX(0);*/
opacity: 0;
}
.board>div:nth-of-type(7n+1):hover~.counter:after {
transform: translateX(14px);
opacity: 1;
}
.board>div:nth-of-type(7n+2):hover~.counter:after {
transform: translateX(114px);
opacity: 1;
}
.board>div:nth-of-type(7n+3):hover~.counter:after {
transform: translateX(214px);
opacity: 1;
}
.board>div:nth-of-type(7n+4):hover~.counter:after {
transform: translateX(314px);
opacity: 1;
}
.board>div:nth-of-type(7n+5):hover~.counter:after {
transform: translateX(414px);
opacity: 1;
}
.board>div:nth-of-type(7n+6):hover~.counter:after {
transform: translateX(514px);
opacity: 1;
}
.board>div:nth-of-type(7n+7):hover~.counter:after {
transform: translateX(614px);
opacity: 1;
}
.board>div:nth-of-type(7n+1):hover~.counter:before {
transform: translateX(14px);
opacity: 1;
}
.board>div:nth-of-type(7n+2):hover~.counter:before {
transform: translateX(114px);
opacity: 1;
}
.board>div:nth-of-type(7n+3):hover~.counter:before {
transform: translateX(214px);
opacity: 1;
}
.board>div:nth-of-type(7n+4):hover~.counter:before {
transform: translateX(314px);
opacity: 1;
}
.board>div:nth-of-type(7n+5):hover~.counter:before {
transform: translateX(414px);
opacity: 1;
}
.board>div:nth-of-type(7n+6):hover~.counter:before {
transform: translateX(514px);
opacity: 1;
}
.board>div:nth-of-type(7n+7):hover~.counter:before {
transform: translateX(614px);
opacity: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Connect Four</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="board-wrapper">
<div class="board">
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="slot"></div>
<div class="counter"></div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
If the purpose of that rule is to highlight all the div
s in a column, you might need a different approach.
Upvotes: 2