I have a javascript function that is only working sometimes. I'm getting Uncaught TypeError: Cannot read property of undefined sometimes and sometimes the function works as expected.
To clearly explain and demonstrate the issue I recorded this short video: https://youtu.be/uSSes2_DPXU
Here is my function:
function openLightBox() {
var itemId = event.target.id;
var lightBox = document.getElementsByClassName(itemId);
console.log(lightBox);
lightBox[0].style.display = 'block' ;
}
SOLUTION
Final HTML:
<a onClick="openLightBox(<?php echo get_the_ID()?>)">
Final JS:
function openLightBox(id) {
var lightBox = document.getElementsByClassName(id);
console.log(lightBox);
lightBox[0].style.display = 'block';
}
The reason why it sometimes works, and I'm a bit guessing here, depends on where on the element you click. Since you have wrapped your a tag around the div that holds the id, does your a tag nicely wrap around the div dimension wise?
Actually it would make more sense to add the id to the a tag.
<a onClick="openLightBox(<?php echo get_the_ID()?>)">
Then your function will be someting like this:
function openLightBox(id) {
var lightBox = document.getElementById(id);
console.log(lightBox);
lightBox.style.display = 'block';
}
extra info: event bubbling and target -vs- currentTarget
You use event.target a bit wrong. So in snippet below you can see that target change depends where you click.
function openlightbox(e) {
console.log(e);
document.getElementById('target').innerHTML = e.target.outerHTML.replace(/</g, '<').replace(/>/g, '>');
}
.overlay {
background-color: #fbfbfb;
width: 100%;
height: 100%;
border: 1px solid black;
}
.title {
width: 200px;
height: 200px;
border: 1px solid red;
margin: auto;
}
h3 {
border: 1px solid green;
}
p {
border: 1px solid blue;
}
<article>
<a onclick="openlightbox(event)">
<div class='overlay' id="v1">
<div class="title">
<h3>Title</h3>
<p>category</p>
</div>
</div>
</a>
</article>
<pre id='target'></pre>
For solving you can just pass it directly to function. Or add event handler with addEventHandler function
var a = document.querySelectorAll('article a.open');
console.log(a);
for (var i = 0, len = a.length; i < len; i++) {
console.log(a[i],a[i].addEventListener);
a[i].addEventListener('click', function(e) {
document.getElementById('target').innerHTML = e.target.outerHTML.replace(/</g, '<').replace(/>/g, '>');
document.getElementById('target').innerHTML += '<br /> this.id:'+ this.id;
document.getElementById('target').innerHTML += '<br /> this:'+ this.outerHTML.replace(/</g, '<').replace(/>/g, '>');
},false);
}
.overlay {
background-color: #fbfbfb;
width: 100%;
height: 100%;
border: 1px solid black;
}
.title {
width: 200px;
height: 100px;
border: 1px solid red;
margin: auto;
}
h3 {
border: 1px solid green;
}
p {
border: 1px solid blue;
}
<article>
<a class="open" href="#" id="v1">
<div class='overlay'>
<div class="title">
<h3>Title</h3>
<p>category</p>
</div>
</div>
</a>
</article>
<pre id='target'></pre>
Related
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>
function myFunction() {
var element = document.getElementById("one1");
element.classList.toggle("one2");
var element = document.getElementById("two1");
element.classList.toggle("two2");
}
<style>
#section{margin-left:50px;
margin-right:50px
}
#monbouton{float:right;
font-size:25px;
width:50px;
height:50px;
background-color:#F1F1F1;
border:1px solid ##F1F1F1
}
#one1{
float:left;
width:40%;
height:100px;
border:1px solid blue
}
.one2{
width:10% !important;
height:200px;
border:1px solid red !important;
}
.one2 #afairedisparaitre{display:none
}
#two1{float:right;
width:59%;
height:100px;
border:1px solid green
}
.two2{width:89% !important
}
</style>
<!DOCTYPE html>
<html>
<body>
<div id="section">
<div id="one1">
<button id="monbouton" onclick="myFunction()">↔</button>
<div id="afairedisparaitre">This is DIV #one1<br />
Button toggle to CLASS .one2<br />
and reverse</div>
</div>
<div id="two1">This is DIV #two1<br />
Button toggle to CLASS .two2<br />
and reverse</div>
</div>
</body>
</html>
I am trying to make the leftside of my website shrink, so that the users can have a wider rightside if they find it more confortable.
What I am missing is a way that would keep the choice all over the site, when an other page is loaded, until the user clicks again. Maybe the solution would be a few more lines in js with "localStorage" ? I would really appreciate any help.
Made your CSS a bit better. Now we need to toggle only one class .with_toggle for #section.
It can sow errors here, in Snippet, but will fork fine on Codepan, see please. Try to switch it and reload the page on Codepan.
// checking if our storage is not empty
if (localStorage.toggled != '') {
// set class to #section form storage value
document.getElementById("section").classList.toggle(localStorage.toggled);
}
function myFunction() {
if (localStorage.toggled != "with_toggle") {
document.getElementById("section").classList.add("with_toggle");
localStorage.toggled = "with_toggle";
} else {
document.getElementById("section").classList.remove("with_toggle");
localStorage.toggled = "";
}
}
#section {
margin-left: 50px;
margin-right: 50px;
}
#monbouton {
float: right;
font-size: 25px;
width: 50px;
height: 50px;
background-color: #F1F1F1;
border: 1px solid #F1F1F1;
}
#one1 {
float: left;
width: 40%;
height: 100px;
border: 1px solid blue;
}
.with_toggle #one1 {
width: 10%;
border: 1px solid red;
}
.with_toggle #one1 #afairedisparaitre {
display: none;
}
#two1 {
float: right;
width: 59%;
height: 100px;
border: 1px solid green;
}
.with_toggle #two1 {
width: 89%;
}
<div id="section">
<div id="one1">
<button id="monbouton" onclick="myFunction()">↔</button>
<div id="afairedisparaitre">This is DIV #one1<br /> Button toggle to CLASS .one2<br /> and reverse</div>
</div>
<div id="two1">This is DIV #two1<br /> Button toggle to CLASS .two2<br /> and reverse</div>
</div>
Sure. Just create a localStorage variable that keeps track of whether the shrink should be active and use that to apply your styles on page load or something similar.
function shrinkActive() {
var shrink;
if (!(shrink = localStorage.getItem("shrink"))) {
localStorage.setItem("shrink", "false");
return false;
}
return JSON.parse(shrink);
}
function setShrink(active) {
var element1 = document.getElementById("one1");
var element2 = document.getElementById("two1");
if (active) {
element1.classList.add("one2");
element2.classList.add("two2");
} else {
element1.classList.remove("one2");
element2.classList.remove("two2");
}
localStorage.setItem("shrink", active.toString());
}
function myFunction() {
setShrink(!shrinkActive());
}
window.onload = function() {
setShrink(shrinkActive());
}
Link to working Codepen. https://codepen.io/bugcatcher9000/pen/pogZbrz?editors=1111
I have 10 links and each of them is different from the others.I want when user hovers on them background image of the div changes and a tooltip text be shown on top of the links with a fade-in animation .
i have tried to make several functions using JS and it works but it's a lot of code and mostly repetitive.I want a good shortcut through all of that useless coding.
document.getElementById("d1").onmouseover = function() {
mouseOver1()
};
document.getElementById("d2").onmouseover = function() {
mouseOver2()
};
document.getElementById("d3").onmouseover = function() {
mouseOver3()
};
document.getElementById("d1").onmouseout = function() {
mouseOut1()
};
document.getElementById("d2").onmouseout = function() {
mouseOut2()
};
document.getElementById("d3").onmouseout = function() {
mouseOut3()
};
function mouseOver1() {
document.getElementById("dogs").style.background = "blue";
document.getElementById("tooltiptext1").style.visibility = "visible";
}
function mouseOut1() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext1").style.visibility = "hidden";
}
function mouseOver2() {
document.getElementById("dogs").style.background = "green";
document.getElementById("tooltiptext2").style.visibility = "visible";
}
function mouseOut2() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext2").style.visibility = "hidden";
}
function mouseOver3() {
document.getElementById("dogs").style.background = "red";
document.getElementById("tooltiptext3").style.visibility = "visible";
}
function mouseOut3() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext3").style.visibility = "hidden";
}
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
#tooltiptext1,
#tooltiptext2,
#tooltiptext3 {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
visibility: hidden;
}
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre style="font-size:22px; color:darkorange">dogs</pre><br />
<pre>white Husky</pre>
<p id="tooltiptext1">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3">Tooltip text3</p>
</div>
</div>
Please have in mind that all of links will change same outer div object and the idea is to change the background image of that div and the tooltip shoud appear on the top of the links....so,
any ideas?
edit: added animation requested.
CSS is almost always better done in script by using classes when multiple elements are being manipulated with similar functions so I used that here. Rather than put some complex set of logic in place I simply added data attributes for the colors - now it works for any new elements you wish to add as well.
I did find your markup to be somewhat strangely chosen and would have done it differently but that was not part of the question as stated.
I took the liberty of removing the style attribute from your dogs element and put it in the CSS also as it seemed to belong there and mixing markup and css will probably make it harder to maintain over time and puts all the style in one place.
Since you DID tag this with jQuery here is an example of that.
$(function() {
$('#d-list').on('mouseenter', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorin'));
$(this).parent().next('.tooltip').animate({
opacity: 1
});
}).on('mouseleave', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorout'));
$(this).parent().next('.tooltip').animate({
opacity: 0
});
});
});
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
.dog-header {
font-size: 22px;
color: darkorange;
margin-bottom: 2em;
}
.tooltip {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
opacity: 0;
position:relative;
top:-4.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre class="dog-header">dogs</pre>
<pre>white Husky</pre>
<p id="tooltiptext1" class="tooltip">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2" class="tooltip">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3" class="tooltip">Tooltip text3</p>
</div>
</div>
Updated
This answer was written before the question was edited to show the intended markup/styling and before all the details were included. The code has been updated to work with that structure.
I think the simplest thing is just to create a configuration object to detail the varying bits, and then use common code for the rest. Here's one approach:
const configs = [
['d1', 'tooltiptext1', 'blue'],
['d2', 'tooltiptext2', 'green'],
['d3', 'tooltiptext3', 'red'],
];
configs.forEach(([id, tt, color]) => {
const dogs = document.getElementById('dogs');
const el = document.getElementById(id);
const tip = document.getElementById(tt);
el.onmouseover = (evt) => {
dogs.style.background = color
tip.style.visibility = "visible";
}
el.onmouseout = (evt) => {
dogs.style.background = "black";
tip.style.visibility = "hidden";
}
})
#dogs{float:right;margin-top:5%;background:#000;width:150px;height:150px}#d-list{color:#fff;direction:ltr;float:right;width:60%;height:60%}#tooltiptext1,#tooltiptext2,#tooltiptext3{color:#000;background-color:gray;width:120px;height:30px;border-radius:6px;text-align:center;padding-top:5px;visibility:hidden}
<div id="animals"> <div id="dogs"></div><div id="d-list"> <pre style="font-size:22px; color:darkorange">dogs</pre><br/> <pre>white Husky</pre> <p id="tooltiptext1">Tooltip text1</p><pre>black Bull</pre> <p id="tooltiptext2">Tooltip text2</p><pre>brown Rex</pre> <p id="tooltiptext3">Tooltip text3</p></div></div>
Obviously you can extend this with new rows really easily. And if you want to add more varying properties, you can simply make the rows longer. If you need to add too many properties to each list, an array might become hard to read, and it might become better to switch to {id: 'demo', tt: 'dem', color: 'blue'} with the corresponding change to the parameters in the forEach callback. (That is, replacing configs.forEach(([id, tt, color]) => { with configs.forEach(({id, tt, color}) => {.) But with only three parameters, a short array seems cleaner.
Older code snippet based on my made-up markup.
const configs = [
['demo', 'dem', 'blue'],
['dd', 'dem1', 'green']
];
configs.forEach(([id1, id2, color]) => {
const a = document.getElementById(id1)
const b = document.getElementById(id2)
a.onmouseover = (evt) => {
a.style.background = color
b.style.visibility = "visible";
}
a.onmouseout = (evt) => {
a.style.background = "black";
b.style.visibility = "hidden";
}
})
div {width: 50px; height: 50px; float: left; margin: 10px; background: black; border: 1px solid #666; color: red; padding: 10px; text-align: center}
#dem , #dem1{visibility:hidden;}
<div id="demo">demo</div>
<div id="dem">dem</div>
<div id="dd">dd</div>
<div id="dem1">dem1</div>
my way of seeing that => zero Javascript:
div[data-info] {
display: inline-block;
margin:80px 20px 0 0;
border:1px solid red;
padding: 10px 20px;
position: relative;
}
div[data-bg=blue]:hover {
background-color: blue;
color: red;
}
div[data-bg=green]:hover {
background-color: green;
color: red;
}
div[data-info]:hover:after {
background: #333;
background: rgba(0, 0, 0, .8);
border-radius: 5px;
bottom: 46px;
color: #fff;
content: attr(data-info);
left: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
min-width: 120px;
max-width: 220px;
}
div[data-info]:hover:before {
border: solid;
border-color: #333 transparent;
border-width: 6px 6px 0px 6px;
bottom: 40px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
<div data-info="Tooltip for A Tooltip for A" data-bg="blue">with Tooltip CSS3 A</div>
<div data-info="Tooltip for B" data-bg="green" >with Tooltip CSS3 B</div>
I am having problem of traversing through each HTML element one by one.There are two buttons #up and #down.On click of #up the id #myID should move to the next element upwards and vice versa for #down.The problem is I am able to move through the siblings but not through the child elements.
For example if I click on #down the id #myID should have moved to p tag which is the child of that div on next click to span which is child of p then on next click to div.But in my code it is directly jumping to div ignoring the children.
JSFIDDLE
Here is the code:
$("#up").click(function() {
$("#startHere").find("#myID").next().attr('id', 'myID');
$('#startHere').find("#myID").removeAttr('id');
});
$("#down").click(function() {
$("#startHere").find("#myID").prev().attr('id', 'myID');
$('#startHere').find("#myID").next().removeAttr('id');
})
#myID {
border: 2px solid yellow;
}
#startHere {
height: 100%;
width: 50%;
}
div {
height: 100px;
width: 100px;
border: 2px solid;
margin: 10px;
}
p {
height: 50px;
width: 50px;
border: 2px solid blue;
margin: 10px;
}
h1 {
height: 40px;
width: 40px;
border: 2px solid red;
margin: 10px;
}
span {
display: block;
height: 25px;
width: 25px;
border: 2px solid green;
margin: 10px;
}
button {
height: 25px;
width: 100px;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="up">GO DOWN</button>
<button id="down">GO UP</button>
<div id="startHere">
<div id="myID">
<p><span></span></p>
</div>
<div><span></span></div>
<div>
<h1></h1>
</div>
<p></p>
<h1></h1>
<p><span></span></p>
</div>
I think you can just find all the elements first, jQuery returns them in DOM order, which is what you want. No need to search for the next/prev element on-the-fly.
var allElements = $("#startHere").find('*');
var currentIndex = allElements.index('#myID');
function move(delta) {
// Find the new index
var index = currentIndex + delta;
// Clamp to 0…lengh of list
// Here we could also make it wrap instead
index = Math.max(Math.min(index, allElements.length - 1), 0);
// Remove the ID from the old element
allElements.eq(currentIndex).removeAttr('id');
// Add the ID to the new element
allElements.eq(index).attr('id', 'myID');
// Update the index
currentIndex = index;
}
$("#up").click(function() {
move(1);
});
$("#down").click(function() {
move(-1);
})
var allElements = $("#startHere").find('*');
var currentIndex = allElements.index('#myID');
function move(delta) {
// Find the new index
var index = currentIndex + delta;
// Clamp to 0…lengh of list
// Here we could also make it wrap instead
index = Math.max(Math.min(index, allElements.length - 1), 0);
// Remove the ID from the old element
allElements.eq(currentIndex).removeAttr('id');
// Add the ID to the new element
allElements.eq(index).attr('id', 'myID');
// Update the index
currentIndex = index;
}
$("#up").click(function() {
move(-1);
});
$("#down").click(function() {
move(1);
})
#myID {
border: 2px solid yellow;
}
#startHere {
height: 100%;
width: 50%;
}
div {
height: 100px;
width: 100px;
border: 2px solid;
margin: 10px;
}
p {
height: 50px;
width: 50px;
border: 2px solid blue;
margin: 10px;
}
h1 {
height: 40px;
width: 40px;
border: 2px solid red;
margin: 10px;
}
span {
display: block;
height: 25px;
width: 25px;
border: 2px solid green;
margin: 10px;
}
button {
height: 25px;
width: 100px;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="down">GO DOWN</button>
<button id="up">GO UP</button>
<div id="startHere">
<div id="myID">
<p><span></span></p>
</div>
<div><span></span></div>
<div>
<h1></h1>
</div>
<p></p>
<h1></h1>
<p><span></span></p>
</div>
If you do need the elements on-the-fly (because they might have changed), you can still use the same tactic (and simply build up the allElements list in the move function and get the index using allElements.index('#myID')) but it might be more performant to update the list only when you know it changed (after an Ajax request, after modification on event handlers, etc.).
Edit:
The code for searching the next/prev element on-the-fly is a bit more work because it has to recurse when traversing up but makes it possible to have a different set of rules for up vs. down movement.
var boundary = $("#startHere");
function findNext(node, anchor) {
if(!anchor && node.children(':first-child').length) {
return node.children(':first-child');
}
if(node.next().length) {
return node.next();
}
if(!boundary.find(node.parent()).length) {
// Out of boundary. Stick to the last node
return anchor||node;
}
return findNext(node.parent(), anchor||node);
}
function findPrev(node, anchor) {
if(!anchor && node.children(':last-child').length) {
return node.children(':last-child');
}
if(node.prev().length) {
return node.prev();
}
if(!boundary.find(node.parent()).length) {
// Out of boundary. Stick to the last node
return anchor||node;
}
return findPrev(node.parent(), anchor||node);
}
function move(finder) {
// Find the current item
var current = boundary.find('#myID');
// Find the next item
var next = finder(current);
// Remove the ID from the old element
current.removeAttr('id');
// Add the ID to the new element
next.attr('id', 'myID');
}
$("#up").click(function() {
move(findPrev);
});
$("#down").click(function() {
move(findNext);
})
var boundary = $("#startHere");
function findNext(node, anchor) {
if(!anchor && node.children(':first-child').length) {
return node.children(':first-child');
}
if(node.next().length) {
return node.next();
}
if(!boundary.find(node.parent()).length) {
// Out of boundary. Stick to the last node
return anchor||node;
}
return findNext(node.parent(), anchor||node);
}
function findPrev(node, anchor) {
if(!anchor && node.children(':last-child').length) {
return node.children(':last-child');
}
if(node.prev().length) {
return node.prev();
}
if(!boundary.find(node.parent()).length) {
// Out of boundary. Stick to the last node
return anchor||node;
}
return findPrev(node.parent(), anchor||node);
}
function move(finder) {
// Find the current item
var current = boundary.find('#myID');
// Find the next item
var next = finder(current);
// Remove the ID from the old element
current.removeAttr('id');
// Add the ID to the new element
next.attr('id', 'myID');
}
$("#up").click(function() {
move(findPrev);
});
$("#down").click(function() {
move(findNext);
})
#myID {
border: 2px solid yellow;
}
#startHere {
height: 100%;
width: 50%;
}
div {
height: 100px;
width: 100px;
border: 2px solid;
margin: 10px;
}
p {
height: 50px;
width: 50px;
border: 2px solid blue;
margin: 10px;
}
h1 {
height: 40px;
width: 40px;
border: 2px solid red;
margin: 10px;
}
span {
display: block;
height: 25px;
width: 25px;
border: 2px solid green;
margin: 10px;
}
button {
height: 25px;
width: 100px;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="down">GO DOWN</button>
<button id="up">GO UP</button>
<div id="startHere">
<div id="myID">
<p><span></span></p>
</div>
<div><span></span></div>
<div>
<h1></h1>
</div>
<p></p>
<h1></h1>
<p><span></span></p>
</div>
This is really bad UI. To select some nodes in some states, you first have to navigate “UP” and then “DOWN” again. But it seems to do what you ask for.
I was tinkering with event bubbling and I created the typical 3 divs each other exercise for myself and I was able to get the code working and event to stop "bubbling" where I wanted.
My code was clunky so I tried to make it a little more simplified. By having all my <divs> point to a single function, that had a statement that said if this <div> was clicked, run the function and then stop propagation, but I believe the way I am "checking" the click is wrong.
Link: https://jsfiddle.net/theodore_steiner/t5r5kov0/3/
var d1 = document.getElementById("d1");
var d2 = document.getElementById("d2");
var d3 = document.getElementById("d3");
function showme(event) {
if (d3.onclick == true) {
alert("hello")
event.stopPropagation();
} else {
alert("hello");
}
};
d1.addEventListener("click", showme);
d2.addEventListener("click", showme);
d3.addEventListener("click", showme);
#d1 {
height: 300px;
width: 300px;
border: 1px solid black;
}
#d2 {
height: 200px;
width: 200px;
border: 1px solid black;
}
#d3 {
height: 100px;
width: 100px;
border: 1px solid black;
}
<div id="d1">
<div id="d2">
<div id="d3">
</div>
</div>
</div>
Use event.target.id as event.target will return element on which event is invoked and id is a property of the DOMElement
Event.target, A reference to the object that dispatched the event.
var d1 = document.getElementById("d1");
var d2 = document.getElementById("d2");
var d3 = document.getElementById("d3");
function showme(event) {
if (event.target.id == 'd3') {
alert("hello")
event.stopPropagation();
} else {
alert("hello");
}
};
d1.addEventListener("click", showme);
d2.addEventListener("click", showme);
d3.addEventListener("click", showme);
#d1 {
height: 300px;
width: 300px;
border: 1px solid black;
}
#d2 {
height: 200px;
width: 200px;
border: 1px solid black;
}
#d3 {
height: 100px;
width: 100px;
border: 1px solid black;
}
<div id="d1">
<div id="d2">
<div id="d3">
</div>
</div>
</div>