15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview This contains an implementation of the EventTarget interface
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as defined by DOM Level 2 Events.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('cr', function() {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a new EventTarget. This class implements the DOM level 2
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * EventTarget interface and can be used wherever those are used.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @constructor
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function EventTarget() {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventTarget.prototype = {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Adds an event listener to the target.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {string} type The name of the event.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {!Function|{handleEvent:Function}} handler The handler for the
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     event. This is called when the event is dispatched.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addEventListener: function(type, handler) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!this.listeners_)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.listeners_ = Object.create(null);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!(type in this.listeners_)) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this.listeners_[type] = [handler];
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var handlers = this.listeners_[type];
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (handlers.indexOf(handler) < 0)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          handlers.push(handler);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Removes an event listener from the target.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {string} type The name of the event.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {!Function|{handleEvent:Function}} handler The handler for the
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     event.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    removeEventListener: function(type, handler) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!this.listeners_)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type in this.listeners_) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var handlers = this.listeners_[type];
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var index = handlers.indexOf(handler);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (index >= 0) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Clean up if this was the last listener.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (handlers.length == 1)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            delete this.listeners_[type];
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            handlers.splice(index, 1);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Dispatches an event and calls all the listeners that are listening to
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the type of the event.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param {!cr.event.Event} event The event to dispatch.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @return {boolean} Whether the default action was prevented. If someone
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *     calls preventDefault on the event object then this returns false.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dispatchEvent: function(event) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!this.listeners_)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Since we are using DOM Event objects we need to override some of the
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // properties and methods so that we can emulate this correctly.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var self = this;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.__defineGetter__('target', function() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      });
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var type = event.type;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var prevented = 0;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (type in this.listeners_) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Clone to prevent removal during dispatch
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var handlers = this.listeners_[type].concat();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (var i = 0, handler; handler = handlers[i]; i++) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (handler.handleEvent)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prevented |= handler.handleEvent.call(handler, event) === false;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prevented |= handler.call(this, event) === false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return !prevented && !event.defaultPrevented;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Export
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventTarget: EventTarget
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
102