Side navigation
#7601 closed bug (invalid)
Opened November 22, 2010 10:56PM UTC
Closed November 23, 2010 06:18AM UTC
Last modified November 24, 2010 02:06AM UTC
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: | ||
| Blocked by: | Blocking: |
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>
Attachments (0)
Change History (8)
Changed November 22, 2010 11:02PM UTC by comment:1
| owner: | → simeyla |
|---|---|
| status: | new → pending |
Changed November 22, 2010 11:12PM UTC by comment:2
| _comment0: | Sample code: http://jsfiddle.net/B3EgD/ → 1290468340864970 |
|---|---|
| status: | pending → 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
Changed November 22, 2010 11:39PM UTC by comment:3
| component: | unfiled → 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.
Changed November 22, 2010 11:50PM UTC by comment:4
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.
Changed November 22, 2010 11:51PM UTC by comment:5
| status: | new → pending |
|---|
Changed November 23, 2010 01:19AM UTC by comment:6
| status: | pending → 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
Changed November 23, 2010 06:18AM UTC by comment:7
| resolution: | → invalid |
|---|---|
| status: | new → closed |
The principal issue here was the self-closing <div> tag. You can usually get away with invalidly nesting things, but you can never self-close a <div>.
Changed November 24, 2010 02:06AM UTC by comment:8
actually the problem was nesting <form> within <p>
but only when it contained <input/><div></div><input/>
changing <div> to <div></div> still exhibited the problem
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!