Setting up Logwatch on a DNS320 (fun_plug)

Logwatch is a customizable log analysis system. Logwatch parses through your system’s logs and creates a report analyzing areas that you specify. Logwatch is easy to use and will work right out of the package on most systems. This guide shows you how to get it up and running on a DNS-320, or any other device running fun_plug.

Configuring System Mail via Gmail

Logwatch needs to be able to send the generated reports via email – if you haven’t setup a mail relay on your fun_plug box then the easiest route is to configure msmtp (a built in SMTP client) and relay your email through an external SMTP provider (in my case, Gmail). If you can already send email from your fun_plug server then just skip over this step.

Start by configuring msmtp.

mkdir -p /ffp/etc/msmtp
touch /ffp/etc/msmtp/msmtp.conf
chmod 600 /ffp/etc/msmtp/msmtp.conf
nano /ffp/etc/msmtp/msmtp.conf

Use the following msmtp.conf file as a template, replacing it with your own SMTP service provider’s details. As a word of advice, I would suggest that you use a separate account just for relaying outgoing email, rather than putting your primary email account’s credentials in a the config file.

# Set gmail default values
defaults
tls on
tls_certcheck off

# Gmail account parameters
account default
host smtp.gmail.com
port 587
from your.address@gmail.com
auth on
user your.address@gmail.com
password yourgmailpassword

# set log file
logfile /ffp/etc/msmtp/msmtp.log

The final step is to create a wrapper for sendmail, as logwatch (and other system utilities) will expect it to be present when sending outgoing messages.

touch /ffp/bin/sendmail
chmod +x /ffp/bin/sendmail
nano /ffp/bin/sendmail
#!/ffp/bin/sh

exec /usr/bin/msmtp --file=/ffp/etc/msmtp/msmtp.conf --read-recipients $*

Finally we need to create a link to our sendmail wrapper so scripts can find it in the expected location of /usr/sbin/sendmail.

Installing Logwatch

Start off by acquiring the Logwatch sources from their Sourceforge site.

wget http://freefr.dl.sourceforge.net/project/logwatch/logwatch-7.4.0/logwatch-7.4.0.tar.gz
tar -zxvf logwatch-7.4.0.tar.gz
cd logwatch-7.4.0

Once unpacked, you can run the interactive install script which will guide you through the install process.

chmod +x ./install_logwatch.sh
./install_logwatch.sh

The install script will now ask you where logwatch should be installed to; note that you must specify alternative paths for *all* of these questions to ensure Logwatch is installed to the fun_plug home.

Preparing to install Logwatch
Enter the path to the Logwatch BaseDir: /ffp/share/logwatch
Enter the path for the Logwatch ConfigDir: /ffp/etc/logwatch
Enter the dir name to be used for temp files: /ffp/var/cache/logwatch
Enter the location of perl [/usr/bin/perl]: /ffp/bin/perl
Enter the dir name to used for the manpage: /ffp/share/man

Once installed, you may wish to change the recipient email address to which the Logwatch reports are emailed, this can be configured in the

/ffp/etc/logwatch/conf/logwatch.conf

file.

TmpDir = /ffp/var/cache/logwatch
MailTo = logwatch@your.domain
MailFrom = noreply@your.domain

Once configured, you can test logwatch by issuing:

logwatch --output stdout --detail medium --debug 5 --range today | more

This will output straight to the command line and should flag up any potential issues with your system’s configuration.

The final step is to add logwatch to your system’s cron, so it automatically runs. Getting cron to work on a fun_plug install can be a touch tricky (thanks to /var being overwritten on reboot).

# Logwatch report at 3am, daily.
0 3 * * * /ffp/etc/logwatch/logwatch.cron >/dev/null 2>&1

Making XHR Request to HTTPS domains with WinJS

I recently came across an interesting caveat when working with WinJS (the JavaScript layer for creating Windows 8 Store applications). If you attempt to make an HTTP POST request to a server over the HTTPS protocol you may run into the following error:

XMLHttpRequest: Network Error 0x2ef3, Could not complete the operation due to error 00002ef3.

This error appears to be caused by a security certificate issue; however the solution is pretty straight forward – you just need to make a GET request before attempting subsequent POST request, for example:

