Reputation: 8663
I have a list of buttons, and on hover, a small (x) appears in the top right corner of the button. I am trying to attach a click handler on the (x), however, when ever i click it, the actually button is clicked, rather than the (x).
Code:
btnArray.forEach(function (button) {
const btn = document.createElement('div');
btn.type = 'button';
btn.value = button.name;
btn.onClick = evt => {
// do soemthing on click
}
btn.onmouseover = function(e) {
var me = d3.select(btn);
me.append('div')
.classed({'btn-close': true})
.append('div')
.classed({'btn-x-icon': true})
.text('x')
.on('click', function() {
alert('you clicked on the x!');
});
}
btn.onmouseout = function(e) {
var me = d3.select(btn);
me.selectAll('.btn-close')
.remove();
}
btn.appendChild(document.createTextNode(button.name))
});
Even when i place my mouse over the (x), the parent button still appears to be in focus.
UPDATE
I can click on the icon by increasing the z-index of the (x) icon.
Howvever, when clicking, the (x) onclick is called as well as the main btn.onclick call.
UPDATE
Markup:
<button type="button" value="Checkout" class="btn btn-primary">
Check out
<div class="btn-close">
<div class="btn-x-icon">x</div>
</div>
</button>
Upvotes: 1
Views: 1367
Reputation: 22339
Using event.target you can ensure you only respond to the correct element being clicked.
In the below examples I only added identifiers so I can attach the click events easier for demonstration but the code inside the event handlers is applicable as is to your code off course.
Also, note that I did not specify a
event
parameter in the handler becauseevent
is assigned automatically, when specifying a parameter for the event such as'click', function(evt)
you are now using the event object as specified by d3 which may or may not be the same event object.
var button = document.getElementById("button");
button.addEventListener('click', function() {
if (event.target == this) {
console.log('button clicked')
}
})
var button = document.getElementById("close");
button.addEventListener('click', function() {
console.log('close clicked')
})
#close {
background-color: red;
}
<button id="button" type="button" value="Checkout" class="btn btn-primary">
Check out
<div id="close" class="btn-close">
<div class="btn-x-icon">x</div>
</div>
</button>
Alternatively you can use stopPropagation
var button = document.getElementById("button");
button.addEventListener('click', function() {
console.log('button clicked')
})
var button = document.getElementById("close");
button.addEventListener('click', function() {
event.stopPropagation();
console.log('close clicked')
})
#close {
background-color: red;
}
<button id="button" type="button" value="Checkout" class="btn btn-primary">
Check out
<div id="close" class="btn-close">
<div class="btn-x-icon">x</div>
</div>
</button>
Upvotes: 1
Reputation: 1723
You should stop the propagation event on click. The event, once is produced, is propagated to all the inherent elements. You should stop that propagation in order to avoid execute more handlers for that event.
More about that Event bubbling (in the other way) and propagation http://www.javascripter.net/faq/eventbubbling.htm https://www.sitepoint.com/event-bubbling-javascript/
btnArray.forEach(function (button) {
const btn = document.createElement('div');
btn.type = 'button';
btn.value = button.name;
btn.onClick = evt => {
// do soemthing on click
}
btn.onmouseover = function(e) {
var me = d3.select(btn);
me.append('div')
.classed({'btn-close': true})
.text('x')
.on('click', function(evt) {
evt.stopPropagation();
alert('you clicked on the x!');
});
}
btn.onmouseout = function(e) {
var me = d3.select(btn);
me.selectAll('.btn-close')
.remove();
}
btn.appendChild(document.createTextNode(button.name))
});
Upvotes: 0