/*
* jQuery @VERSION - 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.
*
*/
// Map over jQuery in case of overwrite
-if ( typeof jQuery != "undefined" )
- var _jQuery = jQuery;
-
-var jQuery = window.jQuery = function( selector, context ) {
- // If the context is a namespace object, return a new object
- return this instanceof jQuery ?
- this.init( selector, context ) :
- new jQuery( selector, context );
-};
+var _jQuery = window.jQuery,
+// Map over the $ in case of overwrite
+ _$ = window.$;
-// Map over the $ in case of overwrite
-if ( typeof $ != "undefined" )
- var _$ = $;
-
-// Map the jQuery namespace to the '$' one
-window.$ = jQuery;
+var jQuery = window.jQuery = window.$ = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context );
+};
// A simple way to check for HTML strings or ID strings
// (both of which we optimize for)
-var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,
+
+// Is it a simple selector
+ isSimple = /^.[^:#\[\.]*$/;
jQuery.fn = jQuery.prototype = {
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
- if ( typeof selector == "string" ) {
+ } else if ( typeof selector == "string" ) {
// Are we dealing with HTML string or an ID?
var match = quickExpr.exec( selector );
// 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 ] );
+
+ return this.setArray(jQuery.makeArray(selector));
},
// The current version of jQuery being used
},
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( text ) {
if ( typeof text != "object" && text != null )
- return this.empty().append( document.createTextNode( text ) );
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
var ret = "";
append: function() {
return this.domManip(arguments, true, false, function(elem){
- this.appendChild( elem );
+ if (this.nodeType == 1)
+ this.appendChild( elem );
});
},
prepend: function() {
return this.domManip(arguments, true, true, function(elem){
- this.insertBefore( elem, this.firstChild );
+ if (this.nodeType == 1)
+ this.insertBefore( elem, this.firstChild );
});
},
clone: function( events ) {
// Do the clone
var ret = this.map(function(){
- return this.outerHTML ?
- jQuery( this.outerHTML )[0] :
- this.cloneNode( true );
+ 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
// 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 )
},
not: function( selector ) {
- return this.pushStack(
- selector.constructor == String &&
- jQuery.multiFilter( selector, this, true ) ||
-
- jQuery.grep(this, function(elem) {
- return selector.constructor == Array || selector.jquery ?
- jQuery.inArray( elem, selector ) < 0 :
- elem != 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 );
+
+ 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( selector ) {
- return this.pushStack( jQuery.merge( this.get(), jQuery( selector ) ) );
+ return !selector ? this : this.pushStack( jQuery.merge(
+ this.get(),
+ selector.constructor == String ?
+ jQuery( selector ).get() :
+ selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
+ selector : [selector] ) );
},
is: function( selector ) {
- return selector ?
- jQuery.multiFilter( selector, this ).length > 0 :
- false;
+ return !!selector && jQuery.multiFilter( selector, this ).length > 0;
},
hasClass: function( selector ) {
if ( this.length ) {
var elem = this[0];
-
+
// We need to handle select boxes special
if ( jQuery.nodeName( elem, "select" ) ) {
var index = elem.selectedIndex,
// Everything else, we just grab the value
} else
- return this[0].value.replace(/\r/g, "");
+ return (this[0].value || "").replace(/\r/g, "");
}
- } else
- return this.each(function(){
- if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
- this.checked = (jQuery.inArray(this.value, value) >= 0 ||
- jQuery.inArray(this.name, value) >= 0);
+ return undefined;
+ }
- else if ( jQuery.nodeName( this, "select" ) ) {
- var values = value.constructor == Array ?
- value :
- [ value ];
+ return this.each(function(){
+ if ( this.nodeType != 1 )
+ return;
- jQuery( "option", this ).each(function(){
- this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
- jQuery.inArray( this.text, values ) >= 0);
- });
+ if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
+ this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+ jQuery.inArray(this.name, value) >= 0);
- if ( !tmp.length )
- this.selectedIndex = -1;
+ else if ( jQuery.nodeName( this, "select" ) ) {
+ var values = value.constructor == Array ?
+ value :
+ [ value ];
- } else
- this.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;
+ });
},
html: function( value ) {
andSelf: function() {
return this.add( this.prevObject );
},
+
+ data: function( key, value ){
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ if ( data === undefined && this.length )
+ data = jQuery.data( this[0], key );
+
+ return data === undefined && 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;
var obj = this;
if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
- obj = this.getElementsByTagName("tbody")[0] || this.appendChild( document.createElement("tbody") );
+ obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
+
+ var scripts = jQuery( [] );
jQuery.each(elems, function(){
var elem = clone ?
- this.cloneNode( true ) :
+ jQuery( this ).clone( true )[0] :
this;
- if ( !evalScript( 0, elem ) )
+ // 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.fn.init.prototype = jQuery.fn;
+
function evalScript( i, elem ) {
- var script = jQuery.nodeName( elem, "script" );
-
- if ( script ) {
- if ( elem.src )
- jQuery.ajax({
- url: elem.src,
- async: false,
- dataType: "script"
- });
+ 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 );
+ else
+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
- } else if ( elem.nodeType == 1 )
- jQuery( "script", elem ).each( evalScript );
+ if ( elem.parentNode )
+ elem.parentNode.removeChild( elem );
+}
- return script;
+function now(){
+ return +new Date;
}
jQuery.extend = jQuery.fn.extend = function() {
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 ( length == 1 ) {
+ if ( length == i ) {
target = this;
- i = 0;
+ --i;
}
for ( ; i < length; i++ )
if ( (options = arguments[ i ]) != null )
// Extend the base object
for ( var name in options ) {
+ var src = target[ name ], copy = options[ name ];
+
// Prevent never-ending loop
- if ( target == options[ name ] )
+ if ( target === copy )
continue;
// Recurse if we're merging object values
- if ( deep && typeof options[ name ] == "object" && target[ name ] )
- jQuery.extend( target[ name ], options[ name ] );
+ if ( deep && copy && typeof copy == "object" && src && !copy.nodeType )
+ target[ name ] = jQuery.extend( deep, src, copy );
// Don't bring in undefined values
- else if ( options[ name ] != undefined )
- target[ name ] = options[ name ];
+ else if ( copy !== undefined )
+ target[ name ] = copy;
}
return target;
};
-var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
+var expando = "jQuery" + now(), uuid = 0, windowData = {},
// exclude the following css properties to add px
-var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
+ exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+// cache getComputedStyle
+ getComputedStyle = document.defaultView && document.defaultView.getComputedStyle;
jQuery.extend({
noConflict: function( deep ) {
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" && !fn.nodeName &&
fn.constructor != Array && /function/i.test( fn + "" );
},
// Evalulates a script in a global context
- // Evaluates Async. in Safari 2 :-(
globalEval: function( data ) {
data = jQuery.trim( data );
jQuery.cache[ id ] = {};
// Prevent overriding the named cache with undefined values
- if ( data != undefined )
+ if ( data !== undefined )
jQuery.cache[ id ][ name ] = data;
// Return the named cache data, or the ID for the element
// args is for internal usage only
each: function( object, callback, args ) {
if ( args ) {
- if ( object.length == undefined )
+ if ( object.length == undefined ) {
for ( var name in object )
- callback.apply( object[ name ], args );
- else
+ 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 )
+ if ( object.length == undefined ) {
for ( var name in object )
- callback.call( object[ name ], name, object[ name ] );
- else
+ 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] ){}
}
// internal only, use addClass("class")
add: function( elem, classNames ) {
jQuery.each((classNames || "").split(/\s+/), function(i, className){
- if ( !jQuery.className.has( elem.className, className ) )
+ if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
elem.className += (elem.className ? " " : "") + className;
});
},
// internal only, use removeClass("class")
remove: function( elem, classNames ) {
- elem.className = classNames != undefined ?
- jQuery.grep(elem.className.split(/\s+/), function(className){
- return !jQuery.className.has( classNames, className );
- }).join(" ") :
- "";
+ 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")
// 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 ) {
- elem.style[ "old" + name ] = elem.style[ name ];
+ old[ name ] = elem.style[ name ];
elem.style[ name ] = options[ name ];
}
// Revert the old values
for ( var name in options )
- elem.style[ name ] = elem.style[ "old" + name ];
+ elem.style[ name ] = old[ name ];
},
- css: function( elem, name ) {
- if ( name == "height" || name == "width" ) {
- var old = {}, height, width;
-
- // Revert the padding and border widths to get the
- // correct height/width values
- jQuery.each([ "Top", "Bottom", "Right", "Left" ], function(){
- old[ "padding" + this ] = 0;
- old[ "border" + this + "Width" ] = 0;
- });
-
- // Swap out the padding/border values temporarily
- jQuery.swap( elem, old, function() {
-
- // If the element is visible, then the calculation is easy
- if ( jQuery( elem ).is(":visible") ) {
- height = elem.offsetHeight;
- width = elem.offsetWidth;
-
- // Otherwise, we need to flip out more values
- } else {
- elem = jQuery( elem.cloneNode(true) )
- .find(":radio").removeAttr("checked").end()
- .css({
- visibility: "hidden",
- position: "absolute",
- display: "block",
- right: "0",
- left: "0"
- }).appendTo( elem.parentNode )[0];
-
- var position = jQuery.css( elem.parentNode, "position" ) || "static";
- if ( position == "static" )
- elem.parentNode.style.position = "relative";
-
- height = elem.clientHeight;
- width = elem.clientWidth;
-
- if ( position == "static" )
- elem.parentNode.style.position = "static";
-
- elem.parentNode.removeChild( elem );
- }
- });
-
- return name == "height" ?
- height :
- width;
+ 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 );
+
+ return jQuery.curCSS( elem, name, force );
},
curCSS: function( elem, name, force ) {
function color( elem ) {
if ( !jQuery.browser.safari )
return false;
-
- var ret = document.defaultView.getComputedStyle( elem, null );
+
+ // getComputedStyle is cached
+ var ret = getComputedStyle( elem, null );
return !ret || ret.getPropertyValue("color") == "";
}
"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;
- if ( !force && elem.style[ name ] )
+ if ( !force && elem.style && elem.style[ name ] )
ret = elem.style[ name ];
- else if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ else if ( getComputedStyle ) {
// Only "float" is needed here
if ( name.match( /float/i ) )
name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
- var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
+ var computedStyle = getComputedStyle( elem, null );
- if ( getComputedStyle && !color( elem ) )
- ret = getComputedStyle.getPropertyValue( name );
+ if ( computedStyle && !color( elem ) )
+ ret = computedStyle.getPropertyValue( name );
// If the element isn't reporting its values properly in Safari
// then some display: none elements are involved
else {
- var swap = [], stack = [];
+ var swap = [], stack = [], a = elem, i = 0;
// Locate all of the parent display: none elements
- for ( var a = elem; a && color(a); a = a.parentNode )
+ for ( ; a && color(a); a = a.parentNode )
stack.unshift(a);
// 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++ )
+ for ( ; i < stack.length; i++ )
if ( color( stack[ i ] ) ) {
swap[ i ] = stack[ i ].style.display;
stack[ i ].style.display = "block";
// one special, otherwise get the value
ret = name == "display" && swap[ stack.length - 1 ] != null ?
"none" :
- document.defaultView.getComputedStyle( elem, null ).getPropertyValue( name ) || "";
+ ( computedStyle && computedStyle.getPropertyValue( name ) ) || "";
// Finally, revert the display styles back
- for ( var i = 0; i < swap.length; i++ )
+ for ( i = 0; i < swap.length; i++ )
if ( swap[ i ] != null )
stack[ i ].style.display = swap[ i ];
}
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(elems, function(i, elem){
if ( !elem )
return;
if ( elem.constructor == Number )
- elem = elem.toString();
+ elem += '';
// 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)$/i) ?
+ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
all :
front + "></" + tag + ">";
});
var wrap =
// option or optgroup
!tags.indexOf("<opt") &&
- [ 1, "<select>", "</select>" ] ||
+ [ 1, "<select multiple='multiple'>", "</select>" ] ||
!tags.indexOf("<leg") &&
[ 1, "<fieldset>", "</fieldset>" ] ||
div.firstChild && div.firstChild.childNodes :
// String was a bare <thead> or <tfoot>
- wrap[1] == "<table>" && s.indexOf("<tbody") < 0 ?
+ wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
div.childNodes :
[];
-
- for ( var i = tbody.length - 1; i >= 0 ; --i )
- if ( jQuery.nodeName( tbody[ i ], "tbody" ) && !tbody[ i ].childNodes.length )
- tbody[ i ].parentNode.removeChild( tbody[ i ] );
-
+
+ for ( var j = tbody.length - 1; j >= 0 ; --j )
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
// IE completely kills leading whitespace when innerHTML is used
if ( /^\s/.test( elem ) )
div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
-
+
}
elem = jQuery.makeArray( div.childNodes );
},
attr: function( elem, name, value ) {
+ // don't set attributes on text and comment nodes
+ if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+ return undefined;
+
var fix = jQuery.isXMLDoc( elem ) ?
{} :
jQuery.props;
if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
throw "type property can't be changed";
- elem.setAttribute( name, value );
+ // convert the value to a string (all browsers do this but IE) see #1070
+ elem.setAttribute( name, "" + value );
}
if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) )
(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
}
- return elem.filter ?
+ return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
"";
}
makeArray: function( array ) {
var ret = [];
- // Need to use typeof to fight Safari childNodes crashes
- if ( typeof array != "array" )
- for ( var i = 0, length = array.length; i < length; i++ )
- ret.push( array[ i ] );
- else
- ret = array.slice( 0 );
+ if( array != undefined ){
+ var i = array.length;
+ //the window, strings and functions also have 'length'
+ if( i != null && !array.split && array != window && !array.call )
+ while( i )
+ ret[--i] = array[i];
+ else
+ ret[0] = array;
+ }
return ret;
},
},
grep: function( elems, callback, inv ) {
- // If a string is passed in for the function, make a function
- // for it (a handy shortcut)
- if ( typeof callback == "string" )
- callback = eval("false||function(a,i){return " + callback + "}");
-
var ret = [];
// Go through the array, only saving the items
readonly: "readOnly",
selected: "selected",
maxlength: "maxLength",
- selectedIndex: "selectedIndex"
+ selectedIndex: "selectedIndex",
+ defaultValue: "defaultValue",
+ tagName: "tagName",
+ nodeName: "nodeName"
}
});
jQuery.each({
- parent: "elem.parentNode",
- parents: "jQuery.dir(elem,'parentNode')",
- next: "jQuery.nth(elem,2,'nextSibling')",
- prev: "jQuery.nth(elem,2,'previousSibling')",
- nextAll: "jQuery.dir(elem,'nextSibling')",
- prevAll: "jQuery.dir(elem,'previousSibling')",
- siblings: "jQuery.sibling(elem.parentNode.firstChild,elem)",
- children: "jQuery.sibling(elem.firstChild)",
- contents: "jQuery.nodeName(elem,'iframe')?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes)"
+ parent: function(elem){return elem.parentNode;},
+ parents: function(elem){return jQuery.dir(elem,"parentNode");},
+ next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+ prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+ nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+ prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+ siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+ children: function(elem){return jQuery.sibling(elem.firstChild);},
+ contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
}, function(name, fn){
- fn = eval("false||function(elem){return " + fn + "}");
-
jQuery.fn[ name ] = function( selector ) {
var ret = jQuery.map( this, fn );
jQuery.each({
removeAttr: function( name ) {
jQuery.attr( this, name, "" );
- this.removeAttribute( name );
+ if (this.nodeType == 1)
+ this.removeAttribute( name );
},
addClass: function( classNames ) {
remove: function( selector ) {
if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
- jQuery.removeData( this );
- this.parentNode.removeChild( this );
+ // Prevent memory leaks
+ jQuery( "*", this ).add(this).each(function(){
+ jQuery.event.remove(this);
+ jQuery.removeData(this);
+ });
+ if (this.parentNode)
+ this.parentNode.removeChild( this );
}
},
empty: function() {
- // Clean up the cache
- jQuery( "*", this ).each(function(){
- jQuery.removeData(this);
- });
-
+ // Remove element nodes and prevent memory leaks
+ jQuery( ">*", this ).remove();
+
+ // Remove any remaining nodes
while ( this.firstChild )
this.removeChild( this.firstChild );
}
jQuery.browser.opera && document.body[ "client" + name ] ||
// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
- jQuery.browser.safari && self[ "inner" + name ] ||
+ jQuery.browser.safari && window[ "inner" + name ] ||
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
// Get document width or height
this[0] == document ?
- // Either scroll[Width/Height] or offset[Width/Height], whichever is greater (Mozilla reports scrollWidth the same as offsetWidth)
- Math.max( document.body[ "scroll" + name ], document.body[ "offset" + name ] ) :
-
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ Math.max(
+ Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
+ Math.max(document.body["offset" + name], document.documentElement["offset" + name])
+ ) :
+
// Get or set width or height on the element
size == undefined ?
// Get width or height on the element