Best practice for inserting large chunks of HTML into elements with Javascript? Best practice for inserting large chunks of HTML into elements with Javascript? ajax ajax

Best practice for inserting large chunks of HTML into elements with Javascript?


is it the best practice?

No. In fact you've got HTML-injection problems leading to bugs, and in the worst case where the injected strings may contain user-submitted content, XSS security holes.

When you put plain text content and attribute values into an HTML string, you must HTML-encode them. In PHP, you have to call htmlspecialchars() on strings going into HTML to do it. In JavaScript, you don't get a built-in HTML-escaping function, so you have to make your own, eg. by using s.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"') on the string going into the HTML.

onclick="someFunc(\'{STRING}\');"

That's a whole new level of escaping mess. In a JavaScript string literal inside an event handler attribute, you would have to JS-encode the string (\-escaping ' and \ plus a few Unicode characters for completeness) and then HTML-encode the results. Otherwise the string can break out of its string-literal delimiter and inject arbitrary JS code. Avoid inline event handler attributes in all cases, but especially in templating.

Creating page content with HTML strings sucks. You are very likely to make escaping errors and compromise the security of your application. Use DOM-like methods instead and you don't have to worry about this. You seem to be using jQuery, so try the jQuery 1.4 element creation shortcuts:

$('<tr>').append(    $('<td>').append(        $('<a>', {            href: o.link,            text: o.word,            onclick: function() {                someFunc(o.string);            }        })    ));

or, keep your blank row actually inside the document as HTML, but then hide it (display: none) or detach it from the document at start time (removeChild or jQuery detach). Then when you want a new row, clone the blank row and make the changes you need:

var blankRow= $('#blankRow').detach();    ...var newRow= blankRow.clone();var link= newRow.find('td>a');link.attr('href': o.link);link.text(o.word);link.click(function() {    someFunc(o.string);});

If you must create content from string templates, ensure your templating function HTML-escapes every replacement by default, and attach events by selecting nodes inside the parsed content to call click(function() { ... }) on. Or use event delegation (eg. jQuery live()) to handle events without having to bind to new nodes when added.


You do it using a good way, and that's pretty fast considering other manners.

An alternate, supposely clean solution is to build in javascript the DOM elements you are to use, by calling several

document.createElement(tagName);

But your code will rapidly grow, in my thought, for nothing.

Another one, my favorite way to achieve DOM creation, is to place inside the HTML body the code you want to copy, give it a className and / or an id like "template" which will additionally ( using css ) hide it, and then process it as needed on event by getting the element back, cloning it, and setting property you want before appending where it belongs


If I understand you well, your question is about initializing large strings the way you'll do that in PHP (or Perl for that matter)? For long (multiline) string I use:

var blankRow = [     'a line',     'another line',     'still more lines',     'lines lines lines',     '... etc'    ].join('')

You can also use a backslash for continuation, but that can get kind of messy:

var blankRow = 'a line\another line\still more lines\lines lines lines\... etc';

EDIT based on comment: I'm lazy too! So I use this for escaping:

function qs(str){    str = str || this || '';    return "'"+str+"'";}function qd(str){    str = str || this || '';    return '"'+str+'"';}String.prototype.qs = qs;String.prototype.qd = qd;// applied:var blankRow = [         'a line',         'another '+qd('line'),         'still more lines',         'lines '+'lines'.qs()+ ' lines',         '... etc'        ].join('');

Problem with being lazy: it's pretty hard work to persist ones lazyness