Home | History | Annotate | Download | only in src
      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.
      4 
      5 /**
      6  * @fileoverview This contains an implementation of the EventTarget interface
      7  * as defined by DOM Level 2 Events.
      8  */
      9 base.exportTo('base', function() {
     10 
     11   /**
     12    * Creates a new EventTarget. This class implements the DOM level 2
     13    * EventTarget interface and can be used wherever those are used.
     14    * @constructor
     15    */
     16   function EventTarget() {
     17   }
     18 
     19   EventTarget.prototype = {
     20 
     21     /**
     22      * Adds an event listener to the target.
     23      * @param {string} type The name of the event.
     24      * @param {!Function|{handleEvent:Function}} handler The handler for the
     25      *     event. This is called when the event is dispatched.
     26      */
     27     addEventListener: function(type, handler) {
     28       if (!this.listeners_)
     29         this.listeners_ = Object.create(null);
     30       if (!(type in this.listeners_)) {
     31         this.listeners_[type] = [handler];
     32       } else {
     33         var handlers = this.listeners_[type];
     34         if (handlers.indexOf(handler) < 0)
     35           handlers.push(handler);
     36       }
     37     },
     38 
     39     /**
     40      * Removes an event listener from the target.
     41      * @param {string} type The name of the event.
     42      * @param {!Function|{handleEvent:Function}} handler The handler for the
     43      *     event.
     44      */
     45     removeEventListener: function(type, handler) {
     46       if (!this.listeners_)
     47         return;
     48       if (type in this.listeners_) {
     49         var handlers = this.listeners_[type];
     50         var index = handlers.indexOf(handler);
     51         if (index >= 0) {
     52           // Clean up if this was the last listener.
     53           if (handlers.length == 1)
     54             delete this.listeners_[type];
     55           else
     56             handlers.splice(index, 1);
     57         }
     58       }
     59     },
     60 
     61     /**
     62      * Dispatches an event and calls all the listeners that are listening to
     63      * the type of the event.
     64      * @param {!cr.event.Event} event The event to dispatch.
     65      * @return {boolean} Whether the default action was prevented. If someone
     66      *     calls preventDefault on the event object then this returns false.
     67      */
     68     dispatchEvent: function(event) {
     69       if (!this.listeners_)
     70         return true;
     71 
     72       // Since we are using DOM Event objects we need to override some of the
     73       // properties and methods so that we can emulate this correctly.
     74       var self = this;
     75       event.__defineGetter__('target', function() {
     76         return self;
     77       });
     78       event.preventDefault = function() {
     79         this.returnValue = false;
     80       };
     81 
     82       var type = event.type;
     83       var prevented = 0;
     84       if (type in this.listeners_) {
     85         // Clone to prevent removal during dispatch
     86         var handlers = this.listeners_[type].concat();
     87         for (var i = 0, handler; handler = handlers[i]; i++) {
     88           if (handler.handleEvent)
     89             prevented |= handler.handleEvent.call(handler, event) === false;
     90           else
     91             prevented |= handler.call(this, event) === false;
     92         }
     93       }
     94 
     95       return !prevented && event.returnValue;
     96     }
     97   };
     98 
     99   // Export
    100   return {
    101     EventTarget: EventTarget
    102   };
    103 });
    104