Adding .indexOf() to arrays in Internet Explorer

Most of you will already know this but hey, it doesn’t hurt to tell the tale again.

Looking up an array elements value by key is trivial:

var bar = someArray['foo'];

In actually working javascript implementations the reverse is simple, too:

'foo' == someArray.indexOf(bar); //will be true after the above code snippet

The actual API docs can be found over at Mozilla.org.

However, there is still this one JavaScript engine that is not only broken beyond repair but also lacks important features in the first place. I’m talling, of course, about our beloved Interbet Explorer.

Trying to use someArray.indexOf() in up to IE8 will result in an error message telling you that the object does not support this method.

So, let’s fix this!

if (typeof Array.prototype.indexOf !== 'function') {
    Array.prototype.indexOf = function(value) {
        for (var idx in this) {
            if (this.hasOwnProperty(idx)) {
                if (this[idx] == value) {
                    return idx;
                }
            }
        }
        return -1;
    }
}

This will check, if the engine that your script is running on already has the indexOf() method, and if not, it will simply add it to the Array prototype and by that to all present and future arrays.

Not exactly a game changer, but useful.

PHP style date formatting in JavaScript

A lot of people probably already know PHPs date formatting system and are quite familiar with it. Using formatting strings like “Y-m-d H:i:s” makes it really easy to produce nicely formatted date strings in a way that is relatively easy to remember since you probably use the same few formatting strings all the time. In combination with the much improved DateTime class in PHP 5.3 this gives you all the tools you need to work with dates and timestamps.

JavaScript has a very powerful and comfortable Date object, too. The only thing that’s missing is an output formatting method that doesn’t involve concatenating the strings from the single outputs of the Date object together manually.

So here it is: An extension of the Date object that replicates the functionality of PHPs formatting system:

/*
 * The following call returns a closure which has some helper functions and objects in it's scope.
 * The closure is then added to the Date prototype and will be available in all Date objects as the "format" method.
 */
Date.prototype.format = (function () {
    /*
     * Helper function for padding numbers with zeros on the left side
     * @private
     * @param {Number} number The input number that is to be padded
     * @param {Number} digits The number of digits of the resulting number
     * @return {String}
     */
    var pad = function(number, digits) {
        var padding = '';
        while ((number + padding).length < digits) {
            padding += '0';
        }
        return padding + number;
    };
    var weekDaysShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    var weekDaysLong  = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
    var monthsShort   = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

    /*
     * Helper method to determine if an hour in 24h format is AM or PM
     * @param {Number} h The hour in 24h Format
     * @return {String}
     * @private
     */
    var amPm = function(h) {
        if (h<=12) {
            return 'am';
        } else {
            return 'pm';
        }
    };

    /*
     * Constructor for the replacer object that provides methods for the format placeholders
     * @param {Date} The Date object that serves a s adata source for the string replacements
     * @constructor
     */
    var Replacer = function(d) {
        this.dO = d; //makes the passed Date object available to the Replacers prototype
    };
    Replacer.prototype = {
        d: function () {return pad(this.dO.getDate(), 2);},
        D: function () {return weekDaysShort[this.dO.getDay()];},
        j: function () {return this.dO.getDate();},
        l: function () {return weekDaysLong[this.dO.getDay()];},
        N: function () {return this.dO.getDay()+1;},
        S: function () {
            var n = this.dO.getDate();
            if (n == 11 || n==12 || n==13) {
                return 'st';
            }
            n = n % 10;
            switch (n) {
                case 1: return 'st';
                        break;
                case 2: return 'nd';
                        break;
                case 3: return 'rd';
                        break;
                default: return 'th';
            }
        },
        w: function () {return this.dO.getDay();},
        m: function () {return pad(this.dO.getMonth(),2);},
        M: function () {return monthsShort[this.dO.getMonth()];},
        n: function () {return this.dO.getMonth()+1;},
        Y: function () {return this.dO.getFullYear();},
        y: function () {return this.dO.getFullYear().toString().substr(2);},
        a: function () {return amPm(this.dO.getHours());},
        A: function () {return amPm(this.dO.getHours()).toUpperCase();},
        g: function () {return this.dO.getHours() % 12;},
        G: function () {return this.dO.getHours();},
        h: function () {return pad(this.dO.getHours() % 12, 2);},
        H: function () {return pad(this.dO.getHours(),2);},
        i: function () {return pad(this.dO.getMinutes(),2);},
        s: function () {return pad(this.dO.getSeconds(),2);},
        U: function () {return this.dO.getTime();}
    };

    /*
     * Returns a closure that has all the needed private helpers in it's scope.
     */
    return function (format) {
        var returnString = '';
        var replacer = new Replacer(this);
        for (var i = 0; i < format.length; i = i + 1) {
            if (typeof replacer[format[i]] !== 'undefined') {
                returnString += replacer[format[i]]();
            } else {
                returnString += format[i];
            }
        }
        return returnString;
    };
}());

