Bug Tracker

Ticket #7601 (closed bug: invalid)

Opened 4 years ago

Last modified 4 years ago

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:1 Changed 4 years ago by rwaldron

  • Owner set to simeyla
  • Status changed from new to pending

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!

comment:2 Changed 4 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

Last edited 4 years ago by simeyla (previous) (diff)

comment:3 Changed 4 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.

 http://jsfiddle.net/rwaldron/xYtTq/1/

comment:4 Changed 4 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:5 Changed 4 years ago by jitter

  • Status changed from new to pending

comment:6 Changed 4 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

comment:7 Changed 4 years ago by snover

  • Status changed from new to closed
  • Resolution set to invalid

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 4 years ago by anonymous

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

Note: See TracTickets for help on using tickets.