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

7Apr/13Off

git prepare-commit-msg with node.js

I think people often overlook using node.js as a scripting tool like ruby or python. If you search the web for examples of customized git hooks, you'll probably have visited git-scm.com, where most of the examples are in ruby.

I wanted to show a pretty simple prepare-commit-msg hook written in node.js. This hook will append the name and description of whatever working branch you commit from. I use this technique to create a working branch for a JIRA ticket number, so all my commits to this ticket automatically include that ticket number. Then, JIRA can be configured to display github commits directly in the ticket details when that commit references the ticket in the commit message.

The script:

#!/usr/bin/env node
var exec = require('child_process').exec,
    util = require('util'),
    fs = require('fs'),
    contents = null,
    branch, desc;

console.log(process.argv);

// expect .git/COMMIT_EDITMSG
if(/COMMIT_EDITMSG/g.test(process.argv[2])){
    // look for current branch name
    branch = exec("git branch | grep '*'",
      function (err, stdout, stderr) {
        if(err){
			// git branch will fail if initial commit has not been done,
			// so we can safely skip this hook
			process.exit(0); 
		}

		// opens .git/COMMIT_EDITMSG
        contents = fs.readFileSync(process.argv[2]);
		
		// trims extra characters from start/end of line
        var name = stdout.replace('* ','').replace('\n','');
		
		// If the branch has a description, pull that
        desc = exec('git config branch.'+ name +'.description',
            function(err, stdout, stderr){
				// don't handle errors (because we write out branch anyway)
                
				// we found a description, add to 'name'
				if(stdout){ name = util.format('%s (%s)', name, stdout.replace(/\n/g,'')); }

				// '(no branch)' indicates we are in a rebase or other non-HEAD scenario
                if(name !== '(no branch)'){
				
					// Append branch name to original contents.
                    contents = util.format('%s\n\n:%s\n', contents, name);
					
					// write contents back out to .git/COMMIT_EDITMSG
                    fs.writeFileSync(process.argv[2], contents);
                    process.exit(0);
                } else {
                    process.exit(0);
                }
        });
    });
}

The above script is pretty well-commented. If you decide to use it, you may want to comment out the first console.log which dumps all arguments sent to the script.

Here's an example of its usage.

Create and initialize a new local git repository.

$ mkdir example
$ cd example
$ git init

Then, copy the above example script into the git hooks directory under .git/hooks/prepare-commit-msg

Now, in the example directory, create and commit a file into the repository:

$ touch first
$ git add .
$ git commit -m 'Initial commit'

You'll see the array of arguments passed through the custom git hook, but if you issue a git log, you'll only see the commit message 'Initial commit'. That's because this custom hook expects a git branch, but there is no git branch until your initial commit is complete. To verify the script is working:

$ touch second
$ git add .
$ git commit -m 'Second commit'

A git log will now show you a tweaked message:

    Second commit
    
    :master

Now, you can create a branch named 'ABC-123' and do another commit:

$ git checkout -b ABC-123
$ touch third
$ git add .
$ git commit -m 'Third commit'

The commit message:

    Third commit
    
    :ABC-123

This hook also allows you to print out the branch description. To test, invoke the branch description editor:

$ git branch --edit-description ABC-123

I've added the text 'Supporting branch for ABC-234 and ABC-567'. Save this buffer according to your editor (:wq if you're using vim).

Add a fourth file as we have before, then verify with git log:

    Fourth commit
    
    :ABC-123 (Supporting branch for ABC-234 and ABC-567)

Because this script strips newlines from the branch description, you'd need to keep it short. Usually, that's not a problem.

This shows how to append text to your commit message, but it can easily be modified to replace commonly misspelled words (teh -> the).

This prepare-commit-msg hook is available in my blogs repo on github.

flattr this!

Tagged as: , No Comments
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!

4Jan/13Off

“Unable to update the dependencies of the project”

I've recently had to switch from Visual Studio 2012 back to Visual Studio 2010 to do maintenance on another project. This project is currently stuck in Visual Studio 2010 until I have time to convert the old setup projects to WiX. I often receive the following error message during Release builds:

"Unable to update the dependencies of the project"

Closing Visual Studio 2010 and reopening seemed to have fixed the problem up until about a week ago. I've found that installing this hotfix seems to resolve the issue. The only problem is that I've had to install the hotfix multiple times.

