I Prefer Jim Developer James Schubert shares his code and his thoughts.

17Mar/13Off

Why I don’t recommend the Step module [node.js, npm]

I prefer asyc to step. The async module has a cleaner interface, more options, and utilities. It's a little beefier in size, but those things are beside the point.

Here's why I don't really like step. Tell me what you'd expect from this function:

var Step = require('step');

Step(
	function first(){
		console.log('first');
		
		this();
	},
	
	function second(){
		var x;
		console.log('second');
		if(!x){
			// do something that should set x
		}
		return x;
	},
	
	function third(){
		console.log('third');
	}
)

Did you guess:

$ node step-example.js 
first
second

If you're not familiar with Step, you'll probably look at that first function and wonder what this(); actually does. Well, it is actually shorthand for next(); (I'm simplifying a little here).

Assuming you're at least somewhat familiar with asynchronous control flow, you could assume this(); calls the next function. But, what about the second function? It's returning a value. Does that return from second, or from Step, or from some other function? It returns from second(), but... it passes the value to third. Or, it should. Unless x is undefined, in which case it will be considered an unchained function. Now, I don't think your variables should regularly be 'undefined' at the point of return, but what if you use or someone on your team uses the popular convention of calling a callback as return callback(x);. If the Step module's convention of tweaking this semantics is ignored, another developer may look at it as a typo, "You can't call the context like that..." Right? Also, what if someone doesn't understand the return value can't be undefined and comments out the middle of that function? You may have cleanup logic that isn't getting checked in third().
We've all seen that happen before.

In the above example, if x was not undefined, it would be passed as a parameter to third().

It's this inconsistency which makes me feel like Step is an accident waiting to happen in a regular development team. The source code is pretty well written and concise. I think the author has done a great job, but the usage is unintuitive and I wouldn't recommend using the module.

On the other hand, async is beautifully intuitive.

Consider this example:

var async = require('async');

async.series([
	function first(done){
		console.log('first');
		done(null, 'first');
	},
	function second(done){
		var x;
		console.log('second');
		if(!x){
			// do something that should set x
		}
		done(null, x);
	},
	function third(done){
		console.log('third');
		
		done(null, 'third');
	}
], function(err, results){
	console.log(results);
})

async.series allows us to run a series of tasks (functions defined within the array), which pass a value to the callback (that last function you see).

If you forget to pass a value, the results will contain undefined at the index of the array. Your third function won't be skipped unless you forget to invoke the callback. To me, this is a pretty obvious error and one that is easy to spot and correct. Here's is the output of the above call:

first
second
first
third
[ 'first', undefined, 'third' ]

To be fair, the example of Step acts more like a waterfall function. Here's what that would look like in async.

async.waterfall([
	function first(done){
		console.log('first');
		done(null, 'first');
	},
	function second(val, done){
		var x;
		console.log('second has val: %j', val);
		if(!x){
			// do something that should set x
		}
		done(null, x);
	},
	function(val, done){
		console.log('third has val: %j', val);
		
		done(null, 'third');
	}
], function(err, val){
	console.log('callback has val: %j', val)
});

The above code is available on github: https://github.com/jimschubert/blogs

flattr this!

2Mar/13Off

CommonJS Modules, node’s require() and private members

CommonJS Modules, node's require() and private members

Interestingly, node.js module documentation doesn't even mention CommonJS or the specification proposal it implements. I won't go over CommonJS Modules 1.0 in-depth in this post, but I suggest you read both of these links if you plan to explore node.js development.

An important take-away from this blog post (so important that I state it first) is that node.js caches modules. A module's exports are nothing more than an object. When you set a function or property to be exported, you're setting it on an object.

Conceptually, this:

var someFunction = function(){ /* implement */ };
module.exports.someFunction = exports.someFunction = someFunction;

...is the same as doing this outside of CommonJS modules...

var someFunction = function(){ /* implement */ };
var exports = {};
exports.someFunction = someFuntion;

I know, that seems like it should be common sense. When node.js caches the exports object at the application level, I think understanding this can become hairy -- especially if you come from a compiled language background.

For example, consider the following module.

var count = 0;

var doSomethingShared = function(){
	count += 1;
	console.log("Shared call count: %d", count);
};

var doSomethingNotShared = function(){
	console.log("Other modules don't know about me!");
};

module.exports.shared = exports.shared =  doSomethingShared;
module.exports.unshared = exports.unshared =  doSomethingNotShared;

We can require this module easily and play around with it in node REPL:

$ node
> var example = require('./example.js');
undefined
> example.shared()
Shared call count: 1
undefined
> example.shared()
Shared call count: 2
undefined
> example.shared()
Shared call count: 3
undefined
> example.shared()
Shared call count: 4
undefined
> example.unshared()
Other modules don't know about me!
undefined

In the same REPL instance, you can re-require the module and see that 'count' is indeed shared:

> var example2 = require('./example.js');
undefined
> example2.shared()
Shared call count: 5
undefined
> example2.shared()
Shared call count: 6
undefined

You can even require the shared function directly:

> var shared = require('./example.js').shared;
undefined
> shared()
Shared call count: 7
undefined
> shared()
Shared call count: 8
undefined

I think you get the point; private variables which aren't exported are shared. In this example, 'count' is a private static property of the module.

Why this matters

This is very important, because when working in the asynchronous environment of node.js you have to be aware about *what* is being cached privately at the module level. In addition to this, if you plan to cache functions for whatever reason, you have to be incredibly sure you know what you're doing. I recommend to NEVER CACHE CALLBACK FUNCTIONS.

As an example of this statement, I've created a sample file processor script in the github repo as fs-example.js. That script reads this blog's directory in the repo, then loops over the files and executes 'processor', which is a custom broken module displaying the above problem. fs-example.js does an inline require, which as you've seen above doesn't make a difference.

The problem I'll display here exists because async calls are likely to take different lengths of time to execute. My example is using the linux commands 'head -1' and 'tail -1' on each file to get the first and last lines, respectively. These commands are nearly instantaneous, so I'm using a random setTimeout to display the problem with caching functions. You could easily modify these scripts to 'head' and 'tail' different web sites. But, whatever. Because head.js and tail.js are simple spawn wrappers, I'll focus on processor.js, which is where the potential bugginess exists.

// begin processor.js
var head = require('./head'),
	tail = require('./tail');
	
// don't do this IRL
var callback = null;

var processor = function(file, cb){
	if('function' === typeof cb){
		callback = cb;
	}
	
	// these fail
	head(file, function(d){
		callback(d)
	});
	tail(file, function(d){
		callback(d)
	});
	
	// these succeed
	// head(file, callback);
	// tail(file, callback);
};

module.exports = exports = processor;

This is a simple file for having such a subtle bug. The file includes the customized head and tail scripts. Then, it creates a function that tags a file, caches the callback function, and calls head and tail to execute the callback. You'll notice the commented-out lines at the end that claim 'these succeed'. Here's why...

When a callback is passed directly to a function as is done with head(file, callback), the function itself is passed as a reference. Meaning, when the head module executes that callback, it will always execute the referenced callback. Now, what if another developer wants to add logging or other processing of the data? You'll likely get something like the example, where a function is created and callback is called directly (rather than the cb passed into the function originally). Because 'callback' is cached at the module level and shared across calls to processor, the scope created by the processor function is shared with the anonymous function callback and points to whatever is the most recent callback function rather than what one might expect to be the intended function.

We could avoid the problem in the above non-commented code by referencing the 'cb' parameter rather than the cached 'callback' variable. This is because processor creates a closure over 'callback', but 'cb' would always be within the current execution context.

You can play around with the code from this post, which is available on github.

flattr this!

22Oct/12Off

[Android] on{X} – automate your life

Lately, I've been obsessing over Microsoft. A couple of months ago, I would have told you that Windows 8 was a terrible move on Microsoft's part. I had installed the Windows 8 preview in a virtual machine and found it difficult to use. After discussing Windows 8 quite a bit with my friend, Travis, I came to the conclusion that the VM made things difficult. My VM manager is VirtualBox and, unlike VMware, the 'Windows Key' is not intercepted by the Guest machine.

This month's edition of MSDN Magazine is focused entirely on Windows 8. After reading about the WindowsMetadata architecture, I was hooked. I have been a .NET developer for almost 5 years now, and I think C# is one of the few languages to 'get it right'. One of the things I've always loved about .NET is the Common Language Runtime (CLR), which allows developers to write in their language of choice while actually compiling down into a bytecode call IL (this is the heart of .NET).

WinRT takes it a little further. Instead of compiling into IL bytecode, WinRT exposes a native API, and the metadata acts as an adapter between the underlying native types and the types of the WinRT language being used. I was pretty stoked about this, so I decided to give Windows 8 a true evaluation.

After installing Windows 8 to physical media, I was pretty impressed with the operating system. Learning a few hotkeys like WINDOWS key, WINDOWS+X, WINDOWS+I, and WINDOWS+J makes things a lot easier, and I was missing out on these in the VM.

You're probably wondering what that has to do with Microsoft' on{X} application for Android? Well, it appears Microsoft has spent a great deal of time in unifying different languages and architectures recently. WinRT is one example. An Android application called on{X} is another. on{X} exposes underlying Android APIs to a scriptable (JavaScript) interface. I was intrigued by the idea, so I wanted to test a pretty simple recipe.

I've been bothered by the lack of customizable volume controls in Android for some time. I have a Samsung Galaxy with Android 4.1 running on it, and I *still* have no way to automatically reduce media and notification volume to nearly nothing between 11pm and 7am while still allowing phone calls.

The on{X} team has created a script which replies to missed calls with a specific message when you're in a noisy place. Using this script as a guide, I created a script called Between 11:00 PM and 7:00 AM, 50% ringer for known contacts and 5% other audio:

(https://gist.github.com/4001499)

After you enter this script into your dashboard on onx.ms, you can push it to your phone. The on{X} application scheduler will automatically load the script based on the timer definitions.

I plan to tweak this script a bit to store the previous ringer state in localStorage and to adjust the stored and current ringer states if the ringer volume is adjusted at any time during the bedtime period. It might also be nice to increase the volume only for phone numbers from contacts in a specific group like 'Family', 'Important People', or 'Favorites.

Updated 2012-11-02: The above script now adjusts volume for incoming calls only if the calling party's number exists as a contact

So, here's the tie-in. It seems Microsoft is trying to unify a lot of things. With Windows 8, they're trying to unify the mobile and desktop experience (Yes, it will probably take you a week to get used to it, but it's worth it). With WinRT, they're trying to unify the applicability and usability of all code; you can expose C# code to JavaScript in WinRT. With on{X}, they're unifying API automation on the Android platform using a very popular dynamic language. For a company that historical has had a reputation for not 'playing along', Microsoft sure is making the game easier for developers in a lot of ways.

flattr this!

13Oct/12Off

Getting started with jQuery plugins

jQuery plugins aren't that difficult to write, but some folks seem to have a hard time understanding how to get started, so I thought I would write a quick blog post about that. I'll show how to make a pretty simple keyword highlighter which also wraps your pre/code elements in a div with a header span element.

I've written a few jQuery plugins before. One of my favorites is jquery.empuzzle. This is a favorite not only because it's incredibly fun, but because it covers a few areas of jquery plugin development:

  1. default options
  2. merge options
  3. custom selectors
  4. plugin structure

It also covers a particular gotcha when your plugin interacts with images (i.e. images may load after document ready is fired). It's definitely worth checking it out, but I'd like to show a much simpler plugin here.

The structure

jQuery plugins are commonly written as an *immediate function*. This is creates a closure which executes immediate on the jQuery object itself:

;(function($) {
    // your plugin goes here.
})(jQuery);

I often wrap a jQuery plugin in semicolons as you see above to prevent any automatic semicolon insertion errors. This is something I would consider a 'best practice' and I suggest you do the same.

Within this structure, you'll want to extend jQuery to include your plugin's code.

$.fn is a pointer to the jQuery prototype object. When you execute a jQuery call like this:

var examples = $('.test-elements');

.. you will receive a jQuery object. This object represents an array of results matching the selector passed to the jQuery function. You can use console.log() from within your plugin function to see how you might interact with this object.

;(function($) {
    $.fn.example = function(arg) {
        console.log(this);
    };
})(jQuery);

You now have the start to a plugin called 'example'. You can execute this 'plugin' in the normal way.

var examples = $('.test-elements');
examples.example();

// same as: $('.test-elements').example();

Now, you'll want to iterate over each object found by the query selector and perform whatever functionality your plugin will provide. Let's define some functionality so we can have a (somewhat) useful plugin. We'll keep with the 'example' theme and write a plugin which stylizes a <code> tag and adds a small box in the top-left corner which says 'Example'. (I got this idea from Twitter's Bootstrap framework, see here). We'll also 'highlight' a few keywords within our example.

Here's what we want our final product to look like (after some hideous styling, of course):

For the goal screenshot, I've used Google's prettify plugin, which is licensed under Apache 2.0. I don't use this in the final product.

There will be a few things we'll need to do in this plugin:

  1. Merge settings specified by the user with our default settings
  2. Wrap the code block in a styled 'example' box
  3. "parse" the contents for a select set of keywords
  4. Wrap any found keywords with a style span

For the parsing bit, I'll just use a global RegEx replace on the contents of the code element.

Providing defaults

Providing defaults in a jQuery plugin and allowing a user to pass options to merge isn't difficult. Your plugin function will accept a parameter I like to call 'opts' and return a `this.each` function. Within the `.each` function, you'll extend the defaults object with those options passed into your plugin function and store the merged options into a new object called 'options'. A very simple example which writes out to console.log might look like this:

;(function($) {
    var defaults = {
        arr: [1,2,3,4,5,6],
        sample: "sample",
        style: "style"
    };

    var example = function(opts) {
        return this.each(function() {
            // merge opts with defaults into new object
            // so changes don't change defaults
            var options = $.extend({}, defaults, opts);
            console.log({ 
                elem: this.innerText,
                options: options
            });
        });
    };

    $.fn.example = example;
})(jQuery);

Here are some options we might want to allow for the example plugin:

  1. A class name for the box and a class name for the label
  2. An object mapping keywords to class names.
  3. A parse error callback
  4. A data attribute to specify a different 'Example' box text (so each element can define its own label)

Our defaults object will look like this (more or less):

    var defaults = {
        boxCss: "example-box",
	labelCss: "example-label",
        keywords: { "function":"blue", "this":"blue", "jQuery":"red" },
        onError: function() { },
        exampleAttr: ""
    };

Wrapping our targets

To make our lives simple, we'll first wrap the target element with a div for our example box. Then, we'll add a span just before the code block. We can improve performance by creating the wrapper div's HTML outside of the '.each' function. Because we're allowing the option of pulling the labeling span's text from the code element itself, we'll have to build that HTML within the '.each' function.

Here's what we have so far.

;(function($) {
    var defaults = {
        boxCss: "example-box",
        labelCss: "example-label",
        keywords: { "function":"blue", "this":"blue", "jQuery":"red" },
        onError: function() { },
        exampleAttr: ""
    };

    var example = function(opts) {
        var options = $.extend({}, defaults, opts);
        
        var wrapperHtml = [
            '<div class="',
            options.boxCss,
            '"></div>'
        ].join('');

        var labelArr = [
            '<span class="',
            options.labelCss,
            '">',
            "Example",
            '</span>'
        ];

        return this.each(function() {
            var labelText = "Example";
            if(options.exampleAttr) {
                labelText = $(this).attr(options.exampleAttr);
            }

            var labelHtml = [
                '<span class="',
                options.labelCss,
                '">',
                labelText,
                '</span>'
            ].join('');

            $(this).wrap(wrapperHtml);
            $(this).before(labelHtml);
        });
    };

    $.fn.example = example;
})(jQuery);

onError function

The onError function we allow in the options object does nothing more than provide a message if we don't have a code element to update with keyword highlights. We will supply a message to the callback function and return from the current iteration of '.each'. This goes at the beginning of the 'this.each' function.

// Find node for replacing text.
var replacementNode = $(this).children('code').andSelf().filter('code');

if(replacementNode.length == 0) {
    if(typeof options.onError === "function"){
        options.onError("No code nodes found");
    }
    
    return;
}

With the combination of children/andSelf/filter in the above code, we allow the plugin to operate on both 'pre' and 'code' elements.

When allowing users to pass functions as callbacks or to provide added functionality to a plugin, *always* check that it is a function.

"Parsing" contents

In the interest of saving some time, I'm going to use a regular expression to replace text within the code block. This isn't necessarily the most efficient way to achieve a budget syntax highlighter, but it will work.

To do this, we'll need to grab the text from our code node in which we'll replace keywords. Then, for every keyword in the hash of keywords-to-classes, we'll create a span to represent the highlighted keyword. Then, we'll do a search and replace using a global regular expression object, substituting each found keyword with the keyword wrapped in a span element. This goes at the end of the 'this.each' function.

    var originalText = replacementNode.text();
            
    Object.keys(options.keywords).forEach(function(key,idx){
        var replacement = [
            '<span class="',
            options.keywords[key],
            '">',
            key,
            '</span>'
        ].join('');
        
        var re = new RegExp(key,"g");
        originalText = originalText.replace(re, replacement);
    });

The only thing left to do is to add styles to your document and you're all set with a customized syntax highlighter!

There are a few issues with this simple implementation. First, keywords don't get merged (I'll leave that as an exercise for you). Second, this only highlights keywords. It doesn't provide regex matching for full-text highlights. In other words, this won't highlight comments.

If you're unfamiliar with jQuery plugins, or you're planning to begin writing a keyword highlighter plugin, this should at least get you started!

Try it out!

Check out the jsfiddle.

Get the code

The code for this blog post is available on Github.

flattr this!

4Oct/12Off

Drawing a custom HTML5 shape

HTML5 is fun. I've meant to post about it more than I have in the past (which is 0 posts). I recently got the urge, so I want to show how to draw a heart and a star on HTML5 canvas.

Some background

A few days ago, I heard about typescript, which is a typed superset of JavaScript. It's similar to coffeescript, dart, and others in that it defines a language which compiles down to plain JavaScript. It's different than most because it gives JavaScript the concept of types and compile-time type checking. The compiler is available cross-platform, but the IDE tools are only available for Visual Studio 2012 or in-browser on the website.

Anyway, I wanted to play around with typescript so I decided to see how easily I could convert brushes.js to use some of the typed semantics of typescript. It wasn't too difficult and the code actually looks way cleaner in typescript. The only issue I've found is that types are not inferred 100% accurately at times. For instance, document.getElementsByTagName returns a NodeList. Indexed elements are considered Node elements and not a more specific type. An example, you would expect the following snippet to compile properly:

if($tag) {
	var canvas = $tag('canvas') ? $tag('canvas')[0] : null;
	if(canvas && canvas.getContext) {
		this.context = canvas.getContext("2d");
	}
}

Unfortunately, you're presented with a message that says getContext doesn't exist on Node.
typescript Node select message

To remove this message, you need to do something I personally don't like doing (although it's completely legal in JavaScript)-- access the function by key.

