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:43 UTC

[28/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/dom/pattern/nodetype.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/nodetype.js b/externs/GCL/externs/goog/dom/pattern/nodetype.js
new file mode 100644
index 0000000..a12c9a1
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/nodetype.js
@@ -0,0 +1,59 @@
+// 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 DOM pattern to match a node of the given type.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.NodeType');
+
+goog.require('goog.dom.pattern.AbstractPattern');
+goog.require('goog.dom.pattern.MatchType');
+
+
+
+/**
+ * Pattern object that matches any node of the given type.
+ * @param {goog.dom.NodeType} nodeType The node type to match.
+ * @constructor
+ * @extends {goog.dom.pattern.AbstractPattern}
+ * @final
+ */
+goog.dom.pattern.NodeType = function(nodeType) {
+  /**
+   * The node type to match.
+   * @type {goog.dom.NodeType}
+   * @private
+   */
+  this.nodeType_ = nodeType;
+};
+goog.inherits(goog.dom.pattern.NodeType, goog.dom.pattern.AbstractPattern);
+
+
+/**
+ * Test whether the given token is a text token which matches the string or
+ * regular expression provided in the constructor.
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
+ *     matches, <code>NO_MATCH</code> otherwise.
+ * @override
+ */
+goog.dom.pattern.NodeType.prototype.matchToken = function(token, type) {
+  return token.nodeType == this.nodeType_ ?
+      goog.dom.pattern.MatchType.MATCH :
+      goog.dom.pattern.MatchType.NO_MATCH;
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/pattern.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/pattern.js b/externs/GCL/externs/goog/dom/pattern/pattern.js
new file mode 100644
index 0000000..19f4d1b
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/pattern.js
@@ -0,0 +1,93 @@
+// 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 DOM patterns.  Allows for description of complex DOM patterns
+ * using regular expression like constructs.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern');
+goog.provide('goog.dom.pattern.MatchType');
+
+
+/**
+ * Regular expression for breaking text nodes.
+ * @type {RegExp}
+ */
+goog.dom.pattern.BREAKING_TEXTNODE_RE = /^\s*$/;
+
+
+/**
+ * Utility function to match a string against either a string or a regular
+ * expression.
+ *
+ * @param {string|RegExp} obj Either a string or a regular expression.
+ * @param {string} str The string to match.
+ * @return {boolean} Whether the strings are equal, or if the string matches
+ *     the regular expression.
+ */
+goog.dom.pattern.matchStringOrRegex = function(obj, str) {
+  if (goog.isString(obj)) {
+    // Match a string
+    return str == obj;
+  } else {
+    // Match a regular expression
+    return !!(str && str.match(obj));
+  }
+};
+
+
+/**
+ * Utility function to match a DOM attribute against either a string or a
+ * regular expression.  Conforms to the interface spec for
+ * {@link goog.object#every}.
+ *
+ * @param {string|RegExp} elem Either a string or a regular expression.
+ * @param {string} index The attribute name to match.
+ * @param {Object} orig The original map of matches to test.
+ * @return {boolean} Whether the strings are equal, or if the attribute matches
+ *     the regular expression.
+ * @this {Element} Called using goog.object every on an Element.
+ */
+goog.dom.pattern.matchStringOrRegexMap = function(elem, index, orig) {
+  return goog.dom.pattern.matchStringOrRegex(elem,
+      index in this ? this[index] :
+          (this.getAttribute ? this.getAttribute(index) : null));
+};
+
+
+/**
+ * When matched to a token, a pattern may return any of the following statuses:
+ *  <ol>
+ *    <li><code>NO_MATCH</code> - The pattern does not match.  This is the only
+ *      value that evaluates to <code>false</code> in a boolean context.
+ *    <li><code>MATCHING</code> - The token is part of an incomplete match.
+ *    <li><code>MATCH</code> - The token completes a match.
+ *    <li><code>BACKTRACK_MATCH</code> - The token does not match, but indicates
+ *      the end of a repetitive match.  For instance, in regular expressions,
+ *      the pattern <code>/a+/</code> would match <code>'aaaaaaaab'</code>.
+ *      Every <code>'a'</code> token would give a status of
+ *      <code>MATCHING</code> while the <code>'b'</code> token would give a
+ *      status of <code>BACKTRACK_MATCH</code>.
+ *  </ol>
+ * @enum {number}
+ */
+goog.dom.pattern.MatchType = {
+  NO_MATCH: 0,
+  MATCHING: 1,
+  MATCH: 2,
+  BACKTRACK_MATCH: 3
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/repeat.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/repeat.js b/externs/GCL/externs/goog/dom/pattern/repeat.js
new file mode 100644
index 0000000..392a6a6
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/repeat.js
@@ -0,0 +1,177 @@
+// 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 DOM pattern to match a tag and all of its children.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.Repeat');
+
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.pattern.AbstractPattern');
+goog.require('goog.dom.pattern.MatchType');
+
+
+
+/**
+ * Pattern object that matches a repetition of another pattern.
+ * @param {goog.dom.pattern.AbstractPattern} pattern The pattern to
+ *     repetitively match.
+ * @param {number=} opt_minimum The minimum number of times to match.  Defaults
+ *     to 0.
+ * @param {number=} opt_maximum The maximum number of times to match.  Defaults
+ *     to unlimited.
+ * @constructor
+ * @extends {goog.dom.pattern.AbstractPattern}
+ * @final
+ */
+goog.dom.pattern.Repeat = function(pattern,
+                                   opt_minimum,
+                                   opt_maximum) {
+  /**
+   * Pattern to repetitively match.
+   *
+   * @private {goog.dom.pattern.AbstractPattern}
+   */
+  this.pattern_ = pattern;
+
+  /**
+   * Minimum number of times to match the pattern.
+   *
+   * @private {number}
+   */
+  this.minimum_ = opt_minimum || 0;
+
+  /**
+   * Optional maximum number of times to match the pattern. A {@code null} value
+   * will be treated as infinity.
+   *
+   * @private {?number}
+   */
+  this.maximum_ = opt_maximum || null;
+
+  /**
+   * The matched nodes.
+   *
+   * @type {Array<Node>}
+   */
+  this.matches = [];
+
+  /**
+   * Number of times the pattern has matched.
+   *
+   * @type {number}
+   */
+  this.count = 0;
+
+  /**
+   * Whether the pattern has recently matched or failed to match and will need
+   * to be reset when starting a new round of matches.
+   *
+   * @private {boolean}
+   */
+  this.needsReset_ = false;
+};
+goog.inherits(goog.dom.pattern.Repeat, goog.dom.pattern.AbstractPattern);
+
+
+/**
+ * Test whether the given token continues a repeated series of matches of the
+ * pattern given in the constructor.
+ *
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
+ *     matches, <code>BACKTRACK_MATCH</code> if the pattern does not match
+ *     but already had accumulated matches, <code>MATCHING</code> if the pattern
+ *     starts a match, and <code>NO_MATCH</code> if the pattern does not match.
+ * @suppress {missingProperties} See the broken line below.
+ * @override
+ */
+goog.dom.pattern.Repeat.prototype.matchToken = function(token, type) {
+  // Reset if we're starting a new match
+  if (this.needsReset_) {
+    this.reset();
+  }
+
+  // If the option is set, ignore any whitespace only text nodes
+  if (token.nodeType == goog.dom.NodeType.TEXT &&
+      token.nodeValue.match(/^\s+$/)) {
+    return goog.dom.pattern.MatchType.MATCHING;
+  }
+
+  switch (this.pattern_.matchToken(token, type)) {
+    case goog.dom.pattern.MatchType.MATCH:
+      // Record the first token we match.
+      if (this.count == 0) {
+        this.matchedNode = token;
+      }
+
+      // Mark the match
+      this.count++;
+
+      // Add to the list
+      this.matches.push(this.pattern_.matchedNode);
+
+      // Check if this match hits our maximum
+      if (this.maximum_ !== null && this.count == this.maximum_) {
+        this.needsReset_ = true;
+        return goog.dom.pattern.MatchType.MATCH;
+      } else {
+        return goog.dom.pattern.MatchType.MATCHING;
+      }
+
+    case goog.dom.pattern.MatchType.MATCHING:
+      // This can happen when our child pattern is a sequence or a repetition.
+      return goog.dom.pattern.MatchType.MATCHING;
+
+    case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
+      // This happens if our child pattern is repetitive too.
+      // TODO(robbyw): Backtrack further if necessary.
+      this.count++;
+
+      // NOTE(nicksantos): This line of code is broken. this.patterns_ doesn't
+      // exist, and this.currentPosition_ doesn't exit. When this is fixed,
+      // remove the missingProperties suppression above.
+      if (this.currentPosition_ == this.patterns_.length) {
+        this.needsReset_ = true;
+        return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
+      } else {
+        // Retry the same token on the next iteration of the child pattern.
+        return this.matchToken(token, type);
+      }
+
+    default:
+      this.needsReset_ = true;
+      if (this.count >= this.minimum_) {
+        return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
+      } else {
+        return goog.dom.pattern.MatchType.NO_MATCH;
+      }
+  }
+};
+
+
+/**
+ * Reset any internal state this pattern keeps.
+ * @override
+ */
+goog.dom.pattern.Repeat.prototype.reset = function() {
+  this.pattern_.reset();
+  this.count = 0;
+  this.needsReset_ = false;
+  this.matches.length = 0;
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/sequence.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/sequence.js b/externs/GCL/externs/goog/dom/pattern/sequence.js
new file mode 100644
index 0000000..2282361
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/sequence.js
@@ -0,0 +1,135 @@
+// 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 DOM pattern to match a sequence of other patterns.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.Sequence');
+
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.pattern');
+goog.require('goog.dom.pattern.AbstractPattern');
+goog.require('goog.dom.pattern.MatchType');
+
+
+
+/**
+ * Pattern object that matches a sequence of other patterns.
+ *
+ * @param {Array<goog.dom.pattern.AbstractPattern>} patterns Ordered array of
+ *     patterns to match.
+ * @param {boolean=} opt_ignoreWhitespace Optional flag to ignore text nodes
+ *     consisting entirely of whitespace.  The default is to not ignore them.
+ * @constructor
+ * @extends {goog.dom.pattern.AbstractPattern}
+ * @final
+ */
+goog.dom.pattern.Sequence = function(patterns, opt_ignoreWhitespace) {
+  /**
+   * Ordered array of patterns to match.
+   *
+   * @type {Array<goog.dom.pattern.AbstractPattern>}
+   */
+  this.patterns = patterns;
+
+  /**
+   * Whether or not to ignore whitespace only Text nodes.
+   *
+   * @private {boolean}
+   */
+  this.ignoreWhitespace_ = !!opt_ignoreWhitespace;
+
+  /**
+   * Position in the patterns array we have reached by successful matches.
+   *
+   * @private {number}
+   */
+  this.currentPosition_ = 0;
+};
+goog.inherits(goog.dom.pattern.Sequence, goog.dom.pattern.AbstractPattern);
+
+
+/**
+ * Test whether the given token starts, continues, or finishes the sequence
+ * of patterns given in the constructor.
+ *
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
+ *     matches, <code>MATCHING</code> if the pattern starts a match, and
+ *     <code>NO_MATCH</code> if the pattern does not match.
+ * @override
+ */
+goog.dom.pattern.Sequence.prototype.matchToken = function(token, type) {
+  // If the option is set, ignore any whitespace only text nodes
+  if (this.ignoreWhitespace_ && token.nodeType == goog.dom.NodeType.TEXT &&
+      goog.dom.pattern.BREAKING_TEXTNODE_RE.test(token.nodeValue)) {
+    return goog.dom.pattern.MatchType.MATCHING;
+  }
+
+  switch (this.patterns[this.currentPosition_].matchToken(token, type)) {
+    case goog.dom.pattern.MatchType.MATCH:
+      // Record the first token we match.
+      if (this.currentPosition_ == 0) {
+        this.matchedNode = token;
+      }
+
+      // Move forward one position.
+      this.currentPosition_++;
+
+      // Check if this is the last position.
+      if (this.currentPosition_ == this.patterns.length) {
+        this.reset();
+        return goog.dom.pattern.MatchType.MATCH;
+      } else {
+        return goog.dom.pattern.MatchType.MATCHING;
+      }
+
+    case goog.dom.pattern.MatchType.MATCHING:
+      // This can happen when our child pattern is a sequence or a repetition.
+      return goog.dom.pattern.MatchType.MATCHING;
+
+    case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
+      // This means a repetitive match succeeded 1 token ago.
+      // TODO(robbyw): Backtrack further if necessary.
+      this.currentPosition_++;
+
+      if (this.currentPosition_ == this.patterns.length) {
+        this.reset();
+        return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
+      } else {
+        // Retry the same token on the next pattern.
+        return this.matchToken(token, type);
+      }
+
+    default:
+      this.reset();
+      return goog.dom.pattern.MatchType.NO_MATCH;
+  }
+};
+
+
+/**
+ * Reset any internal state this pattern keeps.
+ * @override
+ */
+goog.dom.pattern.Sequence.prototype.reset = function() {
+  if (this.patterns[this.currentPosition_]) {
+    this.patterns[this.currentPosition_].reset();
+  }
+  this.currentPosition_ = 0;
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/starttag.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/starttag.js b/externs/GCL/externs/goog/dom/pattern/starttag.js
new file mode 100644
index 0000000..4ce0113
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/starttag.js
@@ -0,0 +1,53 @@
+// 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 DOM pattern to match the start of a tag.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.StartTag');
+
+goog.require('goog.dom.TagWalkType');
+goog.require('goog.dom.pattern.Tag');
+
+
+
+/**
+ * Pattern object that matches an opening tag.
+ *
+ * @param {string|RegExp} tag Name of the tag.  Also will accept a regular
+ *     expression to match against the tag name.
+ * @param {Object=} opt_attrs Optional map of attribute names to desired values.
+ *     This pattern will only match when all attributes are present and match
+ *     the string or regular expression value provided here.
+ * @param {Object=} opt_styles Optional map of CSS style names to desired
+ *     values. This pattern will only match when all styles are present and
+ *     match the string or regular expression value provided here.
+ * @param {Function=} opt_test Optional function that takes the element as a
+ *     parameter and returns true if this pattern should match it.
+ * @constructor
+ * @extends {goog.dom.pattern.Tag}
+ */
+goog.dom.pattern.StartTag = function(tag, opt_attrs, opt_styles, opt_test) {
+  goog.dom.pattern.Tag.call(
+      this,
+      tag,
+      goog.dom.TagWalkType.START_TAG,
+      opt_attrs,
+      opt_styles,
+      opt_test);
+};
+goog.inherits(goog.dom.pattern.StartTag, goog.dom.pattern.Tag);

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/tag.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/tag.js b/externs/GCL/externs/goog/dom/pattern/tag.js
new file mode 100644
index 0000000..ba95123
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/tag.js
@@ -0,0 +1,128 @@
+// 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 DOM pattern to match a tag.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.Tag');
+
+goog.require('goog.dom.pattern');
+goog.require('goog.dom.pattern.AbstractPattern');
+goog.require('goog.dom.pattern.MatchType');
+goog.require('goog.object');
+
+
+
+/**
+ * Pattern object that matches an tag.
+ *
+ * @param {string|RegExp} tag Name of the tag.  Also will accept a regular
+ *     expression to match against the tag name.
+ * @param {goog.dom.TagWalkType} type Type of token to match.
+ * @param {Object=} opt_attrs Optional map of attribute names to desired values.
+ *     This pattern will only match when all attributes are present and match
+ *     the string or regular expression value provided here.
+ * @param {Object=} opt_styles Optional map of CSS style names to desired
+ *     values. This pattern will only match when all styles are present and
+ *     match the string or regular expression value provided here.
+ * @param {Function=} opt_test Optional function that takes the element as a
+ *     parameter and returns true if this pattern should match it.
+ * @constructor
+ * @extends {goog.dom.pattern.AbstractPattern}
+ */
+goog.dom.pattern.Tag = function(tag, type, opt_attrs, opt_styles, opt_test) {
+  /**
+   * The tag to match.
+   *
+   * @private {string|RegExp}
+   */
+  this.tag_ = goog.isString(tag) ? tag.toUpperCase() : tag;
+
+  /**
+   * The type of token to match.
+   *
+   * @private {goog.dom.TagWalkType}
+   */
+  this.type_ = type;
+
+  /**
+   * The attributes to test for.
+   *
+   * @private {Object}
+   */
+  this.attrs_ = opt_attrs || null;
+
+  /**
+   * The styles to test for.
+   *
+   * @private {Object}
+   */
+  this.styles_ = opt_styles || null;
+
+  /**
+   * Function that takes the element as a parameter and returns true if this
+   * pattern should match it.
+   *
+   * @private {Function}
+   */
+  this.test_ = opt_test || null;
+};
+goog.inherits(goog.dom.pattern.Tag, goog.dom.pattern.AbstractPattern);
+
+
+/**
+ * Test whether the given token is a tag token which matches the tag name,
+ * style, and attributes provided in the constructor.
+ *
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
+ *     matches, <code>NO_MATCH</code> otherwise.
+ * @override
+ */
+goog.dom.pattern.Tag.prototype.matchToken = function(token, type) {
+  // Check the direction and tag name.
+  if (type == this.type_ &&
+      goog.dom.pattern.matchStringOrRegex(this.tag_, token.nodeName)) {
+    // Check the attributes.
+    if (this.attrs_ &&
+        !goog.object.every(
+            this.attrs_,
+            goog.dom.pattern.matchStringOrRegexMap,
+            token)) {
+      return goog.dom.pattern.MatchType.NO_MATCH;
+    }
+    // Check the styles.
+    if (this.styles_ &&
+        !goog.object.every(
+            this.styles_,
+            goog.dom.pattern.matchStringOrRegexMap,
+            token.style)) {
+      return goog.dom.pattern.MatchType.NO_MATCH;
+    }
+
+    if (this.test_ && !this.test_(token)) {
+      return goog.dom.pattern.MatchType.NO_MATCH;
+    }
+
+    // If we reach this point, we have a match and should save it.
+    this.matchedNode = token;
+    return goog.dom.pattern.MatchType.MATCH;
+  }
+
+  return goog.dom.pattern.MatchType.NO_MATCH;
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/text.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/text.js b/externs/GCL/externs/goog/dom/pattern/text.js
new file mode 100644
index 0000000..cf920e1
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/text.js
@@ -0,0 +1,67 @@
+// 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 DOM pattern to match a text node.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.Text');
+
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.pattern');
+goog.require('goog.dom.pattern.AbstractPattern');
+goog.require('goog.dom.pattern.MatchType');
+
+
+
+/**
+ * Pattern object that matches text by exact matching or regular expressions.
+ *
+ * @param {string|RegExp} match String or regular expression to match against.
+ * @constructor
+ * @extends {goog.dom.pattern.AbstractPattern}
+ * @final
+ */
+goog.dom.pattern.Text = function(match) {
+  /**
+   * The text or regular expression to match.
+   *
+   * @private {string|RegExp}
+   */
+  this.match_ = match;
+};
+goog.inherits(goog.dom.pattern.Text, goog.dom.pattern.AbstractPattern);
+
+
+/**
+ * Test whether the given token is a text token which matches the string or
+ * regular expression provided in the constructor.
+ *
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
+ *     matches, <code>NO_MATCH</code> otherwise.
+ * @override
+ */
+goog.dom.pattern.Text.prototype.matchToken = function(token, type) {
+  if (token.nodeType == goog.dom.NodeType.TEXT &&
+      goog.dom.pattern.matchStringOrRegex(this.match_, token.nodeValue)) {
+    this.matchedNode = token;
+    return goog.dom.pattern.MatchType.MATCH;
+  }
+
+  return goog.dom.pattern.MatchType.NO_MATCH;
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/range.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/range.js b/externs/GCL/externs/goog/dom/range.js
new file mode 100644
index 0000000..eec784a
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/range.js
@@ -0,0 +1,226 @@
+// 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 Utilities for working with ranges in HTML documents.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.Range');
+
+goog.require('goog.dom');
+goog.require('goog.dom.AbstractRange');
+goog.require('goog.dom.BrowserFeature');
+goog.require('goog.dom.ControlRange');
+goog.require('goog.dom.MultiRange');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TextRange');
+
+
+/**
+ * Create a new selection from the given browser window's current selection.
+ * Note that this object does not auto-update if the user changes their
+ * selection and should be used as a snapshot.
+ * @param {Window=} opt_win The window to get the selection of.  Defaults to the
+ *     window this class was defined in.
+ * @return {goog.dom.AbstractRange?} A range wrapper object, or null if there
+ *     was an error.
+ */
+goog.dom.Range.createFromWindow = function(opt_win) {
+  var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(
+      opt_win || window);
+  return sel && goog.dom.Range.createFromBrowserSelection(sel);
+};
+
+
+/**
+ * Create a new range wrapper from the given browser selection object.  Note
+ * that this object does not auto-update if the user changes their selection and
+ * should be used as a snapshot.
+ * @param {!Object} selection The browser selection object.
+ * @return {goog.dom.AbstractRange?} A range wrapper object or null if there
+ *    was an error.
+ */
+goog.dom.Range.createFromBrowserSelection = function(selection) {
+  var range;
+  var isReversed = false;
+  if (selection.createRange) {
+    /** @preserveTry */
+    try {
+      range = selection.createRange();
+    } catch (e) {
+      // Access denied errors can be thrown here in IE if the selection was
+      // a flash obj or if there are cross domain issues
+      return null;
+    }
+  } else if (selection.rangeCount) {
+    if (selection.rangeCount > 1) {
+      return goog.dom.MultiRange.createFromBrowserSelection(
+          /** @type {!Selection} */ (selection));
+    } else {
+      range = selection.getRangeAt(0);
+      isReversed = goog.dom.Range.isReversed(selection.anchorNode,
+          selection.anchorOffset, selection.focusNode, selection.focusOffset);
+    }
+  } else {
+    return null;
+  }
+
+  return goog.dom.Range.createFromBrowserRange(range, isReversed);
+};
+
+
+/**
+ * Create a new range wrapper from the given browser range object.
+ * @param {Range|TextRange} range The browser range object.
+ * @param {boolean=} opt_isReversed Whether the focus node is before the anchor
+ *     node.
+ * @return {!goog.dom.AbstractRange} A range wrapper object.
+ */
+goog.dom.Range.createFromBrowserRange = function(range, opt_isReversed) {
+  // Create an IE control range when appropriate.
+  return goog.dom.AbstractRange.isNativeControlRange(range) ?
+      goog.dom.ControlRange.createFromBrowserRange(range) :
+      goog.dom.TextRange.createFromBrowserRange(range, opt_isReversed);
+};
+
+
+/**
+ * Create a new range wrapper that selects the given node's text.
+ * @param {Node} node The node to select.
+ * @param {boolean=} opt_isReversed Whether the focus node is before the anchor
+ *     node.
+ * @return {!goog.dom.AbstractRange} A range wrapper object.
+ */
+goog.dom.Range.createFromNodeContents = function(node, opt_isReversed) {
+  return goog.dom.TextRange.createFromNodeContents(node, opt_isReversed);
+};
+
+
+/**
+ * Create a new range wrapper that represents a caret at the given node,
+ * accounting for the given offset.  This always creates a TextRange, regardless
+ * of whether node is an image node or other control range type node.
+ * @param {Node} node The node to place a caret at.
+ * @param {number} offset The offset within the node to place the caret at.
+ * @return {!goog.dom.AbstractRange} A range wrapper object.
+ */
+goog.dom.Range.createCaret = function(node, offset) {
+  return goog.dom.TextRange.createFromNodes(node, offset, node, offset);
+};
+
+
+/**
+ * Create a new range wrapper that selects the area between the given nodes,
+ * accounting for the given offsets.
+ * @param {Node} anchorNode The node to anchor on.
+ * @param {number} anchorOffset The offset within the node to anchor on.
+ * @param {Node} focusNode The node to focus on.
+ * @param {number} focusOffset The offset within the node to focus on.
+ * @return {!goog.dom.AbstractRange} A range wrapper object.
+ */
+goog.dom.Range.createFromNodes = function(anchorNode, anchorOffset, focusNode,
+    focusOffset) {
+  return goog.dom.TextRange.createFromNodes(anchorNode, anchorOffset, focusNode,
+      focusOffset);
+};
+
+
+/**
+ * Clears the window's selection.
+ * @param {Window=} opt_win The window to get the selection of.  Defaults to the
+ *     window this class was defined in.
+ */
+goog.dom.Range.clearSelection = function(opt_win) {
+  var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(
+      opt_win || window);
+  if (!sel) {
+    return;
+  }
+  if (sel.empty) {
+    // We can't just check that the selection is empty, becuase IE
+    // sometimes gets confused.
+    try {
+      sel.empty();
+    } catch (e) {
+      // Emptying an already empty selection throws an exception in IE
+    }
+  } else {
+    try {
+      sel.removeAllRanges();
+    } catch (e) {
+      // This throws in IE9 if the range has been invalidated; for example, if
+      // the user clicked on an element which disappeared during the event
+      // handler.
+    }
+  }
+};
+
+
+/**
+ * Tests if the window has a selection.
+ * @param {Window=} opt_win The window to check the selection of.  Defaults to
+ *     the window this class was defined in.
+ * @return {boolean} Whether the window has a selection.
+ */
+goog.dom.Range.hasSelection = function(opt_win) {
+  var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(
+      opt_win || window);
+  return !!sel &&
+      (goog.dom.BrowserFeature.LEGACY_IE_RANGES ?
+       sel.type != 'None' : !!sel.rangeCount);
+};
+
+
+/**
+ * Returns whether the focus position occurs before the anchor position.
+ * @param {Node} anchorNode The node to anchor on.
+ * @param {number} anchorOffset The offset within the node to anchor on.
+ * @param {Node} focusNode The node to focus on.
+ * @param {number} focusOffset The offset within the node to focus on.
+ * @return {boolean} Whether the focus position occurs before the anchor
+ *     position.
+ */
+goog.dom.Range.isReversed = function(anchorNode, anchorOffset, focusNode,
+    focusOffset) {
+  if (anchorNode == focusNode) {
+    return focusOffset < anchorOffset;
+  }
+  var child;
+  if (anchorNode.nodeType == goog.dom.NodeType.ELEMENT && anchorOffset) {
+    child = anchorNode.childNodes[anchorOffset];
+    if (child) {
+      anchorNode = child;
+      anchorOffset = 0;
+    } else if (goog.dom.contains(anchorNode, focusNode)) {
+      // If focus node is contained in anchorNode, it must be before the
+      // end of the node.  Hence we are reversed.
+      return true;
+    }
+  }
+  if (focusNode.nodeType == goog.dom.NodeType.ELEMENT && focusOffset) {
+    child = focusNode.childNodes[focusOffset];
+    if (child) {
+      focusNode = child;
+      focusOffset = 0;
+    } else if (goog.dom.contains(focusNode, anchorNode)) {
+      // If anchor node is contained in focusNode, it must be before the
+      // end of the node.  Hence we are not reversed.
+      return false;
+    }
+  }
+  return (goog.dom.compareNodeOrder(anchorNode, focusNode) ||
+      anchorOffset - focusOffset) > 0;
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/rangeendpoint.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/rangeendpoint.js b/externs/GCL/externs/goog/dom/rangeendpoint.js
new file mode 100644
index 0000000..f8d0fe4
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/rangeendpoint.js
@@ -0,0 +1,32 @@
+// 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 Simple struct for endpoints of a range.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.RangeEndpoint');
+
+
+/**
+ * Constants for selection endpoints.
+ * @enum {number}
+ */
+goog.dom.RangeEndpoint = {
+  START: 1,
+  END: 0
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/safe.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/safe.js b/externs/GCL/externs/goog/dom/safe.js
new file mode 100644
index 0000000..8aa9d9e
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/safe.js
@@ -0,0 +1,325 @@
+// 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.
+
+/**
+ * @fileoverview Type-safe wrappers for unsafe DOM APIs.
+ *
+ * This file provides type-safe wrappers for DOM APIs that can result in
+ * cross-site scripting (XSS) vulnerabilities, if the API is supplied with
+ * untrusted (attacker-controlled) input.  Instead of plain strings, the type
+ * safe wrappers consume values of types from the goog.html package whose
+ * contract promises that values are safe to use in the corresponding context.
+ *
+ * Hence, a program that exclusively uses the wrappers in this file (i.e., whose
+ * only reference to security-sensitive raw DOM APIs are in this file) is
+ * guaranteed to be free of XSS due to incorrect use of such DOM APIs (modulo
+ * correctness of code that produces values of the respective goog.html types,
+ * and absent code that violates type safety).
+ *
+ * For example, assigning to an element's .innerHTML property a string that is
+ * derived (even partially) from untrusted input typically results in an XSS
+ * vulnerability. The type-safe wrapper goog.html.setInnerHtml consumes a value
+ * of type goog.html.SafeHtml, whose contract states that using its values in a
+ * HTML context will not result in XSS. Hence a program that is free of direct
+ * assignments to any element's innerHTML property (with the exception of the
+ * assignment to .innerHTML in this file) is guaranteed to be free of XSS due to
+ * assignment of untrusted strings to the innerHTML property.
+ */
+
+goog.provide('goog.dom.safe');
+
+goog.require('goog.asserts');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeUrl');
+goog.require('goog.html.TrustedResourceUrl');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+
+
+/**
+ * Assigns known-safe HTML to an element's innerHTML property.
+ * @param {!Element} elem The element whose innerHTML is to be assigned to.
+ * @param {!goog.html.SafeHtml} html The known-safe HTML to assign.
+ */
+goog.dom.safe.setInnerHtml = function(elem, html) {
+  elem.innerHTML = goog.html.SafeHtml.unwrap(html);
+};
+
+
+/**
+ * Assigns known-safe HTML to an element's outerHTML property.
+ * @param {!Element} elem The element whose outerHTML is to be assigned to.
+ * @param {!goog.html.SafeHtml} html The known-safe HTML to assign.
+ */
+goog.dom.safe.setOuterHtml = function(elem, html) {
+  elem.outerHTML = goog.html.SafeHtml.unwrap(html);
+};
+
+
+/**
+ * Writes known-safe HTML to a document.
+ * @param {!Document} doc The document to be written to.
+ * @param {!goog.html.SafeHtml} html The known-safe HTML to assign.
+ */
+goog.dom.safe.documentWrite = function(doc, html) {
+  doc.write(goog.html.SafeHtml.unwrap(html));
+};
+
+
+/**
+ * Safely assigns a URL to an anchor element's href property.
+ *
+ * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
+ * anchor's href property.  If url is of type string however, it is first
+ * sanitized using goog.html.SafeUrl.sanitize.
+ *
+ * Example usage:
+ *   goog.dom.safe.setAnchorHref(anchorEl, url);
+ * which is a safe alternative to
+ *   anchorEl.href = url;
+ * The latter can result in XSS vulnerabilities if url is a
+ * user-/attacker-controlled value.
+ *
+ * @param {!HTMLAnchorElement} anchor The anchor element whose href property
+ *     is to be assigned to.
+ * @param {string|!goog.html.SafeUrl} url The URL to assign.
+ * @see goog.html.SafeUrl#sanitize
+ */
+goog.dom.safe.setAnchorHref = function(anchor, url) {
+  /** @type {!goog.html.SafeUrl} */
+  var safeUrl;
+  if (url instanceof goog.html.SafeUrl) {
+    safeUrl = url;
+  } else {
+    safeUrl = goog.html.SafeUrl.sanitize(url);
+  }
+  anchor.href = goog.html.SafeUrl.unwrap(safeUrl);
+};
+
+
+/**
+ * Safely assigns a URL to an embed element's src property.
+ *
+ * Example usage:
+ *   goog.dom.safe.setEmbedSrc(embedEl, url);
+ * which is a safe alternative to
+ *   embedEl.src = url;
+ * The latter can result in loading untrusted code unless it is ensured that
+ * the URL refers to a trustworthy resource.
+ *
+ * @param {!HTMLEmbedElement} embed The embed element whose src property
+ *     is to be assigned to.
+ * @param {!goog.html.TrustedResourceUrl} url The URL to assign.
+ */
+goog.dom.safe.setEmbedSrc = function(embed, url) {
+  embed.src = goog.html.TrustedResourceUrl.unwrap(url);
+};
+
+
+/**
+ * Safely assigns a URL to a frame element's src property.
+ *
+ * Example usage:
+ *   goog.dom.safe.setFrameSrc(frameEl, url);
+ * which is a safe alternative to
+ *   frameEl.src = url;
+ * The latter can result in loading untrusted code unless it is ensured that
+ * the URL refers to a trustworthy resource.
+ *
+ * @param {!HTMLFrameElement} frame The frame element whose src property
+ *     is to be assigned to.
+ * @param {!goog.html.TrustedResourceUrl} url The URL to assign.
+ */
+goog.dom.safe.setFrameSrc = function(frame, url) {
+  frame.src = goog.html.TrustedResourceUrl.unwrap(url);
+};
+
+
+/**
+ * Safely assigns a URL to an iframe element's src property.
+ *
+ * Example usage:
+ *   goog.dom.safe.setIframeSrc(iframeEl, url);
+ * which is a safe alternative to
+ *   iframeEl.src = url;
+ * The latter can result in loading untrusted code unless it is ensured that
+ * the URL refers to a trustworthy resource.
+ *
+ * @param {!HTMLIFrameElement} iframe The iframe element whose src property
+ *     is to be assigned to.
+ * @param {!goog.html.TrustedResourceUrl} url The URL to assign.
+ */
+goog.dom.safe.setIframeSrc = function(iframe, url) {
+  iframe.src = goog.html.TrustedResourceUrl.unwrap(url);
+};
+
+
+/**
+ * Safely sets a link element's href and rel properties. Whether or not
+ * the URL assigned to href has to be a goog.html.TrustedResourceUrl
+ * depends on the value of the rel property. If rel contains "stylesheet"
+ * then a TrustedResourceUrl is required.
+ *
+ * Example usage:
+ *   goog.dom.safe.setLinkHrefAndRel(linkEl, url, 'stylesheet');
+ * which is a safe alternative to
+ *   linkEl.rel = 'stylesheet';
+ *   linkEl.href = url;
+ * The latter can result in loading untrusted code unless it is ensured that
+ * the URL refers to a trustworthy resource.
+ *
+ * @param {!HTMLLinkElement} link The link element whose href property
+ *     is to be assigned to.
+ * @param {string|!goog.html.SafeUrl|!goog.html.TrustedResourceUrl} url The URL
+ *     to assign to the href property. Must be a TrustedResourceUrl if the
+ *     value assigned to rel contains "stylesheet". A string value is
+ *     sanitized with goog.html.SafeUrl.sanitize.
+ * @param {string} rel The value to assign to the rel property.
+ * @throws {Error} if rel contains "stylesheet" and url is not a
+ *     TrustedResourceUrl
+ * @see goog.html.SafeUrl#sanitize
+ */
+goog.dom.safe.setLinkHrefAndRel = function(link, url, rel) {
+  link.rel = rel;
+  if (goog.string.caseInsensitiveContains(rel, 'stylesheet')) {
+    goog.asserts.assert(
+        url instanceof goog.html.TrustedResourceUrl,
+        'URL must be TrustedResourceUrl because "rel" contains "stylesheet"');
+    link.href = goog.html.TrustedResourceUrl.unwrap(url);
+  } else if (url instanceof goog.html.TrustedResourceUrl) {
+    link.href = goog.html.TrustedResourceUrl.unwrap(url);
+  } else if (url instanceof goog.html.SafeUrl) {
+    link.href = goog.html.SafeUrl.unwrap(url);
+  } else {  // string
+    // SafeUrl.sanitize must return legitimate SafeUrl when passed a string.
+    link.href = goog.html.SafeUrl.sanitize(url).getTypedStringValue();
+  }
+};
+
+
+/**
+ * Safely assigns a URL to an object element's data property.
+ *
+ * Example usage:
+ *   goog.dom.safe.setObjectData(objectEl, url);
+ * which is a safe alternative to
+ *   objectEl.data = url;
+ * The latter can result in loading untrusted code unless setit is ensured that
+ * the URL refers to a trustworthy resource.
+ *
+ * @param {!HTMLObjectElement} object The object element whose data property
+ *     is to be assigned to.
+ * @param {!goog.html.TrustedResourceUrl} url The URL to assign.
+ */
+goog.dom.safe.setObjectData = function(object, url) {
+  object.data = goog.html.TrustedResourceUrl.unwrap(url);
+};
+
+
+/**
+ * Safely assigns a URL to an iframe element's src property.
+ *
+ * Example usage:
+ *   goog.dom.safe.setScriptSrc(scriptEl, url);
+ * which is a safe alternative to
+ *   scriptEl.src = url;
+ * The latter can result in loading untrusted code unless it is ensured that
+ * the URL refers to a trustworthy resource.
+ *
+ * @param {!HTMLScriptElement} script The script element whose src property
+ *     is to be assigned to.
+ * @param {!goog.html.TrustedResourceUrl} url The URL to assign.
+ */
+goog.dom.safe.setScriptSrc = function(script, url) {
+  script.src = goog.html.TrustedResourceUrl.unwrap(url);
+};
+
+
+/**
+ * Safely assigns a URL to a Location object's href property.
+ *
+ * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to
+ * loc's href property.  If url is of type string however, it is first sanitized
+ * using goog.html.SafeUrl.sanitize.
+ *
+ * Example usage:
+ *   goog.dom.safe.setLocationHref(document.location, redirectUrl);
+ * which is a safe alternative to
+ *   document.location.href = redirectUrl;
+ * The latter can result in XSS vulnerabilities if redirectUrl is a
+ * user-/attacker-controlled value.
+ *
+ * @param {!Location} loc The Location object whose href property is to be
+ *     assigned to.
+ * @param {string|!goog.html.SafeUrl} url The URL to assign.
+ * @see goog.html.SafeUrl#sanitize
+ */
+goog.dom.safe.setLocationHref = function(loc, url) {
+  /** @type {!goog.html.SafeUrl} */
+  var safeUrl;
+  if (url instanceof goog.html.SafeUrl) {
+    safeUrl = url;
+  } else {
+    safeUrl = goog.html.SafeUrl.sanitize(url);
+  }
+  loc.href = goog.html.SafeUrl.unwrap(safeUrl);
+};
+
+
+/**
+ * Safely opens a URL in a new window (via window.open).
+ *
+ * If url is of type goog.html.SafeUrl, its value is unwrapped and passed in to
+ * window.open.  If url is of type string however, it is first sanitized
+ * using goog.html.SafeUrl.sanitize.
+ *
+ * Note that this function does not prevent leakages via the referer that is
+ * sent by window.open. It is advised to only use this to open 1st party URLs.
+ *
+ * Example usage:
+ *   goog.dom.safe.openInWindow(url);
+ * which is a safe alternative to
+ *   window.open(url);
+ * The latter can result in XSS vulnerabilities if redirectUrl is a
+ * user-/attacker-controlled value.
+ *
+ * @param {string|!goog.html.SafeUrl} url The URL to open.
+ * @param {Window=} opt_openerWin Window of which to call the .open() method.
+ *     Defaults to the global window.
+ * @param {!goog.string.Const=} opt_name Name of the window to open in. Can be
+ *     _top, etc as allowed by window.open().
+ * @param {string=} opt_specs Comma-separated list of specifications, same as
+ *     in window.open().
+ * @param {boolean=} opt_replace Whether to replace the current entry in browser
+ *     history, same as in window.open().
+ * @return {Window} Window the url was opened in.
+ */
+goog.dom.safe.openInWindow = function(
+    url, opt_openerWin, opt_name, opt_specs, opt_replace) {
+  /** @type {!goog.html.SafeUrl} */
+  var safeUrl;
+  if (url instanceof goog.html.SafeUrl) {
+    safeUrl = url;
+  } else {
+    safeUrl = goog.html.SafeUrl.sanitize(url);
+  }
+  var win = opt_openerWin || window;
+  return win.open(goog.html.SafeUrl.unwrap(safeUrl),
+      // If opt_name is undefined, simply passing that in to open() causes IE to
+      // reuse the current window instead of opening a new one. Thus we pass ''
+      // in instead, which according to spec opens a new window. See
+      // https://html.spec.whatwg.org/multipage/browsers.html#dom-open .
+      opt_name ? goog.string.Const.unwrap(opt_name) : '',
+      opt_specs, opt_replace);
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/savedcaretrange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/savedcaretrange.js b/externs/GCL/externs/goog/dom/savedcaretrange.js
new file mode 100644
index 0000000..ea61050
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/savedcaretrange.js
@@ -0,0 +1,215 @@
+// 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 An API for saving and restoring ranges as HTML carets.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+
+goog.provide('goog.dom.SavedCaretRange');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.SavedRange');
+goog.require('goog.dom.TagName');
+goog.require('goog.string');
+
+
+
+/**
+ * A struct for holding context about saved selections.
+ * This can be used to preserve the selection and restore while the DOM is
+ * manipulated, or through an asynchronous call. Use goog.dom.Range factory
+ * methods to obtain an {@see goog.dom.AbstractRange} instance, and use
+ * {@see goog.dom.AbstractRange#saveUsingCarets} to obtain a SavedCaretRange.
+ * For editor ranges under content-editable elements or design-mode iframes,
+ * prefer using {@see goog.editor.range.saveUsingNormalizedCarets}.
+ * @param {goog.dom.AbstractRange} range The range being saved.
+ * @constructor
+ * @extends {goog.dom.SavedRange}
+ */
+goog.dom.SavedCaretRange = function(range) {
+  goog.dom.SavedRange.call(this);
+
+  /**
+   * The DOM id of the caret at the start of the range.
+   * @type {string}
+   * @private
+   */
+  this.startCaretId_ = goog.string.createUniqueString();
+
+  /**
+   * The DOM id of the caret at the end of the range.
+   * @type {string}
+   * @private
+   */
+  this.endCaretId_ = goog.string.createUniqueString();
+
+  /**
+   * Whether the range is reversed (anchor at the end).
+   * @private {boolean}
+   */
+  this.reversed_ = range.isReversed();
+
+  /**
+   * A DOM helper for storing the current document context.
+   * @type {goog.dom.DomHelper}
+   * @private
+   */
+  this.dom_ = goog.dom.getDomHelper(range.getDocument());
+
+  range.surroundWithNodes(this.createCaret_(true), this.createCaret_(false));
+};
+goog.inherits(goog.dom.SavedCaretRange, goog.dom.SavedRange);
+
+
+/**
+ * Gets the range that this SavedCaretRage represents, without selecting it
+ * or removing the carets from the DOM.
+ * @return {goog.dom.AbstractRange?} An abstract range.
+ */
+goog.dom.SavedCaretRange.prototype.toAbstractRange = function() {
+  var range = null;
+  var startCaret = this.getCaret(true);
+  var endCaret = this.getCaret(false);
+  if (startCaret && endCaret) {
+    /** @suppress {missingRequire} circular dependency */
+    range = goog.dom.Range.createFromNodes(startCaret, 0, endCaret, 0);
+  }
+  return range;
+};
+
+
+/**
+ * Gets carets.
+ * @param {boolean} start If true, returns the start caret. Otherwise, get the
+ *     end caret.
+ * @return {Element} The start or end caret in the given document.
+ */
+goog.dom.SavedCaretRange.prototype.getCaret = function(start) {
+  return this.dom_.getElement(start ? this.startCaretId_ : this.endCaretId_);
+};
+
+
+/**
+ * Removes the carets from the current restoration document.
+ * @param {goog.dom.AbstractRange=} opt_range A range whose offsets have already
+ *     been adjusted for caret removal; it will be adjusted if it is also
+ *     affected by post-removal operations, such as text node normalization.
+ * @return {goog.dom.AbstractRange|undefined} The adjusted range, if opt_range
+ *     was provided.
+ */
+goog.dom.SavedCaretRange.prototype.removeCarets = function(opt_range) {
+  goog.dom.removeNode(this.getCaret(true));
+  goog.dom.removeNode(this.getCaret(false));
+  return opt_range;
+};
+
+
+/**
+ * Sets the document where the range will be restored.
+ * @param {!Document} doc An HTML document.
+ */
+goog.dom.SavedCaretRange.prototype.setRestorationDocument = function(doc) {
+  this.dom_.setDocument(doc);
+};
+
+
+/**
+ * Reconstruct the selection from the given saved range. Removes carets after
+ * restoring the selection. If restore does not dispose this saved range, it may
+ * only be restored a second time if innerHTML or some other mechanism is used
+ * to restore the carets to the dom.
+ * @return {goog.dom.AbstractRange?} Restored selection.
+ * @override
+ * @protected
+ */
+goog.dom.SavedCaretRange.prototype.restoreInternal = function() {
+  var range = null;
+  var anchorCaret = this.getCaret(!this.reversed_);
+  var focusCaret = this.getCaret(this.reversed_);
+  if (anchorCaret && focusCaret) {
+    var anchorNode = anchorCaret.parentNode;
+    var anchorOffset = goog.array.indexOf(anchorNode.childNodes, anchorCaret);
+    var focusNode = focusCaret.parentNode;
+    var focusOffset = goog.array.indexOf(focusNode.childNodes, focusCaret);
+    if (focusNode == anchorNode) {
+      // Compensate for the start caret being removed.
+      if (this.reversed_) {
+        anchorOffset--;
+      } else {
+        focusOffset--;
+      }
+    }
+    /** @suppress {missingRequire} circular dependency */
+    range = goog.dom.Range.createFromNodes(anchorNode, anchorOffset,
+                                           focusNode, focusOffset);
+    range = this.removeCarets(range);
+    range.select();
+  } else {
+    // If only one caret was found, remove it.
+    this.removeCarets();
+  }
+  return range;
+};
+
+
+/**
+ * Dispose the saved range and remove the carets from the DOM.
+ * @override
+ * @protected
+ */
+goog.dom.SavedCaretRange.prototype.disposeInternal = function() {
+  this.removeCarets();
+  this.dom_ = null;
+};
+
+
+/**
+ * Creates a caret element.
+ * @param {boolean} start If true, creates the start caret. Otherwise,
+ *     creates the end caret.
+ * @return {!Element} The new caret element.
+ * @private
+ */
+goog.dom.SavedCaretRange.prototype.createCaret_ = function(start) {
+  return this.dom_.createDom(goog.dom.TagName.SPAN,
+      {'id': start ? this.startCaretId_ : this.endCaretId_});
+};
+
+
+/**
+ * A regex that will match all saved range carets in a string.
+ * @type {RegExp}
+ */
+goog.dom.SavedCaretRange.CARET_REGEX = /<span\s+id="?goog_\d+"?><\/span>/ig;
+
+
+/**
+ * Returns whether two strings of html are equal, ignoring any saved carets.
+ * Thus two strings of html whose only difference is the id of their saved
+ * carets will be considered equal, since they represent html with the
+ * same selection.
+ * @param {string} str1 The first string.
+ * @param {string} str2 The second string.
+ * @return {boolean} Whether two strings of html are equal, ignoring any
+ *     saved carets.
+ */
+goog.dom.SavedCaretRange.htmlEqual = function(str1, str2) {
+  return str1 == str2 ||
+      str1.replace(goog.dom.SavedCaretRange.CARET_REGEX, '') ==
+          str2.replace(goog.dom.SavedCaretRange.CARET_REGEX, '');
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/savedrange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/savedrange.js b/externs/GCL/externs/goog/dom/savedrange.js
new file mode 100644
index 0000000..5a7e951
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/savedrange.js
@@ -0,0 +1,74 @@
+// 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 generic interface for saving and restoring ranges.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.SavedRange');
+
+goog.require('goog.Disposable');
+goog.require('goog.log');
+
+
+
+/**
+ * Abstract interface for a saved range.
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+goog.dom.SavedRange = function() {
+  goog.Disposable.call(this);
+};
+goog.inherits(goog.dom.SavedRange, goog.Disposable);
+
+
+/**
+ * Logging object.
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.dom.SavedRange.logger_ =
+    goog.log.getLogger('goog.dom.SavedRange');
+
+
+/**
+ * Restores the range and by default disposes of the saved copy.  Take note:
+ * this means the by default SavedRange objects are single use objects.
+ * @param {boolean=} opt_stayAlive Whether this SavedRange should stay alive
+ *     (not be disposed) after restoring the range. Defaults to false (dispose).
+ * @return {goog.dom.AbstractRange} The restored range.
+ */
+goog.dom.SavedRange.prototype.restore = function(opt_stayAlive) {
+  if (this.isDisposed()) {
+    goog.log.error(goog.dom.SavedRange.logger_,
+        'Disposed SavedRange objects cannot be restored.');
+  }
+
+  var range = this.restoreInternal();
+  if (!opt_stayAlive) {
+    this.dispose();
+  }
+  return range;
+};
+
+
+/**
+ * Internal method to restore the saved range.
+ * @return {goog.dom.AbstractRange} The restored range.
+ */
+goog.dom.SavedRange.prototype.restoreInternal = goog.abstractMethod;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/selection.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/selection.js b/externs/GCL/externs/goog/dom/selection.js
new file mode 100644
index 0000000..4afb4f7
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/selection.js
@@ -0,0 +1,472 @@
+// 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 Utilities for working with selections in input boxes and text
+ * areas.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/dom_selection.html
+ */
+
+
+goog.provide('goog.dom.selection');
+
+goog.require('goog.dom.InputType');
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+/**
+ * Sets the place where the selection should start inside a textarea or a text
+ * input
+ * @param {Element} textfield A textarea or text input.
+ * @param {number} pos The position to set the start of the selection at.
+ */
+goog.dom.selection.setStart = function(textfield, pos) {
+  if (goog.dom.selection.useSelectionProperties_(textfield)) {
+    textfield.selectionStart = pos;
+  } else if (goog.userAgent.IE) {
+    // destructuring assignment would have been sweet
+    var tmp = goog.dom.selection.getRangeIe_(textfield);
+    var range = tmp[0];
+    var selectionRange = tmp[1];
+
+    if (range.inRange(selectionRange)) {
+      pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos);
+
+      range.collapse(true);
+      range.move('character', pos);
+      range.select();
+    }
+  }
+};
+
+
+/**
+ * Return the place where the selection starts inside a textarea or a text
+ * input
+ * @param {Element} textfield A textarea or text input.
+ * @return {number} The position where the selection starts or 0 if it was
+ *     unable to find the position or no selection exists. Note that we can't
+ *     reliably tell the difference between an element that has no selection and
+ *     one where it starts at 0.
+ */
+goog.dom.selection.getStart = function(textfield) {
+  return goog.dom.selection.getEndPoints_(textfield, true)[0];
+};
+
+
+/**
+ * Returns the start and end points of the selection within a textarea in IE.
+ * IE treats newline characters as \r\n characters, and we need to check for
+ * these characters at the edge of our selection, to ensure that we return the
+ * right cursor position.
+ * @param {TextRange} range Complete range object, e.g., "Hello\r\n".
+ * @param {TextRange} selRange Selected range object.
+ * @param {boolean} getOnlyStart Value indicating if only start
+ *     cursor position is to be returned. In IE, obtaining the end position
+ *     involves extra work, hence we have this parameter for calls which need
+ *     only start position.
+ * @return {!Array<number>} An array with the start and end positions where the
+ *     selection starts and ends or [0,0] if it was unable to find the
+ *     positions or no selection exists. Note that we can't reliably tell the
+ *     difference between an element that has no selection and one where
+ *     it starts and ends at 0. If getOnlyStart was true, we return
+ *     -1 as end offset.
+ * @private
+ */
+goog.dom.selection.getEndPointsTextareaIe_ = function(
+    range, selRange, getOnlyStart) {
+  // Create a duplicate of the selected range object to perform our actions
+  // against. Example of selectionRange = "" (assuming that the cursor is
+  // just after the \r\n combination)
+  var selectionRange = selRange.duplicate();
+
+  // Text before the selection start, e.g.,"Hello" (notice how range.text
+  // excludes the \r\n sequence)
+  var beforeSelectionText = range.text;
+  // Text before the selection start, e.g., "Hello" (this will later include
+  // the \r\n sequences also)
+  var untrimmedBeforeSelectionText = beforeSelectionText;
+  // Text within the selection , e.g. "" assuming that the cursor is just after
+  // the \r\n combination.
+  var selectionText = selectionRange.text;
+  // Text within the selection, e.g.,  "" (this will later include the \r\n
+  // sequences also)
+  var untrimmedSelectionText = selectionText;
+
+  // Boolean indicating whether we are done dealing with the text before the
+  // selection's beginning.
+  var isRangeEndTrimmed = false;
+  // Go over the range until it becomes a 0-lengthed range or until the range
+  // text starts changing when we move the end back by one character.
+  // If after moving the end back by one character, the text remains the same,
+  // then we need to add a "\r\n" at the end to get the actual text.
+  while (!isRangeEndTrimmed) {
+    if (range.compareEndPoints('StartToEnd', range) == 0) {
+      isRangeEndTrimmed = true;
+    } else {
+      range.moveEnd('character', -1);
+      if (range.text == beforeSelectionText) {
+        // If the start position of the cursor was after a \r\n string,
+        // we would skip over it in one go with the moveEnd call, but
+        // range.text will still show "Hello" (because of the IE range.text
+        // bug) - this implies that we should add a \r\n to our
+        // untrimmedBeforeSelectionText string.
+        untrimmedBeforeSelectionText += '\r\n';
+      } else {
+        isRangeEndTrimmed = true;
+      }
+    }
+  }
+
+  if (getOnlyStart) {
+    // We return -1 as end, since the caller is only interested in the start
+    // value.
+    return [untrimmedBeforeSelectionText.length, -1];
+  }
+  // Boolean indicating whether we are done dealing with the text inside the
+  // selection.
+  var isSelectionRangeEndTrimmed = false;
+  // Go over the selected range until it becomes a 0-lengthed range or until
+  // the range text starts changing when we move the end back by one character.
+  // If after moving the end back by one character, the text remains the same,
+  // then we need to add a "\r\n" at the end to get the actual text.
+  while (!isSelectionRangeEndTrimmed) {
+    if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) {
+      isSelectionRangeEndTrimmed = true;
+    } else {
+      selectionRange.moveEnd('character', -1);
+      if (selectionRange.text == selectionText) {
+        // If the selection was not empty, and the end point of the selection
+        // was just after a \r\n, we would have skipped it in one go with the
+        // moveEnd call, and this implies that we should add a \r\n to the
+        // untrimmedSelectionText string.
+        untrimmedSelectionText += '\r\n';
+      } else {
+        isSelectionRangeEndTrimmed = true;
+      }
+    }
+  }
+  return [
+    untrimmedBeforeSelectionText.length,
+    untrimmedBeforeSelectionText.length + untrimmedSelectionText.length];
+};
+
+
+/**
+ * Returns the start and end points of the selection inside a textarea or a
+ * text input.
+ * @param {Element} textfield A textarea or text input.
+ * @return {!Array<number>} An array with the start and end positions where the
+ *     selection starts and ends or [0,0] if it was unable to find the
+ *     positions or no selection exists. Note that we can't reliably tell the
+ *     difference between an element that has no selection and one where
+ *     it starts and ends at 0.
+ */
+goog.dom.selection.getEndPoints = function(textfield) {
+  return goog.dom.selection.getEndPoints_(textfield, false);
+};
+
+
+/**
+ * Returns the start and end points of the selection inside a textarea or a
+ * text input.
+ * @param {Element} textfield A textarea or text input.
+ * @param {boolean} getOnlyStart Value indicating if only start
+ *     cursor position is to be returned. In IE, obtaining the end position
+ *     involves extra work, hence we have this parameter. In FF, there is not
+ *     much extra effort involved.
+ * @return {!Array<number>} An array with the start and end positions where the
+ *     selection starts and ends or [0,0] if it was unable to find the
+ *     positions or no selection exists. Note that we can't reliably tell the
+ *     difference between an element that has no selection and one where
+ *     it starts and ends at 0. If getOnlyStart was true, we return
+ *     -1 as end offset.
+ * @private
+ */
+goog.dom.selection.getEndPoints_ = function(textfield, getOnlyStart) {
+  var startPos = 0;
+  var endPos = 0;
+  if (goog.dom.selection.useSelectionProperties_(textfield)) {
+    startPos = textfield.selectionStart;
+    endPos = getOnlyStart ? -1 : textfield.selectionEnd;
+  } else if (goog.userAgent.IE) {
+    var tmp = goog.dom.selection.getRangeIe_(textfield);
+    var range = tmp[0];
+    var selectionRange = tmp[1];
+
+    if (range.inRange(selectionRange)) {
+      range.setEndPoint('EndToStart', selectionRange);
+      if (textfield.type == goog.dom.InputType.TEXTAREA) {
+        return goog.dom.selection.getEndPointsTextareaIe_(
+            range, selectionRange, getOnlyStart);
+      }
+      startPos = range.text.length;
+      if (!getOnlyStart) {
+        endPos = range.text.length + selectionRange.text.length;
+      } else {
+        endPos = -1;  // caller did not ask for end position
+      }
+    }
+  }
+  return [startPos, endPos];
+};
+
+
+/**
+ * Sets the place where the selection should end inside a text area or a text
+ * input
+ * @param {Element} textfield A textarea or text input.
+ * @param {number} pos The position to end the selection at.
+ */
+goog.dom.selection.setEnd = function(textfield, pos) {
+  if (goog.dom.selection.useSelectionProperties_(textfield)) {
+    textfield.selectionEnd = pos;
+  } else if (goog.userAgent.IE) {
+    var tmp = goog.dom.selection.getRangeIe_(textfield);
+    var range = tmp[0];
+    var selectionRange = tmp[1];
+
+    if (range.inRange(selectionRange)) {
+      // Both the current position and the start cursor position need
+      // to be canonicalized to take care of possible \r\n miscounts.
+      pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos);
+      var startCursorPos = goog.dom.selection.canonicalizePositionIe_(
+          textfield, goog.dom.selection.getStart(textfield));
+
+      selectionRange.collapse(true);
+      selectionRange.moveEnd('character', pos - startCursorPos);
+      selectionRange.select();
+    }
+  }
+};
+
+
+/**
+ * Returns the place where the selection ends inside a textarea or a text input
+ * @param {Element} textfield A textarea or text input.
+ * @return {number} The position where the selection ends or 0 if it was
+ *     unable to find the position or no selection exists.
+ */
+goog.dom.selection.getEnd = function(textfield) {
+  return goog.dom.selection.getEndPoints_(textfield, false)[1];
+};
+
+
+/**
+ * Sets the cursor position within a textfield.
+ * @param {Element} textfield A textarea or text input.
+ * @param {number} pos The position within the text field.
+ */
+goog.dom.selection.setCursorPosition = function(textfield, pos) {
+  if (goog.dom.selection.useSelectionProperties_(textfield)) {
+    // Mozilla directly supports this
+    textfield.selectionStart = pos;
+    textfield.selectionEnd = pos;
+
+  } else if (goog.userAgent.IE) {
+    pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos);
+
+    // IE has textranges. A textfield's textrange encompasses the
+    // entire textfield's text by default
+    var sel = textfield.createTextRange();
+
+    sel.collapse(true);
+    sel.move('character', pos);
+    sel.select();
+  }
+};
+
+
+/**
+ * Sets the selected text inside a textarea or a text input
+ * @param {Element} textfield A textarea or text input.
+ * @param {string} text The text to change the selection to.
+ */
+goog.dom.selection.setText = function(textfield, text) {
+  if (goog.dom.selection.useSelectionProperties_(textfield)) {
+    var value = textfield.value;
+    var oldSelectionStart = textfield.selectionStart;
+    var before = value.substr(0, oldSelectionStart);
+    var after = value.substr(textfield.selectionEnd);
+    textfield.value = before + text + after;
+    textfield.selectionStart = oldSelectionStart;
+    textfield.selectionEnd = oldSelectionStart + text.length;
+  } else if (goog.userAgent.IE) {
+    var tmp = goog.dom.selection.getRangeIe_(textfield);
+    var range = tmp[0];
+    var selectionRange = tmp[1];
+
+    if (!range.inRange(selectionRange)) {
+      return;
+    }
+    // When we set the selection text the selection range is collapsed to the
+    // end. We therefore duplicate the current selection so we know where it
+    // started. Once we've set the selection text we move the start of the
+    // selection range to the old start
+    var range2 = selectionRange.duplicate();
+    selectionRange.text = text;
+    selectionRange.setEndPoint('StartToStart', range2);
+    selectionRange.select();
+  } else {
+    throw Error('Cannot set the selection end');
+  }
+};
+
+
+/**
+ * Returns the selected text inside a textarea or a text input
+ * @param {Element} textfield A textarea or text input.
+ * @return {string} The selected text.
+ */
+goog.dom.selection.getText = function(textfield) {
+  if (goog.dom.selection.useSelectionProperties_(textfield)) {
+    var s = textfield.value;
+    return s.substring(textfield.selectionStart, textfield.selectionEnd);
+  }
+
+  if (goog.userAgent.IE) {
+    var tmp = goog.dom.selection.getRangeIe_(textfield);
+    var range = tmp[0];
+    var selectionRange = tmp[1];
+
+    if (!range.inRange(selectionRange)) {
+      return '';
+    } else if (textfield.type == goog.dom.InputType.TEXTAREA) {
+      return goog.dom.selection.getSelectionRangeText_(selectionRange);
+    }
+    return selectionRange.text;
+  }
+
+  throw Error('Cannot get the selection text');
+};
+
+
+/**
+ * Returns the selected text within a textarea in IE.
+ * IE treats newline characters as \r\n characters, and we need to check for
+ * these characters at the edge of our selection, to ensure that we return the
+ * right string.
+ * @param {TextRange} selRange Selected range object.
+ * @return {string} Selected text in the textarea.
+ * @private
+ */
+goog.dom.selection.getSelectionRangeText_ = function(selRange) {
+  // Create a duplicate of the selected range object to perform our actions
+  // against. Suppose the text in the textarea is "Hello\r\nWorld" and the
+  // selection encompasses the "o\r\n" bit, initial selectionRange will be "o"
+  // (assuming that the cursor is just after the \r\n combination)
+  var selectionRange = selRange.duplicate();
+
+  // Text within the selection , e.g. "o" assuming that the cursor is just after
+  // the \r\n combination.
+  var selectionText = selectionRange.text;
+  // Text within the selection, e.g.,  "o" (this will later include the \r\n
+  // sequences also)
+  var untrimmedSelectionText = selectionText;
+
+  // Boolean indicating whether we are done dealing with the text inside the
+  // selection.
+  var isSelectionRangeEndTrimmed = false;
+  // Go over the selected range until it becomes a 0-lengthed range or until
+  // the range text starts changing when we move the end back by one character.
+  // If after moving the end back by one character, the text remains the same,
+  // then we need to add a "\r\n" at the end to get the actual text.
+  while (!isSelectionRangeEndTrimmed) {
+    if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) {
+      isSelectionRangeEndTrimmed = true;
+    } else {
+      selectionRange.moveEnd('character', -1);
+      if (selectionRange.text == selectionText) {
+        // If the selection was not empty, and the end point of the selection
+        // was just after a \r\n, we would have skipped it in one go with the
+        // moveEnd call, and this implies that we should add a \r\n to the
+        // untrimmedSelectionText string.
+        untrimmedSelectionText += '\r\n';
+      } else {
+        isSelectionRangeEndTrimmed = true;
+      }
+    }
+  }
+  return untrimmedSelectionText;
+};
+
+
+/**
+ * Helper function for returning the range for an object as well as the
+ * selection range
+ * @private
+ * @param {Element} el The element to get the range for.
+ * @return {!Array<TextRange>} Range of object and selection range in two
+ *     element array.
+ */
+goog.dom.selection.getRangeIe_ = function(el) {
+  var doc = el.ownerDocument || el.document;
+
+  var selectionRange = doc.selection.createRange();
+  // el.createTextRange() doesn't work on textareas
+  var range;
+
+  if (el.type == goog.dom.InputType.TEXTAREA) {
+    range = doc.body.createTextRange();
+    range.moveToElementText(el);
+  } else {
+    range = el.createTextRange();
+  }
+
+  return [range, selectionRange];
+};
+
+
+/**
+ * Helper function for canonicalizing a position inside a textfield in IE.
+ * Deals with the issue that \r\n counts as 2 characters, but
+ * move('character', n) passes over both characters in one move.
+ * @private
+ * @param {Element} textfield The text element.
+ * @param {number} pos The position desired in that element.
+ * @return {number} The canonicalized position that will work properly with
+ *     move('character', pos).
+ */
+goog.dom.selection.canonicalizePositionIe_ = function(textfield, pos) {
+  if (textfield.type == goog.dom.InputType.TEXTAREA) {
+    // We do this only for textarea because it is the only one which can
+    // have a \r\n (input cannot have this).
+    var value = textfield.value.substring(0, pos);
+    pos = goog.string.canonicalizeNewlines(value).length;
+  }
+  return pos;
+};
+
+
+/**
+ * Helper function to determine whether it's okay to use
+ * selectionStart/selectionEnd.
+ *
+ * @param {Element} el The element to check for.
+ * @return {boolean} Whether it's okay to use the selectionStart and
+ *     selectionEnd properties on {@code el}.
+ * @private
+ */
+goog.dom.selection.useSelectionProperties_ = function(el) {
+  try {
+    return typeof el.selectionStart == 'number';
+  } catch (e) {
+    // Firefox throws an exception if you try to access selectionStart
+    // on an element with display: none.
+    return false;
+  }
+};

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/tagiterator.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/tagiterator.js b/externs/GCL/externs/goog/dom/tagiterator.js
new file mode 100644
index 0000000..4b6354c
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/tagiterator.js
@@ -0,0 +1,360 @@
+// 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 Iterator subclass for DOM tree traversal.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.TagIterator');
+goog.provide('goog.dom.TagWalkType');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.iter.Iterator');
+goog.require('goog.iter.StopIteration');
+
+
+/**
+ * There are three types of token:
+ *  <ol>
+ *    <li>{@code START_TAG} - The beginning of a tag.
+ *    <li>{@code OTHER} - Any non-element node position.
+ *    <li>{@code END_TAG} - The end of a tag.
+ *  </ol>
+ * Users of this enumeration can rely on {@code START_TAG + END_TAG = 0} and
+ * that {@code OTHER = 0}.
+ *
+ * @enum {number}
+ */
+goog.dom.TagWalkType = {
+  START_TAG: 1,
+  OTHER: 0,
+  END_TAG: -1
+};
+
+
+
+/**
+ * A DOM tree traversal iterator.
+ *
+ * Starting with the given node, the iterator walks the DOM in order, reporting
+ * events for the start and end of Elements, and the presence of text nodes. For
+ * example:
+ *
+ * <pre>
+ * &lt;div&gt;1&lt;span&gt;2&lt;/span&gt;3&lt;/div&gt;
+ * </pre>
+ *
+ * Will return the following nodes:
+ *
+ * <code>[div, 1, span, 2, span, 3, div]</code>
+ *
+ * With the following states:
+ *
+ * <code>[START, OTHER, START, OTHER, END, OTHER, END]</code>
+ *
+ * And the following depths
+ *
+ * <code>[1, 1, 2, 2, 1, 1, 0]</code>
+ *
+ * Imagining <code>|</code> represents iterator position, the traversal stops at
+ * each of the following locations:
+ *
+ * <pre>
+ * &lt;div&gt;|1|&lt;span&gt;|2|&lt;/span&gt;|3|&lt;/div&gt;|
+ * </pre>
+ *
+ * The iterator can also be used in reverse mode, which will return the nodes
+ * and states in the opposite order.  The depths will be slightly different
+ * since, like in normal mode, the depth is computed *after* the given node.
+ *
+ * Lastly, it is possible to create an iterator that is unconstrained, meaning
+ * that it will continue iterating until the end of the document instead of
+ * until exiting the start node.
+ *
+ * @param {Node=} opt_node The start node.  If unspecified or null, defaults to
+ *     an empty iterator.
+ * @param {boolean=} opt_reversed Whether to traverse the tree in reverse.
+ * @param {boolean=} opt_unconstrained Whether the iterator is not constrained
+ *     to the starting node and its children.
+ * @param {goog.dom.TagWalkType?=} opt_tagType The type of the position.
+ *     Defaults to the start of the given node for forward iterators, and
+ *     the end of the node for reverse iterators.
+ * @param {number=} opt_depth The starting tree depth.
+ * @constructor
+ * @extends {goog.iter.Iterator<Node>}
+ */
+goog.dom.TagIterator = function(opt_node, opt_reversed,
+    opt_unconstrained, opt_tagType, opt_depth) {
+  /**
+   * Whether the node iterator is moving in reverse.
+   * @type {boolean}
+   */
+  this.reversed = !!opt_reversed;
+
+  /**
+   * The node this position is located on.
+   * @type {Node}
+   */
+  this.node = null;
+
+  /**
+   * The type of this position.
+   * @type {goog.dom.TagWalkType}
+   */
+  this.tagType = goog.dom.TagWalkType.OTHER;
+
+  /**
+   * The tree depth of this position relative to where the iterator started.
+   * The depth is considered to be the tree depth just past the current node,
+   * so if an iterator is at position
+   * <pre>
+   *     <div>|</div>
+   * </pre>
+   * (i.e. the node is the div and the type is START_TAG) its depth will be 1.
+   * @type {number}
+   */
+  this.depth;
+
+  /**
+   * Whether iteration has started.
+   * @private {boolean}
+   */
+  this.started_ = false;
+
+  /**
+   * Whether the iterator is constrained to the starting node and its children.
+   * @type {boolean}
+   */
+  this.constrained = !opt_unconstrained;
+
+  if (opt_node) {
+    this.setPosition(opt_node, opt_tagType);
+  }
+  this.depth = opt_depth != undefined ? opt_depth : this.tagType || 0;
+  if (this.reversed) {
+    this.depth *= -1;
+  }
+};
+goog.inherits(goog.dom.TagIterator, goog.iter.Iterator);
+
+
+/**
+ * Set the position of the iterator.  Overwrite the tree node and the position
+ * type which can be one of the {@link goog.dom.TagWalkType} token types.
+ * Only overwrites the tree depth when the parameter is specified.
+ * @param {Node} node The node to set the position to.
+ * @param {goog.dom.TagWalkType?=} opt_tagType The type of the position
+ *     Defaults to the start of the given node.
+ * @param {number=} opt_depth The tree depth.
+ */
+goog.dom.TagIterator.prototype.setPosition = function(node,
+    opt_tagType, opt_depth) {
+  this.node = node;
+
+  if (node) {
+    if (goog.isNumber(opt_tagType)) {
+      this.tagType = opt_tagType;
+    } else {
+      // Auto-determine the proper type
+      this.tagType = this.node.nodeType != goog.dom.NodeType.ELEMENT ?
+          goog.dom.TagWalkType.OTHER :
+          this.reversed ? goog.dom.TagWalkType.END_TAG :
+          goog.dom.TagWalkType.START_TAG;
+    }
+  }
+
+  if (goog.isNumber(opt_depth)) {
+    this.depth = opt_depth;
+  }
+};
+
+
+/**
+ * Replace this iterator's values with values from another. The two iterators
+ * must be of the same type.
+ * @param {goog.dom.TagIterator} other The iterator to copy.
+ * @protected
+ */
+goog.dom.TagIterator.prototype.copyFrom = function(other) {
+  this.node = other.node;
+  this.tagType = other.tagType;
+  this.depth = other.depth;
+  this.reversed = other.reversed;
+  this.constrained = other.constrained;
+};
+
+
+/**
+ * @return {!goog.dom.TagIterator} A copy of this iterator.
+ */
+goog.dom.TagIterator.prototype.clone = function() {
+  return new goog.dom.TagIterator(this.node, this.reversed,
+      !this.constrained, this.tagType, this.depth);
+};
+
+
+/**
+ * Skip the current tag.
+ */
+goog.dom.TagIterator.prototype.skipTag = function() {
+  var check = this.reversed ? goog.dom.TagWalkType.END_TAG :
+              goog.dom.TagWalkType.START_TAG;
+  if (this.tagType == check) {
+    this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1);
+    this.depth += this.tagType * (this.reversed ? -1 : 1);
+  }
+};
+
+
+/**
+ * Restart the current tag.
+ */
+goog.dom.TagIterator.prototype.restartTag = function() {
+  var check = this.reversed ? goog.dom.TagWalkType.START_TAG :
+              goog.dom.TagWalkType.END_TAG;
+  if (this.tagType == check) {
+    this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1);
+    this.depth += this.tagType * (this.reversed ? -1 : 1);
+  }
+};
+
+
+/**
+ * Move to the next position in the DOM tree.
+ * @return {Node} Returns the next node, or throws a goog.iter.StopIteration
+ *     exception if the end of the iterator's range has been reached.
+ * @override
+ */
+goog.dom.TagIterator.prototype.next = function() {
+  var node;
+
+  if (this.started_) {
+    if (!this.node || this.constrained && this.depth == 0) {
+      throw goog.iter.StopIteration;
+    }
+    node = this.node;
+
+    var startType = this.reversed ? goog.dom.TagWalkType.END_TAG :
+        goog.dom.TagWalkType.START_TAG;
+
+    if (this.tagType == startType) {
+      // If we have entered the tag, test if there are any children to move to.
+      var child = this.reversed ? node.lastChild : node.firstChild;
+      if (child) {
+        this.setPosition(child);
+      } else {
+        // If not, move on to exiting this tag.
+        this.setPosition(node,
+            /** @type {goog.dom.TagWalkType} */ (startType * -1));
+      }
+    } else {
+      var sibling = this.reversed ? node.previousSibling : node.nextSibling;
+      if (sibling) {
+        // Try to move to the next node.
+        this.setPosition(sibling);
+      } else {
+        // If no such node exists, exit our parent.
+        this.setPosition(node.parentNode,
+            /** @type {goog.dom.TagWalkType} */ (startType * -1));
+      }
+    }
+
+    this.depth += this.tagType * (this.reversed ? -1 : 1);
+  } else {
+    this.started_ = true;
+  }
+
+  // Check the new position for being last, and return it if it's not.
+  node = this.node;
+  if (!this.node) {
+    throw goog.iter.StopIteration;
+  }
+  return node;
+};
+
+
+/**
+ * @return {boolean} Whether next has ever been called on this iterator.
+ * @protected
+ */
+goog.dom.TagIterator.prototype.isStarted = function() {
+  return this.started_;
+};
+
+
+/**
+ * @return {boolean} Whether this iterator's position is a start tag position.
+ */
+goog.dom.TagIterator.prototype.isStartTag = function() {
+  return this.tagType == goog.dom.TagWalkType.START_TAG;
+};
+
+
+/**
+ * @return {boolean} Whether this iterator's position is an end tag position.
+ */
+goog.dom.TagIterator.prototype.isEndTag = function() {
+  return this.tagType == goog.dom.TagWalkType.END_TAG;
+};
+
+
+/**
+ * @return {boolean} Whether this iterator's position is not at an element node.
+ */
+goog.dom.TagIterator.prototype.isNonElement = function() {
+  return this.tagType == goog.dom.TagWalkType.OTHER;
+};
+
+
+/**
+ * Test if two iterators are at the same position - i.e. if the node and tagType
+ * is the same.  This will still return true if the two iterators are moving in
+ * opposite directions or have different constraints.
+ * @param {goog.dom.TagIterator} other The iterator to compare to.
+ * @return {boolean} Whether the two iterators are at the same position.
+ */
+goog.dom.TagIterator.prototype.equals = function(other) {
+  // Nodes must be equal, and we must either have reached the end of our tree
+  // or be at the same position.
+  return other.node == this.node && (!this.node ||
+      other.tagType == this.tagType);
+};
+
+
+/**
+ * Replace the current node with the list of nodes. Reset the iterator so that
+ * it visits the first of the nodes next.
+ * @param {...Object} var_args A list of nodes to replace the current node with.
+ *     If the first argument is array-like, it will be used, otherwise all the
+ *     arguments are assumed to be nodes.
+ */
+goog.dom.TagIterator.prototype.splice = function(var_args) {
+  // Reset the iterator so that it iterates over the first replacement node in
+  // the arguments on the next iteration.
+  var node = this.node;
+  this.restartTag();
+  this.reversed = !this.reversed;
+  goog.dom.TagIterator.prototype.next.call(this);
+  this.reversed = !this.reversed;
+
+  // Replace the node with the arguments.
+  var arr = goog.isArrayLike(arguments[0]) ? arguments[0] : arguments;
+  for (var i = arr.length - 1; i >= 0; i--) {
+    goog.dom.insertSiblingAfter(arr[i], node);
+  }
+  goog.dom.removeNode(node);
+};