// Before making a POST request we first have to issue a GET against the target
// server to work around Network Error 0x2ef3.  Note you only need to do this
// ONCE in your app, not every time.
WinJS.xhr({
    url: "https://my.server/"
}).then(function () {

    // After a single GET request we can now invoke POST requests.
    WinJS.xhr({
        url: "https://my.server/endpoint",
        type: "POST",
        data: {
            foo: "bar"
        }
    })
}).then(function () {
    console.log("HTTPS POST request complete!");
});

Backing up Your GMail on a DNS-320 with Fun_Plug and GMVault

Email is one of those interesting bits of personal data. Although irreplaceable, it’s not on the same level as personal artefacts (like pictures, recordings, etc.) however, if you were to wake up tomorrow and learn that Google had lost all of your email, I bet you’d be pretty miffed.

Fortunately there’s an excellent Open Source script, GMVault, which automates the process of backing up and archiving your email from Google’s servers. This tutorial covers how to get GMVault up and running on Fun_Plug, the popular distribution for running on embedded ARM devices, such as the D-Link DNS-320 which is happily humming away in my shed.

Pre-requesits

This guide presumes that you have already got fun_plug up and running on your target fun_plug device. Before you can configure and run the GMVault script, you will need to install Python 2.6 or greater, this is achieved via slacker.

sudo slacker -a python

I installed the Python 2.7 Package from Mijzelf’s repository. Once Python’s installed, you’ll need to grab the setuptools Python package.

wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg
sudo sh setuptools-0.6c11-py2.7.egg

Once you’ve installed the python package, you can grab the latest GMVault source from their website; you will want to download the archive to your target box with wget and untar it:

wget https://github.com/downloads/gaubert/gmvault/gmvault-v1.7-beta-src.tar.gz
tar -zxvf gmvault-v1.7-beta-src.tar.gz

After studying the README file, you’ll want to install the script via:

sudo python setup.py install

If you run out of disk space whilst installing GMVault then you’ll probably need to re-locate your /tmp directory; this can be achieved with a quick:

rm -rf /tmp && ln -s /ffp/tmp /tmp && chmod 1777 /tmp

Once the script is install you should be able to invoke:

gmvault

If this fails with the error:

-sh: /ffp/bin/gmvault: /bin/bash: bad interpreter: No such file or directory

Then you need to setup a symbolic link to where fun_plug stores the bash interpretor:

sudo ln -s /ffp/bin/bash /bin/bash

Once gmvault is installed, you can start the syncing process by issuing:

gmvault sync you@gmail.com

Once the initial sync completes, you will want to setup a cronjob so the sync happens automatically. This can easily be achieved by adding a line to your /var/spool/cron file, eg:

# GMVault Sync, 2AM daily.
0 2 * * * /ffp/bin/gmvault sync you@gmail.com -t quick

QUnit and RequireJS – Breaking your Tests into modules

Modular application development is essential when working on a large project with more than a handful of developers. Breaking your code into separate modules improves code legibility and organization making it easier to locate logic and help create ‘seams’ in your code so you can do your best to adhere to Single Responsibility Principle. This is all well and good for your application code, but what about the Unit Tests which support it – how can we decompose these tests into modules so they’re well organized and easy to find?

Test Case Structure

First things first, you need to get your Unit Tests broken up into separate test cases. QUnit provides the QUnit.module method which takes care of this, allowing your to group tests in the QUnit test runner. We can extend this metaphor further by ensuring that each QUnit module resides in its own file, or, in other words – each application module has it’s own QUnit module of tests.

Here’s an example of a simple QUnit Test Case defined as a RequireJS module:

define(function (require) {

    // Import depdendencies (note you can use relative paths here)
    var PegiRatings = require("./PegiRatings");

    // Define the QUnit module and lifecycle.
    QUnit.module("example/model/PegiRatings");

    QUnit.test("isSuitibleFor - younger age supplied, returns false", function () { 
        QUnit.equal(PegiRatings.PEGI_18.isSuitibleFor(17), false);
    });

    QUnit.test("isSuitibleFor - same age supplied, returns true", function () { 
        QUnit.equal(PegiRatings.PEGI_18.isSuitibleFor(18), true);
    });

    QUnit.test("isSuitibleFor - older age supplied, returns true", function () { 
        QUnit.equal(PegiRatings.PEGI_18.isSuitibleFor(19), true);
    });
});

