Mind to Code

I code and talk about it

Dont Mix jQuery Events With Inline Event Handlers

| Comments

Hello world,

a few days ago I wasted a lot of time and raw nerves on a tiny problem with legacy code.

The project in question uses jQuery extensively, including its event system. On a page I wanted to prevent the default action on a link tag.

Normally clicking on it would submit the surrounding form, which I didn’t want here. So I removed all javascript click events on the tag by inserting

Remove the click events
1
  $("#the-link").unbind("click");

in the page.

Yay, all good now … or not. The form still submitted!

After some time banging my head against the wall, looking for some other events that might fire, I finally saw and realized, that the form submit is attached to the link tag via an inline evend handler.

Remove the click events
1
  <a href="#" id="the-link" onclick="$('form').submit();">click me</a>

While looking through the jQuery events attached to the tag, I didn’t see this event. By the way, small hint:

If you want to see all events attached to a jQuery selector, the fastest way is:

Show all events attached to a jQuery object
1
  $("#the-link").data('events');

That gives you an object with all events,

Show all events attached to a jQuery object
1
  $("#the-link").data('events').click;

gives you just the click events.

However, I didn’t see any click events left on that link, so I finally realized: jQuery doesn’t show me the javascript inline event handlers, like the onclick and it also doesn’t remove them on unbind().

If you really wand to get rid of all events bound to a html element, jQuery or inline, you have to unbind via jQuery and remove the content of the onclick attribute.

Show all events attached to a jQuery object
1
2
  $("#the-link").unbind("click");
  $("#the-link").attr('onclick', '');

The better way would be of cource to get rid of those inline event handlers altogether.

Finally, a full working example of the problem I just described:

example document (test.html) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE HTML>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>jQuery event test</title>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
  </head>
  <body>

    <a href="#" id="click-me" onclick="console.log('inline event click'); return false">
      click me
    </a>

    <script>
      jQuery(function( $ ) {

        $('#click-me').click(function() {
          console.log("jQuery click");

          // unbind all click events on the <a> tag
          $(this).unbind('click');
        });

      });
    </script>
  </body>
</html>

Click a few times on the link and watch the dev console. The first time, you’ll see both log calls, after that only the one from the inline event. The jQuery event gets removed, the inline event stays.

Cheers,
Marc

Comments