X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fcore.js;h=582e53e7c62e1d6b1da74f2d550985bbdc79327a;hb=540f9304a76eae2eec707db3aeb10496201a6ced;hp=ce2651963dbf0a48a07499106e07085e6da7d9e4;hpb=0a755f6ab38d36ffda02f9ff5a6d606c24a94baa;p=jquery.git diff --git a/src/core.js b/src/core.js index ce26519..582e53e 100644 --- a/src/core.js +++ b/src/core.js @@ -14,10 +14,8 @@ if ( window.jQuery ) var _jQuery = window.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 ); + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.prototype.init( selector, context ); }; // Map over the $ in case of overwrite @@ -202,7 +200,7 @@ jQuery.fn = jQuery.prototype = { 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 = ""; @@ -251,13 +249,15 @@ jQuery.fn = jQuery.prototype = { 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 ); }); }, @@ -290,9 +290,23 @@ jQuery.fn = jQuery.prototype = { 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 ) { + // 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"), + container2 = document.createElement("div"); + container.appendChild(clone); + container2.innerHTML = container.innerHTML; + return container2.firstChild; + } else + return this.cloneNode(true); }); // Need to set the expando to null on the cloned set if it exists @@ -340,7 +354,7 @@ jQuery.fn = jQuery.prototype = { }, add: function( selector ) { - return this.pushStack( jQuery.merge( + return !selector ? this : this.pushStack( jQuery.merge( this.get(), selector.constructor == String ? jQuery( selector ).get() : @@ -396,12 +410,15 @@ jQuery.fn = jQuery.prototype = { // 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 ( 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); @@ -468,7 +485,7 @@ jQuery.fn = jQuery.prototype = { 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( [] ); @@ -477,16 +494,9 @@ jQuery.fn = jQuery.prototype = { this.cloneNode( true ) : this; + // execute all scripts after the elements have been injected if ( jQuery.nodeName( elem, "script" ) ) { - - // If scripts are waiting to be executed, wait on this script as well - if ( scripts.length ) - scripts = scripts.add( elem ); - - // If nothing is waiting to be executed, run immediately - else - evalScript( 0, elem ); - + scripts = scripts.add( elem ); } else { // Remove any inner scripts for later evaluation if ( elem.nodeType == 1 ) @@ -502,6 +512,9 @@ jQuery.fn = jQuery.prototype = { } }; +// 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({ @@ -530,7 +543,7 @@ jQuery.extend = jQuery.fn.extend = function() { } // Handle case when target is a string or something (possible in deep copy) - if ( typeof target != "object" ) + if ( typeof target != "object" && typeof target != "function" ) target = {}; // extend jQuery itself if only one argument is passed @@ -549,7 +562,7 @@ jQuery.extend = jQuery.fn.extend = function() { continue; // Recurse if we're merging object values - if ( deep && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType ) + 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 @@ -591,7 +604,6 @@ jQuery.extend({ }, // Evalulates a script in a global context - // Evaluates Async. in Safari 2 :-( globalEval: function( data ) { data = jQuery.trim( data ); @@ -723,18 +735,19 @@ jQuery.extend({ // 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") @@ -918,6 +931,9 @@ jQuery.extend({ 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 ) @@ -1012,6 +1028,10 @@ jQuery.extend({ }, 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; @@ -1042,7 +1062,8 @@ jQuery.extend({ 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 ) ) @@ -1064,7 +1085,7 @@ jQuery.extend({ (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() : ""; } @@ -1264,7 +1285,8 @@ jQuery.each({ jQuery.each({ removeAttr: function( name ) { jQuery.attr( this, name, "" ); - this.removeAttribute( name ); + if (this.nodeType == 1) + this.removeAttribute( name ); }, addClass: function( classNames ) {