As you can see above, we are able to use require to import other modules from the src folder into the test case (in the above example we are including the PegiRatings object, which just happens to be the module under test). Here’s another example where we pull in not only other modules from the source tree, but also a vendor library (the ever popular, underscore.js):

define(function (require) {

    // Import depdendencies.
    var _ = require("vendor/underscore");
    var Player = require("./Player");
    var Game = require("./Game");
    var PegiRatings = require("./PegiRatings");

    // ... rest of test case omitted for brevity

});

Configuring QUnit and RequireJS

Now that we have our unit tests split out into separate modules, we need to configure the QUnit Test Runner so that it will work with RequireJS to resolve the dependencies. The first step is to modify the stock QUnit Test Runner HTML document so RequireJS is loaded along with all our testcases.

<!DOCTYPE html>
<html>
    <head>
        <title>Example Test Runner</title>
        <link rel="stylesheet" href="vendor/qunit.css" />

        <!-- QUnit includes -->
        <script src="vendor/qunit.js"></script>

        <!-- Load RequireJS & the testsuite -->
        <script src="../src/require-config.js"></script>
        <script src="../src/vendor/require.js" data-main="testsuite.js"></script>
    </head>
    <body>
        <div id="qunit"></div>
    </body>
</html>

In a typical QUnit Test Runner setup you would include your tests.js file which included all your QUnit tests. Instead we load the project’s RequireJS configuration file (which is also used by the main project, to avoid duplication of configuration settings between the tests and the build) and then RequireJS itself with a callback to the testsuite.js file.

(function () {

    // Defer Qunit so RequireJS can work its magic and resolve all modules.
    QUnit.config.autostart = false;

    // Configure RequireJS so it resolves relative module paths from the `src`
    // folder.
    require.config({
        baseUrl: "../src",
    });

    // A list of all QUnit test Modules.  Make sure you include the `.js` 
    // extension so RequireJS resolves them as relative paths rather than using
    // the `baseUrl` value supplied above.
    var testModules = [
        "example/model/PlayerTests.js",
        "example/model/PegiRatingsTests.js"
    ];

    // Resolve all testModules and then start the Test Runner.
    require(testModules, QUnit.start);
}());

This file configures RequireJS ready for our Unit Test run and also provides a list of all test cases that we wish to execute. Once RequireJS has finished loading all the test cases, it makes a call to QUnit.start which kicks off the Test Runner.

Example Project Download

I’ve pushed all the source for this example project to the qunit-require GitHub Repo. You can download the zipball and run the tests to gain a better understanding of the project structure.

Listening for Slide Start and Slide Stop Events from jQuery Mobile 1.1 Sliders

jQuery Mobile provides a neat little slider control; however, the version 1.1 release doesn’t behave very well and fails to dispatch the expected start and stop events triggered by jQuery UI’s slider control. This issue has been raised on jQuery Mobile’s GitHub Issue Tracker but it looks like it won’t be addressed until jQuery Mobile 1.2

The code below is a patch which you can drop into your application’s startup routine; it adds a couple of event listeners to the DOM which will trigger the start and stop events based on the user’s interaction with the slider’s thumb and track.

$(document).on({
    "mousedown touchstart": function () {
        $(this).siblings("input").trigger("start");
    },
    "mouseup touchend": function () {
        $(this).siblings("input").trigger("stop");
    }
}, ".ui-slider");

In a nutshell, it binds an event listener to the document object which listens for both mousedown and touchstart events triggered from .ui-slider elements. Once triggered the handler function will find the input element which sits alongside the .ui-slider control that was interacted with and trigger the corresponding event. You can consume these events like so:

$("#my-slider").on("start", function () { 
    console.log("User has started sliding my-slider!");
});

$("#my-slider").on("stop", function (event) {
    var value = event.target.value;
    console.log("User has finished sliding my slider, final value: " + value);
});

As always, you can also subscribe to the slider’s change event if you want to listen for the actual slide.

$("#my-slider").on("change", function (event) {
    var value = event.target.value;
    console.log("Slider is moving, it's value is now: " + value);
});

Streaming Video from Azure Blob Storage

