When a mousedown and mouseup event don't equal a click
I've been usin开发者_运维百科g some buttons for a while now that have a depressed effect as they are clicked using position relative and a top: 1px in the :active pseudo-class.
I had problems with click events not firing and it turned out to be due to the mousedown and mouseup events not firing on the same element. I did a bit of fiddling to make sure the inner-most element covered the whole button and discovered that the issue remained.
If I click right at the top of the text then the link jumps down (firing the mousedown event) and then back up (firing the mouseup event) but the click does not occur. If I click nicely in the middle of the text or nicely away from the text all is fine.
The only thing I can think of here is that the mousedown event is firing on the textNode and the mouseup is firing on the anchor element as as the textNode is no longer under the cursor. Catching the event objects and looking at the targets using firebug indicates this is not the case but I really can't think of another explanation. Reading around a bit I can find some mention of events firing on textNodes in Safari but nothing about this mismatch.
The following snippet should allow you to replicate the problem. Remember, you must click right at the top of the text, or a pixel or two above, and this issue only occurs with one row of pixels:
<style>
a.button-test {
display: inline-block;
padding: 20px;
background: red;
}
.button-test:active {
position: relative;
top: 1px;
}
</style>
<a class="button-test" href="#">Clickedy click</a>
Messing around with the CSS, not using inline-block, increasing line-height instead of padding etc. doesn't seem to have an effect here. I've tried many combinations. Most of my testing has been done in Firefox to allow me to bind to the events and record what's going on through firebug but I also encounter this problem in other browsers.
Does anyone have any inspiration they can offer on this other than lose the active jump? I'd really like to keep this effect if I can.
Big thanks,
Dom (no pun intended)
Here's my workaround using a custom event with jQuery
var buttonPressed;
// Track buttonPressed only on button mousedown
$(document).on('mousedown', 'button', function (e) {
// Make sure we store the actual button, not any contained
// element we might have clicked instead
buttonPressed = $(e.target).closest('button');
});
// Clear buttonPressed on every mouseup
$(document).on('mouseup', function (e) {
if (buttonPressed) {
// Verify it's the same target button
var target = $(e.target).closest('button');
if (target.is(buttonPressed)) {
buttonPressed.trigger('buttonClick');
}
buttonPressed = null;
}
});
$('button').on('buttonClick', function (e) {
// Do your thing
});
Just make sure you don't handle both the native click and buttonClick events.
It's much easier to reproduce this problem if you change the style to top: 10px
精彩评论