Reputation: 61
I have a html
And js
as below :
document.addEventListener('click', myFunction())
function myFunction(e) {
let inputs = document.querySelectorAll('.my-element');
let m = inputs.forEach((el) => el.contains(e.target));
if (!m) {
console.log('Element');
}
}
<div class="my-element" style: "width:100px; height: 100px">
</div>
<div class="my-element" style: "width:100px; height: 100px">
</div>
<div class="my-element" style: "width:100px; height: 100px">
</div>
The problem is, the condition works even if I click inside the target. I need that the condition works only if I click outside of the elements. What my mistake is?
Upvotes: 2
Views: 113
Reputation: 1
If you want a click event to fire only if it isn't over certain elements you have to check if the event target is not the same as any it those elements
You almost have it except you are setting the value of m to a forEach which always returns undefined, then checking !m which will always be true
Just make a new array from the node list and set m to the .find value instead, so altogether
document.addEventListener('click', myFunction)
function myFunction(e) {
let inputs = document.querySelectorAll('.my-element');
let titles = document.querySelectorAll('.my-title');
let m = Array.apply(0,inputs).find((el) => el.contains(e.target));
if (!m) {
console.log('Element');
}
}
Upvotes: 1
Reputation: 12629
Remove ()
from myFunction
in document.addEventListener('click', myFunction())
just use document.addEventListener('click', myFunction)
.
You can use Element.matches()
with target
as e.target.matches('.my-element')
and verify that it is the one you want. matches
will take selector
as parameter
.
Try in below sample, when you click on label
or input
it won't log
anything. When you click other part of div
then it will log
.
document.addEventListener('click', myFunction);
function myFunction(e) {
//let inputs = document.querySelectorAll('.my-element');
//let titles = document.querySelectorAll('.my-title');
//let m = inputs.forEach((el) => el.contains(e.target));
if (e.target.matches('.my-element')) {
console.log('Element', e.target.innerText);
}
}
<div class="my-element" style: "width:100px; height: 100px">
<label>abcd</label>
</div>
<div class="my-element" style: "width:100px; height: 100px">
<input type='text' value='input' />
</div>
<div class="my-element" style: "width:100px; height: 100px">c
</div>
Upvotes: 0
Reputation: 14904
Here:
Because inputs
is an nodelist you need to convert it to an array.
I have done i here with the spread operator ...
You can also do it with Array.from
, [].concat(inputs)
Then you filter the array for your e.target
and check if the length is 0.
document.addEventListener('click', myFunction)
function myFunction(e) {
let inputs = document.querySelectorAll('.my-element');
let m = [...inputs].filter(el => el === e.target);
if (!m.length) {
console.log('Element');
}
}
<div class="my-element" style="background: black;margin: 10px;width:100px; height: 100px">
</div>
<div class="my-element" style="background: black;margin: 10px;width:100px; height: 100px">
</div>
<div class="my-element" style="background: black;margin: 10px;width:100px; height: 100px">
</div>
Upvotes: 1