if($tag) {
	var canvas = $tag('canvas') ? $tag('canvas')[0] : null;
	if(canvas && canvas["getContext"] && typeof canvas["getContext"] === "function") {
		this.context = canvas["getContext"]("2d");
	}
}

Aside from this little problem, I found the coding experience to be beneficial and fun. In fact, while modifying some of the code for the brushes (hearts and stars), I was motivated to write a blog post showing how to create some basic custom shapes in HTML5...

HTML5

The awesome thing about HTML5 is that you now have a drawing area natively embedded directly into HTML. That's pretty awesome because it opens up the browser to do some really awesome stuff. There are some pretty phenomenal examples of the power of HTML5 (sometimes mixed with WebGL) at chromeexperiments.com. In fact, I had the urge to start working on brushes.js after playing with an experiment called Harmony by MrDoob. MrDoob has since moved onto creating the hugely-popular three.js. With those two links, I think you can get lost for hours in the power of the browser. If you're just getting started with some of the new HTML5 APIs, you may want to check out remy's HTML5 demos.

Drawing

How to draw a star on xkcd.com

Image courtesy of xkcd.com

Drawing is nothing new in programming. You can easily find algorithms for drawing specific shapes on game dev sites. In fact, I believe I found the algorithm for the star in a C++ game programming book I purchased but haven't gotten around to reading fully.

The HTML5 canvas is a grid in which (0,0) is in the top-let corner of the grid. It is easiest to draw shapes starting at the origin, then move them into place when you're done. The canvas API makes this easy using the translate function. Suppose you want to draw an image at (100,100). Using context.translate(100,100) (where context is the 2d drawing context of your canvas element) will cause the drawing context to temporarily set the origin at (100,100), allowing you to draw easily without the headache of calculating offsets.

The steps necessary to draw a simple shape are as follows:

  1. Query the dom for the canvas element
  2. Call context.getContext("2d") on canvas element
  3. Save the context
  4. Translate context origin to desired location
  5. Set additional properties on the context
  6. Call context.beginPath()
  7. Draw your shapes
  8. Stroke or fill your shape
  9. Call context.closePath() to indicate drawing has completed
  10. Call context.restore() to restore the previously saved context

This may seem like quite a bit. For an example, I've created a jsfiddle so you can play around and see the above steps in action.

Try it

Code

The code for this blog post is available on github at jimschubert/blogs

flattr this!

30Apr/12Off

[node.js] Simple Logging in tweeter.js

tweeter.js is a simple OAuth implementation I started working on for a node.js application I had envisioned. The library works, as in it runs through the whole OAuth dance and allows the client to make API calls. There are some more in-depth things I never got around to (like caching the tokens and clearing sessions and whatnot) before I realized I don't like Twitter. Oh well.

I was just looking through my github repositories and I thought it would be cool to post about the simple logging mechanism I created for tweeter.js. Although not the coolest pattern I used in the project (which probably goes to mixins), I like how simple the solution is. Check out the code for other cool features..

Logging

The cool thing about this logging framework is that it allows you to write out logs to different streams. For instance, suppose you want to write all logging information other than errors to log.txt, but you want to keep errors in errors.txt.

The way I implemented this was to create an object of streams on the Log object. I used getters/setters to provide validation that an object being assigned to one of the properties is actually a stream. Although I didn't bother with it, this object could possibly be sealed or frozen.

// An object with safe getters/setters for each stream.  
// Streams are:  
// debug, info, error, warn
Log.prototype.streams = {
    get none() { return { write: function() { }}; },
    get debug() { return this._debug; },
    set debug(val) {
        requiresStream(val);
        this._debug = val;
    },
    get info() { return this._info; },
    set info(val) {
        requiresStream(val);
        this._info = val;
    },
    get warn() { return this._warn; },
    set warn(val) { 
        requiresStream(val);
        this._warn = val;
    },
    get error() { return this._error; },
    set error(val) {
        requiresStream(val);
        this._error = val;
    }
}

Because this is written for node.js, requiresStream() verifies the value is an instance of EventEmitter with a write function.

Defaults for these streams are set in the constructor with a default logLevel of -1 (disabled).

var Log = module.exports = exports = function Log(level) {
    // default error to stderr and the rest to stdout
    this.streams.debug = process.stdout;
    this.streams.info = process.stdout;
    this.streams.warn = process.stdout;
    this.streams.error = process.stderr;

    // default the logLevel to disabled
    this.logLevel = level || -1;
}

An interesting thing about this logger is how I make the calling convention flexible. I use .NET regularly and I would call a logging function in .NET with an enum value to specify the logLevel. I wanted a similar functionality in this logger, so I created a lookup object to map a key (i.e. DEBUG) to a logLevel (0) and a stream (debug).

// [DISABLED] else [DEBUG > INFO > WARN > ERROR]
Log.prototype.logLevels = {
    DISABLED:   { value: -1, stream: 'none' },
    DEBUG:      { value: 0, stream: 'debug' },
    INFO:       { value: 1, stream: 'info' },
    WARN:       { value: 2, stream: 'warn' },
    ERROR:      { value: 3, stream: 'error' }
}

I considered accessing these on the streams object directly, but did it this way for readability and flexibility. A major deciding factor in choosing this route was the ability to reorder logging levels in a single place in the code.

// ## log(level msg);
// logs the output with a nice colorful indicator of the stream.  
// `msg` may be a string or a formattable string and options.
Log.prototype.log = function(level, msg) {
    var original = level;
    try {
        if(typeof level === 'string'){
            level = this.logLevels[level.toUpperCase()];
        }
        // get logLevel value
        if( (this.logLevel > -1) && (level.value >= this.logLevel) ) {
            var stream = this.streams[level.stream];
            stream.write( util.format.call(this, '[\033[%sm%s\033[39m]\t', colors[level.value], level.stream) );
            stream.write( util.format.apply(this, slice.call(arguments,1) ) + '\n');
        }
    } catch (err) { 
        console.error("logging is improperly configured!\nIs %j a supported logLevel?\nError:\n%j\n",original, err);
    }
}

