diff options
Diffstat (limited to 'js/jquery.js')
-rw-r--r-- | js/jquery.js | 1048 |
1 files changed, 605 insertions, 443 deletions
diff --git a/js/jquery.js b/js/jquery.js index 237e1b908..b3b95307a 100644 --- a/js/jquery.js +++ b/js/jquery.js @@ -1,5 +1,5 @@ /*! - * jQuery JavaScript Library v1.4.1 + * jQuery JavaScript Library v1.4.2 * http://jquery.com/ * * Copyright 2010, John Resig @@ -11,7 +11,7 @@ * Copyright 2010, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * - * Date: Mon Jan 25 19:43:33 2010 -0500 + * Date: Sat Feb 13 22:33:48 2010 -0500 */ (function( window, undefined ) { @@ -86,6 +86,15 @@ jQuery.fn = jQuery.prototype = { this.length = 1; return this; } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } // Handle HTML strings if ( typeof selector === "string" ) { @@ -116,7 +125,9 @@ jQuery.fn = jQuery.prototype = { ret = buildFragment( [ match[1] ], [ doc ] ); selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; } - + + return jQuery.merge( this, selector ); + // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); @@ -143,6 +154,7 @@ jQuery.fn = jQuery.prototype = { this.selector = selector; this.context = document; selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { @@ -165,16 +177,14 @@ jQuery.fn = jQuery.prototype = { this.context = selector.context; } - return jQuery.isArray( selector ) ? - this.setArray( selector ) : - jQuery.makeArray( selector, this ); + return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used - jquery: "1.4.1", + jquery: "1.4.2", // The default length of a jQuery object is 0 length: 0, @@ -204,7 +214,14 @@ jQuery.fn = jQuery.prototype = { // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set - var ret = jQuery( elems || null ); + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } // Add the old object onto the stack (as a reference) ret.prevObject = this; @@ -221,18 +238,6 @@ jQuery.fn = jQuery.prototype = { return ret; }, - // Force the current matched set of elements to become - // the specified array of elements (destroying the stack in the process) - // You should use pushStack() in order to do this, but maintain the stack - setArray: function( elems ) { - // Resetting the length to 0, then using the native Array push - // is a super-fast way to populate an object with array-like properties - this.length = 0; - push.apply( this, elems ); - - return this; - }, - // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) @@ -492,6 +497,9 @@ jQuery.extend({ if ( typeof data !== "string" || !data ) { return null; } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js @@ -619,6 +627,7 @@ jQuery.extend({ for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } + } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; @@ -807,7 +816,7 @@ function access( elems, key, value, exec, fn, pass ) { } // Getting an attribute - return length ? fn( elems[0], key ) : null; + return length ? fn( elems[0], key ) : undefined; } function now() { @@ -871,7 +880,10 @@ function now() { // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected, + parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null, + // Will be defined later + deleteExpando: true, checkClone: false, scriptEval: false, noCloneEvent: true, @@ -893,6 +905,15 @@ function now() { delete window[ id ]; } + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete script.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + root.removeChild( script ); if ( div.attachEvent && div.fireEvent ) { @@ -923,6 +944,7 @@ function now() { document.body.appendChild( div ); jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; document.body.removeChild( div ).style.display = 'none'; + div = null; }); @@ -962,7 +984,6 @@ jQuery.props = { frameborder: "frameBorder" }; var expando = "jQuery" + now(), uuid = 0, windowData = {}; -var emptyObject = {}; jQuery.extend({ cache: {}, @@ -988,8 +1009,7 @@ jQuery.extend({ var id = elem[ expando ], cache = jQuery.cache, thisCache; - // Handle the case where there's no name immediately - if ( !name && !id ) { + if ( !id && typeof name === "string" && data === undefined ) { return null; } @@ -1003,17 +1023,16 @@ jQuery.extend({ if ( typeof name === "object" ) { elem[ expando ] = id; thisCache = cache[ id ] = jQuery.extend(true, {}, name); - } else if ( cache[ id ] ) { - thisCache = cache[ id ]; - } else if ( typeof data === "undefined" ) { - thisCache = emptyObject; - } else { - thisCache = cache[ id ] = {}; + + } else if ( !cache[ id ] ) { + elem[ expando ] = id; + cache[ id ] = {}; } + thisCache = cache[ id ]; + // Prevent overriding the named cache with undefined values if ( data !== undefined ) { - elem[ expando ] = id; thisCache[ name ] = data; } @@ -1045,15 +1064,11 @@ jQuery.extend({ // Otherwise, we want to remove all of the element's data } else { - // Clean up the element expando - try { - delete elem[ expando ]; - } catch( e ) { - // IE has trouble directly removing the expando - // but it's ok with using removeAttribute - if ( elem.removeAttribute ) { - elem.removeAttribute( expando ); - } + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); } // Completely remove the data cache @@ -1230,12 +1245,13 @@ jQuery.fn.extend({ elem.className = value; } else { - var className = " " + elem.className + " "; + var className = " " + elem.className + " ", setClass = elem.className; for ( var c = 0, cl = classNames.length; c < cl; c++ ) { if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { - elem.className += " " + classNames[c]; + setClass += " " + classNames[c]; } } + elem.className = jQuery.trim( setClass ); } } } @@ -1264,7 +1280,7 @@ jQuery.fn.extend({ for ( var c = 0, cl = classNames.length; c < cl; c++ ) { className = className.replace(" " + classNames[c] + " ", " "); } - elem.className = className.substring(1, className.length - 1); + elem.className = jQuery.trim( className ); } else { elem.className = ""; @@ -1520,15 +1536,16 @@ jQuery.extend({ } // elem is actually elem.style ... set the style - // Using attr for specific style information is now deprecated. Use style insead. + // Using attr for specific style information is now deprecated. Use style instead. return jQuery.style( elem, name, value ); } }); -var fcleanup = function( nm ) { - return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { - return "\\" + ch; - }); -}; +var rnamespaces = /\.(.*)$/, + fcleanup = function( nm ) { + return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { + return "\\" + ch; + }); + }; /* * A number of helper functions used for managing events. @@ -1550,107 +1567,104 @@ jQuery.event = { elem = window; } + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + // Make sure that the function being executed has a unique ID if ( !handler.guid ) { handler.guid = jQuery.guid++; } - // if data is passed, bind to handler - if ( data !== undefined ) { - // Create temporary function pointer to original handler - var fn = handler; - - // Create unique handler function, wrapped around original handler - handler = jQuery.proxy( fn ); + // Init the element's event structure + var elemData = jQuery.data( elem ); - // Store data in unique handler - handler.data = data; + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; } - // Init the element's event structure - var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ), - handle = jQuery.data( elem, "handle" ), eventHandle; + var events = elemData.events = elemData.events || {}, + eventHandle = elemData.handle, eventHandle; - if ( !handle ) { - eventHandle = function() { + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { // Handle the second event of a trigger and when // an event is called after a page has unloaded return typeof jQuery !== "undefined" && !jQuery.event.triggered ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; - - handle = jQuery.data( elem, "handle", eventHandle ); - } - - // If no handle is found then we must be trying to bind to one of the - // banned noData elements - if ( !handle ) { - return; } // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native - // event in IE. - handle.elem = elem; + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); - types = types.split( /\s+/ ); + types = types.split(" "); - var type, i = 0; + var type, i = 0, namespaces; while ( (type = types[ i++ ]) ) { - // Namespaced event handlers - var namespaces = type.split("."); - type = namespaces.shift(); + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; - if ( i > 1 ) { - handler = jQuery.proxy( handler ); + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); - if ( data !== undefined ) { - handler.data = data; - } + } else { + namespaces = []; + handleObj.namespace = ""; } - handler.type = namespaces.slice(0).sort().join("."); + handleObj.type = type; + handleObj.guid = handler.guid; // Get the current list of functions bound to this event var handlers = events[ type ], - special = this.special[ type ] || {}; + special = jQuery.event.special[ type ] || {}; // Init the event handler queue if ( !handlers ) { - handlers = events[ type ] = {}; + handlers = events[ type ] = []; // Check for a special event handler // Only use addEventListener/attachEvent if the special // events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) { + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { - elem.addEventListener( type, handle, false ); + elem.addEventListener( type, eventHandle, false ); + } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, handle ); + elem.attachEvent( "on" + type, eventHandle ); } } } if ( special.add ) { - var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers ); - if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) { - modifiedHandler.guid = modifiedHandler.guid || handler.guid; - modifiedHandler.data = modifiedHandler.data || handler.data; - modifiedHandler.type = modifiedHandler.type || handler.type; - handler = modifiedHandler; - } - } - + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + // Add the function to the element's handler list - handlers[ handler.guid ] = handler; + handlers.push( handleObj ); // Keep track of which events have been used, for global triggering - this.global[ type ] = true; + jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE @@ -1660,90 +1674,121 @@ jQuery.event = { global: {}, // Detach an event or set of events from an element - remove: function( elem, types, handler ) { + remove: function( elem, types, handler, pos ) { // don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } - var events = jQuery.data( elem, "events" ), ret, type, fn; + var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.data( elem ), + events = elemData && elemData.events; - if ( events ) { - // Unbind all events for the element - if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) { - for ( type in events ) { - this.remove( elem, type + (types || "") ); - } - } else { - // types is actually an event object here - if ( types.type ) { - handler = types.handler; - types = types.type; + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)") + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( var j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } } - // Handle multiple events separated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(/\s+/); - var i = 0; - while ( (type = types[ i++ ]) ) { - // Namespaced event handlers - var namespaces = type.split("."); - type = namespaces.shift(); - var all = !namespaces.length, - cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ), - namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"), - special = this.special[ type ] || {}; - - if ( events[ type ] ) { - // remove the given handler for the given type - if ( handler ) { - fn = events[ type ][ handler.guid ]; - delete events[ type ][ handler.guid ]; - - // remove all handlers for the given type - } else { - for ( var handle in events[ type ] ) { - // Handle the removal of namespaced events - if ( all || namespace.test( events[ type ][ handle ].type ) ) { - delete events[ type ][ handle ]; - } - } + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( var j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); } if ( special.remove ) { - special.remove.call( elem, namespaces, fn); + special.remove.call( elem, handleObj ); } + } - // remove generic event handler if no more handlers exist - for ( ret in events[ type ] ) { - break; - } - if ( !ret ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, jQuery.data( elem, "handle" ), false ); - } else if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) ); - } - } - ret = null; - delete events[ type ]; - } + if ( pos != null ) { + break; } } } - // Remove the expando if it's no longer used - for ( ret in events ) { - break; - } - if ( !ret ) { - var handle = jQuery.data( elem, "handle" ); - if ( handle ) { - handle.elem = null; + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + removeEvent( elem, type, elemData.handle ); } - jQuery.removeData( elem, "events" ); - jQuery.removeData( elem, "handle" ); + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); } } }, @@ -1774,7 +1819,7 @@ jQuery.event = { event.stopPropagation(); // Only trigger if we've ever bound an event for it - if ( this.global[ type ] ) { + if ( jQuery.event.global[ type ] ) { jQuery.each( jQuery.cache, function() { if ( this.events && this.events[type] ) { jQuery.event.trigger( event, data, this.handle.elem ); @@ -1825,9 +1870,12 @@ jQuery.event = { } else if ( !event.isDefaultPrevented() ) { var target = event.target, old, - isClick = jQuery.nodeName(target, "a") && type === "click"; + isClick = jQuery.nodeName(target, "a") && type === "click", + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { - if ( !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { try { if ( target[ type ] ) { // Make sure that we don't accidentally re-trigger the onFOO events @@ -1837,7 +1885,7 @@ jQuery.event = { target[ "on" + type ] = null; } - this.triggered = true; + jQuery.event.triggered = true; target[ type ](); } @@ -1848,53 +1896,57 @@ jQuery.event = { target[ "on" + type ] = old; } - this.triggered = false; + jQuery.event.triggered = false; } } }, handle: function( event ) { - // returned undefined or false - var all, handlers; + var all, handlers, namespaces, namespace, events; event = arguments[0] = jQuery.event.fix( event || window.event ); event.currentTarget = this; // Namespaced event handlers - var namespaces = event.type.split("."); - event.type = namespaces.shift(); + all = event.type.indexOf(".") < 0 && !event.exclusive; - // Cache this now, all = true means, any handler - all = !namespaces.length && !event.exclusive; - - var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); + } - handlers = ( jQuery.data(this, "events") || {} )[ event.type ]; + var events = jQuery.data(this, "events"), handlers = events[ event.type ]; - for ( var j in handlers ) { - var handler = handlers[ j ]; + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); - // Filter the functions by class - if ( all || namespace.test(handler.type) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handler; - event.data = handler.data; + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; - var ret = handler.apply( this, arguments ); + // Filter the functions by class + if ( all || namespace.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, arguments ); - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } } - } - if ( event.isImmediatePropagationStopped() ) { - break; + if ( event.isImmediatePropagationStopped() ) { + break; + } } - } } @@ -1973,44 +2025,39 @@ jQuery.event = { }, live: { - add: function( proxy, data, namespaces, live ) { - jQuery.extend( proxy, data || {} ); - - proxy.guid += data.selector + data.live; - data.liveProxy = proxy; - - jQuery.event.add( this, data.live, liveHandler, data ); - + add: function( handleObj ) { + jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); }, - remove: function( namespaces ) { - if ( namespaces.length ) { - var remove = 0, name = new 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 ); + remove: function( handleObj ) { + var remove = true, + type = handleObj.origType.replace(rnamespaces, ""); + + jQuery.each( jQuery.data(this, "events").live || [], function() { + if ( type === this.origType.replace(rnamespaces, "") ) { + remove = false; + return false; } + }); + + if ( remove ) { + jQuery.event.remove( this, handleObj.origType, liveHandler ); } - }, - special: {} + } + }, + beforeunload: { - setup: function( data, namespaces, fn ) { + setup: function( data, namespaces, eventHandle ) { // We only want to do this special case on windows if ( this.setInterval ) { - this.onbeforeunload = fn; + this.onbeforeunload = eventHandle; } return false; }, - teardown: function( namespaces, fn ) { - if ( this.onbeforeunload === fn ) { + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { this.onbeforeunload = null; } } @@ -2018,6 +2065,14 @@ jQuery.event = { } }; +var removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + elem.removeEventListener( type, handle, false ); + } : + function( elem, type, handle ) { + elem.detachEvent( "on" + type, handle ); + }; + jQuery.Event = function( src ) { // Allow instantiation without the 'new' keyword if ( !this.preventDefault ) { @@ -2095,27 +2150,24 @@ 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 ) { - // Firefox sometimes assigns relatedTarget a XUL element - // which we cannot access the parentNode property of - try { + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { parent = parent.parentNode; - - // assuming we've left the element since we most likely mousedover a xul element - } catch(e) { - break; } - } - if ( parent !== this ) { - // set the correct event type - event.type = event.data; + 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 ); - } + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } }, // In case of event delegation, we only need to rename the event.type, @@ -2143,64 +2195,65 @@ jQuery.each({ // submit delegation if ( !jQuery.support.submitBubbles ) { -jQuery.event.special.submit = { - setup: function( data, namespaces, fn ) { - if ( this.nodeName.toLowerCase() !== "form" ) { - jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) { - var elem = e.target, type = elem.type; + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; - if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { - return trigger( "submit", this, arguments ); - } - }); + 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; + jQuery.event.add(this, "keypress.specialSubmit", 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 ); - } - }); + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + return trigger( "submit", this, arguments ); + } + }); - } else { - return false; - } - }, + } else { + return false; + } + }, - remove: function( namespaces, fn ) { - jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") ); - jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") ); - } -}; + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; } // change delegation, happens here so we have bind. if ( !jQuery.support.changeBubbles ) { -var formElems = /textarea|input|select/i; + var formElems = /textarea|input|select/i, -function getVal( elem ) { - var type = elem.type, val = elem.value; + changeFilters, - if ( type === "radio" || type === "checkbox" ) { - val = elem.checked; + getVal = function( elem ) { + var type = elem.type, val = elem.value; - } else if ( type === "select-multiple" ) { - val = elem.selectedIndex > -1 ? - jQuery.map( elem.options, function( elem ) { - return elem.selected; - }).join("-") : - ""; + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; - } else if ( elem.nodeName.toLowerCase() === "select" ) { - val = elem.selectedIndex; - } + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; - return val; -} + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, -function testChange( e ) { + testChange = function testChange( e ) { var elem = e.target, data, val; if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { @@ -2223,61 +2276,61 @@ function testChange( e ) { e.type = "change"; return jQuery.event.trigger( e, arguments[1], elem ); } -} + }; -jQuery.event.special.change = { - filters: { - focusout: testChange, + jQuery.event.special.change = { + filters: { + focusout: testChange, - click: function( e ) { - var elem = e.target, type = elem.type; + click: function( e ) { + var elem = e.target, type = elem.type; - if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { - return testChange.call( this, e ); - } - }, + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; - // Change has to be called before submit - // Keydown will be called before keypress, which is used in submit-event delegation - keydown: function( e ) { - var elem = e.target, type = elem.type; + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, - if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || - (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || - type === "select-multiple" ) { - return testChange.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 anymore + beforeactivate: function( e ) { + var elem = e.target; + jQuery.data( elem, "_change_data", getVal(elem) ); } }, - // 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 anymore - beforeactivate: function( e ) { - var elem = e.target; + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } - if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) { - jQuery.data( elem, "_change_data", getVal(elem) ); + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); } - } - }, - setup: function( data, namespaces, fn ) { - for ( var type in changeFilters ) { - jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] ); - } - return formElems.test( this.nodeName ); - }, - remove: function( namespaces, fn ) { - for ( var type in changeFilters ) { - jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] ); - } + return formElems.test( this.nodeName ); + }, - return formElems.test( this.nodeName ); - } -}; + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); -var changeFilters = jQuery.event.special.change.filters; + return formElems.test( this.nodeName ); + } + }; + changeFilters = jQuery.event.special.change.filters; } function trigger( type, elem, args ) { @@ -2325,11 +2378,16 @@ jQuery.each(["bind", "one"], function( i, name ) { return fn.apply( this, arguments ); }) : fn; - return type === "unload" && name !== "one" ? - this.one( type, data, fn ) : - this.each(function() { - jQuery.event.add( this, type, handler, data ); - }); + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; }; }); @@ -2340,13 +2398,29 @@ jQuery.fn.extend({ for ( var key in type ) { this.unbind(key, type[key]); } - return this; + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } } - return this.each(function() { - jQuery.event.remove( this, type, fn ); - }); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } }, + trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); @@ -2390,32 +2464,60 @@ jQuery.fn.extend({ } }); +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn ) { - var type, i = 0; + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); if ( jQuery.isFunction( data ) ) { fn = data; data = undefined; } - types = (types || "").split( /\s+/ ); + types = (types || "").split(" "); while ( (type = types[ i++ ]) != null ) { - type = type === "focus" ? "focusin" : // focus --> focusin - type === "blur" ? "focusout" : // blur --> focusout - type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support - type; - + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + if ( name === "live" ) { // bind live handler - jQuery( this.context ).bind( liveConvert( type, this.selector ), { - data: data, selector: this.selector, live: type - }, fn ); + context.each(function(){ + jQuery.event.add( this, liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + }); } else { // unbind live handler - jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null ); + context.unbind( liveConvert( type, selector ), fn ); } } @@ -2425,45 +2527,46 @@ jQuery.each(["live", "die"], function( i, name ) { function liveHandler( event ) { var stop, elems = [], selectors = [], args = arguments, - related, match, fn, elem, j, i, l, data, - live = jQuery.extend({}, jQuery.data( this, "events" ).live); + related, match, handleObj, elem, j, i, l, data, + events = jQuery.data( this, "events" ); // Make sure we avoid non-left-click bubbling in Firefox (#3861) - if ( event.button && event.type === "click" ) { + if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { return; } - for ( j in live ) { - fn = live[j]; - if ( fn.live === event.type || - fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) { + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); - data = fn.data; - if ( !(data.beforeFilter && data.beforeFilter[event.type] && - !data.beforeFilter[event.type](event)) ) { - selectors.push( fn.selector ); - } } else { - delete live[j]; + live.splice( j--, 1 ); } } match = jQuery( event.target ).closest( selectors, event.currentTarget ); for ( i = 0, l = match.length; i < l; i++ ) { - for ( j in live ) { - fn = live[j]; - elem = match[i].elem; - related = null; + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( match[i].selector === handleObj.selector ) { + elem = match[i].elem; + related = null; - if ( match[i].selector === fn.selector ) { // Those two events require additional checking - if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) { - related = jQuery( event.relatedTarget ).closest( fn.selector )[0]; + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; } if ( !related || related !== elem ) { - elems.push({ elem: elem, fn: fn }); + elems.push({ elem: elem, handleObj: handleObj }); } } } @@ -2472,8 +2575,10 @@ function liveHandler( event ) { for ( i = 0, l = elems.length; i < l; i++ ) { match = elems[i]; event.currentTarget = match.elem; - event.data = match.fn.data; - if ( match.fn.apply( match.elem, args ) === false ) { + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) { stop = false; break; } @@ -2483,7 +2588,7 @@ function liveHandler( event ) { } function liveConvert( type, selector ) { - return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); + return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); } jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + @@ -3228,8 +3333,10 @@ var makeArray = function(array, results) { // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 ); + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; // Provide a fallback method if it does not work } catch(e){ @@ -3533,7 +3640,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { } var contains = document.compareDocumentPosition ? function(a, b){ - return a.compareDocumentPosition(b) & 16; + return !!(a.compareDocumentPosition(b) & 16); } : function(a, b){ return a !== b && (a.contains ? a.contains(b) : true); }; @@ -3570,7 +3677,7 @@ jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; jQuery.unique = Sizzle.uniqueSort; -jQuery.getText = getText; +jQuery.text = getText; jQuery.isXMLDoc = isXML; jQuery.contains = contains; @@ -3856,7 +3963,8 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i, rtagName = /<([\w:]+)/, rtbody = /<tbody/i, - rhtml = /<|&\w+;/, + rhtml = /<|&#?\w+;/, + rnocache = /<script|<object|<embed|<option|<style/i, rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5) fcloseTag = function( all, front, tag ) { return rselfClosing.test( tag ) ? @@ -3896,7 +4004,7 @@ jQuery.fn.extend({ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); } - return jQuery.getText( this ); + return jQuery.text( this ); }, wrapAll: function( html ) { @@ -4000,6 +4108,40 @@ jQuery.fn.extend({ return set; } }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }, clone: function( events ) { // Do the clone @@ -4021,6 +4163,8 @@ jQuery.fn.extend({ } return jQuery.clean([html.replace(rinlinejQuery, "") + // Handle the case in IE 8 where action=/test/> self-closes a tag + .replace(/=([^="'>\s]+\/)>/g, '="$1">') .replace(rleadingWhitespace, "")], ownerDocument)[0]; } else { return this.cloneNode(true); @@ -4044,7 +4188,7 @@ jQuery.fn.extend({ null; // See if we can take a shortcut and just use innerHTML - } else if ( typeof value === "string" && !/<script/i.test( value ) && + } else if ( typeof value === "string" && !rnocache.test( value ) && (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { @@ -4083,16 +4227,17 @@ jQuery.fn.extend({ if ( this[0] && this[0].parentNode ) { // Make sure that the elements are removed from the DOM before they are inserted // this can help fix replacing a parent with child elements - if ( !jQuery.isFunction( value ) ) { - value = jQuery( value ).detach(); - - } else { + if ( jQuery.isFunction( value ) ) { return this.each(function(i) { var self = jQuery(this), old = self.html(); self.replaceWith( value.call( this, i, old ) ); }); } + if ( typeof value !== "string" ) { + value = jQuery(value).detach(); + } + return this.each(function() { var next = this.nextSibling, parent = this.parentNode; @@ -4114,7 +4259,7 @@ jQuery.fn.extend({ }, domManip: function( args, table, callback ) { - var results, first, value = args[0], scripts = []; + var results, first, value = args[0], scripts = [], fragment, parent; // We can't cloneNode fragments that contain checked, in WebKit if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { @@ -4132,14 +4277,23 @@ jQuery.fn.extend({ } if ( this[0] ) { + parent = value && value.parentNode; + // If we're in a fragment, just use that instead of building a new one - if ( args[0] && args[0].parentNode && args[0].parentNode.nodeType === 11 ) { - results = { fragment: args[0].parentNode }; + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + } else { results = buildFragment( args, this, scripts ); } - - first = results.fragment.firstChild; + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } if ( first ) { table = table && jQuery.nodeName( first, "tr" ); @@ -4149,14 +4303,14 @@ jQuery.fn.extend({ table ? root(this[i], first) : this[i], - results.cacheable || this.length > 1 || i > 0 ? - results.fragment.cloneNode(true) : - results.fragment + i > 0 || results.cacheable || this.length > 1 ? + fragment.cloneNode(true) : + fragment ); } } - if ( scripts ) { + if ( scripts.length ) { jQuery.each( scripts, evalScript ); } } @@ -4196,10 +4350,16 @@ function cloneCopyEvent(orig, ret) { } function buildFragment( args, nodes, scripts ) { - var fragment, cacheable, cacheresults, doc; + var fragment, cacheable, cacheresults, + doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); + + // Only cache "small" (1/2 KB) strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && + !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { - // webkit does not clone 'checked' attribute of radio inputs on cloneNode, so don't cache if string has a checked - if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { cacheable = true; cacheresults = jQuery.fragments[ args[0] ]; if ( cacheresults ) { @@ -4210,7 +4370,6 @@ function buildFragment( args, nodes, scripts ) { } if ( !fragment ) { - doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); fragment = doc.createDocumentFragment(); jQuery.clean( args, doc, fragment, scripts ); } @@ -4232,46 +4391,22 @@ jQuery.each({ replaceAll: "replaceWith" }, function( name, original ) { jQuery.fn[ name ] = function( selector ) { - var ret = [], insert = jQuery( selector ); - - for ( var i = 0, l = insert.length; i < l; i++ ) { - var elems = (i > 0 ? this.clone(true) : this).get(); - jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); - ret = ret.concat( elems ); - } - return this.pushStack( ret, name, insert.selector ); - }; -}); - -jQuery.each({ - // keepData is for internal use only--do not document - remove: function( selector, keepData ) { - if ( !selector || jQuery.filter( selector, [ this ] ).length ) { - if ( !keepData && this.nodeType === 1 ) { - jQuery.cleanData( this.getElementsByTagName("*") ); - jQuery.cleanData( [ this ] ); - } - - if ( this.parentNode ) { - this.parentNode.removeChild( this ); + var ret = [], insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); + ret = ret.concat( elems ); } + + return this.pushStack( ret, name, insert.selector ); } - }, - - empty: function() { - // Remove element nodes and prevent memory leaks - if ( this.nodeType === 1 ) { - jQuery.cleanData( this.getElementsByTagName("*") ); - } - - // Remove any remaining nodes - while ( this.firstChild ) { - this.removeChild( this.firstChild ); - } - } -}, function( name, fn ) { - jQuery.fn[ name ] = function() { - return this.each( fn, arguments ); }; }); @@ -4286,13 +4421,13 @@ jQuery.extend({ var ret = []; - jQuery.each(elems, function( i, elem ) { + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { if ( typeof elem === "number" ) { elem += ""; } if ( !elem ) { - return; + continue; } // Convert html string into DOM nodes @@ -4343,7 +4478,7 @@ jQuery.extend({ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); } - elem = jQuery.makeArray( div.childNodes ); + elem = div.childNodes; } if ( elem.nodeType ) { @@ -4351,13 +4486,13 @@ jQuery.extend({ } else { ret = jQuery.merge( ret, elem ); } - - }); + } if ( fragment ) { for ( var i = 0; ret[i]; i++ ) { if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); + } else { if ( ret[i].nodeType === 1 ) { ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); @@ -4371,9 +4506,36 @@ jQuery.extend({ }, cleanData: function( elems ) { - for ( var i = 0, elem, id; (elem = elems[i]) != null; i++ ) { - jQuery.event.remove( elem ); - jQuery.removeData( elem ); + var data, id, cache = jQuery.cache, + special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ]; + + if ( data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + } else { + removeEvent( elem, type, data.handle ); + } + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } } } }); @@ -4614,15 +4776,15 @@ var jsc = now(), rquery = /\?/, rts = /(\?|&)_=.*?(&|$)/, rurl = /^(\w+:)?\/\/([^\/?#]+)/, - r20 = /%20/g; + r20 = /%20/g, -jQuery.fn.extend({ - // Keep a copy of the old load - _load: jQuery.fn.load, + // Keep a copy of the old load method + _load = jQuery.fn.load; +jQuery.fn.extend({ load: function( url, params, callback ) { if ( typeof url !== "string" ) { - return this._load( url ); + return _load.call( this, url ); // Don't do a request if no elements are being requested } else if ( !this.length ) { @@ -5243,7 +5405,7 @@ jQuery.extend({ if ( jQuery.isArray(obj) ) { // Serialize array item. jQuery.each( obj, function( i, v ) { - if ( traditional ) { + if ( traditional || /\[\]$/.test( prefix ) ) { // Treat each array item as a scalar. add( prefix, v ); } else { |