1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** @fileoverview EventTracker is a simple class that manages the addition and 6 * removal of DOM event listeners. In particular, it keeps track of all 7 * listeners that have been added and makes it easy to remove some or all of 8 * them without requiring all the information again. This is particularly 9 * handy when the listener is a generated function such as a lambda or the 10 * result of calling Function.bind. 11 */ 12 13// Use an anonymous function to enable strict mode just for this file (which 14// will be concatenated with other files when embedded in Chrome) 15var EventTracker = (function() { 16 'use strict'; 17 18 /** 19 * Create an EventTracker to track a set of events. 20 * EventTracker instances are typically tied 1:1 with other objects or 21 * DOM elements whose listeners should be removed when the object is disposed 22 * or the corresponding elements are removed from the DOM. 23 * @constructor 24 */ 25 function EventTracker() { 26 /** 27 * @type {Array.<EventTracker.Entry>} 28 * @private 29 */ 30 this.listeners_ = []; 31 } 32 33 /** 34 * The type of the internal tracking entry. 35 * @typedef {{node: !Node, 36 * eventType: string, 37 * listener: Function, 38 * capture: boolean}} 39 */ 40 EventTracker.Entry; 41 42 EventTracker.prototype = { 43 /** 44 * Add an event listener - replacement for Node.addEventListener. 45 * @param {!Node} node The DOM node to add a listener to. 46 * @param {string} eventType The type of event to subscribe to. 47 * @param {Function} listener The listener to add. 48 * @param {boolean} capture Whether to invoke during the capture phase. 49 */ 50 add: function(node, eventType, listener, capture) { 51 var h = { 52 node: node, 53 eventType: eventType, 54 listener: listener, 55 capture: capture 56 }; 57 this.listeners_.push(h); 58 node.addEventListener(eventType, listener, capture); 59 }, 60 61 /** 62 * Remove any specified event listeners added with this EventTracker. 63 * @param {!Node} node The DOM node to remove a listener from. 64 * @param {string} eventType The type of event to remove. 65 */ 66 remove: function(node, eventType) { 67 this.listeners_ = this.listeners_.filter(function(h) { 68 if (h.node == node && h.eventType == eventType) { 69 EventTracker.removeEventListener_(h); 70 return false; 71 } 72 return true; 73 }); 74 }, 75 76 /** 77 * Remove all event listeners added with this EventTracker. 78 */ 79 removeAll: function() { 80 this.listeners_.forEach(EventTracker.removeEventListener_); 81 this.listeners_ = []; 82 } 83 }; 84 85 /** 86 * Remove a single event listener given it's tracker entry. It's up to the 87 * caller to ensure the entry is removed from listeners_. 88 * @param {EventTracker.Entry} h The entry describing the listener to remove. 89 * @private 90 */ 91 EventTracker.removeEventListener_ = function(h) { 92 h.node.removeEventListener(h.eventType, h.listener, h.capture); 93 }; 94 95 return EventTracker; 96})(); 97 98