I have this JS code which adds some HTML inside a tbody:
thestring='<tr><td><input type="text" name="entry-'+s+'-api" value="'+getItem('entry-'+s+'-api')+' /></td><td><input type="text" name="entry-'+s+'-talk" value="'+getItem('entry-'+s+'-talk')+' /></td><td><input type="text" name="entry-'+s+'-url" value="'+getItem('entry-'+s+'-url')+' /></td></tr>';
document.getElementById('table').innerHTML+=thestring;
Bit long line, I know…
So when I run it, thestring is evaluated, correctly, to this:
<input type="text" name="entry-0-api" value="http%3A%2F%2Flego.wikia.com%2Fapi.php /><<input type="text" name="entry-0-talk" value="User_talk%3AUltrasonicNXT /><input type="text" name="entry-0-url" value="http%3A%2F%2Flego.wikia.com%2Fwiki%2FUser_talk%3AUltrasonicNXT />
However, this is the content that gets added:
<tr><td></td></tr>
So where did the rest go?
This is the relevent HTML:
<form action="change.js" method="GET">
<table>
<tbody id="table">
</tbody>
</table>
</form>
Incorrect markup. No closing quote on attribute value. Chrome is doing its best to clean up the mistake.
But, in any case, you shouldn’t be building markup strings this way. If there are any HTML-special characters in the
getItemvalue, then they’ll be able to leak into markup. If any of that content comes from an untrusted third-party, this HTML injection is not only a bug but a security hole.Never do this. This converts the entire current DOM of the table into HTML markup, adds to that string, and parses it all back in into new objects, replacing the old ones. This is slow and loses any information that doesn’t serialise to HTML (such as event handlers or form field values).
It is much more reliable to alter the document’s live DOM nodes directly than to mess about with HTML markup. This fixes both problems. eg.: