I too prefer a JSON response with client-side HTML creation logic.
Unfortunately, most real-world client-side HTML writing scripts are broken, containing many HTML-injection flaws that can easily become cross-site-scripting security holes. I think the belief is that because you re talking to your own server rather than directly to a hostile user you re somehow ‘safe’ and can get away without correctly strings when interpolating them into HTML. Which is of course nonsense.
I always see stuff like:
$( #mydiv ).append( <em>Deleted +response.title+ !</em> );
or:
mydiv.innerHTML= <p>Renamed to +response.name+ </p>;
or indeed Resig s microtemplating hack, where there is no HTML-escaping done by default. Come on, people! We ve only just started cleaning up the legacy of broken PHP scripts serving up server-side XSS, now you want to introduce a whole new massive range of client-side XSS exploits?
Sigh. That s the Lure Of Strings. We think we understand them and can sling them together willy-nilly. But strings are treacherous, with hidden contexts and escaping requirements. If you must generate HTML on the client side you will need a function like this:
function h(s) {
return s.split( & ).join( & ).split( < ).join( < ).split( " ).join( " );
}
mydiv.innerHTML= <p>Renamed to +h(response.name)+ </p>;
But personally I prefer DOM methods. Like with parameterisation for SQL, using the DOM methods takes the string-slinging out of the equation by talking raw strings directly to the components that will consume them. OK, the problem with the DOM is that it s rather verbose:
var p= document.createElement( p );
p.appendChild(document.createTextNode( Renamed to +response.name))
mydiv.appendChild(p);
But you can always define helper functions to cut down on that, eg.:
mydiv.appendChild(makeElement( p , {}, Renamed to +response.name));
(The new element creation stuff in jQuery 1.4 uses a similar style.)