JavaScript: The Good Parts

July 18, 2010

I’ve been a huge fan of Douglas Crockford and his articles about JavaScript for a long time. I often point people to his The World’s Most Misunderstood Programming Language article when I hear them complaining about the language. It’s taken me a couple of years to get around to reading his book, JavaScript: The Good Parts, but it exceeded all of my expectations.

Being an avid reader of his online stuff, and having watched various talks of his I knew the book would be well written and informative, but I thought it’d probably just repeat much of what I’d already read, without providing much new information or insights. To a certain extent this was true, the book does reiterate what’s said in many of his online articles and talks, but the book is absolutely amazing for a different reason: The code examples.

The book is extremely succinct. There’s no padding, and very little dialog to join one section to the next. There is a common thread thoughout the book though, and that’s the code. Examples of good coding practices are repeated, and functions written in earlier chapters are often reused in later ones. So although the book appears to be presenting one feature at a time with a small code example you’re actually building up more and more complex javascript applications, and the book ends with a full JSON parser!

Crockford’s coding style seems to match his writing style: succinct and to the point. There’s some really great code in the book, that I think even non-JavaScript developers could appreciate. Here’s my favourite, from the chapter on regular expressions:

var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
var url = 'http://www.ora.com:80/goodparts?q#fragment';
 
var result = parse_url.exec(url);
var names = ['url', 'scheme', 'slash', 'host', 'port', 'path', 'query', 'hash'];
var blanks = '       ';
var i;
for (i = 0; i < names.length; i += 1) {
    document.writeln(names[i] + ':' + blanks.substring(names[i].length), result[i]);
}

Which outputs:

url:    http://www.ora.com:80/goodparts?q#fragment
scheme: http
slash:  //
host:   www.ora.com
port:   80
path:   goodparts
query:  q
hash:   fragment

I also love the explanations Crockford gives as to why he avoids using certain parts of JavaScript, and limits himself to a “good” subset of the language. He doesn’t simply say “This is bad and you shouldn’t use it”, it’s usually accompanied by a story about a time when Crockford had used that feature and got caught out, which is much more compelling.

I think it’s fair to say that JavaScript: The Good Parts is one of my favourite programming books: It’s succinct, packed full of great code examples and best practices for writing maintainable and bug free code. It’s a fantastic JavaScript reference, but much of what the book talks about is relevant to programming in general. Highly recommended!

Recursively Drawing Trees with JavaScript and Canvas

November 22, 2009

I have written an article titled Graphics Programming with Canvas for the upcoming December 2009 edition of JSMag. One of the examples I came up with for the article was a recursive tree drawing algorithm. I had quite a bit of fun tweaking different values and seeing what sort of tree would be produced. After a while it got a bit boring changing a value, saving the JavaScript and then refreshing the page, so with the help of jQuery UI I came up with an interactive version. Below are a couple of tree images I’ve generated with the tool:

tree

tree


You can view the page source to see what’s going on behind the scenes, but for full details check out the December edition of JSMag. Give it a try for yourself, generate your own tree!

Debugging Javascript in Internet Explorer 6

May 16, 2009

If you’ve ever got to work with javascript and IE6 then you might want to read the guest post I wrote for Six Revisions: Debugging Javascript in Internet Explorer 6.

The post describes how to configure IE6 so that instead of displaying subtle and cryptic error messages when you run into a Javascript issue it will instead allow you to debug the problem with the help of Visual Studio’s powerful debugger. I’ve put together a small slideshow that includes a summary of the content:

Javascript, JSON and PHP

March 29, 2009

JSON data is commonly used as a simple way to send data back to client side javascript from the server. For example, a PHP script may output the following JSON to confirm that an action was taken:

{success: true, message: "It worked!"}

or in the case of failure:

{success: fase, message: "It didn't work!"}

Below is a basic javascript callback function to process the JSON data, displaying the returned message:

function callback(data) {
    if(data.success) alert(data.message);
    else alert('ERROR:' + data.message);
}

Sometimes it’s actually useful to send back javascript code to in the JSON data, to be run on the client. For example, if an Ajax request is made that updates some account information we could return javascript code to update several parts of the page with the new information. Here’s PHP code that outputs JSON data which includes javascript code:

