Robert MacGrogan
Robert MacGrogan

Reputation: 357

onclick event not firing after onchange event

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?

Upvotes: 7

Views: 10729

Answers (4)

Abhishek Dixit
Abhishek Dixit

Reputation: 1

Just DO One Trick and bang!!!!

var isTest2ButtonClicked=false;
var test1 = document.getElementById("test1");
var test2 = document.getElementById("test2");
var test3 = document.getElementById("test3");

test1.onchange = function (event) {
    alert("Change");
    if(isTest2ButtonClicked)
    {
        //fire onclick event of test 2 button
        $('#test2').click();
    }
};

test2.onclick = function () {
    alert("Bang!");
};
test2.onmousedown= function () {
    isTest2ButtonClicked=true;
};
test3.onclick = function () {
    alert("Boom!");
};

Upvotes: 0

Steven
Steven

Reputation: 6148

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.

Upvotes: 5

Iron3eagle
Iron3eagle

Reputation: 1077

Rather than try and replicate your problem, I just created the solution in jsFiddle.

I seperated your HTML and your JavaScript.

HTML

<input type="text" name="test1" id="test1" />
<a href="#" id="test2">Bang</a> 
<a href="#" id="test3">Boom</a>

JavaScript

var test1 = document.getElementById("test1");
var test2 = document.getElementById("test2");
var test3 = document.getElementById("test3");

test1.onchange = function (event) {
    alert("Change");
};

test2.onclick = function () {
    alert("Bang!");
};

test3.onclick = function () {
    alert("Boom!");
};

After making a change in the text box and click out side of it will trigger the onchange event, and the onclick events will still fire. If you are expecting the change alert to fire for each key stroke change onchange to onkeyup.

Upvotes: 0

bitoiu
bitoiu

Reputation: 7484

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

Upvotes: 3

Related Questions