1 // Copyright (c) 2012 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.
8 * @fileoverview This contains an implementation of the EventTarget interface
9 * as defined by DOM Level 2 Events.
11 tvcm.exportTo('tvcm', function() {
14 * Creates a new EventTarget. This class implements the DOM level 2
15 * EventTarget interface and can be used wherever those are used.
18 function EventTarget() {
21 EventTarget.prototype = {
24 * Adds an event listener to the target.
25 * @param {string} type The name of the event.
26 * @param {!Function|{handleEvent:Function}} handler The handler for the
27 * event. This is called when the event is dispatched.
29 addEventListener: function(type, handler) {
31 this.listeners_ = Object.create(null);
32 if (!(type in this.listeners_)) {
33 this.listeners_[type] = [handler];
35 var handlers = this.listeners_[type];
36 if (handlers.indexOf(handler) < 0)
37 handlers.push(handler);
42 * Removes an event listener from the target.
43 * @param {string} type The name of the event.
44 * @param {!Function|{handleEvent:Function}} handler The handler for the
47 removeEventListener: function(type, handler) {
50 if (type in this.listeners_) {
51 var handlers = this.listeners_[type];
52 var index = handlers.indexOf(handler);
54 // Clean up if this was the last listener.
55 if (handlers.length == 1)
56 delete this.listeners_[type];
58 handlers.splice(index, 1);
64 * Dispatches an event and calls all the listeners that are listening to
65 * the type of the event.
66 * @param {!cr.event.Event} event The event to dispatch.
67 * @return {boolean} Whether the default action was prevented. If someone
68 * calls preventDefault on the event object then this returns false.
70 dispatchEvent: function(event) {
74 // Since we are using DOM Event objects we need to override some of the
75 // properties and methods so that we can emulate this correctly.
77 event.__defineGetter__('target', function() {
80 var realPreventDefault = event.preventDefault;
81 event.preventDefault = function() {
82 realPreventDefault.call(this);
83 this.rawReturnValue = false;
86 var type = event.type;
88 if (type in this.listeners_) {
89 // Clone to prevent removal during dispatch
90 var handlers = this.listeners_[type].concat();
91 for (var i = 0, handler; handler = handlers[i]; i++) {
92 if (handler.handleEvent)
93 prevented |= handler.handleEvent.call(handler, event) === false;
95 prevented |= handler.call(this, event) === false;
99 return !prevented && event.rawReturnValue;
102 hasEventListener: function(type) {
103 return this.listeners_[type] !== undefined;
107 var EventTargetHelper = {
108 decorate: function(target) {
109 for (var k in EventTargetHelper) {
112 var v = EventTargetHelper[k];
113 if (typeof v !== 'function')
117 target.listenerCounts_ = {};
120 addEventListener: function(type, listener, useCapture) {
121 this.__proto__.addEventListener.call(
122 this, type, listener, useCapture);
123 if (this.listenerCounts_[type] === undefined)
124 this.listenerCounts_[type] = 0;
125 this.listenerCounts_[type]++;
128 removeEventListener: function(type, listener, useCapture) {
129 this.__proto__.removeEventListener.call(
130 this, type, listener, useCapture);
131 this.listenerCounts_[type]--;
134 hasEventListener: function(type) {
135 return this.listenerCounts_[type] > 0;
141 EventTarget: EventTarget,
142 EventTargetHelper: EventTargetHelper