Templates are the best kind of tool: simple to write and implement, but powerful enough to make your architecture slicker and your code leaner. Getting markup out of your Javascript is a huge deal, but templates can help with more than that. They can manage repeated code snippets, allow you to deftly switch states in single page applications, and help keep your code DRY when supporting users with and without Javascript enabled. Using and extending them creatively can make any architecture a little awesomer.
1. using templates to achieve
AWESOMER
architecture
Sunday, October 17, 2010
2. hi!
Garann “it’s like Karen with a G” Means
HTML, CSS, JS at Gerson Lehrman Group
Austin, TX
garann.com / garann@gmail.com / @garannm
Sunday, October 17, 2010
3. ask me how i reduced 12k
lines of js to 4k
Sunday, October 17, 2010
4. get that now
http://github.com/jquery/jquery-tmpl
Sunday, October 17, 2010
6. dom manipulation
var container = $(“div.band-info”);
container.append(“h2”);
container.find(“h2”).html(band.bandName);
$.each(band.members,function() {
var span = container.append(“span”)
.addClass(“band-member”);
span.html(this.name+“ - “+this.instrument);
});
if (band.single) {
var link = container.append(“a”)
.attr(“href”,band.single.url);
link
.text(‘Download “‘+band.single.title+‘“‘);
}
Sunday, October 17, 2010
7. hidden element “templates”
var container = $(“div.band-info”);
container.find(“h2”).html(band.bandName);
var link = container.find(“a”);
$.each(band.members,function() {
link.before(‘<span class=”band-member”>’ +
this.name + ‘ - ‘ + this.instrument + ‘</
span>’);
});
if (band.single) {
link.attr(“href”,band.single.url);
link.text(band.single.title);
} else {
link.hide();
}
ps: still dom manipulation
Sunday, October 17, 2010
8. concatenation
var html = new Array();
html.push(‘<div class=”band-info”><h2>’);
html.push(band.bandName + ‘</h2>’);
$.each(band.members,function() {
html.push(‘<span class=”band-member”>’);
html.push(this.name + ‘ - ‘);
html.push(this.instrument + ‘</span>’);
});
if (band.single) {
html.push(‘<a href=”’ + band.single.url);
html.push(‘”>Download “‘);
html.push(band.single.title + ‘”</a>’);
}
html.push(‘</div>’);
document.append(html.join(“”));
Sunday, October 17, 2010
9. what about just returning
html from an xhr?
send the same data over and over
have to dig properties out of DOM
building HTML server-side is annoying
Sunday, October 17, 2010
10. that’s not an architecture
#thatsaproblem
Sunday, October 17, 2010
11. an AWESOMER architecture:
separates the presentation from the data
abstracts views into reusable components
markup changes in one place
flexibility to treat big and small views differently
where you need it when you need it
Sunday, October 17, 2010
12. pros and cons
no templates templates
Sunday, October 17, 2010
21. properties
${bandName} is the world’s greatest band.
Everyone loves {{= bandName}}.
Sunday, October 17, 2010
22. expressions
${bandName} has ${fans.length} fans
${bandName} has ${fans.length}
fan${fans.length == 1 ? ‘’ : ‘s’}
${bandName} has ${fans.length}
${myApp.pluralize(‘fan’)}
Sunday, October 17, 2010
23. if / else
{{if fans.length}}
${bandName} has ${fans.length}
${myApp.pluralize(‘fan’)}
{{else}}
You’ve probably never heard of ${bandName}.
They’re really obscure.
{{/if}}
Sunday, October 17, 2010
24. each
{{each members}}
${$value.name} plays the ${$value.instrument}
like a GOD.
You heard me. ${this.name} practically
invented the ${this.instrument}.
{{/each}}
Sunday, October 17, 2010
27. other tags
{{! this is a comment}}
{{html thingThatShouldntBeEscaped}}
{{wrap "#otherTmpl”}}
<div class=”thing”>One</div>
<div class=”otherThing”>Two</div>
{{/wrap}}
Sunday, October 17, 2010
28. this
main template: refer to properties directly
$item, $item.data, $data
{{each}}: $value
nested template: parent’s data or whatever you
passed in
Sunday, October 17, 2010
31. $.tmpl
String immediately parsed and evaluated
Tags translated to expressions
Return a jQuery object
Sunday, October 17, 2010
32. compiling
$.template(“veryShortTmpl”,”<b>${name}</b>”);
$(“#stuff-tmpl”).template(“wickedCoolTmpl”);
Sunday, October 17, 2010
33. $.template
Parse the template but don’t populate
Template engine saves in a big ol’ list
Rendering with data like calling a function
Sunday, October 17, 2010
34. get and set
var t = $(“div.comment:last”).tmplItem();
var lastId = t.data.id;
t.tmpl = $.template(“new-tmpl”);
t.update();
Sunday, October 17, 2010
35. $.tmplItem
tmplItem has additional functions and properties
nodes, parent, html, nest, wrap
Functions remain available to object in DOM
Sunday, October 17, 2010
38. awesome
use live() for events on multiple pages
or for things that change containers
// in some function
$(“#some-tmpl”).tmpl(data).appendTo(“#thing”);
// wherever
$(“a.childOfThing”).live(“click”,function(e) {
e.preventDefault();
doMoreStuff();
});
Sunday, October 17, 2010
39. AWESOMER!
use delegate() for events on one page
or always in the same container
// in some function
$(“#some-tmpl”).tmpl(data).appendTo(“#thing”);
// wherever
$(“#thing”).delegate(
“a.childOfThing”,“click”,function(e) {
e.preventDefault();
doMoreStuff();
});
Sunday, October 17, 2010
40. when the only tool you
have is a hammer..
oh wait you have CSS
Sunday, October 17, 2010
41. awesome
$(“#some-tmpl”).tmpl(data).appendTo(“#thing”);
$(“#childOfThing”).tmplItem().tmpl =
$(“#state-two-tmpl”).template();
Sunday, October 17, 2010
42. AWESOMER!
use CSS where possible - it’s faster!
$(“#some-tmpl”).tmpl(data).appendTo(“#thing”);
$(“#childOfThing”)
.removeClass(“stateOne”)
.addClass(“stateTwo”);
Sunday, October 17, 2010
43. css is better for..
errors
small number of elements being shown/hidden
elements with plugins attached
input areas that may have unsubmitted user data
Sunday, October 17, 2010
45. faster-ish templates
break up the family
separate pattern templates from interface templates
Always Be Compiling
templates = functions
Sunday, October 17, 2010
48. polling for new data
window.setTimeout(checkForStuff, 30000);
function checkForStuff() {
$.get(“/moreStuff”,function(items) {
if (items.length) {
var d = {l: items.length, d: items };
$(“#load-new-btn-tmpl”).tmpl(d)
.prependTo(myApp.container);
}
window.setTimeout(checkForStuff, 30000);
});
}
$(“#loadNewBtn”).live(“click”,function(e) {
$(this).tmplItem().tmpl =
$.template(“new-tmpl”);
});
Sunday, October 17, 2010
59. external files
if ($.template("commentTmpl").length) {
updateComment(comment);
} else {
$.get("comment-tmpl.js", function(response) {
$.template("commentTmpl",response);
updateComment(comment);
});
}
function updateComment(comment) {
// rendering happens here
}
hint: ftw
Sunday, October 17, 2010
60. use external files if you enjoy:
Having your templates cached
Only loading code once it’s needed
Better code organization
Using your client-side templates for server-side
rendering
Sunday, October 17, 2010
61. little external templates
put lots of little strings in one file
like a constants file
e.g. internationalization
small patterns available everywhere
Sunday, October 17, 2010
67. takes a little doing
have to write a backend parser
may limit native functions like length()
unless your backend is JS
custom functions pretty much out
unless your backend is JS
even truthy and falsey may be a problem DEMO NAO PLZ
now you’re just showing off.
Sunday, October 17, 2010
73. check out:
jQuery templates: github.com/jquery/jquery-tmpl/
documentation: http://api.jquery.com/
(scroll to the very bottom)
jQuery templates for node.js:
github.com/kof/node-jqtpl
jQuery templates for .NET:
github.com/awhatley/jquery-tmpl.net
photo credit: http://www.flickr.com/photos/ennuiislife/
Sunday, October 17, 2010
74. i appreciate ya!
keep in touch: @garannm / garann@gmail.com
demo code: github.com/garann/templates-example
Sunday, October 17, 2010