function isUndefined(v){
    return(v==undefined||null==v)
}

function isDefined(v){
    return(v!=undefined&&v!=null)
}

zColor = function(hex) {
    if(!hex) return;
    if(hex.match(this.reRGB)) {
        var a = hex.match(this.reRGBVal);
        if(!a || a.length != 4) throw "invalid";
        this.red = parseInt(a[1]);
        this.green = parseInt(a[2]);
        this.blue = parseInt(a[3]);
    }
    else if(hex.match(this.reHex)) {
        var a = hex.match(this.reHexVal);
        if(!a || a.length != 4) throw "invalid";
        this.red = parseInt(a[1], 16);
        this.green = parseInt(a[2], 16);
        this.blue = parseInt(a[3], 16);
    }
    else {
        hex = hex.toLowerCase();
        switch(hex) {
            case "black": break;
            case "red": this.red = 255; break;
            case "white": this.red=255; this.green=255; this.blue=255; break;
            default: throw hex + " unknown";
        }
    }
}

zColor.prototype = {
    red : 0,
    green : 0,
    blue : 0,
    reHex : /^#/,
    reHexVal : /^#([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})/,
    reRGB : /^rgb/,
    reRGBVal : /^rgb.*\((\d+),\s*(\d+),\s*(\d+)/,
    copyTo : function(c) {
        if(!c) return;
        c.red = this.red;
        c.green = this.green;
        c.blue = this.blue;
    },
    clone : function() {
        var c = new zColor();
        this.copyTo(c);
        return c;
    },
    add : function(r, g, b) {
        this.red += r;
        if(this.red < 0 ) this.red = 0;
        if(this.red > 255) this.red = 255;
        this.green += g;
        if(this.green < 0 ) this.green = 0;
        if(this.green > 255) this.green = 255;
        this.blue += b;
        if(this.blue < 0 ) this.blue = 0;
        if(this.blue > 255) this.blue = 255;
    },
    isEqual : function(cmp) {return (cmp && this.red == cmp.red && this.green == cmp.green && this.blue == cmp.blue);},
    toString : function() {
        var clr = '#';
        var n, s;
        for(var i=0; i<3; ++i) {
            switch(i) {
                case 0: n = this.red; break;
                case 1: n = this.green; break;
                case 2: n = this.blue; break;
            }
            s = Math.round(n).toString(16);
            if(s.length < 2) clr += '0';
            clr += s;
        }
        return clr;
    }
}

Animator=function(){}
Animator=new function(){
    var kIEOpacityFilter="DXImageTransform.Microsoft.Alpha";
    var Animator=this;
    Animator.fadeColor=function(e,fromClrStr,toClrStr,iterations, intervalTime,bBkg){
        var css=e.style;
        if(bBkg&&css.backgroundColor==toClrStr)return;
        if(!bBkg&&css.color==toClrStr)return;
        var fromClr=new zColor(fromClrStr);
        var endClr=new zColor(toClrStr);
        var cur=fromClr.clone();
        if(iterations<=0)iterations=1;
        var rInc=Math.floor((endClr.red-fromClr.red)/iterations);
        var gInc=Math.floor((endClr.green-fromClr.green)/iterations);
        var bInc=Math.floor((endClr.blue-fromClr.blue)/iterations);
        fromClr.copyTo(endClr);
        endClr.add((rInc*iterations),(gInc*iterations),(bInc*iterations));
        var key=this._locateId(e)+fromClrStr+toClrStr;
        e.fadeColorKey=key;
        function nextColor(){
            if(isUndefined(e.fadeColorKey)||e.fadeColorKey!=key)clearInterval(tmrId);
            if(cur.isEqual(endClr)){
                if(bBkg)css.backgroundColor=toClrStr;
                else css.color=toClrStr;
                clearInterval(tmrId);
                fromClr.copyTo(cur);
            }
            else{
                cur.add(rInc,gInc,bInc);
                if(bBkg)css.background=cur.toString();
                else css.color=cur.toString();
            }
        }
        var tmrId=setInterval(nextColor, intervalTime);
    }
    Animator._locateId=function(e){
        var id=e.id;
        if(isUndefined(id))id=e.firstChild;
        if(isUndefined(id))id=e.tagName;
        return id;
    }
}

function setFocus(e){
    //e.style.borderColor='#000000'
    if (typeof Animator!="undefined" && null!=Animator)
        Animator.fadeColor (e,'#ffffff','#f2f2f2',13, 15,true)
    else
        e.style.backgroundColor='#f2f2f2'
}
function setBlur(e){
    //e.style.borderColor='#cfcfcf'
    if (typeof Animator!="undefined" && null!=Animator)
        Animator.fadeColor (e,'#f2f2f2','#ffffff',13, 15,true)
    else
        e.style.backgroundColor='#f2f2f2'
}

init();

function init() {
  var oldOnLoad = window.onload;
  window.onload = function() {
    if (oldOnLoad) oldOnLoad();
    addFXEvents();
  }
}

function addFXEvents() {
    if (!document.getElementsByTagName){ return; }

	// set up input boxes
	var focusedInit = false;
	var focusedError = false;
	var initFocus = null;

	var inputs = document.getElementsByTagName("*");

	for (var i=0; i<inputs.length; i++){
		var input = inputs[i];
		if (input.tagName.toLowerCase() == "input" || input.tagName.toLowerCase() == "textarea") {
	        var classTokens = input.className.split(' ');
            for (var j = 0; j < classTokens.length; j++) {
                var thisToken = classTokens[j];
                if (thisToken == "fade") {
                    input.onfocus = function () {setFocus(this);}
        			input.onblur = function () {setBlur(this);}
                }
                if (!focusedInit && !focusedError && thisToken == "initFocus") {
                    initFocus = input;
                    focusedInit = true;
                }
                if (!focusedError && thisToken == "error") {
                    initFocus = input;
                    focusedError = true;
                }
            }
       	}
    }
    if (initFocus) {
        initFocus.focus();
    }
}
