/**
*    Кроссбраузерный класс для работы с событиями (events)
*    @author: kirik [phpforum.ru]
**/
var CTevent = {
    evtsHash: [],

    attach: function (obj, event, fn, useCapture) {
        if(obj.addEventListener) {
            obj.addEventListener(this.ff(event), fn, useCapture);
        } else if(obj.attachEvent) {
            // IE нифига не понимает this внутри назначенной функции, поэтому немного особой, уличной магии:
            var hashKey = '{EVENT::obj:' + this.ie(obj) + ';event:' + event + ';fn:' + fn + '}';
            if(!this.evtsHash[hashKey]) {
                    var _fn = this.evtsHash[hashKey] = function () {
                        fn.call(obj);
                    }
                    obj.attachEvent(event, _fn);
                    // Назначаем на unload страницы функцию, которая будет подчищать event'ы
                    // IE не любит это делать сам
                    window.attachEvent('onunload', function() {
                        obj.detachEvent(event, _fn);
                    });
            }
            hashKey = '';
        } else {
            obj[event] = fn;
        }
    },

    detach: function (obj, event, fn, useCapture) {
        if(obj.addEventListener) {
            obj.removeEventListener(this.ff(event), fn, useCapture);
        } else if(obj.detachEvent) {
            var hashKey = '{EVENT::obj:' + this.ie(obj) + ';event:' + event + ';fn:' + fn + '}';
            if(this.evtsHash[hashKey]) {
                    obj.detachEvent(event, this.evtsHash[hashKey]);
                    delete this.evtsHash[hashKey];
            }
            hashKey = '';
        } else {
            alert('Your browser does not support events.');
        }
    },

    cancel: function (e) {
        if(!e) {
            e = window.event;
        }
        if(e.preventDefault) {
            e.preventDefault();
        } else {
            e.returnValue = false;
        }
    },

    stop: function (e) {
        if(!e) {
            e = window.event;
        }
        if(e.stopPropagation) {
            e.stopPropagation();
        } else {
            e.cancelBubble = true;
        }
    },

    ff: function (str) {
        return str.replace(/on/i, '');
    },

    ie: function (obj) {
        if(obj === window) {
            return 'window';
        } else if (obj === document) {
            return 'document';
        } else {
            return obj.uniqueID;
        }
    }
};