The 'cause' on the hotfix page says the issue is a result of how Visual Studio 2010 refreshes dependencies. I wonder if this is handled by Windows Updates updating the .NET Framework? Whatever it is, it's pretty annoying to have to apply this patch regularly. I guess it's just another reason for developers to move setup projects to WiX.

http://support.microsoft.com/kb/2286556

flattr this!

Tagged as: , , No Comments
25Nov/12Off

My Review of Values, Units, and Colors


Excellent intro or review

By Jim Schubert from Richmond, VA on 11/25/2012

 

5out of 5

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

Best Uses: Expert, Intermediate, Novice, Student

Describe Yourself: Developer

I am reviewing "Values, Units, and Colors" as part of the O'Reilly Blogger Review program. I have had about a 6 month hiatus from full-time web development, so I thought I'd be able to offer a somewhat fresh perspective of this book's content.

It's a short, quick read. It's also well-worth the price. There were quite a few things I didn't know (or hadn't considered), such as some odd behavior in older versions of Internet Explorer and certain times a value may mean something different depending on the order of values and keywords.

I especially loved the explanation of HSL versus RGB. I had always avoided HSL and HSLa, because RGB and RGBa seem more intuitive to me. This book explains the two very well, in a way I think someone more familiar with HSL than RGB would gain an equally better understanding as I have.

The book also covers some relative length units which I've never used or seen used (ex, rem, ch).

Usually, I'm not very impressed with short books of this nature. I think it's fairly difficult to get *enough* information in so few pages. I think the subject matter in this book is focused enough to cover it quickly and concisely in less than 50 pages. I'll admit, I didn't expect to say aloud while reading this, "Huh, now that makes sense."

I'd definitely recommend this book to fellow web developers, or anyone interested in tweaking the styles of their own website. I will definitely reread this book in the future.

(legalese)

flattr this!

Tagged as: No Comments
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!

14Oct/12Off

Generating sprites with HTML5 canvas (node-canvas)

About a week ago, I posted about drawing simple shapes in HTML5. HTML5's Canvas isn't only useful on the client side.

About a year ago, I rewrote my Quaketracker mashup which pulls rss content from USGS and displays markers on a Google Map. For part of this rewrite, I wanted to use custom markers to indicate the magnitude of the earthquake, both numerically and colorfully. That task was more involved than I realized it would be. There doesn't seem to be any easy way to generate such a sprite in The Gimp or other graphics software, so I set out to generate a sprite of magnitudes 0.0 through 9.9 with a color range from yellow to orange using node-canvas. This actually made the task very simple.

base.png

marker

Before writing the script, I had to decide on an image. I created a pretty simple quote-bubble-like marker with a white background and a black outline. The image is 35x35 square with some transparency padding the actual marker image. This allows me to calculate the layout pretty easily. The white background on black outline gives me a very specific color to replace with the desired color of intensity.

node-canvas is a custom implementation of Canvas for node.js. When I originally wrote this script, I had a few issues compiling node-canvas. When I tweaked the script today, I had no issues. However, it seems like some things are not well-documented or incomplete (PixelArray).

Scripting it in node.js

A lot of times, if your script writes out to files, it's best to check for dependencies and cause your script to exit if they're not met. For example, I know this script is completely useless without node-canvas, so I can probe for the availability of that module and provide directions for installation. I'd do this before attempting to load any other functions from the canvas module. You could also check for versions at this point. If someone runs this script with node-canvas 0.6.0 it will still work, but this may not be the case with other modules. Here's how I start off the script.

var p = require('util').puts;

try {
    var probe = require('canvas');
} catch(e) {
    p("Cannot find node-canvas module.");
    p("Did you install dependencies:\n");
    p("\tnpm install -d");
    process.exit();
}

var fs = require('fs');
var Canvas = require('canvas');
var Image = Canvas.Image;

var canvas, ctx, baseImage, outImage, img;

I don't usually use 'global' variables like those in the last line of the above snippet for applications or client-side scripting. For a script like this, you could have everything as a global variable as long as the names don't clash with your imported modules.

To initialize shared variables, I like to define an init() function and call that function at the end of the script. This is pretty common in other languages like Ruby and Python, so why node server-side JavaScript?

