I am doing a Connect Four in HTML CSS JS and I want to display a token at the top of the grid if you are hover the grid, align to the column so I put a listener to the grid. But to display this I need to go over all the elements at least one time and then after it will display as expected.
Here's the snippet, I'm sorry for the low quality code
quiJoue = 0;
$('#grille').on("mouseover", function(e) {
let couleur = quiJoue % 2 === 0 ? "Jaune" : "Rouge";
let classes = e.target.classList;
if (classes.contains("top") && classes.contains("pion")) {
let courant = e.target;
$(courant).css("background", 'yellow').css("background-size", "contain");
} else if (classes.contains('pion')) {
let courant = (e.target);
let colonne = (e.target.parentNode.classList[2]).split("-")[1];
$('.cell.row-top.colonne-' colonne).children().css("background", 'yellow').css("background-size", "contain")
$(courant).hover(function() {
$('.cell.row-top.colonne-' colonne).children().addClass('top_hover');
}, function() {
$('.cell.row-top.colonne-' colonne).children().removeClass('top_hover')
});
} else if (classes.contains('cell')) {
let colonne = (e.target.classList[2]).split("-")[1];
let courant = (e.target);
$('.cell.row-top.colonne-' colonne).children().css("background", 'yellow').css("background-size", "contain")
$(courant).hover(function() {
$('.cell.row-top.colonne-' colonne).children().addClass('top_hover');
}, function() {
$('.cell.row-top.colonne-' colonne).children().removeClass('top_hover')
});
}
});
.game-board {
display: grid;
grid-template-columns: repeat(7, 1fr);
height: 700px;
margin: 10px 0 25px;
width: 700px;
}
.cell {
align-items: center;
background: #4370F1;
display: flex;
height: 100px;
justify-content: center;
width: 100px;
}
.pion {
background: white;
background-size: contain;
border-radius: 50%;
border: 3px solid black;
height: 75px;
width: 75px;
}
.top {
transition: opacity 50ms linear;
opacity: 0;
border: 0;
}
.top:hover {
transition: opacity 50ms linear;
background-size: contain;
opacity: 1;
}
.top_hover {
transition: opacity 50ms linear;
background-size: contain;
opacity: 1;
}
.cell:not(.row-top).red::after {
background: red;
}
.cell:not(.row-top).yellow::after {
background: yellow;
}
.cell:not(.row-top).red.win {
background: red;
}
.cell:not(.row-top).yellow.win {
background: yellow;
}
.cell.row-top {
background: rgba(255, 255, 255, 0);
}
.cell.row-top::after {
border: none;
}
.cell.row-top.red::after {
background: red;
border: 3px solid black;
}
.cell.row-top.yellow::after {
background: yellow;
border: 3px solid black;
}
.left-border {
border-left: 3px solid black;
}
.top-border {
border-top: 3px solid black;
}
.right-border {
border-right: 3px solid black;
}
.bottom-border {
border-bottom: 3px solid black;
}
.left-border.top-border {
border-radius: 10px 0 0 0;
}
.right-border.top-border {
border-radius: 0 10px 0 0;
}
.right-border.bottom-border {
border-radius: 0 0 10px 0;
}
.left-border.bottom-border {
border-radius: 0 0 0 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<div id="grille" style="grid-template-columns: repeat(7, 1fr);">
<div >
<div style="background: rgba(0, 0, 0, 0) url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: rgba(0, 0, 0, 0) url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: rgba(0, 0, 0, 0) url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: rgba(0, 0, 0, 0) url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: rgba(0, 0, 0, 0) url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: rgba(0, 0, 0, 0) url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: rgba(0, 0, 0, 0) url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
</div>
</div>
CodePudding user response:
I will try to demonstrate the issue in some bullet points, so let me know if they are not clear enough.
- After the compiling process ends and your page load, there are no listeners attached to the game elements.
- In the first hover iteration, your code will initialize the event listener dynamically but will not execute it.
- After that, you have a listener attached to your element and will fire its callback function from now on.
- So, for every hover event after that, your code will work as expected
SOLUTION
We need to attach the event listener to all game elements statically not dynamically. so here is the JS code we need.
$(".pion").hover(function(e) {
const colonne = (e.target.parentNode.classList[2]).split("-")[1];
$('.cell.row-top.colonne-' colonne).children().toggleClass('top_hover');
})
It will select all elements with pion
class and will attach them our hover event that toggles the class name of the related colonne
number.
Note: I have hard-coded the background color of the token to yellow in the HTML snippet for all columns. you can remove it and handle the logic of Jaune
and Rouge
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
$(".pion").hover(function(e) {
const colonne = (e.target.parentNode.classList[2]).split("-")[1];
$('.cell.row-top.colonne-' colonne).children().toggleClass('top_hover');
})
.game-board {
display: grid;
grid-template-columns: repeat(7, 1fr);
height: 700px;
margin: 10px 0 25px;
width: 700px;
}
.cell {
align-items: center;
background: #4370F1;
display: flex;
height: 100px;
justify-content: center;
width: 100px;
}
.pion {
background: white;
background-size: contain;
border-radius: 50%;
border: 3px solid black;
height: 75px;
width: 75px;
}
.top {
transition: opacity 50ms linear;
opacity: 0;
border: 0;
}
.top:hover {
transition: opacity 50ms linear;
background-size: contain;
opacity: 1;
}
.top_hover {
transition: opacity 50ms linear;
background-size: contain;
opacity: 1;
}
.cell:not(.row-top).red::after {
background: red;
}
.cell:not(.row-top).yellow::after {
background: yellow;
}
.cell:not(.row-top).red.win {
background: red;
}
.cell:not(.row-top).yellow.win {
background: yellow;
}
.cell.row-top {
background: rgba(255, 255, 255, 0);
}
.cell.row-top::after {
border: none;
}
.cell.row-top.red::after {
background: red;
border: 3px solid black;
}
.cell.row-top.yellow::after {
background: yellow;
border: 3px solid black;
}
.left-border {
border-left: 3px solid black;
}
.top-border {
border-top: 3px solid black;
}
.right-border {
border-right: 3px solid black;
}
.bottom-border {
border-bottom: 3px solid black;
}
.left-border.top-border {
border-radius: 10px 0 0 0;
}
.right-border.top-border {
border-radius: 0 10px 0 0;
}
.right-border.bottom-border {
border-radius: 0 0 10px 0;
}
.left-border.bottom-border {
border-radius: 0 0 0 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<div id="grille" style="grid-template-columns: repeat(7, 1fr);">
<div >
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div >
<div style="background: yellow url("../img/pionJaune.png") repeat scroll center center / contain;"></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
<div data-couleur="">
<div ></div>
</div>
</div>
</div>