Friday, December 23, 2011

Using hogan.js with express on node.js

Thought i'd try getting twitter's hogan.js up and running with express... not as straight forward as i expected. Drawing upon this article on using mustache.js with express.js i created a simple adapter to help bridge functionality.

I would only use this while connect 3.x is in dev. After that i'd use TJ's consolidate.js cause i'm no TJ.

If you're looking for a full, working example, be sure to checkout a Nodestrap-- a repo i use as a project "prototype." It comes out of the box with better than average architecture, hogan-express templating, bootstrap 1.x. Its a good jumping off point.

Here's the adapter:

var HoganExpressAdapter=(function(){
var init=function(hogan) {
var compile=function(source){
return function(options) {
return hogan.compile(source).render(options);
};
}
return {compile:compile};
};
return {init:init};
}());
if(typeof module!== 'undefined' && module.exports){
module.exports=HoganExpressAdapter;
} else if (typeof exports!=='undefined') {
exports.HoganExpressAdapter=HoganExpressAdapter;
}

Here's an example of it in use:

var express=require('express'),
hogan=require('hogan.js'),
adapter=require('./hogan-express.js'),
app = express.createServer();
app.configure(function(){
app.use(express.static(__dirname + '/public'));
app.use(express.logger());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(app.router);
app.use(express.errorHandler({dumpExceptions:true,showStack:true}));
app.set('view engine','hogan.js');
app.set('view options',{layout:false});
app.set('views',__dirname+ '/views');
app.register('hogan.js',adapter.init(hogan));
});
app.get("/",function(req,res,next) {
res.render("index",{name:"micah"});
});
app.listen(8080);

In the views directory i have a index.hogan.js file-- that's the template.

It's worked for simple uses so far. I'll update if needs be.

HTML5 Videos via ffmpeg

Script for making html5 videos in ubuntu linux. I used these directions to get ffmpeg set up correctly.

Run like . html5-vid.sh myfile.avi

#!/bin/bash
# html5 videos maker
ffmpeg -i $1 -b 1500k -vcodec libx264 -g 30 -s 640x360 $1.mp4
ffmpeg -i $1 -b 1500k -vcodec libvpx -acodec libvorbis -ab 55000 -f webm -g 30 -s 640x360 $1.webm
ffmpeg -i $1 -b 1500k -vcodec libtheora -acodec libvorbis -ab 55000 -g 30 -s 640x360 $1.ogv
view raw html5-vid.sh hosted with ❤ by GitHub

Thursday, December 15, 2011

A Very Quick Look at d3.js

I finally got a chance to dig into d3.js today. From what i can tell, d3.js is an amazing dom/svg animation framework. To be honest, i have no idea how to describe it. There very well is much, much more under the hood than i'm aware of.

The jQuery-like Parts

d3.js is a lot like jQuery insofar as many of the operations are based upon items selected with CSS-selector style syntax. For example, d3.selectAll('div') probably looks fairly intuitive to anyone who has written jQuery before-- it grabs all divs on the page.

Another jQuery-esque thing about d3.js is that its API is chainable, so the following code:

//grab all divs on the page
//and set their width to 300
d3.selectAll('div')
.attr("width",300)
.attr("height",400);
view raw gistfile1.txt hosted with ❤ by GitHub

obviously sets the width of all divs to 300, height to 400

d3.selectAll('div').on('click',function(){alert('hi!');});-- i bet you can already tell how events in d3.js work--exactly like (post 1.7) jQuery.

d3.js data()

One of the things that makes d3.js initially difficult to understand is the .data() function. Here's a code snippet that does a little explaining.

//select all divs
d3.selectAll('div')
//map some data to those divs, in order that they were found in the DOM
.data(["hello","world","hi"])
//and now do something to the divs with that data
//perhaps, put the data in the divs
//so this function param "d" is actually the data for that div
.html(function(d) {
return d;
});
view raw gistfile1.txt hosted with ❤ by GitHub

So the above script maps (hmmmm...) the data to the items it gets passed in order. So "hello" would be the innerHtml of the first div, "world" would be the content of the second... makes sense. The data that you pass in can be strings, numbers, object literals, anything. (Hmmm I wonder what you could do with functions...?)

What if you had 2 divs on the page, and the data() array had 3 items in it? How would it map that? Well, it would map the first 2 to the first 2 divs, neglecting the other piece of data. There is a way to work with that extra piece of data though--.enter().

d3.js enter()

.enter() allows you to do something with left over data. Here's an example:

//so there's two divs on the page for this to select
d3.select('body')
.selectAll('div')
.data(["hello","there","world"])
//this will map "hello" and "there" to the only two divs
.html(function(d){return d;})
//but theres 3 pieces of data...?
//this is why d3 has the enter() function
//think of it as "withTheLeftOverDataAfterMapping()" instead of "enter()"
.enter()
//so now we can do something with the leftover data,
//how about create another div?
.append('div')
.html(function(d){return d;});
view raw d3-js-enter.js hosted with ❤ by GitHub

So we were able to add extra divs on with .enter() in order to represent all the data that we passed into it.

Full Bleed d3.js example

Example: Animating SVG Circles on Mouseover

The really interesting stuff i see with d3.js involves the transition() function and SVG, which is supported in Chrome, Firefox, IE9, iOs, and Android(Honeycomb). Here's a script i wrote that draws circles in the DOM which move as soon as you hover over them.