var init = function() {
	// our working image is 35x35, we want 10x10 sheet of sprites
	canvas = new Canvas(35*10,35*10);
	ctx = canvas.getContext('2d');
	baseImage = __dirname + '/base.png';
	outImage = __dirname + '/markers.png';

	// pre-load the image
	img = new Image;
	img.onload = function() {
		processImage(fileProcessingComplete);
	};
	
	img.src = baseImage;
};

The cool thing about node-canvas is that the usage is very similar to the Canvas API implemented in browsers supporting the HTML5 Canvas. In fact, aside from the __dirname special property of node.js, you should be able to drop this init function into a browser with no problems. For this script, I want 100 different magnitudes to be generated from 0.0 through 9.9 (00-99 is 100) so the canvas is initialized to 10 rows and 10 columns of 35x35 squares. Just like a client-side Image object, we want to bind any post-processing of the image via the onload() function.

I'm going to Memento you a bit, and for that I'm sorry but the end is the easier concept. When all the processing is complete, we want to pull image data from the Canvas element and write it out to a file.

var fileProcessingComplete = function() {
	var out = fs.createWriteStream(outImage),
            stream = canvas.createPNGStream();

	stream.on('data', function(chunk){
	  out.write(chunk);
	});

	// when PNG stream is done, drain WriteStream
	stream.on('end', function(){
	  p('saved ' + outImage);
	  out.destroySoon();
	});
};

Accessing streams in node.js is usually done asynchronously. We can take chunks of data from the ReadStream of createPNGStream() and pump that to the WriteStream of the output file. When the data from the PNG is done streaming, we tell the output stream to finish writing its buffered data and destroy itself. It sounds intense, but it's pretty straightforward.

Processing the colors and marker images is the fun part. To match the function call in the init function, we just create a function with a callback in the standard way.

var processImage = function(cb) {
        // other code removed
	if(typeof cb === "function") {
		cb.call(this);
	}
}

If there's a callback function passed as a parameter, when processImage is finished, it will call that function passing the current scope as the execution scope and no parameters.

To draw out the custom marker, we'll want to define how we want to display the text and at what color we want to have the 0.0 marker start.

ctx.font = 'normal 12px Impact';
ctx.textAlign = 'center';
var color = [255, 255, 0, 235];

The color array represents red, green, blue, and alpha channel (opacity). This may look odd if you're used to specifying alpha channels in css as "rgba(255,255,0,0.92)", but that value of 235 will give roughly 92% opacity.

We can make the script run pretty quickly by using a second canvas 2d context for the recolor phases (which modifies every white pixel).

// use a temp Canvas and Context of 35x35 size.
var tempCanvas = new Canvas(35,35);
var tempCtx = tempCanvas.getContext('2d');

This is an optimization I made today when tweaking the original script. In the original version of this script, I would write the base image to the output canvas then iterate over 'NxN' pixels on the output canvas to change the color of one pixel. Using a temporary canvas context, we only have to iterate over 35 pixels wide by 35 pixels high for every new marker. This not only speeds up the process, but it could be a difference of having a script that won't run on slower machines.

For each of the desired 100 magnitudes, we'll want to find the x and y values (top-left pixel) to which we'll write the updated marker. For every 1/2 magnitude, the Green color value decrements by 13 points.

for(var magnitude = 0; magnitude <= 100; magnitude++) {
	var y = 35 * Math.floor(magnitude/10),
		x = ( 35*(magnitude % 10) );

	// This increments the color slightly
	if(magnitude % 5 == 0){
		color[1] = color[1] - 13;
	}

        // some code removed

	ctx.fillText("" + parseFloat(magnitude / 10, 1), x + (35/2), y + (35/2), 35);
}

The last line of the above snippet fills the magnitude text on the output canvas. This could be moved to the next part of the script for a further optimization: instead of just modifying each white pixel's color, we could recolor and apply the text.

The part of the script which changes the color according to the magnitude looks like this:

tempCtx.drawImage(img, 0, 0, 35,35);
var imgData = tempCtx.getImageData(0, 0, 35, 35);
var data = imgData && imgData.data;
if(data) {
	try {
		for(var pixel=0;pixel<data.length;pixel=pixel+4) {
			var red = data[pixel]
			var green = data[pixel+1];
			var blue = data[pixel+2];
			var alpha = data[pixel+3];

			if(red == 255 && green == 255 && blue == 255) {
				data[pixel] = color[0];
				data[pixel+1] = color[1];
				data[pixel+2] = color[2];
				data[pixel+3] = color[3];
			}
		}
	} catch (err) { console.error(err.message); }

	// Write our temp image data to the final canvas context
	/* imageData, dx, dy, sx, sy, sw, sh */
	ctx.putImageData(imgData,x,y,0,0, 35, 35);
}

