(function() {
    // IEのみ処理する
    if (typeof Prototype != 'undefined' && Prototype.Browser.IE) {
        var handlers = {};
        var wrapperCache = {};
        
        var getElementId = function(element) {
            return element._prototypeEventID || element._eventID;
        }
        var getHandlerList = function(element, name) {
            var id = getElementId(element);
            var h = handlers[id] = (handlers[id] || {});
            return h[name] = (h[name] || []);
        }
        var addHandler = function(element, name, handler) {
            getHandlerList(element, name).push(handler);
        }
        var removeHandler = function(element, name, handler) {
            handlers[getElementId(element)][name] =
                getHandlerList(element, name).without(handler);
        }
        
        var getWrapperCache = function(element, name) {
            var id = getElementId(element);
            var wc = wrapperCache[id] = (wrapperCache[id] || {});
            return wc[name] = (wc[name] || null);
        }
        var setWrapperCache = function(element, name, wrapper) {
            var id = getElementId(element);
            var wc = wrapperCache[id] = (wrapperCache[id] || {});
            wc[name] = wrapper;
        }
        
        // 追加されたイベントを1個にしてattachEventに設定
        var updateWrapper = function(element, name) {
            // handlerの数が0になったらイベントを解除
            if (getHandlerList(element, name).length == 0) {
                element.detachEvent("on" + name, getWrapperCache(element, name));
                setWrapperCache(element, name, null);
                
            } else if (getWrapperCache(element, name) == null) {
                var wrapper = function(event) {
                    // 追加したイベントを正しい順序で回す
                    getHandlerList(element, name).each(function(handler) {
                        handler(event);
                    });
                }
                // イベントをキャッシュに設定
                setWrapperCache(element, name, wrapper);
                // イベントを設定
                element.attachEvent("on" + name, wrapper);
            }
        }
        
        // ElementにaddEventListener, removeEventListenerを実装
        Element.addMethods({
            addEventListener: function(element, name, handler, capture) {
                addHandler(element, name, handler);
                updateWrapper(element, name);
            },
            removeEventListener: function(element, name, handler, capture) {
                removeHandler(element, name, handler);
                updateWrapper(element, name);
            }
        });
        
        // window, documentに継承する
        var eventListener = {
            addEventListener: Element.Methods.addEventListener.methodize(),
            removeEventListener: Element.Methods.removeEventListener.methodize()
        };
        Object.extend(window, eventListener);
        Object.extend(document, eventListener);
    }
})(); 