By default Azure Blob Storage and Video do not mix well; the first hurdle that developers must get over is that the Content Type for the video must be set correctly (for .mp4 videos that’s usually video/mp4).

The next problem that you’ll face is that the video will not seek correctly; trying to jump forward or backwards in the video won’t work.

This is resolved by changing the DefaultServiceVersion to 2011-08-18 which can be achieved via the Azure’s REST API, or the Managed C# Library as laid out at the end of this blog post.

var account = CloudStorageAccount.Parse(ConnectionString);
var blobClient = account.CreateCloudBlobClient();
blobClient.SetServiceSettings(new ServiceSettings()
        {
            DefaultServiceVersion = "2011-08-18"
        });

Getting Started with Node JS and Redis on Mac

This weekend I’ve been hacking away on a new project and learning some new technologies in the process. In the past, my default go-to webapp stack has been the classic combination of PHP and MySQL; this time around I thought I would mix things up by giving Node JS a whirl coupled with Redis, a high speed Key/Value store (perfect for pulling back un-related hashes from a datastore).

Getting Node JS installed on mac is very straight forward thanks to the fact Node JS offer a pre-compiled binary for Mac complete with installer on their download page. Running a Node server is really simple, a quick node main.js suffices, however, it gets a bit tedious having to continuously terminate and relaunch the Node server each time you make a change; that’s where node-supervisor comes in. Node-Supervisor will watch your application’s source files and relaunch your server each time one of them changes. Installation is nice and easy via sudo npm install -g supervisor

Note: As supervisor is a command-line utility we want to install it globally so it is globally available, like any other command line application, on the host system.

With Node-Supervisor installed, you can launch it with supervisor main.js and it will take care of the rest… neat!

Redis was a little bit tricker as they only offer sources on their download page. Instead of compiling from source I opted to use use homebrew, a package manager for Mac. Install homebrew is a snap, just drop the one-liner from their install guide into the terminal and it takes care of the rest. Once homebrew’s installed, you should run homebrew doctor to let you know if there’s any issues. If like me, you are missing a compiler on your Mac then you will want to go and download the XCode Command Line Tools from Apple’s developer site.

Once the tools are installed, homebrew doctor still gave the following, slightly cryptic warning:

Error: Your Xcode is configured with an invalid path.
You should change it to the correct path. Please note that there is no correct
path at this time if you have *only* installed the Command Line Tools for Xcode.
If your Xcode is pre-4.3 or you installed the whole of Xcode 4.3 then one of
these is (probably) what you want:

    sudo xcode-select -switch /Developer
    sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer

I had nether of those paths on my system, nor did I have Xcode installed (as I only oped to install the Command Line Tools). I chose to follow the Error message verbatim and just ignored it and went ahead with the redis install via brew install redis. With redis installed, you launch an instance with the default configuration via redis-server /usr/local/etc/redis.conf.

Now we have Node and Redis installed on the system it’s time to start writing some code which brings the two together. The following example makes use of express, a server-side framework.

var app = require('express').createServer();
var db = require("redis").createClient();

// Response to GET requests to /user/{userId}
app.get('/user/:id', function(req, res, next) {
	var userId = req.params.id;
	var key = 'users.' + userId;
	
	// Pull down the hash we have for this user from Redis.
	db.hgetall(key, function(err, reply) { 
    	
	// Redis has responded with an error.
    	if (err) {
    		
    		// Push the exception onto the next piece of express middleware.
    		next(err);
    	}
    	
    	// Redis has returned a record for this user.
    	else if (reply) {
    		
    		// Dump out the stored User object.
    		res.send(JSON.stringify(reply, null, 2));
    	}
    	
    	// Redis has no entry for this user.
    	else {

    		// Create a new User object.
    		userData = {
    			userId: userId,
    			luckyNumber: (Math.random() * 10).toFixed(0)
    		};
    		
    		// Store it in Redis.
    		db.hmset(key, userData, function () { 
    			res.send("Created new user: " + userId);	
    		});
    	}
    });
});

// Start the express app on port 1337.
app.listen(1337);

To test the app, just head on over to http://localhost:1337/users/jonny to create the first record; and refreshing the page will show you the user data object.

Although I’ve only just started playing around with Node JS, I’m really enjoying the rapid development it offers as well as the chance to explore an entire new stack :)