$response = array('success' => 'true',
    'code' => "jQuery('#id').html('Success!');");
echo json_encode($response);
// Outputs {success: true, code: "jQuery('#id').html('Success!');"}

Note how in the returned JSON data “code” is actually a string, so it won’t be possible to run the code simply by doing “data.code()” on the client. Instead we must explicitly tell javascript to evaluate the string as code. Below is an example of how we can do this using eval:

function callback(data) {
    if(data.success && data.code) eval(data.code);
}

If we wanted to update the page with HTML more complicate the the simple “Success!” message in the previous example we must be careful to escape any quotes in the HTML correctly. If we wanted to set the content to: “Javascript”, “json”, “PHP” then we’d need to do the following:

$response = array('success' => 'true',
    'code' => "jQuery('#id').html('\"Javascript\", \"json\", \"PHP"');");
echo json_encode($response);

And It’s easy to imagine a far more complicated example. The code becomes less readable, and if you accidentally forget to escape one of the quotes, or escape of the quotes that shouldn’t be escaped, then the whole thing breaks. A nice alternative is ty store the HTML as a separate JSON property and then to reference it, avoiding the need to escape the quotes and making the code easier to read:

$response = array('success' => 'true',
    'html' => '"Javascript", "json", "PHP"',
    'code' => "jQuery('#id').html(this.html);");
echo json_encode($response);

However, to make the “this.html” reference work the clients side callback function will need to changed, as eval() runs the code in global scope. This means that “this.html” will refer to a global html variable rather than the one in our JSON data. We can get around this problem by using the apply function as follows:

function callback(data) {
    if(data.success && data.code) {
        var f = new Function(data.code);
        f.apply(data);
    }
}

And here’s a complete example which uses jQuery to perform the Ajax call:

jQuery.get('update.php', {} function(data) {
    if(data.success && data.code) {
        var f = new Function(data.code);
        f.apply(data);
    }, 'json');

jQuery Draggable Implementation

February 16, 2009

jQuery UI is an excellent add-on library for jQuery that provides all sorts of UI widgets, effects and behaviours. One particularly useful function is provides is to make any element on the page draggable, so that it can be moved about with the mouse.

Because of all the features that jQuery UI provides the library is fairly large, about 450KB uncompressed. It is possible to only include specific parts of the library, but even the bare minimum required for the draggables feature weighs in at just over 40KB uncompressed.

Therefore I decided to write my own lightweight draggable implementation using only jQuery. The code is shown below:

// Make an element draggable using jQuery
var makeDraggable = function(element) {
	element = jQuery(element);

	// Move the element by the amount of change in the mouse position
	var move = function(event) {
		if(element.data('mouseMove')) {
			var changeX = event.clientX - element.data('mouseX');
			var changeY = event.clientY - element.data('mouseY');

			var newX = parseInt(element.css('left')) + changeX;
			var newY = parseInt(element.css('top')) + changeY;

			element.css('left', newX);
			element.css('top', newY);

			element.data('mouseX', event.clientX);
			element.data('mouseY', event.clientY);
		}
	}

	element.mousedown(function(event) {
		element.data('mouseMove', true);
		element.data('mouseX', event.clientX);
		element.data('mouseY', event.clientY);
	});

	element.parents(':last').mouseup(function() {
		element.data('mouseMove', false);
	});

	element.mouseout(move);
	element.mousemove(move);
}

The element you pass to makeDraggable should already have absolute or fixed CSS positioning, and a top and left CSS value set. Something like the following:

<div id='draggable' style='position: absolute; top: 100; left: 200; padding: 50px; background: black; border: 2px solid #aaa;'>
This box is draggable!
</div>
<script type="text/javascript">
makeDraggable(jQuery('#draggable'));
</script>

Then just click on the div and move the mouse to drag it around.

Obviously it isn’t as flexible as the jQuery UI version, but it is a useful alternative if you want to save on the amount of data your user’s will need to download and you don’t require any other jQuery UI features.

Older Posts »