String.prototype.contains = function (string, s) {
    return (s) ? ((s + this + s).indexOf(s + string + s) > -1) : (this.indexOf(string) > -1);
};
String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, '');
};
if (!(Array.prototype.indexOf && Array.prototype.contains)) {
    Array.prototype.indexOf = function (item, from) {
        var len = this.length;
        for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
            if (this[i] === item) return i;
        }
        return -1;
    };
    Array.prototype.contains = function (item, from) {
        return (this.indexOf(item, from) != -1);
    };
}
function hasClass(element, className) {
    if (!element.className)    return false;
    return element.className.contains(className, ' ');
}
function addClassToElement(element, className) {
//    if (typeof(element.className) != 'string')    return;
    if (hasClass(element, className))    return;
    element.className = (element.className + ' ' + className).trim();
}
function removeClassFromElement(element, className) {
    if (!element.className)    return;
    if (!hasClass(element, className))    return;
    element.className = element.className.replace(className, '').replace(/\s+/g, ' ').trim();
}
function toggleClass(element, className) {
    if (hasClass(element, className)) {
        removeClassFromElement(element, className);
    } else {
        addClassToElement(element, className);
    }
}
if (!document.getElementsByClassName) {
    document.getElementsByClassName = function (className) {
        var result = [];
        if (document.evaluate) {
            var xpath = document.evaluate(
                './/*[contains(concat(" ", @class, " "), " ' + className + ' ")]',
                document,
                (function(prefix){return(prefix=='xhtml')?'http://www.w3.org/1999/xhtml':false;}),
                7,    // XPathResult.ORDERED_NODE_SNAPSHOT_TYPE
                null
            );
            for (var i = 0, j = xpath.snapshotLength; i < j; i++) result.push(xpath.snapshotItem(i));
        } else {
            var elements = ((document.all) ? document.all : document.getElementsByTagName('*'));
            for (var i = 0; i < elements.length; i++) {
                var el = elements[i] || elements.item(i);
                if (hasClass(el, className)) {
                    result[result.length] = el;
                }
            }
        }
        return result;
    };
}
function addEventToElement(element, evtName, fn) {
    if (element.addEventListener) {
        element.addEventListener(evtName, fn, false);
    } else if (element.attachEvent) {
        element.attachEvent('on' + evtName, (function (bind) {
            return function (evt) {
                fn.call(bind, evt);
            };
        })(element));
    } else {
        var fn_org = element['on' + evtName];
        element['on' + evtName] = function (event) {
            fn.call(element, event);
            if (fn_org)    fn_org.call(element, event);
        }
    }
}
