#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: | ||
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>
Change History (8)
comment:1 Changed 13 years ago by
Owner: | set to simeyla |
---|---|
Status: | new → pending |
comment:2 Changed 13 years ago by
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
comment:3 Changed 13 years ago by
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.
comment:4 Changed 13 years ago by
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:5 Changed 13 years ago by
Status: | new → pending |
---|
comment:6 Changed 13 years ago by
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
comment:7 Changed 13 years ago by
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>
.
comment:8 Changed 13 years ago by
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!