// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview This contains an implementation of the EventTarget interface
* as defined by DOM Level 2 Events.
*/
cr.define('cr', function() {
/**
* Creates a new EventTarget. This class implements the DOM level 2
* EventTarget interface and can be used wherever those are used.
* @constructor
*/
function EventTarget() {
}
EventTarget.prototype = {
/**
* Adds an event listener to the target.
* @param {string} type The name of the event.
* @param {!Function|{handleEvent:Function}} handler The handler for the
* event. This is called when the event is dispatched.
*/
addEventListener: function(type, handler) {
if (!this.listeners_)
this.listeners_ = Object.create(null);
if (!(type in this.listeners_)) {
this.listeners_[type] = [handler];
} else {
var handlers = this.listeners_[type];
if (handlers.indexOf(handler) < 0)
handlers.push(handler);
}
},
/**
* Removes an event listener from the target.
* @param {string} type The name of the event.
* @param {!Function|{handleEvent:Function}} handler The handler for the
* event.
*/
removeEventListener: function(type, handler) {
if (!this.listeners_)
return;
if (type in this.listeners_) {
var handlers = this.listeners_[type];
var index = handlers.indexOf(handler);
if (index >= 0) {
// Clean up if this was the last listener.
if (handlers.length == 1)
delete this.listeners_[type];
else
handlers.splice(index, 1);
}
}
},
/**
* Dispatches an event and calls all the listeners that are listening to
* the type of the event.
* @param {!cr.event.Event} event The event to dispatch.
* @return {boolean} Whether the default action was prevented. If someone
* calls preventDefault on the event object then this returns false.
*/
dispatchEvent: function(event) {
if (!this.listeners_)
return true;
// Since we are using DOM Event objects we need to override some of the
// properties and methods so that we can emulate this correctly.
var self = this;
event.__defineGetter__('target', function() {
return self;
});
event.preventDefault = function() {
this.returnValue = false;
};
var type = event.type;
var prevented = 0;
if (type in this.listeners_) {
// Clone to prevent removal during dispatch
var handlers = this.listeners_[type].concat();
for (var i = 0, handler; handler = handlers[i]; i++) {
if (handler.handleEvent)
prevented |= handler.handleEvent.call(handler, event) === false;
else
prevented |= handler.call(this, event) === false;
}
}
return !prevented && event.returnValue;
}
};
// Export
return {
EventTarget: EventTarget
};
});