Is there a good way to get around IE7 producing "Error: Failed" when events are triggered on dynamically created SVG elements (such as those created by raphael.js)?
I think the "Error: Failed" are being produced when jQuery looks through my live handlers to check and see if the SVG element matches any of the live selectors I've specified... for now I manually bind functions that call
e.stopPropagation();
for every event (mouseenter, mouseleave, click, etc.) on my SVGs produced by raphael.
I couldn't find a good way to prevent this jQuery issue.
So what I ened up doing was capturing the events in Raphael.js and calling e.stopPropagation(); then I used IE's fireEvent to start the event again on the parent element of the VML/SVG element. A bit of a hack, but it works for now.
I found that using Brandon Aaron's "livequery" plugin in place of jQuery's native "live" method for any live bindings to the "change" event solved this problem.
See:
hakoniemi
jQuery Bug
Related
I'm curious to know the differences between the bind and live functions.
To me they seem to be almost identical.
I read the benefits of live/bind methods, but it didn't tell me about the differences...
Thanks!
In short: .bind() will only apply to the items you currently have selected in your jQuery object. .live() will apply to all current matching elements, as well as any you might add in the future.
The underlying difference between them is that live() makes use of event bubbling. That is, when you click on a button, that button might exist in a <p>, in a <div>, in a <body> element; so in effect, you're actually clicking on all of those elements at the same time.
live() works by attaching your event handler to the document, not to the element. When you click on that button, as illustrated before, the document receives the same click event. It then looks back up the line of elements targeted by the event and checks to see if any of them match your query.
The outcome of this is twofold: firstly, it means that you don't have to continue reapplying events to new elements, since they'll be implicitly added when the event happens. However, more importantly (depending on your situation), it means that your code is much much lighter! If you have 50 <img> tags on the page and you run this code:
$('img').click(function() { /* doSomething */ });
...then that function is copied into each of those elements. However, if you had this code:
$('img').live('click', function() { /* doSomething */ });
...then that function is stored only in one place (on the document), and is applied to whatever matches your query at event time.
Because of this bubbling behaviour though, not all events can be handled this way. As Ichiban noted, these supported events are click, dblclick mousedown, mouseup, mousemove, mouseover, mouseout, keydown, keypress, keyup.
.bind() attacheds events to elements that exist or match the selector at the time the call is made. Any elements created afterwards or that match going forward because the class was changed, will not fire the bound event.
.live() works for existing and future matching elements. Before jQuery 1.4 this was limited to the following events: click, dblclick mousedown, mouseup, mousemove, mouseover, mouseout, keydown, keypress, keyup
Bind will bind events to the specified pattern, for all matches in the current DOM at the time you call it. Live will bind events to the specified pattern for the current DOM and to future matches in the DOM, even if it changes.
For example, if you bind $("div").bind("hover", ...) it will apply to all "div"s in the DOM at the time. If you then manipulate the DOM and add an extra "div", it won't have that hover event bound. Using live instead of bind would dispatch the event to the new div as well.
Nice read on this: http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/
Is nowadays (since jQuery 1.7) deprecated using the .on() function - http://api.jquery.com/on/
imagine this scenario:
i have several <img> elements.
$('img').bind('click', function(){...});
add some extra images (using get(), or html(), anything)
the new images don't have any binding!!
of course, since the new images didn't exist when you did the $('img')... at step 2, it didn't bind the event handler to them.
now, if you do this:
i have several <img> elements.
$('img').live('click', function(){...});
add some extra images (using get(), or html(), anything)
the new images do have the binding!!
magic? just a little. in fact jQuery binds a generic event handler to another element higher in the DOM tree (body? document? no idea) and lets the event bubble up. when it gets to the generic handler, it checks if it matches your live() events and if so, they're fired, no matter if the element was created before or after the live() call.
In adition to what they said, I think it's best to try to stick to bind when/where you can and use live only when you must.
All these jQuery methods are used for attaching events to selectors or elements. But they all are different from each other.
.bind(): This is the easiest and quick method to bind events. But the issue with bind() is that it doesn’t work for elements added dynamically that matches the same selector. bind() only attach events to the current elements not future element. Above that it also has performance issues when dealing with a large selection.
.live(): This method overcomes the disadvantage of bind(). It works for dynamically added elements or future elements. Because of its poor performance on large pages, this method is deprecated as of jQuery 1.7 and you should stop using it. Chaining is not properly supported using this method.
Find out more here
I wanted to add to this after having to debug a bit due to my own silliness. I applied .live() to a class of button on my page, assuming that it would just render out the correct ID I was trying to pass on the query string and do what I wanted to do with the ajax call. My app has dynamically added buttons associated with an inventory item. For instance, drill down categories to the 'COKE' button to add a coke to your order. Drill down from the top again, and add 'BUDLITE' - each time I wanted those items to be entered into a table via an AJAX call.
However, since I bound .live() to the entire class of buttons, it would remember each ajax call I had made and re-fire it for each subsequent button! It was a little tricky because I wasn't exactly clear on the difference between bind and live (and the answer above is crystal about it), so I figured I'd put this here just in case somebody was doing a search on this stuff.
There is a way to get the live effect but its kind of nasty.
$(this).unbind('mouseout').bind('mouseout',function(){
});
this will clear the previous and reset the new. It has seemed to work fine for me over time.
Difference between live and livequery is discussed here .
Does anyone have a link to a list of ALL events that can be passed to jQuery .on()?
Here are a few, but I cant seem to find a definitive list.
click
mouseenter
mouseleave
contextmenu (works on right click, and tap and hold with Android (not iOS))
focus
blur
focusin
focusout
scroll
I'm looking for Android/iOS touch events in particular.
Thanks!
EDIT 1: So I think the real question i'm asking is what events are standard across all browsers/devices?
I think you have to realise that the important question is not: What events can you pass to jQuery.on()? Because you can technically pass any event to that method.
The real question is, what events does the browser/device fire? Obviously, some events — as the ones you listed — are a standard, but some browsers will surprise you by not firing some events or by having their own custom events.
You can find a pretty extensive list at the MDN:
Events reference
But keep in mind that the point is that you can also define your own custom events, trigger them, and bind event listeners to them.
For touch screen devices you will have the following events:
touchstart
touchend
touchmove
touchcancel
Are you using jQuery mobile? The events are listed here: http://api.jquerymobile.com/category/events/
Google DOM Events, get MDN Event Reference.
You may be particularly interested in the TouchEvent subclass.
Of course, you can bind any custom event using .on and trigger any custom event with .trigger, so the real answer is infinite.
You can register any event names. Whether they will be called is another question… Custom events can be manually triggered, and there are many that are triggered natively in the DOM. For some of them, jQuery has special shorthand methods.
I'm looking for Android/iOS touch events in particular.
Have a look at https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Events/Touch_events then, or the W3 spec.
All jQuery events.
Here are lists of keyboard events and mouse events.
The official documentation only says:
The event's type, such as "click", "blur" or "keypress".
For iOS devices the touchstart is another event which is working. Where can I get the full list of all possible events? I like for example actually to get the event for the <select> event hasChanged(). Is this based on another library?
Meteor doesn't define the events it supports — it simply creates a cross-browser event listener wrapper. If you wanted to create custom events and trigger them, Meteor would pick them up.
The native input events supported depends on the browser: the Mozilla Developer Network reference is a good place to start.
Th docs also says that all the DOM events are also possible in addition to click, focus, blur, etc.
Other DOM events are available as well, but for the events above,
Meteor has taken some care to ensure that they work uniformly in all
browsers.
You can see the list of available Javascript events here and here.
The following codes don't work:
function dnd(){
}
var ele = document.getElementById("relative");
ele.addEventListener("click",dnd,false);
document.write(ele.onclick);
the output is undefined. I guess the output should be function onclick(event){dnd();}
What should I do to solve this problem?
Any suggestion is appreciated.
There are 3 common ways to attach events to DOM nodes.
The addEventListener() method is the way to register an event listener as specified in W3C DOM. It has many benefits, but doesn't work in Internet Explorer. For Internet Explorer you'd have to use the attachEvent() method, which offers similar functionality.
On the other hand, the onclick property is an older, but more supported way to attach event handlers. However it has certain disadvantages, such as allowing just one event handler for each event.
As for how to get back the event handlers that are attached to a particular node, it depends on the method you use to attach the events. The problem with your example is that you're using the addEventListener() method to attach the event, and then trying to read it using the onclick property.
You may want to check out the following Stack Overflow post for further reading into this topic, especially the post by #Crescent Fresh:
How to find event listeners on a DOM node?
The onclick property is only going to show you an event handler if it is registered inline via the markup (e.g, <div id="relative" onclick="alert('foo');"></div>).
Why do you need to read the event handler? This is a relatively strange thing to do...
There are different ways of establishing event handlers, and they use different mechanisms inside the DOM. In particular — and as you've discovered empirically — adding an event listener via "addEventListener" does not affect the "onclick" attribute of the element. The mechanisms are simply separate.
This is one of the current limitation of W3C event registration model. if you register using JS methods then there is no standard way to get the handlers.
Latest DOM LEVEL 3 Events W3C adds eventListenerList spec. i guess we are lacking of some close support for this API across browsers.
Of-course if you add your method using tradition way
then your example would work.
Some StackOverFlow Links
link text
This jQuery 1.3.2 code adds an element to the page, registers a "click" event, then removes and reattaches the element:
var button = $('<button>Click me!</button>')
.click(function(){ alert("Hello") })
.appendTo('body');
$('body').html('');
button.appendTo('body');
The button appears on the page as expected, but clicking on it does nothing. I would like to know why the event handlers were removed from the object.
Note: I am aware of solutions such as jQuery.live() or clone(true) or using appendTo without a removal. What I'm looking for is an explanation, not a solution or workaround.
EDIT: I suppose this could be an arbitrary and counter-intuitive design decision of the DOM. An explanation like "Because that's the way section X of specification Y wants it to be" would be fine.
When you remove an element from the DOM using jQuery, all data (including event handlers) held by jQuery on that element will be destroyed. This is done to avoid memory-leaks.
This isn't a feature (or bug) of the DOM API. It's just jQuery.
If you want your registered events to stay on your element use .detach() instead of .remove(). Use it the same way you'd use .remove(), it will keep your events on your element.