If you look at jQuery 1.3 documentation for live method you will notice that the live method is not supported for following events:
blur, focus, mouseenter, mouseleave, change and submit .
jQuery 1.4 fixed them all.
In this article I am going to discuss how jQuery brought support for these methods in jQuery. If you want a little background on what is live method and how it works then you should read this article which I wrote sometime back.
focus and blur events
IE and other browsers do not bubble focus and blur events. And that is in compliance with the w3c events model. As per the spec focus event and blur event do not bubble.
However the spec also mentions two additional events called DOMFocusIn and DOMFocusOut. As per the spec these two events should bubble. Firefox and other browsers implemented DOMFocusIn/DOMFocusOut . However IE implemented focusin and focusout and IE made sure that these two events do bubble up.
jQuery team decided to pick shorter name and introduced two new events: focusin and focusout. These two events bubble and hence they can be used with live method. This commit makes focusin/focusout work with live method. Here is code snippet.
Once again make sure that you are using focusin/focusout instread of focus/blur when used with live .
mouseenter and mouseleave events
mouseenter and mouseleave events do not bubble in IE. However mouseover and mouseout do bubble in IE. If you are not sure of what the difference is between mouseenter and mouseover then watch this excellent screencast by Ben.
The fix that was applied to map for focusin can be replicated here to fix mousetner and mouseleave issue. This is the commit that fixed mouseenter and mouseleave issue with live method.
Two more events are left to be handled: submit and change. Before jQuery applies fix for these two events, jQuery needs a way to detect if a browser allows submit and change events to bubble or not. jQuery team does not favor browser sniffing. So how to go about detecting event support without browser sniffing.
Juriy Zaytsev posted an excellent blog titled Detecting event support without browser sniffing . Here is the a short and concise way he proposes to find out if an event is supported by a browser.
Next task is to actually make a change event or a submit event bubble if ,based on above code, it is determined that browse is not bubbling those events .
Making change event bubble
On a form a person can change so many things including checkbox, radio button, select menu, textarea etc. jQuery team implemented a full blown change tracker which would detect every single change on the form and will act accordingly.
Radio button, checkbox and select changes will be detected via change event. Here is the code.
IE has a proprietary event called beforeactivate which gets fired before any change happens. This event is used to store the existing value of the field. After the click or keydown event the changed value is captured. Then these two values are matched to see if really a change has happened. Here is code for detecting the match.
123456789101112131415161718192021222324
functiontestChange(e){varelem=e.target,data,val;if(!formElems.test(elem.nodeName)||elem.readOnly){return;}data=jQuery.data(elem,"_change_data");val=getVal(elem);if(val===data){return;}// the current data will be also retrieved by beforeactivateif(e.type!=="focusout"||elem.type!=="radio"){jQuery.data(elem,"_change_data",val);}if(elem.type!=="select"&&(data!=null||val)){e.type="change";returnjQuery.event.trigger(e,arguments[1],this);}}
jQuery.event.special.change={filters:{focusout:testChange,click:function(e){varelem=e.target,type=elem.type;if(type==="radio"||type==="checkbox"||elem.nodeName.toLowerCase()==="select"){returntestChange.call(this,e);}},// Change has to be called before submit// Keydown will be called before keypress, which is used in submit-event delegationkeydown:function(e){varelem=e.target,type=elem.type;if((e.keyCode===13&&elem.nodeName.toLowerCase()!=="textarea")||(e.keyCode===32&&(type==="checkbox"||type==="radio"))||type==="select-multiple"){returntestChange.call(this,e);}},// Beforeactivate happens also before the previous element is blurred// with this event you can't trigger a change event, but you can store// information/focus[in] is not needed anymorebeforeactivate:function(e){varelem=e.target;if(elem.nodeName.toLowerCase()==="input"&&elem.type==="radio"){jQuery.data(elem,"_change_data",getVal(elem));}}},setup:function(data,namespaces,fn){for(vartypeinchangeFilters){jQuery.event.add(this,type+".specialChange."+fn.guid,changeFilters[type]);}returnformElems.test(this.nodeName);},remove:function(namespaces,fn){for(vartypeinchangeFilters){jQuery.event.remove(this,type+".specialChange"+(fn?"."+fn.guid:""),changeFilters[type]);}returnformElems.test(this.nodeName);}};varchangeFilters=jQuery.event.special.change.filters;}
Making submit event bubble
In order to detect submission of a form, one needs to watch for click event on a submit button or an image button. Additionally one can hit ‘enter’ using keyboard and can submit the form. All of these need be tracked.
As you can see if a submit button or an image is clicked inside a form the submit event is triggered. Additionally keypress event is monitored and if the keyCode is 13 then the form is submitted.
live method is just pure awesome. It is great to see last few wrinkles getting sorted out. A big Thank You to Justin Meyer of JavaScriptMVC who submitted most of the patch for fixing this vexing issue.