JavaScript Unit Conversion Gadget Brings Lots of RegEx Fun

My girlfriend started a cooking blog recently, if you want to keep track of what I eat, I suggest you subscribe to her feed. ;) To help her American followers (and others suffering under the burden of a unit system from the middle ages), I kludged together a little gadget to add to her Blogger pages. The gadget tries to convert a few metric units to something equivalent in stones, feet and that Fahrenheit thing.

Doing so, I learned a nifty thing about JavaScript regular expressions. The replace method in JavaScript 3 makes it possible to call a function to return the replacement string. This way, I can match value, a possible prefix and unit, make backreferences and pass those to a conversion function and replace the matched text in the blog posts with converted values in one go, like so:

1
2
3
4
5
6
7
8
9
var re = /(\d+|\u00bd) ?([mcdk]|(?:mili|centi|deci|kilo))?(g(?:r|ram)?|l(?:iter)?|c(?:elcius)?)\b/gi;

function knvrtit() {
        var entries = document.getElementsByClassName('entry-content');

        for (var i = 0; i < entries.length; i++) {
                entries[i].innerHTML = entries[i].innerHTML.replace(re, das_Konvertor);
        };
}

But, what is that unicode \u00bd, you say? Oh, well as it happens some keyboard layouts have a 1/2 character and some people like to use it too….

Das_Konvertor() then does its magic using a case construct to multiply values based on the prefix of a unit, and then uses a second case construct to decide to convert in what way based on the type of unit encountered.

The code for das_Konvertor() is a bit long, but it looks somewhat like this:

1
2
3
4
function das_Konvertor (str, value, prefix, unit, offset, s) {
        // do stuff
        return string_in_imperical_units;
}

It would be fun, and very web2.0ish to, instead of doing my own ugly conversions, pass the calculation to be done to the almighty Google calculator in an XMLHttpRequest and display the result. If it keeps raining in the weekends, I might do so. ;)

Comments