An example

I've uploaded an example to github.

In this example, I write out logs for each of the 4 supported levels. The default is to write these out to stdout. After writing to the defaults, I set

var Log = require('./log.js'),
    fs = require('fs');

var level = process.argv[2] || 1;
var logger = new Log(level),
    level = logger.logLevels;

logger.log(level.DEBUG, "This is a debug message");
logger.log(level.INFO, "This is an info message");
logger.log(level.WARN, "This is a warning message");
logger.log(level.ERROR, "This is an error message");

var debugStream = fs.createWriteStream('./debug.txt');
var infoStream = fs.createWriteStream('./info.txt');
var warnStream = fs.createWriteStream('./warn.txt');
var errorStream = fs.createWriteStream('./error.txt');

logger.streams.debug = debugStream;
logger.streams.info = infoStream;
logger.streams.warn = warnStream;
logger.streams.error = errorStream;

logger.log(level.DEBUG, "This is a debug message");
logger.log(level.INFO, "This is an info message");
logger.log(level.WARN, "This is a warning message");
logger.log(level.ERROR, "This is an error message");

debugStream.end();
infoStream.end();
warnStream.end();
errorStream.end();

This provides the following input when passing a log level in via the command line:

flattr this!

8Nov/11Off

My Review of JavaScript: The Definitive Guide, 6th Edition


