// UTIL METHODS AND FUNCTIONS
var clone = (function(ob1) {
		var newObj = (ob1 instanceof Array) ? [] : {};
		for (i in ob1) {
			if (i == 'clone') continue;
			if (ob1[i] && typeof ob1[i] == "object") {
				newObj[i] = clone(ob1[i]);
			} else newObj[i] = ob1[i]
		} return newObj;
	}),
	extend = (function(ob1, ob2) {
		newObj = clone(ob1);
		for (var z in ob2)
			if (ob2.hasOwnProperty(z))
				newObj[z] = ob2[z];
		return newObj;
	}),
	objAlert = (function(ob1) {	
		var output = '';
		for (var i in ob1)
			 output += i+': '+ob1[i]+'\n';
		alert(output);
	}),
    createCookie = (function(name, value, days) {
        var date, expires;
        if (days) {
            date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            expires = "; expires="+date.toGMTString();
        } else
            expires = "";
        document.cookie = name+"="+value+expires+"; path=/";
    }),
    readCookie = (function(name) {
        var nameEQ = name+"=",
            ca = document.cookie.split(';'),
            c;
        for(var i=0;i < ca.length;i++) {
            c = ca[i];
            while (c.charAt(0) == ' ')
                c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0)
                return c.substring(nameEQ.length, c.length);
        }
        return null;
    }),
    eraseCookie = (function(name) {
        createCookie(name, "", -1);
    }),
    parseBoolean = (function(str) {
        return /^true$/i.test(str);
    }),
    stopPropogation = (function(e) {
        e = window.event || e;
        if (e.stopPropagation)
            e.stopPropagation();
        else
            e.cancelBubble = true;
    }),
/**
 Written by Peter Wilkinson of http://dynamic-tools.net
 Feel free to use or modify this script for any purpose.  I'd appreciate you leaving
 this header in though.
 */
    addEvent = (function(elem, eventType, handler) {
        if (!elem.eventHandlers)
            elem.eventHandlers = [];
        if (!elem.eventHandlers[eventType]) {
            elem.eventHandlers[eventType] = [];
            if (elem['on' + eventType])
                elem.eventHandlers[eventType].push(elem['on' + eventType]);
            elem['on' + eventType] = handleEvent;
        }
        elem.eventHandlers[eventType].push(handler);
    }),
    removeEvent = (function(elem, eventType, handler) {
        var handlers = elem.eventHandlers[eventType];
        for (var i in handlers)
            if (handlers[i] == handler)
                delete handlers[i];
    }),
    handleEvent = (function(e) {
        var returnValue = true;
        if (!e)
            e = fixEvent(event);
        var handlers = this.eventHandlers[e.type]
        for (var i in handlers) {
            this.$$handleEvent = handlers[i];
            returnValue = !((returnValue && this.$$handleEvent(e)) === false);
        }
        return returnValue;
    });

function fixEvent(event) {
    // add W3C standard event methods
    event.preventDefault = fixEvent.preventDefault;
    event.stopPropagation = fixEvent.stopPropagation;
    return event;
};
fixEvent.preventDefault = function() {
    this.returnValue = false;
};
fixEvent.stopPropagation = function() {
    this.cancelBubble = true;
};

// Fix for IE which does not support getElementsByClassName
/*
 Developed by Robert Nyman, http://www.robertnyman.com
 Code/licensing: http://code.google.com/p/getelementsbyclassname/
 */
var IEgetElementsByClassName = function (className, tag, elm){
    if (document.getElementsByClassName) {
        getElementsByClassName = function (className, tag, elm) {
            elm = elm || document;
            var elements = elm.getElementsByClassName(className),
                nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
                returnElements = [],
                current;
            for(var i=0, il=elements.length; i<il; i+=1){
                current = elements[i];
                if(!nodeName || nodeName.test(current.nodeName)) {
                    returnElements.push(current);
                }
            }
            return returnElements;
        };
    }
    else if (document.evaluate) {
        getElementsByClassName = function (className, tag, elm) {
            tag = tag || "*";
            elm = elm || document;
            var classes = className.split(" "),
                classesToCheck = "",
                xhtmlNamespace = "http://www.w3.org/1999/xhtml",
                namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
                returnElements = [],
                elements,
                node;
            for(var j=0, jl=classes.length; j<jl; j+=1){
                classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
            }
            try	{
                elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
            }
            catch (e) {
                elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
            }
            while ((node = elements.iterateNext())) {
                returnElements.push(node);
            }
            return returnElements;
        };
    }
    else {
        getElementsByClassName = function (className, tag, elm) {
            tag = tag || "*";
            elm = elm || document;
            var classes = className.split(" "),
                classesToCheck = [],
                elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
                current,
                returnElements = [],
                match;
            for(var k=0, kl=classes.length; k<kl; k+=1){
                classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
            }
            for(var l=0, ll=elements.length; l<ll; l+=1){
                current = elements[l];
                match = false;
                for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
                    match = classesToCheck[m].test(current.className);
                    if (!match) {
                        break;
                    }
                }
                if (match) {
                    returnElements.push(current);
                }
            }
            return returnElements;
        };
    }
    return getElementsByClassName(className, tag, elm);
};
if (typeof console === 'undefined')
    console = {
        log: function(msg) {
            alert(msg);
        }
    };
var eFix = function(e) {
    e = e || window.event;
    e.target = e.target || e.srcElement;
    e.offsetX = e.offsetX || e.layerX;
    e.offsetY = e.offsetY || e.layerY;
    e.relatedTarget = e.relatedTarget ||
        e.type == 'mouseover' ? e.fromElement : e.toElement;
    e.target = e.target || e.srcElement;
    if (target.nodeType === 3) target = target.parentNode; //Safari bug
    return e;
};
function isEmpty(o) {
    var o = {};
    for(var p in o) {
        if (o[p] != o.constructor.prototype[p])
            return false;
    }
    return true;
}