After executing this piece of code, all your Date objects will have a format() method. Even the ones that have been created earlier due to JavaScripts prototypal inheritance system.

You can call the format() method with a formatting string just like in PHP. It uses the same tokens to represent the individual fields. For a detailed explanation  what every token does, please consult the PHP manual page for date().

This version here does not support all the formatting options that are available in PHP but the common ones are in there.

If you need additional formatting options, you can easily extend the formatter by adding new methods to Replacer.prototype where all the tokens for the format string are defined as functions.

How asynchronicity gets you a nice girl

I just made myself some pasta. Ok, nothing spectacular so far, just pasta with plain tomato sauce. But while doing so, I thought about the way I was acting and recognized the similarity between my pasta cooking and …

… JavaScript. Yes, JavaScript.

Let me explain. What’s the “algorithm” for making pasta with tomato sauce? It’s something like this (may vary depending on your favored pasta style):

  1. Put salt water on the stove.
  2. While the water heats, put some oil into a frying pan.
  3. While the oil heats, cut an onion. The water is still heating.
  4. Fry the onion while you cut some tomatoes.
  5. Add tomatoes to the onions.
  6. Your water could be boiling by now, so add pasta to the water.
  7. Let the sauce loose some water by boiling it for a while.
  8. Then add some spices.
  9. Take the pasta pout of the water, when it’s finished (This will probably take the most time).
  10. Add sauce.
  11. Eat it and Be happy.

You see, there’s a lot of stuff happening concurrently although you are doing it alone - “single threaded”, so to speak. This is very much like the asynchronous calls that are common in JavaScript and some other languages. The whole process just takes as long as its longest part, which is probably boiling the pasta.

Now image making pasta synchronously, like you would program in the more traditional way:

  1. Put water on the stove.
  2. Wait until it boils
  3. Put the pasta in the water
  4. Wait until its ready.
  5. Cut the onion
  6. Put oil into the pan.
  7. Wait …
  8. Put the onion into the hot oil.
  9. Wait …

You see where this is going. There’s a lot of waiting involved. That’s time in which you could have done something useful. Like inviting a nice girl over to share the pasta with. But sadly, because you chose synchronous cooking, you’ll eat not only much later but also alone. And your pasta will most likely have gotten cold while you were so busy with idling.

Now think again about how “complicated” and “hard to grasp” asynchronous programming really is.

PS: I didn’t invite anyone over for pasta because I used the free time that I had because of asynchronous cooking to write this post ;)

Maybe I should set some different priorities …

PPS: And don’t get me started on multithreaded cooking. My kitchen is barely big enough for one person. Just like your computers RAM is just not big enough to be wasted on threads.

Software development over the past decade was pretty much ruled by Java.

I have this strange feeling that the next one will belong to JavaScript.

— My cerebellum just said that …

Precise finance in JavaScript

JavaScript knows only one number type: signed 64Bit floating point.

That is pretty cool most of the time because you can’t run into strange type conversion issues when every number is already of the exakt same type.

However, as soon as you do financial mathematics in JS, you’ll run into pretty bad mojo. Money does not have more than two decimal fractional digits and it’s always rounded before any calculation is made. So if you throw around money values in JavaScript, it will behave incorrect in terms of currency although the math is perfectly fine.

To mitigate the dangers of this problem, you can introduce a new type of number: The Money object! It’s an object made of cash, yeah!

Ok, here’s the code:

var Money = function(amount) {
        if ('number' !== typeof amount) {
            amount = 0;
        }
        this.amount = amount;
    }
Money.prototype.valueOf = function() {
    return Math.round(this.amount * 100) / 100;
}

The valueOf() method is called every time you try to use an object like a primitive type like Number, String or Boolean. By default it returns the string “[object Object]” if you try to do that, which is not very useful. But as you see you can override this behavior by defining a new method of the same name on the constructors prototype.

Now this happens:

var m = new Money(50.42355446);
var n = new Money(30.342141);

sys.puts(m.amount + n.amount); //80.76569546
sys.puts(m+n);                 //80.76

You can implement a more sophisticated (and maybe less customer friendly) rounding algorithm, if you like. I’m not an accountant but I’m sure there are rules how money has to be rounded in different situations.

And hey, having a constructor for Money sounds pretty awesome, right?