Does anyone know how to make a simple JavaScript onclick
event fire if the process of clicking the element causes an onchange event to fire elsewhere on the page? I've created a very simple page to demonstrate this problem:
<html>
<body>
<input type="text" name="test" id="test1" onchange="return change(event);" />
<a href="#" id="test2" onclick="return bang();">Bang</a>
<a href="#" id="test3" onclick="return boom();">Boom</a>
<script type="text/javascript">
function change(event) {
alert("Change");
return true;
}
function bang() {
alert("Bang!");
return true;
}
function boom() {
alert("Boom!");
return true;
}
</script>
</body>
</html>
If you click the bang link you get the Bang! alert. Boom gives you the Boom alert. And if you enter text in the text field and tab out you get the Change alert. All well and good.
However, if you enter text in the text field and, without tabbing or clicking anything else first, click either Bang or Boom you get the Change alert and nothing else. I would expect to see the Change alert followed by either Bang or Boom.
What's going on here? My change event returns true. How can I ensure that my click event is fired?
onchange is not fired when the value of an input is changed. It is only changed when the input's value is changed and then the input is blurred. What you'll need to do is capture the keypress event when fired in the given input. Then you'll test the value of the input against the value before it was keypressed.
The onchange event occurs when the value of an element has been changed. For radiobuttons and checkboxes, the onchange event occurs when the checked state has been changed.
So onclick is more of a cross browser solution. onchange happens only after the element lose focus. (You wont see a difference since you are calling alert and losing focus on every change). The pseudo code on MDC pretty much explains the element.
An element receives a click event when a pointing device button (such as a mouse's primary mouse button) is both pressed and released while the pointer is located inside the element.
Okay... So it seems like it's time for a bit of an explanation.
Explanation
You encounter this error because the onchange
event is triggered as soon as focus is moved away from the element. In your example the action that takes focuse away from the input
element is the mousedown
event which triggers as you click down on the mouse. This means that when you mousedown
on the link it fires off the onchange
function and pops up the alert.
The onclick
event on the other hand is triggered on the mouseup
event (i.e. when you release the pressure on the mouse - prove this to yourself by click, hold/pause, release
on a onlcick
event). Back to your situation... Before the mouseup
(i.e. onclick
) happens the focus is moved to the alert
triggered from your onchange
function.
Fix
There are a couple of options to fix this. Most simple change from using onclick="...."
to onmousedown="...."
.
Alternatively, you could use setTimeout
like,:
function change() {
setTimeout(function (){
alert("Change event")
}, 100)
}
I suggest the onmousedown
method as preferred. The setTimeout
method will fail if you click and hold on the link for more than the prescribed amount on the timeout.
The problem is that the alert()
function grabs the event chain somehow, test this:
<html>
<body>
<input type="text" name="test" id="test1" onchange="return change(event);" />
<a href="#" id="test2" onclick="return bang();">Bang</a> <a href="#" id="test3" onclick="return boom();">Boom</a>
<script type="text/javascript">
function change(event) {
console.log("change");
return true;
}
function bang() {
console.log("bang");
return true;
}
function boom() {
console.log("boom");
return true;
}
</script>
</body>
As you'll see you'll get the expected behaviour in the console.
JSBin
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With