Reserved JavaScript Words in Safari

Posted by Jack Hsu Fri, 12 Feb 2010 17:35:00 GMT

I ran into a problem today where the RIA I’m building works for all browsers except Safari – specifically Safari 4, not sure about 3.

The error happens when a certain page loads, and all I’m greeted with in Safar is `SyntaxError: Parser Error`. Nice.

After a little debugging and Googling, I realized that one of the objects I had setup used a property that was a JavaScript reserved word. For whatever reason, SquirrelFish (Safari 4’s JS engine) was the only engine to throw this error.

So something like this would work in all browsers except Safari:

// Parse Error in Safari 4
var myObject = {
    enum: 1,
    class: 'foobar',
    faz: 'baz'
};

Instead, you need to wrap reserved words around quotation marks.

// Works in Safari 4 now
var myObject = {
    'enum': 1,
    'class': 'foobar',
    faz: 'baz'
};

I’m not sure if SquirrelFish is correct, or the other engines. The inconsistency is a bit annoying though.

Not all jQuery selectors are created equal 2

Posted by Jack Hsu Thu, 24 Dec 2009 14:36:00 GMT

The good thing about JavaScript libraries such as jQuery is that developers can focus on functionality without having to worry too much about cross-browser compatibility. However, often times it is still very useful to know why happens behind the abstractions.

