Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Split out the fragment-building code from domManip. Switched core.js …

…to using that instead. Also moved the standalone tag detection to $(...) for performance.
  • Loading branch information...
commit 9d8d74569c8114f9c9b0f42bca71536e154c5944 1 parent b7d4e0e
John Resig authored September 07, 2009
19  src/core.js
@@ -31,6 +31,9 @@ var jQuery = function( selector, context ) {
31 31
 	// Used for trimming whitespace
32 32
 	rtrim = /^\s+|\s+$/g,
33 33
 
  34
+	// Match a standalone tag
  35
+	rsingleTag = /^<(\w+)\s*\/?>$/,
  36
+
34 37
 	// Keep a UserAgent string for use with jQuery.browser
35 38
 	userAgent = navigator.userAgent.toLowerCase(),
36 39
 
@@ -41,7 +44,7 @@ var jQuery = function( selector, context ) {
41 44
 
42 45
 jQuery.fn = jQuery.prototype = {
43 46
 	init: function( selector, context ) {
44  
-		var match, elem, ret;
  47
+		var match, elem, ret, doc;
45 48
 
46 49
 		// Handle $(""), $(null), or $(undefined)
47 50
 		if ( !selector ) {
@@ -70,7 +73,19 @@ jQuery.fn = jQuery.prototype = {
70 73
 
71 74
 				// HANDLE: $(html) -> $(array)
72 75
 				if ( match[1] ) {
73  
-					selector = jQuery.clean( [ match[1] ], context );
  76
+					doc = (context ? context.ownerDocument || context : document);
  77
+
  78
+					// If a single string is passed in and it's a single tag
  79
+					// just do a createElement and skip the rest
  80
+					ret = rsingleTag.exec( selector );
  81
+
  82
+					if ( ret ) {
  83
+						selector = [ doc.createElement( ret[1] ) ];
  84
+
  85
+					} else {
  86
+						ret = buildFragment( [ match[1] ], [ doc ] );
  87
+						selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
  88
+					}
74 89
 
75 90
 				// HANDLE: $("#id")
76 91
 				} else {
79  src/manipulation.js
... ...
@@ -1,6 +1,5 @@
1 1
 var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
2 2
 	rleadingWhitespace = /^\s+/,
3  
-	rsingleTag = /^<(\w+)\s*\/?>$/,
4 3
 	rxhtmlTag = /(<(\w+)[^>]*?)\/>/g,
5 4
 	rselfClosing = /^(?:abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i,
6 5
 	rinsideTable = /^<(thead|tbody|tfoot|colg|cap)/,
@@ -166,8 +165,7 @@ jQuery.fn.extend({
166 165
 	},
167 166
 
168 167
 	domManip: function( args, table, callback ) {
169  
-		var fragment, scripts, cacheable, cached, cacheresults, first,
170  
-			value = args[0];
  168
+		var results, first, value = args[0], scripts = [];
171 169
 
172 170
 		if ( jQuery.isFunction(value) ) {
173 171
 			return this.each(function() {
@@ -177,23 +175,14 @@ jQuery.fn.extend({
177 175
 		}
178 176
 
179 177
 		if ( this[0] ) {
180  
-			if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 ) {
181  
-				cacheable = true;
182  
-				cacheresults = jQuery.fragments[ args[0] ];
183  
-				if ( cacheresults ) {
184  
-					if ( cacheresults !== 1 ) {
185  
-						fragment = cacheresults;
186  
-					}
187  
-					cached = true;
188  
-				}
189  
-			}
190  
-
191  
-			if ( !fragment ) {
192  
-				fragment = (this[0].ownerDocument || this[0]).createDocumentFragment();
193  
-				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment );
  178
+			// If we're in a fragment, just use that instead of building a new one
  179
+			if ( args[0] && args[0].parentNode && args[0].parentNode.nodeType === 11 ) {
  180
+				results = { fragment: args[0].parentNode };
  181
+			} else {
  182
+				results = buildFragment( args, this[0], scripts );
194 183
 			}
195 184
 
196  
-			first = fragment.firstChild;
  185
+			first = results.fragment.firstChild;
197 186
 
198 187
 			if ( first ) {
199 188
 				table = table && jQuery.nodeName( first, "tr" );
@@ -203,9 +192,9 @@ jQuery.fn.extend({
203 192
 						table ?
204 193
 							root(this[i], first) :
205 194
 							this[i],
206  
-						cacheable || this.length > 1 || i > 0 ?
207  
-							fragment.cloneNode(true) :
208  
-							fragment
  195
+						results.cacheable || this.length > 1 || i > 0 ?
  196
+							results.fragment.cloneNode(true) :
  197
+							results.fragment
209 198
 					);
210 199
 				}
211 200
 			}
@@ -213,10 +202,6 @@ jQuery.fn.extend({
213 202
 			if ( scripts ) {
214 203
 				jQuery.each( scripts, evalScript );
215 204
 			}
216  
-
217  
-			if ( cacheable ) {
218  
-				jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
219  
-			}
220 205
 		}
221 206
 
222 207
 		return this;
@@ -230,6 +215,33 @@ jQuery.fn.extend({
230 215
 	}
231 216
 });
232 217
 
  218
+function buildFragment(args, nodes, scripts){
  219
+	var fragment, cacheable, cached, cacheresults, doc;
  220
+
  221
+	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 ) {
  222
+		cacheable = true;
  223
+		cacheresults = jQuery.fragments[ args[0] ];
  224
+		if ( cacheresults ) {
  225
+			if ( cacheresults !== 1 ) {
  226
+				fragment = cacheresults;
  227
+			}
  228
+			cached = true;
  229
+		}
  230
+	}
  231
+
  232
+	if ( !fragment ) {
  233
+		doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
  234
+		fragment = doc.createDocumentFragment();
  235
+		jQuery.clean( args, doc, fragment, scripts );
  236
+	}
  237
+
  238
+	if ( cacheable ) {
  239
+		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
  240
+	}
  241
+
  242
+	return { fragment: fragment, cacheable: cacheable };
  243
+}
  244
+
233 245
 jQuery.fragments = {};
234 246
 
235 247
 jQuery.each({
@@ -284,7 +296,7 @@ jQuery.each({
284 296
 });
285 297
 
286 298
 jQuery.extend({
287  
-	clean: function( elems, context, fragment ) {
  299
+	clean: function( elems, context, fragment, scripts ) {
288 300
 		context = context || document;
289 301
 
290 302
 		// !context.createElement fails in IE with an error but returns typeof 'object'
@@ -292,16 +304,7 @@ jQuery.extend({
292 304
 			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
293 305
 		}
294 306
 
295  
-		// If a single string is passed in and it's a single tag
296  
-		// just do a createElement and skip the rest
297  
-		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
298  
-			var match = rsingleTag.exec(elems[0]);
299  
-			if ( match ) {
300  
-				return [ context.createElement( match[1] ) ];
301  
-			}
302  
-		}
303  
-
304  
-		var ret = [], scripts = [], div = context.createElement("div");
  307
+		var ret = [], div = context.createElement("div");
305 308
 
306 309
 		jQuery.each(elems, function(i, elem){
307 310
 			if ( typeof elem === "number" ) {
@@ -393,7 +396,7 @@ jQuery.extend({
393 396
 
394 397
 		if ( fragment ) {
395 398
 			for ( var i = 0; ret[i]; i++ ) {
396  
-				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
  399
+				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
397 400
 					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
398 401
 				} else {
399 402
 					if ( ret[i].nodeType === 1 ) {
@@ -402,8 +405,6 @@ jQuery.extend({
402 405
 					fragment.appendChild( ret[i] );
403 406
 				}
404 407
 			}
405  
-
406  
-			return scripts;
407 408
 		}
408 409
 
409 410
 		return ret;
2  test/unit/core.js
@@ -337,7 +337,7 @@ test("jQuery('html')", function() {
337 337
 test("jQuery('html', context)", function() {
338 338
 	expect(1);
339 339
 
340  
-	var $div = jQuery("<div/>");
  340
+	var $div = jQuery("<div/>")[0];
341 341
 	var $span = jQuery("<span/>", $div);
342 342
 	equals($span.length, 1, "Verify a span created with a div context works, #1763");
343 343
 });

0 notes on commit 9d8d745

Please sign in to comment.
Something went wrong with that request. Please try again.