A tome of knowledge

By Jim from Herndon, VA on 11/8/2011

 

4out of 5

Pros: Well-written, Accurate, Concise, Easy to understand

Cons: Huge

Best Uses: Student, Expert, Novice, Intermediate

Describe Yourself: Developer

This is an unbelievably thorough JavaScript book. It's definitely more of a reference book than a front-to-back read.

The first 12 chapters are an excellent introduction into the history of JavaScript and the core functionality of the language. There is a lot of information in these chapters that really shouldn't be overlooked-- especially Chapter 8: "Functions".

I especially appreciate the structure and the approach of the client-side section of the book. Flanagan makes it a point to avoid pushing JavaScript frameworks by explaining the features of the language first, followed by an explanation of the cross-browser simplification of using jQuery.

Later chapters cover additions to more recent browsers like client storage and HTML5 features. Those chapters unfortunately go by really fast. They're definitely not as in-depth as the JavaScript history part of the book.

The last two parts of the book are purely reference. This is pretty helpful, but it makes the book a lot thicker than most "guide" references.

I do agree with others that this book could use a few more examples, especially near the end when discussing JavaScript usage with new HTML5 APIs. If you're looking for an in-depth understanding of the core functionality of JavaScript, this is the book. It has helped me in numerous job interviews!

(legalese)

flattr this!

31Oct/11Off

jQuery plugin: fixed table header

Here's a plugin that I wrote a while ago for fixing a table's header row on scroll.

This code is also available as a gist. Fork it and contribute.

