+ teardown: function(data){
+ jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
+ }
+ };
+});
+
+// submit delegation
+jQuery.event.special.submit = {
+ setup: function( data, namespaces, fn ) {
+ if ( !jQuery.support.submitBubbles && this.nodeName.toLowerCase() !== "form" ) {
+ jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+ return trigger( "submit", this, arguments );
+ }
+ });
+
+ jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+ return trigger( "submit", this, arguments );
+ }
+ });
+ }
+
+ return false;
+ },
+
+ remove: function( namespaces, fn ) {
+ jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
+ jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
+ }
+};
+
+// change delegation, happens here so we have bind.
+jQuery.event.special.change = {
+ filters: {
+ click: function( e ) {
+ var elem = e.target;
+
+ if ( elem.nodeName.toLowerCase() === "input" && elem.type === "checkbox" ) {
+ return trigger( "change", this, arguments );
+ }
+
+ return changeFilters.keyup.call( this, e );
+ },
+ keyup: function( e ) {
+ var elem = e.target, data, index = elem.selectedIndex + "";
+
+ if ( elem.nodeName.toLowerCase() === "select" ) {
+ data = jQuery.data( elem, "_change_data" );
+ jQuery.data( elem, "_change_data", index );
+
+ if ( (elem.type === "select-multiple" || data != null) && data !== index ) {
+ return trigger( "change", this, arguments );
+ }
+ }
+ },
+ beforeactivate: function( e ) {
+ var elem = e.target;
+
+ if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" && !elem.checked ) {
+ return trigger( "change", this, arguments );
+ }
+ },
+ blur: function( e ) {
+ var elem = e.target, nodeName = elem.nodeName.toLowerCase();
+
+ if ( (nodeName === "textarea" || (nodeName === "input" && (elem.type === "text" || elem.type === "password")))
+ && jQuery.data(elem, "_change_data") !== elem.value ) {
+
+ return trigger( "change", this, arguments );
+ }
+ },
+ focus: function( e ) {
+ var elem = e.target, nodeName = elem.nodeName.toLowerCase();
+
+ if ( nodeName === "textarea" || (nodeName === "input" && (elem.type === "text" || elem.type === "password" ) ) ) {
+ jQuery.data( elem, "_change_data", elem.value );
+ }
+ }
+ },
+ setup: function( data, namespaces, fn ) {
+ // return false if we bubble
+ if ( !jQuery.support.changeBubbles ) {
+ for ( var type in changeFilters ) {
+ jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
+ }
+ }
+
+ // always want to listen for change for trigger
+ return false;
+ },
+ remove: function( namespaces, fn ) {
+ if ( !jQuery.support.changeBubbles ) {
+ for ( var type in changeFilters ) {
+ jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
+ }
+ }
+ }
+};
+
+var changeFilters = jQuery.event.special.change.filters;
+
+function trigger( type, elem, args ) {
+ args[0].type = type;
+ return jQuery.event.handle.apply( elem, args );
+}
+
+// Create "bubbling" focus and blur events
+jQuery.each({
+ focus: "focusin",
+ blur: "focusout"
+}, function( orig, fix ){
+ var event = jQuery.event,
+ handle = event.handle;
+
+ function ieHandler() {
+ arguments[0].type = orig;
+ return handle.apply(this, arguments);
+ }
+
+ event.special[orig] = {
+ setup:function() {
+ if ( this.addEventListener ) {
+ this.addEventListener( orig, handle, true );
+ } else {
+ event.add( this, fix, ieHandler );
+ }
+ },
+ teardown:function() {
+ if ( this.removeEventListener ) {
+ this.removeEventListener( orig, handle, true );
+ } else {
+ event.remove( this, fix, ieHandler );
+ }