Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #9466: event_ie_leak_fix.diff

File event_ie_leak_fix.diff, 5.1 kB (added by jdalton, 5 months ago)

Only removes elements that are observing, optimize wrapper lookup.

  • event.js

    old new  
    130130})(); 
    131131 
    132132Object.extend(Event, (function() { 
    133   var cache = Event.cache; 
    134  
     133  var cache = Event.cache, 
     134  Wrapper = Class.create({ 
     135    initialize: function(element, eventName, handler){ 
     136      this.id        = getEventID(element); 
     137      this.handler   = handler; 
     138      this.element   = element; 
     139      this.eventName = eventName; 
     140      this.callback  = function(event) { 
     141        if (!Event || !Event.extend || 
     142          (event.eventName && event.eventName != this.eventName)) 
     143            return false; 
     144         
     145        this.handler.call(this.element, Event.extend(event)); 
     146      }.bind(this); 
     147    } 
     148  }); 
     149   
    135150  function getEventID(element) { 
    136151    if (element._prototypeEventID) return element._prototypeEventID[0]; 
    137     arguments.callee.id = arguments.callee.id || 1; 
    138     return element._prototypeEventID = [++arguments.callee.id]; 
     152    return element._prototypeEventID = [arguments.callee.id++]; 
    139153  } 
     154  getEventID.id = 1; 
    140155   
    141156  function getDOMEventName(eventName) { 
    142157    if (eventName && eventName.include(':')) return "dataavailable"; 
     
    153168  } 
    154169   
    155170  function createWrapper(element, eventName, handler) { 
    156     var id = getEventID(element); 
    157     var c = getWrappersForEventName(id, eventName); 
     171    var c = getWrappersForEventName(getEventID(element), eventName); 
    158172    if (c.pluck("handler").include(handler)) return false; 
    159173     
    160     var wrapper = function(event) { 
    161       if (!Event || !Event.extend || 
    162         (event.eventName && event.eventName != eventName)) 
    163           return false; 
    164        
    165       Event.extend(event); 
    166       handler.call(element, event); 
    167     }; 
    168      
    169     wrapper.handler = handler; 
     174    var wrapper = new Wrapper(element, eventName, handler); 
    170175    c.push(wrapper); 
    171176    return wrapper; 
    172177  } 
     
    177182  } 
    178183   
    179184  function destroyWrapper(id, eventName, handler) { 
     185    var wrapper = (id instanceof Wrapper)? id : null; 
     186    if(wrapper){ 
     187      id = wrapper.id; 
     188      eventName = wrapper.eventName; 
     189    } 
    180190    var c = getCacheForID(id); 
    181191    if (!c[eventName]) return false; 
    182     c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); 
     192    if(!wrapper) wrapper = findWrapper(id, eventName, handler); 
     193    c[eventName] = c[eventName].without(wrapper); 
     194    wrapper.element = null; 
    183195  } 
    184196   
    185197  function destroyCache() { 
    186198    for (var id in cache) 
    187       for (var eventName in cache[id]) 
     199      for (var eventName in cache[id]){ 
     200        var i = cache[id][eventName].length; 
     201        while(i) Event.stopObserving(cache[id][eventName][--i]); 
    188202        cache[id][eventName] = null; 
     203      } 
    189204  } 
    190205   
    191206  if (window.attachEvent) { 
     
    201216      if (!wrapper) return element; 
    202217       
    203218      if (element.addEventListener) { 
    204         element.addEventListener(name, wrapper, false); 
     219        element.addEventListener(name, wrapper.callback, false); 
    205220      } else { 
    206         element.attachEvent("on" + name, wrapper); 
     221        element.attachEvent("on" + name, wrapper.callback); 
    207222      } 
    208223       
    209224      return element; 
    210225    }, 
    211    
     226     
    212227    stopObserving: function(element, eventName, handler) { 
    213228      element = $(element); 
    214       var id = getEventID(element), name = getDOMEventName(eventName); 
    215229       
    216       if (!handler && eventName) { 
    217         getWrappersForEventName(id, eventName).each(function(wrapper) { 
    218           element.stopObserving(eventName, wrapper.handler); 
    219         }); 
    220         return element; 
    221          
    222       } else if (!eventName) { 
    223         Object.keys(getCacheForID(id)).each(function(eventName) { 
    224           element.stopObserving(eventName); 
    225         }); 
    226         return element; 
     230      var name, wrapper; 
     231      if((wrapper=arguments[0]) instanceof Wrapper){ 
     232        element = wrapper.element; 
     233        eventName = wrapper.eventName; 
    227234      } 
     235      else{ 
     236        var id = getEventID(element); 
     237        if (!handler && eventName) { 
     238          getWrappersForEventName(id, eventName).each(function(wrapper) { 
     239            Element.stopObserving(wrapper); 
     240          }); 
     241          return element; 
     242           
     243        } else if (!eventName) { 
     244          Object.keys(getCacheForID(id)).each(function(eventName) { 
     245            element.stopObserving(eventName); 
     246          }); 
     247          return element; 
     248        } 
     249        if (!(wrapper = findWrapper(id, eventName, handler))) return element; 
     250      } 
    228251       
    229       var wrapper = findWrapper(id, eventName, handler); 
    230       if (!wrapper) return element; 
    231        
     252      var name = getDOMEventName(eventName); 
    232253      if (element.removeEventListener) { 
    233         element.removeEventListener(name, wrapper, false); 
     254        element.removeEventListener(name, wrapper.callback, false); 
    234255      } else { 
    235         element.detachEvent("on" + name, wrapper); 
     256        element.detachEvent("on" + name, wrapper.callback); 
    236257      } 
    237        
    238       destroyWrapper(id, eventName, handler); 
    239        
     258 
     259      destroyWrapper(wrapper); 
    240260      return element; 
    241261    }, 
    242    
     262 
    243263    fire: function(element, eventName, memo) { 
    244264      element = $(element); 
    245265      if (element == document && document.createEvent && !element.dispatchEvent)