if(typeof Prototype == undefined) throw("charCounter requires the Prototype library");
var Counter = new Class.create({
    initialize: function(parent, tag, max) {
        this.checkValidity(parent, tag, max);
        this.parent = $(parent);
        this.toCount = $(this.parent).down(tag);
        this.max = max;
        this.createCounter();
        this.prepareCounter();
    },

    checkValidity: function(parent, tag, max) {
        if (parent == undefined) throw("charCounter requires a parent argument");
        if (tag == undefined) throw("charCounter requires a tag argument");
        if (max == undefined) throw("charCounter requires a max argument");    
    },

    createCounter: function() {
        this.parent.insert({
            bottom: new Element("p").insert({
                top: new Element("span", {"id": this.parent.identify() + "Span"}).update("0"),
                bottom: "&nbsp;of " + this.max + " characters remaining."
            })});
        this.span = $(this.parent.identify() + "Span");
    },

    prepareCounter: function(){
        this.toCount.observe("keyup", function() {this.updateCounter();}.bind(this));
        this.toCount.observe("change", function() {this.updateCounter();}.bind(this));
    },

    updateCounter: function() {
        var newCount = this.toCount.value.length;
        this.span.update(newCount);
        if (newCount >= this.max) this.limitText();
    },

    limitText: function() {
        this.toCount.value = this.toCount.value.substring(0, (this.max));
        this.span.update(this.max);
    }
});