I just found out about PIE.htc, a javascript behavior file for IE that enables a lot of CSS3 on IE6+. I though of integrating it with my own css3hacks library to do all the work for ie. So today I just commited the library to google code. It is really simple to use. Just add a javascript file to your html:

<script type="text/javascript" src="css3hacks.js"></script>
<script type="text/javascript">CSS3Hacks.init()</script>

Then write normal css3 like:

#my-box {
    border-radius: 5px;
}

This will enable rounded borders on all browsers I could test: IE6, IE7, Firefox 3, 4, Chrome, Chromium, Opera various versions. Right now it supports just border-radius-* and variable definitions but I’m planning on adding support for more css3 rules in the future. You’re welcome to give suggestions, report problems or contribute code

Notifiy for iPhone, iPod touch and iPad

Home screen for the Notifiy application.


If you want to get notifications of changes in google wave in your iPhone, iPad or iPod touch check out the Notifiy app at the App Store.

For those of you that *REALLY* need MS Office and Open Office is not enough, then install wine just run this two commands on a terminal:

wget http://www.kegel.com/wine/winetricks
sh winetricks msxml3 dotnet20 gdiplus riched20 riched30\
              vcrun2005sp1 allfonts  wsh56js

And then install using your installation CD.

UPDATE: If you are using a non-english locale the second command has to be:

LANG="en_US.UTF-8" sh winetricks msxml3 dotnet20 gdiplus riched20\
              riched30 vcrun2005sp1 allfonts  wsh56js

What I’m talking about is constructing a tree from an email message. Usuallu when you get an email and reply back and forth then you end up with something that looks something like this:

Is there any way to reliably parse a message like this and get a tree of messages with headers, top-posts, inline replies, bottom-posts, etc? I’be been looking around for some time but I haven’t been able to find anything close to that.

Well this is something I plan on adding to the Notifiy wave robot so that it parses incoming emails and posts the relevant content to wave and even corrections to previous posts. Maybe in this case is easier than a multi level email since replies will always start from a clean message, so there’s just one level up.

Wave Notifications on the iPhone

Wave Notifications on the iPhone

I have some news about the Notifiy robot (wave-email-notifications@googlewave.com). It can now send notifications to your iPhone when a wave is updated. The application will be available at the App Store very soon.

I just created a google wave robot that sends email notifications when a wave is updated. To try it out just add: wave-email-notifications@appspot.com to the wave and that’s it. It’s currently in a beta stage so there are no guarantees. Visit the project home page at:

http://wave-email-notifications.googlecode.com/

I found myself needing to implement a tri-state checkbox in javascript. A checkbox has initially 2 states: on or off. From the html perspective if the checkbox is checked then the value is submitted, if it is not then the value is not submitted. From the javascript perspective you can use:

if (checkbox.checked) {
    alert("This checkbox is checked");
}

Some times a true or false is not enough. Other development platforms have tri-state checkboxes that can have either a true, false or null value. The following snippet adds a “greyable” functionality to checkboxes:

Element.addMethods("INPUT", (function() {
    var changeHandler = function(e) {
        if (this.greyed || this.checked) {
            this.setGreyed(!this.greyed);
            if (!this.greyed) {
                this.checked = true;
            }
        }
    };

    function setGreyed(checkbox, greyed) {
        checkbox.greyed = typeof greyed == "undefined" ? true : !!greyed;
        checkbox.setOpacity(checkbox.greyed ? 0.33 : 1);
        if (checkbox.greyed) {
            checkbox.checked = checkbox.greyedState;
        }            
    }

    function setGreyable(element, enable) {
        if (!(element = $(element))) return;
       
        if (!(/checkbox|radiobutton/i.test(element.type))) {
            return;
        }

        if (typeof element.greyedState == "undefined" || enable) {
            element.observe("change", changeHandler);
            element.setGreyState(false);
            element.setGreyed(false);
        } else {
            element.stopObserving("change", changeHandler);
            element.setGreyed(false);
            element.checked = element.greyedState;
            element.greyedState = undefined;
            element.greyed = undefined;
        }
    }

    function setGreyState(element, greyedState) {
        if (!(element = $(element))) return;
       
        if (!(/checkbox|radiobutton/i.test(element.type))) {
            return;
        }

        element.greyedState = typeof greyedState == "undefined" ? true :
            !!greyedState;
    }

    return {
        setGreyed: setGreyed,
        setGreyable: setGreyable,
        setGreyState: setGreyState
    }
})());

