| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2014 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. |
| --> |
| <link rel="import" href="/base/base.html"> |
| <script> |
| 'use strict'; |
| |
| /** |
| * @fileoverview This contains an implementation of the EventTarget interface |
| * as defined by DOM Level 2 Events. |
| */ |
| tv.exportTo('tv.b', 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.decorate = function(target) { |
| for (var k in EventTarget.prototype) { |
| if (k == 'decorate') |
| continue; |
| var v = EventTarget.prototype[k]; |
| if (typeof v !== 'function') |
| continue; |
| target[k] = v; |
| } |
| }; |
| |
| 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; |
| }); |
| var realPreventDefault = event.preventDefault; |
| event.preventDefault = function() { |
| realPreventDefault.call(this); |
| this.rawReturnValue = 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.rawReturnValue; |
| }, |
| |
| hasEventListener: function(type) { |
| return this.listeners_[type] !== undefined; |
| } |
| }; |
| |
| var EventTargetHelper = { |
| decorate: function(target) { |
| for (var k in EventTargetHelper) { |
| if (k == 'decorate') |
| continue; |
| var v = EventTargetHelper[k]; |
| if (typeof v !== 'function') |
| continue; |
| target[k] = v; |
| } |
| target.listenerCounts_ = {}; |
| }, |
| |
| addEventListener: function(type, listener, useCapture) { |
| this.__proto__.addEventListener.call( |
| this, type, listener, useCapture); |
| if (this.listenerCounts_[type] === undefined) |
| this.listenerCounts_[type] = 0; |
| this.listenerCounts_[type]++; |
| }, |
| |
| removeEventListener: function(type, listener, useCapture) { |
| this.__proto__.removeEventListener.call( |
| this, type, listener, useCapture); |
| this.listenerCounts_[type]--; |
| }, |
| |
| hasEventListener: function(type) { |
| return this.listenerCounts_[type] > 0; |
| } |
| }; |
| |
| // Export |
| return { |
| EventTarget: EventTarget, |
| EventTargetHelper: EventTargetHelper |
| }; |
| }); |
| </script> |