Index: openacs-4/packages/ajaxhelper/www/resources/ext2/adapter/jquery/jquery.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/resources/ext2/adapter/jquery/jquery.js,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/ajaxhelper/www/resources/ext2/adapter/jquery/jquery.js 4 Dec 2007 02:48:30 -0000 1.1 +++ openacs-4/packages/ajaxhelper/www/resources/ext2/adapter/jquery/jquery.js 10 Apr 2009 05:56:26 -0000 1.2 @@ -1,832 +1,1450 @@ -/* prevent execution of jQuery if included more than once */ -if(typeof window.jQuery == "undefined") { +(function(){ /* - * jQuery 1.1.1 - New Wave Javascript + * jQuery 1.2.3 - New Wave Javascript * - * Copyright (c) 2007 John Resig (jquery.com) + * Copyright (c) 2008 John Resig (jquery.com) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * $Date$ - * $Rev: 1153 $ + * $Rev: 4663 $ */ -// Global undefined variable -window.undefined = window.undefined; -var jQuery = function(a,c) { - // If the context is global, return a new object - if ( window == this ) - return new jQuery(a,c); +// Map over jQuery in case of overwrite +if ( window.jQuery ) + var _jQuery = window.jQuery; - // Make sure that a selection was provided - a = a || document; - - // HANDLE: $(function) - // Shortcut for document ready - if ( jQuery.isFunction(a) ) - return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( a ); - - // Handle HTML strings - if ( typeof a == "string" ) { - // HANDLE: $(html) -> $(array) - var m = /^[^<]*(<(.|\n)+>)[^>]*$/.exec(a); - if ( m ) - a = jQuery.clean( [ m[1] ] ); - - // HANDLE: $(expr) - else - return new jQuery( c ).find( a ); - } - - return this.setArray( - // HANDLE: $(array) - a.constructor == Array && a || - - // HANDLE: $(arraylike) - // Watch for when an array-like object is passed as the selector - (a.jquery || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType) && jQuery.makeArray( a ) || - - // HANDLE: $(*) - [ a ] ); +var jQuery = window.jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.prototype.init( selector, context ); }; // Map over the $ in case of overwrite -if ( typeof $ != "undefined" ) - jQuery._$ = $; +if ( window.$ ) + var _$ = window.$; // Map the jQuery namespace to the '$' one -var $ = jQuery; +window.$ = jQuery; +// A simple way to check for HTML strings or ID strings +// (both of which we optimize for) +var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; + +// Is it a simple selector +var isSimple = /^.[^:#\[\.]*$/; + jQuery.fn = jQuery.prototype = { - jquery: "1.1.1", + init: function( selector, context ) { + // Make sure that a selection was provided + selector = selector || document; + // Handle $(DOMElement) + if ( selector.nodeType ) { + this[0] = selector; + this.length = 1; + return this; + + // Handle HTML strings + } else if ( typeof selector == "string" ) { + // Are we dealing with HTML string or an ID? + var match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) + selector = jQuery.clean( [ match[1] ], context ); + + // HANDLE: $("#id") + else { + var elem = document.getElementById( match[3] ); + + // Make sure an element was located + if ( elem ) + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id != match[3] ) + return jQuery().find( selector ); + + // Otherwise, we inject the element directly into the jQuery object + else { + this[0] = elem; + this.length = 1; + return this; + } + + else + selector = []; + } + + // HANDLE: $(expr, [context]) + // (which is just equivalent to: $(content).find(expr) + } else + return new jQuery( context ).find( selector ); + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) + return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); + + return this.setArray( + // HANDLE: $(array) + selector.constructor == Array && selector || + + // HANDLE: $(arraylike) + // Watch for when an array-like object, contains DOM nodes, is passed in as the selector + (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) || + + // HANDLE: $(*) + [ selector ] ); + }, + + // The current version of jQuery being used + jquery: "1.2.3", + + // The number of elements contained in the matched element set size: function() { return this.length; }, + // The number of elements contained in the matched element set length: 0, + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array get: function( num ) { return num == undefined ? // Return a 'clean' array jQuery.makeArray( this ) : // Return just the object - this[num]; + this[ num ]; }, - pushStack: function( a ) { - var ret = jQuery(this); + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + // Build a new jQuery matched element set + var ret = jQuery( elems ); + + // Add the old object onto the stack (as a reference) ret.prevObject = this; - return ret.setArray( a ); + + // Return the newly-formed element set + return ret; }, - setArray: function( a ) { + + // 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, a ); + Array.prototype.push.apply( this, elems ); + return this; }, - each: function( fn, args ) { - return jQuery.each( this, fn, args ); + + // 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.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); }, - index: function( obj ) { - var pos = -1; + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + var ret = -1; + + // Locate the position of the desired element this.each(function(i){ - if ( this == obj ) pos = i; + if ( this == elem ) + ret = i; }); - return pos; + + return ret; }, - attr: function( key, value, type ) { - var obj = key; + attr: function( name, value, type ) { + var options = name; // Look for the case where we're accessing a style value - if ( key.constructor == String ) + if ( name.constructor == String ) if ( value == undefined ) - return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined; + return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined; + else { - obj = {}; - obj[ key ] = value; + options = {}; + options[ name ] = value; } // Check to see if we're setting style values - return this.each(function(index){ + return this.each(function(i){ // Set all the styles - for ( var prop in obj ) + for ( name in options ) jQuery.attr( - type ? this.style : this, - prop, jQuery.prop(this, obj[prop], type, index, prop) + type ? + this.style : + this, + name, jQuery.prop( this, options[ name ], type, i, name ) ); }); }, css: function( key, value ) { + // ignore negative width and height values + if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) + value = undefined; return this.attr( key, value, "curCSS" ); }, - text: function(e) { - if ( typeof e == "string" ) - return this.empty().append( document.createTextNode( e ) ); + text: function( text ) { + if ( typeof text != "object" && text != null ) + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); - var t = ""; - jQuery.each( e || this, function(){ + var ret = ""; + + jQuery.each( text || this, function(){ jQuery.each( this.childNodes, function(){ if ( this.nodeType != 8 ) - t += this.nodeType != 1 ? - this.nodeValue : jQuery.fn.text([ this ]); + ret += this.nodeType != 1 ? + this.nodeValue : + jQuery.fn.text( [ this ] ); }); }); - return t; + + return ret; }, - wrap: function() { - // The elements to wrap the target around - var a = jQuery.clean(arguments); + wrapAll: function( html ) { + if ( this[0] ) + // The elements to wrap the target around + jQuery( html, this[0].ownerDocument ) + .clone() + .insertBefore( this[0] ) + .map(function(){ + var elem = this; - // Wrap each of the matched elements individually - return this.each(function(){ - // Clone the structure that we're using to wrap - var b = a[0].cloneNode(true); + while ( elem.firstChild ) + elem = elem.firstChild; - // Insert it before the element to be wrapped - this.parentNode.insertBefore( b, this ); + return elem; + }) + .append(this); - // Find the deepest point in the wrap structure - while ( b.firstChild ) - b = b.firstChild; + return this; + }, - // Move the matched element to within the wrap structure - b.appendChild( this ); + wrapInner: function( html ) { + return this.each(function(){ + jQuery( this ).contents().wrapAll( html ); }); }, + + wrap: function( html ) { + return this.each(function(){ + jQuery( this ).wrapAll( html ); + }); + }, + append: function() { - return this.domManip(arguments, true, 1, function(a){ - this.appendChild( a ); + return this.domManip(arguments, true, false, function(elem){ + if (this.nodeType == 1) + this.appendChild( elem ); }); }, + prepend: function() { - return this.domManip(arguments, true, -1, function(a){ - this.insertBefore( a, this.firstChild ); + return this.domManip(arguments, true, true, function(elem){ + if (this.nodeType == 1) + this.insertBefore( elem, this.firstChild ); }); }, + before: function() { - return this.domManip(arguments, false, 1, function(a){ - this.parentNode.insertBefore( a, this ); + return this.domManip(arguments, false, false, function(elem){ + this.parentNode.insertBefore( elem, this ); }); }, + after: function() { - return this.domManip(arguments, false, -1, function(a){ - this.parentNode.insertBefore( a, this.nextSibling ); + return this.domManip(arguments, false, true, function(elem){ + this.parentNode.insertBefore( elem, this.nextSibling ); }); }, + end: function() { - return this.prevObject || jQuery([]); + return this.prevObject || jQuery( [] ); }, - find: function(t) { - return this.pushStack( jQuery.map( this, function(a){ - return jQuery.find(t,a); - }) ); + + find: function( selector ) { + var elems = jQuery.map(this, function(elem){ + return jQuery.find( selector, elem ); + }); + + return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? + jQuery.unique( elems ) : + elems ); }, - clone: function(deep) { - return this.pushStack( jQuery.map( this, function(a){ - return a.cloneNode( deep != undefined ? deep : true ); - }) ); + + clone: function( events ) { + // Do the clone + var ret = this.map(function(){ + if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { + // IE copies events bound via attachEvent when + // using cloneNode. Calling detachEvent on the + // clone will also remove the events from the orignal + // In order to get around this, we use innerHTML. + // Unfortunately, this means some modifications to + // attributes in IE that are actually only stored + // as properties will not be copied (such as the + // the name attribute on an input). + var clone = this.cloneNode(true), + container = document.createElement("div"); + container.appendChild(clone); + return jQuery.clean([container.innerHTML])[0]; + } else + return this.cloneNode(true); + }); + + // Need to set the expando to null on the cloned set if it exists + // removeData doesn't work here, IE removes it from the original as well + // this is primarily for IE but the data expando shouldn't be copied over in any browser + var clone = ret.find("*").andSelf().each(function(){ + if ( this[ expando ] != undefined ) + this[ expando ] = null; + }); + + // Copy the events from the original to the clone + if ( events === true ) + this.find("*").andSelf().each(function(i){ + if (this.nodeType == 3) + return; + var events = jQuery.data( this, "events" ); + + for ( var type in events ) + for ( var handler in events[ type ] ) + jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); + }); + + // Return the cloned set + return ret; }, - filter: function(t) { + filter: function( selector ) { return this.pushStack( - jQuery.isFunction( t ) && - jQuery.grep(this, function(el, index){ - return t.apply(el, [index]) + jQuery.isFunction( selector ) && + jQuery.grep(this, function(elem, i){ + return selector.call( elem, i ); }) || - jQuery.multiFilter(t,this) ); + jQuery.multiFilter( selector, this ) ); }, - not: function(t) { - return this.pushStack( - t.constructor == String && - jQuery.multiFilter(t,this,true) || + not: function( selector ) { + if ( selector.constructor == String ) + // test special case where just one selector is passed in + if ( isSimple.test( selector ) ) + return this.pushStack( jQuery.multiFilter( selector, this, true ) ); + else + selector = jQuery.multiFilter( selector, this ); - jQuery.grep(this,function(a){ - if ( t.constructor == Array || t.jquery ) - return jQuery.inArray( t, a ) < 0; - else - return a != t; - }) ); + var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; + return this.filter(function() { + return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; + }); }, - add: function(t) { - return this.pushStack( jQuery.merge( + add: function( selector ) { + return !selector ? this : this.pushStack( jQuery.merge( this.get(), - t.constructor == String ? - jQuery(t).get() : - t.length != undefined && !t.nodeName ? - t : [t] ) - ); + selector.constructor == String ? + jQuery( selector ).get() : + selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ? + selector : [selector] ) ); }, - is: function(expr) { - return expr ? jQuery.filter(expr,this).r.length > 0 : false; + + is: function( selector ) { + return selector ? + jQuery.multiFilter( selector, this ).length > 0 : + false; }, - val: function( val ) { - return val == undefined ? - ( this.length ? this[0].value : null ) : - this.attr( "value", val ); + hasClass: function( selector ) { + return this.is( "." + selector ); }, + + val: function( value ) { + if ( value == undefined ) { - html: function( val ) { - return val == undefined ? - ( this.length ? this[0].innerHTML : null ) : - this.empty().append( val ); + if ( this.length ) { + var elem = this[0]; + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type == "select-one"; + + // Nothing was selected + if ( index < 0 ) + return null; + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; + + // We don't need an array for one selects + if ( one ) + return value; + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + + // Everything else, we just grab the value + } else + return (this[0].value || "").replace(/\r/g, ""); + + } + + return undefined; + } + + return this.each(function(){ + if ( this.nodeType != 1 ) + return; + + if ( value.constructor == Array && /radio|checkbox/.test( this.type ) ) + this.checked = (jQuery.inArray(this.value, value) >= 0 || + jQuery.inArray(this.name, value) >= 0); + + else if ( jQuery.nodeName( this, "select" ) ) { + var values = value.constructor == Array ? + value : + [ value ]; + + jQuery( "option", this ).each(function(){ + this.selected = (jQuery.inArray( this.value, values ) >= 0 || + jQuery.inArray( this.text, values ) >= 0); + }); + + if ( !values.length ) + this.selectedIndex = -1; + + } else + this.value = value; + }); }, - domManip: function(args, table, dir, fn){ - var clone = this.length > 1; - var a = jQuery.clean(args); - if ( dir < 0 ) - a.reverse(); + + html: function( value ) { + return value == undefined ? + (this.length ? + this[0].innerHTML : + null) : + this.empty().append( value ); + }, + replaceWith: function( value ) { + return this.after( value ).remove(); + }, + + eq: function( i ) { + return this.slice( i, i + 1 ); + }, + + slice: function() { + return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function(elem, i){ + return callback.call( elem, i, elem ); + })); + }, + + andSelf: function() { + return this.add( this.prevObject ); + }, + + data: function( key, value ){ + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value == null ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data == undefined && this.length ) + data = jQuery.data( this[0], key ); + + return data == null && parts[1] ? + this.data( parts[0] ) : + data; + } else + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ + jQuery.data( this, key, value ); + }); + }, + + removeData: function( key ){ return this.each(function(){ + jQuery.removeData( this, key ); + }); + }, + + domManip: function( args, table, reverse, callback ) { + var clone = this.length > 1, elems; + + return this.each(function(){ + if ( !elems ) { + elems = jQuery.clean( args, this.ownerDocument ); + + if ( reverse ) + elems.reverse(); + } + var obj = this; - if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") ) - obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody")); + if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) ) + obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") ); - jQuery.each( a, function(){ - fn.apply( obj, [ clone ? this.cloneNode(true) : this ] ); + var scripts = jQuery( [] ); + + jQuery.each(elems, function(){ + var elem = clone ? + jQuery( this ).clone( true )[0] : + this; + + // execute all scripts after the elements have been injected + if ( jQuery.nodeName( elem, "script" ) ) { + scripts = scripts.add( elem ); + } else { + // Remove any inner scripts for later evaluation + if ( elem.nodeType == 1 ) + scripts = scripts.add( jQuery( "script", elem ).remove() ); + + // Inject the elements into the document + callback.call( obj, elem ); + } }); + scripts.each( evalScript ); }); } }; +// Give the init function the jQuery prototype for later instantiation +jQuery.prototype.init.prototype = jQuery.prototype; + +function evalScript( i, elem ) { + if ( elem.src ) + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + + else + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + + if ( elem.parentNode ) + elem.parentNode.removeChild( elem ); +} + jQuery.extend = jQuery.fn.extend = function() { // copy reference to target object - var target = arguments[0], - a = 1; + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + // Handle a deep copy situation + if ( target.constructor == Boolean ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target != "object" && typeof target != "function" ) + target = {}; + // extend jQuery itself if only one argument is passed - if ( arguments.length == 1 ) { + if ( length == 1 ) { target = this; - a = 0; + i = 0; } - var prop; - while (prop = arguments[a++]) - // Extend the base object - for ( var i in prop ) target[i] = prop[i]; + for ( ; i < length; i++ ) + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) + // Extend the base object + for ( var name in options ) { + // Prevent never-ending loop + if ( target === options[ name ] ) + continue; + + // Recurse if we're merging object values + if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType ) + target[ name ] = jQuery.extend( target[ name ], options[ name ] ); + + // Don't bring in undefined values + else if ( options[ name ] != undefined ) + target[ name ] = options[ name ]; + + } + // Return the modified object return target; }; +var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {}; + +// exclude the following css properties to add px +var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; + jQuery.extend({ - noConflict: function() { - if ( jQuery._$ ) - $ = jQuery._$; + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) + window.jQuery = _jQuery; + return jQuery; }, - // This may seem like some crazy code, but trust me when I say that this - // is the only cross-browser way to do this. --John + // See test/unit/core.js for details concerning this function. isFunction: function( fn ) { - return !!fn && typeof fn != "string" && - typeof fn[0] == "undefined" && /function/i.test( fn + "" ); + return !!fn && typeof fn != "string" && !fn.nodeName && + fn.constructor != Array && /function/i.test( fn + "" ); }, + + // check if an element is in a (or is an) XML document + isXMLDoc: function( elem ) { + return elem.documentElement && !elem.body || + elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; + }, + // Evalulates a script in a global context + globalEval: function( data ) { + data = jQuery.trim( data ); + + if ( data ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + if ( jQuery.browser.msie ) + script.text = data; + else + script.appendChild( document.createTextNode( data ) ); + + head.appendChild( script ); + head.removeChild( script ); + } + }, + nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); }, + + cache: {}, + + data: function( elem, name, data ) { + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ]; + + // Compute a unique ID for the element + if ( !id ) + id = elem[ expando ] = ++uuid; + + // Only generate the data cache if we're + // trying to access or manipulate it + if ( name && !jQuery.cache[ id ] ) + jQuery.cache[ id ] = {}; + + // Prevent overriding the named cache with undefined values + if ( data != undefined ) + jQuery.cache[ id ][ name ] = data; + + // Return the named cache data, or the ID for the element + return name ? + jQuery.cache[ id ][ name ] : + id; + }, + + removeData: function( elem, name ) { + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( jQuery.cache[ id ] ) { + // Remove the section of cache data + delete jQuery.cache[ id ][ name ]; + + // If we've removed all the data, remove the element's cache + name = ""; + + for ( name in jQuery.cache[ id ] ) + break; + + if ( !name ) + jQuery.removeData( elem ); + } + + // 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 ); + } + + // Completely remove the data cache + delete jQuery.cache[ id ]; + } + }, + // args is for internal usage only - each: function( obj, fn, args ) { - if ( obj.length == undefined ) - for ( var i in obj ) - fn.apply( obj[i], args || [i, obj[i]] ); - else - for ( var i = 0, ol = obj.length; i < ol; i++ ) - if ( fn.apply( obj[i], args || [i, obj[i]] ) === false ) break; - return obj; + each: function( object, callback, args ) { + if ( args ) { + if ( object.length == undefined ) { + for ( var name in object ) + if ( callback.apply( object[ name ], args ) === false ) + break; + } else + for ( var i = 0, length = object.length; i < length; i++ ) + if ( callback.apply( object[ i ], args ) === false ) + break; + + // A special, fast, case for the most common use of each + } else { + if ( object.length == undefined ) { + for ( var name in object ) + if ( callback.call( object[ name ], name, object[ name ] ) === false ) + break; + } else + for ( var i = 0, length = object.length, value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} + } + + return object; }, - prop: function(elem, value, type, index, prop){ + prop: function( elem, value, type, i, name ) { // Handle executable functions if ( jQuery.isFunction( value ) ) - return value.call( elem, [index] ); + value = value.call( elem, i ); - // exclude the following css properties to add px - var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; - // Handle passing in a number to a CSS property - if ( value.constructor == Number && type == "curCSS" && !exclude.test(prop) ) - return value + "px"; - - return value; + return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? + value + "px" : + value; }, className: { // internal only, use addClass("class") - add: function( elem, c ){ - jQuery.each( c.split(/\s+/), function(i, cur){ - if ( !jQuery.className.has( elem.className, cur ) ) - elem.className += ( elem.className ? " " : "" ) + cur; + add: function( elem, classNames ) { + jQuery.each((classNames || "").split(/\s+/), function(i, className){ + if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) + elem.className += (elem.className ? " " : "") + className; }); }, // internal only, use removeClass("class") - remove: function( elem, c ){ - elem.className = c ? - jQuery.grep( elem.className.split(/\s+/), function(cur){ - return !jQuery.className.has( c, cur ); - }).join(" ") : ""; + remove: function( elem, classNames ) { + if (elem.nodeType == 1) + elem.className = classNames != undefined ? + jQuery.grep(elem.className.split(/\s+/), function(className){ + return !jQuery.className.has( classNames, className ); + }).join(" ") : + ""; }, // internal only, use is(".class") - has: function( t, c ) { - t = t.className || t; - return t && new RegExp("(^|\\s)" + c + "(\\s|$)").test( t ); + has: function( elem, className ) { + return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; } }, - swap: function(e,o,f) { - for ( var i in o ) { - e.style["old"+i] = e.style[i]; - e.style[i] = o[i]; + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; } - f.apply( e, [] ); - for ( var i in o ) - e.style[i] = e.style["old"+i]; - }, - css: function(e,p) { - if ( p == "height" || p == "width" ) { - var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"]; + callback.call( elem ); - jQuery.each( d, function(){ - old["padding" + this] = 0; - old["border" + this + "Width"] = 0; - }); + // Revert the old values + for ( var name in options ) + elem.style[ name ] = old[ name ]; + }, - jQuery.swap( e, old, function() { - if (jQuery.css(e,"display") != "none") { - oHeight = e.offsetHeight; - oWidth = e.offsetWidth; - } else { - e = jQuery(e.cloneNode(true)) - .find(":radio").removeAttr("checked").end() - .css({ - visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0" - }).appendTo(e.parentNode)[0]; + css: function( elem, name, force ) { + if ( name == "width" || name == "height" ) { + var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; + + function getWH() { + val = name == "width" ? elem.offsetWidth : elem.offsetHeight; + var padding = 0, border = 0; + jQuery.each( which, function() { + padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; + border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; + }); + val -= Math.round(padding + border); + } + + if ( jQuery(elem).is(":visible") ) + getWH(); + else + jQuery.swap( elem, props, getWH ); + + return Math.max(0, val); + } + + return jQuery.curCSS( elem, name, force ); + }, - var parPos = jQuery.css(e.parentNode,"position"); - if ( parPos == "" || parPos == "static" ) - e.parentNode.style.position = "relative"; + curCSS: function( elem, name, force ) { + var ret; - oHeight = e.clientHeight; - oWidth = e.clientWidth; + // A helper method for determining if an element's values are broken + function color( elem ) { + if ( !jQuery.browser.safari ) + return false; - if ( parPos == "" || parPos == "static" ) - e.parentNode.style.position = "static"; + var ret = document.defaultView.getComputedStyle( elem, null ); + return !ret || ret.getPropertyValue("color") == ""; + } - e.parentNode.removeChild(e); - } - }); + // We need to handle opacity special in IE + if ( name == "opacity" && jQuery.browser.msie ) { + ret = jQuery.attr( elem.style, "opacity" ); - return p == "height" ? oHeight : oWidth; + return ret == "" ? + "1" : + ret; } + // Opera sometimes will give the wrong display answer, this fixes it, see #2037 + if ( jQuery.browser.opera && name == "display" ) { + var save = elem.style.outline; + elem.style.outline = "0 solid black"; + elem.style.outline = save; + } + + // Make sure we're using the right name for getting the float value + if ( name.match( /float/i ) ) + name = styleFloat; - return jQuery.curCSS( e, p ); - }, + if ( !force && elem.style && elem.style[ name ] ) + ret = elem.style[ name ]; - curCSS: function(elem, prop, force) { - var ret; - - if (prop == "opacity" && jQuery.browser.msie) - return jQuery.attr(elem.style, "opacity"); - - if (prop == "float" || prop == "cssFloat") - prop = jQuery.browser.msie ? "styleFloat" : "cssFloat"; + else if ( document.defaultView && document.defaultView.getComputedStyle ) { - if (!force && elem.style[prop]) - ret = elem.style[prop]; + // Only "float" is needed here + if ( name.match( /float/i ) ) + name = "float"; - else if (document.defaultView && document.defaultView.getComputedStyle) { + name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); - if (prop == "cssFloat" || prop == "styleFloat") - prop = "float"; + var getComputedStyle = document.defaultView.getComputedStyle( elem, null ); - prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase(); - var cur = document.defaultView.getComputedStyle(elem, null); + if ( getComputedStyle && !color( elem ) ) + ret = getComputedStyle.getPropertyValue( name ); - if ( cur ) - ret = cur.getPropertyValue(prop); - else if ( prop == "display" ) - ret = "none"; - else - jQuery.swap(elem, { display: "block" }, function() { - var c = document.defaultView.getComputedStyle(this, ""); - ret = c && c.getPropertyValue(prop) || ""; - }); + // If the element isn't reporting its values properly in Safari + // then some display: none elements are involved + else { + var swap = [], stack = []; - } else if (elem.currentStyle) { + // Locate all of the parent display: none elements + for ( var a = elem; a && color(a); a = a.parentNode ) + stack.unshift(a); - var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}); - ret = elem.currentStyle[prop] || elem.currentStyle[newProp]; - + // Go through and make them visible, but in reverse + // (It would be better if we knew the exact display type that they had) + for ( var i = 0; i < stack.length; i++ ) + if ( color( stack[ i ] ) ) { + swap[ i ] = stack[ i ].style.display; + stack[ i ].style.display = "block"; + } + + // Since we flip the display style, we have to handle that + // one special, otherwise get the value + ret = name == "display" && swap[ stack.length - 1 ] != null ? + "none" : + ( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || ""; + + // Finally, revert the display styles back + for ( var i = 0; i < swap.length; i++ ) + if ( swap[ i ] != null ) + stack[ i ].style.display = swap[ i ]; + } + + // We should always get a number back from opacity + if ( name == "opacity" && ret == "" ) + ret = "1"; + + } else if ( elem.currentStyle ) { + var camelCase = name.replace(/\-(\w)/g, function(all, letter){ + return letter.toUpperCase(); + }); + + ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + elem.style.left = ret || 0; + ret = elem.style.pixelLeft + "px"; + + // Revert the changed values + elem.style.left = style; + elem.runtimeStyle.left = runtimeStyle; + } } return ret; }, - clean: function(a) { - var r = []; + clean: function( elems, context ) { + var ret = []; + context = context || document; + // !context.createElement fails in IE with an error but returns typeof 'object' + if (typeof context.createElement == 'undefined') + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; - jQuery.each( a, function(i,arg){ - if ( !arg ) return; + jQuery.each(elems, function(i, elem){ + if ( !elem ) + return; - if ( arg.constructor == Number ) - arg = arg.toString(); + if ( elem.constructor == Number ) + elem = elem.toString(); - // Convert html string into DOM nodes - if ( typeof arg == "string" ) { + // Convert html string into DOM nodes + if ( typeof elem == "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ + return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? + all : + front + ">"; + }); + // Trim whitespace, otherwise indexOf won't work as expected - var s = jQuery.trim(arg), div = document.createElement("div"), tb = []; + var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); var wrap = - // option or optgroup - !s.indexOf("", ""] || + // option or optgroup + !tags.indexOf("", "" ] || - (!s.indexOf("", ""] || + !tags.indexOf("", "" ] || - !s.indexOf("", ""] || + tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && + [ 1, "", "
" ] || + !tags.indexOf("", "" ] || + // matched above - (!s.indexOf("", ""] || + (!tags.indexOf("", "" ] || - [0,"",""]; + !tags.indexOf("", "" ] || + // IE can't serialize and