Tuesday, September 21, 2010

More DRY with fab.js v0.5

‹prev | My Chain | next›

Up tonight I try to put my new fab.accept—an app written for the upcoming v0.5 release of fab.js—to some good use. Currently in my (fab) game, I have a player /status route that looks like:
 ( route, /^\/status/ )
( accept.HTML )
( PRE )
( player_status )
()
()
( accept.PLAIN )
(undefined, {headers: { "Content-Type": "text/plain"}})
( player_status )
()
()
Depending on the requested content type, the status of the players in the game are served up as HTML or plain text. The problem is that the HTML being served up is very small. Ideally I would like to serve it up as part of the same HTML template that the main player board is using:
  (route, /^\/board/)
( HTML )
( HEAD )
( TITLE )( "My (fab) Game" )()
( LINK, { href: "/stylesheets/board.css",
media: "screen",
rel: "stylesheet",
type: "text/css" } )
// Lots more style and script
( BODY )
// The actual body of the request
But how to re-use that? Back when I was first messing about with DRYing up my HTML, I found that I could have two different routes inside the same template (a rather unique fab.js feature):
  ( HTML )
( HEAD )
( TITLE )( "My (fab) Game" )()
( LINK, { href: "/stylesheets/board.css",
media: "screen",
rel: "stylesheet",
type: "text/css" } )
// Lots more style and script
()
( BODY )

(route, /^\/board/)
// the game board HTML

()

(route, /^\/status/)
( PRE )
( player_status )
()
()
I can no longer make use of that because the plain text response cannot include the HTML + HEAD + BODY tags that wrap both routes. Instead, I need to re-use the HTML, but only when the /status resource is requesting HTML. It turns out the upcoming version version of fab.js makes this easy by squirreling away partials in a local variable:
with ( fab )
with ( html ) head =

( fab )
( HEAD )
( TITLE )( "My (fab) Game" )()
( LINK, { href: "/stylesheets/board.css",
media: "screen",
rel: "stylesheet",
type: "text/css" } )
// Lots more style and script
()
();
I can then use that partial in both the /board route:
  (route, /^\/board/)
( HTML )
( head )
( BODY )
( FORM, { id: "login", method: "get" } )
( LABEL )
( "Name" )
( INPUT, { type: "text", name: "player" } )
()
( INPUT, { type: "submit", value: "Play" } )
()
( DIV, { id: "room-container" } )()
() // BODY

() // HTML
()
...and in the player /status route (body only when the client accepts HTML):
  ( route, /^\/status/ )
( accept.HTML )
( HTML )
( head )
( BODY )
( PRE )
( player_status )
()
()
()
()
( accept.PLAIN )
(undefined, {headers: { "Content-Type": "text/plain"}})
( player_status )
()
( "not found", { status: 404 } )
()
That is a surprisingly effective way to get simple partial support. Once again, I am left thinking that there may just be something to this upcoming version of fabjs.


Day #233

No comments:

Post a Comment