Unit Testing Async JavaScript with Promises and Stubs

Asynchronous code lies at the heart of front end development; in order to make your application feel responsive you can’t afford to block execution until some external data has been read. Promises are a well understood design pattern to help encapsulate the state of an asynchronous action. A Promise will only ever transfer from a pending state (ie: when the initial request has been made to the server) to a resolved state. The resolved state can be one of either a failure state (ie: the server sends back a 500 error) or a success state (ie: the JSON data you were expecting has come back). Once a promise has transferred to a resolved state it will not change (it becomes immutable). By employing this pattern you can write some very succinct code which is both easy to read and maintain:

service.fetch("someData")
	.then(function (response) { /* process response */ });
	.otherwise(function (error) { /* handle the error */ });

The code above makes use of Brain Cavalier’s excellent when.js Promises implementation. The rest of this post aims to highlight how you can combine when.js with a mocking framework to make unit testing Promises a piece of cake. If you would still like to learn more about using Promises, and how they make writing asynchronous code easier, then I’d suggest reading his excellent articles on the subject.

Why mock Promises?

One of the golden rules of unit testing is that the code under test must be non-deterministic. Another golden rule is that unit tests must be fast to execute. Although Promises make writing asynchronous code easier, they don’t help with the two points above, take the following example:

// Example of a module that abstracts a RESTful web service.
var service = {
	fetch: function (query) {
		// Returns a when.js Promise which will resolve when the data
		// has been fetched.
		return when(jQuery.get("http://myservice.com/api?q=" + query));
	}
};

// A client object which consumes the Service, this is what we are going to be 
// unit testing.
var client = {
	
	// Returns a promise which will yield the number of pages returned
	// the supplied query.
	getNumPages: function (query) {
		
		// Create a fresh service instance.
		var service = createService();
		
		// Return a promise which will resolve after the following
		// `then` block has performed.
		return service.fetch(query)
			.then(function (response) { 
			
				// Modifies the result of the Service's Promise,
				// future success handlers will reicieve the
				// number of pages instead of the response data.
				return JSON.parse(response).pages.length;
			});
	}
}

Unit testing the above client is pretty easy; a simple test-case could look like this (This example will be based on QUnit):

asyncTest("getNumPages fetches expected number of pages", function () { 
	
	// A special query which we know will return the expected number of pages.
	client.getNumPages("testcase-query")
		.then(function (numPages) { 
			equal(numPages, 5, "5 pages returned");
			start();
		});
});