The most used feature in jQuery is the CSS selector. Instead of selecting elements using pure DOM (e.g. document.getElementById(‘myId’)), you’re able to use jQuery’s CSS selector (e.g. $(‘#myId’)). This makes life much, much easier.

There are cases, however, where not knowing what happens behind the scenes can lead to poor implementations, causing big performance hits. One such case is the class selector (e.g. $(‘.someClass’)).

The reason why class selector is slow is because it has to go through the entire DOM to find those elements. Of course, some browsers like Firefox 3+ has native support for document.getElementsByClassName. And as John Resig analyzed, the native method is much faster than the next fastest implementation (XPath). But if you want your applications to run as fast as possible on as many browsers as possible, it’s better to avoid the class selector all-together (at least for now).

What you can do instead is to use the next fastest selector (behind ID selector), the tag name selector.

So instead of doing $(‘.someClass’), use $(‘div.someClass’), or whichever HTML tag name you want to use. This selector is faster because instead of checking the entire DOM, now it only needs to check against elements with that particular tag name. That is, it first does a document.getElementsByTagName(‘div’), then iterates through that list.

Or why not make it even faster by specifying an ancestor element by its ID? (e.g. $(‘#ancestor div.someClass’))

The thing to keep in mind is, no matter what abstractions come about, it’s still a very good idea to understand what happens underneath the hood. :)

JavaScript: Optimizing loops

Posted by Jack Hsu Wed, 23 Dec 2009 20:35:00 GMT

When looping through very large arrays, you may find this tip useful: it’s much fast to use a while loop to iterate through an array than a for loop.

For example, if you take this code:

var myArray = new Array(10000);
for (var i=0; i<myArray.length; i++) {
    myArray[i] = i;
}

You can make it run faster by using a while loop instead.

var myArray = new Array(10000);
var n = myArray.length;
while (n--) {
    myArray[n] = n;
}

This works because n-- will return the value of n and then decrement it. So when it approaches index zero, it’ll coerce 1 to true, then decrement n before the line myArray[n] = n;.

Of course, this while-loop is looping backwards, so if the order of iteration does matter then you can’t use this method. You could however, still optimize the first example by first assigning myArray.length to a variable, then using that in the for-loop’s exit condition. This will make it run slightly faster (depending on which browser you’re using) because it avoids a property lookup at every loop iteration.

var myArray = new Array(10000);
var n = myArray.length;
for (var i=0; i<n; i++) {
    myArray[i] = i;
}

Cheating on Speed Sudoku -- How to Prevent Greasemonkey Scripts

Posted by Jack Hsu Thu, 07 May 2009 15:24:00 GMT

I recently read about Speed Sudoku in a Globe and Mail article. It’s a website that allows player to compete against each other in a race to solve Sudoku puzzles. Players are given points based on their performance in a game – I’m unsure how the point system works – and these points are used to rank them on the scoreboard. As of this writing, the top player is named "WaterlooMathie" (woot for Waterloo).

Anyway. I decided to write a Greasemonkey script to automatically solve these puzzles. The technique I chose is a simple Backtracking algorithm with cells chosen based on the Most Restrained Variable. *Disclaimer: I’m not planning on climbing to the top of the scoreboard using this script, it’s just for fun.

[See script here]

Nothing too fancy. In fact, the code can be tuned further to perform better – meh. But the results are pretty good. I’m able to solve the Very Hard puzzles on my Mac instantly on page load.

Even though I’m not going to cheat on Speed Sudoku, I’m sure others will, or already have. In fact, you can report users you suspect of cheating to the site admins.

This raises a question for me: How do you prevent Greasemonkey scripts from executing on your website?

The answer lies with how Greasemonkey scripts are fired – it listens to the DomContentLoaded event. To script execution you simply put this piece of code at the top of your page.

document.addEventListener("DOMContentLoaded", function(ev) {
    ev.stopPropagation();
}, false);

This will attach your anonymous function to the same event listener (which will execute first), and we simply need to stop the event from propagating.

You might run into cases where you do want your own functions (attached to DOMContentLoaded event) to fire. In these cases, you could create your own custom events, listen on those, and fire them in the anonymous function after.

Of course, users can still cheat by other means, but at least this can prevent Greasemonkey cheats. That said, I’m against prevent Greasemonkey scripts. I love the addon, and it adds functionality to websites that I can’t live without.

Not Another IE6 Rant

Posted by Jack Hsu Tue, 21 Apr 2009 16:11:00 GMT

For the last few months I’ve seen some aggressive campaigning to rid the online world of Internet Explorer 6. Many web developers and designers have been supporting this browser for what seems like forever, and now that IE6 is losing market shares fast, it seems like a good time to make the final push to kill it.

While I whole-heartedly agree that we’ll all be better off without IE6, I don’t agree with providing zero support for the browser. Let’s face it, the whole "browser X is outdated" thing isn’t new and will always be here to haunt us – remember Netscape 4?

I don’t mind providing users with a nice message about why they should upgrade their browsers, as long as it doesn’t obstruct workflow, and they need to have an option to never be bugged again. But please, please do not do something stupid like the #ie6update script. It’s wrong on many levels, and there is a good post on why it’s wrong.

The best way to approach older browsers, I think, is to use to use graceful degradation (older concept) or progressive enhancement (better). With the latter approach, you design your website for the lowest common denominator and progressively enhance it to improve user experience for newer, more advanced browsers. Of course, while PE sounds nice in theory, it does require a fair amount of discipline in practice.

And let’s not forget that there are JavaScript libraries out there to help developers cope with IE6, and even IE7. The defacto IE6/7 library is ie7-js, which adds support for many CSS selectors that are lacking in IE6/7, as well as many other nice things.

There is also a JS library for detecting different browsers and operating systems. While I don’t personally like this approach, it may be cleaner than writing a lot of IE CSS hacks. Maybe.

Video manipulation in Firefox 3.1 using HTML 5

Posted by Jack Hsu Wed, 04 Mar 2009 20:34:00 GMT

Here’s an cool post from the Mozilla Developer Center regarding the new in Firefox 3.1. The demo featured is a video filmed with a green screen, and the green screen is replaced with an image in real-time using JavaScript.

Pretty neat stuff.

JavaScript, Anonymous Function, Closure, and You

Posted by Jack Hsu Sun, 15 Feb 2009 01:35:00 GMT

There are many things that web developers should know about JavaScript, but the most basic of things are anonymous functions and closure. Both are very powerful tools for anyone working with JavaScript.

So what’s so great about them you ask? Well, I think that’s best explained using some examples.

Let’s say we want to implement a function that will take an integer representing a month, and return it’s name as a string.
e.g. 1 -> ‘January’, 2 –>  ‘February’, 9 –> ‘September’

We’ll start out with a naive implementation, but perhaps one that first comes to mind.

function monthName(i) {
    var months = [
        'January',
        'February',
        'March',
        'April',
        'May',
        'June',
        'July',
        'August',
        'September',
        'October',
        'November',
        'December'
    ];

    return months[i-1];
}

Simple right? But there’s something wrong with this function. Take a look at the array declaration, it’s inside the function! That means everytime you call the monthsName function, it’ll create an array. This not only slows down your function, but it uses an unnecessary amount of memory.

Our first improvement then, would be to move the array to the outside of the function.

var months = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December'
];

function monthName(i) {
    return months[i-1];
}

Great, now we only create array once! But wait, there’s another problem. We’ve just moved the months array into the global namespace. This is bad because we might be overwriting a previously declared variable also named months. Similarly, someone later on might overwrite our months array. D’oh!

Fortunately, there is a way around this. And this is where anonymous functions and closure come in. Let me show you the solution first.

var monthName = function() {
    var months = [
        'January',
        'February',
        'March',
        'April',
        'May',
        'June',
        'July',
        'August',
        'September',
        'October',
        'November',
        'December'
    ];

    return function(i) {
        return months[i-1];
    };
}();

So how does this work?

First, you’ll notice the block of code inside the outter function is similar to our second solution, except that the function name has been dropped, and it is now the return value of the outter function. The outter function is executed immediately,  and is assigned to the variable monthName. Thus monthsName is really the inner function. Sort of.

Here is where closure comes in. The inner function refers to the months array declared outside of it, but because of closure, that array is bound to the function. So when we call the function monthName we are really calling the returned result of an anonymous function (which itself is an anonymous function). And this returned function has the months array bound to it.

Here’s another example using anonymous functions and closure to implement Partial Application in Javascript.

Function.prototype.papply= function() {
    var fixed = Array.prototype.slice.call(arguments),
        fn = this;
    return function() {
        return fn.apply(this, fixed.concat(Array.prototype.slice.call(arguments)));
    };
}   

Of course, you can probably achieve everything I’ve shown here without anonymous functions or closure, but why make it hard for yourself? Learn these tools, use them to your advantage!

Hello Interweb! 1

Posted by Jack Hsu Thu, 12 Feb 2009 02:03:00 GMT

This is my first attempt at a dedicated programming blog. More interesting posts are on their way, but for now here’s a little info about me!

In my short professional career (which includes several co-op jobs when I attended the University of Waterloo) I’ve mostly been in web development. Actually, I’ve been doing the whole web stuff since about mid-90s, starting with HTML, JavaScript and Perl. Just on my personal/hobby websites.

I’ve worked with many languages, but my current interests are JavaScript and Python. I am a huge fan of Django, and have used it on several projects, including GlobeCampus. I expect the majority of my posts in the near-future to be on JavaScript and Python. ;)

Currently, I’m working as a web developer at The Globe and Mail.