This currently requires prototypejs but could be easily modified to not depend on it. To enable it on some element do something like this:

checkbox.setGreyable();

To check if it is greyed or not:

if (checkbox.greyed) {
    alert("This checkbox is greyed");
}

You can also change the state of the checkbox when it is greyed. To set this use the following:

checkbox.setGreyState(true);

The parameter indicates whether the checkbox is checked when grey. Clicking on the checkbox (or changing the state by keyboard) loops through 3 states: checked, not checked and greyed.

If you are constantly running “svn up” or “svn status -u” or maybe “svn log -rBASE:HEAD” then you might find this piece of code useful:

#!/bin/sh  
 
dir="$1"

cd $dir
 
updated=`svn st -u | grep '*'`

if [ "$updated" ]; then
    notify-send SVN "$updated"
fi

What id does is check for updates in subversion and if it finds any then shows a notification using notify-send. Tested on openSUSE 11.1 with subversion 1.6. Add a crontab entry and you are done.

08
Aug

Google Wave Developer Preview at Google I/O 2009

After watching this video many ideas came to my mind! I’ve always wanted to have some sort of a system where you could collaboratively construct stories, movie scripts, etc. When I get my hands on an invitation for wave that’s the first thing I’m going to do. Would make celtx look so old fashioned!

I was in need for a solution to search a very large set of data in a javascript application. I thought of a b+ tree. Looking for a javascript implementation of it, google didn’t help much. So, I just gave up and decided to implement it myself. This is the result: not really a B+ tree but a variation that works better in this case. I call it a B# tree. It depends on the prototype framework but I’m planning on making some changes to it so it would work stand-alone.

var BSharpTree = Class.create( {
    root: null,

    initialize: function(comparator) {
        this.root = $A();
        this.comparator = comparator || function(x) {
            return x
        };
    },

    add: function(text, object, node) {
        var node = node || this.root;

        node.objects = node.objects || $A();
        if (node != this.root) {
            node.objects.push(object);
        }

        if (text.length > 0) {
            var chr = text.charCodeAt(0) - 32;
            var next = node[chr] = chr == 0 ? this.root : node[chr] || $A();
            this.add(text.substring(1), object, next);
        }
    },

    search: function(text, objects) {
        var node = this.root;
        var result = null;

        while (text.length > 0) {
            var chr = text.charCodeAt(0) - 32;
            text = text.substring(1);

            if (char == 0) {
                result = this.search(text, result);
                break;
            } else {
                node = node[chr];
                if (!node) {
                    return $A();
                }
                result = node.objects;
            }
        }

        if (objects) {
            if (node == this.root) {
                return objects;
            } else {
                return this.intersect(result, objects);
            }
        } else {
            if (node == this.root) {
                return $A();
            } else {
                return result;
            }
        }
    },

    intersect: function(a, b) {
        var i = 0;
        var j = 0
        var intersect = $A();

        a = a.sortBy(this.comparator);
        b = b.sortBy(this.comparator);

        while (i < a.length && j < b.length) {
            if (this.comparator(a[i]) == this.comparator(b[j])) {
                intersect.push(a[i]);
                i++;
                j++;
            } else if (this.comparator(a[i]) > this.comparator(b[j])) {
                j++;
            } else {
                i++;
            }
        }

        return intersect;
    }
});

It contains a very efficient intersect method. To use it just do something like this:

var bst = new BSharpTree();

bst.add("some string", "my object");
bst.add("some other string", "other object");
bst.add("last string", "last object");

bst.search("string"); // returns ["my object", "other object", "last object"]
bst.search("some string"); // returns ["my object", "other object"]

You can set any object as the second parameter to the BSharpTree#add method but then you might need to pass a comparator function to the BSharpTree constructor. Use it as you may see fit!