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;
};