+ },
+
+ proxy: function( fn, proxy ){
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+ // So proxy can be declared as an argument
+ return proxy;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: bindReady,
+ teardown: function() {}
+ }
+ },
+
+ specialAll: {
+ live: {
+ setup: function( selector, namespaces ){
+ jQuery.event.add( this, namespaces[0], liveHandler );
+ },
+ teardown: function( namespaces ){
+ if ( namespaces.length ) {
+ var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+
+ jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+ if ( name.test(this.type) )
+ remove++;
+ });
+
+ if ( remove <= 1 )
+ jQuery.event.remove( this, namespaces[0], liveHandler );
+ }
+ }
+ }
+ }
+};
+
+function stopImmediatePropagation(){
+ this._sip = 1;
+ this.stopPropagation();
+}
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+ // Check if mouse(over|out) are still within the same parent element
+ var parent = event.relatedTarget;
+ // Traverse up the tree
+ while ( parent && parent != this )
+ try { parent = parent.parentNode; }
+ catch(e) { parent = this; }
+
+ if( parent != this ){
+ // set the correct event type
+ event.type = event.data;
+ // handle event if we actually just moused on to a non sub-element
+ jQuery.event.handle.apply( this, arguments );