Skip to content

Commit e2497c6

Browse files
committedJun 21, 2012
Add parseHTML for explicitly parsing strings into html. Fixes #11617.
1 parent 7ff3da1 commit e2497c6

File tree

2 files changed

+60
-17
lines changed

2 files changed

+60
-17
lines changed
 

‎src/core.js

+31-17
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ jQuery.fn = jQuery.prototype = {
104104

105105
// Handle HTML strings
106106
if ( typeof selector === "string" ) {
107-
// Are we dealing with HTML string or an ID?
108107
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
109108
// Assume that strings that start and end with <> are HTML and skip the regex check
110109
match = [ null, selector, null ];
@@ -118,19 +117,10 @@ jQuery.fn = jQuery.prototype = {
118117
context = context instanceof jQuery ? context[0] : context;
119118
doc = ( context && context.nodeType ? context.ownerDocument || context : document );
120119

121-
// If a single string is passed in and it's a single tag
122-
// just do a createElement and skip the rest
123-
ret = rsingleTag.exec( selector );
124-
125-
if ( ret ) {
126-
selector = [ doc.createElement( ret[1] ) ];
127-
if ( jQuery.isPlainObject( context ) ) {
128-
this.attr.call( selector, context, true );
129-
}
130-
131-
} else {
132-
ret = jQuery.buildFragment( [ match[1] ], doc );
133-
selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
120+
// scripts is true for back-compat
121+
selector = jQuery.parseHTML( match[1], doc, true );
122+
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
123+
this.attr.call( selector, context, true );
134124
}
135125

136126
return jQuery.merge( this, selector );
@@ -459,8 +449,32 @@ jQuery.extend({
459449
throw new Error( msg );
460450
},
461451

452+
// data: string of html
453+
// context (optional): If specified, the fragment will be created in this context, defaults to document
454+
// scripts (optional): If true, will include scripts passed in the html string
455+
parseHTML: function( data, context, scripts ) {
456+
var parsed;
457+
if ( !data || typeof data !== "string" ) {
458+
return null;
459+
}
460+
if ( typeof context === "boolean" ) {
461+
scripts = context;
462+
context = 0;
463+
}
464+
context = context || document;
465+
466+
// Single tag
467+
if ( (parsed = rsingleTag.exec( data )) ) {
468+
return [ context.createElement( parsed[1] ) ];
469+
}
470+
471+
parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
472+
return jQuery.merge( [],
473+
(parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
474+
},
475+
462476
parseJSON: function( data ) {
463-
if ( typeof data !== "string" || !data ) {
477+
if ( !data || typeof data !== "string") {
464478
return null;
465479
}
466480

@@ -486,10 +500,10 @@ jQuery.extend({
486500

487501
// Cross-browser xml parsing
488502
parseXML: function( data ) {
489-
if ( typeof data !== "string" || !data ) {
503+
var xml, tmp;
504+
if ( !data || typeof data !== "string" ) {
490505
return null;
491506
}
492-
var xml, tmp;
493507
try {
494508
if ( window.DOMParser ) { // Standard
495509
tmp = new DOMParser();

‎test/unit/core.js

+29
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,35 @@ test("jQuery.proxy", function(){
11201120
jQuery.proxy( test4, "meth" )( "boom" );
11211121
});
11221122

1123+
test("jQuery.parseHTML", function() {
1124+
expect( 11 );
1125+
1126+
equal( jQuery.parseHTML(), null, "Nothing in, null out." );
1127+
equal( jQuery.parseHTML( null ), null, "Nothing in, null out." );
1128+
equal( jQuery.parseHTML( "" ), null, "Nothing in, null out." );
1129+
raises(function() {
1130+
jQuery.parseHTML( "<div>", document.getElementById("form") );
1131+
}, "Passing an element as the context raises an exception (context should be a document)");
1132+
1133+
var elems = jQuery.parseHTML( jQuery("body").html() );
1134+
ok( elems.length > 10, "Parse a large html string" );
1135+
equal( jQuery.type( elems ), "array", "parseHTML returns an array rather than a nodelist" );
1136+
1137+
var script = "<script>undefined()</script>";
1138+
equal( jQuery.parseHTML( script ).length, 0, "Passing a script is not allowed by default" );
1139+
raises(function() {
1140+
jQuery(jQuery.parseHTML( script, true )).appendTo("#qunit-fixture");
1141+
}, "Passing a script is allowed if allowScripts is true");
1142+
1143+
var html = script + "<div></div>";
1144+
equal( jQuery.parseHTML( html )[0].nodeName.toLowerCase(), "div", "Ignore scripts by default" );
1145+
raises(function() {
1146+
jQuery(jQuery.parseHTML( html, true )).appendTo("#qunit-fixture");
1147+
}, "Passing a script is allowed if allowScripts is true");
1148+
1149+
equal( jQuery.parseHTML("text")[0].nodeType, 3, "Parsing text returns a text node" );
1150+
});
1151+
11231152
test("jQuery.parseJSON", function(){
11241153
expect(8);
11251154

0 commit comments

Comments
 (0)