# all files / ol/events/ eventtarget.js

100% Statements 51/51
90.91% Branches 20/22
100% Functions 7/7
100% Lines 51/51

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    1471×

    1×
    1×
    1×
    1×

    1×

    8306×

    8306×

    8306×

    1×

    1×
    10818×
    10818×
    10309×

    10818×
    10818×

    1×
    37145×
    37145×
    37145×
    37145×
    37145×
    37145×
    6834×
    6833×

    6834×
    7246×
    7×
    7×

    6834×
    6834×
    6834×
    156×

    6834×

    1×
    582×

    1×
    10×

    1×
    632×

    1×
    4048×
    4048×
    4048×
    4048×
    4048×

    156×
    156×

    3892×
    3892×
    3628×

     goog.provide('ol.events.EventTarget');

    goog.require('goog.asserts');
    goog.require('ol.Disposable');
    goog.require('ol.events');
    goog.require('ol.events.Event');

    /**
     * @classdesc
     * A simplified implementation of the W3C DOM Level 2 EventTarget interface.
     * @see {@link https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget}
     *
     * There are two important simplifications compared to the specification:
     *
     * 1. The handling of `useCapture` in `addEventListener` and
     *    `removeEventListener`. There is no real capture model.
     * 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`.
     *    There is no event target hierarchy. When a listener calls
     *    `stopPropagation` or `preventDefault` on an event object, it means that no
     *    more listeners after this one will be called. Same as when the listener
     *    returns false.
     *
     * @constructor
     * @extends {ol.Disposable}
     */
    ol.events.EventTarget = function() {

      goog.base(this);

      /**
       * @private
       * @type {!Object.<string, number>}
       */
      this.pendingRemovals_ = {};

      /**
       * @private
       * @type {!Object.<string, Array.<ol.events.ListenerFunctionType>>}
       */
      this.listeners_ = {};

    };
    goog.inherits(ol.events.EventTarget, ol.Disposable);

    /**
     * @param {string} type Type.
     * @param {ol.events.ListenerFunctionType} listener Listener.
     */
    ol.events.EventTarget.prototype.addEventListener = function(type, listener) {
      var listeners = this.listeners_[type];
      if (!listeners) {
        listeners = this.listeners_[type] = [];
      }
      Eif (listeners.indexOf(listener) === -1) {
        listeners.push(listener);
      }
    };

    /**
     * @param {{type: string,
     *     target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
     *     string} event Event or event type.
     * @return {boolean|undefined} `false` if anyone called preventDefault on the
     *     event object or if any of the listeners returned false.
     */
    ol.events.EventTarget.prototype.dispatchEvent = function(event) {
      var evt = typeof event === 'string' ? new ol.events.Event(event) : event;
      var type = evt.type;
      evt.target = this;
      var listeners = this.listeners_[type];
      var propagate;
      if (listeners) {
        if (!(type in this.pendingRemovals_)) {
          this.pendingRemovals_[type] = 0;
        }
        for (var i = 0, ii = listeners.length; i < ii; ++i) {
          if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
            propagate = false;
            break;
          }
        }
        var pendingRemovals = this.pendingRemovals_[type];
        delete this.pendingRemovals_[type];
        while (pendingRemovals--) {
          this.removeEventListener(type, ol.nullFunction);
        }
        return propagate;
      }
    };

    /**
     * @inheritDoc
     */
    ol.events.EventTarget.prototype.disposeInternal = function() {
      ol.events.unlistenAll(this);
    };

    /**
     * Get the listeners for a specified event type. Listeners are returned in the
     * order that they will be called in.
     *
     * @param {string} type Type.
     * @return {Array.<ol.events.ListenerFunctionType>} Listeners.
     */
    ol.events.EventTarget.prototype.getListeners = function(type) {
      return this.listeners_[type];
    };

    /**
     * @param {string=} opt_type Type. If not provided,
     *     `true` will be returned if this EventTarget has any listeners.
     * @return {boolean} Has listeners.
     */
    ol.events.EventTarget.prototype.hasListener = function(opt_type) {
      return opt_type ?
          opt_type in this.listeners_ :
          Object.keys(this.listeners_).length > 0;
    };

    /**
     * @param {string} type Type.
     * @param {ol.events.ListenerFunctionType} listener Listener.
     */
    ol.events.EventTarget.prototype.removeEventListener = function(type, listener) {
      var listeners = this.listeners_[type];
      Eif (listeners) {
        var index = listeners.indexOf(listener);
        goog.asserts.assert(index != -1, 'listener not found');
        if (type in this.pendingRemovals_) {
          // make listener a no-op, and remove later in #dispatchEvent()
          listeners[index] = ol.nullFunction;
          ++this.pendingRemovals_[type];
        } else {
          listeners.splice(index, 1);
          if (listeners.length === 0) {
            delete this.listeners_[type];
          }
        }
      }
    };