http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/samplecomponent.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/demos/samplecomponent.js b/externs/GCL/externs/goog/demos/samplecomponent.js new file mode 100644 index 0000000..14d3a15 --- /dev/null +++ b/externs/GCL/externs/goog/demos/samplecomponent.js @@ -0,0 +1,189 @@ +// Copyright 2007 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 simple, sample component. + * + */ +goog.provide('goog.demos.SampleComponent'); + +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.dom.classlist'); +goog.require('goog.events.EventType'); +goog.require('goog.events.KeyCodes'); +goog.require('goog.events.KeyHandler'); +goog.require('goog.ui.Component'); + + + +/** + * A simple box that changes colour when clicked. This class demonstrates the + * goog.ui.Component API, and is keyboard accessible, as per + * http://wiki/Main/ClosureKeyboardAccessible + * + * @param {string=} opt_label A label to display. Defaults to "Click Me" if none + * provided. + * @param {goog.dom.DomHelper=} opt_domHelper DOM helper to use. + * + * @extends {goog.ui.Component} + * @constructor + * @final + */ +goog.demos.SampleComponent = function(opt_label, opt_domHelper) { + goog.demos.SampleComponent.base(this, 'constructor', opt_domHelper); + + /** + * The label to display. + * @type {string} + * @private + */ + this.initialLabel_ = opt_label || 'Click Me'; + + /** + * The current color. + * @type {string} + * @private + */ + this.color_ = 'red'; + + /** + * Keyboard handler for this object. This object is created once the + * component's DOM element is known. + * + * @type {goog.events.KeyHandler?} + * @private + */ + this.kh_ = null; +}; +goog.inherits(goog.demos.SampleComponent, goog.ui.Component); + + +/** + * Changes the color of the element. + * @private + */ +goog.demos.SampleComponent.prototype.changeColor_ = function() { + if (this.color_ == 'red') { + this.color_ = 'green'; + } else if (this.color_ == 'green') { + this.color_ = 'blue'; + } else { + this.color_ = 'red'; + } + this.getElement().style.backgroundColor = this.color_; +}; + + +/** + * Creates an initial DOM representation for the component. + * @override + */ +goog.demos.SampleComponent.prototype.createDom = function() { + this.decorateInternal(this.dom_.createElement(goog.dom.TagName.DIV)); +}; + + +/** + * Decorates an existing HTML DIV element as a SampleComponent. + * + * @param {Element} element The DIV element to decorate. The element's + * text, if any will be used as the component's label. + * @override + */ +goog.demos.SampleComponent.prototype.decorateInternal = function(element) { + goog.demos.SampleComponent.base(this, 'decorateInternal', element); + if (!this.getLabelText()) { + this.setLabelText(this.initialLabel_); + } + + var elem = this.getElement(); + goog.dom.classlist.add(elem, goog.getCssName('goog-sample-component')); + elem.style.backgroundColor = this.color_; + elem.tabIndex = 0; + + this.kh_ = new goog.events.KeyHandler(elem); + this.getHandler().listen(this.kh_, goog.events.KeyHandler.EventType.KEY, + this.onKey_); +}; + + +/** @override */ +goog.demos.SampleComponent.prototype.disposeInternal = function() { + goog.demos.SampleComponent.base(this, 'disposeInternal'); + if (this.kh_) { + this.kh_.dispose(); + } +}; + + +/** + * Called when component's element is known to be in the document. + * @override + */ +goog.demos.SampleComponent.prototype.enterDocument = function() { + goog.demos.SampleComponent.base(this, 'enterDocument'); + this.getHandler().listen(this.getElement(), goog.events.EventType.CLICK, + this.onDivClicked_); +}; + + +/** + * Gets the current label text. + * + * @return {string} The current text set into the label, or empty string if + * none set. + */ +goog.demos.SampleComponent.prototype.getLabelText = function() { + if (!this.getElement()) { + return ''; + } + return goog.dom.getTextContent(this.getElement()); +}; + + +/** + * Handles DIV element clicks, causing the DIV's colour to change. + * @param {goog.events.Event} event The click event. + * @private + */ +goog.demos.SampleComponent.prototype.onDivClicked_ = function(event) { + this.changeColor_(); +}; + + +/** + * Fired when user presses a key while the DIV has focus. If the user presses + * space or enter, the color will be changed. + * @param {goog.events.Event} event The key event. + * @private + */ +goog.demos.SampleComponent.prototype.onKey_ = function(event) { + var keyCodes = goog.events.KeyCodes; + if (event.keyCode == keyCodes.SPACE || event.keyCode == keyCodes.ENTER) { + this.changeColor_(); + } +}; + + +/** + * Sets the current label text. Has no effect if component is not rendered. + * + * @param {string} text The text to set as the label. + */ +goog.demos.SampleComponent.prototype.setLabelText = function(text) { + if (this.getElement()) { + goog.dom.setTextContent(this.getElement(), text); + } +};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/xpc/xpcdemo.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/demos/xpc/xpcdemo.js b/externs/GCL/externs/goog/demos/xpc/xpcdemo.js new file mode 100644 index 0000000..1e403ee --- /dev/null +++ b/externs/GCL/externs/goog/demos/xpc/xpcdemo.js @@ -0,0 +1,308 @@ +// Copyright 2007 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 Contains application code for the XPC demo. + * This script is used in both the container page and the iframe. + * + */ + +goog.require('goog.Uri'); +goog.require('goog.dom'); +goog.require('goog.dom.TagName'); +goog.require('goog.events'); +goog.require('goog.events.EventType'); +goog.require('goog.json'); +goog.require('goog.log'); +goog.require('goog.log.Level'); +goog.require('goog.net.xpc.CfgFields'); +goog.require('goog.net.xpc.CrossPageChannel'); + + +/** + * Namespace for the demo. We don't use goog.provide here because it's not a + * real module (cannot be required). + */ +var xpcdemo = {}; + + +/** + * Global function to kick off initialization in the containing document. + */ +goog.global.initOuter = function() { + goog.events.listen(window, 'load', function() { xpcdemo.initOuter(); }); +}; + + +/** + * Global function to kick off initialization in the iframe. + */ +goog.global.initInner = function() { + goog.events.listen(window, 'load', function() { xpcdemo.initInner(); }); +}; + + +/** + * Initializes XPC in the containing page. + */ +xpcdemo.initOuter = function() { + // Build the configuration object. + var cfg = {}; + + var ownUri = new goog.Uri(window.location.href); + var relayUri = ownUri.resolve(new goog.Uri('relay.html')); + var pollUri = ownUri.resolve(new goog.Uri('blank.html')); + + // Determine the peer domain. Uses the value of the URI-parameter + // 'peerdomain'. If that parameter is not present, it falls back to + // the own domain so that the demo will work out of the box (but + // communication will of course not cross domain-boundaries). For + // real cross-domain communication, the easiest way is to point two + // different host-names to the same webserver and then hit the + // following URI: + // http://host1.com/path/to/closure/demos/xpc/index.html?peerdomain=host2.com + var peerDomain = ownUri.getParameterValue('peerdomain') || ownUri.getDomain(); + + cfg[goog.net.xpc.CfgFields.LOCAL_RELAY_URI] = relayUri.toString(); + cfg[goog.net.xpc.CfgFields.PEER_RELAY_URI] = + relayUri.setDomain(peerDomain).toString(); + + cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] = pollUri.toString(); + cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] = + pollUri.setDomain(peerDomain).toString(); + + + // Force transport to be used if tp-parameter is set. + var tp = ownUri.getParameterValue('tp'); + if (tp) { + cfg[goog.net.xpc.CfgFields.TRANSPORT] = parseInt(tp, 10); + } + + + // Construct the URI of the peer page. + + var peerUri = ownUri.resolve( + new goog.Uri('inner.html')).setDomain(peerDomain); + // Passthrough of verbose and compiled flags. + if (goog.isDef(ownUri.getParameterValue('verbose'))) { + peerUri.setParameterValue('verbose', ''); + } + if (goog.isDef(ownUri.getParameterValue('compiled'))) { + peerUri.setParameterValue('compiled', ''); + } + + cfg[goog.net.xpc.CfgFields.PEER_URI] = peerUri; + + // Instantiate the channel. + xpcdemo.channel = new goog.net.xpc.CrossPageChannel(cfg); + + // Create the peer iframe. + xpcdemo.peerIframe = xpcdemo.channel.createPeerIframe( + goog.dom.getElement('iframeContainer')); + + xpcdemo.initCommon_(); + + goog.dom.getElement('inactive').style.display = 'none'; + goog.dom.getElement('active').style.display = ''; +}; + + +/** + * Initialization in the iframe. + */ +xpcdemo.initInner = function() { + // Get the channel configuration passed by the containing document. + var cfg = goog.json.parse( + (new goog.Uri(window.location.href)).getParameterValue('xpc')); + + xpcdemo.channel = new goog.net.xpc.CrossPageChannel(cfg); + + xpcdemo.initCommon_(); +}; + + +/** + * Initializes the demo. + * Registers service-handlers and connects the channel. + * @private + */ +xpcdemo.initCommon_ = function() { + var xpcLogger = goog.log.getLogger('goog.net.xpc'); + goog.log.addHandler(xpcLogger, function(logRecord) { + xpcdemo.log('[XPC] ' + logRecord.getMessage()); + }); + xpcLogger.setLevel(window.location.href.match(/verbose/) ? + goog.log.Level.ALL : goog.log.Level.INFO); + + // Register services. + xpcdemo.channel.registerService('log', xpcdemo.log); + xpcdemo.channel.registerService('ping', xpcdemo.pingHandler_); + xpcdemo.channel.registerService('events', xpcdemo.eventsMsgHandler_); + + // Connect the channel. + xpcdemo.channel.connect(function() { + xpcdemo.channel.send('log', 'Hi from ' + window.location.host); + goog.events.listen(goog.dom.getElement('clickfwd'), + 'click', xpcdemo.mouseEventHandler_); + }); +}; + + +/** + * Kills the peer iframe and the disposes the channel. + */ +xpcdemo.teardown = function() { + goog.events.unlisten(goog.dom.getElement('clickfwd'), + goog.events.EventType.CLICK, xpcdemo.mouseEventHandler_); + + xpcdemo.channel.dispose(); + delete xpcdemo.channel; + + goog.dom.removeNode(xpcdemo.peerIframe); + xpcdemo.peerIframe = null; + + goog.dom.getElement('inactive').style.display = ''; + goog.dom.getElement('active').style.display = 'none'; +}; + + +/** + * Logging function. Inserts log-message into element with it id 'console'. + * @param {string} msgString The log-message. + */ +xpcdemo.log = function(msgString) { + xpcdemo.consoleElm || (xpcdemo.consoleElm = goog.dom.getElement('console')); + var msgElm = goog.dom.createDom(goog.dom.TagName.DIV); + msgElm.innerHTML = msgString; + xpcdemo.consoleElm.insertBefore(msgElm, xpcdemo.consoleElm.firstChild); +}; + + +/** + * Sends a ping request to the peer. + */ +xpcdemo.ping = function() { + // send current time + xpcdemo.channel.send('ping', goog.now() + ''); +}; + + +/** + * The handler function for incoming pings (messages sent to the service + * called 'ping'); + * @param {string} payload The message payload. + * @private + */ +xpcdemo.pingHandler_ = function(payload) { + // is the incoming message a response to a ping we sent? + if (payload.charAt(0) == '#') { + // calculate roundtrip time and log + var dt = goog.now() - parseInt(payload.substring(1), 10); + xpcdemo.log('roundtrip: ' + dt + 'ms'); + } else { + // incoming message is a ping initiated from peer + // -> prepend with '#' and send back + xpcdemo.channel.send('ping', '#' + payload); + xpcdemo.log('ping reply sent'); + } +}; + + +/** + * Counter for mousemove events. + * @type {number} + * @private + */ +xpcdemo.mmCount_ = 0; + + +/** + * Holds timestamp when the last mousemove rate has been logged. + * @type {number} + * @private + */ +xpcdemo.mmLastRateOutput_ = 0; + + +/** + * Start mousemove event forwarding. Registers a listener on the document which + * sends them over the channel. + */ +xpcdemo.startMousemoveForwarding = function() { + goog.events.listen(document, goog.events.EventType.MOUSEMOVE, + xpcdemo.mouseEventHandler_); + xpcdemo.mmLastRateOutput_ = goog.now(); +}; + + +/** + * Stop mousemove event forwarding. + */ +xpcdemo.stopMousemoveForwarding = function() { + goog.events.unlisten(document, goog.events.EventType.MOUSEMOVE, + xpcdemo.mouseEventHandler_); +}; + + +/** + * Function to be used as handler for mouse-events. + * @param {goog.events.BrowserEvent} e The mouse event. + * @private + */ +xpcdemo.mouseEventHandler_ = function(e) { + xpcdemo.channel.send('events', + [e.type, e.clientX, e.clientY, goog.now()].join(',')); +}; + + +/** + * Handler for the 'events' service. + * @param {string} payload The string returned from the xpcdemo. + * @private + */ +xpcdemo.eventsMsgHandler_ = function(payload) { + var now = goog.now(); + var args = payload.split(','); + var type = args[0]; + var pageX = args[1]; + var pageY = args[2]; + var time = parseInt(args[3], 10); + + var msg = type + ': (' + pageX + ',' + pageY + '), latency: ' + (now - time); + xpcdemo.log(msg); + + if (type == goog.events.EventType.MOUSEMOVE) { + xpcdemo.mmCount_++; + var dt = now - xpcdemo.mmLastRateOutput_; + if (dt > 1000) { + msg = 'RATE (mousemove/s): ' + (1000 * xpcdemo.mmCount_ / dt); + xpcdemo.log(msg); + xpcdemo.mmLastRateOutput_ = now; + xpcdemo.mmCount_ = 0; + } + } +}; + + +/** + * Send multiple messages. + * @param {number} n The number of messages to send. + */ +xpcdemo.sendN = function(n) { + xpcdemo.count_ || (xpcdemo.count_ = 1); + + for (var i = 0; i < n; i++) { + xpcdemo.channel.send('log', '' + xpcdemo.count_++); + } +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/disposable/disposable.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/disposable/disposable.js b/externs/GCL/externs/goog/disposable/disposable.js new file mode 100644 index 0000000..d9c89d9 --- /dev/null +++ b/externs/GCL/externs/goog/disposable/disposable.js @@ -0,0 +1,307 @@ +// 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 Implements the disposable interface. The dispose method is used + * to clean up references and resources. + * @author [email protected] (Erik Arvidsson) + */ + + +goog.provide('goog.Disposable'); +/** @suppress {extraProvide} */ +goog.provide('goog.dispose'); +/** @suppress {extraProvide} */ +goog.provide('goog.disposeAll'); + +goog.require('goog.disposable.IDisposable'); + + + +/** + * Class that provides the basic implementation for disposable objects. If your + * class holds one or more references to COM objects, DOM nodes, or other + * disposable objects, it should extend this class or implement the disposable + * interface (defined in goog.disposable.IDisposable). + * @constructor + * @implements {goog.disposable.IDisposable} + */ +goog.Disposable = function() { + if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) { + if (goog.Disposable.INCLUDE_STACK_ON_CREATION) { + this.creationStack = new Error().stack; + } + goog.Disposable.instances_[goog.getUid(this)] = this; + } + // Support sealing + this.disposed_ = this.disposed_; + this.onDisposeCallbacks_ = this.onDisposeCallbacks_; +}; + + +/** + * @enum {number} Different monitoring modes for Disposable. + */ +goog.Disposable.MonitoringMode = { + /** + * No monitoring. + */ + OFF: 0, + /** + * Creating and disposing the goog.Disposable instances is monitored. All + * disposable objects need to call the {@code goog.Disposable} base + * constructor. The PERMANENT mode must be switched on before creating any + * goog.Disposable instances. + */ + PERMANENT: 1, + /** + * INTERACTIVE mode can be switched on and off on the fly without producing + * errors. It also doesn't warn if the disposable objects don't call the + * {@code goog.Disposable} base constructor. + */ + INTERACTIVE: 2 +}; + + +/** + * @define {number} The monitoring mode of the goog.Disposable + * instances. Default is OFF. Switching on the monitoring is only + * recommended for debugging because it has a significant impact on + * performance and memory usage. If switched off, the monitoring code + * compiles down to 0 bytes. + */ +goog.define('goog.Disposable.MONITORING_MODE', 0); + + +/** + * @define {boolean} Whether to attach creation stack to each created disposable + * instance; This is only relevant for when MonitoringMode != OFF. + */ +goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true); + + +/** + * Maps the unique ID of every undisposed {@code goog.Disposable} object to + * the object itself. + * @type {!Object<number, !goog.Disposable>} + * @private + */ +goog.Disposable.instances_ = {}; + + +/** + * @return {!Array<!goog.Disposable>} All {@code goog.Disposable} objects that + * haven't been disposed of. + */ +goog.Disposable.getUndisposedObjects = function() { + var ret = []; + for (var id in goog.Disposable.instances_) { + if (goog.Disposable.instances_.hasOwnProperty(id)) { + ret.push(goog.Disposable.instances_[Number(id)]); + } + } + return ret; +}; + + +/** + * Clears the registry of undisposed objects but doesn't dispose of them. + */ +goog.Disposable.clearUndisposedObjects = function() { + goog.Disposable.instances_ = {}; +}; + + +/** + * Whether the object has been disposed of. + * @type {boolean} + * @private + */ +goog.Disposable.prototype.disposed_ = false; + + +/** + * Callbacks to invoke when this object is disposed. + * @type {Array<!Function>} + * @private + */ +goog.Disposable.prototype.onDisposeCallbacks_; + + +/** + * If monitoring the goog.Disposable instances is enabled, stores the creation + * stack trace of the Disposable instance. + * @const {string} + */ +goog.Disposable.prototype.creationStack; + + +/** + * @return {boolean} Whether the object has been disposed of. + * @override + */ +goog.Disposable.prototype.isDisposed = function() { + return this.disposed_; +}; + + +/** + * @return {boolean} Whether the object has been disposed of. + * @deprecated Use {@link #isDisposed} instead. + */ +goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed; + + +/** + * Disposes of the object. If the object hasn't already been disposed of, calls + * {@link #disposeInternal}. Classes that extend {@code goog.Disposable} should + * override {@link #disposeInternal} in order to delete references to COM + * objects, DOM nodes, and other disposable objects. Reentrant. + * + * @return {void} Nothing. + * @override + */ +goog.Disposable.prototype.dispose = function() { + if (!this.disposed_) { + // Set disposed_ to true first, in case during the chain of disposal this + // gets disposed recursively. + this.disposed_ = true; + this.disposeInternal(); + if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) { + var uid = goog.getUid(this); + if (goog.Disposable.MONITORING_MODE == + goog.Disposable.MonitoringMode.PERMANENT && + !goog.Disposable.instances_.hasOwnProperty(uid)) { + throw Error(this + ' did not call the goog.Disposable base ' + + 'constructor or was disposed of after a clearUndisposedObjects ' + + 'call'); + } + delete goog.Disposable.instances_[uid]; + } + } +}; + + +/** + * Associates a disposable object with this object so that they will be disposed + * together. + * @param {goog.disposable.IDisposable} disposable that will be disposed when + * this object is disposed. + */ +goog.Disposable.prototype.registerDisposable = function(disposable) { + this.addOnDisposeCallback(goog.partial(goog.dispose, disposable)); +}; + + +/** + * Invokes a callback function when this object is disposed. Callbacks are + * invoked in the order in which they were added. If a callback is added to + * an already disposed Disposable, it will be called immediately. + * @param {function(this:T):?} callback The callback function. + * @param {T=} opt_scope An optional scope to call the callback in. + * @template T + */ +goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) { + if (this.disposed_) { + callback.call(opt_scope); + return; + } + if (!this.onDisposeCallbacks_) { + this.onDisposeCallbacks_ = []; + } + + this.onDisposeCallbacks_.push( + goog.isDef(opt_scope) ? goog.bind(callback, opt_scope) : callback); +}; + + +/** + * Deletes or nulls out any references to COM objects, DOM nodes, or other + * disposable objects. Classes that extend {@code goog.Disposable} should + * override this method. + * Not reentrant. To avoid calling it twice, it must only be called from the + * subclass' {@code disposeInternal} method. Everywhere else the public + * {@code dispose} method must be used. + * For example: + * <pre> + * mypackage.MyClass = function() { + * mypackage.MyClass.base(this, 'constructor'); + * // Constructor logic specific to MyClass. + * ... + * }; + * goog.inherits(mypackage.MyClass, goog.Disposable); + * + * mypackage.MyClass.prototype.disposeInternal = function() { + * // Dispose logic specific to MyClass. + * ... + * // Call superclass's disposeInternal at the end of the subclass's, like + * // in C++, to avoid hard-to-catch issues. + * mypackage.MyClass.base(this, 'disposeInternal'); + * }; + * </pre> + * @protected + */ +goog.Disposable.prototype.disposeInternal = function() { + if (this.onDisposeCallbacks_) { + while (this.onDisposeCallbacks_.length) { + this.onDisposeCallbacks_.shift()(); + } + } +}; + + +/** + * Returns True if we can verify the object is disposed. + * Calls {@code isDisposed} on the argument if it supports it. If obj + * is not an object with an isDisposed() method, return false. + * @param {*} obj The object to investigate. + * @return {boolean} True if we can verify the object is disposed. + */ +goog.Disposable.isDisposed = function(obj) { + if (obj && typeof obj.isDisposed == 'function') { + return obj.isDisposed(); + } + return false; +}; + + +/** + * Calls {@code dispose} on the argument if it supports it. If obj is not an + * object with a dispose() method, this is a no-op. + * @param {*} obj The object to dispose of. + */ +goog.dispose = function(obj) { + if (obj && typeof obj.dispose == 'function') { + obj.dispose(); + } +}; + + +/** + * Calls {@code dispose} on each member of the list that supports it. (If the + * member is an ArrayLike, then {@code goog.disposeAll()} will be called + * recursively on each of its members.) If the member is not an object with a + * {@code dispose()} method, then it is ignored. + * @param {...*} var_args The list. + */ +goog.disposeAll = function(var_args) { + for (var i = 0, len = arguments.length; i < len; ++i) { + var disposable = arguments[i]; + if (goog.isArrayLike(disposable)) { + goog.disposeAll.apply(null, disposable); + } else { + goog.dispose(disposable); + } + } +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/disposable/idisposable.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/disposable/idisposable.js b/externs/GCL/externs/goog/disposable/idisposable.js new file mode 100644 index 0000000..917d17e --- /dev/null +++ b/externs/GCL/externs/goog/disposable/idisposable.js @@ -0,0 +1,45 @@ +// Copyright 2011 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 Definition of the disposable interface. A disposable object + * has a dispose method to to clean up references and resources. + * @author [email protected] (Nathan Naze) + */ + + +goog.provide('goog.disposable.IDisposable'); + + + +/** + * Interface for a disposable object. If a instance requires cleanup + * (references COM objects, DOM notes, or other disposable objects), it should + * implement this interface (it may subclass goog.Disposable). + * @interface + */ +goog.disposable.IDisposable = function() {}; + + +/** + * Disposes of the object and its resources. + * @return {void} Nothing. + */ +goog.disposable.IDisposable.prototype.dispose = goog.abstractMethod; + + +/** + * @return {boolean} Whether the object has been disposed of. + */ +goog.disposable.IDisposable.prototype.isDisposed = goog.abstractMethod; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/abstractmultirange.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/dom/abstractmultirange.js b/externs/GCL/externs/goog/dom/abstractmultirange.js new file mode 100644 index 0000000..d45d38d --- /dev/null +++ b/externs/GCL/externs/goog/dom/abstractmultirange.js @@ -0,0 +1,76 @@ +// Copyright 2008 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 Utilities for working with ranges comprised of multiple + * sub-ranges. + * + * @author [email protected] (Robby Walker) + */ + + +goog.provide('goog.dom.AbstractMultiRange'); + +goog.require('goog.array'); +goog.require('goog.dom'); +goog.require('goog.dom.AbstractRange'); + + + +/** + * Creates a new multi range with no properties. Do not use this + * constructor: use one of the goog.dom.Range.createFrom* methods instead. + * @constructor + * @extends {goog.dom.AbstractRange} + */ +goog.dom.AbstractMultiRange = function() { +}; +goog.inherits(goog.dom.AbstractMultiRange, goog.dom.AbstractRange); + + +/** @override */ +goog.dom.AbstractMultiRange.prototype.containsRange = function( + otherRange, opt_allowPartial) { + // TODO(user): This will incorrectly return false if two (or more) adjacent + // elements are both in the control range, and are also in the text range + // being compared to. + var ranges = this.getTextRanges(); + var otherRanges = otherRange.getTextRanges(); + + var fn = opt_allowPartial ? goog.array.some : goog.array.every; + return fn(otherRanges, function(otherRange) { + return goog.array.some(ranges, function(range) { + return range.containsRange(otherRange, opt_allowPartial); + }); + }); +}; + + +/** @override */ +goog.dom.AbstractMultiRange.prototype.insertNode = function(node, before) { + if (before) { + goog.dom.insertSiblingBefore(node, this.getStartNode()); + } else { + goog.dom.insertSiblingAfter(node, this.getEndNode()); + } + return node; +}; + + +/** @override */ +goog.dom.AbstractMultiRange.prototype.surroundWithNodes = function(startNode, + endNode) { + this.insertNode(startNode, true); + this.insertNode(endNode, false); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/abstractrange.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/dom/abstractrange.js b/externs/GCL/externs/goog/dom/abstractrange.js new file mode 100644 index 0000000..7d66bfb --- /dev/null +++ b/externs/GCL/externs/goog/dom/abstractrange.js @@ -0,0 +1,529 @@ +// Copyright 2007 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 Interface definitions for working with ranges + * in HTML documents. + * + * @author [email protected] (Robby Walker) + */ + + +goog.provide('goog.dom.AbstractRange'); +goog.provide('goog.dom.RangeIterator'); +goog.provide('goog.dom.RangeType'); + +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.SavedCaretRange'); +goog.require('goog.dom.TagIterator'); +goog.require('goog.userAgent'); + + +/** + * Types of ranges. + * @enum {string} + */ +goog.dom.RangeType = { + TEXT: 'text', + CONTROL: 'control', + MULTI: 'mutli' +}; + + + +/** + * Creates a new selection with no properties. Do not use this constructor - + * use one of the goog.dom.Range.from* methods instead. + * @constructor + */ +goog.dom.AbstractRange = function() { +}; + + +/** + * Gets the browser native selection object from the given window. + * @param {Window} win The window to get the selection object from. + * @return {Object} The browser native selection object, or null if it could + * not be retrieved. + */ +goog.dom.AbstractRange.getBrowserSelectionForWindow = function(win) { + if (win.getSelection) { + // W3C + return win.getSelection(); + } else { + // IE + var doc = win.document; + var sel = doc.selection; + if (sel) { + // IE has a bug where it sometimes returns a selection from the wrong + // document. Catching these cases now helps us avoid problems later. + try { + var range = sel.createRange(); + // Only TextRanges have a parentElement method. + if (range.parentElement) { + if (range.parentElement().document != doc) { + return null; + } + } else if (!range.length || + /** @type {ControlRange} */ (range).item(0).document != doc) { + // For ControlRanges, check that the range has items, and that + // the first item in the range is in the correct document. + return null; + } + } catch (e) { + // If the selection is in the wrong document, and the wrong document is + // in a different domain, IE will throw an exception. + return null; + } + // TODO(user|robbyw) Sometimes IE 6 returns a selection instance + // when there is no selection. This object has a 'type' property equals + // to 'None' and a typeDetail property bound to undefined. Ideally this + // function should not return this instance. + return sel; + } + return null; + } +}; + + +/** + * Tests if the given Object is a controlRange. + * @param {Object} range The range object to test. + * @return {boolean} Whether the given Object is a controlRange. + */ +goog.dom.AbstractRange.isNativeControlRange = function(range) { + // For now, tests for presence of a control range function. + return !!range && !!range.addElement; +}; + + +/** + * @return {!goog.dom.AbstractRange} A clone of this range. + */ +goog.dom.AbstractRange.prototype.clone = goog.abstractMethod; + + +/** + * @return {goog.dom.RangeType} The type of range represented by this object. + */ +goog.dom.AbstractRange.prototype.getType = goog.abstractMethod; + + +/** + * @return {Range|TextRange} The native browser range object. + */ +goog.dom.AbstractRange.prototype.getBrowserRangeObject = goog.abstractMethod; + + +/** + * Sets the native browser range object, overwriting any state this range was + * storing. + * @param {Range|TextRange} nativeRange The native browser range object. + * @return {boolean} Whether the given range was accepted. If not, the caller + * will need to call goog.dom.Range.createFromBrowserRange to create a new + * range object. + */ +goog.dom.AbstractRange.prototype.setBrowserRangeObject = function(nativeRange) { + return false; +}; + + +/** + * @return {number} The number of text ranges in this range. + */ +goog.dom.AbstractRange.prototype.getTextRangeCount = goog.abstractMethod; + + +/** + * Get the i-th text range in this range. The behavior is undefined if + * i >= getTextRangeCount or i < 0. + * @param {number} i The range number to retrieve. + * @return {goog.dom.TextRange} The i-th text range. + */ +goog.dom.AbstractRange.prototype.getTextRange = goog.abstractMethod; + + +/** + * Gets an array of all text ranges this range is comprised of. For non-multi + * ranges, returns a single element array containing this. + * @return {!Array<goog.dom.TextRange>} Array of text ranges. + */ +goog.dom.AbstractRange.prototype.getTextRanges = function() { + var output = []; + for (var i = 0, len = this.getTextRangeCount(); i < len; i++) { + output.push(this.getTextRange(i)); + } + return output; +}; + + +/** + * @return {Node} The deepest node that contains the entire range. + */ +goog.dom.AbstractRange.prototype.getContainer = goog.abstractMethod; + + +/** + * Returns the deepest element in the tree that contains the entire range. + * @return {Element} The deepest element that contains the entire range. + */ +goog.dom.AbstractRange.prototype.getContainerElement = function() { + var node = this.getContainer(); + return /** @type {Element} */ ( + node.nodeType == goog.dom.NodeType.ELEMENT ? node : node.parentNode); +}; + + +/** + * @return {Node} The element or text node the range starts in. For text + * ranges, the range comprises all text between the start and end position. + * For other types of range, start and end give bounds of the range but + * do not imply all nodes in those bounds are selected. + */ +goog.dom.AbstractRange.prototype.getStartNode = goog.abstractMethod; + + +/** + * @return {number} The offset into the node the range starts in. For text + * nodes, this is an offset into the node value. For elements, this is + * an offset into the childNodes array. + */ +goog.dom.AbstractRange.prototype.getStartOffset = goog.abstractMethod; + + +/** + * @return {goog.math.Coordinate} The coordinate of the selection start node + * and offset. + */ +goog.dom.AbstractRange.prototype.getStartPosition = goog.abstractMethod; + + +/** + * @return {Node} The element or text node the range ends in. + */ +goog.dom.AbstractRange.prototype.getEndNode = goog.abstractMethod; + + +/** + * @return {number} The offset into the node the range ends in. For text + * nodes, this is an offset into the node value. For elements, this is + * an offset into the childNodes array. + */ +goog.dom.AbstractRange.prototype.getEndOffset = goog.abstractMethod; + + +/** + * @return {goog.math.Coordinate} The coordinate of the selection end + * node and offset. + */ +goog.dom.AbstractRange.prototype.getEndPosition = goog.abstractMethod; + + +/** + * @return {Node} The element or text node the range is anchored at. + */ +goog.dom.AbstractRange.prototype.getAnchorNode = function() { + return this.isReversed() ? this.getEndNode() : this.getStartNode(); +}; + + +/** + * @return {number} The offset into the node the range is anchored at. For + * text nodes, this is an offset into the node value. For elements, this + * is an offset into the childNodes array. + */ +goog.dom.AbstractRange.prototype.getAnchorOffset = function() { + return this.isReversed() ? this.getEndOffset() : this.getStartOffset(); +}; + + +/** + * @return {Node} The element or text node the range is focused at - i.e. where + * the cursor is. + */ +goog.dom.AbstractRange.prototype.getFocusNode = function() { + return this.isReversed() ? this.getStartNode() : this.getEndNode(); +}; + + +/** + * @return {number} The offset into the node the range is focused at - i.e. + * where the cursor is. For text nodes, this is an offset into the node + * value. For elements, this is an offset into the childNodes array. + */ +goog.dom.AbstractRange.prototype.getFocusOffset = function() { + return this.isReversed() ? this.getStartOffset() : this.getEndOffset(); +}; + + +/** + * @return {boolean} Whether the selection is reversed. + */ +goog.dom.AbstractRange.prototype.isReversed = function() { + return false; +}; + + +/** + * @return {!Document} The document this selection is a part of. + */ +goog.dom.AbstractRange.prototype.getDocument = function() { + // Using start node in IE was crashing the browser in some cases so use + // getContainer for that browser. It's also faster for IE, but still slower + // than start node for other browsers so we continue to use getStartNode when + // it is not problematic. See bug 1687309. + return goog.dom.getOwnerDocument(goog.userAgent.IE ? + this.getContainer() : this.getStartNode()); +}; + + +/** + * @return {!Window} The window this selection is a part of. + */ +goog.dom.AbstractRange.prototype.getWindow = function() { + return goog.dom.getWindow(this.getDocument()); +}; + + +/** + * Tests if this range contains the given range. + * @param {goog.dom.AbstractRange} range The range to test. + * @param {boolean=} opt_allowPartial If true, the range can be partially + * contained in the selection, otherwise the range must be entirely + * contained. + * @return {boolean} Whether this range contains the given range. + */ +goog.dom.AbstractRange.prototype.containsRange = goog.abstractMethod; + + +/** + * Tests if this range contains the given node. + * @param {Node} node The node to test for. + * @param {boolean=} opt_allowPartial If not set or false, the node must be + * entirely contained in the selection for this function to return true. + * @return {boolean} Whether this range contains the given node. + */ +goog.dom.AbstractRange.prototype.containsNode = function(node, + opt_allowPartial) { + return this.containsRange(goog.dom.Range.createFromNodeContents(node), + opt_allowPartial); +}; + + +/** + * Tests whether this range is valid (i.e. whether its endpoints are still in + * the document). A range becomes invalid when, after this object was created, + * either one or both of its endpoints are removed from the document. Use of + * an invalid range can lead to runtime errors, particularly in IE. + * @return {boolean} Whether the range is valid. + */ +goog.dom.AbstractRange.prototype.isRangeInDocument = goog.abstractMethod; + + +/** + * @return {boolean} Whether the range is collapsed. + */ +goog.dom.AbstractRange.prototype.isCollapsed = goog.abstractMethod; + + +/** + * @return {string} The text content of the range. + */ +goog.dom.AbstractRange.prototype.getText = goog.abstractMethod; + + +/** + * Returns the HTML fragment this range selects. This is slow on all browsers. + * The HTML fragment may not be valid HTML, for instance if the user selects + * from a to b inclusively in the following html: + * + * >div<a>/div<b + * + * This method will return + * + * a</div>b + * + * If you need valid HTML, use {@link #getValidHtml} instead. + * + * @return {string} HTML fragment of the range, does not include context + * containing elements. + */ +goog.dom.AbstractRange.prototype.getHtmlFragment = goog.abstractMethod; + + +/** + * Returns valid HTML for this range. This is fast on IE, and semi-fast on + * other browsers. + * @return {string} Valid HTML of the range, including context containing + * elements. + */ +goog.dom.AbstractRange.prototype.getValidHtml = goog.abstractMethod; + + +/** + * Returns pastable HTML for this range. This guarantees that any child items + * that must have specific ancestors will have them, for instance all TDs will + * be contained in a TR in a TBODY in a TABLE and all LIs will be contained in + * a UL or OL as appropriate. This is semi-fast on all browsers. + * @return {string} Pastable HTML of the range, including context containing + * elements. + */ +goog.dom.AbstractRange.prototype.getPastableHtml = goog.abstractMethod; + + +/** + * Returns a RangeIterator over the contents of the range. Regardless of the + * direction of the range, the iterator will move in document order. + * @param {boolean=} opt_keys Unused for this iterator. + * @return {!goog.dom.RangeIterator} An iterator over tags in the range. + */ +goog.dom.AbstractRange.prototype.__iterator__ = goog.abstractMethod; + + +// RANGE ACTIONS + + +/** + * Sets this range as the selection in its window. + */ +goog.dom.AbstractRange.prototype.select = goog.abstractMethod; + + +/** + * Removes the contents of the range from the document. + */ +goog.dom.AbstractRange.prototype.removeContents = goog.abstractMethod; + + +/** + * Inserts a node before (or after) the range. The range may be disrupted + * beyond recovery because of the way this splits nodes. + * @param {Node} node The node to insert. + * @param {boolean} before True to insert before, false to insert after. + * @return {Node} The node added to the document. This may be different + * than the node parameter because on IE we have to clone it. + */ +goog.dom.AbstractRange.prototype.insertNode = goog.abstractMethod; + + +/** + * Replaces the range contents with (possibly a copy of) the given node. The + * range may be disrupted beyond recovery because of the way this splits nodes. + * @param {Node} node The node to insert. + * @return {Node} The node added to the document. This may be different + * than the node parameter because on IE we have to clone it. + */ +goog.dom.AbstractRange.prototype.replaceContentsWithNode = function(node) { + if (!this.isCollapsed()) { + this.removeContents(); + } + + return this.insertNode(node, true); +}; + + +/** + * Surrounds this range with the two given nodes. The range may be disrupted + * beyond recovery because of the way this splits nodes. + * @param {Element} startNode The node to insert at the start. + * @param {Element} endNode The node to insert at the end. + */ +goog.dom.AbstractRange.prototype.surroundWithNodes = goog.abstractMethod; + + +// SAVE/RESTORE + + +/** + * Saves the range so that if the start and end nodes are left alone, it can + * be restored. + * @return {!goog.dom.SavedRange} A range representation that can be restored + * as long as the endpoint nodes of the selection are not modified. + */ +goog.dom.AbstractRange.prototype.saveUsingDom = goog.abstractMethod; + + +/** + * Saves the range using HTML carets. As long as the carets remained in the + * HTML, the range can be restored...even when the HTML is copied across + * documents. + * @return {goog.dom.SavedCaretRange?} A range representation that can be + * restored as long as carets are not removed. Returns null if carets + * could not be created. + */ +goog.dom.AbstractRange.prototype.saveUsingCarets = function() { + return (this.getStartNode() && this.getEndNode()) ? + new goog.dom.SavedCaretRange(this) : null; +}; + + +// RANGE MODIFICATION + + +/** + * Collapses the range to one of its boundary points. + * @param {boolean} toAnchor Whether to collapse to the anchor of the range. + */ +goog.dom.AbstractRange.prototype.collapse = goog.abstractMethod; + +// RANGE ITERATION + + + +/** + * Subclass of goog.dom.TagIterator that iterates over a DOM range. It + * adds functions to determine the portion of each text node that is selected. + * @param {Node} node The node to start traversal at. When null, creates an + * empty iterator. + * @param {boolean=} opt_reverse Whether to traverse nodes in reverse. + * @constructor + * @extends {goog.dom.TagIterator} + */ +goog.dom.RangeIterator = function(node, opt_reverse) { + goog.dom.TagIterator.call(this, node, opt_reverse, true); +}; +goog.inherits(goog.dom.RangeIterator, goog.dom.TagIterator); + + +/** + * @return {number} The offset into the current node, or -1 if the current node + * is not a text node. + */ +goog.dom.RangeIterator.prototype.getStartTextOffset = goog.abstractMethod; + + +/** + * @return {number} The end offset into the current node, or -1 if the current + * node is not a text node. + */ +goog.dom.RangeIterator.prototype.getEndTextOffset = goog.abstractMethod; + + +/** + * @return {Node} node The iterator's start node. + */ +goog.dom.RangeIterator.prototype.getStartNode = goog.abstractMethod; + + +/** + * @return {Node} The iterator's end node. + */ +goog.dom.RangeIterator.prototype.getEndNode = goog.abstractMethod; + + +/** + * @return {boolean} Whether a call to next will fail. + */ +goog.dom.RangeIterator.prototype.isLast = goog.abstractMethod; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/animationframe/animationframe.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/dom/animationframe/animationframe.js b/externs/GCL/externs/goog/dom/animationframe/animationframe.js new file mode 100644 index 0000000..b9bccff --- /dev/null +++ b/externs/GCL/externs/goog/dom/animationframe/animationframe.js @@ -0,0 +1,287 @@ +// Copyright 2014 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 goog.dom.animationFrame permits work to be done in-sync with + * the render refresh rate of the browser and to divide work up globally based + * on whether the intent is to measure or to mutate the DOM. The latter avoids + * repeated style recalculation which can be really slow. + * + * Goals of the API: + * <ul> + * <li>Make it easy to schedule work for the next animation frame. + * <li>Make it easy to only do work once per animation frame, even if two + * events fire that trigger the same work. + * <li>Make it easy to do all work in two phases to avoid repeated style + * recalculation caused by interleaved reads and writes. + * <li>Avoid creating closures per schedule operation. + * </ul> + * + * + * Programmatic: + * <pre> + * var animationTask = goog.dom.animationFrame.createTask({ + * measure: function(state) { + * state.width = goog.style.getSize(elem).width; + * this.animationTask(); + * }, + * mutate: function(state) { + * goog.style.setWidth(elem, Math.floor(state.width / 2)); + * } + * }, this); + * }); + * </pre> + * + * See also + * https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame + */ + +goog.provide('goog.dom.animationFrame'); +goog.provide('goog.dom.animationFrame.Spec'); +goog.provide('goog.dom.animationFrame.State'); + +goog.require('goog.dom.animationFrame.polyfill'); + +// Install the polyfill. +goog.dom.animationFrame.polyfill.install(); + + +/** + * @typedef {{ + * id: number, + * fn: !Function, + * context: (!Object|undefined) + * }} + * @private + */ +goog.dom.animationFrame.Task_; + + +/** + * @typedef {{ + * measureTask: goog.dom.animationFrame.Task_, + * mutateTask: goog.dom.animationFrame.Task_, + * state: (!Object|undefined), + * args: (!Array|undefined), + * isScheduled: boolean + * }} + * @private + */ +goog.dom.animationFrame.TaskSet_; + + +/** + * @typedef {{ + * measure: (!Function|undefined), + * mutate: (!Function|undefined) + * }} + */ +goog.dom.animationFrame.Spec; + + + +/** + * A type to represent state. Users may add properties as desired. + * @constructor + * @final + */ +goog.dom.animationFrame.State = function() {}; + + +/** + * Saves a set of tasks to be executed in the next requestAnimationFrame phase. + * This list is initialized once before any event firing occurs. It is not + * affected by the fired events or the requestAnimationFrame processing (unless + * a new event is created during the processing). + * @private {!Array<!Array<goog.dom.animationFrame.TaskSet_>>} + */ +goog.dom.animationFrame.tasks_ = [[], []]; + + +/** + * Values are 0 or 1, for whether the first or second array should be used to + * lookup or add tasks. + * @private {number} + */ +goog.dom.animationFrame.doubleBufferIndex_ = 0; + + +/** + * Whether we have already requested an animation frame that hasn't happened + * yet. + * @private {boolean} + */ +goog.dom.animationFrame.requestedFrame_ = false; + + +/** + * Counter to generate IDs for tasks. + * @private {number} + */ +goog.dom.animationFrame.taskId_ = 0; + + +/** + * Whether the animationframe runTasks_ loop is currently running. + * @private {boolean} + */ +goog.dom.animationFrame.running_ = false; + + +/** + * Returns a function that schedules the two passed-in functions to be run upon + * the next animation frame. Calling the function again during the same + * animation frame does nothing. + * + * The function under the "measure" key will run first and together with all + * other functions scheduled under this key and the function under "mutate" will + * run after that. + * + * @param {{ + * measure: (function(this:THIS, !goog.dom.animationFrame.State)|undefined), + * mutate: (function(this:THIS, !goog.dom.animationFrame.State)|undefined) + * }} spec + * @param {THIS=} opt_context Context in which to run the function. + * @return {function(...?)} + * @template THIS + */ +goog.dom.animationFrame.createTask = function(spec, opt_context) { + var id = goog.dom.animationFrame.taskId_++; + var measureTask = { + id: id, + fn: spec.measure, + context: opt_context + }; + var mutateTask = { + id: id, + fn: spec.mutate, + context: opt_context + }; + + var taskSet = { + measureTask: measureTask, + mutateTask: mutateTask, + state: {}, + args: undefined, + isScheduled: false + }; + + return function() { + // Default the context to the one that was used to call the tasks scheduler + // (this function). + if (!opt_context) { + measureTask.context = this; + mutateTask.context = this; + } + + // Save args and state. + if (arguments.length > 0) { + // The state argument goes last. That is kinda horrible but compatible + // with {@see wiz.async.method}. + if (!taskSet.args) { + taskSet.args = []; + } + taskSet.args.length = 0; + taskSet.args.push.apply(taskSet.args, arguments); + taskSet.args.push(taskSet.state); + } else { + if (!taskSet.args || taskSet.args.length == 0) { + taskSet.args = [taskSet.state]; + } else { + taskSet.args[0] = taskSet.state; + taskSet.args.length = 1; + } + } + if (!taskSet.isScheduled) { + taskSet.isScheduled = true; + var tasksArray = goog.dom.animationFrame.tasks_[ + goog.dom.animationFrame.doubleBufferIndex_]; + tasksArray.push(taskSet); + } + goog.dom.animationFrame.requestAnimationFrame_(); + }; +}; + + +/** + * Run scheduled tasks. + * @private + */ +goog.dom.animationFrame.runTasks_ = function() { + goog.dom.animationFrame.running_ = true; + goog.dom.animationFrame.requestedFrame_ = false; + var tasksArray = goog.dom.animationFrame + .tasks_[goog.dom.animationFrame.doubleBufferIndex_]; + var taskLength = tasksArray.length; + + // During the runTasks_, if there is a recursive call to queue up more + // task(s) for the next frame, we use double-buffering for that. + goog.dom.animationFrame.doubleBufferIndex_ = + (goog.dom.animationFrame.doubleBufferIndex_ + 1) % 2; + + var task; + + // Run all the measure tasks first. + for (var i = 0; i < taskLength; ++i) { + task = tasksArray[i]; + var measureTask = task.measureTask; + task.isScheduled = false; + if (measureTask.fn) { + // TODO (perumaal): Handle any exceptions thrown by the lambda. + measureTask.fn.apply(measureTask.context, task.args); + } + } + + // Run the mutate tasks next. + for (var i = 0; i < taskLength; ++i) { + task = tasksArray[i]; + var mutateTask = task.mutateTask; + task.isScheduled = false; + if (mutateTask.fn) { + // TODO (perumaal): Handle any exceptions thrown by the lambda. + mutateTask.fn.apply(mutateTask.context, task.args); + } + + // Clear state for next vsync. + task.state = {}; + } + + // Clear the tasks array as we have finished processing all the tasks. + tasksArray.length = 0; + goog.dom.animationFrame.running_ = false; +}; + + +/** + * @return {boolean} Whether the animationframe is currently running. For use + * by callers who need not to delay tasks scheduled during runTasks_ for an + * additional frame. + */ +goog.dom.animationFrame.isRunning = function() { + return goog.dom.animationFrame.running_; +}; + + +/** + * Request {@see goog.dom.animationFrame.runTasks_} to be called upon the + * next animation frame if we haven't done so already. + * @private + */ +goog.dom.animationFrame.requestAnimationFrame_ = function() { + if (goog.dom.animationFrame.requestedFrame_) { + return; + } + goog.dom.animationFrame.requestedFrame_ = true; + window.requestAnimationFrame(goog.dom.animationFrame.runTasks_); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/animationframe/polyfill.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/dom/animationframe/polyfill.js b/externs/GCL/externs/goog/dom/animationframe/polyfill.js new file mode 100644 index 0000000..19e8866 --- /dev/null +++ b/externs/GCL/externs/goog/dom/animationframe/polyfill.js @@ -0,0 +1,61 @@ +// Copyright 2014 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 polyfill for window.requestAnimationFrame and + * window.cancelAnimationFrame. + * Code based on https://gist.github.com/paulirish/1579671 + */ + +goog.provide('goog.dom.animationFrame.polyfill'); + + +/** + * @define {boolean} If true, will install the requestAnimationFrame polyfill. + */ +goog.define('goog.dom.animationFrame.polyfill.ENABLED', true); + + +/** + * Installs the requestAnimationFrame (and cancelAnimationFrame) polyfill. + */ +goog.dom.animationFrame.polyfill.install = + goog.dom.animationFrame.polyfill.ENABLED ? function() { + var vendors = ['ms', 'moz', 'webkit', 'o']; + for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x] + + 'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vendors[x] + + 'CancelAnimationFrame'] || + window[vendors[x] + 'CancelRequestAnimationFrame']; + } + + if (!window.requestAnimationFrame) { + var lastTime = 0; + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + lastTime = currTime + timeToCall; + return window.setTimeout(function() { + callback(currTime + timeToCall); + }, timeToCall); + }; + + if (!window.cancelAnimationFrame) { + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; + } + } +} : goog.nullFunction; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/annotate.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/dom/annotate.js b/externs/GCL/externs/goog/dom/annotate.js new file mode 100644 index 0000000..7a772e8 --- /dev/null +++ b/externs/GCL/externs/goog/dom/annotate.js @@ -0,0 +1,357 @@ +// Copyright 2006 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 Methods for annotating occurrences of query terms in text or + * in a DOM tree. Adapted from Gmail code. + * + */ + +goog.provide('goog.dom.annotate'); +goog.provide('goog.dom.annotate.AnnotateFn'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.TagName'); +goog.require('goog.dom.safe'); +goog.require('goog.html.SafeHtml'); + + +/** + * A function that takes: + * (1) the number of the term that is "hit", + * (2) the HTML (search term) to be annotated, + * and returns the annotated term as an HTML. + * @typedef {function(number, !goog.html.SafeHtml): !goog.html.SafeHtml} + */ +goog.dom.annotate.AnnotateFn; + + +/** + * Calls {@code annotateFn} for each occurrence of a search term in text nodes + * under {@code node}. Returns the number of hits. + * + * @param {Node} node A DOM node. + * @param {Array<!Array<string|boolean>>} terms + * An array of [searchTerm, matchWholeWordOnly] tuples. + * The matchWholeWordOnly value is a per-term attribute because some terms + * may be CJK, while others are not. (For correctness, matchWholeWordOnly + * should always be false for CJK terms.). + * @param {goog.dom.annotate.AnnotateFn} annotateFn + * @param {*=} opt_ignoreCase Whether to ignore the case of the query + * terms when looking for matches. + * @param {Array<string>=} opt_classesToSkip Nodes with one of these CSS class + * names (and its descendants) will be skipped. + * @param {number=} opt_maxMs Number of milliseconds after which this function, + * if still annotating, should stop and return. + * + * @return {boolean} Whether any terms were annotated. + */ +goog.dom.annotate.annotateTerms = function(node, terms, annotateFn, + opt_ignoreCase, + opt_classesToSkip, + opt_maxMs) { + if (opt_ignoreCase) { + terms = goog.dom.annotate.lowercaseTerms_(terms); + } + var stopTime = opt_maxMs > 0 ? goog.now() + opt_maxMs : 0; + + return goog.dom.annotate.annotateTermsInNode_( + node, terms, annotateFn, opt_ignoreCase, opt_classesToSkip || [], + stopTime, 0); +}; + + +/** + * The maximum recursion depth allowed. Any DOM nodes deeper than this are + * ignored. + * @type {number} + * @private + */ +goog.dom.annotate.MAX_RECURSION_ = 200; + + +/** + * The node types whose descendants should not be affected by annotation. + * @private {Array<string>} + */ +goog.dom.annotate.NODES_TO_SKIP_ = [ + goog.dom.TagName.SCRIPT, goog.dom.TagName.STYLE, goog.dom.TagName.TEXTAREA]; + + +/** + * Recursive helper function. + * + * @param {Node} node A DOM node. + * @param {Array<!Array<string|boolean>>} terms + * An array of [searchTerm, matchWholeWordOnly] tuples. + * The matchWholeWordOnly value is a per-term attribute because some terms + * may be CJK, while others are not. (For correctness, matchWholeWordOnly + * should always be false for CJK terms.). + * @param {goog.dom.annotate.AnnotateFn} annotateFn + * @param {*} ignoreCase Whether to ignore the case of the query terms + * when looking for matches. + * @param {Array<string>} classesToSkip Nodes with one of these CSS class + * names will be skipped (as will their descendants). + * @param {number} stopTime Deadline for annotation operation (ignored if 0). + * @param {number} recursionLevel How deep this recursive call is; pass the + * value 0 in the initial call. + * @return {boolean} Whether any terms were annotated. + * @private + */ +goog.dom.annotate.annotateTermsInNode_ = + function(node, terms, annotateFn, ignoreCase, classesToSkip, + stopTime, recursionLevel) { + if ((stopTime > 0 && goog.now() >= stopTime) || + recursionLevel > goog.dom.annotate.MAX_RECURSION_) { + return false; + } + + var annotated = false; + + if (node.nodeType == goog.dom.NodeType.TEXT) { + var html = goog.dom.annotate.helpAnnotateText_(node.nodeValue, terms, + annotateFn, ignoreCase); + if (html != null) { + // Replace the text with the annotated html. First we put the html into + // a temporary node, to get its DOM structure. To avoid adding a wrapper + // element as a side effect, we'll only actually use the temporary node's + // children. + var tempNode = goog.dom.getOwnerDocument(node).createElement( + goog.dom.TagName.SPAN); + goog.dom.safe.setInnerHtml(tempNode, html); + + var parentNode = node.parentNode; + var nodeToInsert; + while ((nodeToInsert = tempNode.firstChild) != null) { + // Each parentNode.insertBefore call removes the inserted node from + // tempNode's list of children. + parentNode.insertBefore(nodeToInsert, node); + } + + parentNode.removeChild(node); + annotated = true; + } + } else if (node.hasChildNodes() && + !goog.array.contains(goog.dom.annotate.NODES_TO_SKIP_, + node.tagName)) { + var classes = node.className.split(/\s+/); + var skip = goog.array.some(classes, function(className) { + return goog.array.contains(classesToSkip, className); + }); + + if (!skip) { + ++recursionLevel; + var curNode = node.firstChild; + while (curNode) { + var nextNode = curNode.nextSibling; + var curNodeAnnotated = goog.dom.annotate.annotateTermsInNode_( + curNode, terms, annotateFn, ignoreCase, classesToSkip, + stopTime, recursionLevel); + annotated = annotated || curNodeAnnotated; + curNode = nextNode; + } + } + } + + return annotated; +}; + + +/** + * Regular expression that matches non-word characters. + * + * Performance note: Testing a one-character string using this regex is as fast + * as the equivalent string test ("a-zA-Z0-9_".indexOf(c) < 0), give or take a + * few percent. (The regex is about 5% faster in IE 6 and about 4% slower in + * Firefox 1.5.) If performance becomes critical, it may be better to convert + * the character to a numerical char code and check whether it falls in the + * word character ranges. A quick test suggests that could be 33% faster. + * + * @type {RegExp} + * @private + */ +goog.dom.annotate.NONWORD_RE_ = /\W/; + + +/** + * Annotates occurrences of query terms in plain text. This process consists of + * identifying all occurrences of all query terms, calling a provided function + * to get the appropriate replacement HTML for each occurrence, and + * HTML-escaping all the text. + * + * @param {string} text The plain text to be searched. + * @param {Array<Array<?>>} terms An array of + * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. + * The matchWholeWordOnly value is a per-term attribute because some terms + * may be CJK, while others are not. (For correctness, matchWholeWordOnly + * should always be false for CJK terms.). + * @param {goog.dom.annotate.AnnotateFn} annotateFn + * @param {*=} opt_ignoreCase Whether to ignore the case of the query + * terms when looking for matches. + * @return {goog.html.SafeHtml} The HTML equivalent of {@code text} with terms + * annotated, or null if the text did not contain any of the terms. + */ +goog.dom.annotate.annotateText = function(text, terms, annotateFn, + opt_ignoreCase) { + if (opt_ignoreCase) { + terms = goog.dom.annotate.lowercaseTerms_(terms); + } + return goog.dom.annotate.helpAnnotateText_(text, terms, annotateFn, + opt_ignoreCase); +}; + + +/** + * Annotates occurrences of query terms in plain text. This process consists of + * identifying all occurrences of all query terms, calling a provided function + * to get the appropriate replacement HTML for each occurrence, and + * HTML-escaping all the text. + * + * @param {string} text The plain text to be searched. + * @param {Array<Array<?>>} terms An array of + * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. + * If {@code ignoreCase} is true, each search term must already be lowercase. + * The matchWholeWordOnly value is a per-term attribute because some terms + * may be CJK, while others are not. (For correctness, matchWholeWordOnly + * should always be false for CJK terms.). + * @param {goog.dom.annotate.AnnotateFn} annotateFn + * @param {*} ignoreCase Whether to ignore the case of the query terms + * when looking for matches. + * @return {goog.html.SafeHtml} The HTML equivalent of {@code text} with terms + * annotated, or null if the text did not contain any of the terms. + * @private + */ +goog.dom.annotate.helpAnnotateText_ = function(text, terms, annotateFn, + ignoreCase) { + var hit = false; + var textToSearch = ignoreCase ? text.toLowerCase() : text; + var textLen = textToSearch.length; + var numTerms = terms.length; + + // Each element will be an array of hit positions for the term. + var termHits = new Array(numTerms); + + // First collect all the hits into allHits. + for (var i = 0; i < numTerms; i++) { + var term = terms[i]; + var hits = []; + var termText = term[0]; + if (termText != '') { + var matchWholeWordOnly = term[1]; + var termLen = termText.length; + var pos = 0; + // Find each hit for term t and append to termHits. + while (pos < textLen) { + var hitPos = textToSearch.indexOf(termText, pos); + if (hitPos == -1) { + break; + } else { + var prevCharPos = hitPos - 1; + var nextCharPos = hitPos + termLen; + if (!matchWholeWordOnly || + ((prevCharPos < 0 || + goog.dom.annotate.NONWORD_RE_.test( + textToSearch.charAt(prevCharPos))) && + (nextCharPos >= textLen || + goog.dom.annotate.NONWORD_RE_.test( + textToSearch.charAt(nextCharPos))))) { + hits.push(hitPos); + hit = true; + } + pos = hitPos + termLen; + } + } + } + termHits[i] = hits; + } + + if (hit) { + var html = []; + var pos = 0; + + while (true) { + // First determine which of the n terms is the next hit. + var termIndexOfNextHit; + var posOfNextHit = -1; + + for (var i = 0; i < numTerms; i++) { + var hits = termHits[i]; + // pull off the position of the next hit of term t + // (it's always the first in the array because we're shifting + // hits off the front of the array as we process them) + // this is the next candidate to consider for the next overall hit + if (!goog.array.isEmpty(hits)) { + var hitPos = hits[0]; + + // Discard any hits embedded in the previous hit. + while (hitPos >= 0 && hitPos < pos) { + hits.shift(); + hitPos = goog.array.isEmpty(hits) ? -1 : hits[0]; + } + + if (hitPos >= 0 && (posOfNextHit < 0 || hitPos < posOfNextHit)) { + termIndexOfNextHit = i; + posOfNextHit = hitPos; + } + } + } + + // Quit if there are no more hits. + if (posOfNextHit < 0) break; + + // Remove the next hit from our hit list. + termHits[termIndexOfNextHit].shift(); + + // Append everything from the end of the last hit up to this one. + html.push(text.substr(pos, posOfNextHit - pos)); + + // Append the annotated term. + var termLen = terms[termIndexOfNextHit][0].length; + var termHtml = goog.html.SafeHtml.htmlEscape( + text.substr(posOfNextHit, termLen)); + html.push( + annotateFn(goog.asserts.assertNumber(termIndexOfNextHit), termHtml)); + + pos = posOfNextHit + termLen; + } + + // Append everything after the last hit. + html.push(text.substr(pos)); + return goog.html.SafeHtml.concat(html); + } else { + return null; + } +}; + + +/** + * Converts terms to lowercase. + * + * @param {Array<Array<?>>} terms An array of + * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. + * @return {!Array<Array<?>>} An array of + * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. + * @private + */ +goog.dom.annotate.lowercaseTerms_ = function(terms) { + var lowercaseTerms = []; + for (var i = 0; i < terms.length; ++i) { + var term = terms[i]; + lowercaseTerms[i] = [term[0].toLowerCase(), term[1]]; + } + return lowercaseTerms; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserfeature1.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/dom/browserfeature1.js b/externs/GCL/externs/goog/dom/browserfeature1.js new file mode 100644 index 0000000..2c70cda --- /dev/null +++ b/externs/GCL/externs/goog/dom/browserfeature1.js @@ -0,0 +1,72 @@ +// 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 dom package. + * + */ + + +goog.provide('goog.dom.BrowserFeature'); + +goog.require('goog.userAgent'); + + +/** + * Enum of browser capabilities. + * @enum {boolean} + */ +goog.dom.BrowserFeature = { + /** + * Whether attributes 'name' and 'type' can be added to an element after it's + * created. False in Internet Explorer prior to version 9. + */ + CAN_ADD_NAME_OR_TYPE_ATTRIBUTES: !goog.userAgent.IE || + goog.userAgent.isDocumentModeOrHigher(9), + + /** + * Whether we can use element.children to access an element's Element + * children. Available since Gecko 1.9.1, IE 9. (IE<9 also includes comment + * nodes in the collection.) + */ + CAN_USE_CHILDREN_ATTRIBUTE: !goog.userAgent.GECKO && !goog.userAgent.IE || + goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9) || + goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.1'), + + /** + * Opera, Safari 3, and Internet Explorer 9 all support innerText but they + * include text nodes in script and style tags. Not document-mode-dependent. + */ + CAN_USE_INNER_TEXT: ( + goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')), + + /** + * MSIE, Opera, and Safari>=4 support element.parentElement to access an + * element's parent if it is an Element. + */ + CAN_USE_PARENT_ELEMENT_PROPERTY: goog.userAgent.IE || goog.userAgent.OPERA || + goog.userAgent.WEBKIT, + + /** + * Whether NoScope elements need a scoped element written before them in + * innerHTML. + * MSDN: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx#1 + */ + INNER_HTML_NEEDS_SCOPED_ELEMENT: goog.userAgent.IE, + + /** + * Whether we use legacy IE range API. + */ + LEGACY_IE_RANGES: goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserrange/abstractrange.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/dom/browserrange/abstractrange.js b/externs/GCL/externs/goog/dom/browserrange/abstractrange.js new file mode 100644 index 0000000..3956f3a --- /dev/null +++ b/externs/GCL/externs/goog/dom/browserrange/abstractrange.js @@ -0,0 +1,350 @@ +// Copyright 2007 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 Definition of the browser range interface. + * + * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. + * + * @author [email protected] (Robby Walker) + */ + + +goog.provide('goog.dom.browserrange.AbstractRange'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.RangeEndpoint'); +goog.require('goog.dom.TagName'); +goog.require('goog.dom.TextRangeIterator'); +goog.require('goog.iter'); +goog.require('goog.math.Coordinate'); +goog.require('goog.string'); +goog.require('goog.string.StringBuffer'); +goog.require('goog.userAgent'); + + + +/** + * The constructor for abstract ranges. Don't call this from subclasses. + * @constructor + */ +goog.dom.browserrange.AbstractRange = function() { +}; + + +/** + * @return {goog.dom.browserrange.AbstractRange} A clone of this range. + */ +goog.dom.browserrange.AbstractRange.prototype.clone = goog.abstractMethod; + + +/** + * Returns the browser native implementation of the range. Please refrain from + * using this function - if you find you need the range please add wrappers for + * the functionality you need rather than just using the native range. + * @return {Range|TextRange} The browser native range object. + */ +goog.dom.browserrange.AbstractRange.prototype.getBrowserRange = + goog.abstractMethod; + + +/** + * Returns the deepest node in the tree that contains the entire range. + * @return {Node} The deepest node that contains the entire range. + */ +goog.dom.browserrange.AbstractRange.prototype.getContainer = + goog.abstractMethod; + + +/** + * Returns the node the range starts in. + * @return {Node} The element or text node the range starts in. + */ +goog.dom.browserrange.AbstractRange.prototype.getStartNode = + goog.abstractMethod; + + +/** + * Returns the offset into the node the range starts in. + * @return {number} The offset into the node the range starts in. For text + * nodes, this is an offset into the node value. For elements, this is + * an offset into the childNodes array. + */ +goog.dom.browserrange.AbstractRange.prototype.getStartOffset = + goog.abstractMethod; + + +/** + * @return {goog.math.Coordinate} The coordinate of the selection start node + * and offset. + */ +goog.dom.browserrange.AbstractRange.prototype.getStartPosition = function() { + goog.asserts.assert(this.range_.getClientRects, + 'Getting selection coordinates is not supported.'); + + var rects = this.range_.getClientRects(); + if (rects.length) { + return new goog.math.Coordinate(rects[0]['left'], rects[0]['top']); + } + return null; +}; + + +/** + * Returns the node the range ends in. + * @return {Node} The element or text node the range ends in. + */ +goog.dom.browserrange.AbstractRange.prototype.getEndNode = + goog.abstractMethod; + + +/** + * Returns the offset into the node the range ends in. + * @return {number} The offset into the node the range ends in. For text + * nodes, this is an offset into the node value. For elements, this is + * an offset into the childNodes array. + */ +goog.dom.browserrange.AbstractRange.prototype.getEndOffset = + goog.abstractMethod; + + +/** + * @return {goog.math.Coordinate} The coordinate of the selection end node + * and offset. + */ +goog.dom.browserrange.AbstractRange.prototype.getEndPosition = function() { + goog.asserts.assert(this.range_.getClientRects, + 'Getting selection coordinates is not supported.'); + + var rects = this.range_.getClientRects(); + if (rects.length) { + var lastRect = goog.array.peek(rects); + return new goog.math.Coordinate(lastRect['right'], lastRect['bottom']); + } + return null; +}; + + +/** + * Compares one endpoint of this range with the endpoint of another browser + * native range object. + * @param {Range|TextRange} range The browser native range to compare against. + * @param {goog.dom.RangeEndpoint} thisEndpoint The endpoint of this range + * to compare with. + * @param {goog.dom.RangeEndpoint} otherEndpoint The endpoint of the other + * range to compare with. + * @return {number} 0 if the endpoints are equal, negative if this range + * endpoint comes before the other range endpoint, and positive otherwise. + */ +goog.dom.browserrange.AbstractRange.prototype.compareBrowserRangeEndpoints = + goog.abstractMethod; + + +/** + * Tests if this range contains the given range. + * @param {goog.dom.browserrange.AbstractRange} abstractRange The range to test. + * @param {boolean=} opt_allowPartial If not set or false, the range must be + * entirely contained in the selection for this function to return true. + * @return {boolean} Whether this range contains the given range. + */ +goog.dom.browserrange.AbstractRange.prototype.containsRange = + function(abstractRange, opt_allowPartial) { + // IE sometimes misreports the boundaries for collapsed ranges. So if the + // other range is collapsed, make sure the whole range is contained. This is + // logically equivalent, and works around IE's bug. + var checkPartial = opt_allowPartial && !abstractRange.isCollapsed(); + + var range = abstractRange.getBrowserRange(); + var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END; + /** @preserveTry */ + try { + if (checkPartial) { + // There are two ways to not overlap. Being before, and being after. + // Before is represented by this.end before range.start: comparison < 0. + // After is represented by this.start after range.end: comparison > 0. + // The below is the negation of not overlapping. + return this.compareBrowserRangeEndpoints(range, end, start) >= 0 && + this.compareBrowserRangeEndpoints(range, start, end) <= 0; + + } else { + // Return true if this range bounds the parameter range from both sides. + return this.compareBrowserRangeEndpoints(range, end, end) >= 0 && + this.compareBrowserRangeEndpoints(range, start, start) <= 0; + } + } catch (e) { + if (!goog.userAgent.IE) { + throw e; + } + // IE sometimes throws exceptions when one range is invalid, i.e. points + // to a node that has been removed from the document. Return false in this + // case. + return false; + } +}; + + +/** + * Tests if this range contains the given node. + * @param {Node} node The node to test. + * @param {boolean=} opt_allowPartial If not set or false, the node must be + * entirely contained in the selection for this function to return true. + * @return {boolean} Whether this range contains the given node. + */ +goog.dom.browserrange.AbstractRange.prototype.containsNode = function(node, + opt_allowPartial) { + return this.containsRange( + goog.dom.browserrange.createRangeFromNodeContents(node), + opt_allowPartial); +}; + + +/** + * Tests if the selection is collapsed - i.e. is just a caret. + * @return {boolean} Whether the range is collapsed. + */ +goog.dom.browserrange.AbstractRange.prototype.isCollapsed = + goog.abstractMethod; + + +/** + * @return {string} The text content of the range. + */ +goog.dom.browserrange.AbstractRange.prototype.getText = + goog.abstractMethod; + + +/** + * Returns the HTML fragment this range selects. This is slow on all browsers. + * @return {string} HTML fragment of the range, does not include context + * containing elements. + */ +goog.dom.browserrange.AbstractRange.prototype.getHtmlFragment = function() { + var output = new goog.string.StringBuffer(); + goog.iter.forEach(this, function(node, ignore, it) { + if (node.nodeType == goog.dom.NodeType.TEXT) { + output.append(goog.string.htmlEscape(node.nodeValue.substring( + it.getStartTextOffset(), it.getEndTextOffset()))); + } else if (node.nodeType == goog.dom.NodeType.ELEMENT) { + if (it.isEndTag()) { + if (goog.dom.canHaveChildren(node)) { + output.append('</' + node.tagName + '>'); + } + } else { + var shallow = node.cloneNode(false); + var html = goog.dom.getOuterHtml(shallow); + if (goog.userAgent.IE && node.tagName == goog.dom.TagName.LI) { + // For an LI, IE just returns "<li>" with no closing tag + output.append(html); + } else { + var index = html.lastIndexOf('<'); + output.append(index ? html.substr(0, index) : html); + } + } + } + }, this); + + return output.toString(); +}; + + +/** + * Returns valid HTML for this range. This is fast on IE, and semi-fast on + * other browsers. + * @return {string} Valid HTML of the range, including context containing + * elements. + */ +goog.dom.browserrange.AbstractRange.prototype.getValidHtml = + goog.abstractMethod; + + +/** + * Returns a RangeIterator over the contents of the range. Regardless of the + * direction of the range, the iterator will move in document order. + * @param {boolean=} opt_keys Unused for this iterator. + * @return {!goog.dom.RangeIterator} An iterator over tags in the range. + */ +goog.dom.browserrange.AbstractRange.prototype.__iterator__ = function( + opt_keys) { + return new goog.dom.TextRangeIterator(this.getStartNode(), + this.getStartOffset(), this.getEndNode(), this.getEndOffset()); +}; + + +// SELECTION MODIFICATION + + +/** + * Set this range as the selection in its window. + * @param {boolean=} opt_reverse Whether to select the range in reverse, + * if possible. + */ +goog.dom.browserrange.AbstractRange.prototype.select = + goog.abstractMethod; + + +/** + * Removes the contents of the range from the document. As a side effect, the + * selection will be collapsed. The behavior of content removal is normalized + * across browsers. For instance, IE sometimes creates extra text nodes that + * a W3C browser does not. That behavior is corrected for. + */ +goog.dom.browserrange.AbstractRange.prototype.removeContents = + goog.abstractMethod; + + +/** + * Surrounds the text range with the specified element (on Mozilla) or with a + * clone of the specified element (on IE). Returns a reference to the + * surrounding element if the operation was successful; returns null if the + * operation failed. + * @param {Element} element The element with which the selection is to be + * surrounded. + * @return {Element} The surrounding element (same as the argument on Mozilla, + * but not on IE), or null if unsuccessful. + */ +goog.dom.browserrange.AbstractRange.prototype.surroundContents = + goog.abstractMethod; + + +/** + * Inserts a node before (or after) the range. The range may be disrupted + * beyond recovery because of the way this splits nodes. + * @param {Node} node The node to insert. + * @param {boolean} before True to insert before, false to insert after. + * @return {Node} The node added to the document. This may be different + * than the node parameter because on IE we have to clone it. + */ +goog.dom.browserrange.AbstractRange.prototype.insertNode = + goog.abstractMethod; + + +/** + * Surrounds this range with the two given nodes. The range may be disrupted + * beyond recovery because of the way this splits nodes. + * @param {Element} startNode The node to insert at the start. + * @param {Element} endNode The node to insert at the end. + */ +goog.dom.browserrange.AbstractRange.prototype.surroundWithNodes = + goog.abstractMethod; + + +/** + * Collapses the range to one of its boundary points. + * @param {boolean} toStart Whether to collapse to the start of the range. + */ +goog.dom.browserrange.AbstractRange.prototype.collapse = + goog.abstractMethod;
