How to store previous event.currentTarget in a variable - javascript

I am trying to store the previous node of the event.currentTarget in a variable to apply some styling to the previous node, and another to the current node but so far I haven't find a way.
Bellow you'll find the code I am trying to write but doesn't seem to store the variable as the previous target
questionsArray.map((question) => {
if (Object.values(question).includes(true) == true) {
let previousTarget = e.currentTarget
console.log(previousTarget)
e.previousTarget.className = "qgroup red";
e.currentTarget.className = "qgroup blue";
}
})

Calling a variable previousTarget doesn't make it so. As is, this is just another name for the currentTarget. Move previousTarget outside the handler and only assign the currentTarget to it at the very end of the handler.
previousTarget will be undefined on first click, so be sure to handle that.
let prevTarget = null;
for (const div of [...document.querySelectorAll(".box")]) {
div.addEventListener("click", event => {
if (prevTarget) {
prevTarget.classList.remove("blue");
prevTarget.classList.add("red");
}
event.currentTarget.classList.add("blue");
prevTarget = event.currentTarget;
});
}
.box {
width: 50px;
height: 50px;
border: 1px solid black;
display: inline-block;
cursor: pointer;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
If you want the previous previous to be returned to the default state, you can do that too:
let prevTarget = null;
let prevPrevTarget = null;
for (const div of [...document.querySelectorAll(".box")]) {
div.addEventListener("click", event => {
if (prevPrevTarget) {
prevPrevTarget.classList.remove("red");
}
if (prevTarget) {
prevTarget.classList.remove("blue");
prevTarget.classList.add("red");
}
event.currentTarget.classList.add("blue");
prevPrevTarget = prevTarget;
prevTarget = event.currentTarget;
});
}
.box {
width: 50px;
height: 50px;
border: 1px solid black;
display: inline-block;
cursor: pointer;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>

Related

How to use JavaScript to add a class after clicking and then remove it after clicking again?

I just learned javascript not long ago, and I am practicing how to add color after clicking, and I can cancel the color when I click again!
But even though I checked on the Internet, I still don’t know which grammar is wrong?
Hope to get your guidance, thank you~
let add = document.querySelector('.add');
let box = document.querySelector('.box');
add.addEventListener('click',function(e){
e.preventDefault();
box.setAttribute('class','blue');
})
.add {
display: block;
margin-bottom: 100px;
}
.box {
width: 100px;
height: 100px;
border: 1px solid;
}
.blue {
background-color: blue;
}
<a class="add" href="javascript:;">click</a>
<div class="box"></div>
classList.toggle is exactly what you need. It will remove the class if already present and add it if not. See this.
let add = document.querySelector('.add');
let box = document.querySelector('.box');
add.addEventListener('click',function(e){
e.preventDefault();
box.classList.toggle('blue');
})
.add {
display: block;
margin-bottom: 100px;
}
.box {
width: 100px;
height: 100px;
border: 1px solid;
}
.blue {
background-color: blue;
}
<a class="add" href="javascript:;">click</a>
<div class="box"></div>
Problem in your code:
box.setAttribute('class','blue');
this will always overwrite the class to 'blue'
As you're interested in doing this using setAttribute, the following is one way to do it.
let add = document.querySelector('.add');
let box = document.querySelector('.box');
// not recommended
add.addEventListener('click', function(e) {
e.preventDefault();
const existingClasses = box.getAttribute('class');
const newClasses = (existingClasses.includes('blue') ? existingClasses.replace('blue', '') : `${existingClasses} blue`).trim();
box.setAttribute('class', newClasses);
})
.add {
display: block;
margin-bottom: 100px;
}
.box {
width: 100px;
height: 100px;
border: 1px solid;
}
.blue {
background-color: blue;
}
<a class="add" href="javascript:;">click</a>
<div class="box"></div>
You are missing an event handler in your javascript, that removes the class again. The only handler you have is the one adding blue.
box.addEventListener('click',function(e){
e.preventDefault();
box.removeAttribute('class');
})
You should check if the box has a class and if so, remove & else add
You can do it like this;
box.classList.contains("blue") ? box.classList.remove("blue") : box.classList.add("blue")

How can I add a class to an element from an array on hover?

I have an array of elements. I want when I hover on any element from this array to add a class to said element. How can I do that?
Loop through each item in the array and an event listener for mouseover which adds the class.
const array = document.querySelectorAll('div');
const classToAdd = 'red';
array.forEach(e => e.addEventListener('mouseover', () => {
e.classList.add(classToAdd);
}))
div {
height: 100px;
width: 100px;
border: 1px solid;
}
.red {
background-color: red;
}
<div></div>
<div></div>
<div></div>
<div></div>
If you have multiple elements with different ids or class you can try this.
let elements = ['#hud-menu', '#hud-intro', '.hud-shop', '.hud-settings'];
document.querySelectorAll(elements).forEach(element => {
element.addEventListener('mouseover', () => {
element.classList.add('blue');
});
});
div {
height: 100px;
width: 100px;
border: 2px solid;
border-radius: 10px;
text-align: center;
}
.blue {
background-color: blue;
}
<div id="hud-menu">Hud Menu</div><br>
<div id="hud-intro">Hud Intro</div><br>
<div class="hud-shop">Hud Shop</div><br>
<div class="hud-settings">Hud Settings</div>
And just in case if you want to remove the class when you stop hovering over an element you can use mouseout like the example below.
let elements = ['#hud-menu', '#hud-intro', '.hud-shop', '.hud-settings'];
// Add class on mouseover
document.querySelectorAll(elements).forEach(element => {
element.addEventListener('mouseover', () => {
element.classList.add('blue');
});
});
// Remove class on mouseout
document.querySelectorAll(elements).forEach(element => {
element.addEventListener('mouseout', () => {
element.classList.remove('blue');
});
});
div {
height: 100px;
width: 100px;
border: 2px solid;
border-radius: 10px;
text-align: center;
}
.blue {
background-color: blue;
}
<div id="hud-menu">Hud Menu</div><br>
<div id="hud-intro">Hud Intro</div><br>
<div class="hud-shop">Hud Shop</div><br>
<div class="hud-settings">Hud Settings</div>

How to get html element without its children in JavaScript?

I would like to get an html element without its children, to set an event addEventListener("click) on it, so that the function will only be executed when it is clicked, not on its children. I can only use Javascript. Is this possible?
const divs = document.querySelectorAll("div");
const body = document.querySelector("body");
const myFunction = function() {
this.classList.add("clicked")
}
divs.forEach(function(element) {
element.addEventListener("click", myFunction)
});
.grandparent {
padding: 20px;
border: 5px solid black;
}
.parent {
padding: 20px;
border: 5px solid blue;
}
.child {
padding: 20px;
height: 100px;
width: 100px;
border: 5px solid yellow;
}
.clicked {
background-color: red;
}
<div data-time="3000" class="grandparent">
<div data-time="2000" class="parent">
<div data-time="1000" class="child"></div>
</div>
</div>
this function adds a class to each div, now I would like clicking outside of div to remove that class, however the body variable contains including its children.
If you want to ignore all and any child clicks, then check if the currentTarget is different than the target of the event.
target is the element the event originated from (the deepest child that received the event)
currentTarget is the element on which the event handler is attached
const divs = document.querySelectorAll("div");
const body = document.querySelector("body");
const myFunction = function(event) {
if (event.target === event.currentTarget) {
this.classList.add("clicked")
}
}
divs.forEach(function(element) {
element.addEventListener("click", myFunction)
});
.grandparent {
padding: 20px;
border: 5px solid black;
}
.parent {
padding: 20px;
border: 5px solid blue;
}
.child {
padding: 20px;
height: 100px;
width: 100px;
border: 5px solid yellow;
}
.clicked {
background-color: red;
}
<div data-time="3000" class="grandparent">
<div data-time="2000" class="parent">
<div data-time="1000" class="child"></div>
</div>
</div>

Trigger event if click outside selector

I'm trying to click somewhere other than the button, hide the element, but I do not get it, I have no idea how to do it.
$(function(){
$(document).on('click','#foo',function(){
let div = $('#bar');
if( div.css('display') === 'none' ){
div.show();
}
else{
div.hide();
}
});
})
#foo{
min-width: 35%;
}
#bar{
max-width: 35%;
min-height: 100px;
background-color: aliceblue;
border: 1px solid blue;
border-radius: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="foo">Toggle</button><br><br>
<div id="bar"></div>
I got an idea but it doesn´t work.
$(document).on('click','html',function(e){
if(e.eventTarget !== 'foo'){
$('#bar').hide();
}
});
I got 2 issues, if the selector is html, the page will not answer, and the code in, is just to show what I'm trying to get.
No need for jQuery, you can simply test to see if .closest('#bar') exists:
const bar = document.querySelector('#bar');
let hidden = false;
document.body.addEventListener('click', (e) => {
if (e.target.closest('#foo')) {
console.log('clicked inside, returning');
return;
}
console.log('clicked outside');
bar.style.display = hidden ? 'block' : 'none';
hidden = !hidden;
});
body {
height: 200px;
}
#foo{
min-width: 35%;
}
#bar{
max-width: 35%;
min-height: 100px;
background-color: aliceblue;
border: 1px solid blue;
border-radius: 5px;
}
<button id="foo">Toggle</button>
<div id="bar"></div>
You may have to consume events bubbling up to parent node.
$(function() {
$('#foo').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
$('#bar').toggle();
console.log('toggle ... bar');
});
$(document).on('click', function(e) {
e.stopPropagation();
e.preventDefault();
$('#bar').hide();
console.log('hide ... bar');
});
})
#foo {
min-width: 35%;
}
#bar {
max-width: 35%;
min-height: 100px;
background-color: aliceblue;
border: 1px solid blue;
border-radius: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="foo">Toggle</button><br><br>
<div id="bar"></div>
I think it is better way to use focus and blur functions for that
Here is how I did
<button id="test">
Hello
</button>
<div class="blue-container" tabindex="1">
</div>
The tabindex global attribute indicates if its element can be focused
$('#test').focus(function () {
$('.blue-container').show().focus();
});
$('.blue-container').blur(function () {
$('.blue-container').hide();
});
This is the simplest approach.
$(document).on("click",function() {
if(event.target.id == 'foo') {
//if #foo is clicked, do nothing
}
else {
//if the button is not clicked
$('#bar').hide();
}
});
#foo{
min-width: 35%;
}
#bar{
max-width: 35%;
min-height: 100px;
background-color: aliceblue;
border: 1px solid blue;
border-radius: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="foo">Toggle</button><br><br>
<div id="bar"></div>