Writing to the temporary canvas's 2d context gives us access to a data buffer which represents a 35x35 image where each pixel is represented by 4 bytes (rgba). Iterating this buffer by 4's, we can check that the given pixel (excluding alpha because that doesn't matter in this case) is white or rgba(255,255,255). If the pixel is white, we replace those 4 indexes with the values in our color array. When we're done iterating the buffer representing the 35x35 image, we can call putImageData on the output canvas. With that, the sprite is complete and our callback handles writing the file.

A note about putImageData

putImageData can be a strange beast. Notice the comment imageData, dx, dy, sx, sy, sw, sh... these are the parameters accepted by the function. Even the HTML5 Specs might make you go, "Uhm... what?" The idea is pretty simple once you understand it. You want to write a buffer (imgData) where the top-left pixel is at dx,dy. sx and sy (or dirtyX and dirtyY) represent a dirty rectangle of size sw x sh (or dirtyWidth by dirtyHeight).

If the imageData passed to the function is the same height and width as the target canvas context, you wouldn't want to overwrite every single pixel would you? You'd only want to overwrite pixels that have changed. Suppose in this script, I had an imageData object of 350x350 to complement the output canvas. When putting the modified imageData, I would have to calculate the current 35x35 box offset and write out the imageData to 0,0. As an example, if I wanted to overwrite the 35x35 box for the 9.9 magnitude marker with an imageData buffer of 350x350, I might write:

ctx.putImageData(imgData, 0, 0, 315, 315, 35, 35);

This would tell the context that although my buffer is 350x350, I've only changed a 35x35 rectangle starting at 315x15. Canvas is smart enough to only update those pixels rather than every pixel in the canvas.

On the other hand, in the script I've written, I only have an imageData object which represents a 35x35 buffer. So, I can tell putImageData to start at the point defined by (x,y) and write the buffer into a 35x35 rectangle. I like this method a little more, but it may not always be the case that you're writing a smaller buffer to the context.

The code

As always, the code for this blog post is available on github at jimschubert/blogs.

The sprite

Here's what the generated sprite looks like.

Markers generated for Quaketracker

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!

22Sep/12Off

My Review of Hilary Mason: Advanced Machine Learning


More "Intro to Machine Learning part 2"

By Jim Schubert from Richmond, VA on 9/22/2012

 

4out of 5

Pros: Helpful examples, Easy to understand

Cons: Too basic, Not comprehensive enough

Best Uses: Novice, Student

Describe Yourself: Developer

I watched this video as part of O'Reilly Media's blogger program. I haven't worked with machine learning topics in the past, and I was interested to learn a bit from this video. It turns out that I use many of the machine learning concepts in the linux terminal almost daily, but on much smaller data (personal computer logs). I've even parsed Apache logs in almost the same way as presented in this video's "Learning from your data" segment.

At first, I was little confused why this video is called "Advanced Machine Learning" because I didn't feel like any of the topics were all too advanced. Each segment seems to only skim the surface of a very general topic. In fact, it seems to me that this video is more of a continuation of Ms. Mason's other Machine Learning video on O'Reilly-- "An Introduction to Machine Learning with Web Data." It may be more appropriately named "An introduction to data analysis", and that's not a bad thing! Don't be turned away by a misleading title. Fair warning: I've rated the video based on the content with my proposed title.

If you're looking for an in-depth discussion of machine learning algorithms, this isn't the video for you. If you're looking for an introduction in getting things done with data, you should check out this video. Although the amount of information is pretty light, it is still a good way to get your start conceptually. If you look at the scripts and sample data provided in the code repository, you'll be off to a good start to learn more about your data.

For instance, Hillary makes it a point to break things down into a few simple steps:

1) What is your data?
2) What do you want to learn from your data?
3) How to extract that information.

Again, I wouldn't recommend this video if you're software engineer with a desire to learn in-depth machine learning algorithms. I do recommend this video if you're interested in understanding some fundamentals of machine learning and how they're applied in some advanced production scenarios (especially at bit.ly).

I also recommend checking out the code examples and learning the basics of the python modules used in the scripts. They will help you analyze your data in a meaningful way.

(legalese)

flattr this!

Tagged as: No Comments