Although the above test case is easy to read, it doesn’t make for a very good unit test for the following reasons:

  • It’s deterministic – if the server over at myservice.com is down, or you try and execute these unit tests offline then the test will fail (infact, it will hang the test-runner as it waits for this asyncTest to complete.)
  • It’s not going to be fast – a connection needs to be established to the server.
  • It only tests the success state – we need to test what happens if the service is down, but there’s no obvious way to do that (other than to request an invalid query value from the API.

This is where a mocking framework comes in – it will help us solve all three of the problems listed above.

Promises, Lies and stubbing the truth

A mocking framework allows you to alter the way functions behave during a unit test. Mocking frameworks are especially powerful in dynamic languages, like JavaScript, as they are able to make large changes to your codebase for a given unit test and then restore all those changes immediately after the test completes. This tutorial is going to be looking at Sinon.js.

As mentioned above, Sinon.js is able to completely rewrite a function during a test-case, let’s revisit our service module above:

test("Sinon.js stubbing example", function () {
	// Use sinon.js to redefine the `service.fetch` function.
	sinon.stub(service, 'fetch').returns("Hello!");
	
	// Now when we call it, instead of invoking `jQuery.get`, it returns a String.
	equal(service.fetch("testcase-data"), "Hello!");
});

The above example isn’t very useful; however, instead of returning a String, we can just as easily return a Promise object, and that’s when things start getting useful:

test("Stubbing the service so it returns an expected response", function () { 
    
	// Stub the service so it returns a resolved promise.  Note that `when(value)`
	// is a neat short-cut for creating a Deferred and resolving it.
	var expectedResponse = '{ "pages": [ "page1", "page2", "page3" ]}';
	sinon.stub(service, 'fetch').returns(when(expectedResponse));
    
	// Call the client...
	client.getNumPages('testcase-query')
		.then(function (numPages) { 
			strictEqual(numPages, 3, "3 pages returned");
		});
});

Note that the above test-case didn’t need to make user of QUnits asyncTest block – that’s because the expectedPromise Promise object has already been resolved – no need to wait for anything to complete asynchronously. Our test is no longer reliant on the server (hence non-deterministic) and it no longer relies on a service call (and will therefore execute almost instantly). That leaves only one last point from our rules above – how to test the failure path…

test("Simulating a service failure", function () { 
	
	// Again, start by stubbing our service's fetch method.  This time we will
	// return a rejected Promise with an error.
	var expectedError = new Error("Bad Query");
	sinon.stub(service, 'fetch').returns(when.reject(expectedError));
	
	// Call the client and expect it to fail
	client.getNumPages('testcase-query')
		.otherwise(function (error) { 
			strictEqual(error, expectedError, "Error from API provided to handler");
		});
});

Hopefully this post has been useful in highlight just a couple of the ways in which Promises and a mocking framework can be combined to remove both non-determinism, and slow execution speed from your tests as well as making it easy to test all paths of your code, even if they depend on external data. I’ve create a gist which shows a few other techniques which can be employed for unit testing Promises including the use of Sinon’s yieldTo method which makes it easy to resolve, or reject a Promise resolver supplied as an argument.

jQuery – A single click handler for multiple buttons.

Event bubbling is a wonderful thing; in ActionScript mouse events would readily bubble up through the DisplayList all the way up to the Stage allowing you to add a single event Handler to a parent DisplayObject and then inspecting the event.target property to determine which child button the user had interacted with. The same is true in JavaScript; but instead of events bubbling up the DisplayList they bubble up through the DOM.

Take the following example, here we have three buttons that we want to respond to when they’re clicked:

The HTML for this button group is nice and simple, making use the excellent jQuery mobile:

<div id="screen-selector" data-role="navbar">
	<ul>
		<li><a href="#" class="ui-btn-active">Applications</a></li>
		<li><a href="#">Properties</a></li>
		<li><a href="#">Events</a></li>
	</ul>
</div>

We can easily bind a click event handler to the #screen-selector element which will capture the click events as they bubble up the DOM.

$('#screen-selector').on('click', function(event) {
	console.log("You clicked on: ", event.target);
}

This almost works as desired, but not quite. jQuery Mobile does some magic behind the scenes to transform our button markup into a more complex design, this results in the event.target of the click event being child elements of the <a> tag:

Instead, what we really want is to know which <a> element the user clicked so we can tie it back to the buttons in our original HTML. In ActionScript this could be solved quite easily by setting the mouseChildren attribute of the button DisplayObjects to false, ie:

var buttons : Array = [ getChildByName("btnApplications"), getChildByName("btnProperties"), getChildByName("btnEvents") ];
for each (var button : Sprite in buttons) {
	// Disable mouse interaction with any children nested within the button's DisplayObject.
	button.mouseChildren = false;
}

JavaScript lacks the ability to toggle the mouse interactivity of nested elements, but luckily jQuery comes to the rescue with the closest traversal method. This method will walk up the DOM tree until if finds the first element that matches the supplied selector. In our case we just want to walk up from the click event’s target element until we find an <a> tag:

$('#screen-selector').on('click', function(event) {
	var button = $(event.target).closest('a');
	console.log("You clicked on:", button);
}

This now logs the desired <a> tag for the clicked button!

This code can be improved one step further by passing a selector argument to jQuery’s on method. jQuery will ensure that the event handler function is only called if the selector matches the event’s current target; in our case – we only want it to trigger when it hits an <a> tag, so we can write:

$('#screen-selector').on('click', 'a', function(event) {
	var button = $(event.target);
	console.log("You clicked on:", button);
}

The last piece of the puzzle comes from creating a mapping between the button the user clicked on and the action we want to take. Again, Flash provided a really easy way to do this in the form of the DisplayObject.name property which your button handler could read.

function onButtonClicked(event : MouseEvent) : void { 
	var button : DisplayObject = event.target as DisplayObject;
	trace("You clicked on:", button.name);
}

The buttons created by jQuery mobile don't offer any form of name identifier; one simple solution would be to simply add an id attribute to the <a> tag; however element id's must always be unique which isn't really want we are after (we just want to identify this button group apart, rather than having to ensure these buttons have a unique id across the entire DOM). The option I've settled on is to add a custom data attribute to each <a> tag in the form of a data-name attribute:

<div id="screen-selector" data-role="navbar">
	<ul>
		<li><a href="#" class="ui-btn-active" data-name="applications">Applications</a></li>
		<li><a href="#" data-name="properties">Properties</a></li>
		<li><a href="#" data-name="events">Events</a></li>
	</ul>
</div>

We can now modify our click event handler to read the data-name attribute from the clicked <a> element:

$('#screen-selector').on('click', function(event) {
	// Retrieve the 'name' data attribute of the <a/> tag that the user clicked.
	var name = $(event.target).closest('a').data('name');
	console.log("You clicked on:", name);
});

Which gives us our desired effect! :)

ANT, Windows and NodeJS Modules.

The project I am working on makes use of NodeJS Modules for linting (via the JSHint) and running unit tests (thanks to QUnit); to automate the build process I chose to fall back to my good old swiss-army knife, Apache ANT. However, it quickly became apparent that the combination of ANT, Windows and Node didn’t play nicely together.

My first attempt, after installing the JSHint NodeJS Module was to simple <exec> it:

<exec executable="jshint" failonerror="true">
	<arg value="${src.dir}"/>
</exec>

However, this didn’t quite work as expected…

BUILD FAILED
C:\Users\jreeves\Project\build.xml:6: Execute failed: java.io.IOException: Cannot run program "jshint": CreateProcess error=2, The system cannot find the file specified
        at java.lang.ProcessBuilder.start(Unknown Source)

A quick bit of digging revealed that NodeJS modules are batch files on Windows which reside in your %APP_DATA% folder; ANT doesn’t play well with Batch files and you have to pipe them through cmd.exe first.

<exec executable="cmd.exe" failonerror="true">
	<arg value="/c jshint ${src.dir}"/>
</exec>

This provided the following output:

[exec] Result: 1
BUILD SUCCESSFUL
Total time: 0 seconds

Success! But hang on, that’s not right, I know for a fact that my source files don’t lint correctly at this stage, and shouldn’t there be some kind of output from jshint… This is when I started to realise that ANT doesn’t pass either the output, nor the error code back from any process which batch files spawn (node.exe in the case of jshint.bat). After quite a bit of digging I stumbled upon this buried answer on StackOverflow from Darcy Parker – it’s thanks to his own research that I we have a workaround to this bug!

To wrap this post up, I’ve created a simple macro which you can drop into your ANT script to ensure that NodeJS Modules are invoked correctly on both Windows and Unix systems:

<macrodef name="exec-node">
	<attribute name="module" description="The name of the NodeJS module to execute"/>
	<attribute name="failonerror" default="true" description="Fail if the exit code is not 0"/>
	<element name="args" implicit="yes" description="Argument to pass to the exec task"/>
	<sequential>
		<exec executable="cmd.exe" failonerror="@{failonerror}" osfamily="winnt">
			<arg line="/c  @{module}" />
			<args/>
				
			<!-- Windows cmd output workaround: http://stackoverflow.com/a/10359327/227349 -->
			<!-- Forces node's stderror and stdout to a temporary file -->
			<arg line=" &gt; _tempfile.out 2&lt;&amp;1"/>

			<!-- If command exits with an error, then output the temporary file 		  -->
			<!-- to stdout delete the temporary file and finally exit with error level 1  -->
			<!-- so that the apply task can catch the error if @failonerror="true"        -->
			<arg line=" || (type _tempfile.out &amp; del _tempfile.out &amp; exit /b 1)"/>

			<!-- Otherwise, just type the temporary file and delete it-->
			<arg line=" &amp; type _tempfile.out &amp; del _tempfile.out &amp;"/>
		</exec>
		<exec executable="@{module}" failonerror="@{failonerror}" osfamily="unix">
			<args/>
		</exec>
	</sequential>
</macrodef>

You can now make use of this macro in your targets and it will work on both Windows, and Unix systems:

<exec-node module="jshint">
	<arg value="${src.dir}" />
</exec-node>