How to check if the click was directly in an element or some of its children only?

I don't want clicks on children other than some, and the parent div itself to trigger any events.
Please see this, which does not do what I want:
https://jsfiddle.net/k12e8rgt/3/
$(document).ready(function() {
$('#parent').on('click', function(event) {
alert("you clicked directly on me!");
});
});
you can use event.target
Example :
$(document).ready(function() {
$("div").on("click", function(event) {
alert("You click on : " + event.target.tagName)
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div>this is Div
<p>This is p</p>
</div>
Assign a class to elements which are to be ignored
Use .hasClass() to determine whether any of the matched elements are assigned the given class
$('#parent').on('click', function(event) {
if ($(event.target).hasClass('ignore')) {
alert("Ignore !");
} else {
alert("Do something!");
}
});
#parent {
width: 200px;
height: 200px;
background-color: blue;
color: white;
}
#child2 {
background-color: white;
color: red;
margin: 10px;
}
#child1 {
background-color: white;
color: green;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="parent">it should trigger here
<div id="child1">and here</div>
<div id="child2" class="ignore">but not here, and there are many of this kind</div>
</div>
If there are set of ids which are to be ignored, use event.target.id property and test the value against it!
$('#parent').on('click', function(event) {
if (event.target.id === 'child2' || event.target.id === 'child3') {
alert("Ignore !");
} else {
alert("Do something!");
}
});
#parent {
width: 200px;
height: 200px;
background-color: blue;
color: white;
}
#child2 {
background-color: white;
color: red;
margin: 10px;
}
#child3 {
background-color: white;
color: red;
margin: 10px;
}
#child1 {
background-color: white;
color: green;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="parent">it should trigger here
<div id="child1">and here</div>
<div id="child2">but not here, and there are many of this kind</div>
<div id="child3">but not here, and there are many of this kind</div>
</div>
Use event.target...
https://api.jquery.com/event.target/
Also, for event handling in general with jQuery...
https://learn.jquery.com/events/handling-events/

Categories