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