Tuesday, September 14, 2010

DRY HTML in Fab.js v0.5

‹prev | My Chain | next›

While rooting through the sample apps in the upcoming v0.5 release of fab.js, I noticed an interesting feature. It seems as though it is possible to re-use the new HTML (fab) apps by embedding routes inside of them. For instance, I can re-use the HTML head for multiple routes in my (fab) game:
with ( fab )
with ( html )

( fab )

// Listen on the FAB port and establish the faye server
( listen, 0xFAB, attach_faye )

( HTML )
( HEAD )
( TITLE )( "My (fab) Game" )()
( LINK, { href: "/stylesheets/board.css",
media: "screen",
rel: "stylesheet",
type: "text/css" } )
( SCRIPT, { src: "/javascript/jquery-min.js",
type: "application/javascript" } )()

// More javascript libs///

( SCRIPT, { type: "application/javascript" } )
( board_js_string )
()

()
( BODY )

(route, /^\/board/)

( FORM, { id: "login", method: "get" } )
( LABEL )
( "Name" )
( INPUT, { type: "text", name: "player" } )
()
( INPUT, { type: "submit", value: "Play" } )
()
( DIV, { id: "room-container" } )()
()

(route, /^\/player_status/)
( PRE )
( "player_status 01" )
( "\n" )
( "player_status 02" )
( "\n" )
( "player_status 03" )
( "\n" )
()
()

() // BODY
() // HTML
Checking out the second resource, /player_status, in the browser:



Nice! I get my header, "My (fab) Game", and my styles, but everything else comes from under the (route, /^\/player_status/) resource.

It is not all sunshine and roses, however. Ideally, I would like to embed my player_status (fab) app inside that resource:
      (route, /^\/player_status/)
( PRE )
( player_status )
()
// ...

function player_status(write) {
return write(function(write) {
return fab.stream(function(stream) {
// stream(write(undefined, { headers: { "Content-Type": "text/plain"} }));
players.all(function(list) {
list.forEach(function(player) {
stream(write(player._id + "\n"));
});
stream(write("\n"));
stream(write());
});
});
});
}
The player_status function was originally written as a standalone app. Now that it is embedded in HTML, I have to remove the "Content-Type" header stream write. Even with that, when I access the list of players, I get:



The player, "bob" shows up in the status section, but "fred" and "foo" are outside. Checking out the HTML, I find:
<pre>bob
</pre></body></html>foo
</pre></body></html>fred
</pre></body></html>
</pre></body></html>
Ew.

I have already seen that streaming text ("player_status 01", "player_status 02", etc.) works when re-using HTML (fab) apps. Is the problem with fab.stream, my use of fab.stream, or with dynamic functions? If it is either of the first two, I will have to defer investigation until another night, but I can convert the player_status (fab) app to a simple, dynamic app:
function player_status( write ) {
return function read( data ) {
return write("player_status 01")
("\n")
("player_status 02")
("\n")
("player_status 03")
("\n");
};
}
That produces the same results as my original, simple app—in other words, it works. Thus the problem is either in fab.stream or my use of fab.stream in player_status:
function player_status(write) {
return write(function(write) {
return fab.stream(function(stream) {
players.all(function(list) {
list.forEach(function(player) {
stream(write(player._id + "\n"));
});
stream(write("\n"));
stream(write());
});
});
});
}
I will pick up tomorrow with further investigation.


Day #226

No comments:

Post a Comment