goog.events.listen_ = function()

in asdoc/library/closure/goog/events/events.js [215:284]


goog.events.listen_ = function(
    src, type, listener, callOnce, opt_options, opt_handler) {
  if (!type) {
    throw new Error('Invalid event type');
  }

  var capture =
      goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;
  if (capture && !goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
    if (goog.events.CAPTURE_SIMULATION_MODE ==
        goog.events.CaptureSimulationMode.OFF_AND_FAIL) {
      goog.asserts.fail('Can not register capture listener in IE8-.');
      return null;
    } else if (
        goog.events.CAPTURE_SIMULATION_MODE ==
        goog.events.CaptureSimulationMode.OFF_AND_SILENT) {
      return null;
    }
  }

  var listenerMap = goog.events.getListenerMap_(src);
  if (!listenerMap) {
    src[goog.events.LISTENER_MAP_PROP_] = listenerMap =
        new goog.events.ListenerMap(src);
  }

  var listenerObj = /** @type {goog.events.Listener} */ (
      listenerMap.add(type, listener, callOnce, capture, opt_handler));

  // If the listenerObj already has a proxy, it has been set up
  // previously. We simply return.
  if (listenerObj.proxy) {
    return listenerObj;
  }

  var proxy = goog.events.getProxy();
  listenerObj.proxy = proxy;

  proxy.src = src;
  proxy.listener = listenerObj;

  // Attach the proxy through the browser's API
  if (src.addEventListener) {
    // Don't pass an object as `capture` if the browser doesn't support that.
    if (!goog.events.BrowserFeature.PASSIVE_EVENTS) {
      opt_options = capture;
    }
    // Don't break tests that expect a boolean.
    if (opt_options === undefined) opt_options = false;
    src.addEventListener(type.toString(), proxy, opt_options);
  } else if (src.attachEvent) {
    // The else if above used to be an unconditional else. It would call
    // exception on IE11, spoiling the day of some callers. The previous
    // incarnation of this code, from 2007, indicates that it replaced an
    // earlier still version that caused excess allocations on IE6.
    src.attachEvent(goog.events.getOnString_(type.toString()), proxy);
  } else if (src.addListener && src.removeListener) {
    // In IE, MediaQueryList uses addListener() insteadd of addEventListener. In
    // Safari, there is no global for the MediaQueryList constructor, so we just
    // check whether the object "looks like" MediaQueryList.
    goog.asserts.assert(
        type === 'change', 'MediaQueryList only has a change event');
    src.addListener(proxy);
  } else {
    throw new Error('addEventListener and attachEvent are unavailable.');
  }

  goog.events.listenerCountEstimate_++;
  return listenerObj;
};