You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ft...@apache.org on 2015/09/17 17:28:34 UTC
[19/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/browserevent.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/browserevent.js b/externs/GCL/externs/goog/events/browserevent.js
new file mode 100644
index 0000000..f0773ce
--- /dev/null
+++ b/externs/GCL/externs/goog/events/browserevent.js
@@ -0,0 +1,386 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A patched, standardized event object for browser events.
+ *
+ * <pre>
+ * The patched event object contains the following members:
+ * - type {string} Event type, e.g. 'click'
+ * - target {Object} The element that actually triggered the event
+ * - currentTarget {Object} The element the listener is attached to
+ * - relatedTarget {Object} For mouseover and mouseout, the previous object
+ * - offsetX {number} X-coordinate relative to target
+ * - offsetY {number} Y-coordinate relative to target
+ * - clientX {number} X-coordinate relative to viewport
+ * - clientY {number} Y-coordinate relative to viewport
+ * - screenX {number} X-coordinate relative to the edge of the screen
+ * - screenY {number} Y-coordinate relative to the edge of the screen
+ * - button {number} Mouse button. Use isButton() to test.
+ * - keyCode {number} Key-code
+ * - ctrlKey {boolean} Was ctrl key depressed
+ * - altKey {boolean} Was alt key depressed
+ * - shiftKey {boolean} Was shift key depressed
+ * - metaKey {boolean} Was meta key depressed
+ * - defaultPrevented {boolean} Whether the default action has been prevented
+ * - state {Object} History state object
+ *
+ * NOTE: The keyCode member contains the raw browser keyCode. For normalized
+ * key and character code use {@link goog.events.KeyHandler}.
+ * </pre>
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.events.BrowserEvent');
+goog.provide('goog.events.BrowserEvent.MouseButton');
+
+goog.require('goog.events.BrowserFeature');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventType');
+goog.require('goog.reflect');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Accepts a browser event object and creates a patched, cross browser event
+ * object.
+ * The content of this object will not be initialized if no event object is
+ * provided. If this is the case, init() needs to be invoked separately.
+ * @param {Event=} opt_e Browser event object.
+ * @param {EventTarget=} opt_currentTarget Current target for event.
+ * @constructor
+ * @extends {goog.events.Event}
+ */
+goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
+ goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : '');
+
+ /**
+ * Target that fired the event.
+ * @override
+ * @type {Node}
+ */
+ this.target = null;
+
+ /**
+ * Node that had the listener attached.
+ * @override
+ * @type {Node|undefined}
+ */
+ this.currentTarget = null;
+
+ /**
+ * For mouseover and mouseout events, the related object for the event.
+ * @type {Node}
+ */
+ this.relatedTarget = null;
+
+ /**
+ * X-coordinate relative to target.
+ * @type {number}
+ */
+ this.offsetX = 0;
+
+ /**
+ * Y-coordinate relative to target.
+ * @type {number}
+ */
+ this.offsetY = 0;
+
+ /**
+ * X-coordinate relative to the window.
+ * @type {number}
+ */
+ this.clientX = 0;
+
+ /**
+ * Y-coordinate relative to the window.
+ * @type {number}
+ */
+ this.clientY = 0;
+
+ /**
+ * X-coordinate relative to the monitor.
+ * @type {number}
+ */
+ this.screenX = 0;
+
+ /**
+ * Y-coordinate relative to the monitor.
+ * @type {number}
+ */
+ this.screenY = 0;
+
+ /**
+ * Which mouse button was pressed.
+ * @type {number}
+ */
+ this.button = 0;
+
+ /**
+ * Keycode of key press.
+ * @type {number}
+ */
+ this.keyCode = 0;
+
+ /**
+ * Keycode of key press.
+ * @type {number}
+ */
+ this.charCode = 0;
+
+ /**
+ * Whether control was pressed at time of event.
+ * @type {boolean}
+ */
+ this.ctrlKey = false;
+
+ /**
+ * Whether alt was pressed at time of event.
+ * @type {boolean}
+ */
+ this.altKey = false;
+
+ /**
+ * Whether shift was pressed at time of event.
+ * @type {boolean}
+ */
+ this.shiftKey = false;
+
+ /**
+ * Whether the meta key was pressed at time of event.
+ * @type {boolean}
+ */
+ this.metaKey = false;
+
+ /**
+ * History state object, only set for PopState events where it's a copy of the
+ * state object provided to pushState or replaceState.
+ * @type {Object}
+ */
+ this.state = null;
+
+ /**
+ * Whether the default platform modifier key was pressed at time of event.
+ * (This is control for all platforms except Mac, where it's Meta.)
+ * @type {boolean}
+ */
+ this.platformModifierKey = false;
+
+ /**
+ * The browser event object.
+ * @private {Event}
+ */
+ this.event_ = null;
+
+ if (opt_e) {
+ this.init(opt_e, opt_currentTarget);
+ }
+};
+goog.inherits(goog.events.BrowserEvent, goog.events.Event);
+
+
+/**
+ * Normalized button constants for the mouse.
+ * @enum {number}
+ */
+goog.events.BrowserEvent.MouseButton = {
+ LEFT: 0,
+ MIDDLE: 1,
+ RIGHT: 2
+};
+
+
+/**
+ * Static data for mapping mouse buttons.
+ * @type {!Array<number>}
+ */
+goog.events.BrowserEvent.IEButtonMap = [
+ 1, // LEFT
+ 4, // MIDDLE
+ 2 // RIGHT
+];
+
+
+/**
+ * Accepts a browser event object and creates a patched, cross browser event
+ * object.
+ * @param {Event} e Browser event object.
+ * @param {EventTarget=} opt_currentTarget Current target for event.
+ */
+goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
+ var type = this.type = e.type;
+
+ // TODO(nicksantos): Change this.target to type EventTarget.
+ this.target = /** @type {Node} */ (e.target) || e.srcElement;
+
+ // TODO(nicksantos): Change this.currentTarget to type EventTarget.
+ this.currentTarget = /** @type {Node} */ (opt_currentTarget);
+
+ var relatedTarget = /** @type {Node} */ (e.relatedTarget);
+ if (relatedTarget) {
+ // There's a bug in FireFox where sometimes, relatedTarget will be a
+ // chrome element, and accessing any property of it will get a permission
+ // denied exception. See:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=497780
+ if (goog.userAgent.GECKO) {
+ if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) {
+ relatedTarget = null;
+ }
+ }
+ // TODO(arv): Use goog.events.EventType when it has been refactored into its
+ // own file.
+ } else if (type == goog.events.EventType.MOUSEOVER) {
+ relatedTarget = e.fromElement;
+ } else if (type == goog.events.EventType.MOUSEOUT) {
+ relatedTarget = e.toElement;
+ }
+
+ this.relatedTarget = relatedTarget;
+
+ // Webkit emits a lame warning whenever layerX/layerY is accessed.
+ // http://code.google.com/p/chromium/issues/detail?id=101733
+ this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ?
+ e.offsetX : e.layerX;
+ this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ?
+ e.offsetY : e.layerY;
+
+ this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;
+ this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;
+ this.screenX = e.screenX || 0;
+ this.screenY = e.screenY || 0;
+
+ this.button = e.button;
+
+ this.keyCode = e.keyCode || 0;
+ this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);
+ this.ctrlKey = e.ctrlKey;
+ this.altKey = e.altKey;
+ this.shiftKey = e.shiftKey;
+ this.metaKey = e.metaKey;
+ this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
+ this.state = e.state;
+ this.event_ = e;
+ if (e.defaultPrevented) {
+ this.preventDefault();
+ }
+};
+
+
+/**
+ * Tests to see which button was pressed during the event. This is really only
+ * useful in IE and Gecko browsers. And in IE, it's only useful for
+ * mousedown/mouseup events, because click only fires for the left mouse button.
+ *
+ * Safari 2 only reports the left button being clicked, and uses the value '1'
+ * instead of 0. Opera only reports a mousedown event for the middle button, and
+ * no mouse events for the right button. Opera has default behavior for left and
+ * middle click that can only be overridden via a configuration setting.
+ *
+ * There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html.
+ *
+ * @param {goog.events.BrowserEvent.MouseButton} button The button
+ * to test for.
+ * @return {boolean} True if button was pressed.
+ */
+goog.events.BrowserEvent.prototype.isButton = function(button) {
+ if (!goog.events.BrowserFeature.HAS_W3C_BUTTON) {
+ if (this.type == 'click') {
+ return button == goog.events.BrowserEvent.MouseButton.LEFT;
+ } else {
+ return !!(this.event_.button &
+ goog.events.BrowserEvent.IEButtonMap[button]);
+ }
+ } else {
+ return this.event_.button == button;
+ }
+};
+
+
+/**
+ * Whether this has an "action"-producing mouse button.
+ *
+ * By definition, this includes left-click on windows/linux, and left-click
+ * without the ctrl key on Macs.
+ *
+ * @return {boolean} The result.
+ */
+goog.events.BrowserEvent.prototype.isMouseActionButton = function() {
+ // Webkit does not ctrl+click to be a right-click, so we
+ // normalize it to behave like Gecko and Opera.
+ return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&
+ !(goog.userAgent.WEBKIT && goog.userAgent.MAC && this.ctrlKey);
+};
+
+
+/**
+ * @override
+ */
+goog.events.BrowserEvent.prototype.stopPropagation = function() {
+ goog.events.BrowserEvent.superClass_.stopPropagation.call(this);
+ if (this.event_.stopPropagation) {
+ this.event_.stopPropagation();
+ } else {
+ this.event_.cancelBubble = true;
+ }
+};
+
+
+/**
+ * @override
+ */
+goog.events.BrowserEvent.prototype.preventDefault = function() {
+ goog.events.BrowserEvent.superClass_.preventDefault.call(this);
+ var be = this.event_;
+ if (!be.preventDefault) {
+ be.returnValue = false;
+ if (goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT) {
+ /** @preserveTry */
+ try {
+ // Most keys can be prevented using returnValue. Some special keys
+ // require setting the keyCode to -1 as well:
+ //
+ // In IE7:
+ // F3, F5, F10, F11, Ctrl+P, Crtl+O, Ctrl+F (these are taken from IE6)
+ //
+ // In IE8:
+ // Ctrl+P, Crtl+O, Ctrl+F (F1-F12 cannot be stopped through the event)
+ //
+ // We therefore do this for all function keys as well as when Ctrl key
+ // is pressed.
+ var VK_F1 = 112;
+ var VK_F12 = 123;
+ if (be.ctrlKey || be.keyCode >= VK_F1 && be.keyCode <= VK_F12) {
+ be.keyCode = -1;
+ }
+ } catch (ex) {
+ // IE throws an 'access denied' exception when trying to change
+ // keyCode in some situations (e.g. srcElement is input[type=file],
+ // or srcElement is an anchor tag rewritten by parent's innerHTML).
+ // Do nothing in this case.
+ }
+ }
+ } else {
+ be.preventDefault();
+ }
+};
+
+
+/**
+ * @return {Event} The underlying browser event object.
+ */
+goog.events.BrowserEvent.prototype.getBrowserEvent = function() {
+ return this.event_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/browserfeature3.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/browserfeature3.js b/externs/GCL/externs/goog/events/browserfeature3.js
new file mode 100644
index 0000000..61b9d60
--- /dev/null
+++ b/externs/GCL/externs/goog/events/browserfeature3.js
@@ -0,0 +1,85 @@
+// Copyright 2010 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Browser capability checks for the events package.
+ *
+ */
+
+
+goog.provide('goog.events.BrowserFeature');
+
+goog.require('goog.userAgent');
+
+
+/**
+ * Enum of browser capabilities.
+ * @enum {boolean}
+ */
+goog.events.BrowserFeature = {
+ /**
+ * Whether the button attribute of the event is W3C compliant. False in
+ * Internet Explorer prior to version 9; document-version dependent.
+ */
+ HAS_W3C_BUTTON: !goog.userAgent.IE ||
+ goog.userAgent.isDocumentModeOrHigher(9),
+
+ /**
+ * Whether the browser supports full W3C event model.
+ */
+ HAS_W3C_EVENT_SUPPORT: !goog.userAgent.IE ||
+ goog.userAgent.isDocumentModeOrHigher(9),
+
+ /**
+ * To prevent default in IE7-8 for certain keydown events we need set the
+ * keyCode to -1.
+ */
+ SET_KEY_CODE_TO_PREVENT_DEFAULT: goog.userAgent.IE &&
+ !goog.userAgent.isVersionOrHigher('9'),
+
+ /**
+ * Whether the {@code navigator.onLine} property is supported.
+ */
+ HAS_NAVIGATOR_ONLINE_PROPERTY: !goog.userAgent.WEBKIT ||
+ goog.userAgent.isVersionOrHigher('528'),
+
+ /**
+ * Whether HTML5 network online/offline events are supported.
+ */
+ HAS_HTML5_NETWORK_EVENT_SUPPORT:
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9b') ||
+ goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8') ||
+ goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher('9.5') ||
+ goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('528'),
+
+ /**
+ * Whether HTML5 network events fire on document.body, or otherwise the
+ * window.
+ */
+ HTML5_NETWORK_EVENTS_FIRE_ON_BODY:
+ goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('8') ||
+ goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'),
+
+ /**
+ * Whether touch is enabled in the browser.
+ */
+ TOUCH_ENABLED:
+ ('ontouchstart' in goog.global ||
+ !!(goog.global['document'] &&
+ document.documentElement &&
+ 'ontouchstart' in document.documentElement) ||
+ // IE10 uses non-standard touch events, so it has a different check.
+ !!(goog.global['navigator'] &&
+ goog.global['navigator']['msMaxTouchPoints']))
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/event.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/event.js b/externs/GCL/externs/goog/events/event.js
new file mode 100644
index 0000000..b671289
--- /dev/null
+++ b/externs/GCL/externs/goog/events/event.js
@@ -0,0 +1,143 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A base class for event objects.
+ *
+ */
+
+
+goog.provide('goog.events.Event');
+goog.provide('goog.events.EventLike');
+
+/**
+ * goog.events.Event no longer depends on goog.Disposable. Keep requiring
+ * goog.Disposable here to not break projects which assume this dependency.
+ * @suppress {extraRequire}
+ */
+goog.require('goog.Disposable');
+goog.require('goog.events.EventId');
+
+
+/**
+ * A typedef for event like objects that are dispatchable via the
+ * goog.events.dispatchEvent function. strings are treated as the type for a
+ * goog.events.Event. Objects are treated as an extension of a new
+ * goog.events.Event with the type property of the object being used as the type
+ * of the Event.
+ * @typedef {string|Object|goog.events.Event|goog.events.EventId}
+ */
+goog.events.EventLike;
+
+
+
+/**
+ * A base class for event objects, so that they can support preventDefault and
+ * stopPropagation.
+ *
+ * @param {string|!goog.events.EventId} type Event Type.
+ * @param {Object=} opt_target Reference to the object that is the target of
+ * this event. It has to implement the {@code EventTarget} interface
+ * declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}.
+ * @constructor
+ */
+goog.events.Event = function(type, opt_target) {
+ /**
+ * Event type.
+ * @type {string}
+ */
+ this.type = type instanceof goog.events.EventId ? String(type) : type;
+
+ /**
+ * TODO(tbreisacher): The type should probably be
+ * EventTarget|goog.events.EventTarget.
+ *
+ * Target of the event.
+ * @type {Object|undefined}
+ */
+ this.target = opt_target;
+
+ /**
+ * Object that had the listener attached.
+ * @type {Object|undefined}
+ */
+ this.currentTarget = this.target;
+
+ /**
+ * Whether to cancel the event in internal capture/bubble processing for IE.
+ * @type {boolean}
+ * @public
+ * @suppress {underscore|visibility} Technically public, but referencing this
+ * outside this package is strongly discouraged.
+ */
+ this.propagationStopped_ = false;
+
+ /**
+ * Whether the default action has been prevented.
+ * This is a property to match the W3C specification at
+ * {@link http://www.w3.org/TR/DOM-Level-3-Events/
+ * #events-event-type-defaultPrevented}.
+ * Must be treated as read-only outside the class.
+ * @type {boolean}
+ */
+ this.defaultPrevented = false;
+
+ /**
+ * Return value for in internal capture/bubble processing for IE.
+ * @type {boolean}
+ * @public
+ * @suppress {underscore|visibility} Technically public, but referencing this
+ * outside this package is strongly discouraged.
+ */
+ this.returnValue_ = true;
+};
+
+
+/**
+ * Stops event propagation.
+ */
+goog.events.Event.prototype.stopPropagation = function() {
+ this.propagationStopped_ = true;
+};
+
+
+/**
+ * Prevents the default action, for example a link redirecting to a url.
+ */
+goog.events.Event.prototype.preventDefault = function() {
+ this.defaultPrevented = true;
+ this.returnValue_ = false;
+};
+
+
+/**
+ * Stops the propagation of the event. It is equivalent to
+ * {@code e.stopPropagation()}, but can be used as the callback argument of
+ * {@link goog.events.listen} without declaring another function.
+ * @param {!goog.events.Event} e An event.
+ */
+goog.events.Event.stopPropagation = function(e) {
+ e.stopPropagation();
+};
+
+
+/**
+ * Prevents the default action. It is equivalent to
+ * {@code e.preventDefault()}, but can be used as the callback argument of
+ * {@link goog.events.listen} without declaring another function.
+ * @param {!goog.events.Event} e An event.
+ */
+goog.events.Event.preventDefault = function(e) {
+ e.preventDefault();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventhandler.js b/externs/GCL/externs/goog/events/eventhandler.js
new file mode 100644
index 0000000..16b1ad0
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventhandler.js
@@ -0,0 +1,459 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Class to create objects which want to handle multiple events
+ * and have their listeners easily cleaned up via a dispose method.
+ *
+ * Example:
+ * <pre>
+ * function Something() {
+ * Something.base(this);
+ *
+ * ... set up object ...
+ *
+ * // Add event listeners
+ * this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);
+ * this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);
+ * this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);
+ * this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);
+ * this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);
+ * }
+ * goog.inherits(Something, goog.events.EventHandler);
+ *
+ * Something.prototype.disposeInternal = function() {
+ * Something.base(this, 'disposeInternal');
+ * goog.dom.removeNode(this.container);
+ * };
+ *
+ *
+ * // Then elsewhere:
+ *
+ * var activeSomething = null;
+ * function openSomething() {
+ * activeSomething = new Something();
+ * }
+ *
+ * function closeSomething() {
+ * if (activeSomething) {
+ * activeSomething.dispose(); // Remove event listeners
+ * activeSomething = null;
+ * }
+ * }
+ * </pre>
+ *
+ */
+
+goog.provide('goog.events.EventHandler');
+
+goog.require('goog.Disposable');
+goog.require('goog.events');
+goog.require('goog.object');
+
+goog.forwardDeclare('goog.events.EventWrapper');
+
+
+
+/**
+ * Super class for objects that want to easily manage a number of event
+ * listeners. It allows a short cut to listen and also provides a quick way
+ * to remove all events listeners belonging to this object.
+ * @param {SCOPE=} opt_scope Object in whose scope to call the listeners.
+ * @constructor
+ * @extends {goog.Disposable}
+ * @template SCOPE
+ */
+goog.events.EventHandler = function(opt_scope) {
+ goog.Disposable.call(this);
+ // TODO(mknichel): Rename this to this.scope_ and fix the classes in google3
+ // that access this private variable. :(
+ this.handler_ = opt_scope;
+
+ /**
+ * Keys for events that are being listened to.
+ * @type {!Object<!goog.events.Key>}
+ * @private
+ */
+ this.keys_ = {};
+};
+goog.inherits(goog.events.EventHandler, goog.Disposable);
+
+
+/**
+ * Utility array used to unify the cases of listening for an array of types
+ * and listening for a single event, without using recursion or allocating
+ * an array each time.
+ * @type {!Array<string>}
+ * @const
+ * @private
+ */
+goog.events.EventHandler.typeArray_ = [];
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted then the
+ * EventHandler's handleEvent method will be used.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
+ * opt_fn Optional callback function to be used as the listener or an object
+ * with handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listen = function(
+ src, type, opt_fn, opt_capture) {
+ return this.listen_(src, type, opt_fn, opt_capture);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted then the
+ * EventHandler's handleEvent method will be used.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
+ * null|undefined} fn Optional callback function to be used as the
+ * listener or an object with handleEvent function.
+ * @param {boolean|undefined} capture Optional whether to use capture phase.
+ * @param {T} scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template T,EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listenWithScope = function(
+ src, type, fn, capture, scope) {
+ // TODO(mknichel): Deprecate this function.
+ return this.listen_(src, type, fn, capture, scope);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted then the
+ * EventHandler's handleEvent method will be used.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @param {Object=} opt_scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ * @private
+ */
+goog.events.EventHandler.prototype.listen_ = function(src, type, opt_fn,
+ opt_capture,
+ opt_scope) {
+ if (!goog.isArray(type)) {
+ if (type) {
+ goog.events.EventHandler.typeArray_[0] = type.toString();
+ }
+ type = goog.events.EventHandler.typeArray_;
+ }
+ for (var i = 0; i < type.length; i++) {
+ var listenerObj = goog.events.listen(
+ src, type[i], opt_fn || this.handleEvent,
+ opt_capture || false,
+ opt_scope || this.handler_ || this);
+
+ if (!listenerObj) {
+ // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
+ // (goog.events.CaptureSimulationMode) in IE8-, it will return null
+ // value.
+ return this;
+ }
+
+ var key = listenerObj.key;
+ this.keys_[key] = listenerObj;
+ }
+
+ return this;
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted, then the
+ * EventHandler's handleEvent method will be used. After the event has fired the
+ * event listener is removed from the target. If an array of event types is
+ * provided, each event type will be listened to once.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listenOnce = function(
+ src, type, opt_fn, opt_capture) {
+ return this.listenOnce_(src, type, opt_fn, opt_capture);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted, then the
+ * EventHandler's handleEvent method will be used. After the event has fired the
+ * event listener is removed from the target. If an array of event types is
+ * provided, each event type will be listened to once.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
+ * null|undefined} fn Optional callback function to be used as the
+ * listener or an object with handleEvent function.
+ * @param {boolean|undefined} capture Optional whether to use capture phase.
+ * @param {T} scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template T,EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listenOnceWithScope = function(
+ src, type, fn, capture, scope) {
+ // TODO(mknichel): Deprecate this function.
+ return this.listenOnce_(src, type, fn, capture, scope);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted, then the
+ * EventHandler's handleEvent method will be used. After the event has fired
+ * the event listener is removed from the target. If an array of event types is
+ * provided, each event type will be listened to once.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @param {Object=} opt_scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ * @private
+ */
+goog.events.EventHandler.prototype.listenOnce_ = function(
+ src, type, opt_fn, opt_capture, opt_scope) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ this.listenOnce_(src, type[i], opt_fn, opt_capture, opt_scope);
+ }
+ } else {
+ var listenerObj = goog.events.listenOnce(
+ src, type, opt_fn || this.handleEvent, opt_capture,
+ opt_scope || this.handler_ || this);
+ if (!listenerObj) {
+ // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
+ // (goog.events.CaptureSimulationMode) in IE8-, it will return null
+ // value.
+ return this;
+ }
+
+ var key = listenerObj.key;
+ this.keys_[key] = listenerObj;
+ }
+
+ return this;
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.EventTarget}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The node to listen to
+ * events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener
+ * Callback method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ */
+goog.events.EventHandler.prototype.listenWithWrapper = function(
+ src, wrapper, listener, opt_capt) {
+ // TODO(mknichel): Remove the opt_scope from this function and then
+ // templatize it.
+ return this.listenWithWrapper_(src, wrapper, listener, opt_capt);
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.EventTarget}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The node to listen to
+ * events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}
+ * listener Optional callback function to be used as the
+ * listener or an object with handleEvent function.
+ * @param {boolean|undefined} capture Optional whether to use capture phase.
+ * @param {T} scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template T
+ */
+goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(
+ src, wrapper, listener, capture, scope) {
+ // TODO(mknichel): Deprecate this function.
+ return this.listenWithWrapper_(src, wrapper, listener, capture, scope);
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.EventTarget}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The node to listen to
+ * events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
+ * method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @private
+ */
+goog.events.EventHandler.prototype.listenWithWrapper_ = function(
+ src, wrapper, listener, opt_capt, opt_scope) {
+ wrapper.listen(src, listener, opt_capt, opt_scope || this.handler_ || this,
+ this);
+ return this;
+};
+
+
+/**
+ * @return {number} Number of listeners registered by this handler.
+ */
+goog.events.EventHandler.prototype.getListenerCount = function() {
+ var count = 0;
+ for (var key in this.keys_) {
+ if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {
+ count++;
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Unlistens on an event.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types to unlisten to.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @param {Object=} opt_scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler} This object, allowing for chaining of
+ * calls.
+ * @template EVENTOBJ
+ */
+goog.events.EventHandler.prototype.unlisten = function(src, type, opt_fn,
+ opt_capture,
+ opt_scope) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ this.unlisten(src, type[i], opt_fn, opt_capture, opt_scope);
+ }
+ } else {
+ var listener = goog.events.getListener(src, type,
+ opt_fn || this.handleEvent,
+ opt_capture, opt_scope || this.handler_ || this);
+
+ if (listener) {
+ goog.events.unlistenByKey(listener);
+ delete this.keys_[listener.key];
+ }
+ }
+
+ return this;
+};
+
+
+/**
+ * Removes an event listener which was added with listenWithWrapper().
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The target to stop
+ * listening to events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to remove.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase of the
+ * event.
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @return {!goog.events.EventHandler} This object, allowing for chaining of
+ * calls.
+ */
+goog.events.EventHandler.prototype.unlistenWithWrapper = function(src, wrapper,
+ listener, opt_capt, opt_scope) {
+ wrapper.unlisten(src, listener, opt_capt,
+ opt_scope || this.handler_ || this, this);
+ return this;
+};
+
+
+/**
+ * Unlistens to all events.
+ */
+goog.events.EventHandler.prototype.removeAll = function() {
+ goog.object.forEach(this.keys_, goog.events.unlistenByKey);
+ this.keys_ = {};
+};
+
+
+/**
+ * Disposes of this EventHandler and removes all listeners that it registered.
+ * @override
+ * @protected
+ */
+goog.events.EventHandler.prototype.disposeInternal = function() {
+ goog.events.EventHandler.superClass_.disposeInternal.call(this);
+ this.removeAll();
+};
+
+
+/**
+ * Default event handler
+ * @param {goog.events.Event} e Event object.
+ */
+goog.events.EventHandler.prototype.handleEvent = function(e) {
+ throw Error('EventHandler.handleEvent not implemented');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventid.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventid.js b/externs/GCL/externs/goog/events/eventid.js
new file mode 100644
index 0000000..9a4822e
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventid.js
@@ -0,0 +1,47 @@
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+goog.provide('goog.events.EventId');
+
+
+
+/**
+ * A templated class that is used when registering for events. Typical usage:
+ * <code>
+ * /** @type {goog.events.EventId<MyEventObj>}
+ * var myEventId = new goog.events.EventId(
+ * goog.events.getUniqueId(('someEvent'));
+ *
+ * // No need to cast or declare here since the compiler knows the correct
+ * // type of 'evt' (MyEventObj).
+ * something.listen(myEventId, function(evt) {});
+ * </code>
+ *
+ * @param {string} eventId
+ * @template T
+ * @constructor
+ * @struct
+ * @final
+ */
+goog.events.EventId = function(eventId) {
+ /** @const */ this.id = eventId;
+};
+
+
+/**
+ * @override
+ */
+goog.events.EventId.prototype.toString = function() {
+ return this.id;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/events.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/events.js b/externs/GCL/externs/goog/events/events.js
new file mode 100644
index 0000000..39cc405
--- /dev/null
+++ b/externs/GCL/externs/goog/events/events.js
@@ -0,0 +1,983 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview An event manager for both native browser event
+ * targets and custom JavaScript event targets
+ * ({@code goog.events.Listenable}). This provides an abstraction
+ * over browsers' event systems.
+ *
+ * It also provides a simulation of W3C event model's capture phase in
+ * Internet Explorer (IE 8 and below). Caveat: the simulation does not
+ * interact well with listeners registered directly on the elements
+ * (bypassing goog.events) or even with listeners registered via
+ * goog.events in a separate JS binary. In these cases, we provide
+ * no ordering guarantees.
+ *
+ * The listeners will receive a "patched" event object. Such event object
+ * contains normalized values for certain event properties that differs in
+ * different browsers.
+ *
+ * Example usage:
+ * <pre>
+ * goog.events.listen(myNode, 'click', function(e) { alert('woo') });
+ * goog.events.listen(myNode, 'mouseover', mouseHandler, true);
+ * goog.events.unlisten(myNode, 'mouseover', mouseHandler, true);
+ * goog.events.removeAll(myNode);
+ * </pre>
+ *
+ * in IE and event object patching]
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * @see ../demos/events.html
+ * @see ../demos/event-propagation.html
+ * @see ../demos/stopevent.html
+ */
+
+// IMPLEMENTATION NOTES:
+// goog.events stores an auxiliary data structure on each EventTarget
+// source being listened on. This allows us to take advantage of GC,
+// having the data structure GC'd when the EventTarget is GC'd. This
+// GC behavior is equivalent to using W3C DOM Events directly.
+
+goog.provide('goog.events');
+goog.provide('goog.events.CaptureSimulationMode');
+goog.provide('goog.events.Key');
+goog.provide('goog.events.ListenableType');
+
+goog.require('goog.asserts');
+goog.require('goog.debug.entryPointRegistry');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.BrowserFeature');
+goog.require('goog.events.Listenable');
+goog.require('goog.events.ListenerMap');
+
+goog.forwardDeclare('goog.debug.ErrorHandler');
+goog.forwardDeclare('goog.events.EventWrapper');
+
+
+/**
+ * @typedef {number|goog.events.ListenableKey}
+ */
+goog.events.Key;
+
+
+/**
+ * @typedef {EventTarget|goog.events.Listenable}
+ */
+goog.events.ListenableType;
+
+
+/**
+ * Property name on a native event target for the listener map
+ * associated with the event target.
+ * @private @const {string}
+ */
+goog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0);
+
+
+/**
+ * String used to prepend to IE event types.
+ * @const
+ * @private
+ */
+goog.events.onString_ = 'on';
+
+
+/**
+ * Map of computed "on<eventname>" strings for IE event types. Caching
+ * this removes an extra object allocation in goog.events.listen which
+ * improves IE6 performance.
+ * @const
+ * @dict
+ * @private
+ */
+goog.events.onStringMap_ = {};
+
+
+/**
+ * @enum {number} Different capture simulation mode for IE8-.
+ */
+goog.events.CaptureSimulationMode = {
+ /**
+ * Does not perform capture simulation. Will asserts in IE8- when you
+ * add capture listeners.
+ */
+ OFF_AND_FAIL: 0,
+
+ /**
+ * Does not perform capture simulation, silently ignore capture
+ * listeners.
+ */
+ OFF_AND_SILENT: 1,
+
+ /**
+ * Performs capture simulation.
+ */
+ ON: 2
+};
+
+
+/**
+ * @define {number} The capture simulation mode for IE8-. By default,
+ * this is ON.
+ */
+goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2);
+
+
+/**
+ * Estimated count of total native listeners.
+ * @private {number}
+ */
+goog.events.listenerCountEstimate_ = 0;
+
+
+/**
+ * Adds an event listener for a specific event on a native event
+ * target (such as a DOM element) or an object that has implemented
+ * {@link goog.events.Listenable}. A listener can only be added once
+ * to an object and if it is added again the key for the listener is
+ * returned. Note that if the existing listener is a one-off listener
+ * (registered via listenOnce), it will no longer be a one-off
+ * listener after a call to listen().
+ *
+ * @param {EventTarget|goog.events.Listenable} src The node to listen
+ * to events on.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
+ * listener Callback method, or an object with a handleEvent function.
+ * WARNING: passing an Object is now softly deprecated.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {T=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.Key} Unique key for the listener.
+ * @template T,EVENTOBJ
+ */
+goog.events.listen = function(src, type, listener, opt_capt, opt_handler) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ goog.events.listen(src, type[i], listener, opt_capt, opt_handler);
+ }
+ return null;
+ }
+
+ listener = goog.events.wrapListener(listener);
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.listen(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, opt_capt, opt_handler);
+ } else {
+ return goog.events.listen_(
+ /** @type {!EventTarget} */ (src),
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, /* callOnce */ false, opt_capt, opt_handler);
+ }
+};
+
+
+/**
+ * Adds an event listener for a specific event on a native event
+ * target. A listener can only be added once to an object and if it
+ * is added again the key for the listener is returned.
+ *
+ * Note that a one-off listener will not change an existing listener,
+ * if any. On the other hand a normal listener will change existing
+ * one-off listener to become a normal listener.
+ *
+ * @param {EventTarget} src The node to listen to events on.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {!Function} listener Callback function.
+ * @param {boolean} callOnce Whether the listener is a one-off
+ * listener or otherwise.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ * @private
+ */
+goog.events.listen_ = function(
+ src, type, listener, callOnce, opt_capt, opt_handler) {
+ if (!type) {
+ throw Error('Invalid event type');
+ }
+
+ var capture = !!opt_capt;
+ 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 = listenerMap.add(
+ type, listener, callOnce, opt_capt, 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) {
+ src.addEventListener(type.toString(), proxy, capture);
+ } else {
+ // The else above used to be else if (src.attachEvent) and then there was
+ // another else statement that threw an exception warning the developer
+ // they made a mistake. This resulted in an extra object allocation in IE6
+ // due to a wrapper object that had to be implemented around the element
+ // and so was removed.
+ src.attachEvent(goog.events.getOnString_(type.toString()), proxy);
+ }
+
+ goog.events.listenerCountEstimate_++;
+ return listenerObj;
+};
+
+
+/**
+ * Helper function for returning a proxy function.
+ * @return {!Function} A new or reused function object.
+ */
+goog.events.getProxy = function() {
+ var proxyCallbackFunction = goog.events.handleBrowserEvent_;
+ // Use a local var f to prevent one allocation.
+ var f = goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT ?
+ function(eventObject) {
+ return proxyCallbackFunction.call(f.src, f.listener, eventObject);
+ } :
+ function(eventObject) {
+ var v = proxyCallbackFunction.call(f.src, f.listener, eventObject);
+ // NOTE(chrishenry): In IE, we hack in a capture phase. However, if
+ // there is inline event handler which tries to prevent default (for
+ // example <a href="..." onclick="return false">...</a>) in a
+ // descendant element, the prevent default will be overridden
+ // by this listener if this listener were to return true. Hence, we
+ // return undefined.
+ if (!v) return v;
+ };
+ return f;
+};
+
+
+/**
+ * Adds an event listener for a specific event on a native event
+ * target (such as a DOM element) or an object that has implemented
+ * {@link goog.events.Listenable}. After the event has fired the event
+ * listener is removed from the target.
+ *
+ * If an existing listener already exists, listenOnce will do
+ * nothing. In particular, if the listener was previously registered
+ * via listen(), listenOnce() will not turn the listener into a
+ * one-off listener. Similarly, if there is already an existing
+ * one-off listener, listenOnce does not modify the listeners (it is
+ * still a once listener).
+ *
+ * @param {EventTarget|goog.events.Listenable} src The node to listen
+ * to events on.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
+ * listener Callback method.
+ * @param {boolean=} opt_capt Fire in capture phase?.
+ * @param {T=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.Key} Unique key for the listener.
+ * @template T,EVENTOBJ
+ */
+goog.events.listenOnce = function(src, type, listener, opt_capt, opt_handler) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ goog.events.listenOnce(src, type[i], listener, opt_capt, opt_handler);
+ }
+ return null;
+ }
+
+ listener = goog.events.wrapListener(listener);
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.listenOnce(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, opt_capt, opt_handler);
+ } else {
+ return goog.events.listen_(
+ /** @type {!EventTarget} */ (src),
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, /* callOnce */ true, opt_capt, opt_handler);
+ }
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.Listenable}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target to
+ * listen to events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener
+ * Callback method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {T=} opt_handler Element in whose scope to call the listener.
+ * @template T
+ */
+goog.events.listenWithWrapper = function(src, wrapper, listener, opt_capt,
+ opt_handler) {
+ wrapper.listen(src, listener, opt_capt, opt_handler);
+};
+
+
+/**
+ * Removes an event listener which was added with listen().
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target to stop
+ * listening to events on.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types to unlisten to.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to remove.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase of the
+ * event.
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ * @return {?boolean} indicating whether the listener was there to remove.
+ * @template EVENTOBJ
+ */
+goog.events.unlisten = function(src, type, listener, opt_capt, opt_handler) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ goog.events.unlisten(src, type[i], listener, opt_capt, opt_handler);
+ }
+ return null;
+ }
+
+ listener = goog.events.wrapListener(listener);
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.unlisten(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, opt_capt, opt_handler);
+ }
+
+ if (!src) {
+ // TODO(chrishenry): We should tighten the API to only accept
+ // non-null objects, or add an assertion here.
+ return false;
+ }
+
+ var capture = !!opt_capt;
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (src));
+ if (listenerMap) {
+ var listenerObj = listenerMap.getListener(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, capture, opt_handler);
+ if (listenerObj) {
+ return goog.events.unlistenByKey(listenerObj);
+ }
+ }
+
+ return false;
+};
+
+
+/**
+ * Removes an event listener which was added with listen() by the key
+ * returned by listen().
+ *
+ * @param {goog.events.Key} key The key returned by listen() for this
+ * event listener.
+ * @return {boolean} indicating whether the listener was there to remove.
+ */
+goog.events.unlistenByKey = function(key) {
+ // TODO(chrishenry): Remove this check when tests that rely on this
+ // are fixed.
+ if (goog.isNumber(key)) {
+ return false;
+ }
+
+ var listener = /** @type {goog.events.ListenableKey} */ (key);
+ if (!listener || listener.removed) {
+ return false;
+ }
+
+ var src = listener.src;
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.unlistenByKey(listener);
+ }
+
+ var type = listener.type;
+ var proxy = listener.proxy;
+ if (src.removeEventListener) {
+ src.removeEventListener(type, proxy, listener.capture);
+ } else if (src.detachEvent) {
+ src.detachEvent(goog.events.getOnString_(type), proxy);
+ }
+ goog.events.listenerCountEstimate_--;
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (src));
+ // TODO(chrishenry): Try to remove this conditional and execute the
+ // first branch always. This should be safe.
+ if (listenerMap) {
+ listenerMap.removeByKey(listener);
+ if (listenerMap.getTypeCount() == 0) {
+ // Null the src, just because this is simple to do (and useful
+ // for IE <= 7).
+ listenerMap.src = null;
+ // We don't use delete here because IE does not allow delete
+ // on a window object.
+ src[goog.events.LISTENER_MAP_PROP_] = null;
+ }
+ } else {
+ listener.markAsRemoved();
+ }
+
+ return true;
+};
+
+
+/**
+ * Removes an event listener which was added with listenWithWrapper().
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target to stop
+ * listening to events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to remove.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase of the
+ * event.
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ */
+goog.events.unlistenWithWrapper = function(src, wrapper, listener, opt_capt,
+ opt_handler) {
+ wrapper.unlisten(src, listener, opt_capt, opt_handler);
+};
+
+
+/**
+ * Removes all listeners from an object. You can also optionally
+ * remove listeners of a particular type.
+ *
+ * @param {Object|undefined} obj Object to remove listeners from. Must be an
+ * EventTarget or a goog.events.Listenable.
+ * @param {string|!goog.events.EventId=} opt_type Type of event to remove.
+ * Default is all types.
+ * @return {number} Number of listeners removed.
+ */
+goog.events.removeAll = function(obj, opt_type) {
+ // TODO(chrishenry): Change the type of obj to
+ // (!EventTarget|!goog.events.Listenable).
+
+ if (!obj) {
+ return 0;
+ }
+
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.removeAllListeners(opt_type);
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (obj));
+ if (!listenerMap) {
+ return 0;
+ }
+
+ var count = 0;
+ var typeStr = opt_type && opt_type.toString();
+ for (var type in listenerMap.listeners) {
+ if (!typeStr || type == typeStr) {
+ // Clone so that we don't need to worry about unlistenByKey
+ // changing the content of the ListenerMap.
+ var listeners = listenerMap.listeners[type].concat();
+ for (var i = 0; i < listeners.length; ++i) {
+ if (goog.events.unlistenByKey(listeners[i])) {
+ ++count;
+ }
+ }
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Gets the listeners for a given object, type and capture phase.
+ *
+ * @param {Object} obj Object to get listeners for.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {boolean} capture Capture phase?.
+ * @return {Array<goog.events.Listener>} Array of listener objects.
+ */
+goog.events.getListeners = function(obj, type, capture) {
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.getListeners(type, capture);
+ } else {
+ if (!obj) {
+ // TODO(chrishenry): We should tighten the API to accept
+ // !EventTarget|goog.events.Listenable, and add an assertion here.
+ return [];
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (obj));
+ return listenerMap ? listenerMap.getListeners(type, capture) : [];
+ }
+};
+
+
+/**
+ * Gets the goog.events.Listener for the event or null if no such listener is
+ * in use.
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target from
+ * which to get listeners.
+ * @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to get.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the
+ * capture or bubble phase of the event.
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.ListenableKey} the found listener or null if not found.
+ * @template EVENTOBJ
+ */
+goog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {
+ // TODO(chrishenry): Change type from ?string to string, or add assertion.
+ type = /** @type {string} */ (type);
+ listener = goog.events.wrapListener(listener);
+ var capture = !!opt_capt;
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.getListener(type, listener, capture, opt_handler);
+ }
+
+ if (!src) {
+ // TODO(chrishenry): We should tighten the API to only accept
+ // non-null objects, or add an assertion here.
+ return null;
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (src));
+ if (listenerMap) {
+ return listenerMap.getListener(type, listener, capture, opt_handler);
+ }
+ return null;
+};
+
+
+/**
+ * Returns whether an event target has any active listeners matching the
+ * specified signature. If either the type or capture parameters are
+ * unspecified, the function will match on the remaining criteria.
+ *
+ * @param {EventTarget|goog.events.Listenable} obj Target to get
+ * listeners for.
+ * @param {string|!goog.events.EventId=} opt_type Event type.
+ * @param {boolean=} opt_capture Whether to check for capture or bubble-phase
+ * listeners.
+ * @return {boolean} Whether an event target has one or more listeners matching
+ * the requested type and/or capture phase.
+ */
+goog.events.hasListener = function(obj, opt_type, opt_capture) {
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.hasListener(opt_type, opt_capture);
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (obj));
+ return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);
+};
+
+
+/**
+ * Provides a nice string showing the normalized event objects public members
+ * @param {Object} e Event Object.
+ * @return {string} String of the public members of the normalized event object.
+ */
+goog.events.expose = function(e) {
+ var str = [];
+ for (var key in e) {
+ if (e[key] && e[key].id) {
+ str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')');
+ } else {
+ str.push(key + ' = ' + e[key]);
+ }
+ }
+ return str.join('\n');
+};
+
+
+/**
+ * Returns a string with on prepended to the specified type. This is used for IE
+ * which expects "on" to be prepended. This function caches the string in order
+ * to avoid extra allocations in steady state.
+ * @param {string} type Event type.
+ * @return {string} The type string with 'on' prepended.
+ * @private
+ */
+goog.events.getOnString_ = function(type) {
+ if (type in goog.events.onStringMap_) {
+ return goog.events.onStringMap_[type];
+ }
+ return goog.events.onStringMap_[type] = goog.events.onString_ + type;
+};
+
+
+/**
+ * Fires an object's listeners of a particular type and phase
+ *
+ * @param {Object} obj Object whose listeners to call.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {boolean} capture Which event phase.
+ * @param {Object} eventObject Event object to be passed to listener.
+ * @return {boolean} True if all listeners returned true else false.
+ */
+goog.events.fireListeners = function(obj, type, capture, eventObject) {
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.fireListeners(type, capture, eventObject);
+ }
+
+ return goog.events.fireListeners_(obj, type, capture, eventObject);
+};
+
+
+/**
+ * Fires an object's listeners of a particular type and phase.
+ * @param {Object} obj Object whose listeners to call.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {boolean} capture Which event phase.
+ * @param {Object} eventObject Event object to be passed to listener.
+ * @return {boolean} True if all listeners returned true else false.
+ * @private
+ */
+goog.events.fireListeners_ = function(obj, type, capture, eventObject) {
+ /** @type {boolean} */
+ var retval = true;
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {EventTarget} */ (obj));
+ if (listenerMap) {
+ // TODO(chrishenry): Original code avoids array creation when there
+ // is no listener, so we do the same. If this optimization turns
+ // out to be not required, we can replace this with
+ // listenerMap.getListeners(type, capture) instead, which is simpler.
+ var listenerArray = listenerMap.listeners[type.toString()];
+ if (listenerArray) {
+ listenerArray = listenerArray.concat();
+ for (var i = 0; i < listenerArray.length; i++) {
+ var listener = listenerArray[i];
+ // We might not have a listener if the listener was removed.
+ if (listener && listener.capture == capture && !listener.removed) {
+ var result = goog.events.fireListener(listener, eventObject);
+ retval = retval && (result !== false);
+ }
+ }
+ }
+ }
+ return retval;
+};
+
+
+/**
+ * Fires a listener with a set of arguments
+ *
+ * @param {goog.events.Listener} listener The listener object to call.
+ * @param {Object} eventObject The event object to pass to the listener.
+ * @return {boolean} Result of listener.
+ */
+goog.events.fireListener = function(listener, eventObject) {
+ var listenerFn = listener.listener;
+ var listenerHandler = listener.handler || listener.src;
+
+ if (listener.callOnce) {
+ goog.events.unlistenByKey(listener);
+ }
+ return listenerFn.call(listenerHandler, eventObject);
+};
+
+
+/**
+ * Gets the total number of listeners currently in the system.
+ * @return {number} Number of listeners.
+ * @deprecated This returns estimated count, now that Closure no longer
+ * stores a central listener registry. We still return an estimation
+ * to keep existing listener-related tests passing. In the near future,
+ * this function will be removed.
+ */
+goog.events.getTotalListenerCount = function() {
+ return goog.events.listenerCountEstimate_;
+};
+
+
+/**
+ * Dispatches an event (or event like object) and calls all listeners
+ * listening for events of this type. The type of the event is decided by the
+ * type property on the event object.
+ *
+ * If any of the listeners returns false OR calls preventDefault then this
+ * function will return false. If one of the capture listeners calls
+ * stopPropagation, then the bubble listeners won't fire.
+ *
+ * @param {goog.events.Listenable} src The event target.
+ * @param {goog.events.EventLike} e Event object.
+ * @return {boolean} If anyone called preventDefault on the event object (or
+ * if any of the handlers returns false) this will also return false.
+ * If there are no handlers, or if all handlers return true, this returns
+ * true.
+ */
+goog.events.dispatchEvent = function(src, e) {
+ goog.asserts.assert(
+ goog.events.Listenable.isImplementedBy(src),
+ 'Can not use goog.events.dispatchEvent with ' +
+ 'non-goog.events.Listenable instance.');
+ return src.dispatchEvent(e);
+};
+
+
+/**
+ * Installs exception protection for the browser event entry point using the
+ * given error handler.
+ *
+ * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
+ * protect the entry point.
+ */
+goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
+ goog.events.handleBrowserEvent_ = errorHandler.protectEntryPoint(
+ goog.events.handleBrowserEvent_);
+};
+
+
+/**
+ * Handles an event and dispatches it to the correct listeners. This
+ * function is a proxy for the real listener the user specified.
+ *
+ * @param {goog.events.Listener} listener The listener object.
+ * @param {Event=} opt_evt Optional event object that gets passed in via the
+ * native event handlers.
+ * @return {boolean} Result of the event handler.
+ * @this {EventTarget} The object or Element that fired the event.
+ * @private
+ */
+goog.events.handleBrowserEvent_ = function(listener, opt_evt) {
+ if (listener.removed) {
+ return true;
+ }
+
+ // Synthesize event propagation if the browser does not support W3C
+ // event model.
+ if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
+ var ieEvent = opt_evt ||
+ /** @type {Event} */ (goog.getObjectByName('window.event'));
+ var evt = new goog.events.BrowserEvent(ieEvent, this);
+ /** @type {boolean} */
+ var retval = true;
+
+ if (goog.events.CAPTURE_SIMULATION_MODE ==
+ goog.events.CaptureSimulationMode.ON) {
+ // If we have not marked this event yet, we should perform capture
+ // simulation.
+ if (!goog.events.isMarkedIeEvent_(ieEvent)) {
+ goog.events.markIeEvent_(ieEvent);
+
+ var ancestors = [];
+ for (var parent = evt.currentTarget; parent;
+ parent = parent.parentNode) {
+ ancestors.push(parent);
+ }
+
+ // Fire capture listeners.
+ var type = listener.type;
+ for (var i = ancestors.length - 1; !evt.propagationStopped_ && i >= 0;
+ i--) {
+ evt.currentTarget = ancestors[i];
+ var result = goog.events.fireListeners_(ancestors[i], type, true, evt);
+ retval = retval && result;
+ }
+
+ // Fire bubble listeners.
+ //
+ // We can technically rely on IE to perform bubble event
+ // propagation. However, it turns out that IE fires events in
+ // opposite order of attachEvent registration, which broke
+ // some code and tests that rely on the order. (While W3C DOM
+ // Level 2 Events TR leaves the event ordering unspecified,
+ // modern browsers and W3C DOM Level 3 Events Working Draft
+ // actually specify the order as the registration order.)
+ for (var i = 0; !evt.propagationStopped_ && i < ancestors.length; i++) {
+ evt.currentTarget = ancestors[i];
+ var result = goog.events.fireListeners_(ancestors[i], type, false, evt);
+ retval = retval && result;
+ }
+ }
+ } else {
+ retval = goog.events.fireListener(listener, evt);
+ }
+ return retval;
+ }
+
+ // Otherwise, simply fire the listener.
+ return goog.events.fireListener(
+ listener, new goog.events.BrowserEvent(opt_evt, this));
+};
+
+
+/**
+ * This is used to mark the IE event object so we do not do the Closure pass
+ * twice for a bubbling event.
+ * @param {Event} e The IE browser event.
+ * @private
+ */
+goog.events.markIeEvent_ = function(e) {
+ // Only the keyCode and the returnValue can be changed. We use keyCode for
+ // non keyboard events.
+ // event.returnValue is a bit more tricky. It is undefined by default. A
+ // boolean false prevents the default action. In a window.onbeforeunload and
+ // the returnValue is non undefined it will be alerted. However, we will only
+ // modify the returnValue for keyboard events. We can get a problem if non
+ // closure events sets the keyCode or the returnValue
+
+ var useReturnValue = false;
+
+ if (e.keyCode == 0) {
+ // We cannot change the keyCode in case that srcElement is input[type=file].
+ // We could test that that is the case but that would allocate 3 objects.
+ // If we use try/catch we will only allocate extra objects in the case of a
+ // failure.
+ /** @preserveTry */
+ try {
+ e.keyCode = -1;
+ return;
+ } catch (ex) {
+ useReturnValue = true;
+ }
+ }
+
+ if (useReturnValue ||
+ /** @type {boolean|undefined} */ (e.returnValue) == undefined) {
+ e.returnValue = true;
+ }
+};
+
+
+/**
+ * This is used to check if an IE event has already been handled by the Closure
+ * system so we do not do the Closure pass twice for a bubbling event.
+ * @param {Event} e The IE browser event.
+ * @return {boolean} True if the event object has been marked.
+ * @private
+ */
+goog.events.isMarkedIeEvent_ = function(e) {
+ return e.keyCode < 0 || e.returnValue != undefined;
+};
+
+
+/**
+ * Counter to create unique event ids.
+ * @private {number}
+ */
+goog.events.uniqueIdCounter_ = 0;
+
+
+/**
+ * Creates a unique event id.
+ *
+ * @param {string} identifier The identifier.
+ * @return {string} A unique identifier.
+ * @idGenerator
+ */
+goog.events.getUniqueId = function(identifier) {
+ return identifier + '_' + goog.events.uniqueIdCounter_++;
+};
+
+
+/**
+ * @param {EventTarget} src The source object.
+ * @return {goog.events.ListenerMap} A listener map for the given
+ * source object, or null if none exists.
+ * @private
+ */
+goog.events.getListenerMap_ = function(src) {
+ var listenerMap = src[goog.events.LISTENER_MAP_PROP_];
+ // IE serializes the property as well (e.g. when serializing outer
+ // HTML). So we must check that the value is of the correct type.
+ return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;
+};
+
+
+/**
+ * Expando property for listener function wrapper for Object with
+ * handleEvent.
+ * @private @const {string}
+ */
+goog.events.LISTENER_WRAPPER_PROP_ = '__closure_events_fn_' +
+ ((Math.random() * 1e9) >>> 0);
+
+
+/**
+ * @param {Object|Function} listener The listener function or an
+ * object that contains handleEvent method.
+ * @return {!Function} Either the original function or a function that
+ * calls obj.handleEvent. If the same listener is passed to this
+ * function more than once, the same function is guaranteed to be
+ * returned.
+ */
+goog.events.wrapListener = function(listener) {
+ goog.asserts.assert(listener, 'Listener can not be null.');
+
+ if (goog.isFunction(listener)) {
+ return listener;
+ }
+
+ goog.asserts.assert(
+ listener.handleEvent, 'An object listener must have handleEvent method.');
+ if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) {
+ listener[goog.events.LISTENER_WRAPPER_PROP_] =
+ function(e) { return listener.handleEvent(e); };
+ }
+ return listener[goog.events.LISTENER_WRAPPER_PROP_];
+};
+
+
+// Register the browser event handler as an entry point, so that
+// it can be monitored for exception handling, etc.
+goog.debug.entryPointRegistry.register(
+ /**
+ * @param {function(!Function): !Function} transformer The transforming
+ * function.
+ */
+ function(transformer) {
+ goog.events.handleBrowserEvent_ = transformer(
+ goog.events.handleBrowserEvent_);
+ });
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventtarget.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventtarget.js b/externs/GCL/externs/goog/events/eventtarget.js
new file mode 100644
index 0000000..7408c7e
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventtarget.js
@@ -0,0 +1,394 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A disposable implementation of a custom
+ * listenable/event target. See also: documentation for
+ * {@code goog.events.Listenable}.
+ *
+ * @author arv@google.com (Erik Arvidsson) [Original implementation]
+ * @see ../demos/eventtarget.html
+ * @see goog.events.Listenable
+ */
+
+goog.provide('goog.events.EventTarget');
+
+goog.require('goog.Disposable');
+goog.require('goog.asserts');
+goog.require('goog.events');
+goog.require('goog.events.Event');
+goog.require('goog.events.Listenable');
+goog.require('goog.events.ListenerMap');
+goog.require('goog.object');
+
+
+
+/**
+ * An implementation of {@code goog.events.Listenable} with full W3C
+ * EventTarget-like support (capture/bubble mechanism, stopping event
+ * propagation, preventing default actions).
+ *
+ * You may subclass this class to turn your class into a Listenable.
+ *
+ * Unless propagation is stopped, an event dispatched by an
+ * EventTarget will bubble to the parent returned by
+ * {@code getParentEventTarget}. To set the parent, call
+ * {@code setParentEventTarget}. Subclasses that don't support
+ * changing the parent can override the setter to throw an error.
+ *
+ * Example usage:
+ * <pre>
+ * var source = new goog.events.EventTarget();
+ * function handleEvent(e) {
+ * alert('Type: ' + e.type + '; Target: ' + e.target);
+ * }
+ * source.listen('foo', handleEvent);
+ * // Or: goog.events.listen(source, 'foo', handleEvent);
+ * ...
+ * source.dispatchEvent('foo'); // will call handleEvent
+ * ...
+ * source.unlisten('foo', handleEvent);
+ * // Or: goog.events.unlisten(source, 'foo', handleEvent);
+ * </pre>
+ *
+ * @constructor
+ * @extends {goog.Disposable}
+ * @implements {goog.events.Listenable}
+ */
+goog.events.EventTarget = function() {
+ goog.Disposable.call(this);
+
+ /**
+ * Maps of event type to an array of listeners.
+ * @private {!goog.events.ListenerMap}
+ */
+ this.eventTargetListeners_ = new goog.events.ListenerMap(this);
+
+ /**
+ * The object to use for event.target. Useful when mixing in an
+ * EventTarget to another object.
+ * @private {!Object}
+ */
+ this.actualEventTarget_ = this;
+
+ /**
+ * Parent event target, used during event bubbling.
+ *
+ * TODO(chrishenry): Change this to goog.events.Listenable. This
+ * currently breaks people who expect getParentEventTarget to return
+ * goog.events.EventTarget.
+ *
+ * @private {goog.events.EventTarget}
+ */
+ this.parentEventTarget_ = null;
+};
+goog.inherits(goog.events.EventTarget, goog.Disposable);
+goog.events.Listenable.addImplementation(goog.events.EventTarget);
+
+
+/**
+ * An artificial cap on the number of ancestors you can have. This is mainly
+ * for loop detection.
+ * @const {number}
+ * @private
+ */
+goog.events.EventTarget.MAX_ANCESTORS_ = 1000;
+
+
+/**
+ * Returns the parent of this event target to use for bubbling.
+ *
+ * @return {goog.events.EventTarget} The parent EventTarget or null if
+ * there is no parent.
+ * @override
+ */
+goog.events.EventTarget.prototype.getParentEventTarget = function() {
+ return this.parentEventTarget_;
+};
+
+
+/**
+ * Sets the parent of this event target to use for capture/bubble
+ * mechanism.
+ * @param {goog.events.EventTarget} parent Parent listenable (null if none).
+ */
+goog.events.EventTarget.prototype.setParentEventTarget = function(parent) {
+ this.parentEventTarget_ = parent;
+};
+
+
+/**
+ * Adds an event listener to the event target. The same handler can only be
+ * added once per the type. Even if you add the same handler multiple times
+ * using the same type then it will only be called once when the event is
+ * dispatched.
+ *
+ * @param {string} type The type of the event to listen for.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
+ * to handle the event. The handler can also be an object that implements
+ * the handleEvent method which takes the event object as argument.
+ * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase
+ * of the event.
+ * @param {Object=} opt_handlerScope Object in whose scope to call
+ * the listener.
+ * @deprecated Use {@code #listen} instead, when possible. Otherwise, use
+ * {@code goog.events.listen} if you are passing Object
+ * (instead of Function) as handler.
+ */
+goog.events.EventTarget.prototype.addEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);
+};
+
+
+/**
+ * Removes an event listener from the event target. The handler must be the
+ * same object as the one added. If the handler has not been added then
+ * nothing is done.
+ *
+ * @param {string} type The type of the event to listen for.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
+ * to handle the event. The handler can also be an object that implements
+ * the handleEvent method which takes the event object as argument.
+ * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase
+ * of the event.
+ * @param {Object=} opt_handlerScope Object in whose scope to call
+ * the listener.
+ * @deprecated Use {@code #unlisten} instead, when possible. Otherwise, use
+ * {@code goog.events.unlisten} if you are passing Object
+ * (instead of Function) as handler.
+ */
+goog.events.EventTarget.prototype.removeEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.dispatchEvent = function(e) {
+ this.assertInitialized_();
+
+ var ancestorsTree, ancestor = this.getParentEventTarget();
+ if (ancestor) {
+ ancestorsTree = [];
+ var ancestorCount = 1;
+ for (; ancestor; ancestor = ancestor.getParentEventTarget()) {
+ ancestorsTree.push(ancestor);
+ goog.asserts.assert(
+ (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),
+ 'infinite loop');
+ }
+ }
+
+ return goog.events.EventTarget.dispatchEventInternal_(
+ this.actualEventTarget_, e, ancestorsTree);
+};
+
+
+/**
+ * Removes listeners from this object. Classes that extend EventTarget may
+ * need to override this method in order to remove references to DOM Elements
+ * and additional listeners.
+ * @override
+ */
+goog.events.EventTarget.prototype.disposeInternal = function() {
+ goog.events.EventTarget.superClass_.disposeInternal.call(this);
+
+ this.removeAllListeners();
+ this.parentEventTarget_ = null;
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.listen = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ this.assertInitialized_();
+ return this.eventTargetListeners_.add(
+ String(type), listener, false /* callOnce */, opt_useCapture,
+ opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.listenOnce = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ return this.eventTargetListeners_.add(
+ String(type), listener, true /* callOnce */, opt_useCapture,
+ opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.unlisten = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ return this.eventTargetListeners_.remove(
+ String(type), listener, opt_useCapture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.unlistenByKey = function(key) {
+ return this.eventTargetListeners_.removeByKey(key);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {
+ // TODO(chrishenry): Previously, removeAllListeners can be called on
+ // uninitialized EventTarget, so we preserve that behavior. We
+ // should remove this when usages that rely on that fact are purged.
+ if (!this.eventTargetListeners_) {
+ return 0;
+ }
+ return this.eventTargetListeners_.removeAll(opt_type);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.fireListeners = function(
+ type, capture, eventObject) {
+ // TODO(chrishenry): Original code avoids array creation when there
+ // is no listener, so we do the same. If this optimization turns
+ // out to be not required, we can replace this with
+ // getListeners(type, capture) instead, which is simpler.
+ var listenerArray = this.eventTargetListeners_.listeners[String(type)];
+ if (!listenerArray) {
+ return true;
+ }
+ listenerArray = listenerArray.concat();
+
+ var rv = true;
+ for (var i = 0; i < listenerArray.length; ++i) {
+ var listener = listenerArray[i];
+ // We might not have a listener if the listener was removed.
+ if (listener && !listener.removed && listener.capture == capture) {
+ var listenerFn = listener.listener;
+ var listenerHandler = listener.handler || listener.src;
+
+ if (listener.callOnce) {
+ this.unlistenByKey(listener);
+ }
+ rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;
+ }
+ }
+
+ return rv && eventObject.returnValue_ != false;
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.getListeners = function(type, capture) {
+ return this.eventTargetListeners_.getListeners(String(type), capture);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.getListener = function(
+ type, listener, capture, opt_listenerScope) {
+ return this.eventTargetListeners_.getListener(
+ String(type), listener, capture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.hasListener = function(
+ opt_type, opt_capture) {
+ var id = goog.isDef(opt_type) ? String(opt_type) : undefined;
+ return this.eventTargetListeners_.hasListener(id, opt_capture);
+};
+
+
+/**
+ * Sets the target to be used for {@code event.target} when firing
+ * event. Mainly used for testing. For example, see
+ * {@code goog.testing.events.mixinListenable}.
+ * @param {!Object} target The target.
+ */
+goog.events.EventTarget.prototype.setTargetForTesting = function(target) {
+ this.actualEventTarget_ = target;
+};
+
+
+/**
+ * Asserts that the event target instance is initialized properly.
+ * @private
+ */
+goog.events.EventTarget.prototype.assertInitialized_ = function() {
+ goog.asserts.assert(
+ this.eventTargetListeners_,
+ 'Event target is not initialized. Did you call the superclass ' +
+ '(goog.events.EventTarget) constructor?');
+};
+
+
+/**
+ * Dispatches the given event on the ancestorsTree.
+ *
+ * @param {!Object} target The target to dispatch on.
+ * @param {goog.events.Event|Object|string} e The event object.
+ * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors
+ * tree of the target, in reverse order from the closest ancestor
+ * to the root event target. May be null if the target has no ancestor.
+ * @return {boolean} If anyone called preventDefault on the event object (or
+ * if any of the listeners returns false) this will also return false.
+ * @private
+ */
+goog.events.EventTarget.dispatchEventInternal_ = function(
+ target, e, opt_ancestorsTree) {
+ var type = e.type || /** @type {string} */ (e);
+
+ // If accepting a string or object, create a custom event object so that
+ // preventDefault and stopPropagation work with the event.
+ if (goog.isString(e)) {
+ e = new goog.events.Event(e, target);
+ } else if (!(e instanceof goog.events.Event)) {
+ var oldEvent = e;
+ e = new goog.events.Event(type, target);
+ goog.object.extend(e, oldEvent);
+ } else {
+ e.target = e.target || target;
+ }
+
+ var rv = true, currentTarget;
+
+ // Executes all capture listeners on the ancestors, if any.
+ if (opt_ancestorsTree) {
+ for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0;
+ i--) {
+ currentTarget = e.currentTarget = opt_ancestorsTree[i];
+ rv = currentTarget.fireListeners(type, true, e) && rv;
+ }
+ }
+
+ // Executes capture and bubble listeners on the target.
+ if (!e.propagationStopped_) {
+ currentTarget = e.currentTarget = target;
+ rv = currentTarget.fireListeners(type, true, e) && rv;
+ if (!e.propagationStopped_) {
+ rv = currentTarget.fireListeners(type, false, e) && rv;
+ }
+ }
+
+ // Executes all bubble listeners on the ancestors, if any.
+ if (opt_ancestorsTree) {
+ for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) {
+ currentTarget = e.currentTarget = opt_ancestorsTree[i];
+ rv = currentTarget.fireListeners(type, false, e) && rv;
+ }
+ }
+
+ return rv;
+};