Ticket #7601 (closed bug: invalid)
jQuery breaks DOM when setting html() string beginning with a newline
| Reported by: | simeyla | Owned by: | simeyla |
|---|---|---|---|
| Priority: | undecided | Milestone: | 1.5 |
| Component: | manipulation | Version: | 1.4.4 |
| Keywords: | Cc: | ||
| Blocking: | Blocked by: |
Description
I have an AJAX call that returns HTML beginning with a newline. I am using ASP.NET and this is not unusual because of the standard ASMX and ASPX templates.
In Internet Explorer when running the following code:
$("#placeholder").html("\n<p><form class='payment-form'><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></form></p>");
the DOM breaks such that:
$("#placeholder form").serialize()
returns 'field1=111' instead of the expected value 'field1=111&field2=222'.
This is because the FORM tag gets nested incorrectly - as can be seen in the resultant DOM after the call to jQuery.html().
" <P> <FORM id=form1><INPUT name=field1 value=111></P></FORM> <DIV class=foo></DIV><INPUT name=field2 value=222> <P></P>"
I can ONLY duplicate the problem with this exact HTML (FORM nested within P and DIV separating two INPUT fields). Using innerHTML directly doesn't cause this problem - nor do other browsers. Nesting the P tag within the FORM fixes the problem.
Here is a full sample of 4 tests. Only 1 fails (as described above).
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script>
$(function() {
// the following two blocks of HTML are identical except the P tag is outside the form in the first case
var html1 = "<p><form id='form1'><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></form></p>";
var html2 = "<form id='form1'><p><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></p></form>";
// <FORM> tag nested within <P>
RunTest("<FORM> tag nested within <P> tag", html1); // succeeds in Internet Explorer
RunTest("<FORM> tag nested within <P> tag with leading newline", "\n" + html1); // fails with added new line in Internet Explorer
// <P> tag nested within <HTML>
RunTest("<P> tag nested within <FORM> tag", html2); // succeeds in Internet Explorer
RunTest("<P> tag nested within <FORM> tag with leading newline", "\n" + html2); // succeeds in Internet Explorer even with \n
});
function RunTest(testName, html) {
// run with jQuery
$("#placeholder").html(html);
var jqueryDOM = $('#placeholder').html();
var jqueryFormSerialize = $("#placeholder form").serialize();
// run with innerHTML
$("#placeholder")[0].innerHTML = html;
var innerHTMLDOM = $('#placeholder').html();
var innerHTMLFormSerialize = $("#placeholder form").serialize();
var expectedSerializedValue = "field1=111&field2=222";
alert( 'TEST NAME: ' + testName + '\n\n' +
'The HTML :\n"' + html + '"\n\n' +
'looks like this in the DOM when assigned with jQuery.html() :\n"' + jqueryDOM + '"\n\n' +
'and looks like this in the DOM when assigned with innerHTML :\n"' + innerHTMLDOM + '"\n\n' +
'We expect the form to serialize with jQuery.serialize() to be "' + expectedSerializedValue + '"\n\n' +
'When using jQuery to initially set the DOM the serialized value is :\n"' + jqueryFormSerialize + '\n' +
'When using innerHTML to initially set the DOM the serialized value is :\n"' + innerHTMLFormSerialize + '\n\n' +
'jQuery test : ' + (jqueryFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED") + '\n' +
'InnerHTML test : ' + (innerHTMLFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED")
);
}
</script>
</head>
<div id="placeholder">
This is #placeholder
</p>
</html>
Change History
comment:2 Changed 3 years ago by simeyla
- Status changed from pending to new
Sample code: http://jsfiddle.net/B3EgD/
This link will show SUCCEEDED, FAILED, SUCCEEDED, SUCCEEDED for IE7 This link will show SUCCEEDED, SUCCEEDED, SUCCEEDED, SUCCEEDED for Chrome + FF
Confirmed bug exists on jQuery 0 GIT
comment:3 Changed 3 years ago by rwaldron
- Component changed from unfiled to manipulation
So... that was a bit much.
Anyway, I'm not convinced this is a jQuery bug - in fact I think it's just a bad mix of markup. When you remove "<div class='foo' />" it works fine.
comment:4 Changed 3 years ago by jitter
I too think this is result of invalid html.
- <p><form>...</form></p> isn't valid XHTML
- the action attribute on the form tag is missing
- <div class='foo' /> is invalid
- input tags aren't allowed this way directly inside a form without being wrapped in e.g. p, div, ...
If you can provide a test case with valid html which still breaks by adding a \n to the start of the html we can look into this issue further.
comment:6 Changed 3 years ago by simeyla
- Status changed from pending to new
@rwaldron @jitter - thanks so much for the prompt help.
it turns out that <p><form> ... </form></p> is indeed invalid XHTML
i had never realized that <P> can only contain Inline Elements + Text
I'm still still slightly scared about the difference in behavior with a leading newline - especially considering how common it is for AJAX responses to be bad XHTML - but see now what was going on - and that it wasn't arbitrary
thanks again
Please follow the bug reporting guidlines and use jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

Thanks for taking the time to contribute to the jQuery project! Please provide a reduced jsFiddle test case to help us assess your ticket!
Additionally, test against the jQuery 0 GIT version to ensure the issue still exists. Be Excellent to eachother!