Opera ignoring .live() event handler
Asked Answered
K

7

8

I have the following jQuery which works in all major browsers except Opera:

jQuery(document).ready(function () {

      jQuery("#GetResults").live("click", function(e){
            e.preventDefault(); //Opera doesn't execute anything here
      });

};

Which is supposed to fire when clicking the following link:

<a id="GetResults" href="Folder/File/javascript:void(0);">Get Results</a>

Only Opera ignores this. Any ideas?

Edit:

I've just discovered that if I substitute out .live() for .bind() everything functions as expected. I can't find any documentation relating to .live() bugs in Opera though, and it does work in jsFiddle which would point at something environmental. What could be causing this behavour?

Krilov answered 5/7, 2011 at 15:30 Comment(9)
e.preventDefault() just stops the default action from happening(following the link). i've tested this out in jsfiddle, it doesn't follow the link, what version of opera are you using? what are you trying to do?Milreis
Thats correct - yet Opera follows the link. There's actually a whole bunch more code in there but I removed it for the post and none of it runs. Opera 11.5.Krilov
Can be a very long shot, but first thing I do wherever only Opera behaves differently, is to check if it's cache is cleared.Goncourt
It doesn't seem to for me: try this out: jsfiddle.net/hyGXq with opera 11.11Milreis
@Milreis - Okay something's strange here, your jsFiddle is working perfectly in Opera. Must be another problem.Krilov
probably a problem in your javascript somewhere on the page that the other browsers are working aroundMilreis
This is working in the latest release of Opera (11.50).Shawnee
Yea it's working in jsFiddle, but I'm also using 11.50 when the problem occursKrilov
Please test if the event handler is bound to the jQuery element with this method: #1236567. Maybe we'll have more information after doing that.Umbrage
G
7

This needs clarification. The answers above are correct, but nobody clearly explained where your problem comes from.

In fact I think that you could probably reproduce the problem in other browsers too. That's because of how .live works:

It binds to the event on document and waits for a particular event to bubble up to there. Then it checks if the event.target is what you wanted to handle. *

If you click on a link element it's quite possible that the browser goes to the new page before the event bubbles high enough to trigger your code. In an app with lots of HTML and event handlers all the browsers should have problems. Opera just starts displaying the new page and destroys the previous quicker in this case. It really depends on a particular situation more than on the browser. For example: you probably won't see this happen if you had a high network latency while connecting to the site.

To prevent default action on a a element you have to use .bind like in the old days ;) when a eveloper had to be aware of what he loads with AJAX and bind new events to that in a callback.

* There is more to that and .live is more complicated. I just described what is needed here.

Graticule answered 11/7, 2011 at 9:25 Comment(2)
> "If you click on a link element it's quite possible that the browser goes to the new page before the event bubbles high enough to trigger your code." ... false, bubbling happens before the default action. However, if something up the DOM chain used stopPropagation() without preventDefault(), then it may never bubble up to the document to trigger the .live() handler. If that were the case though, it would fail in all browsers.Zinnes
@jimbojw You are probably more interested in getting your handling function to finish before, or better, instead of default action. The fact that a bubble gets to the top to start the function is not enough. Moreover - despite what you said you can't be sure to prevent default action with live handler - in most cases it's too late. That's from my own experience with multiple browsers.Graticule
E
6

What happens when you attach the handler using:

$ (something).bind ("click", function (e) {
    // do something
})

You can also try to attach the handler using .click() method.

Edibles answered 8/7, 2011 at 14:3 Comment(1)
Doing this works, but does that shine any light on why .live() won't?Krilov
B
4

The following code works as expected in Opera 11.50.

<!doctype html>
<title></title>
<a id="GetResults" href="http://google.com">Get Results</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
jQuery(document).ready(function () {
  jQuery("#GetResults").live("click", function(e){
    alert('doing something');
    e.preventDefault(); //Opera doesn't execute anything here
  });
});
</script>

Either it is a corrected bug, or something more subtle.

Can you check whether the above works on your version of Opera / jQuery?

Berni answered 8/7, 2011 at 9:41 Comment(3)
I can confirm that this does work, with both that an 1.4.2 version of jQuery. This surely must be an environmental issue now, any ideas of what could prevent all .live() from firing? Breakpoints never break into them.Krilov
In your post, there is a missing closing paren in the last javascript line. Can you confirm that this is not the issue here?Berni
Ah yes you're correct. The missing ) only appeared when composing the question, it's there in the sourceKrilov
K
2

Read this article. Try use delegate instead

Kilo answered 8/7, 2011 at 9:12 Comment(2)
I'd already come across that to be honest, the problem is I have elements which come into scope later on so the event handler really does need to sit at the top of the DOM.Krilov
Perhaps you could try using delegate for the body document?Flog
C
1

Not sure if you want to do it, or if it will work for you. I had similar issues with Opera 9.5 and e.preventDefault() not working, the only solution I found was to just return false...

jQuery(document).ready(function () {

      jQuery("#GetResults").live("click", function(e){
            e.preventDefault();
            return false;
      });

};
Corrosive answered 14/7, 2011 at 8:4 Comment(0)
Z
1

There are two aspects of an event bubbling worth considering in this case: propagation and the default action.

Propagation refers to the event bubbling. First the anchor tag gets the click event, then its parent element, then its parent's parent, and so forth, up to the document element. You can stop an event from propagating at any time by calling e.stopPropagation().

The default action is what the browser will do if nothing is done to prevent it. The most well-known case is when an anchor with an href is clicked, the browser will try to navigate there. There are other examples too, though, for example when you click and drag an image, many browsers will create a ghost image you can drop on another application. In both cases, you can stop the browser from doing the default action at any time by calling e.preventDefault()

As mentioned in other answers to this question, jQuery's .live() feature sets a handler at a high level element (like document) and takes action after events have propagated up. If a handler in between the anchor and the document calls e.stopPropagaiton() without calling e.preventDefault() it would stop the live handler from responding, while still allowing the browser to navigate (the default action).

I doubt this is what's happening, since it would affect all browsers, but it's one possible explanation.

Zinnes answered 14/7, 2011 at 20:36 Comment(0)
M
1

Ensure that document.ready event happens before you click on link.

Try to put all lives in the top of the document.ready wrapper. It may help, if you have a lot of javascript code.

Melli answered 15/7, 2011 at 6:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.