(function($) { 
	$.fn.fixedHeader = function(options) {
		var settings = { 
			selector: 'thead:first',
			cssClass: 'fixed',
			fixTo: 0
		};

		var _fixHeader = function(obj) { 
			var header = $(obj.selector, obj.elem);
			if(header) {
				var parent =  header.parents('table:first') || header.parent();
				(parent && parent.css({ borderCollapse: 'collapse'}) );

				var data = header.data('fixedHeader') || header.data('fixedHeader', { 
						top: header.offset().top,
						width: parent.find('tr:eq(1)').width(),
						cells: parent.find('tr:eq(1) > td'),
						processed: false
					});
				var top = data.top - $(document).scrollTop();
				if( top < 0 ) {
					header.addClass(obj.css);	
					if(!data.processed){
						header.width(data.width);
						for(var i = 0; i<data.cells.length;i++) {
							$('th:eq('+i+')', header).width($(data.cells[i]).width());
						}
					}

				} else { 
					header.removeClass(obj.css); 
				}
			}		
		};
		return this.each(function() {
			var self = this;
			if("object" === typeof options) {
				$.extend(settings, options);
			}
			if($(self).parents('table:first')){
				$(window).bind('scroll.fixedHeader', function() {
					_fixHeader({ 
						elem: self,
						selector: settings.selector,
						css: settings.cssClass,
						top: settings.fixTo
					});
				});
			}
		});
	};
})(jQuery);

A demo:

flattr this!

28Sep/11Off

Makefile setup for minifying .js files in an expressjs application

There's not really any reason to uglify or minify your JavaScript files on a per-request basis or on a pre-cache basis. This should be done at deployment time only. This can be achieved by adding uglify-js to your package.json file.

// default package.js for an expressjs app using ejs and uglify-js
{
    "name": "application-name"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.4.6"
    , "ejs": ">=0.4.3"
    , "uglify-js": ">=1.1.0"
  }
}

Make sure the dependencies are installed with

npm install -d

Then, add the following make file and minify your JavaScripts as part of your make process!

JS = $(shell find public/javascripts/*.js)
MINIFY = $(JS:.js=.min.js)

all: clean $(MINIFY)

clean:
	rm -f ./public/javascripts/*.min.js

%.min.js: %.js
	node ./node_modules/uglify-js/bin/uglifyjs -o $@ $<

.PHONY: clean js minify

(expandable source is the same as the gist. It is doubled here to show in RSS feed readers.)

flattr this!

4Sep/11Off

Editing JavaScript in vim

I primarily use vim as my editor of choice for JavaScript.

I have a fairly simple .vimrc:

syntax on " enabled syntax highlighting
:set number " line numbers
:set ai " autoindent
:set tabstop=4 " sets tabs to 4 characters
:set shiftwidth=4
:set expandtab
:set softtabstop=4 " makes the spaces feel like real tabs
" CSS (tabs = 2, lines = 79)
autocmd FileType css set omnifunc=csscomplete#CompleteCSS
autocmd FileType css set sw=2
autocmd FileType css set ts=2
autocmd FileType css set sts=2
" JavaScript (tabs = 4, lines = 79)
autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS
autocmd FileType javascript set sw=4
autocmd FileType javascript set ts=4
autocmd FileType javascript set sts=4
" autocmd FileType javascript set tw=79

autocmd FileType jade set omnifunc=jadecomplete#CompleteJade
autocmd FileType jade set sw=2
autocmd FileType jade set ts=2
autocmd FileType jade set sts=2

" Highlight current line only in insert mode
autocmd InsertLeave * set nocursorline
autocmd InsertEnter * set cursorline

" Makefiles require TAB instead of whitespace
autocmd FileType make setlocal noexpandtab

" Highlight cursor
highlight CursorLine ctermbg=8 cterm=NONE

I also use the JavaScript syntax/indents found here:
https://github.com/pangloss/vim-javascript

You can access the completion by typing CTRL+X,CTRL+O.

If you have any other suggestions for using vim as a JavaScript editor, let me know!

flattr this!

Tagged as: No Comments