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.)