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:16 UTC
[01/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Repository: flex-falcon
Updated Branches:
refs/heads/JsToAs bb6425450 -> e2cad6e69
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/currency.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/currency.js b/externs/GCL/externs/goog/i18n/currency.js
new file mode 100644
index 0000000..6396efd
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/currency.js
@@ -0,0 +1,437 @@
+// Copyright 2009 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 utility to get better currency format pattern.
+ *
+ * This module implements a new currency format representation model. It
+ * provides 3 currency representation forms: global, portable and local. Local
+ * format is the most popular format people use to represent currency in its
+ * circulating country without worrying about how it should be distinguished
+ * from other currencies. Global format is a formal representation in context
+ * of multiple currencies in same page, it is ISO 4217 currency code. Portable
+ * format is a compromise between global and local. It looks similar to how
+ * people would like to see how their currency is being represented in other
+ * media. While at the same time, it should be distinguishable to world's
+ * popular currencies (like USD, EUR) and currencies somewhat relevant in the
+ * area (like CNY in HK, though native currency is HKD). There is no guarantee
+ * of uniqueness.
+ *
+ */
+
+
+goog.provide('goog.i18n.currency');
+goog.provide('goog.i18n.currency.CurrencyInfo');
+goog.provide('goog.i18n.currency.CurrencyInfoTier2');
+
+
+/**
+ * The mask of precision field.
+ * @private
+ */
+goog.i18n.currency.PRECISION_MASK_ = 0x07;
+
+
+/**
+ * Whether the currency sign should be positioned after the number.
+ * @private
+ */
+goog.i18n.currency.POSITION_FLAG_ = 0x10;
+
+
+/**
+ * Whether a space should be inserted between the number and currency sign.
+ * @private
+ */
+goog.i18n.currency.SPACE_FLAG_ = 0x20;
+
+
+/**
+ * Whether tier2 was enabled already by calling addTier2Support().
+ * @private
+ */
+goog.i18n.currency.tier2Enabled_ = false;
+
+
+/**
+ * This function will add tier2 currency support. Be default, only tier1
+ * (most popular currencies) are supported. If an application really needs
+ * to support some of the rarely used currencies, it should call this function
+ * before any other functions in this namespace.
+ */
+goog.i18n.currency.addTier2Support = function() {
+ // Protection from executing this these again and again.
+ if (!goog.i18n.currency.tier2Enabled_) {
+ for (var key in goog.i18n.currency.CurrencyInfoTier2) {
+ goog.i18n.currency.CurrencyInfo[key] =
+ goog.i18n.currency.CurrencyInfoTier2[key];
+ }
+ goog.i18n.currency.tier2Enabled_ = true;
+ }
+};
+
+
+/**
+ * Global currency pattern always uses ISO-4217 currency code as prefix. Local
+ * currency sign is added if it is different from currency code. Each currency
+ * is unique in this form. The negative side is that ISO code looks weird in
+ * some countries as people normally do not use it. Local currency sign
+ * alleviates the problem, but also makes it a little verbose.
+ *
+ * @param {string} currencyCode ISO-4217 3-letter currency code.
+ * @return {string} Global currency pattern string for given currency.
+ */
+goog.i18n.currency.getGlobalCurrencyPattern = function(currencyCode) {
+ var info = goog.i18n.currency.CurrencyInfo[currencyCode];
+ var patternNum = info[0];
+ if (currencyCode == info[1]) {
+ return goog.i18n.currency.getCurrencyPattern_(patternNum, info[1]);
+ }
+ return currencyCode + ' ' +
+ goog.i18n.currency.getCurrencyPattern_(patternNum, info[1]);
+};
+
+
+/**
+ * Return global currency sign string for those applications
+ * that want to handle currency sign themselves.
+ *
+ * @param {string} currencyCode ISO-4217 3-letter currency code.
+ * @return {string} Global currency sign for given currency.
+ */
+goog.i18n.currency.getGlobalCurrencySign = function(currencyCode) {
+ var info = goog.i18n.currency.CurrencyInfo[currencyCode];
+ return (currencyCode == info[1]) ? currencyCode :
+ currencyCode + ' ' + info[1];
+};
+
+
+/**
+ * Local currency pattern is the most frequently used pattern in currency's
+ * native region. It does not care about how it is distinguished from other
+ * currencies.
+ *
+ * @param {string} currencyCode ISO-4217 3-letter currency code.
+ * @return {string} Local currency pattern string for given currency.
+ */
+goog.i18n.currency.getLocalCurrencyPattern = function(currencyCode) {
+ var info = goog.i18n.currency.CurrencyInfo[currencyCode];
+ return goog.i18n.currency.getCurrencyPattern_(info[0], info[1]);
+};
+
+
+/**
+ * Returns local currency sign string for those applications that need to
+ * handle currency sign separately.
+ *
+ * @param {string} currencyCode ISO-4217 3-letter currency code.
+ * @return {string} Local currency sign for given currency.
+ */
+goog.i18n.currency.getLocalCurrencySign = function(currencyCode) {
+ return goog.i18n.currency.CurrencyInfo[currencyCode][1];
+};
+
+
+/**
+ * Portable currency pattern is a compromise between local and global. It is
+ * not a mere blend or mid-way between the two. Currency sign is chosen so that
+ * it looks familiar to native users. It also has enough information to
+ * distinguish itself from other popular currencies in its native region.
+ * In this pattern, currency sign symbols that has availability problem in
+ * popular fonts are also avoided.
+ *
+ * @param {string} currencyCode ISO-4217 3-letter currency code.
+ * @return {string} Portable currency pattern string for given currency.
+ */
+goog.i18n.currency.getPortableCurrencyPattern = function(currencyCode) {
+ var info = goog.i18n.currency.CurrencyInfo[currencyCode];
+ return goog.i18n.currency.getCurrencyPattern_(info[0], info[2]);
+};
+
+
+/**
+ * Return portable currency sign string for those applications that need to
+ * handle currency sign themselves.
+ *
+ * @param {string} currencyCode ISO-4217 3-letter currency code.
+ * @return {string} Portable currency sign for given currency.
+ */
+goog.i18n.currency.getPortableCurrencySign = function(currencyCode) {
+ return goog.i18n.currency.CurrencyInfo[currencyCode][2];
+};
+
+
+/**
+ * This function returns the default currency sign position. Some applications
+ * may want to handle currency sign and currency amount separately. This
+ * function can be used in such situations to correctly position the currency
+ * sign relative to the amount.
+ *
+ * To match the behavior of ICU, position is not determined by display locale.
+ *
+ * @param {string} currencyCode ISO-4217 3-letter currency code.
+ * @return {boolean} true if currency should be positioned before amount field.
+ */
+goog.i18n.currency.isPrefixSignPosition = function(currencyCode) {
+ return (goog.i18n.currency.CurrencyInfo[currencyCode][0] &
+ goog.i18n.currency.POSITION_FLAG_) == 0;
+};
+
+
+/**
+ * This function constructs the currency pattern. Currency sign is provided. The
+ * pattern information is encoded in patternNum.
+ *
+ * @param {number} patternNum Encoded pattern number that has
+ * currency pattern information.
+ * @param {string} sign The currency sign that will be used in pattern.
+ * @return {string} currency pattern string.
+ * @private
+ */
+goog.i18n.currency.getCurrencyPattern_ = function(patternNum, sign) {
+ var strParts = ['#,##0'];
+ var precision = patternNum & goog.i18n.currency.PRECISION_MASK_;
+ if (precision > 0) {
+ strParts.push('.');
+ for (var i = 0; i < precision; i++) {
+ strParts.push('0');
+ }
+ }
+ if ((patternNum & goog.i18n.currency.POSITION_FLAG_) == 0) {
+ strParts.unshift((patternNum & goog.i18n.currency.SPACE_FLAG_) ?
+ "' " : "'");
+ strParts.unshift(sign);
+ strParts.unshift("'");
+ } else {
+ strParts.push((patternNum & goog.i18n.currency.SPACE_FLAG_) ? " '" : "'",
+ sign, "'");
+ }
+ return strParts.join('');
+};
+
+
+/**
+ * Modify currency pattern string by adjusting precision for given currency.
+ * Standard currency pattern will have 2 digit after decimal point.
+ * Examples:
+ * $#,##0.00 -> $#,##0 (precision == 0)
+ * $#,##0.00 -> $#,##0.0 (precision == 1)
+ * $#,##0.00 -> $#,##0.000 (precision == 3)
+ *
+ * @param {string} pattern currency pattern string.
+ * @param {string} currencyCode 3-letter currency code.
+ * @return {string} modified currency pattern string.
+ */
+goog.i18n.currency.adjustPrecision = function(pattern, currencyCode) {
+ var strParts = ['0'];
+ var info = goog.i18n.currency.CurrencyInfo[currencyCode];
+ var precision = info[0] & goog.i18n.currency.PRECISION_MASK_;
+ if (precision > 0) {
+ strParts.push('.');
+ for (var i = 0; i < precision; i++) {
+ strParts.push('0');
+ }
+ }
+ return pattern.replace(/0.00/g, strParts.join(''));
+};
+
+
+/**
+ * Tier 1 currency information.
+ *
+ * The first number in the array is a combination of the precision mask and
+ * other flags. The precision mask indicates how many decimal places to show for
+ * the currency. Valid values are [0..7]. The position flag indicates whether
+ * the currency sign should be positioned after the number. Valid values are 0
+ * (before the number) or 16 (after the number). The space flag indicates
+ * whether a space should be inserted between the currency sign and number.
+ * Valid values are 0 (no space) and 32 (space).
+ *
+ * The number in the array is calculated by adding together the mask and flag
+ * values. For example:
+ *
+ * 0: no precision (0), currency sign first (0), no space (0)
+ * 2: two decimals precision (2), currency sign first (0), no space (0)
+ * 18: two decimals precision (2), currency sign last (16), no space (0)
+ * 50: two decimals precision (2), currency sign last (16), space (32)
+ *
+ * @const {!Object<!Array<?>>}
+ */
+goog.i18n.currency.CurrencyInfo = {
+ 'AED': [2, 'dh', '\u062f.\u0625.', 'DH'],
+ 'ALL': [0, 'Lek', 'Lek'],
+ 'AUD': [2, '$', 'AU$'],
+ 'BDT': [2, '\u09F3', 'Tk'],
+ 'BGN': [2, 'lev', 'lev'],
+ 'BRL': [2, 'R$', 'R$'],
+ 'CAD': [2, '$', 'C$'],
+ 'CDF': [2, 'FrCD', 'CDF'],
+ 'CHF': [2, 'CHF', 'CHF'],
+ 'CLP': [0, '$', 'CL$'],
+ 'CNY': [2, '¥', 'RMB¥'],
+ 'COP': [0, '$', 'COL$'],
+ 'CRC': [0, '\u20a1', 'CR\u20a1'],
+ 'CZK': [50, 'K\u010d', 'K\u010d'],
+ 'DKK': [18, 'kr', 'kr'],
+ 'DOP': [2, '$', 'RD$'],
+ 'EGP': [2, '£', 'LE'],
+ 'ETB': [2, 'Birr', 'Birr'],
+ 'EUR': [2, '€', '€'],
+ 'GBP': [2, '£', 'GB£'],
+ 'HKD': [2, '$', 'HK$'],
+ 'HRK': [2, 'kn', 'kn'],
+ 'HUF': [0, 'Ft', 'Ft'],
+ 'IDR': [0, 'Rp', 'Rp'],
+ 'ILS': [2, '\u20AA', 'IL\u20AA'],
+ 'INR': [2, '\u20B9', 'Rs'],
+ 'IRR': [0, 'Rial', 'IRR'],
+ 'ISK': [0, 'kr', 'kr'],
+ 'JMD': [2, '$', 'JA$'],
+ 'JPY': [0, '¥', 'JP¥'],
+ 'KRW': [0, '\u20A9', 'KR₩'],
+ 'LKR': [2, 'Rs', 'SLRs'],
+ 'LTL': [2, 'Lt', 'Lt'],
+ 'MNT': [0, '\u20AE', 'MN₮'],
+ 'MVR': [2, 'Rf', 'MVR'],
+ 'MXN': [2, '$', 'Mex$'],
+ 'MYR': [2, 'RM', 'RM'],
+ 'NOK': [50, 'kr', 'NOkr'],
+ 'PAB': [2, 'B/.', 'B/.'],
+ 'PEN': [2, 'S/.', 'S/.'],
+ 'PHP': [2, '\u20B1', 'Php'],
+ 'PKR': [0, 'Rs', 'PKRs.'],
+ 'PLN': [50, 'z\u0142', 'z\u0142'],
+ 'RON': [2, 'RON', 'RON'],
+ 'RSD': [0, 'din', 'RSD'],
+ 'RUB': [50, 'руб.', 'руб.'],
+ 'SAR': [2, 'Rial', 'Rial'],
+ 'SEK': [2, 'kr', 'kr'],
+ 'SGD': [2, '$', 'S$'],
+ 'THB': [2, '\u0e3f', 'THB'],
+ 'TRY': [2, 'TL', 'YTL'],
+ 'TWD': [2, 'NT$', 'NT$'],
+ 'TZS': [0, 'TSh', 'TSh'],
+ 'UAH': [2, '\u20B4', 'UAH'],
+ 'USD': [2, '$', 'US$'],
+ 'UYU': [2, '$', '$U'],
+ 'VND': [0, '\u20AB', 'VN\u20AB'],
+ 'YER': [0, 'Rial', 'Rial'],
+ 'ZAR': [2, 'R', 'ZAR']
+};
+
+
+/**
+ * Tier 2 currency information.
+ * @const {!Object<!Array<?>>}
+ */
+goog.i18n.currency.CurrencyInfoTier2 = {
+ 'AFN': [48, 'Af.', 'AFN'],
+ 'AMD': [0, 'Dram', 'dram'],
+ 'ANG': [2, 'NAf.', 'ANG'],
+ 'AOA': [2, 'Kz', 'Kz'],
+ 'ARS': [2, '$', 'AR$'],
+ 'AWG': [2, 'Afl.', 'Afl.'],
+ 'AZN': [2, 'man.', 'man.'],
+ 'BAM': [2, 'KM', 'KM'],
+ 'BBD': [2, '$', 'Bds$'],
+ 'BHD': [3, 'din', 'din'],
+ 'BIF': [0, 'FBu', 'FBu'],
+ 'BMD': [2, '$', 'BD$'],
+ 'BND': [2, '$', 'B$'],
+ 'BOB': [2, 'Bs', 'Bs'],
+ 'BSD': [2, '$', 'BS$'],
+ 'BTN': [2, 'Nu.', 'Nu.'],
+ 'BWP': [2, 'P', 'pula'],
+ 'BYR': [0, 'BYR', 'BYR'],
+ 'BZD': [2, '$', 'BZ$'],
+ 'CUC': [1, '$', 'CUC$'],
+ 'CUP': [2, '$', 'CU$'],
+ 'CVE': [2, 'CVE', 'Esc'],
+ 'DJF': [0, 'Fdj', 'Fdj'],
+ 'DZD': [2, 'din', 'din'],
+ 'ERN': [2, 'Nfk', 'Nfk'],
+ 'FJD': [2, '$', 'FJ$'],
+ 'FKP': [2, '£', 'FK£'],
+ 'GEL': [2, 'GEL', 'GEL'],
+ 'GHS': [2, 'GHS', 'GHS'],
+ 'GIP': [2, '£', 'GI£'],
+ 'GMD': [2, 'GMD', 'GMD'],
+ 'GNF': [0, 'FG', 'FG'],
+ 'GTQ': [2, 'Q', 'GTQ'],
+ 'GYD': [0, '$', 'GY$'],
+ 'HNL': [2, 'L', 'HNL'],
+ 'HTG': [2, 'HTG', 'HTG'],
+ 'IQD': [0, 'din', 'IQD'],
+ 'JOD': [3, 'din', 'JOD'],
+ 'KES': [2, 'Ksh', 'Ksh'],
+ 'KGS': [2, 'KGS', 'KGS'],
+ 'KHR': [2, 'Riel', 'KHR'],
+ 'KMF': [0, 'CF', 'KMF'],
+ 'KPW': [0, '\u20A9KP', 'KPW'],
+ 'KWD': [3, 'din', 'KWD'],
+ 'KYD': [2, '$', 'KY$'],
+ 'KZT': [2, '\u20B8', 'KZT'],
+ 'LAK': [0, '\u20AD', '\u20AD'],
+ 'LBP': [0, 'L£', 'LBP'],
+ 'LRD': [2, '$', 'L$'],
+ 'LSL': [2, 'LSL', 'LSL'],
+ 'LYD': [3, 'din', 'LD'],
+ 'MAD': [2, 'dh', 'MAD'],
+ 'MDL': [2, 'MDL', 'MDL'],
+ 'MGA': [0, 'Ar', 'MGA'],
+ 'MKD': [2, 'din', 'MKD'],
+ 'MMK': [0, 'K', 'MMK'],
+ 'MOP': [2, 'MOP', 'MOP$'],
+ 'MRO': [0, 'MRO', 'MRO'],
+ 'MUR': [0, 'MURs', 'MURs'],
+ 'MWK': [2, 'MWK', 'MWK'],
+ 'MZN': [2, 'MTn', 'MTn'],
+ 'NAD': [2, '$', 'N$'],
+ 'NGN': [2, '\u20A6', 'NG\u20A6'],
+ 'NIO': [2, 'C$', 'C$'],
+ 'NPR': [2, 'Rs', 'NPRs'],
+ 'NZD': [2, '$', 'NZ$'],
+ 'OMR': [3, 'Rial', 'OMR'],
+ 'PGK': [2, 'PGK', 'PGK'],
+ 'PYG': [0, 'Gs', 'PYG'],
+ 'QAR': [2, 'Rial', 'QR'],
+ 'RWF': [0, 'RF', 'RF'],
+ 'SBD': [2, '$', 'SI$'],
+ 'SCR': [2, 'SCR', 'SCR'],
+ 'SDG': [2, 'SDG', 'SDG'],
+ 'SHP': [2, '£', 'SH£'],
+ 'SLL': [0, 'SLL', 'SLL'],
+ 'SOS': [0, 'SOS', 'SOS'],
+ 'SRD': [2, '$', 'SR$'],
+ 'SSP': [2, '£', 'SSP'],
+ 'STD': [0, 'Db', 'Db'],
+ 'SYP': [0, '£', 'SY£'],
+ 'SZL': [2, 'SZL', 'SZL'],
+ 'TJS': [2, 'Som', 'TJS'],
+ 'TND': [3, 'din', 'DT'],
+ 'TOP': [2, 'T$', 'T$'],
+ 'TTD': [2, '$', 'TT$'],
+ 'UGX': [0, 'UGX', 'UGX'],
+ 'UZS': [0, 'so\u02bcm', 'UZS'],
+ 'VEF': [2, 'Bs', 'Bs'],
+ 'VUV': [0, 'VUV', 'VUV'],
+ 'WST': [2, 'WST', 'WST'],
+ 'XAF': [0, 'FCFA', 'FCFA'],
+ 'XCD': [2, '$', 'EC$'],
+ 'XOF': [0, 'CFA', 'CFA'],
+ 'XPF': [0, 'FCFP', 'FCFP'],
+ 'ZMW': [0, 'ZMW', 'ZMW'],
+ 'ZWD': [0, '$', 'Z$']
+};
[02/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/compactnumberformatsymbols_ext.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/compactnumberformatsymbols_ext.js b/externs/GCL/externs/goog/i18n/compactnumberformatsymbols_ext.js
new file mode 100644
index 0000000..c4c49c6
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/compactnumberformatsymbols_ext.js
@@ -0,0 +1,27778 @@
+// 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 Compact number formatting symbols.
+ *
+ * This file is autogenerated by script:
+ * http://go/generate_number_constants.py
+ * using the --for_closure flag.
+ * File generated from CLDR ver. 27.0.1
+ *
+ * This file coveres those locales that are not covered in
+ * "compactnumberformatsymbols.js".
+ *
+ * Before checkin, this file could have been manually edited. This is
+ * to incorporate changes before we could fix CLDR. All manual
+ * modification must be documented in this section, and should be
+ * removed after those changes land to CLDR.
+ */
+
+goog.provide('goog.i18n.CompactNumberFormatSymbolsExt');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_af_NA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_agq');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_agq_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ak');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ak_GH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_AE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_BH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_DJ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_DZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_EH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_ER');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_IL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_IQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_JO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_KM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_KW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_LB');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_LY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_MA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_MR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_OM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_PS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_QA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_TD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_TN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_YE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_as');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_as_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_asa');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_asa_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ast');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ast_ES');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Cyrl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Cyrl_AZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bas');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bas_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_be');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_be_BY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bem');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bem_ZM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bez');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bez_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bm');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bm_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bm_Latn_ML');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bn_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bo_CN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bo_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_brx');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_brx_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bs');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Cyrl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Cyrl_BA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Latn_BA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_cgg');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_cgg_UG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Arab');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_IQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_IR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Latn_IQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dav');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dav_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_de_LI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dje');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dje_NE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dsb');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dsb_DE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dua');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dua_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dyo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dyo_SN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dz');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_dz_BT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ebu');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ebu_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ee');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ee_GH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ee_TG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_150');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BB');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CX');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_DM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ER');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_FJ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_FK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_HK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_JE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_JM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_LC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_LR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_LS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_RW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SB');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SX');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TV');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_UG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_WS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ZM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_eo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_eo_001');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_AR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_BO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_DO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_EC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_GQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_GT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_HN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_MX');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_NI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_SV');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_US');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_UY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_VE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ewo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ewo_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fa_AF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ff');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_GN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_MR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_SN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fo_FO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BJ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_DJ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_DZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_HT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_KM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_LU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_ML');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_NC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_NE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_PF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_RW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_SC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_SN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_SY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_TD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_TG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_TN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_VU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_WF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fur');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fur_IT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fy');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fy_NL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gd');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gd_GB');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw_FR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_guz');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_guz_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gv');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gv_IM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ha');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn_GH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn_NE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn_NG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hr_BA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hsb');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hsb_DE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ig');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ig_NG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ii');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ii_CN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_it_CH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_jgo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_jgo_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_jmc');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_jmc_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kab');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kab_DZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kam');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kam_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kde');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kde_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kea');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kea_CV');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_khq');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_khq_ML');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ki');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ki_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kkj');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kkj_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kl_GL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kln');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kln_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ko_KP');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kok');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kok_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ks');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ks_Arab');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ks_Arab_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ksb');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ksb_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ksf');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ksf_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ksh');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ksh_DE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kw');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kw_GB');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lag');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lag_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lb');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lb_LU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lg');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lg_UG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lkt');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lkt_US');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_AO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_CF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_CG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lu');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lu_CD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_luo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_luo_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_luy');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_luy_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mas');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mas_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mas_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mer');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mer_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mfe');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mfe_MU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mg');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mg_MG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mgh');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mgh_MZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mgo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mgo_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn_BN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn_SG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mua');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mua_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_naq');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_naq_NA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nd');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nd_ZW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ne_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_AW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_BE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_BQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_CW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_SR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_SX');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nmg');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nmg_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nn_NO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nnh');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nnh_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nus');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nus_SD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nyn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nyn_UG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_om');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_om_ET');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_om_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_os');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_os_GE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_os_RU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Arab');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Arab_PK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ps');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ps_AF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_AO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_CV');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_GW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_MO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_MZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_ST');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_TL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_qu');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_qu_BO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_qu_EC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_qu_PE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rm');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rm_CH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rn_BI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ro_MD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rof');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rof_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_BY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_KG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_KZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_MD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_UA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rw');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rw_RW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rwk');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_rwk_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sah');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sah_RU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_saq');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_saq_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sbp');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sbp_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_se');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_se_FI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_se_NO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_se_SE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_seh');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_seh_MZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ses');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ses_ML');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sg');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sg_CF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_shi');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Latn_MA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Tfng');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Tfng_MA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_smn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_smn_FI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sn_ZW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_so');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_so_DJ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_so_ET');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_so_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_so_SO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sq_MK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sq_XK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_BA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_ME');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_XK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_BA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_ME');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_RS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_XK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sv_AX');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sv_FI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sw_CD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sw_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sw_UG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_LK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_MY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_SG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_teo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_teo_KE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_teo_UG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ti');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ti_ER');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ti_ET');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_to');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_to_TO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_tr_CY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_twq');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_twq_NE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_tzm');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_tzm_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_tzm_Latn_MA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ug');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ug_Arab');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ug_Arab_CN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ur_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Arab');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Arab_AF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Cyrl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Cyrl_UZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vai');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Latn_LR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Vaii');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Vaii_LR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vun');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vun_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_wae');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_wae_CH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_xog');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_xog_UG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_yav');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_yav_CM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_yi');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_yi_001');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_yo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_yo_BJ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_yo_NG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zgh');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zgh_MA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_HK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_MO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_SG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant_HK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant_MO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant_TW');
+
+
+/**
+ * Compact number formatting symbols for locale af_NA.
+ */
+goog.i18n.CompactNumberFormatSymbols_af_NA = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0'
+ },
+ '10000': {
+ 'other': '0'
+ },
+ '100000': {
+ 'other': '0'
+ },
+ '1000000': {
+ 'other': '0\u00A0m'
+ },
+ '10000000': {
+ 'other': '00\u00A0m'
+ },
+ '100000000': {
+ 'other': '000\u00A0m'
+ },
+ '1000000000': {
+ 'other': '0\u00A0mjd'
+ },
+ '10000000000': {
+ 'other': '00\u00A0mjd'
+ },
+ '100000000000': {
+ 'other': '000\u00A0mjd'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0bn'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0bn'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0bn'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 duisend'
+ },
+ '10000': {
+ 'other': '00 duisend'
+ },
+ '100000': {
+ 'other': '000 duisend'
+ },
+ '1000000': {
+ 'other': '0 miljoen'
+ },
+ '10000000': {
+ 'other': '00 miljoen'
+ },
+ '100000000': {
+ 'other': '000 miljoen'
+ },
+ '1000000000': {
+ 'other': '0 miljard'
+ },
+ '10000000000': {
+ 'other': '00 miljard'
+ },
+ '100000000000': {
+ 'other': '000 miljard'
+ },
+ '1000000000000': {
+ 'other': '0 biljoen'
+ },
+ '10000000000000': {
+ 'other': '00 biljoen'
+ },
+ '100000000000000': {
+ 'other': '000 biljoen'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale agq.
+ */
+goog.i18n.CompactNumberFormatSymbols_agq = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale agq_CM.
+ */
+goog.i18n.CompactNumberFormatSymbols_agq_CM =
+ goog.i18n.CompactNumberFormatSymbols_agq;
+
+
+/**
+ * Compact number formatting symbols for locale ak.
+ */
+goog.i18n.CompactNumberFormatSymbols_ak = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ak_GH.
+ */
+goog.i18n.CompactNumberFormatSymbols_ak_GH =
+ goog.i18n.CompactNumberFormatSymbols_ak;
+
+
+/**
+ * Compact number formatting symbols for locale ar_AE.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_AE = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_BH.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_BH = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_DJ.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_DJ = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_DZ.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_DZ = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_EH.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_EH = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_ER.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_ER = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_IL.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_IL = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_IQ.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_IQ = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_JO.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_JO = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_KM.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_KM = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_KW.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_KW = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_LB.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_LB = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_LY.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_LY = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_MA.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_MA = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_MR.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_MR = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_OM.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_OM = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_PS.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_PS = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_QA.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_QA = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_SA.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_SA = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_SD.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_SD = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_SO.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_SO = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_SS.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_SS = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_SY.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_SY = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_TD.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_TD = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_TN.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_TN = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_YE.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_YE = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other':
<TRUNCATED>
[50/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/GCL-compile-config.xml
----------------------------------------------------------------------
diff --git a/externs/GCL/GCL-compile-config.xml b/externs/GCL/GCL-compile-config.xml
new file mode 100644
index 0000000..76c85a6
--- /dev/null
+++ b/externs/GCL/GCL-compile-config.xml
@@ -0,0 +1,901 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License</name></exclude> 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.
+
+-->
+<flex-config>
+
+ <as-root>out/as</as-root>
+
+ <compiler>
+ <accessible>true</accessible>
+
+ <locale/>
+
+ <source-path>
+ <path-element>src</path-element>
+ </source-path>
+
+ <warn-no-constructor>false</warn-no-constructor>
+ </compiler>
+
+ <external>
+ <!--<path-element>externs/goog/base.js</path-element>
+ <path-element>externs/goog/a11y/aria/announcer.js</path-element>
+ <path-element>externs/goog/a11y/aria/aria.js</path-element>
+ <path-element>externs/goog/a11y/aria/attributes.js</path-element>
+ <path-element>externs/goog/a11y/aria/datatables.js</path-element>
+ <path-element>externs/goog/a11y/aria/roles.js</path-element>
+ <path-element>externs/goog/array/array.js</path-element>
+ <path-element>externs/goog/asserts/asserts.js</path-element>
+ <path-element>externs/goog/async/animationdelay.js</path-element>
+ <path-element>externs/goog/async/conditionaldelay.js</path-element>
+ <path-element>externs/goog/async/delay.js</path-element>
+ <path-element>externs/goog/async/freelist.js</path-element>
+ <path-element>externs/goog/async/nexttick.js</path-element>
+ <path-element>externs/goog/async/run.js</path-element>
+ <path-element>externs/goog/async/throttle.js</path-element>
+ <path-element>externs/goog/async/workqueue.js</path-element>
+ <path-element>externs/goog/bootstrap/nodejs.js</path-element>
+ <path-element>externs/goog/bootstrap/webworkers.js</path-element>
+ <path-element>externs/goog/color/alpha.js</path-element>
+ <path-element>externs/goog/color/color.js</path-element>
+ <path-element>externs/goog/color/names.js</path-element>
+ <path-element>externs/goog/crypt/aes.js</path-element>
+ <path-element>externs/goog/crypt/arc4.js</path-element>
+ <path-element>externs/goog/crypt/base64.js</path-element>
+ <path-element>externs/goog/crypt/basen.js</path-element>
+ <path-element>externs/goog/crypt/blobhasher.js</path-element>
+ <path-element>externs/goog/crypt/blockcipher.js</path-element>
+ <path-element>externs/goog/crypt/cbc.js</path-element>
+ <path-element>externs/goog/crypt/crypt.js</path-element>
+ <path-element>externs/goog/crypt/hash.js</path-element>
+ <path-element>externs/goog/crypt/hash32.js</path-element>
+ <path-element>externs/goog/crypt/hmac.js</path-element>
+ <path-element>externs/goog/crypt/md5.js</path-element>
+ <path-element>externs/goog/crypt/pbkdf2.js</path-element>
+ <path-element>externs/goog/crypt/sha1.js</path-element>
+ <path-element>externs/goog/crypt/sha2.js</path-element>
+ <path-element>externs/goog/crypt/sha224.js</path-element>
+ <path-element>externs/goog/crypt/sha256.js</path-element>
+ <path-element>externs/goog/crypt/sha2_64bit.js</path-element>
+ <path-element>externs/goog/crypt/sha384.js</path-element>
+ <path-element>externs/goog/crypt/sha512.js</path-element>
+ <path-element>externs/goog/crypt/sha512_256.js</path-element>
+ <path-element>externs/goog/cssom/cssom.js</path-element>
+ <path-element>externs/goog/cssom/iframe/style.js</path-element>
+ <path-element>externs/goog/datasource/datamanager.js</path-element>
+ <path-element>externs/goog/datasource/datasource.js</path-element>
+ <path-element>externs/goog/datasource/expr.js</path-element>
+ <path-element>externs/goog/datasource/fastdatanode.js</path-element>
+ <path-element>externs/goog/datasource/jsdatasource.js</path-element>
+ <path-element>externs/goog/datasource/jsondatasource.js</path-element>
+ <path-element>externs/goog/datasource/jsxmlhttpdatasource.js</path-element>
+ <path-element>externs/goog/datasource/xmldatasource.js</path-element>
+ <path-element>externs/goog/date/date.js</path-element>
+ <path-element>externs/goog/date/datelike.js</path-element>
+ <path-element>externs/goog/date/daterange.js</path-element>
+ <path-element>externs/goog/date/duration.js</path-element>
+ <path-element>externs/goog/date/relative.js</path-element>
+ <path-element>externs/goog/date/relativewithplurals.js</path-element>
+ <path-element>externs/goog/date/utcdatetime.js</path-element>
+ <path-element>externs/goog/db/cursor.js</path-element>
+ <path-element>externs/goog/db/db.js</path-element>
+ <path-element>externs/goog/db/error.js</path-element>
+ <path-element>externs/goog/db/index.js</path-element>
+ <path-element>externs/goog/db/indexeddb.js</path-element>
+ <path-element>externs/goog/db/keyrange.js</path-element>
+ <path-element>externs/goog/db/objectstore.js</path-element>
+ <path-element>externs/goog/db/transaction.js</path-element>
+ <path-element>externs/goog/debug/console.js</path-element>
+ <path-element>externs/goog/debug/debug.js</path-element>
+ <path-element>externs/goog/debug/debugwindow.js</path-element>
+ <path-element>externs/goog/debug/divconsole.js</path-element>
+ <path-element>externs/goog/debug/entrypointregistry.js</path-element>
+ <path-element>externs/goog/debug/error.js</path-element>
+ <path-element>externs/goog/debug/errorhandler.js</path-element>
+ <path-element>externs/goog/debug/errorhandlerweakdep.js</path-element>
+ <path-element>externs/goog/debug/errorreporter.js</path-element>
+ <path-element>externs/goog/debug/fancywindow.js</path-element>
+ <path-element>externs/goog/debug/formatter.js</path-element>
+ <path-element>externs/goog/debug/fpsdisplay.js</path-element>
+ <path-element>externs/goog/debug/gcdiagnostics.js</path-element>
+ <path-element>externs/goog/debug/logbuffer.js</path-element>
+ <path-element>externs/goog/debug/logger.js</path-element>
+ <path-element>externs/goog/debug/logrecord.js</path-element>
+ <path-element>externs/goog/debug/logrecordserializer.js</path-element>
+ <path-element>externs/goog/debug/relativetimeprovider.js</path-element>
+ <path-element>externs/goog/debug/tracer.js</path-element>
+ <path-element>externs/goog/debug/devcss/devcss.js</path-element>
+ <path-element>externs/goog/debug/devcss/devcssrunner.js</path-element>
+ <path-element>externs/goog/demos/autocompleteremotedata.js</path-element>
+ <path-element>externs/goog/demos/autocompleterichremotedata.js</path-element>
+ <path-element>externs/goog/demos/samplecomponent.js</path-element>
+ <path-element>externs/goog/demos/editor/deps.js</path-element>
+ <path-element>externs/goog/demos/editor/helloworld.js</path-element>
+ <path-element>externs/goog/demos/editor/helloworlddialog.js</path-element>
+ <path-element>externs/goog/demos/editor/helloworlddialogplugin.js</path-element>
+ <path-element>externs/goog/demos/graphics/tigerdata.js</path-element>
+ <path-element>externs/goog/demos/xpc/xpcdemo.js</path-element>
+ <path-element>externs/goog/dom/abstractmultirange.js</path-element>
+ <path-element>externs/goog/dom/abstractrange.js</path-element>
+ <path-element>externs/goog/dom/annotate.js</path-element>
+ <path-element>externs/goog/dom/browserfeature.js</path-element>
+ <path-element>externs/goog/dom/bufferedviewportsizemonitor.js</path-element>
+ <path-element>externs/goog/dom/classes.js</path-element>
+ <path-element>externs/goog/dom/classlist.js</path-element>
+ <path-element>externs/goog/dom/controlrange.js</path-element>
+ <path-element>externs/goog/dom/dataset.js</path-element>
+ <path-element>externs/goog/dom/dom.js</path-element>
+ <path-element>externs/goog/dom/fontsizemonitor.js</path-element>
+ <path-element>externs/goog/dom/forms.js</path-element>
+ <path-element>externs/goog/dom/fullscreen.js</path-element>
+ <path-element>externs/goog/dom/iframe.js</path-element>
+ <path-element>externs/goog/dom/inputtype.js</path-element>
+ <path-element>externs/goog/dom/iter.js</path-element>
+ <path-element>externs/goog/dom/multirange.js</path-element>
+ <path-element>externs/goog/dom/nodeiterator.js</path-element>
+ <path-element>externs/goog/dom/nodeoffset.js</path-element>
+ <path-element>externs/goog/dom/nodetype.js</path-element>
+ <path-element>externs/goog/dom/range.js</path-element>
+ <path-element>externs/goog/dom/rangeendpoint.js</path-element>
+ <path-element>externs/goog/dom/safe.js</path-element>
+ <path-element>externs/goog/dom/savedcaretrange.js</path-element>
+ <path-element>externs/goog/dom/savedrange.js</path-element>
+ <path-element>externs/goog/dom/selection.js</path-element>
+ <path-element>externs/goog/dom/tagiterator.js</path-element>
+ <path-element>externs/goog/dom/tagname.js</path-element>
+ <path-element>externs/goog/dom/tags.js</path-element>
+ <path-element>externs/goog/dom/textrange.js</path-element>
+ <path-element>externs/goog/dom/textrangeiterator.js</path-element>
+ <path-element>externs/goog/dom/vendor.js</path-element>
+ <path-element>externs/goog/dom/viewportsizemonitor.js</path-element>
+ <path-element>externs/goog/dom/xml.js</path-element>
+ <path-element>externs/goog/dom/animationframe/animationframe.js</path-element>
+ <path-element>externs/goog/dom/animationframe/polyfill.js</path-element>
+ <path-element>externs/goog/dom/browserrange/abstractrange.js</path-element>
+ <path-element>externs/goog/dom/browserrange/browserrange.js</path-element>
+ <path-element>externs/goog/dom/browserrange/geckorange.js</path-element>
+ <path-element>externs/goog/dom/browserrange/ierange.js</path-element>
+ <path-element>externs/goog/dom/browserrange/operarange.js</path-element>
+ <path-element>externs/goog/dom/browserrange/w3crange.js</path-element>
+ <path-element>externs/goog/dom/browserrange/webkitrange.js</path-element>
+ <path-element>externs/goog/dom/pattern/abstractpattern.js</path-element>
+ <path-element>externs/goog/dom/pattern/allchildren.js</path-element>
+ <path-element>externs/goog/dom/pattern/childmatches.js</path-element>
+ <path-element>externs/goog/dom/pattern/endtag.js</path-element>
+ <path-element>externs/goog/dom/pattern/fulltag.js</path-element>
+ <path-element>externs/goog/dom/pattern/matcher.js</path-element>
+ <path-element>externs/goog/dom/pattern/nodetype.js</path-element>
+ <path-element>externs/goog/dom/pattern/pattern.js</path-element>
+ <path-element>externs/goog/dom/pattern/repeat.js</path-element>
+ <path-element>externs/goog/dom/pattern/sequence.js</path-element>
+ <path-element>externs/goog/dom/pattern/starttag.js</path-element>
+ <path-element>externs/goog/dom/pattern/tag.js</path-element>
+ <path-element>externs/goog/dom/pattern/text.js</path-element>
+ <path-element>externs/goog/dom/pattern/callback/callback.js</path-element>
+ <path-element>externs/goog/dom/pattern/callback/counter.js</path-element>
+ <path-element>externs/goog/editor/browserfeature.js</path-element>
+ <path-element>externs/goog/editor/clicktoeditwrapper.js</path-element>
+ <path-element>externs/goog/editor/command.js</path-element>
+ <path-element>externs/goog/editor/contenteditablefield.js</path-element>
+ <path-element>externs/goog/editor/defines.js</path-element>
+ <path-element>externs/goog/editor/field.js</path-element>
+ <path-element>externs/goog/editor/focus.js</path-element>
+ <path-element>externs/goog/editor/icontent.js</path-element>
+ <path-element>externs/goog/editor/link.js</path-element>
+ <path-element>externs/goog/editor/node.js</path-element>
+ <path-element>externs/goog/editor/plugin.js</path-element>
+ <path-element>externs/goog/editor/range.js</path-element>
+ <path-element>externs/goog/editor/seamlessfield.js</path-element>
+ <path-element>externs/goog/editor/style.js</path-element>
+ <path-element>externs/goog/editor/table.js</path-element>
+ <path-element>externs/goog/editor/plugins/abstractbubbleplugin.js</path-element>
+ <path-element>externs/goog/editor/plugins/abstractdialogplugin.js</path-element>
+ <path-element>externs/goog/editor/plugins/abstracttabhandler.js</path-element>
+ <path-element>externs/goog/editor/plugins/basictextformatter.js</path-element>
+ <path-element>externs/goog/editor/plugins/blockquote.js</path-element>
+ <path-element>externs/goog/editor/plugins/emoticons.js</path-element>
+ <path-element>externs/goog/editor/plugins/enterhandler.js</path-element>
+ <path-element>externs/goog/editor/plugins/firststrong.js</path-element>
+ <path-element>externs/goog/editor/plugins/headerformatter.js</path-element>
+ <path-element>externs/goog/editor/plugins/linkbubble.js</path-element>
+ <path-element>externs/goog/editor/plugins/linkdialogplugin.js</path-element>
+ <path-element>externs/goog/editor/plugins/linkshortcutplugin.js</path-element>
+ <path-element>externs/goog/editor/plugins/listtabhandler.js</path-element>
+ <path-element>externs/goog/editor/plugins/loremipsum.js</path-element>
+ <path-element>externs/goog/editor/plugins/removeformatting.js</path-element>
+ <path-element>externs/goog/editor/plugins/spacestabhandler.js</path-element>
+ <path-element>externs/goog/editor/plugins/tableeditor.js</path-element>
+ <path-element>externs/goog/editor/plugins/tagonenterhandler.js</path-element>
+ <path-element>externs/goog/editor/plugins/undoredo.js</path-element>
+ <path-element>externs/goog/editor/plugins/undoredomanager.js</path-element>
+ <path-element>externs/goog/editor/plugins/undoredostate.js</path-element>
+ <path-element>externs/goog/events/actioneventwrapper.js</path-element>
+ <path-element>externs/goog/events/actionhandler.js</path-element>-->
+ <!--<path-element>externs/goog/events/browserfeature.js</path-element>-->
+ <!--<path-element>externs/goog/events/eventhandler.js</path-element>
+ <path-element>externs/goog/events/eventid.js</path-element>-->
+ <path-element>externs/goog/disposable/disposable.js</path-element>
+ <path-element>externs/goog/disposable/idisposable.js</path-element>
+ <path-element>externs/goog/events/browserevent.js</path-element>
+ <path-element>externs/goog/events/event.js</path-element>
+ <path-element>externs/goog/events/events.js</path-element>
+ <path-element>externs/goog/events/eventtarget.js</path-element>
+ <path-element>externs/goog/events/eventtype.js</path-element>
+ <path-element>externs/goog/events/listenable.js</path-element>
+ <!--<path-element>externs/goog/events/eventwrapper.js</path-element>
+ <path-element>externs/goog/events/filedrophandler.js</path-element>
+ <path-element>externs/goog/events/focushandler.js</path-element>
+ <path-element>externs/goog/events/imehandler.js</path-element>
+ <path-element>externs/goog/events/inputhandler.js</path-element>
+ <path-element>externs/goog/events/keycodes.js</path-element>
+ <path-element>externs/goog/events/keyhandler.js</path-element>
+ <path-element>externs/goog/events/keynames.js</path-element>
+ <path-element>externs/goog/events/listener.js</path-element>
+ <path-element>externs/goog/events/listenermap.js</path-element>
+ <path-element>externs/goog/events/mousewheelhandler.js</path-element>
+ <path-element>externs/goog/events/onlinehandler.js</path-element>
+ <path-element>externs/goog/events/pastehandler.js</path-element>
+ <path-element>externs/goog/events/wheelevent.js</path-element>
+ <path-element>externs/goog/events/wheelhandler.js</path-element>-->
+ <!--<path-element>externs/goog/format/emailaddress.js</path-element>
+ <path-element>externs/goog/format/format.js</path-element>
+ <path-element>externs/goog/format/htmlprettyprinter.js</path-element>
+ <path-element>externs/goog/format/internationalizedemailaddress.js</path-element>
+ <path-element>externs/goog/format/jsonprettyprinter.js</path-element>
+ <path-element>externs/goog/fs/entry.js</path-element>
+ <path-element>externs/goog/fs/entryimpl.js</path-element>
+ <path-element>externs/goog/fs/error.js</path-element>
+ <path-element>externs/goog/fs/filereader.js</path-element>
+ <path-element>externs/goog/fs/filesaver.js</path-element>
+ <path-element>externs/goog/fs/filesystem.js</path-element>
+ <path-element>externs/goog/fs/filesystemimpl.js</path-element>
+ <path-element>externs/goog/fs/filewriter.js</path-element>
+ <path-element>externs/goog/fs/fs.js</path-element>
+ <path-element>externs/goog/fs/progressevent.js</path-element>
+ <path-element>externs/goog/fs/url.js</path-element>
+ <path-element>externs/goog/functions/functions.js</path-element>
+ <path-element>externs/goog/fx/abstractdragdrop.js</path-element>
+ <path-element>externs/goog/fx/animation.js</path-element>
+ <path-element>externs/goog/fx/animationqueue.js</path-element>
+ <path-element>externs/goog/fx/cssspriteanimation.js</path-element>
+ <path-element>externs/goog/fx/dom.js</path-element>
+ <path-element>externs/goog/fx/dragdrop.js</path-element>
+ <path-element>externs/goog/fx/dragdropgroup.js</path-element>
+ <path-element>externs/goog/fx/dragger.js</path-element>
+ <path-element>externs/goog/fx/draglistgroup.js</path-element>
+ <path-element>externs/goog/fx/dragscrollsupport.js</path-element>
+ <path-element>externs/goog/fx/easing.js</path-element>
+ <path-element>externs/goog/fx/fx.js</path-element>
+ <path-element>externs/goog/fx/transition.js</path-element>
+ <path-element>externs/goog/fx/transitionbase.js</path-element>
+ <path-element>externs/goog/fx/anim/anim.js</path-element>
+ <path-element>externs/goog/fx/css3/fx.js</path-element>
+ <path-element>externs/goog/fx/css3/transition.js</path-element>
+ <path-element>externs/goog/graphics/abstractgraphics.js</path-element>
+ <path-element>externs/goog/graphics/affinetransform.js</path-element>
+ <path-element>externs/goog/graphics/canvaselement.js</path-element>
+ <path-element>externs/goog/graphics/canvasgraphics.js</path-element>
+ <path-element>externs/goog/graphics/element.js</path-element>
+ <path-element>externs/goog/graphics/ellipseelement.js</path-element>
+ <path-element>externs/goog/graphics/fill.js</path-element>
+ <path-element>externs/goog/graphics/font.js</path-element>
+ <path-element>externs/goog/graphics/graphics.js</path-element>
+ <path-element>externs/goog/graphics/groupelement.js</path-element>
+ <path-element>externs/goog/graphics/imageelement.js</path-element>
+ <path-element>externs/goog/graphics/lineargradient.js</path-element>
+ <path-element>externs/goog/graphics/path.js</path-element>
+ <path-element>externs/goog/graphics/pathelement.js</path-element>
+ <path-element>externs/goog/graphics/paths.js</path-element>
+ <path-element>externs/goog/graphics/rectelement.js</path-element>
+ <path-element>externs/goog/graphics/solidfill.js</path-element>
+ <path-element>externs/goog/graphics/stroke.js</path-element>
+ <path-element>externs/goog/graphics/strokeandfillelement.js</path-element>
+ <path-element>externs/goog/graphics/svgelement.js</path-element>
+ <path-element>externs/goog/graphics/svggraphics.js</path-element>
+ <path-element>externs/goog/graphics/textelement.js</path-element>
+ <path-element>externs/goog/graphics/vmlelement.js</path-element>
+ <path-element>externs/goog/graphics/vmlgraphics.js</path-element>
+ <path-element>externs/goog/graphics/ext/coordinates.js</path-element>
+ <path-element>externs/goog/graphics/ext/element.js</path-element>
+ <path-element>externs/goog/graphics/ext/ellipse.js</path-element>
+ <path-element>externs/goog/graphics/ext/ext.js</path-element>
+ <path-element>externs/goog/graphics/ext/graphics.js</path-element>
+ <path-element>externs/goog/graphics/ext/group.js</path-element>
+ <path-element>externs/goog/graphics/ext/image.js</path-element>
+ <path-element>externs/goog/graphics/ext/path.js</path-element>
+ <path-element>externs/goog/graphics/ext/rectangle.js</path-element>
+ <path-element>externs/goog/graphics/ext/shape.js</path-element>
+ <path-element>externs/goog/graphics/ext/strokeandfillelement.js</path-element>
+ <path-element>externs/goog/history/event.js</path-element>
+ <path-element>externs/goog/history/eventtype.js</path-element>
+ <path-element>externs/goog/history/history.js</path-element>
+ <path-element>externs/goog/history/html5history.js</path-element>
+ <path-element>externs/goog/html/flash.js</path-element>
+ <path-element>externs/goog/html/legacyconversions.js</path-element>
+ <path-element>externs/goog/html/safehtml.js</path-element>
+ <path-element>externs/goog/html/safescript.js</path-element>
+ <path-element>externs/goog/html/safestyle.js</path-element>
+ <path-element>externs/goog/html/safestylesheet.js</path-element>
+ <path-element>externs/goog/html/safeurl.js</path-element>
+ <path-element>externs/goog/html/silverlight.js</path-element>
+ <path-element>externs/goog/html/trustedresourceurl.js</path-element>
+ <path-element>externs/goog/html/uncheckedconversions.js</path-element>
+ <path-element>externs/goog/html/utils.js</path-element>
+ <path-element>externs/goog/i18n/bidi.js</path-element>
+ <path-element>externs/goog/i18n/bidiformatter.js</path-element>
+ <path-element>externs/goog/i18n/charlistdecompressor.js</path-element>
+ <path-element>externs/goog/i18n/charpickerdata.js</path-element>
+ <path-element>externs/goog/i18n/collation.js</path-element>
+ <path-element>externs/goog/i18n/compactnumberformatsymbols.js</path-element>
+ <path-element>externs/goog/i18n/compactnumberformatsymbols_ext.js</path-element>
+ <path-element>externs/goog/i18n/currency.js</path-element>
+ <path-element>externs/goog/i18n/currencycodemap.js</path-element>
+ <path-element>externs/goog/i18n/datetimeformat.js</path-element>
+ <path-element>externs/goog/i18n/datetimeparse.js</path-element>
+ <path-element>externs/goog/i18n/datetimepatterns.js</path-element>
+ <path-element>externs/goog/i18n/datetimepatternsext.js</path-element>
+ <path-element>externs/goog/i18n/datetimesymbols.js</path-element>
+ <path-element>externs/goog/i18n/datetimesymbolsext.js</path-element>
+ <path-element>externs/goog/i18n/graphemebreak.js</path-element>
+ <path-element>externs/goog/i18n/messageformat.js</path-element>
+ <path-element>externs/goog/i18n/mime.js</path-element>
+ <path-element>externs/goog/i18n/numberformat.js</path-element>
+ <path-element>externs/goog/i18n/numberformatsymbols.js</path-element>
+ <path-element>externs/goog/i18n/numberformatsymbolsext.js</path-element>
+ <path-element>externs/goog/i18n/ordinalrules.js</path-element>
+ <path-element>externs/goog/i18n/pluralrules.js</path-element>
+ <path-element>externs/goog/i18n/timezone.js</path-element>
+ <path-element>externs/goog/i18n/uchar.js</path-element>
+ <path-element>externs/goog/i18n/ucharnames.js</path-element>
+ <path-element>externs/goog/i18n/uchar/localnamefetcher.js</path-element>
+ <path-element>externs/goog/i18n/uchar/namefetcher.js</path-element>
+ <path-element>externs/goog/i18n/uchar/remotenamefetcher.js</path-element>
+ <path-element>externs/goog/iter/iter.js</path-element>
+ <path-element>externs/goog/json/evaljsonprocessor.js</path-element>
+ <path-element>externs/goog/json/hybrid.js</path-element>
+ <path-element>externs/goog/json/hybridjsonprocessor.js</path-element>
+ <path-element>externs/goog/json/json.js</path-element>
+ <path-element>externs/goog/json/json_perf.js</path-element>
+ <path-element>externs/goog/json/nativejsonprocessor.js</path-element>
+ <path-element>externs/goog/json/processor.js</path-element>
+ <path-element>externs/goog/labs/dom/pagevisibilitymonitor.js</path-element>
+ <path-element>externs/goog/labs/events/nondisposableeventtarget.js</path-element>
+ <path-element>externs/goog/labs/events/touch.js</path-element>
+ <path-element>externs/goog/labs/format/csv.js</path-element>
+ <path-element>externs/goog/labs/html/attribute_rewriter.js</path-element>
+ <path-element>externs/goog/labs/html/sanitizer.js</path-element>
+ <path-element>externs/goog/labs/html/scrubber.js</path-element>
+ <path-element>externs/goog/labs/i18n/listformat.js</path-element>
+ <path-element>externs/goog/labs/i18n/listsymbols.js</path-element>
+ <path-element>externs/goog/labs/i18n/listsymbolsext.js</path-element>
+ <path-element>externs/goog/labs/iterable/iterable.js</path-element>
+ <path-element>externs/goog/labs/mock/mock.js</path-element>
+ <path-element>externs/goog/labs/net/image.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel.js</path-element>
+ <path-element>externs/goog/labs/net/webchanneltransport.js</path-element>
+ <path-element>externs/goog/labs/net/webchanneltransportfactory.js</path-element>
+ <path-element>externs/goog/labs/net/xhr.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/channel.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/channelrequest.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/connectionstate.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/forwardchannelrequestpool.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/netutils.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/requeststats.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/webchannelbase.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/webchannelbasetransport.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/webchanneldebug.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/wire.js</path-element>
+ <path-element>externs/goog/labs/net/webchannel/wirev8.js</path-element>
+ <path-element>externs/goog/labs/object/object.js</path-element>
+ <path-element>externs/goog/labs/pubsub/broadcastpubsub.js</path-element>
+ <path-element>externs/goog/labs/storage/boundedcollectablestorage.js</path-element>
+ <path-element>externs/goog/labs/structs/map.js</path-element>
+ <path-element>externs/goog/labs/structs/map_perf.js</path-element>
+ <path-element>externs/goog/labs/structs/multimap.js</path-element>
+ <path-element>externs/goog/labs/style/pixeldensitymonitor.js</path-element>
+ <path-element>externs/goog/labs/testing/assertthat.js</path-element>
+ <path-element>externs/goog/labs/testing/decoratormatcher.js</path-element>
+ <path-element>externs/goog/labs/testing/dictionarymatcher.js</path-element>
+ <path-element>externs/goog/labs/testing/environment.js</path-element>
+ <path-element>externs/goog/labs/testing/logicmatcher.js</path-element>
+ <path-element>externs/goog/labs/testing/matcher.js</path-element>
+ <path-element>externs/goog/labs/testing/numbermatcher.js</path-element>
+ <path-element>externs/goog/labs/testing/objectmatcher.js</path-element>
+ <path-element>externs/goog/labs/testing/stringmatcher.js</path-element>
+ <path-element>externs/goog/labs/useragent/browser.js</path-element>
+ <path-element>externs/goog/labs/useragent/device.js</path-element>
+ <path-element>externs/goog/labs/useragent/engine.js</path-element>
+ <path-element>externs/goog/labs/useragent/platform.js</path-element>
+ <path-element>externs/goog/labs/useragent/util.js</path-element>
+ <path-element>externs/goog/locale/countries.js</path-element>
+ <path-element>externs/goog/locale/defaultlocalenameconstants.js</path-element>
+ <path-element>externs/goog/locale/genericfontnames.js</path-element>
+ <path-element>externs/goog/locale/genericfontnamesdata.js</path-element>
+ <path-element>externs/goog/locale/locale.js</path-element>
+ <path-element>externs/goog/locale/nativenameconstants.js</path-element>
+ <path-element>externs/goog/locale/scriptToLanguages.js</path-element>
+ <path-element>externs/goog/locale/timezonedetection.js</path-element>
+ <path-element>externs/goog/locale/timezonefingerprint.js</path-element>
+ <path-element>externs/goog/locale/timezonelist.js</path-element>
+ <path-element>externs/goog/log/log.js</path-element>
+ <path-element>externs/goog/math/affinetransform.js</path-element>
+ <path-element>externs/goog/math/bezier.js</path-element>
+ <path-element>externs/goog/math/box.js</path-element>
+ <path-element>externs/goog/math/coordinate.js</path-element>
+ <path-element>externs/goog/math/coordinate3.js</path-element>
+ <path-element>externs/goog/math/exponentialbackoff.js</path-element>
+ <path-element>externs/goog/math/integer.js</path-element>
+ <path-element>externs/goog/math/line.js</path-element>
+ <path-element>externs/goog/math/long.js</path-element>
+ <path-element>externs/goog/math/math.js</path-element>
+ <path-element>externs/goog/math/matrix.js</path-element>
+ <path-element>externs/goog/math/path.js</path-element>
+ <path-element>externs/goog/math/paths.js</path-element>
+ <path-element>externs/goog/math/range.js</path-element>
+ <path-element>externs/goog/math/rangeset.js</path-element>
+ <path-element>externs/goog/math/rect.js</path-element>
+ <path-element>externs/goog/math/size.js</path-element>
+ <path-element>externs/goog/math/tdma.js</path-element>
+ <path-element>externs/goog/math/vec2.js</path-element>
+ <path-element>externs/goog/math/vec3.js</path-element>
+ <path-element>externs/goog/math/interpolator/interpolator1.js</path-element>
+ <path-element>externs/goog/math/interpolator/linear1.js</path-element>
+ <path-element>externs/goog/math/interpolator/pchip1.js</path-element>
+ <path-element>externs/goog/math/interpolator/spline1.js</path-element>
+ <path-element>externs/goog/memoize/memoize.js</path-element>
+ <path-element>externs/goog/messaging/abstractchannel.js</path-element>
+ <path-element>externs/goog/messaging/bufferedchannel.js</path-element>
+ <path-element>externs/goog/messaging/deferredchannel.js</path-element>
+ <path-element>externs/goog/messaging/loggerclient.js</path-element>
+ <path-element>externs/goog/messaging/loggerserver.js</path-element>
+ <path-element>externs/goog/messaging/messagechannel.js</path-element>
+ <path-element>externs/goog/messaging/messaging.js</path-element>
+ <path-element>externs/goog/messaging/multichannel.js</path-element>
+ <path-element>externs/goog/messaging/portcaller.js</path-element>
+ <path-element>externs/goog/messaging/portchannel.js</path-element>
+ <path-element>externs/goog/messaging/portnetwork.js</path-element>
+ <path-element>externs/goog/messaging/portoperator.js</path-element>
+ <path-element>externs/goog/messaging/respondingchannel.js</path-element>
+ <path-element>externs/goog/messaging/testdata/portchannel_worker.js</path-element>
+ <path-element>externs/goog/messaging/testdata/portnetwork_worker1.js</path-element>
+ <path-element>externs/goog/messaging/testdata/portnetwork_worker2.js</path-element>
+ <path-element>externs/goog/module/abstractmoduleloader.js</path-element>
+ <path-element>externs/goog/module/basemodule.js</path-element>
+ <path-element>externs/goog/module/loader.js</path-element>
+ <path-element>externs/goog/module/module.js</path-element>
+ <path-element>externs/goog/module/moduleinfo.js</path-element>
+ <path-element>externs/goog/module/moduleloadcallback.js</path-element>
+ <path-element>externs/goog/module/moduleloader.js</path-element>
+ <path-element>externs/goog/module/modulemanager.js</path-element>
+ <path-element>externs/goog/module/testdata/modA_1.js</path-element>
+ <path-element>externs/goog/module/testdata/modA_2.js</path-element>
+ <path-element>externs/goog/module/testdata/modB_1.js</path-element>
+ <path-element>externs/goog/net/browserchannel.js</path-element>
+ <path-element>externs/goog/net/bulkloader.js</path-element>
+ <path-element>externs/goog/net/bulkloaderhelper.js</path-element>
+ <path-element>externs/goog/net/channeldebug.js</path-element>
+ <path-element>externs/goog/net/channelrequest.js</path-element>
+ <path-element>externs/goog/net/cookies.js</path-element>
+ <path-element>externs/goog/net/corsxmlhttpfactory.js</path-element>
+ <path-element>externs/goog/net/crossdomainrpc.js</path-element>
+ <path-element>externs/goog/net/errorcode.js</path-element>
+ <path-element>externs/goog/net/eventtype.js</path-element>
+ <path-element>externs/goog/net/filedownloader.js</path-element>
+ <path-element>externs/goog/net/httpstatus.js</path-element>
+ <path-element>externs/goog/net/iframeio.js</path-element>
+ <path-element>externs/goog/net/iframeloadmonitor.js</path-element>
+ <path-element>externs/goog/net/imageloader.js</path-element>
+ <path-element>externs/goog/net/ipaddress.js</path-element>
+ <path-element>externs/goog/net/jsloader.js</path-element>
+ <path-element>externs/goog/net/jsonp.js</path-element>
+ <path-element>externs/goog/net/mockiframeio.js</path-element>
+ <path-element>externs/goog/net/multiiframeloadmonitor.js</path-element>
+ <path-element>externs/goog/net/networkstatusmonitor.js</path-element>
+ <path-element>externs/goog/net/tmpnetwork.js</path-element>
+ <path-element>externs/goog/net/websocket.js</path-element>
+ <path-element>externs/goog/net/wrapperxmlhttpfactory.js</path-element>
+ <path-element>externs/goog/net/xhrio.js</path-element>
+ <path-element>externs/goog/net/xhriopool.js</path-element>
+ <path-element>externs/goog/net/xhrlike.js</path-element>
+ <path-element>externs/goog/net/xhrmanager.js</path-element>
+ <path-element>externs/goog/net/xmlhttp.js</path-element>
+ <path-element>externs/goog/net/xmlhttpfactory.js</path-element>
+ <path-element>externs/goog/net/xpc/crosspagechannel.js</path-element>
+ <path-element>externs/goog/net/xpc/crosspagechannelrole.js</path-element>
+ <path-element>externs/goog/net/xpc/directtransport.js</path-element>
+ <path-element>externs/goog/net/xpc/frameelementmethodtransport.js</path-element>
+ <path-element>externs/goog/net/xpc/iframepollingtransport.js</path-element>
+ <path-element>externs/goog/net/xpc/iframerelaytransport.js</path-element>
+ <path-element>externs/goog/net/xpc/nativemessagingtransport.js</path-element>
+ <path-element>externs/goog/net/xpc/nixtransport.js</path-element>
+ <path-element>externs/goog/net/xpc/relay.js</path-element>
+ <path-element>externs/goog/net/xpc/transport.js</path-element>
+ <path-element>externs/goog/net/xpc/xpc.js</path-element>
+ <path-element>externs/goog/object/object.js</path-element>
+ <path-element>externs/goog/positioning/absoluteposition.js</path-element>
+ <path-element>externs/goog/positioning/abstractposition.js</path-element>
+ <path-element>externs/goog/positioning/anchoredposition.js</path-element>
+ <path-element>externs/goog/positioning/anchoredviewportposition.js</path-element>
+ <path-element>externs/goog/positioning/clientposition.js</path-element>
+ <path-element>externs/goog/positioning/menuanchoredposition.js</path-element>
+ <path-element>externs/goog/positioning/positioning.js</path-element>
+ <path-element>externs/goog/positioning/viewportclientposition.js</path-element>
+ <path-element>externs/goog/positioning/viewportposition.js</path-element>
+ <path-element>externs/goog/promise/promise.js</path-element>
+ <path-element>externs/goog/promise/resolver.js</path-element>
+ <path-element>externs/goog/promise/thenable.js</path-element>
+ <path-element>externs/goog/proto/proto.js</path-element>
+ <path-element>externs/goog/proto/serializer.js</path-element>
+ <path-element>externs/goog/proto2/descriptor.js</path-element>
+ <path-element>externs/goog/proto2/fielddescriptor.js</path-element>
+ <path-element>externs/goog/proto2/lazydeserializer.js</path-element>
+ <path-element>externs/goog/proto2/message.js</path-element>
+ <path-element>externs/goog/proto2/objectserializer.js</path-element>
+ <path-element>externs/goog/proto2/pbliteserializer.js</path-element>
+ <path-element>externs/goog/proto2/serializer.js</path-element>
+ <path-element>externs/goog/proto2/textformatserializer.js</path-element>
+ <path-element>externs/goog/proto2/util.js</path-element>
+ <path-element>externs/goog/pubsub/pubsub.js</path-element>
+ <path-element>externs/goog/pubsub/topicid.js</path-element>
+ <path-element>externs/goog/pubsub/typedpubsub.js</path-element>
+ <path-element>externs/goog/reflect/reflect.js</path-element>
+ <path-element>externs/goog/result/deferredadaptor.js</path-element>
+ <path-element>externs/goog/result/dependentresult.js</path-element>
+ <path-element>externs/goog/result/resultutil.js</path-element>
+ <path-element>externs/goog/result/result_interface.js</path-element>
+ <path-element>externs/goog/result/simpleresult.js</path-element>
+ <path-element>externs/goog/soy/data.js</path-element>
+ <path-element>externs/goog/soy/renderer.js</path-element>
+ <path-element>externs/goog/soy/soy.js</path-element>
+ <path-element>externs/goog/spell/spellcheck.js</path-element>
+ <path-element>externs/goog/stats/basicstat.js</path-element>
+ <path-element>externs/goog/storage/collectablestorage.js</path-element>
+ <path-element>externs/goog/storage/encryptedstorage.js</path-element>
+ <path-element>externs/goog/storage/errorcode.js</path-element>
+ <path-element>externs/goog/storage/expiringstorage.js</path-element>
+ <path-element>externs/goog/storage/richstorage.js</path-element>
+ <path-element>externs/goog/storage/storage.js</path-element>
+ <path-element>externs/goog/storage/mechanism/errorcode.js</path-element>
+ <path-element>externs/goog/storage/mechanism/errorhandlingmechanism.js</path-element>
+ <path-element>externs/goog/storage/mechanism/html5localstorage.js</path-element>
+ <path-element>externs/goog/storage/mechanism/html5sessionstorage.js</path-element>
+ <path-element>externs/goog/storage/mechanism/html5webstorage.js</path-element>
+ <path-element>externs/goog/storage/mechanism/ieuserdata.js</path-element>
+ <path-element>externs/goog/storage/mechanism/iterablemechanism.js</path-element>
+ <path-element>externs/goog/storage/mechanism/mechanism.js</path-element>
+ <path-element>externs/goog/storage/mechanism/mechanismfactory.js</path-element>
+ <path-element>externs/goog/storage/mechanism/prefixedmechanism.js</path-element>
+ <path-element>externs/goog/string/const.js</path-element>
+ <path-element>externs/goog/string/linkify.js</path-element>
+ <path-element>externs/goog/string/newlines.js</path-element>
+ <path-element>externs/goog/string/parser.js</path-element>
+ <path-element>externs/goog/string/path.js</path-element>
+ <path-element>externs/goog/string/string.js</path-element>
+ <path-element>externs/goog/string/stringbuffer.js</path-element>
+ <path-element>externs/goog/string/stringformat.js</path-element>
+ <path-element>externs/goog/string/stringifier.js</path-element>
+ <path-element>externs/goog/string/typedstring.js</path-element>
+ <path-element>externs/goog/structs/avltree.js</path-element>
+ <path-element>externs/goog/structs/circularbuffer.js</path-element>
+ <path-element>externs/goog/structs/collection.js</path-element>
+ <path-element>externs/goog/structs/heap.js</path-element>
+ <path-element>externs/goog/structs/inversionmap.js</path-element>
+ <path-element>externs/goog/structs/linkedmap.js</path-element>
+ <path-element>externs/goog/structs/map.js</path-element>
+ <path-element>externs/goog/structs/node.js</path-element>
+ <path-element>externs/goog/structs/pool.js</path-element>
+ <path-element>externs/goog/structs/prioritypool.js</path-element>
+ <path-element>externs/goog/structs/priorityqueue.js</path-element>
+ <path-element>externs/goog/structs/quadtree.js</path-element>
+ <path-element>externs/goog/structs/queue.js</path-element>
+ <path-element>externs/goog/structs/set.js</path-element>
+ <path-element>externs/goog/structs/simplepool.js</path-element>
+ <path-element>externs/goog/structs/stringset.js</path-element>
+ <path-element>externs/goog/structs/structs.js</path-element>
+ <path-element>externs/goog/structs/treenode.js</path-element>
+ <path-element>externs/goog/structs/trie.js</path-element>
+ <path-element>externs/goog/structs/weak/weak.js</path-element>
+ <path-element>externs/goog/style/bidi.js</path-element>
+ <path-element>externs/goog/style/cursor.js</path-element>
+ <path-element>externs/goog/style/style.js</path-element>
+ <path-element>externs/goog/style/transform.js</path-element>
+ <path-element>externs/goog/style/transition.js</path-element>
+ <path-element>externs/goog/testing/asserts.js</path-element>
+ <path-element>externs/goog/testing/benchmark.js</path-element>
+ <path-element>externs/goog/testing/dom.js</path-element>
+ <path-element>externs/goog/testing/expectedfailures.js</path-element>
+ <path-element>externs/goog/testing/functionmock.js</path-element>
+ <path-element>externs/goog/testing/graphics.js</path-element>
+ <path-element>externs/goog/testing/jsunit.js</path-element>
+ <path-element>externs/goog/testing/loosemock.js</path-element>
+ <path-element>externs/goog/testing/mock.js</path-element>
+ <path-element>externs/goog/testing/mockclassfactory.js</path-element>
+ <path-element>externs/goog/testing/mockclock.js</path-element>
+ <path-element>externs/goog/testing/mockcontrol.js</path-element>
+ <path-element>externs/goog/testing/mockinterface.js</path-element>
+ <path-element>externs/goog/testing/mockmatchers.js</path-element>
+ <path-element>externs/goog/testing/mockrandom.js</path-element>
+ <path-element>externs/goog/testing/mockrange.js</path-element>
+ <path-element>externs/goog/testing/mockstorage.js</path-element>
+ <path-element>externs/goog/testing/mockuseragent.js</path-element>
+ <path-element>externs/goog/testing/objectpropertystring.js</path-element>
+ <path-element>externs/goog/testing/performancetable.js</path-element>
+ <path-element>externs/goog/testing/performancetimer.js</path-element>
+ <path-element>externs/goog/testing/propertyreplacer.js</path-element>
+ <path-element>externs/goog/testing/pseudorandom.js</path-element>
+ <path-element>externs/goog/testing/recordfunction.js</path-element>
+ <path-element>externs/goog/testing/singleton.js</path-element>
+ <path-element>externs/goog/testing/stacktrace.js</path-element>
+ <path-element>externs/goog/testing/strictmock.js</path-element>
+ <path-element>externs/goog/testing/watchers.js</path-element>
+ <path-element>externs/goog/testing/async/mockcontrol.js</path-element>
+ <path-element>externs/goog/testing/editor/dom.js</path-element>
+ <path-element>externs/goog/testing/editor/fieldmock.js</path-element>
+ <path-element>externs/goog/testing/events/eventobserver.js</path-element>
+ <path-element>externs/goog/testing/events/events.js</path-element>
+ <path-element>externs/goog/testing/events/matchers.js</path-element>
+ <path-element>externs/goog/testing/events/onlinehandler.js</path-element>
+ <path-element>externs/goog/testing/fs/blob.js</path-element>
+ <path-element>externs/goog/testing/fs/entry.js</path-element>
+ <path-element>externs/goog/testing/fs/file.js</path-element>
+ <path-element>externs/goog/testing/fs/filereader.js</path-element>
+ <path-element>externs/goog/testing/fs/filesystem.js</path-element>
+ <path-element>externs/goog/testing/fs/filewriter.js</path-element>
+ <path-element>externs/goog/testing/fs/fs.js</path-element>
+ <path-element>externs/goog/testing/fs/progressevent.js</path-element>
+ <path-element>externs/goog/testing/i18n/asserts.js</path-element>
+ <path-element>externs/goog/testing/messaging/mockmessagechannel.js</path-element>
+ <path-element>externs/goog/testing/messaging/mockmessageevent.js</path-element>
+ <path-element>externs/goog/testing/messaging/mockmessageport.js</path-element>
+ <path-element>externs/goog/testing/messaging/mockportnetwork.js</path-element>
+ <path-element>externs/goog/testing/net/xhrio.js</path-element>
+ <path-element>externs/goog/testing/net/xhriopool.js</path-element>
+ <path-element>externs/goog/testing/proto2/proto2.js</path-element>
+ <path-element>externs/goog/testing/storage/fakemechanism.js</path-element>
+ <path-element>externs/goog/testing/style/layoutasserts.js</path-element>
+ <path-element>externs/goog/testing/style/style.js</path-element>
+ <path-element>externs/goog/testing/ui/rendererasserts.js</path-element>
+ <path-element>externs/goog/testing/ui/rendererharness.js</path-element>
+ <path-element>externs/goog/testing/ui/style.js</path-element>
+ <path-element>externs/goog/timer/timer.js</path-element>
+ <path-element>externs/goog/tweak/entries.js</path-element>
+ <path-element>externs/goog/tweak/registry.js</path-element>
+ <path-element>externs/goog/tweak/tweak.js</path-element>
+ <path-element>externs/goog/tweak/tweakui.js</path-element>
+ <path-element>externs/goog/ui/abstractspellchecker.js</path-element>
+ <path-element>externs/goog/ui/activitymonitor.js</path-element>
+ <path-element>externs/goog/ui/advancedtooltip.js</path-element>
+ <path-element>externs/goog/ui/animatedzippy.js</path-element>
+ <path-element>externs/goog/ui/attachablemenu.js</path-element>
+ <path-element>externs/goog/ui/bidiinput.js</path-element>
+ <path-element>externs/goog/ui/bubble.js</path-element>
+ <path-element>externs/goog/ui/button.js</path-element>
+ <path-element>externs/goog/ui/buttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/buttonside.js</path-element>
+ <path-element>externs/goog/ui/charcounter.js</path-element>
+ <path-element>externs/goog/ui/charpicker.js</path-element>
+ <path-element>externs/goog/ui/checkbox.js</path-element>
+ <path-element>externs/goog/ui/checkboxmenuitem.js</path-element>
+ <path-element>externs/goog/ui/checkboxrenderer.js</path-element>
+ <path-element>externs/goog/ui/colorbutton.js</path-element>
+ <path-element>externs/goog/ui/colorbuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/colormenubutton.js</path-element>
+ <path-element>externs/goog/ui/colormenubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/colorpalette.js</path-element>
+ <path-element>externs/goog/ui/colorpicker.js</path-element>
+ <path-element>externs/goog/ui/colorsplitbehavior.js</path-element>
+ <path-element>externs/goog/ui/combobox.js</path-element>
+ <path-element>externs/goog/ui/component.js</path-element>
+ <path-element>externs/goog/ui/container.js</path-element>
+ <path-element>externs/goog/ui/containerrenderer.js</path-element>
+ <path-element>externs/goog/ui/containerscroller.js</path-element>
+ <path-element>externs/goog/ui/control.js</path-element>
+ <path-element>externs/goog/ui/controlcontent.js</path-element>
+ <path-element>externs/goog/ui/controlrenderer.js</path-element>
+ <path-element>externs/goog/ui/cookieeditor.js</path-element>
+ <path-element>externs/goog/ui/css3buttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/css3menubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/cssnames.js</path-element>
+ <path-element>externs/goog/ui/custombutton.js</path-element>
+ <path-element>externs/goog/ui/custombuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/customcolorpalette.js</path-element>
+ <path-element>externs/goog/ui/datepicker.js</path-element>
+ <path-element>externs/goog/ui/datepickerrenderer.js</path-element>
+ <path-element>externs/goog/ui/decorate.js</path-element>
+ <path-element>externs/goog/ui/defaultdatepickerrenderer.js</path-element>
+ <path-element>externs/goog/ui/dialog.js</path-element>
+ <path-element>externs/goog/ui/dimensionpicker.js</path-element>
+ <path-element>externs/goog/ui/dimensionpickerrenderer.js</path-element>
+ <path-element>externs/goog/ui/dragdropdetector.js</path-element>
+ <path-element>externs/goog/ui/drilldownrow.js</path-element>
+ <path-element>externs/goog/ui/filteredmenu.js</path-element>
+ <path-element>externs/goog/ui/filterobservingmenuitem.js</path-element>
+ <path-element>externs/goog/ui/filterobservingmenuitemrenderer.js</path-element>
+ <path-element>externs/goog/ui/flatbuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/flatmenubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/formpost.js</path-element>
+ <path-element>externs/goog/ui/gauge.js</path-element>
+ <path-element>externs/goog/ui/gaugetheme.js</path-element>
+ <path-element>externs/goog/ui/hovercard.js</path-element>
+ <path-element>externs/goog/ui/hsvapalette.js</path-element>
+ <path-element>externs/goog/ui/hsvpalette.js</path-element>
+ <path-element>externs/goog/ui/idgenerator.js</path-element>
+ <path-element>externs/goog/ui/idletimer.js</path-element>
+ <path-element>externs/goog/ui/iframemask.js</path-element>
+ <path-element>externs/goog/ui/imagelessbuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/imagelessmenubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/inputdatepicker.js</path-element>
+ <path-element>externs/goog/ui/itemevent.js</path-element>
+ <path-element>externs/goog/ui/keyboardshortcuthandler.js</path-element>
+ <path-element>externs/goog/ui/labelinput.js</path-element>
+ <path-element>externs/goog/ui/linkbuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/menu.js</path-element>
+ <path-element>externs/goog/ui/menubar.js</path-element>
+ <path-element>externs/goog/ui/menubardecorator.js</path-element>
+ <path-element>externs/goog/ui/menubarrenderer.js</path-element>
+ <path-element>externs/goog/ui/menubase.js</path-element>
+ <path-element>externs/goog/ui/menubutton.js</path-element>
+ <path-element>externs/goog/ui/menubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/menuheader.js</path-element>
+ <path-element>externs/goog/ui/menuheaderrenderer.js</path-element>
+ <path-element>externs/goog/ui/menuitem.js</path-element>
+ <path-element>externs/goog/ui/menuitemrenderer.js</path-element>
+ <path-element>externs/goog/ui/menurenderer.js</path-element>
+ <path-element>externs/goog/ui/menuseparator.js</path-element>
+ <path-element>externs/goog/ui/menuseparatorrenderer.js</path-element>
+ <path-element>externs/goog/ui/mockactivitymonitor.js</path-element>
+ <path-element>externs/goog/ui/modalariavisibilityhelper.js</path-element>
+ <path-element>externs/goog/ui/modalpopup.js</path-element>
+ <path-element>externs/goog/ui/nativebuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/option.js</path-element>
+ <path-element>externs/goog/ui/palette.js</path-element>
+ <path-element>externs/goog/ui/paletterenderer.js</path-element>
+ <path-element>externs/goog/ui/plaintextspellchecker.js</path-element>
+ <path-element>externs/goog/ui/popup.js</path-element>
+ <path-element>externs/goog/ui/popupbase.js</path-element>
+ <path-element>externs/goog/ui/popupcolorpicker.js</path-element>
+ <path-element>externs/goog/ui/popupdatepicker.js</path-element>
+ <path-element>externs/goog/ui/popupmenu.js</path-element>
+ <path-element>externs/goog/ui/progressbar.js</path-element>
+ <path-element>externs/goog/ui/prompt.js</path-element>
+ <path-element>externs/goog/ui/rangemodel.js</path-element>
+ <path-element>externs/goog/ui/ratings.js</path-element>
+ <path-element>externs/goog/ui/registry.js</path-element>
+ <path-element>externs/goog/ui/richtextspellchecker.js</path-element>
+ <path-element>externs/goog/ui/roundedpanel.js</path-element>
+ <path-element>externs/goog/ui/roundedtabrenderer.js</path-element>
+ <path-element>externs/goog/ui/scrollfloater.js</path-element>
+ <path-element>externs/goog/ui/select.js</path-element>
+ <path-element>externs/goog/ui/selectionmenubutton.js</path-element>
+ <path-element>externs/goog/ui/selectionmodel.js</path-element>
+ <path-element>externs/goog/ui/separator.js</path-element>
+ <path-element>externs/goog/ui/serverchart.js</path-element>
+ <path-element>externs/goog/ui/slider.js</path-element>
+ <path-element>externs/goog/ui/sliderbase.js</path-element>
+ <path-element>externs/goog/ui/splitbehavior.js</path-element>
+ <path-element>externs/goog/ui/splitpane.js</path-element>
+ <path-element>externs/goog/ui/submenu.js</path-element>
+ <path-element>externs/goog/ui/submenurenderer.js</path-element>
+ <path-element>externs/goog/ui/tab.js</path-element>
+ <path-element>externs/goog/ui/tabbar.js</path-element>
+ <path-element>externs/goog/ui/tabbarrenderer.js</path-element>
+ <path-element>externs/goog/ui/tablesorter.js</path-element>
+ <path-element>externs/goog/ui/tabpane.js</path-element>
+ <path-element>externs/goog/ui/tabrenderer.js</path-element>
+ <path-element>externs/goog/ui/textarea.js</path-element>
+ <path-element>externs/goog/ui/textarearenderer.js</path-element>
+ <path-element>externs/goog/ui/togglebutton.js</path-element>
+ <path-element>externs/goog/ui/toolbar.js</path-element>
+ <path-element>externs/goog/ui/toolbarbutton.js</path-element>
+ <path-element>externs/goog/ui/toolbarbuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/toolbarcolormenubutton.js</path-element>
+ <path-element>externs/goog/ui/toolbarcolormenubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/toolbarmenubutton.js</path-element>
+ <path-element>externs/goog/ui/toolbarmenubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/toolbarrenderer.js</path-element>
+ <path-element>externs/goog/ui/toolbarselect.js</path-element>
+ <path-element>externs/goog/ui/toolbarseparator.js</path-element>
+ <path-element>externs/goog/ui/toolbarseparatorrenderer.js</path-element>
+ <path-element>externs/goog/ui/toolbartogglebutton.js</path-element>
+ <path-element>externs/goog/ui/tooltip.js</path-element>
+ <path-element>externs/goog/ui/tristatemenuitem.js</path-element>
+ <path-element>externs/goog/ui/tristatemenuitemrenderer.js</path-element>
+ <path-element>externs/goog/ui/twothumbslider.js</path-element>
+ <path-element>externs/goog/ui/zippy.js</path-element>
+ <path-element>externs/goog/ui/ac/ac.js</path-element>
+ <path-element>externs/goog/ui/ac/arraymatcher.js</path-element>
+ <path-element>externs/goog/ui/ac/autocomplete.js</path-element>
+ <path-element>externs/goog/ui/ac/cachingmatcher.js</path-element>
+ <path-element>externs/goog/ui/ac/inputhandler.js</path-element>
+ <path-element>externs/goog/ui/ac/remote.js</path-element>
+ <path-element>externs/goog/ui/ac/remotearraymatcher.js</path-element>
+ <path-element>externs/goog/ui/ac/renderer.js</path-element>
+ <path-element>externs/goog/ui/ac/renderoptions.js</path-element>
+ <path-element>externs/goog/ui/ac/richinputhandler.js</path-element>
+ <path-element>externs/goog/ui/ac/richremote.js</path-element>
+ <path-element>externs/goog/ui/ac/richremotearraymatcher.js</path-element>
+ <path-element>externs/goog/ui/editor/abstractdialog.js</path-element>
+ <path-element>externs/goog/ui/editor/bubble.js</path-element>
+ <path-element>externs/goog/ui/editor/defaulttoolbar.js</path-element>
+ <path-element>externs/goog/ui/editor/linkdialog.js</path-element>
+ <path-element>externs/goog/ui/editor/messages.js</path-element>
+ <path-element>externs/goog/ui/editor/tabpane.js</path-element>
+ <path-element>externs/goog/ui/editor/toolbarcontroller.js</path-element>
+ <path-element>externs/goog/ui/editor/toolbarfactory.js</path-element>
+ <path-element>externs/goog/ui/emoji/emoji.js</path-element>
+ <path-element>externs/goog/ui/emoji/emojipalette.js</path-element>
+ <path-element>externs/goog/ui/emoji/emojipaletterenderer.js</path-element>
+ <path-element>externs/goog/ui/emoji/emojipicker.js</path-element>
+ <path-element>externs/goog/ui/emoji/popupemojipicker.js</path-element>
+ <path-element>externs/goog/ui/emoji/progressiveemojipaletterenderer.js</path-element>
+ <path-element>externs/goog/ui/emoji/spriteinfo.js</path-element>
+ <path-element>externs/goog/ui/media/flashobject.js</path-element>
+ <path-element>externs/goog/ui/media/flickr.js</path-element>
+ <path-element>externs/goog/ui/media/googlevideo.js</path-element>
+ <path-element>externs/goog/ui/media/media.js</path-element>
+ <path-element>externs/goog/ui/media/mediamodel.js</path-element>
+ <path-element>externs/goog/ui/media/mp3.js</path-element>
+ <path-element>externs/goog/ui/media/photo.js</path-element>
+ <path-element>externs/goog/ui/media/picasa.js</path-element>
+ <path-element>externs/goog/ui/media/vimeo.js</path-element>
+ <path-element>externs/goog/ui/media/youtube.js</path-element>
+ <path-element>externs/goog/ui/style/app/buttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/style/app/menubuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/style/app/primaryactionbuttonrenderer.js</path-element>
+ <path-element>externs/goog/ui/tree/basenode.js</path-element>
+ <path-element>externs/goog/ui/tree/treecontrol.js</path-element>
+ <path-element>externs/goog/ui/tree/treenode.js</path-element>
+ <path-element>externs/goog/ui/tree/typeahead.js</path-element>
+ <path-element>externs/goog/uri/uri.js</path-element>
+ <path-element>externs/goog/uri/utils.js</path-element>
+ <path-element>externs/goog/useragent/adobereader.js</path-element>
+ <path-element>externs/goog/useragent/flash.js</path-element>
+ <path-element>externs/goog/useragent/iphoto.js</path-element>
+ <path-element>externs/goog/useragent/jscript.js</path-element>
+ <path-element>externs/goog/useragent/keyboard.js</path-element>
+ <path-element>externs/goog/useragent/platform.js</path-element>
+ <path-element>externs/goog/useragent/product.js</path-element>
+ <path-element>externs/goog/useragent/product_isversion.js</path-element>
+ <path-element>externs/goog/useragent/useragent.js</path-element>
+ <path-element>externs/goog/vec/float32array.js</path-element>
+ <path-element>externs/goog/vec/float64array.js</path-element>
+ <path-element>externs/goog/vec/mat3.js</path-element>
+ <path-element>externs/goog/vec/mat3d.js</path-element>
+ <path-element>externs/goog/vec/mat3f.js</path-element>
+ <path-element>externs/goog/vec/mat4.js</path-element>
+ <path-element>externs/goog/vec/mat4d.js</path-element>
+ <path-element>externs/goog/vec/mat4f.js</path-element>
+ <path-element>externs/goog/vec/matrix3.js</path-element>
+ <path-element>externs/goog/vec/matrix4.js</path-element>
+ <path-element>externs/goog/vec/quaternion.js</path-element>
+ <path-element>externs/goog/vec/ray.js</path-element>
+ <path-element>externs/goog/vec/vec.js</path-element>
+ <path-element>externs/goog/vec/vec2.js</path-element>
+ <path-element>externs/goog/vec/vec2d.js</path-element>
+ <path-element>externs/goog/vec/vec2f.js</path-element>
+ <path-element>externs/goog/vec/vec3.js</path-element>
+ <path-element>externs/goog/vec/vec3d.js</path-element>
+ <path-element>externs/goog/vec/vec3f.js</path-element>
+ <path-element>externs/goog/vec/vec4.js</path-element>
+ <path-element>externs/goog/vec/vec4d.js</path-element>
+ <path-element>externs/goog/vec/vec4f.js</path-element>
+ <path-element>externs/goog/webgl/webgl.js</path-element>
+ <path-element>externs/goog/window/window.js</path-element>-->
+ </external>
+
+</flex-config>
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/compile-config.xml
----------------------------------------------------------------------
diff --git a/externs/GCL/compile-config.xml b/externs/GCL/compile-config.xml
new file mode 100644
index 0000000..e8b8911
--- /dev/null
+++ b/externs/GCL/compile-config.xml
@@ -0,0 +1,99 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<flex-config>
+
+ <compiler>
+
+ <accessible>true</accessible>
+
+ <!--
+ <external-library-path>
+ <path-element>${env.PLAYERGLOBAL_HOME}/${playerglobal.version}/playerglobal.swc</path-element>
+ <path-element>../../libs/framework.swc</path-element>
+ <path-element>../../libs/mx/mx.swc</path-element>
+ <path-element>../../libs/osmf.swc</path-element>
+ <path-element>../../libs/textLayout.swc</path-element>
+ </external-library-path>
+
+ <keep-as3-metadata>
+ <name>SkinPart</name>
+ </keep-as3-metadata>
+
+ <mxml>
+ <minimum-supported-version>4.0.0</minimum-supported-version>
+ </mxml>
+
+ <locale/>
+
+ <library-path/>
+
+ <namespaces>
+ <namespace>
+ <uri>library://ns.adobe.com/flex/spark</uri>
+ <manifest>manifest.xml</manifest>
+ </namespace>
+ </namespaces>
+ -->
+
+ <source-path>
+ <path-element>src</path-element>
+ <!--<path-element>out/as/classes</path-element>
+ <path-element>out/as/interfaces</path-element>
+ <path-element>out/as/constants</path-element>
+ <path-element>out/as/functions</path-element>
+ <path-element>out/as/interfaces</path-element>
+ <path-element>out/as/typedefs</path-element>-->
+ </source-path>
+
+ <warn-no-constructor>false</warn-no-constructor>
+ </compiler>
+
+ <include-sources>
+ <path-element>src</path-element>
+ <!--<path-element>out/as/classes</path-element>
+ <path-element>out/as/interfaces</path-element>
+ <path-element>out/as/constants</path-element>
+ <path-element>out/as/functions</path-element>
+ <path-element>out/as/interfaces</path-element>
+ <path-element>out/as/typedefs</path-element>-->
+ </include-sources>
+
+ <!--
+ <include-file>
+ <name>defaults.css</name>
+ <path>defaults.css</path>
+ </include-file>
+ <include-file>
+ <name>assets/ErrorIndicator.png</name>
+ <path>assets/ErrorIndicator.png</path>
+ </include-file>
+ <include-file>
+ <name>assets/RequiredIndicator.png</name>
+ <path>assets/RequiredIndicator.png</path>
+ </include-file>
+
+ <include-namespaces>
+ <uri>library://ns.adobe.com/flex/spark</uri>
+ </include-namespaces>
+
+ <resource-bundle-list>bundles.properties</resource-bundle-list>
+
+ <target-player>${playerglobal.version}</target-player>
+ -->
+</flex-config>
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/a11y/aria/announcer.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/a11y/aria/announcer.js b/externs/GCL/externs/goog/a11y/aria/announcer.js
new file mode 100644
index 0000000..6818264
--- /dev/null
+++ b/externs/GCL/externs/goog/a11y/aria/announcer.js
@@ -0,0 +1,123 @@
+// 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 Announcer that allows messages to be spoken by assistive
+ * technologies.
+ */
+
+goog.provide('goog.a11y.aria.Announcer');
+
+goog.require('goog.Disposable');
+goog.require('goog.Timer');
+goog.require('goog.a11y.aria');
+goog.require('goog.a11y.aria.LivePriority');
+goog.require('goog.a11y.aria.State');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.object');
+
+
+
+/**
+ * Class that allows messages to be spoken by assistive technologies that the
+ * user may have active.
+ *
+ * @param {goog.dom.DomHelper=} opt_domHelper DOM helper.
+ * @constructor
+ * @extends {goog.Disposable}
+ * @final
+ */
+goog.a11y.aria.Announcer = function(opt_domHelper) {
+ goog.a11y.aria.Announcer.base(this, 'constructor');
+
+ /**
+ * @type {goog.dom.DomHelper}
+ * @private
+ */
+ this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
+
+ /**
+ * Map of priority to live region elements to use for communicating updates.
+ * Elements are created on demand.
+ * @type {Object<goog.a11y.aria.LivePriority, !Element>}
+ * @private
+ */
+ this.liveRegions_ = {};
+};
+goog.inherits(goog.a11y.aria.Announcer, goog.Disposable);
+
+
+/** @override */
+goog.a11y.aria.Announcer.prototype.disposeInternal = function() {
+ goog.object.forEach(
+ this.liveRegions_, this.domHelper_.removeNode, this.domHelper_);
+ this.liveRegions_ = null;
+ this.domHelper_ = null;
+ goog.a11y.aria.Announcer.base(this, 'disposeInternal');
+};
+
+
+/**
+ * Announce a message to be read by any assistive technologies the user may
+ * have active.
+ * @param {string} message The message to announce to screen readers.
+ * @param {goog.a11y.aria.LivePriority=} opt_priority The priority of the
+ * message. Defaults to POLITE.
+ */
+goog.a11y.aria.Announcer.prototype.say = function(message, opt_priority) {
+ var priority = opt_priority || goog.a11y.aria.LivePriority.POLITE;
+ var liveRegion = this.getLiveRegion_(priority);
+ // Resets text content to force a DOM mutation (so that the setTextContent
+ // post-timeout function will be noticed by the screen reader). This is to
+ // avoid the problem of when the same message is "said" twice, which doesn't
+ // trigger a DOM mutation.
+ goog.dom.setTextContent(liveRegion, '');
+ // Uses non-zero timer to make VoiceOver and NVDA work
+ goog.Timer.callOnce(function() {
+ goog.dom.setTextContent(liveRegion, message);
+ }, 1);
+};
+
+
+/**
+ * Returns an aria-live region that can be used to communicate announcements.
+ * @param {!goog.a11y.aria.LivePriority} priority The required priority.
+ * @return {!Element} A live region of the requested priority.
+ * @private
+ */
+goog.a11y.aria.Announcer.prototype.getLiveRegion_ = function(priority) {
+ var liveRegion = this.liveRegions_[priority];
+ if (liveRegion) {
+ // Make sure the live region is not aria-hidden.
+ goog.a11y.aria.removeState(liveRegion, goog.a11y.aria.State.HIDDEN);
+ return liveRegion;
+ }
+
+ liveRegion = this.domHelper_.createElement(goog.dom.TagName.DIV);
+ // Note that IE has a habit of declaring things that aren't display:none as
+ // invisible to third-party tools like JAWs, so we can't just use height:0.
+ liveRegion.style.position = 'absolute';
+ liveRegion.style.top = '-1000px';
+ liveRegion.style.height = '1px';
+ liveRegion.style.overflow = 'hidden';
+ goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.LIVE,
+ priority);
+ goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.ATOMIC,
+ 'true');
+ this.domHelper_.getDocument().body.appendChild(liveRegion);
+ this.liveRegions_[priority] = liveRegion;
+ return liveRegion;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/a11y/aria/aria.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/a11y/aria/aria.js b/externs/GCL/externs/goog/a11y/aria/aria.js
new file mode 100644
index 0000000..1220d23
--- /dev/null
+++ b/externs/GCL/externs/goog/a11y/aria/aria.js
@@ -0,0 +1,386 @@
+// 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 adding, removing and setting ARIA roles and
+ * states as defined by W3C ARIA standard: http://www.w3.org/TR/wai-aria/
+ * All modern browsers have some form of ARIA support, so no browser checks are
+ * performed when adding ARIA to components.
+ *
+ */
+
+goog.provide('goog.a11y.aria');
+
+goog.require('goog.a11y.aria.Role');
+goog.require('goog.a11y.aria.State');
+goog.require('goog.a11y.aria.datatables');
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.object');
+goog.require('goog.string');
+
+
+/**
+ * ARIA states/properties prefix.
+ * @private
+ */
+goog.a11y.aria.ARIA_PREFIX_ = 'aria-';
+
+
+/**
+ * ARIA role attribute.
+ * @private
+ */
+goog.a11y.aria.ROLE_ATTRIBUTE_ = 'role';
+
+
+/**
+ * A list of tag names for which we don't need to set ARIA role and states
+ * because they have well supported semantics for screen readers or because
+ * they don't contain content to be made accessible.
+ * @private
+ */
+goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_ = [
+ goog.dom.TagName.A,
+ goog.dom.TagName.AREA,
+ goog.dom.TagName.BUTTON,
+ goog.dom.TagName.HEAD,
+ goog.dom.TagName.INPUT,
+ goog.dom.TagName.LINK,
+ goog.dom.TagName.MENU,
+ goog.dom.TagName.META,
+ goog.dom.TagName.OPTGROUP,
+ goog.dom.TagName.OPTION,
+ goog.dom.TagName.PROGRESS,
+ goog.dom.TagName.STYLE,
+ goog.dom.TagName.SELECT,
+ goog.dom.TagName.SOURCE,
+ goog.dom.TagName.TEXTAREA,
+ goog.dom.TagName.TITLE,
+ goog.dom.TagName.TRACK
+];
+
+
+/**
+ * Sets the role of an element. If the roleName is
+ * empty string or null, the role for the element is removed.
+ * We encourage clients to call the goog.a11y.aria.removeRole
+ * method instead of setting null and empty string values.
+ * Special handling for this case is added to ensure
+ * backword compatibility with existing code.
+ *
+ * @param {!Element} element DOM node to set role of.
+ * @param {!goog.a11y.aria.Role|string} roleName role name(s).
+ */
+goog.a11y.aria.setRole = function(element, roleName) {
+ if (!roleName) {
+ // Setting the ARIA role to empty string is not allowed
+ // by the ARIA standard.
+ goog.a11y.aria.removeRole(element);
+ } else {
+ if (goog.asserts.ENABLE_ASSERTS) {
+ goog.asserts.assert(goog.object.containsValue(
+ goog.a11y.aria.Role, roleName), 'No such ARIA role ' + roleName);
+ }
+ element.setAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_, roleName);
+ }
+};
+
+
+/**
+ * Gets role of an element.
+ * @param {!Element} element DOM element to get role of.
+ * @return {goog.a11y.aria.Role} ARIA Role name.
+ */
+goog.a11y.aria.getRole = function(element) {
+ var role = element.getAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_);
+ return /** @type {goog.a11y.aria.Role} */ (role) || null;
+};
+
+
+/**
+ * Removes role of an element.
+ * @param {!Element} element DOM element to remove the role from.
+ */
+goog.a11y.aria.removeRole = function(element) {
+ element.removeAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_);
+};
+
+
+/**
+ * Sets the state or property of an element.
+ * @param {!Element} element DOM node where we set state.
+ * @param {!(goog.a11y.aria.State|string)} stateName State attribute being set.
+ * Automatically adds prefix 'aria-' to the state name if the attribute is
+ * not an extra attribute.
+ * @param {string|boolean|number|!Array<string>} value Value
+ * for the state attribute.
+ */
+goog.a11y.aria.setState = function(element, stateName, value) {
+ if (goog.isArray(value)) {
+ value = value.join(' ');
+ }
+ var attrStateName = goog.a11y.aria.getAriaAttributeName_(stateName);
+ if (value === '' || value == undefined) {
+ var defaultValueMap = goog.a11y.aria.datatables.getDefaultValuesMap();
+ // Work around for browsers that don't properly support ARIA.
+ // According to the ARIA W3C standard, user agents should allow
+ // setting empty value which results in setting the default value
+ // for the ARIA state if such exists. The exact text from the ARIA W3C
+ // standard (http://www.w3.org/TR/wai-aria/states_and_properties):
+ // "When a value is indicated as the default, the user agent
+ // MUST follow the behavior prescribed by this value when the state or
+ // property is empty or undefined."
+ // The defaultValueMap contains the default values for the ARIA states
+ // and has as a key the goog.a11y.aria.State constant for the state.
+ if (stateName in defaultValueMap) {
+ element.setAttribute(attrStateName, defaultValueMap[stateName]);
+ } else {
+ element.removeAttribute(attrStateName);
+ }
+ } else {
+ element.setAttribute(attrStateName, value);
+ }
+};
+
+
+/**
+ * Toggles the ARIA attribute of an element.
+ * Meant for attributes with a true/false value, but works with any attribute.
+ * If the attribute does not have a true/false value, the following rules apply:
+ * A not empty attribute will be removed.
+ * An empty attribute will be set to true.
+ * @param {!Element} el DOM node for which to set attribute.
+ * @param {!(goog.a11y.aria.State|string)} attr ARIA attribute being set.
+ * Automatically adds prefix 'aria-' to the attribute name if the attribute
+ * is not an extra attribute.
+ */
+goog.a11y.aria.toggleState = function(el, attr) {
+ var val = goog.a11y.aria.getState(el, attr);
+ if (!goog.string.isEmptyOrWhitespace(goog.string.makeSafe(val)) &&
+ !(val == 'true' || val == 'false')) {
+ goog.a11y.aria.removeState(el, /** @type {!goog.a11y.aria.State} */ (attr));
+ return;
+ }
+ goog.a11y.aria.setState(el, attr, val == 'true' ? 'false' : 'true');
+};
+
+
+/**
+ * Remove the state or property for the element.
+ * @param {!Element} element DOM node where we set state.
+ * @param {!goog.a11y.aria.State} stateName State name.
+ */
+goog.a11y.aria.removeState = function(element, stateName) {
+ element.removeAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
+};
+
+
+/**
+ * Gets value of specified state or property.
+ * @param {!Element} element DOM node to get state from.
+ * @param {!goog.a11y.aria.State|string} stateName State name.
+ * @return {string} Value of the state attribute.
+ */
+goog.a11y.aria.getState = function(element, stateName) {
+ // TODO(user): return properly typed value result --
+ // boolean, number, string, null. We should be able to chain
+ // getState(...) and setState(...) methods.
+
+ var attr =
+ /** @type {string|number|boolean} */ (element.getAttribute(
+ goog.a11y.aria.getAriaAttributeName_(stateName)));
+ var isNullOrUndefined = attr == null || attr == undefined;
+ return isNullOrUndefined ? '' : String(attr);
+};
+
+
+/**
+ * Returns the activedescendant element for the input element by
+ * using the activedescendant ARIA property of the given element.
+ * @param {!Element} element DOM node to get activedescendant
+ * element for.
+ * @return {?Element} DOM node of the activedescendant, if found.
+ */
+goog.a11y.aria.getActiveDescendant = function(element) {
+ var id = goog.a11y.aria.getState(
+ element, goog.a11y.aria.State.ACTIVEDESCENDANT);
+ return goog.dom.getOwnerDocument(element).getElementById(id);
+};
+
+
+/**
+ * Sets the activedescendant ARIA property value for an element.
+ * If the activeElement is not null, it should have an id set.
+ * @param {!Element} element DOM node to set activedescendant ARIA property to.
+ * @param {?Element} activeElement DOM node being set as activedescendant.
+ */
+goog.a11y.aria.setActiveDescendant = function(element, activeElement) {
+ var id = '';
+ if (activeElement) {
+ id = activeElement.id;
+ goog.asserts.assert(id, 'The active element should have an id.');
+ }
+
+ goog.a11y.aria.setState(element, goog.a11y.aria.State.ACTIVEDESCENDANT, id);
+};
+
+
+/**
+ * Gets the label of the given element.
+ * @param {!Element} element DOM node to get label from.
+ * @return {string} label The label.
+ */
+goog.a11y.aria.getLabel = function(element) {
+ return goog.a11y.aria.getState(element, goog.a11y.aria.State.LABEL);
+};
+
+
+/**
+ * Sets the label of the given element.
+ * @param {!Element} element DOM node to set label to.
+ * @param {string} label The label to set.
+ */
+goog.a11y.aria.setLabel = function(element, label) {
+ goog.a11y.aria.setState(element, goog.a11y.aria.State.LABEL, label);
+};
+
+
+/**
+ * Asserts that the element has a role set if it's not an HTML element whose
+ * semantics is well supported by most screen readers.
+ * Only to be used internally by the ARIA library in goog.a11y.aria.*.
+ * @param {!Element} element The element to assert an ARIA role set.
+ * @param {!goog.array.ArrayLike<string>} allowedRoles The child roles of
+ * the roles.
+ */
+goog.a11y.aria.assertRoleIsSetInternalUtil = function(element, allowedRoles) {
+ if (goog.array.contains(goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_,
+ element.tagName)) {
+ return;
+ }
+ var elementRole = /** @type {string}*/ (goog.a11y.aria.getRole(element));
+ goog.asserts.assert(elementRole != null,
+ 'The element ARIA role cannot be null.');
+
+ goog.asserts.assert(goog.array.contains(allowedRoles, elementRole),
+ 'Non existing or incorrect role set for element.' +
+ 'The role set is "' + elementRole +
+ '". The role should be any of "' + allowedRoles +
+ '". Check the ARIA specification for more details ' +
+ 'http://www.w3.org/TR/wai-aria/roles.');
+};
+
+
+/**
+ * Gets the boolean value of an ARIA state/property.
+ * @param {!Element} element The element to get the ARIA state for.
+ * @param {!goog.a11y.aria.State|string} stateName the ARIA state name.
+ * @return {?boolean} Boolean value for the ARIA state value or null if
+ * the state value is not 'true', not 'false', or not set.
+ */
+goog.a11y.aria.getStateBoolean = function(element, stateName) {
+ var attr =
+ /** @type {string|boolean} */ (element.getAttribute(
+ goog.a11y.aria.getAriaAttributeName_(stateName)));
+ goog.asserts.assert(
+ goog.isBoolean(attr) || attr == null || attr == 'true' ||
+ attr == 'false');
+ if (attr == null) {
+ return attr;
+ }
+ return goog.isBoolean(attr) ? attr : attr == 'true';
+};
+
+
+/**
+ * Gets the number value of an ARIA state/property.
+ * @param {!Element} element The element to get the ARIA state for.
+ * @param {!goog.a11y.aria.State|string} stateName the ARIA state name.
+ * @return {?number} Number value for the ARIA state value or null if
+ * the state value is not a number or not set.
+ */
+goog.a11y.aria.getStateNumber = function(element, stateName) {
+ var attr =
+ /** @type {string|number} */ (element.getAttribute(
+ goog.a11y.aria.getAriaAttributeName_(stateName)));
+ goog.asserts.assert((attr == null || !isNaN(Number(attr))) &&
+ !goog.isBoolean(attr));
+ return attr == null ? null : Number(attr);
+};
+
+
+/**
+ * Gets the string value of an ARIA state/property.
+ * @param {!Element} element The element to get the ARIA state for.
+ * @param {!goog.a11y.aria.State|string} stateName the ARIA state name.
+ * @return {?string} String value for the ARIA state value or null if
+ * the state value is empty string or not set.
+ */
+goog.a11y.aria.getStateString = function(element, stateName) {
+ var attr = element.getAttribute(
+ goog.a11y.aria.getAriaAttributeName_(stateName));
+ goog.asserts.assert((attr == null || goog.isString(attr)) &&
+ isNaN(Number(attr)) && attr != 'true' && attr != 'false');
+ return attr == null ? null : attr;
+};
+
+
+/**
+ * Gets array of strings value of the specified state or
+ * property for the element.
+ * Only to be used internally by the ARIA library in goog.a11y.aria.*.
+ * @param {!Element} element DOM node to get state from.
+ * @param {!goog.a11y.aria.State} stateName State name.
+ * @return {!goog.array.ArrayLike<string>} string Array
+ * value of the state attribute.
+ */
+goog.a11y.aria.getStringArrayStateInternalUtil = function(element, stateName) {
+ var attrValue = element.getAttribute(
+ goog.a11y.aria.getAriaAttributeName_(stateName));
+ return goog.a11y.aria.splitStringOnWhitespace_(attrValue);
+};
+
+
+/**
+ * Splits the input stringValue on whitespace.
+ * @param {string} stringValue The value of the string to split.
+ * @return {!goog.array.ArrayLike<string>} string Array
+ * value as result of the split.
+ * @private
+ */
+goog.a11y.aria.splitStringOnWhitespace_ = function(stringValue) {
+ return stringValue ? stringValue.split(/\s+/) : [];
+};
+
+
+/**
+ * Adds the 'aria-' prefix to ariaName.
+ * @param {string} ariaName ARIA state/property name.
+ * @private
+ * @return {string} The ARIA attribute name with added 'aria-' prefix.
+ * @throws {Error} If no such attribute exists.
+ */
+goog.a11y.aria.getAriaAttributeName_ = function(ariaName) {
+ if (goog.asserts.ENABLE_ASSERTS) {
+ goog.asserts.assert(ariaName, 'ARIA attribute cannot be empty.');
+ goog.asserts.assert(goog.object.containsValue(
+ goog.a11y.aria.State, ariaName),
+ 'No such ARIA attribute ' + ariaName);
+ }
+ return goog.a11y.aria.ARIA_PREFIX_ + ariaName;
+};
[12/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/transitionbase.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/transitionbase.js b/externs/GCL/externs/goog/fx/transitionbase.js
new file mode 100644
index 0000000..0a2c184
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/transitionbase.js
@@ -0,0 +1,236 @@
+// 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 An abstract base class for transitions. This is a simple
+ * interface that allows for playing, pausing and stopping an animation. It adds
+ * a simple event model, and animation status.
+ */
+goog.provide('goog.fx.TransitionBase');
+goog.provide('goog.fx.TransitionBase.State');
+
+goog.require('goog.events.EventTarget');
+goog.require('goog.fx.Transition'); // Unreferenced: interface
+
+
+
+/**
+ * Constructor for a transition object.
+ *
+ * @constructor
+ * @implements {goog.fx.Transition}
+ * @extends {goog.events.EventTarget}
+ */
+goog.fx.TransitionBase = function() {
+ goog.fx.TransitionBase.base(this, 'constructor');
+
+ /**
+ * The internal state of the animation.
+ * @type {goog.fx.TransitionBase.State}
+ * @private
+ */
+ this.state_ = goog.fx.TransitionBase.State.STOPPED;
+
+ /**
+ * Timestamp for when the animation was started.
+ * @type {?number}
+ * @protected
+ */
+ this.startTime = null;
+
+ /**
+ * Timestamp for when the animation finished or was stopped.
+ * @type {?number}
+ * @protected
+ */
+ this.endTime = null;
+};
+goog.inherits(goog.fx.TransitionBase, goog.events.EventTarget);
+
+
+/**
+ * Enum for the possible states of an animation.
+ * @enum {number}
+ */
+goog.fx.TransitionBase.State = {
+ STOPPED: 0,
+ PAUSED: -1,
+ PLAYING: 1
+};
+
+
+/**
+ * Plays the animation.
+ *
+ * @param {boolean=} opt_restart Optional parameter to restart the animation.
+ * @return {boolean} True iff the animation was started.
+ * @override
+ */
+goog.fx.TransitionBase.prototype.play = goog.abstractMethod;
+
+
+/**
+ * Stops the animation.
+ *
+ * @param {boolean=} opt_gotoEnd Optional boolean parameter to go the the end of
+ * the animation.
+ * @override
+ */
+goog.fx.TransitionBase.prototype.stop = goog.abstractMethod;
+
+
+/**
+ * Pauses the animation.
+ */
+goog.fx.TransitionBase.prototype.pause = goog.abstractMethod;
+
+
+/**
+ * Returns the current state of the animation.
+ * @return {goog.fx.TransitionBase.State} State of the animation.
+ */
+goog.fx.TransitionBase.prototype.getStateInternal = function() {
+ return this.state_;
+};
+
+
+/**
+ * Sets the current state of the animation to playing.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.setStatePlaying = function() {
+ this.state_ = goog.fx.TransitionBase.State.PLAYING;
+};
+
+
+/**
+ * Sets the current state of the animation to paused.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.setStatePaused = function() {
+ this.state_ = goog.fx.TransitionBase.State.PAUSED;
+};
+
+
+/**
+ * Sets the current state of the animation to stopped.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.setStateStopped = function() {
+ this.state_ = goog.fx.TransitionBase.State.STOPPED;
+};
+
+
+/**
+ * @return {boolean} True iff the current state of the animation is playing.
+ */
+goog.fx.TransitionBase.prototype.isPlaying = function() {
+ return this.state_ == goog.fx.TransitionBase.State.PLAYING;
+};
+
+
+/**
+ * @return {boolean} True iff the current state of the animation is paused.
+ */
+goog.fx.TransitionBase.prototype.isPaused = function() {
+ return this.state_ == goog.fx.TransitionBase.State.PAUSED;
+};
+
+
+/**
+ * @return {boolean} True iff the current state of the animation is stopped.
+ */
+goog.fx.TransitionBase.prototype.isStopped = function() {
+ return this.state_ == goog.fx.TransitionBase.State.STOPPED;
+};
+
+
+/**
+ * Dispatches the BEGIN event. Sub classes should override this instead
+ * of listening to the event, and call this instead of dispatching the event.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.onBegin = function() {
+ this.dispatchAnimationEvent(goog.fx.Transition.EventType.BEGIN);
+};
+
+
+/**
+ * Dispatches the END event. Sub classes should override this instead
+ * of listening to the event, and call this instead of dispatching the event.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.onEnd = function() {
+ this.dispatchAnimationEvent(goog.fx.Transition.EventType.END);
+};
+
+
+/**
+ * Dispatches the FINISH event. Sub classes should override this instead
+ * of listening to the event, and call this instead of dispatching the event.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.onFinish = function() {
+ this.dispatchAnimationEvent(goog.fx.Transition.EventType.FINISH);
+};
+
+
+/**
+ * Dispatches the PAUSE event. Sub classes should override this instead
+ * of listening to the event, and call this instead of dispatching the event.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.onPause = function() {
+ this.dispatchAnimationEvent(goog.fx.Transition.EventType.PAUSE);
+};
+
+
+/**
+ * Dispatches the PLAY event. Sub classes should override this instead
+ * of listening to the event, and call this instead of dispatching the event.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.onPlay = function() {
+ this.dispatchAnimationEvent(goog.fx.Transition.EventType.PLAY);
+};
+
+
+/**
+ * Dispatches the RESUME event. Sub classes should override this instead
+ * of listening to the event, and call this instead of dispatching the event.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.onResume = function() {
+ this.dispatchAnimationEvent(goog.fx.Transition.EventType.RESUME);
+};
+
+
+/**
+ * Dispatches the STOP event. Sub classes should override this instead
+ * of listening to the event, and call this instead of dispatching the event.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.onStop = function() {
+ this.dispatchAnimationEvent(goog.fx.Transition.EventType.STOP);
+};
+
+
+/**
+ * Dispatches an event object for the current animation.
+ * @param {string} type Event type that will be dispatched.
+ * @protected
+ */
+goog.fx.TransitionBase.prototype.dispatchAnimationEvent = function(type) {
+ this.dispatchEvent(type);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/abstractgraphics.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/abstractgraphics.js b/externs/GCL/externs/goog/graphics/abstractgraphics.js
new file mode 100644
index 0000000..0ae1776
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/abstractgraphics.js
@@ -0,0 +1,454 @@
+// 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 Graphics utility functions and factory methods.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.AbstractGraphics');
+
+goog.require('goog.dom');
+goog.require('goog.graphics.Path');
+goog.require('goog.math.Coordinate');
+goog.require('goog.math.Size');
+goog.require('goog.style');
+goog.require('goog.ui.Component');
+
+
+
+/**
+ * Base class for the different graphics. You should never construct objects
+ * of this class. Instead us goog.graphics.createGraphics
+ * @param {number|string} width The width in pixels or percent.
+ * @param {number|string} height The height in pixels or percent.
+ * @param {?number=} opt_coordWidth Optional coordinate system width - if
+ * omitted or null, defaults to same as width.
+ * @param {?number=} opt_coordHeight Optional coordinate system height - if
+ * omitted or null, defaults to same as height.
+ * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
+ * document we want to render in.
+ * @constructor
+ * @extends {goog.ui.Component}
+ */
+goog.graphics.AbstractGraphics = function(width, height,
+ opt_coordWidth, opt_coordHeight,
+ opt_domHelper) {
+ goog.ui.Component.call(this, opt_domHelper);
+
+ /**
+ * Width of graphics in pixels or percentage points.
+ * @type {number|string}
+ * @protected
+ */
+ this.width = width;
+
+ /**
+ * Height of graphics in pixels or precentage points.
+ * @type {number|string}
+ * @protected
+ */
+ this.height = height;
+
+ /**
+ * Width of coordinate system in units.
+ * @type {?number}
+ * @protected
+ */
+ this.coordWidth = opt_coordWidth || null;
+
+ /**
+ * Height of coordinate system in units.
+ * @type {?number}
+ * @protected
+ */
+ this.coordHeight = opt_coordHeight || null;
+};
+goog.inherits(goog.graphics.AbstractGraphics, goog.ui.Component);
+
+
+/**
+ * The root level group element.
+ * @type {goog.graphics.GroupElement?}
+ * @protected
+ */
+goog.graphics.AbstractGraphics.prototype.canvasElement = null;
+
+
+/**
+ * Left coordinate of the view box
+ * @type {number}
+ * @protected
+ */
+goog.graphics.AbstractGraphics.prototype.coordLeft = 0;
+
+
+/**
+ * Top coordinate of the view box
+ * @type {number}
+ * @protected
+ */
+goog.graphics.AbstractGraphics.prototype.coordTop = 0;
+
+
+/**
+ * @return {goog.graphics.GroupElement} The root level canvas element.
+ */
+goog.graphics.AbstractGraphics.prototype.getCanvasElement = function() {
+ return this.canvasElement;
+};
+
+
+/**
+ * Changes the coordinate size.
+ * @param {number} coordWidth The coordinate width.
+ * @param {number} coordHeight The coordinate height.
+ */
+goog.graphics.AbstractGraphics.prototype.setCoordSize = function(coordWidth,
+ coordHeight) {
+ this.coordWidth = coordWidth;
+ this.coordHeight = coordHeight;
+};
+
+
+/**
+ * @return {goog.math.Size} The coordinate size.
+ */
+goog.graphics.AbstractGraphics.prototype.getCoordSize = function() {
+ if (this.coordWidth) {
+ return new goog.math.Size(this.coordWidth,
+ /** @type {number} */ (this.coordHeight));
+ } else {
+ return this.getPixelSize();
+ }
+};
+
+
+/**
+ * Changes the coordinate system position.
+ * @param {number} left The coordinate system left bound.
+ * @param {number} top The coordinate system top bound.
+ */
+goog.graphics.AbstractGraphics.prototype.setCoordOrigin = goog.abstractMethod;
+
+
+/**
+ * @return {!goog.math.Coordinate} The coordinate system position.
+ */
+goog.graphics.AbstractGraphics.prototype.getCoordOrigin = function() {
+ return new goog.math.Coordinate(this.coordLeft, this.coordTop);
+};
+
+
+/**
+ * Change the size of the canvas.
+ * @param {number} pixelWidth The width in pixels.
+ * @param {number} pixelHeight The height in pixels.
+ */
+goog.graphics.AbstractGraphics.prototype.setSize = goog.abstractMethod;
+
+
+/**
+ * @return {goog.math.Size} The size of canvas.
+ * @deprecated Use getPixelSize.
+ */
+goog.graphics.AbstractGraphics.prototype.getSize = function() {
+ return this.getPixelSize();
+};
+
+
+/**
+ * @return {goog.math.Size?} Returns the number of pixels spanned by the
+ * surface, or null if the size could not be computed due to the size being
+ * specified in percentage points and the component not being in the
+ * document.
+ */
+goog.graphics.AbstractGraphics.prototype.getPixelSize = function() {
+ if (this.isInDocument()) {
+ return goog.style.getSize(this.getElement());
+ }
+ if (goog.isNumber(this.width) && goog.isNumber(this.height)) {
+ return new goog.math.Size(this.width, this.height);
+ }
+ return null;
+};
+
+
+/**
+ * @return {number} Returns the number of pixels per unit in the x direction.
+ */
+goog.graphics.AbstractGraphics.prototype.getPixelScaleX = function() {
+ var pixelSize = this.getPixelSize();
+ return pixelSize ? pixelSize.width / this.getCoordSize().width : 0;
+};
+
+
+/**
+ * @return {number} Returns the number of pixels per unit in the y direction.
+ */
+goog.graphics.AbstractGraphics.prototype.getPixelScaleY = function() {
+ var pixelSize = this.getPixelSize();
+ return pixelSize ? pixelSize.height / this.getCoordSize().height : 0;
+};
+
+
+/**
+ * Remove all drawing elements from the graphics.
+ */
+goog.graphics.AbstractGraphics.prototype.clear = goog.abstractMethod;
+
+
+/**
+ * Remove a single drawing element from the surface. The default implementation
+ * assumes a DOM based drawing surface.
+ * @param {goog.graphics.Element} element The element to remove.
+ */
+goog.graphics.AbstractGraphics.prototype.removeElement = function(element) {
+ goog.dom.removeNode(element.getElement());
+};
+
+
+/**
+ * Sets the fill for the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
+ * @param {goog.graphics.Fill?} fill The fill object.
+ */
+goog.graphics.AbstractGraphics.prototype.setElementFill = goog.abstractMethod;
+
+
+/**
+ * Sets the stroke for the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
+ * @param {goog.graphics.Stroke?} stroke The stroke object.
+ */
+goog.graphics.AbstractGraphics.prototype.setElementStroke = goog.abstractMethod;
+
+
+/**
+ * Set the transformation of an element.
+ *
+ * If a more general affine transform is needed than this provides
+ * (e.g. skew and scale) then use setElementAffineTransform.
+ * @param {goog.graphics.Element} element The element wrapper.
+ * @param {number} x The x coordinate of the translation transform.
+ * @param {number} y The y coordinate of the translation transform.
+ * @param {number} angle The angle of the rotation transform.
+ * @param {number} centerX The horizontal center of the rotation transform.
+ * @param {number} centerY The vertical center of the rotation transform.
+ */
+goog.graphics.AbstractGraphics.prototype.setElementTransform =
+ goog.abstractMethod;
+
+
+/**
+ * Set the affine transform of an element.
+ * @param {!goog.graphics.Element} element The element wrapper.
+ * @param {!goog.graphics.AffineTransform} affineTransform The
+ * transformation applied to this element.
+ */
+goog.graphics.AbstractGraphics.prototype.setElementAffineTransform =
+ goog.abstractMethod;
+
+
+/**
+ * Draw a circle
+ *
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @param {number} r Radius length.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
+ * append to. If not specified, appends to the main canvas.
+ *
+ * @return {goog.graphics.EllipseElement} The newly created element.
+ */
+goog.graphics.AbstractGraphics.prototype.drawCircle = function(
+ cx, cy, r, stroke, fill, opt_group) {
+ return this.drawEllipse(cx, cy, r, r, stroke, fill, opt_group);
+};
+
+
+/**
+ * Draw an ellipse
+ *
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
+ * append to. If not specified, appends to the main canvas.
+ *
+ * @return {goog.graphics.EllipseElement} The newly created element.
+ */
+goog.graphics.AbstractGraphics.prototype.drawEllipse = goog.abstractMethod;
+
+
+/**
+ * Draw a rectangle
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
+ * append to. If not specified, appends to the main canvas.
+ *
+ * @return {goog.graphics.RectElement} The newly created element.
+ */
+goog.graphics.AbstractGraphics.prototype.drawRect = goog.abstractMethod;
+
+
+/**
+ * Draw a text string within a rectangle (drawing is horizontal)
+ *
+ * @param {string} text The text to draw.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @param {string} align Horizontal alignment: left (default), center, right.
+ * @param {string} vAlign Vertical alignment: top (default), center, bottom.
+ * @param {goog.graphics.Font} font Font describing the font properties.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
+ * append to. If not specified, appends to the main canvas.
+ *
+ * @return {goog.graphics.TextElement} The newly created element.
+ */
+goog.graphics.AbstractGraphics.prototype.drawText = function(
+ text, x, y, width, height, align, vAlign, font, stroke, fill, opt_group) {
+ var baseline = font.size / 2; // Baseline is middle of line
+ var textY;
+ if (vAlign == 'bottom') {
+ textY = y + height - baseline;
+ } else if (vAlign == 'center') {
+ textY = y + height / 2;
+ } else {
+ textY = y + baseline;
+ }
+
+ return this.drawTextOnLine(text, x, textY, x + width, textY, align,
+ font, stroke, fill, opt_group);
+};
+
+
+/**
+ * Draw a text string vertically centered on a given line.
+ *
+ * @param {string} text The text to draw.
+ * @param {number} x1 X coordinate of start of line.
+ * @param {number} y1 Y coordinate of start of line.
+ * @param {number} x2 X coordinate of end of line.
+ * @param {number} y2 Y coordinate of end of line.
+ * @param {string} align Horizontal alingnment: left (default), center, right.
+ * @param {goog.graphics.Font} font Font describing the font properties.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
+ * append to. If not specified, appends to the main canvas.
+ *
+ * @return {goog.graphics.TextElement} The newly created element.
+ */
+goog.graphics.AbstractGraphics.prototype.drawTextOnLine = goog.abstractMethod;
+
+
+/**
+ * Draw a path.
+ *
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
+ * append to. If not specified, appends to the main canvas.
+ *
+ * @return {goog.graphics.PathElement} The newly created element.
+ */
+goog.graphics.AbstractGraphics.prototype.drawPath = goog.abstractMethod;
+
+
+/**
+ * Create an empty group of drawing elements.
+ *
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
+ * append to. If not specified, appends to the main canvas.
+ *
+ * @return {goog.graphics.GroupElement} The newly created group.
+ */
+goog.graphics.AbstractGraphics.prototype.createGroup = goog.abstractMethod;
+
+
+/**
+ * Create an empty path.
+ *
+ * @return {!goog.graphics.Path} The path.
+ * @deprecated Use {@code new goog.graphics.Path()}.
+ */
+goog.graphics.AbstractGraphics.prototype.createPath = function() {
+ return new goog.graphics.Path();
+};
+
+
+/**
+ * Measure and return the width (in pixels) of a given text string.
+ * Text measurement is needed to make sure a text can fit in the allocated
+ * area. The way text length is measured is by writing it into a div that is
+ * after the visible area, measure the div width, and immediatly erase the
+ * written value.
+ *
+ * @param {string} text The text string to measure.
+ * @param {goog.graphics.Font} font The font object describing the font style.
+ *
+ * @return {number} The width in pixels of the text strings.
+ */
+goog.graphics.AbstractGraphics.prototype.getTextWidth = goog.abstractMethod;
+
+
+/**
+ * @return {boolean} Whether the underlying element can be cloned resulting in
+ * an accurate reproduction of the graphics contents.
+ */
+goog.graphics.AbstractGraphics.prototype.isDomClonable = function() {
+ return false;
+};
+
+
+/**
+ * Start preventing redraws - useful for chaining large numbers of changes
+ * together. Not guaranteed to do anything - i.e. only use this for
+ * optimization of a single code path.
+ */
+goog.graphics.AbstractGraphics.prototype.suspend = function() {
+};
+
+
+/**
+ * Stop preventing redraws. If any redraws had been prevented, a redraw will
+ * be done now.
+ */
+goog.graphics.AbstractGraphics.prototype.resume = function() {
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/affinetransform.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/affinetransform.js b/externs/GCL/externs/goog/graphics/affinetransform.js
new file mode 100644
index 0000000..ec328f2
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/affinetransform.js
@@ -0,0 +1,588 @@
+// 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 Provides an object representation of an AffineTransform and
+ * methods for working with it.
+ */
+
+
+goog.provide('goog.graphics.AffineTransform');
+
+goog.require('goog.math');
+
+
+
+/**
+ * Creates a 2D affine transform. An affine transform performs a linear
+ * mapping from 2D coordinates to other 2D coordinates that preserves the
+ * "straightness" and "parallelness" of lines.
+ *
+ * Such a coordinate transformation can be represented by a 3 row by 3 column
+ * matrix with an implied last row of [ 0 0 1 ]. This matrix transforms source
+ * coordinates (x,y) into destination coordinates (x',y') by considering them
+ * to be a column vector and multiplying the coordinate vector by the matrix
+ * according to the following process:
+ * <pre>
+ * [ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ]
+ * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ]
+ * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
+ * </pre>
+ *
+ * This class is optimized for speed and minimizes calculations based on its
+ * knowledge of the underlying matrix (as opposed to say simply performing
+ * matrix multiplication).
+ *
+ * @param {number=} opt_m00 The m00 coordinate of the transform.
+ * @param {number=} opt_m10 The m10 coordinate of the transform.
+ * @param {number=} opt_m01 The m01 coordinate of the transform.
+ * @param {number=} opt_m11 The m11 coordinate of the transform.
+ * @param {number=} opt_m02 The m02 coordinate of the transform.
+ * @param {number=} opt_m12 The m12 coordinate of the transform.
+ * @constructor
+ * @final
+ */
+goog.graphics.AffineTransform = function(opt_m00, opt_m10, opt_m01,
+ opt_m11, opt_m02, opt_m12) {
+ if (arguments.length == 6) {
+ this.setTransform(/** @type {number} */ (opt_m00),
+ /** @type {number} */ (opt_m10),
+ /** @type {number} */ (opt_m01),
+ /** @type {number} */ (opt_m11),
+ /** @type {number} */ (opt_m02),
+ /** @type {number} */ (opt_m12));
+ } else if (arguments.length != 0) {
+ throw Error('Insufficient matrix parameters');
+ } else {
+ this.m00_ = this.m11_ = 1;
+ this.m10_ = this.m01_ = this.m02_ = this.m12_ = 0;
+ }
+};
+
+
+/**
+ * @return {boolean} Whether this transform is the identity transform.
+ */
+goog.graphics.AffineTransform.prototype.isIdentity = function() {
+ return this.m00_ == 1 && this.m10_ == 0 && this.m01_ == 0 &&
+ this.m11_ == 1 && this.m02_ == 0 && this.m12_ == 0;
+};
+
+
+/**
+ * @return {!goog.graphics.AffineTransform} A copy of this transform.
+ */
+goog.graphics.AffineTransform.prototype.clone = function() {
+ return new goog.graphics.AffineTransform(this.m00_, this.m10_, this.m01_,
+ this.m11_, this.m02_, this.m12_);
+};
+
+
+/**
+ * Sets this transform to the matrix specified by the 6 values.
+ *
+ * @param {number} m00 The m00 coordinate of the transform.
+ * @param {number} m10 The m10 coordinate of the transform.
+ * @param {number} m01 The m01 coordinate of the transform.
+ * @param {number} m11 The m11 coordinate of the transform.
+ * @param {number} m02 The m02 coordinate of the transform.
+ * @param {number} m12 The m12 coordinate of the transform.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.setTransform = function(m00, m10, m01,
+ m11, m02, m12) {
+ if (!goog.isNumber(m00) || !goog.isNumber(m10) || !goog.isNumber(m01) ||
+ !goog.isNumber(m11) || !goog.isNumber(m02) || !goog.isNumber(m12)) {
+ throw Error('Invalid transform parameters');
+ }
+ this.m00_ = m00;
+ this.m10_ = m10;
+ this.m01_ = m01;
+ this.m11_ = m11;
+ this.m02_ = m02;
+ this.m12_ = m12;
+ return this;
+};
+
+
+/**
+ * Sets this transform to be identical to the given transform.
+ *
+ * @param {!goog.graphics.AffineTransform} tx The transform to copy.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.copyFrom = function(tx) {
+ this.m00_ = tx.m00_;
+ this.m10_ = tx.m10_;
+ this.m01_ = tx.m01_;
+ this.m11_ = tx.m11_;
+ this.m02_ = tx.m02_;
+ this.m12_ = tx.m12_;
+ return this;
+};
+
+
+/**
+ * Concatenates this transform with a scaling transformation.
+ *
+ * @param {number} sx The x-axis scaling factor.
+ * @param {number} sy The y-axis scaling factor.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.scale = function(sx, sy) {
+ this.m00_ *= sx;
+ this.m10_ *= sx;
+ this.m01_ *= sy;
+ this.m11_ *= sy;
+ return this;
+};
+
+
+/**
+ * Pre-concatenates this transform with a scaling transformation,
+ * i.e. calculates the following matrix product:
+ *
+ * <pre>
+ * [sx 0 0] [m00 m01 m02]
+ * [ 0 sy 0] [m10 m11 m12]
+ * [ 0 0 1] [ 0 0 1]
+ * </pre>
+ *
+ * @param {number} sx The x-axis scaling factor.
+ * @param {number} sy The y-axis scaling factor.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.preScale = function(sx, sy) {
+ this.m00_ *= sx;
+ this.m01_ *= sx;
+ this.m02_ *= sx;
+ this.m10_ *= sy;
+ this.m11_ *= sy;
+ this.m12_ *= sy;
+ return this;
+};
+
+
+/**
+ * Concatenates this transform with a translate transformation.
+ *
+ * @param {number} dx The distance to translate in the x direction.
+ * @param {number} dy The distance to translate in the y direction.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.translate = function(dx, dy) {
+ this.m02_ += dx * this.m00_ + dy * this.m01_;
+ this.m12_ += dx * this.m10_ + dy * this.m11_;
+ return this;
+};
+
+
+/**
+ * Pre-concatenates this transform with a translate transformation,
+ * i.e. calculates the following matrix product:
+ *
+ * <pre>
+ * [1 0 dx] [m00 m01 m02]
+ * [0 1 dy] [m10 m11 m12]
+ * [0 0 1] [ 0 0 1]
+ * </pre>
+ *
+ * @param {number} dx The distance to translate in the x direction.
+ * @param {number} dy The distance to translate in the y direction.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.preTranslate = function(dx, dy) {
+ this.m02_ += dx;
+ this.m12_ += dy;
+ return this;
+};
+
+
+/**
+ * Concatenates this transform with a rotation transformation around an anchor
+ * point.
+ *
+ * @param {number} theta The angle of rotation measured in radians.
+ * @param {number} x The x coordinate of the anchor point.
+ * @param {number} y The y coordinate of the anchor point.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.rotate = function(theta, x, y) {
+ return this.concatenate(
+ goog.graphics.AffineTransform.getRotateInstance(theta, x, y));
+};
+
+
+/**
+ * Pre-concatenates this transform with a rotation transformation around an
+ * anchor point.
+ *
+ * @param {number} theta The angle of rotation measured in radians.
+ * @param {number} x The x coordinate of the anchor point.
+ * @param {number} y The y coordinate of the anchor point.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.preRotate = function(theta, x, y) {
+ return this.preConcatenate(
+ goog.graphics.AffineTransform.getRotateInstance(theta, x, y));
+};
+
+
+/**
+ * Concatenates this transform with a shear transformation.
+ *
+ * @param {number} shx The x shear factor.
+ * @param {number} shy The y shear factor.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.shear = function(shx, shy) {
+ var m00 = this.m00_;
+ var m10 = this.m10_;
+ this.m00_ += shy * this.m01_;
+ this.m10_ += shy * this.m11_;
+ this.m01_ += shx * m00;
+ this.m11_ += shx * m10;
+ return this;
+};
+
+
+/**
+ * Pre-concatenates this transform with a shear transformation.
+ * i.e. calculates the following matrix product:
+ *
+ * <pre>
+ * [ 1 shx 0] [m00 m01 m02]
+ * [shy 1 0] [m10 m11 m12]
+ * [ 0 0 1] [ 0 0 1]
+ * </pre>
+ *
+ * @param {number} shx The x shear factor.
+ * @param {number} shy The y shear factor.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.preShear = function(shx, shy) {
+ var m00 = this.m00_;
+ var m01 = this.m01_;
+ var m02 = this.m02_;
+ this.m00_ += shx * this.m10_;
+ this.m01_ += shx * this.m11_;
+ this.m02_ += shx * this.m12_;
+ this.m10_ += shy * m00;
+ this.m11_ += shy * m01;
+ this.m12_ += shy * m02;
+ return this;
+};
+
+
+/**
+ * @return {string} A string representation of this transform. The format of
+ * of the string is compatible with SVG matrix notation, i.e.
+ * "matrix(a,b,c,d,e,f)".
+ * @override
+ */
+goog.graphics.AffineTransform.prototype.toString = function() {
+ return 'matrix(' +
+ [this.m00_, this.m10_, this.m01_, this.m11_, this.m02_, this.m12_].join(
+ ',') +
+ ')';
+};
+
+
+/**
+ * @return {number} The scaling factor in the x-direction (m00).
+ */
+goog.graphics.AffineTransform.prototype.getScaleX = function() {
+ return this.m00_;
+};
+
+
+/**
+ * @return {number} The scaling factor in the y-direction (m11).
+ */
+goog.graphics.AffineTransform.prototype.getScaleY = function() {
+ return this.m11_;
+};
+
+
+/**
+ * @return {number} The translation in the x-direction (m02).
+ */
+goog.graphics.AffineTransform.prototype.getTranslateX = function() {
+ return this.m02_;
+};
+
+
+/**
+ * @return {number} The translation in the y-direction (m12).
+ */
+goog.graphics.AffineTransform.prototype.getTranslateY = function() {
+ return this.m12_;
+};
+
+
+/**
+ * @return {number} The shear factor in the x-direction (m01).
+ */
+goog.graphics.AffineTransform.prototype.getShearX = function() {
+ return this.m01_;
+};
+
+
+/**
+ * @return {number} The shear factor in the y-direction (m10).
+ */
+goog.graphics.AffineTransform.prototype.getShearY = function() {
+ return this.m10_;
+};
+
+
+/**
+ * Concatenates an affine transform to this transform.
+ *
+ * @param {!goog.graphics.AffineTransform} tx The transform to concatenate.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.concatenate = function(tx) {
+ var m0 = this.m00_;
+ var m1 = this.m01_;
+ this.m00_ = tx.m00_ * m0 + tx.m10_ * m1;
+ this.m01_ = tx.m01_ * m0 + tx.m11_ * m1;
+ this.m02_ += tx.m02_ * m0 + tx.m12_ * m1;
+
+ m0 = this.m10_;
+ m1 = this.m11_;
+ this.m10_ = tx.m00_ * m0 + tx.m10_ * m1;
+ this.m11_ = tx.m01_ * m0 + tx.m11_ * m1;
+ this.m12_ += tx.m02_ * m0 + tx.m12_ * m1;
+ return this;
+};
+
+
+/**
+ * Pre-concatenates an affine transform to this transform.
+ *
+ * @param {!goog.graphics.AffineTransform} tx The transform to preconcatenate.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.preConcatenate = function(tx) {
+ var m0 = this.m00_;
+ var m1 = this.m10_;
+ this.m00_ = tx.m00_ * m0 + tx.m01_ * m1;
+ this.m10_ = tx.m10_ * m0 + tx.m11_ * m1;
+
+ m0 = this.m01_;
+ m1 = this.m11_;
+ this.m01_ = tx.m00_ * m0 + tx.m01_ * m1;
+ this.m11_ = tx.m10_ * m0 + tx.m11_ * m1;
+
+ m0 = this.m02_;
+ m1 = this.m12_;
+ this.m02_ = tx.m00_ * m0 + tx.m01_ * m1 + tx.m02_;
+ this.m12_ = tx.m10_ * m0 + tx.m11_ * m1 + tx.m12_;
+ return this;
+};
+
+
+/**
+ * Transforms an array of coordinates by this transform and stores the result
+ * into a destination array.
+ *
+ * @param {!Array<number>} src The array containing the source points
+ * as x, y value pairs.
+ * @param {number} srcOff The offset to the first point to be transformed.
+ * @param {!Array<number>} dst The array into which to store the transformed
+ * point pairs.
+ * @param {number} dstOff The offset of the location of the first transformed
+ * point in the destination array.
+ * @param {number} numPts The number of points to tranform.
+ */
+goog.graphics.AffineTransform.prototype.transform = function(src, srcOff, dst,
+ dstOff, numPts) {
+ var i = srcOff;
+ var j = dstOff;
+ var srcEnd = srcOff + 2 * numPts;
+ while (i < srcEnd) {
+ var x = src[i++];
+ var y = src[i++];
+ dst[j++] = x * this.m00_ + y * this.m01_ + this.m02_;
+ dst[j++] = x * this.m10_ + y * this.m11_ + this.m12_;
+ }
+};
+
+
+/**
+ * @return {number} The determinant of this transform.
+ */
+goog.graphics.AffineTransform.prototype.getDeterminant = function() {
+ return this.m00_ * this.m11_ - this.m01_ * this.m10_;
+};
+
+
+/**
+ * Returns whether the transform is invertible. A transform is not invertible
+ * if the determinant is 0 or any value is non-finite or NaN.
+ *
+ * @return {boolean} Whether the transform is invertible.
+ */
+goog.graphics.AffineTransform.prototype.isInvertible = function() {
+ var det = this.getDeterminant();
+ return goog.math.isFiniteNumber(det) &&
+ goog.math.isFiniteNumber(this.m02_) &&
+ goog.math.isFiniteNumber(this.m12_) &&
+ det != 0;
+};
+
+
+/**
+ * @return {!goog.graphics.AffineTransform} An AffineTransform object
+ * representing the inverse transformation.
+ */
+goog.graphics.AffineTransform.prototype.createInverse = function() {
+ var det = this.getDeterminant();
+ return new goog.graphics.AffineTransform(
+ this.m11_ / det,
+ -this.m10_ / det,
+ -this.m01_ / det,
+ this.m00_ / det,
+ (this.m01_ * this.m12_ - this.m11_ * this.m02_) / det,
+ (this.m10_ * this.m02_ - this.m00_ * this.m12_) / det);
+};
+
+
+/**
+ * Creates a transform representing a scaling transformation.
+ *
+ * @param {number} sx The x-axis scaling factor.
+ * @param {number} sy The y-axis scaling factor.
+ * @return {!goog.graphics.AffineTransform} A transform representing a scaling
+ * transformation.
+ */
+goog.graphics.AffineTransform.getScaleInstance = function(sx, sy) {
+ return new goog.graphics.AffineTransform().setToScale(sx, sy);
+};
+
+
+/**
+ * Creates a transform representing a translation transformation.
+ *
+ * @param {number} dx The distance to translate in the x direction.
+ * @param {number} dy The distance to translate in the y direction.
+ * @return {!goog.graphics.AffineTransform} A transform representing a
+ * translation transformation.
+ */
+goog.graphics.AffineTransform.getTranslateInstance = function(dx, dy) {
+ return new goog.graphics.AffineTransform().setToTranslation(dx, dy);
+};
+
+
+/**
+ * Creates a transform representing a shearing transformation.
+ *
+ * @param {number} shx The x-axis shear factor.
+ * @param {number} shy The y-axis shear factor.
+ * @return {!goog.graphics.AffineTransform} A transform representing a shearing
+ * transformation.
+ */
+goog.graphics.AffineTransform.getShearInstance = function(shx, shy) {
+ return new goog.graphics.AffineTransform().setToShear(shx, shy);
+};
+
+
+/**
+ * Creates a transform representing a rotation transformation.
+ *
+ * @param {number} theta The angle of rotation measured in radians.
+ * @param {number} x The x coordinate of the anchor point.
+ * @param {number} y The y coordinate of the anchor point.
+ * @return {!goog.graphics.AffineTransform} A transform representing a rotation
+ * transformation.
+ */
+goog.graphics.AffineTransform.getRotateInstance = function(theta, x, y) {
+ return new goog.graphics.AffineTransform().setToRotation(theta, x, y);
+};
+
+
+/**
+ * Sets this transform to a scaling transformation.
+ *
+ * @param {number} sx The x-axis scaling factor.
+ * @param {number} sy The y-axis scaling factor.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.setToScale = function(sx, sy) {
+ return this.setTransform(sx, 0, 0, sy, 0, 0);
+};
+
+
+/**
+ * Sets this transform to a translation transformation.
+ *
+ * @param {number} dx The distance to translate in the x direction.
+ * @param {number} dy The distance to translate in the y direction.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.setToTranslation = function(dx, dy) {
+ return this.setTransform(1, 0, 0, 1, dx, dy);
+};
+
+
+/**
+ * Sets this transform to a shearing transformation.
+ *
+ * @param {number} shx The x-axis shear factor.
+ * @param {number} shy The y-axis shear factor.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.setToShear = function(shx, shy) {
+ return this.setTransform(1, shy, shx, 1, 0, 0);
+};
+
+
+/**
+ * Sets this transform to a rotation transformation.
+ *
+ * @param {number} theta The angle of rotation measured in radians.
+ * @param {number} x The x coordinate of the anchor point.
+ * @param {number} y The y coordinate of the anchor point.
+ * @return {!goog.graphics.AffineTransform} This affine transform.
+ */
+goog.graphics.AffineTransform.prototype.setToRotation = function(theta, x, y) {
+ var cos = Math.cos(theta);
+ var sin = Math.sin(theta);
+ return this.setTransform(cos, sin, -sin, cos,
+ x - x * cos + y * sin, y - x * sin - y * cos);
+};
+
+
+/**
+ * Compares two affine transforms for equality.
+ *
+ * @param {goog.graphics.AffineTransform} tx The other affine transform.
+ * @return {boolean} whether the two transforms are equal.
+ */
+goog.graphics.AffineTransform.prototype.equals = function(tx) {
+ if (this == tx) {
+ return true;
+ }
+ if (!tx) {
+ return false;
+ }
+ return this.m00_ == tx.m00_ &&
+ this.m01_ == tx.m01_ &&
+ this.m02_ == tx.m02_ &&
+ this.m10_ == tx.m10_ &&
+ this.m11_ == tx.m11_ &&
+ this.m12_ == tx.m12_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/canvaselement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/canvaselement.js b/externs/GCL/externs/goog/graphics/canvaselement.js
new file mode 100644
index 0000000..6c400db
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/canvaselement.js
@@ -0,0 +1,812 @@
+// 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 Objects representing shapes drawn on a canvas.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.graphics.CanvasEllipseElement');
+goog.provide('goog.graphics.CanvasGroupElement');
+goog.provide('goog.graphics.CanvasImageElement');
+goog.provide('goog.graphics.CanvasPathElement');
+goog.provide('goog.graphics.CanvasRectElement');
+goog.provide('goog.graphics.CanvasTextElement');
+
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.safe');
+goog.require('goog.graphics.EllipseElement');
+goog.require('goog.graphics.GroupElement');
+goog.require('goog.graphics.ImageElement');
+goog.require('goog.graphics.Path');
+goog.require('goog.graphics.PathElement');
+goog.require('goog.graphics.RectElement');
+goog.require('goog.graphics.TextElement');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.uncheckedconversions');
+goog.require('goog.math');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+
+
+
+/**
+ * Object representing a group of objects in a canvas.
+ * This is an implementation of the goog.graphics.GroupElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.graphics.GroupElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.CanvasGroupElement = function(graphics) {
+ goog.graphics.GroupElement.call(this, null, graphics);
+
+
+ /**
+ * Children contained by this group.
+ * @type {Array<goog.graphics.Element>}
+ * @private
+ */
+ this.children_ = [];
+};
+goog.inherits(goog.graphics.CanvasGroupElement, goog.graphics.GroupElement);
+
+
+/**
+ * Remove all drawing elements from the group.
+ * @override
+ */
+goog.graphics.CanvasGroupElement.prototype.clear = function() {
+ if (this.children_.length) {
+ this.children_.length = 0;
+ this.getGraphics().redraw();
+ }
+};
+
+
+/**
+ * Set the size of the group element.
+ * @param {number|string} width The width of the group element.
+ * @param {number|string} height The height of the group element.
+ * @override
+ */
+goog.graphics.CanvasGroupElement.prototype.setSize = function(width, height) {
+ // Do nothing.
+};
+
+
+/**
+ * Append a child to the group. Does not draw it
+ * @param {goog.graphics.Element} element The child to append.
+ */
+goog.graphics.CanvasGroupElement.prototype.appendChild = function(element) {
+ this.children_.push(element);
+};
+
+
+/**
+ * Draw the group.
+ * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
+ */
+goog.graphics.CanvasGroupElement.prototype.draw = function(ctx) {
+ for (var i = 0, len = this.children_.length; i < len; i++) {
+ this.getGraphics().drawElement(this.children_[i]);
+ }
+};
+
+
+
+/**
+ * Thin wrapper for canvas ellipse elements.
+ * This is an implementation of the goog.graphics.EllipseElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
+ * this element.
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.EllipseElement}
+ * @final
+ */
+goog.graphics.CanvasEllipseElement = function(element, graphics,
+ cx, cy, rx, ry, stroke, fill) {
+ goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill);
+
+ /**
+ * X coordinate of the ellipse center.
+ * @type {number}
+ * @private
+ */
+ this.cx_ = cx;
+
+
+ /**
+ * Y coordinate of the ellipse center.
+ * @type {number}
+ * @private
+ */
+ this.cy_ = cy;
+
+
+ /**
+ * Radius length for the x-axis.
+ * @type {number}
+ * @private
+ */
+ this.rx_ = rx;
+
+
+ /**
+ * Radius length for the y-axis.
+ * @type {number}
+ * @private
+ */
+ this.ry_ = ry;
+
+
+ /**
+ * Internal path approximating an ellipse.
+ * @type {goog.graphics.Path}
+ * @private
+ */
+ this.path_ = new goog.graphics.Path();
+ this.setUpPath_();
+
+ /**
+ * Internal path element that actually does the drawing.
+ * @type {goog.graphics.CanvasPathElement}
+ * @private
+ */
+ this.pathElement_ = new goog.graphics.CanvasPathElement(null, graphics,
+ this.path_, stroke, fill);
+};
+goog.inherits(goog.graphics.CanvasEllipseElement, goog.graphics.EllipseElement);
+
+
+/**
+ * Sets up the path.
+ * @private
+ */
+goog.graphics.CanvasEllipseElement.prototype.setUpPath_ = function() {
+ this.path_.clear();
+ this.path_.moveTo(this.cx_ + goog.math.angleDx(0, this.rx_),
+ this.cy_ + goog.math.angleDy(0, this.ry_));
+ this.path_.arcTo(this.rx_, this.ry_, 0, 360);
+ this.path_.close();
+};
+
+
+/**
+ * Update the center point of the ellipse.
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @override
+ */
+goog.graphics.CanvasEllipseElement.prototype.setCenter = function(cx, cy) {
+ this.cx_ = cx;
+ this.cy_ = cy;
+ this.setUpPath_();
+ this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_));
+};
+
+
+/**
+ * Update the radius of the ellipse.
+ * @param {number} rx Center X coordinate.
+ * @param {number} ry Center Y coordinate.
+ * @override
+ */
+goog.graphics.CanvasEllipseElement.prototype.setRadius = function(rx, ry) {
+ this.rx_ = rx;
+ this.ry_ = ry;
+ this.setUpPath_();
+ this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_));
+};
+
+
+/**
+ * Draw the ellipse. Should be treated as package scope.
+ * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
+ */
+goog.graphics.CanvasEllipseElement.prototype.draw = function(ctx) {
+ this.pathElement_.draw(ctx);
+};
+
+
+
+/**
+ * Thin wrapper for canvas rectangle elements.
+ * This is an implementation of the goog.graphics.RectElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
+ * this element.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} w Width of rectangle.
+ * @param {number} h Height of rectangle.
+ * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.RectElement}
+ * @final
+ */
+goog.graphics.CanvasRectElement = function(element, graphics, x, y, w, h,
+ stroke, fill) {
+ goog.graphics.RectElement.call(this, element, graphics, stroke, fill);
+
+ /**
+ * X coordinate of the top left corner.
+ * @type {number}
+ * @private
+ */
+ this.x_ = x;
+
+
+ /**
+ * Y coordinate of the top left corner.
+ * @type {number}
+ * @private
+ */
+ this.y_ = y;
+
+
+ /**
+ * Width of the rectangle.
+ * @type {number}
+ * @private
+ */
+ this.w_ = w;
+
+
+ /**
+ * Height of the rectangle.
+ * @type {number}
+ * @private
+ */
+ this.h_ = h;
+};
+goog.inherits(goog.graphics.CanvasRectElement, goog.graphics.RectElement);
+
+
+/**
+ * Update the position of the rectangle.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @override
+ */
+goog.graphics.CanvasRectElement.prototype.setPosition = function(x, y) {
+ this.x_ = x;
+ this.y_ = y;
+ if (this.drawn_) {
+ this.getGraphics().redraw();
+ }
+};
+
+
+/**
+ * Whether the rectangle has been drawn yet.
+ * @type {boolean}
+ * @private
+ */
+goog.graphics.CanvasRectElement.prototype.drawn_ = false;
+
+
+/**
+ * Update the size of the rectangle.
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @override
+ */
+goog.graphics.CanvasRectElement.prototype.setSize = function(width, height) {
+ this.w_ = width;
+ this.h_ = height;
+ if (this.drawn_) {
+ this.getGraphics().redraw();
+ }
+};
+
+
+/**
+ * Draw the rectangle. Should be treated as package scope.
+ * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
+ */
+goog.graphics.CanvasRectElement.prototype.draw = function(ctx) {
+ this.drawn_ = true;
+ ctx.beginPath();
+ ctx.moveTo(this.x_, this.y_);
+ ctx.lineTo(this.x_, this.y_ + this.h_);
+ ctx.lineTo(this.x_ + this.w_, this.y_ + this.h_);
+ ctx.lineTo(this.x_ + this.w_, this.y_);
+ ctx.closePath();
+};
+
+
+
+/**
+ * Thin wrapper for canvas path elements.
+ * This is an implementation of the goog.graphics.PathElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
+ * this element.
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.PathElement}
+ * @final
+ */
+goog.graphics.CanvasPathElement = function(element, graphics, path, stroke,
+ fill) {
+ goog.graphics.PathElement.call(this, element, graphics, stroke, fill);
+
+ this.setPath(path);
+};
+goog.inherits(goog.graphics.CanvasPathElement, goog.graphics.PathElement);
+
+
+/**
+ * Whether the shape has been drawn yet.
+ * @type {boolean}
+ * @private
+ */
+goog.graphics.CanvasPathElement.prototype.drawn_ = false;
+
+
+/**
+ * The path to draw.
+ * @type {goog.graphics.Path}
+ * @private
+ */
+goog.graphics.CanvasPathElement.prototype.path_;
+
+
+/**
+ * Update the underlying path.
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @override
+ */
+goog.graphics.CanvasPathElement.prototype.setPath = function(path) {
+ this.path_ = path.isSimple() ? path :
+ goog.graphics.Path.createSimplifiedPath(path);
+ if (this.drawn_) {
+ this.getGraphics().redraw();
+ }
+};
+
+
+/**
+ * Draw the path. Should be treated as package scope.
+ * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
+ * @suppress {deprecated} goog.graphics is deprecated.
+ */
+goog.graphics.CanvasPathElement.prototype.draw = function(ctx) {
+ this.drawn_ = true;
+
+ ctx.beginPath();
+ this.path_.forEachSegment(function(segment, args) {
+ switch (segment) {
+ case goog.graphics.Path.Segment.MOVETO:
+ ctx.moveTo(args[0], args[1]);
+ break;
+ case goog.graphics.Path.Segment.LINETO:
+ for (var i = 0; i < args.length; i += 2) {
+ ctx.lineTo(args[i], args[i + 1]);
+ }
+ break;
+ case goog.graphics.Path.Segment.CURVETO:
+ for (var i = 0; i < args.length; i += 6) {
+ ctx.bezierCurveTo(args[i], args[i + 1], args[i + 2],
+ args[i + 3], args[i + 4], args[i + 5]);
+ }
+ break;
+ case goog.graphics.Path.Segment.ARCTO:
+ throw Error('Canvas paths cannot contain arcs');
+ case goog.graphics.Path.Segment.CLOSE:
+ ctx.closePath();
+ break;
+ }
+ });
+};
+
+
+
+/**
+ * Thin wrapper for canvas text elements.
+ * This is an implementation of the goog.graphics.TextElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {!goog.graphics.CanvasGraphics} graphics The graphics creating
+ * this element.
+ * @param {string} text The text to draw.
+ * @param {number} x1 X coordinate of start of line.
+ * @param {number} y1 Y coordinate of start of line.
+ * @param {number} x2 X coordinate of end of line.
+ * @param {number} y2 Y coordinate of end of line.
+ * @param {?string} align Horizontal alignment: left (default), center, right.
+ * @param {!goog.graphics.Font} font Font describing the font properties.
+ * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.TextElement}
+ * @final
+ */
+goog.graphics.CanvasTextElement = function(graphics, text, x1, y1, x2, y2,
+ align, font, stroke, fill) {
+ var element = goog.dom.createDom(goog.dom.TagName.DIV, {
+ 'style': 'display:table;position:absolute;padding:0;margin:0;border:0'
+ });
+ goog.graphics.TextElement.call(this, element, graphics, stroke, fill);
+
+ /**
+ * The text to draw.
+ * @type {string}
+ * @private
+ */
+ this.text_ = text;
+
+ /**
+ * X coordinate of the start of the line the text is drawn on.
+ * @type {number}
+ * @private
+ */
+ this.x1_ = x1;
+
+ /**
+ * Y coordinate of the start of the line the text is drawn on.
+ * @type {number}
+ * @private
+ */
+ this.y1_ = y1;
+
+ /**
+ * X coordinate of the end of the line the text is drawn on.
+ * @type {number}
+ * @private
+ */
+ this.x2_ = x2;
+
+ /**
+ * Y coordinate of the end of the line the text is drawn on.
+ * @type {number}
+ * @private
+ */
+ this.y2_ = y2;
+
+ /**
+ * Horizontal alignment: left (default), center, right.
+ * @type {string}
+ * @private
+ */
+ this.align_ = align || 'left';
+
+ /**
+ * Font object describing the font properties.
+ * @type {goog.graphics.Font}
+ * @private
+ */
+ this.font_ = font;
+
+ /**
+ * The inner element that contains the text.
+ * @type {Element}
+ * @private
+ */
+ this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV, {
+ 'style': 'display:table-cell;padding: 0;margin: 0;border: 0'
+ });
+
+ this.updateStyle_();
+ this.updateText_();
+
+ // Append to the DOM.
+ graphics.getElement().appendChild(element);
+ element.appendChild(this.innerElement_);
+};
+goog.inherits(goog.graphics.CanvasTextElement, goog.graphics.TextElement);
+
+
+/**
+ * Update the displayed text of the element.
+ * @param {string} text The text to draw.
+ * @override
+ */
+goog.graphics.CanvasTextElement.prototype.setText = function(text) {
+ this.text_ = text;
+ this.updateText_();
+};
+
+
+/**
+ * Sets the fill for this element.
+ * @param {goog.graphics.Fill} fill The fill object.
+ * @override
+ */
+goog.graphics.CanvasTextElement.prototype.setFill = function(fill) {
+ this.fill = fill;
+ var element = this.getElement();
+ if (element) {
+ element.style.color = fill.getColor() || fill.getColor1();
+ }
+};
+
+
+/**
+ * Sets the stroke for this element.
+ * @param {goog.graphics.Stroke} stroke The stroke object.
+ * @override
+ */
+goog.graphics.CanvasTextElement.prototype.setStroke = function(stroke) {
+ // Ignore stroke
+};
+
+
+/**
+ * Draw the text. Should be treated as package scope.
+ * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
+ */
+goog.graphics.CanvasTextElement.prototype.draw = function(ctx) {
+ // Do nothing - the text is already drawn.
+};
+
+
+/**
+ * Update the styles of the DIVs.
+ * @private
+ */
+goog.graphics.CanvasTextElement.prototype.updateStyle_ = function() {
+ var x1 = this.x1_;
+ var x2 = this.x2_;
+ var y1 = this.y1_;
+ var y2 = this.y2_;
+ var align = this.align_;
+ var font = this.font_;
+ var style = this.getElement().style;
+ var scaleX = this.getGraphics().getPixelScaleX();
+ var scaleY = this.getGraphics().getPixelScaleY();
+
+ if (x1 == x2) {
+ // Special case vertical text
+ style.lineHeight = '90%';
+
+ this.innerElement_.style.verticalAlign = align == 'center' ? 'middle' :
+ align == 'left' ? (y1 < y2 ? 'top' : 'bottom') :
+ y1 < y2 ? 'bottom' : 'top';
+ style.textAlign = 'center';
+
+ var w = font.size * scaleX;
+ style.top = Math.round(Math.min(y1, y2) * scaleY) + 'px';
+ style.left = Math.round((x1 - w / 2) * scaleX) + 'px';
+ style.width = Math.round(w) + 'px';
+ style.height = Math.abs(y1 - y2) * scaleY + 'px';
+
+ style.fontSize = font.size * 0.6 * scaleY + 'pt';
+ } else {
+ style.lineHeight = '100%';
+ this.innerElement_.style.verticalAlign = 'top';
+ style.textAlign = align;
+
+ style.top = Math.round(((y1 + y2) / 2 - font.size * 2 / 3) * scaleY) + 'px';
+ style.left = Math.round(x1 * scaleX) + 'px';
+ style.width = Math.round(Math.abs(x2 - x1) * scaleX) + 'px';
+ style.height = 'auto';
+
+ style.fontSize = font.size * scaleY + 'pt';
+ }
+
+ style.fontWeight = font.bold ? 'bold' : 'normal';
+ style.fontStyle = font.italic ? 'italic' : 'normal';
+ style.fontFamily = font.family;
+
+ var fill = this.getFill();
+ style.color = fill.getColor() || fill.getColor1();
+};
+
+
+/**
+ * Update the text content.
+ * @private
+ */
+goog.graphics.CanvasTextElement.prototype.updateText_ = function() {
+ if (this.x1_ == this.x2_) {
+ // Special case vertical text
+ var html =
+ goog.array.map(
+ this.text_.split(''),
+ function(entry) { return goog.string.htmlEscape(entry); })
+ .join('<br>');
+ // Creating a SafeHtml for each character would be quite expensive, and it's
+ // obvious that this is safe, so an unchecked conversion is appropriate.
+ var safeHtml = goog.html.uncheckedconversions
+ .safeHtmlFromStringKnownToSatisfyTypeContract(
+ goog.string.Const.from('Concatenate escaped chars and <br>'),
+ html);
+ goog.dom.safe.setInnerHtml(
+ /** @type {!Element} */ (this.innerElement_), safeHtml);
+ } else {
+ goog.dom.safe.setInnerHtml(
+ /** @type {!Element} */ (this.innerElement_),
+ goog.html.SafeHtml.htmlEscape(this.text_));
+ }
+};
+
+
+
+/**
+ * Thin wrapper for canvas image elements.
+ * This is an implementation of the goog.graphics.ImageElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
+ * this element.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} w Width of rectangle.
+ * @param {number} h Height of rectangle.
+ * @param {string} src Source of the image.
+ * @constructor
+ * @extends {goog.graphics.ImageElement}
+ * @final
+ */
+goog.graphics.CanvasImageElement = function(element, graphics, x, y, w, h,
+ src) {
+ goog.graphics.ImageElement.call(this, element, graphics);
+
+ /**
+ * X coordinate of the top left corner.
+ * @type {number}
+ * @private
+ */
+ this.x_ = x;
+
+
+ /**
+ * Y coordinate of the top left corner.
+ * @type {number}
+ * @private
+ */
+ this.y_ = y;
+
+
+ /**
+ * Width of the rectangle.
+ * @type {number}
+ * @private
+ */
+ this.w_ = w;
+
+
+ /**
+ * Height of the rectangle.
+ * @type {number}
+ * @private
+ */
+ this.h_ = h;
+
+
+ /**
+ * URL of the image source.
+ * @type {string}
+ * @private
+ */
+ this.src_ = src;
+};
+goog.inherits(goog.graphics.CanvasImageElement, goog.graphics.ImageElement);
+
+
+/**
+ * Whether the image has been drawn yet.
+ * @type {boolean}
+ * @private
+ */
+goog.graphics.CanvasImageElement.prototype.drawn_ = false;
+
+
+/**
+ * Update the position of the image.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @override
+ */
+goog.graphics.CanvasImageElement.prototype.setPosition = function(x, y) {
+ this.x_ = x;
+ this.y_ = y;
+ if (this.drawn_) {
+ this.getGraphics().redraw();
+ }
+};
+
+
+/**
+ * Update the size of the image.
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @override
+ */
+goog.graphics.CanvasImageElement.prototype.setSize = function(width, height) {
+ this.w_ = width;
+ this.h_ = height;
+ if (this.drawn_) {
+ this.getGraphics().redraw();
+ }
+};
+
+
+/**
+ * Update the source of the image.
+ * @param {string} src Source of the image.
+ * @override
+ */
+goog.graphics.CanvasImageElement.prototype.setSource = function(src) {
+ this.src_ = src;
+ if (this.drawn_) {
+ // TODO(robbyw): Probably need to reload the image here.
+ this.getGraphics().redraw();
+ }
+};
+
+
+/**
+ * Draw the image. Should be treated as package scope.
+ * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
+ */
+goog.graphics.CanvasImageElement.prototype.draw = function(ctx) {
+ if (this.img_) {
+ if (this.w_ && this.h_) {
+ // If the image is already loaded, draw it.
+ ctx.drawImage(this.img_, this.x_, this.y_, this.w_, this.h_);
+ }
+ this.drawn_ = true;
+
+ } else {
+ // Otherwise, load it.
+ var img = new Image();
+ img.onload = goog.bind(this.handleImageLoad_, this, img);
+ // TODO(robbyw): Handle image load errors.
+ img.src = this.src_;
+ }
+};
+
+
+/**
+ * Handle an image load.
+ * @param {Element} img The image element that finished loading.
+ * @private
+ */
+goog.graphics.CanvasImageElement.prototype.handleImageLoad_ = function(img) {
+ this.img_ = img;
+
+ // TODO(robbyw): Add a small delay to catch batched images
+ this.getGraphics().redraw();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/canvasgraphics.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/canvasgraphics.js b/externs/GCL/externs/goog/graphics/canvasgraphics.js
new file mode 100644
index 0000000..2c55938
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/canvasgraphics.js
@@ -0,0 +1,670 @@
+// 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 CanvasGraphics sub class that uses the canvas tag for drawing.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.CanvasGraphics');
+
+
+goog.require('goog.dom.TagName');
+goog.require('goog.events.EventType');
+goog.require('goog.graphics.AbstractGraphics');
+goog.require('goog.graphics.CanvasEllipseElement');
+goog.require('goog.graphics.CanvasGroupElement');
+goog.require('goog.graphics.CanvasImageElement');
+goog.require('goog.graphics.CanvasPathElement');
+goog.require('goog.graphics.CanvasRectElement');
+goog.require('goog.graphics.CanvasTextElement');
+goog.require('goog.graphics.SolidFill');
+goog.require('goog.math.Size');
+goog.require('goog.style');
+
+
+
+/**
+ * A Graphics implementation for drawing using canvas.
+ * @param {string|number} width The (non-zero) width in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {string|number} height The (non-zero) height in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {?number=} opt_coordWidth The coordinate width - if
+ * omitted or null, defaults to same as width.
+ * @param {?number=} opt_coordHeight The coordinate height - if
+ * omitted or null, defaults to same as height.
+ * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
+ * document we want to render in.
+ * @constructor
+ * @extends {goog.graphics.AbstractGraphics}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.CanvasGraphics = function(width, height,
+ opt_coordWidth, opt_coordHeight,
+ opt_domHelper) {
+ goog.graphics.AbstractGraphics.call(this, width, height,
+ opt_coordWidth, opt_coordHeight,
+ opt_domHelper);
+};
+goog.inherits(goog.graphics.CanvasGraphics, goog.graphics.AbstractGraphics);
+
+
+/**
+ * Sets the fill for the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element
+ * wrapper.
+ * @param {goog.graphics.Fill} fill The fill object.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.setElementFill = function(element,
+ fill) {
+ this.redraw();
+};
+
+
+/**
+ * Sets the stroke for the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element
+ * wrapper.
+ * @param {goog.graphics.Stroke} stroke The stroke object.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.setElementStroke = function(
+ element, stroke) {
+ this.redraw();
+};
+
+
+/**
+ * Set the translation and rotation of an element.
+ *
+ * If a more general affine transform is needed than this provides
+ * (e.g. skew and scale) then use setElementAffineTransform.
+ * @param {goog.graphics.Element} element The element wrapper.
+ * @param {number} x The x coordinate of the translation transform.
+ * @param {number} y The y coordinate of the translation transform.
+ * @param {number} angle The angle of the rotation transform.
+ * @param {number} centerX The horizontal center of the rotation transform.
+ * @param {number} centerY The vertical center of the rotation transform.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.setElementTransform = function(element,
+ x, y, angle, centerX, centerY) {
+ this.redraw();
+};
+
+
+/**
+ * Set the transformation of an element.
+ *
+ * Note that in this implementation this method just calls this.redraw()
+ * and the affineTransform param is unused.
+ * @param {!goog.graphics.Element} element The element wrapper.
+ * @param {!goog.graphics.AffineTransform} affineTransform The
+ * transformation applied to this element.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.setElementAffineTransform =
+ function(element, affineTransform) {
+ this.redraw();
+};
+
+
+/**
+ * Push an element transform on to the transform stack.
+ * @param {goog.graphics.Element} element The transformed element.
+ */
+goog.graphics.CanvasGraphics.prototype.pushElementTransform = function(
+ element) {
+ var ctx = this.getContext();
+ ctx.save();
+
+ var transform = element.getTransform();
+
+ // TODO(robbyw): Test for unsupported transforms i.e. skews.
+ var tx = transform.getTranslateX();
+ var ty = transform.getTranslateY();
+ if (tx || ty) {
+ ctx.translate(tx, ty);
+ }
+
+ var sinTheta = transform.getShearY();
+ if (sinTheta) {
+ ctx.rotate(Math.asin(sinTheta));
+ }
+};
+
+
+/**
+ * Pop an element transform off of the transform stack.
+ */
+goog.graphics.CanvasGraphics.prototype.popElementTransform = function() {
+ this.getContext().restore();
+};
+
+
+/**
+ * Creates the DOM representation of the graphics area.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.createDom = function() {
+ var element = this.dom_.createDom(goog.dom.TagName.DIV,
+ {'style': 'position:relative;overflow:hidden'});
+ this.setElementInternal(element);
+
+ this.canvas_ = this.dom_.createDom(goog.dom.TagName.CANVAS);
+ element.appendChild(this.canvas_);
+
+ /**
+ * The main canvas element.
+ * @type {goog.graphics.CanvasGroupElement}
+ */
+ this.canvasElement = new goog.graphics.CanvasGroupElement(this);
+
+ this.lastGroup_ = this.canvasElement;
+ this.redrawTimeout_ = 0;
+
+ this.updateSize();
+};
+
+
+/**
+ * Clears the drawing context object in response to actions that make the old
+ * context invalid - namely resize of the canvas element.
+ * @private
+ */
+goog.graphics.CanvasGraphics.prototype.clearContext_ = function() {
+ this.context_ = null;
+};
+
+
+/**
+ * Returns the drawing context.
+ * @return {Object} The canvas element rendering context.
+ */
+goog.graphics.CanvasGraphics.prototype.getContext = function() {
+ if (!this.getElement()) {
+ this.createDom();
+ }
+ if (!this.context_) {
+ this.context_ = this.canvas_.getContext('2d');
+ this.context_.save();
+ }
+ return this.context_;
+};
+
+
+/**
+ * Changes the coordinate system position.
+ * @param {number} left The coordinate system left bound.
+ * @param {number} top The coordinate system top bound.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.setCoordOrigin = function(left, top) {
+ this.coordLeft = left;
+ this.coordTop = top;
+ this.redraw();
+};
+
+
+/**
+ * Changes the coordinate size.
+ * @param {number} coordWidth The coordinate width.
+ * @param {number} coordHeight The coordinate height.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.setCoordSize = function(coordWidth,
+ coordHeight) {
+ goog.graphics.CanvasGraphics.superClass_.setCoordSize.apply(this, arguments);
+ this.redraw();
+};
+
+
+/**
+ * Change the size of the canvas.
+ * @param {number} pixelWidth The width in pixels.
+ * @param {number} pixelHeight The height in pixels.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.setSize = function(pixelWidth,
+ pixelHeight) {
+ this.width = pixelWidth;
+ this.height = pixelHeight;
+
+ this.updateSize();
+ this.redraw();
+};
+
+
+/** @override */
+goog.graphics.CanvasGraphics.prototype.getPixelSize = function() {
+ // goog.style.getSize does not work for Canvas elements. We
+ // have to compute the size manually if it is percentage based.
+ var width = this.width;
+ var height = this.height;
+ var computeWidth = goog.isString(width) && width.indexOf('%') != -1;
+ var computeHeight = goog.isString(height) && height.indexOf('%') != -1;
+
+ if (!this.isInDocument() && (computeWidth || computeHeight)) {
+ return null;
+ }
+
+ var parent;
+ var parentSize;
+
+ if (computeWidth) {
+ parent = /** @type {Element} */ (this.getElement().parentNode);
+ parentSize = goog.style.getSize(parent);
+ width = parseFloat(/** @type {string} */ (width)) * parentSize.width / 100;
+ }
+
+ if (computeHeight) {
+ parent = parent || /** @type {Element} */ (this.getElement().parentNode);
+ parentSize = parentSize || goog.style.getSize(parent);
+ height = parseFloat(/** @type {string} */ (height)) * parentSize.height /
+ 100;
+ }
+
+ return new goog.math.Size(/** @type {number} */ (width),
+ /** @type {number} */ (height));
+};
+
+
+/**
+ * Update the size of the canvas.
+ */
+goog.graphics.CanvasGraphics.prototype.updateSize = function() {
+ goog.style.setSize(this.getElement(), this.width, this.height);
+
+ var pixels = this.getPixelSize();
+ if (pixels) {
+ goog.style.setSize(this.canvas_,
+ /** @type {number} */ (pixels.width),
+ /** @type {number} */ (pixels.height));
+ this.canvas_.width = pixels.width;
+ this.canvas_.height = pixels.height;
+ this.clearContext_();
+ }
+};
+
+
+/**
+ * Reset the canvas.
+ */
+goog.graphics.CanvasGraphics.prototype.reset = function() {
+ var ctx = this.getContext();
+ ctx.restore();
+ var size = this.getPixelSize();
+ if (size.width && size.height) {
+ ctx.clearRect(0, 0, size.width, size.height);
+ }
+ ctx.save();
+};
+
+
+/**
+ * Remove all drawing elements from the graphics.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.clear = function() {
+ this.reset();
+ this.canvasElement.clear();
+ var el = this.getElement();
+
+ // Remove all children (text nodes) except the canvas (which is at index 0)
+ while (el.childNodes.length > 1) {
+ el.removeChild(el.lastChild);
+ }
+};
+
+
+/**
+ * Redraw the entire canvas.
+ */
+goog.graphics.CanvasGraphics.prototype.redraw = function() {
+ if (this.preventRedraw_) {
+ this.needsRedraw_ = true;
+ return;
+ }
+
+ if (this.isInDocument()) {
+ this.reset();
+
+ if (this.coordWidth) {
+ var pixels = this.getPixelSize();
+ this.getContext().scale(pixels.width / this.coordWidth,
+ pixels.height / this.coordHeight);
+ }
+ if (this.coordLeft || this.coordTop) {
+ this.getContext().translate(-this.coordLeft, -this.coordTop);
+ }
+ this.pushElementTransform(this.canvasElement);
+ this.canvasElement.draw(this.context_);
+ this.popElementTransform();
+ }
+};
+
+
+/**
+ * Draw an element, including any stroke or fill.
+ * @param {goog.graphics.Element} element The element to draw.
+ */
+goog.graphics.CanvasGraphics.prototype.drawElement = function(element) {
+ if (element instanceof goog.graphics.CanvasTextElement) {
+ // Don't draw text since that is not implemented using canvas.
+ return;
+ }
+
+ var ctx = this.getContext();
+ this.pushElementTransform(element);
+
+ if (!element.getFill || !element.getStroke) {
+ // Draw without stroke or fill (e.g. the element is an image or group).
+ element.draw(ctx);
+ this.popElementTransform();
+ return;
+ }
+
+ var fill = element.getFill();
+ if (fill) {
+ if (fill instanceof goog.graphics.SolidFill) {
+ if (fill.getOpacity() != 0) {
+ ctx.globalAlpha = fill.getOpacity();
+ ctx.fillStyle = fill.getColor();
+ element.draw(ctx);
+ ctx.fill();
+ ctx.globalAlpha = 1;
+ }
+ } else { // (fill instanceof goog.graphics.LinearGradient)
+ var linearGradient = ctx.createLinearGradient(fill.getX1(), fill.getY1(),
+ fill.getX2(), fill.getY2());
+ linearGradient.addColorStop(0.0, fill.getColor1());
+ linearGradient.addColorStop(1.0, fill.getColor2());
+
+ ctx.fillStyle = linearGradient;
+ element.draw(ctx);
+ ctx.fill();
+ }
+ }
+
+ var stroke = element.getStroke();
+ if (stroke) {
+ element.draw(ctx);
+ ctx.strokeStyle = stroke.getColor();
+
+ var width = stroke.getWidth();
+ if (goog.isString(width) && width.indexOf('px') != -1) {
+ width = parseFloat(width) / this.getPixelScaleX();
+ }
+ ctx.lineWidth = width;
+
+ ctx.stroke();
+ }
+
+ this.popElementTransform();
+};
+
+
+/**
+ * Append an element.
+ *
+ * @param {goog.graphics.Element} element The element to draw.
+ * @param {goog.graphics.GroupElement|undefined} group The group to draw
+ * it in. If null or undefined, defaults to the root group.
+ * @protected
+ */
+goog.graphics.CanvasGraphics.prototype.append = function(element, group) {
+ group = group || this.canvasElement;
+ group.appendChild(element);
+
+ if (this.isDrawable(group)) {
+ this.drawElement(element);
+ }
+};
+
+
+/**
+ * Draw an ellipse.
+ *
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ * @param {goog.graphics.Stroke} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper
+ * element to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.EllipseElement} The newly created element.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.drawEllipse = function(cx, cy, rx, ry,
+ stroke, fill, opt_group) {
+ var element = new goog.graphics.CanvasEllipseElement(null, this,
+ cx, cy, rx, ry, stroke, fill);
+ this.append(element, opt_group);
+ return element;
+};
+
+
+/**
+ * Draw a rectangle.
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @param {goog.graphics.Stroke} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper
+ * element to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.RectElement} The newly created element.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.drawRect = function(x, y, width, height,
+ stroke, fill, opt_group) {
+ var element = new goog.graphics.CanvasRectElement(null, this,
+ x, y, width, height, stroke, fill);
+ this.append(element, opt_group);
+ return element;
+};
+
+
+/**
+ * Draw an image.
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of image.
+ * @param {number} height Height of image.
+ * @param {string} src Source of the image.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper
+ * element to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.ImageElement} The newly created element.
+ */
+goog.graphics.CanvasGraphics.prototype.drawImage = function(x, y, width, height,
+ src, opt_group) {
+ var element = new goog.graphics.CanvasImageElement(null, this, x, y, width,
+ height, src);
+ this.append(element, opt_group);
+ return element;
+};
+
+
+/**
+ * Draw a text string vertically centered on a given line.
+ *
+ * @param {string} text The text to draw.
+ * @param {number} x1 X coordinate of start of line.
+ * @param {number} y1 Y coordinate of start of line.
+ * @param {number} x2 X coordinate of end of line.
+ * @param {number} y2 Y coordinate of end of line.
+ * @param {?string} align Horizontal alignment: left (default), center, right.
+ * @param {goog.graphics.Font} font Font describing the font properties.
+ * @param {goog.graphics.Stroke} stroke Stroke object describing the stroke.
+ * @param {goog.graphics.Fill} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper
+ * element to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.TextElement} The newly created element.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.drawTextOnLine = function(
+ text, x1, y1, x2, y2, align, font, stroke, fill, opt_group) {
+ var element = new goog.graphics.CanvasTextElement(this,
+ text, x1, y1, x2, y2, align, /** @type {!goog.graphics.Font} */ (font),
+ stroke, fill);
+ this.append(element, opt_group);
+ return element;
+};
+
+
+/**
+ * Draw a path.
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @param {goog.graphics.Stroke} stroke Stroke object describing the stroke.
+ * @param {goog.graphics.Fill} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper
+ * element to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.PathElement} The newly created element.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.drawPath = function(path, stroke, fill,
+ opt_group) {
+ var element = new goog.graphics.CanvasPathElement(null, this,
+ path, stroke, fill);
+ this.append(element, opt_group);
+ return element;
+};
+
+
+/**
+ * @param {goog.graphics.GroupElement} group The group to possibly
+ * draw to.
+ * @return {boolean} Whether drawing can occur now.
+ */
+goog.graphics.CanvasGraphics.prototype.isDrawable = function(group) {
+ return this.isInDocument() && !this.redrawTimeout_ &&
+ !this.isRedrawRequired(group);
+};
+
+
+/**
+ * Returns true if drawing to the given group means a redraw is required.
+ * @param {goog.graphics.GroupElement} group The group to draw to.
+ * @return {boolean} Whether drawing to this group should force a redraw.
+ */
+goog.graphics.CanvasGraphics.prototype.isRedrawRequired = function(group) {
+ // TODO(robbyw): Moving up to any parent of lastGroup should not force redraw.
+ return group != this.canvasElement && group != this.lastGroup_;
+};
+
+
+/**
+ * Create an empty group of drawing elements.
+ *
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper
+ * element to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.CanvasGroupElement} The newly created group.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.createGroup = function(opt_group) {
+ var group = new goog.graphics.CanvasGroupElement(this);
+
+ opt_group = opt_group || this.canvasElement;
+
+ // TODO(robbyw): Moving up to any parent group should not force redraw.
+ if (opt_group == this.canvasElement || opt_group == this.lastGroup_) {
+ this.lastGroup_ = group;
+ }
+
+ this.append(group, opt_group);
+
+ return group;
+};
+
+
+/**
+ * Measure and return the width (in pixels) of a given text string.
+ * Text measurement is needed to make sure a text can fit in the allocated
+ * area. The way text length is measured is by writing it into a div that is
+ * after the visible area, measure the div width, and immediatly erase the
+ * written value.
+ *
+ * @param {string} text The text string to measure.
+ * @param {goog.graphics.Font} font The font object describing the font style.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.getTextWidth = goog.abstractMethod;
+
+
+/**
+ * Disposes of the component by removing event handlers, detacing DOM nodes from
+ * the document body, and removing references to them.
+ * @override
+ * @protected
+ */
+goog.graphics.CanvasGraphics.prototype.disposeInternal = function() {
+ this.context_ = null;
+ goog.graphics.CanvasGraphics.superClass_.disposeInternal.call(this);
+};
+
+
+/** @override */
+goog.graphics.CanvasGraphics.prototype.enterDocument = function() {
+ var oldPixelSize = this.getPixelSize();
+ goog.graphics.CanvasGraphics.superClass_.enterDocument.call(this);
+ if (!oldPixelSize) {
+ this.updateSize();
+ this.dispatchEvent(goog.events.EventType.RESIZE);
+ }
+ this.redraw();
+};
+
+
+/**
+ * Start preventing redraws - useful for chaining large numbers of changes
+ * together. Not guaranteed to do anything - i.e. only use this for
+ * optimization of a single code path.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.suspend = function() {
+ this.preventRedraw_ = true;
+};
+
+
+/**
+ * Stop preventing redraws. If any redraws had been prevented, a redraw will
+ * be done now.
+ * @override
+ */
+goog.graphics.CanvasGraphics.prototype.resume = function() {
+ this.preventRedraw_ = false;
+
+ if (this.needsRedraw_) {
+ this.redraw();
+ this.needsRedraw_ = false;
+ }
+};
[49/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/a11y/aria/attributes.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/a11y/aria/attributes.js b/externs/GCL/externs/goog/a11y/aria/attributes.js
new file mode 100644
index 0000000..f4e0a3d
--- /dev/null
+++ b/externs/GCL/externs/goog/a11y/aria/attributes.js
@@ -0,0 +1,389 @@
+// 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 The file contains generated enumerations for ARIA states
+ * and properties as defined by W3C ARIA standard:
+ * http://www.w3.org/TR/wai-aria/.
+ *
+ * This is auto-generated code. Do not manually edit! For more details
+ * about how to edit it via the generator check go/closure-ariagen.
+ */
+
+goog.provide('goog.a11y.aria.AutoCompleteValues');
+goog.provide('goog.a11y.aria.CheckedValues');
+goog.provide('goog.a11y.aria.DropEffectValues');
+goog.provide('goog.a11y.aria.ExpandedValues');
+goog.provide('goog.a11y.aria.GrabbedValues');
+goog.provide('goog.a11y.aria.InvalidValues');
+goog.provide('goog.a11y.aria.LivePriority');
+goog.provide('goog.a11y.aria.OrientationValues');
+goog.provide('goog.a11y.aria.PressedValues');
+goog.provide('goog.a11y.aria.RelevantValues');
+goog.provide('goog.a11y.aria.SelectedValues');
+goog.provide('goog.a11y.aria.SortValues');
+goog.provide('goog.a11y.aria.State');
+
+
+/**
+ * ARIA states and properties.
+ * @enum {string}
+ */
+goog.a11y.aria.State = {
+ // ARIA property for setting the currently active descendant of an element,
+ // for example the selected item in a list box. Value: ID of an element.
+ ACTIVEDESCENDANT: 'activedescendant',
+
+ // ARIA property that, if true, indicates that all of a changed region should
+ // be presented, instead of only parts. Value: one of {true, false}.
+ ATOMIC: 'atomic',
+
+ // ARIA property to specify that input completion is provided. Value:
+ // one of {'inline', 'list', 'both', 'none'}.
+ AUTOCOMPLETE: 'autocomplete',
+
+ // ARIA state to indicate that an element and its subtree are being updated.
+ // Value: one of {true, false}.
+ BUSY: 'busy',
+
+ // ARIA state for a checked item. Value: one of {'true', 'false', 'mixed',
+ // undefined}.
+ CHECKED: 'checked',
+
+ // ARIA property that identifies the element or elements whose contents or
+ // presence are controlled by this element.
+ // Value: space-separated IDs of other elements.
+ CONTROLS: 'controls',
+
+ // ARIA property that identifies the element or elements that describe
+ // this element. Value: space-separated IDs of other elements.
+ DESCRIBEDBY: 'describedby',
+
+ // ARIA state for a disabled item. Value: one of {true, false}.
+ DISABLED: 'disabled',
+
+ // ARIA property that indicates what functions can be performed when a
+ // dragged object is released on the drop target. Value: one of
+ // {'copy', 'move', 'link', 'execute', 'popup', 'none'}.
+ DROPEFFECT: 'dropeffect',
+
+ // ARIA state for setting whether the element like a tree node is expanded.
+ // Value: one of {true, false, undefined}.
+ EXPANDED: 'expanded',
+
+ // ARIA property that identifies the next element (or elements) in the
+ // recommended reading order of content. Value: space-separated ids of
+ // elements to flow to.
+ FLOWTO: 'flowto',
+
+ // ARIA state that indicates an element's "grabbed" state in drag-and-drop.
+ // Value: one of {true, false, undefined}.
+ GRABBED: 'grabbed',
+
+ // ARIA property indicating whether the element has a popup.
+ // Value: one of {true, false}.
+ HASPOPUP: 'haspopup',
+
+ // ARIA state indicating that the element is not visible or perceivable
+ // to any user. Value: one of {true, false}.
+ HIDDEN: 'hidden',
+
+ // ARIA state indicating that the entered value does not conform. Value:
+ // one of {false, true, 'grammar', 'spelling'}
+ INVALID: 'invalid',
+
+ // ARIA property that provides a label to override any other text, value, or
+ // contents used to describe this element. Value: string.
+ LABEL: 'label',
+
+ // ARIA property for setting the element which labels another element.
+ // Value: space-separated IDs of elements.
+ LABELLEDBY: 'labelledby',
+
+ // ARIA property for setting the level of an element in the hierarchy.
+ // Value: integer.
+ LEVEL: 'level',
+
+ // ARIA property indicating that an element will be updated, and
+ // describes the types of updates the user agents, assistive technologies,
+ // and user can expect from the live region. Value: one of {'off', 'polite',
+ // 'assertive'}.
+ LIVE: 'live',
+
+ // ARIA property indicating whether a text box can accept multiline input.
+ // Value: one of {true, false}.
+ MULTILINE: 'multiline',
+
+ // ARIA property indicating if the user may select more than one item.
+ // Value: one of {true, false}.
+ MULTISELECTABLE: 'multiselectable',
+
+ // ARIA property indicating if the element is horizontal or vertical.
+ // Value: one of {'vertical', 'horizontal'}.
+ ORIENTATION: 'orientation',
+
+ // ARIA property creating a visual, functional, or contextual parent/child
+ // relationship when the DOM hierarchy can't be used to represent it.
+ // Value: Space-separated IDs of elements.
+ OWNS: 'owns',
+
+ // ARIA property that defines an element's number of position in a list.
+ // Value: integer.
+ POSINSET: 'posinset',
+
+ // ARIA state for a pressed item.
+ // Value: one of {true, false, undefined, 'mixed'}.
+ PRESSED: 'pressed',
+
+ // ARIA property indicating that an element is not editable.
+ // Value: one of {true, false}.
+ READONLY: 'readonly',
+
+ // ARIA property indicating that change notifications within this subtree
+ // of a live region should be announced. Value: one of {'additions',
+ // 'removals', 'text', 'all', 'additions text'}.
+ RELEVANT: 'relevant',
+
+ // ARIA property indicating that user input is required on this element
+ // before a form may be submitted. Value: one of {true, false}.
+ REQUIRED: 'required',
+
+ // ARIA state for setting the currently selected item in the list.
+ // Value: one of {true, false, undefined}.
+ SELECTED: 'selected',
+
+ // ARIA property defining the number of items in a list. Value: integer.
+ SETSIZE: 'setsize',
+
+ // ARIA property indicating if items are sorted. Value: one of {'ascending',
+ // 'descending', 'none', 'other'}.
+ SORT: 'sort',
+
+ // ARIA property for slider maximum value. Value: number.
+ VALUEMAX: 'valuemax',
+
+ // ARIA property for slider minimum value. Value: number.
+ VALUEMIN: 'valuemin',
+
+ // ARIA property for slider active value. Value: number.
+ VALUENOW: 'valuenow',
+
+ // ARIA property for slider active value represented as text.
+ // Value: string.
+ VALUETEXT: 'valuetext'
+};
+
+
+/**
+ * ARIA state values for AutoCompleteValues.
+ * @enum {string}
+ */
+goog.a11y.aria.AutoCompleteValues = {
+ // The system provides text after the caret as a suggestion
+ // for how to complete the field.
+ INLINE: 'inline',
+ // A list of choices appears from which the user can choose,
+ // but the edit box retains focus.
+ LIST: 'list',
+ // A list of choices appears and the currently selected suggestion
+ // also appears inline.
+ BOTH: 'both',
+ // No input completion suggestions are provided.
+ NONE: 'none'
+};
+
+
+/**
+ * ARIA state values for DropEffectValues.
+ * @enum {string}
+ */
+goog.a11y.aria.DropEffectValues = {
+ // A duplicate of the source object will be dropped into the target.
+ COPY: 'copy',
+ // The source object will be removed from its current location
+ // and dropped into the target.
+ MOVE: 'move',
+ // A reference or shortcut to the dragged object
+ // will be created in the target object.
+ LINK: 'link',
+ // A function supported by the drop target is
+ // executed, using the drag source as an input.
+ EXECUTE: 'execute',
+ // There is a popup menu or dialog that allows the user to choose
+ // one of the drag operations (copy, move, link, execute) and any other
+ // drag functionality, such as cancel.
+ POPUP: 'popup',
+ // No operation can be performed; effectively
+ // cancels the drag operation if an attempt is made to drop on this object.
+ NONE: 'none'
+};
+
+
+/**
+ * ARIA state values for LivePriority.
+ * @enum {string}
+ */
+goog.a11y.aria.LivePriority = {
+ // Updates to the region will not be presented to the user
+ // unless the assitive technology is currently focused on that region.
+ OFF: 'off',
+ // (Background change) Assistive technologies SHOULD announce
+ // updates at the next graceful opportunity, such as at the end of
+ // speaking the current sentence or when the user pauses typing.
+ POLITE: 'polite',
+ // This information has the highest priority and assistive
+ // technologies SHOULD notify the user immediately.
+ // Because an interruption may disorient users or cause them to not complete
+ // their current task, authors SHOULD NOT use the assertive value unless the
+ // interruption is imperative.
+ ASSERTIVE: 'assertive'
+};
+
+
+/**
+ * ARIA state values for OrientationValues.
+ * @enum {string}
+ */
+goog.a11y.aria.OrientationValues = {
+ // The element is oriented vertically.
+ VERTICAL: 'vertical',
+ // The element is oriented horizontally.
+ HORIZONTAL: 'horizontal'
+};
+
+
+/**
+ * ARIA state values for RelevantValues.
+ * @enum {string}
+ */
+goog.a11y.aria.RelevantValues = {
+ // Element nodes are added to the DOM within the live region.
+ ADDITIONS: 'additions',
+ // Text or element nodes within the live region are removed from the DOM.
+ REMOVALS: 'removals',
+ // Text is added to any DOM descendant nodes of the live region.
+ TEXT: 'text',
+ // Equivalent to the combination of all values, "additions removals text".
+ ALL: 'all'
+};
+
+
+/**
+ * ARIA state values for SortValues.
+ * @enum {string}
+ */
+goog.a11y.aria.SortValues = {
+ // Items are sorted in ascending order by this column.
+ ASCENDING: 'ascending',
+ // Items are sorted in descending order by this column.
+ DESCENDING: 'descending',
+ // There is no defined sort applied to the column.
+ NONE: 'none',
+ // A sort algorithm other than ascending or descending has been applied.
+ OTHER: 'other'
+};
+
+
+/**
+ * ARIA state values for CheckedValues.
+ * @enum {string}
+ */
+goog.a11y.aria.CheckedValues = {
+ // The selectable element is checked.
+ TRUE: 'true',
+ // The selectable element is not checked.
+ FALSE: 'false',
+ // Indicates a mixed mode value for a tri-state
+ // checkbox or menuitemcheckbox.
+ MIXED: 'mixed',
+ // The element does not support being checked.
+ UNDEFINED: 'undefined'
+};
+
+
+/**
+ * ARIA state values for ExpandedValues.
+ * @enum {string}
+ */
+goog.a11y.aria.ExpandedValues = {
+ // The element, or another grouping element it controls, is expanded.
+ TRUE: 'true',
+ // The element, or another grouping element it controls, is collapsed.
+ FALSE: 'false',
+ // The element, or another grouping element
+ // it controls, is neither expandable nor collapsible; all its
+ // child elements are shown or there are no child elements.
+ UNDEFINED: 'undefined'
+};
+
+
+/**
+ * ARIA state values for GrabbedValues.
+ * @enum {string}
+ */
+goog.a11y.aria.GrabbedValues = {
+ // Indicates that the element has been "grabbed" for dragging.
+ TRUE: 'true',
+ // Indicates that the element supports being dragged.
+ FALSE: 'false',
+ // Indicates that the element does not support being dragged.
+ UNDEFINED: 'undefined'
+};
+
+
+/**
+ * ARIA state values for InvalidValues.
+ * @enum {string}
+ */
+goog.a11y.aria.InvalidValues = {
+ // There are no detected errors in the value.
+ FALSE: 'false',
+ // The value entered by the user has failed validation.
+ TRUE: 'true',
+ // A grammatical error was detected.
+ GRAMMAR: 'grammar',
+ // A spelling error was detected.
+ SPELLING: 'spelling'
+};
+
+
+/**
+ * ARIA state values for PressedValues.
+ * @enum {string}
+ */
+goog.a11y.aria.PressedValues = {
+ // The element is pressed.
+ TRUE: 'true',
+ // The element supports being pressed but is not currently pressed.
+ FALSE: 'false',
+ // Indicates a mixed mode value for a tri-state toggle button.
+ MIXED: 'mixed',
+ // The element does not support being pressed.
+ UNDEFINED: 'undefined'
+};
+
+
+/**
+ * ARIA state values for SelectedValues.
+ * @enum {string}
+ */
+goog.a11y.aria.SelectedValues = {
+ // The selectable element is selected.
+ TRUE: 'true',
+ // The selectable element is not selected.
+ FALSE: 'false',
+ // The element is not selectable.
+ UNDEFINED: 'undefined'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/a11y/aria/datatables.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/a11y/aria/datatables.js b/externs/GCL/externs/goog/a11y/aria/datatables.js
new file mode 100644
index 0000000..f1ba566
--- /dev/null
+++ b/externs/GCL/externs/goog/a11y/aria/datatables.js
@@ -0,0 +1,68 @@
+// 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 The file contains data tables generated from the ARIA
+ * standard schema http://www.w3.org/TR/wai-aria/.
+ *
+ * This is auto-generated code. Do not manually edit!
+ */
+
+goog.provide('goog.a11y.aria.datatables');
+
+goog.require('goog.a11y.aria.State');
+goog.require('goog.object');
+
+
+/**
+ * A map that contains mapping between an ARIA state and the default value
+ * for it. Note that not all ARIA states have default values.
+ *
+ * @type {Object<!(goog.a11y.aria.State|string), (string|boolean|number)>}
+ */
+goog.a11y.aria.DefaultStateValueMap_;
+
+
+/**
+ * A method that creates a map that contains mapping between an ARIA state and
+ * the default value for it. Note that not all ARIA states have default values.
+ *
+ * @return {!Object<!(goog.a11y.aria.State|string), (string|boolean|number)>}
+ * The names for each of the notification methods.
+ */
+goog.a11y.aria.datatables.getDefaultValuesMap = function() {
+ if (!goog.a11y.aria.DefaultStateValueMap_) {
+ goog.a11y.aria.DefaultStateValueMap_ = goog.object.create(
+ goog.a11y.aria.State.ATOMIC, false,
+ goog.a11y.aria.State.AUTOCOMPLETE, 'none',
+ goog.a11y.aria.State.DROPEFFECT, 'none',
+ goog.a11y.aria.State.HASPOPUP, false,
+ goog.a11y.aria.State.LIVE, 'off',
+ goog.a11y.aria.State.MULTILINE, false,
+ goog.a11y.aria.State.MULTISELECTABLE, false,
+ goog.a11y.aria.State.ORIENTATION, 'vertical',
+ goog.a11y.aria.State.READONLY, false,
+ goog.a11y.aria.State.RELEVANT, 'additions text',
+ goog.a11y.aria.State.REQUIRED, false,
+ goog.a11y.aria.State.SORT, 'none',
+ goog.a11y.aria.State.BUSY, false,
+ goog.a11y.aria.State.DISABLED, false,
+ goog.a11y.aria.State.HIDDEN, false,
+ goog.a11y.aria.State.INVALID, 'false');
+ }
+
+ return goog.a11y.aria.DefaultStateValueMap_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/a11y/aria/roles.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/a11y/aria/roles.js b/externs/GCL/externs/goog/a11y/aria/roles.js
new file mode 100644
index 0000000..a282cc2
--- /dev/null
+++ b/externs/GCL/externs/goog/a11y/aria/roles.js
@@ -0,0 +1,216 @@
+// 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 The file contains generated enumerations for ARIA roles
+ * as defined by W3C ARIA standard: http://www.w3.org/TR/wai-aria/.
+ *
+ * This is auto-generated code. Do not manually edit! For more details
+ * about how to edit it via the generator check go/closure-ariagen.
+ */
+
+goog.provide('goog.a11y.aria.Role');
+
+
+/**
+ * ARIA role values.
+ * @enum {string}
+ */
+goog.a11y.aria.Role = {
+ // ARIA role for an alert element that doesn't need to be explicitly closed.
+ ALERT: 'alert',
+
+ // ARIA role for an alert dialog element that takes focus and must be closed.
+ ALERTDIALOG: 'alertdialog',
+
+ // ARIA role for an application that implements its own keyboard navigation.
+ APPLICATION: 'application',
+
+ // ARIA role for an article.
+ ARTICLE: 'article',
+
+ // ARIA role for a banner containing mostly site content, not page content.
+ BANNER: 'banner',
+
+ // ARIA role for a button element.
+ BUTTON: 'button',
+
+ // ARIA role for a checkbox button element; use with the CHECKED state.
+ CHECKBOX: 'checkbox',
+
+ // ARIA role for a column header of a table or grid.
+ COLUMNHEADER: 'columnheader',
+
+ // ARIA role for a combo box element.
+ COMBOBOX: 'combobox',
+
+ // ARIA role for a supporting section of the document.
+ COMPLEMENTARY: 'complementary',
+
+ // ARIA role for a large perceivable region that contains information
+ // about the parent document.
+ CONTENTINFO: 'contentinfo',
+
+ // ARIA role for a definition of a term or concept.
+ DEFINITION: 'definition',
+
+ // ARIA role for a dialog, some descendant must take initial focus.
+ DIALOG: 'dialog',
+
+ // ARIA role for a directory, like a table of contents.
+ DIRECTORY: 'directory',
+
+ // ARIA role for a part of a page that's a document, not a web application.
+ DOCUMENT: 'document',
+
+ // ARIA role for a landmark region logically considered one form.
+ FORM: 'form',
+
+ // ARIA role for an interactive control of tabular data.
+ GRID: 'grid',
+
+ // ARIA role for a cell in a grid.
+ GRIDCELL: 'gridcell',
+
+ // ARIA role for a group of related elements like tree item siblings.
+ GROUP: 'group',
+
+ // ARIA role for a heading element.
+ HEADING: 'heading',
+
+ // ARIA role for a container of elements that together comprise one image.
+ IMG: 'img',
+
+ // ARIA role for a link.
+ LINK: 'link',
+
+ // ARIA role for a list of non-interactive list items.
+ LIST: 'list',
+
+ // ARIA role for a listbox.
+ LISTBOX: 'listbox',
+
+ // ARIA role for a list item.
+ LISTITEM: 'listitem',
+
+ // ARIA role for a live region where new information is added.
+ LOG: 'log',
+
+ // ARIA landmark role for the main content in a document. Use only once.
+ MAIN: 'main',
+
+ // ARIA role for a live region of non-essential information that changes.
+ MARQUEE: 'marquee',
+
+ // ARIA role for a mathematical expression.
+ MATH: 'math',
+
+ // ARIA role for a popup menu.
+ MENU: 'menu',
+
+ // ARIA role for a menubar element containing menu elements.
+ MENUBAR: 'menubar',
+
+ // ARIA role for menu item elements.
+ MENU_ITEM: 'menuitem',
+
+ // ARIA role for a checkbox box element inside a menu.
+ MENU_ITEM_CHECKBOX: 'menuitemcheckbox',
+
+ // ARIA role for a radio button element inside a menu.
+ MENU_ITEM_RADIO: 'menuitemradio',
+
+ // ARIA landmark role for a collection of navigation links.
+ NAVIGATION: 'navigation',
+
+ // ARIA role for a section ancillary to the main content.
+ NOTE: 'note',
+
+ // ARIA role for option items that are children of combobox, listbox, menu,
+ // radiogroup, or tree elements.
+ OPTION: 'option',
+
+ // ARIA role for ignorable cosmetic elements with no semantic significance.
+ PRESENTATION: 'presentation',
+
+ // ARIA role for a progress bar element.
+ PROGRESSBAR: 'progressbar',
+
+ // ARIA role for a radio button element.
+ RADIO: 'radio',
+
+ // ARIA role for a group of connected radio button elements.
+ RADIOGROUP: 'radiogroup',
+
+ // ARIA role for an important region of the page.
+ REGION: 'region',
+
+ // ARIA role for a row of cells in a grid.
+ ROW: 'row',
+
+ // ARIA role for a group of one or more rows in a grid.
+ ROWGROUP: 'rowgroup',
+
+ // ARIA role for a row header of a table or grid.
+ ROWHEADER: 'rowheader',
+
+ // ARIA role for a scrollbar element.
+ SCROLLBAR: 'scrollbar',
+
+ // ARIA landmark role for a part of the page providing search functionality.
+ SEARCH: 'search',
+
+ // ARIA role for a menu separator.
+ SEPARATOR: 'separator',
+
+ // ARIA role for a slider.
+ SLIDER: 'slider',
+
+ // ARIA role for a spin button.
+ SPINBUTTON: 'spinbutton',
+
+ // ARIA role for a live region with advisory info less severe than an alert.
+ STATUS: 'status',
+
+ // ARIA role for a tab button.
+ TAB: 'tab',
+
+ // ARIA role for a tab bar (i.e. a list of tab buttons).
+ TAB_LIST: 'tablist',
+
+ // ARIA role for a tab page (i.e. the element holding tab contents).
+ TAB_PANEL: 'tabpanel',
+
+ // ARIA role for a textbox element.
+ TEXTBOX: 'textbox',
+
+ // ARIA role for an element displaying elapsed time or time remaining.
+ TIMER: 'timer',
+
+ // ARIA role for a toolbar element.
+ TOOLBAR: 'toolbar',
+
+ // ARIA role for a tooltip element.
+ TOOLTIP: 'tooltip',
+
+ // ARIA role for a tree.
+ TREE: 'tree',
+
+ // ARIA role for a grid whose rows can be expanded and collapsed like a tree.
+ TREEGRID: 'treegrid',
+
+ // ARIA role for a tree item that sometimes may be expanded or collapsed.
+ TREEITEM: 'treeitem'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/array/array.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/array/array.js b/externs/GCL/externs/goog/array/array.js
new file mode 100644
index 0000000..bd99626
--- /dev/null
+++ b/externs/GCL/externs/goog/array/array.js
@@ -0,0 +1,1655 @@
+// 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 manipulating arrays.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.array');
+goog.provide('goog.array.ArrayLike');
+
+goog.require('goog.asserts');
+
+
+/**
+ * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should
+ * rely on Array.prototype functions, if available.
+ *
+ * The Array.prototype functions can be defined by external libraries like
+ * Prototype and setting this flag to false forces closure to use its own
+ * goog.array implementation.
+ *
+ * If your javascript can be loaded by a third party site and you are wary about
+ * relying on the prototype functions, specify
+ * "--define goog.NATIVE_ARRAY_PROTOTYPES=false" to the JSCompiler.
+ *
+ * Setting goog.TRUSTED_SITE to false will automatically set
+ * NATIVE_ARRAY_PROTOTYPES to false.
+ */
+goog.define('goog.NATIVE_ARRAY_PROTOTYPES', goog.TRUSTED_SITE);
+
+
+/**
+ * @define {boolean} If true, JSCompiler will use the native implementation of
+ * array functions where appropriate (e.g., {@code Array#filter}) and remove the
+ * unused pure JS implementation.
+ */
+goog.define('goog.array.ASSUME_NATIVE_FUNCTIONS', false);
+
+
+/**
+ * @typedef {Array|NodeList|Arguments|{length: number}}
+ */
+goog.array.ArrayLike;
+
+
+/**
+ * Returns the last element in an array without removing it.
+ * Same as goog.array.last.
+ * @param {Array<T>|goog.array.ArrayLike} array The array.
+ * @return {T} Last item in array.
+ * @template T
+ */
+goog.array.peek = function(array) {
+ return array[array.length - 1];
+};
+
+
+/**
+ * Returns the last element in an array without removing it.
+ * Same as goog.array.peek.
+ * @param {Array<T>|goog.array.ArrayLike} array The array.
+ * @return {T} Last item in array.
+ * @template T
+ */
+goog.array.last = goog.array.peek;
+
+
+/**
+ * Reference to the original {@code Array.prototype}.
+ * @private
+ */
+goog.array.ARRAY_PROTOTYPE_ = Array.prototype;
+
+
+// NOTE(arv): Since most of the array functions are generic it allows you to
+// pass an array-like object. Strings have a length and are considered array-
+// like. However, the 'in' operator does not work on strings so we cannot just
+// use the array path even if the browser supports indexing into strings. We
+// therefore end up splitting the string.
+
+
+/**
+ * Returns the index of the first element of an array with a specified value, or
+ * -1 if the element is not present in the array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof}
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr The array to be searched.
+ * @param {T} obj The object for which we are searching.
+ * @param {number=} opt_fromIndex The index at which to start the search. If
+ * omitted the search starts at index 0.
+ * @return {number} The index of the first matching array element.
+ * @template T
+ */
+goog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.indexOf) ?
+ function(arr, obj, opt_fromIndex) {
+ goog.asserts.assert(arr.length != null);
+
+ return goog.array.ARRAY_PROTOTYPE_.indexOf.call(arr, obj, opt_fromIndex);
+ } :
+ function(arr, obj, opt_fromIndex) {
+ var fromIndex = opt_fromIndex == null ?
+ 0 : (opt_fromIndex < 0 ?
+ Math.max(0, arr.length + opt_fromIndex) : opt_fromIndex);
+
+ if (goog.isString(arr)) {
+ // Array.prototype.indexOf uses === so only strings should be found.
+ if (!goog.isString(obj) || obj.length != 1) {
+ return -1;
+ }
+ return arr.indexOf(obj, fromIndex);
+ }
+
+ for (var i = fromIndex; i < arr.length; i++) {
+ if (i in arr && arr[i] === obj)
+ return i;
+ }
+ return -1;
+ };
+
+
+/**
+ * Returns the index of the last element of an array with a specified value, or
+ * -1 if the element is not present in the array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof}
+ *
+ * @param {!Array<T>|!goog.array.ArrayLike} arr The array to be searched.
+ * @param {T} obj The object for which we are searching.
+ * @param {?number=} opt_fromIndex The index at which to start the search. If
+ * omitted the search starts at the end of the array.
+ * @return {number} The index of the last matching array element.
+ * @template T
+ */
+goog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.lastIndexOf) ?
+ function(arr, obj, opt_fromIndex) {
+ goog.asserts.assert(arr.length != null);
+
+ // Firefox treats undefined and null as 0 in the fromIndex argument which
+ // leads it to always return -1
+ var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
+ return goog.array.ARRAY_PROTOTYPE_.lastIndexOf.call(arr, obj, fromIndex);
+ } :
+ function(arr, obj, opt_fromIndex) {
+ var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
+
+ if (fromIndex < 0) {
+ fromIndex = Math.max(0, arr.length + fromIndex);
+ }
+
+ if (goog.isString(arr)) {
+ // Array.prototype.lastIndexOf uses === so only strings should be found.
+ if (!goog.isString(obj) || obj.length != 1) {
+ return -1;
+ }
+ return arr.lastIndexOf(obj, fromIndex);
+ }
+
+ for (var i = fromIndex; i >= 0; i--) {
+ if (i in arr && arr[i] === obj)
+ return i;
+ }
+ return -1;
+ };
+
+
+/**
+ * Calls a function for each element in an array. Skips holes in the array.
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach}
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array like object over
+ * which to iterate.
+ * @param {?function(this: S, T, number, ?): ?} f The function to call for every
+ * element. This function takes 3 arguments (the element, the index and the
+ * array). The return value is ignored.
+ * @param {S=} opt_obj The object to be used as the value of 'this' within f.
+ * @template T,S
+ */
+goog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.forEach) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ goog.array.ARRAY_PROTOTYPE_.forEach.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2) {
+ f.call(opt_obj, arr2[i], i, arr);
+ }
+ }
+ };
+
+
+/**
+ * Calls a function for each element in an array, starting from the last
+ * element rather than the first.
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this: S, T, number, ?): ?} f The function to call for every
+ * element. This function
+ * takes 3 arguments (the element, the index and the array). The return
+ * value is ignored.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @template T,S
+ */
+goog.array.forEachRight = function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = l - 1; i >= 0; --i) {
+ if (i in arr2) {
+ f.call(opt_obj, arr2[i], i, arr);
+ }
+ }
+};
+
+
+/**
+ * Calls a function for each element in an array, and if the function returns
+ * true adds the element to a new array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-filter}
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?):boolean} f The function to call for
+ * every element. This function
+ * takes 3 arguments (the element, the index and the array) and must
+ * return a Boolean. If the return value is true the element is added to the
+ * result array. If it is false the element is not included.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {!Array<T>} a new array in which only elements that passed the test
+ * are present.
+ * @template T,S
+ */
+goog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.filter) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return goog.array.ARRAY_PROTOTYPE_.filter.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var res = [];
+ var resLength = 0;
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2) {
+ var val = arr2[i]; // in case f mutates arr2
+ if (f.call(opt_obj, val, i, arr)) {
+ res[resLength++] = val;
+ }
+ }
+ }
+ return res;
+ };
+
+
+/**
+ * Calls a function for each element in an array and inserts the result into a
+ * new array.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-map}
+ *
+ * @param {Array<VALUE>|goog.array.ArrayLike} arr Array or array like object
+ * over which to iterate.
+ * @param {function(this:THIS, VALUE, number, ?): RESULT} f The function to call
+ * for every element. This function takes 3 arguments (the element,
+ * the index and the array) and should return something. The result will be
+ * inserted into a new array.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this' within f.
+ * @return {!Array<RESULT>} a new array with the results from f.
+ * @template THIS, VALUE, RESULT
+ */
+goog.array.map = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.map) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return goog.array.ARRAY_PROTOTYPE_.map.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var res = new Array(l);
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2) {
+ res[i] = f.call(opt_obj, arr2[i], i, arr);
+ }
+ }
+ return res;
+ };
+
+
+/**
+ * Passes every element of an array into a function and accumulates the result.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce}
+ *
+ * For example:
+ * var a = [1, 2, 3, 4];
+ * goog.array.reduce(a, function(r, v, i, arr) {return r + v;}, 0);
+ * returns 10
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {function(this:S, R, T, number, ?) : R} f The function to call for
+ * every element. This function
+ * takes 4 arguments (the function's previous result or the initial value,
+ * the value of the current array element, the current array index, and the
+ * array itself)
+ * function(previousValue, currentValue, index, array).
+ * @param {?} val The initial value to pass into the function on the first call.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {R} Result of evaluating f repeatedly across the values of the array.
+ * @template T,S,R
+ */
+goog.array.reduce = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.reduce) ?
+ function(arr, f, val, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+ if (opt_obj) {
+ f = goog.bind(f, opt_obj);
+ }
+ return goog.array.ARRAY_PROTOTYPE_.reduce.call(arr, f, val);
+ } :
+ function(arr, f, val, opt_obj) {
+ var rval = val;
+ goog.array.forEach(arr, function(val, index) {
+ rval = f.call(opt_obj, rval, val, index, arr);
+ });
+ return rval;
+ };
+
+
+/**
+ * Passes every element of an array into a function and accumulates the result,
+ * starting from the last element and working towards the first.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright}
+ *
+ * For example:
+ * var a = ['a', 'b', 'c'];
+ * goog.array.reduceRight(a, function(r, v, i, arr) {return r + v;}, '');
+ * returns 'cba'
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, R, T, number, ?) : R} f The function to call for
+ * every element. This function
+ * takes 4 arguments (the function's previous result or the initial value,
+ * the value of the current array element, the current array index, and the
+ * array itself)
+ * function(previousValue, currentValue, index, array).
+ * @param {?} val The initial value to pass into the function on the first call.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {R} Object returned as a result of evaluating f repeatedly across the
+ * values of the array.
+ * @template T,S,R
+ */
+goog.array.reduceRight = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.reduceRight) ?
+ function(arr, f, val, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+ if (opt_obj) {
+ f = goog.bind(f, opt_obj);
+ }
+ return goog.array.ARRAY_PROTOTYPE_.reduceRight.call(arr, f, val);
+ } :
+ function(arr, f, val, opt_obj) {
+ var rval = val;
+ goog.array.forEachRight(arr, function(val, index) {
+ rval = f.call(opt_obj, rval, val, index, arr);
+ });
+ return rval;
+ };
+
+
+/**
+ * Calls f for each element of an array. If any call returns true, some()
+ * returns true (without checking the remaining elements). If all calls
+ * return false, some() returns false.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-some}
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
+ * for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a boolean.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {boolean} true if any element passes the test.
+ * @template T,S
+ */
+goog.array.some = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.some) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return goog.array.ARRAY_PROTOTYPE_.some.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+
+/**
+ * Call f for each element of an array. If all calls return true, every()
+ * returns true. If any call returns false, every() returns false and
+ * does not continue to check the remaining elements.
+ *
+ * See {@link http://tinyurl.com/developer-mozilla-org-array-every}
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
+ * for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a boolean.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within f.
+ * @return {boolean} false if any element fails the test.
+ * @template T,S
+ */
+goog.array.every = goog.NATIVE_ARRAY_PROTOTYPES &&
+ (goog.array.ASSUME_NATIVE_FUNCTIONS ||
+ goog.array.ARRAY_PROTOTYPE_.every) ?
+ function(arr, f, opt_obj) {
+ goog.asserts.assert(arr.length != null);
+
+ return goog.array.ARRAY_PROTOTYPE_.every.call(arr, f, opt_obj);
+ } :
+ function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2 && !f.call(opt_obj, arr2[i], i, arr)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+
+/**
+ * Counts the array elements that fulfill the predicate, i.e. for which the
+ * callback function returns true. Skips holes in the array.
+ *
+ * @param {!(Array<T>|goog.array.ArrayLike)} arr Array or array like object
+ * over which to iterate.
+ * @param {function(this: S, T, number, ?): boolean} f The function to call for
+ * every element. Takes 3 arguments (the element, the index and the array).
+ * @param {S=} opt_obj The object to be used as the value of 'this' within f.
+ * @return {number} The number of the matching elements.
+ * @template T,S
+ */
+goog.array.count = function(arr, f, opt_obj) {
+ var count = 0;
+ goog.array.forEach(arr, function(element, index, arr) {
+ if (f.call(opt_obj, element, index, arr)) {
+ ++count;
+ }
+ }, opt_obj);
+ return count;
+};
+
+
+/**
+ * Search an array for the first element that satisfies a given condition and
+ * return that element.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {T|null} The first array element that passes the test, or null if no
+ * element is found.
+ * @template T,S
+ */
+goog.array.find = function(arr, f, opt_obj) {
+ var i = goog.array.findIndex(arr, f, opt_obj);
+ return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];
+};
+
+
+/**
+ * Search an array for the first element that satisfies a given condition and
+ * return its index.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call for
+ * every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {number} The index of the first array element that passes the test,
+ * or -1 if no element is found.
+ * @template T,S
+ */
+goog.array.findIndex = function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = 0; i < l; i++) {
+ if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+
+/**
+ * Search an array (in reverse order) for the last element that satisfies a
+ * given condition and return that element.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {T|null} The last array element that passes the test, or null if no
+ * element is found.
+ * @template T,S
+ */
+goog.array.findRight = function(arr, f, opt_obj) {
+ var i = goog.array.findIndexRight(arr, f, opt_obj);
+ return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];
+};
+
+
+/**
+ * Search an array (in reverse order) for the last element that satisfies a
+ * given condition and return its index.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {number} The index of the last array element that passes the test,
+ * or -1 if no element is found.
+ * @template T,S
+ */
+goog.array.findIndexRight = function(arr, f, opt_obj) {
+ var l = arr.length; // must be fixed during loop... see docs
+ var arr2 = goog.isString(arr) ? arr.split('') : arr;
+ for (var i = l - 1; i >= 0; i--) {
+ if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) {
+ return i;
+ }
+ }
+ return -1;
+};
+
+
+/**
+ * Whether the array contains the given object.
+ * @param {goog.array.ArrayLike} arr The array to test for the presence of the
+ * element.
+ * @param {*} obj The object for which to test.
+ * @return {boolean} true if obj is present.
+ */
+goog.array.contains = function(arr, obj) {
+ return goog.array.indexOf(arr, obj) >= 0;
+};
+
+
+/**
+ * Whether the array is empty.
+ * @param {goog.array.ArrayLike} arr The array to test.
+ * @return {boolean} true if empty.
+ */
+goog.array.isEmpty = function(arr) {
+ return arr.length == 0;
+};
+
+
+/**
+ * Clears the array.
+ * @param {goog.array.ArrayLike} arr Array or array like object to clear.
+ */
+goog.array.clear = function(arr) {
+ // For non real arrays we don't have the magic length so we delete the
+ // indices.
+ if (!goog.isArray(arr)) {
+ for (var i = arr.length - 1; i >= 0; i--) {
+ delete arr[i];
+ }
+ }
+ arr.length = 0;
+};
+
+
+/**
+ * Pushes an item into an array, if it's not already in the array.
+ * @param {Array<T>} arr Array into which to insert the item.
+ * @param {T} obj Value to add.
+ * @template T
+ */
+goog.array.insert = function(arr, obj) {
+ if (!goog.array.contains(arr, obj)) {
+ arr.push(obj);
+ }
+};
+
+
+/**
+ * Inserts an object at the given index of the array.
+ * @param {goog.array.ArrayLike} arr The array to modify.
+ * @param {*} obj The object to insert.
+ * @param {number=} opt_i The index at which to insert the object. If omitted,
+ * treated as 0. A negative index is counted from the end of the array.
+ */
+goog.array.insertAt = function(arr, obj, opt_i) {
+ goog.array.splice(arr, opt_i, 0, obj);
+};
+
+
+/**
+ * Inserts at the given index of the array, all elements of another array.
+ * @param {goog.array.ArrayLike} arr The array to modify.
+ * @param {goog.array.ArrayLike} elementsToAdd The array of elements to add.
+ * @param {number=} opt_i The index at which to insert the object. If omitted,
+ * treated as 0. A negative index is counted from the end of the array.
+ */
+goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) {
+ goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd);
+};
+
+
+/**
+ * Inserts an object into an array before a specified object.
+ * @param {Array<T>} arr The array to modify.
+ * @param {T} obj The object to insert.
+ * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2
+ * is omitted or not found, obj is inserted at the end of the array.
+ * @template T
+ */
+goog.array.insertBefore = function(arr, obj, opt_obj2) {
+ var i;
+ if (arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) {
+ arr.push(obj);
+ } else {
+ goog.array.insertAt(arr, obj, i);
+ }
+};
+
+
+/**
+ * Removes the first occurrence of a particular value from an array.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array from which to remove
+ * value.
+ * @param {T} obj Object to remove.
+ * @return {boolean} True if an element was removed.
+ * @template T
+ */
+goog.array.remove = function(arr, obj) {
+ var i = goog.array.indexOf(arr, obj);
+ var rv;
+ if ((rv = i >= 0)) {
+ goog.array.removeAt(arr, i);
+ }
+ return rv;
+};
+
+
+/**
+ * Removes from an array the element at index i
+ * @param {goog.array.ArrayLike} arr Array or array like object from which to
+ * remove value.
+ * @param {number} i The index to remove.
+ * @return {boolean} True if an element was removed.
+ */
+goog.array.removeAt = function(arr, i) {
+ goog.asserts.assert(arr.length != null);
+
+ // use generic form of splice
+ // splice returns the removed items and if successful the length of that
+ // will be 1
+ return goog.array.ARRAY_PROTOTYPE_.splice.call(arr, i, 1).length == 1;
+};
+
+
+/**
+ * Removes the first value that satisfies the given condition.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {boolean} True if an element was removed.
+ * @template T,S
+ */
+goog.array.removeIf = function(arr, f, opt_obj) {
+ var i = goog.array.findIndex(arr, f, opt_obj);
+ if (i >= 0) {
+ goog.array.removeAt(arr, i);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes all values that satisfy the given condition.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array
+ * like object over which to iterate.
+ * @param {?function(this:S, T, number, ?) : boolean} f The function to call
+ * for every element. This function
+ * takes 3 arguments (the element, the index and the array) and should
+ * return a boolean.
+ * @param {S=} opt_obj An optional "this" context for the function.
+ * @return {number} The number of items removed
+ * @template T,S
+ */
+goog.array.removeAllIf = function(arr, f, opt_obj) {
+ var removedCount = 0;
+ goog.array.forEachRight(arr, function(val, index) {
+ if (f.call(opt_obj, val, index, arr)) {
+ if (goog.array.removeAt(arr, index)) {
+ removedCount++;
+ }
+ }
+ });
+ return removedCount;
+};
+
+
+/**
+ * Returns a new array that is the result of joining the arguments. If arrays
+ * are passed then their items are added, however, if non-arrays are passed they
+ * will be added to the return array as is.
+ *
+ * Note that ArrayLike objects will be added as is, rather than having their
+ * items added.
+ *
+ * goog.array.concat([1, 2], [3, 4]) -> [1, 2, 3, 4]
+ * goog.array.concat(0, [1, 2]) -> [0, 1, 2]
+ * goog.array.concat([1, 2], null) -> [1, 2, null]
+ *
+ * There is bug in all current versions of IE (6, 7 and 8) where arrays created
+ * in an iframe become corrupted soon (not immediately) after the iframe is
+ * destroyed. This is common if loading data via goog.net.IframeIo, for example.
+ * This corruption only affects the concat method which will start throwing
+ * Catastrophic Errors (#-2147418113).
+ *
+ * See http://endoflow.com/scratch/corrupted-arrays.html for a test case.
+ *
+ * Internally goog.array should use this, so that all methods will continue to
+ * work on these broken array objects.
+ *
+ * @param {...*} var_args Items to concatenate. Arrays will have each item
+ * added, while primitives and objects will be added as is.
+ * @return {!Array<?>} The new resultant array.
+ */
+goog.array.concat = function(var_args) {
+ return goog.array.ARRAY_PROTOTYPE_.concat.apply(
+ goog.array.ARRAY_PROTOTYPE_, arguments);
+};
+
+
+/**
+ * Returns a new array that contains the contents of all the arrays passed.
+ * @param {...!Array<T>} var_args
+ * @return {!Array<T>}
+ * @template T
+ */
+goog.array.join = function(var_args) {
+ return goog.array.ARRAY_PROTOTYPE_.concat.apply(
+ goog.array.ARRAY_PROTOTYPE_, arguments);
+};
+
+
+/**
+ * Converts an object to an array.
+ * @param {Array<T>|goog.array.ArrayLike} object The object to convert to an
+ * array.
+ * @return {!Array<T>} The object converted into an array. If object has a
+ * length property, every property indexed with a non-negative number
+ * less than length will be included in the result. If object does not
+ * have a length property, an empty array will be returned.
+ * @template T
+ */
+goog.array.toArray = function(object) {
+ var length = object.length;
+
+ // If length is not a number the following it false. This case is kept for
+ // backwards compatibility since there are callers that pass objects that are
+ // not array like.
+ if (length > 0) {
+ var rv = new Array(length);
+ for (var i = 0; i < length; i++) {
+ rv[i] = object[i];
+ }
+ return rv;
+ }
+ return [];
+};
+
+
+/**
+ * Does a shallow copy of an array.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array-like object to
+ * clone.
+ * @return {!Array<T>} Clone of the input array.
+ * @template T
+ */
+goog.array.clone = goog.array.toArray;
+
+
+/**
+ * Extends an array with another array, element, or "array like" object.
+ * This function operates 'in-place', it does not create a new Array.
+ *
+ * Example:
+ * var a = [];
+ * goog.array.extend(a, [0, 1]);
+ * a; // [0, 1]
+ * goog.array.extend(a, 2);
+ * a; // [0, 1, 2]
+ *
+ * @param {Array<VALUE>} arr1 The array to modify.
+ * @param {...(Array<VALUE>|VALUE)} var_args The elements or arrays of elements
+ * to add to arr1.
+ * @template VALUE
+ */
+goog.array.extend = function(arr1, var_args) {
+ for (var i = 1; i < arguments.length; i++) {
+ var arr2 = arguments[i];
+ if (goog.isArrayLike(arr2)) {
+ var len1 = arr1.length || 0;
+ var len2 = arr2.length || 0;
+ arr1.length = len1 + len2;
+ for (var j = 0; j < len2; j++) {
+ arr1[len1 + j] = arr2[j];
+ }
+ } else {
+ arr1.push(arr2);
+ }
+ }
+};
+
+
+/**
+ * Adds or removes elements from an array. This is a generic version of Array
+ * splice. This means that it might work on other objects similar to arrays,
+ * such as the arguments object.
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr The array to modify.
+ * @param {number|undefined} index The index at which to start changing the
+ * array. If not defined, treated as 0.
+ * @param {number} howMany How many elements to remove (0 means no removal. A
+ * value below 0 is treated as zero and so is any other non number. Numbers
+ * are floored).
+ * @param {...T} var_args Optional, additional elements to insert into the
+ * array.
+ * @return {!Array<T>} the removed elements.
+ * @template T
+ */
+goog.array.splice = function(arr, index, howMany, var_args) {
+ goog.asserts.assert(arr.length != null);
+
+ return goog.array.ARRAY_PROTOTYPE_.splice.apply(
+ arr, goog.array.slice(arguments, 1));
+};
+
+
+/**
+ * Returns a new array from a segment of an array. This is a generic version of
+ * Array slice. This means that it might work on other objects similar to
+ * arrays, such as the arguments object.
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr The array from
+ * which to copy a segment.
+ * @param {number} start The index of the first element to copy.
+ * @param {number=} opt_end The index after the last element to copy.
+ * @return {!Array<T>} A new array containing the specified segment of the
+ * original array.
+ * @template T
+ */
+goog.array.slice = function(arr, start, opt_end) {
+ goog.asserts.assert(arr.length != null);
+
+ // passing 1 arg to slice is not the same as passing 2 where the second is
+ // null or undefined (in that case the second argument is treated as 0).
+ // we could use slice on the arguments object and then use apply instead of
+ // testing the length
+ if (arguments.length <= 2) {
+ return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start);
+ } else {
+ return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start, opt_end);
+ }
+};
+
+
+/**
+ * Removes all duplicates from an array (retaining only the first
+ * occurrence of each array element). This function modifies the
+ * array in place and doesn't change the order of the non-duplicate items.
+ *
+ * For objects, duplicates are identified as having the same unique ID as
+ * defined by {@link goog.getUid}.
+ *
+ * Alternatively you can specify a custom hash function that returns a unique
+ * value for each item in the array it should consider unique.
+ *
+ * Runtime: N,
+ * Worstcase space: 2N (no dupes)
+ *
+ * @param {Array<T>|goog.array.ArrayLike} arr The array from which to remove
+ * duplicates.
+ * @param {Array=} opt_rv An optional array in which to return the results,
+ * instead of performing the removal inplace. If specified, the original
+ * array will remain unchanged.
+ * @param {function(T):string=} opt_hashFn An optional function to use to
+ * apply to every item in the array. This function should return a unique
+ * value for each item in the array it should consider unique.
+ * @template T
+ */
+goog.array.removeDuplicates = function(arr, opt_rv, opt_hashFn) {
+ var returnArray = opt_rv || arr;
+ var defaultHashFn = function(item) {
+ // Prefix each type with a single character representing the type to
+ // prevent conflicting keys (e.g. true and 'true').
+ return goog.isObject(current) ? 'o' + goog.getUid(current) :
+ (typeof current).charAt(0) + current;
+ };
+ var hashFn = opt_hashFn || defaultHashFn;
+
+ var seen = {}, cursorInsert = 0, cursorRead = 0;
+ while (cursorRead < arr.length) {
+ var current = arr[cursorRead++];
+ var key = hashFn(current);
+ if (!Object.prototype.hasOwnProperty.call(seen, key)) {
+ seen[key] = true;
+ returnArray[cursorInsert++] = current;
+ }
+ }
+ returnArray.length = cursorInsert;
+};
+
+
+/**
+ * Searches the specified array for the specified target using the binary
+ * search algorithm. If no opt_compareFn is specified, elements are compared
+ * using <code>goog.array.defaultCompare</code>, which compares the elements
+ * using the built in < and > operators. This will produce the expected
+ * behavior for homogeneous arrays of String(s) and Number(s). The array
+ * specified <b>must</b> be sorted in ascending order (as defined by the
+ * comparison function). If the array is not sorted, results are undefined.
+ * If the array contains multiple instances of the specified target value, any
+ * of these instances may be found.
+ *
+ * Runtime: O(log n)
+ *
+ * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to be searched.
+ * @param {TARGET} target The sought value.
+ * @param {function(TARGET, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {number} Lowest index of the target value if found, otherwise
+ * (-(insertion point) - 1). The insertion point is where the value should
+ * be inserted into arr to preserve the sorted property. Return value >= 0
+ * iff target is found.
+ * @template TARGET, VALUE
+ */
+goog.array.binarySearch = function(arr, target, opt_compareFn) {
+ return goog.array.binarySearch_(arr,
+ opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */,
+ target);
+};
+
+
+/**
+ * Selects an index in the specified array using the binary search algorithm.
+ * The evaluator receives an element and determines whether the desired index
+ * is before, at, or after it. The evaluator must be consistent (formally,
+ * goog.array.map(goog.array.map(arr, evaluator, opt_obj), goog.math.sign)
+ * must be monotonically non-increasing).
+ *
+ * Runtime: O(log n)
+ *
+ * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to be searched.
+ * @param {function(this:THIS, VALUE, number, ?): number} evaluator
+ * Evaluator function that receives 3 arguments (the element, the index and
+ * the array). Should return a negative number, zero, or a positive number
+ * depending on whether the desired index is before, at, or after the
+ * element passed to it.
+ * @param {THIS=} opt_obj The object to be used as the value of 'this'
+ * within evaluator.
+ * @return {number} Index of the leftmost element matched by the evaluator, if
+ * such exists; otherwise (-(insertion point) - 1). The insertion point is
+ * the index of the first element for which the evaluator returns negative,
+ * or arr.length if no such element exists. The return value is non-negative
+ * iff a match is found.
+ * @template THIS, VALUE
+ */
+goog.array.binarySelect = function(arr, evaluator, opt_obj) {
+ return goog.array.binarySearch_(arr, evaluator, true /* isEvaluator */,
+ undefined /* opt_target */, opt_obj);
+};
+
+
+/**
+ * Implementation of a binary search algorithm which knows how to use both
+ * comparison functions and evaluators. If an evaluator is provided, will call
+ * the evaluator with the given optional data object, conforming to the
+ * interface defined in binarySelect. Otherwise, if a comparison function is
+ * provided, will call the comparison function against the given data object.
+ *
+ * This implementation purposefully does not use goog.bind or goog.partial for
+ * performance reasons.
+ *
+ * Runtime: O(log n)
+ *
+ * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to be searched.
+ * @param {function(TARGET, VALUE): number|
+ * function(this:THIS, VALUE, number, ?): number} compareFn Either an
+ * evaluator or a comparison function, as defined by binarySearch
+ * and binarySelect above.
+ * @param {boolean} isEvaluator Whether the function is an evaluator or a
+ * comparison function.
+ * @param {TARGET=} opt_target If the function is a comparison function, then
+ * this is the target to binary search for.
+ * @param {THIS=} opt_selfObj If the function is an evaluator, this is an
+ * optional this object for the evaluator.
+ * @return {number} Lowest index of the target value if found, otherwise
+ * (-(insertion point) - 1). The insertion point is where the value should
+ * be inserted into arr to preserve the sorted property. Return value >= 0
+ * iff target is found.
+ * @template THIS, VALUE, TARGET
+ * @private
+ */
+goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target,
+ opt_selfObj) {
+ var left = 0; // inclusive
+ var right = arr.length; // exclusive
+ var found;
+ while (left < right) {
+ var middle = (left + right) >> 1;
+ var compareResult;
+ if (isEvaluator) {
+ compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr);
+ } else {
+ compareResult = compareFn(opt_target, arr[middle]);
+ }
+ if (compareResult > 0) {
+ left = middle + 1;
+ } else {
+ right = middle;
+ // We are looking for the lowest index so we can't return immediately.
+ found = !compareResult;
+ }
+ }
+ // left is the index if found, or the insertion point otherwise.
+ // ~left is a shorthand for -left - 1.
+ return found ? left : ~left;
+};
+
+
+/**
+ * Sorts the specified array into ascending order. If no opt_compareFn is
+ * specified, elements are compared using
+ * <code>goog.array.defaultCompare</code>, which compares the elements using
+ * the built in < and > operators. This will produce the expected behavior
+ * for homogeneous arrays of String(s) and Number(s), unlike the native sort,
+ * but will give unpredictable results for heterogenous lists of strings and
+ * numbers with different numbers of digits.
+ *
+ * This sort is not guaranteed to be stable.
+ *
+ * Runtime: Same as <code>Array.prototype.sort</code>
+ *
+ * @param {Array<T>} arr The array to be sorted.
+ * @param {?function(T,T):number=} opt_compareFn Optional comparison
+ * function by which the
+ * array is to be ordered. Should take 2 arguments to compare, and return a
+ * negative number, zero, or a positive number depending on whether the
+ * first argument is less than, equal to, or greater than the second.
+ * @template T
+ */
+goog.array.sort = function(arr, opt_compareFn) {
+ // TODO(arv): Update type annotation since null is not accepted.
+ arr.sort(opt_compareFn || goog.array.defaultCompare);
+};
+
+
+/**
+ * Sorts the specified array into ascending order in a stable way. If no
+ * opt_compareFn is specified, elements are compared using
+ * <code>goog.array.defaultCompare</code>, which compares the elements using
+ * the built in < and > operators. This will produce the expected behavior
+ * for homogeneous arrays of String(s) and Number(s).
+ *
+ * Runtime: Same as <code>Array.prototype.sort</code>, plus an additional
+ * O(n) overhead of copying the array twice.
+ *
+ * @param {Array<T>} arr The array to be sorted.
+ * @param {?function(T, T): number=} opt_compareFn Optional comparison function
+ * by which the array is to be ordered. Should take 2 arguments to compare,
+ * and return a negative number, zero, or a positive number depending on
+ * whether the first argument is less than, equal to, or greater than the
+ * second.
+ * @template T
+ */
+goog.array.stableSort = function(arr, opt_compareFn) {
+ for (var i = 0; i < arr.length; i++) {
+ arr[i] = {index: i, value: arr[i]};
+ }
+ var valueCompareFn = opt_compareFn || goog.array.defaultCompare;
+ function stableCompareFn(obj1, obj2) {
+ return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index;
+ };
+ goog.array.sort(arr, stableCompareFn);
+ for (var i = 0; i < arr.length; i++) {
+ arr[i] = arr[i].value;
+ }
+};
+
+
+/**
+ * Sort the specified array into ascending order based on item keys
+ * returned by the specified key function.
+ * If no opt_compareFn is specified, the keys are compared in ascending order
+ * using <code>goog.array.defaultCompare</code>.
+ *
+ * Runtime: O(S(f(n)), where S is runtime of <code>goog.array.sort</code>
+ * and f(n) is runtime of the key function.
+ *
+ * @param {Array<T>} arr The array to be sorted.
+ * @param {function(T): K} keyFn Function taking array element and returning
+ * a key used for sorting this element.
+ * @param {?function(K, K): number=} opt_compareFn Optional comparison function
+ * by which the keys are to be ordered. Should take 2 arguments to compare,
+ * and return a negative number, zero, or a positive number depending on
+ * whether the first argument is less than, equal to, or greater than the
+ * second.
+ * @template T
+ * @template K
+ */
+goog.array.sortByKey = function(arr, keyFn, opt_compareFn) {
+ var keyCompareFn = opt_compareFn || goog.array.defaultCompare;
+ goog.array.sort(arr, function(a, b) {
+ return keyCompareFn(keyFn(a), keyFn(b));
+ });
+};
+
+
+/**
+ * Sorts an array of objects by the specified object key and compare
+ * function. If no compare function is provided, the key values are
+ * compared in ascending order using <code>goog.array.defaultCompare</code>.
+ * This won't work for keys that get renamed by the compiler. So use
+ * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}.
+ * @param {Array<Object>} arr An array of objects to sort.
+ * @param {string} key The object key to sort by.
+ * @param {Function=} opt_compareFn The function to use to compare key
+ * values.
+ */
+goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) {
+ goog.array.sortByKey(arr,
+ function(obj) { return obj[key]; },
+ opt_compareFn);
+};
+
+
+/**
+ * Tells if the array is sorted.
+ * @param {!Array<T>} arr The array.
+ * @param {?function(T,T):number=} opt_compareFn Function to compare the
+ * array elements.
+ * Should take 2 arguments to compare, and return a negative number, zero,
+ * or a positive number depending on whether the first argument is less
+ * than, equal to, or greater than the second.
+ * @param {boolean=} opt_strict If true no equal elements are allowed.
+ * @return {boolean} Whether the array is sorted.
+ * @template T
+ */
+goog.array.isSorted = function(arr, opt_compareFn, opt_strict) {
+ var compare = opt_compareFn || goog.array.defaultCompare;
+ for (var i = 1; i < arr.length; i++) {
+ var compareResult = compare(arr[i - 1], arr[i]);
+ if (compareResult > 0 || compareResult == 0 && opt_strict) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Compares two arrays for equality. Two arrays are considered equal if they
+ * have the same length and their corresponding elements are equal according to
+ * the comparison function.
+ *
+ * @param {goog.array.ArrayLike} arr1 The first array to compare.
+ * @param {goog.array.ArrayLike} arr2 The second array to compare.
+ * @param {Function=} opt_equalsFn Optional comparison function.
+ * Should take 2 arguments to compare, and return true if the arguments
+ * are equal. Defaults to {@link goog.array.defaultCompareEquality} which
+ * compares the elements using the built-in '===' operator.
+ * @return {boolean} Whether the two arrays are equal.
+ */
+goog.array.equals = function(arr1, arr2, opt_equalsFn) {
+ if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) ||
+ arr1.length != arr2.length) {
+ return false;
+ }
+ var l = arr1.length;
+ var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
+ for (var i = 0; i < l; i++) {
+ if (!equalsFn(arr1[i], arr2[i])) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * 3-way array compare function.
+ * @param {!Array<VALUE>|!goog.array.ArrayLike} arr1 The first array to
+ * compare.
+ * @param {!Array<VALUE>|!goog.array.ArrayLike} arr2 The second array to
+ * compare.
+ * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is to be ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {number} Negative number, zero, or a positive number depending on
+ * whether the first argument is less than, equal to, or greater than the
+ * second.
+ * @template VALUE
+ */
+goog.array.compare3 = function(arr1, arr2, opt_compareFn) {
+ var compare = opt_compareFn || goog.array.defaultCompare;
+ var l = Math.min(arr1.length, arr2.length);
+ for (var i = 0; i < l; i++) {
+ var result = compare(arr1[i], arr2[i]);
+ if (result != 0) {
+ return result;
+ }
+ }
+ return goog.array.defaultCompare(arr1.length, arr2.length);
+};
+
+
+/**
+ * Compares its two arguments for order, using the built in < and >
+ * operators.
+ * @param {VALUE} a The first object to be compared.
+ * @param {VALUE} b The second object to be compared.
+ * @return {number} A negative number, zero, or a positive number as the first
+ * argument is less than, equal to, or greater than the second,
+ * respectively.
+ * @template VALUE
+ */
+goog.array.defaultCompare = function(a, b) {
+ return a > b ? 1 : a < b ? -1 : 0;
+};
+
+
+/**
+ * Compares its two arguments for inverse order, using the built in < and >
+ * operators.
+ * @param {VALUE} a The first object to be compared.
+ * @param {VALUE} b The second object to be compared.
+ * @return {number} A negative number, zero, or a positive number as the first
+ * argument is greater than, equal to, or less than the second,
+ * respectively.
+ * @template VALUE
+ */
+goog.array.inverseDefaultCompare = function(a, b) {
+ return -goog.array.defaultCompare(a, b);
+};
+
+
+/**
+ * Compares its two arguments for equality, using the built in === operator.
+ * @param {*} a The first object to compare.
+ * @param {*} b The second object to compare.
+ * @return {boolean} True if the two arguments are equal, false otherwise.
+ */
+goog.array.defaultCompareEquality = function(a, b) {
+ return a === b;
+};
+
+
+/**
+ * Inserts a value into a sorted array. The array is not modified if the
+ * value is already present.
+ * @param {Array<VALUE>|goog.array.ArrayLike} array The array to modify.
+ * @param {VALUE} value The object to insert.
+ * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {boolean} True if an element was inserted.
+ * @template VALUE
+ */
+goog.array.binaryInsert = function(array, value, opt_compareFn) {
+ var index = goog.array.binarySearch(array, value, opt_compareFn);
+ if (index < 0) {
+ goog.array.insertAt(array, value, -(index + 1));
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a value from a sorted array.
+ * @param {!Array<VALUE>|!goog.array.ArrayLike} array The array to modify.
+ * @param {VALUE} value The object to remove.
+ * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison
+ * function by which the array is ordered. Should take 2 arguments to
+ * compare, and return a negative number, zero, or a positive number
+ * depending on whether the first argument is less than, equal to, or
+ * greater than the second.
+ * @return {boolean} True if an element was removed.
+ * @template VALUE
+ */
+goog.array.binaryRemove = function(array, value, opt_compareFn) {
+ var index = goog.array.binarySearch(array, value, opt_compareFn);
+ return (index >= 0) ? goog.array.removeAt(array, index) : false;
+};
+
+
+/**
+ * Splits an array into disjoint buckets according to a splitting function.
+ * @param {Array<T>} array The array.
+ * @param {function(this:S, T,number,Array<T>):?} sorter Function to call for
+ * every element. This takes 3 arguments (the element, the index and the
+ * array) and must return a valid object key (a string, number, etc), or
+ * undefined, if that object should not be placed in a bucket.
+ * @param {S=} opt_obj The object to be used as the value of 'this' within
+ * sorter.
+ * @return {!Object} An object, with keys being all of the unique return values
+ * of sorter, and values being arrays containing the items for
+ * which the splitter returned that key.
+ * @template T,S
+ */
+goog.array.bucket = function(array, sorter, opt_obj) {
+ var buckets = {};
+
+ for (var i = 0; i < array.length; i++) {
+ var value = array[i];
+ var key = sorter.call(opt_obj, value, i, array);
+ if (goog.isDef(key)) {
+ // Push the value to the right bucket, creating it if necessary.
+ var bucket = buckets[key] || (buckets[key] = []);
+ bucket.push(value);
+ }
+ }
+
+ return buckets;
+};
+
+
+/**
+ * Creates a new object built from the provided array and the key-generation
+ * function.
+ * @param {Array<T>|goog.array.ArrayLike} arr Array or array like object over
+ * which to iterate whose elements will be the values in the new object.
+ * @param {?function(this:S, T, number, ?) : string} keyFunc The function to
+ * call for every element. This function takes 3 arguments (the element, the
+ * index and the array) and should return a string that will be used as the
+ * key for the element in the new object. If the function returns the same
+ * key for more than one element, the value for that key is
+ * implementation-defined.
+ * @param {S=} opt_obj The object to be used as the value of 'this'
+ * within keyFunc.
+ * @return {!Object<T>} The new object.
+ * @template T,S
+ */
+goog.array.toObject = function(arr, keyFunc, opt_obj) {
+ var ret = {};
+ goog.array.forEach(arr, function(element, index) {
+ ret[keyFunc.call(opt_obj, element, index, arr)] = element;
+ });
+ return ret;
+};
+
+
+/**
+ * Creates a range of numbers in an arithmetic progression.
+ *
+ * Range takes 1, 2, or 3 arguments:
+ * <pre>
+ * range(5) is the same as range(0, 5, 1) and produces [0, 1, 2, 3, 4]
+ * range(2, 5) is the same as range(2, 5, 1) and produces [2, 3, 4]
+ * range(-2, -5, -1) produces [-2, -3, -4]
+ * range(-2, -5, 1) produces [], since stepping by 1 wouldn't ever reach -5.
+ * </pre>
+ *
+ * @param {number} startOrEnd The starting value of the range if an end argument
+ * is provided. Otherwise, the start value is 0, and this is the end value.
+ * @param {number=} opt_end The optional end value of the range.
+ * @param {number=} opt_step The step size between range values. Defaults to 1
+ * if opt_step is undefined or 0.
+ * @return {!Array<number>} An array of numbers for the requested range. May be
+ * an empty array if adding the step would not converge toward the end
+ * value.
+ */
+goog.array.range = function(startOrEnd, opt_end, opt_step) {
+ var array = [];
+ var start = 0;
+ var end = startOrEnd;
+ var step = opt_step || 1;
+ if (opt_end !== undefined) {
+ start = startOrEnd;
+ end = opt_end;
+ }
+
+ if (step * (end - start) < 0) {
+ // Sign mismatch: start + step will never reach the end value.
+ return [];
+ }
+
+ if (step > 0) {
+ for (var i = start; i < end; i += step) {
+ array.push(i);
+ }
+ } else {
+ for (var i = start; i > end; i += step) {
+ array.push(i);
+ }
+ }
+ return array;
+};
+
+
+/**
+ * Returns an array consisting of the given value repeated N times.
+ *
+ * @param {VALUE} value The value to repeat.
+ * @param {number} n The repeat count.
+ * @return {!Array<VALUE>} An array with the repeated value.
+ * @template VALUE
+ */
+goog.array.repeat = function(value, n) {
+ var array = [];
+ for (var i = 0; i < n; i++) {
+ array[i] = value;
+ }
+ return array;
+};
+
+
+/**
+ * Returns an array consisting of every argument with all arrays
+ * expanded in-place recursively.
+ *
+ * @param {...*} var_args The values to flatten.
+ * @return {!Array<?>} An array containing the flattened values.
+ */
+goog.array.flatten = function(var_args) {
+ var CHUNK_SIZE = 8192;
+
+ var result = [];
+ for (var i = 0; i < arguments.length; i++) {
+ var element = arguments[i];
+ if (goog.isArray(element)) {
+ for (var c = 0; c < element.length; c += CHUNK_SIZE) {
+ var chunk = goog.array.slice(element, c, c + CHUNK_SIZE);
+ var recurseResult = goog.array.flatten.apply(null, chunk);
+ for (var r = 0; r < recurseResult.length; r++) {
+ result.push(recurseResult[r]);
+ }
+ }
+ } else {
+ result.push(element);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Rotates an array in-place. After calling this method, the element at
+ * index i will be the element previously at index (i - n) %
+ * array.length, for all values of i between 0 and array.length - 1,
+ * inclusive.
+ *
+ * For example, suppose list comprises [t, a, n, k, s]. After invoking
+ * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k].
+ *
+ * @param {!Array<T>} array The array to rotate.
+ * @param {number} n The amount to rotate.
+ * @return {!Array<T>} The array.
+ * @template T
+ */
+goog.array.rotate = function(array, n) {
+ goog.asserts.assert(array.length != null);
+
+ if (array.length) {
+ n %= array.length;
+ if (n > 0) {
+ goog.array.ARRAY_PROTOTYPE_.unshift.apply(array, array.splice(-n, n));
+ } else if (n < 0) {
+ goog.array.ARRAY_PROTOTYPE_.push.apply(array, array.splice(0, -n));
+ }
+ }
+ return array;
+};
+
+
+/**
+ * Moves one item of an array to a new position keeping the order of the rest
+ * of the items. Example use case: keeping a list of JavaScript objects
+ * synchronized with the corresponding list of DOM elements after one of the
+ * elements has been dragged to a new position.
+ * @param {!(Array|Arguments|{length:number})} arr The array to modify.
+ * @param {number} fromIndex Index of the item to move between 0 and
+ * {@code arr.length - 1}.
+ * @param {number} toIndex Target index between 0 and {@code arr.length - 1}.
+ */
+goog.array.moveItem = function(arr, fromIndex, toIndex) {
+ goog.asserts.assert(fromIndex >= 0 && fromIndex < arr.length);
+ goog.asserts.assert(toIndex >= 0 && toIndex < arr.length);
+ // Remove 1 item at fromIndex.
+ var removedItems = goog.array.ARRAY_PROTOTYPE_.splice.call(arr, fromIndex, 1);
+ // Insert the removed item at toIndex.
+ goog.array.ARRAY_PROTOTYPE_.splice.call(arr, toIndex, 0, removedItems[0]);
+ // We don't use goog.array.insertAt and goog.array.removeAt, because they're
+ // significantly slower than splice.
+};
+
+
+/**
+ * Creates a new array for which the element at position i is an array of the
+ * ith element of the provided arrays. The returned array will only be as long
+ * as the shortest array provided; additional values are ignored. For example,
+ * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]].
+ *
+ * This is similar to the zip() function in Python. See {@link
+ * http://docs.python.org/library/functions.html#zip}
+ *
+ * @param {...!goog.array.ArrayLike} var_args Arrays to be combined.
+ * @return {!Array<!Array<?>>} A new array of arrays created from
+ * provided arrays.
+ */
+goog.array.zip = function(var_args) {
+ if (!arguments.length) {
+ return [];
+ }
+ var result = [];
+ for (var i = 0; true; i++) {
+ var value = [];
+ for (var j = 0; j < arguments.length; j++) {
+ var arr = arguments[j];
+ // If i is larger than the array length, this is the shortest array.
+ if (i >= arr.length) {
+ return result;
+ }
+ value.push(arr[i]);
+ }
+ result.push(value);
+ }
+};
+
+
+/**
+ * Shuffles the values in the specified array using the Fisher-Yates in-place
+ * shuffle (also known as the Knuth Shuffle). By default, calls Math.random()
+ * and so resets the state of that random number generator. Similarly, may reset
+ * the state of the any other specified random number generator.
+ *
+ * Runtime: O(n)
+ *
+ * @param {!Array<?>} arr The array to be shuffled.
+ * @param {function():number=} opt_randFn Optional random function to use for
+ * shuffling.
+ * Takes no arguments, and returns a random number on the interval [0, 1).
+ * Defaults to Math.random() using JavaScript's built-in Math library.
+ */
+goog.array.shuffle = function(arr, opt_randFn) {
+ var randFn = opt_randFn || Math.random;
+
+ for (var i = arr.length - 1; i > 0; i--) {
+ // Choose a random array index in [0, i] (inclusive with i).
+ var j = Math.floor(randFn() * (i + 1));
+
+ var tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+};
+
+
+/**
+ * Returns a new array of elements from arr, based on the indexes of elements
+ * provided by index_arr. For example, the result of index copying
+ * ['a', 'b', 'c'] with index_arr [1,0,0,2] is ['b', 'a', 'a', 'c'].
+ *
+ * @param {!Array<T>} arr The array to get a indexed copy from.
+ * @param {!Array<number>} index_arr An array of indexes to get from arr.
+ * @return {!Array<T>} A new array of elements from arr in index_arr order.
+ * @template T
+ */
+goog.array.copyByIndex = function(arr, index_arr) {
+ var result = [];
+ goog.array.forEach(index_arr, function(index) {
+ result.push(arr[index]);
+ });
+ return result;
+};
[20/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/range.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/range.js b/externs/GCL/externs/goog/editor/range.js
new file mode 100644
index 0000000..ec1a6a7
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/range.js
@@ -0,0 +1,632 @@
+// 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 Utilties for working with ranges.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.range');
+goog.provide('goog.editor.range.Point');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.RangeEndpoint');
+goog.require('goog.dom.SavedCaretRange');
+goog.require('goog.editor.node');
+goog.require('goog.editor.style');
+goog.require('goog.iter');
+goog.require('goog.userAgent');
+
+
+/**
+ * Given a range and an element, create a narrower range that is limited to the
+ * boundaries of the element. If the range starts (or ends) outside the
+ * element, the narrowed range's start point (or end point) will be the
+ * leftmost (or rightmost) leaf of the element.
+ * @param {goog.dom.AbstractRange} range The range.
+ * @param {Element} el The element to limit the range to.
+ * @return {goog.dom.AbstractRange} A new narrowed range, or null if the
+ * element does not contain any part of the given range.
+ */
+goog.editor.range.narrow = function(range, el) {
+ var startContainer = range.getStartNode();
+ var endContainer = range.getEndNode();
+
+ if (startContainer && endContainer) {
+ var isElement = function(node) {
+ return node == el;
+ };
+ var hasStart = goog.dom.getAncestor(startContainer, isElement, true);
+ var hasEnd = goog.dom.getAncestor(endContainer, isElement, true);
+
+ if (hasStart && hasEnd) {
+ // The range is contained entirely within this element.
+ return range.clone();
+ } else if (hasStart) {
+ // The range starts inside the element, but ends outside it.
+ var leaf = goog.editor.node.getRightMostLeaf(el);
+ return goog.dom.Range.createFromNodes(
+ range.getStartNode(), range.getStartOffset(),
+ leaf, goog.editor.node.getLength(leaf));
+ } else if (hasEnd) {
+ // The range starts outside the element, but ends inside it.
+ return goog.dom.Range.createFromNodes(
+ goog.editor.node.getLeftMostLeaf(el), 0,
+ range.getEndNode(), range.getEndOffset());
+ }
+ }
+
+ // The selection starts and ends outside the element.
+ return null;
+};
+
+
+/**
+ * Given a range, expand the range to include outer tags if the full contents of
+ * those tags are entirely selected. This essentially changes the dom position,
+ * but not the visible position of the range.
+ * Ex. <li>foo</li> if "foo" is selected, instead of returning start and end
+ * nodes as the foo text node, return the li.
+ * @param {goog.dom.AbstractRange} range The range.
+ * @param {Node=} opt_stopNode Optional node to stop expanding past.
+ * @return {!goog.dom.AbstractRange} The expanded range.
+ */
+goog.editor.range.expand = function(range, opt_stopNode) {
+ // Expand the start out to the common container.
+ var expandedRange = goog.editor.range.expandEndPointToContainer_(
+ range, goog.dom.RangeEndpoint.START, opt_stopNode);
+ // Expand the end out to the common container.
+ expandedRange = goog.editor.range.expandEndPointToContainer_(
+ expandedRange, goog.dom.RangeEndpoint.END, opt_stopNode);
+
+ var startNode = expandedRange.getStartNode();
+ var endNode = expandedRange.getEndNode();
+ var startOffset = expandedRange.getStartOffset();
+ var endOffset = expandedRange.getEndOffset();
+
+ // If we have reached a common container, now expand out.
+ if (startNode == endNode) {
+ while (endNode != opt_stopNode &&
+ startOffset == 0 &&
+ endOffset == goog.editor.node.getLength(endNode)) {
+ // Select the parent instead.
+ var parentNode = endNode.parentNode;
+ startOffset = goog.array.indexOf(parentNode.childNodes, endNode);
+ endOffset = startOffset + 1;
+ endNode = parentNode;
+ }
+ startNode = endNode;
+ }
+
+ return goog.dom.Range.createFromNodes(startNode, startOffset,
+ endNode, endOffset);
+};
+
+
+/**
+ * Given a range, expands the start or end points as far out towards the
+ * range's common container (or stopNode, if provided) as possible, while
+ * perserving the same visible position.
+ *
+ * @param {goog.dom.AbstractRange} range The range to expand.
+ * @param {goog.dom.RangeEndpoint} endpoint The endpoint to expand.
+ * @param {Node=} opt_stopNode Optional node to stop expanding past.
+ * @return {!goog.dom.AbstractRange} The expanded range.
+ * @private
+ */
+goog.editor.range.expandEndPointToContainer_ = function(range, endpoint,
+ opt_stopNode) {
+ var expandStart = endpoint == goog.dom.RangeEndpoint.START;
+ var node = expandStart ? range.getStartNode() : range.getEndNode();
+ var offset = expandStart ? range.getStartOffset() : range.getEndOffset();
+ var container = range.getContainerElement();
+
+ // Expand the node out until we reach the container or the stop node.
+ while (node != container && node != opt_stopNode) {
+ // It is only valid to expand the start if we are at the start of a node
+ // (offset 0) or expand the end if we are at the end of a node
+ // (offset length).
+ if (expandStart && offset != 0 ||
+ !expandStart && offset != goog.editor.node.getLength(node)) {
+ break;
+ }
+
+ var parentNode = node.parentNode;
+ var index = goog.array.indexOf(parentNode.childNodes, node);
+ offset = expandStart ? index : index + 1;
+ node = parentNode;
+ }
+
+ return goog.dom.Range.createFromNodes(
+ expandStart ? node : range.getStartNode(),
+ expandStart ? offset : range.getStartOffset(),
+ expandStart ? range.getEndNode() : node,
+ expandStart ? range.getEndOffset() : offset);
+};
+
+
+/**
+ * Cause the window's selection to be the start of this node.
+ * @param {Node} node The node to select the start of.
+ */
+goog.editor.range.selectNodeStart = function(node) {
+ goog.dom.Range.createCaret(goog.editor.node.getLeftMostLeaf(node), 0).
+ select();
+};
+
+
+/**
+ * Position the cursor immediately to the left or right of "node".
+ * In Firefox, the selection parent is outside of "node", so the cursor can
+ * effectively be moved to the end of a link node, without being considered
+ * inside of it.
+ * Note: This does not always work in WebKit. In particular, if you try to
+ * place a cursor to the right of a link, typing still puts you in the link.
+ * Bug: http://bugs.webkit.org/show_bug.cgi?id=17697
+ * @param {Node} node The node to position the cursor relative to.
+ * @param {boolean} toLeft True to place it to the left, false to the right.
+ * @return {!goog.dom.AbstractRange} The newly selected range.
+ */
+goog.editor.range.placeCursorNextTo = function(node, toLeft) {
+ var parent = node.parentNode;
+ var offset = goog.array.indexOf(parent.childNodes, node) +
+ (toLeft ? 0 : 1);
+ var point = goog.editor.range.Point.createDeepestPoint(
+ parent, offset, toLeft, true);
+ var range = goog.dom.Range.createCaret(point.node, point.offset);
+ range.select();
+ return range;
+};
+
+
+/**
+ * Normalizes the node, preserving the selection of the document.
+ *
+ * May also normalize things outside the node, if it is more efficient to do so.
+ *
+ * @param {Node} node The node to normalize.
+ */
+goog.editor.range.selectionPreservingNormalize = function(node) {
+ var doc = goog.dom.getOwnerDocument(node);
+ var selection = goog.dom.Range.createFromWindow(goog.dom.getWindow(doc));
+ var normalizedRange =
+ goog.editor.range.rangePreservingNormalize(node, selection);
+ if (normalizedRange) {
+ normalizedRange.select();
+ }
+};
+
+
+/**
+ * Manually normalizes the node in IE, since native normalize in IE causes
+ * transient problems.
+ * @param {Node} node The node to normalize.
+ * @private
+ */
+goog.editor.range.normalizeNodeIe_ = function(node) {
+ var lastText = null;
+ var child = node.firstChild;
+ while (child) {
+ var next = child.nextSibling;
+ if (child.nodeType == goog.dom.NodeType.TEXT) {
+ if (child.nodeValue == '') {
+ node.removeChild(child);
+ } else if (lastText) {
+ lastText.nodeValue += child.nodeValue;
+ node.removeChild(child);
+ } else {
+ lastText = child;
+ }
+ } else {
+ goog.editor.range.normalizeNodeIe_(child);
+ lastText = null;
+ }
+ child = next;
+ }
+};
+
+
+/**
+ * Normalizes the given node.
+ * @param {Node} node The node to normalize.
+ */
+goog.editor.range.normalizeNode = function(node) {
+ if (goog.userAgent.IE) {
+ goog.editor.range.normalizeNodeIe_(node);
+ } else {
+ node.normalize();
+ }
+};
+
+
+/**
+ * Normalizes the node, preserving a range of the document.
+ *
+ * May also normalize things outside the node, if it is more efficient to do so.
+ *
+ * @param {Node} node The node to normalize.
+ * @param {goog.dom.AbstractRange?} range The range to normalize.
+ * @return {goog.dom.AbstractRange?} The range, adjusted for normalization.
+ */
+goog.editor.range.rangePreservingNormalize = function(node, range) {
+ if (range) {
+ var rangeFactory = goog.editor.range.normalize(range);
+ // WebKit has broken selection affinity, so carets tend to jump out of the
+ // beginning of inline elements. This means that if we're doing the
+ // normalize as the result of a range that will later become the selection,
+ // we might not normalize something in the range after it is read back from
+ // the selection. We can't just normalize the parentNode here because WebKit
+ // can move the selection range out of multiple inline parents.
+ var container = goog.editor.style.getContainer(range.getContainerElement());
+ }
+
+ if (container) {
+ goog.editor.range.normalizeNode(
+ goog.dom.findCommonAncestor(container, node));
+ } else if (node) {
+ goog.editor.range.normalizeNode(node);
+ }
+
+ if (rangeFactory) {
+ return rangeFactory();
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Get the deepest point in the DOM that's equivalent to the endpoint of the
+ * given range.
+ *
+ * @param {goog.dom.AbstractRange} range A range.
+ * @param {boolean} atStart True for the start point, false for the end point.
+ * @return {!goog.editor.range.Point} The end point, expressed as a node
+ * and an offset.
+ */
+goog.editor.range.getDeepEndPoint = function(range, atStart) {
+ return atStart ?
+ goog.editor.range.Point.createDeepestPoint(
+ range.getStartNode(), range.getStartOffset()) :
+ goog.editor.range.Point.createDeepestPoint(
+ range.getEndNode(), range.getEndOffset());
+};
+
+
+/**
+ * Given a range in the current DOM, create a factory for a range that
+ * represents the same selection in a normalized DOM. The factory function
+ * should be invoked after the DOM is normalized.
+ *
+ * All browsers do a bad job preserving ranges across DOM normalization.
+ * The issue is best described in this 5-year-old bug report:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=191864
+ * For most applications, this isn't a problem. The browsers do a good job
+ * handling un-normalized text, so there's usually no reason to normalize.
+ *
+ * The exception to this rule is the rich text editing commands
+ * execCommand and queryCommandValue, which will fail often if there are
+ * un-normalized text nodes.
+ *
+ * The factory function creates new ranges so that we can normalize the DOM
+ * without problems. It must be created before any normalization happens,
+ * and invoked after normalization happens.
+ *
+ * @param {goog.dom.AbstractRange} range The range to normalize. It may
+ * become invalid after body.normalize() is called.
+ * @return {function(): goog.dom.AbstractRange} A factory for a normalized
+ * range. Should be called after body.normalize() is called.
+ */
+goog.editor.range.normalize = function(range) {
+ var isReversed = range.isReversed();
+ var anchorPoint = goog.editor.range.normalizePoint_(
+ goog.editor.range.getDeepEndPoint(range, !isReversed));
+ var anchorParent = anchorPoint.getParentPoint();
+ var anchorPreviousSibling = anchorPoint.node.previousSibling;
+ if (anchorPoint.node.nodeType == goog.dom.NodeType.TEXT) {
+ anchorPoint.node = null;
+ }
+
+ var focusPoint = goog.editor.range.normalizePoint_(
+ goog.editor.range.getDeepEndPoint(range, isReversed));
+ var focusParent = focusPoint.getParentPoint();
+ var focusPreviousSibling = focusPoint.node.previousSibling;
+ if (focusPoint.node.nodeType == goog.dom.NodeType.TEXT) {
+ focusPoint.node = null;
+ }
+
+ return function() {
+ if (!anchorPoint.node && anchorPreviousSibling) {
+ // If anchorPoint.node was previously an empty text node with no siblings,
+ // anchorPreviousSibling may not have a nextSibling since that node will
+ // no longer exist. Do our best and point to the end of the previous
+ // element.
+ anchorPoint.node = anchorPreviousSibling.nextSibling;
+ if (!anchorPoint.node) {
+ anchorPoint = goog.editor.range.Point.getPointAtEndOfNode(
+ anchorPreviousSibling);
+ }
+ }
+
+ if (!focusPoint.node && focusPreviousSibling) {
+ // If focusPoint.node was previously an empty text node with no siblings,
+ // focusPreviousSibling may not have a nextSibling since that node will no
+ // longer exist. Do our best and point to the end of the previous
+ // element.
+ focusPoint.node = focusPreviousSibling.nextSibling;
+ if (!focusPoint.node) {
+ focusPoint = goog.editor.range.Point.getPointAtEndOfNode(
+ focusPreviousSibling);
+ }
+ }
+
+ return goog.dom.Range.createFromNodes(
+ anchorPoint.node || anchorParent.node.firstChild || anchorParent.node,
+ anchorPoint.offset,
+ focusPoint.node || focusParent.node.firstChild || focusParent.node,
+ focusPoint.offset);
+ };
+};
+
+
+/**
+ * Given a point in the current DOM, adjust it to represent the same point in
+ * a normalized DOM.
+ *
+ * See the comments on goog.editor.range.normalize for more context.
+ *
+ * @param {goog.editor.range.Point} point A point in the document.
+ * @return {!goog.editor.range.Point} The same point, for easy chaining.
+ * @private
+ */
+goog.editor.range.normalizePoint_ = function(point) {
+ var previous;
+ if (point.node.nodeType == goog.dom.NodeType.TEXT) {
+ // If the cursor position is in a text node,
+ // look at all the previous text siblings of the text node,
+ // and set the offset relative to the earliest text sibling.
+ for (var current = point.node.previousSibling;
+ current && current.nodeType == goog.dom.NodeType.TEXT;
+ current = current.previousSibling) {
+ point.offset += goog.editor.node.getLength(current);
+ }
+
+ previous = current;
+ } else {
+ previous = point.node.previousSibling;
+ }
+
+ var parent = point.node.parentNode;
+ point.node = previous ? previous.nextSibling : parent.firstChild;
+ return point;
+};
+
+
+/**
+ * Checks if a range is completely inside an editable region.
+ * @param {goog.dom.AbstractRange} range The range to test.
+ * @return {boolean} Whether the range is completely inside an editable region.
+ */
+goog.editor.range.isEditable = function(range) {
+ var rangeContainer = range.getContainerElement();
+
+ // Closure's implementation of getContainerElement() is a little too
+ // smart in IE when exactly one element is contained in the range.
+ // It assumes that there's a user whose intent was actually to select
+ // all that element's children, so it returns the element itself as its
+ // own containing element.
+ // This little sanity check detects this condition so we can account for it.
+ var rangeContainerIsOutsideRange =
+ range.getStartNode() != rangeContainer.parentElement;
+
+ return (rangeContainerIsOutsideRange &&
+ goog.editor.node.isEditableContainer(rangeContainer)) ||
+ goog.editor.node.isEditable(rangeContainer);
+};
+
+
+/**
+ * Returns whether the given range intersects with any instance of the given
+ * tag.
+ * @param {goog.dom.AbstractRange} range The range to check.
+ * @param {goog.dom.TagName} tagName The name of the tag.
+ * @return {boolean} Whether the given range intersects with any instance of
+ * the given tag.
+ */
+goog.editor.range.intersectsTag = function(range, tagName) {
+ if (goog.dom.getAncestorByTagNameAndClass(range.getContainerElement(),
+ tagName)) {
+ return true;
+ }
+
+ return goog.iter.some(range, function(node) {
+ return node.tagName == tagName;
+ });
+};
+
+
+
+/**
+ * One endpoint of a range, represented as a Node and and offset.
+ * @param {Node} node The node containing the point.
+ * @param {number} offset The offset of the point into the node.
+ * @constructor
+ * @final
+ */
+goog.editor.range.Point = function(node, offset) {
+ /**
+ * The node containing the point.
+ * @type {Node}
+ */
+ this.node = node;
+
+ /**
+ * The offset of the point into the node.
+ * @type {number}
+ */
+ this.offset = offset;
+};
+
+
+/**
+ * Gets the point of this point's node in the DOM.
+ * @return {!goog.editor.range.Point} The node's point.
+ */
+goog.editor.range.Point.prototype.getParentPoint = function() {
+ var parent = this.node.parentNode;
+ return new goog.editor.range.Point(
+ parent, goog.array.indexOf(parent.childNodes, this.node));
+};
+
+
+/**
+ * Construct the deepest possible point in the DOM that's equivalent
+ * to the given point, expressed as a node and an offset.
+ * @param {Node} node The node containing the point.
+ * @param {number} offset The offset of the point from the node.
+ * @param {boolean=} opt_trendLeft Notice that a (node, offset) pair may be
+ * equivalent to more than one descendent (node, offset) pair in the DOM.
+ * By default, we trend rightward. If this parameter is true, then we
+ * trend leftward. The tendency to fall rightward by default is for
+ * consistency with other range APIs (like placeCursorNextTo).
+ * @param {boolean=} opt_stopOnChildlessElement If true, and we encounter
+ * a Node which is an Element that cannot have children, we return a Point
+ * based on its parent rather than that Node itself.
+ * @return {!goog.editor.range.Point} A new point.
+ */
+goog.editor.range.Point.createDeepestPoint =
+ function(node, offset, opt_trendLeft, opt_stopOnChildlessElement) {
+ while (node.nodeType == goog.dom.NodeType.ELEMENT) {
+ var child = node.childNodes[offset];
+ if (!child && !node.lastChild) {
+ break;
+ } else if (child) {
+ var prevSibling = child.previousSibling;
+ if (opt_trendLeft && prevSibling) {
+ if (opt_stopOnChildlessElement &&
+ goog.editor.range.Point.isTerminalElement_(prevSibling)) {
+ break;
+ }
+ node = prevSibling;
+ offset = goog.editor.node.getLength(node);
+ } else {
+ if (opt_stopOnChildlessElement &&
+ goog.editor.range.Point.isTerminalElement_(child)) {
+ break;
+ }
+ node = child;
+ offset = 0;
+ }
+ } else {
+ if (opt_stopOnChildlessElement &&
+ goog.editor.range.Point.isTerminalElement_(node.lastChild)) {
+ break;
+ }
+ node = node.lastChild;
+ offset = goog.editor.node.getLength(node);
+ }
+ }
+
+ return new goog.editor.range.Point(node, offset);
+};
+
+
+/**
+ * Return true if the specified node is an Element that is not expected to have
+ * children. The createDeepestPoint() method should not traverse into
+ * such elements.
+ * @param {Node} node .
+ * @return {boolean} True if the node is an Element that does not contain
+ * child nodes (e.g. BR, IMG).
+ * @private
+ */
+goog.editor.range.Point.isTerminalElement_ = function(node) {
+ return (node.nodeType == goog.dom.NodeType.ELEMENT &&
+ !goog.dom.canHaveChildren(node));
+};
+
+
+/**
+ * Construct a point at the very end of the given node.
+ * @param {Node} node The node to create a point for.
+ * @return {!goog.editor.range.Point} A new point.
+ */
+goog.editor.range.Point.getPointAtEndOfNode = function(node) {
+ return new goog.editor.range.Point(node, goog.editor.node.getLength(node));
+};
+
+
+/**
+ * Saves the range by inserting carets into the HTML.
+ *
+ * Unlike the regular saveUsingCarets, this SavedRange normalizes text nodes.
+ * Browsers have other bugs where they don't handle split text nodes in
+ * contentEditable regions right.
+ *
+ * @param {goog.dom.AbstractRange} range The abstract range object.
+ * @return {!goog.dom.SavedCaretRange} A saved caret range that normalizes
+ * text nodes.
+ */
+goog.editor.range.saveUsingNormalizedCarets = function(range) {
+ return new goog.editor.range.NormalizedCaretRange_(range);
+};
+
+
+
+/**
+ * Saves the range using carets, but normalizes text nodes when carets
+ * are removed.
+ * @see goog.editor.range.saveUsingNormalizedCarets
+ * @param {goog.dom.AbstractRange} range The range being saved.
+ * @constructor
+ * @extends {goog.dom.SavedCaretRange}
+ * @private
+ */
+goog.editor.range.NormalizedCaretRange_ = function(range) {
+ goog.dom.SavedCaretRange.call(this, range);
+};
+goog.inherits(goog.editor.range.NormalizedCaretRange_,
+ goog.dom.SavedCaretRange);
+
+
+/**
+ * Normalizes text nodes whenever carets are removed from the document.
+ * @param {goog.dom.AbstractRange=} opt_range A range whose offsets have already
+ * been adjusted for caret removal; it will be adjusted and returned 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.
+ * @override
+ */
+goog.editor.range.NormalizedCaretRange_.prototype.removeCarets =
+ function(opt_range) {
+ var startCaret = this.getCaret(true);
+ var endCaret = this.getCaret(false);
+ var node = startCaret && endCaret ?
+ goog.dom.findCommonAncestor(startCaret, endCaret) :
+ startCaret || endCaret;
+
+ goog.editor.range.NormalizedCaretRange_.superClass_.removeCarets.call(this);
+
+ if (opt_range) {
+ return goog.editor.range.rangePreservingNormalize(node, opt_range);
+ } else if (node) {
+ goog.editor.range.selectionPreservingNormalize(node);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/seamlessfield.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/seamlessfield.js b/externs/GCL/externs/goog/editor/seamlessfield.js
new file mode 100644
index 0000000..7d84533
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/seamlessfield.js
@@ -0,0 +1,746 @@
+// 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 Class to encapsulate an editable field that blends in with
+ * the style of the page. The field can be fixed height, grow with its
+ * contents, or have a min height after which it grows to its contents.
+ * This is a goog.editor.Field, but with blending and sizing capabilities,
+ * and avoids using an iframe whenever possible.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ * @see ../demos/editor/seamlessfield.html
+ */
+
+
+goog.provide('goog.editor.SeamlessField');
+
+goog.require('goog.cssom.iframe.style');
+goog.require('goog.dom');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.safe');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Field');
+goog.require('goog.editor.icontent');
+goog.require('goog.editor.icontent.FieldFormatInfo');
+goog.require('goog.editor.icontent.FieldStyleInfo');
+goog.require('goog.editor.node');
+goog.require('goog.events');
+goog.require('goog.events.EventType');
+goog.require('goog.html.uncheckedconversions');
+goog.require('goog.log');
+goog.require('goog.string.Const');
+goog.require('goog.style');
+
+
+
+/**
+ * This class encapsulates an editable field that blends in with the
+ * surrounding page.
+ * To see events fired by this object, please see the base class.
+ *
+ * @param {string} id An identifer for the field. This is used to find the
+ * field and the element associated with this field.
+ * @param {Document=} opt_doc The document that the element with the given
+ * id can be found it.
+ * @constructor
+ * @extends {goog.editor.Field}
+ */
+goog.editor.SeamlessField = function(id, opt_doc) {
+ goog.editor.Field.call(this, id, opt_doc);
+};
+goog.inherits(goog.editor.SeamlessField, goog.editor.Field);
+
+
+/**
+ * @override
+ */
+goog.editor.SeamlessField.prototype.logger =
+ goog.log.getLogger('goog.editor.SeamlessField');
+
+// Functions dealing with field sizing.
+
+
+/**
+ * The key used for listening for the "dragover" event.
+ * @type {goog.events.Key}
+ * @private
+ */
+goog.editor.SeamlessField.prototype.listenForDragOverEventKey_;
+
+
+/**
+ * The key used for listening for the iframe "load" event.
+ * @type {goog.events.Key}
+ * @private
+ */
+goog.editor.SeamlessField.prototype.listenForIframeLoadEventKey_;
+
+
+/**
+ * Sets the min height of this editable field's iframe. Only used in growing
+ * mode when an iframe is used. This will cause an immediate field sizing to
+ * update the field if necessary based on the new min height.
+ * @param {number} height The min height specified as a number of pixels,
+ * e.g., 75.
+ */
+goog.editor.SeamlessField.prototype.setMinHeight = function(height) {
+ if (height == this.minHeight_) {
+ // Do nothing if the min height isn't changing.
+ return;
+ }
+ this.minHeight_ = height;
+ if (this.usesIframe()) {
+ this.doFieldSizingGecko();
+ }
+};
+
+
+/**
+ * Whether the field should be rendered with a fixed height, or should expand
+ * to fit its contents.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.SeamlessField.prototype.isFixedHeight_ = false;
+
+
+/**
+ * Whether the fixed-height handling has been overridden manually.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.SeamlessField.prototype.isFixedHeightOverridden_ = false;
+
+
+/**
+ * @return {boolean} Whether the field should be rendered with a fixed
+ * height, or should expand to fit its contents.
+ * @override
+ */
+goog.editor.SeamlessField.prototype.isFixedHeight = function() {
+ return this.isFixedHeight_;
+};
+
+
+/**
+ * @param {boolean} newVal Explicitly set whether the field should be
+ * of a fixed-height. This overrides auto-detection.
+ */
+goog.editor.SeamlessField.prototype.overrideFixedHeight = function(newVal) {
+ this.isFixedHeight_ = newVal;
+ this.isFixedHeightOverridden_ = true;
+};
+
+
+/**
+ * Auto-detect whether the current field should have a fixed height.
+ * @private
+ */
+goog.editor.SeamlessField.prototype.autoDetectFixedHeight_ = function() {
+ if (!this.isFixedHeightOverridden_) {
+ var originalElement = this.getOriginalElement();
+ if (originalElement) {
+ this.isFixedHeight_ =
+ goog.style.getComputedOverflowY(originalElement) == 'auto';
+ }
+ }
+};
+
+
+/**
+ * Resize the iframe in response to the wrapper div changing size.
+ * @private
+ */
+goog.editor.SeamlessField.prototype.handleOuterDocChange_ = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
+ return;
+ }
+ this.sizeIframeToWrapperGecko_();
+};
+
+
+/**
+ * Sizes the iframe to its body's height.
+ * @private
+ */
+goog.editor.SeamlessField.prototype.sizeIframeToBodyHeightGecko_ = function() {
+ if (this.acquireSizeIframeLockGecko_()) {
+ var resized = false;
+ var ifr = this.getEditableIframe();
+ if (ifr) {
+ var fieldHeight = this.getIframeBodyHeightGecko_();
+
+ if (this.minHeight_) {
+ fieldHeight = Math.max(fieldHeight, this.minHeight_);
+ }
+ if (parseInt(goog.style.getStyle(ifr, 'height'), 10) != fieldHeight) {
+ ifr.style.height = fieldHeight + 'px';
+ resized = true;
+ }
+ }
+ this.releaseSizeIframeLockGecko_();
+ if (resized) {
+ this.dispatchEvent(goog.editor.Field.EventType.IFRAME_RESIZED);
+ }
+ }
+};
+
+
+/**
+ * @return {number} The height of the editable iframe's body.
+ * @private
+ */
+goog.editor.SeamlessField.prototype.getIframeBodyHeightGecko_ = function() {
+ var ifr = this.getEditableIframe();
+ var body = ifr.contentDocument.body;
+ var htmlElement = body.parentNode;
+
+
+ // If the iframe's height is 0, then the offsetHeight/scrollHeight of the
+ // HTML element in the iframe can be totally wack (i.e. too large
+ // by 50-500px). Also, in standard's mode the clientHeight is 0.
+ if (parseInt(goog.style.getStyle(ifr, 'height'), 10) === 0) {
+ goog.style.setStyle(ifr, 'height', 1 + 'px');
+ }
+
+ var fieldHeight;
+ if (goog.editor.node.isStandardsMode(body)) {
+
+ // If in standards-mode,
+ // grab the HTML element as it will contain all the field's
+ // contents. The body's height, for example, will not include that of
+ // floated images at the bottom in standards mode.
+ // Note that this value include all scrollbars *except* for scrollbars
+ // on the HTML element itself.
+ fieldHeight = htmlElement.offsetHeight;
+ } else {
+ // In quirks-mode, the body-element always seems
+ // to size to the containing window. The html-element however,
+ // sizes to the content, and can thus end up with a value smaller
+ // than its child body-element if the content is shrinking.
+ // We want to make the iframe shrink too when the content shrinks,
+ // so rather than size the iframe to the body-element, size it to
+ // the html-element.
+ fieldHeight = htmlElement.scrollHeight;
+
+ // If there is a horizontal scroll, add in the thickness of the
+ // scrollbar.
+ if (htmlElement.clientHeight != htmlElement.offsetHeight) {
+ fieldHeight += goog.editor.SeamlessField.getScrollbarWidth_();
+ }
+ }
+
+ return fieldHeight;
+};
+
+
+/**
+ * Grabs the width of a scrollbar from the browser and caches the result.
+ * @return {number} The scrollbar width in pixels.
+ * @private
+ */
+goog.editor.SeamlessField.getScrollbarWidth_ = function() {
+ return goog.editor.SeamlessField.scrollbarWidth_ ||
+ (goog.editor.SeamlessField.scrollbarWidth_ =
+ goog.style.getScrollbarWidth());
+};
+
+
+/**
+ * Sizes the iframe to its container div's width. The width of the div
+ * is controlled by its containing context, not by its contents.
+ * if it extends outside of it's contents, then it gets a horizontal scroll.
+ * @private
+ */
+goog.editor.SeamlessField.prototype.sizeIframeToWrapperGecko_ = function() {
+ if (this.acquireSizeIframeLockGecko_()) {
+ var ifr = this.getEditableIframe();
+ var field = this.getElement();
+ var resized = false;
+ if (ifr && field) {
+ var fieldPaddingBox;
+ var widthDiv = ifr.parentNode;
+
+ var width = widthDiv.offsetWidth;
+ if (parseInt(goog.style.getStyle(ifr, 'width'), 10) != width) {
+ fieldPaddingBox = goog.style.getPaddingBox(field);
+ ifr.style.width = width + 'px';
+ field.style.width =
+ width - fieldPaddingBox.left - fieldPaddingBox.right + 'px';
+ resized = true;
+ }
+
+ var height = widthDiv.offsetHeight;
+ if (this.isFixedHeight() &&
+ parseInt(goog.style.getStyle(ifr, 'height'), 10) != height) {
+ if (!fieldPaddingBox) {
+ fieldPaddingBox = goog.style.getPaddingBox(field);
+ }
+ ifr.style.height = height + 'px';
+ field.style.height =
+ height - fieldPaddingBox.top - fieldPaddingBox.bottom + 'px';
+ resized = true;
+ }
+
+ }
+ this.releaseSizeIframeLockGecko_();
+ if (resized) {
+ this.dispatchEvent(goog.editor.Field.EventType.IFRAME_RESIZED);
+ }
+ }
+};
+
+
+/**
+ * Perform all the sizing immediately.
+ */
+goog.editor.SeamlessField.prototype.doFieldSizingGecko = function() {
+ // Because doFieldSizingGecko can be called after a setTimeout
+ // it is possible that the field has been destroyed before this call
+ // to do the sizing is executed. Check for field existence and do nothing
+ // if it has already been destroyed.
+ if (this.getElement()) {
+ // The order of operations is important here. Sizing the iframe to the
+ // wrapper could cause the width to change, which could change the line
+ // wrapping, which could change the body height. So we need to do that
+ // first, then size the iframe to fit the body height.
+ this.sizeIframeToWrapperGecko_();
+ if (!this.isFixedHeight()) {
+ this.sizeIframeToBodyHeightGecko_();
+ }
+ }
+};
+
+
+/**
+ * Acquires a lock on resizing the field iframe. This is used to ensure that
+ * modifications we make while in a mutation event handler don't cause
+ * infinite loops.
+ * @return {boolean} False if the lock is already acquired.
+ * @private
+ */
+goog.editor.SeamlessField.prototype.acquireSizeIframeLockGecko_ = function() {
+ if (this.sizeIframeLock_) {
+ return false;
+ }
+ return this.sizeIframeLock_ = true;
+};
+
+
+/**
+ * Releases a lock on resizing the field iframe. This is used to ensure that
+ * modifications we make while in a mutation event handler don't cause
+ * infinite loops.
+ * @private
+ */
+goog.editor.SeamlessField.prototype.releaseSizeIframeLockGecko_ = function() {
+ this.sizeIframeLock_ = false;
+};
+
+
+// Functions dealing with blending in with the surrounding page.
+
+
+/**
+ * String containing the css rules that, if applied to a document's body,
+ * would style that body as if it were the original element we made editable.
+ * See goog.cssom.iframe.style.getElementContext for more details.
+ * @type {string}
+ * @private
+ */
+goog.editor.SeamlessField.prototype.iframeableCss_ = '';
+
+
+/**
+ * Gets the css rules that should be used to style an iframe's body as if it
+ * were the original element that we made editable.
+ * @param {boolean=} opt_forceRegeneration Set to true to not read the cached
+ * copy and instead completely regenerate the css rules.
+ * @return {string} The string containing the css rules to use.
+ */
+goog.editor.SeamlessField.prototype.getIframeableCss = function(
+ opt_forceRegeneration) {
+ if (!this.iframeableCss_ || opt_forceRegeneration) {
+ var originalElement = this.getOriginalElement();
+ if (originalElement) {
+ this.iframeableCss_ =
+ goog.cssom.iframe.style.getElementContext(originalElement,
+ opt_forceRegeneration);
+ }
+ }
+ return this.iframeableCss_;
+};
+
+
+/**
+ * Sets the css rules that should be used inside the editable iframe.
+ * Note: to clear the css cache between makeNotEditable/makeEditable,
+ * call this with "" as iframeableCss.
+ * TODO(user): Unify all these css setting methods + Nick's open
+ * CL. This is getting ridiculous.
+ * @param {string} iframeableCss String containing the css rules to use.
+ */
+goog.editor.SeamlessField.prototype.setIframeableCss = function(iframeableCss) {
+ this.iframeableCss_ = iframeableCss;
+};
+
+
+/**
+ * Used to ensure that CSS stylings are only installed once for none
+ * iframe seamless mode.
+ * TODO(user): Make it a formal part of the API that you can only
+ * set one set of styles globally.
+ * In seamless, non-iframe mode, all the stylings would go in the
+ * same document and conflict.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.SeamlessField.haveInstalledCss_ = false;
+
+
+/**
+ * Applies CSS from the wrapper-div to the field iframe.
+ */
+goog.editor.SeamlessField.prototype.inheritBlendedCSS = function() {
+ // No-op if the field isn't using an iframe.
+ if (!this.usesIframe()) {
+ return;
+ }
+ var field = this.getElement();
+ var head = goog.dom.getDomHelper(field).getElementsByTagNameAndClass(
+ goog.dom.TagName.HEAD)[0];
+ if (head) {
+ // We created this <head>, and we know the only thing we put in there
+ // is a <style> block. So it's safe to blow away all the children
+ // as part of rewriting the styles.
+ goog.dom.removeChildren(head);
+ }
+
+ // Force a cache-clearing in CssUtil - this function was called because
+ // we're applying the 'blend' for the first time, or because we
+ // *need* to recompute the blend.
+ var newCSS = this.getIframeableCss(true);
+ goog.style.installStyles(newCSS, field);
+};
+
+
+// Overridden methods.
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.usesIframe = function() {
+ // TODO(user): Switch Firefox to using contentEditable
+ // rather than designMode iframe once contentEditable support
+ // is less buggy.
+ return !goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE;
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.setupMutationEventHandlersGecko =
+ function() {
+ goog.editor.SeamlessField.superClass_.setupMutationEventHandlersGecko.call(
+ this);
+
+ if (this.usesIframe()) {
+ var iframe = this.getEditableIframe();
+ var outerDoc = iframe.ownerDocument;
+ this.eventRegister.listen(outerDoc,
+ goog.editor.Field.MUTATION_EVENTS_GECKO,
+ this.handleOuterDocChange_, true);
+
+ // If the images load after we do the initial sizing, then this will
+ // force a field resize.
+ this.listenForIframeLoadEventKey_ = goog.events.listenOnce(
+ this.getEditableDomHelper().getWindow(),
+ goog.events.EventType.LOAD, this.sizeIframeToBodyHeightGecko_,
+ true, this);
+
+ this.eventRegister.listen(outerDoc,
+ 'DOMAttrModified',
+ goog.bind(this.handleDomAttrChange, this, this.handleOuterDocChange_),
+ true);
+ }
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.handleChange = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
+ return;
+ }
+
+ goog.editor.SeamlessField.superClass_.handleChange.call(this);
+
+ if (this.usesIframe()) {
+ this.sizeIframeToBodyHeightGecko_();
+ }
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.dispatchBlur = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.BLUR)) {
+ return;
+ }
+
+ goog.editor.SeamlessField.superClass_.dispatchBlur.call(this);
+
+ // Clear the selection and restore the current range back after collapsing
+ // it. The ideal solution would have been to just leave the range intact; but
+ // when there are multiple fields present on the page, its important that
+ // the selection isn't retained when we switch between the fields. We also
+ // have to make sure that the cursor position is retained when we tab in and
+ // out of a field and our approach addresses both these issues.
+ // Another point to note is that we do it on a setTimeout to allow for
+ // DOM modifications on blur. Otherwise, something like setLoremIpsum will
+ // leave a blinking cursor in the field even though it's blurred.
+ if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE &&
+ !goog.editor.BrowserFeature.CLEARS_SELECTION_WHEN_FOCUS_LEAVES) {
+ var win = this.getEditableDomHelper().getWindow();
+ var dragging = false;
+ goog.events.unlistenByKey(this.listenForDragOverEventKey_);
+ this.listenForDragOverEventKey_ = goog.events.listenOnce(
+ win.document.body, 'dragover',
+ function() {
+ dragging = true;
+ });
+ goog.global.setTimeout(goog.bind(function() {
+ // Do not clear the selection if we're only dragging text.
+ // This addresses a bug on FF1.5/linux where dragging fires a blur,
+ // but clearing the selection confuses Firefox's drag-and-drop
+ // implementation. For more info, see http://b/1061064
+ if (!dragging) {
+ if (this.editableDomHelper) {
+ var rng = this.getRange();
+
+ // If there are multiple fields on a page, we need to make sure that
+ // the selection isn't retained when we switch between fields. We
+ // could have collapsed the range but there is a bug in GECKO where
+ // the selection stays highlighted even though its backing range is
+ // collapsed (http://b/1390115). To get around this, we clear the
+ // selection and restore the collapsed range back in. Restoring the
+ // range is important so that the cursor stays intact when we tab out
+ // and into a field (See http://b/1790301 for additional details on
+ // this).
+ var iframeWindow = this.editableDomHelper.getWindow();
+ goog.dom.Range.clearSelection(iframeWindow);
+
+ if (rng) {
+ rng.collapse(true);
+ rng.select();
+ }
+ }
+ }
+ }, this), 0);
+ }
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.turnOnDesignModeGecko = function() {
+ goog.editor.SeamlessField.superClass_.turnOnDesignModeGecko.call(this);
+ var doc = this.getEditableDomHelper().getDocument();
+
+ doc.execCommand('enableInlineTableEditing', false, 'false');
+ doc.execCommand('enableObjectResizing', false, 'false');
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.installStyles = function() {
+ if (!this.usesIframe()) {
+ if (!goog.editor.SeamlessField.haveInstalledCss_) {
+ if (this.cssStyles) {
+ goog.style.installStyles(this.cssStyles, this.getElement());
+ }
+
+ // TODO(user): this should be reset to false when the editor is quit.
+ // In non-iframe mode, CSS styles should only be instaled once.
+ goog.editor.SeamlessField.haveInstalledCss_ = true;
+ }
+ }
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.makeEditableInternal = function(
+ opt_iframeSrc) {
+ if (this.usesIframe()) {
+ goog.editor.SeamlessField.superClass_.makeEditableInternal.call(this,
+ opt_iframeSrc);
+ } else {
+ var field = this.getOriginalElement();
+ if (field) {
+ this.setupFieldObject(field);
+ field.contentEditable = true;
+
+ this.injectContents(field.innerHTML, field);
+
+ this.handleFieldLoad();
+ }
+ }
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.handleFieldLoad = function() {
+ if (this.usesIframe()) {
+ // If the CSS inheriting code screws up (e.g. makes fonts too large) and
+ // the field is sized off in goog.editor.Field.makeIframeField, then we need
+ // to size it correctly, but it needs to be visible for the browser
+ // to have fully rendered it. We need to put this on a timeout to give
+ // the browser time to render.
+ var self = this;
+ goog.global.setTimeout(function() {
+ self.doFieldSizingGecko();
+ }, 0);
+ }
+ goog.editor.SeamlessField.superClass_.handleFieldLoad.call(this);
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.getIframeAttributes = function() {
+ return { 'frameBorder': 0, 'style': 'padding:0;' };
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.attachIframe = function(iframe) {
+ this.autoDetectFixedHeight_();
+ var field = this.getOriginalElement();
+ var dh = goog.dom.getDomHelper(field);
+
+ // Grab the width/height values of the field before modifying any CSS
+ // as some of the modifications affect its size (e.g. innerHTML='')
+ // Here, we set the size of the field to fixed so there's not too much
+ // jiggling when we set the innerHTML of the field.
+ var oldWidth = field.style.width;
+ var oldHeight = field.style.height;
+ goog.style.setStyle(field, 'visibility', 'hidden');
+
+ // If there is a floated element at the bottom of the field,
+ // then it needs a clearing div at the end to cause the clientHeight
+ // to contain the entire field.
+ // Also, with css re-writing, the margins of the first/last
+ // paragraph don't seem to get included in the clientHeight. Specifically,
+ // the extra divs below force the field's clientHeight to include the
+ // margins on the first and last elements contained within it.
+ var startDiv = dh.createDom(goog.dom.TagName.DIV,
+ {'style': 'height:0;clear:both', 'innerHTML': ' '});
+ var endDiv = startDiv.cloneNode(true);
+ field.insertBefore(startDiv, field.firstChild);
+ goog.dom.appendChild(field, endDiv);
+
+ var contentBox = goog.style.getContentBoxSize(field);
+ var width = contentBox.width;
+ var height = contentBox.height;
+
+ var html = '';
+ if (this.isFixedHeight()) {
+ html = ' ';
+
+ goog.style.setStyle(field, 'position', 'relative');
+ goog.style.setStyle(field, 'overflow', 'visible');
+
+ goog.style.setStyle(iframe, 'position', 'absolute');
+ goog.style.setStyle(iframe, 'top', '0');
+ goog.style.setStyle(iframe, 'left', '0');
+ }
+ goog.style.setSize(field, width, height);
+
+ // In strict mode, browsers put blank space at the bottom and right
+ // if a field when it has an iframe child, to fill up the remaining line
+ // height. So make the line height = 0.
+ if (goog.editor.node.isStandardsMode(field)) {
+ this.originalFieldLineHeight_ = field.style.lineHeight;
+ goog.style.setStyle(field, 'lineHeight', '0');
+ }
+
+ goog.editor.node.replaceInnerHtml(field, html);
+ // Set the initial size
+ goog.style.setSize(iframe, width, height);
+ goog.style.setSize(field, oldWidth, oldHeight);
+ goog.style.setStyle(field, 'visibility', '');
+ goog.dom.appendChild(field, iframe);
+
+ // Only write if its not IE HTTPS in which case we're waiting for load.
+ if (!this.shouldLoadAsynchronously()) {
+ var doc = iframe.contentWindow.document;
+ if (goog.editor.node.isStandardsMode(iframe.ownerDocument)) {
+ doc.open();
+ var emptyHtml = goog.html.uncheckedconversions
+ .safeHtmlFromStringKnownToSatisfyTypeContract(
+ goog.string.Const.from('HTML from constant string'),
+ '<!DOCTYPE HTML><html></html>');
+ goog.dom.safe.documentWrite(doc, emptyHtml);
+ doc.close();
+ }
+ }
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.getFieldFormatInfo = function(
+ extraStyles) {
+ var originalElement = this.getOriginalElement();
+ if (originalElement) {
+ return new goog.editor.icontent.FieldFormatInfo(
+ this.id,
+ goog.editor.node.isStandardsMode(originalElement),
+ true,
+ this.isFixedHeight(),
+ extraStyles);
+ }
+ throw Error('no field');
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.writeIframeContent = function(
+ iframe, innerHtml, extraStyles) {
+ // For seamless iframes, hide the iframe while we're laying it out to
+ // prevent the flicker.
+ goog.style.setStyle(iframe, 'visibility', 'hidden');
+ var formatInfo = this.getFieldFormatInfo(extraStyles);
+ var styleInfo = new goog.editor.icontent.FieldStyleInfo(
+ this.getOriginalElement(),
+ this.cssStyles + this.getIframeableCss());
+ goog.editor.icontent.writeNormalInitialBlendedIframe(
+ formatInfo, innerHtml, styleInfo, iframe);
+ this.doFieldSizingGecko();
+ goog.style.setStyle(iframe, 'visibility', 'visible');
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.restoreDom = function() {
+ // TODO(user): Consider only removing the iframe if we are
+ // restoring the original node.
+ if (this.usesIframe()) {
+ goog.dom.removeNode(this.getEditableIframe());
+ }
+};
+
+
+/** @override */
+goog.editor.SeamlessField.prototype.clearListeners = function() {
+ goog.events.unlistenByKey(this.listenForDragOverEventKey_);
+ goog.events.unlistenByKey(this.listenForIframeLoadEventKey_);
+
+ goog.editor.SeamlessField.base(this, 'clearListeners');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/style.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/style.js b/externs/GCL/externs/goog/editor/style.js
new file mode 100644
index 0000000..55b703b
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/style.js
@@ -0,0 +1,225 @@
+// Copyright 2009 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 Utilties for working with the styles of DOM nodes, and
+ * related to rich text editing.
+ *
+ * Many of these are not general enough to go into goog.style, and use
+ * constructs (like "isContainer") that only really make sense inside
+ * of an HTML editor.
+ *
+ * The API has been optimized for iterating over large, irregular DOM
+ * structures (with lots of text nodes), and so the API tends to be a bit
+ * more permissive than the goog.style API should be. For example,
+ * goog.style.getComputedStyle will throw an exception if you give it a
+ * text node.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.style');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.events.EventType');
+goog.require('goog.object');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+
+
+/**
+ * Gets the computed or cascaded style.
+ *
+ * This is different than goog.style.getStyle_ because it returns null
+ * for text nodes (instead of throwing an exception), and never reads
+ * inline style. These two functions may need to be reconciled.
+ *
+ * @param {!Node} node Node to get style of.
+ * @param {string} stylePropertyName Property to get (must be camelCase,
+ * not css-style).
+ * @return {?string} Style value, or null if this is not an element node.
+ * @private
+ */
+goog.editor.style.getComputedOrCascadedStyle_ = function(
+ node, stylePropertyName) {
+ if (node.nodeType != goog.dom.NodeType.ELEMENT) {
+ // Only element nodes have style.
+ return null;
+ }
+ return goog.userAgent.IE ?
+ goog.style.getCascadedStyle(/** @type {!Element} */ (node),
+ stylePropertyName) :
+ goog.style.getComputedStyle(/** @type {!Element} */ (node),
+ stylePropertyName);
+};
+
+
+/**
+ * Checks whether the given element inherits display: block.
+ * @param {!Node} node The Node to check.
+ * @return {boolean} Whether the element inherits CSS display: block.
+ */
+goog.editor.style.isDisplayBlock = function(node) {
+ return goog.editor.style.getComputedOrCascadedStyle_(
+ node, 'display') == 'block';
+};
+
+
+/**
+ * Returns true if the element is a container of other non-inline HTML
+ * Note that span, strong and em tags, being inline can only contain
+ * other inline elements and are thus, not containers. Containers are elements
+ * that should not be broken up when wrapping selections with a node of an
+ * inline block styling.
+ * @param {Node} element The element to check.
+ * @return {boolean} Whether the element is a container.
+ */
+goog.editor.style.isContainer = function(element) {
+ var nodeName = element && element.nodeName;
+ return !!(element &&
+ (goog.editor.style.isDisplayBlock(element) ||
+ nodeName == goog.dom.TagName.TD ||
+ nodeName == goog.dom.TagName.TABLE ||
+ nodeName == goog.dom.TagName.LI));
+};
+
+
+/**
+ * Return the first ancestor of this node that is a container, inclusive.
+ * @see isContainer
+ * @param {Node} node Node to find the container of.
+ * @return {Element} The element which contains node.
+ */
+goog.editor.style.getContainer = function(node) {
+ // We assume that every node must have a container.
+ return /** @type {Element} */ (
+ goog.dom.getAncestor(node, goog.editor.style.isContainer, true));
+};
+
+
+/**
+ * Set of input types that should be kept selectable even when their ancestors
+ * are made unselectable.
+ * @type {Object}
+ * @private
+ */
+goog.editor.style.SELECTABLE_INPUT_TYPES_ = goog.object.createSet(
+ 'text', 'file', 'url');
+
+
+/**
+ * Prevent the default action on mousedown events.
+ * @param {goog.events.Event} e The mouse down event.
+ * @private
+ */
+goog.editor.style.cancelMouseDownHelper_ = function(e) {
+ var targetTagName = e.target.tagName;
+ if (targetTagName != goog.dom.TagName.TEXTAREA &&
+ targetTagName != goog.dom.TagName.INPUT) {
+ e.preventDefault();
+ }
+};
+
+
+/**
+ * Makes the given element unselectable, as well as all of its children, except
+ * for text areas, text, file and url inputs.
+ * @param {Element} element The element to make unselectable.
+ * @param {goog.events.EventHandler} eventHandler An EventHandler to register
+ * the event with. Assumes when the node is destroyed, the eventHandler's
+ * listeners are destroyed as well.
+ */
+goog.editor.style.makeUnselectable = function(element, eventHandler) {
+ if (goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE) {
+ // The mousing down on a node should not blur the focused node.
+ // This is consistent with how IE works.
+ // TODO: Consider using just the mousedown handler and not the css property.
+ eventHandler.listen(element, goog.events.EventType.MOUSEDOWN,
+ goog.editor.style.cancelMouseDownHelper_, true);
+ }
+
+ goog.style.setUnselectable(element, true);
+
+ // Make inputs and text areas selectable.
+ var inputs = element.getElementsByTagName(goog.dom.TagName.INPUT);
+ for (var i = 0, len = inputs.length; i < len; i++) {
+ var input = inputs[i];
+ if (input.type in goog.editor.style.SELECTABLE_INPUT_TYPES_) {
+ goog.editor.style.makeSelectable(input);
+ }
+ }
+ goog.array.forEach(element.getElementsByTagName(goog.dom.TagName.TEXTAREA),
+ goog.editor.style.makeSelectable);
+};
+
+
+/**
+ * Make the given element selectable.
+ *
+ * For IE this simply turns off the "unselectable" property.
+ *
+ * Under FF no descendent of an unselectable node can be selectable:
+ *
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=203291
+ *
+ * So we make each ancestor of node selectable, while trying to preserve the
+ * unselectability of other nodes along that path
+ *
+ * This may cause certain text nodes which should be unselectable, to become
+ * selectable. For example:
+ *
+ * <div id=div1 style="-moz-user-select: none">
+ * Text1
+ * <span id=span1>Text2</span>
+ * </div>
+ *
+ * If we call makeSelectable on span1, then it will cause "Text1" to become
+ * selectable, since it had to make div1 selectable in order for span1 to be
+ * selectable.
+ *
+ * If "Text1" were enclosed within a <p> or <span>, then this problem would
+ * not arise. Text nodes do not have styles, so its style can't be set to
+ * unselectable.
+ *
+ * @param {Element} element The element to make selectable.
+ */
+goog.editor.style.makeSelectable = function(element) {
+ goog.style.setUnselectable(element, false);
+ if (goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE) {
+ // Go up ancestor chain, searching for nodes that are unselectable.
+ // If such a node exists, mark it as selectable but mark its other children
+ // as unselectable so the minimum set of nodes is changed.
+ var child = element;
+ var current = /** @type {Element} */ (element.parentNode);
+ while (current && current.tagName != goog.dom.TagName.HTML) {
+ if (goog.style.isUnselectable(current)) {
+ goog.style.setUnselectable(current, false, true);
+
+ for (var i = 0, len = current.childNodes.length; i < len; i++) {
+ var node = current.childNodes[i];
+ if (node != child && node.nodeType == goog.dom.NodeType.ELEMENT) {
+ goog.style.setUnselectable(current.childNodes[i], true);
+ }
+ }
+ }
+
+ child = current;
+ current = /** @type {Element} */ (current.parentNode);
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/table.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/table.js b/externs/GCL/externs/goog/editor/table.js
new file mode 100644
index 0000000..1bddc6d
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/table.js
@@ -0,0 +1,570 @@
+// 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 Table editing support.
+ * This file provides the class goog.editor.Table and two
+ * supporting classes, goog.editor.TableRow and
+ * goog.editor.TableCell. Together these provide support for
+ * high level table modifications: Adding and deleting rows and columns,
+ * and merging and splitting cells.
+ *
+ * @supported IE6+, WebKit 525+, Firefox 2+.
+ */
+
+goog.provide('goog.editor.Table');
+goog.provide('goog.editor.TableCell');
+goog.provide('goog.editor.TableRow');
+
+goog.require('goog.dom');
+goog.require('goog.dom.DomHelper');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TagName');
+goog.require('goog.log');
+goog.require('goog.string.Unicode');
+goog.require('goog.style');
+
+
+
+/**
+ * Class providing high level table editing functions.
+ * @param {Element} node Element that is a table or descendant of a table.
+ * @constructor
+ * @final
+ */
+goog.editor.Table = function(node) {
+ this.element = goog.dom.getAncestorByTagNameAndClass(node,
+ goog.dom.TagName.TABLE);
+ if (!this.element) {
+ goog.log.error(this.logger_,
+ "Can't create Table based on a node " +
+ "that isn't a table, or descended from a table.");
+ }
+ this.dom_ = goog.dom.getDomHelper(this.element);
+ this.refresh();
+};
+
+
+/**
+ * Logger object for debugging and error messages.
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.editor.Table.prototype.logger_ =
+ goog.log.getLogger('goog.editor.Table');
+
+
+/**
+ * Walks the dom structure of this object's table element and populates
+ * this.rows with goog.editor.TableRow objects. This is done initially
+ * to populate the internal data structures, and also after each time the
+ * DOM structure is modified. Currently this means that the all existing
+ * information is discarded and re-read from the DOM.
+ */
+// TODO(user): support partial refresh to save cost of full update
+// every time there is a change to the DOM.
+goog.editor.Table.prototype.refresh = function() {
+ var rows = this.rows = [];
+ var tbody = this.element.getElementsByTagName(goog.dom.TagName.TBODY)[0];
+ if (!tbody) {
+ return;
+ }
+ var trs = [];
+ for (var child = tbody.firstChild; child; child = child.nextSibling) {
+ if (child.nodeName == goog.dom.TagName.TR) {
+ trs.push(child);
+ }
+ }
+
+ for (var rowNum = 0, tr; tr = trs[rowNum]; rowNum++) {
+ var existingRow = rows[rowNum];
+ var tds = goog.editor.Table.getChildCellElements(tr);
+ var columnNum = 0;
+ // A note on cellNum vs. columnNum: A cell is a td/th element. Cells may
+ // use colspan/rowspan to extend over multiple rows/columns. cellNum
+ // is the dom element number, columnNum is the logical column number.
+ for (var cellNum = 0, td; td = tds[cellNum]; cellNum++) {
+ // If there's already a cell extending into this column
+ // (due to that cell's colspan/rowspan), increment the column counter.
+ while (existingRow && existingRow.columns[columnNum]) {
+ columnNum++;
+ }
+ var cell = new goog.editor.TableCell(td, rowNum, columnNum);
+ // Place this cell in every row and column into which it extends.
+ for (var i = 0; i < cell.rowSpan; i++) {
+ var cellRowNum = rowNum + i;
+ // Create TableRow objects in this.rows as needed.
+ var cellRow = rows[cellRowNum];
+ if (!cellRow) {
+ // TODO(user): try to avoid second trs[] lookup.
+ rows.push(
+ cellRow = new goog.editor.TableRow(trs[cellRowNum], cellRowNum));
+ }
+ // Extend length of column array to make room for this cell.
+ var minimumColumnLength = columnNum + cell.colSpan;
+ if (cellRow.columns.length < minimumColumnLength) {
+ cellRow.columns.length = minimumColumnLength;
+ }
+ for (var j = 0; j < cell.colSpan; j++) {
+ var cellColumnNum = columnNum + j;
+ cellRow.columns[cellColumnNum] = cell;
+ }
+ }
+ columnNum += cell.colSpan;
+ }
+ }
+};
+
+
+/**
+ * Returns all child elements of a TR element that are of type TD or TH.
+ * @param {Element} tr TR element in which to find children.
+ * @return {!Array<Element>} array of child cell elements.
+ */
+goog.editor.Table.getChildCellElements = function(tr) {
+ var cells = [];
+ for (var i = 0, cell; cell = tr.childNodes[i]; i++) {
+ if (cell.nodeName == goog.dom.TagName.TD ||
+ cell.nodeName == goog.dom.TagName.TH) {
+ cells.push(cell);
+ }
+ }
+ return cells;
+};
+
+
+/**
+ * Inserts a new row in the table. The row will be populated with new
+ * cells, and existing rowspanned cells that overlap the new row will
+ * be extended.
+ * @param {number=} opt_rowIndex Index at which to insert the row. If
+ * this is omitted the row will be appended to the end of the table.
+ * @return {!Element} The new row.
+ */
+goog.editor.Table.prototype.insertRow = function(opt_rowIndex) {
+ var rowIndex = goog.isDefAndNotNull(opt_rowIndex) ?
+ opt_rowIndex : this.rows.length;
+ var refRow;
+ var insertAfter;
+ if (rowIndex == 0) {
+ refRow = this.rows[0];
+ insertAfter = false;
+ } else {
+ refRow = this.rows[rowIndex - 1];
+ insertAfter = true;
+ }
+ var newTr = this.dom_.createElement(goog.dom.TagName.TR);
+ for (var i = 0, cell; cell = refRow.columns[i]; i += 1) {
+ // Check whether the existing cell will span this new row.
+ // If so, instead of creating a new cell, extend
+ // the rowspan of the existing cell.
+ if ((insertAfter && cell.endRow > rowIndex) ||
+ (!insertAfter && cell.startRow < rowIndex)) {
+ cell.setRowSpan(cell.rowSpan + 1);
+ if (cell.colSpan > 1) {
+ i += cell.colSpan - 1;
+ }
+ } else {
+ newTr.appendChild(this.createEmptyTd());
+ }
+ if (insertAfter) {
+ goog.dom.insertSiblingAfter(newTr, refRow.element);
+ } else {
+ goog.dom.insertSiblingBefore(newTr, refRow.element);
+ }
+ }
+ this.refresh();
+ return newTr;
+};
+
+
+/**
+ * Inserts a new column in the table. The column will be created by
+ * inserting new TD elements in each row, or extending the colspan
+ * of existing TD elements.
+ * @param {number=} opt_colIndex Index at which to insert the column. If
+ * this is omitted the column will be appended to the right side of
+ * the table.
+ * @return {!Array<Element>} Array of new cell elements that were created
+ * to populate the new column.
+ */
+goog.editor.Table.prototype.insertColumn = function(opt_colIndex) {
+ // TODO(user): set column widths in a way that makes sense.
+ var colIndex = goog.isDefAndNotNull(opt_colIndex) ?
+ opt_colIndex :
+ (this.rows[0] && this.rows[0].columns.length) || 0;
+ var newTds = [];
+ for (var rowNum = 0, row; row = this.rows[rowNum]; rowNum++) {
+ var existingCell = row.columns[colIndex];
+ if (existingCell && existingCell.endCol >= colIndex &&
+ existingCell.startCol < colIndex) {
+ existingCell.setColSpan(existingCell.colSpan + 1);
+ rowNum += existingCell.rowSpan - 1;
+ } else {
+ var newTd = this.createEmptyTd();
+ // TODO(user): figure out a way to intelligently size new columns.
+ newTd.style.width = goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH + 'px';
+ this.insertCellElement(newTd, rowNum, colIndex);
+ newTds.push(newTd);
+ }
+ }
+ this.refresh();
+ return newTds;
+};
+
+
+/**
+ * Removes a row from the table, removing the TR element and
+ * decrementing the rowspan of any cells in other rows that overlap the row.
+ * @param {number} rowIndex Index of the row to delete.
+ */
+goog.editor.Table.prototype.removeRow = function(rowIndex) {
+ var row = this.rows[rowIndex];
+ if (!row) {
+ goog.log.warning(this.logger_,
+ "Can't remove row at position " + rowIndex + ': no such row.');
+ }
+ for (var i = 0, cell; cell = row.columns[i]; i += cell.colSpan) {
+ if (cell.rowSpan > 1) {
+ cell.setRowSpan(cell.rowSpan - 1);
+ if (cell.startRow == rowIndex) {
+ // Rowspanned cell started in this row - move it down to the next row.
+ this.insertCellElement(cell.element, rowIndex + 1, cell.startCol);
+ }
+ }
+ }
+ row.element.parentNode.removeChild(row.element);
+ this.refresh();
+};
+
+
+/**
+ * Removes a column from the table. This is done by removing cell elements,
+ * or shrinking the colspan of elements that span multiple columns.
+ * @param {number} colIndex Index of the column to delete.
+ */
+goog.editor.Table.prototype.removeColumn = function(colIndex) {
+ for (var i = 0, row; row = this.rows[i]; i++) {
+ var cell = row.columns[colIndex];
+ if (!cell) {
+ goog.log.error(this.logger_,
+ "Can't remove cell at position " + i + ', ' + colIndex +
+ ': no such cell.');
+ }
+ if (cell.colSpan > 1) {
+ cell.setColSpan(cell.colSpan - 1);
+ } else {
+ cell.element.parentNode.removeChild(cell.element);
+ }
+ // Skip over following rows that contain this same cell.
+ i += cell.rowSpan - 1;
+ }
+ this.refresh();
+};
+
+
+/**
+ * Merges multiple cells into a single cell, and sets the rowSpan and colSpan
+ * attributes of the cell to take up the same space as the original cells.
+ * @param {number} startRowIndex Top coordinate of the cells to merge.
+ * @param {number} startColIndex Left coordinate of the cells to merge.
+ * @param {number} endRowIndex Bottom coordinate of the cells to merge.
+ * @param {number} endColIndex Right coordinate of the cells to merge.
+ * @return {boolean} Whether or not the merge was possible. If the cells
+ * in the supplied coordinates can't be merged this will return false.
+ */
+goog.editor.Table.prototype.mergeCells = function(
+ startRowIndex, startColIndex, endRowIndex, endColIndex) {
+ // TODO(user): take a single goog.math.Rect parameter instead?
+ var cells = [];
+ var cell;
+ if (startRowIndex == endRowIndex && startColIndex == endColIndex) {
+ goog.log.warning(this.logger_, "Can't merge single cell");
+ return false;
+ }
+ // Gather cells and do sanity check.
+ for (var i = startRowIndex; i <= endRowIndex; i++) {
+ for (var j = startColIndex; j <= endColIndex; j++) {
+ cell = this.rows[i].columns[j];
+ if (cell.startRow < startRowIndex ||
+ cell.endRow > endRowIndex ||
+ cell.startCol < startColIndex ||
+ cell.endCol > endColIndex) {
+ goog.log.warning(this.logger_,
+ "Can't merge cells: the cell in row " + i + ', column ' + j +
+ 'extends outside the supplied rectangle.');
+ return false;
+ }
+ // TODO(user): this is somewhat inefficient, as we will add
+ // a reference for a cell for each position, even if it's a single
+ // cell with row/colspan.
+ cells.push(cell);
+ }
+ }
+ var targetCell = cells[0];
+ var targetTd = targetCell.element;
+ var doc = this.dom_.getDocument();
+
+ // Merge cell contents and discard other cells.
+ for (var i = 1; cell = cells[i]; i++) {
+ var td = cell.element;
+ if (!td.parentNode || td == targetTd) {
+ // We've already handled this cell at one of its previous positions.
+ continue;
+ }
+ // Add a space if needed, to keep merged content from getting squished
+ // together.
+ if (targetTd.lastChild &&
+ targetTd.lastChild.nodeType == goog.dom.NodeType.TEXT) {
+ targetTd.appendChild(doc.createTextNode(' '));
+ }
+ var childNode;
+ while ((childNode = td.firstChild)) {
+ targetTd.appendChild(childNode);
+ }
+ td.parentNode.removeChild(td);
+ }
+ targetCell.setColSpan((endColIndex - startColIndex) + 1);
+ targetCell.setRowSpan((endRowIndex - startRowIndex) + 1);
+ if (endColIndex > startColIndex) {
+ // Clear width on target cell.
+ // TODO(user): instead of clearing width, calculate width
+ // based on width of input cells
+ targetTd.removeAttribute('width');
+ targetTd.style.width = null;
+ }
+ this.refresh();
+
+ return true;
+};
+
+
+/**
+ * Splits a cell with colspans or rowspans into multiple descrete cells.
+ * @param {number} rowIndex y coordinate of the cell to split.
+ * @param {number} colIndex x coordinate of the cell to split.
+ * @return {!Array<Element>} Array of new cell elements created by splitting
+ * the cell.
+ */
+// TODO(user): support splitting only horizontally or vertically,
+// support splitting cells that aren't already row/colspanned.
+goog.editor.Table.prototype.splitCell = function(rowIndex, colIndex) {
+ var row = this.rows[rowIndex];
+ var cell = row.columns[colIndex];
+ var newTds = [];
+ for (var i = 0; i < cell.rowSpan; i++) {
+ for (var j = 0; j < cell.colSpan; j++) {
+ if (i > 0 || j > 0) {
+ var newTd = this.createEmptyTd();
+ this.insertCellElement(newTd, rowIndex + i, colIndex + j);
+ newTds.push(newTd);
+ }
+ }
+ }
+ cell.setColSpan(1);
+ cell.setRowSpan(1);
+ this.refresh();
+ return newTds;
+};
+
+
+/**
+ * Inserts a cell element at the given position. The colIndex is the logical
+ * column index, not the position in the dom. This takes into consideration
+ * that cells in a given logical row may actually be children of a previous
+ * DOM row that have used rowSpan to extend into the row.
+ * @param {Element} td The new cell element to insert.
+ * @param {number} rowIndex Row in which to insert the element.
+ * @param {number} colIndex Column in which to insert the element.
+ */
+goog.editor.Table.prototype.insertCellElement = function(
+ td, rowIndex, colIndex) {
+ var row = this.rows[rowIndex];
+ var nextSiblingElement = null;
+ for (var i = colIndex, cell; cell = row.columns[i]; i += cell.colSpan) {
+ if (cell.startRow == rowIndex) {
+ nextSiblingElement = cell.element;
+ break;
+ }
+ }
+ row.element.insertBefore(td, nextSiblingElement);
+};
+
+
+/**
+ * Creates an empty TD element and fill it with some empty content so it will
+ * show up with borders even in IE pre-7 or if empty-cells is set to 'hide'
+ * @return {!Element} a new TD element.
+ */
+goog.editor.Table.prototype.createEmptyTd = function() {
+ // TODO(user): more cross-browser testing to determine best
+ // and least annoying filler content.
+ return this.dom_.createDom(goog.dom.TagName.TD, {}, goog.string.Unicode.NBSP);
+};
+
+
+
+/**
+ * Class representing a logical table row: a tr element and any cells
+ * that appear in that row.
+ * @param {Element} trElement This rows's underlying TR element.
+ * @param {number} rowIndex This row's index in its parent table.
+ * @constructor
+ * @final
+ */
+goog.editor.TableRow = function(trElement, rowIndex) {
+ this.index = rowIndex;
+ this.element = trElement;
+ this.columns = [];
+};
+
+
+
+/**
+ * Class representing a table cell, which may span across multiple
+ * rows and columns
+ * @param {Element} td This cell's underlying TD or TH element.
+ * @param {number} startRow Index of the row where this cell begins.
+ * @param {number} startCol Index of the column where this cell begins.
+ * @constructor
+ * @final
+ */
+goog.editor.TableCell = function(td, startRow, startCol) {
+ this.element = td;
+ this.colSpan = parseInt(td.colSpan, 10) || 1;
+ this.rowSpan = parseInt(td.rowSpan, 10) || 1;
+ this.startRow = startRow;
+ this.startCol = startCol;
+ this.updateCoordinates_();
+};
+
+
+/**
+ * Calculates this cell's endRow/endCol coordinates based on rowSpan/colSpan
+ * @private
+ */
+goog.editor.TableCell.prototype.updateCoordinates_ = function() {
+ this.endCol = this.startCol + this.colSpan - 1;
+ this.endRow = this.startRow + this.rowSpan - 1;
+};
+
+
+/**
+ * Set this cell's colSpan, updating both its colSpan property and the
+ * underlying element's colSpan attribute.
+ * @param {number} colSpan The new colSpan.
+ */
+goog.editor.TableCell.prototype.setColSpan = function(colSpan) {
+ if (colSpan != this.colSpan) {
+ if (colSpan > 1) {
+ this.element.colSpan = colSpan;
+ } else {
+ this.element.colSpan = 1,
+ this.element.removeAttribute('colSpan');
+ }
+ this.colSpan = colSpan;
+ this.updateCoordinates_();
+ }
+};
+
+
+/**
+ * Set this cell's rowSpan, updating both its rowSpan property and the
+ * underlying element's rowSpan attribute.
+ * @param {number} rowSpan The new rowSpan.
+ */
+goog.editor.TableCell.prototype.setRowSpan = function(rowSpan) {
+ if (rowSpan != this.rowSpan) {
+ if (rowSpan > 1) {
+ this.element.rowSpan = rowSpan.toString();
+ } else {
+ this.element.rowSpan = '1';
+ this.element.removeAttribute('rowSpan');
+ }
+ this.rowSpan = rowSpan;
+ this.updateCoordinates_();
+ }
+};
+
+
+/**
+ * Optimum size of empty cells (in pixels), if possible.
+ * @type {number}
+ */
+goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH = 60;
+
+
+/**
+ * Maximum width for new tables.
+ * @type {number}
+ */
+goog.editor.Table.OPTIMUM_MAX_NEW_TABLE_WIDTH = 600;
+
+
+/**
+ * Default color for table borders.
+ * @type {string}
+ */
+goog.editor.Table.DEFAULT_BORDER_COLOR = '#888';
+
+
+/**
+ * Creates a new table element, populated with cells and formatted.
+ * @param {Document} doc Document in which to create the table element.
+ * @param {number} columns Number of columns in the table.
+ * @param {number} rows Number of rows in the table.
+ * @param {Object=} opt_tableStyle Object containing borderWidth and borderColor
+ * properties, used to set the inital style of the table.
+ * @return {!Element} a table element.
+ */
+goog.editor.Table.createDomTable = function(
+ doc, columns, rows, opt_tableStyle) {
+ // TODO(user): define formatting properties as constants,
+ // make separate formatTable() function
+ var style = {
+ borderWidth: '1',
+ borderColor: goog.editor.Table.DEFAULT_BORDER_COLOR
+ };
+ for (var prop in opt_tableStyle) {
+ style[prop] = opt_tableStyle[prop];
+ }
+ var dom = new goog.dom.DomHelper(doc);
+ var tableElement = dom.createTable(rows, columns, true);
+
+ var minimumCellWidth = 10;
+ // Calculate a good cell width.
+ var cellWidth = Math.max(
+ minimumCellWidth,
+ Math.min(goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH,
+ goog.editor.Table.OPTIMUM_MAX_NEW_TABLE_WIDTH / columns));
+
+ var tds = tableElement.getElementsByTagName(goog.dom.TagName.TD);
+ for (var i = 0, td; td = tds[i]; i++) {
+ td.style.width = cellWidth + 'px';
+ }
+
+ // Set border somewhat redundantly to make sure they show
+ // up correctly in all browsers.
+ goog.style.setStyle(
+ tableElement, {
+ 'borderCollapse': 'collapse',
+ 'borderColor': style.borderColor,
+ 'borderWidth': style.borderWidth + 'px'
+ });
+ tableElement.border = style.borderWidth;
+ tableElement.setAttribute('bordercolor', style.borderColor);
+ tableElement.setAttribute('cellspacing', '0');
+
+ return tableElement;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/actioneventwrapper.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/actioneventwrapper.js b/externs/GCL/externs/goog/events/actioneventwrapper.js
new file mode 100644
index 0000000..779150f
--- /dev/null
+++ b/externs/GCL/externs/goog/events/actioneventwrapper.js
@@ -0,0 +1,151 @@
+// Copyright 2009 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 Action event wrapper implementation.
+ * @author eae@google.com (Emil A Eklund)
+ */
+
+goog.provide('goog.events.actionEventWrapper');
+
+goog.require('goog.a11y.aria');
+goog.require('goog.a11y.aria.Role');
+goog.require('goog.dom');
+goog.require('goog.events');
+/** @suppress {extraRequire} */
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventType');
+goog.require('goog.events.EventWrapper');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Event wrapper for action handling. Fires when an element is activated either
+ * by clicking it or by focusing it and pressing Enter.
+ *
+ * @constructor
+ * @implements {goog.events.EventWrapper}
+ * @private
+ */
+goog.events.ActionEventWrapper_ = function() {
+};
+
+
+/**
+ * Singleton instance of ActionEventWrapper_.
+ * @type {goog.events.ActionEventWrapper_}
+ */
+goog.events.actionEventWrapper = new goog.events.ActionEventWrapper_();
+
+
+/**
+ * Event types used by the wrapper.
+ *
+ * @type {Array<goog.events.EventType>}
+ * @private
+ */
+goog.events.ActionEventWrapper_.EVENT_TYPES_ = [
+ goog.events.EventType.CLICK,
+ goog.userAgent.GECKO ?
+ goog.events.EventType.KEYPRESS : goog.events.EventType.KEYDOWN,
+ goog.events.EventType.KEYUP
+];
+
+
+/**
+ * Adds an event listener using the wrapper on a DOM Node or an object that has
+ * implemented {@link goog.events.EventTarget}. A listener can only be added
+ * once to an object.
+ *
+ * @param {goog.events.ListenableType} target The target to listen to events on.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
+ * method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @param {goog.events.EventHandler=} opt_eventHandler Event handler to add
+ * listener to.
+ * @override
+ */
+goog.events.ActionEventWrapper_.prototype.listen = function(target, listener,
+ opt_capt, opt_scope, opt_eventHandler) {
+ var callback = function(e) {
+ var listenerFn = goog.events.wrapListener(listener);
+ var role = goog.dom.isElement(e.target) ?
+ goog.a11y.aria.getRole(/** @type {!Element} */ (e.target)) : null;
+ if (e.type == goog.events.EventType.CLICK && e.isMouseActionButton()) {
+ listenerFn.call(opt_scope, e);
+ } else if ((e.keyCode == goog.events.KeyCodes.ENTER ||
+ e.keyCode == goog.events.KeyCodes.MAC_ENTER) &&
+ e.type != goog.events.EventType.KEYUP) {
+ // convert keydown to keypress for backward compatibility.
+ e.type = goog.events.EventType.KEYPRESS;
+ listenerFn.call(opt_scope, e);
+ } else if (e.keyCode == goog.events.KeyCodes.SPACE &&
+ e.type == goog.events.EventType.KEYUP &&
+ (role == goog.a11y.aria.Role.BUTTON ||
+ role == goog.a11y.aria.Role.TAB)) {
+ listenerFn.call(opt_scope, e);
+ e.preventDefault();
+ }
+ };
+ callback.listener_ = listener;
+ callback.scope_ = opt_scope;
+
+ if (opt_eventHandler) {
+ opt_eventHandler.listen(target,
+ goog.events.ActionEventWrapper_.EVENT_TYPES_,
+ callback, opt_capt);
+ } else {
+ goog.events.listen(target,
+ goog.events.ActionEventWrapper_.EVENT_TYPES_,
+ callback, opt_capt);
+ }
+};
+
+
+/**
+ * Removes an event listener added using goog.events.EventWrapper.listen.
+ *
+ * @param {goog.events.ListenableType} target The node to remove listener from.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
+ * method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @param {goog.events.EventHandler=} opt_eventHandler Event handler to remove
+ * listener from.
+ * @override
+ */
+goog.events.ActionEventWrapper_.prototype.unlisten = function(target, listener,
+ opt_capt, opt_scope, opt_eventHandler) {
+ for (var type, j = 0; type = goog.events.ActionEventWrapper_.EVENT_TYPES_[j];
+ j++) {
+ var listeners = goog.events.getListeners(target, type, !!opt_capt);
+ for (var obj, i = 0; obj = listeners[i]; i++) {
+ if (obj.listener.listener_ == listener &&
+ obj.listener.scope_ == opt_scope) {
+ if (opt_eventHandler) {
+ opt_eventHandler.unlisten(target, type, obj.listener, opt_capt,
+ opt_scope);
+ } else {
+ goog.events.unlisten(target, type, obj.listener, opt_capt, opt_scope);
+ }
+ break;
+ }
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/actionhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/actionhandler.js b/externs/GCL/externs/goog/events/actionhandler.js
new file mode 100644
index 0000000..190cc26
--- /dev/null
+++ b/externs/GCL/externs/goog/events/actionhandler.js
@@ -0,0 +1,184 @@
+// 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 This file contains a class to provide a unified mechanism for
+ * CLICK and enter KEYDOWN events. This provides better accessibility by
+ * providing the given functionality to a keyboard user which is otherwise
+ * would be available only via a mouse click.
+ *
+ * If there is an existing CLICK listener or planning to be added as below -
+ *
+ * <code>this.eventHandler_.listen(el, CLICK, this.onClick_);<code>
+ *
+ * it can be replaced with an ACTION listener as follows:
+ *
+ * <code>this.eventHandler_.listen(
+ * new goog.events.ActionHandler(el),
+ * ACTION,
+ * this.onAction_);<code>
+ *
+ */
+
+goog.provide('goog.events.ActionEvent');
+goog.provide('goog.events.ActionHandler');
+goog.provide('goog.events.ActionHandler.EventType');
+goog.provide('goog.events.BeforeActionEvent');
+
+goog.require('goog.events');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A wrapper around an element that you want to listen to ACTION events on.
+ * @param {Element|Document} element The element or document to listen on.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.events.ActionHandler = function(element) {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * This is the element that we will listen to events on.
+ * @type {Element|Document}
+ * @private
+ */
+ this.element_ = element;
+
+ goog.events.listen(element, goog.events.ActionHandler.KEY_EVENT_TYPE_,
+ this.handleKeyDown_, false, this);
+ goog.events.listen(element, goog.events.EventType.CLICK,
+ this.handleClick_, false, this);
+};
+goog.inherits(goog.events.ActionHandler, goog.events.EventTarget);
+
+
+/**
+ * Enum type for the events fired by the action handler
+ * @enum {string}
+ */
+goog.events.ActionHandler.EventType = {
+ ACTION: 'action',
+ BEFOREACTION: 'beforeaction'
+};
+
+
+/**
+ * Key event type to listen for.
+ * @type {string}
+ * @private
+ */
+goog.events.ActionHandler.KEY_EVENT_TYPE_ = goog.userAgent.GECKO ?
+ goog.events.EventType.KEYPRESS :
+ goog.events.EventType.KEYDOWN;
+
+
+/**
+ * Handles key press events.
+ * @param {!goog.events.BrowserEvent} e The key press event.
+ * @private
+ */
+goog.events.ActionHandler.prototype.handleKeyDown_ = function(e) {
+ if (e.keyCode == goog.events.KeyCodes.ENTER ||
+ goog.userAgent.WEBKIT && e.keyCode == goog.events.KeyCodes.MAC_ENTER) {
+ this.dispatchEvents_(e);
+ }
+};
+
+
+/**
+ * Handles mouse events.
+ * @param {!goog.events.BrowserEvent} e The click event.
+ * @private
+ */
+goog.events.ActionHandler.prototype.handleClick_ = function(e) {
+ this.dispatchEvents_(e);
+};
+
+
+/**
+ * Dispatches BeforeAction and Action events to the element
+ * @param {!goog.events.BrowserEvent} e The event causing dispatches.
+ * @private
+ */
+goog.events.ActionHandler.prototype.dispatchEvents_ = function(e) {
+ var beforeActionEvent = new goog.events.BeforeActionEvent(e);
+
+ // Allow application specific logic here before the ACTION event.
+ // For example, Gmail uses this event to restore keyboard focus
+ if (!this.dispatchEvent(beforeActionEvent)) {
+ // If the listener swallowed the BEFOREACTION event, don't dispatch the
+ // ACTION event.
+ return;
+ }
+
+
+ // Wrap up original event and send it off
+ var actionEvent = new goog.events.ActionEvent(e);
+ try {
+ this.dispatchEvent(actionEvent);
+ } finally {
+ // Stop propagating the event
+ e.stopPropagation();
+ }
+};
+
+
+/** @override */
+goog.events.ActionHandler.prototype.disposeInternal = function() {
+ goog.events.ActionHandler.superClass_.disposeInternal.call(this);
+ goog.events.unlisten(this.element_, goog.events.ActionHandler.KEY_EVENT_TYPE_,
+ this.handleKeyDown_, false, this);
+ goog.events.unlisten(this.element_, goog.events.EventType.CLICK,
+ this.handleClick_, false, this);
+ delete this.element_;
+};
+
+
+
+/**
+ * This class is used for the goog.events.ActionHandler.EventType.ACTION event.
+ * @param {!goog.events.BrowserEvent} browserEvent Browser event object.
+ * @constructor
+ * @extends {goog.events.BrowserEvent}
+ * @final
+ */
+goog.events.ActionEvent = function(browserEvent) {
+ goog.events.BrowserEvent.call(this, browserEvent.getBrowserEvent());
+ this.type = goog.events.ActionHandler.EventType.ACTION;
+};
+goog.inherits(goog.events.ActionEvent, goog.events.BrowserEvent);
+
+
+
+/**
+ * This class is used for the goog.events.ActionHandler.EventType.BEFOREACTION
+ * event. BEFOREACTION gives a chance to the application so the keyboard focus
+ * can be restored back, if required.
+ * @param {!goog.events.BrowserEvent} browserEvent Browser event object.
+ * @constructor
+ * @extends {goog.events.BrowserEvent}
+ * @final
+ */
+goog.events.BeforeActionEvent = function(browserEvent) {
+ goog.events.BrowserEvent.call(this, browserEvent.getBrowserEvent());
+ this.type = goog.events.ActionHandler.EventType.BEFOREACTION;
+};
+goog.inherits(goog.events.BeforeActionEvent, goog.events.BrowserEvent);
[36/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/logrecordserializer.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/logrecordserializer.js b/externs/GCL/externs/goog/debug/logrecordserializer.js
new file mode 100644
index 0000000..9b09d56
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/logrecordserializer.js
@@ -0,0 +1,121 @@
+// 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 Static methods for serializing and deserializing log
+ * messages. These methods are deliberately kept separate from logrecord.js
+ * and logger.js because they add dependencies on goog.json and goog.object.
+ *
+ */
+
+goog.provide('goog.debug.logRecordSerializer');
+
+goog.require('goog.debug.LogRecord');
+goog.require('goog.debug.Logger');
+goog.require('goog.json');
+goog.require('goog.object');
+
+
+/**
+ * Enumeration of object keys used when serializing a log message.
+ * @enum {string}
+ * @private
+ */
+goog.debug.logRecordSerializer.Param_ = {
+ TIME: 't',
+ LEVEL_NAME: 'ln',
+ LEVEL_VALUE: 'lv',
+ MSG: 'm',
+ LOGGER_NAME: 'n',
+ SEQUENCE_NUMBER: 's',
+ EXCEPTION: 'e'
+};
+
+
+/**
+ * Serializes a LogRecord to a JSON string. Note that any associated
+ * exception is likely to be lost.
+ * @param {goog.debug.LogRecord} record The record to serialize.
+ * @return {string} Serialized JSON string of the log message.
+ */
+goog.debug.logRecordSerializer.serialize = function(record) {
+ var param = goog.debug.logRecordSerializer.Param_;
+ return goog.json.serialize(goog.object.create(
+ param.TIME, record.getMillis(),
+ param.LEVEL_NAME, record.getLevel().name,
+ param.LEVEL_VALUE, record.getLevel().value,
+ param.MSG, record.getMessage(),
+ param.LOGGER_NAME, record.getLoggerName(),
+ param.SEQUENCE_NUMBER, record.getSequenceNumber(),
+ param.EXCEPTION, record.getException() && record.getException().message));
+};
+
+
+/**
+ * Deserializes a JSON-serialized LogRecord.
+ * @param {string} s The JSON serialized record.
+ * @return {!goog.debug.LogRecord} The deserialized record.
+ */
+goog.debug.logRecordSerializer.parse = function(s) {
+ return goog.debug.logRecordSerializer.reconstitute_(goog.json.parse(s));
+};
+
+
+/**
+ * Deserializes a JSON-serialized LogRecord. Use this only if you're
+ * naive enough to blindly trust any JSON formatted input that comes
+ * your way.
+ * @param {string} s The JSON serialized record.
+ * @return {!goog.debug.LogRecord} The deserialized record.
+ */
+goog.debug.logRecordSerializer.unsafeParse = function(s) {
+ return goog.debug.logRecordSerializer.reconstitute_(goog.json.unsafeParse(s));
+};
+
+
+/**
+ * Common reconsitution method for for parse and unsafeParse.
+ * @param {Object} o The JSON object.
+ * @return {!goog.debug.LogRecord} The reconstituted record.
+ * @private
+ */
+goog.debug.logRecordSerializer.reconstitute_ = function(o) {
+ var param = goog.debug.logRecordSerializer.Param_;
+ var level = goog.debug.logRecordSerializer.getLevel_(
+ o[param.LEVEL_NAME], o[param.LEVEL_VALUE]);
+
+ var ret = new goog.debug.LogRecord(level, o[param.MSG],
+ o[param.LOGGER_NAME], o[param.TIME], o[param.SEQUENCE_NUMBER]);
+ var exceptionMessage = o[param.EXCEPTION];
+ if (goog.isDefAndNotNull(exceptionMessage)) {
+ ret.setException(new Error(exceptionMessage));
+ }
+ return ret;
+};
+
+
+/**
+ * @param {string} name The name of the log level to return.
+ * @param {number} value The numeric value of the log level to return.
+ * @return {!goog.debug.Logger.Level} Returns a goog.debug.Logger.Level with
+ * the specified name and value. If the name and value match a predefined
+ * log level, that instance will be returned, otherwise a new one will be
+ * created.
+ * @private
+ */
+goog.debug.logRecordSerializer.getLevel_ = function(name, value) {
+ var level = goog.debug.Logger.Level.getPredefinedLevel(name);
+ return level && level.value == value ?
+ level : new goog.debug.Logger.Level(name, value);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/relativetimeprovider.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/relativetimeprovider.js b/externs/GCL/externs/goog/debug/relativetimeprovider.js
new file mode 100644
index 0000000..1201147
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/relativetimeprovider.js
@@ -0,0 +1,84 @@
+// 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 the goog.debug.RelativeTimeProvider class.
+ *
+ */
+
+goog.provide('goog.debug.RelativeTimeProvider');
+
+
+
+/**
+ * A simple object to keep track of a timestamp considered the start of
+ * something. The main use is for the logger system to maintain a start time
+ * that is occasionally reset. For example, in Gmail, we reset this relative
+ * time at the start of a user action so that timings are offset from the
+ * beginning of the action. This class also provides a singleton as the default
+ * behavior for most use cases is to share the same start time.
+ *
+ * @constructor
+ * @final
+ */
+goog.debug.RelativeTimeProvider = function() {
+ /**
+ * The start time.
+ * @type {number}
+ * @private
+ */
+ this.relativeTimeStart_ = goog.now();
+};
+
+
+/**
+ * Default instance.
+ * @type {goog.debug.RelativeTimeProvider}
+ * @private
+ */
+goog.debug.RelativeTimeProvider.defaultInstance_ =
+ new goog.debug.RelativeTimeProvider();
+
+
+/**
+ * Sets the start time to the specified time.
+ * @param {number} timeStamp The start time.
+ */
+goog.debug.RelativeTimeProvider.prototype.set = function(timeStamp) {
+ this.relativeTimeStart_ = timeStamp;
+};
+
+
+/**
+ * Resets the start time to now.
+ */
+goog.debug.RelativeTimeProvider.prototype.reset = function() {
+ this.set(goog.now());
+};
+
+
+/**
+ * @return {number} The start time.
+ */
+goog.debug.RelativeTimeProvider.prototype.get = function() {
+ return this.relativeTimeStart_;
+};
+
+
+/**
+ * @return {goog.debug.RelativeTimeProvider} The default instance.
+ */
+goog.debug.RelativeTimeProvider.getDefaultInstance = function() {
+ return goog.debug.RelativeTimeProvider.defaultInstance_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/tracer.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/tracer.js b/externs/GCL/externs/goog/debug/tracer.js
new file mode 100644
index 0000000..b56a324
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/tracer.js
@@ -0,0 +1,725 @@
+// 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 Definition of the Tracer class and associated classes.
+ *
+ * @see ../demos/tracer.html
+ */
+
+goog.provide('goog.debug.Trace');
+
+goog.require('goog.array');
+goog.require('goog.debug.Logger');
+goog.require('goog.iter');
+goog.require('goog.log');
+goog.require('goog.structs.Map');
+goog.require('goog.structs.SimplePool');
+
+
+
+/**
+ * Class used for singleton goog.debug.Trace. Used for timing slow points in
+ * the code. Based on the java Tracer class but optimized for javascript.
+ * See com.google.common.tracing.Tracer.
+ * @constructor
+ * @private
+ */
+goog.debug.Trace_ = function() {
+
+ /**
+ * Events in order.
+ * @type {Array<goog.debug.Trace_.Event_>}
+ * @private
+ */
+ this.events_ = [];
+
+ /**
+ * Outstanding events that have started but haven't yet ended. The keys are
+ * numeric ids and the values are goog.debug.Trace_.Event_ objects.
+ * @type {goog.structs.Map}
+ * @private
+ */
+ this.outstandingEvents_ = new goog.structs.Map();
+
+ /**
+ * Start time of the event trace
+ * @type {number}
+ * @private
+ */
+ this.startTime_ = 0;
+
+ /**
+ * Cummulative overhead of calls to startTracer
+ * @type {number}
+ * @private
+ */
+ this.tracerOverheadStart_ = 0;
+
+ /**
+ * Cummulative overhead of calls to endTracer
+ * @type {number}
+ * @private
+ */
+ this.tracerOverheadEnd_ = 0;
+
+ /**
+ * Cummulative overhead of calls to addComment
+ * @type {number}
+ * @private
+ */
+ this.tracerOverheadComment_ = 0;
+
+ /**
+ * Keeps stats on different types of tracers. The keys are strings and the
+ * values are goog.debug.Stat
+ * @type {goog.structs.Map}
+ * @private
+ */
+ this.stats_ = new goog.structs.Map();
+
+ /**
+ * Total number of traces created in the trace.
+ * @type {number}
+ * @private
+ */
+ this.tracerCount_ = 0;
+
+ /**
+ * Total number of comments created in the trace.
+ * @type {number}
+ * @private
+ */
+ this.commentCount_ = 0;
+
+ /**
+ * Next id to use for the trace.
+ * @type {number}
+ * @private
+ */
+ this.nextId_ = 1;
+
+ /**
+ * A pool for goog.debug.Trace_.Event_ objects so we don't keep creating and
+ * garbage collecting these (which is very expensive in IE6).
+ * @private {!goog.structs.SimplePool}
+ */
+ this.eventPool_ = new goog.structs.SimplePool(0, 4000);
+ this.eventPool_.createObject = function() {
+ return new goog.debug.Trace_.Event_();
+ };
+
+
+ /**
+ * A pool for goog.debug.Trace_.Stat_ objects so we don't keep creating and
+ * garbage collecting these (which is very expensive in IE6).
+ * @private {!goog.structs.SimplePool}
+ */
+ this.statPool_ = new goog.structs.SimplePool(0, 50);
+ this.statPool_.createObject = function() {
+ return new goog.debug.Trace_.Stat_();
+ };
+
+ var self = this;
+
+ /** @private {!goog.structs.SimplePool} */
+ this.idPool_ = new goog.structs.SimplePool(0, 2000);
+
+ // TODO(nicksantos): SimplePool is supposed to only return objects.
+ // Reconcile this so that we don't have to cast to number below.
+ this.idPool_.createObject = function() {
+ return String(self.nextId_++);
+ };
+ this.idPool_.disposeObject = function(obj) {};
+
+ /**
+ * Default threshold below which a tracer shouldn't be reported
+ * @type {number}
+ * @private
+ */
+ this.defaultThreshold_ = 3;
+};
+
+
+/**
+ * Logger for the tracer
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.debug.Trace_.prototype.logger_ =
+ goog.log.getLogger('goog.debug.Trace');
+
+
+/**
+ * Maximum size of the trace before we discard events
+ * @type {number}
+ */
+goog.debug.Trace_.prototype.MAX_TRACE_SIZE = 1000;
+
+
+/**
+ * Event type supported by tracer
+ * @enum {number}
+ */
+goog.debug.Trace_.EventType = {
+ /**
+ * Start event type
+ */
+ START: 0,
+
+ /**
+ * Stop event type
+ */
+ STOP: 1,
+
+ /**
+ * Comment event type
+ */
+ COMMENT: 2
+};
+
+
+
+/**
+ * Class to keep track of a stat of a single tracer type. Stores the count
+ * and cumulative time.
+ * @constructor
+ * @private
+ */
+goog.debug.Trace_.Stat_ = function() {
+ /**
+ * Number of tracers
+ * @type {number}
+ */
+ this.count = 0;
+
+ /**
+ * Cumulative time of traces
+ * @type {number}
+ */
+ this.time = 0;
+
+ /**
+ * Total number of allocations for this tracer type
+ * @type {number}
+ */
+ this.varAlloc = 0;
+};
+
+
+/**
+ * @type {string|null|undefined}
+ */
+goog.debug.Trace_.Stat_.prototype.type;
+
+
+/**
+ * @return {string} A string describing the tracer stat.
+ * @override
+ */
+goog.debug.Trace_.Stat_.prototype.toString = function() {
+ var sb = [];
+ sb.push(this.type, ' ', this.count, ' (', Math.round(this.time * 10) / 10,
+ ' ms)');
+ if (this.varAlloc) {
+ sb.push(' [VarAlloc = ', this.varAlloc, ']');
+ }
+ return sb.join('');
+};
+
+
+
+/**
+ * Private class used to encapsulate a single event, either the start or stop
+ * of a tracer.
+ * @constructor
+ * @private
+ */
+goog.debug.Trace_.Event_ = function() {
+ // the fields are different for different events - see usage in code
+};
+
+
+/**
+ * @type {string|null|undefined}
+ */
+goog.debug.Trace_.Event_.prototype.type;
+
+
+/**
+ * Returns a formatted string for the event.
+ * @param {number} startTime The start time of the trace to generate relative
+ * times.
+ * @param {number} prevTime The completion time of the previous event or -1.
+ * @param {string} indent Extra indent for the message
+ * if there was no previous event.
+ * @return {string} The formatted tracer string.
+ */
+goog.debug.Trace_.Event_.prototype.toTraceString = function(startTime, prevTime,
+ indent) {
+ var sb = [];
+
+ if (prevTime == -1) {
+ sb.push(' ');
+ } else {
+ sb.push(goog.debug.Trace_.longToPaddedString_(this.eventTime - prevTime));
+ }
+
+ sb.push(' ', goog.debug.Trace_.formatTime_(this.eventTime - startTime));
+ if (this.eventType == goog.debug.Trace_.EventType.START) {
+ sb.push(' Start ');
+ } else if (this.eventType == goog.debug.Trace_.EventType.STOP) {
+ sb.push(' Done ');
+ var delta = this.stopTime - this.startTime;
+ sb.push(goog.debug.Trace_.longToPaddedString_(delta), ' ms ');
+ } else {
+ sb.push(' Comment ');
+ }
+
+ sb.push(indent, this);
+ if (this.totalVarAlloc > 0) {
+ sb.push('[VarAlloc ', this.totalVarAlloc, '] ');
+ }
+ return sb.join('');
+};
+
+
+/**
+ * @return {string} A string describing the tracer event.
+ * @override
+ */
+goog.debug.Trace_.Event_.prototype.toString = function() {
+ if (this.type == null) {
+ return this.comment;
+ } else {
+ return '[' + this.type + '] ' + this.comment;
+ }
+};
+
+
+/**
+ * Add the ability to explicitly set the start time. This is useful for example
+ * for measuring initial load time where you can set a variable as soon as the
+ * main page of the app is loaded and then later call this function when the
+ * Tracer code has been loaded.
+ * @param {number} startTime The start time to set.
+ */
+goog.debug.Trace_.prototype.setStartTime = function(startTime) {
+ this.startTime_ = startTime;
+};
+
+
+/**
+ * Initializes and resets the current trace
+ * @param {number} defaultThreshold The default threshold below which the
+ * tracer output will be supressed. Can be overridden on a per-Tracer basis.
+ */
+goog.debug.Trace_.prototype.initCurrentTrace = function(defaultThreshold) {
+ this.reset(defaultThreshold);
+};
+
+
+/**
+ * Clears the current trace
+ */
+goog.debug.Trace_.prototype.clearCurrentTrace = function() {
+ this.reset(0);
+};
+
+
+/**
+ * Resets the trace.
+ * @param {number} defaultThreshold The default threshold below which the
+ * tracer output will be supressed. Can be overridden on a per-Tracer basis.
+ */
+goog.debug.Trace_.prototype.reset = function(defaultThreshold) {
+ this.defaultThreshold_ = defaultThreshold;
+
+ for (var i = 0; i < this.events_.length; i++) {
+ var id = /** @type {Object} */ (this.eventPool_).id;
+ if (id) {
+ this.idPool_.releaseObject(id);
+ }
+ this.eventPool_.releaseObject(this.events_[i]);
+ }
+
+ this.events_.length = 0;
+ this.outstandingEvents_.clear();
+ this.startTime_ = goog.debug.Trace_.now();
+ this.tracerOverheadStart_ = 0;
+ this.tracerOverheadEnd_ = 0;
+ this.tracerOverheadComment_ = 0;
+ this.tracerCount_ = 0;
+ this.commentCount_ = 0;
+
+ var keys = this.stats_.getKeys();
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ var stat = this.stats_.get(key);
+ stat.count = 0;
+ stat.time = 0;
+ stat.varAlloc = 0;
+ this.statPool_.releaseObject(/** @type {Object} */ (stat));
+ }
+ this.stats_.clear();
+};
+
+
+/**
+ * Starts a tracer
+ * @param {string} comment A comment used to identify the tracer. Does not
+ * need to be unique.
+ * @param {string=} opt_type Type used to identify the tracer. If a Trace is
+ * given a type (the first argument to the constructor) and multiple Traces
+ * are done on that type then a "TOTAL line will be produced showing the
+ * total number of traces and the sum of the time
+ * ("TOTAL Database 2 (37 ms)" in our example). These traces should be
+ * mutually exclusive or else the sum won't make sense (the time will
+ * be double counted if the second starts before the first ends).
+ * @return {number} The identifier for the tracer that should be passed to the
+ * the stopTracer method.
+ */
+goog.debug.Trace_.prototype.startTracer = function(comment, opt_type) {
+ var tracerStartTime = goog.debug.Trace_.now();
+ var varAlloc = this.getTotalVarAlloc();
+ var outstandingEventCount = this.outstandingEvents_.getCount();
+ if (this.events_.length + outstandingEventCount > this.MAX_TRACE_SIZE) {
+ goog.log.warning(this.logger_,
+ 'Giant thread trace. Clearing to avoid memory leak.');
+ // This is the more likely case. This usually means that we
+ // either forgot to clear the trace or else we are performing a
+ // very large number of events
+ if (this.events_.length > this.MAX_TRACE_SIZE / 2) {
+ for (var i = 0; i < this.events_.length; i++) {
+ var event = this.events_[i];
+ if (event.id) {
+ this.idPool_.releaseObject(event.id);
+ }
+ this.eventPool_.releaseObject(event);
+ }
+ this.events_.length = 0;
+ }
+
+ // This is less likely and probably indicates that a lot of traces
+ // aren't being closed. We want to avoid unnecessarily clearing
+ // this though in case the events do eventually finish.
+ if (outstandingEventCount > this.MAX_TRACE_SIZE / 2) {
+ this.outstandingEvents_.clear();
+ }
+ }
+
+ goog.debug.Logger.logToProfilers('Start : ' + comment);
+
+ var event = /** @type {goog.debug.Trace_.Event_} */ (
+ this.eventPool_.getObject());
+ event.totalVarAlloc = varAlloc;
+ event.eventType = goog.debug.Trace_.EventType.START;
+ event.id = Number(this.idPool_.getObject());
+ event.comment = comment;
+ event.type = opt_type;
+ this.events_.push(event);
+ this.outstandingEvents_.set(String(event.id), event);
+ this.tracerCount_++;
+ var now = goog.debug.Trace_.now();
+ event.startTime = event.eventTime = now;
+ this.tracerOverheadStart_ += now - tracerStartTime;
+ return event.id;
+};
+
+
+/**
+ * Stops a tracer
+ * @param {number|undefined|null} id The id of the tracer that is ending.
+ * @param {number=} opt_silenceThreshold Threshold below which the tracer is
+ * silenced.
+ * @return {?number} The elapsed time for the tracer or null if the tracer
+ * identitifer was not recognized.
+ */
+goog.debug.Trace_.prototype.stopTracer = function(id, opt_silenceThreshold) {
+ // this used to call goog.isDef(opt_silenceThreshold) but that causes an
+ // object allocation in IE for some reason (doh!). The following code doesn't
+ // cause an allocation
+ var now = goog.debug.Trace_.now();
+ var silenceThreshold;
+ if (opt_silenceThreshold === 0) {
+ silenceThreshold = 0;
+ } else if (opt_silenceThreshold) {
+ silenceThreshold = opt_silenceThreshold;
+ } else {
+ silenceThreshold = this.defaultThreshold_;
+ }
+
+ var startEvent = this.outstandingEvents_.get(String(id));
+ if (startEvent == null) {
+ return null;
+ }
+
+ this.outstandingEvents_.remove(String(id));
+
+ var stopEvent;
+ var elapsed = now - startEvent.startTime;
+ if (elapsed < silenceThreshold) {
+ var count = this.events_.length;
+ for (var i = count - 1; i >= 0; i--) {
+ var nextEvent = this.events_[i];
+ if (nextEvent == startEvent) {
+ this.events_.splice(i, 1);
+ this.idPool_.releaseObject(startEvent.id);
+ this.eventPool_.releaseObject(/** @type {Object} */ (startEvent));
+ break;
+ }
+ }
+
+ } else {
+ stopEvent = /** @type {goog.debug.Trace_.Event_} */ (
+ this.eventPool_.getObject());
+ stopEvent.eventType = goog.debug.Trace_.EventType.STOP;
+ stopEvent.startTime = startEvent.startTime;
+ stopEvent.comment = startEvent.comment;
+ stopEvent.type = startEvent.type;
+ stopEvent.stopTime = stopEvent.eventTime = now;
+
+ this.events_.push(stopEvent);
+ }
+
+ var type = startEvent.type;
+ var stat = null;
+ if (type) {
+ stat = this.getStat_(type);
+ stat.count++;
+ stat.time += elapsed;
+ }
+ if (stopEvent) {
+ goog.debug.Logger.logToProfilers('Stop : ' + stopEvent.comment);
+
+ stopEvent.totalVarAlloc = this.getTotalVarAlloc();
+
+ if (stat) {
+ stat.varAlloc += (stopEvent.totalVarAlloc - startEvent.totalVarAlloc);
+ }
+ }
+ var tracerFinishTime = goog.debug.Trace_.now();
+ this.tracerOverheadEnd_ += tracerFinishTime - now;
+ return elapsed;
+};
+
+
+/**
+ * Sets the ActiveX object that can be used to get GC tracing in IE6.
+ * @param {Object} gcTracer GCTracer ActiveX object.
+ */
+goog.debug.Trace_.prototype.setGcTracer = function(gcTracer) {
+ this.gcTracer_ = gcTracer;
+};
+
+
+/**
+ * Returns the total number of allocations since the GC stats were reset. Only
+ * works in IE.
+ * @return {number} The number of allocaitons or -1 if not supported.
+ */
+goog.debug.Trace_.prototype.getTotalVarAlloc = function() {
+ var gcTracer = this.gcTracer_;
+ // isTracing is defined on the ActiveX object.
+ if (gcTracer && gcTracer['isTracing']()) {
+ return gcTracer['totalVarAlloc'];
+ }
+ return -1;
+};
+
+
+/**
+ * Adds a comment to the trace. Makes it possible to see when a specific event
+ * happened in relation to the traces.
+ * @param {string} comment A comment that is inserted into the trace.
+ * @param {?string=} opt_type Type used to identify the tracer. If a comment is
+ * given a type and multiple comments are done on that type then a "TOTAL
+ * line will be produced showing the total number of comments of that type.
+ * @param {?number=} opt_timeStamp The timestamp to insert the comment. If not
+ * specified, the current time wil be used.
+ */
+goog.debug.Trace_.prototype.addComment = function(comment, opt_type,
+ opt_timeStamp) {
+ var now = goog.debug.Trace_.now();
+ var timeStamp = opt_timeStamp ? opt_timeStamp : now;
+
+ var eventComment = /** @type {goog.debug.Trace_.Event_} */ (
+ this.eventPool_.getObject());
+ eventComment.eventType = goog.debug.Trace_.EventType.COMMENT;
+ eventComment.eventTime = timeStamp;
+ eventComment.type = opt_type;
+ eventComment.comment = comment;
+ eventComment.totalVarAlloc = this.getTotalVarAlloc();
+ this.commentCount_++;
+
+ if (opt_timeStamp) {
+ var numEvents = this.events_.length;
+ for (var i = 0; i < numEvents; i++) {
+ var event = this.events_[i];
+ var eventTime = event.eventTime;
+
+ if (eventTime > timeStamp) {
+ goog.array.insertAt(this.events_, eventComment, i);
+ break;
+ }
+ }
+ if (i == numEvents) {
+ this.events_.push(eventComment);
+ }
+ } else {
+ this.events_.push(eventComment);
+ }
+
+ var type = eventComment.type;
+ if (type) {
+ var stat = this.getStat_(type);
+ stat.count++;
+ }
+
+ this.tracerOverheadComment_ += goog.debug.Trace_.now() - now;
+};
+
+
+/**
+ * Gets a stat object for a particular type. The stat object is created if it
+ * hasn't yet been.
+ * @param {string} type The type of stat.
+ * @return {goog.debug.Trace_.Stat_} The stat object.
+ * @private
+ */
+goog.debug.Trace_.prototype.getStat_ = function(type) {
+ var stat = this.stats_.get(type);
+ if (!stat) {
+ stat = /** @type {goog.debug.Trace_.Event_} */ (
+ this.statPool_.getObject());
+ stat.type = type;
+ this.stats_.set(type, stat);
+ }
+ return /** @type {goog.debug.Trace_.Stat_} */(stat);
+};
+
+
+/**
+ * Returns a formatted string for the current trace
+ * @return {string} A formatted string that shows the timings of the current
+ * trace.
+ */
+goog.debug.Trace_.prototype.getFormattedTrace = function() {
+ return this.toString();
+};
+
+
+/**
+ * Returns a formatted string that describes the thread trace.
+ * @return {string} A formatted string.
+ * @override
+ */
+goog.debug.Trace_.prototype.toString = function() {
+ var sb = [];
+ var etime = -1;
+ var indent = [];
+ for (var i = 0; i < this.events_.length; i++) {
+ var e = this.events_[i];
+ if (e.eventType == goog.debug.Trace_.EventType.STOP) {
+ indent.pop();
+ }
+ sb.push(' ', e.toTraceString(this.startTime_, etime, indent.join('')));
+ etime = e.eventTime;
+ sb.push('\n');
+ if (e.eventType == goog.debug.Trace_.EventType.START) {
+ indent.push('| ');
+ }
+ }
+
+ if (this.outstandingEvents_.getCount() != 0) {
+ var now = goog.debug.Trace_.now();
+
+ sb.push(' Unstopped timers:\n');
+ goog.iter.forEach(this.outstandingEvents_, function(startEvent) {
+ sb.push(' ', startEvent, ' (', now - startEvent.startTime,
+ ' ms, started at ',
+ goog.debug.Trace_.formatTime_(startEvent.startTime),
+ ')\n');
+ });
+ }
+
+ var statKeys = this.stats_.getKeys();
+ for (var i = 0; i < statKeys.length; i++) {
+ var stat = this.stats_.get(statKeys[i]);
+ if (stat.count > 1) {
+ sb.push(' TOTAL ', stat, '\n');
+ }
+ }
+
+ sb.push('Total tracers created ', this.tracerCount_, '\n',
+ 'Total comments created ', this.commentCount_, '\n',
+ 'Overhead start: ', this.tracerOverheadStart_, ' ms\n',
+ 'Overhead end: ', this.tracerOverheadEnd_, ' ms\n',
+ 'Overhead comment: ', this.tracerOverheadComment_, ' ms\n');
+
+ return sb.join('');
+};
+
+
+/**
+ * Converts 'v' to a string and pads it with up to 3 spaces for
+ * improved alignment. TODO there must be a better way
+ * @param {number} v A number.
+ * @return {string} A padded string.
+ * @private
+ */
+goog.debug.Trace_.longToPaddedString_ = function(v) {
+ v = Math.round(v);
+ // todo (pupius) - there should be a generic string in goog.string for this
+ var space = '';
+ if (v < 1000) space = ' ';
+ if (v < 100) space = ' ';
+ if (v < 10) space = ' ';
+ return space + v;
+};
+
+
+/**
+ * Return the sec.ms part of time (if time = "20:06:11.566", "11.566
+ * @param {number} time The time in MS.
+ * @return {string} A formatted string as sec.ms'.
+ * @private
+ */
+goog.debug.Trace_.formatTime_ = function(time) {
+ time = Math.round(time);
+ var sec = (time / 1000) % 60;
+ var ms = time % 1000;
+
+ // TODO their must be a nicer way to get zero padded integers
+ return String(100 + sec).substring(1, 3) + '.' +
+ String(1000 + ms).substring(1, 4);
+};
+
+
+/**
+ * Returns the current time. Done through a wrapper function so it can be
+ * overridden by application code. Gmail has an ActiveX extension that provides
+ * higher precision timing info.
+ * @return {number} The current time in milliseconds.
+ */
+goog.debug.Trace_.now = function() {
+ return goog.now();
+};
+
+
+/**
+ * Singleton trace object
+ * @type {goog.debug.Trace_}
+ */
+goog.debug.Trace = new goog.debug.Trace_();
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/autocompleteremotedata.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/autocompleteremotedata.js b/externs/GCL/externs/goog/demos/autocompleteremotedata.js
new file mode 100644
index 0000000..ff55f67
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/autocompleteremotedata.js
@@ -0,0 +1,18 @@
+// 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.
+
+/** @nocompile */
+
+['Big Table', 'Googlebot', 'Instant Indexing', 'Mustang', 'Page Rank',
+ 'Proto Buffer']
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/autocompleterichremotedata.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/autocompleterichremotedata.js b/externs/GCL/externs/goog/demos/autocompleterichremotedata.js
new file mode 100644
index 0000000..0fad7db
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/autocompleterichremotedata.js
@@ -0,0 +1,33 @@
+// 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.
+
+/** @nocompile */
+
+[
+ ['apple',
+ {name: 'Fuji', url: 'http://www.google.com/images?q=fuji+apple'},
+ {name: 'Gala', url: 'http://www.google.com/images?q=gala+apple'},
+ {name: 'Golden Delicious',
+ url: 'http://www.google.com/images?q=golden delicious+apple'}
+ ],
+ ['citrus',
+ {name: 'Lemon', url: 'http://www.google.com/images?q=lemon+fruit'},
+ {name: 'Orange', url: 'http://www.google.com/images?q=orange+fruit'}
+ ],
+ ['berry',
+ {name: 'Strawberry', url: 'http://www.google.com/images?q=strawberry+fruit'},
+ {name: 'Blueberry', url: 'http://www.google.com/images?q=blueberry+fruit'},
+ {name: 'Blackberry', url: 'http://www.google.com/images?q=blackberry+fruit'}
+ ]
+]
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/css/demo.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/css/demo.css b/externs/GCL/externs/goog/demos/css/demo.css
new file mode 100644
index 0000000..6eb82e8
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/css/demo.css
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: attila@google.com (Attila Bodis) */
+
+
+@import url(../../css/common.css);
+
+
+body {
+ background-color: #ffe;
+ font: normal 10pt Arial, sans-serif;
+}
+
+
+/* Misc. styles used for logging and debugging. */
+fieldset {
+ padding: 4px 8px;
+ margin-bottom: 1em;
+}
+
+fieldset legend {
+ font-weight: bold;
+ color: #036;
+}
+
+label, input {
+ vertical-align: middle;
+}
+
+.hint {
+ font-size: 90%;
+ color: #369;
+}
+
+.goog-debug-panel {
+ border: 1px solid #369;
+}
+
+.goog-debug-panel .logdiv {
+ position: relative;
+ width: 100%;
+ height: 8em;
+ overflow: scroll;
+ overflow-x: hidden;
+ overflow-y: scroll;
+}
+
+.goog-debug-panel .logdiv .logmsg {
+ font: normal 10px "Lucida Sans Typewriter", "Courier New", Courier, fixed;
+}
+
+.perf {
+ margin: 0;
+ border: 0;
+ padding: 4px;
+ font: italic 95% Arial, sans-serif;
+ color: #999;
+}
+
+#perf {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ text-align: right;
+ margin: 0;
+ border: 0;
+ padding: 4px;
+ font: italic 95% Arial, sans-serif;
+ color: #999;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/css/emojipicker.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/css/emojipicker.css b/externs/GCL/externs/goog/demos/css/emojipicker.css
new file mode 100644
index 0000000..826d5bd
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/css/emojipicker.css
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: dalewis@google.com (Darren Lewis) */
+
+/* Styles used in the emojipicker demo */
+.goog-ui-popupemojipicker {
+ position: absolute;
+ -moz-outline: 0;
+ outline: 0;
+ visibility: hidden;
+}
+
+.goog-palette-cell {
+ padding: 2px;
+ background: white;
+}
+
+.goog-palette-cell div {
+ vertical-align: middle;
+ text-align: center;
+ margin: auto;
+}
+
+.goog-palette-cell-wrapper {
+ width: 25px;
+ height: 25px;
+}
+
+.goog-palette-cell-hover {
+ background: lightblue;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/css/emojisprite.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/css/emojisprite.css b/externs/GCL/externs/goog/demos/css/emojisprite.css
new file mode 100644
index 0000000..fe1a2cc
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/css/emojisprite.css
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* This file is autogenerated. To regenerate, do:
+cd google3/javascript/closure/demos/emoji
+/home/build/static/projects/sitespeed optisprite *.gif
+
+This will generate an optimal sprite in /usr/local/google/tmp/bestsprite.tar.gz.
+
+Rename the optimal sprite to "sprite.png" (from sprite_XX.png), rename the css
+to "sprite.css" (from sprite_XX.css), then change all the URLs in sprite.css to
+point to sprite.png in google3/javascript/closure/demos/emoji, and cp the
+sprite.png into that directory.
+*/
+
+.SPRITE_200{background:no-repeat url(../emoji/sprite.png) -18px 0;width:18px;height:18px}
+.SPRITE_201{background:no-repeat url(../emoji/sprite.png) 0 -234px;width:18px;height:18px}
+.SPRITE_202{background:no-repeat url(../emoji/sprite.png) -18px -338px;width:18px;height:18px}
+.SPRITE_203{background:no-repeat url(../emoji/sprite.png) -36px 0;width:18px;height:18px}
+.SPRITE_204{background:no-repeat url(../emoji/sprite.png) 0 -305px;width:18px;height:19px}
+.SPRITE_205{background:no-repeat url(../emoji/sprite.png) -36px -126px;width:18px;height:18px}
+.SPRITE_206{background:no-repeat url(../emoji/sprite.png) -36px -36px;width:18px;height:18px}
+.SPRITE_2BC{background:no-repeat url(../emoji/sprite.png) -18px -144px;width:18px;height:18px}
+.SPRITE_2BD{background:no-repeat url(../emoji/sprite.png) 0 -18px;width:18px;height:18px}
+.SPRITE_2BE{background:no-repeat url(../emoji/sprite.png) -36px -54px;width:18px;height:18px}
+.SPRITE_2BF{background:no-repeat url(../emoji/sprite.png) 0 -126px;width:18px;height:18px}
+.SPRITE_2C0{background:no-repeat url(../emoji/sprite.png) -18px -305px;width:18px;height:18px}
+.SPRITE_2C1{background:no-repeat url(../emoji/sprite.png) 0 -287px;width:18px;height:18px}
+.SPRITE_2C2{background:no-repeat url(../emoji/sprite.png) -18px -126px;width:18px;height:18px}
+.SPRITE_2C3{background:no-repeat url(../emoji/sprite.png) -36px -234px;width:18px;height:20px}
+.SPRITE_2C4{background:no-repeat url(../emoji/sprite.png) -36px -72px;width:18px;height:18px}
+.SPRITE_2C5{background:no-repeat url(../emoji/sprite.png) -54px -54px;width:18px;height:18px}
+.SPRITE_2C6{background:no-repeat url(../emoji/sprite.png) 0 -72px;width:18px;height:18px}
+.SPRITE_2C7{background:no-repeat url(../emoji/sprite.png) -18px -180px;width:18px;height:18px}
+.SPRITE_2C8{background:no-repeat url(../emoji/sprite.png) -36px -198px;width:18px;height:18px}
+.SPRITE_2C9{background:no-repeat url(../emoji/sprite.png) -36px -287px;width:18px;height:18px}
+.SPRITE_2CB{background:no-repeat url(../emoji/sprite.png) -54px -252px;width:18px;height:18px}
+.SPRITE_2CC{background:no-repeat url(../emoji/sprite.png) -54px -288px;width:18px;height:16px}
+.SPRITE_2CD{background:no-repeat url(../emoji/sprite.png) -36px -162px;width:18px;height:18px}
+.SPRITE_2CE{background:no-repeat url(../emoji/sprite.png) 0 -269px;width:18px;height:18px}
+.SPRITE_2CF{background:no-repeat url(../emoji/sprite.png) -36px -108px;width:18px;height:18px}
+.SPRITE_2D0{background:no-repeat url(../emoji/sprite.png) -36px -338px;width:18px;height:18px}
+.SPRITE_2D1{background:no-repeat url(../emoji/sprite.png) 0 -338px;width:18px;height:18px}
+.SPRITE_2D2{background:no-repeat url(../emoji/sprite.png) -54px -36px;width:18px;height:16px}
+.SPRITE_2D3{background:no-repeat url(../emoji/sprite.png) -36px -305px;width:18px;height:18px}
+.SPRITE_2D4{background:no-repeat url(../emoji/sprite.png) -36px -18px;width:18px;height:18px}
+.SPRITE_2D5{background:no-repeat url(../emoji/sprite.png) -18px -108px;width:18px;height:18px}
+.SPRITE_2D6{background:no-repeat url(../emoji/sprite.png) -36px -144px;width:18px;height:18px}
+.SPRITE_2D7{background:no-repeat url(../emoji/sprite.png) 0 -36px;width:18px;height:18px}
+.SPRITE_2D8{background:no-repeat url(../emoji/sprite.png) -54px -126px;width:18px;height:18px}
+.SPRITE_2D9{background:no-repeat url(../emoji/sprite.png) -18px -287px;width:18px;height:18px}
+.SPRITE_2DA{background:no-repeat url(../emoji/sprite.png) -54px -216px;width:18px;height:18px}
+.SPRITE_2DB{background:no-repeat url(../emoji/sprite.png) -36px -180px;width:18px;height:18px}
+.SPRITE_2DC{background:no-repeat url(../emoji/sprite.png) 0 -54px;width:18px;height:18px}
+.SPRITE_2DD{background:no-repeat url(../emoji/sprite.png) -18px -72px;width:18px;height:18px}
+.SPRITE_2DE{background:no-repeat url(../emoji/sprite.png) -36px -90px;width:18px;height:18px}
+.SPRITE_2DF{background:no-repeat url(../emoji/sprite.png) -54px -108px;width:18px;height:18px}
+.SPRITE_2E0{background:no-repeat url(../emoji/sprite.png) -18px -198px;width:18px;height:18px}
+.SPRITE_2E1{background:no-repeat url(../emoji/sprite.png) 0 -180px;width:18px;height:18px}
+.SPRITE_2E2{background:no-repeat url(../emoji/sprite.png) -54px -338px;width:18px;height:18px}
+.SPRITE_2E4{background:no-repeat url(../emoji/sprite.png) -54px -198px;width:18px;height:18px}
+.SPRITE_2E5{background:no-repeat url(../emoji/sprite.png) 0 -162px;width:18px;height:18px}
+.SPRITE_2E6{background:no-repeat url(../emoji/sprite.png) -54px -270px;width:18px;height:18px}
+.SPRITE_2E7{background:no-repeat url(../emoji/sprite.png) 0 -108px;width:18px;height:18px}
+.SPRITE_2E8{background:no-repeat url(../emoji/sprite.png) 0 -198px;width:18px;height:18px}
+.SPRITE_2E9{background:no-repeat url(../emoji/sprite.png) -54px 0;width:18px;height:18px}
+.SPRITE_2EA{background:no-repeat url(../emoji/sprite.png) -54px -144px;width:18px;height:18px}
+.SPRITE_2EB{background:no-repeat url(../emoji/sprite.png) -18px -36px;width:18px;height:18px}
+.SPRITE_2EC{background:no-repeat url(../emoji/sprite.png) -18px -18px;width:18px;height:18px}
+.SPRITE_2ED{background:no-repeat url(../emoji/sprite.png) -36px -269px;width:18px;height:18px}
+.SPRITE_2EE{background:no-repeat url(../emoji/sprite.png) -18px -90px;width:18px;height:18px}
+.SPRITE_2F0{background:no-repeat url(../emoji/sprite.png) 0 0;width:18px;height:18px}
+.SPRITE_2F2{background:no-repeat url(../emoji/sprite.png) -54px -234px;width:18px;height:18px}
+.SPRITE_2F3{background:no-repeat url(../emoji/sprite.png) 0 -144px;width:18px;height:18px}
+.SPRITE_2F4{background:no-repeat url(../emoji/sprite.png) 0 -252px;width:18px;height:17px}
+.SPRITE_2F5{background:no-repeat url(../emoji/sprite.png) -54px -321px;width:18px;height:14px}
+.SPRITE_2F6{background:no-repeat url(../emoji/sprite.png) -36px -254px;width:18px;height:15px}
+.SPRITE_2F7{background:no-repeat url(../emoji/sprite.png) -18px -54px;width:18px;height:18px}
+.SPRITE_2F8{background:no-repeat url(../emoji/sprite.png) 0 -216px;width:18px;height:18px}
+.SPRITE_2F9{background:no-repeat url(../emoji/sprite.png) -18px -234px;width:18px;height:18px}
+.SPRITE_2FA{background:no-repeat url(../emoji/sprite.png) -18px -216px;width:18px;height:18px}
+.SPRITE_2FB{background:no-repeat url(../emoji/sprite.png) -36px -216px;width:18px;height:18px}
+.SPRITE_2FC{background:no-repeat url(../emoji/sprite.png) -54px -162px;width:18px;height:18px}
+.SPRITE_2FD{background:no-repeat url(../emoji/sprite.png) 0 -90px;width:18px;height:18px}
+.SPRITE_2FE{background:no-repeat url(../emoji/sprite.png) -54px -305px;width:18px;height:16px}
+.SPRITE_2FF{background:no-repeat url(../emoji/sprite.png) -54px -72px;width:18px;height:16px}
+.SPRITE_none{background:no-repeat url(../emoji/sprite.png) -54px -180px;width:18px;height:18px}
+.SPRITE_unknown{background:no-repeat url(../emoji/sprite.png) -36px -323px;width:14px;height:15px}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/editor/deps.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/editor/deps.js b/externs/GCL/externs/goog/demos/editor/deps.js
new file mode 100644
index 0000000..70b0973
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/editor/deps.js
@@ -0,0 +1,21 @@
+// Copyright 2009 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.
+//
+// This file has been auto-generated by GenJsDeps, please do not edit.
+
+goog.addDependency('demos/editor/equationeditor.js', ['goog.demos.editor.EquationEditor'], ['goog.ui.equation.EquationEditorDialog']);
+goog.addDependency('demos/editor/helloworld.js', ['goog.demos.editor.HelloWorld'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']);
+goog.addDependency('demos/editor/helloworlddialog.js', ['goog.demos.editor.HelloWorldDialog', 'goog.demos.editor.HelloWorldDialog.OkEvent'], ['goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType']);
+goog.addDependency('demos/editor/helloworlddialogplugin.js', ['goog.demos.editor.HelloWorldDialogPlugin', 'goog.demos.editor.HelloWorldDialogPlugin.Command'], ['goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range', 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType']);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/editor/helloworld.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/editor/helloworld.js b/externs/GCL/externs/goog/demos/editor/helloworld.js
new file mode 100644
index 0000000..4b2f0c7
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/editor/helloworld.js
@@ -0,0 +1,82 @@
+// 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 A simple plugin that inserts 'Hello World!' on command. This
+ * plugin is intended to be an example of a very simple plugin for plugin
+ * developers.
+ *
+ * @author gak@google.com (Gregory Kick)
+ * @see helloworld.html
+ */
+
+goog.provide('goog.demos.editor.HelloWorld');
+
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.Plugin');
+
+
+
+/**
+ * Plugin to insert 'Hello World!' into an editable field.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.demos.editor.HelloWorld = function() {
+ goog.editor.Plugin.call(this);
+};
+goog.inherits(goog.demos.editor.HelloWorld, goog.editor.Plugin);
+
+
+/** @override */
+goog.demos.editor.HelloWorld.prototype.getTrogClassId = function() {
+ return 'HelloWorld';
+};
+
+
+/**
+ * Commands implemented by this plugin.
+ * @enum {string}
+ */
+goog.demos.editor.HelloWorld.COMMAND = {
+ HELLO_WORLD: '+helloWorld'
+};
+
+
+/** @override */
+goog.demos.editor.HelloWorld.prototype.isSupportedCommand = function(
+ command) {
+ return command == goog.demos.editor.HelloWorld.COMMAND.HELLO_WORLD;
+};
+
+
+/**
+ * Executes a command. Does not fire any BEFORECHANGE, CHANGE, or
+ * SELECTIONCHANGE events (these are handled by the super class implementation
+ * of {@code execCommand}.
+ * @param {string} command Command to execute.
+ * @override
+ * @protected
+ */
+goog.demos.editor.HelloWorld.prototype.execCommandInternal = function(
+ command) {
+ var domHelper = this.getFieldObject().getEditableDomHelper();
+ var range = this.getFieldObject().getRange();
+ range.removeContents();
+ var newNode =
+ domHelper.createDom(goog.dom.TagName.SPAN, null, 'Hello World!');
+ range.insertNode(newNode, false);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/editor/helloworlddialog.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/editor/helloworlddialog.js b/externs/GCL/externs/goog/demos/editor/helloworlddialog.js
new file mode 100644
index 0000000..5ab271e
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/editor/helloworlddialog.js
@@ -0,0 +1,173 @@
+// 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 example of how to write a dialog to be opened by a plugin.
+ *
+ */
+
+goog.provide('goog.demos.editor.HelloWorldDialog');
+goog.provide('goog.demos.editor.HelloWorldDialog.OkEvent');
+
+goog.require('goog.dom.TagName');
+goog.require('goog.events.Event');
+goog.require('goog.string');
+goog.require('goog.ui.editor.AbstractDialog');
+
+
+// *** Public interface ***************************************************** //
+
+
+
+/**
+ * Creates a dialog to let the user enter a customized hello world message.
+ * @param {goog.dom.DomHelper} domHelper DomHelper to be used to create the
+ * dialog's dom structure.
+ * @constructor
+ * @extends {goog.ui.editor.AbstractDialog}
+ * @final
+ */
+goog.demos.editor.HelloWorldDialog = function(domHelper) {
+ goog.ui.editor.AbstractDialog.call(this, domHelper);
+};
+goog.inherits(goog.demos.editor.HelloWorldDialog,
+ goog.ui.editor.AbstractDialog);
+
+
+// *** Event **************************************************************** //
+
+
+
+/**
+ * OK event object for the hello world dialog.
+ * @param {string} message Customized hello world message chosen by the user.
+ * @constructor
+ * @extends {goog.events.Event}
+ * @final
+ */
+goog.demos.editor.HelloWorldDialog.OkEvent = function(message) {
+ this.message = message;
+};
+goog.inherits(goog.demos.editor.HelloWorldDialog.OkEvent, goog.events.Event);
+
+
+/**
+ * Event type.
+ * @type {goog.ui.editor.AbstractDialog.EventType}
+ * @override
+ */
+goog.demos.editor.HelloWorldDialog.OkEvent.prototype.type =
+ goog.ui.editor.AbstractDialog.EventType.OK;
+
+
+/**
+ * Customized hello world message chosen by the user.
+ * @type {string}
+ */
+goog.demos.editor.HelloWorldDialog.OkEvent.prototype.message;
+
+
+// *** Protected interface ************************************************** //
+
+
+/** @override */
+goog.demos.editor.HelloWorldDialog.prototype.createDialogControl = function() {
+ var builder = new goog.ui.editor.AbstractDialog.Builder(this);
+ /** @desc Title of the hello world dialog. */
+ var MSG_HELLO_WORLD_DIALOG_TITLE = goog.getMsg('Add a Hello World message');
+ builder.setTitle(MSG_HELLO_WORLD_DIALOG_TITLE).
+ setContent(this.createContent_());
+ return builder.build();
+};
+
+
+/**
+ * Creates and returns the event object to be used when dispatching the OK
+ * event to listeners, or returns null to prevent the dialog from closing.
+ * @param {goog.events.Event} e The event object dispatched by the wrapped
+ * dialog.
+ * @return {goog.demos.editor.HelloWorldDialog.OkEvent} The event object to be
+ * used when dispatching the OK event to listeners.
+ * @protected
+ * @override
+ */
+goog.demos.editor.HelloWorldDialog.prototype.createOkEvent = function(e) {
+ var message = this.getMessage_();
+ if (message &&
+ goog.demos.editor.HelloWorldDialog.isValidHelloWorld_(message)) {
+ return new goog.demos.editor.HelloWorldDialog.OkEvent(message);
+ } else {
+ /** @desc Error message telling the user why their message was rejected. */
+ var MSG_HELLO_WORLD_DIALOG_ERROR =
+ goog.getMsg('Your message must contain the words "hello" and "world".');
+ this.dom.getWindow().alert(MSG_HELLO_WORLD_DIALOG_ERROR);
+ return null; // Prevents the dialog from closing.
+ }
+};
+
+
+// *** Private implementation *********************************************** //
+
+
+/**
+ * Input element where the user will type their hello world message.
+ * @type {Element}
+ * @private
+ */
+goog.demos.editor.HelloWorldDialog.prototype.input_;
+
+
+/**
+ * Creates the DOM structure that makes up the dialog's content area.
+ * @return {Element} The DOM structure that makes up the dialog's content area.
+ * @private
+ */
+goog.demos.editor.HelloWorldDialog.prototype.createContent_ = function() {
+ /** @desc Sample hello world message to prepopulate the dialog with. */
+ var MSG_HELLO_WORLD_DIALOG_SAMPLE = goog.getMsg('Hello, world!');
+ this.input_ = this.dom.createDom(goog.dom.TagName.INPUT,
+ {size: 25, value: MSG_HELLO_WORLD_DIALOG_SAMPLE});
+ /** @desc Prompt telling the user to enter a hello world message. */
+ var MSG_HELLO_WORLD_DIALOG_PROMPT =
+ goog.getMsg('Enter your Hello World message');
+ return this.dom.createDom(goog.dom.TagName.DIV,
+ null,
+ [MSG_HELLO_WORLD_DIALOG_PROMPT, this.input_]);
+};
+
+
+/**
+ * Returns the hello world message currently typed into the dialog's input.
+ * @return {?string} The hello world message currently typed into the dialog's
+ * input, or null if called before the input is created.
+ * @private
+ */
+goog.demos.editor.HelloWorldDialog.prototype.getMessage_ = function() {
+ return this.input_ && this.input_.value;
+};
+
+
+/**
+ * Returns whether or not the given message contains the strings "hello" and
+ * "world". Case-insensitive and order doesn't matter.
+ * @param {string} message The message to be checked.
+ * @return {boolean} Whether or not the given message contains the strings
+ * "hello" and "world".
+ * @private
+ */
+goog.demos.editor.HelloWorldDialog.isValidHelloWorld_ = function(message) {
+ message = message.toLowerCase();
+ return goog.string.contains(message, 'hello') &&
+ goog.string.contains(message, 'world');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/editor/helloworlddialogplugin.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/editor/helloworlddialogplugin.js b/externs/GCL/externs/goog/demos/editor/helloworlddialogplugin.js
new file mode 100644
index 0000000..56a65b6
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/editor/helloworlddialogplugin.js
@@ -0,0 +1,117 @@
+// 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 example of how to write a dialog plugin.
+ *
+ */
+
+goog.provide('goog.demos.editor.HelloWorldDialogPlugin');
+goog.provide('goog.demos.editor.HelloWorldDialogPlugin.Command');
+
+goog.require('goog.demos.editor.HelloWorldDialog');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.plugins.AbstractDialogPlugin');
+goog.require('goog.editor.range');
+goog.require('goog.functions');
+goog.require('goog.ui.editor.AbstractDialog');
+
+
+// *** Public interface ***************************************************** //
+
+
+
+/**
+ * A plugin that opens the hello world dialog.
+ * @constructor
+ * @extends {goog.editor.plugins.AbstractDialogPlugin}
+ * @final
+ */
+goog.demos.editor.HelloWorldDialogPlugin = function() {
+ goog.editor.plugins.AbstractDialogPlugin.call(this,
+ goog.demos.editor.HelloWorldDialogPlugin.Command.HELLO_WORLD_DIALOG);
+};
+goog.inherits(goog.demos.editor.HelloWorldDialogPlugin,
+ goog.editor.plugins.AbstractDialogPlugin);
+
+
+/**
+ * Commands implemented by this plugin.
+ * @enum {string}
+ */
+goog.demos.editor.HelloWorldDialogPlugin.Command = {
+ HELLO_WORLD_DIALOG: 'helloWorldDialog'
+};
+
+
+/** @override */
+goog.demos.editor.HelloWorldDialogPlugin.prototype.getTrogClassId =
+ goog.functions.constant('HelloWorldDialog');
+
+
+// *** Protected interface ************************************************** //
+
+
+/**
+ * Creates a new instance of the dialog and registers for the relevant events.
+ * @param {goog.dom.DomHelper} dialogDomHelper The dom helper to be used to
+ * create the dialog.
+ * @return {goog.demos.editor.HelloWorldDialog} The dialog.
+ * @override
+ * @protected
+ */
+goog.demos.editor.HelloWorldDialogPlugin.prototype.createDialog = function(
+ dialogDomHelper) {
+ var dialog = new goog.demos.editor.HelloWorldDialog(dialogDomHelper);
+ dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.OK,
+ this.handleOk_,
+ false,
+ this);
+ return dialog;
+};
+
+
+// *** Private implementation *********************************************** //
+
+
+/**
+ * Handles the OK event from the dialog by inserting the hello world message
+ * into the field.
+ * @param {goog.demos.editor.HelloWorldDialog.OkEvent} e OK event object.
+ * @private
+ */
+goog.demos.editor.HelloWorldDialogPlugin.prototype.handleOk_ = function(e) {
+ // First restore the selection so we can manipulate the field's content
+ // according to what was selected.
+ this.restoreOriginalSelection();
+
+ // Notify listeners that the field's contents are about to change.
+ this.getFieldObject().dispatchBeforeChange();
+
+ // Now we can clear out what was previously selected (if anything).
+ var range = this.getFieldObject().getRange();
+ range.removeContents();
+ // And replace it with a span containing our hello world message.
+ var createdNode = this.getFieldDomHelper().createDom(goog.dom.TagName.SPAN,
+ null,
+ e.message);
+ createdNode = range.insertNode(createdNode, false);
+ // Place the cursor at the end of the new text node (false == to the right).
+ goog.editor.range.placeCursorNextTo(createdNode, false);
+
+ // Notify listeners that the field's selection has changed.
+ this.getFieldObject().dispatchSelectionChangeEvent();
+ // Notify listeners that the field's contents have changed.
+ this.getFieldObject().dispatchChange();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/200.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/200.gif b/externs/GCL/externs/goog/demos/emoji/200.gif
new file mode 100644
index 0000000..6245f69
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/200.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/201.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/201.gif b/externs/GCL/externs/goog/demos/emoji/201.gif
new file mode 100644
index 0000000..b740d39
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/201.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/202.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/202.gif b/externs/GCL/externs/goog/demos/emoji/202.gif
new file mode 100644
index 0000000..2bc9be6
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/202.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/203.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/203.gif b/externs/GCL/externs/goog/demos/emoji/203.gif
new file mode 100644
index 0000000..1ce3f56
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/203.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/204.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/204.gif b/externs/GCL/externs/goog/demos/emoji/204.gif
new file mode 100644
index 0000000..2166ce8
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/204.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/205.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/205.gif b/externs/GCL/externs/goog/demos/emoji/205.gif
new file mode 100644
index 0000000..363e045
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/205.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/206.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/206.gif b/externs/GCL/externs/goog/demos/emoji/206.gif
new file mode 100644
index 0000000..5b95f44
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/206.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2BC.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2BC.gif b/externs/GCL/externs/goog/demos/emoji/2BC.gif
new file mode 100644
index 0000000..aecbdc0
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2BC.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2BD.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2BD.gif b/externs/GCL/externs/goog/demos/emoji/2BD.gif
new file mode 100644
index 0000000..0b352dd
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2BD.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2BE.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2BE.gif b/externs/GCL/externs/goog/demos/emoji/2BE.gif
new file mode 100644
index 0000000..282c361
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2BE.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2BF.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2BF.gif b/externs/GCL/externs/goog/demos/emoji/2BF.gif
new file mode 100644
index 0000000..5b88ee7
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2BF.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C0.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C0.gif b/externs/GCL/externs/goog/demos/emoji/2C0.gif
new file mode 100644
index 0000000..17fa1a3
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C0.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C1.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C1.gif b/externs/GCL/externs/goog/demos/emoji/2C1.gif
new file mode 100644
index 0000000..a1f294a
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C1.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C2.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C2.gif b/externs/GCL/externs/goog/demos/emoji/2C2.gif
new file mode 100644
index 0000000..01dadbe
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C2.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C3.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C3.gif b/externs/GCL/externs/goog/demos/emoji/2C3.gif
new file mode 100644
index 0000000..69a6126
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C3.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C4.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C4.gif b/externs/GCL/externs/goog/demos/emoji/2C4.gif
new file mode 100644
index 0000000..224527b
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C4.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C5.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C5.gif b/externs/GCL/externs/goog/demos/emoji/2C5.gif
new file mode 100644
index 0000000..2fe94b3
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C5.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C6.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C6.gif b/externs/GCL/externs/goog/demos/emoji/2C6.gif
new file mode 100644
index 0000000..8b1e731
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C6.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C7.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C7.gif b/externs/GCL/externs/goog/demos/emoji/2C7.gif
new file mode 100644
index 0000000..3d7c63a
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C7.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C8.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C8.gif b/externs/GCL/externs/goog/demos/emoji/2C8.gif
new file mode 100644
index 0000000..cb44d16
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C8.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2C9.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2C9.gif b/externs/GCL/externs/goog/demos/emoji/2C9.gif
new file mode 100644
index 0000000..69fe427
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2C9.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2CA.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2CA.gif b/externs/GCL/externs/goog/demos/emoji/2CA.gif
new file mode 100644
index 0000000..cba4c24
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2CA.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2CB.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2CB.gif b/externs/GCL/externs/goog/demos/emoji/2CB.gif
new file mode 100644
index 0000000..c1f035e
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2CB.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2CC.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2CC.gif b/externs/GCL/externs/goog/demos/emoji/2CC.gif
new file mode 100644
index 0000000..bd757fa
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2CC.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2CD.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2CD.gif b/externs/GCL/externs/goog/demos/emoji/2CD.gif
new file mode 100644
index 0000000..f42f5a1
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2CD.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2CE.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2CE.gif b/externs/GCL/externs/goog/demos/emoji/2CE.gif
new file mode 100644
index 0000000..3f6eff3
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2CE.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2CF.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2CF.gif b/externs/GCL/externs/goog/demos/emoji/2CF.gif
new file mode 100644
index 0000000..2f7d407
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2CF.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D0.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D0.gif b/externs/GCL/externs/goog/demos/emoji/2D0.gif
new file mode 100644
index 0000000..37da48e
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D0.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D1.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D1.gif b/externs/GCL/externs/goog/demos/emoji/2D1.gif
new file mode 100644
index 0000000..2bc951d
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D1.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D2.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D2.gif b/externs/GCL/externs/goog/demos/emoji/2D2.gif
new file mode 100644
index 0000000..a7c50db
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D2.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D3.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D3.gif b/externs/GCL/externs/goog/demos/emoji/2D3.gif
new file mode 100644
index 0000000..22ceddf
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D3.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D4.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D4.gif b/externs/GCL/externs/goog/demos/emoji/2D4.gif
new file mode 100644
index 0000000..8e99652
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D4.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D5.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D5.gif b/externs/GCL/externs/goog/demos/emoji/2D5.gif
new file mode 100644
index 0000000..4837a48
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D5.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D6.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D6.gif b/externs/GCL/externs/goog/demos/emoji/2D6.gif
new file mode 100644
index 0000000..bd7230f
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D6.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D7.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D7.gif b/externs/GCL/externs/goog/demos/emoji/2D7.gif
new file mode 100644
index 0000000..880829f
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D7.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D8.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D8.gif b/externs/GCL/externs/goog/demos/emoji/2D8.gif
new file mode 100644
index 0000000..7d727db
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D8.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2D9.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2D9.gif b/externs/GCL/externs/goog/demos/emoji/2D9.gif
new file mode 100644
index 0000000..98a0fa2
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2D9.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2DA.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2DA.gif b/externs/GCL/externs/goog/demos/emoji/2DA.gif
new file mode 100644
index 0000000..c831816
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2DA.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2DB.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2DB.gif b/externs/GCL/externs/goog/demos/emoji/2DB.gif
new file mode 100644
index 0000000..301c931
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2DB.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2DC.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2DC.gif b/externs/GCL/externs/goog/demos/emoji/2DC.gif
new file mode 100644
index 0000000..27ab408
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2DC.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2DD.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2DD.gif b/externs/GCL/externs/goog/demos/emoji/2DD.gif
new file mode 100644
index 0000000..b5e6edf
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2DD.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2DE.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2DE.gif b/externs/GCL/externs/goog/demos/emoji/2DE.gif
new file mode 100644
index 0000000..b9a7272
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2DE.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2DF.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2DF.gif b/externs/GCL/externs/goog/demos/emoji/2DF.gif
new file mode 100644
index 0000000..89fa186
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2DF.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E0.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E0.gif b/externs/GCL/externs/goog/demos/emoji/2E0.gif
new file mode 100644
index 0000000..7fd754a
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E0.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E1.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E1.gif b/externs/GCL/externs/goog/demos/emoji/2E1.gif
new file mode 100644
index 0000000..6926e4e
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E1.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E2.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E2.gif b/externs/GCL/externs/goog/demos/emoji/2E2.gif
new file mode 100644
index 0000000..1718dae
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E2.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E3.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E3.gif b/externs/GCL/externs/goog/demos/emoji/2E3.gif
new file mode 100644
index 0000000..4f23b2b
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E3.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E4.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E4.gif b/externs/GCL/externs/goog/demos/emoji/2E4.gif
new file mode 100644
index 0000000..ab2c9eb
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E4.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E5.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E5.gif b/externs/GCL/externs/goog/demos/emoji/2E5.gif
new file mode 100644
index 0000000..ff8f45b
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E5.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E6.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E6.gif b/externs/GCL/externs/goog/demos/emoji/2E6.gif
new file mode 100644
index 0000000..56e75e8
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E6.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E7.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E7.gif b/externs/GCL/externs/goog/demos/emoji/2E7.gif
new file mode 100644
index 0000000..157042d
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E7.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E8.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E8.gif b/externs/GCL/externs/goog/demos/emoji/2E8.gif
new file mode 100644
index 0000000..1eb1cc9
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E8.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2E9.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2E9.gif b/externs/GCL/externs/goog/demos/emoji/2E9.gif
new file mode 100644
index 0000000..5b98149
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2E9.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2EA.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2EA.gif b/externs/GCL/externs/goog/demos/emoji/2EA.gif
new file mode 100644
index 0000000..40d60a6
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2EA.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2EB.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2EB.gif b/externs/GCL/externs/goog/demos/emoji/2EB.gif
new file mode 100644
index 0000000..8e2ca7d
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2EB.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2EC.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2EC.gif b/externs/GCL/externs/goog/demos/emoji/2EC.gif
new file mode 100644
index 0000000..884e226
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2EC.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2ED.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2ED.gif b/externs/GCL/externs/goog/demos/emoji/2ED.gif
new file mode 100644
index 0000000..b50ba96
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2ED.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2EE.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2EE.gif b/externs/GCL/externs/goog/demos/emoji/2EE.gif
new file mode 100644
index 0000000..a96fbd1
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2EE.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2EF.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2EF.gif b/externs/GCL/externs/goog/demos/emoji/2EF.gif
new file mode 100644
index 0000000..13a0d2b
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2EF.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F0.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F0.gif b/externs/GCL/externs/goog/demos/emoji/2F0.gif
new file mode 100644
index 0000000..1538221
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F0.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F1.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F1.gif b/externs/GCL/externs/goog/demos/emoji/2F1.gif
new file mode 100644
index 0000000..d04c68d
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F1.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F2.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F2.gif b/externs/GCL/externs/goog/demos/emoji/2F2.gif
new file mode 100644
index 0000000..402dfce
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F2.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F3.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F3.gif b/externs/GCL/externs/goog/demos/emoji/2F3.gif
new file mode 100644
index 0000000..250271e
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F3.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F4.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F4.gif b/externs/GCL/externs/goog/demos/emoji/2F4.gif
new file mode 100644
index 0000000..dec31af
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F4.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F5.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F5.gif b/externs/GCL/externs/goog/demos/emoji/2F5.gif
new file mode 100644
index 0000000..bed6e71
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F5.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F6.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F6.gif b/externs/GCL/externs/goog/demos/emoji/2F6.gif
new file mode 100644
index 0000000..e9b885f
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F6.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F7.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F7.gif b/externs/GCL/externs/goog/demos/emoji/2F7.gif
new file mode 100644
index 0000000..5bdcb64
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F7.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F8.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F8.gif b/externs/GCL/externs/goog/demos/emoji/2F8.gif
new file mode 100644
index 0000000..629016b
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F8.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2F9.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2F9.gif b/externs/GCL/externs/goog/demos/emoji/2F9.gif
new file mode 100644
index 0000000..f8b41da
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2F9.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2FA.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2FA.gif b/externs/GCL/externs/goog/demos/emoji/2FA.gif
new file mode 100644
index 0000000..0a4a5b3
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2FA.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2FB.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2FB.gif b/externs/GCL/externs/goog/demos/emoji/2FB.gif
new file mode 100644
index 0000000..620d898
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2FB.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2FC.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2FC.gif b/externs/GCL/externs/goog/demos/emoji/2FC.gif
new file mode 100644
index 0000000..2171097
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2FC.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2FD.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2FD.gif b/externs/GCL/externs/goog/demos/emoji/2FD.gif
new file mode 100644
index 0000000..c6bcdb4
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2FD.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2FE.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2FE.gif b/externs/GCL/externs/goog/demos/emoji/2FE.gif
new file mode 100644
index 0000000..a8888c5
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2FE.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/2FF.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/2FF.gif b/externs/GCL/externs/goog/demos/emoji/2FF.gif
new file mode 100644
index 0000000..6022c4c
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/2FF.gif differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/none.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/none.gif b/externs/GCL/externs/goog/demos/emoji/none.gif
new file mode 100644
index 0000000..8e1f90e
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/none.gif differ
[14/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/anim/anim.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/anim/anim.js b/externs/GCL/externs/goog/fx/anim/anim.js
new file mode 100644
index 0000000..fdce513
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/anim/anim.js
@@ -0,0 +1,211 @@
+// 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 Basic animation controls.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+goog.provide('goog.fx.anim');
+goog.provide('goog.fx.anim.Animated');
+
+goog.require('goog.async.AnimationDelay');
+goog.require('goog.async.Delay');
+goog.require('goog.object');
+
+
+
+/**
+ * An interface for programatically animated objects. I.e. rendered in
+ * javascript frame by frame.
+ *
+ * @interface
+ */
+goog.fx.anim.Animated = function() {};
+
+
+/**
+ * Function called when a frame is requested for the animation.
+ *
+ * @param {number} now Current time in milliseconds.
+ */
+goog.fx.anim.Animated.prototype.onAnimationFrame;
+
+
+/**
+ * Default wait timeout for animations (in milliseconds). Only used for timed
+ * animation, which uses a timer (setTimeout) to schedule animation.
+ *
+ * @type {number}
+ * @const
+ */
+goog.fx.anim.TIMEOUT = goog.async.AnimationDelay.TIMEOUT;
+
+
+/**
+ * A map of animations which should be cycled on the global timer.
+ *
+ * @type {Object<number, goog.fx.anim.Animated>}
+ * @private
+ */
+goog.fx.anim.activeAnimations_ = {};
+
+
+/**
+ * An optional animation window.
+ * @type {Window}
+ * @private
+ */
+goog.fx.anim.animationWindow_ = null;
+
+
+/**
+ * An interval ID for the global timer or event handler uid.
+ * @type {goog.async.Delay|goog.async.AnimationDelay}
+ * @private
+ */
+goog.fx.anim.animationDelay_ = null;
+
+
+/**
+ * Registers an animation to be cycled on the global timer.
+ * @param {goog.fx.anim.Animated} animation The animation to register.
+ */
+goog.fx.anim.registerAnimation = function(animation) {
+ var uid = goog.getUid(animation);
+ if (!(uid in goog.fx.anim.activeAnimations_)) {
+ goog.fx.anim.activeAnimations_[uid] = animation;
+ }
+
+ // If the timer is not already started, start it now.
+ goog.fx.anim.requestAnimationFrame_();
+};
+
+
+/**
+ * Removes an animation from the list of animations which are cycled on the
+ * global timer.
+ * @param {goog.fx.anim.Animated} animation The animation to unregister.
+ */
+goog.fx.anim.unregisterAnimation = function(animation) {
+ var uid = goog.getUid(animation);
+ delete goog.fx.anim.activeAnimations_[uid];
+
+ // If a timer is running and we no longer have any active timers we stop the
+ // timers.
+ if (goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
+ goog.fx.anim.cancelAnimationFrame_();
+ }
+};
+
+
+/**
+ * Tears down this module. Useful for testing.
+ */
+// TODO(nicksantos): Wow, this api is pretty broken. This should be fixed.
+goog.fx.anim.tearDown = function() {
+ goog.fx.anim.animationWindow_ = null;
+ goog.dispose(goog.fx.anim.animationDelay_);
+ goog.fx.anim.animationDelay_ = null;
+ goog.fx.anim.activeAnimations_ = {};
+};
+
+
+/**
+ * Registers an animation window. This allows usage of the timing control API
+ * for animations. Note that this window must be visible, as non-visible
+ * windows can potentially stop animating. This window does not necessarily
+ * need to be the window inside which animation occurs, but must remain visible.
+ * See: https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame.
+ *
+ * @param {Window} animationWindow The window in which to animate elements.
+ */
+goog.fx.anim.setAnimationWindow = function(animationWindow) {
+ // If a timer is currently running, reset it and restart with new functions
+ // after a timeout. This is to avoid mismatching timer UIDs if we change the
+ // animation window during a running animation.
+ //
+ // In practice this cannot happen before some animation window and timer
+ // control functions has already been set.
+ var hasTimer =
+ goog.fx.anim.animationDelay_ && goog.fx.anim.animationDelay_.isActive();
+
+ goog.dispose(goog.fx.anim.animationDelay_);
+ goog.fx.anim.animationDelay_ = null;
+ goog.fx.anim.animationWindow_ = animationWindow;
+
+ // If the timer was running, start it again.
+ if (hasTimer) {
+ goog.fx.anim.requestAnimationFrame_();
+ }
+};
+
+
+/**
+ * Requests an animation frame based on the requestAnimationFrame and
+ * cancelRequestAnimationFrame function pair.
+ * @private
+ */
+goog.fx.anim.requestAnimationFrame_ = function() {
+ if (!goog.fx.anim.animationDelay_) {
+ // We cannot guarantee that the global window will be one that fires
+ // requestAnimationFrame events (consider off-screen chrome extension
+ // windows). Default to use goog.async.Delay, unless
+ // the client has explicitly set an animation window.
+ if (goog.fx.anim.animationWindow_) {
+ // requestAnimationFrame will call cycleAnimations_ with the current
+ // time in ms, as returned from goog.now().
+ goog.fx.anim.animationDelay_ = new goog.async.AnimationDelay(
+ function(now) {
+ goog.fx.anim.cycleAnimations_(now);
+ }, goog.fx.anim.animationWindow_);
+ } else {
+ goog.fx.anim.animationDelay_ = new goog.async.Delay(function() {
+ goog.fx.anim.cycleAnimations_(goog.now());
+ }, goog.fx.anim.TIMEOUT);
+ }
+ }
+
+ var delay = goog.fx.anim.animationDelay_;
+ if (!delay.isActive()) {
+ delay.start();
+ }
+};
+
+
+/**
+ * Cancels an animation frame created by requestAnimationFrame_().
+ * @private
+ */
+goog.fx.anim.cancelAnimationFrame_ = function() {
+ if (goog.fx.anim.animationDelay_) {
+ goog.fx.anim.animationDelay_.stop();
+ }
+};
+
+
+/**
+ * Cycles through all registered animations.
+ * @param {number} now Current time in milliseconds.
+ * @private
+ */
+goog.fx.anim.cycleAnimations_ = function(now) {
+ goog.object.forEach(goog.fx.anim.activeAnimations_, function(anim) {
+ anim.onAnimationFrame(now);
+ });
+
+ if (!goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
+ goog.fx.anim.requestAnimationFrame_();
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/animation.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/animation.js b/externs/GCL/externs/goog/fx/animation.js
new file mode 100644
index 0000000..0a4401b
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/animation.js
@@ -0,0 +1,524 @@
+// 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 Classes for doing animations and visual effects.
+ *
+ * (Based loosly on my animation code for 13thparallel.org, with extra
+ * inspiration from the DojoToolkit's modifications to my code)
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.fx.Animation');
+goog.provide('goog.fx.Animation.EventType');
+goog.provide('goog.fx.Animation.State');
+goog.provide('goog.fx.AnimationEvent');
+
+goog.require('goog.array');
+goog.require('goog.events.Event');
+goog.require('goog.fx.Transition'); // Unreferenced: interface
+goog.require('goog.fx.TransitionBase');
+goog.require('goog.fx.anim');
+goog.require('goog.fx.anim.Animated'); // Unreferenced: interface
+
+
+
+/**
+ * Constructor for an animation object.
+ * @param {Array<number>} start Array for start coordinates.
+ * @param {Array<number>} end Array for end coordinates.
+ * @param {number} duration Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @constructor
+ * @implements {goog.fx.anim.Animated}
+ * @implements {goog.fx.Transition}
+ * @extends {goog.fx.TransitionBase}
+ */
+goog.fx.Animation = function(start, end, duration, opt_acc) {
+ goog.fx.Animation.base(this, 'constructor');
+
+ if (!goog.isArray(start) || !goog.isArray(end)) {
+ throw Error('Start and end parameters must be arrays');
+ }
+
+ if (start.length != end.length) {
+ throw Error('Start and end points must be the same length');
+ }
+
+ /**
+ * Start point.
+ * @type {Array<number>}
+ * @protected
+ */
+ this.startPoint = start;
+
+ /**
+ * End point.
+ * @type {Array<number>}
+ * @protected
+ */
+ this.endPoint = end;
+
+ /**
+ * Duration of animation in milliseconds.
+ * @type {number}
+ * @protected
+ */
+ this.duration = duration;
+
+ /**
+ * Acceleration function, which must return a number between 0 and 1 for
+ * inputs between 0 and 1.
+ * @type {Function|undefined}
+ * @private
+ */
+ this.accel_ = opt_acc;
+
+ /**
+ * Current coordinate for animation.
+ * @type {Array<number>}
+ * @protected
+ */
+ this.coords = [];
+
+ /**
+ * Whether the animation should use "right" rather than "left" to position
+ * elements in RTL. This is a temporary flag to allow clients to transition
+ * to the new behavior at their convenience. At some point it will be the
+ * default.
+ * @type {boolean}
+ * @private
+ */
+ this.useRightPositioningForRtl_ = false;
+
+ /**
+ * Current frame rate.
+ * @private {number}
+ */
+ this.fps_ = 0;
+
+ /**
+ * Percent of the way through the animation.
+ * @protected {number}
+ */
+ this.progress = 0;
+
+ /**
+ * Timestamp for when last frame was run.
+ * @protected {?number}
+ */
+ this.lastFrame = null;
+};
+goog.inherits(goog.fx.Animation, goog.fx.TransitionBase);
+
+
+/**
+ * Sets whether the animation should use "right" rather than "left" to position
+ * elements. This is a temporary flag to allow clients to transition
+ * to the new component at their convenience. At some point "right" will be
+ * used for RTL elements by default.
+ * @param {boolean} useRightPositioningForRtl True if "right" should be used for
+ * positioning, false if "left" should be used for positioning.
+ */
+goog.fx.Animation.prototype.enableRightPositioningForRtl =
+ function(useRightPositioningForRtl) {
+ this.useRightPositioningForRtl_ = useRightPositioningForRtl;
+};
+
+
+/**
+ * Whether the animation should use "right" rather than "left" to position
+ * elements. This is a temporary flag to allow clients to transition
+ * to the new component at their convenience. At some point "right" will be
+ * used for RTL elements by default.
+ * @return {boolean} True if "right" should be used for positioning, false if
+ * "left" should be used for positioning.
+ */
+goog.fx.Animation.prototype.isRightPositioningForRtlEnabled = function() {
+ return this.useRightPositioningForRtl_;
+};
+
+
+/**
+ * Events fired by the animation.
+ * @enum {string}
+ */
+goog.fx.Animation.EventType = {
+ /**
+ * Dispatched when played for the first time OR when it is resumed.
+ * @deprecated Use goog.fx.Transition.EventType.PLAY.
+ */
+ PLAY: goog.fx.Transition.EventType.PLAY,
+
+ /**
+ * Dispatched only when the animation starts from the beginning.
+ * @deprecated Use goog.fx.Transition.EventType.BEGIN.
+ */
+ BEGIN: goog.fx.Transition.EventType.BEGIN,
+
+ /**
+ * Dispatched only when animation is restarted after a pause.
+ * @deprecated Use goog.fx.Transition.EventType.RESUME.
+ */
+ RESUME: goog.fx.Transition.EventType.RESUME,
+
+ /**
+ * Dispatched when animation comes to the end of its duration OR stop
+ * is called.
+ * @deprecated Use goog.fx.Transition.EventType.END.
+ */
+ END: goog.fx.Transition.EventType.END,
+
+ /**
+ * Dispatched only when stop is called.
+ * @deprecated Use goog.fx.Transition.EventType.STOP.
+ */
+ STOP: goog.fx.Transition.EventType.STOP,
+
+ /**
+ * Dispatched only when animation comes to its end naturally.
+ * @deprecated Use goog.fx.Transition.EventType.FINISH.
+ */
+ FINISH: goog.fx.Transition.EventType.FINISH,
+
+ /**
+ * Dispatched when an animation is paused.
+ * @deprecated Use goog.fx.Transition.EventType.PAUSE.
+ */
+ PAUSE: goog.fx.Transition.EventType.PAUSE,
+
+ /**
+ * Dispatched each frame of the animation. This is where the actual animator
+ * will listen.
+ */
+ ANIMATE: 'animate',
+
+ /**
+ * Dispatched when the animation is destroyed.
+ */
+ DESTROY: 'destroy'
+};
+
+
+/**
+ * @deprecated Use goog.fx.anim.TIMEOUT.
+ */
+goog.fx.Animation.TIMEOUT = goog.fx.anim.TIMEOUT;
+
+
+/**
+ * Enum for the possible states of an animation.
+ * @deprecated Use goog.fx.Transition.State instead.
+ * @enum {number}
+ */
+goog.fx.Animation.State = goog.fx.TransitionBase.State;
+
+
+/**
+ * @deprecated Use goog.fx.anim.setAnimationWindow.
+ * @param {Window} animationWindow The window in which to animate elements.
+ */
+goog.fx.Animation.setAnimationWindow = function(animationWindow) {
+ goog.fx.anim.setAnimationWindow(animationWindow);
+};
+
+
+/**
+ * Starts or resumes an animation.
+ * @param {boolean=} opt_restart Whether to restart the
+ * animation from the beginning if it has been paused.
+ * @return {boolean} Whether animation was started.
+ * @override
+ */
+goog.fx.Animation.prototype.play = function(opt_restart) {
+ if (opt_restart || this.isStopped()) {
+ this.progress = 0;
+ this.coords = this.startPoint;
+ } else if (this.isPlaying()) {
+ return false;
+ }
+
+ goog.fx.anim.unregisterAnimation(this);
+
+ var now = /** @type {number} */ (goog.now());
+
+ this.startTime = now;
+ if (this.isPaused()) {
+ this.startTime -= this.duration * this.progress;
+ }
+
+ this.endTime = this.startTime + this.duration;
+ this.lastFrame = this.startTime;
+
+ if (!this.progress) {
+ this.onBegin();
+ }
+
+ this.onPlay();
+
+ if (this.isPaused()) {
+ this.onResume();
+ }
+
+ this.setStatePlaying();
+
+ goog.fx.anim.registerAnimation(this);
+ this.cycle(now);
+
+ return true;
+};
+
+
+/**
+ * Stops the animation.
+ * @param {boolean=} opt_gotoEnd If true the animation will move to the
+ * end coords.
+ * @override
+ */
+goog.fx.Animation.prototype.stop = function(opt_gotoEnd) {
+ goog.fx.anim.unregisterAnimation(this);
+ this.setStateStopped();
+
+ if (!!opt_gotoEnd) {
+ this.progress = 1;
+ }
+
+ this.updateCoords_(this.progress);
+
+ this.onStop();
+ this.onEnd();
+};
+
+
+/**
+ * Pauses the animation (iff it's playing).
+ * @override
+ */
+goog.fx.Animation.prototype.pause = function() {
+ if (this.isPlaying()) {
+ goog.fx.anim.unregisterAnimation(this);
+ this.setStatePaused();
+ this.onPause();
+ }
+};
+
+
+/**
+ * @return {number} The current progress of the animation, the number
+ * is between 0 and 1 inclusive.
+ */
+goog.fx.Animation.prototype.getProgress = function() {
+ return this.progress;
+};
+
+
+/**
+ * Sets the progress of the animation.
+ * @param {number} progress The new progress of the animation.
+ */
+goog.fx.Animation.prototype.setProgress = function(progress) {
+ this.progress = progress;
+ if (this.isPlaying()) {
+ var now = goog.now();
+ // If the animation is already playing, we recompute startTime and endTime
+ // such that the animation plays consistently, that is:
+ // now = startTime + progress * duration.
+ this.startTime = now - this.duration * this.progress;
+ this.endTime = this.startTime + this.duration;
+ }
+};
+
+
+/**
+ * Disposes of the animation. Stops an animation, fires a 'destroy' event and
+ * then removes all the event handlers to clean up memory.
+ * @override
+ * @protected
+ */
+goog.fx.Animation.prototype.disposeInternal = function() {
+ if (!this.isStopped()) {
+ this.stop(false);
+ }
+ this.onDestroy();
+ goog.fx.Animation.base(this, 'disposeInternal');
+};
+
+
+/**
+ * Stops an animation, fires a 'destroy' event and then removes all the event
+ * handlers to clean up memory.
+ * @deprecated Use dispose() instead.
+ */
+goog.fx.Animation.prototype.destroy = function() {
+ this.dispose();
+};
+
+
+/** @override */
+goog.fx.Animation.prototype.onAnimationFrame = function(now) {
+ this.cycle(now);
+};
+
+
+/**
+ * Handles the actual iteration of the animation in a timeout
+ * @param {number} now The current time.
+ */
+goog.fx.Animation.prototype.cycle = function(now) {
+ this.progress = (now - this.startTime) / (this.endTime - this.startTime);
+
+ if (this.progress >= 1) {
+ this.progress = 1;
+ }
+
+ this.fps_ = 1000 / (now - this.lastFrame);
+ this.lastFrame = now;
+
+ this.updateCoords_(this.progress);
+
+ // Animation has finished.
+ if (this.progress == 1) {
+ this.setStateStopped();
+ goog.fx.anim.unregisterAnimation(this);
+
+ this.onFinish();
+ this.onEnd();
+
+ // Animation is still under way.
+ } else if (this.isPlaying()) {
+ this.onAnimate();
+ }
+};
+
+
+/**
+ * Calculates current coordinates, based on the current state. Applies
+ * the accelleration function if it exists.
+ * @param {number} t Percentage of the way through the animation as a decimal.
+ * @private
+ */
+goog.fx.Animation.prototype.updateCoords_ = function(t) {
+ if (goog.isFunction(this.accel_)) {
+ t = this.accel_(t);
+ }
+ this.coords = new Array(this.startPoint.length);
+ for (var i = 0; i < this.startPoint.length; i++) {
+ this.coords[i] = (this.endPoint[i] - this.startPoint[i]) * t +
+ this.startPoint[i];
+ }
+};
+
+
+/**
+ * Dispatches the ANIMATE event. Sub classes should override this instead
+ * of listening to the event.
+ * @protected
+ */
+goog.fx.Animation.prototype.onAnimate = function() {
+ this.dispatchAnimationEvent(goog.fx.Animation.EventType.ANIMATE);
+};
+
+
+/**
+ * Dispatches the DESTROY event. Sub classes should override this instead
+ * of listening to the event.
+ * @protected
+ */
+goog.fx.Animation.prototype.onDestroy = function() {
+ this.dispatchAnimationEvent(goog.fx.Animation.EventType.DESTROY);
+};
+
+
+/** @override */
+goog.fx.Animation.prototype.dispatchAnimationEvent = function(type) {
+ this.dispatchEvent(new goog.fx.AnimationEvent(type, this));
+};
+
+
+
+/**
+ * Class for an animation event object.
+ * @param {string} type Event type.
+ * @param {goog.fx.Animation} anim An animation object.
+ * @constructor
+ * @extends {goog.events.Event}
+ */
+goog.fx.AnimationEvent = function(type, anim) {
+ goog.fx.AnimationEvent.base(this, 'constructor', type);
+
+ /**
+ * The current coordinates.
+ * @type {Array<number>}
+ */
+ this.coords = anim.coords;
+
+ /**
+ * The x coordinate.
+ * @type {number}
+ */
+ this.x = anim.coords[0];
+
+ /**
+ * The y coordinate.
+ * @type {number}
+ */
+ this.y = anim.coords[1];
+
+ /**
+ * The z coordinate.
+ * @type {number}
+ */
+ this.z = anim.coords[2];
+
+ /**
+ * The current duration.
+ * @type {number}
+ */
+ this.duration = anim.duration;
+
+ /**
+ * The current progress.
+ * @type {number}
+ */
+ this.progress = anim.getProgress();
+
+ /**
+ * Frames per second so far.
+ */
+ this.fps = anim.fps_;
+
+ /**
+ * The state of the animation.
+ * @type {number}
+ */
+ this.state = anim.getStateInternal();
+
+ /**
+ * The animation object.
+ * @type {goog.fx.Animation}
+ */
+ // TODO(arv): This can be removed as this is the same as the target
+ this.anim = anim;
+};
+goog.inherits(goog.fx.AnimationEvent, goog.events.Event);
+
+
+/**
+ * Returns the coordinates as integers (rounded to nearest integer).
+ * @return {!Array<number>} An array of the coordinates rounded to
+ * the nearest integer.
+ */
+goog.fx.AnimationEvent.prototype.coordsAsInts = function() {
+ return goog.array.map(this.coords, Math.round);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/animationqueue.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/animationqueue.js b/externs/GCL/externs/goog/fx/animationqueue.js
new file mode 100644
index 0000000..2ad74ab
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/animationqueue.js
@@ -0,0 +1,310 @@
+// 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 class which automatically plays through a queue of
+ * animations. AnimationParallelQueue and AnimationSerialQueue provide
+ * specific implementations of the abstract class AnimationQueue.
+ *
+ * @see ../demos/animationqueue.html
+ */
+
+goog.provide('goog.fx.AnimationParallelQueue');
+goog.provide('goog.fx.AnimationQueue');
+goog.provide('goog.fx.AnimationSerialQueue');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.events');
+goog.require('goog.fx.Transition');
+goog.require('goog.fx.TransitionBase');
+
+
+
+/**
+ * Constructor for AnimationQueue object.
+ *
+ * @constructor
+ * @extends {goog.fx.TransitionBase}
+ * @struct
+ * @suppress {checkStructDictInheritance}
+ */
+goog.fx.AnimationQueue = function() {
+ goog.fx.AnimationQueue.base(this, 'constructor');
+
+ /**
+ * An array holding all animations in the queue.
+ * @type {Array<goog.fx.TransitionBase>}
+ * @protected
+ */
+ this.queue = [];
+};
+goog.inherits(goog.fx.AnimationQueue, goog.fx.TransitionBase);
+
+
+/**
+ * Pushes an Animation to the end of the queue.
+ * @param {goog.fx.TransitionBase} animation The animation to add to the queue.
+ */
+goog.fx.AnimationQueue.prototype.add = function(animation) {
+ goog.asserts.assert(this.isStopped(),
+ 'Not allowed to add animations to a running animation queue.');
+
+ if (goog.array.contains(this.queue, animation)) {
+ return;
+ }
+
+ this.queue.push(animation);
+ goog.events.listen(animation, goog.fx.Transition.EventType.FINISH,
+ this.onAnimationFinish, false, this);
+};
+
+
+/**
+ * Removes an Animation from the queue.
+ * @param {goog.fx.Animation} animation The animation to remove.
+ */
+goog.fx.AnimationQueue.prototype.remove = function(animation) {
+ goog.asserts.assert(this.isStopped(),
+ 'Not allowed to remove animations from a running animation queue.');
+
+ if (goog.array.remove(this.queue, animation)) {
+ goog.events.unlisten(animation, goog.fx.Transition.EventType.FINISH,
+ this.onAnimationFinish, false, this);
+ }
+};
+
+
+/**
+ * Handles the event that an animation has finished.
+ * @param {goog.events.Event} e The finishing event.
+ * @protected
+ */
+goog.fx.AnimationQueue.prototype.onAnimationFinish = goog.abstractMethod;
+
+
+/**
+ * Disposes of the animations.
+ * @override
+ */
+goog.fx.AnimationQueue.prototype.disposeInternal = function() {
+ goog.array.forEach(this.queue, function(animation) {
+ animation.dispose();
+ });
+ this.queue.length = 0;
+
+ goog.fx.AnimationQueue.base(this, 'disposeInternal');
+};
+
+
+
+/**
+ * Constructor for AnimationParallelQueue object.
+ * @constructor
+ * @extends {goog.fx.AnimationQueue}
+ * @struct
+ */
+goog.fx.AnimationParallelQueue = function() {
+ goog.fx.AnimationParallelQueue.base(this, 'constructor');
+
+ /**
+ * Number of finished animations.
+ * @type {number}
+ * @private
+ */
+ this.finishedCounter_ = 0;
+};
+goog.inherits(goog.fx.AnimationParallelQueue, goog.fx.AnimationQueue);
+
+
+/** @override */
+goog.fx.AnimationParallelQueue.prototype.play = function(opt_restart) {
+ if (this.queue.length == 0) {
+ return false;
+ }
+
+ if (opt_restart || this.isStopped()) {
+ this.finishedCounter_ = 0;
+ this.onBegin();
+ } else if (this.isPlaying()) {
+ return false;
+ }
+
+ this.onPlay();
+ if (this.isPaused()) {
+ this.onResume();
+ }
+ var resuming = this.isPaused() && !opt_restart;
+
+ this.startTime = goog.now();
+ this.endTime = null;
+ this.setStatePlaying();
+
+ goog.array.forEach(this.queue, function(anim) {
+ if (!resuming || anim.isPaused()) {
+ anim.play(opt_restart);
+ }
+ });
+
+ return true;
+};
+
+
+/** @override */
+goog.fx.AnimationParallelQueue.prototype.pause = function() {
+ if (this.isPlaying()) {
+ goog.array.forEach(this.queue, function(anim) {
+ if (anim.isPlaying()) {
+ anim.pause();
+ }
+ });
+
+ this.setStatePaused();
+ this.onPause();
+ }
+};
+
+
+/** @override */
+goog.fx.AnimationParallelQueue.prototype.stop = function(opt_gotoEnd) {
+ goog.array.forEach(this.queue, function(anim) {
+ if (!anim.isStopped()) {
+ anim.stop(opt_gotoEnd);
+ }
+ });
+
+ this.setStateStopped();
+ this.endTime = goog.now();
+
+ this.onStop();
+ this.onEnd();
+};
+
+
+/** @override */
+goog.fx.AnimationParallelQueue.prototype.onAnimationFinish = function(e) {
+ this.finishedCounter_++;
+ if (this.finishedCounter_ == this.queue.length) {
+ this.endTime = goog.now();
+
+ this.setStateStopped();
+
+ this.onFinish();
+ this.onEnd();
+ }
+};
+
+
+
+/**
+ * Constructor for AnimationSerialQueue object.
+ * @constructor
+ * @extends {goog.fx.AnimationQueue}
+ * @struct
+ */
+goog.fx.AnimationSerialQueue = function() {
+ goog.fx.AnimationSerialQueue.base(this, 'constructor');
+
+ /**
+ * Current animation in queue currently active.
+ * @type {number}
+ * @private
+ */
+ this.current_ = 0;
+};
+goog.inherits(goog.fx.AnimationSerialQueue, goog.fx.AnimationQueue);
+
+
+/** @override */
+goog.fx.AnimationSerialQueue.prototype.play = function(opt_restart) {
+ if (this.queue.length == 0) {
+ return false;
+ }
+
+ if (opt_restart || this.isStopped()) {
+ if (this.current_ < this.queue.length &&
+ !this.queue[this.current_].isStopped()) {
+ this.queue[this.current_].stop(false);
+ }
+
+ this.current_ = 0;
+ this.onBegin();
+ } else if (this.isPlaying()) {
+ return false;
+ }
+
+ this.onPlay();
+ if (this.isPaused()) {
+ this.onResume();
+ }
+
+ this.startTime = goog.now();
+ this.endTime = null;
+ this.setStatePlaying();
+
+ this.queue[this.current_].play(opt_restart);
+
+ return true;
+};
+
+
+/** @override */
+goog.fx.AnimationSerialQueue.prototype.pause = function() {
+ if (this.isPlaying()) {
+ this.queue[this.current_].pause();
+ this.setStatePaused();
+ this.onPause();
+ }
+};
+
+
+/** @override */
+goog.fx.AnimationSerialQueue.prototype.stop = function(opt_gotoEnd) {
+ this.setStateStopped();
+ this.endTime = goog.now();
+
+ if (opt_gotoEnd) {
+ for (var i = this.current_; i < this.queue.length; ++i) {
+ var anim = this.queue[i];
+ // If the animation is stopped, start it to initiate rendering. This
+ // might be needed to make the next line work.
+ if (anim.isStopped()) anim.play();
+ // If the animation is not done, stop it and go to the end state of the
+ // animation.
+ if (!anim.isStopped()) anim.stop(true);
+ }
+ } else if (this.current_ < this.queue.length) {
+ this.queue[this.current_].stop(false);
+ }
+
+ this.onStop();
+ this.onEnd();
+};
+
+
+/** @override */
+goog.fx.AnimationSerialQueue.prototype.onAnimationFinish = function(e) {
+ if (this.isPlaying()) {
+ this.current_++;
+ if (this.current_ < this.queue.length) {
+ this.queue[this.current_].play();
+ } else {
+ this.endTime = goog.now();
+ this.setStateStopped();
+
+ this.onFinish();
+ this.onEnd();
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/css3/fx.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/css3/fx.js b/externs/GCL/externs/goog/fx/css3/fx.js
new file mode 100644
index 0000000..267c78a
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/css3/fx.js
@@ -0,0 +1,63 @@
+// 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 A collection of CSS3 targeted animation, based on
+ * {@code goog.fx.css3.Transition}.
+ *
+ * @author chrishenry@google.com (Chris Henry)
+ */
+
+goog.provide('goog.fx.css3');
+
+goog.require('goog.fx.css3.Transition');
+
+
+/**
+ * Creates a transition to fade the element.
+ * @param {Element} element The element to fade.
+ * @param {number} duration Duration in seconds.
+ * @param {string} timing The CSS3 timing function.
+ * @param {number} startOpacity Starting opacity.
+ * @param {number} endOpacity Ending opacity.
+ * @return {!goog.fx.css3.Transition} The transition object.
+ */
+goog.fx.css3.fade = function(
+ element, duration, timing, startOpacity, endOpacity) {
+ return new goog.fx.css3.Transition(
+ element, duration, {'opacity': startOpacity}, {'opacity': endOpacity},
+ {property: 'opacity', duration: duration, timing: timing, delay: 0});
+};
+
+
+/**
+ * Creates a transition to fade in the element.
+ * @param {Element} element The element to fade in.
+ * @param {number} duration Duration in seconds.
+ * @return {!goog.fx.css3.Transition} The transition object.
+ */
+goog.fx.css3.fadeIn = function(element, duration) {
+ return goog.fx.css3.fade(element, duration, 'ease-out', 0, 1);
+};
+
+
+/**
+ * Creates a transition to fade out the element.
+ * @param {Element} element The element to fade out.
+ * @param {number} duration Duration in seconds.
+ * @return {!goog.fx.css3.Transition} The transition object.
+ */
+goog.fx.css3.fadeOut = function(element, duration) {
+ return goog.fx.css3.fade(element, duration, 'ease-in', 1, 0);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/css3/transition.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/css3/transition.js b/externs/GCL/externs/goog/fx/css3/transition.js
new file mode 100644
index 0000000..59ec3f7
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/css3/transition.js
@@ -0,0 +1,201 @@
+// 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 CSS3 transition base library.
+ *
+ * @author chrishenry@google.com (Chris Henry)
+ */
+
+goog.provide('goog.fx.css3.Transition');
+
+goog.require('goog.Timer');
+goog.require('goog.asserts');
+goog.require('goog.fx.TransitionBase');
+goog.require('goog.style');
+goog.require('goog.style.transition');
+
+
+
+/**
+ * A class to handle targeted CSS3 transition. This class
+ * handles common features required for targeted CSS3 transition.
+ *
+ * Browser that does not support CSS3 transition will still receive all
+ * the events fired by the transition object, but will not have any transition
+ * played. If the browser supports the final state as set in setFinalState
+ * method, the element will ends in the final state.
+ *
+ * Transitioning multiple properties with the same setting is possible
+ * by setting Css3Property's property to 'all'. Performing multiple
+ * transitions can be done via setting multiple initialStyle,
+ * finalStyle and transitions. Css3Property's delay can be used to
+ * delay one of the transition. Here is an example for a transition
+ * that expands on the width and then followed by the height:
+ *
+ * <pre>
+ * initialStyle: {width: 10px, height: 10px}
+ * finalStyle: {width: 100px, height: 100px}
+ * transitions: [
+ * {property: width, duration: 1, timing: 'ease-in', delay: 0},
+ * {property: height, duration: 1, timing: 'ease-in', delay: 1}
+ * ]
+ * </pre>
+ *
+ * @param {Element} element The element to be transitioned.
+ * @param {number} duration The duration of the transition in seconds.
+ * This should be the longest of all transitions.
+ * @param {Object} initialStyle Initial style properties of the element before
+ * animating. Set using {@code goog.style.setStyle}.
+ * @param {Object} finalStyle Final style properties of the element after
+ * animating. Set using {@code goog.style.setStyle}.
+ * @param {goog.style.transition.Css3Property|
+ * Array<goog.style.transition.Css3Property>} transitions A single CSS3
+ * transition property or an array of it.
+ * @extends {goog.fx.TransitionBase}
+ * @constructor
+ */
+goog.fx.css3.Transition = function(
+ element, duration, initialStyle, finalStyle, transitions) {
+ goog.fx.css3.Transition.base(this, 'constructor');
+
+ /**
+ * @type {Element}
+ * @private
+ */
+ this.element_ = element;
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.duration_ = duration;
+
+ /**
+ * @type {Object}
+ * @private
+ */
+ this.initialStyle_ = initialStyle;
+
+ /**
+ * @type {Object}
+ * @private
+ */
+ this.finalStyle_ = finalStyle;
+
+ /**
+ * @type {Array<goog.style.transition.Css3Property>}
+ * @private
+ */
+ this.transitions_ = goog.isArray(transitions) ? transitions : [transitions];
+};
+goog.inherits(goog.fx.css3.Transition, goog.fx.TransitionBase);
+
+
+/**
+ * Timer id to be used to cancel animation part-way.
+ * @type {number}
+ * @private
+ */
+goog.fx.css3.Transition.prototype.timerId_;
+
+
+/** @override */
+goog.fx.css3.Transition.prototype.play = function() {
+ if (this.isPlaying()) {
+ return false;
+ }
+
+ this.onBegin();
+ this.onPlay();
+
+ this.startTime = goog.now();
+ this.setStatePlaying();
+
+ if (goog.style.transition.isSupported()) {
+ goog.style.setStyle(this.element_, this.initialStyle_);
+ // Allow element to get updated to its initial state before installing
+ // CSS3 transition.
+ this.timerId_ = goog.Timer.callOnce(this.play_, undefined, this);
+ return true;
+ } else {
+ this.stop_(false);
+ return false;
+ }
+};
+
+
+/**
+ * Helper method for play method. This needs to be executed on a timer.
+ * @private
+ */
+goog.fx.css3.Transition.prototype.play_ = function() {
+ // This measurement of the DOM element causes the browser to recalculate its
+ // initial state before the transition starts.
+ goog.style.getSize(this.element_);
+ goog.style.transition.set(this.element_, this.transitions_);
+ goog.style.setStyle(this.element_, this.finalStyle_);
+ this.timerId_ = goog.Timer.callOnce(
+ goog.bind(this.stop_, this, false), this.duration_ * 1000);
+};
+
+
+/** @override */
+goog.fx.css3.Transition.prototype.stop = function() {
+ if (!this.isPlaying()) return;
+
+ this.stop_(true);
+};
+
+
+/**
+ * Helper method for stop method.
+ * @param {boolean} stopped If the transition was stopped.
+ * @private
+ */
+goog.fx.css3.Transition.prototype.stop_ = function(stopped) {
+ goog.style.transition.removeAll(this.element_);
+
+ // Clear the timer.
+ goog.Timer.clear(this.timerId_);
+
+ // Make sure that we have reached the final style.
+ goog.style.setStyle(this.element_, this.finalStyle_);
+
+ this.endTime = goog.now();
+ this.setStateStopped();
+
+ if (stopped) {
+ this.onStop();
+ } else {
+ this.onFinish();
+ }
+ this.onEnd();
+};
+
+
+/** @override */
+goog.fx.css3.Transition.prototype.disposeInternal = function() {
+ this.stop();
+ goog.fx.css3.Transition.base(this, 'disposeInternal');
+};
+
+
+/**
+ * Pausing CSS3 Transitions in not supported.
+ * @override
+ */
+goog.fx.css3.Transition.prototype.pause = function() {
+ goog.asserts.assert(false, 'Css3 transitions does not support pause action.');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/cssspriteanimation.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/cssspriteanimation.js b/externs/GCL/externs/goog/fx/cssspriteanimation.js
new file mode 100644
index 0000000..9813f7d
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/cssspriteanimation.js
@@ -0,0 +1,130 @@
+// 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 animation class that animates CSS sprites by changing the
+ * CSS background-position.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/cssspriteanimation.html
+ */
+
+goog.provide('goog.fx.CssSpriteAnimation');
+
+goog.require('goog.fx.Animation');
+
+
+
+/**
+ * This animation class is used to animate a CSS sprite (moving a background
+ * image). This moves through a series of images in a single image sprite. By
+ * default, the animation loops when done. Looping can be disabled by setting
+ * {@code opt_disableLoop} and results in the animation stopping on the last
+ * image in the image sprite. You should set up the {@code background-image}
+ * and size in a CSS rule for the relevant element.
+ *
+ * @param {Element} element The HTML element to animate the background for.
+ * @param {goog.math.Size} size The size of one image in the image sprite.
+ * @param {goog.math.Box} box The box describing the layout of the sprites to
+ * use in the large image. The sprites can be position horizontally or
+ * vertically and using a box here allows the implementation to know which
+ * way to go.
+ * @param {number} time The duration in milliseconds for one iteration of the
+ * animation. For example, if the sprite contains 4 images and the duration
+ * is set to 400ms then each sprite will be displayed for 100ms.
+ * @param {function(number) : number=} opt_acc Acceleration function,
+ * returns 0-1 for inputs 0-1. This can be used to make certain frames be
+ * shown for a longer period of time.
+ * @param {boolean=} opt_disableLoop Whether the animation should be halted
+ * after a single loop of the images in the sprite.
+ *
+ * @constructor
+ * @extends {goog.fx.Animation}
+ * @final
+ */
+goog.fx.CssSpriteAnimation = function(element, size, box, time, opt_acc,
+ opt_disableLoop) {
+ var start = [box.left, box.top];
+ // We never draw for the end so we do not need to subtract for the size
+ var end = [box.right, box.bottom];
+ goog.fx.CssSpriteAnimation.base(
+ this, 'constructor', start, end, time, opt_acc);
+
+ /**
+ * HTML element that will be used in the animation.
+ * @type {Element}
+ * @private
+ */
+ this.element_ = element;
+
+ /**
+ * The size of an individual sprite in the image sprite.
+ * @type {goog.math.Size}
+ * @private
+ */
+ this.size_ = size;
+
+ /**
+ * Whether the animation should be halted after a single loop of the images
+ * in the sprite.
+ * @type {boolean}
+ * @private
+ */
+ this.disableLoop_ = !!opt_disableLoop;
+};
+goog.inherits(goog.fx.CssSpriteAnimation, goog.fx.Animation);
+
+
+/** @override */
+goog.fx.CssSpriteAnimation.prototype.onAnimate = function() {
+ // Round to nearest sprite.
+ var x = -Math.floor(this.coords[0] / this.size_.width) * this.size_.width;
+ var y = -Math.floor(this.coords[1] / this.size_.height) * this.size_.height;
+ this.element_.style.backgroundPosition = x + 'px ' + y + 'px';
+
+ goog.fx.CssSpriteAnimation.base(this, 'onAnimate');
+};
+
+
+/** @override */
+goog.fx.CssSpriteAnimation.prototype.onFinish = function() {
+ if (!this.disableLoop_) {
+ this.play(true);
+ }
+ goog.fx.CssSpriteAnimation.base(this, 'onFinish');
+};
+
+
+/**
+ * Clears the background position style set directly on the element
+ * by the animation. Allows to apply CSS styling for background position on the
+ * same element when the sprite animation is not runniing.
+ */
+goog.fx.CssSpriteAnimation.prototype.clearSpritePosition = function() {
+ var style = this.element_.style;
+ style.backgroundPosition = '';
+
+ if (typeof style.backgroundPositionX != 'undefined') {
+ // IE needs to clear x and y to actually clear the position
+ style.backgroundPositionX = '';
+ style.backgroundPositionY = '';
+ }
+};
+
+
+/** @override */
+goog.fx.CssSpriteAnimation.prototype.disposeInternal = function() {
+ goog.fx.CssSpriteAnimation.superClass_.disposeInternal.call(this);
+ this.element_ = null;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/dom.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/dom.js b/externs/GCL/externs/goog/fx/dom.js
new file mode 100644
index 0000000..8430fba
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/dom.js
@@ -0,0 +1,686 @@
+// 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 Predefined DHTML animations such as slide, resize and fade.
+ *
+ * @see ../demos/effects.html
+ */
+
+goog.provide('goog.fx.dom');
+goog.provide('goog.fx.dom.BgColorTransform');
+goog.provide('goog.fx.dom.ColorTransform');
+goog.provide('goog.fx.dom.Fade');
+goog.provide('goog.fx.dom.FadeIn');
+goog.provide('goog.fx.dom.FadeInAndShow');
+goog.provide('goog.fx.dom.FadeOut');
+goog.provide('goog.fx.dom.FadeOutAndHide');
+goog.provide('goog.fx.dom.PredefinedEffect');
+goog.provide('goog.fx.dom.Resize');
+goog.provide('goog.fx.dom.ResizeHeight');
+goog.provide('goog.fx.dom.ResizeWidth');
+goog.provide('goog.fx.dom.Scroll');
+goog.provide('goog.fx.dom.Slide');
+goog.provide('goog.fx.dom.SlideFrom');
+goog.provide('goog.fx.dom.Swipe');
+
+goog.require('goog.color');
+goog.require('goog.events');
+goog.require('goog.fx.Animation');
+goog.require('goog.fx.Transition');
+goog.require('goog.style');
+goog.require('goog.style.bidi');
+
+
+
+/**
+ * Abstract class that provides reusable functionality for predefined animations
+ * that manipulate a single DOM element
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start Array for start coordinates.
+ * @param {Array<number>} end Array for end coordinates.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.Animation}
+ * @constructor
+ */
+goog.fx.dom.PredefinedEffect = function(element, start, end, time, opt_acc) {
+ goog.fx.Animation.call(this, start, end, time, opt_acc);
+
+ /**
+ * DOM Node that will be used in the animation
+ * @type {Element}
+ */
+ this.element = element;
+
+ /**
+ * Whether the element is rendered right-to-left. We cache this here for
+ * efficiency.
+ * @private {boolean|undefined}
+ */
+ this.rightToLeft_;
+};
+goog.inherits(goog.fx.dom.PredefinedEffect, goog.fx.Animation);
+
+
+/**
+ * Called to update the style of the element.
+ * @protected
+ */
+goog.fx.dom.PredefinedEffect.prototype.updateStyle = goog.nullFunction;
+
+
+/**
+ * Whether the DOM element being manipulated is rendered right-to-left.
+ * @return {boolean} True if the DOM element is rendered right-to-left, false
+ * otherwise.
+ */
+goog.fx.dom.PredefinedEffect.prototype.isRightToLeft = function() {
+ if (!goog.isDef(this.rightToLeft_)) {
+ this.rightToLeft_ = goog.style.isRightToLeft(this.element);
+ }
+ return this.rightToLeft_;
+};
+
+
+/** @override */
+goog.fx.dom.PredefinedEffect.prototype.onAnimate = function() {
+ this.updateStyle();
+ goog.fx.dom.PredefinedEffect.superClass_.onAnimate.call(this);
+};
+
+
+/** @override */
+goog.fx.dom.PredefinedEffect.prototype.onEnd = function() {
+ this.updateStyle();
+ goog.fx.dom.PredefinedEffect.superClass_.onEnd.call(this);
+};
+
+
+/** @override */
+goog.fx.dom.PredefinedEffect.prototype.onBegin = function() {
+ this.updateStyle();
+ goog.fx.dom.PredefinedEffect.superClass_.onBegin.call(this);
+};
+
+
+
+/**
+ * Creates an animation object that will slide an element from A to B. (This
+ * in effect automatically sets up the onanimate event for an Animation object)
+ *
+ * Start and End should be 2 dimensional arrays
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start 2D array for start coordinates (X, Y).
+ * @param {Array<number>} end 2D array for end coordinates (X, Y).
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.Slide = function(element, start, end, time, opt_acc) {
+ if (start.length != 2 || end.length != 2) {
+ throw Error('Start and end points must be 2D');
+ }
+ goog.fx.dom.PredefinedEffect.apply(this, arguments);
+};
+goog.inherits(goog.fx.dom.Slide, goog.fx.dom.PredefinedEffect);
+
+
+/** @override */
+goog.fx.dom.Slide.prototype.updateStyle = function() {
+ var pos = (this.isRightPositioningForRtlEnabled() && this.isRightToLeft()) ?
+ 'right' : 'left';
+ this.element.style[pos] = Math.round(this.coords[0]) + 'px';
+ this.element.style.top = Math.round(this.coords[1]) + 'px';
+};
+
+
+
+/**
+ * Slides an element from its current position.
+ *
+ * @param {Element} element DOM node to be used in the animation.
+ * @param {Array<number>} end 2D array for end coordinates (X, Y).
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.Slide}
+ * @constructor
+ */
+goog.fx.dom.SlideFrom = function(element, end, time, opt_acc) {
+ var offsetLeft = this.isRightPositioningForRtlEnabled() ?
+ goog.style.bidi.getOffsetStart(element) : element.offsetLeft;
+ var start = [offsetLeft, element.offsetTop];
+ goog.fx.dom.Slide.call(this, element, start, end, time, opt_acc);
+};
+goog.inherits(goog.fx.dom.SlideFrom, goog.fx.dom.Slide);
+
+
+/** @override */
+goog.fx.dom.SlideFrom.prototype.onBegin = function() {
+ var offsetLeft = this.isRightPositioningForRtlEnabled() ?
+ goog.style.bidi.getOffsetStart(this.element) : this.element.offsetLeft;
+ this.startPoint = [offsetLeft, this.element.offsetTop];
+ goog.fx.dom.SlideFrom.superClass_.onBegin.call(this);
+};
+
+
+
+/**
+ * Creates an animation object that will slide an element into its final size.
+ * Requires that the element is absolutely positioned.
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start 2D array for start size (W, H).
+ * @param {Array<number>} end 2D array for end size (W, H).
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.Swipe = function(element, start, end, time, opt_acc) {
+ if (start.length != 2 || end.length != 2) {
+ throw Error('Start and end points must be 2D');
+ }
+ goog.fx.dom.PredefinedEffect.apply(this, arguments);
+
+ /**
+ * Maximum width for element.
+ * @type {number}
+ * @private
+ */
+ this.maxWidth_ = Math.max(this.endPoint[0], this.startPoint[0]);
+
+ /**
+ * Maximum height for element.
+ * @type {number}
+ * @private
+ */
+ this.maxHeight_ = Math.max(this.endPoint[1], this.startPoint[1]);
+};
+goog.inherits(goog.fx.dom.Swipe, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * Animation event handler that will resize an element by setting its width,
+ * height and clipping.
+ * @protected
+ * @override
+ */
+goog.fx.dom.Swipe.prototype.updateStyle = function() {
+ var x = this.coords[0];
+ var y = this.coords[1];
+ this.clip_(Math.round(x), Math.round(y), this.maxWidth_, this.maxHeight_);
+ this.element.style.width = Math.round(x) + 'px';
+ var marginX = (this.isRightPositioningForRtlEnabled() &&
+ this.isRightToLeft()) ? 'marginRight' : 'marginLeft';
+
+ this.element.style[marginX] = Math.round(x) - this.maxWidth_ + 'px';
+ this.element.style.marginTop = Math.round(y) - this.maxHeight_ + 'px';
+};
+
+
+/**
+ * Helper function for setting element clipping.
+ * @param {number} x Current element width.
+ * @param {number} y Current element height.
+ * @param {number} w Maximum element width.
+ * @param {number} h Maximum element height.
+ * @private
+ */
+goog.fx.dom.Swipe.prototype.clip_ = function(x, y, w, h) {
+ this.element.style.clip =
+ 'rect(' + (h - y) + 'px ' + w + 'px ' + h + 'px ' + (w - x) + 'px)';
+};
+
+
+
+/**
+ * Creates an animation object that will scroll an element from A to B.
+ *
+ * Start and End should be 2 dimensional arrays
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start 2D array for start scroll left and top.
+ * @param {Array<number>} end 2D array for end scroll left and top.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.Scroll = function(element, start, end, time, opt_acc) {
+ if (start.length != 2 || end.length != 2) {
+ throw Error('Start and end points must be 2D');
+ }
+ goog.fx.dom.PredefinedEffect.apply(this, arguments);
+};
+goog.inherits(goog.fx.dom.Scroll, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * Animation event handler that will set the scroll position of an element.
+ * @protected
+ * @override
+ */
+goog.fx.dom.Scroll.prototype.updateStyle = function() {
+ if (this.isRightPositioningForRtlEnabled()) {
+ goog.style.bidi.setScrollOffset(this.element, Math.round(this.coords[0]));
+ } else {
+ this.element.scrollLeft = Math.round(this.coords[0]);
+ }
+ this.element.scrollTop = Math.round(this.coords[1]);
+};
+
+
+
+/**
+ * Creates an animation object that will resize an element between two widths
+ * and heights.
+ *
+ * Start and End should be 2 dimensional arrays
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start 2D array for start width and height.
+ * @param {Array<number>} end 2D array for end width and height.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.Resize = function(element, start, end, time, opt_acc) {
+ if (start.length != 2 || end.length != 2) {
+ throw Error('Start and end points must be 2D');
+ }
+ goog.fx.dom.PredefinedEffect.apply(this, arguments);
+};
+goog.inherits(goog.fx.dom.Resize, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * Animation event handler that will resize an element by setting its width and
+ * height.
+ * @protected
+ * @override
+ */
+goog.fx.dom.Resize.prototype.updateStyle = function() {
+ this.element.style.width = Math.round(this.coords[0]) + 'px';
+ this.element.style.height = Math.round(this.coords[1]) + 'px';
+};
+
+
+
+/**
+ * Creates an animation object that will resize an element between two widths
+ *
+ * Start and End should be numbers
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {number} start Start width.
+ * @param {number} end End width.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.ResizeWidth = function(element, start, end, time, opt_acc) {
+ goog.fx.dom.PredefinedEffect.call(this, element, [start],
+ [end], time, opt_acc);
+};
+goog.inherits(goog.fx.dom.ResizeWidth, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * Animation event handler that will resize an element by setting its width.
+ * @protected
+ * @override
+ */
+goog.fx.dom.ResizeWidth.prototype.updateStyle = function() {
+ this.element.style.width = Math.round(this.coords[0]) + 'px';
+};
+
+
+
+/**
+ * Creates an animation object that will resize an element between two heights
+ *
+ * Start and End should be numbers
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {number} start Start height.
+ * @param {number} end End height.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.ResizeHeight = function(element, start, end, time, opt_acc) {
+ goog.fx.dom.PredefinedEffect.call(this, element, [start],
+ [end], time, opt_acc);
+};
+goog.inherits(goog.fx.dom.ResizeHeight, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * Animation event handler that will resize an element by setting its height.
+ * @protected
+ * @override
+ */
+goog.fx.dom.ResizeHeight.prototype.updateStyle = function() {
+ this.element.style.height = Math.round(this.coords[0]) + 'px';
+};
+
+
+
+/**
+ * Creates an animation object that fades the opacity of an element between two
+ * limits.
+ *
+ * Start and End should be floats between 0 and 1
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>|number} start 1D Array or Number with start opacity.
+ * @param {Array<number>|number} end 1D Array or Number for end opacity.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.Fade = function(element, start, end, time, opt_acc) {
+ if (goog.isNumber(start)) start = [start];
+ if (goog.isNumber(end)) end = [end];
+
+ goog.fx.dom.Fade.base(this, 'constructor',
+ element, start, end, time, opt_acc);
+
+ if (start.length != 1 || end.length != 1) {
+ throw Error('Start and end points must be 1D');
+ }
+
+ /**
+ * The last opacity we set, or -1 for not set.
+ * @private {number}
+ */
+ this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
+};
+goog.inherits(goog.fx.dom.Fade, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * The quantization of opacity values to use.
+ * @private {number}
+ */
+goog.fx.dom.Fade.TOLERANCE_ = 1.0 / 0x400; // 10-bit color
+
+
+/**
+ * Value indicating that the opacity must be set on next update.
+ * @private {number}
+ */
+goog.fx.dom.Fade.OPACITY_UNSET_ = -1;
+
+
+/**
+ * Animation event handler that will set the opacity of an element.
+ * @protected
+ * @override
+ */
+goog.fx.dom.Fade.prototype.updateStyle = function() {
+ var opacity = this.coords[0];
+ var delta = Math.abs(opacity - this.lastOpacityUpdate_);
+ // In order to keep eager browsers from over-rendering, only update
+ // on a potentially visible change in opacity.
+ if (delta >= goog.fx.dom.Fade.TOLERANCE_) {
+ goog.style.setOpacity(this.element, opacity);
+ this.lastOpacityUpdate_ = opacity;
+ }
+};
+
+
+/** @override */
+goog.fx.dom.Fade.prototype.onBegin = function() {
+ this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
+ goog.fx.dom.Fade.base(this, 'onBegin');
+};
+
+
+/** @override */
+goog.fx.dom.Fade.prototype.onEnd = function() {
+ this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
+ goog.fx.dom.Fade.base(this, 'onEnd');
+};
+
+
+/**
+ * Animation event handler that will show the element.
+ */
+goog.fx.dom.Fade.prototype.show = function() {
+ this.element.style.display = '';
+};
+
+
+/**
+ * Animation event handler that will hide the element
+ */
+goog.fx.dom.Fade.prototype.hide = function() {
+ this.element.style.display = 'none';
+};
+
+
+
+/**
+ * Fades an element out from full opacity to completely transparent.
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.Fade}
+ * @constructor
+ */
+goog.fx.dom.FadeOut = function(element, time, opt_acc) {
+ goog.fx.dom.Fade.call(this, element, 1, 0, time, opt_acc);
+};
+goog.inherits(goog.fx.dom.FadeOut, goog.fx.dom.Fade);
+
+
+
+/**
+ * Fades an element in from completely transparent to fully opacity.
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.Fade}
+ * @constructor
+ */
+goog.fx.dom.FadeIn = function(element, time, opt_acc) {
+ goog.fx.dom.Fade.call(this, element, 0, 1, time, opt_acc);
+};
+goog.inherits(goog.fx.dom.FadeIn, goog.fx.dom.Fade);
+
+
+
+/**
+ * Fades an element out from full opacity to completely transparent and then
+ * sets the display to 'none'
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.Fade}
+ * @constructor
+ */
+goog.fx.dom.FadeOutAndHide = function(element, time, opt_acc) {
+ goog.fx.dom.Fade.call(this, element, 1, 0, time, opt_acc);
+};
+goog.inherits(goog.fx.dom.FadeOutAndHide, goog.fx.dom.Fade);
+
+
+/** @override */
+goog.fx.dom.FadeOutAndHide.prototype.onBegin = function() {
+ this.show();
+ goog.fx.dom.FadeOutAndHide.superClass_.onBegin.call(this);
+};
+
+
+/** @override */
+goog.fx.dom.FadeOutAndHide.prototype.onEnd = function() {
+ this.hide();
+ goog.fx.dom.FadeOutAndHide.superClass_.onEnd.call(this);
+};
+
+
+
+/**
+ * Sets an element's display to be visible and then fades an element in from
+ * completely transparent to fully opaque.
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.Fade}
+ * @constructor
+ */
+goog.fx.dom.FadeInAndShow = function(element, time, opt_acc) {
+ goog.fx.dom.Fade.call(this, element, 0, 1, time, opt_acc);
+};
+goog.inherits(goog.fx.dom.FadeInAndShow, goog.fx.dom.Fade);
+
+
+/** @override */
+goog.fx.dom.FadeInAndShow.prototype.onBegin = function() {
+ this.show();
+ goog.fx.dom.FadeInAndShow.superClass_.onBegin.call(this);
+};
+
+
+
+/**
+ * Provides a transformation of an elements background-color.
+ *
+ * Start and End should be 3D arrays representing R,G,B
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start 3D Array for RGB of start color.
+ * @param {Array<number>} end 3D Array for RGB of end color.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @extends {goog.fx.dom.PredefinedEffect}
+ * @constructor
+ */
+goog.fx.dom.BgColorTransform = function(element, start, end, time, opt_acc) {
+ if (start.length != 3 || end.length != 3) {
+ throw Error('Start and end points must be 3D');
+ }
+ goog.fx.dom.PredefinedEffect.apply(this, arguments);
+};
+goog.inherits(goog.fx.dom.BgColorTransform, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * Animation event handler that will set the background-color of an element
+ */
+goog.fx.dom.BgColorTransform.prototype.setColor = function() {
+ var coordsAsInts = [];
+ for (var i = 0; i < this.coords.length; i++) {
+ coordsAsInts[i] = Math.round(this.coords[i]);
+ }
+ var color = 'rgb(' + coordsAsInts.join(',') + ')';
+ this.element.style.backgroundColor = color;
+};
+
+
+/** @override */
+goog.fx.dom.BgColorTransform.prototype.updateStyle = function() {
+ this.setColor();
+};
+
+
+/**
+ * Fade elements background color from start color to the element's current
+ * background color.
+ *
+ * Start should be a 3D array representing R,G,B
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start 3D Array for RGB of start color.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {goog.events.EventHandler=} opt_eventHandler Optional event handler
+ * to use when listening for events.
+ */
+goog.fx.dom.bgColorFadeIn = function(element, start, time, opt_eventHandler) {
+ var initialBgColor = element.style.backgroundColor || '';
+ var computedBgColor = goog.style.getBackgroundColor(element);
+ var end;
+
+ if (computedBgColor && computedBgColor != 'transparent' &&
+ computedBgColor != 'rgba(0, 0, 0, 0)') {
+ end = goog.color.hexToRgb(goog.color.parse(computedBgColor).hex);
+ } else {
+ end = [255, 255, 255];
+ }
+
+ var anim = new goog.fx.dom.BgColorTransform(element, start, end, time);
+
+ function setBgColor() {
+ element.style.backgroundColor = initialBgColor;
+ }
+
+ if (opt_eventHandler) {
+ opt_eventHandler.listen(
+ anim, goog.fx.Transition.EventType.END, setBgColor);
+ } else {
+ goog.events.listen(
+ anim, goog.fx.Transition.EventType.END, setBgColor);
+ }
+
+ anim.play();
+};
+
+
+
+/**
+ * Provides a transformation of an elements color.
+ *
+ * @param {Element} element Dom Node to be used in the animation.
+ * @param {Array<number>} start 3D Array representing R,G,B.
+ * @param {Array<number>} end 3D Array representing R,G,B.
+ * @param {number} time Length of animation in milliseconds.
+ * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
+ * @constructor
+ * @extends {goog.fx.dom.PredefinedEffect}
+ */
+goog.fx.dom.ColorTransform = function(element, start, end, time, opt_acc) {
+ if (start.length != 3 || end.length != 3) {
+ throw Error('Start and end points must be 3D');
+ }
+ goog.fx.dom.PredefinedEffect.apply(this, arguments);
+};
+goog.inherits(goog.fx.dom.ColorTransform, goog.fx.dom.PredefinedEffect);
+
+
+/**
+ * Animation event handler that will set the color of an element.
+ * @protected
+ * @override
+ */
+goog.fx.dom.ColorTransform.prototype.updateStyle = function() {
+ var coordsAsInts = [];
+ for (var i = 0; i < this.coords.length; i++) {
+ coordsAsInts[i] = Math.round(this.coords[i]);
+ }
+ var color = 'rgb(' + coordsAsInts.join(',') + ')';
+ this.element.style.color = color;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/dragdrop.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/dragdrop.js b/externs/GCL/externs/goog/fx/dragdrop.js
new file mode 100644
index 0000000..7fe9545
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/dragdrop.js
@@ -0,0 +1,50 @@
+// 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 Single Element Drag and Drop.
+ *
+ * Drag and drop implementation for sources/targets consisting of a single
+ * element.
+ *
+ * @author eae@google.com (Emil A Eklund)
+ * @see ../demos/dragdrop.html
+ */
+
+goog.provide('goog.fx.DragDrop');
+
+goog.require('goog.fx.AbstractDragDrop');
+goog.require('goog.fx.DragDropItem');
+
+
+
+/**
+ * Drag/drop implementation for creating drag sources/drop targets consisting of
+ * a single HTML Element.
+ *
+ * @param {Element|string} element Dom Node, or string representation of node
+ * id, to be used as drag source/drop target.
+ * @param {Object=} opt_data Data associated with the source/target.
+ * @throws Error If no element argument is provided or if the type is invalid
+ * @extends {goog.fx.AbstractDragDrop}
+ * @constructor
+ */
+goog.fx.DragDrop = function(element, opt_data) {
+ goog.fx.AbstractDragDrop.call(this);
+
+ var item = new goog.fx.DragDropItem(element, opt_data);
+ item.setParent(this);
+ this.items_.push(item);
+};
+goog.inherits(goog.fx.DragDrop, goog.fx.AbstractDragDrop);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/dragdropgroup.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/dragdropgroup.js b/externs/GCL/externs/goog/fx/dragdropgroup.js
new file mode 100644
index 0000000..01aab56
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/dragdropgroup.js
@@ -0,0 +1,109 @@
+// 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 Multiple Element Drag and Drop.
+ *
+ * Drag and drop implementation for sources/targets consisting of multiple
+ * elements.
+ *
+ * @author eae@google.com (Emil A Eklund)
+ * @see ../demos/dragdrop.html
+ */
+
+goog.provide('goog.fx.DragDropGroup');
+
+goog.require('goog.dom');
+goog.require('goog.fx.AbstractDragDrop');
+goog.require('goog.fx.DragDropItem');
+
+
+
+/**
+ * Drag/drop implementation for creating drag sources/drop targets consisting of
+ * multiple HTML Elements (items). All items share the same drop target(s) but
+ * can be dragged individually.
+ *
+ * @extends {goog.fx.AbstractDragDrop}
+ * @constructor
+ */
+goog.fx.DragDropGroup = function() {
+ goog.fx.AbstractDragDrop.call(this);
+};
+goog.inherits(goog.fx.DragDropGroup, goog.fx.AbstractDragDrop);
+
+
+/**
+ * Add item to drag object.
+ *
+ * @param {Element|string} element Dom Node, or string representation of node
+ * id, to be used as drag source/drop target.
+ * @param {Object=} opt_data Data associated with the source/target.
+ * @throws Error If no element argument is provided or if the type is
+ * invalid
+ * @override
+ */
+goog.fx.DragDropGroup.prototype.addItem = function(element, opt_data) {
+ var item = new goog.fx.DragDropItem(element, opt_data);
+ this.addDragDropItem(item);
+};
+
+
+/**
+ * Add DragDropItem to drag object.
+ *
+ * @param {goog.fx.DragDropItem} item DragDropItem being added to the
+ * drag object.
+ * @throws Error If no element argument is provided or if the type is
+ * invalid
+ */
+goog.fx.DragDropGroup.prototype.addDragDropItem = function(item) {
+ item.setParent(this);
+ this.items_.push(item);
+ if (this.isInitialized()) {
+ this.initItem(item);
+ }
+};
+
+
+/**
+ * Remove item from drag object.
+ *
+ * @param {Element|string} element Dom Node, or string representation of node
+ * id, that was previously added with addItem().
+ */
+goog.fx.DragDropGroup.prototype.removeItem = function(element) {
+ element = goog.dom.getElement(element);
+ for (var item, i = 0; item = this.items_[i]; i++) {
+ if (item.element == element) {
+ this.items_.splice(i, 1);
+ this.disposeItem(item);
+ break;
+ }
+ }
+};
+
+
+/**
+ * Marks the supplied list of items as selected. A drag operation for any of the
+ * selected items will affect all of them.
+ *
+ * @param {Array<goog.fx.DragDropItem>} list List of items to select or null to
+ * clear selection.
+ *
+ * TODO(eae): Not yet implemented.
+ */
+goog.fx.DragDropGroup.prototype.setSelection = function(list) {
+
+};
[31/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/classlist.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/classlist.js b/externs/GCL/externs/goog/dom/classlist.js
new file mode 100644
index 0000000..dcbb7ed
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/classlist.js
@@ -0,0 +1,277 @@
+// Copyright 2012 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 detecting, adding and removing classes. Prefer
+ * this over goog.dom.classes for new code since it attempts to use classList
+ * (DOMTokenList: http://dom.spec.whatwg.org/#domtokenlist) which is faster
+ * and requires less code.
+ *
+ * Note: these utilities are meant to operate on HTMLElements
+ * and may have unexpected behavior on elements with differing interfaces
+ * (such as SVGElements).
+ */
+
+
+goog.provide('goog.dom.classlist');
+
+goog.require('goog.array');
+
+
+/**
+ * Override this define at build-time if you know your target supports it.
+ * @define {boolean} Whether to use the classList property (DOMTokenList).
+ */
+goog.define('goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST', false);
+
+
+/**
+ * Gets an array-like object of class names on an element.
+ * @param {Element} element DOM node to get the classes of.
+ * @return {!goog.array.ArrayLike} Class names on {@code element}.
+ */
+goog.dom.classlist.get = function(element) {
+ if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
+ return element.classList;
+ }
+
+ var className = element.className;
+ // Some types of elements don't have a className in IE (e.g. iframes).
+ // Furthermore, in Firefox, className is not a string when the element is
+ // an SVG element.
+ return goog.isString(className) && className.match(/\S+/g) || [];
+};
+
+
+/**
+ * Sets the entire class name of an element.
+ * @param {Element} element DOM node to set class of.
+ * @param {string} className Class name(s) to apply to element.
+ */
+goog.dom.classlist.set = function(element, className) {
+ element.className = className;
+};
+
+
+/**
+ * Returns true if an element has a class. This method may throw a DOM
+ * exception for an invalid or empty class name if DOMTokenList is used.
+ * @param {Element} element DOM node to test.
+ * @param {string} className Class name to test for.
+ * @return {boolean} Whether element has the class.
+ */
+goog.dom.classlist.contains = function(element, className) {
+ if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
+ return element.classList.contains(className);
+ }
+ return goog.array.contains(goog.dom.classlist.get(element), className);
+};
+
+
+/**
+ * Adds a class to an element. Does not add multiples of class names. This
+ * method may throw a DOM exception for an invalid or empty class name if
+ * DOMTokenList is used.
+ * @param {Element} element DOM node to add class to.
+ * @param {string} className Class name to add.
+ */
+goog.dom.classlist.add = function(element, className) {
+ if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
+ element.classList.add(className);
+ return;
+ }
+
+ if (!goog.dom.classlist.contains(element, className)) {
+ // Ensure we add a space if this is not the first class name added.
+ element.className += element.className.length > 0 ?
+ (' ' + className) : className;
+ }
+};
+
+
+/**
+ * Convenience method to add a number of class names at once.
+ * @param {Element} element The element to which to add classes.
+ * @param {goog.array.ArrayLike<string>} classesToAdd An array-like object
+ * containing a collection of class names to add to the element.
+ * This method may throw a DOM exception if classesToAdd contains invalid
+ * or empty class names.
+ */
+goog.dom.classlist.addAll = function(element, classesToAdd) {
+ if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
+ goog.array.forEach(classesToAdd, function(className) {
+ goog.dom.classlist.add(element, className);
+ });
+ return;
+ }
+
+ var classMap = {};
+
+ // Get all current class names into a map.
+ goog.array.forEach(goog.dom.classlist.get(element),
+ function(className) {
+ classMap[className] = true;
+ });
+
+ // Add new class names to the map.
+ goog.array.forEach(classesToAdd,
+ function(className) {
+ classMap[className] = true;
+ });
+
+ // Flatten the keys of the map into the className.
+ element.className = '';
+ for (var className in classMap) {
+ element.className += element.className.length > 0 ?
+ (' ' + className) : className;
+ }
+};
+
+
+/**
+ * Removes a class from an element. This method may throw a DOM exception
+ * for an invalid or empty class name if DOMTokenList is used.
+ * @param {Element} element DOM node to remove class from.
+ * @param {string} className Class name to remove.
+ */
+goog.dom.classlist.remove = function(element, className) {
+ if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
+ element.classList.remove(className);
+ return;
+ }
+
+ if (goog.dom.classlist.contains(element, className)) {
+ // Filter out the class name.
+ element.className = goog.array.filter(
+ goog.dom.classlist.get(element),
+ function(c) {
+ return c != className;
+ }).join(' ');
+ }
+};
+
+
+/**
+ * Removes a set of classes from an element. Prefer this call to
+ * repeatedly calling {@code goog.dom.classlist.remove} if you want to remove
+ * a large set of class names at once.
+ * @param {Element} element The element from which to remove classes.
+ * @param {goog.array.ArrayLike<string>} classesToRemove An array-like object
+ * containing a collection of class names to remove from the element.
+ * This method may throw a DOM exception if classesToRemove contains invalid
+ * or empty class names.
+ */
+goog.dom.classlist.removeAll = function(element, classesToRemove) {
+ if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
+ goog.array.forEach(classesToRemove, function(className) {
+ goog.dom.classlist.remove(element, className);
+ });
+ return;
+ }
+ // Filter out those classes in classesToRemove.
+ element.className = goog.array.filter(
+ goog.dom.classlist.get(element),
+ function(className) {
+ // If this class is not one we are trying to remove,
+ // add it to the array of new class names.
+ return !goog.array.contains(classesToRemove, className);
+ }).join(' ');
+};
+
+
+/**
+ * Adds or removes a class depending on the enabled argument. This method
+ * may throw a DOM exception for an invalid or empty class name if DOMTokenList
+ * is used.
+ * @param {Element} element DOM node to add or remove the class on.
+ * @param {string} className Class name to add or remove.
+ * @param {boolean} enabled Whether to add or remove the class (true adds,
+ * false removes).
+ */
+goog.dom.classlist.enable = function(element, className, enabled) {
+ if (enabled) {
+ goog.dom.classlist.add(element, className);
+ } else {
+ goog.dom.classlist.remove(element, className);
+ }
+};
+
+
+/**
+ * Adds or removes a set of classes depending on the enabled argument. This
+ * method may throw a DOM exception for an invalid or empty class name if
+ * DOMTokenList is used.
+ * @param {!Element} element DOM node to add or remove the class on.
+ * @param {goog.array.ArrayLike<string>} classesToEnable An array-like object
+ * containing a collection of class names to add or remove from the element.
+ * @param {boolean} enabled Whether to add or remove the classes (true adds,
+ * false removes).
+ */
+goog.dom.classlist.enableAll = function(element, classesToEnable, enabled) {
+ var f = enabled ? goog.dom.classlist.addAll :
+ goog.dom.classlist.removeAll;
+ f(element, classesToEnable);
+};
+
+
+/**
+ * Switches a class on an element from one to another without disturbing other
+ * classes. If the fromClass isn't removed, the toClass won't be added. This
+ * method may throw a DOM exception if the class names are empty or invalid.
+ * @param {Element} element DOM node to swap classes on.
+ * @param {string} fromClass Class to remove.
+ * @param {string} toClass Class to add.
+ * @return {boolean} Whether classes were switched.
+ */
+goog.dom.classlist.swap = function(element, fromClass, toClass) {
+ if (goog.dom.classlist.contains(element, fromClass)) {
+ goog.dom.classlist.remove(element, fromClass);
+ goog.dom.classlist.add(element, toClass);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a class if an element has it, and adds it the element doesn't have
+ * it. Won't affect other classes on the node. This method may throw a DOM
+ * exception if the class name is empty or invalid.
+ * @param {Element} element DOM node to toggle class on.
+ * @param {string} className Class to toggle.
+ * @return {boolean} True if class was added, false if it was removed
+ * (in other words, whether element has the class after this function has
+ * been called).
+ */
+goog.dom.classlist.toggle = function(element, className) {
+ var add = !goog.dom.classlist.contains(element, className);
+ goog.dom.classlist.enable(element, className, add);
+ return add;
+};
+
+
+/**
+ * Adds and removes a class of an element. Unlike
+ * {@link goog.dom.classlist.swap}, this method adds the classToAdd regardless
+ * of whether the classToRemove was present and had been removed. This method
+ * may throw a DOM exception if the class names are empty or invalid.
+ *
+ * @param {Element} element DOM node to swap classes on.
+ * @param {string} classToRemove Class to remove.
+ * @param {string} classToAdd Class to add.
+ */
+goog.dom.classlist.addRemove = function(element, classToRemove, classToAdd) {
+ goog.dom.classlist.remove(element, classToRemove);
+ goog.dom.classlist.add(element, classToAdd);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/controlrange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/controlrange.js b/externs/GCL/externs/goog/dom/controlrange.js
new file mode 100644
index 0000000..61df59a
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/controlrange.js
@@ -0,0 +1,494 @@
+// 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 IE control ranges.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.ControlRange');
+goog.provide('goog.dom.ControlRangeIterator');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.AbstractMultiRange');
+goog.require('goog.dom.AbstractRange');
+goog.require('goog.dom.RangeIterator');
+goog.require('goog.dom.RangeType');
+goog.require('goog.dom.SavedRange');
+goog.require('goog.dom.TagWalkType');
+goog.require('goog.dom.TextRange');
+goog.require('goog.iter.StopIteration');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Create a new control selection with no properties. Do not use this
+ * constructor: use one of the goog.dom.Range.createFrom* methods instead.
+ * @constructor
+ * @extends {goog.dom.AbstractMultiRange}
+ * @final
+ */
+goog.dom.ControlRange = function() {
+ /**
+ * The IE control range obejct.
+ * @private {Object}
+ */
+ this.range_ = null;
+
+ /**
+ * Cached list of elements.
+ * @private {Array<Element>}
+ */
+ this.elements_ = null;
+
+ /**
+ * Cached sorted list of elements.
+ * @private {Array<Element>}
+ */
+ this.sortedElements_ = null;
+};
+goog.inherits(goog.dom.ControlRange, goog.dom.AbstractMultiRange);
+
+
+/**
+ * Create a new range wrapper from the given browser range object. Do not use
+ * this method directly - please use goog.dom.Range.createFrom* instead.
+ * @param {Object} controlRange The browser range object.
+ * @return {!goog.dom.ControlRange} A range wrapper object.
+ */
+goog.dom.ControlRange.createFromBrowserRange = function(controlRange) {
+ var range = new goog.dom.ControlRange();
+ range.range_ = controlRange;
+ return range;
+};
+
+
+/**
+ * Create a new range wrapper that selects the given element. Do not use
+ * this method directly - please use goog.dom.Range.createFrom* instead.
+ * @param {...Element} var_args The element(s) to select.
+ * @return {!goog.dom.ControlRange} A range wrapper object.
+ */
+goog.dom.ControlRange.createFromElements = function(var_args) {
+ var range = goog.dom.getOwnerDocument(arguments[0]).body.createControlRange();
+ for (var i = 0, len = arguments.length; i < len; i++) {
+ range.addElement(arguments[i]);
+ }
+ return goog.dom.ControlRange.createFromBrowserRange(range);
+};
+
+
+// Method implementations
+
+
+/**
+ * Clear cached values.
+ * @private
+ */
+goog.dom.ControlRange.prototype.clearCachedValues_ = function() {
+ this.elements_ = null;
+ this.sortedElements_ = null;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.clone = function() {
+ return goog.dom.ControlRange.createFromElements.apply(this,
+ this.getElements());
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getType = function() {
+ return goog.dom.RangeType.CONTROL;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getBrowserRangeObject = function() {
+ return this.range_ || document.body.createControlRange();
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.setBrowserRangeObject = function(nativeRange) {
+ if (!goog.dom.AbstractRange.isNativeControlRange(nativeRange)) {
+ return false;
+ }
+ this.range_ = nativeRange;
+ return true;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getTextRangeCount = function() {
+ return this.range_ ? this.range_.length : 0;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getTextRange = function(i) {
+ return goog.dom.TextRange.createFromNodeContents(this.range_.item(i));
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getContainer = function() {
+ return goog.dom.findCommonAncestor.apply(null, this.getElements());
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getStartNode = function() {
+ return this.getSortedElements()[0];
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getStartOffset = function() {
+ return 0;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getEndNode = function() {
+ var sorted = this.getSortedElements();
+ var startsLast = /** @type {Node} */ (goog.array.peek(sorted));
+ return /** @type {Node} */ (goog.array.find(sorted, function(el) {
+ return goog.dom.contains(el, startsLast);
+ }));
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getEndOffset = function() {
+ return this.getEndNode().childNodes.length;
+};
+
+
+// TODO(robbyw): Figure out how to unify getElements with TextRange API.
+/**
+ * @return {!Array<Element>} Array of elements in the control range.
+ */
+goog.dom.ControlRange.prototype.getElements = function() {
+ if (!this.elements_) {
+ this.elements_ = [];
+ if (this.range_) {
+ for (var i = 0; i < this.range_.length; i++) {
+ this.elements_.push(this.range_.item(i));
+ }
+ }
+ }
+
+ return this.elements_;
+};
+
+
+/**
+ * @return {!Array<Element>} Array of elements comprising the control range,
+ * sorted by document order.
+ */
+goog.dom.ControlRange.prototype.getSortedElements = function() {
+ if (!this.sortedElements_) {
+ this.sortedElements_ = this.getElements().concat();
+ this.sortedElements_.sort(function(a, b) {
+ return a.sourceIndex - b.sourceIndex;
+ });
+ }
+
+ return this.sortedElements_;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.isRangeInDocument = function() {
+ var returnValue = false;
+
+ try {
+ returnValue = goog.array.every(this.getElements(), function(element) {
+ // On IE, this throws an exception when the range is detached.
+ return goog.userAgent.IE ?
+ !!element.parentNode :
+ goog.dom.contains(element.ownerDocument.body, element);
+ });
+ } catch (e) {
+ // IE sometimes throws Invalid Argument errors for detached elements.
+ // Note: trying to return a value from the above try block can cause IE
+ // to crash. It is necessary to use the local returnValue.
+ }
+
+ return returnValue;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.isCollapsed = function() {
+ return !this.range_ || !this.range_.length;
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getText = function() {
+ // TODO(robbyw): What about for table selections? Should those have text?
+ return '';
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getHtmlFragment = function() {
+ return goog.array.map(this.getSortedElements(), goog.dom.getOuterHtml).
+ join('');
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getValidHtml = function() {
+ return this.getHtmlFragment();
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.getPastableHtml =
+ goog.dom.ControlRange.prototype.getValidHtml;
+
+
+/** @override */
+goog.dom.ControlRange.prototype.__iterator__ = function(opt_keys) {
+ return new goog.dom.ControlRangeIterator(this);
+};
+
+
+// RANGE ACTIONS
+
+
+/** @override */
+goog.dom.ControlRange.prototype.select = function() {
+ if (this.range_) {
+ this.range_.select();
+ }
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.removeContents = function() {
+ // TODO(robbyw): Test implementing with execCommand('Delete')
+ if (this.range_) {
+ var nodes = [];
+ for (var i = 0, len = this.range_.length; i < len; i++) {
+ nodes.push(this.range_.item(i));
+ }
+ goog.array.forEach(nodes, goog.dom.removeNode);
+
+ this.collapse(false);
+ }
+};
+
+
+/** @override */
+goog.dom.ControlRange.prototype.replaceContentsWithNode = function(node) {
+ // Control selections have to have the node inserted before removing the
+ // selection contents because a collapsed control range doesn't have start or
+ // end nodes.
+ var result = this.insertNode(node, true);
+
+ if (!this.isCollapsed()) {
+ this.removeContents();
+ }
+
+ return result;
+};
+
+
+// SAVE/RESTORE
+
+
+/** @override */
+goog.dom.ControlRange.prototype.saveUsingDom = function() {
+ return new goog.dom.DomSavedControlRange_(this);
+};
+
+
+// RANGE MODIFICATION
+
+
+/** @override */
+goog.dom.ControlRange.prototype.collapse = function(toAnchor) {
+ // TODO(robbyw): Should this return a text range? If so, API needs to change.
+ this.range_ = null;
+ this.clearCachedValues_();
+};
+
+
+// SAVED RANGE OBJECTS
+
+
+
+/**
+ * A SavedRange implementation using DOM endpoints.
+ * @param {goog.dom.ControlRange} range The range to save.
+ * @constructor
+ * @extends {goog.dom.SavedRange}
+ * @private
+ */
+goog.dom.DomSavedControlRange_ = function(range) {
+ /**
+ * The element list.
+ * @type {Array<Element>}
+ * @private
+ */
+ this.elements_ = range.getElements();
+};
+goog.inherits(goog.dom.DomSavedControlRange_, goog.dom.SavedRange);
+
+
+/** @override */
+goog.dom.DomSavedControlRange_.prototype.restoreInternal = function() {
+ var doc = this.elements_.length ?
+ goog.dom.getOwnerDocument(this.elements_[0]) : document;
+ var controlRange = doc.body.createControlRange();
+ for (var i = 0, len = this.elements_.length; i < len; i++) {
+ controlRange.addElement(this.elements_[i]);
+ }
+ return goog.dom.ControlRange.createFromBrowserRange(controlRange);
+};
+
+
+/** @override */
+goog.dom.DomSavedControlRange_.prototype.disposeInternal = function() {
+ goog.dom.DomSavedControlRange_.superClass_.disposeInternal.call(this);
+ delete this.elements_;
+};
+
+
+// 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 {goog.dom.ControlRange?} range The range to traverse.
+ * @constructor
+ * @extends {goog.dom.RangeIterator}
+ * @final
+ */
+goog.dom.ControlRangeIterator = function(range) {
+ /**
+ * The first node in the selection.
+ * @private {Node}
+ */
+ this.startNode_ = null;
+
+ /**
+ * The last node in the selection.
+ * @private {Node}
+ */
+ this.endNode_ = null;
+
+ /**
+ * The list of elements left to traverse.
+ * @private {Array<Element>?}
+ */
+ this.elements_ = null;
+
+ if (range) {
+ this.elements_ = range.getSortedElements();
+ this.startNode_ = this.elements_.shift();
+ this.endNode_ = /** @type {Node} */ (goog.array.peek(this.elements_)) ||
+ this.startNode_;
+ }
+
+ goog.dom.ControlRangeIterator.base(
+ this, 'constructor', this.startNode_, false);
+};
+goog.inherits(goog.dom.ControlRangeIterator, goog.dom.RangeIterator);
+
+
+/** @override */
+goog.dom.ControlRangeIterator.prototype.getStartTextOffset = function() {
+ return 0;
+};
+
+
+/** @override */
+goog.dom.ControlRangeIterator.prototype.getEndTextOffset = function() {
+ return 0;
+};
+
+
+/** @override */
+goog.dom.ControlRangeIterator.prototype.getStartNode = function() {
+ return this.startNode_;
+};
+
+
+/** @override */
+goog.dom.ControlRangeIterator.prototype.getEndNode = function() {
+ return this.endNode_;
+};
+
+
+/** @override */
+goog.dom.ControlRangeIterator.prototype.isLast = function() {
+ return !this.depth && !this.elements_.length;
+};
+
+
+/**
+ * Move to the next position in the selection.
+ * Throws {@code goog.iter.StopIteration} when it passes the end of the range.
+ * @return {Node} The node at the next position.
+ * @override
+ */
+goog.dom.ControlRangeIterator.prototype.next = function() {
+ // Iterate over each element in the range, and all of its children.
+ if (this.isLast()) {
+ throw goog.iter.StopIteration;
+ } else if (!this.depth) {
+ var el = this.elements_.shift();
+ this.setPosition(el,
+ goog.dom.TagWalkType.START_TAG,
+ goog.dom.TagWalkType.START_TAG);
+ return el;
+ }
+
+ // Call the super function.
+ return goog.dom.ControlRangeIterator.superClass_.next.call(this);
+};
+
+
+/** @override */
+goog.dom.ControlRangeIterator.prototype.copyFrom = function(other) {
+ this.elements_ = other.elements_;
+ this.startNode_ = other.startNode_;
+ this.endNode_ = other.endNode_;
+
+ goog.dom.ControlRangeIterator.superClass_.copyFrom.call(this, other);
+};
+
+
+/**
+ * @return {!goog.dom.ControlRangeIterator} An identical iterator.
+ * @override
+ */
+goog.dom.ControlRangeIterator.prototype.clone = function() {
+ var copy = new goog.dom.ControlRangeIterator(null);
+ copy.copyFrom(this);
+ return copy;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/dataset.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/dataset.js b/externs/GCL/externs/goog/dom/dataset.js
new file mode 100644
index 0000000..6f24587
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/dataset.js
@@ -0,0 +1,154 @@
+// Copyright 2009 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 adding, removing and setting values in
+ * an Element's dataset.
+ * See {@link http://www.w3.org/TR/html5/Overview.html#dom-dataset}.
+ *
+ * @author nicksay@google.com (Alex Nicksay)
+ */
+
+goog.provide('goog.dom.dataset');
+
+goog.require('goog.string');
+goog.require('goog.userAgent.product');
+
+
+/**
+ * Whether using the dataset property is allowed. In IE (up to and including
+ * IE 11), setting element.dataset in JS does not propagate values to CSS,
+ * breaking expressions such as `content: attr(data-content)` that would
+ * otherwise work.
+ * See {@link https://github.com/google/closure-library/issues/396}.
+ * @const
+ * @private
+ */
+goog.dom.dataset.ALLOWED_ = !goog.userAgent.product.IE;
+
+
+/**
+ * The DOM attribute name prefix that must be present for it to be considered
+ * for a dataset.
+ * @type {string}
+ * @const
+ * @private
+ */
+goog.dom.dataset.PREFIX_ = 'data-';
+
+
+/**
+ * Sets a custom data attribute on an element. The key should be
+ * in camelCase format (e.g "keyName" for the "data-key-name" attribute).
+ * @param {Element} element DOM node to set the custom data attribute on.
+ * @param {string} key Key for the custom data attribute.
+ * @param {string} value Value for the custom data attribute.
+ */
+goog.dom.dataset.set = function(element, key, value) {
+ if (goog.dom.dataset.ALLOWED_ && element.dataset) {
+ element.dataset[key] = value;
+ } else {
+ element.setAttribute(
+ goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key),
+ value);
+ }
+};
+
+
+/**
+ * Gets a custom data attribute from an element. The key should be
+ * in camelCase format (e.g "keyName" for the "data-key-name" attribute).
+ * @param {Element} element DOM node to get the custom data attribute from.
+ * @param {string} key Key for the custom data attribute.
+ * @return {?string} The attribute value, if it exists.
+ */
+goog.dom.dataset.get = function(element, key) {
+ if (goog.dom.dataset.ALLOWED_ && element.dataset) {
+ // Android browser (non-chrome) returns the empty string for
+ // element.dataset['doesNotExist'].
+ if (!(key in element.dataset)) {
+ return null;
+ }
+ return element.dataset[key];
+ } else {
+ return element.getAttribute(goog.dom.dataset.PREFIX_ +
+ goog.string.toSelectorCase(key));
+ }
+};
+
+
+/**
+ * Removes a custom data attribute from an element. The key should be
+ * in camelCase format (e.g "keyName" for the "data-key-name" attribute).
+ * @param {Element} element DOM node to get the custom data attribute from.
+ * @param {string} key Key for the custom data attribute.
+ */
+goog.dom.dataset.remove = function(element, key) {
+ if (goog.dom.dataset.ALLOWED_ && element.dataset) {
+ delete element.dataset[key];
+ } else {
+ element.removeAttribute(goog.dom.dataset.PREFIX_ +
+ goog.string.toSelectorCase(key));
+ }
+};
+
+
+/**
+ * Checks whether custom data attribute exists on an element. The key should be
+ * in camelCase format (e.g "keyName" for the "data-key-name" attribute).
+ *
+ * @param {Element} element DOM node to get the custom data attribute from.
+ * @param {string} key Key for the custom data attribute.
+ * @return {boolean} Whether the attribute exists.
+ */
+goog.dom.dataset.has = function(element, key) {
+ if (goog.dom.dataset.ALLOWED_ && element.dataset) {
+ return key in element.dataset;
+ } else if (element.hasAttribute) {
+ return element.hasAttribute(goog.dom.dataset.PREFIX_ +
+ goog.string.toSelectorCase(key));
+ } else {
+ return !!(element.getAttribute(goog.dom.dataset.PREFIX_ +
+ goog.string.toSelectorCase(key)));
+ }
+};
+
+
+/**
+ * Gets all custom data attributes as a string map. The attribute names will be
+ * camel cased (e.g., data-foo-bar -> dataset['fooBar']). This operation is not
+ * safe for attributes having camel-cased names clashing with already existing
+ * properties (e.g., data-to-string -> dataset['toString']).
+ * @param {!Element} element DOM node to get the data attributes from.
+ * @return {!Object} The string map containing data attributes and their
+ * respective values.
+ */
+goog.dom.dataset.getAll = function(element) {
+ if (goog.dom.dataset.ALLOWED_ && element.dataset) {
+ return element.dataset;
+ } else {
+ var dataset = {};
+ var attributes = element.attributes;
+ for (var i = 0; i < attributes.length; ++i) {
+ var attribute = attributes[i];
+ if (goog.string.startsWith(attribute.name,
+ goog.dom.dataset.PREFIX_)) {
+ // We use substr(5), since it's faster than replacing 'data-' with ''.
+ var key = goog.string.toCamelCase(attribute.name.substr(5));
+ dataset[key] = attribute.value;
+ }
+ }
+ return dataset;
+ }
+};
[24/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/abstractdialogplugin.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/abstractdialogplugin.js b/externs/GCL/externs/goog/editor/plugins/abstractdialogplugin.js
new file mode 100644
index 0000000..278277e
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/abstractdialogplugin.js
@@ -0,0 +1,333 @@
+// 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 abstract superclass for TrogEdit dialog plugins. Each
+ * Trogedit dialog has its own plugin.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.plugins.AbstractDialogPlugin');
+goog.provide('goog.editor.plugins.AbstractDialogPlugin.EventType');
+
+goog.require('goog.dom');
+goog.require('goog.dom.Range');
+goog.require('goog.editor.Field');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.range');
+goog.require('goog.events');
+goog.require('goog.ui.editor.AbstractDialog');
+
+
+// *** Public interface ***************************************************** //
+
+
+
+/**
+ * An abstract superclass for a Trogedit plugin that creates exactly one
+ * dialog. By default dialogs are not reused -- each time execCommand is called,
+ * a new instance of the dialog object is created (and the old one disposed of).
+ * To enable reusing of the dialog object, subclasses should call
+ * setReuseDialog() after calling the superclass constructor.
+ * @param {string} command The command that this plugin handles.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ */
+goog.editor.plugins.AbstractDialogPlugin = function(command) {
+ goog.editor.Plugin.call(this);
+ this.command_ = command;
+};
+goog.inherits(goog.editor.plugins.AbstractDialogPlugin, goog.editor.Plugin);
+
+
+/** @override */
+goog.editor.plugins.AbstractDialogPlugin.prototype.isSupportedCommand =
+ function(command) {
+ return command == this.command_;
+};
+
+
+/**
+ * Handles execCommand. Dialog plugins don't make any changes when they open a
+ * dialog, just when the dialog closes (because only modal dialogs are
+ * supported). Hence this method does not dispatch the change events that the
+ * superclass method does.
+ * @param {string} command The command to execute.
+ * @param {...*} var_args Any additional parameters needed to
+ * execute the command.
+ * @return {*} The result of the execCommand, if any.
+ * @override
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.execCommand = function(
+ command, var_args) {
+ return this.execCommandInternal.apply(this, arguments);
+};
+
+
+// *** Events *************************************************************** //
+
+
+/**
+ * Event type constants for events the dialog plugins fire.
+ * @enum {string}
+ */
+goog.editor.plugins.AbstractDialogPlugin.EventType = {
+ // This event is fired when a dialog has been opened.
+ OPENED: 'dialogOpened',
+ // This event is fired when a dialog has been closed.
+ CLOSED: 'dialogClosed'
+};
+
+
+// *** Protected interface ************************************************** //
+
+
+/**
+ * Creates a new instance of this plugin's dialog. Must be overridden by
+ * subclasses.
+ * @param {!goog.dom.DomHelper} dialogDomHelper The dom helper to be used to
+ * create the dialog.
+ * @param {*=} opt_arg The dialog specific argument. Concrete subclasses should
+ * declare a specific type.
+ * @return {goog.ui.editor.AbstractDialog} The newly created dialog.
+ * @protected
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.createDialog =
+ goog.abstractMethod;
+
+
+/**
+ * Returns the current dialog that was created and opened by this plugin.
+ * @return {goog.ui.editor.AbstractDialog} The current dialog that was created
+ * and opened by this plugin.
+ * @protected
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.getDialog = function() {
+ return this.dialog_;
+};
+
+
+/**
+ * Sets whether this plugin should reuse the same instance of the dialog each
+ * time execCommand is called or create a new one. This is intended for use by
+ * subclasses only, hence protected.
+ * @param {boolean} reuse Whether to reuse the dialog.
+ * @protected
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.setReuseDialog =
+ function(reuse) {
+ this.reuseDialog_ = reuse;
+};
+
+
+/**
+ * Handles execCommand by opening the dialog. Dispatches
+ * {@link goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED} after the
+ * dialog is shown.
+ * @param {string} command The command to execute.
+ * @param {*=} opt_arg The dialog specific argument. Should be the same as
+ * {@link createDialog}.
+ * @return {*} Always returns true, indicating the dialog was shown.
+ * @protected
+ * @override
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.execCommandInternal =
+ function(command, opt_arg) {
+ // If this plugin should not reuse dialog instances, first dispose of the
+ // previous dialog.
+ if (!this.reuseDialog_) {
+ this.disposeDialog_();
+ }
+ // If there is no dialog yet (or we aren't reusing the previous one), create
+ // one.
+ if (!this.dialog_) {
+ this.dialog_ = this.createDialog(
+ // TODO(user): Add Field.getAppDomHelper. (Note dom helper will
+ // need to be updated if setAppWindow is called by clients.)
+ goog.dom.getDomHelper(this.getFieldObject().getAppWindow()),
+ opt_arg);
+ }
+
+ // Since we're opening a dialog, we need to clear the selection because the
+ // focus will be going to the dialog, and if we leave an selection in the
+ // editor while another selection is active in the dialog as the user is
+ // typing, some browsers will screw up the original selection. But first we
+ // save it so we can restore it when the dialog closes.
+ // getRange may return null if there is no selection in the field.
+ var tempRange = this.getFieldObject().getRange();
+ // saveUsingDom() did not work as well as saveUsingNormalizedCarets(),
+ // not sure why.
+ this.savedRange_ = tempRange && goog.editor.range.saveUsingNormalizedCarets(
+ tempRange);
+ goog.dom.Range.clearSelection(
+ this.getFieldObject().getEditableDomHelper().getWindow());
+
+ // Listen for the dialog closing so we can clean up.
+ goog.events.listenOnce(this.dialog_,
+ goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE,
+ this.handleAfterHide,
+ false,
+ this);
+
+ this.getFieldObject().setModalMode(true);
+ this.dialog_.show();
+ this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED);
+
+ // Since the selection has left the document, dispatch a selection
+ // change event.
+ this.getFieldObject().dispatchSelectionChangeEvent();
+
+ return true;
+};
+
+
+/**
+ * Cleans up after the dialog has closed, including restoring the selection to
+ * what it was before the dialog was opened. If a subclass modifies the editable
+ * field's content such that the original selection is no longer valid (usually
+ * the case when the user clicks OK, and sometimes also on Cancel), it is that
+ * subclass' responsibility to place the selection in the desired place during
+ * the OK or Cancel (or other) handler. In that case, this method will leave the
+ * selection in place.
+ * @param {goog.events.Event} e The AFTER_HIDE event object.
+ * @protected
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.handleAfterHide = function(
+ e) {
+ this.getFieldObject().setModalMode(false);
+ this.restoreOriginalSelection();
+
+ if (!this.reuseDialog_) {
+ this.disposeDialog_();
+ }
+
+ this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.CLOSED);
+
+ // Since the selection has returned to the document, dispatch a selection
+ // change event.
+ this.getFieldObject().dispatchSelectionChangeEvent();
+
+ // When the dialog closes due to pressing enter or escape, that happens on the
+ // keydown event. But the browser will still fire a keyup event after that,
+ // which is caught by the editable field and causes it to try to fire a
+ // selection change event. To avoid that, we "debounce" the selection change
+ // event, meaning the editable field will not fire that event if the keyup
+ // that caused it immediately after this dialog was hidden ("immediately"
+ // means a small number of milliseconds defined by the editable field).
+ this.getFieldObject().debounceEvent(
+ goog.editor.Field.EventType.SELECTIONCHANGE);
+};
+
+
+/**
+ * Restores the selection in the editable field to what it was before the dialog
+ * was opened. This is not guaranteed to work if the contents of the field
+ * have changed.
+ * @protected
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.restoreOriginalSelection =
+ function() {
+ this.getFieldObject().restoreSavedRange(this.savedRange_);
+ this.savedRange_ = null;
+};
+
+
+/**
+ * Cleans up the structure used to save the original selection before the dialog
+ * was opened. Should be used by subclasses that don't restore the original
+ * selection via restoreOriginalSelection.
+ * @protected
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.disposeOriginalSelection =
+ function() {
+ if (this.savedRange_) {
+ this.savedRange_.dispose();
+ this.savedRange_ = null;
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.AbstractDialogPlugin.prototype.disposeInternal =
+ function() {
+ this.disposeDialog_();
+ goog.editor.plugins.AbstractDialogPlugin.base(this, 'disposeInternal');
+};
+
+
+// *** Private implementation *********************************************** //
+
+
+/**
+ * The command that this plugin handles.
+ * @type {string}
+ * @private
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.command_;
+
+
+/**
+ * The current dialog that was created and opened by this plugin.
+ * @type {goog.ui.editor.AbstractDialog}
+ * @private
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.dialog_;
+
+
+/**
+ * Whether this plugin should reuse the same instance of the dialog each time
+ * execCommand is called or create a new one.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.reuseDialog_ = false;
+
+
+/**
+ * Mutex to prevent recursive calls to disposeDialog_.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.isDisposingDialog_ = false;
+
+
+/**
+ * SavedRange representing the selection before the dialog was opened.
+ * @type {goog.dom.SavedRange}
+ * @private
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.savedRange_;
+
+
+/**
+ * Disposes of the dialog if needed. It is this abstract class' responsibility
+ * to dispose of the dialog. The "if needed" refers to the fact this method
+ * might be called twice (nested calls, not sequential) in the dispose flow, so
+ * if the dialog was already disposed once it should not be disposed again.
+ * @private
+ */
+goog.editor.plugins.AbstractDialogPlugin.prototype.disposeDialog_ = function() {
+ // Wrap disposing the dialog in a mutex. Otherwise disposing it would cause it
+ // to get hidden (if it is still open) and fire AFTER_HIDE, which in
+ // turn would cause the dialog to be disposed again (closure only flags an
+ // object as disposed after the dispose call chain completes, so it doesn't
+ // prevent recursive dispose calls).
+ if (this.dialog_ && !this.isDisposingDialog_) {
+ this.isDisposingDialog_ = true;
+ this.dialog_.dispose();
+ this.dialog_ = null;
+ this.isDisposingDialog_ = false;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/abstracttabhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/abstracttabhandler.js b/externs/GCL/externs/goog/editor/plugins/abstracttabhandler.js
new file mode 100644
index 0000000..de1a13a
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/abstracttabhandler.js
@@ -0,0 +1,78 @@
+// 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 Abstract Editor plugin class to handle tab keys. Has one
+ * abstract method which should be overriden to handle a tab key press.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.AbstractTabHandler');
+
+goog.require('goog.editor.Plugin');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Plugin to handle tab keys. Specific tab behavior defined by subclasses.
+ *
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ */
+goog.editor.plugins.AbstractTabHandler = function() {
+ goog.editor.Plugin.call(this);
+};
+goog.inherits(goog.editor.plugins.AbstractTabHandler, goog.editor.Plugin);
+
+
+/** @override */
+goog.editor.plugins.AbstractTabHandler.prototype.getTrogClassId =
+ goog.abstractMethod;
+
+
+/** @override */
+goog.editor.plugins.AbstractTabHandler.prototype.handleKeyboardShortcut =
+ function(e, key, isModifierPressed) {
+ // If a dialog doesn't have selectable field, Moz grabs the event and
+ // performs actions in editor window. This solves that problem and allows
+ // the event to be passed on to proper handlers.
+ if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) {
+ return false;
+ }
+
+ // Don't handle Ctrl+Tab since the user is most likely trying to switch
+ // browser tabs. See bug 1305086.
+ // FF3 on Mac sends Ctrl-Tab to trogedit and we end up inserting a tab, but
+ // then it also switches the tabs. See bug 1511681. Note that we don't use
+ // isModifierPressed here since isModifierPressed is true only if metaKey
+ // is true on Mac.
+ if (e.keyCode == goog.events.KeyCodes.TAB && !e.metaKey && !e.ctrlKey) {
+ return this.handleTabKey(e);
+ }
+
+ return false;
+};
+
+
+/**
+ * Handle a tab key press.
+ * @param {goog.events.Event} e The key event.
+ * @return {boolean} Whether this event was handled by this plugin.
+ * @protected
+ */
+goog.editor.plugins.AbstractTabHandler.prototype.handleTabKey =
+ goog.abstractMethod;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/basictextformatter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/basictextformatter.js b/externs/GCL/externs/goog/editor/plugins/basictextformatter.js
new file mode 100644
index 0000000..1cac1cd
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/basictextformatter.js
@@ -0,0 +1,1769 @@
+// 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 Functions to style text.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.plugins.BasicTextFormatter');
+goog.provide('goog.editor.plugins.BasicTextFormatter.COMMAND');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Link');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.node');
+goog.require('goog.editor.range');
+goog.require('goog.editor.style');
+goog.require('goog.iter');
+goog.require('goog.iter.StopIteration');
+goog.require('goog.log');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.string.Unicode');
+goog.require('goog.style');
+goog.require('goog.ui.editor.messages');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Functions to style text (e.g. underline, make bold, etc.)
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ */
+goog.editor.plugins.BasicTextFormatter = function() {
+ goog.editor.Plugin.call(this);
+};
+goog.inherits(goog.editor.plugins.BasicTextFormatter, goog.editor.Plugin);
+
+
+/** @override */
+goog.editor.plugins.BasicTextFormatter.prototype.getTrogClassId = function() {
+ return 'BTF';
+};
+
+
+/**
+ * Logging object.
+ * @type {goog.log.Logger}
+ * @protected
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.logger =
+ goog.log.getLogger('goog.editor.plugins.BasicTextFormatter');
+
+
+/**
+ * Commands implemented by this plugin.
+ * @enum {string}
+ */
+goog.editor.plugins.BasicTextFormatter.COMMAND = {
+ LINK: '+link',
+ FORMAT_BLOCK: '+formatBlock',
+ INDENT: '+indent',
+ OUTDENT: '+outdent',
+ STRIKE_THROUGH: '+strikeThrough',
+ HORIZONTAL_RULE: '+insertHorizontalRule',
+ SUBSCRIPT: '+subscript',
+ SUPERSCRIPT: '+superscript',
+ UNDERLINE: '+underline',
+ BOLD: '+bold',
+ ITALIC: '+italic',
+ FONT_SIZE: '+fontSize',
+ FONT_FACE: '+fontName',
+ FONT_COLOR: '+foreColor',
+ BACKGROUND_COLOR: '+backColor',
+ ORDERED_LIST: '+insertOrderedList',
+ UNORDERED_LIST: '+insertUnorderedList',
+ JUSTIFY_CENTER: '+justifyCenter',
+ JUSTIFY_FULL: '+justifyFull',
+ JUSTIFY_RIGHT: '+justifyRight',
+ JUSTIFY_LEFT: '+justifyLeft'
+};
+
+
+/**
+ * Inverse map of execCommand strings to
+ * {@link goog.editor.plugins.BasicTextFormatter.COMMAND} constants. Used to
+ * determine whether a string corresponds to a command this plugin
+ * handles in O(1) time.
+ * @type {Object}
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_ =
+ goog.object.transpose(goog.editor.plugins.BasicTextFormatter.COMMAND);
+
+
+/**
+ * Whether the string corresponds to a command this plugin handles.
+ * @param {string} command Command string to check.
+ * @return {boolean} Whether the string corresponds to a command
+ * this plugin handles.
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.isSupportedCommand = function(
+ command) {
+ // TODO(user): restore this to simple check once table editing
+ // is moved out into its own plugin
+ return command in goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_;
+};
+
+
+/**
+ * @return {goog.dom.AbstractRange} The closure range object that wraps the
+ * current user selection.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.getRange_ = function() {
+ return this.getFieldObject().getRange();
+};
+
+
+/**
+ * @return {!Document} The document object associated with the currently active
+ * field.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.getDocument_ = function() {
+ return this.getFieldDomHelper().getDocument();
+};
+
+
+/**
+ * Execute a user-initiated command.
+ * @param {string} command Command to execute.
+ * @param {...*} var_args For color commands, this
+ * should be the hex color (with the #). For FORMAT_BLOCK, this should be
+ * the goog.editor.plugins.BasicTextFormatter.BLOCK_COMMAND.
+ * It will be unused for other commands.
+ * @return {Object|undefined} The result of the command.
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.execCommandInternal = function(
+ command, var_args) {
+ var preserveDir, styleWithCss, needsFormatBlockDiv, hasDummySelection;
+ var result;
+ var opt_arg = arguments[1];
+
+ switch (command) {
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.BACKGROUND_COLOR:
+ // Don't bother for no color selected, color picker is resetting itself.
+ if (!goog.isNull(opt_arg)) {
+ if (goog.editor.BrowserFeature.EATS_EMPTY_BACKGROUND_COLOR) {
+ this.applyBgColorManually_(opt_arg);
+ } else if (goog.userAgent.OPERA) {
+ // backColor will color the block level element instead of
+ // the selected span of text in Opera.
+ this.execCommandHelper_('hiliteColor', opt_arg);
+ } else {
+ this.execCommandHelper_(command, opt_arg);
+ }
+ }
+ break;
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.LINK:
+ result = this.toggleLink_(opt_arg);
+ break;
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT:
+ this.justify_(command);
+ break;
+
+ default:
+ if (goog.userAgent.IE &&
+ command ==
+ goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK &&
+ opt_arg) {
+ // IE requires that the argument be in the form of an opening
+ // tag, like <h1>, including angle brackets. WebKit will accept
+ // the arguemnt with or without brackets, and Firefox pre-3 supports
+ // only a fixed subset of tags with brackets, and prefers without.
+ // So we only add them IE only.
+ opt_arg = '<' + opt_arg + '>';
+ }
+
+ if (command ==
+ goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR &&
+ goog.isNull(opt_arg)) {
+ // If we don't have a color, then FONT_COLOR is a no-op.
+ break;
+ }
+
+ switch (command) {
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.INDENT:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT:
+ if (goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS) {
+ if (goog.userAgent.GECKO) {
+ styleWithCss = true;
+ }
+ if (goog.userAgent.OPERA) {
+ if (command ==
+ goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT) {
+ // styleWithCSS actually sets negative margins on <blockquote>
+ // to outdent them. If the command is enabled without
+ // styleWithCSS flipped on, then the caret is in a blockquote so
+ // styleWithCSS must not be used. But if the command is not
+ // enabled, styleWithCSS should be used so that elements such as
+ // a <div> with a margin-left style can still be outdented.
+ // (Opera bug: CORE-21118)
+ styleWithCss =
+ !this.getDocument_().queryCommandEnabled('outdent');
+ } else {
+ // Always use styleWithCSS for indenting. Otherwise, Opera will
+ // make separate <blockquote>s around *each* indented line,
+ // which adds big default <blockquote> margins between each
+ // indented line.
+ styleWithCss = true;
+ }
+ }
+ }
+ // Fall through.
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.ORDERED_LIST:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.UNORDERED_LIST:
+ if (goog.editor.BrowserFeature.LEAVES_P_WHEN_REMOVING_LISTS &&
+ this.queryCommandStateInternal_(this.getDocument_(),
+ command)) {
+ // IE leaves behind P tags when unapplying lists.
+ // If we're not in P-mode, then we want divs
+ // So, unlistify, then convert the Ps into divs.
+ needsFormatBlockDiv = this.getFieldObject().queryCommandValue(
+ goog.editor.Command.DEFAULT_TAG) != goog.dom.TagName.P;
+ } else if (!goog.editor.BrowserFeature.CAN_LISTIFY_BR) {
+ // IE doesn't convert BRed line breaks into separate list items.
+ // So convert the BRs to divs, then do the listify.
+ this.convertBreaksToDivs_();
+ }
+
+ // This fix only works in Gecko.
+ if (goog.userAgent.GECKO &&
+ goog.editor.BrowserFeature.FORGETS_FORMATTING_WHEN_LISTIFYING &&
+ !this.queryCommandValue(command)) {
+ hasDummySelection |= this.beforeInsertListGecko_();
+ }
+ // Fall through to preserveDir block
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK:
+ // Both FF & IE may lose directionality info. Save/restore it.
+ // TODO(user): Does Safari also need this?
+ // TODO (gmark, jparent): This isn't ideal because it uses a string
+ // literal, so if the plugin name changes, it would break. We need a
+ // better solution. See also other places in code that use
+ // this.getPluginByClassId('Bidi').
+ preserveDir = !!this.getFieldObject().getPluginByClassId('Bidi');
+ break;
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT:
+ if (goog.editor.BrowserFeature.NESTS_SUBSCRIPT_SUPERSCRIPT) {
+ // This browser nests subscript and superscript when both are
+ // applied, instead of canceling out the first when applying the
+ // second.
+ this.applySubscriptSuperscriptWorkarounds_(command);
+ }
+ break;
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC:
+ // If we are applying the formatting, then we want to have
+ // styleWithCSS false so that we generate html tags (like <b>). If we
+ // are unformatting something, we want to have styleWithCSS true so
+ // that we can unformat both html tags and inline styling.
+ // TODO(user): What about WebKit and Opera?
+ styleWithCss = goog.userAgent.GECKO &&
+ goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS &&
+ this.queryCommandValue(command);
+ break;
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE:
+ // It is very expensive in FF (order of magnitude difference) to use
+ // font tags instead of styled spans. Whenever possible,
+ // force FF to use spans.
+ // Font size is very expensive too, but FF always uses font tags,
+ // regardless of which styleWithCSS value you use.
+ styleWithCss = goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS &&
+ goog.userAgent.GECKO;
+ }
+
+ /**
+ * Cases where we just use the default execCommand (in addition
+ * to the above fall-throughs)
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.STRIKE_THROUGH:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.HORIZONTAL_RULE:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE:
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE:
+ */
+ this.execCommandHelper_(command, opt_arg, preserveDir, !!styleWithCss);
+
+ if (hasDummySelection) {
+ this.getDocument_().execCommand('Delete', false, true);
+ }
+
+ if (needsFormatBlockDiv) {
+ this.getDocument_().execCommand('FormatBlock', false, '<div>');
+ }
+ }
+ // FF loses focus, so we have to set the focus back to the document or the
+ // user can't type after selecting from menu. In IE, focus is set correctly
+ // and resetting it here messes it up.
+ if (goog.userAgent.GECKO && !this.getFieldObject().inModalMode()) {
+ this.focusField_();
+ }
+ return result;
+};
+
+
+/**
+ * Focuses on the field.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.focusField_ = function() {
+ this.getFieldDomHelper().getWindow().focus();
+};
+
+
+/**
+ * Gets the command value.
+ * @param {string} command The command value to get.
+ * @return {string|boolean|null} The current value of the command in the given
+ * selection. NOTE: This return type list is not documented in MSDN or MDC
+ * and has been constructed from experience. Please update it
+ * if necessary.
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.queryCommandValue = function(
+ command) {
+ var styleWithCss;
+ switch (command) {
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.LINK:
+ return this.isNodeInState_(goog.dom.TagName.A);
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT:
+ return this.isJustification_(command);
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK:
+ // TODO(nicksantos): See if we can use queryCommandValue here.
+ return goog.editor.plugins.BasicTextFormatter.getSelectionBlockState_(
+ this.getFieldObject().getRange());
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.INDENT:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.HORIZONTAL_RULE:
+ // TODO: See if there are reasonable results to return for
+ // these commands.
+ return false;
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.BACKGROUND_COLOR:
+ // We use queryCommandValue here since we don't just want to know if a
+ // color/fontface/fontsize is applied, we want to know WHICH one it is.
+ return this.queryCommandValueInternal_(this.getDocument_(), command,
+ goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS &&
+ goog.userAgent.GECKO);
+
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD:
+ case goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC:
+ styleWithCss = goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS &&
+ goog.userAgent.GECKO;
+
+ default:
+ /**
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.STRIKE_THROUGH
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.ORDERED_LIST
+ * goog.editor.plugins.BasicTextFormatter.COMMAND.UNORDERED_LIST
+ */
+ // This only works for commands that use the default execCommand
+ return this.queryCommandStateInternal_(this.getDocument_(), command,
+ styleWithCss);
+ }
+};
+
+
+/**
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.prepareContentsHtml =
+ function(html) {
+ // If the browser collapses empty nodes and the field has only a script
+ // tag in it, then it will collapse this node. Which will mean the user
+ // can't click into it to edit it.
+ if (goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES &&
+ html.match(/^\s*<script/i)) {
+ html = ' ' + html;
+ }
+
+ if (goog.editor.BrowserFeature.CONVERT_TO_B_AND_I_TAGS) {
+ // Some browsers (FF) can't undo strong/em in some cases, but can undo b/i!
+ html = html.replace(/<(\/?)strong([^\w])/gi, '<$1b$2');
+ html = html.replace(/<(\/?)em([^\w])/gi, '<$1i$2');
+ }
+
+ return html;
+};
+
+
+/**
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.cleanContentsDom =
+ function(fieldCopy) {
+ var images = fieldCopy.getElementsByTagName(goog.dom.TagName.IMG);
+ for (var i = 0, image; image = images[i]; i++) {
+ if (goog.editor.BrowserFeature.SHOWS_CUSTOM_ATTRS_IN_INNER_HTML) {
+ // Only need to remove these attributes in IE because
+ // Firefox and Safari don't show custom attributes in the innerHTML.
+ image.removeAttribute('tabIndex');
+ image.removeAttribute('tabIndexSet');
+ goog.removeUid(image);
+
+ // Declare oldTypeIndex for the compiler. The associated plugin may not be
+ // included in the compiled bundle.
+ /** @type {string} */ image.oldTabIndex;
+
+ // oldTabIndex will only be set if
+ // goog.editor.BrowserFeature.TABS_THROUGH_IMAGES is true and we're in
+ // P-on-enter mode.
+ if (image.oldTabIndex) {
+ image.tabIndex = image.oldTabIndex;
+ }
+ }
+ }
+};
+
+
+/**
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.cleanContentsHtml =
+ function(html) {
+ if (goog.editor.BrowserFeature.MOVES_STYLE_TO_HEAD) {
+ // Safari creates a new <head> element for <style> tags, so prepend their
+ // contents to the output.
+ var heads = this.getFieldObject().getEditableDomHelper().
+ getElementsByTagNameAndClass(goog.dom.TagName.HEAD);
+ var stylesHtmlArr = [];
+
+ // i starts at 1 so we don't copy in the original, legitimate <head>.
+ var numHeads = heads.length;
+ for (var i = 1; i < numHeads; ++i) {
+ var styles = heads[i].getElementsByTagName(goog.dom.TagName.STYLE);
+ var numStyles = styles.length;
+ for (var j = 0; j < numStyles; ++j) {
+ stylesHtmlArr.push(styles[j].outerHTML);
+ }
+ }
+ return stylesHtmlArr.join('') + html;
+ }
+
+ return html;
+};
+
+
+/**
+ * @override
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.handleKeyboardShortcut =
+ function(e, key, isModifierPressed) {
+ if (!isModifierPressed) {
+ return false;
+ }
+ var command;
+ switch (key) {
+ case 'b': // Ctrl+B
+ command = goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD;
+ break;
+ case 'i': // Ctrl+I
+ command = goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC;
+ break;
+ case 'u': // Ctrl+U
+ command = goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE;
+ break;
+ case 's': // Ctrl+S
+ // TODO(user): This doesn't belong in here. Clients should handle
+ // this themselves.
+ // Catching control + s prevents the annoying browser save dialog
+ // from appearing.
+ return true;
+ }
+
+ if (command) {
+ this.getFieldObject().execCommand(command);
+ return true;
+ }
+
+ return false;
+};
+
+
+// Helpers for execCommand
+
+
+/**
+ * Regular expression to match BRs in HTML. Saves the BRs' attributes in $1 for
+ * use with replace(). In non-IE browsers, does not match BRs adjacent to an
+ * opening or closing DIV or P tag, since nonrendered BR elements can occur at
+ * the end of block level containers in those browsers' editors.
+ * @type {RegExp}
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.BR_REGEXP_ =
+ goog.userAgent.IE ? /<br([^\/>]*)\/?>/gi :
+ /<br([^\/>]*)\/?>(?!<\/(div|p)>)/gi;
+
+
+/**
+ * Convert BRs in the selection to divs.
+ * This is only intended to be used in IE and Opera.
+ * @return {boolean} Whether any BR's were converted.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.convertBreaksToDivs_ =
+ function() {
+ if (!goog.userAgent.IE && !goog.userAgent.OPERA) {
+ // This function is only supported on IE and Opera.
+ return false;
+ }
+ var range = this.getRange_();
+ var parent = range.getContainerElement();
+ var doc = this.getDocument_();
+
+ goog.editor.plugins.BasicTextFormatter.BR_REGEXP_.lastIndex = 0;
+ // Only mess with the HTML/selection if it contains a BR.
+ if (goog.editor.plugins.BasicTextFormatter.BR_REGEXP_.test(
+ parent.innerHTML)) {
+ // Insert temporary markers to remember the selection.
+ var savedRange = range.saveUsingCarets();
+
+ if (parent.tagName == goog.dom.TagName.P) {
+ // Can't append paragraphs to paragraph tags. Throws an exception in IE.
+ goog.editor.plugins.BasicTextFormatter.convertParagraphToDiv_(
+ parent, true);
+ } else {
+ // Used to do:
+ // IE: <div>foo<br>bar</div> --> <div>foo<p id="temp_br">bar</div>
+ // Opera: <div>foo<br>bar</div> --> <div>foo<p class="temp_br">bar</div>
+ // To fix bug 1939883, now does for both:
+ // <div>foo<br>bar</div> --> <div>foo<p trtempbr="temp_br">bar</div>
+ // TODO(user): Confirm if there's any way to skip this
+ // intermediate step of converting br's to p's before converting those to
+ // div's. The reason may be hidden in CLs 5332866 and 8530601.
+ var attribute = 'trtempbr';
+ var value = 'temp_br';
+ var newHtml = parent.innerHTML.replace(
+ goog.editor.plugins.BasicTextFormatter.BR_REGEXP_,
+ '<p$1 ' + attribute + '="' + value + '">');
+ goog.editor.node.replaceInnerHtml(parent, newHtml);
+
+ var paragraphs =
+ goog.array.toArray(parent.getElementsByTagName(goog.dom.TagName.P));
+ goog.iter.forEach(paragraphs, function(paragraph) {
+ if (paragraph.getAttribute(attribute) == value) {
+ paragraph.removeAttribute(attribute);
+ if (goog.string.isBreakingWhitespace(
+ goog.dom.getTextContent(paragraph))) {
+ // Prevent the empty blocks from collapsing.
+ // A <BR> is preferable because it doesn't result in any text being
+ // added to the "blank" line. In IE, however, it is possible to
+ // place the caret after the <br>, which effectively creates a
+ // visible line break. Because of this, we have to resort to using a
+ // in IE.
+ var child = goog.userAgent.IE ?
+ doc.createTextNode(goog.string.Unicode.NBSP) :
+ doc.createElement(goog.dom.TagName.BR);
+ paragraph.appendChild(child);
+ }
+ goog.editor.plugins.BasicTextFormatter.convertParagraphToDiv_(
+ paragraph);
+ }
+ });
+ }
+
+ // Select the previously selected text so we only listify
+ // the selected portion and maintain the user's selection.
+ savedRange.restore();
+ return true;
+ }
+
+ return false;
+};
+
+
+/**
+ * Convert the given paragraph to being a div. This clobbers the
+ * passed-in node!
+ * This is only intended to be used in IE and Opera.
+ * @param {Node} paragraph Paragragh to convert to a div.
+ * @param {boolean=} opt_convertBrs If true, also convert BRs to divs.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.convertParagraphToDiv_ =
+ function(paragraph, opt_convertBrs) {
+ if (!goog.userAgent.IE && !goog.userAgent.OPERA) {
+ // This function is only supported on IE and Opera.
+ return;
+ }
+ var outerHTML = paragraph.outerHTML.replace(/<(\/?)p/gi, '<$1div');
+ if (opt_convertBrs) {
+ // IE fills in the closing div tag if it's missing!
+ outerHTML = outerHTML.replace(
+ goog.editor.plugins.BasicTextFormatter.BR_REGEXP_,
+ '</div><div$1>');
+ }
+ if (goog.userAgent.OPERA && !/<\/div>$/i.test(outerHTML)) {
+ // Opera doesn't automatically add the closing tag, so add it if needed.
+ outerHTML += '</div>';
+ }
+ paragraph.outerHTML = outerHTML;
+};
+
+
+/**
+ * If this is a goog.editor.plugins.BasicTextFormatter.COMMAND,
+ * convert it to something that we can pass into execCommand,
+ * queryCommandState, etc.
+ *
+ * TODO(user): Consider doing away with the + and converter completely.
+ *
+ * @param {goog.editor.plugins.BasicTextFormatter.COMMAND|string}
+ * command A command key.
+ * @return {string} The equivalent execCommand command.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.convertToRealExecCommand_ = function(
+ command) {
+ return command.indexOf('+') == 0 ? command.substring(1) : command;
+};
+
+
+/**
+ * Justify the text in the selection.
+ * @param {string} command The type of justification to perform.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.justify_ = function(command) {
+ this.execCommandHelper_(command, null, false, true);
+ // Firefox cannot justify divs. In fact, justifying divs results in removing
+ // the divs and replacing them with brs. So "<div>foo</div><div>bar</div>"
+ // becomes "foo<br>bar" after alignment is applied. However, if you justify
+ // again, then you get "<div style='text-align: right'>foo<br>bar</div>",
+ // which at least looks visually correct. Since justification is (normally)
+ // idempotent, it isn't a problem when the selection does not contain divs to
+ // apply justifcation again.
+ if (goog.userAgent.GECKO) {
+ this.execCommandHelper_(command, null, false, true);
+ }
+
+ // Convert all block elements in the selection to use CSS text-align
+ // instead of the align property. This works better because the align
+ // property is overridden by the CSS text-align property.
+ //
+ // Only for browsers that can't handle this by the styleWithCSS execCommand,
+ // which allows us to specify if we should insert align or text-align.
+ // TODO(user): What about WebKit or Opera?
+ if (!(goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS &&
+ goog.userAgent.GECKO)) {
+ goog.iter.forEach(this.getFieldObject().getRange(),
+ goog.editor.plugins.BasicTextFormatter.convertContainerToTextAlign_);
+ }
+};
+
+
+/**
+ * Converts the block element containing the given node to use CSS text-align
+ * instead of the align property.
+ * @param {Node} node The node to convert the container of.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.convertContainerToTextAlign_ =
+ function(node) {
+ var container = goog.editor.style.getContainer(node);
+
+ // TODO(user): Fix this so that it doesn't screw up tables.
+ if (container.align) {
+ container.style.textAlign = container.align;
+ container.removeAttribute('align');
+ }
+};
+
+
+/**
+ * Perform an execCommand on the active document.
+ * @param {string} command The command to execute.
+ * @param {string|number|boolean|null=} opt_value Optional value.
+ * @param {boolean=} opt_preserveDir Set true to make sure that command does not
+ * change directionality of the selected text (works only if all selected
+ * text has the same directionality, otherwise ignored). Should not be true
+ * if bidi plugin is not loaded.
+ * @param {boolean=} opt_styleWithCss Set to true to ask the browser to use CSS
+ * to perform the execCommand.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.execCommandHelper_ = function(
+ command, opt_value, opt_preserveDir, opt_styleWithCss) {
+ // There is a bug in FF: some commands do not preserve attributes of the
+ // block-level elements they replace.
+ // This (among the rest) leads to loss of directionality information.
+ // For now we use a hack (when opt_preserveDir==true) to avoid this
+ // directionality problem in the simplest cases.
+ // Known affected commands: formatBlock, insertOrderedList,
+ // insertUnorderedList, indent, outdent.
+ // A similar problem occurs in IE when insertOrderedList or
+ // insertUnorderedList remove existing list.
+ var dir = null;
+ if (opt_preserveDir) {
+ dir =
+ this.getFieldObject().queryCommandValue(
+ goog.editor.Command.DIR_RTL) ? 'rtl' :
+ this.getFieldObject().queryCommandValue(
+ goog.editor.Command.DIR_LTR) ? 'ltr' :
+ null;
+ }
+
+ command = goog.editor.plugins.BasicTextFormatter.convertToRealExecCommand_(
+ command);
+
+ var endDiv, nbsp;
+ if (goog.userAgent.IE) {
+ var ret = this.applyExecCommandIEFixes_(command);
+ endDiv = ret[0];
+ nbsp = ret[1];
+ }
+
+ if (goog.userAgent.WEBKIT) {
+ endDiv = this.applyExecCommandSafariFixes_(command);
+ }
+
+ if (goog.userAgent.GECKO) {
+ this.applyExecCommandGeckoFixes_(command);
+ }
+
+ if (goog.editor.BrowserFeature.DOESNT_OVERRIDE_FONT_SIZE_IN_STYLE_ATTR &&
+ command.toLowerCase() == 'fontsize') {
+ this.removeFontSizeFromStyleAttrs_();
+ }
+
+ var doc = this.getDocument_();
+ if (opt_styleWithCss &&
+ goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS) {
+ doc.execCommand('styleWithCSS', false, true);
+ if (goog.userAgent.OPERA) {
+ this.invalidateInlineCss_();
+ }
+ }
+
+ doc.execCommand(command, false, opt_value);
+ if (opt_styleWithCss &&
+ goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS) {
+ // If we enabled styleWithCSS, turn it back off.
+ doc.execCommand('styleWithCSS', false, false);
+ }
+
+ if (goog.userAgent.WEBKIT &&
+ !goog.userAgent.isVersionOrHigher('526') &&
+ command.toLowerCase() == 'formatblock' &&
+ opt_value && /^[<]?h\d[>]?$/i.test(opt_value)) {
+ this.cleanUpSafariHeadings_();
+ }
+
+ if (/insert(un)?orderedlist/i.test(command)) {
+ // NOTE(user): This doesn't check queryCommandState because it seems to
+ // lie. Also, this runs for insertunorderedlist so that the the list
+ // isn't made up of an <ul> for each <li> - even though it looks the same,
+ // the markup is disgusting.
+ if (goog.userAgent.WEBKIT &&
+ !goog.userAgent.isVersionOrHigher(534)) {
+ this.fixSafariLists_();
+ }
+ if (goog.userAgent.IE) {
+ this.fixIELists_();
+
+ if (nbsp) {
+ // Remove the text node, if applicable. Do not try to instead clobber
+ // the contents of the text node if it was added, or the same invalid
+ // node thing as above will happen. The error won't happen here, it
+ // will happen after you hit enter and then do anything that loops
+ // through the dom and tries to read that node.
+ goog.dom.removeNode(nbsp);
+ }
+ }
+ }
+
+ if (endDiv) {
+ // Remove the dummy div.
+ goog.dom.removeNode(endDiv);
+ }
+
+ // Restore directionality if required and only when unambigous (dir!=null).
+ if (dir) {
+ this.getFieldObject().execCommand(dir);
+ }
+};
+
+
+/**
+ * Applies a background color to a selection when the browser can't do the job.
+ *
+ * NOTE(nicksantos): If you think this is hacky, you should try applying
+ * background color in Opera. It made me cry.
+ *
+ * @param {string} bgColor backgroundColor from .formatText to .execCommand.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.applyBgColorManually_ =
+ function(bgColor) {
+ var needsSpaceInTextNode = goog.userAgent.GECKO;
+ var range = this.getFieldObject().getRange();
+ var textNode;
+ var parentTag;
+ if (range && range.isCollapsed()) {
+ // Hack to handle Firefox bug:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=279330
+ // execCommand hiliteColor in Firefox on collapsed selection creates
+ // a font tag onkeypress
+ textNode = this.getFieldDomHelper().
+ createTextNode(needsSpaceInTextNode ? ' ' : '');
+
+ var containerNode = range.getStartNode();
+ // Check if we're inside a tag that contains the cursor and nothing else;
+ // if we are, don't create a dummySpan. Just use this containing tag to
+ // hide the 1-space selection.
+ // If the user sets a background color on a collapsed selection, then sets
+ // another one immediately, we get a span tag with a single empty TextNode.
+ // If the user sets a background color, types, then backspaces, we get a
+ // span tag with nothing inside it (container is the span).
+ parentTag = containerNode.nodeType == goog.dom.NodeType.ELEMENT ?
+ containerNode : containerNode.parentNode;
+
+ if (parentTag.innerHTML == '') {
+ // There's an Element to work with
+ // make the space character invisible using a CSS indent hack
+ parentTag.style.textIndent = '-10000px';
+ parentTag.appendChild(textNode);
+ } else {
+ // No Element to work with; make one
+ // create a span with a space character inside
+ // make the space character invisible using a CSS indent hack
+ parentTag = this.getFieldDomHelper().createDom(goog.dom.TagName.SPAN,
+ {'style': 'text-indent:-10000px'}, textNode);
+ range.replaceContentsWithNode(parentTag);
+ }
+ goog.dom.Range.createFromNodeContents(textNode).select();
+ }
+
+ this.execCommandHelper_('hiliteColor', bgColor, false, true);
+
+ if (textNode) {
+ // eliminate the space if necessary.
+ if (needsSpaceInTextNode) {
+ textNode.data = '';
+ }
+
+ // eliminate the hack.
+ parentTag.style.textIndent = '';
+ // execCommand modified our span so we leave it in place.
+ }
+};
+
+
+/**
+ * Toggle link for the current selection:
+ * If selection contains a link, unlink it, return null.
+ * Otherwise, make selection into a link, return the link.
+ * @param {string=} opt_target Target for the link.
+ * @return {goog.editor.Link?} The resulting link, or null if a link was
+ * removed.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.toggleLink_ = function(
+ opt_target) {
+ if (!this.getFieldObject().isSelectionEditable()) {
+ this.focusField_();
+ }
+
+ var range = this.getRange_();
+ // Since we wrap images in links, its possible that the user selected an
+ // image and clicked link, in which case we want to actually use the
+ // image as the selection.
+ var parent = range && range.getContainerElement();
+ var link = /** @type {Element} */ (
+ goog.dom.getAncestorByTagNameAndClass(parent, goog.dom.TagName.A));
+ if (link && goog.editor.node.isEditable(link)) {
+ goog.dom.flattenElement(link);
+ } else {
+ var editableLink = this.createLink_(range, '/', opt_target);
+ if (editableLink) {
+ if (!this.getFieldObject().execCommand(
+ goog.editor.Command.MODAL_LINK_EDITOR, editableLink)) {
+ var url = this.getFieldObject().getAppWindow().prompt(
+ goog.ui.editor.messages.MSG_LINK_TO, 'http://');
+ if (url) {
+ editableLink.setTextAndUrl(editableLink.getCurrentText() || url, url);
+ editableLink.placeCursorRightOf();
+ } else {
+ var savedRange = goog.editor.range.saveUsingNormalizedCarets(
+ goog.dom.Range.createFromNodeContents(editableLink.getAnchor()));
+ editableLink.removeLink();
+ savedRange.restore().select();
+ return null;
+ }
+ }
+ return editableLink;
+ }
+ }
+ return null;
+};
+
+
+/**
+ * Create a link out of the current selection. If nothing is selected, insert
+ * a new link. Otherwise, enclose the selection in a link.
+ * @param {goog.dom.AbstractRange} range The closure range object for the
+ * current selection.
+ * @param {string} url The url to link to.
+ * @param {string=} opt_target Target for the link.
+ * @return {goog.editor.Link?} The newly created link, or null if the link
+ * couldn't be created.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.createLink_ = function(range,
+ url, opt_target) {
+ var anchor = null;
+ var anchors = [];
+ var parent = range && range.getContainerElement();
+ // We do not yet support creating links around images. Instead of throwing
+ // lots of js errors, just fail silently.
+ // TODO(user): Add support for linking images.
+ if (parent && parent.tagName == goog.dom.TagName.IMG) {
+ return null;
+ }
+ // If range is not present, the editable field doesn't have focus, abort
+ // creating a link.
+ if (!range) {
+ return null;
+ }
+
+ if (range.isCollapsed()) {
+ var textRange = range.getTextRange(0).getBrowserRangeObject();
+ if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
+ anchor = this.getFieldDomHelper().createElement(goog.dom.TagName.A);
+ textRange.insertNode(anchor);
+ } else if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
+ // TODO: Use goog.dom.AbstractRange's surroundContents
+ textRange.pasteHTML("<a id='newLink'></a>");
+ anchor = this.getFieldDomHelper().getElement('newLink');
+ anchor.removeAttribute('id');
+ }
+ } else {
+ // Create a unique identifier for the link so we can retrieve it later.
+ // execCommand doesn't return the link to us, and we need a way to find
+ // the newly created link in the dom, and the url is the only property
+ // we have control over, so we set that to be unique and then find it.
+ var uniqueId = goog.string.createUniqueString();
+ this.execCommandHelper_('CreateLink', uniqueId);
+ var setHrefAndLink = function(element, index, arr) {
+ // We can't do straight comparision since the href can contain the
+ // absolute url.
+ if (goog.string.endsWith(element.href, uniqueId)) {
+ anchors.push(element);
+ }
+ };
+
+ goog.array.forEach(this.getFieldObject().getElement().getElementsByTagName(
+ goog.dom.TagName.A), setHrefAndLink);
+ if (anchors.length) {
+ anchor = anchors.pop();
+ }
+ var isLikelyUrl = function(a, i, anchors) {
+ return goog.editor.Link.isLikelyUrl(goog.dom.getRawTextContent(a));
+ };
+ if (anchors.length && goog.array.every(anchors, isLikelyUrl)) {
+ for (var i = 0, a; a = anchors[i]; i++) {
+ goog.editor.Link.createNewLinkFromText(a, opt_target);
+ }
+ anchors = null;
+ }
+ }
+
+ return goog.editor.Link.createNewLink(
+ /** @type {HTMLAnchorElement} */ (anchor), url, opt_target, anchors);
+};
+
+
+//---------------------------------------------------------------------
+// browser fixes
+
+
+/**
+ * The following execCommands are "broken" in some way - in IE they allow
+ * the nodes outside the contentEditable region to get modified (see
+ * execCommand below for more details).
+ * @const
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.brokenExecCommandsIE_ = {
+ 'indent' : 1,
+ 'outdent' : 1,
+ 'insertOrderedList' : 1,
+ 'insertUnorderedList' : 1,
+ 'justifyCenter' : 1,
+ 'justifyFull' : 1,
+ 'justifyRight': 1,
+ 'justifyLeft': 1,
+ 'ltr' : 1,
+ 'rtl' : 1
+};
+
+
+/**
+ * When the following commands are executed while the selection is
+ * inside a blockquote, they hose the blockquote tag in weird and
+ * unintuitive ways.
+ * @const
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.blockquoteHatingCommandsIE_ = {
+ 'insertOrderedList' : 1,
+ 'insertUnorderedList' : 1
+};
+
+
+/**
+ * Makes sure that superscript is removed before applying subscript, and vice
+ * versa. Fixes {@link http://buganizer/issue?id=1173491} .
+ * @param {goog.editor.plugins.BasicTextFormatter.COMMAND} command The command
+ * being applied, either SUBSCRIPT or SUPERSCRIPT.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.
+ prototype.applySubscriptSuperscriptWorkarounds_ = function(command) {
+ if (!this.queryCommandValue(command)) {
+ // The current selection doesn't currently have the requested
+ // command, so we are applying it as opposed to removing it.
+ // (Note that queryCommandValue() will only return true if the
+ // command is applied to the whole selection, not just part of it.
+ // In this case it is fine because only if the whole selection has
+ // the command applied will we be removing it and thus skipping the
+ // removal of the opposite command.)
+ var oppositeCommand =
+ (command == goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT ?
+ goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT :
+ goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT);
+ var oppositeExecCommand = goog.editor.plugins.BasicTextFormatter.
+ convertToRealExecCommand_(oppositeCommand);
+ // Executing the opposite command on a selection that already has it
+ // applied will cancel it out. But if the selection only has the
+ // opposite command applied to a part of it, the browser will
+ // normalize the selection to have the opposite command applied on
+ // the whole of it.
+ if (!this.queryCommandValue(oppositeCommand)) {
+ // The selection doesn't have the opposite command applied to the
+ // whole of it, so let's exec the opposite command to normalize
+ // the selection.
+ // Note: since we know both subscript and superscript commands
+ // will boil down to a simple call to the browser's execCommand(),
+ // for performance reasons we can do that directly instead of
+ // calling execCommandHelper_(). However this is a potential for
+ // bugs if the implementation of execCommandHelper_() is changed
+ // to do something more int eh case of subscript and superscript.
+ this.getDocument_().execCommand(oppositeExecCommand, false, null);
+ }
+ // Now that we know the whole selection has the opposite command
+ // applied, we exec it a second time to properly remove it.
+ this.getDocument_().execCommand(oppositeExecCommand, false, null);
+ }
+};
+
+
+/**
+ * Removes inline font-size styles from elements fully contained in the
+ * selection, so the font tags produced by execCommand work properly.
+ * See {@bug 1286408}.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.removeFontSizeFromStyleAttrs_ =
+ function() {
+ // Expand the range so that we consider surrounding tags. E.g. if only the
+ // text node inside a span is selected, the browser could wrap a font tag
+ // around the span and leave the selection such that only the text node is
+ // found when looking inside the range, not the span.
+ var range = goog.editor.range.expand(this.getFieldObject().getRange(),
+ this.getFieldObject().getElement());
+ goog.iter.forEach(goog.iter.filter(range, function(tag, dummy, iter) {
+ return iter.isStartTag() && range.containsNode(tag);
+ }), function(node) {
+ goog.style.setStyle(node, 'font-size', '');
+ // Gecko doesn't remove empty style tags.
+ if (goog.userAgent.GECKO &&
+ node.style.length == 0 && node.getAttribute('style') != null) {
+ node.removeAttribute('style');
+ }
+ });
+};
+
+
+/**
+ * Apply pre-execCommand fixes for IE.
+ * @param {string} command The command to execute.
+ * @return {!Array<Node>} Array of nodes to be removed after the execCommand.
+ * Will never be longer than 2 elements.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.applyExecCommandIEFixes_ =
+ function(command) {
+ // IE has a crazy bug where executing list commands
+ // around blockquotes cause the blockquotes to get transformed
+ // into "<OL><OL>" or "<UL><UL>" tags.
+ var toRemove = [];
+ var endDiv = null;
+ var range = this.getRange_();
+ var dh = this.getFieldDomHelper();
+ if (command in
+ goog.editor.plugins.BasicTextFormatter.blockquoteHatingCommandsIE_) {
+ var parent = range && range.getContainerElement();
+ if (parent) {
+ var blockquotes = goog.dom.getElementsByTagNameAndClass(
+ goog.dom.TagName.BLOCKQUOTE, null, parent);
+
+ // If a blockquote contains the selection, the fix is easy:
+ // add a dummy div to the blockquote that isn't in the current selection.
+ //
+ // if the selection contains a blockquote,
+ // there appears to be no easy way to protect it from getting mangled.
+ // For now, we're just going to punt on this and try to
+ // adjust the selection so that IE does something reasonable.
+ //
+ // TODO(nicksantos): Find a better fix for this.
+ var bq;
+ for (var i = 0; i < blockquotes.length; i++) {
+ if (range.containsNode(blockquotes[i])) {
+ bq = blockquotes[i];
+ break;
+ }
+ }
+
+ var bqThatNeedsDummyDiv = bq || goog.dom.getAncestorByTagNameAndClass(
+ parent, goog.dom.TagName.BLOCKQUOTE);
+ if (bqThatNeedsDummyDiv) {
+ endDiv = dh.createDom(goog.dom.TagName.DIV, {style: 'height:0'});
+ goog.dom.appendChild(bqThatNeedsDummyDiv, endDiv);
+ toRemove.push(endDiv);
+
+ if (bq) {
+ range = goog.dom.Range.createFromNodes(bq, 0, endDiv, 0);
+ } else if (range.containsNode(endDiv)) {
+ // the selection might be the entire blockquote, and
+ // it's important that endDiv not be in the selection.
+ range = goog.dom.Range.createFromNodes(
+ range.getStartNode(), range.getStartOffset(),
+ endDiv, 0);
+ }
+ range.select();
+ }
+ }
+ }
+
+ // IE has a crazy bug where certain block execCommands cause it to mess with
+ // the DOM nodes above the contentEditable element if the selection contains
+ // or partially contains the last block element in the contentEditable
+ // element.
+ // Known commands: Indent, outdent, insertorderedlist, insertunorderedlist,
+ // Justify (all of them)
+
+ // Both of the above are "solved" by appending a dummy div to the field
+ // before the execCommand and removing it after, but we don't need to do this
+ // if we've alread added a dummy div somewhere else.
+ var fieldObject = this.getFieldObject();
+ if (!fieldObject.usesIframe() && !endDiv) {
+ if (command in
+ goog.editor.plugins.BasicTextFormatter.brokenExecCommandsIE_) {
+ var field = fieldObject.getElement();
+
+ // If the field is totally empty, or if the field contains only text nodes
+ // and the cursor is at the end of the field, then IE stills walks outside
+ // the contentEditable region and destroys things AND justify will not
+ // work. This is "solved" by adding a text node into the end of the
+ // field and moving the cursor before it.
+ if (range && range.isCollapsed() &&
+ !goog.dom.getFirstElementChild(field)) {
+ // The problem only occurs if the selection is at the end of the field.
+ var selection = range.getTextRange(0).getBrowserRangeObject();
+ var testRange = selection.duplicate();
+ testRange.moveToElementText(field);
+ testRange.collapse(false);
+
+ if (testRange.isEqual(selection)) {
+ // For reasons I really don't understand, if you use a breaking space
+ // here, either " " or String.fromCharCode(32), this textNode becomes
+ // corrupted, only after you hit ENTER to split it. It exists in the
+ // dom in that its parent has it as childNode and the parent's
+ // innerText is correct, but the node itself throws invalid argument
+ // errors when you try to access its data, parentNode, nextSibling,
+ // previousSibling or most other properties. WTF.
+ var nbsp = dh.createTextNode(goog.string.Unicode.NBSP);
+ field.appendChild(nbsp);
+ selection.move('character', 1);
+ selection.move('character', -1);
+ selection.select();
+ toRemove.push(nbsp);
+ }
+ }
+
+ endDiv = dh.createDom(goog.dom.TagName.DIV, {style: 'height:0'});
+ goog.dom.appendChild(field, endDiv);
+ toRemove.push(endDiv);
+ }
+ }
+
+ return toRemove;
+};
+
+
+/**
+ * Fix a ridiculous Safari bug: the first letters of new headings
+ * somehow retain their original font size and weight if multiple lines are
+ * selected during the execCommand that turns them into headings.
+ * The solution is to strip these styles which are normally stripped when
+ * making things headings anyway.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.cleanUpSafariHeadings_ =
+ function() {
+ goog.iter.forEach(this.getRange_(), function(node) {
+ if (node.className == 'Apple-style-span') {
+ // These shouldn't persist after creating headings via
+ // a FormatBlock execCommand.
+ node.style.fontSize = '';
+ node.style.fontWeight = '';
+ }
+ });
+};
+
+
+/**
+ * Prevent Safari from making each list item be "1" when converting from
+ * unordered to ordered lists.
+ * (see https://bugs.webkit.org/show_bug.cgi?id=19539, fixed by 2010-04-21)
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.fixSafariLists_ = function() {
+ var previousList = false;
+ goog.iter.forEach(this.getRange_(), function(node) {
+ var tagName = node.tagName;
+ if (tagName == goog.dom.TagName.UL || tagName == goog.dom.TagName.OL) {
+ // Don't disturb lists outside of the selection. If this is the first <ul>
+ // or <ol> in the range, we don't really want to merge the previous list
+ // into it, since that list isn't in the range.
+ if (!previousList) {
+ previousList = true;
+ return;
+ }
+ // The lists must be siblings to be merged; otherwise, indented sublists
+ // could be broken.
+ var previousElementSibling = goog.dom.getPreviousElementSibling(node);
+ if (!previousElementSibling) {
+ return;
+ }
+ // Make sure there isn't text between the two lists before they are merged
+ var range = node.ownerDocument.createRange();
+ range.setStartAfter(previousElementSibling);
+ range.setEndBefore(node);
+ if (!goog.string.isEmptyOrWhitespace(range.toString())) {
+ return;
+ }
+ // Make sure both are lists of the same type (ordered or unordered)
+ if (previousElementSibling.nodeName == node.nodeName) {
+ // We must merge the previous list into this one. Moving around
+ // the current node will break the iterator, so we can't merge
+ // this list into the previous one.
+ while (previousElementSibling.lastChild) {
+ node.insertBefore(previousElementSibling.lastChild, node.firstChild);
+ }
+ previousElementSibling.parentNode.removeChild(previousElementSibling);
+ }
+ }
+ });
+};
+
+
+/**
+ * Sane "type" attribute values for OL elements
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.orderedListTypes_ = {
+ '1' : 1,
+ 'a' : 1,
+ 'A' : 1,
+ 'i' : 1,
+ 'I' : 1
+};
+
+
+/**
+ * Sane "type" attribute values for UL elements
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.unorderedListTypes_ = {
+ 'disc' : 1,
+ 'circle' : 1,
+ 'square' : 1
+};
+
+
+/**
+ * Changing an OL to a UL (or the other way around) will fail if the list
+ * has a type attribute (such as "UL type=disc" becoming "OL type=disc", which
+ * is visually identical). Most browsers will remove the type attribute
+ * automatically, but IE doesn't. This does it manually.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.fixIELists_ = function() {
+ // Find the lowest-level <ul> or <ol> that contains the entire range.
+ var range = this.getRange_();
+ var container = range && range.getContainer();
+ while (container &&
+ container.tagName != goog.dom.TagName.UL &&
+ container.tagName != goog.dom.TagName.OL) {
+ container = container.parentNode;
+ }
+ if (container) {
+ // We want the parent node of the list so that we can grab it using
+ // getElementsByTagName
+ container = container.parentNode;
+ }
+ if (!container) return;
+ var lists = goog.array.toArray(
+ container.getElementsByTagName(goog.dom.TagName.UL));
+ goog.array.extend(lists, goog.array.toArray(
+ container.getElementsByTagName(goog.dom.TagName.OL)));
+ // Fix the lists
+ goog.array.forEach(lists, function(node) {
+ var type = node.type;
+ if (type) {
+ var saneTypes =
+ (node.tagName == goog.dom.TagName.UL ?
+ goog.editor.plugins.BasicTextFormatter.unorderedListTypes_ :
+ goog.editor.plugins.BasicTextFormatter.orderedListTypes_);
+ if (!saneTypes[type]) {
+ node.type = '';
+ }
+ }
+ });
+};
+
+
+/**
+ * In WebKit, the following commands will modify the node with
+ * contentEditable=true if there are no block-level elements.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.brokenExecCommandsSafari_ = {
+ 'justifyCenter' : 1,
+ 'justifyFull' : 1,
+ 'justifyRight': 1,
+ 'justifyLeft': 1,
+ 'formatBlock' : 1
+};
+
+
+/**
+ * In WebKit, the following commands can hang the browser if the selection
+ * touches the beginning of the field.
+ * https://bugs.webkit.org/show_bug.cgi?id=19735
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.hangingExecCommandWebkit_ = {
+ 'insertOrderedList': 1,
+ 'insertUnorderedList': 1
+};
+
+
+/**
+ * Apply pre-execCommand fixes for Safari.
+ * @param {string} command The command to execute.
+ * @return {!Element|undefined} The div added to the field.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.applyExecCommandSafariFixes_ =
+ function(command) {
+ // See the comment on brokenExecCommandsSafari_
+ var div;
+ if (goog.editor.plugins.BasicTextFormatter.
+ brokenExecCommandsSafari_[command]) {
+ // Add a new div at the end of the field.
+ // Safari knows that it would be wrong to apply text-align to the
+ // contentEditable element if there are non-empty block nodes in the field,
+ // because then it would align them too. So in this case, it will
+ // enclose the current selection in a block node.
+ div = this.getFieldDomHelper().createDom(
+ goog.dom.TagName.DIV, {'style': 'height: 0'}, 'x');
+ goog.dom.appendChild(this.getFieldObject().getElement(), div);
+ }
+
+ if (!goog.userAgent.isVersionOrHigher(534) &&
+ goog.editor.plugins.BasicTextFormatter.
+ hangingExecCommandWebkit_[command]) {
+ // Add a new div at the beginning of the field.
+ var field = this.getFieldObject().getElement();
+ div = this.getFieldDomHelper().createDom(
+ goog.dom.TagName.DIV, {'style': 'height: 0'}, 'x');
+ field.insertBefore(div, field.firstChild);
+ }
+
+ return div;
+};
+
+
+/**
+ * Apply pre-execCommand fixes for Gecko.
+ * @param {string} command The command to execute.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.applyExecCommandGeckoFixes_ =
+ function(command) {
+ if (goog.userAgent.isVersionOrHigher('1.9') &&
+ command.toLowerCase() == 'formatblock') {
+ // Firefox 3 and above throw a JS error for formatblock if the range is
+ // a child of the body node. Changing the selection to the BR fixes the
+ // problem.
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=481696
+ var range = this.getRange_();
+ var startNode = range.getStartNode();
+ if (range.isCollapsed() && startNode &&
+ startNode.tagName == goog.dom.TagName.BODY) {
+ var startOffset = range.getStartOffset();
+ var childNode = startNode.childNodes[startOffset];
+ if (childNode && childNode.tagName == goog.dom.TagName.BR) {
+ // Change the range using getBrowserRange() because goog.dom.TextRange
+ // will avoid setting <br>s directly.
+ // @see goog.dom.TextRange#createFromNodes
+ var browserRange = range.getBrowserRangeObject();
+ browserRange.setStart(childNode, 0);
+ browserRange.setEnd(childNode, 0);
+ }
+ }
+ }
+};
+
+
+/**
+ * Workaround for Opera bug CORE-23903. Opera sometimes fails to invalidate
+ * serialized CSS or innerHTML for the DOM after certain execCommands when
+ * styleWithCSS is on. Toggling an inline style on the elements fixes it.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.invalidateInlineCss_ =
+ function() {
+ var ancestors = [];
+ var ancestor = this.getFieldObject().getRange().getContainerElement();
+ do {
+ ancestors.push(ancestor);
+ } while (ancestor = ancestor.parentNode);
+ var nodesInSelection = goog.iter.chain(
+ goog.iter.toIterator(this.getFieldObject().getRange()),
+ goog.iter.toIterator(ancestors));
+ var containersInSelection =
+ goog.iter.filter(nodesInSelection, goog.editor.style.isContainer);
+ goog.iter.forEach(containersInSelection, function(element) {
+ var oldOutline = element.style.outline;
+ element.style.outline = '0px solid red';
+ element.style.outline = oldOutline;
+ });
+};
+
+
+/**
+ * Work around a Gecko bug that causes inserted lists to forget the current
+ * font. This affects WebKit in the same way and Opera in a slightly different
+ * way, but this workaround only works in Gecko.
+ * WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=19653
+ * Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=439966
+ * Opera bug: https://bugs.opera.com/show_bug.cgi?id=340392
+ * TODO: work around this issue in WebKit and Opera as well.
+ * @return {boolean} Whether the workaround was applied.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.beforeInsertListGecko_ =
+ function() {
+ var tag = this.getFieldObject().queryCommandValue(
+ goog.editor.Command.DEFAULT_TAG);
+ if (tag == goog.dom.TagName.P || tag == goog.dom.TagName.DIV) {
+ return false;
+ }
+
+ // Prevent Firefox from forgetting current formatting
+ // when creating a list.
+ // The bug happens with a collapsed selection, but it won't
+ // happen when text with the desired formatting is selected.
+ // So, we insert some dummy text, insert the list,
+ // then remove the dummy text (while preserving its formatting).
+ // (This formatting bug also affects WebKit, but this fix
+ // only seems to work in Firefox)
+ var range = this.getRange_();
+ if (range.isCollapsed() &&
+ (range.getContainer().nodeType != goog.dom.NodeType.TEXT)) {
+ var tempTextNode = this.getFieldDomHelper().
+ createTextNode(goog.string.Unicode.NBSP);
+ range.insertNode(tempTextNode, false);
+ goog.dom.Range.createFromNodeContents(tempTextNode).select();
+ return true;
+ }
+ return false;
+};
+
+
+// Helpers for queryCommandState
+
+
+/**
+ * Get the toolbar state for the block-level elements in the given range.
+ * @param {goog.dom.AbstractRange} range The range to get toolbar state for.
+ * @return {string?} The selection block state.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.getSelectionBlockState_ =
+ function(range) {
+ var tagName = null;
+ goog.iter.forEach(range, function(node, ignore, it) {
+ if (!it.isEndTag()) {
+ // Iterate over all containers in the range, checking if they all have the
+ // same tagName.
+ var container = goog.editor.style.getContainer(node);
+ var thisTagName = container.tagName;
+ tagName = tagName || thisTagName;
+
+ if (tagName != thisTagName) {
+ // If we find a container tag that doesn't match, exit right away.
+ tagName = null;
+ throw goog.iter.StopIteration;
+ }
+
+ // Skip the tag.
+ it.skipTag();
+ }
+ });
+
+ return tagName;
+};
+
+
+/**
+ * Hash of suppoted justifications.
+ * @type {Object}
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.SUPPORTED_JUSTIFICATIONS_ = {
+ 'center': 1,
+ 'justify': 1,
+ 'right': 1,
+ 'left': 1
+};
+
+
+/**
+ * Returns true if the current justification matches the justification
+ * command for the entire selection.
+ * @param {string} command The justification command to check for.
+ * @return {boolean} Whether the current justification matches the justification
+ * command for the entire selection.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.isJustification_ =
+ function(command) {
+ var alignment = command.replace('+justify', '').toLowerCase();
+ if (alignment == 'full') {
+ alignment = 'justify';
+ }
+ var bidiPlugin = this.getFieldObject().getPluginByClassId('Bidi');
+ if (bidiPlugin) {
+ // BiDi aware version
+
+ // TODO: Since getComputedStyle is not used here, this version may be even
+ // faster. If profiling confirms that it would be good to use this approach
+ // in both cases. Otherwise the bidi part should be moved into an
+ // execCommand so this bidi plugin dependence isn't needed here.
+ /** @type {Function} */
+ bidiPlugin.getSelectionAlignment;
+ return alignment == bidiPlugin.getSelectionAlignment();
+ } else {
+ // BiDi unaware version
+ var range = this.getRange_();
+ if (!range) {
+ // When nothing is in the selection then no justification
+ // command matches.
+ return false;
+ }
+
+ var parent = range.getContainerElement();
+ var nodes =
+ goog.array.filter(
+ parent.childNodes,
+ function(node) {
+ return goog.editor.node.isImportant(node) &&
+ range.containsNode(node, true);
+ });
+ nodes = nodes.length ? nodes : [parent];
+
+ for (var i = 0; i < nodes.length; i++) {
+ var current = nodes[i];
+
+ // If any node in the selection is not aligned the way we are checking,
+ // then the justification command does not match.
+ var container = goog.editor.style.getContainer(
+ /** @type {Node} */ (current));
+ if (alignment !=
+ goog.editor.plugins.BasicTextFormatter.getNodeJustification_(
+ container)) {
+ return false;
+ }
+ }
+
+ // If all nodes in the selection are aligned the way we are checking,
+ // the justification command does match.
+ return true;
+ }
+};
+
+
+/**
+ * Determines the justification for a given block-level element.
+ * @param {Element} element The node to get justification for.
+ * @return {string} The justification for a given block-level node.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.getNodeJustification_ =
+ function(element) {
+ var value = goog.style.getComputedTextAlign(element);
+ // Strip preceding -moz- or -webkit- (@bug 2472589).
+ value = value.replace(/^-(moz|webkit)-/, '');
+
+ // If there is no alignment, try the inline property,
+ // otherwise assume left aligned.
+ // TODO: for rtl languages we probably need to assume right.
+ if (!goog.editor.plugins.BasicTextFormatter.
+ SUPPORTED_JUSTIFICATIONS_[value]) {
+ value = element.align || 'left';
+ }
+ return /** @type {string} */ (value);
+};
+
+
+/**
+ * Returns true if a selection contained in the node should set the appropriate
+ * toolbar state for the given nodeName, e.g. if the node is contained in a
+ * strong element and nodeName is "strong", then it will return true.
+ * @param {string} nodeName The type of node to check for.
+ * @return {boolean} Whether the user's selection is in the given state.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.isNodeInState_ =
+ function(nodeName) {
+ var range = this.getRange_();
+ var node = range && range.getContainerElement();
+ var ancestor = goog.dom.getAncestorByTagNameAndClass(node, nodeName);
+ return !!ancestor && goog.editor.node.isEditable(ancestor);
+};
+
+
+/**
+ * Wrapper for browser's queryCommandState.
+ * @param {Document|TextRange|Range} queryObject The object to query.
+ * @param {string} command The command to check.
+ * @param {boolean=} opt_styleWithCss Set to true to enable styleWithCSS before
+ * performing the queryCommandState.
+ * @return {boolean} The command state.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.queryCommandStateInternal_ =
+ function(queryObject, command, opt_styleWithCss) {
+ return /** @type {boolean} */ (this.queryCommandHelper_(true, queryObject,
+ command, opt_styleWithCss));
+};
+
+
+/**
+ * Wrapper for browser's queryCommandValue.
+ * @param {Document|TextRange|Range} queryObject The object to query.
+ * @param {string} command The command to check.
+ * @param {boolean=} opt_styleWithCss Set to true to enable styleWithCSS before
+ * performing the queryCommandValue.
+ * @return {string|boolean|null} The command value.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.queryCommandValueInternal_ =
+ function(queryObject, command, opt_styleWithCss) {
+ return this.queryCommandHelper_(false, queryObject,
+ command, opt_styleWithCss);
+};
+
+
+/**
+ * Helper function to perform queryCommand(Value|State).
+ * @param {boolean} isGetQueryCommandState True to use queryCommandState, false
+ * to use queryCommandValue.
+ * @param {Document|TextRange|Range} queryObject The object to query.
+ * @param {string} command The command to check.
+ * @param {boolean=} opt_styleWithCss Set to true to enable styleWithCSS before
+ * performing the queryCommand(Value|State).
+ * @return {string|boolean|null} The command value.
+ * @private
+ */
+goog.editor.plugins.BasicTextFormatter.prototype.queryCommandHelper_ = function(
+ isGetQueryCommandState, queryObject, command, opt_styleWithCss) {
+ command =
+ goog.editor.plugins.BasicTextFormatter.convertToRealExecCommand_(
+ command);
+ if (opt_styleWithCss) {
+ var doc = this.getDocument_();
+ // Don't use this.execCommandHelper_ here, as it is more heavyweight
+ // and inserts a dummy div to protect against comamnds that could step
+ // outside the editable region, which would cause change event on
+ // every toolbar update.
+ doc.execCommand('styleWithCSS', false, true);
+ }
+ var ret = isGetQueryCommandState ? queryObject.queryCommandState(command) :
+ queryObject.queryCommandValue(command);
+ if (opt_styleWithCss) {
+ doc.execCommand('styleWithCSS', false, false);
+ }
+ return ret;
+};
[51/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
Added GCL extern.
The sources are not in out/as like other externs but in src because I tried to use EXTERNC first, it didn't work well on it but I used parts of what it generated, created an IntelliJ project to build the lib, so, the Ant target doesn't work.
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/e2cad6e6
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/e2cad6e6
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/e2cad6e6
Branch: refs/heads/JsToAs
Commit: e2cad6e69f655d8ccd6fa522eee75592778e8ff7
Parents: 21e347e
Author: Frédéric THOMAS <we...@gmail.com>
Authored: Thu Sep 17 16:25:32 2015 +0100
Committer: Frédéric THOMAS <we...@gmail.com>
Committed: Thu Sep 17 16:25:51 2015 +0100
----------------------------------------------------------------------
externs/GCL/GCL-compile-config.xml | 901 +
externs/GCL/compile-config.xml | 99 +
externs/GCL/externs/goog/a11y/aria/announcer.js | 123 +
externs/GCL/externs/goog/a11y/aria/aria.js | 386 +
.../GCL/externs/goog/a11y/aria/attributes.js | 389 +
.../GCL/externs/goog/a11y/aria/datatables.js | 68 +
externs/GCL/externs/goog/a11y/aria/roles.js | 216 +
externs/GCL/externs/goog/array/array.js | 1655 +
externs/GCL/externs/goog/asserts/asserts.js | 365 +
.../GCL/externs/goog/async/animationdelay.js | 267 +
.../GCL/externs/goog/async/conditionaldelay.js | 228 +
externs/GCL/externs/goog/async/delay.js | 182 +
externs/GCL/externs/goog/async/freelist.js | 88 +
externs/GCL/externs/goog/async/nexttick.js | 241 +
externs/GCL/externs/goog/async/run.js | 130 +
externs/GCL/externs/goog/async/throttle.js | 195 +
externs/GCL/externs/goog/async/workqueue.js | 139 +
externs/GCL/externs/goog/base.js | 2547 ++
externs/GCL/externs/goog/bootstrap/nodejs.js | 110 +
.../GCL/externs/goog/bootstrap/webworkers.js | 37 +
externs/GCL/externs/goog/color/alpha.js | 472 +
externs/GCL/externs/goog/color/color.js | 776 +
externs/GCL/externs/goog/color/names.js | 176 +
externs/GCL/externs/goog/crypt/aes.js | 1029 +
externs/GCL/externs/goog/crypt/arc4.js | 164 +
externs/GCL/externs/goog/crypt/base64.js | 286 +
externs/GCL/externs/goog/crypt/basen.js | 242 +
externs/GCL/externs/goog/crypt/blobhasher.js | 285 +
externs/GCL/externs/goog/crypt/blockcipher.js | 52 +
externs/GCL/externs/goog/crypt/cbc.js | 153 +
externs/GCL/externs/goog/crypt/crypt.js | 173 +
externs/GCL/externs/goog/crypt/hash.js | 69 +
externs/GCL/externs/goog/crypt/hash32.js | 184 +
externs/GCL/externs/goog/crypt/hmac.js | 160 +
externs/GCL/externs/goog/crypt/md5.js | 435 +
externs/GCL/externs/goog/crypt/pbkdf2.js | 128 +
externs/GCL/externs/goog/crypt/sha1.js | 294 +
externs/GCL/externs/goog/crypt/sha2.js | 338 +
externs/GCL/externs/goog/crypt/sha224.js | 50 +
externs/GCL/externs/goog/crypt/sha256.js | 49 +
externs/GCL/externs/goog/crypt/sha2_64bit.js | 550 +
externs/GCL/externs/goog/crypt/sha384.js | 59 +
externs/GCL/externs/goog/crypt/sha512.js | 59 +
externs/GCL/externs/goog/crypt/sha512_256.js | 65 +
externs/GCL/externs/goog/css/autocomplete.css | 43 +
externs/GCL/externs/goog/css/bubble.css | 84 +
externs/GCL/externs/goog/css/button.css | 38 +
externs/GCL/externs/goog/css/charpicker.css | 206 +
externs/GCL/externs/goog/css/checkbox.css | 38 +
.../GCL/externs/goog/css/colormenubutton.css | 25 +
externs/GCL/externs/goog/css/colorpalette.css | 54 +
.../externs/goog/css/colorpicker-simplegrid.css | 49 +
externs/GCL/externs/goog/css/combobox.css | 54 +
externs/GCL/externs/goog/css/common.css | 41 +
externs/GCL/externs/goog/css/css3button.css | 77 +
externs/GCL/externs/goog/css/css3menubutton.css | 23 +
externs/GCL/externs/goog/css/custombutton.css | 161 +
externs/GCL/externs/goog/css/datepicker.css | 154 +
externs/GCL/externs/goog/css/dialog.css | 72 +
.../GCL/externs/goog/css/dimensionpicker.css | 47 +
.../GCL/externs/goog/css/dragdropdetector.css | 48 +
externs/GCL/externs/goog/css/editor/bubble.css | 73 +
externs/GCL/externs/goog/css/editor/dialog.css | 66 +
.../externs/goog/css/editor/equationeditor.css | 113 +
.../GCL/externs/goog/css/editor/linkdialog.css | 36 +
externs/GCL/externs/goog/css/editortoolbar.css | 225 +
externs/GCL/externs/goog/css/filteredmenu.css | 30 +
.../goog/css/filterobservingmenuitem.css | 25 +
externs/GCL/externs/goog/css/flatbutton.css | 64 +
externs/GCL/externs/goog/css/flatmenubutton.css | 63 +
externs/GCL/externs/goog/css/hovercard.css | 51 +
externs/GCL/externs/goog/css/hsvapalette.css | 231 +
externs/GCL/externs/goog/css/hsvpalette.css | 179 +
.../GCL/externs/goog/css/imagelessbutton.css | 160 +
.../externs/goog/css/imagelessmenubutton.css | 23 +
.../GCL/externs/goog/css/inputdatepicker.css | 12 +
externs/GCL/externs/goog/css/linkbutton.css | 26 +
externs/GCL/externs/goog/css/menu.css | 27 +
externs/GCL/externs/goog/css/menubar.css | 57 +
externs/GCL/externs/goog/css/menubutton.css | 169 +
externs/GCL/externs/goog/css/menuitem.css | 148 +
externs/GCL/externs/goog/css/menuseparator.css | 19 +
.../GCL/externs/goog/css/multitestrunner.css | 121 +
externs/GCL/externs/goog/css/palette.css | 36 +
.../GCL/externs/goog/css/popupdatepicker.css | 17 +
externs/GCL/externs/goog/css/roundedpanel.css | 29 +
externs/GCL/externs/goog/css/roundedtab.css | 158 +
externs/GCL/externs/goog/css/submenu.css | 38 +
externs/GCL/externs/goog/css/tab.css | 105 +
externs/GCL/externs/goog/css/tabbar.css | 52 +
externs/GCL/externs/goog/css/tablesorter.css | 14 +
externs/GCL/externs/goog/css/toolbar.css | 400 +
externs/GCL/externs/goog/css/tooltip.css | 14 +
externs/GCL/externs/goog/css/tree.css | 146 +
.../GCL/externs/goog/css/tristatemenuitem.css | 43 +
externs/GCL/externs/goog/cssom/cssom.js | 455 +
.../externs/goog/cssom/cssom_test_import_1.css | 11 +
.../externs/goog/cssom/cssom_test_import_2.css | 10 +
.../externs/goog/cssom/cssom_test_link_1.css | 10 +
externs/GCL/externs/goog/cssom/iframe/style.js | 1016 +
.../goog/cssom/iframe/style_test_import.css | 10 +
.../GCL/externs/goog/datasource/datamanager.js | 561 +
.../GCL/externs/goog/datasource/datasource.js | 658 +
externs/GCL/externs/goog/datasource/expr.js | 545 +
.../GCL/externs/goog/datasource/fastdatanode.js | 814 +
.../GCL/externs/goog/datasource/jsdatasource.js | 462 +
.../externs/goog/datasource/jsondatasource.js | 153 +
.../goog/datasource/jsxmlhttpdatasource.js | 196 +
.../externs/goog/datasource/xmldatasource.js | 417 +
externs/GCL/externs/goog/date/date.js | 1761 ++
externs/GCL/externs/goog/date/datelike.js | 27 +
externs/GCL/externs/goog/date/daterange.js | 430 +
externs/GCL/externs/goog/date/duration.js | 153 +
externs/GCL/externs/goog/date/relative.js | 490 +
.../externs/goog/date/relativewithplurals.js | 120 +
externs/GCL/externs/goog/date/utcdatetime.js | 191 +
externs/GCL/externs/goog/db/cursor.js | 215 +
externs/GCL/externs/goog/db/db.js | 185 +
externs/GCL/externs/goog/db/error1.js | 364 +
externs/GCL/externs/goog/db/index.js | 246 +
externs/GCL/externs/goog/db/indexeddb.js | 353 +
externs/GCL/externs/goog/db/keyrange.js | 118 +
externs/GCL/externs/goog/db/objectstore.js | 400 +
externs/GCL/externs/goog/db/transaction.js | 223 +
externs/GCL/externs/goog/debug/console.js | 207 +
externs/GCL/externs/goog/debug/debug.js | 653 +
externs/GCL/externs/goog/debug/debugwindow.js | 632 +
externs/GCL/externs/goog/debug/devcss/devcss.js | 445 +
.../externs/goog/debug/devcss/devcssrunner.js | 26 +
externs/GCL/externs/goog/debug/divconsole.js | 150 +
.../externs/goog/debug/entrypointregistry.js | 158 +
externs/GCL/externs/goog/debug/error2.js | 63 +
externs/GCL/externs/goog/debug/errorhandler.js | 367 +
.../externs/goog/debug/errorhandlerweakdep.js | 38 +
externs/GCL/externs/goog/debug/errorreporter.js | 434 +
externs/GCL/externs/goog/debug/fancywindow.js | 385 +
externs/GCL/externs/goog/debug/formatter.js | 387 +
externs/GCL/externs/goog/debug/fpsdisplay.js | 165 +
externs/GCL/externs/goog/debug/gcdiagnostics.js | 143 +
externs/GCL/externs/goog/debug/logbuffer.js | 148 +
externs/GCL/externs/goog/debug/logger.js | 873 +
externs/GCL/externs/goog/debug/logrecord.js | 242 +
.../externs/goog/debug/logrecordserializer.js | 121 +
.../externs/goog/debug/relativetimeprovider.js | 84 +
externs/GCL/externs/goog/debug/tracer.js | 725 +
.../goog/demos/autocompleteremotedata.js | 18 +
.../goog/demos/autocompleterichremotedata.js | 33 +
externs/GCL/externs/goog/demos/css/demo.css | 75 +
.../GCL/externs/goog/demos/css/emojipicker.css | 36 +
.../GCL/externs/goog/demos/css/emojisprite.css | 92 +
externs/GCL/externs/goog/demos/editor/deps.js | 21 +
.../GCL/externs/goog/demos/editor/helloworld.js | 82 +
.../goog/demos/editor/helloworlddialog.js | 173 +
.../goog/demos/editor/helloworlddialogplugin.js | 117 +
externs/GCL/externs/goog/demos/emoji/200.gif | Bin 0 -> 941 bytes
externs/GCL/externs/goog/demos/emoji/201.gif | Bin 0 -> 980 bytes
externs/GCL/externs/goog/demos/emoji/202.gif | Bin 0 -> 1054 bytes
externs/GCL/externs/goog/demos/emoji/203.gif | Bin 0 -> 996 bytes
externs/GCL/externs/goog/demos/emoji/204.gif | Bin 0 -> 1016 bytes
externs/GCL/externs/goog/demos/emoji/205.gif | Bin 0 -> 1032 bytes
externs/GCL/externs/goog/demos/emoji/206.gif | Bin 0 -> 990 bytes
externs/GCL/externs/goog/demos/emoji/2BC.gif | Bin 0 -> 1039 bytes
externs/GCL/externs/goog/demos/emoji/2BD.gif | Bin 0 -> 986 bytes
externs/GCL/externs/goog/demos/emoji/2BE.gif | Bin 0 -> 1074 bytes
externs/GCL/externs/goog/demos/emoji/2BF.gif | Bin 0 -> 996 bytes
externs/GCL/externs/goog/demos/emoji/2C0.gif | Bin 0 -> 1036 bytes
externs/GCL/externs/goog/demos/emoji/2C1.gif | Bin 0 -> 1080 bytes
externs/GCL/externs/goog/demos/emoji/2C2.gif | Bin 0 -> 1049 bytes
externs/GCL/externs/goog/demos/emoji/2C3.gif | Bin 0 -> 1104 bytes
externs/GCL/externs/goog/demos/emoji/2C4.gif | Bin 0 -> 1072 bytes
externs/GCL/externs/goog/demos/emoji/2C5.gif | Bin 0 -> 1087 bytes
externs/GCL/externs/goog/demos/emoji/2C6.gif | Bin 0 -> 1041 bytes
externs/GCL/externs/goog/demos/emoji/2C7.gif | Bin 0 -> 1079 bytes
externs/GCL/externs/goog/demos/emoji/2C8.gif | Bin 0 -> 1049 bytes
externs/GCL/externs/goog/demos/emoji/2C9.gif | Bin 0 -> 996 bytes
externs/GCL/externs/goog/demos/emoji/2CA.gif | Bin 0 -> 2299 bytes
externs/GCL/externs/goog/demos/emoji/2CB.gif | Bin 0 -> 992 bytes
externs/GCL/externs/goog/demos/emoji/2CC.gif | Bin 0 -> 977 bytes
externs/GCL/externs/goog/demos/emoji/2CD.gif | Bin 0 -> 1035 bytes
externs/GCL/externs/goog/demos/emoji/2CE.gif | Bin 0 -> 1074 bytes
externs/GCL/externs/goog/demos/emoji/2CF.gif | Bin 0 -> 1022 bytes
externs/GCL/externs/goog/demos/emoji/2D0.gif | Bin 0 -> 987 bytes
externs/GCL/externs/goog/demos/emoji/2D1.gif | Bin 0 -> 997 bytes
externs/GCL/externs/goog/demos/emoji/2D2.gif | Bin 0 -> 1012 bytes
externs/GCL/externs/goog/demos/emoji/2D3.gif | Bin 0 -> 1040 bytes
externs/GCL/externs/goog/demos/emoji/2D4.gif | Bin 0 -> 1043 bytes
externs/GCL/externs/goog/demos/emoji/2D5.gif | Bin 0 -> 1014 bytes
externs/GCL/externs/goog/demos/emoji/2D6.gif | Bin 0 -> 1026 bytes
externs/GCL/externs/goog/demos/emoji/2D7.gif | Bin 0 -> 1048 bytes
externs/GCL/externs/goog/demos/emoji/2D8.gif | Bin 0 -> 884 bytes
externs/GCL/externs/goog/demos/emoji/2D9.gif | Bin 0 -> 974 bytes
externs/GCL/externs/goog/demos/emoji/2DA.gif | Bin 0 -> 920 bytes
externs/GCL/externs/goog/demos/emoji/2DB.gif | Bin 0 -> 949 bytes
externs/GCL/externs/goog/demos/emoji/2DC.gif | Bin 0 -> 949 bytes
externs/GCL/externs/goog/demos/emoji/2DD.gif | Bin 0 -> 1000 bytes
externs/GCL/externs/goog/demos/emoji/2DE.gif | Bin 0 -> 963 bytes
externs/GCL/externs/goog/demos/emoji/2DF.gif | Bin 0 -> 865 bytes
externs/GCL/externs/goog/demos/emoji/2E0.gif | Bin 0 -> 1018 bytes
externs/GCL/externs/goog/demos/emoji/2E1.gif | Bin 0 -> 1004 bytes
externs/GCL/externs/goog/demos/emoji/2E2.gif | Bin 0 -> 1046 bytes
externs/GCL/externs/goog/demos/emoji/2E3.gif | Bin 0 -> 1547 bytes
externs/GCL/externs/goog/demos/emoji/2E4.gif | Bin 0 -> 999 bytes
externs/GCL/externs/goog/demos/emoji/2E5.gif | Bin 0 -> 1032 bytes
externs/GCL/externs/goog/demos/emoji/2E6.gif | Bin 0 -> 1013 bytes
externs/GCL/externs/goog/demos/emoji/2E7.gif | Bin 0 -> 1040 bytes
externs/GCL/externs/goog/demos/emoji/2E8.gif | Bin 0 -> 1028 bytes
externs/GCL/externs/goog/demos/emoji/2E9.gif | Bin 0 -> 1030 bytes
externs/GCL/externs/goog/demos/emoji/2EA.gif | Bin 0 -> 1001 bytes
externs/GCL/externs/goog/demos/emoji/2EB.gif | Bin 0 -> 1086 bytes
externs/GCL/externs/goog/demos/emoji/2EC.gif | Bin 0 -> 1007 bytes
externs/GCL/externs/goog/demos/emoji/2ED.gif | Bin 0 -> 1045 bytes
externs/GCL/externs/goog/demos/emoji/2EE.gif | Bin 0 -> 1016 bytes
externs/GCL/externs/goog/demos/emoji/2EF.gif | Bin 0 -> 2363 bytes
externs/GCL/externs/goog/demos/emoji/2F0.gif | Bin 0 -> 1014 bytes
externs/GCL/externs/goog/demos/emoji/2F1.gif | Bin 0 -> 1902 bytes
externs/GCL/externs/goog/demos/emoji/2F2.gif | Bin 0 -> 1092 bytes
externs/GCL/externs/goog/demos/emoji/2F3.gif | Bin 0 -> 1033 bytes
externs/GCL/externs/goog/demos/emoji/2F4.gif | Bin 0 -> 1065 bytes
externs/GCL/externs/goog/demos/emoji/2F5.gif | Bin 0 -> 954 bytes
externs/GCL/externs/goog/demos/emoji/2F6.gif | Bin 0 -> 1030 bytes
externs/GCL/externs/goog/demos/emoji/2F7.gif | Bin 0 -> 1006 bytes
externs/GCL/externs/goog/demos/emoji/2F8.gif | Bin 0 -> 1016 bytes
externs/GCL/externs/goog/demos/emoji/2F9.gif | Bin 0 -> 1051 bytes
externs/GCL/externs/goog/demos/emoji/2FA.gif | Bin 0 -> 1082 bytes
externs/GCL/externs/goog/demos/emoji/2FB.gif | Bin 0 -> 1012 bytes
externs/GCL/externs/goog/demos/emoji/2FC.gif | Bin 0 -> 977 bytes
externs/GCL/externs/goog/demos/emoji/2FD.gif | Bin 0 -> 989 bytes
externs/GCL/externs/goog/demos/emoji/2FE.gif | Bin 0 -> 1036 bytes
externs/GCL/externs/goog/demos/emoji/2FF.gif | Bin 0 -> 1034 bytes
externs/GCL/externs/goog/demos/emoji/none.gif | Bin 0 -> 834 bytes
externs/GCL/externs/goog/demos/emoji/sprite.png | Bin 0 -> 25195 bytes
.../GCL/externs/goog/demos/emoji/sprite2.png | Bin 0 -> 27856 bytes
.../GCL/externs/goog/demos/emoji/unknown.gif | Bin 0 -> 90 bytes
.../externs/goog/demos/graphics/tigerdata.js | 2841 ++
.../GCL/externs/goog/demos/samplecomponent.js | 189 +
externs/GCL/externs/goog/demos/xpc/xpcdemo.js | 308 +
.../GCL/externs/goog/disposable/disposable.js | 307 +
.../GCL/externs/goog/disposable/idisposable.js | 45 +
.../GCL/externs/goog/dom/abstractmultirange.js | 76 +
externs/GCL/externs/goog/dom/abstractrange.js | 529 +
.../goog/dom/animationframe/animationframe.js | 287 +
.../externs/goog/dom/animationframe/polyfill.js | 61 +
externs/GCL/externs/goog/dom/annotate.js | 357 +
externs/GCL/externs/goog/dom/browserfeature1.js | 72 +
.../goog/dom/browserrange/abstractrange.js | 350 +
.../goog/dom/browserrange/browserrange.js | 149 +
.../externs/goog/dom/browserrange/geckorange.js | 88 +
.../externs/goog/dom/browserrange/ierange.js | 935 +
.../externs/goog/dom/browserrange/operarange.js | 84 +
.../externs/goog/dom/browserrange/w3crange.js | 396 +
.../goog/dom/browserrange/webkitrange.js | 108 +
.../goog/dom/bufferedviewportsizemonitor.js | 201 +
externs/GCL/externs/goog/dom/classes.js | 239 +
externs/GCL/externs/goog/dom/classlist.js | 277 +
externs/GCL/externs/goog/dom/controlrange.js | 494 +
externs/GCL/externs/goog/dom/dataset.js | 154 +
externs/GCL/externs/goog/dom/dom.js | 2990 ++
externs/GCL/externs/goog/dom/fontsizemonitor.js | 162 +
externs/GCL/externs/goog/dom/forms.js | 417 +
externs/GCL/externs/goog/dom/fullscreen.js | 144 +
externs/GCL/externs/goog/dom/iframe.js | 216 +
externs/GCL/externs/goog/dom/inputtype.js | 66 +
externs/GCL/externs/goog/dom/iter.js | 129 +
externs/GCL/externs/goog/dom/multirange.js | 510 +
externs/GCL/externs/goog/dom/nodeiterator.js | 87 +
externs/GCL/externs/goog/dom/nodeoffset.js | 114 +
externs/GCL/externs/goog/dom/nodetype.js | 48 +
.../externs/goog/dom/pattern/abstractpattern.js | 58 +
.../GCL/externs/goog/dom/pattern/allchildren.js | 72 +
.../goog/dom/pattern/callback/callback.js | 82 +
.../goog/dom/pattern/callback/counter.js | 69 +
.../externs/goog/dom/pattern/childmatches.js | 145 +
externs/GCL/externs/goog/dom/pattern/endtag.js | 54 +
externs/GCL/externs/goog/dom/pattern/fulltag.js | 88 +
externs/GCL/externs/goog/dom/pattern/matcher.js | 144 +
.../GCL/externs/goog/dom/pattern/nodetype.js | 59 +
externs/GCL/externs/goog/dom/pattern/pattern.js | 93 +
externs/GCL/externs/goog/dom/pattern/repeat.js | 177 +
.../GCL/externs/goog/dom/pattern/sequence.js | 135 +
.../GCL/externs/goog/dom/pattern/starttag.js | 53 +
externs/GCL/externs/goog/dom/pattern/tag.js | 128 +
externs/GCL/externs/goog/dom/pattern/text.js | 67 +
externs/GCL/externs/goog/dom/range.js | 226 +
externs/GCL/externs/goog/dom/rangeendpoint.js | 32 +
externs/GCL/externs/goog/dom/safe.js | 325 +
externs/GCL/externs/goog/dom/savedcaretrange.js | 215 +
externs/GCL/externs/goog/dom/savedrange.js | 74 +
externs/GCL/externs/goog/dom/selection.js | 472 +
externs/GCL/externs/goog/dom/tagiterator.js | 360 +
externs/GCL/externs/goog/dom/tagname.js | 160 +
externs/GCL/externs/goog/dom/tags.js | 42 +
externs/GCL/externs/goog/dom/textrange.js | 615 +
.../GCL/externs/goog/dom/textrangeiterator.js | 239 +
externs/GCL/externs/goog/dom/vendor.js | 96 +
.../GCL/externs/goog/dom/viewportsizemonitor.js | 165 +
externs/GCL/externs/goog/dom/xml.js | 204 +
.../GCL/externs/goog/editor/browserfeature2.js | 273 +
.../externs/goog/editor/clicktoeditwrapper.js | 423 +
externs/GCL/externs/goog/editor/command.js | 76 +
.../externs/goog/editor/contenteditablefield.js | 108 +
externs/GCL/externs/goog/editor/defines.js | 34 +
externs/GCL/externs/goog/editor/field.js | 2750 ++
externs/GCL/externs/goog/editor/focus.js | 32 +
externs/GCL/externs/goog/editor/icontent.js | 300 +
externs/GCL/externs/goog/editor/link.js | 390 +
externs/GCL/externs/goog/editor/node.js | 484 +
externs/GCL/externs/goog/editor/plugin.js | 463 +
.../goog/editor/plugins/abstractbubbleplugin.js | 712 +
.../goog/editor/plugins/abstractdialogplugin.js | 333 +
.../goog/editor/plugins/abstracttabhandler.js | 78 +
.../goog/editor/plugins/basictextformatter.js | 1769 ++
.../externs/goog/editor/plugins/blockquote.js | 451 +
.../externs/goog/editor/plugins/emoticons.js | 89 +
.../externs/goog/editor/plugins/enterhandler.js | 768 +
.../externs/goog/editor/plugins/firststrong.js | 334 +
.../goog/editor/plugins/headerformatter.js | 96 +
.../externs/goog/editor/plugins/linkbubble.js | 585 +
.../goog/editor/plugins/linkdialogplugin.js | 438 +
.../goog/editor/plugins/linkshortcutplugin.js | 61 +
.../goog/editor/plugins/listtabhandler.js | 68 +
.../externs/goog/editor/plugins/loremipsum.js | 192 +
.../goog/editor/plugins/removeformatting.js | 780 +
.../goog/editor/plugins/spacestabhandler.js | 92 +
.../externs/goog/editor/plugins/tableeditor.js | 475 +
.../goog/editor/plugins/tagonenterhandler.js | 744 +
.../GCL/externs/goog/editor/plugins/undoredo.js | 1016 +
.../goog/editor/plugins/undoredomanager.js | 338 +
.../goog/editor/plugins/undoredostate.js | 86 +
externs/GCL/externs/goog/editor/range.js | 632 +
.../GCL/externs/goog/editor/seamlessfield.js | 746 +
externs/GCL/externs/goog/editor/style.js | 225 +
externs/GCL/externs/goog/editor/table.js | 570 +
.../externs/goog/events/actioneventwrapper.js | 151 +
.../GCL/externs/goog/events/actionhandler.js | 184 +
externs/GCL/externs/goog/events/browserevent.js | 386 +
.../GCL/externs/goog/events/browserfeature3.js | 85 +
externs/GCL/externs/goog/events/event.js | 143 +
externs/GCL/externs/goog/events/eventhandler.js | 459 +
externs/GCL/externs/goog/events/eventid.js | 47 +
externs/GCL/externs/goog/events/events.js | 983 +
externs/GCL/externs/goog/events/eventtarget.js | 394 +
externs/GCL/externs/goog/events/eventtype.js | 233 +
externs/GCL/externs/goog/events/eventwrapper.js | 66 +
.../GCL/externs/goog/events/filedrophandler.js | 222 +
externs/GCL/externs/goog/events/focushandler.js | 107 +
externs/GCL/externs/goog/events/imehandler.js | 369 +
externs/GCL/externs/goog/events/inputhandler.js | 212 +
externs/GCL/externs/goog/events/keycodes.js | 420 +
externs/GCL/externs/goog/events/keyhandler.js | 556 +
externs/GCL/externs/goog/events/keynames.js | 139 +
externs/GCL/externs/goog/events/listenable.js | 335 +
externs/GCL/externs/goog/events/listener.js | 131 +
externs/GCL/externs/goog/events/listenermap.js | 308 +
.../externs/goog/events/mousewheelhandler.js | 296 +
.../GCL/externs/goog/events/onlinehandler.js | 159 +
externs/GCL/externs/goog/events/pastehandler.js | 517 +
externs/GCL/externs/goog/events/wheelevent.js | 169 +
externs/GCL/externs/goog/events/wheelhandler.js | 159 +
externs/GCL/externs/goog/format/emailaddress.js | 499 +
externs/GCL/externs/goog/format/format.js | 502 +
.../externs/goog/format/htmlprettyprinter.js | 408 +
.../format/internationalizedemailaddress.js | 256 +
.../externs/goog/format/jsonprettyprinter.js | 414 +
externs/GCL/externs/goog/fs/entry.js | 272 +
externs/GCL/externs/goog/fs/entryimpl.js | 404 +
externs/GCL/externs/goog/fs/error3.js | 181 +
externs/GCL/externs/goog/fs/filereader.js | 288 +
externs/GCL/externs/goog/fs/filesaver.js | 166 +
externs/GCL/externs/goog/fs/filesystem.js | 41 +
externs/GCL/externs/goog/fs/filesystemimpl.js | 65 +
externs/GCL/externs/goog/fs/filewriter.js | 111 +
externs/GCL/externs/goog/fs/fs.js | 278 +
externs/GCL/externs/goog/fs/progressevent.js | 69 +
externs/GCL/externs/goog/fs/url.js | 105 +
externs/GCL/externs/goog/functions/functions.js | 332 +
externs/GCL/externs/goog/fx/abstractdragdrop.js | 1540 +
externs/GCL/externs/goog/fx/anim/anim.js | 211 +
externs/GCL/externs/goog/fx/animation.js | 524 +
externs/GCL/externs/goog/fx/animationqueue.js | 310 +
externs/GCL/externs/goog/fx/css3/fx.js | 63 +
externs/GCL/externs/goog/fx/css3/transition.js | 201 +
.../GCL/externs/goog/fx/cssspriteanimation.js | 130 +
externs/GCL/externs/goog/fx/dom.js | 686 +
externs/GCL/externs/goog/fx/dragdrop.js | 50 +
externs/GCL/externs/goog/fx/dragdropgroup.js | 109 +
externs/GCL/externs/goog/fx/dragger.js | 869 +
externs/GCL/externs/goog/fx/draglistgroup.js | 1312 +
.../GCL/externs/goog/fx/dragscrollsupport.js | 300 +
externs/GCL/externs/goog/fx/easing.js | 85 +
externs/GCL/externs/goog/fx/fx.js | 34 +
externs/GCL/externs/goog/fx/transition.js | 76 +
externs/GCL/externs/goog/fx/transitionbase.js | 236 +
.../externs/goog/graphics/abstractgraphics.js | 454 +
.../externs/goog/graphics/affinetransform.js | 588 +
.../GCL/externs/goog/graphics/canvaselement.js | 812 +
.../GCL/externs/goog/graphics/canvasgraphics.js | 670 +
externs/GCL/externs/goog/graphics/element.js | 164 +
.../GCL/externs/goog/graphics/ellipseelement.js | 63 +
.../externs/goog/graphics/ext/coordinates.js | 159 +
.../GCL/externs/goog/graphics/ext/element.js | 963 +
.../GCL/externs/goog/graphics/ext/ellipse.js | 60 +
externs/GCL/externs/goog/graphics/ext/ext.js | 31 +
.../GCL/externs/goog/graphics/ext/graphics.js | 218 +
externs/GCL/externs/goog/graphics/ext/group.js | 216 +
externs/GCL/externs/goog/graphics/ext/image.js | 64 +
externs/GCL/externs/goog/graphics/ext/path.js | 142 +
.../GCL/externs/goog/graphics/ext/rectangle.js | 55 +
externs/GCL/externs/goog/graphics/ext/shape.js | 145 +
.../goog/graphics/ext/strokeandfillelement.js | 70 +
externs/GCL/externs/goog/graphics/fill.js | 46 +
externs/GCL/externs/goog/graphics/font.js | 64 +
externs/GCL/externs/goog/graphics/graphics.js | 142 +
.../GCL/externs/goog/graphics/groupelement.js | 58 +
.../GCL/externs/goog/graphics/imageelement.js | 70 +
.../GCL/externs/goog/graphics/lineargradient.js | 175 +
externs/GCL/externs/goog/graphics/path.js | 511 +
.../GCL/externs/goog/graphics/pathelement.js | 54 +
externs/GCL/externs/goog/graphics/paths.js | 86 +
.../GCL/externs/goog/graphics/rectelement.js | 63 +
externs/GCL/externs/goog/graphics/solidfill.js | 74 +
externs/GCL/externs/goog/graphics/stroke.js | 86 +
.../goog/graphics/strokeandfillelement.js | 114 +
externs/GCL/externs/goog/graphics/svgelement.js | 284 +
.../GCL/externs/goog/graphics/svggraphics.js | 878 +
.../GCL/externs/goog/graphics/textelement.js | 55 +
externs/GCL/externs/goog/graphics/vmlelement.js | 438 +
.../GCL/externs/goog/graphics/vmlgraphics.js | 948 +
externs/GCL/externs/goog/history/event.js | 55 +
externs/GCL/externs/goog/history/eventtype.js | 30 +
externs/GCL/externs/goog/history/history.js | 1005 +
.../GCL/externs/goog/history/html5history.js | 303 +
externs/GCL/externs/goog/html/flash.js | 177 +
.../GCL/externs/goog/html/legacyconversions.js | 200 +
externs/GCL/externs/goog/html/safehtml.js | 756 +
externs/GCL/externs/goog/html/safescript.js | 234 +
externs/GCL/externs/goog/html/safestyle.js | 442 +
externs/GCL/externs/goog/html/safestylesheet.js | 276 +
externs/GCL/externs/goog/html/safeurl.js | 431 +
externs/GCL/externs/goog/html/silverlight.js | 92 +
.../GCL/externs/goog/html/trustedresourceurl.js | 224 +
.../externs/goog/html/uncheckedconversions.js | 231 +
externs/GCL/externs/goog/html/utils.js | 67 +
externs/GCL/externs/goog/i18n/bidi.js | 897 +
externs/GCL/externs/goog/i18n/bidiformatter.js | 596 +
.../externs/goog/i18n/charlistdecompressor.js | 158 +
externs/GCL/externs/goog/i18n/charpickerdata.js | 3666 +++
externs/GCL/externs/goog/i18n/collation.js | 58 +
.../goog/i18n/compactnumberformatsymbols.js | 9763 ++++++
.../goog/i18n/compactnumberformatsymbols_ext.js | 27778 +++++++++++++++++
externs/GCL/externs/goog/i18n/currency.js | 437 +
.../GCL/externs/goog/i18n/currencycodemap.js | 207 +
externs/GCL/externs/goog/i18n/datetimeformat.js | 771 +
externs/GCL/externs/goog/i18n/datetimeparse.js | 1150 +
.../GCL/externs/goog/i18n/datetimepatterns.js | 2520 ++
.../externs/goog/i18n/datetimepatternsext.js | 14208 +++++++++
.../GCL/externs/goog/i18n/datetimesymbols.js | 4524 +++
.../GCL/externs/goog/i18n/datetimesymbolsext.js | 22115 +++++++++++++
externs/GCL/externs/goog/i18n/graphemebreak.js | 214 +
externs/GCL/externs/goog/i18n/messageformat.js | 780 +
externs/GCL/externs/goog/i18n/mime.js | 111 +
externs/GCL/externs/goog/i18n/numberformat.js | 1266 +
.../externs/goog/i18n/numberformatsymbols.js | 4271 +++
.../externs/goog/i18n/numberformatsymbolsext.js | 11335 +++++++
externs/GCL/externs/goog/i18n/ordinalrules.js | 748 +
externs/GCL/externs/goog/i18n/pluralrules.js | 1120 +
externs/GCL/externs/goog/i18n/timezone.js | 341 +
externs/GCL/externs/goog/i18n/uchar.js | 292 +
.../externs/goog/i18n/uchar/localnamefetcher.js | 74 +
.../GCL/externs/goog/i18n/uchar/namefetcher.js | 70 +
.../goog/i18n/uchar/remotenamefetcher.js | 282 +
externs/GCL/externs/goog/i18n/ucharnames.js | 1098 +
externs/GCL/externs/goog/images/blank.gif | Bin 0 -> 49 bytes
.../GCL/externs/goog/images/bubble_close.jpg | Bin 0 -> 586 bytes
externs/GCL/externs/goog/images/bubble_left.gif | Bin 0 -> 85 bytes
.../GCL/externs/goog/images/bubble_right.gif | Bin 0 -> 86 bytes
externs/GCL/externs/goog/images/button-bg.gif | Bin 0 -> 454 bytes
.../GCL/externs/goog/images/check-outline.gif | Bin 0 -> 69 bytes
.../GCL/externs/goog/images/check-sprite.gif | Bin 0 -> 75 bytes
externs/GCL/externs/goog/images/check.gif | Bin 0 -> 53 bytes
externs/GCL/externs/goog/images/close_box.gif | Bin 0 -> 65 bytes
.../externs/goog/images/color-swatch-tick.gif | Bin 0 -> 69 bytes
.../externs/goog/images/dialog_close_box.gif | Bin 0 -> 86 bytes
.../goog/images/dimension-highlighted.png | Bin 0 -> 171 bytes
.../goog/images/dimension-unhighlighted.png | Bin 0 -> 171 bytes
externs/GCL/externs/goog/images/dropdn.gif | Bin 0 -> 51 bytes
.../GCL/externs/goog/images/dropdn_disabled.gif | Bin 0 -> 51 bytes
externs/GCL/externs/goog/images/dropdown.gif | Bin 0 -> 78 bytes
.../GCL/externs/goog/images/gears_bluedot.gif | Bin 0 -> 236 bytes
.../GCL/externs/goog/images/gears_online.gif | Bin 0 -> 137 bytes
.../GCL/externs/goog/images/gears_paused.gif | Bin 0 -> 93 bytes
.../GCL/externs/goog/images/gears_syncing.gif | Bin 0 -> 761 bytes
.../GCL/externs/goog/images/hsv-sprite-sm.gif | Bin 0 -> 11851 bytes
.../GCL/externs/goog/images/hsv-sprite-sm.png | Bin 0 -> 19537 bytes
externs/GCL/externs/goog/images/hsv-sprite.gif | Bin 0 -> 33309 bytes
externs/GCL/externs/goog/images/hsv-sprite.png | Bin 0 -> 58142 bytes
.../GCL/externs/goog/images/hsva-sprite-sm.gif | Bin 0 -> 12571 bytes
.../GCL/externs/goog/images/hsva-sprite-sm.png | Bin 0 -> 19921 bytes
externs/GCL/externs/goog/images/hsva-sprite.gif | Bin 0 -> 36428 bytes
externs/GCL/externs/goog/images/hsva-sprite.png | Bin 0 -> 60591 bytes
.../goog/images/left_anchor_bubble_bot.gif | Bin 0 -> 431 bytes
.../goog/images/left_anchor_bubble_top.gif | Bin 0 -> 332 bytes
externs/GCL/externs/goog/images/menu-arrows.gif | Bin 0 -> 113 bytes
externs/GCL/externs/goog/images/minus.png | Bin 0 -> 238 bytes
.../goog/images/no_anchor_bubble_bot.gif | Bin 0 -> 228 bytes
.../goog/images/no_anchor_bubble_top.gif | Bin 0 -> 123 bytes
.../GCL/externs/goog/images/offlineicons.png | Bin 0 -> 5643 bytes
externs/GCL/externs/goog/images/plus.png | Bin 0 -> 239 bytes
externs/GCL/externs/goog/images/ratingstars.gif | Bin 0 -> 1139 bytes
.../goog/images/right_anchor_bubble_bot.gif | Bin 0 -> 425 bytes
.../goog/images/right_anchor_bubble_top.gif | Bin 0 -> 335 bytes
externs/GCL/externs/goog/images/toolbar-bg.png | Bin 0 -> 203 bytes
.../externs/goog/images/toolbar-separator.gif | Bin 0 -> 472 bytes
.../GCL/externs/goog/images/toolbar_icons.gif | Bin 0 -> 1062 bytes
externs/GCL/externs/goog/images/tree/I.png | Bin 0 -> 232 bytes
.../GCL/externs/goog/images/tree/cleardot.gif | Bin 0 -> 43 bytes
externs/GCL/externs/goog/images/tree/tree.gif | Bin 0 -> 1568 bytes
externs/GCL/externs/goog/images/tree/tree.png | Bin 0 -> 1262 bytes
externs/GCL/externs/goog/images/ui_controls.jpg | Bin 0 -> 21680 bytes
externs/GCL/externs/goog/iter/iter.js | 1305 +
.../GCL/externs/goog/json/evaljsonprocessor.js | 67 +
externs/GCL/externs/goog/json/hybrid.js | 103 +
.../externs/goog/json/hybridjsonprocessor.js | 47 +
externs/GCL/externs/goog/json/json.js | 365 +
externs/GCL/externs/goog/json/json_perf.js | 112 +
.../externs/goog/json/nativejsonprocessor.js | 73 +
externs/GCL/externs/goog/json/processor.js | 33 +
.../goog/labs/dom/pagevisibilitymonitor.js | 211 +
.../labs/events/nondisposableeventtarget.js | 305 +
externs/GCL/externs/goog/labs/events/touch.js | 82 +
externs/GCL/externs/goog/labs/format/csv.js | 415 +
.../goog/labs/html/attribute_rewriter.js | 74 +
externs/GCL/externs/goog/labs/html/sanitizer.js | 392 +
externs/GCL/externs/goog/labs/html/scrubber.js | 1027 +
.../GCL/externs/goog/labs/i18n/listformat.js | 261 +
.../GCL/externs/goog/labs/i18n/listsymbols.js | 1796 ++
.../externs/goog/labs/i18n/listsymbolsext.js | 10071 ++++++
.../GCL/externs/goog/labs/iterable/iterable.js | 139 +
externs/GCL/externs/goog/labs/mock/mock.js | 861 +
externs/GCL/externs/goog/labs/net/image.js | 94 +
.../externs/goog/labs/net/testdata/cleardot.gif | Bin 0 -> 43 bytes
.../goog/labs/net/testdata/xhr_test_json.data | 2 +
.../goog/labs/net/testdata/xhr_test_text.data | 1 +
externs/GCL/externs/goog/labs/net/webchannel.js | 311 +
.../externs/goog/labs/net/webchannel/channel.js | 181 +
.../goog/labs/net/webchannel/channelrequest.js | 1084 +
.../goog/labs/net/webchannel/connectionstate.js | 50 +
.../net/webchannel/forwardchannelrequestpool.js | 279 +
.../goog/labs/net/webchannel/netutils.js | 162 +
.../goog/labs/net/webchannel/requeststats.js | 383 +
.../goog/labs/net/webchannel/webchannelbase.js | 2084 ++
.../net/webchannel/webchannelbasetransport.js | 379 +
.../goog/labs/net/webchannel/webchanneldebug.js | 260 +
.../externs/goog/labs/net/webchannel/wire.js | 75 +
.../externs/goog/labs/net/webchannel/wirev8.js | 136 +
.../goog/labs/net/webchanneltransport.js | 75 +
.../goog/labs/net/webchanneltransportfactory.js | 37 +
externs/GCL/externs/goog/labs/net/xhr.js | 468 +
externs/GCL/externs/goog/labs/object/object.js | 47 +
.../externs/goog/labs/pubsub/broadcastpubsub.js | 564 +
.../labs/storage/boundedcollectablestorage.js | 287 +
externs/GCL/externs/goog/labs/structs/map.js | 348 +
.../GCL/externs/goog/labs/structs/map_perf.js | 205 +
.../GCL/externs/goog/labs/structs/multimap.js | 282 +
.../goog/labs/style/pixeldensitymonitor.js | 179 +
.../GCL/externs/goog/labs/testing/assertthat.js | 58 +
.../goog/labs/testing/decoratormatcher.js | 95 +
.../goog/labs/testing/dictionarymatcher.js | 273 +
.../externs/goog/labs/testing/environment.js | 293 +
.../externs/goog/labs/testing/logicmatcher.js | 212 +
.../GCL/externs/goog/labs/testing/matcher.js | 80 +
.../externs/goog/labs/testing/numbermatcher.js | 346 +
.../externs/goog/labs/testing/objectmatcher.js | 317 +
.../externs/goog/labs/testing/stringmatcher.js | 415 +
.../GCL/externs/goog/labs/useragent/browser.js | 327 +
.../GCL/externs/goog/labs/useragent/device.js | 65 +
.../GCL/externs/goog/labs/useragent/engine.js | 160 +
.../GCL/externs/goog/labs/useragent/platform.js | 160 +
externs/GCL/externs/goog/labs/useragent/util.js | 148 +
externs/GCL/externs/goog/locale/countries.js | 291 +
.../goog/locale/defaultlocalenameconstants.js | 941 +
.../GCL/externs/goog/locale/genericfontnames.js | 73 +
.../externs/goog/locale/genericfontnamesdata.js | 327 +
externs/GCL/externs/goog/locale/locale.js | 403 +
.../externs/goog/locale/nativenameconstants.js | 1354 +
.../externs/goog/locale/scriptToLanguages.js | 482 +
.../externs/goog/locale/timezonedetection.js | 116 +
.../externs/goog/locale/timezonefingerprint.js | 248 +
externs/GCL/externs/goog/locale/timezonelist.js | 131 +
externs/GCL/externs/goog/log/log.js | 197 +
.../GCL/externs/goog/math/affinetransform.js | 589 +
externs/GCL/externs/goog/math/bezier.js | 340 +
externs/GCL/externs/goog/math/box.js | 389 +
externs/GCL/externs/goog/math/coordinate.js | 268 +
externs/GCL/externs/goog/math/coordinate3.js | 170 +
.../GCL/externs/goog/math/exponentialbackoff.js | 104 +
externs/GCL/externs/goog/math/integer.js | 739 +
.../goog/math/interpolator/interpolator1.js | 64 +
.../externs/goog/math/interpolator/linear1.js | 84 +
.../externs/goog/math/interpolator/pchip1.js | 82 +
.../externs/goog/math/interpolator/spline1.js | 203 +
externs/GCL/externs/goog/math/line.js | 179 +
externs/GCL/externs/goog/math/long.js | 804 +
externs/GCL/externs/goog/math/math.js | 435 +
externs/GCL/externs/goog/math/matrix.js | 681 +
externs/GCL/externs/goog/math/path.js | 598 +
externs/GCL/externs/goog/math/paths.js | 86 +
externs/GCL/externs/goog/math/range.js | 186 +
externs/GCL/externs/goog/math/rangeset.js | 396 +
externs/GCL/externs/goog/math/rect.js | 464 +
externs/GCL/externs/goog/math/size.js | 227 +
externs/GCL/externs/goog/math/tdma.js | 73 +
externs/GCL/externs/goog/math/vec2.js | 284 +
externs/GCL/externs/goog/math/vec3.js | 310 +
externs/GCL/externs/goog/memoize/memoize.js | 104 +
.../externs/goog/messaging/abstractchannel.js | 209 +
.../externs/goog/messaging/bufferedchannel.js | 287 +
.../externs/goog/messaging/deferredchannel.js | 98 +
.../GCL/externs/goog/messaging/loggerclient.js | 132 +
.../GCL/externs/goog/messaging/loggerserver.js | 100 +
.../externs/goog/messaging/messagechannel.js | 116 +
externs/GCL/externs/goog/messaging/messaging.js | 32 +
.../GCL/externs/goog/messaging/multichannel.js | 303 +
.../GCL/externs/goog/messaging/portcaller.js | 152 +
.../GCL/externs/goog/messaging/portchannel.js | 401 +
.../GCL/externs/goog/messaging/portnetwork.js | 78 +
.../GCL/externs/goog/messaging/portoperator.js | 198 +
.../externs/goog/messaging/respondingchannel.js | 234 +
.../messaging/testdata/portchannel_worker.js | 37 +
.../messaging/testdata/portnetwork_worker1.js | 32 +
.../messaging/testdata/portnetwork_worker2.js | 32 +
.../externs/goog/module/abstractmoduleloader.js | 58 +
externs/GCL/externs/goog/module/basemodule.js | 47 +
externs/GCL/externs/goog/module/loader.js | 347 +
externs/GCL/externs/goog/module/module.js | 33 +
externs/GCL/externs/goog/module/moduleinfo.js | 341 +
.../externs/goog/module/moduleloadcallback.js | 86 +
externs/GCL/externs/goog/module/moduleloader.js | 461 +
.../GCL/externs/goog/module/modulemanager.js | 1358 +
.../GCL/externs/goog/module/testdata/modA_1.js | 26 +
.../GCL/externs/goog/module/testdata/modA_2.js | 29 +
.../GCL/externs/goog/module/testdata/modB_1.js | 33 +
externs/GCL/externs/goog/net/browserchannel.js | 2765 ++
externs/GCL/externs/goog/net/bulkloader.js | 182 +
.../GCL/externs/goog/net/bulkloaderhelper.js | 119 +
externs/GCL/externs/goog/net/channeldebug.js | 300 +
externs/GCL/externs/goog/net/channelrequest.js | 1339 +
externs/GCL/externs/goog/net/cookies.js | 371 +
.../GCL/externs/goog/net/corsxmlhttpfactory.js | 272 +
externs/GCL/externs/goog/net/crossdomainrpc.js | 894 +
.../externs/goog/net/crossdomainrpc_test.css | 7 +
.../externs/goog/net/crossdomainrpc_test.gif | 0
externs/GCL/externs/goog/net/errorcode.js | 130 +
externs/GCL/externs/goog/net/eventtype.js | 37 +
externs/GCL/externs/goog/net/filedownloader.js | 746 +
externs/GCL/externs/goog/net/httpstatus.js | 116 +
externs/GCL/externs/goog/net/iframeio.js | 1405 +
.../goog/net/iframeio_different_base_test.data | 2 +
.../GCL/externs/goog/net/iframeloadmonitor.js | 204 +
externs/GCL/externs/goog/net/imageloader.js | 338 +
.../externs/goog/net/imageloader_testimg1.gif | Bin 0 -> 453 bytes
.../externs/goog/net/imageloader_testimg2.gif | Bin 0 -> 460 bytes
.../externs/goog/net/imageloader_testimg3.gif | Bin 0 -> 13446 bytes
externs/GCL/externs/goog/net/ipaddress.js | 509 +
externs/GCL/externs/goog/net/jsloader.js | 367 +
externs/GCL/externs/goog/net/jsonp.js | 340 +
externs/GCL/externs/goog/net/mockiframeio.js | 308 +
.../externs/goog/net/multiiframeloadmonitor.js | 118 +
.../externs/goog/net/networkstatusmonitor.js | 47 +
externs/GCL/externs/goog/net/tmpnetwork.js | 164 +
externs/GCL/externs/goog/net/websocket.js | 524 +
.../externs/goog/net/wrapperxmlhttpfactory.js | 71 +
externs/GCL/externs/goog/net/xhrio.js | 1224 +
externs/GCL/externs/goog/net/xhriopool.js | 79 +
externs/GCL/externs/goog/net/xhrlike.js | 124 +
externs/GCL/externs/goog/net/xhrmanager.js | 772 +
externs/GCL/externs/goog/net/xmlhttp.js | 246 +
externs/GCL/externs/goog/net/xmlhttpfactory.js | 67 +
.../externs/goog/net/xpc/crosspagechannel.js | 855 +
.../goog/net/xpc/crosspagechannelrole.js | 30 +
.../GCL/externs/goog/net/xpc/directtransport.js | 635 +
.../goog/net/xpc/frameelementmethodtransport.js | 270 +
.../goog/net/xpc/iframepollingtransport.js | 985 +
.../goog/net/xpc/iframerelaytransport.js | 410 +
.../goog/net/xpc/nativemessagingtransport.js | 648 +
.../GCL/externs/goog/net/xpc/nixtransport.js | 483 +
externs/GCL/externs/goog/net/xpc/relay.js | 73 +
externs/GCL/externs/goog/net/xpc/transport.js | 105 +
externs/GCL/externs/goog/net/xpc/xpc.js | 300 +
externs/GCL/externs/goog/object/object.js | 686 +
.../goog/positioning/absoluteposition.js | 73 +
.../goog/positioning/abstractposition.js | 44 +
.../goog/positioning/anchoredposition.js | 92 +
.../positioning/anchoredviewportposition.js | 189 +
.../externs/goog/positioning/clientposition.js | 89 +
.../goog/positioning/menuanchoredposition.js | 66 +
.../GCL/externs/goog/positioning/positioning.js | 619 +
.../goog/positioning/viewportclientposition.js | 124 +
.../goog/positioning/viewportposition.js | 66 +
externs/GCL/externs/goog/promise/promise.js | 1304 +
externs/GCL/externs/goog/promise/resolver.js | 48 +
externs/GCL/externs/goog/promise/thenable.js | 111 +
externs/GCL/externs/goog/proto/proto.js | 44 +
externs/GCL/externs/goog/proto/serializer.js | 70 +
externs/GCL/externs/goog/proto2/descriptor.js | 202 +
.../GCL/externs/goog/proto2/fielddescriptor.js | 312 +
.../GCL/externs/goog/proto2/lazydeserializer.js | 70 +
externs/GCL/externs/goog/proto2/message.js | 722 +
.../GCL/externs/goog/proto2/objectserializer.js | 176 +
.../GCL/externs/goog/proto2/pbliteserializer.js | 199 +
externs/GCL/externs/goog/proto2/serializer.js | 182 +
.../externs/goog/proto2/textformatserializer.js | 1072 +
externs/GCL/externs/goog/proto2/util.js | 54 +
externs/GCL/externs/goog/pubsub/pubsub.js | 321 +
externs/GCL/externs/goog/pubsub/topicid.js | 61 +
externs/GCL/externs/goog/pubsub/typedpubsub.js | 126 +
externs/GCL/externs/goog/reflect/reflect.js | 78 +
.../GCL/externs/goog/result/deferredadaptor.js | 59 +
.../GCL/externs/goog/result/dependentresult.js | 45 +
.../GCL/externs/goog/result/result_interface.js | 119 +
externs/GCL/externs/goog/result/resultutil.js | 556 +
externs/GCL/externs/goog/result/simpleresult.js | 260 +
externs/GCL/externs/goog/soy/data.js | 160 +
externs/GCL/externs/goog/soy/renderer.js | 314 +
externs/GCL/externs/goog/soy/soy.js | 218 +
externs/GCL/externs/goog/spell/spellcheck.js | 478 +
externs/GCL/externs/goog/stats/basicstat.js | 270 +
.../externs/goog/storage/collectablestorage.js | 134 +
.../externs/goog/storage/encryptedstorage.js | 196 +
externs/GCL/externs/goog/storage/errorcode.js | 30 +
.../GCL/externs/goog/storage/expiringstorage.js | 141 +
.../externs/goog/storage/mechanism/errorcode.js | 31 +
.../storage/mechanism/errorhandlingmechanism.js | 131 +
.../goog/storage/mechanism/html5localstorage.js | 46 +
.../storage/mechanism/html5sessionstorage.js | 47 +
.../goog/storage/mechanism/html5webstorage.js | 172 +
.../goog/storage/mechanism/ieuserdata.js | 279 +
.../goog/storage/mechanism/iterablemechanism.js | 86 +
.../externs/goog/storage/mechanism/mechanism.js | 57 +
.../goog/storage/mechanism/mechanismfactory.js | 112 +
.../goog/storage/mechanism/prefixedmechanism.js | 92 +
externs/GCL/externs/goog/storage/richstorage.js | 150 +
externs/GCL/externs/goog/storage/storage.js | 97 +
externs/GCL/externs/goog/string/const.js | 182 +
externs/GCL/externs/goog/string/linkify.js | 252 +
externs/GCL/externs/goog/string/newlines.js | 154 +
externs/GCL/externs/goog/string/parser.js | 38 +
externs/GCL/externs/goog/string/path.js | 169 +
externs/GCL/externs/goog/string/string.js | 1565 +
externs/GCL/externs/goog/string/stringbuffer.js | 103 +
externs/GCL/externs/goog/string/stringformat.js | 250 +
externs/GCL/externs/goog/string/stringifier.js | 38 +
externs/GCL/externs/goog/string/typedstring.js | 48 +
externs/GCL/externs/goog/structs/avltree.js | 899 +
.../GCL/externs/goog/structs/circularbuffer.js | 216 +
externs/GCL/externs/goog/structs/collection.js | 56 +
externs/GCL/externs/goog/structs/heap.js | 334 +
.../GCL/externs/goog/structs/inversionmap.js | 155 +
externs/GCL/externs/goog/structs/linkedmap.js | 488 +
externs/GCL/externs/goog/structs/map.js | 456 +
externs/GCL/externs/goog/structs/node.js | 73 +
externs/GCL/externs/goog/structs/pool.js | 376 +
.../GCL/externs/goog/structs/prioritypool.js | 182 +
.../GCL/externs/goog/structs/priorityqueue.js | 66 +
externs/GCL/externs/goog/structs/quadtree.js | 570 +
externs/GCL/externs/goog/structs/queue.js | 187 +
externs/GCL/externs/goog/structs/set.js | 279 +
externs/GCL/externs/goog/structs/simplepool.js | 200 +
externs/GCL/externs/goog/structs/stringset.js | 405 +
externs/GCL/externs/goog/structs/structs.js | 354 +
externs/GCL/externs/goog/structs/treenode.js | 458 +
externs/GCL/externs/goog/structs/trie.js | 395 +
externs/GCL/externs/goog/structs/weak/weak.js | 159 +
externs/GCL/externs/goog/style/bidi.js | 184 +
externs/GCL/externs/goog/style/cursor.js | 116 +
externs/GCL/externs/goog/style/style.js | 2045 ++
.../GCL/externs/goog/style/style_test_rect.svg | 11 +
externs/GCL/externs/goog/style/transform.js | 169 +
externs/GCL/externs/goog/style/transition.js | 133 +
externs/GCL/externs/goog/testing/asserts.js | 1265 +
.../externs/goog/testing/async/mockcontrol.js | 175 +
externs/GCL/externs/goog/testing/benchmark.js | 96 +
externs/GCL/externs/goog/testing/dom.js | 633 +
externs/GCL/externs/goog/testing/editor/dom.js | 293 +
.../externs/goog/testing/editor/fieldmock.js | 116 +
.../goog/testing/events/eventobserver.js | 87 +
.../GCL/externs/goog/testing/events/events.js | 727 +
.../GCL/externs/goog/testing/events/matchers.js | 42 +
.../goog/testing/events/onlinehandler.js | 65 +
.../externs/goog/testing/expectedfailures.js | 237 +
externs/GCL/externs/goog/testing/fs/blob.js | 135 +
externs/GCL/externs/goog/testing/fs/entry.js | 637 +
externs/GCL/externs/goog/testing/fs/file.js | 53 +
.../GCL/externs/goog/testing/fs/filereader.js | 275 +
.../GCL/externs/goog/testing/fs/filesystem.js | 64 +
.../GCL/externs/goog/testing/fs/filewriter.js | 268 +
externs/GCL/externs/goog/testing/fs/fs.js | 169 +
.../externs/goog/testing/fs/progressevent.js | 82 +
.../GCL/externs/goog/testing/functionmock.js | 176 +
externs/GCL/externs/goog/testing/graphics.js | 64 +
.../GCL/externs/goog/testing/i18n/asserts.js | 77 +
externs/GCL/externs/goog/testing/jsunit.js | 162 +
externs/GCL/externs/goog/testing/loosemock.js | 242 +
.../testing/messaging/mockmessagechannel.js | 80 +
.../goog/testing/messaging/mockmessageevent.js | 102 +
.../goog/testing/messaging/mockmessageport.js | 86 +
.../goog/testing/messaging/mockportnetwork.js | 66 +
externs/GCL/externs/goog/testing/mock.js | 645 +
.../externs/goog/testing/mockclassfactory.js | 585 +
externs/GCL/externs/goog/testing/mockclock.js | 600 +
externs/GCL/externs/goog/testing/mockcontrol.js | 220 +
.../GCL/externs/goog/testing/mockinterface.js | 45 +
.../GCL/externs/goog/testing/mockmatchers.js | 400 +
externs/GCL/externs/goog/testing/mockrandom.js | 153 +
externs/GCL/externs/goog/testing/mockrange.js | 67 +
externs/GCL/externs/goog/testing/mockstorage.js | 108 +
.../GCL/externs/goog/testing/mockuseragent.js | 143 +
externs/GCL/externs/goog/testing/net/xhrio.js | 743 +
.../GCL/externs/goog/testing/net/xhriopool.js | 65 +
.../goog/testing/objectpropertystring.js | 68 +
.../externs/goog/testing/performancetable.css | 46 +
.../externs/goog/testing/performancetable.js | 196 +
.../externs/goog/testing/performancetimer.js | 418 +
.../externs/goog/testing/propertyreplacer.js | 245 +
.../GCL/externs/goog/testing/proto2/proto2.js | 145 +
.../GCL/externs/goog/testing/pseudorandom.js | 180 +
.../GCL/externs/goog/testing/recordfunction.js | 215 +
externs/GCL/externs/goog/testing/singleton.js | 46 +
externs/GCL/externs/goog/testing/stacktrace.js | 594 +
.../goog/testing/storage/fakemechanism.js | 68 +
externs/GCL/externs/goog/testing/strictmock.js | 130 +
.../externs/goog/testing/style/layoutasserts.js | 310 +
externs/GCL/externs/goog/testing/style/style.js | 101 +
.../externs/goog/testing/ui/rendererasserts.js | 58 +
.../externs/goog/testing/ui/rendererharness.js | 177 +
externs/GCL/externs/goog/testing/ui/style.js | 140 +
externs/GCL/externs/goog/testing/watchers.js | 46 +
externs/GCL/externs/goog/timer/timer.js | 329 +
externs/GCL/externs/goog/tweak/entries.js | 1002 +
externs/GCL/externs/goog/tweak/registry.js | 315 +
externs/GCL/externs/goog/tweak/tweak.js | 301 +
externs/GCL/externs/goog/tweak/tweakui.js | 841 +
.../GCL/externs/goog/ui/abstractspellchecker.js | 1231 +
externs/GCL/externs/goog/ui/ac/ac.js | 50 +
externs/GCL/externs/goog/ui/ac/arraymatcher.js | 216 +
externs/GCL/externs/goog/ui/ac/autocomplete.js | 921 +
.../GCL/externs/goog/ui/ac/cachingmatcher.js | 273 +
externs/GCL/externs/goog/ui/ac/inputhandler.js | 1327 +
externs/GCL/externs/goog/ui/ac/remote.js | 114 +
.../externs/goog/ui/ac/remotearraymatcher.js | 274 +
externs/GCL/externs/goog/ui/ac/renderer.js | 1109 +
externs/GCL/externs/goog/ui/ac/renderoptions.js | 80 +
.../GCL/externs/goog/ui/ac/richinputhandler.js | 58 +
externs/GCL/externs/goog/ui/ac/richremote.js | 113 +
.../goog/ui/ac/richremotearraymatcher.js | 144 +
externs/GCL/externs/goog/ui/activitymonitor.js | 348 +
externs/GCL/externs/goog/ui/advancedtooltip.js | 367 +
externs/GCL/externs/goog/ui/animatedzippy.js | 202 +
externs/GCL/externs/goog/ui/attachablemenu.js | 476 +
externs/GCL/externs/goog/ui/bidiinput.js | 174 +
externs/GCL/externs/goog/ui/bubble.js | 490 +
externs/GCL/externs/goog/ui/button.js | 214 +
externs/GCL/externs/goog/ui/buttonrenderer.js | 219 +
externs/GCL/externs/goog/ui/buttonside.js | 41 +
externs/GCL/externs/goog/ui/charcounter.js | 199 +
externs/GCL/externs/goog/ui/charpicker.js | 925 +
externs/GCL/externs/goog/ui/checkbox.js | 272 +
externs/GCL/externs/goog/ui/checkboxmenuitem.js | 53 +
externs/GCL/externs/goog/ui/checkboxrenderer.js | 191 +
externs/GCL/externs/goog/ui/colorbutton.js | 59 +
.../GCL/externs/goog/ui/colorbuttonrenderer.js | 75 +
externs/GCL/externs/goog/ui/colormenubutton.js | 215 +
.../externs/goog/ui/colormenubuttonrenderer.js | 148 +
externs/GCL/externs/goog/ui/colorpalette.js | 179 +
externs/GCL/externs/goog/ui/colorpicker.js | 345 +
.../GCL/externs/goog/ui/colorsplitbehavior.js | 61 +
externs/GCL/externs/goog/ui/combobox.js | 993 +
externs/GCL/externs/goog/ui/component.js | 1298 +
externs/GCL/externs/goog/ui/container.js | 1354 +
.../GCL/externs/goog/ui/containerrenderer.js | 375 +
.../GCL/externs/goog/ui/containerscroller.js | 223 +
externs/GCL/externs/goog/ui/control.js | 1542 +
externs/GCL/externs/goog/ui/controlcontent.js | 28 +
externs/GCL/externs/goog/ui/controlrenderer.js | 949 +
externs/GCL/externs/goog/ui/cookieeditor.js | 185 +
.../GCL/externs/goog/ui/css3buttonrenderer.js | 155 +
.../externs/goog/ui/css3menubuttonrenderer.js | 148 +
externs/GCL/externs/goog/ui/cssnames.js | 29 +
externs/GCL/externs/goog/ui/custombutton.js | 58 +
.../GCL/externs/goog/ui/custombuttonrenderer.js | 272 +
.../GCL/externs/goog/ui/customcolorpalette.js | 141 +
externs/GCL/externs/goog/ui/datepicker.js | 1550 +
.../GCL/externs/goog/ui/datepickerrenderer.js | 55 +
externs/GCL/externs/goog/ui/decorate.js | 38 +
.../goog/ui/defaultdatepickerrenderer.js | 202 +
externs/GCL/externs/goog/ui/dialog.js | 1611 +
externs/GCL/externs/goog/ui/dimensionpicker.js | 318 +
.../externs/goog/ui/dimensionpickerrenderer.js | 420 +
externs/GCL/externs/goog/ui/dragdropdetector.js | 648 +
externs/GCL/externs/goog/ui/drilldownrow.js | 547 +
.../externs/goog/ui/editor/abstractdialog.js | 444 +
externs/GCL/externs/goog/ui/editor/bubble.js | 559 +
.../externs/goog/ui/editor/defaulttoolbar.js | 1066 +
.../GCL/externs/goog/ui/editor/linkdialog.js | 1065 +
externs/GCL/externs/goog/ui/editor/messages.js | 148 +
externs/GCL/externs/goog/ui/editor/tabpane.js | 202 +
.../externs/goog/ui/editor/toolbarcontroller.js | 296 +
.../externs/goog/ui/editor/toolbarfactory.js | 439 +
externs/GCL/externs/goog/ui/emoji/emoji.js | 73 +
.../GCL/externs/goog/ui/emoji/emojipalette.js | 288 +
.../goog/ui/emoji/emojipaletterenderer.js | 210 +
.../GCL/externs/goog/ui/emoji/emojipicker.js | 802 +
.../externs/goog/ui/emoji/popupemojipicker.js | 411 +
.../ui/emoji/progressiveemojipaletterenderer.js | 100 +
externs/GCL/externs/goog/ui/emoji/spriteinfo.js | 213 +
externs/GCL/externs/goog/ui/filteredmenu.js | 638 +
.../externs/goog/ui/filterobservingmenuitem.js | 98 +
.../goog/ui/filterobservingmenuitemrenderer.js | 63 +
.../GCL/externs/goog/ui/flatbuttonrenderer.js | 148 +
.../externs/goog/ui/flatmenubuttonrenderer.js | 209 +
externs/GCL/externs/goog/ui/formpost.js | 109 +
externs/GCL/externs/goog/ui/gauge.js | 1014 +
externs/GCL/externs/goog/ui/gaugetheme.js | 170 +
externs/GCL/externs/goog/ui/hovercard.js | 458 +
externs/GCL/externs/goog/ui/hsvapalette.js | 295 +
externs/GCL/externs/goog/ui/hsvpalette.js | 527 +
externs/GCL/externs/goog/ui/idgenerator.js | 48 +
externs/GCL/externs/goog/ui/idletimer.js | 300 +
externs/GCL/externs/goog/ui/iframemask.js | 258 +
.../externs/goog/ui/imagelessbuttonrenderer.js | 208 +
.../goog/ui/imagelessmenubuttonrenderer.js | 213 +
externs/GCL/externs/goog/ui/inputdatepicker.js | 343 +
externs/GCL/externs/goog/ui/itemevent.js | 51 +
.../externs/goog/ui/keyboardshortcuthandler.js | 1162 +
externs/GCL/externs/goog/ui/labelinput.js | 614 +
.../GCL/externs/goog/ui/linkbuttonrenderer.js | 67 +
.../GCL/externs/goog/ui/media/flashobject.js | 632 +
externs/GCL/externs/goog/ui/media/flickr.js | 314 +
.../GCL/externs/goog/ui/media/googlevideo.js | 283 +
externs/GCL/externs/goog/ui/media/media.js | 290 +
externs/GCL/externs/goog/ui/media/mediamodel.js | 978 +
externs/GCL/externs/goog/ui/media/mp3.js | 226 +
externs/GCL/externs/goog/ui/media/photo.js | 144 +
externs/GCL/externs/goog/ui/media/picasa.js | 327 +
externs/GCL/externs/goog/ui/media/vimeo.js | 278 +
externs/GCL/externs/goog/ui/media/youtube.js | 359 +
externs/GCL/externs/goog/ui/menu.js | 479 +
externs/GCL/externs/goog/ui/menubar.js | 44 +
externs/GCL/externs/goog/ui/menubardecorator.js | 35 +
externs/GCL/externs/goog/ui/menubarrenderer.js | 68 +
externs/GCL/externs/goog/ui/menubase.js | 190 +
externs/GCL/externs/goog/ui/menubutton.js | 1052 +
.../GCL/externs/goog/ui/menubuttonrenderer.js | 192 +
externs/GCL/externs/goog/ui/menuheader.js | 62 +
.../GCL/externs/goog/ui/menuheaderrenderer.js | 54 +
externs/GCL/externs/goog/ui/menuitem.js | 322 +
externs/GCL/externs/goog/ui/menuitemrenderer.js | 356 +
externs/GCL/externs/goog/ui/menurenderer.js | 115 +
externs/GCL/externs/goog/ui/menuseparator.js | 52 +
.../externs/goog/ui/menuseparatorrenderer.js | 114 +
.../GCL/externs/goog/ui/mockactivitymonitor.js | 72 +
.../goog/ui/modalariavisibilityhelper.js | 87 +
externs/GCL/externs/goog/ui/modalpopup.js | 732 +
.../GCL/externs/goog/ui/nativebuttonrenderer.js | 213 +
externs/GCL/externs/goog/ui/option.js | 68 +
externs/GCL/externs/goog/ui/palette.js | 604 +
externs/GCL/externs/goog/ui/paletterenderer.js | 383 +
.../externs/goog/ui/plaintextspellchecker.js | 643 +
externs/GCL/externs/goog/ui/popup.js | 185 +
externs/GCL/externs/goog/ui/popupbase.js | 894 +
externs/GCL/externs/goog/ui/popupcolorpicker.js | 475 +
externs/GCL/externs/goog/ui/popupdatepicker.js | 288 +
externs/GCL/externs/goog/ui/popupmenu.js | 643 +
externs/GCL/externs/goog/ui/progressbar.js | 408 +
externs/GCL/externs/goog/ui/prompt.js | 411 +
externs/GCL/externs/goog/ui/rangemodel.js | 303 +
externs/GCL/externs/goog/ui/ratings.js | 509 +
externs/GCL/externs/goog/ui/registry.js | 172 +
.../GCL/externs/goog/ui/richtextspellchecker.js | 780 +
externs/GCL/externs/goog/ui/roundedpanel.js | 632 +
.../GCL/externs/goog/ui/roundedtabrenderer.js | 201 +
externs/GCL/externs/goog/ui/scrollfloater.js | 637 +
externs/GCL/externs/goog/ui/select.js | 538 +
.../GCL/externs/goog/ui/selectionmenubutton.js | 302 +
externs/GCL/externs/goog/ui/selectionmodel.js | 301 +
externs/GCL/externs/goog/ui/separator.js | 80 +
externs/GCL/externs/goog/ui/serverchart.js | 1840 ++
externs/GCL/externs/goog/ui/slider.js | 136 +
externs/GCL/externs/goog/ui/sliderbase.js | 1657 +
externs/GCL/externs/goog/ui/splitbehavior.js | 335 +
externs/GCL/externs/goog/ui/splitpane.js | 911 +
.../externs/goog/ui/style/app/buttonrenderer.js | 205 +
.../goog/ui/style/app/menubuttonrenderer.js | 236 +
.../ui/style/app/primaryactionbuttonrenderer.js | 89 +
externs/GCL/externs/goog/ui/submenu.js | 672 +
externs/GCL/externs/goog/ui/submenurenderer.js | 241 +
externs/GCL/externs/goog/ui/tab.js | 103 +
externs/GCL/externs/goog/ui/tabbar.js | 395 +
externs/GCL/externs/goog/ui/tabbarrenderer.js | 165 +
externs/GCL/externs/goog/ui/tablesorter.js | 324 +
externs/GCL/externs/goog/ui/tabpane.js | 682 +
externs/GCL/externs/goog/ui/tabrenderer.js | 153 +
externs/GCL/externs/goog/ui/textarea.js | 736 +
externs/GCL/externs/goog/ui/textarearenderer.js | 170 +
externs/GCL/externs/goog/ui/togglebutton.js | 58 +
externs/GCL/externs/goog/ui/toolbar.js | 59 +
externs/GCL/externs/goog/ui/toolbarbutton.js | 54 +
.../externs/goog/ui/toolbarbuttonrenderer.js | 57 +
.../externs/goog/ui/toolbarcolormenubutton.js | 57 +
.../goog/ui/toolbarcolormenubuttonrenderer.js | 101 +
.../GCL/externs/goog/ui/toolbarmenubutton.js | 56 +
.../goog/ui/toolbarmenubuttonrenderer.js | 57 +
externs/GCL/externs/goog/ui/toolbarrenderer.js | 90 +
externs/GCL/externs/goog/ui/toolbarselect.js | 55 +
externs/GCL/externs/goog/ui/toolbarseparator.js | 53 +
.../externs/goog/ui/toolbarseparatorrenderer.js | 95 +
.../GCL/externs/goog/ui/toolbartogglebutton.js | 53 +
externs/GCL/externs/goog/ui/tooltip.js | 1050 +
externs/GCL/externs/goog/ui/tree/basenode.js | 1569 +
externs/GCL/externs/goog/ui/tree/treecontrol.js | 642 +
externs/GCL/externs/goog/ui/tree/treenode.js | 100 +
externs/GCL/externs/goog/ui/tree/typeahead.js | 332 +
externs/GCL/externs/goog/ui/tristatemenuitem.js | 196 +
.../externs/goog/ui/tristatemenuitemrenderer.js | 92 +
externs/GCL/externs/goog/ui/twothumbslider.js | 159 +
externs/GCL/externs/goog/ui/zippy.js | 461 +
externs/GCL/externs/goog/uri/uri.js | 1507 +
externs/GCL/externs/goog/uri/utils.js | 1116 +
.../GCL/externs/goog/useragent/adobereader.js | 90 +
externs/GCL/externs/goog/useragent/flash.js | 156 +
externs/GCL/externs/goog/useragent/iphoto.js | 87 +
externs/GCL/externs/goog/useragent/jscript.js | 95 +
externs/GCL/externs/goog/useragent/keyboard.js | 49 +
externs/GCL/externs/goog/useragent/platform.js | 83 +
externs/GCL/externs/goog/useragent/product.js | 175 +
.../externs/goog/useragent/product_isversion.js | 143 +
externs/GCL/externs/goog/useragent/useragent.js | 538 +
externs/GCL/externs/goog/vec/float32array.js | 111 +
externs/GCL/externs/goog/vec/float64array.js | 118 +
externs/GCL/externs/goog/vec/mat3.js | 1211 +
externs/GCL/externs/goog/vec/mat3d.js | 1039 +
externs/GCL/externs/goog/vec/mat3f.js | 1039 +
externs/GCL/externs/goog/vec/mat4.js | 1822 ++
externs/GCL/externs/goog/vec/mat4d.js | 1769 ++
externs/GCL/externs/goog/vec/mat4f.js | 1769 ++
externs/GCL/externs/goog/vec/matrix3.js | 720 +
externs/GCL/externs/goog/vec/matrix4.js | 1405 +
externs/GCL/externs/goog/vec/quaternion.js | 458 +
externs/GCL/externs/goog/vec/ray.js | 95 +
externs/GCL/externs/goog/vec/vec.js | 73 +
externs/GCL/externs/goog/vec/vec2.js | 439 +
externs/GCL/externs/goog/vec/vec2d.js | 424 +
externs/GCL/externs/goog/vec/vec2f.js | 424 +
externs/GCL/externs/goog/vec/vec3.js | 542 +
externs/GCL/externs/goog/vec/vec3d.js | 426 +
externs/GCL/externs/goog/vec/vec3f.js | 426 +
externs/GCL/externs/goog/vec/vec4.js | 479 +
externs/GCL/externs/goog/vec/vec4d.js | 366 +
externs/GCL/externs/goog/vec/vec4f.js | 366 +
externs/GCL/externs/goog/webgl/webgl.js | 2194 ++
externs/GCL/externs/goog/window/window.js | 284 +
externs/GCL/src/goog/Disposable.as | 132 +
externs/GCL/src/goog/disposable/Disposable.as | 14 +
externs/GCL/src/goog/disposable/IDisposable.as | 14 +
.../GCL/src/goog/disposable/MonitoringMode.as | 31 +
externs/GCL/src/goog/events.as | 6 +
externs/GCL/src/goog/events/BrowserEvent.as | 94 +
.../src/goog/events/BrowserEvent/MouseButton.as | 33 +
.../src/goog/events/CaptureSimulationMode.as | 31 +
externs/GCL/src/goog/events/Event.as | 52 +
externs/GCL/src/goog/events/EventTarget.as | 213 +
externs/GCL/src/goog/events/EventType.as | 838 +
externs/GCL/src/goog/events/Listenable.as | 143 +
externs/GCL/src/goog/events/ListenableKey.as | 73 +
externs/GCL/src/goog/events/listen.as | 5 +
1074 files changed, 412464 insertions(+)
----------------------------------------------------------------------
[38/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/debug.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/debug.js b/externs/GCL/externs/goog/debug/debug.js
new file mode 100644
index 0000000..ff15374
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/debug.js
@@ -0,0 +1,653 @@
+// 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 Logging and debugging utilities.
+ *
+ * @see ../demos/debug.html
+ */
+
+goog.provide('goog.debug');
+
+goog.require('goog.array');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeUrl');
+goog.require('goog.html.uncheckedconversions');
+goog.require('goog.string.Const');
+goog.require('goog.structs.Set');
+goog.require('goog.userAgent');
+
+
+/** @define {boolean} Whether logging should be enabled. */
+goog.define('goog.debug.LOGGING_ENABLED', goog.DEBUG);
+
+
+/**
+ * Catches onerror events fired by windows and similar objects.
+ * @param {function(Object)} logFunc The function to call with the error
+ * information.
+ * @param {boolean=} opt_cancel Whether to stop the error from reaching the
+ * browser.
+ * @param {Object=} opt_target Object that fires onerror events.
+ */
+goog.debug.catchErrors = function(logFunc, opt_cancel, opt_target) {
+ var target = opt_target || goog.global;
+ var oldErrorHandler = target.onerror;
+ var retVal = !!opt_cancel;
+
+ // Chrome interprets onerror return value backwards (http://crbug.com/92062)
+ // until it was fixed in webkit revision r94061 (Webkit 535.3). This
+ // workaround still needs to be skipped in Safari after the webkit change
+ // gets pushed out in Safari.
+ // See https://bugs.webkit.org/show_bug.cgi?id=67119
+ if (goog.userAgent.WEBKIT &&
+ !goog.userAgent.isVersionOrHigher('535.3')) {
+ retVal = !retVal;
+ }
+
+ /**
+ * New onerror handler for this target. This onerror handler follows the spec
+ * according to
+ * http://www.whatwg.org/specs/web-apps/current-work/#runtime-script-errors
+ * The spec was changed in August 2013 to support receiving column information
+ * and an error object for all scripts on the same origin or cross origin
+ * scripts with the proper headers. See
+ * https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
+ *
+ * @param {string} message The error message. For cross-origin errors, this
+ * will be scrubbed to just "Script error.". For new browsers that have
+ * updated to follow the latest spec, errors that come from origins that
+ * have proper cross origin headers will not be scrubbed.
+ * @param {string} url The URL of the script that caused the error. The URL
+ * will be scrubbed to "" for cross origin scripts unless the script has
+ * proper cross origin headers and the browser has updated to the latest
+ * spec.
+ * @param {number} line The line number in the script that the error
+ * occurred on.
+ * @param {number=} opt_col The optional column number that the error
+ * occurred on. Only browsers that have updated to the latest spec will
+ * include this.
+ * @param {Error=} opt_error The optional actual error object for this
+ * error that should include the stack. Only browsers that have updated
+ * to the latest spec will inlude this parameter.
+ * @return {boolean} Whether to prevent the error from reaching the browser.
+ */
+ target.onerror = function(message, url, line, opt_col, opt_error) {
+ if (oldErrorHandler) {
+ oldErrorHandler(message, url, line, opt_col, opt_error);
+ }
+ logFunc({
+ message: message,
+ fileName: url,
+ line: line,
+ col: opt_col,
+ error: opt_error
+ });
+ return retVal;
+ };
+};
+
+
+/**
+ * Creates a string representing an object and all its properties.
+ * @param {Object|null|undefined} obj Object to expose.
+ * @param {boolean=} opt_showFn Show the functions as well as the properties,
+ * default is false.
+ * @return {string} The string representation of {@code obj}.
+ */
+goog.debug.expose = function(obj, opt_showFn) {
+ if (typeof obj == 'undefined') {
+ return 'undefined';
+ }
+ if (obj == null) {
+ return 'NULL';
+ }
+ var str = [];
+
+ for (var x in obj) {
+ if (!opt_showFn && goog.isFunction(obj[x])) {
+ continue;
+ }
+ var s = x + ' = ';
+ /** @preserveTry */
+ try {
+ s += obj[x];
+ } catch (e) {
+ s += '*** ' + e + ' ***';
+ }
+ str.push(s);
+ }
+ return str.join('\n');
+};
+
+
+/**
+ * Creates a string representing a given primitive or object, and for an
+ * object, all its properties and nested objects. WARNING: If an object is
+ * given, it and all its nested objects will be modified. To detect reference
+ * cycles, this method identifies objects using goog.getUid() which mutates the
+ * object.
+ * @param {*} obj Object to expose.
+ * @param {boolean=} opt_showFn Also show properties that are functions (by
+ * default, functions are omitted).
+ * @return {string} A string representation of {@code obj}.
+ */
+goog.debug.deepExpose = function(obj, opt_showFn) {
+ var str = [];
+
+ var helper = function(obj, space, parentSeen) {
+ var nestspace = space + ' ';
+ var seen = new goog.structs.Set(parentSeen);
+
+ var indentMultiline = function(str) {
+ return str.replace(/\n/g, '\n' + space);
+ };
+
+ /** @preserveTry */
+ try {
+ if (!goog.isDef(obj)) {
+ str.push('undefined');
+ } else if (goog.isNull(obj)) {
+ str.push('NULL');
+ } else if (goog.isString(obj)) {
+ str.push('"' + indentMultiline(obj) + '"');
+ } else if (goog.isFunction(obj)) {
+ str.push(indentMultiline(String(obj)));
+ } else if (goog.isObject(obj)) {
+ if (seen.contains(obj)) {
+ str.push('*** reference loop detected ***');
+ } else {
+ seen.add(obj);
+ str.push('{');
+ for (var x in obj) {
+ if (!opt_showFn && goog.isFunction(obj[x])) {
+ continue;
+ }
+ str.push('\n');
+ str.push(nestspace);
+ str.push(x + ' = ');
+ helper(obj[x], nestspace, seen);
+ }
+ str.push('\n' + space + '}');
+ }
+ } else {
+ str.push(obj);
+ }
+ } catch (e) {
+ str.push('*** ' + e + ' ***');
+ }
+ };
+
+ helper(obj, '', new goog.structs.Set());
+ return str.join('');
+};
+
+
+/**
+ * Recursively outputs a nested array as a string.
+ * @param {Array<?>} arr The array.
+ * @return {string} String representing nested array.
+ */
+goog.debug.exposeArray = function(arr) {
+ var str = [];
+ for (var i = 0; i < arr.length; i++) {
+ if (goog.isArray(arr[i])) {
+ str.push(goog.debug.exposeArray(arr[i]));
+ } else {
+ str.push(arr[i]);
+ }
+ }
+ return '[ ' + str.join(', ') + ' ]';
+};
+
+
+/**
+ * Exposes an exception that has been caught by a try...catch and outputs the
+ * error as HTML with a stack trace.
+ * @param {Object} err Error object or string.
+ * @param {Function=} opt_fn Optional function to start stack trace from.
+ * @return {string} Details of exception, as HTML.
+ */
+goog.debug.exposeException = function(err, opt_fn) {
+ var html = goog.debug.exposeExceptionAsHtml(err, opt_fn);
+ return goog.html.SafeHtml.unwrap(html);
+};
+
+
+/**
+ * Exposes an exception that has been caught by a try...catch and outputs the
+ * error with a stack trace.
+ * @param {Object} err Error object or string.
+ * @param {Function=} opt_fn Optional function to start stack trace from.
+ * @return {!goog.html.SafeHtml} Details of exception.
+ */
+goog.debug.exposeExceptionAsHtml = function(err, opt_fn) {
+ /** @preserveTry */
+ try {
+ var e = goog.debug.normalizeErrorObject(err);
+ // Create the error message
+ var viewSourceUrl = goog.debug.createViewSourceUrl_(e.fileName);
+ var error = goog.html.SafeHtml.concat(
+ goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
+ 'Message: ' + e.message + '\nUrl: '),
+ goog.html.SafeHtml.create('a',
+ {href: viewSourceUrl, target: '_new'}, e.fileName),
+ goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
+ '\nLine: ' + e.lineNumber + '\n\nBrowser stack:\n' +
+ e.stack + '-> ' + '[end]\n\nJS stack traversal:\n' +
+ goog.debug.getStacktrace(opt_fn) + '-> '));
+ return error;
+ } catch (e2) {
+ return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
+ 'Exception trying to expose exception! You win, we lose. ' + e2);
+ }
+};
+
+
+/**
+ * @param {?string=} opt_fileName
+ * @return {!goog.html.SafeUrl} SafeUrl with view-source scheme, pointing at
+ * fileName.
+ * @private
+ */
+goog.debug.createViewSourceUrl_ = function(opt_fileName) {
+ if (!goog.isDefAndNotNull(opt_fileName)) {
+ opt_fileName = '';
+ }
+ if (!/^https?:\/\//i.test(opt_fileName)) {
+ return goog.html.SafeUrl.fromConstant(
+ goog.string.Const.from('sanitizedviewsrc'));
+ }
+ var sanitizedFileName = goog.html.SafeUrl.sanitize(opt_fileName);
+ return goog.html.uncheckedconversions.
+ safeUrlFromStringKnownToSatisfyTypeContract(
+ goog.string.Const.from('view-source scheme plus HTTP/HTTPS URL'),
+ 'view-source:' + goog.html.SafeUrl.unwrap(sanitizedFileName));
+};
+
+
+/**
+ * Normalizes the error/exception object between browsers.
+ * @param {Object} err Raw error object.
+ * @return {!Object} Normalized error object.
+ */
+goog.debug.normalizeErrorObject = function(err) {
+ var href = goog.getObjectByName('window.location.href');
+ if (goog.isString(err)) {
+ return {
+ 'message': err,
+ 'name': 'Unknown error',
+ 'lineNumber': 'Not available',
+ 'fileName': href,
+ 'stack': 'Not available'
+ };
+ }
+
+ var lineNumber, fileName;
+ var threwError = false;
+
+ try {
+ lineNumber = err.lineNumber || err.line || 'Not available';
+ } catch (e) {
+ // Firefox 2 sometimes throws an error when accessing 'lineNumber':
+ // Message: Permission denied to get property UnnamedClass.lineNumber
+ lineNumber = 'Not available';
+ threwError = true;
+ }
+
+ try {
+ fileName = err.fileName || err.filename || err.sourceURL ||
+ // $googDebugFname may be set before a call to eval to set the filename
+ // that the eval is supposed to present.
+ goog.global['$googDebugFname'] || href;
+ } catch (e) {
+ // Firefox 2 may also throw an error when accessing 'filename'.
+ fileName = 'Not available';
+ threwError = true;
+ }
+
+ // The IE Error object contains only the name and the message.
+ // The Safari Error object uses the line and sourceURL fields.
+ if (threwError || !err.lineNumber || !err.fileName || !err.stack ||
+ !err.message || !err.name) {
+ return {
+ 'message': err.message || 'Not available',
+ 'name': err.name || 'UnknownError',
+ 'lineNumber': lineNumber,
+ 'fileName': fileName,
+ 'stack': err.stack || 'Not available'
+ };
+ }
+
+ // Standards error object
+ return err;
+};
+
+
+/**
+ * Converts an object to an Error if it's a String,
+ * adds a stacktrace if there isn't one,
+ * and optionally adds an extra message.
+ * @param {Error|string} err the original thrown object or string.
+ * @param {string=} opt_message optional additional message to add to the
+ * error.
+ * @return {!Error} If err is a string, it is used to create a new Error,
+ * which is enhanced and returned. Otherwise err itself is enhanced
+ * and returned.
+ */
+goog.debug.enhanceError = function(err, opt_message) {
+ var error;
+ if (typeof err == 'string') {
+ error = Error(err);
+ if (Error.captureStackTrace) {
+ // Trim this function off the call stack, if we can.
+ Error.captureStackTrace(error, goog.debug.enhanceError);
+ }
+ } else {
+ error = err;
+ }
+
+ if (!error.stack) {
+ error.stack = goog.debug.getStacktrace(goog.debug.enhanceError);
+ }
+ if (opt_message) {
+ // find the first unoccupied 'messageX' property
+ var x = 0;
+ while (error['message' + x]) {
+ ++x;
+ }
+ error['message' + x] = String(opt_message);
+ }
+ return error;
+};
+
+
+/**
+ * Gets the current stack trace. Simple and iterative - doesn't worry about
+ * catching circular references or getting the args.
+ * @param {number=} opt_depth Optional maximum depth to trace back to.
+ * @return {string} A string with the function names of all functions in the
+ * stack, separated by \n.
+ * @suppress {es5Strict}
+ */
+goog.debug.getStacktraceSimple = function(opt_depth) {
+ if (goog.STRICT_MODE_COMPATIBLE) {
+ var stack = goog.debug.getNativeStackTrace_(goog.debug.getStacktraceSimple);
+ if (stack) {
+ return stack;
+ }
+ // NOTE: browsers that have strict mode support also have native "stack"
+ // properties. Fall-through for legacy browser support.
+ }
+
+ var sb = [];
+ var fn = arguments.callee.caller;
+ var depth = 0;
+
+ while (fn && (!opt_depth || depth < opt_depth)) {
+ sb.push(goog.debug.getFunctionName(fn));
+ sb.push('()\n');
+ /** @preserveTry */
+ try {
+ fn = fn.caller;
+ } catch (e) {
+ sb.push('[exception trying to get caller]\n');
+ break;
+ }
+ depth++;
+ if (depth >= goog.debug.MAX_STACK_DEPTH) {
+ sb.push('[...long stack...]');
+ break;
+ }
+ }
+ if (opt_depth && depth >= opt_depth) {
+ sb.push('[...reached max depth limit...]');
+ } else {
+ sb.push('[end]');
+ }
+
+ return sb.join('');
+};
+
+
+/**
+ * Max length of stack to try and output
+ * @type {number}
+ */
+goog.debug.MAX_STACK_DEPTH = 50;
+
+
+/**
+ * @param {Function} fn The function to start getting the trace from.
+ * @return {?string}
+ * @private
+ */
+goog.debug.getNativeStackTrace_ = function(fn) {
+ var tempErr = new Error();
+ if (Error.captureStackTrace) {
+ Error.captureStackTrace(tempErr, fn);
+ return String(tempErr.stack);
+ } else {
+ // IE10, only adds stack traces when an exception is thrown.
+ try {
+ throw tempErr;
+ } catch (e) {
+ tempErr = e;
+ }
+ var stack = tempErr.stack;
+ if (stack) {
+ return String(stack);
+ }
+ }
+ return null;
+};
+
+
+/**
+ * Gets the current stack trace, either starting from the caller or starting
+ * from a specified function that's currently on the call stack.
+ * @param {Function=} opt_fn Optional function to start getting the trace from.
+ * If not provided, defaults to the function that called this.
+ * @return {string} Stack trace.
+ * @suppress {es5Strict}
+ */
+goog.debug.getStacktrace = function(opt_fn) {
+ var stack;
+ if (goog.STRICT_MODE_COMPATIBLE) {
+ // Try to get the stack trace from the environment if it is available.
+ var contextFn = opt_fn || goog.debug.getStacktrace;
+ stack = goog.debug.getNativeStackTrace_(contextFn);
+ }
+ if (!stack) {
+ // NOTE: browsers that have strict mode support also have native "stack"
+ // properties. This function will throw in strict mode.
+ stack = goog.debug.getStacktraceHelper_(
+ opt_fn || arguments.callee.caller, []);
+ }
+ return stack;
+};
+
+
+/**
+ * Private helper for getStacktrace().
+ * @param {Function} fn Function to start getting the trace from.
+ * @param {Array<!Function>} visited List of functions visited so far.
+ * @return {string} Stack trace starting from function fn.
+ * @suppress {es5Strict}
+ * @private
+ */
+goog.debug.getStacktraceHelper_ = function(fn, visited) {
+ var sb = [];
+
+ // Circular reference, certain functions like bind seem to cause a recursive
+ // loop so we need to catch circular references
+ if (goog.array.contains(visited, fn)) {
+ sb.push('[...circular reference...]');
+
+ // Traverse the call stack until function not found or max depth is reached
+ } else if (fn && visited.length < goog.debug.MAX_STACK_DEPTH) {
+ sb.push(goog.debug.getFunctionName(fn) + '(');
+ var args = fn.arguments;
+ // Args may be null for some special functions such as host objects or eval.
+ for (var i = 0; args && i < args.length; i++) {
+ if (i > 0) {
+ sb.push(', ');
+ }
+ var argDesc;
+ var arg = args[i];
+ switch (typeof arg) {
+ case 'object':
+ argDesc = arg ? 'object' : 'null';
+ break;
+
+ case 'string':
+ argDesc = arg;
+ break;
+
+ case 'number':
+ argDesc = String(arg);
+ break;
+
+ case 'boolean':
+ argDesc = arg ? 'true' : 'false';
+ break;
+
+ case 'function':
+ argDesc = goog.debug.getFunctionName(arg);
+ argDesc = argDesc ? argDesc : '[fn]';
+ break;
+
+ case 'undefined':
+ default:
+ argDesc = typeof arg;
+ break;
+ }
+
+ if (argDesc.length > 40) {
+ argDesc = argDesc.substr(0, 40) + '...';
+ }
+ sb.push(argDesc);
+ }
+ visited.push(fn);
+ sb.push(')\n');
+ /** @preserveTry */
+ try {
+ sb.push(goog.debug.getStacktraceHelper_(fn.caller, visited));
+ } catch (e) {
+ sb.push('[exception trying to get caller]\n');
+ }
+
+ } else if (fn) {
+ sb.push('[...long stack...]');
+ } else {
+ sb.push('[end]');
+ }
+ return sb.join('');
+};
+
+
+/**
+ * Set a custom function name resolver.
+ * @param {function(Function): string} resolver Resolves functions to their
+ * names.
+ */
+goog.debug.setFunctionResolver = function(resolver) {
+ goog.debug.fnNameResolver_ = resolver;
+};
+
+
+/**
+ * Gets a function name
+ * @param {Function} fn Function to get name of.
+ * @return {string} Function's name.
+ */
+goog.debug.getFunctionName = function(fn) {
+ if (goog.debug.fnNameCache_[fn]) {
+ return goog.debug.fnNameCache_[fn];
+ }
+ if (goog.debug.fnNameResolver_) {
+ var name = goog.debug.fnNameResolver_(fn);
+ if (name) {
+ goog.debug.fnNameCache_[fn] = name;
+ return name;
+ }
+ }
+
+ // Heuristically determine function name based on code.
+ var functionSource = String(fn);
+ if (!goog.debug.fnNameCache_[functionSource]) {
+ var matches = /function ([^\(]+)/.exec(functionSource);
+ if (matches) {
+ var method = matches[1];
+ goog.debug.fnNameCache_[functionSource] = method;
+ } else {
+ goog.debug.fnNameCache_[functionSource] = '[Anonymous]';
+ }
+ }
+
+ return goog.debug.fnNameCache_[functionSource];
+};
+
+
+/**
+ * Makes whitespace visible by replacing it with printable characters.
+ * This is useful in finding diffrences between the expected and the actual
+ * output strings of a testcase.
+ * @param {string} string whose whitespace needs to be made visible.
+ * @return {string} string whose whitespace is made visible.
+ */
+goog.debug.makeWhitespaceVisible = function(string) {
+ return string.replace(/ /g, '[_]')
+ .replace(/\f/g, '[f]')
+ .replace(/\n/g, '[n]\n')
+ .replace(/\r/g, '[r]')
+ .replace(/\t/g, '[t]');
+};
+
+
+/**
+ * Returns the type of a value. If a constructor is passed, and a suitable
+ * string cannot be found, 'unknown type name' will be returned.
+ *
+ * <p>Forked rather than moved from {@link goog.asserts.getType_}
+ * to avoid adding a dependency to goog.asserts.
+ * @param {*} value A constructor, object, or primitive.
+ * @return {string} The best display name for the value, or 'unknown type name'.
+ */
+goog.debug.runtimeType = function(value) {
+ if (value instanceof Function) {
+ return value.displayName || value.name || 'unknown type name';
+ } else if (value instanceof Object) {
+ return value.constructor.displayName || value.constructor.name ||
+ Object.prototype.toString.call(value);
+ } else {
+ return value === null ? 'null' : typeof value;
+ }
+};
+
+
+/**
+ * Hash map for storing function names that have already been looked up.
+ * @type {Object}
+ * @private
+ */
+goog.debug.fnNameCache_ = {};
+
+
+/**
+ * Resolves functions to their names. Resolved function names will be cached.
+ * @type {function(Function):string}
+ * @private
+ */
+goog.debug.fnNameResolver_;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/debugwindow.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/debugwindow.js b/externs/GCL/externs/goog/debug/debugwindow.js
new file mode 100644
index 0000000..ab251ef
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/debugwindow.js
@@ -0,0 +1,632 @@
+// 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 Definition of the DebugWindow class. Please minimize
+ * dependencies this file has on other closure classes as any dependency it
+ * takes won't be able to use the logging infrastructure.
+ *
+ */
+
+goog.provide('goog.debug.DebugWindow');
+
+goog.require('goog.debug.HtmlFormatter');
+goog.require('goog.debug.LogManager');
+goog.require('goog.debug.Logger');
+goog.require('goog.dom.safe');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeStyleSheet');
+goog.require('goog.string.Const');
+goog.require('goog.structs.CircularBuffer');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Provides a debug DebugWindow that is bound to the goog.debug.Logger.
+ * It handles log messages and writes them to the DebugWindow. This doesn't
+ * provide a lot of functionality that the old Gmail logging infrastructure
+ * provided like saving debug logs for exporting to the server. Now that we
+ * have an event-based logging infrastructure, we can encapsulate that
+ * functionality in a separate class.
+ *
+ * @constructor
+ * @param {string=} opt_identifier Identifier for this logging class.
+ * @param {string=} opt_prefix Prefix prepended to messages.
+ */
+goog.debug.DebugWindow = function(opt_identifier, opt_prefix) {
+ /**
+ * Identifier for this logging class
+ * @protected {string}
+ */
+ this.identifier = opt_identifier || '';
+
+ /**
+ * Array used to buffer log output
+ * @protected {!Array<!goog.html.SafeHtml>}
+ */
+ this.outputBuffer = [];
+
+ /**
+ * Optional prefix to be prepended to error strings
+ * @private {string}
+ */
+ this.prefix_ = opt_prefix || '';
+
+ /**
+ * Buffer for saving the last 1000 messages
+ * @private {!goog.structs.CircularBuffer}
+ */
+ this.savedMessages_ =
+ new goog.structs.CircularBuffer(goog.debug.DebugWindow.MAX_SAVED);
+
+ /**
+ * Save the publish handler so it can be removed
+ * @private {!Function}
+ */
+ this.publishHandler_ = goog.bind(this.addLogRecord, this);
+
+ /**
+ * Formatter for formatted output
+ * @private {goog.debug.Formatter}
+ */
+ this.formatter_ = new goog.debug.HtmlFormatter(this.prefix_);
+
+ /**
+ * Loggers that we shouldn't output
+ * @private {!Object}
+ */
+ this.filteredLoggers_ = {};
+
+ // enable by default
+ this.setCapturing(true);
+
+ /**
+ * Whether we are currently enabled. When the DebugWindow is enabled, it tries
+ * to keep its window open. When it's disabled, it can still be capturing log
+ * output if, but it won't try to write them to the DebugWindow window until
+ * it's enabled.
+ * @private {boolean}
+ */
+ this.enabled_ = goog.debug.DebugWindow.isEnabled(this.identifier);
+
+ // timer to save the DebugWindow's window position in a cookie
+ goog.global.setInterval(goog.bind(this.saveWindowPositionSize_, this), 7500);
+};
+
+
+/**
+ * Max number of messages to be saved
+ * @type {number}
+ */
+goog.debug.DebugWindow.MAX_SAVED = 500;
+
+
+/**
+ * How long to keep the cookies for in milliseconds
+ * @type {number}
+ */
+goog.debug.DebugWindow.COOKIE_TIME = 30 * 24 * 60 * 60 * 1000; // 30-days
+
+
+/**
+ * HTML string printed when the debug window opens
+ * @type {string}
+ * @protected
+ */
+goog.debug.DebugWindow.prototype.welcomeMessage = 'LOGGING';
+
+
+/**
+ * Whether to force enable the window on a severe log.
+ * @type {boolean}
+ * @private
+ */
+goog.debug.DebugWindow.prototype.enableOnSevere_ = false;
+
+
+/**
+ * Reference to debug window
+ * @type {Window}
+ * @protected
+ */
+goog.debug.DebugWindow.prototype.win = null;
+
+
+/**
+ * In the process of opening the window
+ * @type {boolean}
+ * @private
+ */
+goog.debug.DebugWindow.prototype.winOpening_ = false;
+
+
+/**
+ * Whether we are currently capturing logger output.
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.debug.DebugWindow.prototype.isCapturing_ = false;
+
+
+/**
+ * Whether we already showed an alert that the DebugWindow was blocked.
+ * @type {boolean}
+ * @private
+ */
+goog.debug.DebugWindow.showedBlockedAlert_ = false;
+
+
+/**
+ * Reference to timeout used to buffer the output stream.
+ * @type {?number}
+ * @private
+ */
+goog.debug.DebugWindow.prototype.bufferTimeout_ = null;
+
+
+/**
+ * Timestamp for the last time the log was written to.
+ * @protected {number}
+ */
+goog.debug.DebugWindow.prototype.lastCall = goog.now();
+
+
+/**
+ * Sets the welcome message shown when the window is first opened or reset.
+ *
+ * @param {string} msg An HTML string.
+ */
+goog.debug.DebugWindow.prototype.setWelcomeMessage = function(msg) {
+ this.welcomeMessage = msg;
+};
+
+
+/**
+ * Initializes the debug window.
+ */
+goog.debug.DebugWindow.prototype.init = function() {
+ if (this.enabled_) {
+ this.openWindow_();
+ }
+};
+
+
+/**
+ * Whether the DebugWindow is enabled. When the DebugWindow is enabled, it
+ * tries to keep its window open and logs all messages to the window. When the
+ * DebugWindow is disabled, it stops logging messages to its window.
+ *
+ * @return {boolean} Whether the DebugWindow is enabled.
+ */
+goog.debug.DebugWindow.prototype.isEnabled = function() {
+ return this.enabled_;
+};
+
+
+/**
+ * Sets whether the DebugWindow is enabled. When the DebugWindow is enabled, it
+ * tries to keep its window open and log all messages to the window. When the
+ * DebugWindow is disabled, it stops logging messages to its window. The
+ * DebugWindow also saves this state to a cookie so that it's persisted across
+ * application refreshes.
+ * @param {boolean} enable Whether the DebugWindow is enabled.
+ */
+goog.debug.DebugWindow.prototype.setEnabled = function(enable) {
+ this.enabled_ = enable;
+
+ if (this.enabled_) {
+ this.openWindow_();
+ }
+
+ this.setCookie_('enabled', enable ? '1' : '0');
+};
+
+
+/**
+ * Sets whether the debug window should be force enabled when a severe log is
+ * encountered.
+ * @param {boolean} enableOnSevere Whether to enable on severe logs..
+ */
+goog.debug.DebugWindow.prototype.setForceEnableOnSevere =
+ function(enableOnSevere) {
+ this.enableOnSevere_ = enableOnSevere;
+};
+
+
+/**
+ * Whether we are currently capturing logger output.
+ * @return {boolean} whether we are currently capturing logger output.
+ */
+goog.debug.DebugWindow.prototype.isCapturing = function() {
+ return this.isCapturing_;
+};
+
+
+/**
+ * Sets whether we are currently capturing logger output.
+ * @param {boolean} capturing Whether to capture logger output.
+ */
+goog.debug.DebugWindow.prototype.setCapturing = function(capturing) {
+ if (capturing == this.isCapturing_) {
+ return;
+ }
+ this.isCapturing_ = capturing;
+
+ // attach or detach handler from the root logger
+ var rootLogger = goog.debug.LogManager.getRoot();
+ if (capturing) {
+ rootLogger.addHandler(this.publishHandler_);
+ } else {
+ rootLogger.removeHandler(this.publishHandler_);
+ }
+};
+
+
+/**
+ * Gets the formatter for outputting to the debug window. The default formatter
+ * is an instance of goog.debug.HtmlFormatter
+ * @return {goog.debug.Formatter} The formatter in use.
+ */
+goog.debug.DebugWindow.prototype.getFormatter = function() {
+ return this.formatter_;
+};
+
+
+/**
+ * Sets the formatter for outputting to the debug window.
+ * @param {goog.debug.Formatter} formatter The formatter to use.
+ */
+goog.debug.DebugWindow.prototype.setFormatter = function(formatter) {
+ this.formatter_ = formatter;
+};
+
+
+/**
+ * Adds a separator to the debug window.
+ */
+goog.debug.DebugWindow.prototype.addSeparator = function() {
+ this.write_(goog.html.SafeHtml.create('hr'));
+};
+
+
+/**
+ * @return {boolean} Whether there is an active window.
+ */
+goog.debug.DebugWindow.prototype.hasActiveWindow = function() {
+ return !!this.win && !this.win.closed;
+};
+
+
+/**
+ * Clears the contents of the debug window
+ * @protected
+ */
+goog.debug.DebugWindow.prototype.clear = function() {
+ this.savedMessages_.clear();
+ if (this.hasActiveWindow()) {
+ this.writeInitialDocument();
+ }
+};
+
+
+/**
+ * Adds a log record.
+ * @param {goog.debug.LogRecord} logRecord the LogRecord.
+ */
+goog.debug.DebugWindow.prototype.addLogRecord = function(logRecord) {
+ if (this.filteredLoggers_[logRecord.getLoggerName()]) {
+ return;
+ }
+ var html = this.formatter_.formatRecordAsHtml(logRecord);
+ this.write_(html);
+ if (this.enableOnSevere_ &&
+ logRecord.getLevel().value >= goog.debug.Logger.Level.SEVERE.value) {
+ this.setEnabled(true);
+ }
+};
+
+
+/**
+ * Writes a message to the log, possibly opening up the window if it's enabled,
+ * or saving it if it's disabled.
+ * @param {!goog.html.SafeHtml} html The HTML to write.
+ * @private
+ */
+goog.debug.DebugWindow.prototype.write_ = function(html) {
+ // If the logger is enabled, open window and write html message to log
+ // otherwise save it
+ if (this.enabled_) {
+ this.openWindow_();
+ this.savedMessages_.add(html);
+ this.writeToLog_(html);
+ } else {
+ this.savedMessages_.add(html);
+ }
+};
+
+
+/**
+ * Write to the buffer. If a message hasn't been sent for more than 750ms just
+ * write, otherwise delay for a minimum of 250ms.
+ * @param {!goog.html.SafeHtml} html HTML to post to the log.
+ * @private
+ */
+goog.debug.DebugWindow.prototype.writeToLog_ = function(html) {
+ this.outputBuffer.push(html);
+ goog.global.clearTimeout(this.bufferTimeout_);
+
+ if (goog.now() - this.lastCall > 750) {
+ this.writeBufferToLog();
+ } else {
+ this.bufferTimeout_ =
+ goog.global.setTimeout(goog.bind(this.writeBufferToLog, this), 250);
+ }
+};
+
+
+/**
+ * Write to the log and maybe scroll into view.
+ * @protected
+ */
+goog.debug.DebugWindow.prototype.writeBufferToLog = function() {
+ this.lastCall = goog.now();
+ if (this.hasActiveWindow()) {
+ var body = this.win.document.body;
+ var scroll = body &&
+ body.scrollHeight - (body.scrollTop + body.clientHeight) <= 100;
+
+ goog.dom.safe.documentWrite(
+ this.win.document, goog.html.SafeHtml.concat(this.outputBuffer));
+ this.outputBuffer.length = 0;
+
+ if (scroll) {
+ this.win.scrollTo(0, 1000000);
+ }
+ }
+};
+
+
+/**
+ * Writes all saved messages to the DebugWindow.
+ * @protected
+ */
+goog.debug.DebugWindow.prototype.writeSavedMessages = function() {
+ var messages = this.savedMessages_.getValues();
+ for (var i = 0; i < messages.length; i++) {
+ this.writeToLog_(messages[i]);
+ }
+};
+
+
+/**
+ * Opens the debug window if it is not already referenced
+ * @private
+ */
+goog.debug.DebugWindow.prototype.openWindow_ = function() {
+ if (this.hasActiveWindow() || this.winOpening_) {
+ return;
+ }
+
+ var winpos = this.getCookie_('dbg', '0,0,800,500').split(',');
+ var x = Number(winpos[0]);
+ var y = Number(winpos[1]);
+ var w = Number(winpos[2]);
+ var h = Number(winpos[3]);
+
+ this.winOpening_ = true;
+ this.win = window.open('', this.getWindowName_(), 'width=' + w +
+ ',height=' + h + ',toolbar=no,resizable=yes,' +
+ 'scrollbars=yes,left=' + x + ',top=' + y +
+ ',status=no,screenx=' + x + ',screeny=' + y);
+
+ if (!this.win) {
+ if (!goog.debug.DebugWindow.showedBlockedAlert_) {
+ // only show this once
+ alert('Logger popup was blocked');
+ goog.debug.DebugWindow.showedBlockedAlert_ = true;
+ }
+ }
+
+ this.winOpening_ = false;
+
+ if (this.win) {
+ this.writeInitialDocument();
+ }
+};
+
+
+/**
+ * Gets a valid window name for the debug window. Replaces invalid characters in
+ * IE.
+ * @return {string} Valid window name.
+ * @private
+ */
+goog.debug.DebugWindow.prototype.getWindowName_ = function() {
+ return goog.userAgent.IE ?
+ this.identifier.replace(/[\s\-\.\,]/g, '_') : this.identifier;
+};
+
+
+/**
+ * @return {!goog.html.SafeStyleSheet} The stylesheet, for inclusion in the
+ * initial HTML.
+ */
+goog.debug.DebugWindow.prototype.getStyleRules = function() {
+ return goog.html.SafeStyleSheet.fromConstant(goog.string.Const.from(
+ '*{font:normal 14px monospace;}' +
+ '.dbg-sev{color:#F00}' +
+ '.dbg-w{color:#E92}' +
+ '.dbg-sh{background-color:#fd4;font-weight:bold;color:#000}' +
+ '.dbg-i{color:#666}' +
+ '.dbg-f{color:#999}' +
+ '.dbg-ev{color:#0A0}' +
+ '.dbg-m{color:#990}'));
+};
+
+
+/**
+ * Writes the initial HTML of the debug window.
+ * @protected
+ */
+goog.debug.DebugWindow.prototype.writeInitialDocument = function() {
+ if (!this.hasActiveWindow()) {
+ return;
+ }
+
+ this.win.document.open();
+
+ var div = goog.html.SafeHtml.create(
+ 'div', {
+ 'class': 'dbg-ev',
+ 'style': goog.string.Const.from('text-align:center;')},
+ goog.html.SafeHtml.concat(
+ this.welcomeMessage,
+ goog.html.SafeHtml.create('br'),
+ goog.html.SafeHtml.create(
+ 'small', {}, 'Logger: ' + this.identifier)));
+ var html = goog.html.SafeHtml.concat(
+ goog.html.SafeHtml.createStyle(this.getStyleRules()),
+ goog.html.SafeHtml.create('hr'),
+ div,
+ goog.html.SafeHtml.create('hr'));
+
+ this.writeToLog_(html);
+ this.writeSavedMessages();
+};
+
+
+/**
+ * Save persistent data (using cookies) for 1 month (cookie specific to this
+ * logger object).
+ * @param {string} key Data name.
+ * @param {string} value Data value.
+ * @private
+ */
+goog.debug.DebugWindow.prototype.setCookie_ = function(key, value) {
+ var fullKey = goog.debug.DebugWindow.getCookieKey_(this.identifier, key);
+ document.cookie = fullKey + '=' + encodeURIComponent(value) +
+ ';path=/;expires=' +
+ (new Date(goog.now() + goog.debug.DebugWindow.COOKIE_TIME)).toUTCString();
+};
+
+
+/**
+ * Retrieve data (using cookies).
+ * @param {string} key Data name.
+ * @param {string=} opt_default Optional default value if cookie doesn't exist.
+ * @return {string} Cookie value.
+ * @private
+ */
+goog.debug.DebugWindow.prototype.getCookie_ = function(key, opt_default) {
+ return goog.debug.DebugWindow.getCookieValue_(
+ this.identifier, key, opt_default);
+};
+
+
+/**
+ * Creates a valid cookie key name which is scoped to the given identifier.
+ * Substitutes all occurences of invalid cookie name characters (whitespace,
+ * ';', and '=') with '_', which is a valid and readable alternative.
+ * @see goog.net.Cookies#isValidName
+ * @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
+ * @param {string} identifier Identifier for logging class.
+ * @param {string} key Data name.
+ * @return {string} Cookie key name.
+ * @private
+ */
+goog.debug.DebugWindow.getCookieKey_ = function(identifier, key) {
+ var fullKey = key + identifier;
+ return fullKey.replace(/[;=\s]/g, '_');
+};
+
+
+/**
+ * Retrieve data (using cookies).
+ * @param {string} identifier Identifier for logging class.
+ * @param {string} key Data name.
+ * @param {string=} opt_default Optional default value if cookie doesn't exist.
+ * @return {string} Cookie value.
+ * @private
+ */
+goog.debug.DebugWindow.getCookieValue_ = function(
+ identifier, key, opt_default) {
+ var fullKey = goog.debug.DebugWindow.getCookieKey_(identifier, key);
+ var cookie = String(document.cookie);
+ var start = cookie.indexOf(fullKey + '=');
+ if (start != -1) {
+ var end = cookie.indexOf(';', start);
+ return decodeURIComponent(cookie.substring(start + fullKey.length + 1,
+ end == -1 ? cookie.length : end));
+ } else {
+ return opt_default || '';
+ }
+};
+
+
+/**
+ * @param {string} identifier Identifier for logging class.
+ * @return {boolean} Whether the DebugWindow is enabled.
+ */
+goog.debug.DebugWindow.isEnabled = function(identifier) {
+ return goog.debug.DebugWindow.getCookieValue_(identifier, 'enabled') == '1';
+};
+
+
+/**
+ * Saves the window position size to a cookie
+ * @private
+ */
+goog.debug.DebugWindow.prototype.saveWindowPositionSize_ = function() {
+ if (!this.hasActiveWindow()) {
+ return;
+ }
+ var x = this.win.screenX || this.win.screenLeft || 0;
+ var y = this.win.screenY || this.win.screenTop || 0;
+ var w = this.win.outerWidth || 800;
+ var h = this.win.outerHeight || 500;
+ this.setCookie_('dbg', x + ',' + y + ',' + w + ',' + h);
+};
+
+
+/**
+ * Adds a logger name to be filtered.
+ * @param {string} loggerName the logger name to add.
+ */
+goog.debug.DebugWindow.prototype.addFilter = function(loggerName) {
+ this.filteredLoggers_[loggerName] = 1;
+};
+
+
+/**
+ * Removes a logger name to be filtered.
+ * @param {string} loggerName the logger name to remove.
+ */
+goog.debug.DebugWindow.prototype.removeFilter = function(loggerName) {
+ delete this.filteredLoggers_[loggerName];
+};
+
+
+/**
+ * Modify the size of the circular buffer. Allows the log to retain more
+ * information while the window is closed.
+ * @param {number} size New size of the circular buffer.
+ */
+goog.debug.DebugWindow.prototype.resetBufferWithNewSize = function(size) {
+ if (size > 0 && size < 50000) {
+ this.clear();
+ this.savedMessages_ = new goog.structs.CircularBuffer(size);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/devcss/devcss.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/devcss/devcss.js b/externs/GCL/externs/goog/debug/devcss/devcss.js
new file mode 100644
index 0000000..8716ca4
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/devcss/devcss.js
@@ -0,0 +1,445 @@
+// 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 Runtime development CSS Compiler emulation, via javascript.
+ * This class provides an approximation to CSSCompiler's functionality by
+ * hacking the live CSSOM.
+ * This code is designed to be inserted in the DOM immediately after the last
+ * style block in HEAD when in development mode, i.e. you are not using a
+ * running instance of a CSS Compiler to pass your CSS through.
+ */
+
+
+goog.provide('goog.debug.DevCss');
+goog.provide('goog.debug.DevCss.UserAgent');
+
+goog.require('goog.asserts');
+goog.require('goog.cssom');
+goog.require('goog.dom.classlist');
+goog.require('goog.events');
+goog.require('goog.events.EventType');
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A class for solving development CSS issues/emulating the CSS Compiler.
+ * @param {goog.debug.DevCss.UserAgent=} opt_userAgent The user agent, if not
+ * passed in, will be determined using goog.userAgent.
+ * @param {number|string=} opt_userAgentVersion The user agent's version.
+ * If not passed in, will be determined using goog.userAgent.
+ * @throws {Error} When userAgent detection fails.
+ * @constructor
+ * @final
+ */
+goog.debug.DevCss = function(opt_userAgent, opt_userAgentVersion) {
+ if (!opt_userAgent) {
+ // Walks through the known goog.userAgents.
+ if (goog.userAgent.IE) {
+ opt_userAgent = goog.debug.DevCss.UserAgent.IE;
+ } else if (goog.userAgent.GECKO) {
+ opt_userAgent = goog.debug.DevCss.UserAgent.GECKO;
+ } else if (goog.userAgent.WEBKIT) {
+ opt_userAgent = goog.debug.DevCss.UserAgent.WEBKIT;
+ } else if (goog.userAgent.MOBILE) {
+ opt_userAgent = goog.debug.DevCss.UserAgent.MOBILE;
+ } else if (goog.userAgent.OPERA) {
+ opt_userAgent = goog.debug.DevCss.UserAgent.OPERA;
+ }
+ }
+ switch (opt_userAgent) {
+ case goog.debug.DevCss.UserAgent.OPERA:
+ case goog.debug.DevCss.UserAgent.IE:
+ case goog.debug.DevCss.UserAgent.GECKO:
+ case goog.debug.DevCss.UserAgent.FIREFOX:
+ case goog.debug.DevCss.UserAgent.WEBKIT:
+ case goog.debug.DevCss.UserAgent.SAFARI:
+ case goog.debug.DevCss.UserAgent.MOBILE:
+ break;
+ default:
+ throw Error('Could not determine the user agent from known UserAgents');
+ }
+
+ /**
+ * One of goog.debug.DevCss.UserAgent.
+ * @type {string}
+ * @private
+ */
+ this.userAgent_ = opt_userAgent;
+
+ /**
+ * @const @private
+ */
+ this.userAgentTokens_ = {};
+
+ /**
+ * @type {number|string}
+ * @private
+ */
+ this.userAgentVersion_ = opt_userAgentVersion || goog.userAgent.VERSION;
+ this.generateUserAgentTokens_();
+
+ /**
+ * @type {boolean}
+ * @private
+ */
+ this.isIe6OrLess_ = this.userAgent_ == goog.debug.DevCss.UserAgent.IE &&
+ goog.string.compareVersions('7', this.userAgentVersion_) > 0;
+
+ if (this.isIe6OrLess_) {
+ /**
+ * @type {Array<{classNames,combinedClassName,els}>}
+ * @private
+ */
+ this.ie6CombinedMatches_ = [];
+ }
+};
+
+
+/**
+ * Rewrites the CSSOM as needed to activate any useragent-specific selectors.
+ * @param {boolean=} opt_enableIe6ReadyHandler If true(the default), and the
+ * userAgent is ie6, we set a document "ready" event handler to walk the DOM
+ * and make combined selector className changes. Having this parameter also
+ * aids unit testing.
+ */
+goog.debug.DevCss.prototype.activateBrowserSpecificCssRules = function(
+ opt_enableIe6ReadyHandler) {
+ var enableIe6EventHandler = goog.isDef(opt_enableIe6ReadyHandler) ?
+ opt_enableIe6ReadyHandler : true;
+ var cssRules = goog.cssom.getAllCssStyleRules();
+
+ for (var i = 0, cssRule; cssRule = cssRules[i]; i++) {
+ this.replaceBrowserSpecificClassNames_(cssRule);
+ }
+
+ // Since we may have manipulated the rules above, we'll have to do a
+ // complete sweep again if we're in IE6. Luckily performance doesn't
+ // matter for this tool.
+ if (this.isIe6OrLess_) {
+ cssRules = goog.cssom.getAllCssStyleRules();
+ for (var i = 0, cssRule; cssRule = cssRules[i]; i++) {
+ this.replaceIe6CombinedSelectors_(cssRule);
+ }
+ }
+
+ // Add an event listener for document ready to rewrite any necessary
+ // combined classnames in IE6.
+ if (this.isIe6OrLess_ && enableIe6EventHandler) {
+ goog.events.listen(document, goog.events.EventType.LOAD, goog.bind(
+ this.addIe6CombinedClassNames_, this));
+ }
+};
+
+
+/**
+ * A list of possible user agent strings.
+ * @enum {string}
+ */
+goog.debug.DevCss.UserAgent = {
+ OPERA: 'OPERA',
+ IE: 'IE',
+ GECKO: 'GECKO',
+ FIREFOX: 'GECKO',
+ WEBKIT: 'WEBKIT',
+ SAFARI: 'WEBKIT',
+ MOBILE: 'MOBILE'
+};
+
+
+/**
+ * A list of strings that may be used for matching in CSS files/development.
+ * @enum {string}
+ * @private
+ */
+goog.debug.DevCss.CssToken_ = {
+ USERAGENT: 'USERAGENT',
+ SEPARATOR: '-',
+ LESS_THAN: 'LT',
+ GREATER_THAN: 'GT',
+ LESS_THAN_OR_EQUAL: 'LTE',
+ GREATER_THAN_OR_EQUAL: 'GTE',
+ IE6_SELECTOR_TEXT: 'goog-ie6-selector',
+ IE6_COMBINED_GLUE: '_'
+};
+
+
+/**
+ * Generates user agent token match strings with comparison and version bits.
+ * For example:
+ * userAgentTokens_.ANY will be like 'GECKO'
+ * userAgentTokens_.LESS_THAN will be like 'GECKO-LT3' etc...
+ * @private
+ */
+goog.debug.DevCss.prototype.generateUserAgentTokens_ = function() {
+ this.userAgentTokens_.ANY = goog.debug.DevCss.CssToken_.USERAGENT +
+ goog.debug.DevCss.CssToken_.SEPARATOR + this.userAgent_;
+ this.userAgentTokens_.EQUALS = this.userAgentTokens_.ANY +
+ goog.debug.DevCss.CssToken_.SEPARATOR;
+ this.userAgentTokens_.LESS_THAN = this.userAgentTokens_.ANY +
+ goog.debug.DevCss.CssToken_.SEPARATOR +
+ goog.debug.DevCss.CssToken_.LESS_THAN;
+ this.userAgentTokens_.LESS_THAN_OR_EQUAL = this.userAgentTokens_.ANY +
+ goog.debug.DevCss.CssToken_.SEPARATOR +
+ goog.debug.DevCss.CssToken_.LESS_THAN_OR_EQUAL;
+ this.userAgentTokens_.GREATER_THAN = this.userAgentTokens_.ANY +
+ goog.debug.DevCss.CssToken_.SEPARATOR +
+ goog.debug.DevCss.CssToken_.GREATER_THAN;
+ this.userAgentTokens_.GREATER_THAN_OR_EQUAL = this.userAgentTokens_.ANY +
+ goog.debug.DevCss.CssToken_.SEPARATOR +
+ goog.debug.DevCss.CssToken_.GREATER_THAN_OR_EQUAL;
+};
+
+
+/**
+ * Gets the version number bit from a selector matching userAgentToken.
+ * @param {string} selectorText The selector text of a CSS rule.
+ * @param {string} userAgentToken Includes the LTE/GTE bit to see if it matches.
+ * @return {string|undefined} The version number.
+ * @private
+ */
+goog.debug.DevCss.prototype.getVersionNumberFromSelectorText_ = function(
+ selectorText, userAgentToken) {
+ var regex = new RegExp(userAgentToken + '([\\d\\.]+)');
+ var matches = regex.exec(selectorText);
+ if (matches && matches.length == 2) {
+ return matches[1];
+ }
+};
+
+
+/**
+ * Extracts a rule version from the selector text, and if it finds one, calls
+ * compareVersions against it and the passed in token string to provide the
+ * value needed to determine if we have a match or not.
+ * @param {CSSRule} cssRule The rule to test against.
+ * @param {string} token The match token to test against the rule.
+ * @return {!Array|undefined} A tuple with the result of the compareVersions
+ * call and the matched ruleVersion.
+ * @private
+ */
+goog.debug.DevCss.prototype.getRuleVersionAndCompare_ = function(cssRule,
+ token) {
+ if (!cssRule.selectorText.match(token)) {
+ return;
+ }
+ var ruleVersion = this.getVersionNumberFromSelectorText_(
+ cssRule.selectorText, token);
+ if (!ruleVersion) {
+ return;
+ }
+
+ var comparison = goog.string.compareVersions(this.userAgentVersion_,
+ ruleVersion);
+ return [comparison, ruleVersion];
+};
+
+
+/**
+ * Replaces a CSS selector if we have matches based on our useragent/version.
+ * Example: With a selector like ".USERAGENT-IE-LTE6 .class { prop: value }" if
+ * we are running IE6 we'll end up with ".class { prop: value }", thereby
+ * "activating" the selector.
+ * @param {CSSRule} cssRule The cssRule to potentially replace.
+ * @private
+ */
+goog.debug.DevCss.prototype.replaceBrowserSpecificClassNames_ = function(
+ cssRule) {
+
+ // If we don't match the browser token, we can stop now.
+ if (!cssRule.selectorText.match(this.userAgentTokens_.ANY)) {
+ return;
+ }
+
+ // We know it will begin as a classname.
+ var additionalRegexString;
+
+ // Tests "Less than or equals".
+ var compared = this.getRuleVersionAndCompare_(cssRule,
+ this.userAgentTokens_.LESS_THAN_OR_EQUAL);
+ if (compared && compared.length) {
+ if (compared[0] > 0) {
+ return;
+ }
+ additionalRegexString = this.userAgentTokens_.LESS_THAN_OR_EQUAL +
+ compared[1];
+ }
+
+ // Tests "Less than".
+ compared = this.getRuleVersionAndCompare_(cssRule,
+ this.userAgentTokens_.LESS_THAN);
+ if (compared && compared.length) {
+ if (compared[0] > -1) {
+ return;
+ }
+ additionalRegexString = this.userAgentTokens_.LESS_THAN + compared[1];
+ }
+
+ // Tests "Greater than or equals".
+ compared = this.getRuleVersionAndCompare_(cssRule,
+ this.userAgentTokens_.GREATER_THAN_OR_EQUAL);
+ if (compared && compared.length) {
+ if (compared[0] < 0) {
+ return;
+ }
+ additionalRegexString = this.userAgentTokens_.GREATER_THAN_OR_EQUAL +
+ compared[1];
+ }
+
+ // Tests "Greater than".
+ compared = this.getRuleVersionAndCompare_(cssRule,
+ this.userAgentTokens_.GREATER_THAN);
+ if (compared && compared.length) {
+ if (compared[0] < 1) {
+ return;
+ }
+ additionalRegexString = this.userAgentTokens_.GREATER_THAN + compared[1];
+ }
+
+ // Tests "Equals".
+ compared = this.getRuleVersionAndCompare_(cssRule,
+ this.userAgentTokens_.EQUALS);
+ if (compared && compared.length) {
+ if (compared[0] != 0) {
+ return;
+ }
+ additionalRegexString = this.userAgentTokens_.EQUALS + compared[1];
+ }
+
+ // If we got to here without generating the additionalRegexString, then
+ // we did not match any of our comparison token strings, and we want a
+ // general browser token replacement.
+ if (!additionalRegexString) {
+ additionalRegexString = this.userAgentTokens_.ANY;
+ }
+
+ // We need to match at least a single whitespace character to know that
+ // we are matching the entire useragent string token.
+ var regexString = '\\.' + additionalRegexString + '\\s+';
+ var re = new RegExp(regexString, 'g');
+
+ var currentCssText = goog.cssom.getCssTextFromCssRule(cssRule);
+
+ // Replacing the token with '' activates the selector for this useragent.
+ var newCssText = currentCssText.replace(re, '');
+
+ if (newCssText != currentCssText) {
+ goog.cssom.replaceCssRule(cssRule, newCssText);
+ }
+};
+
+
+/**
+ * Replaces IE6 combined selector rules with a workable development alternative.
+ * IE6 actually parses .class1.class2 {} to simply .class2 {} which is nasty.
+ * To fully support combined selectors in IE6 this function needs to be paired
+ * with a call to replace the relevant DOM elements classNames as well.
+ * @see {this.addIe6CombinedClassNames_}
+ * @param {CSSRule} cssRule The rule to potentially fix.
+ * @private
+ */
+goog.debug.DevCss.prototype.replaceIe6CombinedSelectors_ = function(cssRule) {
+ // This match only ever works in IE because other UA's won't have our
+ // IE6_SELECTOR_TEXT in the cssText property.
+ if (cssRule.style.cssText &&
+ cssRule.style.cssText.match(
+ goog.debug.DevCss.CssToken_.IE6_SELECTOR_TEXT)) {
+ var cssText = goog.cssom.getCssTextFromCssRule(cssRule);
+ var combinedSelectorText = this.getIe6CombinedSelectorText_(cssText);
+ if (combinedSelectorText) {
+ var newCssText = combinedSelectorText + '{' + cssRule.style.cssText + '}';
+ goog.cssom.replaceCssRule(cssRule, newCssText);
+ }
+ }
+};
+
+
+/**
+ * Gets the appropriate new combined selector text for IE6.
+ * Also adds an entry onto ie6CombinedMatches_ with relevant info for the
+ * likely following call to walk the DOM and rewrite the class attribute.
+ * Example: With a selector like
+ * ".class2 { -goog-ie6-selector: .class1.class2; prop: value }".
+ * this function will return:
+ * ".class1_class2 { prop: value }".
+ * @param {string} cssText The CSS selector text and css rule text combined.
+ * @return {?string} The rewritten css rule text.
+ * @private
+ */
+goog.debug.DevCss.prototype.getIe6CombinedSelectorText_ = function(cssText) {
+ var regex = new RegExp(goog.debug.DevCss.CssToken_.IE6_SELECTOR_TEXT +
+ '\\s*:\\s*\\"([^\\"]+)\\"', 'gi');
+ var matches = regex.exec(cssText);
+ if (matches) {
+ var combinedSelectorText = matches[1];
+ // To aid in later fixing the DOM, we need to split up the possible
+ // selector groups by commas.
+ var groupedSelectors = combinedSelectorText.split(/\s*\,\s*/);
+ for (var i = 0, selector; selector = groupedSelectors[i]; i++) {
+ // Strips off the leading ".".
+ var combinedClassName = selector.substr(1);
+ var classNames = combinedClassName.split(
+ goog.debug.DevCss.CssToken_.IE6_COMBINED_GLUE);
+ var entry = {
+ classNames: classNames,
+ combinedClassName: combinedClassName,
+ els: []
+ };
+ this.ie6CombinedMatches_.push(entry);
+ }
+ return combinedSelectorText;
+ }
+ return null;
+};
+
+
+/**
+ * Adds combined selectors with underscores to make them "work" in IE6.
+ * @see {this.replaceIe6CombinedSelectors_}
+ * @private
+ */
+goog.debug.DevCss.prototype.addIe6CombinedClassNames_ = function() {
+ if (!this.ie6CombinedMatches_.length) {
+ return;
+ }
+ var allEls = document.getElementsByTagName('*');
+ // Match nodes for all classNames.
+ for (var i = 0, classNameEntry; classNameEntry =
+ this.ie6CombinedMatches_[i]; i++) {
+ for (var j = 0, el; el = allEls[j]; j++) {
+ var classNamesLength = classNameEntry.classNames.length;
+ for (var k = 0, className; className = classNameEntry.classNames[k];
+ k++) {
+ if (!goog.dom.classlist.contains(goog.asserts.assert(el), className)) {
+ break;
+ }
+ if (k == classNamesLength - 1) {
+ classNameEntry.els.push(el);
+ }
+ }
+ }
+ // Walks over our matching nodes and fixes them.
+ if (classNameEntry.els.length) {
+ for (var j = 0, el; el = classNameEntry.els[j]; j++) {
+ goog.asserts.assert(el);
+ if (!goog.dom.classlist.contains(el,
+ classNameEntry.combinedClassName)) {
+ goog.dom.classlist.add(el, classNameEntry.combinedClassName);
+ }
+ }
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/devcss/devcssrunner.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/devcss/devcssrunner.js b/externs/GCL/externs/goog/debug/devcss/devcssrunner.js
new file mode 100644
index 0000000..cfe4f39
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/devcss/devcssrunner.js
@@ -0,0 +1,26 @@
+// 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 Development CSS Compiler runtime execution.
+ */
+
+goog.provide('goog.debug.devCssRunner');
+
+goog.require('goog.debug.DevCss');
+
+(function() {
+ var devCssInstance = new goog.debug.DevCss();
+ devCssInstance.activateBrowserSpecificCssRules();
+})();
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/divconsole.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/divconsole.js b/externs/GCL/externs/goog/debug/divconsole.js
new file mode 100644
index 0000000..e3eacb9
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/divconsole.js
@@ -0,0 +1,150 @@
+// 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 Simple logger that logs a Div Element.
+ *
+ */
+
+goog.provide('goog.debug.DivConsole');
+
+goog.require('goog.debug.HtmlFormatter');
+goog.require('goog.debug.LogManager');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.safe');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.style');
+
+
+
+/**
+ * A class for visualising logger calls in a div element.
+ * @param {Element} element The element to append to.
+ * @constructor
+ */
+goog.debug.DivConsole = function(element) {
+ this.publishHandler_ = goog.bind(this.addLogRecord, this);
+ this.formatter_ = new goog.debug.HtmlFormatter();
+ this.formatter_.showAbsoluteTime = false;
+ this.isCapturing_ = false;
+ this.element_ = element;
+ this.elementOwnerDocument_ =
+ this.element_.ownerDocument || this.element_.document;
+
+ this.installStyles();
+};
+
+
+/**
+ * Installs styles for the log messages and its div
+ */
+goog.debug.DivConsole.prototype.installStyles = function() {
+ goog.style.installStyles(
+ '.dbg-sev{color:#F00}' +
+ '.dbg-w{color:#C40}' +
+ '.dbg-sh{font-weight:bold;color:#000}' +
+ '.dbg-i{color:#444}' +
+ '.dbg-f{color:#999}' +
+ '.dbg-ev{color:#0A0}' +
+ '.dbg-m{color:#990}' +
+ '.logmsg{border-bottom:1px solid #CCC;padding:2px}' +
+ '.logsep{background-color: #8C8;}' +
+ '.logdiv{border:1px solid #CCC;background-color:#FCFCFC;' +
+ 'font:medium monospace}',
+ this.element_);
+ this.element_.className += ' logdiv';
+};
+
+
+/**
+ * Sets whether we are currently capturing logger output.
+ * @param {boolean} capturing Whether to capture logger output.
+ */
+goog.debug.DivConsole.prototype.setCapturing = function(capturing) {
+ if (capturing == this.isCapturing_) {
+ return;
+ }
+
+ // attach or detach handler from the root logger
+ var rootLogger = goog.debug.LogManager.getRoot();
+ if (capturing) {
+ rootLogger.addHandler(this.publishHandler_);
+ } else {
+ rootLogger.removeHandler(this.publishHandler_);
+ this.logBuffer = '';
+ }
+ this.isCapturing_ = capturing;
+};
+
+
+/**
+ * Adds a log record.
+ * @param {goog.debug.LogRecord} logRecord The log entry.
+ */
+goog.debug.DivConsole.prototype.addLogRecord = function(logRecord) {
+ if (!logRecord) {
+ return;
+ }
+ var scroll = this.element_.scrollHeight - this.element_.scrollTop -
+ this.element_.clientHeight <= 100;
+
+ var div = this.elementOwnerDocument_.createElement(goog.dom.TagName.DIV);
+ div.className = 'logmsg';
+ goog.dom.safe.setInnerHtml(
+ div, this.formatter_.formatRecordAsHtml(logRecord));
+ this.element_.appendChild(div);
+
+ if (scroll) {
+ this.element_.scrollTop = this.element_.scrollHeight;
+ }
+};
+
+
+/**
+ * Gets the formatter for outputting to the console. The default formatter
+ * is an instance of goog.debug.HtmlFormatter
+ * @return {!goog.debug.Formatter} The formatter in use.
+ */
+goog.debug.DivConsole.prototype.getFormatter = function() {
+ return this.formatter_;
+};
+
+
+/**
+ * Sets the formatter for outputting to the console.
+ * @param {goog.debug.HtmlFormatter} formatter The formatter to use.
+ */
+goog.debug.DivConsole.prototype.setFormatter = function(formatter) {
+ this.formatter_ = formatter;
+};
+
+
+/**
+ * Adds a separator to the debug window.
+ */
+goog.debug.DivConsole.prototype.addSeparator = function() {
+ var div = this.elementOwnerDocument_.createElement(goog.dom.TagName.DIV);
+ div.className = 'logmsg logsep';
+ this.element_.appendChild(div);
+};
+
+
+/**
+ * Clears the console.
+ */
+goog.debug.DivConsole.prototype.clear = function() {
+ if (this.element_) {
+ goog.dom.safe.setInnerHtml(this.element_, goog.html.SafeHtml.EMPTY);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/entrypointregistry.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/entrypointregistry.js b/externs/GCL/externs/goog/debug/entrypointregistry.js
new file mode 100644
index 0000000..3ae7549
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/entrypointregistry.js
@@ -0,0 +1,158 @@
+// 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 A global registry for entry points into a program,
+ * so that they can be instrumented. Each module should register their
+ * entry points with this registry. Designed to be compiled out
+ * if no instrumentation is requested.
+ *
+ * Entry points may be registered before or after a call to
+ * goog.debug.entryPointRegistry.monitorAll. If an entry point is registered
+ * later, the existing monitor will instrument the new entry point.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.debug.EntryPointMonitor');
+goog.provide('goog.debug.entryPointRegistry');
+
+goog.require('goog.asserts');
+
+
+
+/**
+ * @interface
+ */
+goog.debug.EntryPointMonitor = function() {};
+
+
+/**
+ * Instruments a function.
+ *
+ * @param {!Function} fn A function to instrument.
+ * @return {!Function} The instrumented function.
+ */
+goog.debug.EntryPointMonitor.prototype.wrap;
+
+
+/**
+ * Try to remove an instrumentation wrapper created by this monitor.
+ * If the function passed to unwrap is not a wrapper created by this
+ * monitor, then we will do nothing.
+ *
+ * Notice that some wrappers may not be unwrappable. For example, if other
+ * monitors have applied their own wrappers, then it will be impossible to
+ * unwrap them because their wrappers will have captured our wrapper.
+ *
+ * So it is important that entry points are unwrapped in the reverse
+ * order that they were wrapped.
+ *
+ * @param {!Function} fn A function to unwrap.
+ * @return {!Function} The unwrapped function, or {@code fn} if it was not
+ * a wrapped function created by this monitor.
+ */
+goog.debug.EntryPointMonitor.prototype.unwrap;
+
+
+/**
+ * An array of entry point callbacks.
+ * @type {!Array<function(!Function)>}
+ * @private
+ */
+goog.debug.entryPointRegistry.refList_ = [];
+
+
+/**
+ * Monitors that should wrap all the entry points.
+ * @type {!Array<!goog.debug.EntryPointMonitor>}
+ * @private
+ */
+goog.debug.entryPointRegistry.monitors_ = [];
+
+
+/**
+ * Whether goog.debug.entryPointRegistry.monitorAll has ever been called.
+ * Checking this allows the compiler to optimize out the registrations.
+ * @type {boolean}
+ * @private
+ */
+goog.debug.entryPointRegistry.monitorsMayExist_ = false;
+
+
+/**
+ * Register an entry point with this module.
+ *
+ * The entry point will be instrumented when a monitor is passed to
+ * goog.debug.entryPointRegistry.monitorAll. If this has already occurred, the
+ * entry point is instrumented immediately.
+ *
+ * @param {function(!Function)} callback A callback function which is called
+ * with a transforming function to instrument the entry point. The callback
+ * is responsible for wrapping the relevant entry point with the
+ * transforming function.
+ */
+goog.debug.entryPointRegistry.register = function(callback) {
+ // Don't use push(), so that this can be compiled out.
+ goog.debug.entryPointRegistry.refList_[
+ goog.debug.entryPointRegistry.refList_.length] = callback;
+ // If no one calls monitorAll, this can be compiled out.
+ if (goog.debug.entryPointRegistry.monitorsMayExist_) {
+ var monitors = goog.debug.entryPointRegistry.monitors_;
+ for (var i = 0; i < monitors.length; i++) {
+ callback(goog.bind(monitors[i].wrap, monitors[i]));
+ }
+ }
+};
+
+
+/**
+ * Configures a monitor to wrap all entry points.
+ *
+ * Entry points that have already been registered are immediately wrapped by
+ * the monitor. When an entry point is registered in the future, it will also
+ * be wrapped by the monitor when it is registered.
+ *
+ * @param {!goog.debug.EntryPointMonitor} monitor An entry point monitor.
+ */
+goog.debug.entryPointRegistry.monitorAll = function(monitor) {
+ goog.debug.entryPointRegistry.monitorsMayExist_ = true;
+ var transformer = goog.bind(monitor.wrap, monitor);
+ for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
+ goog.debug.entryPointRegistry.refList_[i](transformer);
+ }
+ goog.debug.entryPointRegistry.monitors_.push(monitor);
+};
+
+
+/**
+ * Try to unmonitor all the entry points that have already been registered. If
+ * an entry point is registered in the future, it will not be wrapped by the
+ * monitor when it is registered. Note that this may fail if the entry points
+ * have additional wrapping.
+ *
+ * @param {!goog.debug.EntryPointMonitor} monitor The last monitor to wrap
+ * the entry points.
+ * @throws {Error} If the monitor is not the most recently configured monitor.
+ */
+goog.debug.entryPointRegistry.unmonitorAllIfPossible = function(monitor) {
+ var monitors = goog.debug.entryPointRegistry.monitors_;
+ goog.asserts.assert(monitor == monitors[monitors.length - 1],
+ 'Only the most recent monitor can be unwrapped.');
+ var transformer = goog.bind(monitor.unwrap, monitor);
+ for (var i = 0; i < goog.debug.entryPointRegistry.refList_.length; i++) {
+ goog.debug.entryPointRegistry.refList_[i](transformer);
+ }
+ monitors.length--;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/error2.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/error2.js b/externs/GCL/externs/goog/debug/error2.js
new file mode 100644
index 0000000..5f1bd3e
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/error2.js
@@ -0,0 +1,63 @@
+// Copyright 2009 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 Provides a base class for custom Error objects such that the
+ * stack is correctly maintained.
+ *
+ * You should never need to throw goog.debug.Error(msg) directly, Error(msg) is
+ * sufficient.
+ *
+ */
+
+goog.provide('goog.debug.Error');
+
+
+
+/**
+ * Base class for custom error objects.
+ * @param {*=} opt_msg The message associated with the error.
+ * @constructor
+ * @extends {Error}
+ */
+goog.debug.Error = function(opt_msg) {
+
+ // Attempt to ensure there is a stack trace.
+ if (Error.captureStackTrace) {
+ Error.captureStackTrace(this, goog.debug.Error);
+ } else {
+ var stack = new Error().stack;
+ if (stack) {
+ this.stack = stack;
+ }
+ }
+
+ if (opt_msg) {
+ this.message = String(opt_msg);
+ }
+
+ /**
+ * Whether to report this error to the server. Setting this to false will
+ * cause the error reporter to not report the error back to the server,
+ * which can be useful if the client knows that the error has already been
+ * logged on the server.
+ * @type {boolean}
+ */
+ this.reportErrorToServer = true;
+};
+goog.inherits(goog.debug.Error, Error);
+
+
+/** @override */
+goog.debug.Error.prototype.name = 'CustomError';
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/errorhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/errorhandler.js b/externs/GCL/externs/goog/debug/errorhandler.js
new file mode 100644
index 0000000..3d8b004
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/errorhandler.js
@@ -0,0 +1,367 @@
+// 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 Error handling utilities.
+ *
+ */
+
+goog.provide('goog.debug.ErrorHandler');
+goog.provide('goog.debug.ErrorHandler.ProtectedFunctionError');
+
+goog.require('goog.Disposable');
+goog.require('goog.asserts');
+goog.require('goog.debug');
+goog.require('goog.debug.EntryPointMonitor');
+goog.require('goog.debug.Error');
+goog.require('goog.debug.Trace');
+
+
+
+/**
+ * The ErrorHandler can be used to to wrap functions with a try/catch
+ * statement. If an exception is thrown, the given error handler function will
+ * be called.
+ *
+ * When this object is disposed, it will stop handling exceptions and tracing.
+ * It will also try to restore window.setTimeout and window.setInterval
+ * if it wrapped them. Notice that in the general case, it is not technically
+ * possible to remove the wrapper, because functions have no knowledge of
+ * what they have been assigned to. So the app is responsible for other
+ * forms of unwrapping.
+ *
+ * @param {Function} handler Handler for exceptions.
+ * @constructor
+ * @extends {goog.Disposable}
+ * @implements {goog.debug.EntryPointMonitor}
+ */
+goog.debug.ErrorHandler = function(handler) {
+ goog.debug.ErrorHandler.base(this, 'constructor');
+
+ /**
+ * Handler for exceptions, which can do logging, reporting, etc.
+ * @type {Function}
+ * @private
+ */
+ this.errorHandlerFn_ = handler;
+
+ /**
+ * Whether errors should be wrapped in
+ * goog.debug.ErrorHandler.ProtectedFunctionError before rethrowing.
+ * @type {boolean}
+ * @private
+ */
+ this.wrapErrors_ = true; // TODO(user) Change default.
+
+ /**
+ * Whether to add a prefix to all error messages. The prefix is
+ * goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX. This option
+ * only has an effect if this.wrapErrors_ is set to false.
+ * @type {boolean}
+ * @private
+ */
+ this.prefixErrorMessages_ = false;
+};
+goog.inherits(goog.debug.ErrorHandler, goog.Disposable);
+
+
+/**
+ * Whether to add tracers when instrumenting entry points.
+ * @type {boolean}
+ * @private
+ */
+goog.debug.ErrorHandler.prototype.addTracersToProtectedFunctions_ = false;
+
+
+/**
+ * Enable tracers when instrumenting entry points.
+ * @param {boolean} newVal See above.
+ */
+goog.debug.ErrorHandler.prototype.setAddTracersToProtectedFunctions =
+ function(newVal) {
+ this.addTracersToProtectedFunctions_ = newVal;
+};
+
+
+/** @override */
+goog.debug.ErrorHandler.prototype.wrap = function(fn) {
+ return this.protectEntryPoint(goog.asserts.assertFunction(fn));
+};
+
+
+/** @override */
+goog.debug.ErrorHandler.prototype.unwrap = function(fn) {
+ goog.asserts.assertFunction(fn);
+ return fn[this.getFunctionIndex_(false)] || fn;
+};
+
+
+/**
+ * Private helper function to return a span that can be clicked on to display
+ * an alert with the current stack trace. Newlines are replaced with a
+ * placeholder so that they will not be html-escaped.
+ * @param {string} stackTrace The stack trace to create a span for.
+ * @return {string} A span which can be clicked on to show the stack trace.
+ * @private
+ */
+goog.debug.ErrorHandler.prototype.getStackTraceHolder_ = function(stackTrace) {
+ var buffer = [];
+ buffer.push('##PE_STACK_START##');
+ buffer.push(stackTrace.replace(/(\r\n|\r|\n)/g, '##STACK_BR##'));
+ buffer.push('##PE_STACK_END##');
+ return buffer.join('');
+};
+
+
+/**
+ * Get the index for a function. Used for internal indexing.
+ * @param {boolean} wrapper True for the wrapper; false for the wrapped.
+ * @return {string} The index where we should store the function in its
+ * wrapper/wrapped function.
+ * @private
+ */
+goog.debug.ErrorHandler.prototype.getFunctionIndex_ = function(wrapper) {
+ return (wrapper ? '__wrapper_' : '__protected_') + goog.getUid(this) + '__';
+};
+
+
+/**
+ * Installs exception protection for an entry point function. When an exception
+ * is thrown from a protected function, a handler will be invoked to handle it.
+ *
+ * @param {Function} fn An entry point function to be protected.
+ * @return {!Function} A protected wrapper function that calls the entry point
+ * function.
+ */
+goog.debug.ErrorHandler.prototype.protectEntryPoint = function(fn) {
+ var protectedFnName = this.getFunctionIndex_(true);
+ if (!fn[protectedFnName]) {
+ var wrapper = fn[protectedFnName] = this.getProtectedFunction(fn);
+ wrapper[this.getFunctionIndex_(false)] = fn;
+ }
+ return fn[protectedFnName];
+};
+
+
+/**
+ * Helps {@link #protectEntryPoint} by actually creating the protected
+ * wrapper function, after {@link #protectEntryPoint} determines that one does
+ * not already exist for the given function. Can be overriden by subclasses
+ * that may want to implement different error handling, or add additional
+ * entry point hooks.
+ * @param {!Function} fn An entry point function to be protected.
+ * @return {!Function} protected wrapper function.
+ * @protected
+ */
+goog.debug.ErrorHandler.prototype.getProtectedFunction = function(fn) {
+ var that = this;
+ var tracers = this.addTracersToProtectedFunctions_;
+ if (tracers) {
+ var stackTrace = goog.debug.getStacktraceSimple(15);
+ }
+ var googDebugErrorHandlerProtectedFunction = function() {
+ if (that.isDisposed()) {
+ return fn.apply(this, arguments);
+ }
+
+ if (tracers) {
+ var tracer = goog.debug.Trace.startTracer('protectedEntryPoint: ' +
+ that.getStackTraceHolder_(stackTrace));
+ }
+ try {
+ return fn.apply(this, arguments);
+ } catch (e) {
+ that.errorHandlerFn_(e);
+ if (!that.wrapErrors_) {
+ // Add the prefix to the existing message.
+ if (that.prefixErrorMessages_) {
+ if (typeof e === 'object') {
+ e.message =
+ goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX +
+ e.message;
+ } else {
+ e = goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX +
+ e;
+ }
+ }
+ if (goog.DEBUG) {
+ // Work around for https://code.google.com/p/v8/issues/detail?id=2625
+ // and https://code.google.com/p/chromium/issues/detail?id=237059
+ // Custom errors and errors with custom stack traces show the wrong
+ // stack trace
+ // If it has a stack and Error.captureStackTrace is supported (only
+ // supported in V8 as of May 2013) log the stack to the console.
+ if (e && e.stack && Error.captureStackTrace &&
+ goog.global['console']) {
+ goog.global['console']['error'](e.message, e.stack);
+ }
+ }
+ // Re-throw original error. This is great for debugging as it makes
+ // browser JS dev consoles show the correct error and stack trace.
+ throw e;
+ }
+ // Re-throw it since this may be expected by the caller.
+ throw new goog.debug.ErrorHandler.ProtectedFunctionError(e);
+ } finally {
+ if (tracers) {
+ goog.debug.Trace.stopTracer(tracer);
+ }
+ }
+ };
+ googDebugErrorHandlerProtectedFunction[this.getFunctionIndex_(false)] = fn;
+ return googDebugErrorHandlerProtectedFunction;
+};
+
+
+// TODO(mknichel): Allow these functions to take in the window to protect.
+/**
+ * Installs exception protection for window.setTimeout to handle exceptions.
+ */
+goog.debug.ErrorHandler.prototype.protectWindowSetTimeout =
+ function() {
+ this.protectWindowFunctionsHelper_('setTimeout');
+};
+
+
+/**
+ * Install exception protection for window.setInterval to handle exceptions.
+ */
+goog.debug.ErrorHandler.prototype.protectWindowSetInterval =
+ function() {
+ this.protectWindowFunctionsHelper_('setInterval');
+};
+
+
+/**
+ * Install exception protection for window.requestAnimationFrame to handle
+ * exceptions.
+ */
+goog.debug.ErrorHandler.prototype.protectWindowRequestAnimationFrame =
+ function() {
+ var win = goog.getObjectByName('window');
+ var fnNames = [
+ 'requestAnimationFrame',
+ 'mozRequestAnimationFrame',
+ 'webkitAnimationFrame',
+ 'msRequestAnimationFrame'
+ ];
+ for (var i = 0; i < fnNames.length; i++) {
+ var fnName = fnNames[i];
+ if (fnNames[i] in win) {
+ this.protectWindowFunctionsHelper_(fnName);
+ }
+ }
+};
+
+
+/**
+ * Helper function for protecting a function that causes a function to be
+ * asynchronously called, for example setTimeout or requestAnimationFrame.
+ * @param {string} fnName The name of the function to protect.
+ * @private
+ */
+goog.debug.ErrorHandler.prototype.protectWindowFunctionsHelper_ =
+ function(fnName) {
+ var win = goog.getObjectByName('window');
+ var originalFn = win[fnName];
+ var that = this;
+ win[fnName] = function(fn, time) {
+ // Don't try to protect strings. In theory, we could try to globalEval
+ // the string, but this seems to lead to permission errors on IE6.
+ if (goog.isString(fn)) {
+ fn = goog.partial(goog.globalEval, fn);
+ }
+ fn = that.protectEntryPoint(fn);
+
+ // IE doesn't support .call for setInterval/setTimeout, but it
+ // also doesn't care what "this" is, so we can just call the
+ // original function directly
+ if (originalFn.call) {
+ return originalFn.call(this, fn, time);
+ } else {
+ return originalFn(fn, time);
+ }
+ };
+ win[fnName][this.getFunctionIndex_(false)] = originalFn;
+};
+
+
+/**
+ * Set whether to wrap errors that occur in protected functions in a
+ * goog.debug.ErrorHandler.ProtectedFunctionError.
+ * @param {boolean} wrapErrors Whether to wrap errors.
+ */
+goog.debug.ErrorHandler.prototype.setWrapErrors = function(wrapErrors) {
+ this.wrapErrors_ = wrapErrors;
+};
+
+
+/**
+ * Set whether to add a prefix to all error messages that occur in protected
+ * functions.
+ * @param {boolean} prefixErrorMessages Whether to add a prefix to error
+ * messages.
+ */
+goog.debug.ErrorHandler.prototype.setPrefixErrorMessages =
+ function(prefixErrorMessages) {
+ this.prefixErrorMessages_ = prefixErrorMessages;
+};
+
+
+/** @override */
+goog.debug.ErrorHandler.prototype.disposeInternal = function() {
+ // Try to unwrap window.setTimeout and window.setInterval.
+ var win = goog.getObjectByName('window');
+ win.setTimeout = this.unwrap(win.setTimeout);
+ win.setInterval = this.unwrap(win.setInterval);
+
+ goog.debug.ErrorHandler.base(this, 'disposeInternal');
+};
+
+
+
+/**
+ * Error thrown to the caller of a protected entry point if the entry point
+ * throws an error.
+ * @param {*} cause The error thrown by the entry point.
+ * @constructor
+ * @extends {goog.debug.Error}
+ * @final
+ */
+goog.debug.ErrorHandler.ProtectedFunctionError = function(cause) {
+ var message = goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX +
+ (cause && cause.message ? String(cause.message) : String(cause));
+ goog.debug.ErrorHandler.ProtectedFunctionError.base(
+ this, 'constructor', message);
+
+ /**
+ * The error thrown by the entry point.
+ * @type {*}
+ */
+ this.cause = cause;
+
+ var stack = cause && cause.stack;
+ if (stack && goog.isString(stack)) {
+ this.stack = /** @type {string} */ (stack);
+ }
+};
+goog.inherits(goog.debug.ErrorHandler.ProtectedFunctionError, goog.debug.Error);
+
+
+/**
+ * Text to prefix the message with.
+ * @type {string}
+ */
+goog.debug.ErrorHandler.ProtectedFunctionError.MESSAGE_PREFIX =
+ 'Error in protected function: ';
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/errorhandlerweakdep.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/errorhandlerweakdep.js b/externs/GCL/externs/goog/debug/errorhandlerweakdep.js
new file mode 100644
index 0000000..284ddb0
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/errorhandlerweakdep.js
@@ -0,0 +1,38 @@
+// 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 File which defines dummy object to work around undefined
+ * properties compiler warning for weak dependencies on
+ * {@link goog.debug.ErrorHandler#protectEntryPoint}.
+ *
+ */
+
+goog.provide('goog.debug.errorHandlerWeakDep');
+
+
+/**
+ * Dummy object to work around undefined properties compiler warning.
+ * @type {!Object<string,Function>}
+ */
+goog.debug.errorHandlerWeakDep = {
+ /**
+ * @param {Function} fn An entry point function to be protected.
+ * @param {boolean=} opt_tracers Whether to install tracers around the
+ * fn.
+ * @return {Function} A protected wrapper function that calls the
+ * entry point function.
+ */
+ protectEntryPoint: function(fn, opt_tracers) { return fn; }
+};
[04/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/collation.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/collation.js b/externs/GCL/externs/goog/i18n/collation.js
new file mode 100644
index 0000000..7314912
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/collation.js
@@ -0,0 +1,58 @@
+// 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 Contains helper functions for performing locale-sensitive
+ * collation.
+ */
+
+
+goog.provide('goog.i18n.collation');
+
+
+/**
+ * Returns the comparator for a locale. If a locale is not explicitly specified,
+ * a comparator for the user's locale will be returned. Note that if the browser
+ * does not support locale-sensitive string comparisons, the comparator returned
+ * will be a simple codepoint comparator.
+ *
+ * @param {string=} opt_locale the locale that the comparator is used for.
+ * @return {function(string, string): number} The locale-specific comparator.
+ */
+goog.i18n.collation.createComparator = function(opt_locale) {
+ // See http://code.google.com/p/v8-i18n.
+ if (goog.i18n.collation.hasNativeComparator()) {
+ var intl = goog.global.Intl;
+ return new intl.Collator([opt_locale || goog.LOCALE]).compare;
+ } else {
+ return function(arg1, arg2) {
+ return arg1.localeCompare(arg2);
+ };
+ }
+};
+
+
+/**
+ * Returns true if a locale-sensitive comparator is available for a locale. If
+ * a locale is not explicitly specified, the user's locale is used instead.
+ *
+ * @param {string=} opt_locale The locale to be checked.
+ * @return {boolean} Whether there is a locale-sensitive comparator available
+ * for the locale.
+ */
+goog.i18n.collation.hasNativeComparator = function(opt_locale) {
+ var intl = goog.global.Intl;
+ return !!(intl && intl.Collator);
+};
[10/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/groupelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/groupelement.js b/externs/GCL/externs/goog/graphics/groupelement.js
new file mode 100644
index 0000000..9e60cd7
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/groupelement.js
@@ -0,0 +1,58 @@
+// 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 thin wrapper around the DOM element for graphics groups.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.GroupElement');
+
+goog.require('goog.graphics.Element');
+
+
+
+/**
+ * Interface for a graphics group element.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.graphics.Element}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.GroupElement = function(element, graphics) {
+ goog.graphics.Element.call(this, element, graphics);
+};
+goog.inherits(goog.graphics.GroupElement, goog.graphics.Element);
+
+
+/**
+ * Remove all drawing elements from the group.
+ */
+goog.graphics.GroupElement.prototype.clear = goog.abstractMethod;
+
+
+/**
+ * Set the size of the group element.
+ * @param {number|string} width The width of the group element.
+ * @param {number|string} height The height of the group element.
+ */
+goog.graphics.GroupElement.prototype.setSize = goog.abstractMethod;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/imageelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/imageelement.js b/externs/GCL/externs/goog/graphics/imageelement.js
new file mode 100644
index 0000000..2f2d9b7
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/imageelement.js
@@ -0,0 +1,70 @@
+// 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 thin wrapper around the DOM element for images.
+ */
+
+
+goog.provide('goog.graphics.ImageElement');
+
+goog.require('goog.graphics.Element');
+
+
+
+/**
+ * Interface for a graphics image element.
+ * You should not construct objects from this constructor. Instead,
+ * you should use {@code goog.graphics.Graphics.drawImage} and it
+ * will return an implementation of this interface for you.
+ *
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.graphics.Element}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.ImageElement = function(element, graphics) {
+ goog.graphics.Element.call(this, element, graphics);
+};
+goog.inherits(goog.graphics.ImageElement, goog.graphics.Element);
+
+
+/**
+ * Update the position of the image.
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ */
+goog.graphics.ImageElement.prototype.setPosition = goog.abstractMethod;
+
+
+/**
+ * Update the size of the image.
+ *
+ * @param {number} width Width of image.
+ * @param {number} height Height of image.
+ */
+goog.graphics.ImageElement.prototype.setSize = goog.abstractMethod;
+
+
+/**
+ * Update the source of the image.
+ * @param {string} src Source of the image.
+ */
+goog.graphics.ImageElement.prototype.setSource = goog.abstractMethod;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/lineargradient.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/lineargradient.js b/externs/GCL/externs/goog/graphics/lineargradient.js
new file mode 100644
index 0000000..df59cbf
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/lineargradient.js
@@ -0,0 +1,175 @@
+// 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 Represents a gradient to be used with a Graphics implementor.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.LinearGradient');
+
+
+goog.require('goog.asserts');
+goog.require('goog.graphics.Fill');
+
+
+
+/**
+ * Creates an immutable linear gradient fill object.
+ *
+ * @param {number} x1 Start X position of the gradient.
+ * @param {number} y1 Start Y position of the gradient.
+ * @param {number} x2 End X position of the gradient.
+ * @param {number} y2 End Y position of the gradient.
+ * @param {string} color1 Start color of the gradient.
+ * @param {string} color2 End color of the gradient.
+ * @param {?number=} opt_opacity1 Start opacity of the gradient, both or neither
+ * of opt_opacity1 and opt_opacity2 have to be set.
+ * @param {?number=} opt_opacity2 End opacity of the gradient.
+ * @constructor
+ * @extends {goog.graphics.Fill}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.LinearGradient =
+ function(x1, y1, x2, y2, color1, color2, opt_opacity1, opt_opacity2) {
+ /**
+ * Start X position of the gradient.
+ * @type {number}
+ * @private
+ */
+ this.x1_ = x1;
+
+ /**
+ * Start Y position of the gradient.
+ * @type {number}
+ * @private
+ */
+ this.y1_ = y1;
+
+ /**
+ * End X position of the gradient.
+ * @type {number}
+ * @private
+ */
+ this.x2_ = x2;
+
+ /**
+ * End Y position of the gradient.
+ * @type {number}
+ * @private
+ */
+ this.y2_ = y2;
+
+ /**
+ * Start color of the gradient.
+ * @type {string}
+ * @private
+ */
+ this.color1_ = color1;
+
+ /**
+ * End color of the gradient.
+ * @type {string}
+ * @private
+ */
+ this.color2_ = color2;
+
+ goog.asserts.assert(
+ goog.isNumber(opt_opacity1) == goog.isNumber(opt_opacity2),
+ 'Both or neither of opt_opacity1 and opt_opacity2 have to be set.');
+
+ /**
+ * Start opacity of the gradient.
+ * @type {?number}
+ * @private
+ */
+ this.opacity1_ = goog.isDef(opt_opacity1) ? opt_opacity1 : null;
+
+ /**
+ * End opacity of the gradient.
+ * @type {?number}
+ * @private
+ */
+ this.opacity2_ = goog.isDef(opt_opacity2) ? opt_opacity2 : null;
+};
+goog.inherits(goog.graphics.LinearGradient, goog.graphics.Fill);
+
+
+/**
+ * @return {number} The start X position of the gradient.
+ */
+goog.graphics.LinearGradient.prototype.getX1 = function() {
+ return this.x1_;
+};
+
+
+/**
+ * @return {number} The start Y position of the gradient.
+ */
+goog.graphics.LinearGradient.prototype.getY1 = function() {
+ return this.y1_;
+};
+
+
+/**
+ * @return {number} The end X position of the gradient.
+ */
+goog.graphics.LinearGradient.prototype.getX2 = function() {
+ return this.x2_;
+};
+
+
+/**
+ * @return {number} The end Y position of the gradient.
+ */
+goog.graphics.LinearGradient.prototype.getY2 = function() {
+ return this.y2_;
+};
+
+
+/**
+ * @override
+ */
+goog.graphics.LinearGradient.prototype.getColor1 = function() {
+ return this.color1_;
+};
+
+
+/**
+ * @override
+ */
+goog.graphics.LinearGradient.prototype.getColor2 = function() {
+ return this.color2_;
+};
+
+
+/**
+ * @return {?number} The start opacity of the gradient.
+ */
+goog.graphics.LinearGradient.prototype.getOpacity1 = function() {
+ return this.opacity1_;
+};
+
+
+/**
+ * @return {?number} The end opacity of the gradient.
+ */
+goog.graphics.LinearGradient.prototype.getOpacity2 = function() {
+ return this.opacity2_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/path.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/path.js b/externs/GCL/externs/goog/graphics/path.js
new file mode 100644
index 0000000..c19f2d9
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/path.js
@@ -0,0 +1,511 @@
+// 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 Represents a path used with a Graphics implementation.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.graphics.Path');
+goog.provide('goog.graphics.Path.Segment');
+
+goog.require('goog.array');
+goog.require('goog.math');
+
+
+
+/**
+ * Creates a path object. A path is a sequence of segments and may be open or
+ * closed. Path uses the EVEN-ODD fill rule for determining the interior of the
+ * path. A path must start with a moveTo command.
+ *
+ * A "simple" path does not contain any arcs and may be transformed using
+ * the {@code transform} method.
+ *
+ * @constructor
+ */
+goog.graphics.Path = function() {
+ /**
+ * The segment types that constitute this path.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.segments_ = [];
+
+ /**
+ * The number of repeated segments of the current type.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.count_ = [];
+
+ /**
+ * The arguments corresponding to each of the segments.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.arguments_ = [];
+};
+
+
+/**
+ * The coordinates of the point which closes the path (the point of the
+ * last moveTo command).
+ * @type {Array<number>?}
+ * @private
+ */
+goog.graphics.Path.prototype.closePoint_ = null;
+
+
+/**
+ * The coordinates most recently added to the end of the path.
+ * @type {Array<number>?}
+ * @private
+ */
+goog.graphics.Path.prototype.currentPoint_ = null;
+
+
+/**
+ * Flag for whether this is a simple path (contains no arc segments).
+ * @type {boolean}
+ * @private
+ */
+goog.graphics.Path.prototype.simple_ = true;
+
+
+/**
+ * Path segment types.
+ * @enum {number}
+ */
+goog.graphics.Path.Segment = {
+ MOVETO: 0,
+ LINETO: 1,
+ CURVETO: 2,
+ ARCTO: 3,
+ CLOSE: 4
+};
+
+
+/**
+ * The number of points for each segment type.
+ * @type {!Array<number>}
+ * @private
+ */
+goog.graphics.Path.segmentArgCounts_ = (function() {
+ var counts = [];
+ counts[goog.graphics.Path.Segment.MOVETO] = 2;
+ counts[goog.graphics.Path.Segment.LINETO] = 2;
+ counts[goog.graphics.Path.Segment.CURVETO] = 6;
+ counts[goog.graphics.Path.Segment.ARCTO] = 6;
+ counts[goog.graphics.Path.Segment.CLOSE] = 0;
+ return counts;
+})();
+
+
+/**
+ * Returns the number of points for a segment type.
+ *
+ * @param {number} segment The segment type.
+ * @return {number} The number of points.
+ */
+goog.graphics.Path.getSegmentCount = function(segment) {
+ return goog.graphics.Path.segmentArgCounts_[segment];
+};
+
+
+/**
+ * Appends another path to the end of this path.
+ *
+ * @param {!goog.graphics.Path} path The path to append.
+ * @return {!goog.graphics.Path} This path.
+ */
+goog.graphics.Path.prototype.appendPath = function(path) {
+ if (path.currentPoint_) {
+ Array.prototype.push.apply(this.segments_, path.segments_);
+ Array.prototype.push.apply(this.count_, path.count_);
+ Array.prototype.push.apply(this.arguments_, path.arguments_);
+ this.currentPoint_ = path.currentPoint_.concat();
+ this.closePoint_ = path.closePoint_.concat();
+ this.simple_ = this.simple_ && path.simple_;
+ }
+ return this;
+};
+
+
+/**
+ * Clears the path.
+ *
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.clear = function() {
+ this.segments_.length = 0;
+ this.count_.length = 0;
+ this.arguments_.length = 0;
+ delete this.closePoint_;
+ delete this.currentPoint_;
+ delete this.simple_;
+ return this;
+};
+
+
+/**
+ * Adds a point to the path by moving to the specified point. Repeated moveTo
+ * commands are collapsed into a single moveTo.
+ *
+ * @param {number} x X coordinate of destination point.
+ * @param {number} y Y coordinate of destination point.
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.moveTo = function(x, y) {
+ if (goog.array.peek(this.segments_) == goog.graphics.Path.Segment.MOVETO) {
+ this.arguments_.length -= 2;
+ } else {
+ this.segments_.push(goog.graphics.Path.Segment.MOVETO);
+ this.count_.push(1);
+ }
+ this.arguments_.push(x, y);
+ this.currentPoint_ = this.closePoint_ = [x, y];
+ return this;
+};
+
+
+/**
+ * Adds points to the path by drawing a straight line to each point.
+ *
+ * @param {...number} var_args The coordinates of each destination point as x, y
+ * value pairs.
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.lineTo = function(var_args) {
+ var lastSegment = goog.array.peek(this.segments_);
+ if (lastSegment == null) {
+ throw Error('Path cannot start with lineTo');
+ }
+ if (lastSegment != goog.graphics.Path.Segment.LINETO) {
+ this.segments_.push(goog.graphics.Path.Segment.LINETO);
+ this.count_.push(0);
+ }
+ for (var i = 0; i < arguments.length; i += 2) {
+ var x = arguments[i];
+ var y = arguments[i + 1];
+ this.arguments_.push(x, y);
+ }
+ this.count_[this.count_.length - 1] += i / 2;
+ this.currentPoint_ = [x, y];
+ return this;
+};
+
+
+/**
+ * Adds points to the path by drawing cubic Bezier curves. Each curve is
+ * specified using 3 points (6 coordinates) - two control points and the end
+ * point of the curve.
+ *
+ * @param {...number} var_args The coordinates specifiying each curve in sets of
+ * 6 points: {@code [x1, y1]} the first control point, {@code [x2, y2]} the
+ * second control point and {@code [x, y]} the end point.
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.curveTo = function(var_args) {
+ var lastSegment = goog.array.peek(this.segments_);
+ if (lastSegment == null) {
+ throw Error('Path cannot start with curve');
+ }
+ if (lastSegment != goog.graphics.Path.Segment.CURVETO) {
+ this.segments_.push(goog.graphics.Path.Segment.CURVETO);
+ this.count_.push(0);
+ }
+ for (var i = 0; i < arguments.length; i += 6) {
+ var x = arguments[i + 4];
+ var y = arguments[i + 5];
+ this.arguments_.push(arguments[i], arguments[i + 1],
+ arguments[i + 2], arguments[i + 3], x, y);
+ }
+ this.count_[this.count_.length - 1] += i / 6;
+ this.currentPoint_ = [x, y];
+ return this;
+};
+
+
+/**
+ * Adds a path command to close the path by connecting the
+ * last point to the first point.
+ *
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.close = function() {
+ var lastSegment = goog.array.peek(this.segments_);
+ if (lastSegment == null) {
+ throw Error('Path cannot start with close');
+ }
+ if (lastSegment != goog.graphics.Path.Segment.CLOSE) {
+ this.segments_.push(goog.graphics.Path.Segment.CLOSE);
+ this.count_.push(1);
+ this.currentPoint_ = this.closePoint_;
+ }
+ return this;
+};
+
+
+/**
+ * Adds a path command to draw an arc centered at the point {@code (cx, cy)}
+ * with radius {@code rx} along the x-axis and {@code ry} along the y-axis from
+ * {@code startAngle} through {@code extent} degrees. Positive rotation is in
+ * the direction from positive x-axis to positive y-axis.
+ *
+ * @param {number} cx X coordinate of center of ellipse.
+ * @param {number} cy Y coordinate of center of ellipse.
+ * @param {number} rx Radius of ellipse on x axis.
+ * @param {number} ry Radius of ellipse on y axis.
+ * @param {number} fromAngle Starting angle measured in degrees from the
+ * positive x-axis.
+ * @param {number} extent The span of the arc in degrees.
+ * @param {boolean} connect If true, the starting point of the arc is connected
+ * to the current point.
+ * @return {!goog.graphics.Path} The path itself.
+ * @deprecated Use {@code arcTo} or {@code arcToAsCurves} instead.
+ */
+goog.graphics.Path.prototype.arc = function(cx, cy, rx, ry,
+ fromAngle, extent, connect) {
+ var startX = cx + goog.math.angleDx(fromAngle, rx);
+ var startY = cy + goog.math.angleDy(fromAngle, ry);
+ if (connect) {
+ if (!this.currentPoint_ || startX != this.currentPoint_[0] ||
+ startY != this.currentPoint_[1]) {
+ this.lineTo(startX, startY);
+ }
+ } else {
+ this.moveTo(startX, startY);
+ }
+ return this.arcTo(rx, ry, fromAngle, extent);
+};
+
+
+/**
+ * Adds a path command to draw an arc starting at the path's current point,
+ * with radius {@code rx} along the x-axis and {@code ry} along the y-axis from
+ * {@code startAngle} through {@code extent} degrees. Positive rotation is in
+ * the direction from positive x-axis to positive y-axis.
+ *
+ * This method makes the path non-simple.
+ *
+ * @param {number} rx Radius of ellipse on x axis.
+ * @param {number} ry Radius of ellipse on y axis.
+ * @param {number} fromAngle Starting angle measured in degrees from the
+ * positive x-axis.
+ * @param {number} extent The span of the arc in degrees.
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.arcTo = function(rx, ry, fromAngle, extent) {
+ var cx = this.currentPoint_[0] - goog.math.angleDx(fromAngle, rx);
+ var cy = this.currentPoint_[1] - goog.math.angleDy(fromAngle, ry);
+ var ex = cx + goog.math.angleDx(fromAngle + extent, rx);
+ var ey = cy + goog.math.angleDy(fromAngle + extent, ry);
+ this.segments_.push(goog.graphics.Path.Segment.ARCTO);
+ this.count_.push(1);
+ this.arguments_.push(rx, ry, fromAngle, extent, ex, ey);
+ this.simple_ = false;
+ this.currentPoint_ = [ex, ey];
+ return this;
+};
+
+
+/**
+ * Same as {@code arcTo}, but approximates the arc using bezier curves.
+.* As a result, this method does not affect the simplified status of this path.
+ * The algorithm is adapted from {@code java.awt.geom.ArcIterator}.
+ *
+ * @param {number} rx Radius of ellipse on x axis.
+ * @param {number} ry Radius of ellipse on y axis.
+ * @param {number} fromAngle Starting angle measured in degrees from the
+ * positive x-axis.
+ * @param {number} extent The span of the arc in degrees.
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.arcToAsCurves = function(
+ rx, ry, fromAngle, extent) {
+ var cx = this.currentPoint_[0] - goog.math.angleDx(fromAngle, rx);
+ var cy = this.currentPoint_[1] - goog.math.angleDy(fromAngle, ry);
+ var extentRad = goog.math.toRadians(extent);
+ var arcSegs = Math.ceil(Math.abs(extentRad) / Math.PI * 2);
+ var inc = extentRad / arcSegs;
+ var angle = goog.math.toRadians(fromAngle);
+ for (var j = 0; j < arcSegs; j++) {
+ var relX = Math.cos(angle);
+ var relY = Math.sin(angle);
+ var z = 4 / 3 * Math.sin(inc / 2) / (1 + Math.cos(inc / 2));
+ var c0 = cx + (relX - z * relY) * rx;
+ var c1 = cy + (relY + z * relX) * ry;
+ angle += inc;
+ relX = Math.cos(angle);
+ relY = Math.sin(angle);
+ this.curveTo(c0, c1,
+ cx + (relX + z * relY) * rx,
+ cy + (relY - z * relX) * ry,
+ cx + relX * rx,
+ cy + relY * ry);
+ }
+ return this;
+};
+
+
+/**
+ * Iterates over the path calling the supplied callback once for each path
+ * segment. The arguments to the callback function are the segment type and
+ * an array of its arguments.
+ *
+ * The {@code LINETO} and {@code CURVETO} arrays can contain multiple
+ * segments of the same type. The number of segments is the length of the
+ * array divided by the segment length (2 for lines, 6 for curves).
+ *
+ * As a convenience the {@code ARCTO} segment also includes the end point as the
+ * last two arguments: {@code rx, ry, fromAngle, extent, x, y}.
+ *
+ * @param {function(number, Array)} callback The function to call with each
+ * path segment.
+ */
+goog.graphics.Path.prototype.forEachSegment = function(callback) {
+ var points = this.arguments_;
+ var index = 0;
+ for (var i = 0, length = this.segments_.length; i < length; i++) {
+ var seg = this.segments_[i];
+ var n = goog.graphics.Path.segmentArgCounts_[seg] * this.count_[i];
+ callback(seg, points.slice(index, index + n));
+ index += n;
+ }
+};
+
+
+/**
+ * Returns the coordinates most recently added to the end of the path.
+ *
+ * @return {Array<number>?} An array containing the ending coordinates of the
+ * path of the form {@code [x, y]}.
+ */
+goog.graphics.Path.prototype.getCurrentPoint = function() {
+ return this.currentPoint_ && this.currentPoint_.concat();
+};
+
+
+/**
+ * @return {!goog.graphics.Path} A copy of this path.
+ */
+goog.graphics.Path.prototype.clone = function() {
+ var path = new this.constructor();
+ path.segments_ = this.segments_.concat();
+ path.count_ = this.count_.concat();
+ path.arguments_ = this.arguments_.concat();
+ path.closePoint_ = this.closePoint_ && this.closePoint_.concat();
+ path.currentPoint_ = this.currentPoint_ && this.currentPoint_.concat();
+ path.simple_ = this.simple_;
+ return path;
+};
+
+
+/**
+ * Returns true if this path contains no arcs. Simplified paths can be
+ * created using {@code createSimplifiedPath}.
+ *
+ * @return {boolean} True if the path contains no arcs.
+ */
+goog.graphics.Path.prototype.isSimple = function() {
+ return this.simple_;
+};
+
+
+/**
+ * A map from segment type to the path function to call to simplify a path.
+ * @type {!Object}
+ * @private
+ * @suppress {deprecated} goog.graphics.Path is deprecated.
+ */
+goog.graphics.Path.simplifySegmentMap_ = (function() {
+ var map = {};
+ map[goog.graphics.Path.Segment.MOVETO] = goog.graphics.Path.prototype.moveTo;
+ map[goog.graphics.Path.Segment.LINETO] = goog.graphics.Path.prototype.lineTo;
+ map[goog.graphics.Path.Segment.CLOSE] = goog.graphics.Path.prototype.close;
+ map[goog.graphics.Path.Segment.CURVETO] =
+ goog.graphics.Path.prototype.curveTo;
+ map[goog.graphics.Path.Segment.ARCTO] =
+ goog.graphics.Path.prototype.arcToAsCurves;
+ return map;
+})();
+
+
+/**
+ * Creates a copy of the given path, replacing {@code arcTo} with
+ * {@code arcToAsCurves}. The resulting path is simplified and can
+ * be transformed.
+ *
+ * @param {!goog.graphics.Path} src The path to simplify.
+ * @return {!goog.graphics.Path} A new simplified path.
+ * @suppress {deprecated} goog.graphics is deprecated.
+ */
+goog.graphics.Path.createSimplifiedPath = function(src) {
+ if (src.isSimple()) {
+ return src.clone();
+ }
+ var path = new goog.graphics.Path();
+ src.forEachSegment(function(segment, args) {
+ goog.graphics.Path.simplifySegmentMap_[segment].apply(path, args);
+ });
+ return path;
+};
+
+
+// TODO(chrisn): Delete this method
+/**
+ * Creates a transformed copy of this path. The path is simplified
+ * {@see #createSimplifiedPath} prior to transformation.
+ *
+ * @param {!goog.graphics.AffineTransform} tx The transformation to perform.
+ * @return {!goog.graphics.Path} A new, transformed path.
+ */
+goog.graphics.Path.prototype.createTransformedPath = function(tx) {
+ var path = goog.graphics.Path.createSimplifiedPath(this);
+ path.transform(tx);
+ return path;
+};
+
+
+/**
+ * Transforms the path. Only simple paths are transformable. Attempting
+ * to transform a non-simple path will throw an error.
+ *
+ * @param {!goog.graphics.AffineTransform} tx The transformation to perform.
+ * @return {!goog.graphics.Path} The path itself.
+ */
+goog.graphics.Path.prototype.transform = function(tx) {
+ if (!this.isSimple()) {
+ throw Error('Non-simple path');
+ }
+ tx.transform(this.arguments_, 0, this.arguments_, 0,
+ this.arguments_.length / 2);
+ if (this.closePoint_) {
+ tx.transform(this.closePoint_, 0, this.closePoint_, 0, 1);
+ }
+ if (this.currentPoint_ && this.closePoint_ != this.currentPoint_) {
+ tx.transform(this.currentPoint_, 0, this.currentPoint_, 0, 1);
+ }
+ return this;
+};
+
+
+/**
+ * @return {boolean} Whether the path is empty.
+ */
+goog.graphics.Path.prototype.isEmpty = function() {
+ return this.segments_.length == 0;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/pathelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/pathelement.js b/externs/GCL/externs/goog/graphics/pathelement.js
new file mode 100644
index 0000000..b58b8c6
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/pathelement.js
@@ -0,0 +1,54 @@
+// 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 thin wrapper around the DOM element for paths.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.PathElement');
+
+goog.require('goog.graphics.StrokeAndFillElement');
+
+
+
+/**
+ * Interface for a graphics path element.
+ * You should not construct objects from this constructor. The graphics
+ * will return an implementation of this interface for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.PathElement = function(element, graphics, stroke, fill) {
+ goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
+ fill);
+};
+goog.inherits(goog.graphics.PathElement, goog.graphics.StrokeAndFillElement);
+
+
+/**
+ * Update the underlying path.
+ * @param {!goog.graphics.Path} path The path object to draw.
+ */
+goog.graphics.PathElement.prototype.setPath = goog.abstractMethod;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/paths.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/paths.js b/externs/GCL/externs/goog/graphics/paths.js
new file mode 100644
index 0000000..37b53d9
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/paths.js
@@ -0,0 +1,86 @@
+// 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 Factories for common path types.
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+
+goog.provide('goog.graphics.paths');
+
+goog.require('goog.graphics.Path');
+goog.require('goog.math.Coordinate');
+
+
+/**
+ * Defines a regular n-gon by specifing the center, a vertex, and the total
+ * number of vertices.
+ * @param {goog.math.Coordinate} center The center point.
+ * @param {goog.math.Coordinate} vertex The vertex, which implicitly defines
+ * a radius as well.
+ * @param {number} n The number of vertices.
+ * @return {!goog.graphics.Path} The path.
+ */
+goog.graphics.paths.createRegularNGon = function(center, vertex, n) {
+ var path = new goog.graphics.Path();
+ path.moveTo(vertex.x, vertex.y);
+
+ var startAngle = Math.atan2(vertex.y - center.y, vertex.x - center.x);
+ var radius = goog.math.Coordinate.distance(center, vertex);
+ for (var i = 1; i < n; i++) {
+ var angle = startAngle + 2 * Math.PI * (i / n);
+ path.lineTo(center.x + radius * Math.cos(angle),
+ center.y + radius * Math.sin(angle));
+ }
+ path.close();
+ return path;
+};
+
+
+/**
+ * Defines an arrow.
+ * @param {goog.math.Coordinate} a Point A.
+ * @param {goog.math.Coordinate} b Point B.
+ * @param {?number} aHead The size of the arrow head at point A.
+ * 0 omits the head.
+ * @param {?number} bHead The size of the arrow head at point B.
+ * 0 omits the head.
+ * @return {!goog.graphics.Path} The path.
+ */
+goog.graphics.paths.createArrow = function(a, b, aHead, bHead) {
+ var path = new goog.graphics.Path();
+ path.moveTo(a.x, a.y);
+ path.lineTo(b.x, b.y);
+
+ var angle = Math.atan2(b.y - a.y, b.x - a.x);
+ if (aHead) {
+ path.appendPath(
+ goog.graphics.paths.createRegularNGon(
+ new goog.math.Coordinate(
+ a.x + aHead * Math.cos(angle),
+ a.y + aHead * Math.sin(angle)),
+ a, 3));
+ }
+ if (bHead) {
+ path.appendPath(
+ goog.graphics.paths.createRegularNGon(
+ new goog.math.Coordinate(
+ b.x + bHead * Math.cos(angle + Math.PI),
+ b.y + bHead * Math.sin(angle + Math.PI)),
+ b, 3));
+ }
+ return path;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/rectelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/rectelement.js b/externs/GCL/externs/goog/graphics/rectelement.js
new file mode 100644
index 0000000..9a6e9a1
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/rectelement.js
@@ -0,0 +1,63 @@
+// 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 thin wrapper around the DOM element for rectangles.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.RectElement');
+
+goog.require('goog.graphics.StrokeAndFillElement');
+
+
+
+/**
+ * Interface for a graphics rectangle element.
+ * You should not construct objects from this constructor. The graphics
+ * will return an implementation of this interface for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.RectElement = function(element, graphics, stroke, fill) {
+ goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
+ fill);
+};
+goog.inherits(goog.graphics.RectElement, goog.graphics.StrokeAndFillElement);
+
+
+/**
+ * Update the position of the rectangle.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ */
+goog.graphics.RectElement.prototype.setPosition = goog.abstractMethod;
+
+
+/**
+ * Update the size of the rectangle.
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ */
+goog.graphics.RectElement.prototype.setSize = goog.abstractMethod;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/solidfill.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/solidfill.js b/externs/GCL/externs/goog/graphics/solidfill.js
new file mode 100644
index 0000000..fae3fc4
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/solidfill.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 Represents a solid color fill goog.graphics.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.SolidFill');
+
+
+goog.require('goog.graphics.Fill');
+
+
+
+/**
+ * Creates an immutable solid color fill object.
+ *
+ * @param {string} color The color of the background.
+ * @param {number=} opt_opacity The opacity of the background fill. The value
+ * must be greater than or equal to zero (transparent) and less than or
+ * equal to 1 (opaque).
+ * @constructor
+ * @extends {goog.graphics.Fill}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.SolidFill = function(color, opt_opacity) {
+ /**
+ * The color with which to fill.
+ * @type {string}
+ * @private
+ */
+ this.color_ = color;
+
+
+ /**
+ * The opacity of the fill.
+ * @type {number}
+ * @private
+ */
+ this.opacity_ = opt_opacity == null ? 1.0 : opt_opacity;
+};
+goog.inherits(goog.graphics.SolidFill, goog.graphics.Fill);
+
+
+/**
+ * @return {string} The color of this fill.
+ */
+goog.graphics.SolidFill.prototype.getColor = function() {
+ return this.color_;
+};
+
+
+/**
+ * @return {number} The opacity of this fill.
+ */
+goog.graphics.SolidFill.prototype.getOpacity = function() {
+ return this.opacity_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/stroke.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/stroke.js b/externs/GCL/externs/goog/graphics/stroke.js
new file mode 100644
index 0000000..ae1eb8e
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/stroke.js
@@ -0,0 +1,86 @@
+// 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 Represents a stroke object for goog.graphics.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.Stroke');
+
+
+
+/**
+ * Creates an immutable stroke object.
+ *
+ * @param {number|string} width The width of the stroke.
+ * @param {string} color The color of the stroke.
+ * @param {number=} opt_opacity The opacity of the background fill. The value
+ * must be greater than or equal to zero (transparent) and less than or
+ * equal to 1 (opaque).
+ * @constructor
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.Stroke = function(width, color, opt_opacity) {
+ /**
+ * The width of the stroke.
+ * @type {number|string}
+ * @private
+ */
+ this.width_ = width;
+
+
+ /**
+ * The color with which to fill.
+ * @type {string}
+ * @private
+ */
+ this.color_ = color;
+
+
+ /**
+ * The opacity of the fill.
+ * @type {number}
+ * @private
+ */
+ this.opacity_ = opt_opacity == null ? 1.0 : opt_opacity;
+};
+
+
+/**
+ * @return {number|string} The width of this stroke.
+ */
+goog.graphics.Stroke.prototype.getWidth = function() {
+ return this.width_;
+};
+
+
+/**
+ * @return {string} The color of this stroke.
+ */
+goog.graphics.Stroke.prototype.getColor = function() {
+ return this.color_;
+};
+
+
+/**
+ * @return {number} The opacity of this fill.
+ */
+goog.graphics.Stroke.prototype.getOpacity = function() {
+ return this.opacity_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/strokeandfillelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/strokeandfillelement.js b/externs/GCL/externs/goog/graphics/strokeandfillelement.js
new file mode 100644
index 0000000..e3b50f9
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/strokeandfillelement.js
@@ -0,0 +1,114 @@
+// 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 thin wrapper around the DOM element for elements with a
+ * stroke and fill.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.StrokeAndFillElement');
+
+goog.require('goog.graphics.Element');
+
+
+
+/**
+ * Interface for a graphics element with a stroke and fill.
+ * This is the base interface for ellipse, rectangle and other
+ * shape interfaces.
+ * You should not construct objects from this constructor. The graphics
+ * will return an implementation of this interface for you.
+ *
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.Element}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.StrokeAndFillElement = function(element, graphics, stroke, fill) {
+ goog.graphics.Element.call(this, element, graphics);
+ this.setStroke(stroke);
+ this.setFill(fill);
+};
+goog.inherits(goog.graphics.StrokeAndFillElement, goog.graphics.Element);
+
+
+/**
+ * The latest fill applied to this element.
+ * @type {goog.graphics.Fill?}
+ * @protected
+ */
+goog.graphics.StrokeAndFillElement.prototype.fill = null;
+
+
+/**
+ * The latest stroke applied to this element.
+ * @type {goog.graphics.Stroke?}
+ * @private
+ */
+goog.graphics.StrokeAndFillElement.prototype.stroke_ = null;
+
+
+/**
+ * Sets the fill for this element.
+ * @param {goog.graphics.Fill?} fill The fill object.
+ */
+goog.graphics.StrokeAndFillElement.prototype.setFill = function(fill) {
+ this.fill = fill;
+ this.getGraphics().setElementFill(this, fill);
+};
+
+
+/**
+ * @return {goog.graphics.Fill?} fill The fill object.
+ */
+goog.graphics.StrokeAndFillElement.prototype.getFill = function() {
+ return this.fill;
+};
+
+
+/**
+ * Sets the stroke for this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke object.
+ */
+goog.graphics.StrokeAndFillElement.prototype.setStroke = function(stroke) {
+ this.stroke_ = stroke;
+ this.getGraphics().setElementStroke(this, stroke);
+};
+
+
+/**
+ * @return {goog.graphics.Stroke?} stroke The stroke object.
+ */
+goog.graphics.StrokeAndFillElement.prototype.getStroke = function() {
+ return this.stroke_;
+};
+
+
+/**
+ * Re-strokes the element to react to coordinate size changes.
+ */
+goog.graphics.StrokeAndFillElement.prototype.reapplyStroke = function() {
+ if (this.stroke_) {
+ this.setStroke(this.stroke_);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/svgelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/svgelement.js b/externs/GCL/externs/goog/graphics/svgelement.js
new file mode 100644
index 0000000..eddcbb5
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/svgelement.js
@@ -0,0 +1,284 @@
+// 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 Thin wrappers around the DOM element returned from
+ * the different draw methods of the graphics. This is the SVG implementation.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.graphics.SvgEllipseElement');
+goog.provide('goog.graphics.SvgGroupElement');
+goog.provide('goog.graphics.SvgImageElement');
+goog.provide('goog.graphics.SvgPathElement');
+goog.provide('goog.graphics.SvgRectElement');
+goog.provide('goog.graphics.SvgTextElement');
+
+
+goog.require('goog.dom');
+goog.require('goog.graphics.EllipseElement');
+goog.require('goog.graphics.GroupElement');
+goog.require('goog.graphics.ImageElement');
+goog.require('goog.graphics.PathElement');
+goog.require('goog.graphics.RectElement');
+goog.require('goog.graphics.TextElement');
+
+
+
+/**
+ * Thin wrapper for SVG group elements.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.SvgGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.graphics.GroupElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.SvgGroupElement = function(element, graphics) {
+ goog.graphics.GroupElement.call(this, element, graphics);
+};
+goog.inherits(goog.graphics.SvgGroupElement, goog.graphics.GroupElement);
+
+
+/**
+ * Remove all drawing elements from the group.
+ * @override
+ */
+goog.graphics.SvgGroupElement.prototype.clear = function() {
+ goog.dom.removeChildren(this.getElement());
+};
+
+
+/**
+ * Set the size of the group element.
+ * @param {number|string} width The width of the group element.
+ * @param {number|string} height The height of the group element.
+ * @override
+ */
+goog.graphics.SvgGroupElement.prototype.setSize = function(width, height) {
+ this.getGraphics().setElementAttributes(this.getElement(),
+ {'width': width, 'height': height});
+};
+
+
+
+/**
+ * Thin wrapper for SVG ellipse elements.
+ * This is an implementation of the goog.graphics.EllipseElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.SvgGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.EllipseElement}
+ * @final
+ */
+goog.graphics.SvgEllipseElement = function(element, graphics, stroke, fill) {
+ goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill);
+};
+goog.inherits(goog.graphics.SvgEllipseElement, goog.graphics.EllipseElement);
+
+
+/**
+ * Update the center point of the ellipse.
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @override
+ */
+goog.graphics.SvgEllipseElement.prototype.setCenter = function(cx, cy) {
+ this.getGraphics().setElementAttributes(this.getElement(),
+ {'cx': cx, 'cy': cy});
+};
+
+
+/**
+ * Update the radius of the ellipse.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ * @override
+ */
+goog.graphics.SvgEllipseElement.prototype.setRadius = function(rx, ry) {
+ this.getGraphics().setElementAttributes(this.getElement(),
+ {'rx': rx, 'ry': ry});
+};
+
+
+
+/**
+ * Thin wrapper for SVG rectangle elements.
+ * This is an implementation of the goog.graphics.RectElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.SvgGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.RectElement}
+ * @final
+ */
+goog.graphics.SvgRectElement = function(element, graphics, stroke, fill) {
+ goog.graphics.RectElement.call(this, element, graphics, stroke, fill);
+};
+goog.inherits(goog.graphics.SvgRectElement, goog.graphics.RectElement);
+
+
+/**
+ * Update the position of the rectangle.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @override
+ */
+goog.graphics.SvgRectElement.prototype.setPosition = function(x, y) {
+ this.getGraphics().setElementAttributes(this.getElement(), {'x': x, 'y': y});
+};
+
+
+/**
+ * Update the size of the rectangle.
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @override
+ */
+goog.graphics.SvgRectElement.prototype.setSize = function(width, height) {
+ this.getGraphics().setElementAttributes(this.getElement(),
+ {'width': width, 'height': height});
+};
+
+
+
+/**
+ * Thin wrapper for SVG path elements.
+ * This is an implementation of the goog.graphics.PathElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.SvgGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.PathElement}
+ * @final
+ */
+goog.graphics.SvgPathElement = function(element, graphics, stroke, fill) {
+ goog.graphics.PathElement.call(this, element, graphics, stroke, fill);
+};
+goog.inherits(goog.graphics.SvgPathElement, goog.graphics.PathElement);
+
+
+/**
+ * Update the underlying path.
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @override
+ */
+goog.graphics.SvgPathElement.prototype.setPath = function(path) {
+ this.getGraphics().setElementAttributes(this.getElement(),
+ {'d': /** @suppress {missingRequire} */
+ goog.graphics.SvgGraphics.getSvgPath(path)});
+};
+
+
+
+/**
+ * Thin wrapper for SVG text elements.
+ * This is an implementation of the goog.graphics.TextElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.SvgGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.TextElement}
+ * @final
+ */
+goog.graphics.SvgTextElement = function(element, graphics, stroke, fill) {
+ goog.graphics.TextElement.call(this, element, graphics, stroke, fill);
+};
+goog.inherits(goog.graphics.SvgTextElement, goog.graphics.TextElement);
+
+
+/**
+ * Update the displayed text of the element.
+ * @param {string} text The text to draw.
+ * @override
+ */
+goog.graphics.SvgTextElement.prototype.setText = function(text) {
+ this.getElement().firstChild.data = text;
+};
+
+
+
+/**
+ * Thin wrapper for SVG image elements.
+ * This is an implementation of the goog.graphics.ImageElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.SvgGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.graphics.ImageElement}
+ * @final
+ */
+goog.graphics.SvgImageElement = function(element, graphics) {
+ goog.graphics.ImageElement.call(this, element, graphics);
+};
+goog.inherits(goog.graphics.SvgImageElement, goog.graphics.ImageElement);
+
+
+/**
+ * Update the position of the image.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @override
+ */
+goog.graphics.SvgImageElement.prototype.setPosition = function(x, y) {
+ this.getGraphics().setElementAttributes(this.getElement(), {'x': x, 'y': y});
+};
+
+
+/**
+ * Update the size of the image.
+ * @param {number} width Width of image.
+ * @param {number} height Height of image.
+ * @override
+ */
+goog.graphics.SvgImageElement.prototype.setSize = function(width, height) {
+ this.getGraphics().setElementAttributes(this.getElement(),
+ {'width': width, 'height': height});
+};
+
+
+/**
+ * Update the source of the image.
+ * @param {string} src Source of the image.
+ * @override
+ */
+goog.graphics.SvgImageElement.prototype.setSource = function(src) {
+ this.getGraphics().setElementAttributes(this.getElement(),
+ {'xlink:href': src});
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/svggraphics.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/svggraphics.js b/externs/GCL/externs/goog/graphics/svggraphics.js
new file mode 100644
index 0000000..59db4a2
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/svggraphics.js
@@ -0,0 +1,878 @@
+// 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 SvgGraphics sub class that uses SVG to draw the graphics.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.graphics.SvgGraphics');
+
+goog.require('goog.Timer');
+goog.require('goog.dom');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventType');
+goog.require('goog.graphics.AbstractGraphics');
+goog.require('goog.graphics.LinearGradient');
+goog.require('goog.graphics.Path');
+goog.require('goog.graphics.SolidFill');
+goog.require('goog.graphics.Stroke');
+goog.require('goog.graphics.SvgEllipseElement');
+goog.require('goog.graphics.SvgGroupElement');
+goog.require('goog.graphics.SvgImageElement');
+goog.require('goog.graphics.SvgPathElement');
+goog.require('goog.graphics.SvgRectElement');
+goog.require('goog.graphics.SvgTextElement');
+goog.require('goog.math');
+goog.require('goog.math.Size');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A Graphics implementation for drawing using SVG.
+ * @param {string|number} width The width in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {string|number} height The height in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {?number=} opt_coordWidth The coordinate width - if
+ * omitted or null, defaults to same as width.
+ * @param {?number=} opt_coordHeight The coordinate height - if
+ * omitted or null, defaults to same as height.
+ * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
+ * document we want to render in.
+ * @constructor
+ * @extends {goog.graphics.AbstractGraphics}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.SvgGraphics = function(width, height,
+ opt_coordWidth, opt_coordHeight,
+ opt_domHelper) {
+ goog.graphics.AbstractGraphics.call(this, width, height,
+ opt_coordWidth, opt_coordHeight,
+ opt_domHelper);
+
+ /**
+ * Map from def key to id of def root element.
+ * Defs are global "defines" of svg that are used to share common attributes,
+ * for example gradients.
+ * @type {Object}
+ * @private
+ */
+ this.defs_ = {};
+
+ /**
+ * Whether to manually implement viewBox by using a coordinate transform.
+ * As of 1/11/08 this is necessary for Safari 3 but not for the nightly
+ * WebKit build. Apply to webkit versions < 526. 525 is the
+ * last version used by Safari 3.1.
+ * @type {boolean}
+ * @private
+ */
+ this.useManualViewbox_ = goog.userAgent.WEBKIT &&
+ !goog.userAgent.isVersionOrHigher(526);
+
+ /**
+ * Event handler.
+ * @type {goog.events.EventHandler<!goog.graphics.SvgGraphics>}
+ * @private
+ */
+ this.handler_ = new goog.events.EventHandler(this);
+};
+goog.inherits(goog.graphics.SvgGraphics, goog.graphics.AbstractGraphics);
+
+
+/**
+ * The SVG namespace URN
+ * @private
+ * @type {string}
+ */
+goog.graphics.SvgGraphics.SVG_NS_ = 'http://www.w3.org/2000/svg';
+
+
+/**
+ * The name prefix for def entries
+ * @private
+ * @type {string}
+ */
+goog.graphics.SvgGraphics.DEF_ID_PREFIX_ = '_svgdef_';
+
+
+/**
+ * The next available unique identifier for a def entry.
+ * This is a static variable, so that when multiple graphics are used in one
+ * document, the same def id can not be re-defined by another SvgGraphics.
+ * @type {number}
+ * @private
+ */
+goog.graphics.SvgGraphics.nextDefId_ = 0;
+
+
+/**
+ * Svg element for definitions for other elements, e.g. linear gradients.
+ * @type {Element}
+ * @private
+ */
+goog.graphics.SvgGraphics.prototype.defsElement_;
+
+
+/**
+ * Creates an SVG element. Used internally and by different SVG classes.
+ * @param {string} tagName The type of element to create.
+ * @param {Object=} opt_attributes Map of name-value pairs for attributes.
+ * @return {!Element} The created element.
+ * @private
+ */
+goog.graphics.SvgGraphics.prototype.createSvgElement_ = function(tagName,
+ opt_attributes) {
+ var element = this.dom_.getDocument().createElementNS(
+ goog.graphics.SvgGraphics.SVG_NS_, tagName);
+
+ if (opt_attributes) {
+ this.setElementAttributes(element, opt_attributes);
+ }
+
+ return element;
+};
+
+
+/**
+ * Sets properties to an SVG element. Used internally and by different
+ * SVG elements.
+ * @param {Element} element The svg element.
+ * @param {Object} attributes Map of name-value pairs for attributes.
+ */
+goog.graphics.SvgGraphics.prototype.setElementAttributes = function(element,
+ attributes) {
+ for (var key in attributes) {
+ element.setAttribute(key, attributes[key]);
+ }
+};
+
+
+/**
+ * Appends an element.
+ *
+ * @param {goog.graphics.Element} element The element wrapper.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ * @private
+ */
+goog.graphics.SvgGraphics.prototype.append_ = function(element, opt_group) {
+ var parent = opt_group || this.canvasElement;
+ parent.getElement().appendChild(element.getElement());
+};
+
+
+/**
+ * Sets the fill of the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
+ * @param {goog.graphics.Fill?} fill The fill object.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.setElementFill = function(element, fill) {
+ var svgElement = element.getElement();
+ if (fill instanceof goog.graphics.SolidFill) {
+ svgElement.setAttribute('fill', fill.getColor());
+ svgElement.setAttribute('fill-opacity', fill.getOpacity());
+ } else if (fill instanceof goog.graphics.LinearGradient) {
+ // create a def key which is just a concat of all the relevant fields
+ var defKey = 'lg-' +
+ fill.getX1() + '-' + fill.getY1() + '-' +
+ fill.getX2() + '-' + fill.getY2() + '-' +
+ fill.getColor1() + '-' + fill.getColor2();
+ // It seems that the SVG version accepts opacity where the VML does not
+
+ var id = this.getDef(defKey);
+
+ if (!id) { // No def for this yet, create it
+ // Create the gradient def entry (only linear gradient are supported)
+ var gradient = this.createSvgElement_('linearGradient', {
+ 'x1': fill.getX1(),
+ 'y1': fill.getY1(),
+ 'x2': fill.getX2(),
+ 'y2': fill.getY2(),
+ 'gradientUnits': 'userSpaceOnUse'
+ });
+
+ var gstyle = 'stop-color:' + fill.getColor1();
+ if (goog.isNumber(fill.getOpacity1())) {
+ gstyle += ';stop-opacity:' + fill.getOpacity1();
+ }
+ var stop1 = this.createSvgElement_(
+ 'stop', {'offset': '0%', 'style': gstyle});
+ gradient.appendChild(stop1);
+
+ // LinearGradients don't have opacity in VML so implement that before
+ // enabling the following code.
+ // if (fill.getOpacity() != null) {
+ // gstyles += 'opacity:' + fill.getOpacity() + ';'
+ // }
+ gstyle = 'stop-color:' + fill.getColor2();
+ if (goog.isNumber(fill.getOpacity2())) {
+ gstyle += ';stop-opacity:' + fill.getOpacity2();
+ }
+ var stop2 = this.createSvgElement_(
+ 'stop', {'offset': '100%', 'style': gstyle});
+ gradient.appendChild(stop2);
+
+ // LinearGradients don't have opacity in VML so implement that before
+ // enabling the following code.
+ // if (fill.getOpacity() != null) {
+ // gstyles += 'opacity:' + fill.getOpacity() + ';'
+ // }
+
+ id = this.addDef(defKey, gradient);
+ }
+
+ // Link element to linearGradient definition
+ svgElement.setAttribute('fill', 'url(#' + id + ')');
+ } else {
+ svgElement.setAttribute('fill', 'none');
+ }
+};
+
+
+/**
+ * Sets the stroke of the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
+ * @param {goog.graphics.Stroke?} stroke The stroke object.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.setElementStroke = function(element,
+ stroke) {
+ var svgElement = element.getElement();
+ if (stroke) {
+ svgElement.setAttribute('stroke', stroke.getColor());
+ svgElement.setAttribute('stroke-opacity', stroke.getOpacity());
+
+ var width = stroke.getWidth();
+ if (goog.isString(width) && width.indexOf('px') != -1) {
+ svgElement.setAttribute('stroke-width',
+ parseFloat(width) / this.getPixelScaleX());
+ } else {
+ svgElement.setAttribute('stroke-width', width);
+ }
+ } else {
+ svgElement.setAttribute('stroke', 'none');
+ }
+};
+
+
+/**
+ * Set the translation and rotation of an element.
+ *
+ * If a more general affine transform is needed than this provides
+ * (e.g. skew and scale) then use setElementAffineTransform.
+ * @param {goog.graphics.Element} element The element wrapper.
+ * @param {number} x The x coordinate of the translation transform.
+ * @param {number} y The y coordinate of the translation transform.
+ * @param {number} angle The angle of the rotation transform.
+ * @param {number} centerX The horizontal center of the rotation transform.
+ * @param {number} centerY The vertical center of the rotation transform.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.setElementTransform = function(element, x,
+ y, angle, centerX, centerY) {
+ element.getElement().setAttribute('transform', 'translate(' + x + ',' + y +
+ ') rotate(' + angle + ' ' + centerX + ' ' + centerY + ')');
+};
+
+
+/**
+ * Set the transformation of an element.
+ * @param {goog.graphics.Element} element The element wrapper.
+ * @param {!goog.graphics.AffineTransform} affineTransform The
+ * transformation applied to this element.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.setElementAffineTransform = function(
+ element, affineTransform) {
+ var t = affineTransform;
+ var substr = [t.getScaleX(), t.getShearY(), t.getShearX(), t.getScaleY(),
+ t.getTranslateX(), t.getTranslateY()].join(',');
+ element.getElement().setAttribute('transform', 'matrix(' + substr + ')');
+};
+
+
+/**
+ * Creates the DOM representation of the graphics area.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.createDom = function() {
+ // Set up the standard attributes.
+ var attributes = {
+ 'width': this.width,
+ 'height': this.height,
+ 'overflow': 'hidden'
+ };
+
+ var svgElement = this.createSvgElement_('svg', attributes);
+
+ var groupElement = this.createSvgElement_('g');
+
+ this.defsElement_ = this.createSvgElement_('defs');
+ this.canvasElement = new goog.graphics.SvgGroupElement(groupElement, this);
+
+ svgElement.appendChild(this.defsElement_);
+ svgElement.appendChild(groupElement);
+
+ // Use the svgElement as the root element.
+ this.setElementInternal(svgElement);
+
+ // Set up the coordinate system.
+ this.setViewBox_();
+};
+
+
+/**
+ * Changes the coordinate system position.
+ * @param {number} left The coordinate system left bound.
+ * @param {number} top The coordinate system top bound.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.setCoordOrigin = function(left, top) {
+ this.coordLeft = left;
+ this.coordTop = top;
+
+ this.setViewBox_();
+};
+
+
+/**
+ * Changes the coordinate size.
+ * @param {number} coordWidth The coordinate width.
+ * @param {number} coordHeight The coordinate height.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.setCoordSize = function(coordWidth,
+ coordHeight) {
+ goog.graphics.SvgGraphics.superClass_.setCoordSize.apply(
+ this, arguments);
+ this.setViewBox_();
+};
+
+
+/**
+ * @return {string} The view box string.
+ * @private
+ */
+goog.graphics.SvgGraphics.prototype.getViewBox_ = function() {
+ return this.coordLeft + ' ' + this.coordTop + ' ' +
+ (this.coordWidth ? this.coordWidth + ' ' + this.coordHeight : '');
+};
+
+
+/**
+ * Sets up the view box.
+ * @private
+ */
+goog.graphics.SvgGraphics.prototype.setViewBox_ = function() {
+ if (this.coordWidth || this.coordLeft || this.coordTop) {
+ this.getElement().setAttribute('preserveAspectRatio', 'none');
+ if (this.useManualViewbox_) {
+ this.updateManualViewBox_();
+ } else {
+ this.getElement().setAttribute('viewBox', this.getViewBox_());
+ }
+ }
+};
+
+
+/**
+ * Updates the transform of the root element to fake a viewBox. Should only
+ * be called when useManualViewbox_ is set.
+ * @private
+ */
+goog.graphics.SvgGraphics.prototype.updateManualViewBox_ = function() {
+ if (!this.isInDocument() ||
+ !(this.coordWidth || this.coordLeft || !this.coordTop)) {
+ return;
+ }
+
+ var size = this.getPixelSize();
+ if (size.width == 0) {
+ // In Safari, invisible SVG is sometimes shown. Explicitly hide it.
+ this.getElement().style.visibility = 'hidden';
+ return;
+ }
+
+ this.getElement().style.visibility = '';
+
+ var offsetX = - this.coordLeft;
+ var offsetY = - this.coordTop;
+ var scaleX = size.width / this.coordWidth;
+ var scaleY = size.height / this.coordHeight;
+
+ this.canvasElement.getElement().setAttribute('transform',
+ 'scale(' + scaleX + ' ' + scaleY + ') ' +
+ 'translate(' + offsetX + ' ' + offsetY + ')');
+};
+
+
+/**
+ * Change the size of the canvas.
+ * @param {number} pixelWidth The width in pixels.
+ * @param {number} pixelHeight The height in pixels.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.setSize = function(pixelWidth,
+ pixelHeight) {
+ goog.style.setSize(this.getElement(), pixelWidth, pixelHeight);
+};
+
+
+/** @override */
+goog.graphics.SvgGraphics.prototype.getPixelSize = function() {
+ if (!goog.userAgent.GECKO) {
+ return this.isInDocument() ?
+ goog.style.getSize(this.getElement()) :
+ goog.graphics.SvgGraphics.base(this, 'getPixelSize');
+ }
+
+ // In Gecko, goog.style.getSize does not work for SVG elements. We have to
+ // compute the size manually if it is percentage based.
+ var width = this.width;
+ var height = this.height;
+ var computeWidth = goog.isString(width) && width.indexOf('%') != -1;
+ var computeHeight = goog.isString(height) && height.indexOf('%') != -1;
+
+ if (!this.isInDocument() && (computeWidth || computeHeight)) {
+ return null;
+ }
+
+ var parent;
+ var parentSize;
+
+ if (computeWidth) {
+ parent = /** @type {Element} */ (this.getElement().parentNode);
+ parentSize = goog.style.getSize(parent);
+ width = parseFloat(/** @type {string} */ (width)) * parentSize.width / 100;
+ }
+
+ if (computeHeight) {
+ parent = parent || /** @type {Element} */ (this.getElement().parentNode);
+ parentSize = parentSize || goog.style.getSize(parent);
+ height = parseFloat(/** @type {string} */ (height)) * parentSize.height /
+ 100;
+ }
+
+ return new goog.math.Size(/** @type {number} */ (width),
+ /** @type {number} */ (height));
+};
+
+
+/**
+ * Remove all drawing elements from the graphics.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.clear = function() {
+ this.canvasElement.clear();
+ goog.dom.removeChildren(this.defsElement_);
+ this.defs_ = {};
+};
+
+
+/**
+ * Draw an ellipse.
+ *
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.EllipseElement} The newly created element.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.drawEllipse = function(
+ cx, cy, rx, ry, stroke, fill, opt_group) {
+ var element = this.createSvgElement_('ellipse',
+ {'cx': cx, 'cy': cy, 'rx': rx, 'ry': ry});
+ var wrapper = new goog.graphics.SvgEllipseElement(element, this, stroke,
+ fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw a rectangle.
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.RectElement} The newly created element.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.drawRect = function(x, y, width, height,
+ stroke, fill, opt_group) {
+ var element = this.createSvgElement_('rect',
+ {'x': x, 'y': y, 'width': width, 'height': height});
+ var wrapper = new goog.graphics.SvgRectElement(element, this, stroke, fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw an image.
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of the image.
+ * @param {number} height Height of the image.
+ * @param {string} src The source fo the image.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.ImageElement} The newly created image wrapped in a
+ * rectangle element.
+ */
+goog.graphics.SvgGraphics.prototype.drawImage = function(x, y, width, height,
+ src, opt_group) {
+ var element = this.createSvgElement_('image', {
+ 'x': x,
+ 'y': y,
+ 'width': width,
+ 'height': height,
+ 'image-rendering': 'optimizeQuality',
+ 'preserveAspectRatio': 'none'
+ });
+ element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', src);
+ var wrapper = new goog.graphics.SvgImageElement(element, this);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw a text string vertically centered on a given line.
+ *
+ * @param {string} text The text to draw.
+ * @param {number} x1 X coordinate of start of line.
+ * @param {number} y1 Y coordinate of start of line.
+ * @param {number} x2 X coordinate of end of line.
+ * @param {number} y2 Y coordinate of end of line.
+ * @param {string} align Horizontal alignment: left (default), center, right.
+ * @param {goog.graphics.Font} font Font describing the font properties.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.TextElement} The newly created element.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.drawTextOnLine = function(
+ text, x1, y1, x2, y2, align, font, stroke, fill, opt_group) {
+ var angle = Math.round(goog.math.angle(x1, y1, x2, y2));
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+ var lineLength = Math.round(Math.sqrt(dx * dx + dy * dy)); // Length of line
+
+ // SVG baseline is on the glyph's base line. We estimate it as 85% of the
+ // font height. This is just a rough estimate, but do not have a better way.
+ var fontSize = font.size;
+ var attributes = {'font-family': font.family, 'font-size': fontSize};
+ var baseline = Math.round(fontSize * 0.85);
+ var textY = Math.round(y1 - (fontSize / 2) + baseline);
+ var textX = x1;
+ if (align == 'center') {
+ textX += Math.round(lineLength / 2);
+ attributes['text-anchor'] = 'middle';
+ } else if (align == 'right') {
+ textX += lineLength;
+ attributes['text-anchor'] = 'end';
+ }
+ attributes['x'] = textX;
+ attributes['y'] = textY;
+ if (font.bold) {
+ attributes['font-weight'] = 'bold';
+ }
+ if (font.italic) {
+ attributes['font-style'] = 'italic';
+ }
+ if (angle != 0) {
+ attributes['transform'] = 'rotate(' + angle + ' ' + x1 + ' ' + y1 + ')';
+ }
+
+ var element = this.createSvgElement_('text', attributes);
+ element.appendChild(this.dom_.getDocument().createTextNode(text));
+
+ // Bypass a Firefox-Mac bug where text fill is ignored. If text has no stroke,
+ // set a stroke, otherwise the text will not be visible.
+ if (stroke == null && goog.userAgent.GECKO && goog.userAgent.MAC) {
+ var color = 'black';
+ // For solid fills, use the fill color
+ if (fill instanceof goog.graphics.SolidFill) {
+ color = fill.getColor();
+ }
+ stroke = new goog.graphics.Stroke(1, color);
+ }
+
+ var wrapper = new goog.graphics.SvgTextElement(element, this, stroke, fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw a path.
+ *
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.PathElement} The newly created element.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.drawPath = function(
+ path, stroke, fill, opt_group) {
+
+ var element = this.createSvgElement_('path',
+ {'d': goog.graphics.SvgGraphics.getSvgPath(path)});
+ var wrapper = new goog.graphics.SvgPathElement(element, this, stroke, fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Returns a string representation of a logical path suitable for use in
+ * an SVG element.
+ *
+ * @param {goog.graphics.Path} path The logical path.
+ * @return {string} The SVG path representation.
+ * @suppress {deprecated} goog.graphics is deprecated.
+ */
+goog.graphics.SvgGraphics.getSvgPath = function(path) {
+ var list = [];
+ path.forEachSegment(function(segment, args) {
+ switch (segment) {
+ case goog.graphics.Path.Segment.MOVETO:
+ list.push('M');
+ Array.prototype.push.apply(list, args);
+ break;
+ case goog.graphics.Path.Segment.LINETO:
+ list.push('L');
+ Array.prototype.push.apply(list, args);
+ break;
+ case goog.graphics.Path.Segment.CURVETO:
+ list.push('C');
+ Array.prototype.push.apply(list, args);
+ break;
+ case goog.graphics.Path.Segment.ARCTO:
+ var extent = args[3];
+ list.push('A', args[0], args[1],
+ 0, Math.abs(extent) > 180 ? 1 : 0, extent > 0 ? 1 : 0,
+ args[4], args[5]);
+ break;
+ case goog.graphics.Path.Segment.CLOSE:
+ list.push('Z');
+ break;
+ }
+ });
+ return list.join(' ');
+};
+
+
+/**
+ * Create an empty group of drawing elements.
+ *
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.GroupElement} The newly created group.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.createGroup = function(opt_group) {
+ var element = this.createSvgElement_('g');
+ var parent = opt_group || this.canvasElement;
+ parent.getElement().appendChild(element);
+ return new goog.graphics.SvgGroupElement(element, this);
+};
+
+
+/**
+ * Measure and return the width (in pixels) of a given text string.
+ * Text measurement is needed to make sure a text can fit in the allocated area.
+ * The way text length is measured is by writing it into a div that is after
+ * the visible area, measure the div width, and immediatly erase the written
+ * value.
+ *
+ * @param {string} text The text string to measure.
+ * @param {goog.graphics.Font} font The font object describing the font style.
+ * @override
+ */
+goog.graphics.SvgGraphics.prototype.getTextWidth = function(text, font) {
+ // TODO(user) Implement
+};
+
+
+/**
+ * Adds a defintion of an element to the global definitions.
+ * @param {string} defKey This is a key that should be unique in a way that
+ * if two definitions are equal the should have the same key.
+ * @param {Element} defElement DOM element to add as a definition. It must
+ * have an id attribute set.
+ * @return {string} The assigned id of the defElement.
+ */
+goog.graphics.SvgGraphics.prototype.addDef = function(defKey, defElement) {
+ if (defKey in this.defs_) {
+ return this.defs_[defKey];
+ }
+ var id = goog.graphics.SvgGraphics.DEF_ID_PREFIX_ +
+ goog.graphics.SvgGraphics.nextDefId_++;
+ defElement.setAttribute('id', id);
+ this.defs_[defKey] = id;
+
+ // Add the def defElement of the defs list.
+ var defs = this.defsElement_;
+ defs.appendChild(defElement);
+ return id;
+};
+
+
+/**
+ * Returns the id of a definition element.
+ * @param {string} defKey This is a key that should be unique in a way that
+ * if two definitions are equal the should have the same key.
+ * @return {?string} The id of the found definition element or null if
+ * not found.
+ */
+goog.graphics.SvgGraphics.prototype.getDef = function(defKey) {
+ return defKey in this.defs_ ? this.defs_[defKey] : null;
+};
+
+
+/**
+ * Removes a definition of an elemnt from the global definitions.
+ * @param {string} defKey This is a key that should be unique in a way that
+ * if two definitions are equal they should have the same key.
+ */
+goog.graphics.SvgGraphics.prototype.removeDef = function(defKey) {
+ var id = this.getDef(defKey);
+ if (id) {
+ var element = this.dom_.getElement(id);
+ this.defsElement_.removeChild(element);
+ delete this.defs_[defKey];
+ }
+};
+
+
+/** @override */
+goog.graphics.SvgGraphics.prototype.enterDocument = function() {
+ var oldPixelSize = this.getPixelSize();
+ goog.graphics.SvgGraphics.superClass_.enterDocument.call(this);
+
+ // Dispatch a resize if this is the first time the size value is accurate.
+ if (!oldPixelSize) {
+ this.dispatchEvent(goog.events.EventType.RESIZE);
+ }
+
+
+ // For percentage based heights, listen for changes to size.
+ if (this.useManualViewbox_) {
+ var width = this.width;
+ var height = this.height;
+
+ if (typeof width == 'string' && width.indexOf('%') != -1 &&
+ typeof height == 'string' && height.indexOf('%') != -1) {
+ // SVG elements don't behave well with respect to size events, so we
+ // resort to polling.
+ this.handler_.listen(goog.graphics.SvgGraphics.getResizeCheckTimer_(),
+ goog.Timer.TICK, this.updateManualViewBox_);
+ }
+
+ this.updateManualViewBox_();
+ }
+};
+
+
+/** @override */
+goog.graphics.SvgGraphics.prototype.exitDocument = function() {
+ goog.graphics.SvgGraphics.superClass_.exitDocument.call(this);
+
+ // Stop polling.
+ if (this.useManualViewbox_) {
+ this.handler_.unlisten(goog.graphics.SvgGraphics.getResizeCheckTimer_(),
+ goog.Timer.TICK, this.updateManualViewBox_);
+ }
+};
+
+
+/**
+ * Disposes of the component by removing event handlers, detacing DOM nodes from
+ * the document body, and removing references to them.
+ * @override
+ * @protected
+ */
+goog.graphics.SvgGraphics.prototype.disposeInternal = function() {
+ delete this.defs_;
+ delete this.defsElement_;
+ delete this.canvasElement;
+ this.handler_.dispose();
+ delete this.handler_;
+ goog.graphics.SvgGraphics.superClass_.disposeInternal.call(this);
+};
+
+
+/**
+ * The centralized resize checking timer.
+ * @type {goog.Timer|undefined}
+ * @private
+ */
+goog.graphics.SvgGraphics.resizeCheckTimer_;
+
+
+/**
+ * @return {goog.Timer} The centralized timer object used for interval timing.
+ * @private
+ */
+goog.graphics.SvgGraphics.getResizeCheckTimer_ = function() {
+ if (!goog.graphics.SvgGraphics.resizeCheckTimer_) {
+ goog.graphics.SvgGraphics.resizeCheckTimer_ = new goog.Timer(400);
+ goog.graphics.SvgGraphics.resizeCheckTimer_.start();
+ }
+
+ return /** @type {goog.Timer} */ (
+ goog.graphics.SvgGraphics.resizeCheckTimer_);
+};
+
+
+/** @override */
+goog.graphics.SvgGraphics.prototype.isDomClonable = function() {
+ return true;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/textelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/textelement.js b/externs/GCL/externs/goog/graphics/textelement.js
new file mode 100644
index 0000000..c96ae6d
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/textelement.js
@@ -0,0 +1,55 @@
+// 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 thin wrapper around the DOM element for text elements.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.TextElement');
+
+goog.require('goog.graphics.StrokeAndFillElement');
+
+
+
+/**
+ * Interface for a graphics text element.
+ * You should not construct objects from this constructor. The graphics
+ * will return an implementation of this interface for you.
+ *
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.TextElement = function(element, graphics, stroke, fill) {
+ goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
+ fill);
+};
+goog.inherits(goog.graphics.TextElement, goog.graphics.StrokeAndFillElement);
+
+
+/**
+ * Update the displayed text of the element.
+ * @param {string} text The text to draw.
+ */
+goog.graphics.TextElement.prototype.setText = goog.abstractMethod;
[21/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/tagonenterhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/tagonenterhandler.js b/externs/GCL/externs/goog/editor/plugins/tagonenterhandler.js
new file mode 100644
index 0000000..e5776fd
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/tagonenterhandler.js
@@ -0,0 +1,744 @@
+// 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 TrogEdit plugin to handle enter keys by inserting the
+ * specified block level tag.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.TagOnEnterHandler');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.node');
+goog.require('goog.editor.plugins.EnterHandler');
+goog.require('goog.editor.range');
+goog.require('goog.editor.style');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.functions');
+goog.require('goog.string.Unicode');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Plugin to handle enter keys. This subclass normalizes all browsers to use
+ * the given block tag on enter.
+ * @param {goog.dom.TagName} tag The type of tag to add on enter.
+ * @constructor
+ * @extends {goog.editor.plugins.EnterHandler}
+ */
+goog.editor.plugins.TagOnEnterHandler = function(tag) {
+ this.tag = tag;
+
+ goog.editor.plugins.EnterHandler.call(this);
+};
+goog.inherits(goog.editor.plugins.TagOnEnterHandler,
+ goog.editor.plugins.EnterHandler);
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.getTrogClassId = function() {
+ return 'TagOnEnterHandler';
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.getNonCollapsingBlankHtml =
+ function() {
+ if (this.tag == goog.dom.TagName.P) {
+ return '<p> </p>';
+ } else if (this.tag == goog.dom.TagName.DIV) {
+ return '<div><br></div>';
+ }
+ return '<br>';
+};
+
+
+/**
+ * This plugin is active on uneditable fields so it can provide a value for
+ * queryCommandValue calls asking for goog.editor.Command.BLOCKQUOTE.
+ * @return {boolean} True.
+ * @override
+ */
+goog.editor.plugins.TagOnEnterHandler.prototype.activeOnUneditableFields =
+ goog.functions.TRUE;
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.isSupportedCommand = function(
+ command) {
+ return command == goog.editor.Command.DEFAULT_TAG;
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.queryCommandValue = function(
+ command) {
+ return command == goog.editor.Command.DEFAULT_TAG ? this.tag : null;
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.handleBackspaceInternal =
+ function(e, range) {
+ goog.editor.plugins.TagOnEnterHandler.superClass_.handleBackspaceInternal.
+ call(this, e, range);
+
+ if (goog.userAgent.GECKO) {
+ this.markBrToNotBeRemoved_(range, true);
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.processParagraphTagsInternal =
+ function(e, split) {
+ if ((goog.userAgent.OPERA || goog.userAgent.IE) &&
+ this.tag != goog.dom.TagName.P) {
+ this.ensureBlockIeOpera(this.tag);
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.handleDeleteGecko = function(
+ e) {
+ var range = this.getFieldObject().getRange();
+ var container = goog.editor.style.getContainer(
+ range && range.getContainerElement());
+ if (this.getFieldObject().getElement().lastChild == container &&
+ goog.editor.plugins.EnterHandler.isBrElem(container)) {
+ // Don't delete if it's the last node in the field and just has a BR.
+ e.preventDefault();
+ // TODO(user): I think we probably don't need to stopPropagation here
+ e.stopPropagation();
+ } else {
+ // Go ahead with deletion.
+ // Prevent an existing BR immediately following the selection being deleted
+ // from being removed in the keyup stage (as opposed to a BR added by FF
+ // after deletion, which we do remove).
+ this.markBrToNotBeRemoved_(range, false);
+ // Manually delete the selection if it's at a BR.
+ this.deleteBrGecko(e);
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.handleKeyUpInternal = function(
+ e) {
+ if (goog.userAgent.GECKO) {
+ if (e.keyCode == goog.events.KeyCodes.DELETE) {
+ this.removeBrIfNecessary_(false);
+ } else if (e.keyCode == goog.events.KeyCodes.BACKSPACE) {
+ this.removeBrIfNecessary_(true);
+ }
+ } else if ((goog.userAgent.IE || goog.userAgent.OPERA) &&
+ e.keyCode == goog.events.KeyCodes.ENTER) {
+ this.ensureBlockIeOpera(this.tag, true);
+ }
+ // Safari uses DIVs by default.
+};
+
+
+/**
+ * String that matches a single BR tag or NBSP surrounded by non-breaking
+ * whitespace
+ * @type {string}
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.BrOrNbspSurroundedWithWhiteSpace_ =
+ '[\t\n\r ]*(<br[^>]*\/?>| )[\t\n\r ]*';
+
+
+/**
+ * String that matches a single BR tag or NBSP surrounded by non-breaking
+ * whitespace
+ * @type {RegExp}
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.emptyLiRegExp_ = new RegExp('^' +
+ goog.editor.plugins.TagOnEnterHandler.BrOrNbspSurroundedWithWhiteSpace_ +
+ '$');
+
+
+/**
+ * Ensures the current node is wrapped in the tag.
+ * @param {Node} node The node to ensure gets wrapped.
+ * @param {Element} container Element containing the selection.
+ * @return {Element} Element containing the selection, after the wrapping.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.prototype.ensureNodeIsWrappedW3c_ =
+ function(node, container) {
+ if (container == this.getFieldObject().getElement()) {
+ // If the first block-level ancestor of cursor is the field,
+ // don't split the tree. Find all the text from the cursor
+ // to both block-level elements surrounding it (if they exist)
+ // and split the text into two elements.
+ // This is the IE contentEditable behavior.
+
+ // The easy way to do this is to wrap all the text in an element
+ // and then split the element as if the user had hit enter
+ // in the paragraph
+
+ // However, simply wrapping the text into an element creates problems
+ // if the text was already wrapped using some other element such as an
+ // anchor. For example, wrapping the text of
+ // <a href="">Text</a>
+ // would produce
+ // <a href=""><p>Text</p></a>
+ // which is not what we want. What we really want is
+ // <p><a href="">Text</a></p>
+ // So we need to search for an ancestor of position.node to be wrapped.
+ // We do this by iterating up the hierarchy of postiion.node until we've
+ // reached the node that's just under the container.
+ var isChildOfFn = function(child) {
+ return container == child.parentNode; };
+ var nodeToWrap = goog.dom.getAncestor(node, isChildOfFn, true);
+ container = goog.editor.plugins.TagOnEnterHandler.wrapInContainerW3c_(
+ this.tag, {node: nodeToWrap, offset: 0}, container);
+ }
+ return container;
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.handleEnterWebkitInternal =
+ function(e) {
+ if (this.tag == goog.dom.TagName.DIV) {
+ var range = this.getFieldObject().getRange();
+ var container =
+ goog.editor.style.getContainer(range.getContainerElement());
+
+ var position = goog.editor.range.getDeepEndPoint(range, true);
+ container = this.ensureNodeIsWrappedW3c_(position.node, container);
+ goog.dom.Range.createCaret(position.node, position.offset).select();
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.TagOnEnterHandler.prototype.
+ handleEnterAtCursorGeckoInternal = function(e, wasCollapsed, range) {
+ // We use this because there are a few cases where FF default
+ // implementation doesn't follow IE's:
+ // -Inserts BRs into empty elements instead of NBSP which has nasty
+ // side effects w/ making/deleting selections
+ // -Hitting enter when your cursor is in the field itself. IE will
+ // create two elements. FF just inserts a BR.
+ // -Hitting enter inside an empty list-item doesn't create a block
+ // tag. It just splits the list and puts your cursor in the middle.
+ var li = null;
+ if (wasCollapsed) {
+ // Only break out of lists for collapsed selections.
+ li = goog.dom.getAncestorByTagNameAndClass(
+ range && range.getContainerElement(), goog.dom.TagName.LI);
+ }
+ var isEmptyLi = (li &&
+ li.innerHTML.match(
+ goog.editor.plugins.TagOnEnterHandler.emptyLiRegExp_));
+ var elementAfterCursor = isEmptyLi ?
+ this.breakOutOfEmptyListItemGecko_(li) :
+ this.handleRegularEnterGecko_();
+
+ // Move the cursor in front of "nodeAfterCursor", and make sure it
+ // is visible
+ this.scrollCursorIntoViewGecko_(elementAfterCursor);
+
+ // Fix for http://b/1991234 :
+ if (goog.editor.plugins.EnterHandler.isBrElem(elementAfterCursor)) {
+ // The first element in the new line is a line with just a BR and maybe some
+ // whitespace.
+ // Calling normalize() is needed because there might be empty text nodes
+ // before BR and empty text nodes cause the cursor position bug in Firefox.
+ // See http://b/5220858
+ elementAfterCursor.normalize();
+ var br = elementAfterCursor.getElementsByTagName(goog.dom.TagName.BR)[0];
+ if (br.previousSibling &&
+ br.previousSibling.nodeType == goog.dom.NodeType.TEXT) {
+ // If there is some whitespace before the BR, don't put the selection on
+ // the BR, put it in the text node that's there, otherwise when you type
+ // it will create adjacent text nodes.
+ elementAfterCursor = br.previousSibling;
+ }
+ }
+
+ goog.editor.range.selectNodeStart(elementAfterCursor);
+
+ e.preventDefault();
+ // TODO(user): I think we probably don't need to stopPropagation here
+ e.stopPropagation();
+};
+
+
+/**
+ * If The cursor is in an empty LI then break out of the list like in IE
+ * @param {Node} li LI to break out of.
+ * @return {!Element} Element to put the cursor after.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.prototype.breakOutOfEmptyListItemGecko_ =
+ function(li) {
+ // Do this as follows:
+ // 1. <ul>...<li> </li>...</ul>
+ // 2. <ul id='foo1'>...<li id='foo2'> </li>...</ul>
+ // 3. <ul id='foo1'>...</ul><p id='foo3'> </p><ul id='foo2'>...</ul>
+ // 4. <ul>...</ul><p> </p><ul>...</ul>
+ //
+ // There are a couple caveats to the above. If the UL is contained in
+ // a list, then the new node inserted is an LI, not a P.
+ // For an OL, it's all the same, except the tagname of course.
+ // Finally, it's possible that with the LI at the beginning or the end
+ // of the list that we'll end up with an empty list. So we special case
+ // those cases.
+
+ var listNode = li.parentNode;
+ var grandparent = listNode.parentNode;
+ var inSubList = grandparent.tagName == goog.dom.TagName.OL ||
+ grandparent.tagName == goog.dom.TagName.UL;
+
+ // TODO(robbyw): Should we apply the list or list item styles to the new node?
+ var newNode = goog.dom.getDomHelper(li).createElement(
+ inSubList ? goog.dom.TagName.LI : this.tag);
+
+ if (!li.previousSibling) {
+ goog.dom.insertSiblingBefore(newNode, listNode);
+ } else {
+ if (li.nextSibling) {
+ var listClone = listNode.cloneNode(false);
+ while (li.nextSibling) {
+ listClone.appendChild(li.nextSibling);
+ }
+ goog.dom.insertSiblingAfter(listClone, listNode);
+ }
+ goog.dom.insertSiblingAfter(newNode, listNode);
+ }
+ if (goog.editor.node.isEmpty(listNode)) {
+ goog.dom.removeNode(listNode);
+ }
+ goog.dom.removeNode(li);
+ newNode.innerHTML = ' ';
+
+ return newNode;
+};
+
+
+/**
+ * Wrap the text indicated by "position" in an HTML container of type
+ * "nodeName".
+ * @param {string} nodeName Type of container, e.g. "p" (paragraph).
+ * @param {Object} position The W3C cursor position object
+ * (from getCursorPositionW3c).
+ * @param {Node} container The field containing position.
+ * @return {!Element} The container element that holds the contents from
+ * position.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.wrapInContainerW3c_ = function(nodeName,
+ position, container) {
+ var start = position.node;
+ while (start.previousSibling &&
+ !goog.editor.style.isContainer(start.previousSibling)) {
+ start = start.previousSibling;
+ }
+
+ var end = position.node;
+ while (end.nextSibling &&
+ !goog.editor.style.isContainer(end.nextSibling)) {
+ end = end.nextSibling;
+ }
+
+ var para = container.ownerDocument.createElement(nodeName);
+ while (start != end) {
+ var newStart = start.nextSibling;
+ goog.dom.appendChild(para, start);
+ start = newStart;
+ }
+ var nextSibling = end.nextSibling;
+ goog.dom.appendChild(para, end);
+ container.insertBefore(para, nextSibling);
+
+ return para;
+};
+
+
+/**
+ * When we delete an element, FF inserts a BR. We want to strip that
+ * BR after the fact, but in the case where your cursor is at a character
+ * right before a BR and you delete that character, we don't want to
+ * strip it. So we detect this case on keydown and mark the BR as not needing
+ * removal.
+ * @param {goog.dom.AbstractRange} range The closure range object.
+ * @param {boolean} isBackspace Whether this is handling the backspace key.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.prototype.markBrToNotBeRemoved_ =
+ function(range, isBackspace) {
+ var focusNode = range.getFocusNode();
+ var focusOffset = range.getFocusOffset();
+ var newEndOffset = isBackspace ? focusOffset : focusOffset + 1;
+
+ if (goog.editor.node.getLength(focusNode) == newEndOffset) {
+ var sibling = focusNode.nextSibling;
+ if (sibling && sibling.tagName == goog.dom.TagName.BR) {
+ this.brToKeep_ = sibling;
+ }
+ }
+};
+
+
+/**
+ * If we hit delete/backspace to merge elements, FF inserts a BR.
+ * We want to strip that BR. In markBrToNotBeRemoved, we detect if
+ * there was already a BR there before the delete/backspace so that
+ * we don't accidentally remove a user-inserted BR.
+ * @param {boolean} isBackSpace Whether this is handling the backspace key.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.prototype.removeBrIfNecessary_ = function(
+ isBackSpace) {
+ var range = this.getFieldObject().getRange();
+ var focusNode = range.getFocusNode();
+ var focusOffset = range.getFocusOffset();
+
+ var sibling;
+ if (isBackSpace && focusNode.data == '') {
+ // nasty hack. sometimes firefox will backspace a paragraph and put
+ // the cursor before the BR. when it does this, the focusNode is
+ // an empty textnode.
+ sibling = focusNode.nextSibling;
+ } else if (isBackSpace && focusOffset == 0) {
+ var node = focusNode;
+ while (node && !node.previousSibling &&
+ node.parentNode != this.getFieldObject().getElement()) {
+ node = node.parentNode;
+ }
+ sibling = node.previousSibling;
+ } else if (focusNode.length == focusOffset) {
+ sibling = focusNode.nextSibling;
+ }
+
+ if (!sibling || sibling.tagName != goog.dom.TagName.BR ||
+ this.brToKeep_ == sibling) {
+ return;
+ }
+
+ goog.dom.removeNode(sibling);
+ if (focusNode.nodeType == goog.dom.NodeType.TEXT) {
+ // Sometimes firefox inserts extra whitespace. Do our best to deal.
+ // This is buggy though.
+ focusNode.data =
+ goog.editor.plugins.TagOnEnterHandler.trimTabsAndLineBreaks_(
+ focusNode.data);
+ // When we strip whitespace, make sure that our cursor is still at
+ // the end of the textnode.
+ goog.dom.Range.createCaret(focusNode,
+ Math.min(focusOffset, focusNode.length)).select();
+ }
+};
+
+
+/**
+ * Trim the tabs and line breaks from a string.
+ * @param {string} string String to trim.
+ * @return {string} Trimmed string.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.trimTabsAndLineBreaks_ = function(
+ string) {
+ return string.replace(/^[\t\n\r]|[\t\n\r]$/g, '');
+};
+
+
+/**
+ * Called in response to a normal enter keystroke. It has the action of
+ * splitting elements.
+ * @return {Element} The node that the cursor should be before.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.prototype.handleRegularEnterGecko_ =
+ function() {
+ var range = this.getFieldObject().getRange();
+ var container =
+ goog.editor.style.getContainer(range.getContainerElement());
+ var newNode;
+ if (goog.editor.plugins.EnterHandler.isBrElem(container)) {
+ if (container.tagName == goog.dom.TagName.BODY) {
+ // If the field contains only a single BR, this code ensures we don't
+ // try to clone the body tag.
+ container = this.ensureNodeIsWrappedW3c_(
+ container.getElementsByTagName(goog.dom.TagName.BR)[0],
+ container);
+ }
+
+ newNode = container.cloneNode(true);
+ goog.dom.insertSiblingAfter(newNode, container);
+ } else {
+ if (!container.firstChild) {
+ container.innerHTML = ' ';
+ }
+
+ var position = goog.editor.range.getDeepEndPoint(range, true);
+ container = this.ensureNodeIsWrappedW3c_(position.node, container);
+
+ newNode = goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_(
+ position.node, position.offset, container);
+
+ // If the left half and right half of the splitted node are anchors then
+ // that means the user pressed enter while the caret was inside
+ // an anchor tag and split it. The left half is the first anchor
+ // found while traversing the right branch of container. The right half
+ // is the first anchor found while traversing the left branch of newNode.
+ var leftAnchor =
+ goog.editor.plugins.TagOnEnterHandler.findAnchorInTraversal_(
+ container);
+ var rightAnchor =
+ goog.editor.plugins.TagOnEnterHandler.findAnchorInTraversal_(
+ newNode, true);
+ if (leftAnchor && rightAnchor &&
+ leftAnchor.tagName == goog.dom.TagName.A &&
+ rightAnchor.tagName == goog.dom.TagName.A) {
+ // If the original anchor (left anchor) is now empty, that means
+ // the user pressed [Enter] at the beginning of the anchor,
+ // in which case we we
+ // want to replace that anchor with its child nodes
+ // Otherwise, we take the second half of the splitted text and break
+ // it out of the anchor.
+ var anchorToRemove = goog.editor.node.isEmpty(leftAnchor, false) ?
+ leftAnchor : rightAnchor;
+ goog.dom.flattenElement(/** @type {!Element} */ (anchorToRemove));
+ }
+ }
+ return /** @type {!Element} */ (newNode);
+};
+
+
+/**
+ * Scroll the cursor into view, resulting from splitting the paragraph/adding
+ * a br. It behaves differently than scrollIntoView
+ * @param {Element} element The element immediately following the cursor. Will
+ * be used to determine how to scroll in order to make the cursor visible.
+ * CANNOT be a BR, as they do not have offsetHeight/offsetTop.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.prototype.scrollCursorIntoViewGecko_ =
+ function(element) {
+ if (!this.getFieldObject().isFixedHeight()) {
+ return; // Only need to scroll fixed height fields.
+ }
+
+ var field = this.getFieldObject().getElement();
+
+ // Get the y position of the element we want to scroll to
+ var elementY = goog.style.getPageOffsetTop(element);
+
+ // Determine the height of that element, since we want the bottom of the
+ // element to be in view.
+ var bottomOfNode = elementY + element.offsetHeight;
+
+ var dom = this.getFieldDomHelper();
+ var win = this.getFieldDomHelper().getWindow();
+ var scrollY = dom.getDocumentScroll().y;
+ var viewportHeight = goog.dom.getViewportSize(win).height;
+
+ // If the botom of the element is outside the viewport, move it into view
+ if (bottomOfNode > viewportHeight + scrollY) {
+ // In standards mode, use the html element and not the body
+ if (field.tagName == goog.dom.TagName.BODY &&
+ goog.editor.node.isStandardsMode(field)) {
+ field = field.parentNode;
+ }
+ field.scrollTop = bottomOfNode - viewportHeight;
+ }
+};
+
+
+/**
+ * Splits the DOM tree around the given node and returns the node
+ * containing the second half of the tree. The first half of the tree
+ * is modified, but not removed from the DOM.
+ * @param {Node} positionNode Node to split at.
+ * @param {number} positionOffset Offset into positionNode to split at. If
+ * positionNode is a text node, this offset is an offset in to the text
+ * content of that node. Otherwise, positionOffset is an offset in to
+ * the childNodes array. All elements with child index of positionOffset
+ * or greater will be moved to the second half. If positionNode is an
+ * empty element, the dom will be split at that element, with positionNode
+ * ending up in the second half. positionOffset must be 0 in this case.
+ * @param {Node=} opt_root Node at which to stop splitting the dom (the root
+ * is also split).
+ * @return {!Node} The node containing the second half of the tree.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.splitDom_ = function(
+ positionNode, positionOffset, opt_root) {
+ if (!opt_root) opt_root = positionNode.ownerDocument.body;
+
+ // Split the node.
+ var textSplit = positionNode.nodeType == goog.dom.NodeType.TEXT;
+ var secondHalfOfSplitNode;
+ if (textSplit) {
+ if (goog.userAgent.IE &&
+ positionOffset == positionNode.nodeValue.length) {
+ // Since splitText fails in IE at the end of a node, we split it manually.
+ secondHalfOfSplitNode = goog.dom.getDomHelper(positionNode).
+ createTextNode('');
+ goog.dom.insertSiblingAfter(secondHalfOfSplitNode, positionNode);
+ } else {
+ secondHalfOfSplitNode = positionNode.splitText(positionOffset);
+ }
+ } else {
+ // Here we ensure positionNode is the last node in the first half of the
+ // resulting tree.
+ if (positionOffset) {
+ // Use offset as an index in to childNodes.
+ positionNode = positionNode.childNodes[positionOffset - 1];
+ } else {
+ // In this case, positionNode would be the last node in the first half
+ // of the tree, but we actually want to move it to the second half.
+ // Therefore we set secondHalfOfSplitNode to the same node.
+ positionNode = secondHalfOfSplitNode = positionNode.firstChild ||
+ positionNode;
+ }
+ }
+
+ // Create second half of the tree.
+ var secondHalf = goog.editor.node.splitDomTreeAt(
+ positionNode, secondHalfOfSplitNode, opt_root);
+
+ if (textSplit) {
+ // Join secondHalfOfSplitNode and its right text siblings together and
+ // then replace leading NonNbspWhiteSpace with a Nbsp. If
+ // secondHalfOfSplitNode has a right sibling that isn't a text node,
+ // then we can leave secondHalfOfSplitNode empty.
+ secondHalfOfSplitNode =
+ goog.editor.plugins.TagOnEnterHandler.joinTextNodes_(
+ secondHalfOfSplitNode, true);
+ goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
+ secondHalfOfSplitNode, true, !!secondHalfOfSplitNode.nextSibling);
+
+ // Join positionNode and its left text siblings together and then replace
+ // trailing NonNbspWhiteSpace with a Nbsp.
+ var firstHalf = goog.editor.plugins.TagOnEnterHandler.joinTextNodes_(
+ positionNode, false);
+ goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
+ firstHalf, false, false);
+ }
+
+ return secondHalf;
+};
+
+
+/**
+ * Splits the DOM tree around the given node and returns the node containing
+ * second half of the tree, which is appended after the old node. The first
+ * half of the tree is modified, but not removed from the DOM.
+ * @param {Node} positionNode Node to split at.
+ * @param {number} positionOffset Offset into positionNode to split at. If
+ * positionNode is a text node, this offset is an offset in to the text
+ * content of that node. Otherwise, positionOffset is an offset in to
+ * the childNodes array. All elements with child index of positionOffset
+ * or greater will be moved to the second half. If positionNode is an
+ * empty element, the dom will be split at that element, with positionNode
+ * ending up in the second half. positionOffset must be 0 in this case.
+ * @param {Node} node Node to split.
+ * @return {!Node} The node containing the second half of the tree.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_ = function(
+ positionNode, positionOffset, node) {
+ var newNode = goog.editor.plugins.TagOnEnterHandler.splitDom_(
+ positionNode, positionOffset, node);
+ goog.dom.insertSiblingAfter(newNode, node);
+ return newNode;
+};
+
+
+/**
+ * Joins node and its adjacent text nodes together.
+ * @param {Node} node The node to start joining.
+ * @param {boolean} moveForward Determines whether to join left siblings (false)
+ * or right siblings (true).
+ * @return {Node} The joined text node.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.joinTextNodes_ = function(node,
+ moveForward) {
+ if (node && node.nodeName == '#text') {
+ var nextNodeFn = moveForward ? 'nextSibling' : 'previousSibling';
+ var prevNodeFn = moveForward ? 'previousSibling' : 'nextSibling';
+ var nodeValues = [node.nodeValue];
+ while (node[nextNodeFn] &&
+ node[nextNodeFn].nodeType == goog.dom.NodeType.TEXT) {
+ node = node[nextNodeFn];
+ nodeValues.push(node.nodeValue);
+ goog.dom.removeNode(node[prevNodeFn]);
+ }
+ if (!moveForward) {
+ nodeValues.reverse();
+ }
+ node.nodeValue = nodeValues.join('');
+ }
+ return node;
+};
+
+
+/**
+ * Replaces leading or trailing spaces of a text node to a single Nbsp.
+ * @param {Node} textNode The text node to search and replace white spaces.
+ * @param {boolean} fromStart Set to true to replace leading spaces, false to
+ * replace trailing spaces.
+ * @param {boolean} isLeaveEmpty Set to true to leave the node empty if the
+ * text node was empty in the first place, otherwise put a Nbsp into the
+ * text node.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_ = function(
+ textNode, fromStart, isLeaveEmpty) {
+ var regExp = fromStart ? /^[ \t\r\n]+/ : /[ \t\r\n]+$/;
+ textNode.nodeValue = textNode.nodeValue.replace(regExp,
+ goog.string.Unicode.NBSP);
+
+ if (!isLeaveEmpty && textNode.nodeValue == '') {
+ textNode.nodeValue = goog.string.Unicode.NBSP;
+ }
+};
+
+
+/**
+ * Finds the first A element in a traversal from the input node. The input
+ * node itself is not included in the search.
+ * @param {Node} node The node to start searching from.
+ * @param {boolean=} opt_useFirstChild Whether to traverse along the first child
+ * (true) or last child (false).
+ * @return {Node} The first anchor node found in the search, or null if none
+ * was found.
+ * @private
+ */
+goog.editor.plugins.TagOnEnterHandler.findAnchorInTraversal_ = function(node,
+ opt_useFirstChild) {
+ while ((node = opt_useFirstChild ? node.firstChild : node.lastChild) &&
+ node.tagName != goog.dom.TagName.A) {
+ // Do nothing - advancement is handled in the condition.
+ }
+ return node;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/undoredo.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/undoredo.js b/externs/GCL/externs/goog/editor/plugins/undoredo.js
new file mode 100644
index 0000000..d273a4c
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/undoredo.js
@@ -0,0 +1,1016 @@
+// 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 Code for handling edit history (undo/redo).
+ *
+ */
+
+
+goog.provide('goog.editor.plugins.UndoRedo');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeOffset');
+goog.require('goog.dom.Range');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Field');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.node');
+goog.require('goog.editor.plugins.UndoRedoManager');
+goog.require('goog.editor.plugins.UndoRedoState');
+goog.require('goog.events');
+goog.require('goog.events.EventHandler');
+goog.require('goog.log');
+goog.require('goog.object');
+
+
+
+/**
+ * Encapsulates undo/redo logic using a custom undo stack (i.e. not browser
+ * built-in). Browser built-in undo stacks are too flaky (e.g. IE's gets
+ * clobbered on DOM modifications). Also, this allows interleaving non-editing
+ * commands into the undo stack via the UndoRedoManager.
+ *
+ * @param {goog.editor.plugins.UndoRedoManager=} opt_manager An undo redo
+ * manager to be used by this plugin. If none is provided one is created.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ */
+goog.editor.plugins.UndoRedo = function(opt_manager) {
+ goog.editor.Plugin.call(this);
+
+ this.setUndoRedoManager(opt_manager ||
+ new goog.editor.plugins.UndoRedoManager());
+
+ // Map of goog.editor.Field hashcode to goog.events.EventHandler
+ this.eventHandlers_ = {};
+
+ this.currentStates_ = {};
+
+ /**
+ * @type {?string}
+ * @private
+ */
+ this.initialFieldChange_ = null;
+
+ /**
+ * A copy of {@code goog.editor.plugins.UndoRedo.restoreState} bound to this,
+ * used by undo-redo state objects to restore the state of an editable field.
+ * @type {Function}
+ * @see goog.editor.plugins.UndoRedo#restoreState
+ * @private
+ */
+ this.boundRestoreState_ = goog.bind(this.restoreState, this);
+};
+goog.inherits(goog.editor.plugins.UndoRedo, goog.editor.Plugin);
+
+
+/**
+ * The logger for this class.
+ * @type {goog.log.Logger}
+ * @protected
+ * @override
+ */
+goog.editor.plugins.UndoRedo.prototype.logger =
+ goog.log.getLogger('goog.editor.plugins.UndoRedo');
+
+
+/**
+ * The {@code UndoState_} whose change is in progress, null if an undo or redo
+ * is not in progress.
+ *
+ * @type {goog.editor.plugins.UndoRedo.UndoState_?}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.inProgressUndo_ = null;
+
+
+/**
+ * The undo-redo stack manager used by this plugin.
+ * @type {goog.editor.plugins.UndoRedoManager}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.undoManager_;
+
+
+/**
+ * The key for the event listener handling state change events from the
+ * undo-redo manager.
+ * @type {goog.events.Key}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.managerStateChangeKey_;
+
+
+/**
+ * Commands implemented by this plugin.
+ * @enum {string}
+ */
+goog.editor.plugins.UndoRedo.COMMAND = {
+ UNDO: '+undo',
+ REDO: '+redo'
+};
+
+
+/**
+ * Inverse map of execCommand strings to
+ * {@link goog.editor.plugins.UndoRedo.COMMAND} constants. Used to determine
+ * whether a string corresponds to a command this plugin handles in O(1) time.
+ * @type {Object}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.SUPPORTED_COMMANDS_ =
+ goog.object.transpose(goog.editor.plugins.UndoRedo.COMMAND);
+
+
+/**
+ * Set the max undo stack depth (not the real memory usage).
+ * @param {number} depth Depth of the stack.
+ */
+goog.editor.plugins.UndoRedo.prototype.setMaxUndoDepth = function(depth) {
+ this.undoManager_.setMaxUndoDepth(depth);
+};
+
+
+/**
+ * Set the undo-redo manager used by this plugin. Any state on a previous
+ * undo-redo manager is lost.
+ * @param {goog.editor.plugins.UndoRedoManager} manager The undo-redo manager.
+ */
+goog.editor.plugins.UndoRedo.prototype.setUndoRedoManager = function(manager) {
+ if (this.managerStateChangeKey_) {
+ goog.events.unlistenByKey(this.managerStateChangeKey_);
+ }
+
+ this.undoManager_ = manager;
+ this.managerStateChangeKey_ =
+ goog.events.listen(this.undoManager_,
+ goog.editor.plugins.UndoRedoManager.EventType.STATE_CHANGE,
+ this.dispatchCommandValueChange_,
+ false,
+ this);
+};
+
+
+/**
+ * Whether the string corresponds to a command this plugin handles.
+ * @param {string} command Command string to check.
+ * @return {boolean} Whether the string corresponds to a command
+ * this plugin handles.
+ * @override
+ */
+goog.editor.plugins.UndoRedo.prototype.isSupportedCommand = function(command) {
+ return command in goog.editor.plugins.UndoRedo.SUPPORTED_COMMANDS_;
+};
+
+
+/**
+ * Unregisters and disables the fieldObject with this plugin. Thie does *not*
+ * clobber the undo stack for the fieldObject though.
+ * TODO(user): For the multifield version, we really should add a way to
+ * ignore undo actions on field's that have been made uneditable.
+ * This is probably as simple as skipping over entries in the undo stack
+ * that have a hashcode of an uneditable field.
+ * @param {goog.editor.Field} fieldObject The field to register with the plugin.
+ * @override
+ */
+goog.editor.plugins.UndoRedo.prototype.unregisterFieldObject = function(
+ fieldObject) {
+ this.disable(fieldObject);
+ this.setFieldObject(null);
+};
+
+
+/**
+ * This is so subclasses can deal with multifield undo-redo.
+ * @return {goog.editor.Field} The active field object for this field. This is
+ * the one registered field object for the single-plugin case and the
+ * focused field for the multi-field plugin case.
+ */
+goog.editor.plugins.UndoRedo.prototype.getCurrentFieldObject = function() {
+ return this.getFieldObject();
+};
+
+
+/**
+ * This is so subclasses can deal with multifield undo-redo.
+ * @param {string} fieldHashCode The Field's hashcode.
+ * @return {goog.editor.Field} The field object with the hashcode.
+ */
+goog.editor.plugins.UndoRedo.prototype.getFieldObjectForHash = function(
+ fieldHashCode) {
+ // With single field undoredo, there's only one Field involved.
+ return this.getFieldObject();
+};
+
+
+/**
+ * This is so subclasses can deal with multifield undo-redo.
+ * @return {goog.editor.Field} Target for COMMAND_VALUE_CHANGE events.
+ */
+goog.editor.plugins.UndoRedo.prototype.getCurrentEventTarget = function() {
+ return this.getFieldObject();
+};
+
+
+/** @override */
+goog.editor.plugins.UndoRedo.prototype.enable = function(fieldObject) {
+ if (this.isEnabled(fieldObject)) {
+ return;
+ }
+
+ // Don't want pending delayed changes from when undo-redo was disabled
+ // firing after undo-redo is enabled since they might cause undo-redo stack
+ // updates.
+ fieldObject.clearDelayedChange();
+
+ var eventHandler = new goog.events.EventHandler(this);
+
+ // TODO(user): From ojan during a code review:
+ // The beforechange handler is meant to be there so you can grab the cursor
+ // position *before* the change is made as that's where you want the cursor to
+ // be after an undo.
+ //
+ // It kinda looks like updateCurrentState_ doesn't do that correctly right
+ // now, but it really should be fixed to do so. The cursor position stored in
+ // the state should be the cursor position before any changes are made, not
+ // the cursor position when the change finishes.
+ //
+ // It also seems like the if check below is just a bad one. We should do this
+ // for browsers that use mutation events as well even though the beforechange
+ // happens too late...maybe not. I don't know about this.
+ if (!goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
+ // We don't listen to beforechange in mutation-event browsers because
+ // there we fire beforechange, then syncronously file change. The point
+ // of before change is to capture before the user has changed anything.
+ eventHandler.listen(fieldObject,
+ goog.editor.Field.EventType.BEFORECHANGE, this.handleBeforeChange_);
+ }
+ eventHandler.listen(fieldObject,
+ goog.editor.Field.EventType.DELAYEDCHANGE, this.handleDelayedChange_);
+ eventHandler.listen(fieldObject, goog.editor.Field.EventType.BLUR,
+ this.handleBlur_);
+
+ this.eventHandlers_[fieldObject.getHashCode()] = eventHandler;
+
+ // We want to capture the initial state of a Trogedit field before any
+ // editing has happened. This is necessary so that we can undo the first
+ // change to a field, even if we don't handle beforeChange.
+ this.updateCurrentState_(fieldObject);
+};
+
+
+/** @override */
+goog.editor.plugins.UndoRedo.prototype.disable = function(fieldObject) {
+ // Process any pending changes so we don't lose any undo-redo states that we
+ // want prior to disabling undo-redo.
+ fieldObject.clearDelayedChange();
+
+ var eventHandler = this.eventHandlers_[fieldObject.getHashCode()];
+ if (eventHandler) {
+ eventHandler.dispose();
+ delete this.eventHandlers_[fieldObject.getHashCode()];
+ }
+
+ // We delete the current state of the field on disable. When we re-enable
+ // the state will be re-fetched. In most cases the content will be the same,
+ // but this allows us to pick up changes while not editable. That way, when
+ // undoing after starting an editable session, you can always undo to the
+ // state you started in. Given this sequence of events:
+ // Make editable
+ // Type 'anakin'
+ // Make not editable
+ // Set HTML to be 'padme'
+ // Make editable
+ // Type 'dark side'
+ // Undo
+ // Without re-snapshoting current state on enable, the undo would go from
+ // 'dark-side' -> 'anakin', rather than 'dark-side' -> 'padme'. You couldn't
+ // undo the field to the state that existed immediately after it was made
+ // editable for the second time.
+ if (this.currentStates_[fieldObject.getHashCode()]) {
+ delete this.currentStates_[fieldObject.getHashCode()];
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.UndoRedo.prototype.isEnabled = function(fieldObject) {
+ // All enabled plugins have a eventHandler so reuse that map rather than
+ // storing additional enabled state.
+ return !!this.eventHandlers_[fieldObject.getHashCode()];
+};
+
+
+/** @override */
+goog.editor.plugins.UndoRedo.prototype.disposeInternal = function() {
+ goog.editor.plugins.UndoRedo.superClass_.disposeInternal.call(this);
+
+ for (var hashcode in this.eventHandlers_) {
+ this.eventHandlers_[hashcode].dispose();
+ delete this.eventHandlers_[hashcode];
+ }
+ this.setFieldObject(null);
+
+ if (this.undoManager_) {
+ this.undoManager_.dispose();
+ delete this.undoManager_;
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.UndoRedo.prototype.getTrogClassId = function() {
+ return 'UndoRedo';
+};
+
+
+/** @override */
+goog.editor.plugins.UndoRedo.prototype.execCommand = function(command,
+ var_args) {
+ if (command == goog.editor.plugins.UndoRedo.COMMAND.UNDO) {
+ this.undoManager_.undo();
+ } else if (command == goog.editor.plugins.UndoRedo.COMMAND.REDO) {
+ this.undoManager_.redo();
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.UndoRedo.prototype.queryCommandValue = function(command) {
+ var state = null;
+ if (command == goog.editor.plugins.UndoRedo.COMMAND.UNDO) {
+ state = this.undoManager_.hasUndoState();
+ } else if (command == goog.editor.plugins.UndoRedo.COMMAND.REDO) {
+ state = this.undoManager_.hasRedoState();
+ }
+ return state;
+};
+
+
+/**
+ * Dispatches the COMMAND_VALUE_CHANGE event on the editable field or the field
+ * manager, as appropriate.
+ * Note: Really, people using multi field mode should be listening directly
+ * to the undo-redo manager for events.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.dispatchCommandValueChange_ =
+ function() {
+ var eventTarget = this.getCurrentEventTarget();
+ eventTarget.dispatchEvent({
+ type: goog.editor.Field.EventType.COMMAND_VALUE_CHANGE,
+ commands: [goog.editor.plugins.UndoRedo.COMMAND.REDO,
+ goog.editor.plugins.UndoRedo.COMMAND.UNDO]});
+};
+
+
+/**
+ * Restores the state of the editable field.
+ * @param {goog.editor.plugins.UndoRedo.UndoState_} state The state initiating
+ * the restore.
+ * @param {string} content The content to restore.
+ * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
+ * The cursor position within the content.
+ */
+goog.editor.plugins.UndoRedo.prototype.restoreState = function(
+ state, content, cursorPosition) {
+ // Fire any pending changes to get the current field state up to date and
+ // then stop listening to changes while doing the undo/redo.
+ var fieldObj = this.getFieldObjectForHash(state.fieldHashCode);
+ if (!fieldObj) {
+ return;
+ }
+
+ // Fires any pending changes, and stops the change events. Still want to
+ // dispatch before change, as a change is being made and the change event
+ // will be manually dispatched below after the new content has been restored
+ // (also restarting change events).
+ fieldObj.stopChangeEvents(true, true);
+
+ // To prevent the situation where we stop change events and then an exception
+ // happens before we can restart change events, the following code must be in
+ // a try-finally block.
+ try {
+ fieldObj.dispatchBeforeChange();
+
+ // Restore the state
+ fieldObj.execCommand(goog.editor.Command.CLEAR_LOREM, true);
+
+ // We specifically set the raw innerHTML of the field here as that's what
+ // we get from the field when we save an undo/redo state. There's
+ // no need to clean/unclean the contents in either direction.
+ goog.editor.node.replaceInnerHtml(fieldObj.getElement(), content);
+
+ if (cursorPosition) {
+ cursorPosition.select();
+ }
+
+ var previousFieldObject = this.getCurrentFieldObject();
+ fieldObj.focus();
+
+ // Apps that integrate their undo-redo with Trogedit may be
+ // in a state where there is no previous field object (no field focused at
+ // the time of undo), so check for existence first.
+ if (previousFieldObject &&
+ previousFieldObject.getHashCode() != state.fieldHashCode) {
+ previousFieldObject.execCommand(goog.editor.Command.UPDATE_LOREM);
+ }
+
+ // We need to update currentState_ to reflect the change.
+ this.currentStates_[state.fieldHashCode].setUndoState(
+ content, cursorPosition);
+ } catch (e) {
+ goog.log.error(this.logger, 'Error while restoring undo state', e);
+ } finally {
+ // Clear the delayed change event, set flag so we know not to act on it.
+ this.inProgressUndo_ = state;
+ // Notify the editor that we've changed (fire autosave).
+ // Note that this starts up change events again, so we don't have to
+ // manually do so even though we stopped change events above.
+ fieldObj.dispatchChange();
+ fieldObj.dispatchSelectionChangeEvent();
+ }
+};
+
+
+/**
+ * @override
+ */
+goog.editor.plugins.UndoRedo.prototype.handleKeyboardShortcut = function(e, key,
+ isModifierPressed) {
+ if (isModifierPressed) {
+ var command;
+ if (key == 'z') {
+ command = e.shiftKey ? goog.editor.plugins.UndoRedo.COMMAND.REDO :
+ goog.editor.plugins.UndoRedo.COMMAND.UNDO;
+ } else if (key == 'y') {
+ command = goog.editor.plugins.UndoRedo.COMMAND.REDO;
+ }
+
+ if (command) {
+ // In the case where Trogedit shares its undo redo stack with another
+ // application it's possible that an undo or redo will not be for an
+ // goog.editor.Field. In this case we don't want to go through the
+ // goog.editor.Field execCommand flow which stops and restarts events on
+ // the current field. Only Trogedit UndoState's have a fieldHashCode so
+ // use that to distinguish between Trogedit and other states.
+ var state = command == goog.editor.plugins.UndoRedo.COMMAND.UNDO ?
+ this.undoManager_.undoPeek() : this.undoManager_.redoPeek();
+ if (state && state.fieldHashCode) {
+ this.getCurrentFieldObject().execCommand(command);
+ } else {
+ this.execCommand(command);
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+};
+
+
+/**
+ * Clear the undo/redo stack.
+ */
+goog.editor.plugins.UndoRedo.prototype.clearHistory = function() {
+ // Fire all pending change events, so that they don't come back
+ // asynchronously to fill the queue.
+ this.getFieldObject().stopChangeEvents(true, true);
+ this.undoManager_.clearHistory();
+ this.getFieldObject().startChangeEvents();
+};
+
+
+/**
+ * Refreshes the current state of the editable field as maintained by undo-redo,
+ * without adding any undo-redo states to the stack.
+ * @param {goog.editor.Field} fieldObject The editable field.
+ */
+goog.editor.plugins.UndoRedo.prototype.refreshCurrentState = function(
+ fieldObject) {
+ if (this.isEnabled(fieldObject)) {
+ if (this.currentStates_[fieldObject.getHashCode()]) {
+ delete this.currentStates_[fieldObject.getHashCode()];
+ }
+ this.updateCurrentState_(fieldObject);
+ }
+};
+
+
+/**
+ * Before the field changes, we want to save the state.
+ * @param {goog.events.Event} e The event.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.handleBeforeChange_ = function(e) {
+ if (this.inProgressUndo_) {
+ // We are in between a previous undo and its delayed change event.
+ // Continuing here clobbers the redo stack.
+ // This does mean that if you are trying to undo/redo really quickly, it
+ // will be gated by the speed of delayed change events.
+ return;
+ }
+
+ var fieldObj = /** @type {goog.editor.Field} */ (e.target);
+ var fieldHashCode = fieldObj.getHashCode();
+
+ if (this.initialFieldChange_ != fieldHashCode) {
+ this.initialFieldChange_ = fieldHashCode;
+ this.updateCurrentState_(fieldObj);
+ }
+};
+
+
+/**
+ * After some idle time, we want to save the state.
+ * @param {goog.events.Event} e The event.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.handleDelayedChange_ = function(e) {
+ // This was undo making a change, don't add it BACK into the history
+ if (this.inProgressUndo_) {
+ // Must clear this.inProgressUndo_ before dispatching event because the
+ // dispatch can cause another, queued undo that should be allowed to go
+ // through.
+ var state = this.inProgressUndo_;
+ this.inProgressUndo_ = null;
+ state.dispatchEvent(goog.editor.plugins.UndoRedoState.ACTION_COMPLETED);
+ return;
+ }
+
+ this.updateCurrentState_(/** @type {goog.editor.Field} */ (e.target));
+};
+
+
+/**
+ * When the user blurs away, we need to save the state on that field.
+ * @param {goog.events.Event} e The event.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.handleBlur_ = function(e) {
+ var fieldObj = /** @type {goog.editor.Field} */ (e.target);
+ if (fieldObj) {
+ fieldObj.clearDelayedChange();
+ }
+};
+
+
+/**
+ * Returns the goog.editor.plugins.UndoRedo.CursorPosition_ for the current
+ * selection in the given Field.
+ * @param {goog.editor.Field} fieldObj The field object.
+ * @return {goog.editor.plugins.UndoRedo.CursorPosition_} The CursorPosition_ or
+ * null if there is no valid selection.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.getCursorPosition_ = function(fieldObj) {
+ var cursorPos = new goog.editor.plugins.UndoRedo.CursorPosition_(fieldObj);
+ if (!cursorPos.isValid()) {
+ return null;
+ }
+ return cursorPos;
+};
+
+
+/**
+ * Helper method for saving state.
+ * @param {goog.editor.Field} fieldObj The field object.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.prototype.updateCurrentState_ = function(
+ fieldObj) {
+ var fieldHashCode = fieldObj.getHashCode();
+ // We specifically grab the raw innerHTML of the field here as that's what
+ // we would set on the field in the case of an undo/redo operation. There's
+ // no need to clean/unclean the contents in either direction. In the case of
+ // lorem ipsum being used, we want to capture the effective state (empty, no
+ // cursor position) rather than capturing the lorem html.
+ var content, cursorPos;
+ if (fieldObj.queryCommandValue(goog.editor.Command.USING_LOREM)) {
+ content = '';
+ cursorPos = null;
+ } else {
+ content = fieldObj.getElement().innerHTML;
+ cursorPos = this.getCursorPosition_(fieldObj);
+ }
+
+ var currentState = this.currentStates_[fieldHashCode];
+ if (currentState) {
+ // Don't create states if the content hasn't changed (spurious
+ // delayed change). This can happen when lorem is cleared, for example.
+ if (currentState.undoContent_ == content) {
+ return;
+ } else if (content == '' || currentState.undoContent_ == '') {
+ // If lorem ipsum is on we say the contents are the empty string. However,
+ // for an empty text shape with focus, the empty contents might not be
+ // the same, depending on plugins. We want these two empty states to be
+ // considered identical because to the user they are indistinguishable,
+ // so we use fieldObj.getInjectableContents to map between them.
+ // We cannot use getInjectableContents when first creating the undo
+ // content for a field with lorem, because on enable when this is first
+ // called we can't guarantee plugin registration order, so the
+ // injectableContents at that time might not match the final
+ // injectableContents.
+ var emptyContents = fieldObj.getInjectableContents('', {});
+ if (content == emptyContents && currentState.undoContent_ == '' ||
+ currentState.undoContent_ == emptyContents && content == '') {
+ return;
+ }
+ }
+
+ currentState.setRedoState(content, cursorPos);
+ this.undoManager_.addState(currentState);
+ }
+
+ this.currentStates_[fieldHashCode] =
+ new goog.editor.plugins.UndoRedo.UndoState_(fieldHashCode, content,
+ cursorPos, this.boundRestoreState_);
+};
+
+
+
+/**
+ * This object encapsulates the state of an editable field.
+ *
+ * @param {string} fieldHashCode String the id of the field we're saving the
+ * content of.
+ * @param {string} content String the actual text we're saving.
+ * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
+ * CursorPosLite object for the cursor position in the field.
+ * @param {Function} restore The function used to restore editable field state.
+ * @private
+ * @constructor
+ * @extends {goog.editor.plugins.UndoRedoState}
+ */
+goog.editor.plugins.UndoRedo.UndoState_ = function(fieldHashCode, content,
+ cursorPosition, restore) {
+ goog.editor.plugins.UndoRedoState.call(this, true);
+
+ /**
+ * The hash code for the field whose content is being saved.
+ * @type {string}
+ */
+ this.fieldHashCode = fieldHashCode;
+
+ /**
+ * The bound copy of {@code goog.editor.plugins.UndoRedo.restoreState} used by
+ * this state.
+ * @type {Function}
+ * @private
+ */
+ this.restore_ = restore;
+
+ this.setUndoState(content, cursorPosition);
+};
+goog.inherits(goog.editor.plugins.UndoRedo.UndoState_,
+ goog.editor.plugins.UndoRedoState);
+
+
+/**
+ * The content to restore on undo.
+ * @type {string}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.undoContent_;
+
+
+/**
+ * The cursor position to restore on undo.
+ * @type {goog.editor.plugins.UndoRedo.CursorPosition_?}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.undoCursorPosition_;
+
+
+/**
+ * The content to restore on redo, undefined until the state is pushed onto the
+ * undo stack.
+ * @type {string|undefined}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.redoContent_;
+
+
+/**
+ * The cursor position to restore on redo, undefined until the state is pushed
+ * onto the undo stack.
+ * @type {goog.editor.plugins.UndoRedo.CursorPosition_|null|undefined}
+ * @private
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.redoCursorPosition_;
+
+
+/**
+ * Performs the undo operation represented by this state.
+ * @override
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.undo = function() {
+ this.restore_(this, this.undoContent_,
+ this.undoCursorPosition_);
+};
+
+
+/**
+ * Performs the redo operation represented by this state.
+ * @override
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.redo = function() {
+ this.restore_(this, this.redoContent_,
+ this.redoCursorPosition_);
+};
+
+
+/**
+ * Updates the undo portion of this state. Should only be used to update the
+ * current state of an editable field, which is not yet on the undo stack after
+ * an undo or redo operation. You should never be modifying states on the stack!
+ * @param {string} content The current content.
+ * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
+ * The current cursor position.
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.setUndoState = function(
+ content, cursorPosition) {
+ this.undoContent_ = content;
+ this.undoCursorPosition_ = cursorPosition;
+};
+
+
+/**
+ * Adds redo information to this state. This method should be called before the
+ * state is added onto the undo stack.
+ *
+ * @param {string} content The content to restore on a redo.
+ * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
+ * The cursor position to restore on a redo.
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.setRedoState = function(
+ content, cursorPosition) {
+ this.redoContent_ = content;
+ this.redoCursorPosition_ = cursorPosition;
+};
+
+
+/**
+ * Checks if the *contents* of two
+ * {@code goog.editor.plugins.UndoRedo.UndoState_}s are the same. We don't
+ * bother checking the cursor position (that's not something we'd want to save
+ * anyway).
+ * @param {goog.editor.plugins.UndoRedoState} rhs The state to compare.
+ * @return {boolean} Whether the contents are the same.
+ * @override
+ */
+goog.editor.plugins.UndoRedo.UndoState_.prototype.equals = function(rhs) {
+ return this.fieldHashCode == rhs.fieldHashCode &&
+ this.undoContent_ == rhs.undoContent_ &&
+ this.redoContent_ == rhs.redoContent_;
+};
+
+
+
+/**
+ * Stores the state of the selection in a way the survives DOM modifications
+ * that don't modify the user-interactable content (e.g. making something bold
+ * vs. typing a character).
+ *
+ * TODO(user): Completely get rid of this and use goog.dom.SavedCaretRange.
+ *
+ * @param {goog.editor.Field} field The field the selection is in.
+ * @private
+ * @constructor
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_ = function(field) {
+ this.field_ = field;
+
+ var win = field.getEditableDomHelper().getWindow();
+ var range = field.getRange();
+ var isValidRange = !!range && range.isRangeInDocument() &&
+ range.getWindow() == win;
+ range = isValidRange ? range : null;
+
+ if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
+ this.initW3C_(range);
+ } else if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
+ this.initIE_(range);
+ }
+};
+
+
+/**
+ * The standards compliant version keeps a list of childNode offsets.
+ * @param {goog.dom.AbstractRange?} range The range to save.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_.prototype.initW3C_ = function(
+ range) {
+ this.isValid_ = false;
+
+ // TODO: Check if the range is in the field before trying to save it
+ // for FF 3 contentEditable.
+ if (!range) {
+ return;
+ }
+
+ var anchorNode = range.getAnchorNode();
+ var focusNode = range.getFocusNode();
+ if (!anchorNode || !focusNode) {
+ return;
+ }
+
+ var anchorOffset = range.getAnchorOffset();
+ var anchor = new goog.dom.NodeOffset(anchorNode, this.field_.getElement());
+
+ var focusOffset = range.getFocusOffset();
+ var focus = new goog.dom.NodeOffset(focusNode, this.field_.getElement());
+
+ // Test range direction.
+ if (range.isReversed()) {
+ this.startOffset_ = focus;
+ this.startChildOffset_ = focusOffset;
+ this.endOffset_ = anchor;
+ this.endChildOffset_ = anchorOffset;
+ } else {
+ this.startOffset_ = anchor;
+ this.startChildOffset_ = anchorOffset;
+ this.endOffset_ = focus;
+ this.endChildOffset_ = focusOffset;
+ }
+
+ this.isValid_ = true;
+};
+
+
+/**
+ * In IE, we just keep track of the text offset (number of characters).
+ * @param {goog.dom.AbstractRange?} range The range to save.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_.prototype.initIE_ = function(
+ range) {
+ this.isValid_ = false;
+
+ if (!range) {
+ return;
+ }
+
+ var ieRange = range.getTextRange(0).getBrowserRangeObject();
+
+ if (!goog.dom.contains(this.field_.getElement(), ieRange.parentElement())) {
+ return;
+ }
+
+ // Create a range that encompasses the contentEditable region to serve
+ // as a reference to form ranges below.
+ var contentEditableRange =
+ this.field_.getEditableDomHelper().getDocument().body.createTextRange();
+ contentEditableRange.moveToElementText(this.field_.getElement());
+
+ // startMarker is a range from the start of the contentEditable node to the
+ // start of the current selection.
+ var startMarker = ieRange.duplicate();
+ startMarker.collapse(true);
+ startMarker.setEndPoint('StartToStart', contentEditableRange);
+ this.startOffset_ =
+ goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_(
+ startMarker);
+
+ // endMarker is a range from the start of teh contentEditable node to the
+ // end of the current selection.
+ var endMarker = ieRange.duplicate();
+ endMarker.setEndPoint('StartToStart', contentEditableRange);
+ this.endOffset_ =
+ goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_(
+ endMarker);
+
+ this.isValid_ = true;
+};
+
+
+/**
+ * @return {boolean} Whether this object is valid.
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_.prototype.isValid = function() {
+ return this.isValid_;
+};
+
+
+/**
+ * @return {string} A string representation of this object.
+ * @override
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_.prototype.toString = function() {
+ if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
+ return 'W3C:' + this.startOffset_.toString() + '\n' +
+ this.startChildOffset_ + ':' + this.endOffset_.toString() + '\n' +
+ this.endChildOffset_;
+ }
+ return 'IE:' + this.startOffset_ + ',' + this.endOffset_;
+};
+
+
+/**
+ * Makes the browser's selection match the cursor position.
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_.prototype.select = function() {
+ var range = this.getRange_(this.field_.getElement());
+ if (range) {
+ if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
+ this.field_.getElement().focus();
+ }
+ goog.dom.Range.createFromBrowserRange(range).select();
+ }
+};
+
+
+/**
+ * Get the range that encompases the the cursor position relative to a given
+ * base node.
+ * @param {Element} baseNode The node to get the cursor position relative to.
+ * @return {Range|TextRange|null} The browser range for this position.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_.prototype.getRange_ =
+ function(baseNode) {
+ if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
+ var startNode = this.startOffset_.findTargetNode(baseNode);
+ var endNode = this.endOffset_.findTargetNode(baseNode);
+ if (!startNode || !endNode) {
+ return null;
+ }
+
+ // Create range.
+ return /** @type {Range} */ (
+ goog.dom.Range.createFromNodes(startNode, this.startChildOffset_,
+ endNode, this.endChildOffset_).getBrowserRangeObject());
+ }
+
+ // Create a collapsed selection at the start of the contentEditable region,
+ // which the offsets were calculated relative to before. Note that we force
+ // a text range here so we can use moveToElementText.
+ var sel = baseNode.ownerDocument.body.createTextRange();
+ sel.moveToElementText(baseNode);
+ sel.collapse(true);
+ sel.moveEnd('character', this.endOffset_);
+ sel.moveStart('character', this.startOffset_);
+ return sel;
+};
+
+
+/**
+ * Compute the number of characters to the end of the range in IE.
+ * @param {TextRange} range The range to compute an offset for.
+ * @return {number} The number of characters to the end of the range.
+ * @private
+ */
+goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_ =
+ function(range) {
+ var testRange = range.duplicate();
+
+ // The number of offset characters is a little off depending on
+ // what type of block elements happen to be between the start of the
+ // textedit and the cursor position. We fudge the offset until the
+ // two ranges match.
+ var text = range.text;
+ var guess = text.length;
+
+ testRange.collapse(true);
+ testRange.moveEnd('character', guess);
+
+ // Adjust the range until the end points match. This doesn't quite
+ // work if we're at the end of the field so we give up after a few
+ // iterations.
+ var diff;
+ var numTries = 10;
+ while (diff = testRange.compareEndPoints('EndToEnd', range)) {
+ guess -= diff;
+ testRange.moveEnd('character', -diff);
+ --numTries;
+ if (0 == numTries) {
+ break;
+ }
+ }
+ // When we set innerHTML, blank lines become a single space, causing
+ // the cursor position to be off by one. So we accommodate for blank
+ // lines.
+ var offset = 0;
+ var pos = text.indexOf('\n\r');
+ while (pos != -1) {
+ ++offset;
+ pos = text.indexOf('\n\r', pos + 1);
+ }
+ return guess + offset;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/undoredomanager.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/undoredomanager.js b/externs/GCL/externs/goog/editor/plugins/undoredomanager.js
new file mode 100644
index 0000000..5e054fd
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/undoredomanager.js
@@ -0,0 +1,338 @@
+// 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 Code for managing series of undo-redo actions in the form of
+ * {@link goog.editor.plugins.UndoRedoState}s.
+ *
+ */
+
+
+goog.provide('goog.editor.plugins.UndoRedoManager');
+goog.provide('goog.editor.plugins.UndoRedoManager.EventType');
+
+goog.require('goog.editor.plugins.UndoRedoState');
+goog.require('goog.events');
+goog.require('goog.events.EventTarget');
+
+
+
+/**
+ * Manages undo and redo operations through a series of {@code UndoRedoState}s
+ * maintained on undo and redo stacks.
+ *
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.editor.plugins.UndoRedoManager = function() {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * The maximum number of states on the undo stack at any time. Used to limit
+ * the memory footprint of the undo-redo stack.
+ * TODO(user) have a separate memory size based limit.
+ * @type {number}
+ * @private
+ */
+ this.maxUndoDepth_ = 100;
+
+ /**
+ * The undo stack.
+ * @type {Array<goog.editor.plugins.UndoRedoState>}
+ * @private
+ */
+ this.undoStack_ = [];
+
+ /**
+ * The redo stack.
+ * @type {Array<goog.editor.plugins.UndoRedoState>}
+ * @private
+ */
+ this.redoStack_ = [];
+
+ /**
+ * A queue of pending undo or redo actions. Stored as objects with two
+ * properties: func and state. The func property stores the undo or redo
+ * function to be called, the state property stores the state that method
+ * came from.
+ * @type {Array<Object>}
+ * @private
+ */
+ this.pendingActions_ = [];
+};
+goog.inherits(goog.editor.plugins.UndoRedoManager, goog.events.EventTarget);
+
+
+/**
+ * Event types for the events dispatched by undo-redo manager.
+ * @enum {string}
+ */
+goog.editor.plugins.UndoRedoManager.EventType = {
+ /**
+ * Signifies that he undo or redo stack transitioned between 0 and 1 states,
+ * meaning that the ability to peform undo or redo operations has changed.
+ */
+ STATE_CHANGE: 'state_change',
+
+ /**
+ * Signifies that a state was just added to the undo stack. Events of this
+ * type will have a {@code state} property whose value is the state that
+ * was just added.
+ */
+ STATE_ADDED: 'state_added',
+
+ /**
+ * Signifies that the undo method of a state is about to be called.
+ * Events of this type will have a {@code state} property whose value is the
+ * state whose undo action is about to be performed. If the event is cancelled
+ * the action does not proceed, but the state will still transition between
+ * stacks.
+ */
+ BEFORE_UNDO: 'before_undo',
+
+ /**
+ * Signifies that the redo method of a state is about to be called.
+ * Events of this type will have a {@code state} property whose value is the
+ * state whose redo action is about to be performed. If the event is cancelled
+ * the action does not proceed, but the state will still transition between
+ * stacks.
+ */
+ BEFORE_REDO: 'before_redo'
+};
+
+
+/**
+ * The key for the listener for the completion of the asynchronous state whose
+ * undo or redo action is in progress. Null if no action is in progress.
+ * @type {goog.events.Key}
+ * @private
+ */
+goog.editor.plugins.UndoRedoManager.prototype.inProgressActionKey_ = null;
+
+
+/**
+ * Set the max undo stack depth (not the real memory usage).
+ * @param {number} depth Depth of the stack.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.setMaxUndoDepth =
+ function(depth) {
+ this.maxUndoDepth_ = depth;
+};
+
+
+/**
+ * Add state to the undo stack. This clears the redo stack.
+ *
+ * @param {goog.editor.plugins.UndoRedoState} state The state to add to the undo
+ * stack.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.addState = function(state) {
+ // TODO: is the state.equals check necessary?
+ if (this.undoStack_.length == 0 ||
+ !state.equals(this.undoStack_[this.undoStack_.length - 1])) {
+ this.undoStack_.push(state);
+ if (this.undoStack_.length > this.maxUndoDepth_) {
+ this.undoStack_.shift();
+ }
+ // Clobber the redo stack.
+ var redoLength = this.redoStack_.length;
+ this.redoStack_.length = 0;
+
+ this.dispatchEvent({
+ type: goog.editor.plugins.UndoRedoManager.EventType.STATE_ADDED,
+ state: state
+ });
+
+ // If the redo state had states on it, then clobbering the redo stack above
+ // has caused a state change.
+ if (this.undoStack_.length == 1 || redoLength) {
+ this.dispatchStateChange_();
+ }
+ }
+};
+
+
+/**
+ * Dispatches a STATE_CHANGE event with this manager as the target.
+ * @private
+ */
+goog.editor.plugins.UndoRedoManager.prototype.dispatchStateChange_ =
+ function() {
+ this.dispatchEvent(
+ goog.editor.plugins.UndoRedoManager.EventType.STATE_CHANGE);
+};
+
+
+/**
+ * Performs the undo operation of the state at the top of the undo stack, moving
+ * that state to the top of the redo stack. If the undo stack is empty, does
+ * nothing.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.undo = function() {
+ this.shiftState_(this.undoStack_, this.redoStack_);
+};
+
+
+/**
+ * Performs the redo operation of the state at the top of the redo stack, moving
+ * that state to the top of the undo stack. If redo undo stack is empty, does
+ * nothing.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.redo = function() {
+ this.shiftState_(this.redoStack_, this.undoStack_);
+};
+
+
+/**
+ * @return {boolean} Wether the undo stack has items on it, i.e., if it is
+ * possible to perform an undo operation.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.hasUndoState = function() {
+ return this.undoStack_.length > 0;
+};
+
+
+/**
+ * @return {boolean} Wether the redo stack has items on it, i.e., if it is
+ * possible to perform a redo operation.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.hasRedoState = function() {
+ return this.redoStack_.length > 0;
+};
+
+
+/**
+ * Move a state from one stack to the other, performing the appropriate undo
+ * or redo action.
+ *
+ * @param {Array<goog.editor.plugins.UndoRedoState>} fromStack Stack to move
+ * the state from.
+ * @param {Array<goog.editor.plugins.UndoRedoState>} toStack Stack to move
+ * the state to.
+ * @private
+ */
+goog.editor.plugins.UndoRedoManager.prototype.shiftState_ = function(
+ fromStack, toStack) {
+ if (fromStack.length) {
+ var state = fromStack.pop();
+
+ // Push the current state into the redo stack.
+ toStack.push(state);
+
+ this.addAction_({
+ type: fromStack == this.undoStack_ ?
+ goog.editor.plugins.UndoRedoManager.EventType.BEFORE_UNDO :
+ goog.editor.plugins.UndoRedoManager.EventType.BEFORE_REDO,
+ func: fromStack == this.undoStack_ ? state.undo : state.redo,
+ state: state
+ });
+
+ // If either stack transitioned between 0 and 1 in size then the ability
+ // to do an undo or redo has changed and we must dispatch a state change.
+ if (fromStack.length == 0 || toStack.length == 1) {
+ this.dispatchStateChange_();
+ }
+ }
+};
+
+
+/**
+ * Adds an action to the queue of pending undo or redo actions. If no actions
+ * are pending, immediately performs the action.
+ *
+ * @param {Object} action An undo or redo action. Stored as an object with two
+ * properties: func and state. The func property stores the undo or redo
+ * function to be called, the state property stores the state that method
+ * came from.
+ * @private
+ */
+goog.editor.plugins.UndoRedoManager.prototype.addAction_ = function(action) {
+ this.pendingActions_.push(action);
+ if (this.pendingActions_.length == 1) {
+ this.doAction_();
+ }
+};
+
+
+/**
+ * Executes the action at the front of the pending actions queue. If an action
+ * is already in progress or the queue is empty, does nothing.
+ * @private
+ */
+goog.editor.plugins.UndoRedoManager.prototype.doAction_ = function() {
+ if (this.inProgressActionKey_ || this.pendingActions_.length == 0) {
+ return;
+ }
+
+ var action = this.pendingActions_.shift();
+
+ var e = {
+ type: action.type,
+ state: action.state
+ };
+
+ if (this.dispatchEvent(e)) {
+ if (action.state.isAsynchronous()) {
+ this.inProgressActionKey_ = goog.events.listen(action.state,
+ goog.editor.plugins.UndoRedoState.ACTION_COMPLETED,
+ this.finishAction_, false, this);
+ action.func.call(action.state);
+ } else {
+ action.func.call(action.state);
+ this.doAction_();
+ }
+ }
+};
+
+
+/**
+ * Finishes processing the current in progress action, starting the next queued
+ * action if one exists.
+ * @private
+ */
+goog.editor.plugins.UndoRedoManager.prototype.finishAction_ = function() {
+ goog.events.unlistenByKey(/** @type {number} */ (this.inProgressActionKey_));
+ this.inProgressActionKey_ = null;
+ this.doAction_();
+};
+
+
+/**
+ * Clears the undo and redo stacks.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.clearHistory = function() {
+ if (this.undoStack_.length > 0 || this.redoStack_.length > 0) {
+ this.undoStack_.length = 0;
+ this.redoStack_.length = 0;
+ this.dispatchStateChange_();
+ }
+};
+
+
+/**
+ * @return {goog.editor.plugins.UndoRedoState|undefined} The state at the top of
+ * the undo stack without removing it from the stack.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.undoPeek = function() {
+ return this.undoStack_[this.undoStack_.length - 1];
+};
+
+
+/**
+ * @return {goog.editor.plugins.UndoRedoState|undefined} The state at the top of
+ * the redo stack without removing it from the stack.
+ */
+goog.editor.plugins.UndoRedoManager.prototype.redoPeek = function() {
+ return this.redoStack_[this.redoStack_.length - 1];
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/undoredostate.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/undoredostate.js b/externs/GCL/externs/goog/editor/plugins/undoredostate.js
new file mode 100644
index 0000000..9a772dd
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/undoredostate.js
@@ -0,0 +1,86 @@
+// 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 Code for an UndoRedoState interface representing an undo and
+ * redo action for a particular state change. To be used by
+ * {@link goog.editor.plugins.UndoRedoManager}.
+ *
+ */
+
+
+goog.provide('goog.editor.plugins.UndoRedoState');
+
+goog.require('goog.events.EventTarget');
+
+
+
+/**
+ * Represents an undo and redo action for a particular state transition.
+ *
+ * @param {boolean} asynchronous Whether the undo or redo actions for this
+ * state complete asynchronously. If true, then this state must fire
+ * an ACTION_COMPLETED event when undo or redo is complete.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.editor.plugins.UndoRedoState = function(asynchronous) {
+ goog.editor.plugins.UndoRedoState.base(this, 'constructor');
+
+ /**
+ * Indicates if the undo or redo actions for this state complete
+ * asynchronously.
+ * @type {boolean}
+ * @private
+ */
+ this.asynchronous_ = asynchronous;
+};
+goog.inherits(goog.editor.plugins.UndoRedoState, goog.events.EventTarget);
+
+
+/**
+ * Event type for events indicating that this state has completed an undo or
+ * redo operation.
+ */
+goog.editor.plugins.UndoRedoState.ACTION_COMPLETED = 'action_completed';
+
+
+/**
+ * @return {boolean} Whether or not the undo and redo actions of this state
+ * complete asynchronously. If true, the state will fire an ACTION_COMPLETED
+ * event when an undo or redo action is complete.
+ */
+goog.editor.plugins.UndoRedoState.prototype.isAsynchronous = function() {
+ return this.asynchronous_;
+};
+
+
+/**
+ * Undoes the action represented by this state.
+ */
+goog.editor.plugins.UndoRedoState.prototype.undo = goog.abstractMethod;
+
+
+/**
+ * Redoes the action represented by this state.
+ */
+goog.editor.plugins.UndoRedoState.prototype.redo = goog.abstractMethod;
+
+
+/**
+ * Checks if two undo-redo states are the same.
+ * @param {goog.editor.plugins.UndoRedoState} state The state to compare.
+ * @return {boolean} Wether the two states are equal.
+ */
+goog.editor.plugins.UndoRedoState.prototype.equals = goog.abstractMethod;
[28/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
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>
+ * <div>1<span>2</span>3</div>
+ * </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>
+ * <div>|1|<span>|2|</span>|3|</div>|
+ * </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);
+};
[16/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/format/format.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/format/format.js b/externs/GCL/externs/goog/format/format.js
new file mode 100644
index 0000000..f78067d
--- /dev/null
+++ b/externs/GCL/externs/goog/format/format.js
@@ -0,0 +1,502 @@
+// 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 Provides utility functions for formatting strings, numbers etc.
+ *
+ */
+
+goog.provide('goog.format');
+
+goog.require('goog.i18n.GraphemeBreak');
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+/**
+ * Formats a number of bytes in human readable form.
+ * 54, 450K, 1.3M, 5G etc.
+ * @param {number} bytes The number of bytes to show.
+ * @param {number=} opt_decimals The number of decimals to use. Defaults to 2.
+ * @return {string} The human readable form of the byte size.
+ */
+goog.format.fileSize = function(bytes, opt_decimals) {
+ return goog.format.numBytesToString(bytes, opt_decimals, false);
+};
+
+
+/**
+ * Checks whether string value containing scaling units (K, M, G, T, P, m,
+ * u, n) can be converted to a number.
+ *
+ * Where there is a decimal, there must be a digit to the left of the
+ * decimal point.
+ *
+ * Negative numbers are valid.
+ *
+ * Examples:
+ * 0, 1, 1.0, 10.4K, 2.3M, -0.3P, 1.2m
+ *
+ * @param {string} val String value to check.
+ * @return {boolean} True if string could be converted to a numeric value.
+ */
+goog.format.isConvertableScaledNumber = function(val) {
+ return goog.format.SCALED_NUMERIC_RE_.test(val);
+};
+
+
+/**
+ * Converts a string to numeric value, taking into account the units.
+ * If string ends in 'B', use binary conversion.
+ * @param {string} stringValue String to be converted to numeric value.
+ * @return {number} Numeric value for string.
+ */
+goog.format.stringToNumericValue = function(stringValue) {
+ if (goog.string.endsWith(stringValue, 'B')) {
+ return goog.format.stringToNumericValue_(
+ stringValue, goog.format.NUMERIC_SCALES_BINARY_);
+ }
+ return goog.format.stringToNumericValue_(
+ stringValue, goog.format.NUMERIC_SCALES_SI_);
+};
+
+
+/**
+ * Converts a string to number of bytes, taking into account the units.
+ * Binary conversion.
+ * @param {string} stringValue String to be converted to numeric value.
+ * @return {number} Numeric value for string.
+ */
+goog.format.stringToNumBytes = function(stringValue) {
+ return goog.format.stringToNumericValue_(
+ stringValue, goog.format.NUMERIC_SCALES_BINARY_);
+};
+
+
+/**
+ * Converts a numeric value to string representation. SI conversion.
+ * @param {number} val Value to be converted.
+ * @param {number=} opt_decimals The number of decimals to use. Defaults to 2.
+ * @return {string} String representation of number.
+ */
+goog.format.numericValueToString = function(val, opt_decimals) {
+ return goog.format.numericValueToString_(
+ val, goog.format.NUMERIC_SCALES_SI_, opt_decimals);
+};
+
+
+/**
+ * Converts number of bytes to string representation. Binary conversion.
+ * Default is to return the additional 'B' suffix, e.g. '10.5KB' to minimize
+ * confusion with counts that are scaled by powers of 1000.
+ * @param {number} val Value to be converted.
+ * @param {number=} opt_decimals The number of decimals to use. Defaults to 2.
+ * @param {boolean=} opt_suffix If true, include trailing 'B' in returned
+ * string. Default is true.
+ * @param {boolean=} opt_useSeparator If true, number and scale will be
+ * separated by a no break space. Default is false.
+ * @return {string} String representation of number of bytes.
+ */
+goog.format.numBytesToString = function(val, opt_decimals, opt_suffix,
+ opt_useSeparator) {
+ var suffix = '';
+ if (!goog.isDef(opt_suffix) || opt_suffix) {
+ suffix = 'B';
+ }
+ return goog.format.numericValueToString_(
+ val, goog.format.NUMERIC_SCALES_BINARY_, opt_decimals, suffix,
+ opt_useSeparator);
+};
+
+
+/**
+ * Converts a string to numeric value, taking into account the units.
+ * @param {string} stringValue String to be converted to numeric value.
+ * @param {Object} conversion Dictionary of conversion scales.
+ * @return {number} Numeric value for string. If it cannot be converted,
+ * returns NaN.
+ * @private
+ */
+goog.format.stringToNumericValue_ = function(stringValue, conversion) {
+ var match = stringValue.match(goog.format.SCALED_NUMERIC_RE_);
+ if (!match) {
+ return NaN;
+ }
+ var val = match[1] * conversion[match[2]];
+ return val;
+};
+
+
+/**
+ * Converts a numeric value to string, using specified conversion
+ * scales.
+ * @param {number} val Value to be converted.
+ * @param {Object} conversion Dictionary of scaling factors.
+ * @param {number=} opt_decimals The number of decimals to use. Default is 2.
+ * @param {string=} opt_suffix Optional suffix to append.
+ * @param {boolean=} opt_useSeparator If true, number and scale will be
+ * separated by a space. Default is false.
+ * @return {string} The human readable form of the byte size.
+ * @private
+ */
+goog.format.numericValueToString_ = function(val, conversion,
+ opt_decimals, opt_suffix, opt_useSeparator) {
+ var prefixes = goog.format.NUMERIC_SCALE_PREFIXES_;
+ var orig_val = val;
+ var symbol = '';
+ var separator = '';
+ var scale = 1;
+ if (val < 0) {
+ val = -val;
+ }
+ for (var i = 0; i < prefixes.length; i++) {
+ var unit = prefixes[i];
+ scale = conversion[unit];
+ if (val >= scale || (scale <= 1 && val > 0.1 * scale)) {
+ // Treat values less than 1 differently, allowing 0.5 to be "0.5" rather
+ // than "500m"
+ symbol = unit;
+ break;
+ }
+ }
+ if (!symbol) {
+ scale = 1;
+ } else {
+ if (opt_suffix) {
+ symbol += opt_suffix;
+ }
+ if (opt_useSeparator) {
+ separator = ' ';
+ }
+ }
+ var ex = Math.pow(10, goog.isDef(opt_decimals) ? opt_decimals : 2);
+ return Math.round(orig_val / scale * ex) / ex + separator + symbol;
+};
+
+
+/**
+ * Regular expression for detecting scaling units, such as K, M, G, etc. for
+ * converting a string representation to a numeric value.
+ *
+ * Also allow 'k' to be aliased to 'K'. These could be used for SI (powers
+ * of 1000) or Binary (powers of 1024) conversions.
+ *
+ * Also allow final 'B' to be interpreted as byte-count, implicitly triggering
+ * binary conversion (e.g., '10.2MB').
+ *
+ * @type {RegExp}
+ * @private
+ */
+goog.format.SCALED_NUMERIC_RE_ = /^([-]?\d+\.?\d*)([K,M,G,T,P,k,m,u,n]?)[B]?$/;
+
+
+/**
+ * Ordered list of scaling prefixes in decreasing order.
+ * @private {Array<string>}
+ */
+goog.format.NUMERIC_SCALE_PREFIXES_ = [
+ 'P', 'T', 'G', 'M', 'K', '', 'm', 'u', 'n'
+];
+
+
+/**
+ * Scaling factors for conversion of numeric value to string. SI conversion.
+ * @type {Object}
+ * @private
+ */
+goog.format.NUMERIC_SCALES_SI_ = {
+ '': 1,
+ 'n': 1e-9,
+ 'u': 1e-6,
+ 'm': 1e-3,
+ 'k': 1e3,
+ 'K': 1e3,
+ 'M': 1e6,
+ 'G': 1e9,
+ 'T': 1e12,
+ 'P': 1e15
+};
+
+
+/**
+ * Scaling factors for conversion of numeric value to string. Binary
+ * conversion.
+ * @type {Object}
+ * @private
+ */
+goog.format.NUMERIC_SCALES_BINARY_ = {
+ '': 1,
+ 'n': Math.pow(1024, -3),
+ 'u': Math.pow(1024, -2),
+ 'm': 1.0 / 1024,
+ 'k': 1024,
+ 'K': 1024,
+ 'M': Math.pow(1024, 2),
+ 'G': Math.pow(1024, 3),
+ 'T': Math.pow(1024, 4),
+ 'P': Math.pow(1024, 5)
+};
+
+
+/**
+ * First Unicode code point that has the Mark property.
+ * @type {number}
+ * @private
+ */
+goog.format.FIRST_GRAPHEME_EXTEND_ = 0x300;
+
+
+/**
+ * Returns true if and only if given character should be treated as a breaking
+ * space. All ASCII control characters, the main Unicode range of spacing
+ * characters (U+2000 to U+200B inclusive except for U+2007), and several other
+ * Unicode space characters are treated as breaking spaces.
+ * @param {number} charCode The character code under consideration.
+ * @return {boolean} True if the character is a breaking space.
+ * @private
+ */
+goog.format.isTreatedAsBreakingSpace_ = function(charCode) {
+ return (charCode <= goog.format.WbrToken_.SPACE) ||
+ (charCode >= 0x1000 &&
+ ((charCode >= 0x2000 && charCode <= 0x2006) ||
+ (charCode >= 0x2008 && charCode <= 0x200B) ||
+ charCode == 0x1680 ||
+ charCode == 0x180E ||
+ charCode == 0x2028 ||
+ charCode == 0x2029 ||
+ charCode == 0x205f ||
+ charCode == 0x3000));
+};
+
+
+/**
+ * Returns true if and only if given character is an invisible formatting
+ * character.
+ * @param {number} charCode The character code under consideration.
+ * @return {boolean} True if the character is an invisible formatting character.
+ * @private
+ */
+goog.format.isInvisibleFormattingCharacter_ = function(charCode) {
+ // See: http://unicode.org/charts/PDF/U2000.pdf
+ return (charCode >= 0x200C && charCode <= 0x200F) ||
+ (charCode >= 0x202A && charCode <= 0x202E);
+};
+
+
+/**
+ * Inserts word breaks into an HTML string at a given interval. The counter is
+ * reset if a space or a character which behaves like a space is encountered,
+ * but it isn't incremented if an invisible formatting character is encountered.
+ * WBRs aren't inserted into HTML tags or entities. Entities count towards the
+ * character count, HTML tags do not.
+ *
+ * With common strings aliased, objects allocations are constant based on the
+ * length of the string: N + 3. This guarantee does not hold if the string
+ * contains an element >= U+0300 and hasGraphemeBreak is non-trivial.
+ *
+ * @param {string} str HTML to insert word breaks into.
+ * @param {function(number, number, boolean): boolean} hasGraphemeBreak A
+ * function determining if there is a grapheme break between two characters,
+ * in the same signature as goog.i18n.GraphemeBreak.hasGraphemeBreak.
+ * @param {number=} opt_maxlen Maximum length after which to ensure
+ * there is a break. Default is 10 characters.
+ * @return {string} The string including word breaks.
+ * @private
+ */
+goog.format.insertWordBreaksGeneric_ = function(str, hasGraphemeBreak,
+ opt_maxlen) {
+ var maxlen = opt_maxlen || 10;
+ if (maxlen > str.length) return str;
+
+ var rv = [];
+ var n = 0; // The length of the current token
+
+ // This will contain the ampersand or less-than character if one of the
+ // two has been seen; otherwise, the value is zero.
+ var nestingCharCode = 0;
+
+ // First character position from input string that has not been outputted.
+ var lastDumpPosition = 0;
+
+ var charCode = 0;
+ for (var i = 0; i < str.length; i++) {
+ // Using charCodeAt versus charAt avoids allocating new string objects.
+ var lastCharCode = charCode;
+ charCode = str.charCodeAt(i);
+
+ // Don't add a WBR before characters that might be grapheme extending.
+ var isPotentiallyGraphemeExtending =
+ charCode >= goog.format.FIRST_GRAPHEME_EXTEND_ &&
+ !hasGraphemeBreak(lastCharCode, charCode, true);
+
+ // Don't add a WBR at the end of a word. For the purposes of determining
+ // work breaks, all ASCII control characters and some commonly encountered
+ // Unicode spacing characters are treated as breaking spaces.
+ if (n >= maxlen &&
+ !goog.format.isTreatedAsBreakingSpace_(charCode) &&
+ !isPotentiallyGraphemeExtending) {
+ // Flush everything seen so far, and append a word break.
+ rv.push(str.substring(lastDumpPosition, i), goog.format.WORD_BREAK_HTML);
+ lastDumpPosition = i;
+ n = 0;
+ }
+
+ if (!nestingCharCode) {
+ // Not currently within an HTML tag or entity
+
+ if (charCode == goog.format.WbrToken_.LT ||
+ charCode == goog.format.WbrToken_.AMP) {
+
+ // Entering an HTML Entity '&' or open tag '<'
+ nestingCharCode = charCode;
+ } else if (goog.format.isTreatedAsBreakingSpace_(charCode)) {
+
+ // A space or control character -- reset the token length
+ n = 0;
+ } else if (!goog.format.isInvisibleFormattingCharacter_(charCode)) {
+
+ // A normal flow character - increment. For grapheme extending
+ // characters, this is not *technically* a new character. However,
+ // since the grapheme break detector might be overly conservative,
+ // we have to continue incrementing, or else we won't even be able
+ // to add breaks when we get to things like punctuation. For the
+ // case where we have a full grapheme break detector, it is okay if
+ // we occasionally break slightly early.
+ n++;
+ }
+ } else if (charCode == goog.format.WbrToken_.GT &&
+ nestingCharCode == goog.format.WbrToken_.LT) {
+
+ // Leaving an HTML tag, treat the tag as zero-length
+ nestingCharCode = 0;
+ } else if (charCode == goog.format.WbrToken_.SEMI_COLON &&
+ nestingCharCode == goog.format.WbrToken_.AMP) {
+
+ // Leaving an HTML entity, treat it as length one
+ nestingCharCode = 0;
+ n++;
+ }
+ }
+
+ // Take care of anything we haven't flushed so far.
+ rv.push(str.substr(lastDumpPosition));
+
+ return rv.join('');
+};
+
+
+/**
+ * Inserts word breaks into an HTML string at a given interval.
+ *
+ * This method is as aggressive as possible, using a full table of Unicode
+ * characters where it is legal to insert word breaks; however, this table
+ * comes at a 2.5k pre-gzip (~1k post-gzip) size cost. Consider using
+ * insertWordBreaksBasic to minimize the size impact.
+ *
+ * @param {string} str HTML to insert word breaks into.
+ * @param {number=} opt_maxlen Maximum length after which to ensure there is a
+ * break. Default is 10 characters.
+ * @return {string} The string including word breaks.
+ */
+goog.format.insertWordBreaks = function(str, opt_maxlen) {
+ return goog.format.insertWordBreaksGeneric_(str,
+ goog.i18n.GraphemeBreak.hasGraphemeBreak, opt_maxlen);
+};
+
+
+/**
+ * Determines conservatively if a character has a Grapheme break.
+ *
+ * Conforms to a similar signature as goog.i18n.GraphemeBreak, but is overly
+ * conservative, returning true only for characters in common scripts that
+ * are simple to account for.
+ *
+ * @param {number} lastCharCode The previous character code. Ignored.
+ * @param {number} charCode The character code under consideration. It must be
+ * at least \u0300 as a precondition -- this case is covered by
+ * insertWordBreaksGeneric_.
+ * @param {boolean=} opt_extended Ignored, to conform with the interface.
+ * @return {boolean} Whether it is one of the recognized subsets of characters
+ * with a grapheme break.
+ * @private
+ */
+goog.format.conservativelyHasGraphemeBreak_ = function(
+ lastCharCode, charCode, opt_extended) {
+ // Return false for everything except the most common Cyrillic characters.
+ // Don't worry about Latin characters, because insertWordBreaksGeneric_
+ // itself already handles those.
+ // TODO(gboyer): Also account for Greek, Armenian, and Georgian if it is
+ // simple to do so.
+ return charCode >= 0x400 && charCode < 0x523;
+};
+
+
+// TODO(gboyer): Consider using a compile-time flag to switch implementations
+// rather than relying on the developers to toggle implementations.
+/**
+ * Inserts word breaks into an HTML string at a given interval.
+ *
+ * This method is less aggressive than insertWordBreaks, only inserting
+ * breaks next to punctuation and between Latin or Cyrillic characters.
+ * However, this is good enough for the common case of URLs. It also
+ * works for all Latin and Cyrillic languages, plus CJK has no need for word
+ * breaks. When this method is used, goog.i18n.GraphemeBreak may be dead
+ * code eliminated.
+ *
+ * @param {string} str HTML to insert word breaks into.
+ * @param {number=} opt_maxlen Maximum length after which to ensure there is a
+ * break. Default is 10 characters.
+ * @return {string} The string including word breaks.
+ */
+goog.format.insertWordBreaksBasic = function(str, opt_maxlen) {
+ return goog.format.insertWordBreaksGeneric_(str,
+ goog.format.conservativelyHasGraphemeBreak_, opt_maxlen);
+};
+
+
+/**
+ * True iff the current userAgent is IE8 or above.
+ * @type {boolean}
+ * @private
+ */
+goog.format.IS_IE8_OR_ABOVE_ = goog.userAgent.IE &&
+ goog.userAgent.isVersionOrHigher(8);
+
+
+/**
+ * Constant for the WBR replacement used by insertWordBreaks. Safari requires
+ * <wbr></wbr>, Opera needs the ­ entity, though this will give a visible
+ * hyphen at breaks. IE8 uses a zero width space.
+ * Other browsers just use <wbr>.
+ * @type {string}
+ */
+goog.format.WORD_BREAK_HTML =
+ goog.userAgent.WEBKIT ?
+ '<wbr></wbr>' : goog.userAgent.OPERA ?
+ '­' : goog.format.IS_IE8_OR_ABOVE_ ?
+ '​' : '<wbr>';
+
+
+/**
+ * Tokens used within insertWordBreaks.
+ * @private
+ * @enum {number}
+ */
+goog.format.WbrToken_ = {
+ LT: 60, // '<'.charCodeAt(0)
+ GT: 62, // '>'.charCodeAt(0)
+ AMP: 38, // '&'.charCodeAt(0)
+ SEMI_COLON: 59, // ';'.charCodeAt(0)
+ SPACE: 32 // ' '.charCodeAt(0)
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/format/htmlprettyprinter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/format/htmlprettyprinter.js b/externs/GCL/externs/goog/format/htmlprettyprinter.js
new file mode 100644
index 0000000..86366fa
--- /dev/null
+++ b/externs/GCL/externs/goog/format/htmlprettyprinter.js
@@ -0,0 +1,408 @@
+// 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 Provides functions to parse and pretty-print HTML strings.
+ *
+ */
+
+goog.provide('goog.format.HtmlPrettyPrinter');
+goog.provide('goog.format.HtmlPrettyPrinter.Buffer');
+
+goog.require('goog.dom.TagName');
+goog.require('goog.object');
+goog.require('goog.string.StringBuffer');
+
+
+
+/**
+ * This class formats HTML to be more human-readable.
+ * TODO(user): Add hierarchical indentation.
+ * @param {number=} opt_timeOutMillis Max # milliseconds to spend on #format. If
+ * this time is exceeded, return partially formatted. 0 or negative number
+ * indicates no timeout.
+ * @constructor
+ * @final
+ */
+goog.format.HtmlPrettyPrinter = function(opt_timeOutMillis) {
+ /**
+ * Max # milliseconds to spend on #format.
+ * @type {number}
+ * @private
+ */
+ this.timeOutMillis_ = opt_timeOutMillis && opt_timeOutMillis > 0 ?
+ opt_timeOutMillis : 0;
+};
+
+
+/**
+ * Singleton.
+ * @private {goog.format.HtmlPrettyPrinter?}
+ */
+goog.format.HtmlPrettyPrinter.instance_ = null;
+
+
+/**
+ * Singleton lazy initializer.
+ * @return {!goog.format.HtmlPrettyPrinter} Singleton.
+ * @private
+ */
+goog.format.HtmlPrettyPrinter.getInstance_ = function() {
+ if (!goog.format.HtmlPrettyPrinter.instance_) {
+ goog.format.HtmlPrettyPrinter.instance_ =
+ new goog.format.HtmlPrettyPrinter();
+ }
+ return goog.format.HtmlPrettyPrinter.instance_;
+};
+
+
+/**
+ * Static utility function. See prototype #format.
+ * @param {string} html The HTML text to pretty print.
+ * @return {string} Formatted result.
+ */
+goog.format.HtmlPrettyPrinter.format = function(html) {
+ return goog.format.HtmlPrettyPrinter.getInstance_().format(html);
+};
+
+
+/**
+ * List of patterns used to tokenize HTML for pretty printing. Cache
+ * subexpression for tag name.
+ * comment|meta-tag|tag|text|other-less-than-characters
+ * @private {!RegExp}
+ * @const
+ */
+goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ =
+ /(?:<!--.*?-->|<!.*?>|<(\/?)(\w+)[^>]*>|[^<]+|<)/g;
+
+
+/**
+ * Tags whose contents we don't want pretty printed.
+ * @private {!Object}
+ * @const
+ */
+goog.format.HtmlPrettyPrinter.NON_PRETTY_PRINTED_TAGS_ = goog.object.createSet(
+ goog.dom.TagName.SCRIPT,
+ goog.dom.TagName.STYLE,
+ goog.dom.TagName.PRE,
+ 'XMP');
+
+
+/**
+ * 'Block' tags. We should add newlines before and after these tags during
+ * pretty printing. Tags drawn mostly from HTML4 definitions for block and other
+ * non-online tags, excepting the ones in
+ * #goog.format.HtmlPrettyPrinter.NON_PRETTY_PRINTED_TAGS_.
+ * @private {!Object}
+ * @const
+ */
+goog.format.HtmlPrettyPrinter.BLOCK_TAGS_ = goog.object.createSet(
+ goog.dom.TagName.ADDRESS,
+ goog.dom.TagName.APPLET,
+ goog.dom.TagName.AREA,
+ goog.dom.TagName.BASE,
+ goog.dom.TagName.BASEFONT,
+ goog.dom.TagName.BLOCKQUOTE,
+ goog.dom.TagName.BODY,
+ goog.dom.TagName.CAPTION,
+ goog.dom.TagName.CENTER,
+ goog.dom.TagName.COL,
+ goog.dom.TagName.COLGROUP,
+ goog.dom.TagName.DIR,
+ goog.dom.TagName.DIV,
+ goog.dom.TagName.DL,
+ goog.dom.TagName.FIELDSET,
+ goog.dom.TagName.FORM,
+ goog.dom.TagName.FRAME,
+ goog.dom.TagName.FRAMESET,
+ goog.dom.TagName.H1,
+ goog.dom.TagName.H2,
+ goog.dom.TagName.H3,
+ goog.dom.TagName.H4,
+ goog.dom.TagName.H5,
+ goog.dom.TagName.H6,
+ goog.dom.TagName.HEAD,
+ goog.dom.TagName.HR,
+ goog.dom.TagName.HTML,
+ goog.dom.TagName.IFRAME,
+ goog.dom.TagName.ISINDEX,
+ goog.dom.TagName.LEGEND,
+ goog.dom.TagName.LINK,
+ goog.dom.TagName.MENU,
+ goog.dom.TagName.META,
+ goog.dom.TagName.NOFRAMES,
+ goog.dom.TagName.NOSCRIPT,
+ goog.dom.TagName.OL,
+ goog.dom.TagName.OPTGROUP,
+ goog.dom.TagName.OPTION,
+ goog.dom.TagName.P,
+ goog.dom.TagName.PARAM,
+ goog.dom.TagName.TABLE,
+ goog.dom.TagName.TBODY,
+ goog.dom.TagName.TD,
+ goog.dom.TagName.TFOOT,
+ goog.dom.TagName.TH,
+ goog.dom.TagName.THEAD,
+ goog.dom.TagName.TITLE,
+ goog.dom.TagName.TR,
+ goog.dom.TagName.UL);
+
+
+/**
+ * Non-block tags that break flow. We insert a line break after, but not before
+ * these. Tags drawn from HTML4 definitions.
+ * @private {!Object}
+ * @const
+ */
+goog.format.HtmlPrettyPrinter.BREAKS_FLOW_TAGS_ = goog.object.createSet(
+ goog.dom.TagName.BR,
+ goog.dom.TagName.DD,
+ goog.dom.TagName.DT,
+ goog.dom.TagName.BR,
+ goog.dom.TagName.LI,
+ goog.dom.TagName.NOFRAMES);
+
+
+/**
+ * Empty tags. These are treated as both start and end tags.
+ * @private {!Object}
+ * @const
+ */
+goog.format.HtmlPrettyPrinter.EMPTY_TAGS_ = goog.object.createSet(
+ goog.dom.TagName.BR,
+ goog.dom.TagName.HR,
+ goog.dom.TagName.ISINDEX);
+
+
+/**
+ * Breaks up HTML so it's easily readable by the user.
+ * @param {string} html The HTML text to pretty print.
+ * @return {string} Formatted result.
+ * @throws {Error} Regex error, data loss, or endless loop detected.
+ */
+goog.format.HtmlPrettyPrinter.prototype.format = function(html) {
+ // Trim leading whitespace, but preserve first indent; in other words, keep
+ // any spaces immediately before the first non-whitespace character (that's
+ // what $1 is), but remove all other leading whitespace. This adjustment
+ // historically had been made in Docs. The motivation is that some
+ // browsers prepend several line breaks in designMode.
+ html = html.replace(/^\s*?( *\S)/, '$1');
+
+ // Trim trailing whitespace.
+ html = html.replace(/\s+$/, '');
+
+ // Keep track of how much time we've used.
+ var timeOutMillis = this.timeOutMillis_;
+ var startMillis = timeOutMillis ? goog.now() : 0;
+
+ // Handles concatenation of the result and required line breaks.
+ var buffer = new goog.format.HtmlPrettyPrinter.Buffer();
+
+ // Declare these for efficiency since we access them in a loop.
+ var tokenRegex = goog.format.HtmlPrettyPrinter.TOKEN_REGEX_;
+ var nonPpTags = goog.format.HtmlPrettyPrinter.NON_PRETTY_PRINTED_TAGS_;
+ var blockTags = goog.format.HtmlPrettyPrinter.BLOCK_TAGS_;
+ var breaksFlowTags = goog.format.HtmlPrettyPrinter.BREAKS_FLOW_TAGS_;
+ var emptyTags = goog.format.HtmlPrettyPrinter.EMPTY_TAGS_;
+
+ // Used to verify we're making progress through our regex tokenization.
+ var lastIndex = 0;
+
+ // Use this to track non-pretty-printed tags and childen.
+ var nonPpTagStack = [];
+
+ // Loop through each matched token.
+ var match;
+ while (match = tokenRegex.exec(html)) {
+ // Get token.
+ var token = match[0];
+
+ // Is this token a tag? match.length == 3 for tags, 1 for all others.
+ if (match.length == 3) {
+ var tagName = match[2];
+ if (tagName) {
+ tagName = tagName.toUpperCase();
+ }
+
+ // Non-pretty-printed tags?
+ if (nonPpTags.hasOwnProperty(tagName)) {
+ // End tag?
+ if (match[1] == '/') {
+ // Do we have a matching start tag?
+ var stackSize = nonPpTagStack.length;
+ var startTagName = stackSize ? nonPpTagStack[stackSize - 1] : null;
+ if (startTagName == tagName) {
+ // End of non-pretty-printed block. Line break after.
+ nonPpTagStack.pop();
+ buffer.pushToken(false, token, !nonPpTagStack.length);
+ } else {
+ // Malformed HTML. No line breaks.
+ buffer.pushToken(false, token, false);
+ }
+ } else {
+ // Start of non-pretty-printed block. Line break before.
+ buffer.pushToken(!nonPpTagStack.length, token, false);
+ nonPpTagStack.push(tagName);
+ }
+ } else if (nonPpTagStack.length) {
+ // Inside non-pretty-printed block, no new line breaks.
+ buffer.pushToken(false, token, false);
+ } else if (blockTags.hasOwnProperty(tagName)) {
+ // Put line break before start block and after end block tags.
+ var isEmpty = emptyTags.hasOwnProperty(tagName);
+ var isEndTag = match[1] == '/';
+ buffer.pushToken(isEmpty || !isEndTag, token, isEmpty || isEndTag);
+ } else if (breaksFlowTags.hasOwnProperty(tagName)) {
+ var isEmpty = emptyTags.hasOwnProperty(tagName);
+ var isEndTag = match[1] == '/';
+ // Put line break after end flow-breaking tags.
+ buffer.pushToken(false, token, isEndTag || isEmpty);
+ } else {
+ // All other tags, no line break.
+ buffer.pushToken(false, token, false);
+ }
+ } else {
+ // Non-tags, no line break.
+ buffer.pushToken(false, token, false);
+ }
+
+ // Double check that we're making progress.
+ var newLastIndex = tokenRegex.lastIndex;
+ if (!token || newLastIndex <= lastIndex) {
+ throw Error('Regex failed to make progress through source html.');
+ }
+ lastIndex = newLastIndex;
+
+ // Out of time?
+ if (timeOutMillis) {
+ if (goog.now() - startMillis > timeOutMillis) {
+ // Push unprocessed data as one big token and reset regex object.
+ buffer.pushToken(false, html.substring(tokenRegex.lastIndex), false);
+ tokenRegex.lastIndex = 0;
+ break;
+ }
+ }
+ }
+
+ // Ensure we end in a line break.
+ buffer.lineBreak();
+
+ // Construct result string.
+ var result = String(buffer);
+
+ // Length should be original length plus # line breaks added.
+ var expectedLength = html.length + buffer.breakCount;
+ if (result.length != expectedLength) {
+ throw Error('Lost data pretty printing html.');
+ }
+
+ return result;
+};
+
+
+
+/**
+ * This class is a buffer to which we push our output. It tracks line breaks to
+ * make sure we don't add unnecessary ones.
+ * @constructor
+ * @final
+ */
+goog.format.HtmlPrettyPrinter.Buffer = function() {
+ /**
+ * Tokens to be output in #toString.
+ * @type {goog.string.StringBuffer}
+ * @private
+ */
+ this.out_ = new goog.string.StringBuffer();
+};
+
+
+/**
+ * Tracks number of line breaks added.
+ * @type {number}
+ */
+goog.format.HtmlPrettyPrinter.Buffer.prototype.breakCount = 0;
+
+
+/**
+ * Tracks if we are at the start of a new line.
+ * @type {boolean}
+ * @private
+ */
+goog.format.HtmlPrettyPrinter.Buffer.prototype.isBeginningOfNewLine_ = true;
+
+
+/**
+ * Tracks if we need a new line before the next token.
+ * @type {boolean}
+ * @private
+ */
+goog.format.HtmlPrettyPrinter.Buffer.prototype.needsNewLine_ = false;
+
+
+/**
+ * Adds token and necessary line breaks to output buffer.
+ * @param {boolean} breakBefore If true, add line break before token if
+ * necessary.
+ * @param {string} token Token to push.
+ * @param {boolean} breakAfter If true, add line break after token if
+ * necessary.
+ */
+goog.format.HtmlPrettyPrinter.Buffer.prototype.pushToken = function(
+ breakBefore, token, breakAfter) {
+ // If this token needs a preceeding line break, and
+ // we haven't already added a line break, and
+ // this token does not start with a line break,
+ // then add line break.
+ // Due to FF3.0 bug with lists, we don't insert a /n
+ // right before </ul>. See bug 1520665.
+ if ((this.needsNewLine_ || breakBefore) &&
+ !/^\r?\n/.test(token) &&
+ !/\/ul/i.test(token)) {
+ this.lineBreak();
+ }
+
+ // Token.
+ this.out_.append(token);
+
+ // Remember if this string ended with a line break so we know we don't have to
+ // insert another one before the next token.
+ this.isBeginningOfNewLine_ = /\r?\n$/.test(token);
+
+ // Remember if this token requires a line break after it. We don't insert it
+ // here because we might not have to if the next token starts with a line
+ // break.
+ this.needsNewLine_ = breakAfter && !this.isBeginningOfNewLine_;
+};
+
+
+/**
+ * Append line break if we need one.
+ */
+goog.format.HtmlPrettyPrinter.Buffer.prototype.lineBreak = function() {
+ if (!this.isBeginningOfNewLine_) {
+ this.out_.append('\n');
+ ++this.breakCount;
+ }
+};
+
+
+/**
+ * @return {string} String representation of tokens.
+ * @override
+ */
+goog.format.HtmlPrettyPrinter.Buffer.prototype.toString = function() {
+ return this.out_.toString();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/format/internationalizedemailaddress.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/format/internationalizedemailaddress.js b/externs/GCL/externs/goog/format/internationalizedemailaddress.js
new file mode 100644
index 0000000..fd1dfe6
--- /dev/null
+++ b/externs/GCL/externs/goog/format/internationalizedemailaddress.js
@@ -0,0 +1,256 @@
+// 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 Provides functions to parse and manipulate internationalized
+ * email addresses. This is useful in the context of Email Address
+ * Internationalization (EAI) as defined by RFC6530.
+ *
+ */
+
+goog.provide('goog.format.InternationalizedEmailAddress');
+
+goog.require('goog.format.EmailAddress');
+
+goog.require('goog.string');
+
+
+
+/**
+ * Formats an email address string for display, and allows for extraction of
+ * the individual components of the address.
+ * @param {string=} opt_address The email address.
+ * @param {string=} opt_name The name associated with the email address.
+ * @constructor
+ * @extends {goog.format.EmailAddress}
+ */
+goog.format.InternationalizedEmailAddress = function(opt_address, opt_name) {
+ goog.format.InternationalizedEmailAddress.base(
+ this, 'constructor', opt_address, opt_name);
+};
+goog.inherits(
+ goog.format.InternationalizedEmailAddress, goog.format.EmailAddress);
+
+
+/**
+ * A string representing the RegExp for the local part of an EAI email address.
+ * @private
+ */
+goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ =
+ '((?!\\s)[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}~\u0080-\uFFFFFF-])+';
+
+
+/**
+ * A string representing the RegExp for a label in the domain part of an EAI
+ * email address.
+ * @private
+ */
+goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ =
+ '(?!\\s)[a-zA-Z0-9\u0080-\u3001\u3003-\uFF0D\uFF0F-\uFF60\uFF62-\uFFFFFF-]';
+
+
+/**
+ * A string representing the RegExp for the domain part of an EAI email address.
+ * @private
+ */
+goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ =
+ // A unicode character (ASCII or Unicode excluding periods)
+ '(' + goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ +
+ // Such character 1+ times, followed by a Unicode period. All 1+ times.
+ '+[\\.\\uFF0E\\u3002\\uFF61])+' +
+ // And same thing but without a period in the end
+ goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ +
+ '{2,63}';
+
+
+/**
+ * Match string for address separators. This list is the result of the
+ * discussion in b/16241003.
+ * @type {string}
+ * @private
+ */
+goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_ =
+ ',' + // U+002C ( , ) COMMA
+ ';' + // U+003B ( ; ) SEMICOLON
+ '\u055D' + // ( ՝ ) ARMENIAN COMMA
+ '\u060C' + // ( ، ) ARABIC COMMA
+ '\u1363' + // ( ፣ ) ETHIOPIC COMMA
+ '\u1802' + // ( ᠂ ) MONGOLIAN COMMA
+ '\u1808' + // ( ᠈ ) MONGOLIAN MANCHU COMMA
+ '\u2E41' + // ( ⹁ ) REVERSED COMMA
+ '\u3001' + // ( 、 ) IDEOGRAPHIC COMMA
+ '\uFF0C' + // ( , ) FULLWIDTH COMMA
+ '\u061B' + // ( ؛ ) ARABIC SEMICOLON
+ '\u1364' + // ( ፤ ) ETHIOPIC SEMICOLON
+ '\uFF1B' + // ( ; ) FULLWIDTH SEMICOLON
+ '\uFF64' + // ( 、 ) HALFWIDTH IDEOGRAPHIC COMMA
+ '\u104A'; // ( ၊ ) MYANMAR SIGN LITTLE SECTION
+
+
+/**
+ * Match string for characters that, when in a display name, require it to be
+ * quoted.
+ * @type {string}
+ * @private
+ */
+goog.format.InternationalizedEmailAddress.CHARS_REQUIRE_QUOTES_ =
+ goog.format.EmailAddress.SPECIAL_CHARS +
+ goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_;
+
+
+/**
+ * A RegExp to match the local part of an EAI email address.
+ * @private {!RegExp}
+ */
+goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_ =
+ new RegExp('^' +
+ goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ +
+ '$');
+
+
+/**
+ * A RegExp to match the domain part of an EAI email address.
+ * @private {!RegExp}
+ */
+goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_ =
+ new RegExp('^' +
+ goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ +
+ '$');
+
+
+/**
+ * A RegExp to match an EAI email address.
+ * @private {!RegExp}
+ */
+goog.format.InternationalizedEmailAddress.EAI_EMAIL_ADDRESS_ =
+ new RegExp('^' +
+ goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ +
+ '@' +
+ goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ +
+ '$');
+
+
+/**
+ * Checks if the provided string is a valid local part (part before the '@') of
+ * an EAI email address.
+ * @param {string} str The local part to check.
+ * @return {boolean} Whether the provided string is a valid local part.
+ */
+goog.format.InternationalizedEmailAddress.isValidLocalPartSpec = function(str) {
+ if (!goog.isDefAndNotNull(str)) {
+ return false;
+ }
+ return goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_.test(str);
+};
+
+
+/**
+ * Checks if the provided string is a valid domain part (part after the '@') of
+ * an EAI email address.
+ * @param {string} str The domain part to check.
+ * @return {boolean} Whether the provided string is a valid domain part.
+ */
+goog.format.InternationalizedEmailAddress.isValidDomainPartSpec =
+ function(str) {
+ if (!goog.isDefAndNotNull(str)) {
+ return false;
+ }
+ return goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_.test(str);
+};
+
+
+/** @override */
+goog.format.InternationalizedEmailAddress.prototype.isValid = function() {
+ return goog.format.InternationalizedEmailAddress.isValidAddrSpec(
+ this.address);
+};
+
+
+/**
+ * Checks if the provided string is a valid email address. Supports both
+ * simple email addresses (address specs) and addresses that contain display
+ * names.
+ * @param {string} str The email address to check.
+ * @return {boolean} Whether the provided string is a valid address.
+ */
+goog.format.InternationalizedEmailAddress.isValidAddress = function(str) {
+ if (!goog.isDefAndNotNull(str)) {
+ return false;
+ }
+ return goog.format.InternationalizedEmailAddress.parse(str).isValid();
+};
+
+
+/**
+ * Checks if the provided string is a valid address spec (local@domain.com).
+ * @param {string} str The email address to check.
+ * @return {boolean} Whether the provided string is a valid address spec.
+ */
+goog.format.InternationalizedEmailAddress.isValidAddrSpec = function(str) {
+ if (!goog.isDefAndNotNull(str)) {
+ return false;
+ }
+
+ // This is a fairly naive implementation, but it covers 99% of use cases.
+ // For more details, see http://en.wikipedia.org/wiki/Email_address#Syntax
+ return goog.format.InternationalizedEmailAddress.EAI_EMAIL_ADDRESS_.test(str);
+};
+
+
+/**
+ * Parses a string containing email addresses of the form
+ * "name" <address> into an array of email addresses.
+ * @param {string} str The address list.
+ * @return {!Array<!goog.format.EmailAddress>} The parsed emails.
+ */
+goog.format.InternationalizedEmailAddress.parseList = function(str) {
+ return goog.format.EmailAddress.parseListInternal(
+ str, goog.format.InternationalizedEmailAddress.parse,
+ goog.format.InternationalizedEmailAddress.isAddressSeparator);
+};
+
+
+/**
+ * Parses an email address of the form "name" <address> into
+ * an email address.
+ * @param {string} addr The address string.
+ * @return {!goog.format.EmailAddress} The parsed address.
+ */
+goog.format.InternationalizedEmailAddress.parse = function(addr) {
+ return goog.format.EmailAddress.parseInternal(
+ addr, goog.format.InternationalizedEmailAddress);
+};
+
+
+/**
+ * @param {string} ch The character to test.
+ * @return {boolean} Whether the provided character is an address separator.
+ */
+goog.format.InternationalizedEmailAddress.isAddressSeparator = function(ch) {
+ return goog.string.contains(
+ goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_, ch);
+};
+
+
+/**
+ * Return the address in a standard format:
+ * - remove extra spaces.
+ * - Surround name with quotes if it contains special characters.
+ * @return {string} The cleaned address.
+ * @override
+ */
+goog.format.InternationalizedEmailAddress.prototype.toString = function() {
+ return this.toStringInternal(
+ goog.format.InternationalizedEmailAddress.CHARS_REQUIRE_QUOTES_);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/format/jsonprettyprinter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/format/jsonprettyprinter.js b/externs/GCL/externs/goog/format/jsonprettyprinter.js
new file mode 100644
index 0000000..15e2cd2
--- /dev/null
+++ b/externs/GCL/externs/goog/format/jsonprettyprinter.js
@@ -0,0 +1,414 @@
+// 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 Creates a string of a JSON object, properly indented for
+ * display.
+ *
+ */
+
+goog.provide('goog.format.JsonPrettyPrinter');
+goog.provide('goog.format.JsonPrettyPrinter.HtmlDelimiters');
+goog.provide('goog.format.JsonPrettyPrinter.TextDelimiters');
+
+goog.require('goog.json');
+goog.require('goog.json.Serializer');
+goog.require('goog.string');
+goog.require('goog.string.StringBuffer');
+goog.require('goog.string.format');
+
+
+
+/**
+ * Formats a JSON object as a string, properly indented for display. Supports
+ * displaying the string as text or html. Users can also specify their own
+ * set of delimiters for different environments. For example, the JSON object:
+ *
+ * <code>{"a": 1, "b": {"c": null, "d": true, "e": [1, 2]}}</code>
+ *
+ * Will be displayed like this:
+ *
+ * <code>{
+ * "a": 1,
+ * "b": {
+ * "c": null,
+ * "d": true,
+ * "e": [
+ * 1,
+ * 2
+ * ]
+ * }
+ * }</code>
+ * @param {goog.format.JsonPrettyPrinter.TextDelimiters} delimiters Container
+ * for the various strings to use to delimit objects, arrays, newlines, and
+ * other pieces of the output.
+ * @constructor
+ */
+goog.format.JsonPrettyPrinter = function(delimiters) {
+
+ /**
+ * The set of characters to use as delimiters.
+ * @type {goog.format.JsonPrettyPrinter.TextDelimiters}
+ * @private
+ */
+ this.delimiters_ = delimiters ||
+ new goog.format.JsonPrettyPrinter.TextDelimiters();
+
+ /**
+ * Used to serialize property names and values.
+ * @type {goog.json.Serializer}
+ * @private
+ */
+ this.jsonSerializer_ = new goog.json.Serializer();
+};
+
+
+/**
+ * Formats a JSON object as a string, properly indented for display.
+ * @param {*} json The object to pretty print. It could be a JSON object, a
+ * string representing a JSON object, or any other type.
+ * @return {string} Returns a string of the JSON object, properly indented for
+ * display.
+ */
+goog.format.JsonPrettyPrinter.prototype.format = function(json) {
+ // If input is undefined, null, or empty, return an empty string.
+ if (!goog.isDefAndNotNull(json)) {
+ return '';
+ }
+ if (goog.isString(json)) {
+ if (goog.string.isEmptyOrWhitespace(json)) {
+ return '';
+ }
+ // Try to coerce a string into a JSON object.
+ json = goog.json.parse(json);
+ }
+ var outputBuffer = new goog.string.StringBuffer();
+ this.printObject_(json, outputBuffer, 0);
+ return outputBuffer.toString();
+};
+
+
+/**
+ * Formats a property value based on the type of the propery.
+ * @param {*} val The object to format.
+ * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
+ * response to.
+ * @param {number} indent The number of spaces to indent each line of the
+ * output.
+ * @private
+ */
+goog.format.JsonPrettyPrinter.prototype.printObject_ = function(val,
+ outputBuffer, indent) {
+ var typeOf = goog.typeOf(val);
+ switch (typeOf) {
+ case 'null':
+ case 'boolean':
+ case 'number':
+ case 'string':
+ // "null", "boolean", "number" and "string" properties are printed
+ // directly to the output.
+ this.printValue_(
+ /** @type {null|string|boolean|number} */ (val),
+ typeOf, outputBuffer);
+ break;
+ case 'array':
+ // Example of how an array looks when formatted
+ // (using the default delimiters):
+ // [
+ // 1,
+ // 2,
+ // 3
+ // ]
+ outputBuffer.append(this.delimiters_.arrayStart);
+ var i = 0;
+ // Iterate through the array and format each element.
+ for (i = 0; i < val.length; i++) {
+ if (i > 0) {
+ // There are multiple elements, add a comma to separate them.
+ outputBuffer.append(this.delimiters_.propertySeparator);
+ }
+ outputBuffer.append(this.delimiters_.lineBreak);
+ this.printSpaces_(indent + this.delimiters_.indent, outputBuffer);
+ this.printObject_(val[i], outputBuffer,
+ indent + this.delimiters_.indent);
+ }
+ // If there are no properties in this object, don't put a line break
+ // between the beginning "[" and ending "]", so the output of an empty
+ // array looks like <code>[]</code>.
+ if (i > 0) {
+ outputBuffer.append(this.delimiters_.lineBreak);
+ this.printSpaces_(indent, outputBuffer);
+ }
+ outputBuffer.append(this.delimiters_.arrayEnd);
+ break;
+ case 'object':
+ // Example of how an object looks when formatted
+ // (using the default delimiters):
+ // {
+ // "a": 1,
+ // "b": 2,
+ // "c": "3"
+ // }
+ outputBuffer.append(this.delimiters_.objectStart);
+ var propertyCount = 0;
+ // Iterate through the object and display each property.
+ for (var name in val) {
+ if (!val.hasOwnProperty(name)) {
+ continue;
+ }
+ if (propertyCount > 0) {
+ // There are multiple properties, add a comma to separate them.
+ outputBuffer.append(this.delimiters_.propertySeparator);
+ }
+ outputBuffer.append(this.delimiters_.lineBreak);
+ this.printSpaces_(indent + this.delimiters_.indent, outputBuffer);
+ this.printName_(name, outputBuffer);
+ outputBuffer.append(this.delimiters_.nameValueSeparator,
+ this.delimiters_.space);
+ this.printObject_(val[name], outputBuffer,
+ indent + this.delimiters_.indent);
+ propertyCount++;
+ }
+ // If there are no properties in this object, don't put a line break
+ // between the beginning "{" and ending "}", so the output of an empty
+ // object looks like <code>{}</code>.
+ if (propertyCount > 0) {
+ outputBuffer.append(this.delimiters_.lineBreak);
+ this.printSpaces_(indent, outputBuffer);
+ }
+ outputBuffer.append(this.delimiters_.objectEnd);
+ break;
+ // Other types, such as "function", aren't expected in JSON, and their
+ // behavior is undefined. In these cases, just print an empty string to the
+ // output buffer. This allows the pretty printer to continue while still
+ // outputing well-formed JSON.
+ default:
+ this.printValue_('', 'unknown', outputBuffer);
+ }
+};
+
+
+/**
+ * Prints a property name to the output.
+ * @param {string} name The property name.
+ * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
+ * response to.
+ * @private
+ */
+goog.format.JsonPrettyPrinter.prototype.printName_ = function(name,
+ outputBuffer) {
+ outputBuffer.append(this.delimiters_.preName,
+ this.jsonSerializer_.serialize(name), this.delimiters_.postName);
+};
+
+
+/**
+ * Prints a property name to the output.
+ * @param {string|boolean|number|null} val The property value.
+ * @param {string} typeOf The type of the value. Used to customize
+ * value-specific css in the display. This allows clients to distinguish
+ * between different types in css. For example, the client may define two
+ * classes: "goog-jsonprettyprinter-propertyvalue-string" and
+ * "goog-jsonprettyprinter-propertyvalue-number" to assign a different color
+ * to string and number values.
+ * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
+ * response to.
+ * @private
+ */
+goog.format.JsonPrettyPrinter.prototype.printValue_ = function(val,
+ typeOf, outputBuffer) {
+ outputBuffer.append(goog.string.format(this.delimiters_.preValue, typeOf),
+ this.jsonSerializer_.serialize(val),
+ goog.string.format(this.delimiters_.postValue, typeOf));
+};
+
+
+/**
+ * Print a number of space characters to the output.
+ * @param {number} indent The number of spaces to indent the line.
+ * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
+ * response to.
+ * @private
+ */
+goog.format.JsonPrettyPrinter.prototype.printSpaces_ = function(indent,
+ outputBuffer) {
+ outputBuffer.append(goog.string.repeat(this.delimiters_.space, indent));
+};
+
+
+
+/**
+ * A container for the delimiting characters used to display the JSON string
+ * to a text display. Each delimiter is a publicly accessible property of
+ * the object, which makes it easy to tweak delimiters to specific environments.
+ * @constructor
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters = function() {
+};
+
+
+/**
+ * Represents a space character in the output. Used to indent properties a
+ * certain number of spaces, and to separate property names from property
+ * values.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.space = ' ';
+
+
+/**
+ * Represents a newline character in the output. Used to begin a new line.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.lineBreak = '\n';
+
+
+/**
+ * Represents the start of an object in the output.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.objectStart = '{';
+
+
+/**
+ * Represents the end of an object in the output.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.objectEnd = '}';
+
+
+/**
+ * Represents the start of an array in the output.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.arrayStart = '[';
+
+
+/**
+ * Represents the end of an array in the output.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.arrayEnd = ']';
+
+
+/**
+ * Represents the string used to separate properties in the output.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.propertySeparator = ',';
+
+
+/**
+ * Represents the string used to separate property names from property values in
+ * the output.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.nameValueSeparator = ':';
+
+
+/**
+ * A string that's placed before a property name in the output. Useful for
+ * wrapping a property name in an html tag.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.preName = '';
+
+
+/**
+ * A string that's placed after a property name in the output. Useful for
+ * wrapping a property name in an html tag.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.postName = '';
+
+
+/**
+ * A string that's placed before a property value in the output. Useful for
+ * wrapping a property value in an html tag.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.preValue = '';
+
+
+/**
+ * A string that's placed after a property value in the output. Useful for
+ * wrapping a property value in an html tag.
+ * @type {string}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.postValue = '';
+
+
+/**
+ * Represents the number of spaces to indent each sub-property of the JSON.
+ * @type {number}
+ */
+goog.format.JsonPrettyPrinter.TextDelimiters.prototype.indent = 2;
+
+
+
+/**
+ * A container for the delimiting characters used to display the JSON string
+ * to an HTML <code><pre></code> or <code><code></code> element.
+ * @constructor
+ * @extends {goog.format.JsonPrettyPrinter.TextDelimiters}
+ * @final
+ */
+goog.format.JsonPrettyPrinter.HtmlDelimiters = function() {
+ goog.format.JsonPrettyPrinter.TextDelimiters.call(this);
+};
+goog.inherits(goog.format.JsonPrettyPrinter.HtmlDelimiters,
+ goog.format.JsonPrettyPrinter.TextDelimiters);
+
+
+/**
+ * A <code>span</code> tag thats placed before a property name. Used to style
+ * property names with CSS.
+ * @type {string}
+ * @override
+ */
+goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.preName =
+ '<span class="' +
+ goog.getCssName('goog-jsonprettyprinter-propertyname') +
+ '">';
+
+
+/**
+ * A closing <code>span</code> tag that's placed after a property name.
+ * @type {string}
+ * @override
+ */
+goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.postName = '</span>';
+
+
+/**
+ * A <code>span</code> tag thats placed before a property value. Used to style
+ * property value with CSS. The span tag's class is in the format
+ * goog-jsonprettyprinter-propertyvalue-{TYPE}, where {TYPE} is the JavaScript
+ * type of the object (the {TYPE} parameter is obtained from goog.typeOf). This
+ * can be used to style different value types.
+ * @type {string}
+ * @override
+ */
+goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.preValue =
+ '<span class="' +
+ goog.getCssName('goog-jsonprettyprinter-propertyvalue') +
+ '-%s">';
+
+
+/**
+ * A closing <code>span</code> tag that's placed after a property value.
+ * @type {string}
+ * @override
+ */
+goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.postValue = '</span>';
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/entry.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/entry.js b/externs/GCL/externs/goog/fs/entry.js
new file mode 100644
index 0000000..8143daa
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/entry.js
@@ -0,0 +1,272 @@
+// 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 Wrappers for HTML5 Entry objects. These are all in the same
+ * file to avoid circular dependency issues.
+ *
+ * When adding or modifying functionality in this namespace, be sure to update
+ * the mock counterparts in goog.testing.fs.
+ *
+ */
+goog.provide('goog.fs.DirectoryEntry');
+goog.provide('goog.fs.DirectoryEntry.Behavior');
+goog.provide('goog.fs.Entry');
+goog.provide('goog.fs.FileEntry');
+
+
+
+/**
+ * The interface for entries in the filesystem.
+ * @interface
+ */
+goog.fs.Entry = function() {};
+
+
+/**
+ * @return {boolean} Whether or not this entry is a file.
+ */
+goog.fs.Entry.prototype.isFile = function() {};
+
+
+/**
+ * @return {boolean} Whether or not this entry is a directory.
+ */
+goog.fs.Entry.prototype.isDirectory = function() {};
+
+
+/**
+ * @return {string} The name of this entry.
+ */
+goog.fs.Entry.prototype.getName = function() {};
+
+
+/**
+ * @return {string} The full path to this entry.
+ */
+goog.fs.Entry.prototype.getFullPath = function() {};
+
+
+/**
+ * @return {!goog.fs.FileSystem} The filesystem backing this entry.
+ */
+goog.fs.Entry.prototype.getFileSystem = function() {};
+
+
+/**
+ * Retrieves the last modified date for this entry.
+ *
+ * @return {!goog.async.Deferred} The deferred Date for this entry. If an error
+ * occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.getLastModified = function() {};
+
+
+/**
+ * Retrieves the metadata for this entry.
+ *
+ * @return {!goog.async.Deferred} The deferred Metadata for this entry. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.getMetadata = function() {};
+
+
+/**
+ * Move this entry to a new location.
+ *
+ * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
+ * @param {string=} opt_newName The new name of the entry. If omitted, the entry
+ * retains its original name.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
+ * {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
+ * errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.moveTo = function(parent, opt_newName) {};
+
+
+/**
+ * Copy this entry to a new location.
+ *
+ * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
+ * @param {string=} opt_newName The name of the new entry. If omitted, the new
+ * entry has the same name as the original.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
+ * {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
+ * errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.copyTo = function(parent, opt_newName) {};
+
+
+/**
+ * Wrap an HTML5 entry object in an appropriate subclass instance.
+ *
+ * @param {!Entry} entry The underlying Entry object.
+ * @return {!goog.fs.Entry} The appropriate subclass wrapper.
+ * @protected
+ */
+goog.fs.Entry.prototype.wrapEntry = function(entry) {};
+
+
+/**
+ * Get the URL for this file.
+ *
+ * @param {string=} opt_mimeType The MIME type that will be served for the URL.
+ * @return {string} The URL.
+ */
+goog.fs.Entry.prototype.toUrl = function(opt_mimeType) {};
+
+
+/**
+ * Get the URI for this file.
+ *
+ * @deprecated Use {@link #toUrl} instead.
+ * @param {string=} opt_mimeType The MIME type that will be served for the URI.
+ * @return {string} The URI.
+ */
+goog.fs.Entry.prototype.toUri = function(opt_mimeType) {};
+
+
+/**
+ * Remove this entry.
+ *
+ * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
+ * the callback is called with true. If an error occurs, the errback is
+ * called a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.remove = function() {};
+
+
+/**
+ * Gets the parent directory.
+ *
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
+ * If an error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.Entry.prototype.getParent = function() {};
+
+
+
+/**
+ * A directory in a local FileSystem.
+ *
+ * @interface
+ * @extends {goog.fs.Entry}
+ */
+goog.fs.DirectoryEntry = function() {};
+
+
+/**
+ * Behaviors for getting files and directories.
+ * @enum {number}
+ */
+goog.fs.DirectoryEntry.Behavior = {
+ /**
+ * Get the file if it exists, error out if it doesn't.
+ */
+ DEFAULT: 1,
+ /**
+ * Get the file if it exists, create it if it doesn't.
+ */
+ CREATE: 2,
+ /**
+ * Error out if the file exists, create it if it doesn't.
+ */
+ CREATE_EXCLUSIVE: 3
+};
+
+
+/**
+ * Get a file in the directory.
+ *
+ * @param {string} path The path to the file, relative to this directory.
+ * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
+ * handling an existing file, or the lack thereof.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry}. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.getFile = function(path, opt_behavior) {};
+
+
+/**
+ * Get a directory within this directory.
+ *
+ * @param {string} path The path to the directory, relative to this directory.
+ * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
+ * handling an existing directory, or the lack thereof.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
+ * If an error occurs, the errback is called a {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.getDirectory = function(path, opt_behavior) {};
+
+
+/**
+ * Opens the directory for the specified path, creating the directory and any
+ * intermediate directories as necessary.
+ *
+ * @param {string} path The directory path to create. May be absolute or
+ * relative to the current directory. The parent directory ".." and current
+ * directory "." are supported.
+ * @return {!goog.async.Deferred} A deferred {@link goog.fs.DirectoryEntry} for
+ * the requested path. If an error occurs, the errback is called with a
+ * {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.createPath = function(path) {};
+
+
+/**
+ * Gets a list of all entries in this directory.
+ *
+ * @return {!goog.async.Deferred} The deferred list of {@link goog.fs.Entry}
+ * results. If an error occurs, the errback is called with a
+ * {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.listDirectory = function() {};
+
+
+/**
+ * Removes this directory and all its contents.
+ *
+ * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
+ * the callback is called with true. If an error occurs, the errback is
+ * called a {@link goog.fs.Error}.
+ */
+goog.fs.DirectoryEntry.prototype.removeRecursively = function() {};
+
+
+
+/**
+ * A file in a local filesystem.
+ *
+ * @interface
+ * @extends {goog.fs.Entry}
+ */
+goog.fs.FileEntry = function() {};
+
+
+/**
+ * Create a writer for writing to the file.
+ *
+ * @return {!goog.async.Deferred<!goog.fs.FileWriter>} If an error occurs, the
+ * errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileEntry.prototype.createWriter = function() {};
+
+
+/**
+ * Get the file contents as a File blob.
+ *
+ * @return {!goog.async.Deferred<!File>} If an error occurs, the errback is
+ * called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileEntry.prototype.file = function() {};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/entryimpl.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/entryimpl.js b/externs/GCL/externs/goog/fs/entryimpl.js
new file mode 100644
index 0000000..a4cbe7a
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/entryimpl.js
@@ -0,0 +1,404 @@
+// 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 Concrete implementations of the
+ * goog.fs.DirectoryEntry, and goog.fs.FileEntry interfaces.
+ */
+goog.provide('goog.fs.DirectoryEntryImpl');
+goog.provide('goog.fs.EntryImpl');
+goog.provide('goog.fs.FileEntryImpl');
+
+goog.require('goog.array');
+goog.require('goog.async.Deferred');
+goog.require('goog.fs.DirectoryEntry');
+goog.require('goog.fs.Entry');
+goog.require('goog.fs.Error');
+goog.require('goog.fs.FileEntry');
+goog.require('goog.fs.FileWriter');
+goog.require('goog.functions');
+goog.require('goog.string');
+
+
+
+/**
+ * Base class for concrete implementations of goog.fs.Entry.
+ * @param {!goog.fs.FileSystem} fs The wrapped filesystem.
+ * @param {!Entry} entry The underlying Entry object.
+ * @constructor
+ * @implements {goog.fs.Entry}
+ */
+goog.fs.EntryImpl = function(fs, entry) {
+ /**
+ * The wrapped filesystem.
+ *
+ * @type {!goog.fs.FileSystem}
+ * @private
+ */
+ this.fs_ = fs;
+
+ /**
+ * The underlying Entry object.
+ *
+ * @type {!Entry}
+ * @private
+ */
+ this.entry_ = entry;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.isFile = function() {
+ return this.entry_.isFile;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.isDirectory = function() {
+ return this.entry_.isDirectory;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.getName = function() {
+ return this.entry_.name;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.getFullPath = function() {
+ return this.entry_.fullPath;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.getFileSystem = function() {
+ return this.fs_;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.getLastModified = function() {
+ return this.getMetadata().addCallback(function(metadata) {
+ return metadata.modificationTime;
+ });
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.getMetadata = function() {
+ var d = new goog.async.Deferred();
+
+ this.entry_.getMetadata(
+ function(metadata) { d.callback(metadata); },
+ goog.bind(function(err) {
+ var msg = 'retrieving metadata for ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.moveTo = function(parent, opt_newName) {
+ var d = new goog.async.Deferred();
+ this.entry_.moveTo(
+ parent.dir_, opt_newName,
+ goog.bind(function(entry) { d.callback(this.wrapEntry(entry)); }, this),
+ goog.bind(function(err) {
+ var msg = 'moving ' + this.getFullPath() + ' into ' +
+ parent.getFullPath() +
+ (opt_newName ? ', renaming to ' + opt_newName : '');
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.copyTo = function(parent, opt_newName) {
+ var d = new goog.async.Deferred();
+ this.entry_.copyTo(
+ parent.dir_, opt_newName,
+ goog.bind(function(entry) { d.callback(this.wrapEntry(entry)); }, this),
+ goog.bind(function(err) {
+ var msg = 'copying ' + this.getFullPath() + ' into ' +
+ parent.getFullPath() +
+ (opt_newName ? ', renaming to ' + opt_newName : '');
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.wrapEntry = function(entry) {
+ return entry.isFile ?
+ new goog.fs.FileEntryImpl(this.fs_, /** @type {!FileEntry} */ (entry)) :
+ new goog.fs.DirectoryEntryImpl(
+ this.fs_, /** @type {!DirectoryEntry} */ (entry));
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.toUrl = function(opt_mimeType) {
+ return this.entry_.toURL(opt_mimeType);
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.toUri = goog.fs.EntryImpl.prototype.toUrl;
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.remove = function() {
+ var d = new goog.async.Deferred();
+ this.entry_.remove(
+ goog.bind(d.callback, d, true /* result */),
+ goog.bind(function(err) {
+ var msg = 'removing ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/** @override */
+goog.fs.EntryImpl.prototype.getParent = function() {
+ var d = new goog.async.Deferred();
+ this.entry_.getParent(
+ goog.bind(function(parent) {
+ d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, parent));
+ }, this),
+ goog.bind(function(err) {
+ var msg = 'getting parent of ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+
+/**
+ * A directory in a local FileSystem.
+ *
+ * This should not be instantiated directly. Instead, it should be accessed via
+ * {@link goog.fs.FileSystem#getRoot} or
+ * {@link goog.fs.DirectoryEntry#getDirectoryEntry}.
+ *
+ * @param {!goog.fs.FileSystem} fs The wrapped filesystem.
+ * @param {!DirectoryEntry} dir The underlying DirectoryEntry object.
+ * @constructor
+ * @extends {goog.fs.EntryImpl}
+ * @implements {goog.fs.DirectoryEntry}
+ * @final
+ */
+goog.fs.DirectoryEntryImpl = function(fs, dir) {
+ goog.fs.DirectoryEntryImpl.base(this, 'constructor', fs, dir);
+
+ /**
+ * The underlying DirectoryEntry object.
+ *
+ * @type {!DirectoryEntry}
+ * @private
+ */
+ this.dir_ = dir;
+};
+goog.inherits(goog.fs.DirectoryEntryImpl, goog.fs.EntryImpl);
+
+
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.getFile = function(path, opt_behavior) {
+ var d = new goog.async.Deferred();
+ this.dir_.getFile(
+ path, this.getOptions_(opt_behavior),
+ goog.bind(function(entry) {
+ d.callback(new goog.fs.FileEntryImpl(this.fs_, entry));
+ }, this),
+ goog.bind(function(err) {
+ var msg = 'loading file ' + path + ' from ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.getDirectory =
+ function(path, opt_behavior) {
+ var d = new goog.async.Deferred();
+ this.dir_.getDirectory(
+ path, this.getOptions_(opt_behavior),
+ goog.bind(function(entry) {
+ d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, entry));
+ }, this),
+ goog.bind(function(err) {
+ var msg = 'loading directory ' + path + ' from ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.createPath = function(path) {
+ // If the path begins at the root, reinvoke createPath on the root directory.
+ if (goog.string.startsWith(path, '/')) {
+ var root = this.getFileSystem().getRoot();
+ if (this.getFullPath() != root.getFullPath()) {
+ return root.createPath(path);
+ }
+ }
+
+ // Filter out any empty path components caused by '//' or a leading slash.
+ var parts = goog.array.filter(path.split('/'), goog.functions.identity);
+
+ /**
+ * @param {goog.fs.DirectoryEntryImpl} dir
+ * @return {!goog.async.Deferred}
+ */
+ function getNextDirectory(dir) {
+ if (!parts.length) {
+ return goog.async.Deferred.succeed(dir);
+ }
+
+ var def;
+ var nextDir = parts.shift();
+
+ if (nextDir == '..') {
+ def = dir.getParent();
+ } else if (nextDir == '.') {
+ def = goog.async.Deferred.succeed(dir);
+ } else {
+ def = dir.getDirectory(nextDir, goog.fs.DirectoryEntry.Behavior.CREATE);
+ }
+ return def.addCallback(getNextDirectory);
+ }
+
+ return getNextDirectory(this);
+};
+
+
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.listDirectory = function() {
+ var d = new goog.async.Deferred();
+ var reader = this.dir_.createReader();
+ var results = [];
+
+ var errorCallback = goog.bind(function(err) {
+ var msg = 'listing directory ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this);
+
+ var successCallback = goog.bind(function(entries) {
+ if (entries.length) {
+ for (var i = 0, entry; entry = entries[i]; i++) {
+ results.push(this.wrapEntry(entry));
+ }
+ reader.readEntries(successCallback, errorCallback);
+ } else {
+ d.callback(results);
+ }
+ }, this);
+
+ reader.readEntries(successCallback, errorCallback);
+ return d;
+};
+
+
+/** @override */
+goog.fs.DirectoryEntryImpl.prototype.removeRecursively = function() {
+ var d = new goog.async.Deferred();
+ this.dir_.removeRecursively(
+ goog.bind(d.callback, d, true /* result */),
+ goog.bind(function(err) {
+ var msg = 'removing ' + this.getFullPath() + ' recursively';
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/**
+ * Converts a value in the Behavior enum into an options object expected by the
+ * File API.
+ *
+ * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
+ * existing files.
+ * @return {!Object<boolean>} The options object expected by the File API.
+ * @private
+ */
+goog.fs.DirectoryEntryImpl.prototype.getOptions_ = function(opt_behavior) {
+ if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE) {
+ return {'create': true};
+ } else if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE) {
+ return {'create': true, 'exclusive': true};
+ } else {
+ return {};
+ }
+};
+
+
+
+/**
+ * A file in a local filesystem.
+ *
+ * This should not be instantiated directly. Instead, it should be accessed via
+ * {@link goog.fs.DirectoryEntry#getFile}.
+ *
+ * @param {!goog.fs.FileSystem} fs The wrapped filesystem.
+ * @param {!FileEntry} file The underlying FileEntry object.
+ * @constructor
+ * @extends {goog.fs.EntryImpl}
+ * @implements {goog.fs.FileEntry}
+ * @final
+ */
+goog.fs.FileEntryImpl = function(fs, file) {
+ goog.fs.FileEntryImpl.base(this, 'constructor', fs, file);
+
+ /**
+ * The underlying FileEntry object.
+ *
+ * @type {!FileEntry}
+ * @private
+ */
+ this.file_ = file;
+};
+goog.inherits(goog.fs.FileEntryImpl, goog.fs.EntryImpl);
+
+
+/** @override */
+goog.fs.FileEntryImpl.prototype.createWriter = function() {
+ var d = new goog.async.Deferred();
+ this.file_.createWriter(
+ function(w) { d.callback(new goog.fs.FileWriter(w)); },
+ goog.bind(function(err) {
+ var msg = 'creating writer for ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
+
+
+/** @override */
+goog.fs.FileEntryImpl.prototype.file = function() {
+ var d = new goog.async.Deferred();
+ this.file_.file(
+ function(f) { d.callback(f); },
+ goog.bind(function(err) {
+ var msg = 'getting file for ' + this.getFullPath();
+ d.errback(new goog.fs.Error(err, msg));
+ }, this));
+ return d;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/error3.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/error3.js b/externs/GCL/externs/goog/fs/error3.js
new file mode 100644
index 0000000..3a54f28
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/error3.js
@@ -0,0 +1,181 @@
+// 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 A wrapper for the HTML5 FileError object.
+ *
+ */
+
+goog.provide('goog.fs.Error');
+goog.provide('goog.fs.Error.ErrorCode');
+
+goog.require('goog.debug.Error');
+goog.require('goog.object');
+goog.require('goog.string');
+
+
+
+/**
+ * A filesystem error. Since the filesystem API is asynchronous, stack traces
+ * are less useful for identifying where errors come from, so this includes a
+ * large amount of metadata in the message.
+ *
+ * @param {!DOMError} error
+ * @param {string} action The action being undertaken when the error was raised.
+ * @constructor
+ * @extends {goog.debug.Error}
+ * @final
+ */
+goog.fs.Error = function(error, action) {
+ /** @type {string} */
+ this.name;
+
+ /**
+ * @type {goog.fs.Error.ErrorCode}
+ * @deprecated Use the 'name' or 'message' field instead.
+ */
+ this.code;
+
+ if (goog.isDef(error.name)) {
+ this.name = error.name;
+ // TODO(user): Remove warning suppression after JSCompiler stops
+ // firing a spurious warning here.
+ /** @suppress {deprecated} */
+ this.code = goog.fs.Error.getCodeFromName_(error.name);
+ } else {
+ this.code = error.code;
+ this.name = goog.fs.Error.getNameFromCode_(error.code);
+ }
+ goog.fs.Error.base(this, 'constructor',
+ goog.string.subs('%s %s', this.name, action));
+};
+goog.inherits(goog.fs.Error, goog.debug.Error);
+
+
+/**
+ * Names of errors that may be thrown by the File API, the File System API, or
+ * the File Writer API.
+ *
+ * @see http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException
+ * @see http://www.w3.org/TR/file-system-api/#definitions
+ * @see http://dev.w3.org/2009/dap/file-system/file-writer.html#definitions
+ * @enum {string}
+ */
+goog.fs.Error.ErrorName = {
+ ABORT: 'AbortError',
+ ENCODING: 'EncodingError',
+ INVALID_MODIFICATION: 'InvalidModificationError',
+ INVALID_STATE: 'InvalidStateError',
+ NOT_FOUND: 'NotFoundError',
+ NOT_READABLE: 'NotReadableError',
+ NO_MODIFICATION_ALLOWED: 'NoModificationAllowedError',
+ PATH_EXISTS: 'PathExistsError',
+ QUOTA_EXCEEDED: 'QuotaExceededError',
+ SECURITY: 'SecurityError',
+ SYNTAX: 'SyntaxError',
+ TYPE_MISMATCH: 'TypeMismatchError'
+};
+
+
+/**
+ * Error codes for file errors.
+ * @see http://www.w3.org/TR/file-system-api/#idl-def-FileException
+ *
+ * @enum {number}
+ * @deprecated Use the 'name' or 'message' attribute instead.
+ */
+goog.fs.Error.ErrorCode = {
+ NOT_FOUND: 1,
+ SECURITY: 2,
+ ABORT: 3,
+ NOT_READABLE: 4,
+ ENCODING: 5,
+ NO_MODIFICATION_ALLOWED: 6,
+ INVALID_STATE: 7,
+ SYNTAX: 8,
+ INVALID_MODIFICATION: 9,
+ QUOTA_EXCEEDED: 10,
+ TYPE_MISMATCH: 11,
+ PATH_EXISTS: 12
+};
+
+
+/**
+ * @param {goog.fs.Error.ErrorCode} code
+ * @return {string} name
+ * @private
+ */
+goog.fs.Error.getNameFromCode_ = function(code) {
+ var name = goog.object.findKey(goog.fs.Error.NameToCodeMap_, function(c) {
+ return code == c;
+ });
+ if (!goog.isDef(name)) {
+ throw new Error('Invalid code: ' + code);
+ }
+ return name;
+};
+
+
+/**
+ * Returns the code that corresponds to the given name.
+ * @param {string} name
+ * @return {goog.fs.Error.ErrorCode} code
+ * @private
+ */
+goog.fs.Error.getCodeFromName_ = function(name) {
+ return goog.fs.Error.NameToCodeMap_[name];
+};
+
+
+/**
+ * Mapping from error names to values from the ErrorCode enum.
+ * @see http://www.w3.org/TR/file-system-api/#definitions.
+ * @private {!Object<string, goog.fs.Error.ErrorCode>}
+ */
+goog.fs.Error.NameToCodeMap_ = goog.object.create(
+ goog.fs.Error.ErrorName.ABORT,
+ goog.fs.Error.ErrorCode.ABORT,
+
+ goog.fs.Error.ErrorName.ENCODING,
+ goog.fs.Error.ErrorCode.ENCODING,
+
+ goog.fs.Error.ErrorName.INVALID_MODIFICATION,
+ goog.fs.Error.ErrorCode.INVALID_MODIFICATION,
+
+ goog.fs.Error.ErrorName.INVALID_STATE,
+ goog.fs.Error.ErrorCode.INVALID_STATE,
+
+ goog.fs.Error.ErrorName.NOT_FOUND,
+ goog.fs.Error.ErrorCode.NOT_FOUND,
+
+ goog.fs.Error.ErrorName.NOT_READABLE,
+ goog.fs.Error.ErrorCode.NOT_READABLE,
+
+ goog.fs.Error.ErrorName.NO_MODIFICATION_ALLOWED,
+ goog.fs.Error.ErrorCode.NO_MODIFICATION_ALLOWED,
+
+ goog.fs.Error.ErrorName.PATH_EXISTS,
+ goog.fs.Error.ErrorCode.PATH_EXISTS,
+
+ goog.fs.Error.ErrorName.QUOTA_EXCEEDED,
+ goog.fs.Error.ErrorCode.QUOTA_EXCEEDED,
+
+ goog.fs.Error.ErrorName.SECURITY,
+ goog.fs.Error.ErrorCode.SECURITY,
+
+ goog.fs.Error.ErrorName.SYNTAX,
+ goog.fs.Error.ErrorCode.SYNTAX,
+
+ goog.fs.Error.ErrorName.TYPE_MISMATCH,
+ goog.fs.Error.ErrorCode.TYPE_MISMATCH);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/filereader.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/filereader.js b/externs/GCL/externs/goog/fs/filereader.js
new file mode 100644
index 0000000..14d5245
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/filereader.js
@@ -0,0 +1,288 @@
+// 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 A wrapper for the HTML5 FileReader object.
+ *
+ */
+
+goog.provide('goog.fs.FileReader');
+goog.provide('goog.fs.FileReader.EventType');
+goog.provide('goog.fs.FileReader.ReadyState');
+
+goog.require('goog.async.Deferred');
+goog.require('goog.events.EventTarget');
+goog.require('goog.fs.Error');
+goog.require('goog.fs.ProgressEvent');
+
+
+
+/**
+ * An object for monitoring the reading of files. This emits ProgressEvents of
+ * the types listed in {@link goog.fs.FileReader.EventType}.
+ *
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.fs.FileReader = function() {
+ goog.fs.FileReader.base(this, 'constructor');
+
+ /**
+ * The underlying FileReader object.
+ *
+ * @type {!FileReader}
+ * @private
+ */
+ this.reader_ = new FileReader();
+
+ this.reader_.onloadstart = goog.bind(this.dispatchProgressEvent_, this);
+ this.reader_.onprogress = goog.bind(this.dispatchProgressEvent_, this);
+ this.reader_.onload = goog.bind(this.dispatchProgressEvent_, this);
+ this.reader_.onabort = goog.bind(this.dispatchProgressEvent_, this);
+ this.reader_.onerror = goog.bind(this.dispatchProgressEvent_, this);
+ this.reader_.onloadend = goog.bind(this.dispatchProgressEvent_, this);
+};
+goog.inherits(goog.fs.FileReader, goog.events.EventTarget);
+
+
+/**
+ * Possible states for a FileReader.
+ *
+ * @enum {number}
+ */
+goog.fs.FileReader.ReadyState = {
+ /**
+ * The object has been constructed, but there is no pending read.
+ */
+ INIT: 0,
+ /**
+ * Data is being read.
+ */
+ LOADING: 1,
+ /**
+ * The data has been read from the file, the read was aborted, or an error
+ * occurred.
+ */
+ DONE: 2
+};
+
+
+/**
+ * Events emitted by a FileReader.
+ *
+ * @enum {string}
+ */
+goog.fs.FileReader.EventType = {
+ /**
+ * Emitted when the reading begins. readyState will be LOADING.
+ */
+ LOAD_START: 'loadstart',
+ /**
+ * Emitted when progress has been made in reading the file. readyState will be
+ * LOADING.
+ */
+ PROGRESS: 'progress',
+ /**
+ * Emitted when the data has been successfully read. readyState will be
+ * LOADING.
+ */
+ LOAD: 'load',
+ /**
+ * Emitted when the reading has been aborted. readyState will be LOADING.
+ */
+ ABORT: 'abort',
+ /**
+ * Emitted when an error is encountered or the reading has been aborted.
+ * readyState will be LOADING.
+ */
+ ERROR: 'error',
+ /**
+ * Emitted when the reading is finished, whether successfully or not.
+ * readyState will be DONE.
+ */
+ LOAD_END: 'loadend'
+};
+
+
+/**
+ * Abort the reading of the file.
+ */
+goog.fs.FileReader.prototype.abort = function() {
+ try {
+ this.reader_.abort();
+ } catch (e) {
+ throw new goog.fs.Error(e, 'aborting read');
+ }
+};
+
+
+/**
+ * @return {goog.fs.FileReader.ReadyState} The current state of the FileReader.
+ */
+goog.fs.FileReader.prototype.getReadyState = function() {
+ return /** @type {goog.fs.FileReader.ReadyState} */ (this.reader_.readyState);
+};
+
+
+/**
+ * @return {*} The result of the file read.
+ */
+goog.fs.FileReader.prototype.getResult = function() {
+ return this.reader_.result;
+};
+
+
+/**
+ * @return {goog.fs.Error} The error encountered while reading, if any.
+ */
+goog.fs.FileReader.prototype.getError = function() {
+ return this.reader_.error &&
+ new goog.fs.Error(this.reader_.error, 'reading file');
+};
+
+
+/**
+ * Wrap a progress event emitted by the underlying file reader and re-emit it.
+ *
+ * @param {!ProgressEvent} event The underlying event.
+ * @private
+ */
+goog.fs.FileReader.prototype.dispatchProgressEvent_ = function(event) {
+ this.dispatchEvent(new goog.fs.ProgressEvent(event, this));
+};
+
+
+/** @override */
+goog.fs.FileReader.prototype.disposeInternal = function() {
+ goog.fs.FileReader.base(this, 'disposeInternal');
+ delete this.reader_;
+};
+
+
+/**
+ * Starts reading a blob as a binary string.
+ * @param {!Blob} blob The blob to read.
+ */
+goog.fs.FileReader.prototype.readAsBinaryString = function(blob) {
+ this.reader_.readAsBinaryString(blob);
+};
+
+
+/**
+ * Reads a blob as a binary string.
+ * @param {!Blob} blob The blob to read.
+ * @return {!goog.async.Deferred} The deferred Blob contents as a binary string.
+ * If an error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileReader.readAsBinaryString = function(blob) {
+ var reader = new goog.fs.FileReader();
+ var d = goog.fs.FileReader.createDeferred_(reader);
+ reader.readAsBinaryString(blob);
+ return d;
+};
+
+
+/**
+ * Starts reading a blob as an array buffer.
+ * @param {!Blob} blob The blob to read.
+ */
+goog.fs.FileReader.prototype.readAsArrayBuffer = function(blob) {
+ this.reader_.readAsArrayBuffer(blob);
+};
+
+
+/**
+ * Reads a blob as an array buffer.
+ * @param {!Blob} blob The blob to read.
+ * @return {!goog.async.Deferred} The deferred Blob contents as an array buffer.
+ * If an error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileReader.readAsArrayBuffer = function(blob) {
+ var reader = new goog.fs.FileReader();
+ var d = goog.fs.FileReader.createDeferred_(reader);
+ reader.readAsArrayBuffer(blob);
+ return d;
+};
+
+
+/**
+ * Starts reading a blob as text.
+ * @param {!Blob} blob The blob to read.
+ * @param {string=} opt_encoding The name of the encoding to use.
+ */
+goog.fs.FileReader.prototype.readAsText = function(blob, opt_encoding) {
+ this.reader_.readAsText(blob, opt_encoding);
+};
+
+
+/**
+ * Reads a blob as text.
+ * @param {!Blob} blob The blob to read.
+ * @param {string=} opt_encoding The name of the encoding to use.
+ * @return {!goog.async.Deferred} The deferred Blob contents as text.
+ * If an error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileReader.readAsText = function(blob, opt_encoding) {
+ var reader = new goog.fs.FileReader();
+ var d = goog.fs.FileReader.createDeferred_(reader);
+ reader.readAsText(blob, opt_encoding);
+ return d;
+};
+
+
+/**
+ * Starts reading a blob as a data URL.
+ * @param {!Blob} blob The blob to read.
+ */
+goog.fs.FileReader.prototype.readAsDataUrl = function(blob) {
+ this.reader_.readAsDataURL(blob);
+};
+
+
+/**
+ * Reads a blob as a data URL.
+ * @param {!Blob} blob The blob to read.
+ * @return {!goog.async.Deferred} The deferred Blob contents as a data URL.
+ * If an error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.FileReader.readAsDataUrl = function(blob) {
+ var reader = new goog.fs.FileReader();
+ var d = goog.fs.FileReader.createDeferred_(reader);
+ reader.readAsDataUrl(blob);
+ return d;
+};
+
+
+/**
+ * Creates a new deferred object for the results of a read method.
+ * @param {goog.fs.FileReader} reader The reader to create a deferred for.
+ * @return {!goog.async.Deferred} The deferred results.
+ * @private
+ */
+goog.fs.FileReader.createDeferred_ = function(reader) {
+ var deferred = new goog.async.Deferred();
+ reader.listen(goog.fs.FileReader.EventType.LOAD_END,
+ goog.partial(function(d, r, e) {
+ var result = r.getResult();
+ var error = r.getError();
+ if (result != null && !error) {
+ d.callback(result);
+ } else {
+ d.errback(error);
+ }
+ r.dispose();
+ }, deferred, reader));
+ return deferred;
+};
[48/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/asserts/asserts.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/asserts/asserts.js b/externs/GCL/externs/goog/asserts/asserts.js
new file mode 100644
index 0000000..95513d1
--- /dev/null
+++ b/externs/GCL/externs/goog/asserts/asserts.js
@@ -0,0 +1,365 @@
+// 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 to check the preconditions, postconditions and
+ * invariants runtime.
+ *
+ * Methods in this package should be given special treatment by the compiler
+ * for type-inference. For example, <code>goog.asserts.assert(foo)</code>
+ * will restrict <code>foo</code> to a truthy value.
+ *
+ * The compiler has an option to disable asserts. So code like:
+ * <code>
+ * var x = goog.asserts.assert(foo()); goog.asserts.assert(bar());
+ * </code>
+ * will be transformed into:
+ * <code>
+ * var x = foo();
+ * </code>
+ * The compiler will leave in foo() (because its return value is used),
+ * but it will remove bar() because it assumes it does not have side-effects.
+ *
+ * @author agrieve@google.com (Andrew Grieve)
+ */
+
+goog.provide('goog.asserts');
+goog.provide('goog.asserts.AssertionError');
+
+goog.require('goog.debug.Error');
+goog.require('goog.dom.NodeType');
+goog.require('goog.string');
+
+
+/**
+ * @define {boolean} Whether to strip out asserts or to leave them in.
+ */
+goog.define('goog.asserts.ENABLE_ASSERTS', goog.DEBUG);
+
+
+
+/**
+ * Error object for failed assertions.
+ * @param {string} messagePattern The pattern that was used to form message.
+ * @param {!Array<*>} messageArgs The items to substitute into the pattern.
+ * @constructor
+ * @extends {goog.debug.Error}
+ * @final
+ */
+goog.asserts.AssertionError = function(messagePattern, messageArgs) {
+ messageArgs.unshift(messagePattern);
+ goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs));
+ // Remove the messagePattern afterwards to avoid permenantly modifying the
+ // passed in array.
+ messageArgs.shift();
+
+ /**
+ * The message pattern used to format the error message. Error handlers can
+ * use this to uniquely identify the assertion.
+ * @type {string}
+ */
+ this.messagePattern = messagePattern;
+};
+goog.inherits(goog.asserts.AssertionError, goog.debug.Error);
+
+
+/** @override */
+goog.asserts.AssertionError.prototype.name = 'AssertionError';
+
+
+/**
+ * The default error handler.
+ * @param {!goog.asserts.AssertionError} e The exception to be handled.
+ */
+goog.asserts.DEFAULT_ERROR_HANDLER = function(e) { throw e; };
+
+
+/**
+ * The handler responsible for throwing or logging assertion errors.
+ * @private {function(!goog.asserts.AssertionError)}
+ */
+goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER;
+
+
+/**
+ * Throws an exception with the given message and "Assertion failed" prefixed
+ * onto it.
+ * @param {string} defaultMessage The message to use if givenMessage is empty.
+ * @param {Array<*>} defaultArgs The substitution arguments for defaultMessage.
+ * @param {string|undefined} givenMessage Message supplied by the caller.
+ * @param {Array<*>} givenArgs The substitution arguments for givenMessage.
+ * @throws {goog.asserts.AssertionError} When the value is not a number.
+ * @private
+ */
+goog.asserts.doAssertFailure_ =
+ function(defaultMessage, defaultArgs, givenMessage, givenArgs) {
+ var message = 'Assertion failed';
+ if (givenMessage) {
+ message += ': ' + givenMessage;
+ var args = givenArgs;
+ } else if (defaultMessage) {
+ message += ': ' + defaultMessage;
+ args = defaultArgs;
+ }
+ // The '' + works around an Opera 10 bug in the unit tests. Without it,
+ // a stack trace is added to var message above. With this, a stack trace is
+ // not added until this line (it causes the extra garbage to be added after
+ // the assertion message instead of in the middle of it).
+ var e = new goog.asserts.AssertionError('' + message, args || []);
+ goog.asserts.errorHandler_(e);
+};
+
+
+/**
+ * Sets a custom error handler that can be used to customize the behavior of
+ * assertion failures, for example by turning all assertion failures into log
+ * messages.
+ * @param {function(!goog.asserts.AssertionError)} errorHandler
+ */
+goog.asserts.setErrorHandler = function(errorHandler) {
+ if (goog.asserts.ENABLE_ASSERTS) {
+ goog.asserts.errorHandler_ = errorHandler;
+ }
+};
+
+
+/**
+ * Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is
+ * true.
+ * @template T
+ * @param {T} condition The condition to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {T} The value of the condition.
+ * @throws {goog.asserts.AssertionError} When the condition evaluates to false.
+ */
+goog.asserts.assert = function(condition, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !condition) {
+ goog.asserts.doAssertFailure_('', null, opt_message,
+ Array.prototype.slice.call(arguments, 2));
+ }
+ return condition;
+};
+
+
+/**
+ * Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case
+ * when we want to add a check in the unreachable area like switch-case
+ * statement:
+ *
+ * <pre>
+ * switch(type) {
+ * case FOO: doSomething(); break;
+ * case BAR: doSomethingElse(); break;
+ * default: goog.assert.fail('Unrecognized type: ' + type);
+ * // We have only 2 types - "default:" section is unreachable code.
+ * }
+ * </pre>
+ *
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @throws {goog.asserts.AssertionError} Failure.
+ */
+goog.asserts.fail = function(opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS) {
+ goog.asserts.errorHandler_(new goog.asserts.AssertionError(
+ 'Failure' + (opt_message ? ': ' + opt_message : ''),
+ Array.prototype.slice.call(arguments, 1)));
+ }
+};
+
+
+/**
+ * Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true.
+ * @param {*} value The value to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {number} The value, guaranteed to be a number when asserts enabled.
+ * @throws {goog.asserts.AssertionError} When the value is not a number.
+ */
+goog.asserts.assertNumber = function(value, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) {
+ goog.asserts.doAssertFailure_('Expected number but got %s: %s.',
+ [goog.typeOf(value), value], opt_message,
+ Array.prototype.slice.call(arguments, 2));
+ }
+ return /** @type {number} */ (value);
+};
+
+
+/**
+ * Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true.
+ * @param {*} value The value to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {string} The value, guaranteed to be a string when asserts enabled.
+ * @throws {goog.asserts.AssertionError} When the value is not a string.
+ */
+goog.asserts.assertString = function(value, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) {
+ goog.asserts.doAssertFailure_('Expected string but got %s: %s.',
+ [goog.typeOf(value), value], opt_message,
+ Array.prototype.slice.call(arguments, 2));
+ }
+ return /** @type {string} */ (value);
+};
+
+
+/**
+ * Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true.
+ * @param {*} value The value to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {!Function} The value, guaranteed to be a function when asserts
+ * enabled.
+ * @throws {goog.asserts.AssertionError} When the value is not a function.
+ */
+goog.asserts.assertFunction = function(value, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) {
+ goog.asserts.doAssertFailure_('Expected function but got %s: %s.',
+ [goog.typeOf(value), value], opt_message,
+ Array.prototype.slice.call(arguments, 2));
+ }
+ return /** @type {!Function} */ (value);
+};
+
+
+/**
+ * Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true.
+ * @param {*} value The value to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {!Object} The value, guaranteed to be a non-null object.
+ * @throws {goog.asserts.AssertionError} When the value is not an object.
+ */
+goog.asserts.assertObject = function(value, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) {
+ goog.asserts.doAssertFailure_('Expected object but got %s: %s.',
+ [goog.typeOf(value), value],
+ opt_message, Array.prototype.slice.call(arguments, 2));
+ }
+ return /** @type {!Object} */ (value);
+};
+
+
+/**
+ * Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true.
+ * @param {*} value The value to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {!Array<?>} The value, guaranteed to be a non-null array.
+ * @throws {goog.asserts.AssertionError} When the value is not an array.
+ */
+goog.asserts.assertArray = function(value, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) {
+ goog.asserts.doAssertFailure_('Expected array but got %s: %s.',
+ [goog.typeOf(value), value], opt_message,
+ Array.prototype.slice.call(arguments, 2));
+ }
+ return /** @type {!Array<?>} */ (value);
+};
+
+
+/**
+ * Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true.
+ * @param {*} value The value to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {boolean} The value, guaranteed to be a boolean when asserts are
+ * enabled.
+ * @throws {goog.asserts.AssertionError} When the value is not a boolean.
+ */
+goog.asserts.assertBoolean = function(value, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) {
+ goog.asserts.doAssertFailure_('Expected boolean but got %s: %s.',
+ [goog.typeOf(value), value], opt_message,
+ Array.prototype.slice.call(arguments, 2));
+ }
+ return /** @type {boolean} */ (value);
+};
+
+
+/**
+ * Checks if the value is a DOM Element if goog.asserts.ENABLE_ASSERTS is true.
+ * @param {*} value The value to check.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @return {!Element} The value, likely to be a DOM Element when asserts are
+ * enabled.
+ * @throws {goog.asserts.AssertionError} When the value is not an Element.
+ */
+goog.asserts.assertElement = function(value, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && (!goog.isObject(value) ||
+ value.nodeType != goog.dom.NodeType.ELEMENT)) {
+ goog.asserts.doAssertFailure_('Expected Element but got %s: %s.',
+ [goog.typeOf(value), value], opt_message,
+ Array.prototype.slice.call(arguments, 2));
+ }
+ return /** @type {!Element} */ (value);
+};
+
+
+/**
+ * Checks if the value is an instance of the user-defined type if
+ * goog.asserts.ENABLE_ASSERTS is true.
+ *
+ * The compiler may tighten the type returned by this function.
+ *
+ * @param {*} value The value to check.
+ * @param {function(new: T, ...)} type A user-defined constructor.
+ * @param {string=} opt_message Error message in case of failure.
+ * @param {...*} var_args The items to substitute into the failure message.
+ * @throws {goog.asserts.AssertionError} When the value is not an instance of
+ * type.
+ * @return {T}
+ * @template T
+ */
+goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) {
+ if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) {
+ goog.asserts.doAssertFailure_('Expected instanceof %s but got %s.',
+ [goog.asserts.getType_(type), goog.asserts.getType_(value)],
+ opt_message, Array.prototype.slice.call(arguments, 3));
+ }
+ return value;
+};
+
+
+/**
+ * Checks that no enumerable keys are present in Object.prototype. Such keys
+ * would break most code that use {@code for (var ... in ...)} loops.
+ */
+goog.asserts.assertObjectPrototypeIsIntact = function() {
+ for (var key in Object.prototype) {
+ goog.asserts.fail(key + ' should not be enumerable in Object.prototype.');
+ }
+};
+
+
+/**
+ * Returns the type of a value. If a constructor is passed, and a suitable
+ * string cannot be found, 'unknown type name' will be returned.
+ * @param {*} value A constructor, object, or primitive.
+ * @return {string} The best display name for the value, or 'unknown type name'.
+ * @private
+ */
+goog.asserts.getType_ = function(value) {
+ if (value instanceof Function) {
+ return value.displayName || value.name || 'unknown type name';
+ } else if (value instanceof Object) {
+ return value.constructor.displayName || value.constructor.name ||
+ Object.prototype.toString.call(value);
+ } else {
+ return value === null ? 'null' : typeof value;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/animationdelay.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/animationdelay.js b/externs/GCL/externs/goog/async/animationdelay.js
new file mode 100644
index 0000000..1e24b34
--- /dev/null
+++ b/externs/GCL/externs/goog/async/animationdelay.js
@@ -0,0 +1,267 @@
+// Copyright 2012 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 delayed callback that pegs to the next animation frame
+ * instead of a user-configurable timeout.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.async.AnimationDelay');
+
+goog.require('goog.Disposable');
+goog.require('goog.events');
+goog.require('goog.functions');
+
+
+
+// TODO(nicksantos): Should we factor out the common code between this and
+// goog.async.Delay? I'm not sure if there's enough code for this to really
+// make sense. Subclassing seems like the wrong approach for a variety of
+// reasons. Maybe there should be a common interface?
+
+
+
+/**
+ * A delayed callback that pegs to the next animation frame
+ * instead of a user configurable timeout. By design, this should have
+ * the same interface as goog.async.Delay.
+ *
+ * Uses requestAnimationFrame and friends when available, but falls
+ * back to a timeout of goog.async.AnimationDelay.TIMEOUT.
+ *
+ * For more on requestAnimationFrame and how you can use it to create smoother
+ * animations, see:
+ * @see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+ *
+ * @param {function(number)} listener Function to call when the delay completes.
+ * Will be passed the timestamp when it's called, in unix ms.
+ * @param {Window=} opt_window The window object to execute the delay in.
+ * Defaults to the global object.
+ * @param {Object=} opt_handler The object scope to invoke the function in.
+ * @constructor
+ * @struct
+ * @suppress {checkStructDictInheritance}
+ * @extends {goog.Disposable}
+ * @final
+ */
+goog.async.AnimationDelay = function(listener, opt_window, opt_handler) {
+ goog.async.AnimationDelay.base(this, 'constructor');
+
+ /**
+ * Identifier of the active delay timeout, or event listener,
+ * or null when inactive.
+ * @private {goog.events.Key|number}
+ */
+ this.id_ = null;
+
+ /**
+ * If we're using dom listeners.
+ * @private {?boolean}
+ */
+ this.usingListeners_ = false;
+
+ /**
+ * The function that will be invoked after a delay.
+ * @private {function(number)}
+ */
+ this.listener_ = listener;
+
+ /**
+ * The object context to invoke the callback in.
+ * @private {Object|undefined}
+ */
+ this.handler_ = opt_handler;
+
+ /**
+ * @private {Window}
+ */
+ this.win_ = opt_window || window;
+
+ /**
+ * Cached callback function invoked when the delay finishes.
+ * @private {function()}
+ */
+ this.callback_ = goog.bind(this.doAction_, this);
+};
+goog.inherits(goog.async.AnimationDelay, goog.Disposable);
+
+
+/**
+ * Default wait timeout for animations (in milliseconds). Only used for timed
+ * animation, which uses a timer (setTimeout) to schedule animation.
+ *
+ * @type {number}
+ * @const
+ */
+goog.async.AnimationDelay.TIMEOUT = 20;
+
+
+/**
+ * Name of event received from the requestAnimationFrame in Firefox.
+ *
+ * @type {string}
+ * @const
+ * @private
+ */
+goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_ = 'MozBeforePaint';
+
+
+/**
+ * Starts the delay timer. The provided listener function will be called
+ * before the next animation frame.
+ */
+goog.async.AnimationDelay.prototype.start = function() {
+ this.stop();
+ this.usingListeners_ = false;
+
+ var raf = this.getRaf_();
+ var cancelRaf = this.getCancelRaf_();
+ if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
+ // Because Firefox (Gecko) runs animation in separate threads, it also saves
+ // time by running the requestAnimationFrame callbacks in that same thread.
+ // Sadly this breaks the assumption of implicit thread-safety in JS, and can
+ // thus create thread-based inconsistencies on counters etc.
+ //
+ // Calling cycleAnimations_ using the MozBeforePaint event instead of as
+ // callback fixes this.
+ //
+ // Trigger this condition only if the mozRequestAnimationFrame is available,
+ // but not the W3C requestAnimationFrame function (as in draft) or the
+ // equivalent cancel functions.
+ this.id_ = goog.events.listen(
+ this.win_,
+ goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_,
+ this.callback_);
+ this.win_.mozRequestAnimationFrame(null);
+ this.usingListeners_ = true;
+ } else if (raf && cancelRaf) {
+ this.id_ = raf.call(this.win_, this.callback_);
+ } else {
+ this.id_ = this.win_.setTimeout(
+ // Prior to Firefox 13, Gecko passed a non-standard parameter
+ // to the callback that we want to ignore.
+ goog.functions.lock(this.callback_),
+ goog.async.AnimationDelay.TIMEOUT);
+ }
+};
+
+
+/**
+ * Stops the delay timer if it is active. No action is taken if the timer is not
+ * in use.
+ */
+goog.async.AnimationDelay.prototype.stop = function() {
+ if (this.isActive()) {
+ var raf = this.getRaf_();
+ var cancelRaf = this.getCancelRaf_();
+ if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
+ goog.events.unlistenByKey(this.id_);
+ } else if (raf && cancelRaf) {
+ cancelRaf.call(this.win_, /** @type {number} */ (this.id_));
+ } else {
+ this.win_.clearTimeout(/** @type {number} */ (this.id_));
+ }
+ }
+ this.id_ = null;
+};
+
+
+/**
+ * Fires delay's action even if timer has already gone off or has not been
+ * started yet; guarantees action firing. Stops the delay timer.
+ */
+goog.async.AnimationDelay.prototype.fire = function() {
+ this.stop();
+ this.doAction_();
+};
+
+
+/**
+ * Fires delay's action only if timer is currently active. Stops the delay
+ * timer.
+ */
+goog.async.AnimationDelay.prototype.fireIfActive = function() {
+ if (this.isActive()) {
+ this.fire();
+ }
+};
+
+
+/**
+ * @return {boolean} True if the delay is currently active, false otherwise.
+ */
+goog.async.AnimationDelay.prototype.isActive = function() {
+ return this.id_ != null;
+};
+
+
+/**
+ * Invokes the callback function after the delay successfully completes.
+ * @private
+ */
+goog.async.AnimationDelay.prototype.doAction_ = function() {
+ if (this.usingListeners_ && this.id_) {
+ goog.events.unlistenByKey(this.id_);
+ }
+ this.id_ = null;
+
+ // We are not using the timestamp returned by requestAnimationFrame
+ // because it may be either a Date.now-style time or a
+ // high-resolution time (depending on browser implementation). Using
+ // goog.now() will ensure that the timestamp used is consistent and
+ // compatible with goog.fx.Animation.
+ this.listener_.call(this.handler_, goog.now());
+};
+
+
+/** @override */
+goog.async.AnimationDelay.prototype.disposeInternal = function() {
+ this.stop();
+ goog.async.AnimationDelay.base(this, 'disposeInternal');
+};
+
+
+/**
+ * @return {?function(function(number)): number} The requestAnimationFrame
+ * function, or null if not available on this browser.
+ * @private
+ */
+goog.async.AnimationDelay.prototype.getRaf_ = function() {
+ var win = this.win_;
+ return win.requestAnimationFrame ||
+ win.webkitRequestAnimationFrame ||
+ win.mozRequestAnimationFrame ||
+ win.oRequestAnimationFrame ||
+ win.msRequestAnimationFrame ||
+ null;
+};
+
+
+/**
+ * @return {?function(number): number} The cancelAnimationFrame function,
+ * or null if not available on this browser.
+ * @private
+ */
+goog.async.AnimationDelay.prototype.getCancelRaf_ = function() {
+ var win = this.win_;
+ return win.cancelAnimationFrame ||
+ win.cancelRequestAnimationFrame ||
+ win.webkitCancelRequestAnimationFrame ||
+ win.mozCancelRequestAnimationFrame ||
+ win.oCancelRequestAnimationFrame ||
+ win.msCancelRequestAnimationFrame ||
+ null;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/conditionaldelay.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/conditionaldelay.js b/externs/GCL/externs/goog/async/conditionaldelay.js
new file mode 100644
index 0000000..c5ff892
--- /dev/null
+++ b/externs/GCL/externs/goog/async/conditionaldelay.js
@@ -0,0 +1,228 @@
+// 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 Defines a class useful for handling functions that must be
+ * invoked later when some condition holds. Examples include deferred function
+ * calls that return a boolean flag whether it succedeed or not.
+ *
+ * Example:
+ *
+ * function deferred() {
+ * var succeeded = false;
+ * // ... custom code
+ * return succeeded;
+ * }
+ *
+ * var deferredCall = new goog.async.ConditionalDelay(deferred);
+ * deferredCall.onSuccess = function() {
+ * alert('Success: The deferred function has been successfully executed.');
+ * }
+ * deferredCall.onFailure = function() {
+ * alert('Failure: Time limit exceeded.');
+ * }
+ *
+ * // Call the deferred() every 100 msec until it returns true,
+ * // or 5 seconds pass.
+ * deferredCall.start(100, 5000);
+ *
+ * // Stop the deferred function call (does nothing if it's not active).
+ * deferredCall.stop();
+ *
+ */
+
+
+goog.provide('goog.async.ConditionalDelay');
+
+goog.require('goog.Disposable');
+goog.require('goog.async.Delay');
+
+
+
+/**
+ * A ConditionalDelay object invokes the associated function after a specified
+ * interval delay and checks its return value. If the function returns
+ * {@code true} the conditional delay is cancelled and {@see #onSuccess}
+ * is called. Otherwise this object keeps to invoke the deferred function until
+ * either it returns {@code true} or the timeout is exceeded. In the latter case
+ * the {@see #onFailure} method will be called.
+ *
+ * The interval duration and timeout can be specified each time the delay is
+ * started. Calling start on an active delay will reset the timer.
+ *
+ * @param {function():boolean} listener Function to call when the delay
+ * completes. Should return a value that type-converts to {@code true} if
+ * the call succeeded and this delay should be stopped.
+ * @param {Object=} opt_handler The object scope to invoke the function in.
+ * @constructor
+ * @struct
+ * @suppress {checkStructDictInheritance}
+ * @extends {goog.Disposable}
+ */
+goog.async.ConditionalDelay = function(listener, opt_handler) {
+ goog.async.ConditionalDelay.base(this, 'constructor');
+
+ /**
+ * The delay interval in milliseconds to between the calls to the callback.
+ * Note, that the callback may be invoked earlier than this interval if the
+ * timeout is exceeded.
+ * @private {number}
+ */
+ this.interval_ = 0;
+
+ /**
+ * The timeout timestamp until which the delay is to be executed.
+ * A negative value means no timeout.
+ * @private {number}
+ */
+ this.runUntil_ = 0;
+
+ /**
+ * True if the listener has been executed, and it returned {@code true}.
+ * @private {boolean}
+ */
+ this.isDone_ = false;
+
+ /**
+ * The function that will be invoked after a delay.
+ * @private {function():boolean}
+ */
+ this.listener_ = listener;
+
+ /**
+ * The object context to invoke the callback in.
+ * @private {Object|undefined}
+ */
+ this.handler_ = opt_handler;
+
+ /**
+ * The underlying goog.async.Delay delegate object.
+ * @private {goog.async.Delay}
+ */
+ this.delay_ = new goog.async.Delay(
+ goog.bind(this.onTick_, this), 0 /*interval*/, this /*scope*/);
+};
+goog.inherits(goog.async.ConditionalDelay, goog.Disposable);
+
+
+/** @override */
+goog.async.ConditionalDelay.prototype.disposeInternal = function() {
+ this.delay_.dispose();
+ delete this.listener_;
+ delete this.handler_;
+ goog.async.ConditionalDelay.superClass_.disposeInternal.call(this);
+};
+
+
+/**
+ * Starts the delay timer. The provided listener function will be called
+ * repeatedly after the specified interval until the function returns
+ * {@code true} or the timeout is exceeded. Calling start on an active timer
+ * will stop the timer first.
+ * @param {number=} opt_interval The time interval between the function
+ * invocations (in milliseconds). Default is 0.
+ * @param {number=} opt_timeout The timeout interval (in milliseconds). Takes
+ * precedence over the {@code opt_interval}, i.e. if the timeout is less
+ * than the invocation interval, the function will be called when the
+ * timeout is exceeded. A negative value means no timeout. Default is 0.
+ */
+goog.async.ConditionalDelay.prototype.start = function(opt_interval,
+ opt_timeout) {
+ this.stop();
+ this.isDone_ = false;
+
+ var timeout = opt_timeout || 0;
+ this.interval_ = Math.max(opt_interval || 0, 0);
+ this.runUntil_ = timeout < 0 ? -1 : (goog.now() + timeout);
+ this.delay_.start(
+ timeout < 0 ? this.interval_ : Math.min(this.interval_, timeout));
+};
+
+
+/**
+ * Stops the delay timer if it is active. No action is taken if the timer is not
+ * in use.
+ */
+goog.async.ConditionalDelay.prototype.stop = function() {
+ this.delay_.stop();
+};
+
+
+/**
+ * @return {boolean} True if the delay is currently active, false otherwise.
+ */
+goog.async.ConditionalDelay.prototype.isActive = function() {
+ return this.delay_.isActive();
+};
+
+
+/**
+ * @return {boolean} True if the listener has been executed and returned
+ * {@code true} since the last call to {@see #start}.
+ */
+goog.async.ConditionalDelay.prototype.isDone = function() {
+ return this.isDone_;
+};
+
+
+/**
+ * Called when the listener has been successfully executed and returned
+ * {@code true}. The {@see #isDone} method should return {@code true} by now.
+ * Designed for inheritance, should be overridden by subclasses or on the
+ * instances if they care.
+ */
+goog.async.ConditionalDelay.prototype.onSuccess = function() {
+ // Do nothing by default.
+};
+
+
+/**
+ * Called when this delayed call is cancelled because the timeout has been
+ * exceeded, and the listener has never returned {@code true}.
+ * Designed for inheritance, should be overridden by subclasses or on the
+ * instances if they care.
+ */
+goog.async.ConditionalDelay.prototype.onFailure = function() {
+ // Do nothing by default.
+};
+
+
+/**
+ * A callback function for the underlying {@code goog.async.Delay} object. When
+ * executed the listener function is called, and if it returns {@code true}
+ * the delay is stopped and the {@see #onSuccess} method is invoked.
+ * If the timeout is exceeded the delay is stopped and the
+ * {@see #onFailure} method is called.
+ * @private
+ */
+goog.async.ConditionalDelay.prototype.onTick_ = function() {
+ var successful = this.listener_.call(this.handler_);
+ if (successful) {
+ this.isDone_ = true;
+ this.onSuccess();
+ } else {
+ // Try to reschedule the task.
+ if (this.runUntil_ < 0) {
+ // No timeout.
+ this.delay_.start(this.interval_);
+ } else {
+ var timeLeft = this.runUntil_ - goog.now();
+ if (timeLeft <= 0) {
+ this.onFailure();
+ } else {
+ this.delay_.start(Math.min(this.interval_, timeLeft));
+ }
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/delay.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/delay.js b/externs/GCL/externs/goog/async/delay.js
new file mode 100644
index 0000000..0b8225d
--- /dev/null
+++ b/externs/GCL/externs/goog/async/delay.js
@@ -0,0 +1,182 @@
+// 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 Defines a class useful for handling functions that must be
+ * invoked after a delay, especially when that delay is frequently restarted.
+ * Examples include delaying before displaying a tooltip, menu hysteresis,
+ * idle timers, etc.
+ * @author brenneman@google.com (Shawn Brenneman)
+ * @see ../demos/timers.html
+ */
+
+
+goog.provide('goog.Delay');
+goog.provide('goog.async.Delay');
+
+goog.require('goog.Disposable');
+goog.require('goog.Timer');
+
+
+
+/**
+ * A Delay object invokes the associated function after a specified delay. The
+ * interval duration can be specified once in the constructor, or can be defined
+ * each time the delay is started. Calling start on an active delay will reset
+ * the timer.
+ *
+ * @param {function(this:THIS)} listener Function to call when the
+ * delay completes.
+ * @param {number=} opt_interval The default length of the invocation delay (in
+ * milliseconds).
+ * @param {THIS=} opt_handler The object scope to invoke the function in.
+ * @template THIS
+ * @constructor
+ * @struct
+ * @suppress {checkStructDictInheritance}
+ * @extends {goog.Disposable}
+ * @final
+ */
+goog.async.Delay = function(listener, opt_interval, opt_handler) {
+ goog.async.Delay.base(this, 'constructor');
+
+ /**
+ * The function that will be invoked after a delay.
+ * @private {function(this:THIS)}
+ */
+ this.listener_ = listener;
+
+ /**
+ * The default amount of time to delay before invoking the callback.
+ * @type {number}
+ * @private
+ */
+ this.interval_ = opt_interval || 0;
+
+ /**
+ * The object context to invoke the callback in.
+ * @type {Object|undefined}
+ * @private
+ */
+ this.handler_ = opt_handler;
+
+
+ /**
+ * Cached callback function invoked when the delay finishes.
+ * @type {Function}
+ * @private
+ */
+ this.callback_ = goog.bind(this.doAction_, this);
+};
+goog.inherits(goog.async.Delay, goog.Disposable);
+
+
+
+/**
+ * A deprecated alias.
+ * @deprecated Use goog.async.Delay instead.
+ * @constructor
+ * @final
+ */
+goog.Delay = goog.async.Delay;
+
+
+/**
+ * Identifier of the active delay timeout, or 0 when inactive.
+ * @type {number}
+ * @private
+ */
+goog.async.Delay.prototype.id_ = 0;
+
+
+/**
+ * Disposes of the object, cancelling the timeout if it is still outstanding and
+ * removing all object references.
+ * @override
+ * @protected
+ */
+goog.async.Delay.prototype.disposeInternal = function() {
+ goog.async.Delay.base(this, 'disposeInternal');
+ this.stop();
+ delete this.listener_;
+ delete this.handler_;
+};
+
+
+/**
+ * Starts the delay timer. The provided listener function will be called after
+ * the specified interval. Calling start on an active timer will reset the
+ * delay interval.
+ * @param {number=} opt_interval If specified, overrides the object's default
+ * interval with this one (in milliseconds).
+ */
+goog.async.Delay.prototype.start = function(opt_interval) {
+ this.stop();
+ this.id_ = goog.Timer.callOnce(
+ this.callback_,
+ goog.isDef(opt_interval) ? opt_interval : this.interval_);
+};
+
+
+/**
+ * Stops the delay timer if it is active. No action is taken if the timer is not
+ * in use.
+ */
+goog.async.Delay.prototype.stop = function() {
+ if (this.isActive()) {
+ goog.Timer.clear(this.id_);
+ }
+ this.id_ = 0;
+};
+
+
+/**
+ * Fires delay's action even if timer has already gone off or has not been
+ * started yet; guarantees action firing. Stops the delay timer.
+ */
+goog.async.Delay.prototype.fire = function() {
+ this.stop();
+ this.doAction_();
+};
+
+
+/**
+ * Fires delay's action only if timer is currently active. Stops the delay
+ * timer.
+ */
+goog.async.Delay.prototype.fireIfActive = function() {
+ if (this.isActive()) {
+ this.fire();
+ }
+};
+
+
+/**
+ * @return {boolean} True if the delay is currently active, false otherwise.
+ */
+goog.async.Delay.prototype.isActive = function() {
+ return this.id_ != 0;
+};
+
+
+/**
+ * Invokes the callback function after the delay successfully completes.
+ * @private
+ */
+goog.async.Delay.prototype.doAction_ = function() {
+ this.id_ = 0;
+ if (this.listener_) {
+ this.listener_.call(this.handler_);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/freelist.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/freelist.js b/externs/GCL/externs/goog/async/freelist.js
new file mode 100644
index 0000000..d0331f2
--- /dev/null
+++ b/externs/GCL/externs/goog/async/freelist.js
@@ -0,0 +1,88 @@
+// Copyright 2015 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 freelist.
+ *
+ * An anterative to goog.structs.SimplePool, it imposes the requirement that the
+ * objects in the list contain a "next" property that can be used to maintain
+ * the pool.
+ */
+
+goog.provide('goog.async.FreeList');
+
+
+/**
+ * @template ITEM
+ */
+goog.async.FreeList = goog.defineClass(null, {
+ /**
+ * @param {function():ITEM} create
+ * @param {function(ITEM):void} reset
+ * @param {number} limit
+ */
+ constructor: function(create, reset, limit) {
+ /** @const {number} */
+ this.limit_ = limit;
+ /** @const {function()} */
+ this.create_ = create;
+ /** @const {function(ITEM):void} */
+ this.reset_ = reset;
+
+ /** @type {number} */
+ this.occupants_ = 0;
+ /** @type {ITEM} */
+ this.head_ = null;
+ },
+
+ /**
+ * @return {ITEM}
+ */
+ get: function() {
+ var item;
+ if (this.occupants_ > 0) {
+ this.occupants_--;
+ item = this.head_;
+ this.head_ = item.next;
+ item.next = null;
+ } else {
+ item = this.create_();
+ }
+ return item;
+ },
+
+ /**
+ * @param {ITEM} item An item available for possible future reuse.
+ */
+ put: function(item) {
+ this.reset_(item);
+ if (this.occupants_ < this.limit_) {
+ this.occupants_++;
+ item.next = this.head_;
+ this.head_ = item;
+ }
+ },
+
+ /**
+ * Visible for testing.
+ * @package
+ * @return {number}
+ */
+ occupants: function() {
+ return this.occupants_;
+ }
+});
+
+
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/nexttick.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/nexttick.js b/externs/GCL/externs/goog/async/nexttick.js
new file mode 100644
index 0000000..bdbad6b
--- /dev/null
+++ b/externs/GCL/externs/goog/async/nexttick.js
@@ -0,0 +1,241 @@
+// 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 Provides a function to schedule running a function as soon
+ * as possible after the current JS execution stops and yields to the event
+ * loop.
+ *
+ */
+
+goog.provide('goog.async.nextTick');
+goog.provide('goog.async.throwException');
+
+goog.require('goog.debug.entryPointRegistry');
+goog.require('goog.dom.TagName');
+goog.require('goog.functions');
+goog.require('goog.labs.userAgent.browser');
+goog.require('goog.labs.userAgent.engine');
+
+
+/**
+ * Throw an item without interrupting the current execution context. For
+ * example, if processing a group of items in a loop, sometimes it is useful
+ * to report an error while still allowing the rest of the batch to be
+ * processed.
+ * @param {*} exception
+ */
+goog.async.throwException = function(exception) {
+ // Each throw needs to be in its own context.
+ goog.global.setTimeout(function() { throw exception; }, 0);
+};
+
+
+/**
+ * Fires the provided callbacks as soon as possible after the current JS
+ * execution context. setTimeout(…, 0) takes at least 4ms when called from
+ * within another setTimeout(…, 0) for legacy reasons.
+ *
+ * This will not schedule the callback as a microtask (i.e. a task that can
+ * preempt user input or networking callbacks). It is meant to emulate what
+ * setTimeout(_, 0) would do if it were not throttled. If you desire microtask
+ * behavior, use {@see goog.Promise} instead.
+ *
+ * @param {function(this:SCOPE)} callback Callback function to fire as soon as
+ * possible.
+ * @param {SCOPE=} opt_context Object in whose scope to call the listener.
+ * @param {boolean=} opt_useSetImmediate Avoid the IE workaround that
+ * ensures correctness at the cost of speed. See comments for details.
+ * @template SCOPE
+ */
+goog.async.nextTick = function(callback, opt_context, opt_useSetImmediate) {
+ var cb = callback;
+ if (opt_context) {
+ cb = goog.bind(callback, opt_context);
+ }
+ cb = goog.async.nextTick.wrapCallback_(cb);
+ // window.setImmediate was introduced and currently only supported by IE10+,
+ // but due to a bug in the implementation it is not guaranteed that
+ // setImmediate is faster than setTimeout nor that setImmediate N is before
+ // setImmediate N+1. That is why we do not use the native version if
+ // available. We do, however, call setImmediate if it is a normal function
+ // because that indicates that it has been replaced by goog.testing.MockClock
+ // which we do want to support.
+ // See
+ // http://connect.microsoft.com/IE/feedback/details/801823/setimmediate-and-messagechannel-are-broken-in-ie10
+ //
+ // Note we do allow callers to also request setImmediate if they are willing
+ // to accept the possible tradeoffs of incorrectness in exchange for speed.
+ // The IE fallback of readystate change is much slower.
+ if (goog.isFunction(goog.global.setImmediate) &&
+ // Opt in.
+ (opt_useSetImmediate ||
+ // or it isn't a browser or the environment is weird
+ !goog.global.Window || !goog.global.Window.prototype ||
+ // or something redefined setImmediate in which case we (YOLO) decide
+ // to use it (This is so that we use the mockClock setImmediate. sigh).
+ goog.global.Window.prototype.setImmediate != goog.global.setImmediate)) {
+ goog.global.setImmediate(cb);
+ return;
+ }
+
+ // Look for and cache the custom fallback version of setImmediate.
+ if (!goog.async.nextTick.setImmediate_) {
+ goog.async.nextTick.setImmediate_ =
+ goog.async.nextTick.getSetImmediateEmulator_();
+ }
+ goog.async.nextTick.setImmediate_(cb);
+};
+
+
+/**
+ * Cache for the setImmediate implementation.
+ * @type {function(function())}
+ * @private
+ */
+goog.async.nextTick.setImmediate_;
+
+
+/**
+ * Determines the best possible implementation to run a function as soon as
+ * the JS event loop is idle.
+ * @return {function(function())} The "setImmediate" implementation.
+ * @private
+ */
+goog.async.nextTick.getSetImmediateEmulator_ = function() {
+ // Create a private message channel and use it to postMessage empty messages
+ // to ourselves.
+ var Channel = goog.global['MessageChannel'];
+ // If MessageChannel is not available and we are in a browser, implement
+ // an iframe based polyfill in browsers that have postMessage and
+ // document.addEventListener. The latter excludes IE8 because it has a
+ // synchronous postMessage implementation.
+ if (typeof Channel === 'undefined' && typeof window !== 'undefined' &&
+ window.postMessage && window.addEventListener &&
+ // Presto (The old pre-blink Opera engine) has problems with iframes
+ // and contentWindow.
+ !goog.labs.userAgent.engine.isPresto()) {
+ /** @constructor */
+ Channel = function() {
+ // Make an empty, invisible iframe.
+ var iframe = document.createElement(goog.dom.TagName.IFRAME);
+ iframe.style.display = 'none';
+ iframe.src = '';
+ document.documentElement.appendChild(iframe);
+ var win = iframe.contentWindow;
+ var doc = win.document;
+ doc.open();
+ doc.write('');
+ doc.close();
+ // Do not post anything sensitive over this channel, as the workaround for
+ // pages with file: origin could allow that information to be modified or
+ // intercepted.
+ var message = 'callImmediate' + Math.random();
+ // The same origin policy rejects attempts to postMessage from file: urls
+ // unless the origin is '*'.
+ // TODO(b/16335441): Use '*' origin for data: and other similar protocols.
+ var origin = win.location.protocol == 'file:' ?
+ '*' : win.location.protocol + '//' + win.location.host;
+ var onmessage = goog.bind(function(e) {
+ // Validate origin and message to make sure that this message was
+ // intended for us. If the origin is set to '*' (see above) only the
+ // message needs to match since, for example, '*' != 'file://'. Allowing
+ // the wildcard is ok, as we are not concerned with security here.
+ if ((origin != '*' && e.origin != origin) || e.data != message) {
+ return;
+ }
+ this['port1'].onmessage();
+ }, this);
+ win.addEventListener('message', onmessage, false);
+ this['port1'] = {};
+ this['port2'] = {
+ postMessage: function() {
+ win.postMessage(message, origin);
+ }
+ };
+ };
+ }
+ if (typeof Channel !== 'undefined' &&
+ (!goog.labs.userAgent.browser.isIE())) {
+ // Exclude all of IE due to
+ // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/
+ // which allows starving postMessage with a busy setTimeout loop.
+ // This currently affects IE10 and IE11 which would otherwise be able
+ // to use the postMessage based fallbacks.
+ var channel = new Channel();
+ // Use a fifo linked list to call callbacks in the right order.
+ var head = {};
+ var tail = head;
+ channel['port1'].onmessage = function() {
+ if (goog.isDef(head.next)) {
+ head = head.next;
+ var cb = head.cb;
+ head.cb = null;
+ cb();
+ }
+ };
+ return function(cb) {
+ tail.next = {
+ cb: cb
+ };
+ tail = tail.next;
+ channel['port2'].postMessage(0);
+ };
+ }
+ // Implementation for IE6+: Script elements fire an asynchronous
+ // onreadystatechange event when inserted into the DOM.
+ if (typeof document !== 'undefined' && 'onreadystatechange' in
+ document.createElement(goog.dom.TagName.SCRIPT)) {
+ return function(cb) {
+ var script = document.createElement(goog.dom.TagName.SCRIPT);
+ script.onreadystatechange = function() {
+ // Clean up and call the callback.
+ script.onreadystatechange = null;
+ script.parentNode.removeChild(script);
+ script = null;
+ cb();
+ cb = null;
+ };
+ document.documentElement.appendChild(script);
+ };
+ }
+ // Fall back to setTimeout with 0. In browsers this creates a delay of 5ms
+ // or more.
+ return function(cb) {
+ goog.global.setTimeout(cb, 0);
+ };
+};
+
+
+/**
+ * Helper function that is overrided to protect callbacks with entry point
+ * monitor if the application monitors entry points.
+ * @param {function()} callback Callback function to fire as soon as possible.
+ * @return {function()} The wrapped callback.
+ * @private
+ */
+goog.async.nextTick.wrapCallback_ = goog.functions.identity;
+
+
+// Register the callback function as an entry point, so that it can be
+// monitored for exception handling, etc. This has to be done in this file
+// since it requires special code to handle all browsers.
+goog.debug.entryPointRegistry.register(
+ /**
+ * @param {function(!Function): !Function} transformer The transforming
+ * function.
+ */
+ function(transformer) {
+ goog.async.nextTick.wrapCallback_ = transformer;
+ });
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/run.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/run.js b/externs/GCL/externs/goog/async/run.js
new file mode 100644
index 0000000..b621477
--- /dev/null
+++ b/externs/GCL/externs/goog/async/run.js
@@ -0,0 +1,130 @@
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+goog.provide('goog.async.run');
+
+goog.require('goog.async.WorkQueue');
+goog.require('goog.async.nextTick');
+goog.require('goog.async.throwException');
+goog.require('goog.testing.watchers');
+
+
+/**
+ * Fires the provided callback just before the current callstack unwinds, or as
+ * soon as possible after the current JS execution context.
+ * @param {function(this:THIS)} callback
+ * @param {THIS=} opt_context Object to use as the "this value" when calling
+ * the provided function.
+ * @template THIS
+ */
+goog.async.run = function(callback, opt_context) {
+ if (!goog.async.run.schedule_) {
+ goog.async.run.initializeRunner_();
+ }
+ if (!goog.async.run.workQueueScheduled_) {
+ // Nothing is currently scheduled, schedule it now.
+ goog.async.run.schedule_();
+ goog.async.run.workQueueScheduled_ = true;
+ }
+
+ goog.async.run.workQueue_.add(callback, opt_context);
+};
+
+
+/**
+ * Initializes the function to use to process the work queue.
+ * @private
+ */
+goog.async.run.initializeRunner_ = function() {
+ // If native Promises are available in the browser, just schedule the callback
+ // on a fulfilled promise, which is specified to be async, but as fast as
+ // possible.
+ if (goog.global.Promise && goog.global.Promise.resolve) {
+ var promise = goog.global.Promise.resolve();
+ goog.async.run.schedule_ = function() {
+ promise.then(goog.async.run.processWorkQueue);
+ };
+ } else {
+ goog.async.run.schedule_ = function() {
+ goog.async.nextTick(goog.async.run.processWorkQueue);
+ };
+ }
+};
+
+
+/**
+ * Forces goog.async.run to use nextTick instead of Promise.
+ *
+ * This should only be done in unit tests. It's useful because MockClock
+ * replaces nextTick, but not the browser Promise implementation, so it allows
+ * Promise-based code to be tested with MockClock.
+ */
+goog.async.run.forceNextTick = function() {
+ goog.async.run.schedule_ = function() {
+ goog.async.nextTick(goog.async.run.processWorkQueue);
+ };
+};
+
+
+/**
+ * The function used to schedule work asynchronousely.
+ * @private {function()}
+ */
+goog.async.run.schedule_;
+
+
+/** @private {boolean} */
+goog.async.run.workQueueScheduled_ = false;
+
+
+/** @private {!goog.async.WorkQueue} */
+goog.async.run.workQueue_ = new goog.async.WorkQueue();
+
+
+if (goog.DEBUG) {
+ /**
+ * Reset the work queue.
+ * @private
+ */
+ goog.async.run.resetQueue_ = function() {
+ goog.async.run.workQueueScheduled_ = false;
+ goog.async.run.workQueue_ = new goog.async.WorkQueue();
+ };
+
+ // If there is a clock implemenation in use for testing
+ // and it is reset, reset the queue.
+ goog.testing.watchers.watchClockReset(goog.async.run.resetQueue_);
+}
+
+
+/**
+ * Run any pending goog.async.run work items. This function is not intended
+ * for general use, but for use by entry point handlers to run items ahead of
+ * goog.async.nextTick.
+ */
+goog.async.run.processWorkQueue = function() {
+ // NOTE: additional work queue items may be added while processing.
+ var item = null;
+ while (item = goog.async.run.workQueue_.remove()) {
+ try {
+ item.fn.call(item.scope);
+ } catch (e) {
+ goog.async.throwException(e);
+ }
+ goog.async.run.workQueue_.returnUnused(item);
+ }
+
+ // There are no more work items, allow processing to be scheduled again.
+ goog.async.run.workQueueScheduled_ = false;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/throttle.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/throttle.js b/externs/GCL/externs/goog/async/throttle.js
new file mode 100644
index 0000000..2efa119
--- /dev/null
+++ b/externs/GCL/externs/goog/async/throttle.js
@@ -0,0 +1,195 @@
+// 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 goog.async.Throttle class.
+ *
+ * @see ../demos/timers.html
+ */
+
+goog.provide('goog.Throttle');
+goog.provide('goog.async.Throttle');
+
+goog.require('goog.Disposable');
+goog.require('goog.Timer');
+
+
+
+/**
+ * Throttle will perform an action that is passed in no more than once
+ * per interval (specified in milliseconds). If it gets multiple signals
+ * to perform the action while it is waiting, it will only perform the action
+ * once at the end of the interval.
+ * @param {function(this: T)} listener Function to callback when the action is
+ * triggered.
+ * @param {number} interval Interval over which to throttle. The listener can
+ * only be called once per interval.
+ * @param {T=} opt_handler Object in whose scope to call the listener.
+ * @constructor
+ * @struct
+ * @suppress {checkStructDictInheritance}
+ * @extends {goog.Disposable}
+ * @final
+ * @template T
+ */
+goog.async.Throttle = function(listener, interval, opt_handler) {
+ goog.async.Throttle.base(this, 'constructor');
+
+ /**
+ * Function to callback
+ * @type {function(this: T)}
+ * @private
+ */
+ this.listener_ = listener;
+
+ /**
+ * Interval for the throttle time
+ * @type {number}
+ * @private
+ */
+ this.interval_ = interval;
+
+ /**
+ * "this" context for the listener
+ * @type {Object|undefined}
+ * @private
+ */
+ this.handler_ = opt_handler;
+
+ /**
+ * Cached callback function invoked after the throttle timeout completes
+ * @type {Function}
+ * @private
+ */
+ this.callback_ = goog.bind(this.onTimer_, this);
+};
+goog.inherits(goog.async.Throttle, goog.Disposable);
+
+
+
+/**
+ * A deprecated alias.
+ * @deprecated Use goog.async.Throttle instead.
+ * @constructor
+ * @final
+ */
+goog.Throttle = goog.async.Throttle;
+
+
+/**
+ * Indicates that the action is pending and needs to be fired.
+ * @type {boolean}
+ * @private
+ */
+goog.async.Throttle.prototype.shouldFire_ = false;
+
+
+/**
+ * Indicates the count of nested pauses currently in effect on the throttle.
+ * When this count is not zero, fired actions will be postponed until the
+ * throttle is resumed enough times to drop the pause count to zero.
+ * @type {number}
+ * @private
+ */
+goog.async.Throttle.prototype.pauseCount_ = 0;
+
+
+/**
+ * Timer for scheduling the next callback
+ * @type {?number}
+ * @private
+ */
+goog.async.Throttle.prototype.timer_ = null;
+
+
+/**
+ * Notifies the throttle that the action has happened. It will throttle the call
+ * so that the callback is not called too often according to the interval
+ * parameter passed to the constructor.
+ */
+goog.async.Throttle.prototype.fire = function() {
+ if (!this.timer_ && !this.pauseCount_) {
+ this.doAction_();
+ } else {
+ this.shouldFire_ = true;
+ }
+};
+
+
+/**
+ * Cancels any pending action callback. The throttle can be restarted by
+ * calling {@link #fire}.
+ */
+goog.async.Throttle.prototype.stop = function() {
+ if (this.timer_) {
+ goog.Timer.clear(this.timer_);
+ this.timer_ = null;
+ this.shouldFire_ = false;
+ }
+};
+
+
+/**
+ * Pauses the throttle. All pending and future action callbacks will be
+ * delayed until the throttle is resumed. Pauses can be nested.
+ */
+goog.async.Throttle.prototype.pause = function() {
+ this.pauseCount_++;
+};
+
+
+/**
+ * Resumes the throttle. If doing so drops the pausing count to zero, pending
+ * action callbacks will be executed as soon as possible, but still no sooner
+ * than an interval's delay after the previous call. Future action callbacks
+ * will be executed as normal.
+ */
+goog.async.Throttle.prototype.resume = function() {
+ this.pauseCount_--;
+ if (!this.pauseCount_ && this.shouldFire_ && !this.timer_) {
+ this.shouldFire_ = false;
+ this.doAction_();
+ }
+};
+
+
+/** @override */
+goog.async.Throttle.prototype.disposeInternal = function() {
+ goog.async.Throttle.base(this, 'disposeInternal');
+ this.stop();
+};
+
+
+/**
+ * Handler for the timer to fire the throttle
+ * @private
+ */
+goog.async.Throttle.prototype.onTimer_ = function() {
+ this.timer_ = null;
+
+ if (this.shouldFire_ && !this.pauseCount_) {
+ this.shouldFire_ = false;
+ this.doAction_();
+ }
+};
+
+
+/**
+ * Calls the callback
+ * @private
+ */
+goog.async.Throttle.prototype.doAction_ = function() {
+ this.timer_ = goog.Timer.callOnce(this.callback_, this.interval_);
+ this.listener_.call(this.handler_);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/async/workqueue.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/async/workqueue.js b/externs/GCL/externs/goog/async/workqueue.js
new file mode 100644
index 0000000..2d86c89
--- /dev/null
+++ b/externs/GCL/externs/goog/async/workqueue.js
@@ -0,0 +1,139 @@
+// Copyright 2015 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+goog.provide('goog.async.WorkItem');
+goog.provide('goog.async.WorkQueue');
+
+goog.require('goog.asserts');
+goog.require('goog.async.FreeList');
+
+
+// TODO(johnlenz): generalize the WorkQueue if this is used by more
+// than goog.async.run.
+
+
+
+/**
+ * A low GC workqueue. The key elements of this design:
+ * - avoids the need for goog.bind or equivalent by carrying scope
+ * - avoids the need for array reallocation by using a linked list
+ * - minimizes work entry objects allocation by recycling objects
+ * @constructor
+ * @final
+ * @struct
+ */
+goog.async.WorkQueue = function() {
+ this.workHead_ = null;
+ this.workTail_ = null;
+};
+
+
+/** @define {number} The maximum number of entries to keep for recycling. */
+goog.define('goog.async.WorkQueue.DEFAULT_MAX_UNUSED', 100);
+
+
+/** @const @private {goog.async.FreeList<goog.async.WorkItem>} */
+goog.async.WorkQueue.freelist_ = new goog.async.FreeList(
+ function() {return new goog.async.WorkItem(); },
+ function(item) {item.reset()},
+ goog.async.WorkQueue.DEFAULT_MAX_UNUSED);
+
+
+/**
+ * @param {function()} fn
+ * @param {Object|null|undefined} scope
+ */
+goog.async.WorkQueue.prototype.add = function(fn, scope) {
+ var item = this.getUnusedItem_();
+ item.set(fn, scope);
+
+ if (this.workTail_) {
+ this.workTail_.next = item;
+ this.workTail_ = item;
+ } else {
+ goog.asserts.assert(!this.workHead_);
+ this.workHead_ = item;
+ this.workTail_ = item;
+ }
+};
+
+
+/**
+ * @return {goog.async.WorkItem}
+ */
+goog.async.WorkQueue.prototype.remove = function() {
+ var item = null;
+
+ if (this.workHead_) {
+ item = this.workHead_;
+ this.workHead_ = this.workHead_.next;
+ if (!this.workHead_) {
+ this.workTail_ = null;
+ }
+ item.next = null;
+ }
+ return item;
+};
+
+
+/**
+ * @param {goog.async.WorkItem} item
+ */
+goog.async.WorkQueue.prototype.returnUnused = function(item) {
+ goog.async.WorkQueue.freelist_.put(item);
+};
+
+
+/**
+ * @return {goog.async.WorkItem}
+ * @private
+ */
+goog.async.WorkQueue.prototype.getUnusedItem_ = function() {
+ return goog.async.WorkQueue.freelist_.get();
+};
+
+
+
+/**
+ * @constructor
+ * @final
+ * @struct
+ */
+goog.async.WorkItem = function() {
+ /** @type {?function()} */
+ this.fn = null;
+ /** @type {Object|null|undefined} */
+ this.scope = null;
+ /** @type {?goog.async.WorkItem} */
+ this.next = null;
+};
+
+
+/**
+ * @param {function()} fn
+ * @param {Object|null|undefined} scope
+ */
+goog.async.WorkItem.prototype.set = function(fn, scope) {
+ this.fn = fn;
+ this.scope = scope;
+ this.next = null;
+};
+
+
+/** Reset the work item so they don't prevent GC before reuse */
+goog.async.WorkItem.prototype.reset = function() {
+ this.fn = null;
+ this.scope = null;
+ this.next = null;
+};
[17/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/listenable.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/listenable.js b/externs/GCL/externs/goog/events/listenable.js
new file mode 100644
index 0000000..a05b348
--- /dev/null
+++ b/externs/GCL/externs/goog/events/listenable.js
@@ -0,0 +1,335 @@
+// Copyright 2012 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 interface for a listenable JavaScript object.
+ * @author chrishenry@google.com (Chris Henry)
+ */
+
+goog.provide('goog.events.Listenable');
+goog.provide('goog.events.ListenableKey');
+
+/** @suppress {extraRequire} */
+goog.require('goog.events.EventId');
+
+
+
+/**
+ * A listenable interface. A listenable is an object with the ability
+ * to dispatch/broadcast events to "event listeners" registered via
+ * listen/listenOnce.
+ *
+ * The interface allows for an event propagation mechanism similar
+ * to one offered by native browser event targets, such as
+ * capture/bubble mechanism, stopping propagation, and preventing
+ * default actions. Capture/bubble mechanism depends on the ancestor
+ * tree constructed via {@code #getParentEventTarget}; this tree
+ * must be directed acyclic graph. The meaning of default action(s)
+ * in preventDefault is specific to a particular use case.
+ *
+ * Implementations that do not support capture/bubble or can not have
+ * a parent listenable can simply not implement any ability to set the
+ * parent listenable (and have {@code #getParentEventTarget} return
+ * null).
+ *
+ * Implementation of this class can be used with or independently from
+ * goog.events.
+ *
+ * Implementation must call {@code #addImplementation(implClass)}.
+ *
+ * @interface
+ * @see goog.events
+ * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html
+ */
+goog.events.Listenable = function() {};
+
+
+/**
+ * An expando property to indicate that an object implements
+ * goog.events.Listenable.
+ *
+ * See addImplementation/isImplementedBy.
+ *
+ * @type {string}
+ * @const
+ */
+goog.events.Listenable.IMPLEMENTED_BY_PROP =
+ 'closure_listenable_' + ((Math.random() * 1e6) | 0);
+
+
+/**
+ * Marks a given class (constructor) as an implementation of
+ * Listenable, do that we can query that fact at runtime. The class
+ * must have already implemented the interface.
+ * @param {!Function} cls The class constructor. The corresponding
+ * class must have already implemented the interface.
+ */
+goog.events.Listenable.addImplementation = function(cls) {
+ cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;
+};
+
+
+/**
+ * @param {Object} obj The object to check.
+ * @return {boolean} Whether a given instance implements Listenable. The
+ * class/superclass of the instance must call addImplementation.
+ */
+goog.events.Listenable.isImplementedBy = function(obj) {
+ return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);
+};
+
+
+/**
+ * Adds an event listener. A listener can only be added once to an
+ * object and if it is added again the key for the listener is
+ * returned. Note that if the existing listener is a one-off listener
+ * (registered via listenOnce), it will no longer be a one-off
+ * listener after a call to listen().
+ *
+ * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
+ * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
+ * method.
+ * @param {boolean=} opt_useCapture Whether to fire in capture phase
+ * (defaults to false).
+ * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ * @template SCOPE,EVENTOBJ
+ */
+goog.events.Listenable.prototype.listen;
+
+
+/**
+ * Adds an event listener that is removed automatically after the
+ * listener fired once.
+ *
+ * If an existing listener already exists, listenOnce will do
+ * nothing. In particular, if the listener was previously registered
+ * via listen(), listenOnce() will not turn the listener into a
+ * one-off listener. Similarly, if there is already an existing
+ * one-off listener, listenOnce does not modify the listeners (it is
+ * still a once listener).
+ *
+ * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
+ * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
+ * method.
+ * @param {boolean=} opt_useCapture Whether to fire in capture phase
+ * (defaults to false).
+ * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ * @template SCOPE,EVENTOBJ
+ */
+goog.events.Listenable.prototype.listenOnce;
+
+
+/**
+ * Removes an event listener which was added with listen() or listenOnce().
+ *
+ * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
+ * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
+ * method.
+ * @param {boolean=} opt_useCapture Whether to fire in capture phase
+ * (defaults to false).
+ * @param {SCOPE=} opt_listenerScope Object in whose scope to call
+ * the listener.
+ * @return {boolean} Whether any listener was removed.
+ * @template SCOPE,EVENTOBJ
+ */
+goog.events.Listenable.prototype.unlisten;
+
+
+/**
+ * Removes an event listener which was added with listen() by the key
+ * returned by listen().
+ *
+ * @param {goog.events.ListenableKey} key The key returned by
+ * listen() or listenOnce().
+ * @return {boolean} Whether any listener was removed.
+ */
+goog.events.Listenable.prototype.unlistenByKey;
+
+
+/**
+ * Dispatches an event (or event like object) and calls all listeners
+ * listening for events of this type. The type of the event is decided by the
+ * type property on the event object.
+ *
+ * If any of the listeners returns false OR calls preventDefault then this
+ * function will return false. If one of the capture listeners calls
+ * stopPropagation, then the bubble listeners won't fire.
+ *
+ * @param {goog.events.EventLike} e Event object.
+ * @return {boolean} If anyone called preventDefault on the event object (or
+ * if any of the listeners returns false) this will also return false.
+ */
+goog.events.Listenable.prototype.dispatchEvent;
+
+
+/**
+ * Removes all listeners from this listenable. If type is specified,
+ * it will only remove listeners of the particular type. otherwise all
+ * registered listeners will be removed.
+ *
+ * @param {string=} opt_type Type of event to remove, default is to
+ * remove all types.
+ * @return {number} Number of listeners removed.
+ */
+goog.events.Listenable.prototype.removeAllListeners;
+
+
+/**
+ * Returns the parent of this event target to use for capture/bubble
+ * mechanism.
+ *
+ * NOTE(chrishenry): The name reflects the original implementation of
+ * custom event target ({@code goog.events.EventTarget}). We decided
+ * that changing the name is not worth it.
+ *
+ * @return {goog.events.Listenable} The parent EventTarget or null if
+ * there is no parent.
+ */
+goog.events.Listenable.prototype.getParentEventTarget;
+
+
+/**
+ * Fires all registered listeners in this listenable for the given
+ * type and capture mode, passing them the given eventObject. This
+ * does not perform actual capture/bubble. Only implementors of the
+ * interface should be using this.
+ *
+ * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the
+ * listeners to fire.
+ * @param {boolean} capture The capture mode of the listeners to fire.
+ * @param {EVENTOBJ} eventObject The event object to fire.
+ * @return {boolean} Whether all listeners succeeded without
+ * attempting to prevent default behavior. If any listener returns
+ * false or called goog.events.Event#preventDefault, this returns
+ * false.
+ * @template EVENTOBJ
+ */
+goog.events.Listenable.prototype.fireListeners;
+
+
+/**
+ * Gets all listeners in this listenable for the given type and
+ * capture mode.
+ *
+ * @param {string|!goog.events.EventId} type The type of the listeners to fire.
+ * @param {boolean} capture The capture mode of the listeners to fire.
+ * @return {!Array<goog.events.ListenableKey>} An array of registered
+ * listeners.
+ * @template EVENTOBJ
+ */
+goog.events.Listenable.prototype.getListeners;
+
+
+/**
+ * Gets the goog.events.ListenableKey for the event or null if no such
+ * listener is in use.
+ *
+ * @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event
+ * without the 'on' prefix.
+ * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The
+ * listener function to get.
+ * @param {boolean} capture Whether the listener is a capturing listener.
+ * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} the found listener or null if not found.
+ * @template SCOPE,EVENTOBJ
+ */
+goog.events.Listenable.prototype.getListener;
+
+
+/**
+ * Whether there is any active listeners matching the specified
+ * signature. If either the type or capture parameters are
+ * unspecified, the function will match on the remaining criteria.
+ *
+ * @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.
+ * @param {boolean=} opt_capture Whether to check for capture or bubble
+ * listeners.
+ * @return {boolean} Whether there is any active listeners matching
+ * the requested type and/or capture phase.
+ * @template EVENTOBJ
+ */
+goog.events.Listenable.prototype.hasListener;
+
+
+
+/**
+ * An interface that describes a single registered listener.
+ * @interface
+ */
+goog.events.ListenableKey = function() {};
+
+
+/**
+ * Counter used to create a unique key
+ * @type {number}
+ * @private
+ */
+goog.events.ListenableKey.counter_ = 0;
+
+
+/**
+ * Reserves a key to be used for ListenableKey#key field.
+ * @return {number} A number to be used to fill ListenableKey#key
+ * field.
+ */
+goog.events.ListenableKey.reserveKey = function() {
+ return ++goog.events.ListenableKey.counter_;
+};
+
+
+/**
+ * The source event target.
+ * @type {!(Object|goog.events.Listenable|goog.events.EventTarget)}
+ */
+goog.events.ListenableKey.prototype.src;
+
+
+/**
+ * The event type the listener is listening to.
+ * @type {string}
+ */
+goog.events.ListenableKey.prototype.type;
+
+
+/**
+ * The listener function.
+ * @type {function(?):?|{handleEvent:function(?):?}|null}
+ */
+goog.events.ListenableKey.prototype.listener;
+
+
+/**
+ * Whether the listener works on capture phase.
+ * @type {boolean}
+ */
+goog.events.ListenableKey.prototype.capture;
+
+
+/**
+ * The 'this' object for the listener function's scope.
+ * @type {Object}
+ */
+goog.events.ListenableKey.prototype.handler;
+
+
+/**
+ * A globally unique number to identify the key.
+ * @type {number}
+ */
+goog.events.ListenableKey.prototype.key;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/listener.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/listener.js b/externs/GCL/externs/goog/events/listener.js
new file mode 100644
index 0000000..60c7370
--- /dev/null
+++ b/externs/GCL/externs/goog/events/listener.js
@@ -0,0 +1,131 @@
+// 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 Listener object.
+ * @see ../demos/events.html
+ */
+
+goog.provide('goog.events.Listener');
+
+goog.require('goog.events.ListenableKey');
+
+
+
+/**
+ * Simple class that stores information about a listener
+ * @param {!Function} listener Callback function.
+ * @param {Function} proxy Wrapper for the listener that patches the event.
+ * @param {EventTarget|goog.events.Listenable} src Source object for
+ * the event.
+ * @param {string} type Event type.
+ * @param {boolean} capture Whether in capture or bubble phase.
+ * @param {Object=} opt_handler Object in whose context to execute the callback.
+ * @implements {goog.events.ListenableKey}
+ * @constructor
+ */
+goog.events.Listener = function(
+ listener, proxy, src, type, capture, opt_handler) {
+ if (goog.events.Listener.ENABLE_MONITORING) {
+ this.creationStack = new Error().stack;
+ }
+
+ /**
+ * Callback function.
+ * @type {Function}
+ */
+ this.listener = listener;
+
+ /**
+ * A wrapper over the original listener. This is used solely to
+ * handle native browser events (it is used to simulate the capture
+ * phase and to patch the event object).
+ * @type {Function}
+ */
+ this.proxy = proxy;
+
+ /**
+ * Object or node that callback is listening to
+ * @type {EventTarget|goog.events.Listenable}
+ */
+ this.src = src;
+
+ /**
+ * The event type.
+ * @const {string}
+ */
+ this.type = type;
+
+ /**
+ * Whether the listener is being called in the capture or bubble phase
+ * @const {boolean}
+ */
+ this.capture = !!capture;
+
+ /**
+ * Optional object whose context to execute the listener in
+ * @type {Object|undefined}
+ */
+ this.handler = opt_handler;
+
+ /**
+ * The key of the listener.
+ * @const {number}
+ * @override
+ */
+ this.key = goog.events.ListenableKey.reserveKey();
+
+ /**
+ * Whether to remove the listener after it has been called.
+ * @type {boolean}
+ */
+ this.callOnce = false;
+
+ /**
+ * Whether the listener has been removed.
+ * @type {boolean}
+ */
+ this.removed = false;
+};
+
+
+/**
+ * @define {boolean} Whether to enable the monitoring of the
+ * goog.events.Listener instances. 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.events.Listener.ENABLE_MONITORING', false);
+
+
+/**
+ * If monitoring the goog.events.Listener instances is enabled, stores the
+ * creation stack trace of the Disposable instance.
+ * @type {string}
+ */
+goog.events.Listener.prototype.creationStack;
+
+
+/**
+ * Marks this listener as removed. This also remove references held by
+ * this listener object (such as listener and event source).
+ */
+goog.events.Listener.prototype.markAsRemoved = function() {
+ this.removed = true;
+ this.listener = null;
+ this.proxy = null;
+ this.src = null;
+ this.handler = null;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/listenermap.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/listenermap.js b/externs/GCL/externs/goog/events/listenermap.js
new file mode 100644
index 0000000..c20cdb9
--- /dev/null
+++ b/externs/GCL/externs/goog/events/listenermap.js
@@ -0,0 +1,308 @@
+// 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 A map of listeners that provides utility functions to
+ * deal with listeners on an event target. Used by
+ * {@code goog.events.EventTarget}.
+ *
+ * WARNING: Do not use this class from outside goog.events package.
+ *
+ * @visibility {//closure/goog/bin/sizetests:__pkg__}
+ * @visibility {//closure/goog/events:__pkg__}
+ * @visibility {//closure/goog/labs/events:__pkg__}
+ */
+
+goog.provide('goog.events.ListenerMap');
+
+goog.require('goog.array');
+goog.require('goog.events.Listener');
+goog.require('goog.object');
+
+
+
+/**
+ * Creates a new listener map.
+ * @param {EventTarget|goog.events.Listenable} src The src object.
+ * @constructor
+ * @final
+ */
+goog.events.ListenerMap = function(src) {
+ /** @type {EventTarget|goog.events.Listenable} */
+ this.src = src;
+
+ /**
+ * Maps of event type to an array of listeners.
+ * @type {Object<string, !Array<!goog.events.Listener>>}
+ */
+ this.listeners = {};
+
+ /**
+ * The count of types in this map that have registered listeners.
+ * @private {number}
+ */
+ this.typeCount_ = 0;
+};
+
+
+/**
+ * @return {number} The count of event types in this map that actually
+ * have registered listeners.
+ */
+goog.events.ListenerMap.prototype.getTypeCount = function() {
+ return this.typeCount_;
+};
+
+
+/**
+ * @return {number} Total number of registered listeners.
+ */
+goog.events.ListenerMap.prototype.getListenerCount = function() {
+ var count = 0;
+ for (var type in this.listeners) {
+ count += this.listeners[type].length;
+ }
+ return count;
+};
+
+
+/**
+ * Adds an event listener. A listener can only be added once to an
+ * object and if it is added again the key for the listener is
+ * returned.
+ *
+ * Note that a one-off listener will not change an existing listener,
+ * if any. On the other hand a normal listener will change existing
+ * one-off listener to become a normal listener.
+ *
+ * @param {string|!goog.events.EventId} type The listener event type.
+ * @param {!Function} listener This listener callback method.
+ * @param {boolean} callOnce Whether the listener is a one-off
+ * listener.
+ * @param {boolean=} opt_useCapture The capture mode of the listener.
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ */
+goog.events.ListenerMap.prototype.add = function(
+ type, listener, callOnce, opt_useCapture, opt_listenerScope) {
+ var typeStr = type.toString();
+ var listenerArray = this.listeners[typeStr];
+ if (!listenerArray) {
+ listenerArray = this.listeners[typeStr] = [];
+ this.typeCount_++;
+ }
+
+ var listenerObj;
+ var index = goog.events.ListenerMap.findListenerIndex_(
+ listenerArray, listener, opt_useCapture, opt_listenerScope);
+ if (index > -1) {
+ listenerObj = listenerArray[index];
+ if (!callOnce) {
+ // Ensure that, if there is an existing callOnce listener, it is no
+ // longer a callOnce listener.
+ listenerObj.callOnce = false;
+ }
+ } else {
+ listenerObj = new goog.events.Listener(
+ listener, null, this.src, typeStr, !!opt_useCapture, opt_listenerScope);
+ listenerObj.callOnce = callOnce;
+ listenerArray.push(listenerObj);
+ }
+ return listenerObj;
+};
+
+
+/**
+ * Removes a matching listener.
+ * @param {string|!goog.events.EventId} type The listener event type.
+ * @param {!Function} listener This listener callback method.
+ * @param {boolean=} opt_useCapture The capture mode of the listener.
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {boolean} Whether any listener was removed.
+ */
+goog.events.ListenerMap.prototype.remove = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ var typeStr = type.toString();
+ if (!(typeStr in this.listeners)) {
+ return false;
+ }
+
+ var listenerArray = this.listeners[typeStr];
+ var index = goog.events.ListenerMap.findListenerIndex_(
+ listenerArray, listener, opt_useCapture, opt_listenerScope);
+ if (index > -1) {
+ var listenerObj = listenerArray[index];
+ listenerObj.markAsRemoved();
+ goog.array.removeAt(listenerArray, index);
+ if (listenerArray.length == 0) {
+ delete this.listeners[typeStr];
+ this.typeCount_--;
+ }
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes the given listener object.
+ * @param {goog.events.ListenableKey} listener The listener to remove.
+ * @return {boolean} Whether the listener is removed.
+ */
+goog.events.ListenerMap.prototype.removeByKey = function(listener) {
+ var type = listener.type;
+ if (!(type in this.listeners)) {
+ return false;
+ }
+
+ var removed = goog.array.remove(this.listeners[type], listener);
+ if (removed) {
+ listener.markAsRemoved();
+ if (this.listeners[type].length == 0) {
+ delete this.listeners[type];
+ this.typeCount_--;
+ }
+ }
+ return removed;
+};
+
+
+/**
+ * Removes all listeners from this map. If opt_type is provided, only
+ * listeners that match the given type are removed.
+ * @param {string|!goog.events.EventId=} opt_type Type of event to remove.
+ * @return {number} Number of listeners removed.
+ */
+goog.events.ListenerMap.prototype.removeAll = function(opt_type) {
+ var typeStr = opt_type && opt_type.toString();
+ var count = 0;
+ for (var type in this.listeners) {
+ if (!typeStr || type == typeStr) {
+ var listenerArray = this.listeners[type];
+ for (var i = 0; i < listenerArray.length; i++) {
+ ++count;
+ listenerArray[i].markAsRemoved();
+ }
+ delete this.listeners[type];
+ this.typeCount_--;
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Gets all listeners that match the given type and capture mode. The
+ * returned array is a copy (but the listener objects are not).
+ * @param {string|!goog.events.EventId} type The type of the listeners
+ * to retrieve.
+ * @param {boolean} capture The capture mode of the listeners to retrieve.
+ * @return {!Array<goog.events.ListenableKey>} An array of matching
+ * listeners.
+ */
+goog.events.ListenerMap.prototype.getListeners = function(type, capture) {
+ var listenerArray = this.listeners[type.toString()];
+ var rv = [];
+ if (listenerArray) {
+ for (var i = 0; i < listenerArray.length; ++i) {
+ var listenerObj = listenerArray[i];
+ if (listenerObj.capture == capture) {
+ rv.push(listenerObj);
+ }
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Gets the goog.events.ListenableKey for the event or null if no such
+ * listener is in use.
+ *
+ * @param {string|!goog.events.EventId} type The type of the listener
+ * to retrieve.
+ * @param {!Function} listener The listener function to get.
+ * @param {boolean} capture Whether the listener is a capturing listener.
+ * @param {Object=} opt_listenerScope Object in whose scope to call the
+ * listener.
+ * @return {goog.events.ListenableKey} the found listener or null if not found.
+ */
+goog.events.ListenerMap.prototype.getListener = function(
+ type, listener, capture, opt_listenerScope) {
+ var listenerArray = this.listeners[type.toString()];
+ var i = -1;
+ if (listenerArray) {
+ i = goog.events.ListenerMap.findListenerIndex_(
+ listenerArray, listener, capture, opt_listenerScope);
+ }
+ return i > -1 ? listenerArray[i] : null;
+};
+
+
+/**
+ * Whether there is a matching listener. If either the type or capture
+ * parameters are unspecified, the function will match on the
+ * remaining criteria.
+ *
+ * @param {string|!goog.events.EventId=} opt_type The type of the listener.
+ * @param {boolean=} opt_capture The capture mode of the listener.
+ * @return {boolean} Whether there is an active listener matching
+ * the requested type and/or capture phase.
+ */
+goog.events.ListenerMap.prototype.hasListener = function(
+ opt_type, opt_capture) {
+ var hasType = goog.isDef(opt_type);
+ var typeStr = hasType ? opt_type.toString() : '';
+ var hasCapture = goog.isDef(opt_capture);
+
+ return goog.object.some(
+ this.listeners, function(listenerArray, type) {
+ for (var i = 0; i < listenerArray.length; ++i) {
+ if ((!hasType || listenerArray[i].type == typeStr) &&
+ (!hasCapture || listenerArray[i].capture == opt_capture)) {
+ return true;
+ }
+ }
+
+ return false;
+ });
+};
+
+
+/**
+ * Finds the index of a matching goog.events.Listener in the given
+ * listenerArray.
+ * @param {!Array<!goog.events.Listener>} listenerArray Array of listener.
+ * @param {!Function} listener The listener function.
+ * @param {boolean=} opt_useCapture The capture flag for the listener.
+ * @param {Object=} opt_listenerScope The listener scope.
+ * @return {number} The index of the matching listener within the
+ * listenerArray.
+ * @private
+ */
+goog.events.ListenerMap.findListenerIndex_ = function(
+ listenerArray, listener, opt_useCapture, opt_listenerScope) {
+ for (var i = 0; i < listenerArray.length; ++i) {
+ var listenerObj = listenerArray[i];
+ if (!listenerObj.removed &&
+ listenerObj.listener == listener &&
+ listenerObj.capture == !!opt_useCapture &&
+ listenerObj.handler == opt_listenerScope) {
+ return i;
+ }
+ }
+ return -1;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/mousewheelhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/mousewheelhandler.js b/externs/GCL/externs/goog/events/mousewheelhandler.js
new file mode 100644
index 0000000..6729064
--- /dev/null
+++ b/externs/GCL/externs/goog/events/mousewheelhandler.js
@@ -0,0 +1,296 @@
+// 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 This event wrapper will dispatch an event when the user uses
+ * the mouse wheel to scroll an element. You can get the direction by checking
+ * the deltaX and deltaY properties of the event.
+ *
+ * This class aims to smooth out inconsistencies between browser platforms with
+ * regards to mousewheel events, but we do not cover every possible
+ * software/hardware combination out there, some of which occasionally produce
+ * very large deltas in mousewheel events. If your application wants to guard
+ * against extremely large deltas, use the setMaxDeltaX and setMaxDeltaY APIs
+ * to set maximum values that make sense for your application.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/mousewheelhandler.html
+ */
+
+goog.provide('goog.events.MouseWheelEvent');
+goog.provide('goog.events.MouseWheelHandler');
+goog.provide('goog.events.MouseWheelHandler.EventType');
+
+goog.require('goog.dom');
+goog.require('goog.events');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventTarget');
+goog.require('goog.math');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * This event handler allows you to catch mouse wheel events in a consistent
+ * manner.
+ * @param {Element|Document} element The element to listen to the mouse wheel
+ * event on.
+ * @param {boolean=} opt_capture Whether to handle the mouse wheel event in
+ * capture phase.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.events.MouseWheelHandler = function(element, opt_capture) {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * This is the element that we will listen to the real mouse wheel events on.
+ * @type {Element|Document}
+ * @private
+ */
+ this.element_ = element;
+
+ var rtlElement = goog.dom.isElement(this.element_) ?
+ /** @type {Element} */ (this.element_) :
+ (this.element_ ? /** @type {Document} */ (this.element_).body : null);
+
+ /**
+ * True if the element exists and is RTL, false otherwise.
+ * @type {boolean}
+ * @private
+ */
+ this.isRtl_ = !!rtlElement && goog.style.isRightToLeft(rtlElement);
+
+ var type = goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel';
+
+ /**
+ * The key returned from the goog.events.listen.
+ * @type {goog.events.Key}
+ * @private
+ */
+ this.listenKey_ = goog.events.listen(this.element_, type, this, opt_capture);
+};
+goog.inherits(goog.events.MouseWheelHandler, goog.events.EventTarget);
+
+
+/**
+ * Enum type for the events fired by the mouse wheel handler.
+ * @enum {string}
+ */
+goog.events.MouseWheelHandler.EventType = {
+ MOUSEWHEEL: 'mousewheel'
+};
+
+
+/**
+ * Optional maximum magnitude for x delta on each mousewheel event.
+ * @type {number|undefined}
+ * @private
+ */
+goog.events.MouseWheelHandler.prototype.maxDeltaX_;
+
+
+/**
+ * Optional maximum magnitude for y delta on each mousewheel event.
+ * @type {number|undefined}
+ * @private
+ */
+goog.events.MouseWheelHandler.prototype.maxDeltaY_;
+
+
+/**
+ * @param {number} maxDeltaX Maximum magnitude for x delta on each mousewheel
+ * event. Should be non-negative.
+ */
+goog.events.MouseWheelHandler.prototype.setMaxDeltaX = function(maxDeltaX) {
+ this.maxDeltaX_ = maxDeltaX;
+};
+
+
+/**
+ * @param {number} maxDeltaY Maximum magnitude for y delta on each mousewheel
+ * event. Should be non-negative.
+ */
+goog.events.MouseWheelHandler.prototype.setMaxDeltaY = function(maxDeltaY) {
+ this.maxDeltaY_ = maxDeltaY;
+};
+
+
+/**
+ * Handles the events on the element.
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ */
+goog.events.MouseWheelHandler.prototype.handleEvent = function(e) {
+ var deltaX = 0;
+ var deltaY = 0;
+ var detail = 0;
+ var be = e.getBrowserEvent();
+ if (be.type == 'mousewheel') {
+ var wheelDeltaScaleFactor = 1;
+ if (goog.userAgent.IE ||
+ goog.userAgent.WEBKIT &&
+ (goog.userAgent.WINDOWS || goog.userAgent.isVersionOrHigher('532.0'))) {
+ // In IE we get a multiple of 120; we adjust to a multiple of 3 to
+ // represent number of lines scrolled (like Gecko).
+ // Newer versions of Webkit match IE behavior, and WebKit on
+ // Windows also matches IE behavior.
+ // See bug https://bugs.webkit.org/show_bug.cgi?id=24368
+ wheelDeltaScaleFactor = 40;
+ }
+
+ detail = goog.events.MouseWheelHandler.smartScale_(
+ -be.wheelDelta, wheelDeltaScaleFactor);
+ if (goog.isDef(be.wheelDeltaX)) {
+ // Webkit has two properties to indicate directional scroll, and
+ // can scroll both directions at once.
+ deltaX = goog.events.MouseWheelHandler.smartScale_(
+ -be.wheelDeltaX, wheelDeltaScaleFactor);
+ deltaY = goog.events.MouseWheelHandler.smartScale_(
+ -be.wheelDeltaY, wheelDeltaScaleFactor);
+ } else {
+ deltaY = detail;
+ }
+
+ // Historical note: Opera (pre 9.5) used to negate the detail value.
+ } else { // Gecko
+ // Gecko returns multiple of 3 (representing the number of lines scrolled)
+ detail = be.detail;
+
+ // Gecko sometimes returns really big values if the user changes settings to
+ // scroll a whole page per scroll
+ if (detail > 100) {
+ detail = 3;
+ } else if (detail < -100) {
+ detail = -3;
+ }
+
+ // Firefox 3.1 adds an axis field to the event to indicate direction of
+ // scroll. See https://developer.mozilla.org/en/Gecko-Specific_DOM_Events
+ if (goog.isDef(be.axis) && be.axis === be.HORIZONTAL_AXIS) {
+ deltaX = detail;
+ } else {
+ deltaY = detail;
+ }
+ }
+
+ if (goog.isNumber(this.maxDeltaX_)) {
+ deltaX = goog.math.clamp(deltaX, -this.maxDeltaX_, this.maxDeltaX_);
+ }
+ if (goog.isNumber(this.maxDeltaY_)) {
+ deltaY = goog.math.clamp(deltaY, -this.maxDeltaY_, this.maxDeltaY_);
+ }
+ // Don't clamp 'detail', since it could be ambiguous which axis it refers to
+ // and because it's informally deprecated anyways.
+
+ // For horizontal scrolling we need to flip the value for RTL grids.
+ if (this.isRtl_) {
+ deltaX = -deltaX;
+ }
+ var newEvent = new goog.events.MouseWheelEvent(detail, be, deltaX, deltaY);
+ this.dispatchEvent(newEvent);
+};
+
+
+/**
+ * Helper for scaling down a mousewheel delta by a scale factor, if appropriate.
+ * @param {number} mouseWheelDelta Delta from a mouse wheel event. Expected to
+ * be an integer.
+ * @param {number} scaleFactor Factor to scale the delta down by. Expected to
+ * be an integer.
+ * @return {number} Scaled-down delta value, or the original delta if the
+ * scaleFactor does not appear to be applicable.
+ * @private
+ */
+goog.events.MouseWheelHandler.smartScale_ = function(mouseWheelDelta,
+ scaleFactor) {
+ // The basic problem here is that in Webkit on Mac and Linux, we can get two
+ // very different types of mousewheel events: from continuous devices
+ // (touchpads, Mighty Mouse) or non-continuous devices (normal wheel mice).
+ //
+ // Non-continuous devices in Webkit get their wheel deltas scaled up to
+ // behave like IE. Continuous devices return much smaller unscaled values
+ // (which most of the time will not be cleanly divisible by the IE scale
+ // factor), so we should not try to normalize them down.
+ //
+ // Detailed discussion:
+ // https://bugs.webkit.org/show_bug.cgi?id=29601
+ // http://trac.webkit.org/browser/trunk/WebKit/chromium/src/mac/WebInputEventFactory.mm#L1063
+ if (goog.userAgent.WEBKIT &&
+ (goog.userAgent.MAC || goog.userAgent.LINUX) &&
+ (mouseWheelDelta % scaleFactor) != 0) {
+ return mouseWheelDelta;
+ } else {
+ return mouseWheelDelta / scaleFactor;
+ }
+};
+
+
+/** @override */
+goog.events.MouseWheelHandler.prototype.disposeInternal = function() {
+ goog.events.MouseWheelHandler.superClass_.disposeInternal.call(this);
+ goog.events.unlistenByKey(this.listenKey_);
+ this.listenKey_ = null;
+};
+
+
+
+/**
+ * A base class for mouse wheel events. This is used with the
+ * MouseWheelHandler.
+ *
+ * @param {number} detail The number of rows the user scrolled.
+ * @param {Event} browserEvent Browser event object.
+ * @param {number} deltaX The number of rows the user scrolled in the X
+ * direction.
+ * @param {number} deltaY The number of rows the user scrolled in the Y
+ * direction.
+ * @constructor
+ * @extends {goog.events.BrowserEvent}
+ * @final
+ */
+goog.events.MouseWheelEvent = function(detail, browserEvent, deltaX, deltaY) {
+ goog.events.BrowserEvent.call(this, browserEvent);
+
+ this.type = goog.events.MouseWheelHandler.EventType.MOUSEWHEEL;
+
+ /**
+ * The number of lines the user scrolled
+ * @type {number}
+ * NOTE: Informally deprecated. Use deltaX and deltaY instead, they provide
+ * more information.
+ */
+ this.detail = detail;
+
+ /**
+ * The number of "lines" scrolled in the X direction.
+ *
+ * Note that not all browsers provide enough information to distinguish
+ * horizontal and vertical scroll events, so for these unsupported browsers,
+ * we will always have a deltaX of 0, even if the user scrolled their mouse
+ * wheel or trackpad sideways.
+ *
+ * Currently supported browsers are Webkit and Firefox 3.1 or later.
+ *
+ * @type {number}
+ */
+ this.deltaX = deltaX;
+
+ /**
+ * The number of lines scrolled in the Y direction.
+ * @type {number}
+ */
+ this.deltaY = deltaY;
+};
+goog.inherits(goog.events.MouseWheelEvent, goog.events.BrowserEvent);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/onlinehandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/onlinehandler.js b/externs/GCL/externs/goog/events/onlinehandler.js
new file mode 100644
index 0000000..5c9fb16
--- /dev/null
+++ b/externs/GCL/externs/goog/events/onlinehandler.js
@@ -0,0 +1,159 @@
+// 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 This event handler will dispatch events when
+ * {@code navigator.onLine} changes. HTML5 defines two events, online and
+ * offline that is fired on the window. As of today 3 browsers support these
+ * events: Firefox 3 (Gecko 1.9), Opera 9.5, and IE8. If we have any of these
+ * we listen to the 'online' and 'offline' events on the current window
+ * object. Otherwise we poll the navigator.onLine property to detect changes.
+ *
+ * Note that this class only reflects what the browser tells us and this usually
+ * only reflects changes to the File -> Work Offline menu item.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/onlinehandler.html
+ */
+
+// TODO(arv): We should probably implement some kind of polling service and/or
+// a poll for changes event handler that can be used to fire events when a state
+// changes.
+
+goog.provide('goog.events.OnlineHandler');
+goog.provide('goog.events.OnlineHandler.EventType');
+
+goog.require('goog.Timer');
+goog.require('goog.events.BrowserFeature');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.net.NetworkStatusMonitor');
+
+
+
+/**
+ * Basic object for detecting whether the online state changes.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @implements {goog.net.NetworkStatusMonitor}
+ */
+goog.events.OnlineHandler = function() {
+ goog.events.OnlineHandler.base(this, 'constructor');
+
+ /**
+ * @private {goog.events.EventHandler<!goog.events.OnlineHandler>}
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ // Some browsers do not support navigator.onLine and therefore we don't
+ // bother setting up events or timers.
+ if (!goog.events.BrowserFeature.HAS_NAVIGATOR_ONLINE_PROPERTY) {
+ return;
+ }
+
+ if (goog.events.BrowserFeature.HAS_HTML5_NETWORK_EVENT_SUPPORT) {
+ var target =
+ goog.events.BrowserFeature.HTML5_NETWORK_EVENTS_FIRE_ON_BODY ?
+ document.body : window;
+ this.eventHandler_.listen(target,
+ [goog.events.EventType.ONLINE, goog.events.EventType.OFFLINE],
+ this.handleChange_);
+ } else {
+ this.online_ = this.isOnline();
+ this.timer_ = new goog.Timer(goog.events.OnlineHandler.POLL_INTERVAL_);
+ this.eventHandler_.listen(this.timer_, goog.Timer.TICK, this.handleTick_);
+ this.timer_.start();
+ }
+};
+goog.inherits(goog.events.OnlineHandler, goog.events.EventTarget);
+
+
+/**
+ * Enum for the events dispatched by the OnlineHandler.
+ * @enum {string}
+ * @deprecated Use goog.net.NetworkStatusMonitor.EventType instead.
+ */
+goog.events.OnlineHandler.EventType = goog.net.NetworkStatusMonitor.EventType;
+
+
+/**
+ * The time to wait before checking the {@code navigator.onLine} again.
+ * @type {number}
+ * @private
+ */
+goog.events.OnlineHandler.POLL_INTERVAL_ = 250;
+
+
+/**
+ * Stores the last value of the online state so we can detect if this has
+ * changed.
+ * @type {boolean}
+ * @private
+ */
+goog.events.OnlineHandler.prototype.online_;
+
+
+/**
+ * The timer object used to poll the online state.
+ * @type {goog.Timer}
+ * @private
+ */
+goog.events.OnlineHandler.prototype.timer_;
+
+
+/** @override */
+goog.events.OnlineHandler.prototype.isOnline = function() {
+ return goog.events.BrowserFeature.HAS_NAVIGATOR_ONLINE_PROPERTY ?
+ navigator.onLine : true;
+};
+
+
+/**
+ * Called every time the timer ticks to see if the state has changed and when
+ * the online state changes the method handleChange_ is called.
+ * @private
+ */
+goog.events.OnlineHandler.prototype.handleTick_ = function() {
+ var online = this.isOnline();
+ if (online != this.online_) {
+ this.online_ = online;
+ this.handleChange_();
+ }
+};
+
+
+/**
+ * Called when the online state changes. This dispatches the
+ * {@code ONLINE} and {@code OFFLINE} events respectively.
+ * @private
+ */
+goog.events.OnlineHandler.prototype.handleChange_ = function() {
+ var type = this.isOnline() ?
+ goog.net.NetworkStatusMonitor.EventType.ONLINE :
+ goog.net.NetworkStatusMonitor.EventType.OFFLINE;
+ this.dispatchEvent(type);
+};
+
+
+/** @override */
+goog.events.OnlineHandler.prototype.disposeInternal = function() {
+ goog.events.OnlineHandler.base(this, 'disposeInternal');
+ this.eventHandler_.dispose();
+ this.eventHandler_ = null;
+ if (this.timer_) {
+ this.timer_.dispose();
+ this.timer_ = null;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/pastehandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/pastehandler.js b/externs/GCL/externs/goog/events/pastehandler.js
new file mode 100644
index 0000000..4992ff0
--- /dev/null
+++ b/externs/GCL/externs/goog/events/pastehandler.js
@@ -0,0 +1,517 @@
+// Copyright 2009 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 Provides a 'paste' event detector that works consistently
+ * across different browsers.
+ *
+ * IE5, IE6, IE7, Safari3.0 and FF3.0 all fire 'paste' events on textareas.
+ * FF2 doesn't. This class uses 'paste' events when they are available
+ * and uses heuristics to detect the 'paste' event when they are not available.
+ *
+ * Known issue: will not detect paste events in FF2 if you pasted exactly the
+ * same existing text.
+ * Known issue: Opera + Mac doesn't work properly because of the meta key. We
+ * can probably fix that. TODO(user): {@link KeyboardShortcutHandler} does not
+ * work either very well with opera + mac. fix that.
+ *
+ * @supported IE5, IE6, IE7, Safari3.0, Chrome, FF2.0 (linux) and FF3.0 and
+ * Opera (mac and windows).
+ *
+ * @see ../demos/pastehandler.html
+ */
+
+goog.provide('goog.events.PasteHandler');
+goog.provide('goog.events.PasteHandler.EventType');
+goog.provide('goog.events.PasteHandler.State');
+
+goog.require('goog.Timer');
+goog.require('goog.async.ConditionalDelay');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.log');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A paste event detector. Gets an {@code element} as parameter and fires
+ * {@code goog.events.PasteHandler.EventType.PASTE} events when text is
+ * pasted in the {@code element}. Uses heuristics to detect paste events in FF2.
+ * See more details of the heuristic on {@link #handleEvent_}.
+ *
+ * @param {Element} element The textarea element we are listening on.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.events.PasteHandler = function(element) {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * The element that you want to listen for paste events on.
+ * @type {Element}
+ * @private
+ */
+ this.element_ = element;
+
+ /**
+ * The last known value of the element. Kept to check if things changed. See
+ * more details on {@link #handleEvent_}.
+ * @type {string}
+ * @private
+ */
+ this.oldValue_ = this.element_.value;
+
+ /**
+ * Handler for events.
+ * @type {goog.events.EventHandler<!goog.events.PasteHandler>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ /**
+ * The last time an event occurred on the element. Kept to check whether the
+ * last event was generated by two input events or by multiple fast key events
+ * that got swallowed. See more details on {@link #handleEvent_}.
+ * @type {number}
+ * @private
+ */
+ this.lastTime_ = goog.now();
+
+ if (goog.userAgent.WEBKIT ||
+ goog.userAgent.IE ||
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9')) {
+ // Most modern browsers support the paste event.
+ this.eventHandler_.listen(element, goog.events.EventType.PASTE,
+ this.dispatch_);
+ } else {
+ // But FF2 and Opera doesn't. we listen for a series of events to try to
+ // find out if a paste occurred. We enumerate and cover all known ways to
+ // paste text on textareas. See more details on {@link #handleEvent_}.
+ var events = [
+ goog.events.EventType.KEYDOWN,
+ goog.events.EventType.BLUR,
+ goog.events.EventType.FOCUS,
+ goog.events.EventType.MOUSEOVER,
+ 'input'
+ ];
+ this.eventHandler_.listen(element, events, this.handleEvent_);
+ }
+
+ /**
+ * ConditionalDelay used to poll for changes in the text element once users
+ * paste text. Browsers fire paste events BEFORE the text is actually present
+ * in the element.value property.
+ * @type {goog.async.ConditionalDelay}
+ * @private
+ */
+ this.delay_ = new goog.async.ConditionalDelay(
+ goog.bind(this.checkUpdatedText_, this));
+
+};
+goog.inherits(goog.events.PasteHandler, goog.events.EventTarget);
+
+
+/**
+ * The types of events fired by this class.
+ * @enum {string}
+ */
+goog.events.PasteHandler.EventType = {
+ /**
+ * Dispatched as soon as the paste event is detected, but before the pasted
+ * text has been added to the text element we're listening to.
+ */
+ PASTE: 'paste',
+
+ /**
+ * Dispatched after detecting a change to the value of text element
+ * (within 200msec of receiving the PASTE event).
+ */
+ AFTER_PASTE: 'after_paste'
+};
+
+
+/**
+ * The mandatory delay we expect between two {@code input} events, used to
+ * differentiated between non key paste events and key events.
+ * @type {number}
+ */
+goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER =
+ 400;
+
+
+/**
+ * The period between each time we check whether the pasted text appears in the
+ * text element or not.
+ * @type {number}
+ * @private
+ */
+goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_ = 50;
+
+
+/**
+ * The maximum amount of time we want to poll for changes.
+ * @type {number}
+ * @private
+ */
+goog.events.PasteHandler.PASTE_POLLING_TIMEOUT_MS_ = 200;
+
+
+/**
+ * The states that this class can be found, on the paste detection algorithm.
+ * @enum {string}
+ */
+goog.events.PasteHandler.State = {
+ INIT: 'init',
+ FOCUSED: 'focused',
+ TYPING: 'typing'
+};
+
+
+/**
+ * The initial state of the paste detection algorithm.
+ * @type {goog.events.PasteHandler.State}
+ * @private
+ */
+goog.events.PasteHandler.prototype.state_ =
+ goog.events.PasteHandler.State.INIT;
+
+
+/**
+ * The previous event that caused us to be on the current state.
+ * @type {?string}
+ * @private
+ */
+goog.events.PasteHandler.prototype.previousEvent_;
+
+
+/**
+ * A logger, used to help us debug the algorithm.
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.events.PasteHandler.prototype.logger_ =
+ goog.log.getLogger('goog.events.PasteHandler');
+
+
+/** @override */
+goog.events.PasteHandler.prototype.disposeInternal = function() {
+ goog.events.PasteHandler.superClass_.disposeInternal.call(this);
+ this.eventHandler_.dispose();
+ this.eventHandler_ = null;
+ this.delay_.dispose();
+ this.delay_ = null;
+};
+
+
+/**
+ * Returns the current state of the paste detection algorithm. Used mostly for
+ * testing.
+ * @return {goog.events.PasteHandler.State} The current state of the class.
+ */
+goog.events.PasteHandler.prototype.getState = function() {
+ return this.state_;
+};
+
+
+/**
+ * Returns the event handler.
+ * @return {goog.events.EventHandler<T>} The event handler.
+ * @protected
+ * @this T
+ * @template T
+ */
+goog.events.PasteHandler.prototype.getEventHandler = function() {
+ return this.eventHandler_;
+};
+
+
+/**
+ * Checks whether the element.value property was updated, and if so, dispatches
+ * the event that let clients know that the text is available.
+ * @return {boolean} Whether the polling should stop or not, based on whether
+ * we found a text change or not.
+ * @private
+ */
+goog.events.PasteHandler.prototype.checkUpdatedText_ = function() {
+ if (this.oldValue_ == this.element_.value) {
+ return false;
+ }
+ goog.log.info(this.logger_, 'detected textchange after paste');
+ this.dispatchEvent(goog.events.PasteHandler.EventType.AFTER_PASTE);
+ return true;
+};
+
+
+/**
+ * Dispatches the paste event.
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ * @private
+ */
+goog.events.PasteHandler.prototype.dispatch_ = function(e) {
+ var event = new goog.events.BrowserEvent(e.getBrowserEvent());
+ event.type = goog.events.PasteHandler.EventType.PASTE;
+ this.dispatchEvent(event);
+
+ // Starts polling for updates in the element.value property so we can tell
+ // when do dispatch the AFTER_PASTE event. (We do an initial check after an
+ // async delay of 0 msec since some browsers update the text right away and
+ // our poller will always wait one period before checking).
+ goog.Timer.callOnce(function() {
+ if (!this.checkUpdatedText_()) {
+ this.delay_.start(
+ goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_,
+ goog.events.PasteHandler.PASTE_POLLING_TIMEOUT_MS_);
+ }
+ }, 0, this);
+};
+
+
+/**
+ * The main event handler which implements a state machine.
+ *
+ * To handle FF2, we enumerate and cover all the known ways a user can paste:
+ *
+ * 1) ctrl+v, shift+insert, cmd+v
+ * 2) right click -> paste
+ * 3) edit menu -> paste
+ * 4) drag and drop
+ * 5) middle click
+ *
+ * (1) is easy and can be detected by listening for key events and finding out
+ * which keys are pressed. (2), (3), (4) and (5) do not generate a key event,
+ * so we need to listen for more than that. (2-5) all generate 'input' events,
+ * but so does key events. So we need to have some sort of 'how did the input
+ * event was generated' history algorithm.
+ *
+ * (2) is an interesting case in Opera on a Mac: since Macs does not have two
+ * buttons, right clicking involves pressing the CTRL key. Even more interesting
+ * is the fact that opera does NOT set the e.ctrlKey bit. Instead, it sets
+ * e.keyCode = 0.
+ * {@link http://www.quirksmode.org/js/keys.html}
+ *
+ * (1) is also an interesting case in Opera on a Mac: Opera is the only browser
+ * covered by this class that can detect the cmd key (FF2 can't apparently). And
+ * it fires e.keyCode = 17, which is the CTRL key code.
+ * {@link http://www.quirksmode.org/js/keys.html}
+ *
+ * NOTE(user, pbarry): There is an interesting thing about (5): on Linux, (5)
+ * pastes the last thing that you highlighted, not the last thing that you
+ * ctrl+c'ed. This code will still generate a {@code PASTE} event though.
+ *
+ * We enumerate all the possible steps a user can take to paste text and we
+ * implemented the transition between the steps in a state machine. The
+ * following is the design of the state machine:
+ *
+ * matching paths:
+ *
+ * (1) happens on INIT -> FOCUSED -> TYPING -> [e.ctrlKey & e.keyCode = 'v']
+ * (2-3) happens on INIT -> FOCUSED -> [input event happened]
+ * (4) happens on INIT -> [mouseover && text changed]
+ *
+ * non matching paths:
+ *
+ * user is typing normally
+ * INIT -> FOCUS -> TYPING -> INPUT -> INIT
+ *
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ * @private
+ */
+goog.events.PasteHandler.prototype.handleEvent_ = function(e) {
+ // transition between states happen at each browser event, and depend on the
+ // current state, the event that led to this state, and the event input.
+ switch (this.state_) {
+ case goog.events.PasteHandler.State.INIT: {
+ this.handleUnderInit_(e);
+ break;
+ }
+ case goog.events.PasteHandler.State.FOCUSED: {
+ this.handleUnderFocused_(e);
+ break;
+ }
+ case goog.events.PasteHandler.State.TYPING: {
+ this.handleUnderTyping_(e);
+ break;
+ }
+ default: {
+ goog.log.error(this.logger_, 'invalid ' + this.state_ + ' state');
+ }
+ }
+ this.lastTime_ = goog.now();
+ this.oldValue_ = this.element_.value;
+ goog.log.info(this.logger_, e.type + ' -> ' + this.state_);
+ this.previousEvent_ = e.type;
+};
+
+
+/**
+ * {@code goog.events.PasteHandler.EventType.INIT} is the first initial state
+ * the textarea is found. You can only leave this state by setting focus on the
+ * textarea, which is how users will input text. You can also paste things using
+ * drag and drop, which will not generate a {@code goog.events.EventType.FOCUS}
+ * event, but will generate a {@code goog.events.EventType.MOUSEOVER}.
+ *
+ * For browsers that support the 'paste' event, we match it and stay on the same
+ * state.
+ *
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ * @private
+ */
+goog.events.PasteHandler.prototype.handleUnderInit_ = function(e) {
+ switch (e.type) {
+ case goog.events.EventType.BLUR: {
+ this.state_ = goog.events.PasteHandler.State.INIT;
+ break;
+ }
+ case goog.events.EventType.FOCUS: {
+ this.state_ = goog.events.PasteHandler.State.FOCUSED;
+ break;
+ }
+ case goog.events.EventType.MOUSEOVER: {
+ this.state_ = goog.events.PasteHandler.State.INIT;
+ if (this.element_.value != this.oldValue_) {
+ goog.log.info(this.logger_, 'paste by dragdrop while on init!');
+ this.dispatch_(e);
+ }
+ break;
+ }
+ default: {
+ goog.log.error(this.logger_,
+ 'unexpected event ' + e.type + 'during init');
+ }
+ }
+};
+
+
+/**
+ * {@code goog.events.PasteHandler.EventType.FOCUSED} is typically the second
+ * state the textarea will be, which is followed by the {@code INIT} state. On
+ * this state, users can paste in three different ways: edit -> paste,
+ * right click -> paste and drag and drop.
+ *
+ * The latter will generate a {@code goog.events.EventType.MOUSEOVER} event,
+ * which we match by making sure the textarea text changed. The first two will
+ * generate an 'input', which we match by making sure it was NOT generated by a
+ * key event (which also generates an 'input' event).
+ *
+ * Unfortunately, in Firefox, if you type fast, some KEYDOWN events are
+ * swallowed but an INPUT event may still happen. That means we need to
+ * differentiate between two consecutive INPUT events being generated either by
+ * swallowed key events OR by a valid edit -> paste -> edit -> paste action. We
+ * do this by checking a minimum time between the two events. This heuristic
+ * seems to work well, but it is obviously a heuristic :).
+ *
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ * @private
+ */
+goog.events.PasteHandler.prototype.handleUnderFocused_ = function(e) {
+ switch (e.type) {
+ case 'input' : {
+ // there are two different events that happen in practice that involves
+ // consecutive 'input' events. we use a heuristic to differentiate
+ // between the one that generates a valid paste action and the one that
+ // doesn't.
+ // @see testTypingReallyFastDispatchesTwoInputEventsBeforeTheKEYDOWNEvent
+ // and
+ // @see testRightClickRightClickAlsoDispatchesTwoConsecutiveInputEvents
+ // Notice that an 'input' event may be also triggered by a 'middle click'
+ // paste event, which is described in
+ // @see testMiddleClickWithoutFocusTriggersPasteEvent
+ var minimumMilisecondsBetweenInputEvents = this.lastTime_ +
+ goog.events.PasteHandler.
+ MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER;
+ if (goog.now() > minimumMilisecondsBetweenInputEvents ||
+ this.previousEvent_ == goog.events.EventType.FOCUS) {
+ goog.log.info(this.logger_, 'paste by textchange while focused!');
+ this.dispatch_(e);
+ }
+ break;
+ }
+ case goog.events.EventType.BLUR: {
+ this.state_ = goog.events.PasteHandler.State.INIT;
+ break;
+ }
+ case goog.events.EventType.KEYDOWN: {
+ goog.log.info(this.logger_, 'key down ... looking for ctrl+v');
+ // Opera + MAC does not set e.ctrlKey. Instead, it gives me e.keyCode = 0.
+ // http://www.quirksmode.org/js/keys.html
+ if (goog.userAgent.MAC && goog.userAgent.OPERA && e.keyCode == 0 ||
+ goog.userAgent.MAC && goog.userAgent.OPERA && e.keyCode == 17) {
+ break;
+ }
+ this.state_ = goog.events.PasteHandler.State.TYPING;
+ break;
+ }
+ case goog.events.EventType.MOUSEOVER: {
+ if (this.element_.value != this.oldValue_) {
+ goog.log.info(this.logger_, 'paste by dragdrop while focused!');
+ this.dispatch_(e);
+ }
+ break;
+ }
+ default: {
+ goog.log.error(this.logger_,
+ 'unexpected event ' + e.type + ' during focused');
+ }
+ }
+};
+
+
+/**
+ * {@code goog.events.PasteHandler.EventType.TYPING} is the third state
+ * this class can be. It exists because each KEYPRESS event will ALSO generate
+ * an INPUT event (because the textarea value changes), and we need to
+ * differentiate between an INPUT event generated by a key event and an INPUT
+ * event generated by edit -> paste actions.
+ *
+ * This is the state that we match the ctrl+v pattern.
+ *
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ * @private
+ */
+goog.events.PasteHandler.prototype.handleUnderTyping_ = function(e) {
+ switch (e.type) {
+ case 'input' : {
+ this.state_ = goog.events.PasteHandler.State.FOCUSED;
+ break;
+ }
+ case goog.events.EventType.BLUR: {
+ this.state_ = goog.events.PasteHandler.State.INIT;
+ break;
+ }
+ case goog.events.EventType.KEYDOWN: {
+ if (e.ctrlKey && e.keyCode == goog.events.KeyCodes.V ||
+ e.shiftKey && e.keyCode == goog.events.KeyCodes.INSERT ||
+ e.metaKey && e.keyCode == goog.events.KeyCodes.V) {
+ goog.log.info(this.logger_, 'paste by ctrl+v while keypressed!');
+ this.dispatch_(e);
+ }
+ break;
+ }
+ case goog.events.EventType.MOUSEOVER: {
+ if (this.element_.value != this.oldValue_) {
+ goog.log.info(this.logger_, 'paste by dragdrop while keypressed!');
+ this.dispatch_(e);
+ }
+ break;
+ }
+ default: {
+ goog.log.error(this.logger_,
+ 'unexpected event ' + e.type + ' during keypressed');
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/wheelevent.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/wheelevent.js b/externs/GCL/externs/goog/events/wheelevent.js
new file mode 100644
index 0000000..1f172eb
--- /dev/null
+++ b/externs/GCL/externs/goog/events/wheelevent.js
@@ -0,0 +1,169 @@
+// 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 This class aims to smooth out inconsistencies between browser
+ * handling of wheel events by providing an event that is similar to that
+ * defined in the standard, but also easier to consume.
+ *
+ * It is based upon the WheelEvent, which allows for up to 3 dimensional
+ * scrolling events that come in units of either pixels, lines or pages.
+ * http://www.w3.org/TR/2014/WD-DOM-Level-3-Events-20140925/#interface-WheelEvent
+ *
+ * The significant difference here is that it also provides reasonable pixel
+ * deltas for clients that do not want to treat line and page scrolling events
+ * specially.
+ *
+ * Clients of this code should be aware that some input devices only fire a few
+ * discrete events (such as a mouse wheel without acceleration) whereas some can
+ * generate a large number of events for a single interaction (such as a
+ * touchpad with acceleration). There is no signal in the events to reliably
+ * distinguish between these.
+ *
+ * @see ../demos/wheelhandler.html
+ */
+
+goog.provide('goog.events.WheelEvent');
+
+goog.require('goog.asserts');
+goog.require('goog.events.BrowserEvent');
+
+
+
+/**
+ * A common class for wheel events. This is used with the WheelHandler.
+ *
+ * @param {Event} browserEvent Browser event object.
+ * @param {goog.events.WheelEvent.DeltaMode} deltaMode The delta mode units of
+ * the wheel event.
+ * @param {number} deltaX The number of delta units the user in the X axis.
+ * @param {number} deltaY The number of delta units the user in the Y axis.
+ * @param {number} deltaZ The number of delta units the user in the Z axis.
+ * @constructor
+ * @extends {goog.events.BrowserEvent}
+ * @final
+ */
+goog.events.WheelEvent = function(
+ browserEvent, deltaMode, deltaX, deltaY, deltaZ) {
+ goog.events.WheelEvent.base(this, 'constructor', browserEvent);
+ goog.asserts.assert(browserEvent, 'Expecting a non-null browserEvent');
+
+ /** @type {goog.events.WheelEvent.EventType} */
+ this.type = goog.events.WheelEvent.EventType.WHEEL;
+
+ /**
+ * An enum corresponding to the units of this event.
+ * @type {goog.events.WheelEvent.DeltaMode}
+ */
+ this.deltaMode = deltaMode;
+
+ /**
+ * The number of delta units in the X axis.
+ * @type {number}
+ */
+ this.deltaX = deltaX;
+
+ /**
+ * The number of delta units in the Y axis.
+ * @type {number}
+ */
+ this.deltaY = deltaY;
+
+ /**
+ * The number of delta units in the Z axis.
+ * @type {number}
+ */
+ this.deltaZ = deltaZ;
+
+ // Ratio between delta and pixel values.
+ var pixelRatio = 1; // Value for DeltaMode.PIXEL
+ switch (deltaMode) {
+ case goog.events.WheelEvent.DeltaMode.PAGE:
+ pixelRatio *= goog.events.WheelEvent.PIXELS_PER_PAGE_;
+ break;
+ case goog.events.WheelEvent.DeltaMode.LINE:
+ pixelRatio *= goog.events.WheelEvent.PIXELS_PER_LINE_;
+ break;
+ }
+
+ /**
+ * The number of delta pixels in the X axis. Code that doesn't want to handle
+ * different deltaMode units can just look here.
+ * @type {number}
+ */
+ this.pixelDeltaX = this.deltaX * pixelRatio;
+
+ /**
+ * The number of pixels in the Y axis. Code that doesn't want to
+ * handle different deltaMode units can just look here.
+ * @type {number}
+ */
+ this.pixelDeltaY = this.deltaY * pixelRatio;
+
+ /**
+ * The number of pixels scrolled in the Z axis. Code that doesn't want to
+ * handle different deltaMode units can just look here.
+ * @type {number}
+ */
+ this.pixelDeltaZ = this.deltaZ * pixelRatio;
+};
+goog.inherits(goog.events.WheelEvent, goog.events.BrowserEvent);
+
+
+/**
+ * Enum type for the events fired by the wheel handler.
+ * @enum {string}
+ */
+goog.events.WheelEvent.EventType = {
+ /** The user has provided wheel-based input. */
+ WHEEL: 'wheel'
+};
+
+
+/**
+ * Units for the deltas in a WheelEvent.
+ * @enum {number}
+ */
+goog.events.WheelEvent.DeltaMode = {
+ /** The units are in pixels. From DOM_DELTA_PIXEL. */
+ PIXEL: 0,
+ /** The units are in lines. From DOM_DELTA_LINE. */
+ LINE: 1,
+ /** The units are in pages. From DOM_DELTA_PAGE. */
+ PAGE: 2
+};
+
+
+/**
+ * A conversion number between line scroll units and pixel scroll units. The
+ * actual value per line can vary a lot between devices and font sizes. This
+ * number can not be perfect, but it should be reasonable for converting lines
+ * scroll events into pixels.
+ * @const {number}
+ * @private
+ */
+goog.events.WheelEvent.PIXELS_PER_LINE_ = 15;
+
+
+/**
+ * A conversion number between page scroll units and pixel scroll units. The
+ * actual value per page can vary a lot as many different devices have different
+ * screen sizes, and the window might not be taking up the full screen. This
+ * number can not be perfect, but it should be reasonable for converting page
+ * scroll events into pixels.
+ * @const {number}
+ * @private
+ */
+goog.events.WheelEvent.PIXELS_PER_PAGE_ = 30 *
+ goog.events.WheelEvent.PIXELS_PER_LINE_;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/wheelhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/wheelhandler.js b/externs/GCL/externs/goog/events/wheelhandler.js
new file mode 100644
index 0000000..9d0f1e3
--- /dev/null
+++ b/externs/GCL/externs/goog/events/wheelhandler.js
@@ -0,0 +1,159 @@
+// 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 This event wrapper will dispatch an event when the user uses
+ * the wheel on an element. The event provides details of the unit type (pixel /
+ * line / page) and deltas in those units in up to 3 dimensions. Additionally,
+ * simplified pixel deltas are provided for code that doesn't need to handle the
+ * different units differently. This is not to be confused with the scroll
+ * event, where an element in the dom can report that it was scrolled.
+ *
+ * This class aims to smooth out inconsistencies between browser platforms with
+ * regards to wheel events, but we do not cover every possible software/hardware
+ * combination out there, some of which occasionally produce very large deltas
+ * in wheel events, especially when the device supports acceleration.
+ *
+ * Relevant standard:
+ * http://www.w3.org/TR/2014/WD-DOM-Level-3-Events-20140925/#interface-WheelEvent
+ *
+ * Clients of this code should be aware that some input devices only fire a few
+ * discrete events (such as a mouse wheel without acceleration) whereas some can
+ * generate a large number of events for a single interaction (such as a
+ * touchpad with acceleration). There is no signal in the events to reliably
+ * distinguish between these.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/wheelhandler.html
+ */
+
+goog.provide('goog.events.WheelHandler');
+
+goog.require('goog.dom');
+goog.require('goog.events');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.WheelEvent');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+goog.require('goog.userAgent.product');
+goog.require('goog.userAgent.product.isVersion');
+
+
+
+/**
+ * This event handler allows you to catch wheel events in a consistent manner.
+ * @param {!Element|!Document} element The element to listen to the wheel event
+ * on.
+ * @param {boolean=} opt_capture Whether to handle the wheel event in capture
+ * phase.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.events.WheelHandler = function(element, opt_capture) {
+ goog.events.WheelHandler.base(this, 'constructor');
+
+ /**
+ * This is the element that we will listen to the real wheel events on.
+ * @private {!Element|!Document}
+ */
+ this.element_ = element;
+
+ var rtlElement = goog.dom.isElement(this.element_) ?
+ /** @type {!Element} */ (this.element_) :
+ /** @type {!Document} */ (this.element_).body;
+
+ /**
+ * True if the element exists and is RTL, false otherwise.
+ * @private {boolean}
+ */
+ this.isRtl_ = !!rtlElement && goog.style.isRightToLeft(rtlElement);
+
+ /**
+ * The key returned from the goog.events.listen.
+ * @private {goog.events.Key}
+ */
+ this.listenKey_ = goog.events.listen(
+ this.element_, goog.events.WheelHandler.getDomEventType(),
+ this, opt_capture);
+};
+goog.inherits(goog.events.WheelHandler, goog.events.EventTarget);
+
+
+/**
+ * Returns the dom event type.
+ * @return {string} The dom event type.
+ */
+goog.events.WheelHandler.getDomEventType = function() {
+ // Prefer to use wheel events whenever supported.
+ if (goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher(17) ||
+ goog.userAgent.IE && goog.userAgent.isVersionOrHigher(9) ||
+ goog.userAgent.product.CHROME && goog.userAgent.product.isVersion(31)) {
+ return 'wheel';
+ }
+
+ // Legacy events. Still the best we have on Opera and Safari.
+ return goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel';
+};
+
+
+/**
+ * Handles the events on the element.
+ * @param {!goog.events.BrowserEvent} e The underlying browser event.
+ */
+goog.events.WheelHandler.prototype.handleEvent = function(e) {
+ var deltaMode = goog.events.WheelEvent.DeltaMode.PIXEL;
+ var deltaX = 0;
+ var deltaY = 0;
+ var deltaZ = 0;
+ var be = e.getBrowserEvent();
+ if (be.type == 'wheel') {
+ deltaMode = be.deltaMode;
+ deltaX = be.deltaX;
+ deltaY = be.deltaY;
+ deltaZ = be.deltaZ;
+ } else if (be.type == 'mousewheel') {
+ // Assume that these are still comparable to pixels. This may not be true
+ // for all old browsers.
+ if (goog.isDef(be.wheelDeltaX)) {
+ deltaX = -be.wheelDeltaX;
+ deltaY = -be.wheelDeltaY;
+ } else {
+ deltaY = -be.wheelDelta;
+ }
+ } else { // Historical Gecko
+ // Gecko returns multiple of 3 (representing the number of lines)
+ deltaMode = goog.events.WheelEvent.DeltaMode.LINE;
+ // Firefox 3.1 adds an axis field to the event to indicate axis.
+ if (goog.isDef(be.axis) && be.axis === be.HORIZONTAL_AXIS) {
+ deltaX = be.detail;
+ } else {
+ deltaY = be.detail;
+ }
+ }
+ // For horizontal deltas we need to flip the value for RTL grids.
+ if (this.isRtl_) {
+ deltaX = -deltaX;
+ }
+ var newEvent = new goog.events.WheelEvent(
+ be, deltaMode, deltaX, deltaY, deltaZ);
+ this.dispatchEvent(newEvent);
+};
+
+
+/** @override */
+goog.events.WheelHandler.prototype.disposeInternal = function() {
+ goog.events.WheelHandler.superClass_.disposeInternal.call(this);
+ goog.events.unlistenByKey(this.listenKey_);
+ this.listenKey_ = null;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/format/emailaddress.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/format/emailaddress.js b/externs/GCL/externs/goog/format/emailaddress.js
new file mode 100644
index 0000000..670bc33
--- /dev/null
+++ b/externs/GCL/externs/goog/format/emailaddress.js
@@ -0,0 +1,499 @@
+// 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 Provides functions to parse and manipulate email addresses.
+ *
+ */
+
+goog.provide('goog.format.EmailAddress');
+
+goog.require('goog.string');
+
+
+
+/**
+ * Formats an email address string for display, and allows for extraction of
+ * the individual components of the address.
+ * @param {string=} opt_address The email address.
+ * @param {string=} opt_name The name associated with the email address.
+ * @constructor
+ */
+goog.format.EmailAddress = function(opt_address, opt_name) {
+ /**
+ * The name or personal string associated with the address.
+ * @type {string}
+ * @private
+ */
+ this.name_ = opt_name || '';
+
+ /**
+ * The email address.
+ * @type {string}
+ * @protected
+ */
+ this.address = opt_address || '';
+};
+
+
+/**
+ * Match string for opening tokens.
+ * @type {string}
+ * @private
+ */
+goog.format.EmailAddress.OPENERS_ = '"<([';
+
+
+/**
+ * Match string for closing tokens.
+ * @type {string}
+ * @private
+ */
+goog.format.EmailAddress.CLOSERS_ = '">)]';
+
+
+/**
+ * Match string for characters that require display names to be quoted and are
+ * not address separators.
+ * @type {string}
+ * @const
+ * @package
+ */
+goog.format.EmailAddress.SPECIAL_CHARS = '()<>@:\\\".[]';
+
+
+/**
+ * Match string for address separators.
+ * @type {string}
+ * @const
+ * @private
+ */
+goog.format.EmailAddress.ADDRESS_SEPARATORS_ = ',;';
+
+
+/**
+ * Match string for characters that, when in a display name, require it to be
+ * quoted.
+ * @type {string}
+ * @const
+ * @private
+ */
+goog.format.EmailAddress.CHARS_REQUIRE_QUOTES_ =
+ goog.format.EmailAddress.SPECIAL_CHARS +
+ goog.format.EmailAddress.ADDRESS_SEPARATORS_;
+
+
+/**
+ * A RegExp to match all double quotes. Used in cleanAddress().
+ * @type {RegExp}
+ * @private
+ */
+goog.format.EmailAddress.ALL_DOUBLE_QUOTES_ = /\"/g;
+
+
+/**
+ * A RegExp to match escaped double quotes. Used in parse().
+ * @type {RegExp}
+ * @private
+ */
+goog.format.EmailAddress.ESCAPED_DOUBLE_QUOTES_ = /\\\"/g;
+
+
+/**
+ * A RegExp to match all backslashes. Used in cleanAddress().
+ * @type {RegExp}
+ * @private
+ */
+goog.format.EmailAddress.ALL_BACKSLASHES_ = /\\/g;
+
+
+/**
+ * A RegExp to match escaped backslashes. Used in parse().
+ * @type {RegExp}
+ * @private
+ */
+goog.format.EmailAddress.ESCAPED_BACKSLASHES_ = /\\\\/g;
+
+
+/**
+ * A string representing the RegExp for the local part of an email address.
+ * @private {string}
+ */
+goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ =
+ '[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}~-]+';
+
+
+/**
+ * A string representing the RegExp for the domain part of an email address.
+ * @private {string}
+ */
+goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ =
+ '([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9]{2,63}';
+
+
+/**
+ * A RegExp to match the local part of an email address.
+ * @private {!RegExp}
+ */
+goog.format.EmailAddress.LOCAL_PART_ =
+ new RegExp('^' + goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ + '$');
+
+
+/**
+ * A RegExp to match the domain part of an email address.
+ * @private {!RegExp}
+ */
+goog.format.EmailAddress.DOMAIN_PART_ =
+ new RegExp('^' + goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ + '$');
+
+
+/**
+ * A RegExp to match an email address.
+ * @private {!RegExp}
+ */
+goog.format.EmailAddress.EMAIL_ADDRESS_ =
+ new RegExp('^' + goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ + '@' +
+ goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ + '$');
+
+
+/**
+ * Get the name associated with the email address.
+ * @return {string} The name or personal portion of the address.
+ * @final
+ */
+goog.format.EmailAddress.prototype.getName = function() {
+ return this.name_;
+};
+
+
+/**
+ * Get the email address.
+ * @return {string} The email address.
+ * @final
+ */
+goog.format.EmailAddress.prototype.getAddress = function() {
+ return this.address;
+};
+
+
+/**
+ * Set the name associated with the email address.
+ * @param {string} name The name to associate.
+ * @final
+ */
+goog.format.EmailAddress.prototype.setName = function(name) {
+ this.name_ = name;
+};
+
+
+/**
+ * Set the email address.
+ * @param {string} address The email address.
+ * @final
+ */
+goog.format.EmailAddress.prototype.setAddress = function(address) {
+ this.address = address;
+};
+
+
+/**
+ * Return the address in a standard format:
+ * - remove extra spaces.
+ * - Surround name with quotes if it contains special characters.
+ * @return {string} The cleaned address.
+ * @override
+ */
+goog.format.EmailAddress.prototype.toString = function() {
+ return this.toStringInternal(
+ goog.format.EmailAddress.CHARS_REQUIRE_QUOTES_);
+};
+
+
+/**
+ * Check if a display name requires quoting.
+ * @param {string} name The display name
+ * @param {string} specialChars String that contains the characters that require
+ * the display name to be quoted. This may change based in whereas we are
+ * in EAI context or not.
+ * @return {boolean}
+ * @private
+ */
+goog.format.EmailAddress.isQuoteNeeded_ = function(name, specialChars) {
+ for (var i = 0; i < specialChars.length; i++) {
+ var specialChar = specialChars[i];
+ if (goog.string.contains(name, specialChar)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Return the address in a standard format:
+ * - remove extra spaces.
+ * - Surround name with quotes if it contains special characters.
+ * @param {string} specialChars String that contains the characters that require
+ * the display name to be quoted.
+ * @return {string} The cleaned address.
+ * @protected
+ */
+goog.format.EmailAddress.prototype.toStringInternal = function(specialChars) {
+ var name = this.getName();
+
+ // We intentionally remove double quotes in the name because escaping
+ // them to \" looks ugly.
+ name = name.replace(goog.format.EmailAddress.ALL_DOUBLE_QUOTES_, '');
+
+ // If the name has special characters, we need to quote it and escape \'s.
+ if (goog.format.EmailAddress.isQuoteNeeded_(name, specialChars)) {
+ name = '"' +
+ name.replace(goog.format.EmailAddress.ALL_BACKSLASHES_, '\\\\') + '"';
+ }
+
+ if (name == '') {
+ return this.address;
+ }
+ if (this.address == '') {
+ return name;
+ }
+ return name + ' <' + this.address + '>';
+};
+
+
+/**
+ * Determines is the current object is a valid email address.
+ * @return {boolean} Whether the email address is valid.
+ */
+goog.format.EmailAddress.prototype.isValid = function() {
+ return goog.format.EmailAddress.isValidAddrSpec(this.address);
+};
+
+
+/**
+ * Checks if the provided string is a valid email address. Supports both
+ * simple email addresses (address specs) and addresses that contain display
+ * names.
+ * @param {string} str The email address to check.
+ * @return {boolean} Whether the provided string is a valid address.
+ */
+goog.format.EmailAddress.isValidAddress = function(str) {
+ return goog.format.EmailAddress.parse(str).isValid();
+};
+
+
+/**
+ * Checks if the provided string is a valid address spec (local@domain.com).
+ * @param {string} str The email address to check.
+ * @return {boolean} Whether the provided string is a valid address spec.
+ */
+goog.format.EmailAddress.isValidAddrSpec = function(str) {
+ // This is a fairly naive implementation, but it covers 99% of use cases.
+ // For more details, see http://en.wikipedia.org/wiki/Email_address#Syntax
+ return goog.format.EmailAddress.EMAIL_ADDRESS_.test(str);
+};
+
+
+/**
+ * Checks if the provided string is a valid local part (part before the '@') of
+ * an email address.
+ * @param {string} str The local part to check.
+ * @return {boolean} Whether the provided string is a valid local part.
+ */
+goog.format.EmailAddress.isValidLocalPartSpec = function(str) {
+ return goog.format.EmailAddress.LOCAL_PART_.test(str);
+};
+
+
+/**
+ * Checks if the provided string is a valid domain part (part after the '@') of
+ * an email address.
+ * @param {string} str The domain part to check.
+ * @return {boolean} Whether the provided string is a valid domain part.
+ */
+goog.format.EmailAddress.isValidDomainPartSpec = function(str) {
+ return goog.format.EmailAddress.DOMAIN_PART_.test(str);
+};
+
+
+/**
+ * Parses an email address of the form "name" <address> ("name" is
+ * optional) into an email address.
+ * @param {string} addr The address string.
+ * @param {function(new: goog.format.EmailAddress, string=,string=)} ctor
+ * EmailAddress constructor to instantiate the output address.
+ * @return {!goog.format.EmailAddress} The parsed address.
+ * @protected
+ */
+goog.format.EmailAddress.parseInternal = function(addr, ctor) {
+ // TODO(ecattell): Strip bidi markers.
+ var name = '';
+ var address = '';
+ for (var i = 0; i < addr.length;) {
+ var token = goog.format.EmailAddress.getToken_(addr, i);
+ if (token.charAt(0) == '<' && token.indexOf('>') != -1) {
+ var end = token.indexOf('>');
+ address = token.substring(1, end);
+ } else if (address == '') {
+ name += token;
+ }
+ i += token.length;
+ }
+
+ // Check if it's a simple email address of the form "jlim@google.com".
+ if (address == '' && name.indexOf('@') != -1) {
+ address = name;
+ name = '';
+ }
+
+ name = goog.string.collapseWhitespace(name);
+ name = goog.string.stripQuotes(name, '\'');
+ name = goog.string.stripQuotes(name, '"');
+ // Replace escaped quotes and slashes.
+ name = name.replace(goog.format.EmailAddress.ESCAPED_DOUBLE_QUOTES_, '"');
+ name = name.replace(goog.format.EmailAddress.ESCAPED_BACKSLASHES_, '\\');
+ address = goog.string.collapseWhitespace(address);
+ return new ctor(address, name);
+};
+
+
+/**
+ * Parses an email address of the form "name" <address> into
+ * an email address.
+ * @param {string} addr The address string.
+ * @return {!goog.format.EmailAddress} The parsed address.
+ */
+goog.format.EmailAddress.parse = function(addr) {
+ return goog.format.EmailAddress.parseInternal(
+ addr, goog.format.EmailAddress);
+};
+
+
+/**
+ * Parse a string containing email addresses of the form
+ * "name" <address> into an array of email addresses.
+ * @param {string} str The address list.
+ * @param {function(string)} parser The parser to employ.
+ * @param {function(string):boolean} separatorChecker Accepts a character and
+ * returns whether it should be considered an address separator.
+ * @return {!Array<!goog.format.EmailAddress>} The parsed emails.
+ * @protected
+ */
+goog.format.EmailAddress.parseListInternal = function(
+ str, parser, separatorChecker) {
+ var result = [];
+ var email = '';
+ var token;
+
+ // Remove non-UNIX-style newlines that would otherwise cause getToken_ to
+ // choke. Remove multiple consecutive whitespace characters for the same
+ // reason.
+ str = goog.string.collapseWhitespace(str);
+
+ for (var i = 0; i < str.length; ) {
+ token = goog.format.EmailAddress.getToken_(str, i);
+ if (separatorChecker(token) ||
+ (token == ' ' && parser(email).isValid())) {
+ if (!goog.string.isEmptyOrWhitespace(email)) {
+ result.push(parser(email));
+ }
+ email = '';
+ i++;
+ continue;
+ }
+ email += token;
+ i += token.length;
+ }
+
+ // Add the final token.
+ if (!goog.string.isEmptyOrWhitespace(email)) {
+ result.push(parser(email));
+ }
+ return result;
+};
+
+
+/**
+ * Parses a string containing email addresses of the form
+ * "name" <address> into an array of email addresses.
+ * @param {string} str The address list.
+ * @return {!Array<!goog.format.EmailAddress>} The parsed emails.
+ */
+goog.format.EmailAddress.parseList = function(str) {
+ return goog.format.EmailAddress.parseListInternal(
+ str, goog.format.EmailAddress.parse,
+ goog.format.EmailAddress.isAddressSeparator);
+};
+
+
+/**
+ * Get the next token from a position in an address string.
+ * @param {string} str the string.
+ * @param {number} pos the position.
+ * @return {string} the token.
+ * @private
+ */
+goog.format.EmailAddress.getToken_ = function(str, pos) {
+ var ch = str.charAt(pos);
+ var p = goog.format.EmailAddress.OPENERS_.indexOf(ch);
+ if (p == -1) {
+ return ch;
+ }
+ if (goog.format.EmailAddress.isEscapedDlQuote_(str, pos)) {
+
+ // If an opener is an escaped quote we do not treat it as a real opener
+ // and keep accumulating the token.
+ return ch;
+ }
+ var closerChar = goog.format.EmailAddress.CLOSERS_.charAt(p);
+ var endPos = str.indexOf(closerChar, pos + 1);
+
+ // If the closer is a quote we go forward skipping escaped quotes until we
+ // hit the real closing one.
+ while (endPos >= 0 &&
+ goog.format.EmailAddress.isEscapedDlQuote_(str, endPos)) {
+ endPos = str.indexOf(closerChar, endPos + 1);
+ }
+ var token = (endPos >= 0) ? str.substring(pos, endPos + 1) : ch;
+ return token;
+};
+
+
+/**
+ * Checks if the character in the current position is an escaped double quote
+ * ( \" ).
+ * @param {string} str the string.
+ * @param {number} pos the position.
+ * @return {boolean} true if the char is escaped double quote.
+ * @private
+ */
+goog.format.EmailAddress.isEscapedDlQuote_ = function(str, pos) {
+ if (str.charAt(pos) != '"') {
+ return false;
+ }
+ var slashCount = 0;
+ for (var idx = pos - 1; idx >= 0 && str.charAt(idx) == '\\'; idx--) {
+ slashCount++;
+ }
+ return ((slashCount % 2) != 0);
+};
+
+
+/**
+ * @param {string} ch The character to test.
+ * @return {boolean} Whether the provided character is an address separator.
+ */
+goog.format.EmailAddress.isAddressSeparator = function(ch) {
+ return goog.string.contains(goog.format.EmailAddress.ADDRESS_SEPARATORS_, ch);
+};
[15/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/filesaver.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/filesaver.js b/externs/GCL/externs/goog/fs/filesaver.js
new file mode 100644
index 0000000..8d441c4
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/filesaver.js
@@ -0,0 +1,166 @@
+// 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 A wrapper for the HTML5 FileSaver object.
+ *
+ */
+
+goog.provide('goog.fs.FileSaver');
+goog.provide('goog.fs.FileSaver.EventType');
+goog.provide('goog.fs.FileSaver.ReadyState');
+
+goog.require('goog.events.EventTarget');
+goog.require('goog.fs.Error');
+goog.require('goog.fs.ProgressEvent');
+
+
+
+/**
+ * An object for monitoring the saving of files. This emits ProgressEvents of
+ * the types listed in {@link goog.fs.FileSaver.EventType}.
+ *
+ * This should not be instantiated directly. Instead, its subclass
+ * {@link goog.fs.FileWriter} should be accessed via
+ * {@link goog.fs.FileEntry#createWriter}.
+ *
+ * @param {!FileSaver} fileSaver The underlying FileSaver object.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.fs.FileSaver = function(fileSaver) {
+ goog.fs.FileSaver.base(this, 'constructor');
+
+ /**
+ * The underlying FileSaver object.
+ *
+ * @type {!FileSaver}
+ * @private
+ */
+ this.saver_ = fileSaver;
+
+ this.saver_.onwritestart = goog.bind(this.dispatchProgressEvent_, this);
+ this.saver_.onprogress = goog.bind(this.dispatchProgressEvent_, this);
+ this.saver_.onwrite = goog.bind(this.dispatchProgressEvent_, this);
+ this.saver_.onabort = goog.bind(this.dispatchProgressEvent_, this);
+ this.saver_.onerror = goog.bind(this.dispatchProgressEvent_, this);
+ this.saver_.onwriteend = goog.bind(this.dispatchProgressEvent_, this);
+};
+goog.inherits(goog.fs.FileSaver, goog.events.EventTarget);
+
+
+/**
+ * Possible states for a FileSaver.
+ *
+ * @enum {number}
+ */
+goog.fs.FileSaver.ReadyState = {
+ /**
+ * The object has been constructed, but there is no pending write.
+ */
+ INIT: 0,
+ /**
+ * Data is being written.
+ */
+ WRITING: 1,
+ /**
+ * The data has been written to the file, the write was aborted, or an error
+ * occurred.
+ */
+ DONE: 2
+};
+
+
+/**
+ * Events emitted by a FileSaver.
+ *
+ * @enum {string}
+ */
+goog.fs.FileSaver.EventType = {
+ /**
+ * Emitted when the writing begins. readyState will be WRITING.
+ */
+ WRITE_START: 'writestart',
+ /**
+ * Emitted when progress has been made in saving the file. readyState will be
+ * WRITING.
+ */
+ PROGRESS: 'progress',
+ /**
+ * Emitted when the data has been successfully written. readyState will be
+ * WRITING.
+ */
+ WRITE: 'write',
+ /**
+ * Emitted when the writing has been aborted. readyState will be WRITING.
+ */
+ ABORT: 'abort',
+ /**
+ * Emitted when an error is encountered or the writing has been aborted.
+ * readyState will be WRITING.
+ */
+ ERROR: 'error',
+ /**
+ * Emitted when the writing is finished, whether successfully or not.
+ * readyState will be DONE.
+ */
+ WRITE_END: 'writeend'
+};
+
+
+/**
+ * Abort the writing of the file.
+ */
+goog.fs.FileSaver.prototype.abort = function() {
+ try {
+ this.saver_.abort();
+ } catch (e) {
+ throw new goog.fs.Error(e, 'aborting save');
+ }
+};
+
+
+/**
+ * @return {goog.fs.FileSaver.ReadyState} The current state of the FileSaver.
+ */
+goog.fs.FileSaver.prototype.getReadyState = function() {
+ return /** @type {goog.fs.FileSaver.ReadyState} */ (this.saver_.readyState);
+};
+
+
+/**
+ * @return {goog.fs.Error} The error encountered while writing, if any.
+ */
+goog.fs.FileSaver.prototype.getError = function() {
+ return this.saver_.error &&
+ new goog.fs.Error(this.saver_.error, 'saving file');
+};
+
+
+/**
+ * Wrap a progress event emitted by the underlying file saver and re-emit it.
+ *
+ * @param {!ProgressEvent} event The underlying event.
+ * @private
+ */
+goog.fs.FileSaver.prototype.dispatchProgressEvent_ = function(event) {
+ this.dispatchEvent(new goog.fs.ProgressEvent(event, this));
+};
+
+
+/** @override */
+goog.fs.FileSaver.prototype.disposeInternal = function() {
+ delete this.saver_;
+ goog.fs.FileSaver.base(this, 'disposeInternal');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/filesystem.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/filesystem.js b/externs/GCL/externs/goog/fs/filesystem.js
new file mode 100644
index 0000000..b120b92
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/filesystem.js
@@ -0,0 +1,41 @@
+// 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 A wrapper for the HTML5 FileSystem object.
+ *
+ */
+
+goog.provide('goog.fs.FileSystem');
+
+
+
+/**
+ * A local filesystem.
+ *
+ * @interface
+ */
+goog.fs.FileSystem = function() {};
+
+
+/**
+ * @return {string} The name of the filesystem.
+ */
+goog.fs.FileSystem.prototype.getName = function() {};
+
+
+/**
+ * @return {!goog.fs.DirectoryEntry} The root directory of the filesystem.
+ */
+goog.fs.FileSystem.prototype.getRoot = function() {};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/filesystemimpl.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/filesystemimpl.js b/externs/GCL/externs/goog/fs/filesystemimpl.js
new file mode 100644
index 0000000..b5ebb33
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/filesystemimpl.js
@@ -0,0 +1,65 @@
+// 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 Concrete implementation of the goog.fs.FileSystem interface
+ * using an HTML FileSystem object.
+ */
+goog.provide('goog.fs.FileSystemImpl');
+
+goog.require('goog.fs.DirectoryEntryImpl');
+goog.require('goog.fs.FileSystem');
+
+
+
+/**
+ * A local filesystem.
+ *
+ * This shouldn't be instantiated directly. Instead, it should be accessed via
+ * {@link goog.fs.getTemporary} or {@link goog.fs.getPersistent}.
+ *
+ * @param {!FileSystem} fs The underlying FileSystem object.
+ * @constructor
+ * @implements {goog.fs.FileSystem}
+ * @final
+ */
+goog.fs.FileSystemImpl = function(fs) {
+ /**
+ * The underlying FileSystem object.
+ *
+ * @type {!FileSystem}
+ * @private
+ */
+ this.fs_ = fs;
+};
+
+
+/** @override */
+goog.fs.FileSystemImpl.prototype.getName = function() {
+ return this.fs_.name;
+};
+
+
+/** @override */
+goog.fs.FileSystemImpl.prototype.getRoot = function() {
+ return new goog.fs.DirectoryEntryImpl(this, this.fs_.root);
+};
+
+
+/**
+ * @return {!FileSystem} The underlying FileSystem object.
+ */
+goog.fs.FileSystemImpl.prototype.getBrowserFileSystem = function() {
+ return this.fs_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/filewriter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/filewriter.js b/externs/GCL/externs/goog/fs/filewriter.js
new file mode 100644
index 0000000..1709846
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/filewriter.js
@@ -0,0 +1,111 @@
+// 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 A wrapper for the HTML5 FileWriter object.
+ *
+ * When adding or modifying functionality in this namespace, be sure to update
+ * the mock counterparts in goog.testing.fs.
+ *
+ */
+
+goog.provide('goog.fs.FileWriter');
+
+goog.require('goog.fs.Error');
+goog.require('goog.fs.FileSaver');
+
+
+
+/**
+ * An object for monitoring the saving of files, as well as other fine-grained
+ * writing operations.
+ *
+ * This should not be instantiated directly. Instead, it should be accessed via
+ * {@link goog.fs.FileEntry#createWriter}.
+ *
+ * @param {!FileWriter} writer The underlying FileWriter object.
+ * @constructor
+ * @extends {goog.fs.FileSaver}
+ * @final
+ */
+goog.fs.FileWriter = function(writer) {
+ goog.fs.FileWriter.base(this, 'constructor', writer);
+
+ /**
+ * The underlying FileWriter object.
+ *
+ * @type {!FileWriter}
+ * @private
+ */
+ this.writer_ = writer;
+};
+goog.inherits(goog.fs.FileWriter, goog.fs.FileSaver);
+
+
+/**
+ * @return {number} The byte offset at which the next write will occur.
+ */
+goog.fs.FileWriter.prototype.getPosition = function() {
+ return this.writer_.position;
+};
+
+
+/**
+ * @return {number} The length of the file.
+ */
+goog.fs.FileWriter.prototype.getLength = function() {
+ return this.writer_.length;
+};
+
+
+/**
+ * Write data to the file.
+ *
+ * @param {!Blob} blob The data to write.
+ */
+goog.fs.FileWriter.prototype.write = function(blob) {
+ try {
+ this.writer_.write(blob);
+ } catch (e) {
+ throw new goog.fs.Error(e, 'writing file');
+ }
+};
+
+
+/**
+ * Set the file position at which the next write will occur.
+ *
+ * @param {number} offset An absolute byte offset into the file.
+ */
+goog.fs.FileWriter.prototype.seek = function(offset) {
+ try {
+ this.writer_.seek(offset);
+ } catch (e) {
+ throw new goog.fs.Error(e, 'seeking in file');
+ }
+};
+
+
+/**
+ * Changes the length of the file to that specified.
+ *
+ * @param {number} size The new size of the file, in bytes.
+ */
+goog.fs.FileWriter.prototype.truncate = function(size) {
+ try {
+ this.writer_.truncate(size);
+ } catch (e) {
+ throw new goog.fs.Error(e, 'truncating file');
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/fs.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/fs.js b/externs/GCL/externs/goog/fs/fs.js
new file mode 100644
index 0000000..6081f6e
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/fs.js
@@ -0,0 +1,278 @@
+// 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 Wrappers for the HTML5 File API. These wrappers closely mirror
+ * the underlying APIs, but use Closure-style events and Deferred return values.
+ * Their existence also makes it possible to mock the FileSystem API for testing
+ * in browsers that don't support it natively.
+ *
+ * When adding public functions to anything under this namespace, be sure to add
+ * its mock counterpart to goog.testing.fs.
+ *
+ */
+
+goog.provide('goog.fs');
+
+goog.require('goog.array');
+goog.require('goog.async.Deferred');
+goog.require('goog.fs.Error');
+goog.require('goog.fs.FileReader');
+goog.require('goog.fs.FileSystemImpl');
+goog.require('goog.fs.url');
+goog.require('goog.userAgent');
+
+
+/**
+ * Get a wrapped FileSystem object.
+ *
+ * @param {goog.fs.FileSystemType_} type The type of the filesystem to get.
+ * @param {number} size The size requested for the filesystem, in bytes.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ * @private
+ */
+goog.fs.get_ = function(type, size) {
+ var requestFileSystem = goog.global.requestFileSystem ||
+ goog.global.webkitRequestFileSystem;
+
+ if (!goog.isFunction(requestFileSystem)) {
+ return goog.async.Deferred.fail(new Error('File API unsupported'));
+ }
+
+ var d = new goog.async.Deferred();
+ requestFileSystem(type, size, function(fs) {
+ d.callback(new goog.fs.FileSystemImpl(fs));
+ }, function(err) {
+ d.errback(new goog.fs.Error(err, 'requesting filesystem'));
+ });
+ return d;
+};
+
+
+/**
+ * The two types of filesystem.
+ *
+ * @enum {number}
+ * @private
+ */
+goog.fs.FileSystemType_ = {
+ /**
+ * A temporary filesystem may be deleted by the user agent at its discretion.
+ */
+ TEMPORARY: 0,
+ /**
+ * A persistent filesystem will never be deleted without the user's or
+ * application's authorization.
+ */
+ PERSISTENT: 1
+};
+
+
+/**
+ * Returns a temporary FileSystem object. A temporary filesystem may be deleted
+ * by the user agent at its discretion.
+ *
+ * @param {number} size The size requested for the filesystem, in bytes.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.getTemporary = function(size) {
+ return goog.fs.get_(goog.fs.FileSystemType_.TEMPORARY, size);
+};
+
+
+/**
+ * Returns a persistent FileSystem object. A persistent filesystem will never be
+ * deleted without the user's or application's authorization.
+ *
+ * @param {number} size The size requested for the filesystem, in bytes.
+ * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
+ * error occurs, the errback is called with a {@link goog.fs.Error}.
+ */
+goog.fs.getPersistent = function(size) {
+ return goog.fs.get_(goog.fs.FileSystemType_.PERSISTENT, size);
+};
+
+
+/**
+ * Creates a blob URL for a blob object.
+ * Throws an error if the browser does not support Object Urls.
+ *
+ * TODO(user): Update references to this method to use
+ * goog.fs.url.createObjectUrl instead.
+ *
+ * @param {!Blob} blob The object for which to create the URL.
+ * @return {string} The URL for the object.
+ */
+goog.fs.createObjectUrl = function(blob) {
+ return goog.fs.url.createObjectUrl(blob);
+};
+
+
+/**
+ * Revokes a URL created by {@link goog.fs.createObjectUrl}.
+ * Throws an error if the browser does not support Object Urls.
+ *
+ * TODO(user): Update references to this method to use
+ * goog.fs.url.revokeObjectUrl instead.
+ *
+ * @param {string} url The URL to revoke.
+ */
+goog.fs.revokeObjectUrl = function(url) {
+ goog.fs.url.revokeObjectUrl(url);
+};
+
+
+/**
+ * Checks whether this browser supports Object Urls. If not, calls to
+ * createObjectUrl and revokeObjectUrl will result in an error.
+ *
+ * TODO(user): Update references to this method to use
+ * goog.fs.url.browserSupportsObjectUrls instead.
+ *
+ * @return {boolean} True if this browser supports Object Urls.
+ */
+goog.fs.browserSupportsObjectUrls = function() {
+ return goog.fs.url.browserSupportsObjectUrls();
+};
+
+
+/**
+ * Concatenates one or more values together and converts them to a Blob.
+ *
+ * @param {...(string|!Blob|!ArrayBuffer)} var_args The values that will make up
+ * the resulting blob.
+ * @return {!Blob} The blob.
+ */
+goog.fs.getBlob = function(var_args) {
+ var BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
+
+ if (goog.isDef(BlobBuilder)) {
+ var bb = new BlobBuilder();
+ for (var i = 0; i < arguments.length; i++) {
+ bb.append(arguments[i]);
+ }
+ return bb.getBlob();
+ } else {
+ return goog.fs.getBlobWithProperties(goog.array.toArray(arguments));
+ }
+};
+
+
+/**
+ * Creates a blob with the given properties.
+ * See https://developer.mozilla.org/en-US/docs/Web/API/Blob for more details.
+ *
+ * @param {Array<string|!Blob>} parts The values that will make up the
+ * resulting blob.
+ * @param {string=} opt_type The MIME type of the Blob.
+ * @param {string=} opt_endings Specifies how strings containing newlines are to
+ * be written out.
+ * @return {!Blob} The blob.
+ */
+goog.fs.getBlobWithProperties = function(parts, opt_type, opt_endings) {
+ var BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
+
+ if (goog.isDef(BlobBuilder)) {
+ var bb = new BlobBuilder();
+ for (var i = 0; i < parts.length; i++) {
+ bb.append(parts[i], opt_endings);
+ }
+ return bb.getBlob(opt_type);
+ } else if (goog.isDef(goog.global.Blob)) {
+ var properties = {};
+ if (opt_type) {
+ properties['type'] = opt_type;
+ }
+ if (opt_endings) {
+ properties['endings'] = opt_endings;
+ }
+ return new Blob(parts, properties);
+ } else {
+ throw Error('This browser doesn\'t seem to support creating Blobs');
+ }
+};
+
+
+/**
+ * Converts a Blob or a File into a string. This should only be used when the
+ * blob is known to be small.
+ *
+ * @param {!Blob} blob The blob to convert.
+ * @param {string=} opt_encoding The name of the encoding to use.
+ * @return {!goog.async.Deferred} The deferred string. If an error occurrs, the
+ * errback is called with a {@link goog.fs.Error}.
+ * @deprecated Use {@link goog.fs.FileReader.readAsText} instead.
+ */
+goog.fs.blobToString = function(blob, opt_encoding) {
+ return goog.fs.FileReader.readAsText(blob, opt_encoding);
+};
+
+
+/**
+ * Slices the blob. The returned blob contains data from the start byte
+ * (inclusive) till the end byte (exclusive). Negative indices can be used
+ * to count bytes from the end of the blob (-1 == blob.size - 1). Indices
+ * are always clamped to blob range. If end is omitted, all the data till
+ * the end of the blob is taken.
+ *
+ * @param {!Blob} blob The blob to be sliced.
+ * @param {number} start Index of the starting byte.
+ * @param {number=} opt_end Index of the ending byte.
+ * @return {Blob} The blob slice or null if not supported.
+ */
+goog.fs.sliceBlob = function(blob, start, opt_end) {
+ if (!goog.isDef(opt_end)) {
+ opt_end = blob.size;
+ }
+ if (blob.webkitSlice) {
+ // Natively accepts negative indices, clamping to the blob range and
+ // range end is optional. See http://trac.webkit.org/changeset/83873
+ return blob.webkitSlice(start, opt_end);
+ } else if (blob.mozSlice) {
+ // Natively accepts negative indices, clamping to the blob range and
+ // range end is optional. See https://developer.mozilla.org/en/DOM/Blob
+ // and http://hg.mozilla.org/mozilla-central/rev/dae833f4d934
+ return blob.mozSlice(start, opt_end);
+ } else if (blob.slice) {
+ // Old versions of Firefox and Chrome use the original specification.
+ // Negative indices are not accepted, only range end is clamped and
+ // range end specification is obligatory.
+ // See http://www.w3.org/TR/2009/WD-FileAPI-20091117/
+ if ((goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('13.0')) ||
+ (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('537.1'))) {
+ if (start < 0) {
+ start += blob.size;
+ }
+ if (start < 0) {
+ start = 0;
+ }
+ if (opt_end < 0) {
+ opt_end += blob.size;
+ }
+ if (opt_end < start) {
+ opt_end = start;
+ }
+ return blob.slice(start, opt_end - start);
+ }
+ // IE and the latest versions of Firefox and Chrome use the new
+ // specification. Natively accepts negative indices, clamping to the blob
+ // range and range end is optional.
+ // See http://dev.w3.org/2006/webapi/FileAPI/
+ return blob.slice(start, opt_end);
+ }
+ return null;
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/progressevent.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/progressevent.js b/externs/GCL/externs/goog/fs/progressevent.js
new file mode 100644
index 0000000..b0695be
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/progressevent.js
@@ -0,0 +1,69 @@
+// 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 A wrapper for the HTML5 File ProgressEvent objects.
+ *
+ */
+goog.provide('goog.fs.ProgressEvent');
+
+goog.require('goog.events.Event');
+
+
+
+/**
+ * A wrapper for the progress events emitted by the File APIs.
+ *
+ * @param {!ProgressEvent} event The underlying event object.
+ * @param {!Object} target The file access object emitting the event.
+ * @extends {goog.events.Event}
+ * @constructor
+ * @final
+ */
+goog.fs.ProgressEvent = function(event, target) {
+ goog.fs.ProgressEvent.base(this, 'constructor', event.type, target);
+
+ /**
+ * The underlying event object.
+ * @type {!ProgressEvent}
+ * @private
+ */
+ this.event_ = event;
+};
+goog.inherits(goog.fs.ProgressEvent, goog.events.Event);
+
+
+/**
+ * @return {boolean} Whether or not the total size of the of the file being
+ * saved is known.
+ */
+goog.fs.ProgressEvent.prototype.isLengthComputable = function() {
+ return this.event_.lengthComputable;
+};
+
+
+/**
+ * @return {number} The number of bytes saved so far.
+ */
+goog.fs.ProgressEvent.prototype.getLoaded = function() {
+ return this.event_.loaded;
+};
+
+
+/**
+ * @return {number} The total number of bytes in the file being saved.
+ */
+goog.fs.ProgressEvent.prototype.getTotal = function() {
+ return this.event_.total;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fs/url.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fs/url.js b/externs/GCL/externs/goog/fs/url.js
new file mode 100644
index 0000000..083c066
--- /dev/null
+++ b/externs/GCL/externs/goog/fs/url.js
@@ -0,0 +1,105 @@
+// Copyright 2015 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 Wrapper for URL and its createObjectUrl and revokeObjectUrl
+ * methods that are part of the HTML5 File API.
+ */
+
+goog.provide('goog.fs.url');
+
+
+/**
+ * Creates a blob URL for a blob object.
+ * Throws an error if the browser does not support Object Urls.
+ *
+ * @param {!Blob} blob The object for which to create the URL.
+ * @return {string} The URL for the object.
+ */
+goog.fs.url.createObjectUrl = function(blob) {
+ return goog.fs.url.getUrlObject_().createObjectURL(blob);
+};
+
+
+/**
+ * Revokes a URL created by {@link goog.fs.url.createObjectUrl}.
+ * Throws an error if the browser does not support Object Urls.
+ *
+ * @param {string} url The URL to revoke.
+ */
+goog.fs.url.revokeObjectUrl = function(url) {
+ goog.fs.url.getUrlObject_().revokeObjectURL(url);
+};
+
+
+/**
+ * @typedef {{createObjectURL: (function(!Blob): string),
+ * revokeObjectURL: function(string): void}}
+ */
+goog.fs.url.UrlObject_;
+
+
+/**
+ * Get the object that has the createObjectURL and revokeObjectURL functions for
+ * this browser.
+ *
+ * @return {goog.fs.url.UrlObject_} The object for this browser.
+ * @private
+ */
+goog.fs.url.getUrlObject_ = function() {
+ var urlObject = goog.fs.url.findUrlObject_();
+ if (urlObject != null) {
+ return urlObject;
+ } else {
+ throw Error('This browser doesn\'t seem to support blob URLs');
+ }
+};
+
+
+/**
+ * Finds the object that has the createObjectURL and revokeObjectURL functions
+ * for this browser.
+ *
+ * @return {?goog.fs.url.UrlObject_} The object for this browser or null if the
+ * browser does not support Object Urls.
+ * @private
+ */
+goog.fs.url.findUrlObject_ = function() {
+ // This is what the spec says to do
+ // http://dev.w3.org/2006/webapi/FileAPI/#dfn-createObjectURL
+ if (goog.isDef(goog.global.URL) &&
+ goog.isDef(goog.global.URL.createObjectURL)) {
+ return /** @type {goog.fs.url.UrlObject_} */ (goog.global.URL);
+ // This is what Chrome does (as of 10.0.648.6 dev)
+ } else if (goog.isDef(goog.global.webkitURL) &&
+ goog.isDef(goog.global.webkitURL.createObjectURL)) {
+ return /** @type {goog.fs.url.UrlObject_} */ (goog.global.webkitURL);
+ // This is what the spec used to say to do
+ } else if (goog.isDef(goog.global.createObjectURL)) {
+ return /** @type {goog.fs.url.UrlObject_} */ (goog.global);
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Checks whether this browser supports Object Urls. If not, calls to
+ * createObjectUrl and revokeObjectUrl will result in an error.
+ *
+ * @return {boolean} True if this browser supports Object Urls.
+ */
+goog.fs.url.browserSupportsObjectUrls = function() {
+ return goog.fs.url.findUrlObject_() != null;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/functions/functions.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/functions/functions.js b/externs/GCL/externs/goog/functions/functions.js
new file mode 100644
index 0000000..d7ccf40
--- /dev/null
+++ b/externs/GCL/externs/goog/functions/functions.js
@@ -0,0 +1,332 @@
+// 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 creating functions. Loosely inspired by the
+ * java classes: http://goo.gl/GM0Hmu and http://goo.gl/6k7nI8.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+
+goog.provide('goog.functions');
+
+
+/**
+ * Creates a function that always returns the same value.
+ * @param {T} retValue The value to return.
+ * @return {function():T} The new function.
+ * @template T
+ */
+goog.functions.constant = function(retValue) {
+ return function() {
+ return retValue;
+ };
+};
+
+
+/**
+ * Always returns false.
+ * @type {function(...): boolean}
+ */
+goog.functions.FALSE = goog.functions.constant(false);
+
+
+/**
+ * Always returns true.
+ * @type {function(...): boolean}
+ */
+goog.functions.TRUE = goog.functions.constant(true);
+
+
+/**
+ * Always returns NULL.
+ * @type {function(...): null}
+ */
+goog.functions.NULL = goog.functions.constant(null);
+
+
+/**
+ * A simple function that returns the first argument of whatever is passed
+ * into it.
+ * @param {T=} opt_returnValue The single value that will be returned.
+ * @param {...*} var_args Optional trailing arguments. These are ignored.
+ * @return {T} The first argument passed in, or undefined if nothing was passed.
+ * @template T
+ */
+goog.functions.identity = function(opt_returnValue, var_args) {
+ return opt_returnValue;
+};
+
+
+/**
+ * Creates a function that always throws an error with the given message.
+ * @param {string} message The error message.
+ * @return {!Function} The error-throwing function.
+ */
+goog.functions.error = function(message) {
+ return function() {
+ throw Error(message);
+ };
+};
+
+
+/**
+ * Creates a function that throws the given object.
+ * @param {*} err An object to be thrown.
+ * @return {!Function} The error-throwing function.
+ */
+goog.functions.fail = function(err) {
+ return function() {
+ throw err;
+ }
+};
+
+
+/**
+ * Given a function, create a function that keeps opt_numArgs arguments and
+ * silently discards all additional arguments.
+ * @param {Function} f The original function.
+ * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.
+ * @return {!Function} A version of f that only keeps the first opt_numArgs
+ * arguments.
+ */
+goog.functions.lock = function(f, opt_numArgs) {
+ opt_numArgs = opt_numArgs || 0;
+ return function() {
+ return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs));
+ };
+};
+
+
+/**
+ * Creates a function that returns its nth argument.
+ * @param {number} n The position of the return argument.
+ * @return {!Function} A new function.
+ */
+goog.functions.nth = function(n) {
+ return function() {
+ return arguments[n];
+ };
+};
+
+
+/**
+ * Given a function, create a new function that swallows its return value
+ * and replaces it with a new one.
+ * @param {Function} f A function.
+ * @param {T} retValue A new return value.
+ * @return {function(...?):T} A new function.
+ * @template T
+ */
+goog.functions.withReturnValue = function(f, retValue) {
+ return goog.functions.sequence(f, goog.functions.constant(retValue));
+};
+
+
+/**
+ * Creates a function that returns whether its arguement equals the given value.
+ *
+ * Example:
+ * var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));
+ *
+ * @param {*} value The value to compare to.
+ * @param {boolean=} opt_useLooseComparison Whether to use a loose (==)
+ * comparison rather than a strict (===) one. Defaults to false.
+ * @return {function(*):boolean} The new function.
+ */
+goog.functions.equalTo = function(value, opt_useLooseComparison) {
+ return function(other) {
+ return opt_useLooseComparison ? (value == other) : (value === other);
+ };
+};
+
+
+/**
+ * Creates the composition of the functions passed in.
+ * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
+ * @param {function(...?):T} fn The final function.
+ * @param {...Function} var_args A list of functions.
+ * @return {function(...?):T} The composition of all inputs.
+ * @template T
+ */
+goog.functions.compose = function(fn, var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ var result;
+ if (length) {
+ result = functions[length - 1].apply(this, arguments);
+ }
+
+ for (var i = length - 2; i >= 0; i--) {
+ result = functions[i].call(this, result);
+ }
+ return result;
+ };
+};
+
+
+/**
+ * Creates a function that calls the functions passed in in sequence, and
+ * returns the value of the last function. For example,
+ * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).
+ * @param {...Function} var_args A list of functions.
+ * @return {!Function} A function that calls all inputs in sequence.
+ */
+goog.functions.sequence = function(var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ var result;
+ for (var i = 0; i < length; i++) {
+ result = functions[i].apply(this, arguments);
+ }
+ return result;
+ };
+};
+
+
+/**
+ * Creates a function that returns true if each of its components evaluates
+ * to true. The components are evaluated in order, and the evaluation will be
+ * short-circuited as soon as a function returns false.
+ * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
+ * @param {...Function} var_args A list of functions.
+ * @return {function(...?):boolean} A function that ANDs its component
+ * functions.
+ */
+goog.functions.and = function(var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ for (var i = 0; i < length; i++) {
+ if (!functions[i].apply(this, arguments)) {
+ return false;
+ }
+ }
+ return true;
+ };
+};
+
+
+/**
+ * Creates a function that returns true if any of its components evaluates
+ * to true. The components are evaluated in order, and the evaluation will be
+ * short-circuited as soon as a function returns true.
+ * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
+ * @param {...Function} var_args A list of functions.
+ * @return {function(...?):boolean} A function that ORs its component
+ * functions.
+ */
+goog.functions.or = function(var_args) {
+ var functions = arguments;
+ var length = functions.length;
+ return function() {
+ for (var i = 0; i < length; i++) {
+ if (functions[i].apply(this, arguments)) {
+ return true;
+ }
+ }
+ return false;
+ };
+};
+
+
+/**
+ * Creates a function that returns the Boolean opposite of a provided function.
+ * For example, (goog.functions.not(f))(x) is equivalent to !f(x).
+ * @param {!Function} f The original function.
+ * @return {function(...?):boolean} A function that delegates to f and returns
+ * opposite.
+ */
+goog.functions.not = function(f) {
+ return function() {
+ return !f.apply(this, arguments);
+ };
+};
+
+
+/**
+ * Generic factory function to construct an object given the constructor
+ * and the arguments. Intended to be bound to create object factories.
+ *
+ * Example:
+ *
+ * var factory = goog.partial(goog.functions.create, Class);
+ *
+ * @param {function(new:T, ...)} constructor The constructor for the Object.
+ * @param {...*} var_args The arguments to be passed to the constructor.
+ * @return {T} A new instance of the class given in {@code constructor}.
+ * @template T
+ */
+goog.functions.create = function(constructor, var_args) {
+ /**
+ * @constructor
+ * @final
+ */
+ var temp = function() {};
+ temp.prototype = constructor.prototype;
+
+ // obj will have constructor's prototype in its chain and
+ // 'obj instanceof constructor' will be true.
+ var obj = new temp();
+
+ // obj is initialized by constructor.
+ // arguments is only array-like so lacks shift(), but can be used with
+ // the Array prototype function.
+ constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
+ return obj;
+};
+
+
+/**
+ * @define {boolean} Whether the return value cache should be used.
+ * This should only be used to disable caches when testing.
+ */
+goog.define('goog.functions.CACHE_RETURN_VALUE', true);
+
+
+/**
+ * Gives a wrapper function that caches the return value of a parameterless
+ * function when first called.
+ *
+ * When called for the first time, the given function is called and its
+ * return value is cached (thus this is only appropriate for idempotent
+ * functions). Subsequent calls will return the cached return value. This
+ * allows the evaluation of expensive functions to be delayed until first used.
+ *
+ * To cache the return values of functions with parameters, see goog.memoize.
+ *
+ * @param {!function():T} fn A function to lazily evaluate.
+ * @return {!function():T} A wrapped version the function.
+ * @template T
+ */
+goog.functions.cacheReturnValue = function(fn) {
+ var called = false;
+ var value;
+
+ return function() {
+ if (!goog.functions.CACHE_RETURN_VALUE) {
+ return fn();
+ }
+
+ if (!called) {
+ value = fn();
+ called = true;
+ }
+
+ return value;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/abstractdragdrop.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/abstractdragdrop.js b/externs/GCL/externs/goog/fx/abstractdragdrop.js
new file mode 100644
index 0000000..afd4af8
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/abstractdragdrop.js
@@ -0,0 +1,1540 @@
+// 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 Abstract Base Class for Drag and Drop.
+ *
+ * Provides functionality for implementing drag and drop classes. Also provides
+ * support classes and events.
+ *
+ * @author eae@google.com (Emil A Eklund)
+ */
+
+goog.provide('goog.fx.AbstractDragDrop');
+goog.provide('goog.fx.AbstractDragDrop.EventType');
+goog.provide('goog.fx.DragDropEvent');
+goog.provide('goog.fx.DragDropItem');
+
+goog.require('goog.asserts');
+goog.require('goog.dom');
+goog.require('goog.dom.classlist');
+goog.require('goog.events');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.fx.Dragger');
+goog.require('goog.math.Box');
+goog.require('goog.math.Coordinate');
+goog.require('goog.style');
+
+
+
+/**
+ * Abstract class that provides reusable functionality for implementing drag
+ * and drop functionality.
+ *
+ * This class also allows clients to define their own subtargeting function
+ * so that drop areas can have finer granularity then a singe element. This is
+ * accomplished by using a client provided function to map from element and
+ * coordinates to a subregion id.
+ *
+ * This class can also be made aware of scrollable containers that contain
+ * drop targets by calling addScrollableContainer. This will cause dnd to
+ * take changing scroll positions into account while a drag is occuring.
+ *
+ * @extends {goog.events.EventTarget}
+ * @constructor
+ */
+goog.fx.AbstractDragDrop = function() {
+ goog.fx.AbstractDragDrop.base(this, 'constructor');
+
+ /**
+ * List of items that makes up the drag source or drop target.
+ * @type {Array<goog.fx.DragDropItem>}
+ * @protected
+ * @suppress {underscore|visibility}
+ */
+ this.items_ = [];
+
+ /**
+ * List of associated drop targets.
+ * @type {Array<goog.fx.AbstractDragDrop>}
+ * @private
+ */
+ this.targets_ = [];
+
+ /**
+ * Scrollable containers to account for during drag
+ * @type {Array<goog.fx.ScrollableContainer_>}
+ * @private
+ */
+ this.scrollableContainers_ = [];
+
+};
+goog.inherits(goog.fx.AbstractDragDrop, goog.events.EventTarget);
+
+
+/**
+ * Minimum size (in pixels) for a dummy target. If the box for the target is
+ * less than the specified size it's not created.
+ * @type {number}
+ * @private
+ */
+goog.fx.AbstractDragDrop.DUMMY_TARGET_MIN_SIZE_ = 10;
+
+
+/**
+ * Flag indicating if it's a drag source, set by addTarget.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.isSource_ = false;
+
+
+/**
+ * Flag indicating if it's a drop target, set when added as target to another
+ * DragDrop object.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.isTarget_ = false;
+
+
+/**
+ * Subtargeting function accepting args:
+ * (goog.fx.DragDropItem, goog.math.Box, number, number)
+ * @type {Function}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.subtargetFunction_;
+
+
+/**
+ * Last active subtarget.
+ * @type {Object}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.activeSubtarget_;
+
+
+/**
+ * Class name to add to source elements being dragged. Set by setDragClass.
+ * @type {?string}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.dragClass_;
+
+
+/**
+ * Class name to add to source elements. Set by setSourceClass.
+ * @type {?string}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.sourceClass_;
+
+
+/**
+ * Class name to add to target elements. Set by setTargetClass.
+ * @type {?string}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.targetClass_;
+
+
+/**
+ * The SCROLL event target used to make drag element follow scrolling.
+ * @type {EventTarget}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.scrollTarget_;
+
+
+/**
+ * Dummy target, {@see maybeCreateDummyTargetForPosition_}.
+ * @type {goog.fx.ActiveDropTarget_}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.dummyTarget_;
+
+
+/**
+ * Whether the object has been initialized.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.initialized_ = false;
+
+
+/**
+ * Constants for event names
+ * @const
+ */
+goog.fx.AbstractDragDrop.EventType = {
+ DRAGOVER: 'dragover',
+ DRAGOUT: 'dragout',
+ DRAG: 'drag',
+ DROP: 'drop',
+ DRAGSTART: 'dragstart',
+ DRAGEND: 'dragend'
+};
+
+
+/**
+ * Constant for distance threshold, in pixels, an element has to be moved to
+ * initiate a drag operation.
+ * @type {number}
+ */
+goog.fx.AbstractDragDrop.initDragDistanceThreshold = 5;
+
+
+/**
+ * Set class to add to source elements being dragged.
+ *
+ * @param {string} className Class to be added. Must be a single, valid
+ * classname.
+ */
+goog.fx.AbstractDragDrop.prototype.setDragClass = function(className) {
+ this.dragClass_ = className;
+};
+
+
+/**
+ * Set class to add to source elements.
+ *
+ * @param {string} className Class to be added. Must be a single, valid
+ * classname.
+ */
+goog.fx.AbstractDragDrop.prototype.setSourceClass = function(className) {
+ this.sourceClass_ = className;
+};
+
+
+/**
+ * Set class to add to target elements.
+ *
+ * @param {string} className Class to be added. Must be a single, valid
+ * classname.
+ */
+goog.fx.AbstractDragDrop.prototype.setTargetClass = function(className) {
+ this.targetClass_ = className;
+};
+
+
+/**
+ * Whether the control has been initialized.
+ *
+ * @return {boolean} True if it's been initialized.
+ */
+goog.fx.AbstractDragDrop.prototype.isInitialized = function() {
+ return this.initialized_;
+};
+
+
+/**
+ * Add item to drag object.
+ *
+ * @param {Element|string} element Dom Node, or string representation of node
+ * id, to be used as drag source/drop target.
+ * @throws Error Thrown if called on instance of abstract class
+ */
+goog.fx.AbstractDragDrop.prototype.addItem = goog.abstractMethod;
+
+
+/**
+ * Associate drop target with drag element.
+ *
+ * @param {goog.fx.AbstractDragDrop} target Target to add.
+ */
+goog.fx.AbstractDragDrop.prototype.addTarget = function(target) {
+ this.targets_.push(target);
+ target.isTarget_ = true;
+ this.isSource_ = true;
+};
+
+
+/**
+ * Sets the SCROLL event target to make drag element follow scrolling.
+ *
+ * @param {EventTarget} scrollTarget The element that dispatches SCROLL events.
+ */
+goog.fx.AbstractDragDrop.prototype.setScrollTarget = function(scrollTarget) {
+ this.scrollTarget_ = scrollTarget;
+};
+
+
+/**
+ * Initialize drag and drop functionality for sources/targets already added.
+ * Sources/targets added after init has been called will initialize themselves
+ * one by one.
+ */
+goog.fx.AbstractDragDrop.prototype.init = function() {
+ if (this.initialized_) {
+ return;
+ }
+ for (var item, i = 0; item = this.items_[i]; i++) {
+ this.initItem(item);
+ }
+
+ this.initialized_ = true;
+};
+
+
+/**
+ * Initializes a single item.
+ *
+ * @param {goog.fx.DragDropItem} item Item to initialize.
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.initItem = function(item) {
+ if (this.isSource_) {
+ goog.events.listen(item.element, goog.events.EventType.MOUSEDOWN,
+ item.mouseDown_, false, item);
+ if (this.sourceClass_) {
+ goog.dom.classlist.add(
+ goog.asserts.assert(item.element), this.sourceClass_);
+ }
+ }
+
+ if (this.isTarget_ && this.targetClass_) {
+ goog.dom.classlist.add(
+ goog.asserts.assert(item.element), this.targetClass_);
+ }
+};
+
+
+/**
+ * Called when removing an item. Removes event listeners and classes.
+ *
+ * @param {goog.fx.DragDropItem} item Item to dispose.
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.disposeItem = function(item) {
+ if (this.isSource_) {
+ goog.events.unlisten(item.element, goog.events.EventType.MOUSEDOWN,
+ item.mouseDown_, false, item);
+ if (this.sourceClass_) {
+ goog.dom.classlist.remove(
+ goog.asserts.assert(item.element), this.sourceClass_);
+ }
+ }
+ if (this.isTarget_ && this.targetClass_) {
+ goog.dom.classlist.remove(
+ goog.asserts.assert(item.element), this.targetClass_);
+ }
+ item.dispose();
+};
+
+
+/**
+ * Removes all items.
+ */
+goog.fx.AbstractDragDrop.prototype.removeItems = function() {
+ for (var item, i = 0; item = this.items_[i]; i++) {
+ this.disposeItem(item);
+ }
+ this.items_.length = 0;
+};
+
+
+/**
+ * Starts a drag event for an item if the mouse button stays pressed and the
+ * cursor moves a few pixels. Allows dragging of items without first having to
+ * register them with addItem.
+ *
+ * @param {goog.events.BrowserEvent} event Mouse down event.
+ * @param {goog.fx.DragDropItem} item Item that's being dragged.
+ */
+goog.fx.AbstractDragDrop.prototype.maybeStartDrag = function(event, item) {
+ item.maybeStartDrag_(event, item.element);
+};
+
+
+/**
+ * Event handler that's used to start drag.
+ *
+ * @param {goog.events.BrowserEvent} event Mouse move event.
+ * @param {goog.fx.DragDropItem} item Item that's being dragged.
+ */
+goog.fx.AbstractDragDrop.prototype.startDrag = function(event, item) {
+
+ // Prevent a new drag operation from being started if another one is already
+ // in progress (could happen if the mouse was released outside of the
+ // document).
+ if (this.dragItem_) {
+ return;
+ }
+
+ this.dragItem_ = item;
+
+ // Dispatch DRAGSTART event
+ var dragStartEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DRAGSTART, this, this.dragItem_);
+ if (this.dispatchEvent(dragStartEvent) == false) {
+ this.dragItem_ = null;
+ return;
+ }
+
+ // Get the source element and create a drag element for it.
+ var el = item.getCurrentDragElement();
+ this.dragEl_ = this.createDragElement(el);
+ var doc = goog.dom.getOwnerDocument(el);
+ doc.body.appendChild(this.dragEl_);
+
+ this.dragger_ = this.createDraggerFor(el, this.dragEl_, event);
+ this.dragger_.setScrollTarget(this.scrollTarget_);
+
+ goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.DRAG,
+ this.moveDrag_, false, this);
+
+ goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.END,
+ this.endDrag, false, this);
+
+ // IE may issue a 'selectstart' event when dragging over an iframe even when
+ // default mousemove behavior is suppressed. If the default selectstart
+ // behavior is not suppressed, elements dragged over will show as selected.
+ goog.events.listen(doc.body, goog.events.EventType.SELECTSTART,
+ this.suppressSelect_);
+
+ this.recalculateDragTargets();
+ this.recalculateScrollableContainers();
+ this.activeTarget_ = null;
+ this.initScrollableContainerListeners_();
+ this.dragger_.startDrag(event);
+
+ event.preventDefault();
+};
+
+
+/**
+ * Recalculates the geometry of this source's drag targets. Call this
+ * if the position or visibility of a drag target has changed during
+ * a drag, or if targets are added or removed.
+ *
+ * TODO(user): this is an expensive operation; more efficient APIs
+ * may be necessary.
+ */
+goog.fx.AbstractDragDrop.prototype.recalculateDragTargets = function() {
+ this.targetList_ = [];
+ for (var target, i = 0; target = this.targets_[i]; i++) {
+ for (var itm, j = 0; itm = target.items_[j]; j++) {
+ this.addDragTarget_(target, itm);
+ }
+ }
+ if (!this.targetBox_) {
+ this.targetBox_ = new goog.math.Box(0, 0, 0, 0);
+ }
+};
+
+
+/**
+ * Recalculates the current scroll positions of scrollable containers and
+ * allocates targets. Call this if the position of a container changed or if
+ * targets are added or removed.
+ */
+goog.fx.AbstractDragDrop.prototype.recalculateScrollableContainers =
+ function() {
+ var container, i, j, target;
+ for (i = 0; container = this.scrollableContainers_[i]; i++) {
+ container.containedTargets_ = [];
+ container.savedScrollLeft_ = container.element_.scrollLeft;
+ container.savedScrollTop_ = container.element_.scrollTop;
+ var pos = goog.style.getPageOffset(container.element_);
+ var size = goog.style.getSize(container.element_);
+ container.box_ = new goog.math.Box(pos.y, pos.x + size.width,
+ pos.y + size.height, pos.x);
+ }
+
+ for (i = 0; target = this.targetList_[i]; i++) {
+ for (j = 0; container = this.scrollableContainers_[j]; j++) {
+ if (goog.dom.contains(container.element_, target.element_)) {
+ container.containedTargets_.push(target);
+ target.scrollableContainer_ = container;
+ }
+ }
+ }
+};
+
+
+/**
+ * Creates the Dragger for the drag element.
+ * @param {Element} sourceEl Drag source element.
+ * @param {Element} el the element created by createDragElement().
+ * @param {goog.events.BrowserEvent} event Mouse down event for start of drag.
+ * @return {!goog.fx.Dragger} The new Dragger.
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.createDraggerFor =
+ function(sourceEl, el, event) {
+ // Position the drag element.
+ var pos = this.getDragElementPosition(sourceEl, el, event);
+ el.style.position = 'absolute';
+ el.style.left = pos.x + 'px';
+ el.style.top = pos.y + 'px';
+ return new goog.fx.Dragger(el);
+};
+
+
+/**
+ * Event handler that's used to stop drag. Fires a drop event if over a valid
+ * target.
+ *
+ * @param {goog.fx.DragEvent} event Drag event.
+ */
+goog.fx.AbstractDragDrop.prototype.endDrag = function(event) {
+ var activeTarget = event.dragCanceled ? null : this.activeTarget_;
+ if (activeTarget && activeTarget.target_) {
+ var clientX = event.clientX;
+ var clientY = event.clientY;
+ var scroll = this.getScrollPos();
+ var x = clientX + scroll.x;
+ var y = clientY + scroll.y;
+
+ var subtarget;
+ // If a subtargeting function is enabled get the current subtarget
+ if (this.subtargetFunction_) {
+ subtarget = this.subtargetFunction_(activeTarget.item_,
+ activeTarget.box_, x, y);
+ }
+
+ var dragEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DRAG, this, this.dragItem_,
+ activeTarget.target_, activeTarget.item_, activeTarget.element_,
+ clientX, clientY, x, y);
+ this.dispatchEvent(dragEvent);
+
+ var dropEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DROP, this, this.dragItem_,
+ activeTarget.target_, activeTarget.item_, activeTarget.element_,
+ clientX, clientY, x, y, subtarget);
+ activeTarget.target_.dispatchEvent(dropEvent);
+ }
+
+ var dragEndEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DRAGEND, this, this.dragItem_);
+ this.dispatchEvent(dragEndEvent);
+
+ goog.events.unlisten(this.dragger_, goog.fx.Dragger.EventType.DRAG,
+ this.moveDrag_, false, this);
+ goog.events.unlisten(this.dragger_, goog.fx.Dragger.EventType.END,
+ this.endDrag, false, this);
+ var doc = goog.dom.getOwnerDocument(this.dragItem_.getCurrentDragElement());
+ goog.events.unlisten(doc.body, goog.events.EventType.SELECTSTART,
+ this.suppressSelect_);
+
+
+ this.afterEndDrag(this.activeTarget_ ? this.activeTarget_.item_ : null);
+};
+
+
+/**
+ * Called after a drag operation has finished.
+ *
+ * @param {goog.fx.DragDropItem=} opt_dropTarget Target for successful drop.
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.afterEndDrag = function(opt_dropTarget) {
+ this.disposeDrag();
+};
+
+
+/**
+ * Called once a drag operation has finished. Removes event listeners and
+ * elements.
+ *
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.disposeDrag = function() {
+ this.disposeScrollableContainerListeners_();
+ this.dragger_.dispose();
+
+ goog.dom.removeNode(this.dragEl_);
+ delete this.dragItem_;
+ delete this.dragEl_;
+ delete this.dragger_;
+ delete this.targetList_;
+ delete this.activeTarget_;
+};
+
+
+/**
+ * Event handler for drag events. Determines the active drop target, if any, and
+ * fires dragover and dragout events appropriately.
+ *
+ * @param {goog.fx.DragEvent} event Drag event.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.moveDrag_ = function(event) {
+ var position = this.getEventPosition(event);
+ var x = position.x;
+ var y = position.y;
+
+ // Check if we're still inside the bounds of the active target, if not fire
+ // a dragout event and proceed to find a new target.
+ var activeTarget = this.activeTarget_;
+
+ var subtarget;
+ if (activeTarget) {
+ // If a subtargeting function is enabled get the current subtarget
+ if (this.subtargetFunction_ && activeTarget.target_) {
+ subtarget = this.subtargetFunction_(activeTarget.item_,
+ activeTarget.box_, x, y);
+ }
+
+ if (activeTarget.box_.contains(position) &&
+ subtarget == this.activeSubtarget_) {
+ return;
+ }
+
+ if (activeTarget.target_) {
+ var sourceDragOutEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DRAGOUT, this, this.dragItem_,
+ activeTarget.target_, activeTarget.item_, activeTarget.element_);
+ this.dispatchEvent(sourceDragOutEvent);
+
+ // The event should be dispatched the by target DragDrop so that the
+ // target DragDrop can manage these events without having to know what
+ // sources this is a target for.
+ var targetDragOutEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DRAGOUT,
+ this,
+ this.dragItem_,
+ activeTarget.target_,
+ activeTarget.item_,
+ activeTarget.element_,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ this.activeSubtarget_);
+ activeTarget.target_.dispatchEvent(targetDragOutEvent);
+ }
+ this.activeSubtarget_ = subtarget;
+ this.activeTarget_ = null;
+ }
+
+ // Check if inside target box
+ if (this.targetBox_.contains(position)) {
+ // Search for target and fire a dragover event if found
+ activeTarget = this.activeTarget_ = this.getTargetFromPosition_(position);
+ if (activeTarget && activeTarget.target_) {
+ // If a subtargeting function is enabled get the current subtarget
+ if (this.subtargetFunction_) {
+ subtarget = this.subtargetFunction_(activeTarget.item_,
+ activeTarget.box_, x, y);
+ }
+ var sourceDragOverEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DRAGOVER, this, this.dragItem_,
+ activeTarget.target_, activeTarget.item_, activeTarget.element_);
+ sourceDragOverEvent.subtarget = subtarget;
+ this.dispatchEvent(sourceDragOverEvent);
+
+ // The event should be dispatched by the target DragDrop so that the
+ // target DragDrop can manage these events without having to know what
+ // sources this is a target for.
+ var targetDragOverEvent = new goog.fx.DragDropEvent(
+ goog.fx.AbstractDragDrop.EventType.DRAGOVER, this, this.dragItem_,
+ activeTarget.target_, activeTarget.item_, activeTarget.element_,
+ event.clientX, event.clientY, undefined, undefined, subtarget);
+ activeTarget.target_.dispatchEvent(targetDragOverEvent);
+
+ } else if (!activeTarget) {
+ // If no target was found create a dummy one so we won't have to iterate
+ // over all possible targets for every move event.
+ this.activeTarget_ = this.maybeCreateDummyTargetForPosition_(x, y);
+ }
+ }
+};
+
+
+/**
+ * Event handler for suppressing selectstart events. Selecting should be
+ * disabled while dragging.
+ *
+ * @param {goog.events.Event} event The selectstart event to suppress.
+ * @return {boolean} Whether to perform default behavior.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.suppressSelect_ = function(event) {
+ return false;
+};
+
+
+/**
+ * Sets up listeners for the scrollable containers that keep track of their
+ * scroll positions.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.initScrollableContainerListeners_ =
+ function() {
+ var container, i;
+ for (i = 0; container = this.scrollableContainers_[i]; i++) {
+ goog.events.listen(container.element_, goog.events.EventType.SCROLL,
+ this.containerScrollHandler_, false, this);
+ }
+};
+
+
+/**
+ * Cleans up the scrollable container listeners.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.disposeScrollableContainerListeners_ =
+ function() {
+ for (var i = 0, container; container = this.scrollableContainers_[i]; i++) {
+ goog.events.unlisten(container.element_, 'scroll',
+ this.containerScrollHandler_, false, this);
+ container.containedTargets_ = [];
+ }
+};
+
+
+/**
+ * Makes drag and drop aware of a target container that could scroll mid drag.
+ * @param {Element} element The scroll container.
+ */
+goog.fx.AbstractDragDrop.prototype.addScrollableContainer = function(element) {
+ this.scrollableContainers_.push(new goog.fx.ScrollableContainer_(element));
+};
+
+
+/**
+ * Removes all scrollable containers.
+ */
+goog.fx.AbstractDragDrop.prototype.removeAllScrollableContainers = function() {
+ this.disposeScrollableContainerListeners_();
+ this.scrollableContainers_ = [];
+};
+
+
+/**
+ * Event handler for containers scrolling.
+ * @param {goog.events.Event} e The event.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.containerScrollHandler_ = function(e) {
+ for (var i = 0, container; container = this.scrollableContainers_[i]; i++) {
+ if (e.target == container.element_) {
+ var deltaTop = container.savedScrollTop_ - container.element_.scrollTop;
+ var deltaLeft =
+ container.savedScrollLeft_ - container.element_.scrollLeft;
+ container.savedScrollTop_ = container.element_.scrollTop;
+ container.savedScrollLeft_ = container.element_.scrollLeft;
+
+ // When the container scrolls, it's possible that one of the targets will
+ // move to the region contained by the dummy target. Since we don't know
+ // which sides (if any) of the dummy target are defined by targets
+ // contained by this container, we are conservative and just shrink it.
+ if (this.dummyTarget_ && this.activeTarget_ == this.dummyTarget_) {
+ if (deltaTop > 0) {
+ this.dummyTarget_.box_.top += deltaTop;
+ } else {
+ this.dummyTarget_.box_.bottom += deltaTop;
+ }
+ if (deltaLeft > 0) {
+ this.dummyTarget_.box_.left += deltaLeft;
+ } else {
+ this.dummyTarget_.box_.right += deltaLeft;
+ }
+ }
+ for (var j = 0, target; target = container.containedTargets_[j]; j++) {
+ var box = target.box_;
+ box.top += deltaTop;
+ box.left += deltaLeft;
+ box.bottom += deltaTop;
+ box.right += deltaLeft;
+
+ this.calculateTargetBox_(box);
+ }
+ }
+ }
+ this.dragger_.onScroll_(e);
+};
+
+
+/**
+ * Set a function that provides subtargets. A subtargeting function
+ * returns an arbitrary identifier for each subtarget of an element.
+ * DnD code will generate additional drag over / out events when
+ * switching from subtarget to subtarget. This is useful for instance
+ * if you are interested if you are on the top half or the bottom half
+ * of the element.
+ * The provided function will be given the DragDropItem, box, x, y
+ * box is the current window coordinates occupied by element
+ * x, y is the mouse position in window coordinates
+ *
+ * @param {Function} f The new subtarget function.
+ */
+goog.fx.AbstractDragDrop.prototype.setSubtargetFunction = function(f) {
+ this.subtargetFunction_ = f;
+};
+
+
+/**
+ * Creates an element for the item being dragged.
+ *
+ * @param {Element} sourceEl Drag source element.
+ * @return {Element} The new drag element.
+ */
+goog.fx.AbstractDragDrop.prototype.createDragElement = function(sourceEl) {
+ var dragEl = this.createDragElementInternal(sourceEl);
+ goog.asserts.assert(dragEl);
+ if (this.dragClass_) {
+ goog.dom.classlist.add(dragEl, this.dragClass_);
+ }
+
+ return dragEl;
+};
+
+
+/**
+ * Returns the position for the drag element.
+ *
+ * @param {Element} el Drag source element.
+ * @param {Element} dragEl The dragged element created by createDragElement().
+ * @param {goog.events.BrowserEvent} event Mouse down event for start of drag.
+ * @return {!goog.math.Coordinate} The position for the drag element.
+ */
+goog.fx.AbstractDragDrop.prototype.getDragElementPosition =
+ function(el, dragEl, event) {
+ var pos = goog.style.getPageOffset(el);
+
+ // Subtract margin from drag element position twice, once to adjust the
+ // position given by the original node and once for the drag node.
+ var marginBox = goog.style.getMarginBox(el);
+ pos.x -= (marginBox.left || 0) * 2;
+ pos.y -= (marginBox.top || 0) * 2;
+
+ return pos;
+};
+
+
+/**
+ * Returns the dragger object.
+ *
+ * @return {goog.fx.Dragger} The dragger object used by this drag and drop
+ * instance.
+ */
+goog.fx.AbstractDragDrop.prototype.getDragger = function() {
+ return this.dragger_;
+};
+
+
+/**
+ * Creates copy of node being dragged.
+ *
+ * @param {Element} sourceEl Element to copy.
+ * @return {!Element} The clone of {@code sourceEl}.
+ * @deprecated Use goog.fx.Dragger.cloneNode().
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.cloneNode_ = function(sourceEl) {
+ return goog.fx.Dragger.cloneNode(sourceEl);
+};
+
+
+/**
+ * Generates an element to follow the cursor during dragging, given a drag
+ * source element. The default behavior is simply to clone the source element,
+ * but this may be overridden in subclasses. This method is called by
+ * {@code createDragElement()} before the drag class is added.
+ *
+ * @param {Element} sourceEl Drag source element.
+ * @return {!Element} The new drag element.
+ * @protected
+ * @suppress {deprecated}
+ */
+goog.fx.AbstractDragDrop.prototype.createDragElementInternal =
+ function(sourceEl) {
+ return this.cloneNode_(sourceEl);
+};
+
+
+/**
+ * Add possible drop target for current drag operation.
+ *
+ * @param {goog.fx.AbstractDragDrop} target Drag handler.
+ * @param {goog.fx.DragDropItem} item Item that's being dragged.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.addDragTarget_ = function(target, item) {
+
+ // Get all the draggable elements and add each one.
+ var draggableElements = item.getDraggableElements();
+ var targetList = this.targetList_;
+ for (var i = 0; i < draggableElements.length; i++) {
+ var draggableElement = draggableElements[i];
+
+ // Determine target position and dimension
+ var box = this.getElementBox(item, draggableElement);
+
+ targetList.push(
+ new goog.fx.ActiveDropTarget_(box, target, item, draggableElement));
+
+ this.calculateTargetBox_(box);
+ }
+};
+
+
+/**
+ * Calculates the position and dimension of a draggable element.
+ *
+ * @param {goog.fx.DragDropItem} item Item that's being dragged.
+ * @param {Element} element The element to calculate the box.
+ *
+ * @return {!goog.math.Box} Box describing the position and dimension
+ * of element.
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.getElementBox = function(item, element) {
+ var pos = goog.style.getPageOffset(element);
+ var size = goog.style.getSize(element);
+ return new goog.math.Box(pos.y, pos.x + size.width, pos.y + size.height,
+ pos.x);
+};
+
+
+/**
+ * Calculate the outer bounds (the region all targets are inside).
+ *
+ * @param {goog.math.Box} box Box describing the position and dimension
+ * of a drag target.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.calculateTargetBox_ = function(box) {
+ if (this.targetList_.length == 1) {
+ this.targetBox_ = new goog.math.Box(box.top, box.right,
+ box.bottom, box.left);
+ } else {
+ var tb = this.targetBox_;
+ tb.left = Math.min(box.left, tb.left);
+ tb.right = Math.max(box.right, tb.right);
+ tb.top = Math.min(box.top, tb.top);
+ tb.bottom = Math.max(box.bottom, tb.bottom);
+ }
+};
+
+
+/**
+ * Creates a dummy target for the given cursor position. The assumption is to
+ * create as big dummy target box as possible, the only constraints are:
+ * - The dummy target box cannot overlap any of real target boxes.
+ * - The dummy target has to contain a point with current mouse coordinates.
+ *
+ * NOTE: For performance reasons the box construction algorithm is kept simple
+ * and it is not optimal (see example below). Currently it is O(n) in regard to
+ * the number of real drop target boxes, but its result depends on the order
+ * of those boxes being processed (the order in which they're added to the
+ * targetList_ collection).
+ *
+ * The algorithm.
+ * a) Assumptions
+ * - Mouse pointer is in the bounding box of real target boxes.
+ * - None of the boxes have negative coordinate values.
+ * - Mouse pointer is not contained by any of "real target" boxes.
+ * - For targets inside a scrollable container, the box used is the
+ * intersection of the scrollable container's box and the target's box.
+ * This is because the part of the target that extends outside the scrollable
+ * container should not be used in the clipping calculations.
+ *
+ * b) Outline
+ * - Initialize the fake target to the bounding box of real targets.
+ * - For each real target box - clip the fake target box so it does not contain
+ * that target box, but does contain the mouse pointer.
+ * -- Project the real target box, mouse pointer and fake target box onto
+ * both axes and calculate the clipping coordinates.
+ * -- Only one coordinate is used to clip the fake target box to keep the
+ * fake target as big as possible.
+ * -- If the projection of the real target box contains the mouse pointer,
+ * clipping for a given axis is not possible.
+ * -- If both clippings are possible, the clipping more distant from the
+ * mouse pointer is selected to keep bigger fake target area.
+ * - Save the created fake target only if it has a big enough area.
+ *
+ *
+ * c) Example
+ * <pre>
+ * Input: Algorithm created box: Maximum box:
+ * +---------------------+ +---------------------+ +---------------------+
+ * | B1 | B2 | | B1 B2 | | B1 B2 |
+ * | | | | +-------------+ | |+-------------------+|
+ * |---------x-----------| | | | | || ||
+ * | | | | | | | || ||
+ * | | | | | | | || ||
+ * | | | | | | | || ||
+ * | | | | | | | || ||
+ * | | | | +-------------+ | |+-------------------+|
+ * | B4 | B3 | | B4 B3 | | B4 B3 |
+ * +---------------------+ +---------------------+ +---------------------+
+ * </pre>
+ *
+ * @param {number} x Cursor position on the x-axis.
+ * @param {number} y Cursor position on the y-axis.
+ * @return {goog.fx.ActiveDropTarget_} Dummy drop target.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.maybeCreateDummyTargetForPosition_ =
+ function(x, y) {
+ if (!this.dummyTarget_) {
+ this.dummyTarget_ = new goog.fx.ActiveDropTarget_(this.targetBox_.clone());
+ }
+ var fakeTargetBox = this.dummyTarget_.box_;
+
+ // Initialize the fake target box to the bounding box of DnD targets.
+ fakeTargetBox.top = this.targetBox_.top;
+ fakeTargetBox.right = this.targetBox_.right;
+ fakeTargetBox.bottom = this.targetBox_.bottom;
+ fakeTargetBox.left = this.targetBox_.left;
+
+ // Clip the fake target based on mouse position and DnD target boxes.
+ for (var i = 0, target; target = this.targetList_[i]; i++) {
+ var box = target.box_;
+
+ if (target.scrollableContainer_) {
+ // If the target has a scrollable container, use the intersection of that
+ // container's box and the target's box.
+ var scrollBox = target.scrollableContainer_.box_;
+
+ box = new goog.math.Box(
+ Math.max(box.top, scrollBox.top),
+ Math.min(box.right, scrollBox.right),
+ Math.min(box.bottom, scrollBox.bottom),
+ Math.max(box.left, scrollBox.left));
+ }
+
+ // Calculate clipping coordinates for horizontal and vertical axis.
+ // The clipping coordinate is calculated by projecting fake target box,
+ // the mouse pointer and DnD target box onto an axis and checking how
+ // box projections overlap and if the projected DnD target box contains
+ // mouse pointer. The clipping coordinate cannot be computed and is set to
+ // a negative value if the projected DnD target contains the mouse pointer.
+
+ var horizontalClip = null; // Assume mouse is above or below the DnD box.
+ if (x >= box.right) { // Mouse is to the right of the DnD box.
+ // Clip the fake box only if the DnD box overlaps it.
+ horizontalClip = box.right > fakeTargetBox.left ?
+ box.right : fakeTargetBox.left;
+ } else if (x < box.left) { // Mouse is to the left of the DnD box.
+ // Clip the fake box only if the DnD box overlaps it.
+ horizontalClip = box.left < fakeTargetBox.right ?
+ box.left : fakeTargetBox.right;
+ }
+ var verticalClip = null;
+ if (y >= box.bottom) {
+ verticalClip = box.bottom > fakeTargetBox.top ?
+ box.bottom : fakeTargetBox.top;
+ } else if (y < box.top) {
+ verticalClip = box.top < fakeTargetBox.bottom ?
+ box.top : fakeTargetBox.bottom;
+ }
+
+ // If both clippings are possible, choose one that gives us larger distance
+ // to mouse pointer (mark the shorter clipping as impossible, by setting it
+ // to null).
+ if (!goog.isNull(horizontalClip) && !goog.isNull(verticalClip)) {
+ if (Math.abs(horizontalClip - x) > Math.abs(verticalClip - y)) {
+ verticalClip = null;
+ } else {
+ horizontalClip = null;
+ }
+ }
+
+ // Clip none or one of fake target box sides (at most one clipping
+ // coordinate can be active).
+ if (!goog.isNull(horizontalClip)) {
+ if (horizontalClip <= x) {
+ fakeTargetBox.left = horizontalClip;
+ } else {
+ fakeTargetBox.right = horizontalClip;
+ }
+ } else if (!goog.isNull(verticalClip)) {
+ if (verticalClip <= y) {
+ fakeTargetBox.top = verticalClip;
+ } else {
+ fakeTargetBox.bottom = verticalClip;
+ }
+ }
+ }
+
+ // Only return the new fake target if it is big enough.
+ return (fakeTargetBox.right - fakeTargetBox.left) *
+ (fakeTargetBox.bottom - fakeTargetBox.top) >=
+ goog.fx.AbstractDragDrop.DUMMY_TARGET_MIN_SIZE_ ?
+ this.dummyTarget_ : null;
+};
+
+
+/**
+ * Returns the target for a given cursor position.
+ *
+ * @param {goog.math.Coordinate} position Cursor position.
+ * @return {Object} Target for position or null if no target was defined
+ * for the given position.
+ * @private
+ */
+goog.fx.AbstractDragDrop.prototype.getTargetFromPosition_ = function(position) {
+ for (var target, i = 0; target = this.targetList_[i]; i++) {
+ if (target.box_.contains(position)) {
+ if (target.scrollableContainer_) {
+ // If we have a scrollable container we will need to make sure
+ // we account for clipping of the scroll area
+ var box = target.scrollableContainer_.box_;
+ if (box.contains(position)) {
+ return target;
+ }
+ } else {
+ return target;
+ }
+ }
+ }
+
+ return null;
+};
+
+
+/**
+ * Checks whatever a given point is inside a given box.
+ *
+ * @param {number} x Cursor position on the x-axis.
+ * @param {number} y Cursor position on the y-axis.
+ * @param {goog.math.Box} box Box to check position against.
+ * @return {boolean} Whether the given point is inside {@code box}.
+ * @protected
+ * @deprecated Use goog.math.Box.contains.
+ */
+goog.fx.AbstractDragDrop.prototype.isInside = function(x, y, box) {
+ return x >= box.left &&
+ x < box.right &&
+ y >= box.top &&
+ y < box.bottom;
+};
+
+
+/**
+ * Gets the scroll distance as a coordinate object, using
+ * the window of the current drag element's dom.
+ * @return {!goog.math.Coordinate} Object with scroll offsets 'x' and 'y'.
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.getScrollPos = function() {
+ return goog.dom.getDomHelper(this.dragEl_).getDocumentScroll();
+};
+
+
+/**
+ * Get the position of a drag event.
+ * @param {goog.fx.DragEvent} event Drag event.
+ * @return {!goog.math.Coordinate} Position of the event.
+ * @protected
+ */
+goog.fx.AbstractDragDrop.prototype.getEventPosition = function(event) {
+ var scroll = this.getScrollPos();
+ return new goog.math.Coordinate(event.clientX + scroll.x,
+ event.clientY + scroll.y);
+};
+
+
+/** @override */
+goog.fx.AbstractDragDrop.prototype.disposeInternal = function() {
+ goog.fx.AbstractDragDrop.base(this, 'disposeInternal');
+ this.removeItems();
+};
+
+
+
+/**
+ * Object representing a drag and drop event.
+ *
+ * @param {string} type Event type.
+ * @param {goog.fx.AbstractDragDrop} source Source drag drop object.
+ * @param {goog.fx.DragDropItem} sourceItem Source item.
+ * @param {goog.fx.AbstractDragDrop=} opt_target Target drag drop object.
+ * @param {goog.fx.DragDropItem=} opt_targetItem Target item.
+ * @param {Element=} opt_targetElement Target element.
+ * @param {number=} opt_clientX X-Position relative to the screen.
+ * @param {number=} opt_clientY Y-Position relative to the screen.
+ * @param {number=} opt_x X-Position relative to the viewport.
+ * @param {number=} opt_y Y-Position relative to the viewport.
+ * @param {Object=} opt_subtarget The currently active subtarget.
+ * @extends {goog.events.Event}
+ * @constructor
+ */
+goog.fx.DragDropEvent = function(type, source, sourceItem,
+ opt_target, opt_targetItem, opt_targetElement,
+ opt_clientX, opt_clientY, opt_x, opt_y,
+ opt_subtarget) {
+ // TODO(eae): Get rid of all the optional parameters and have the caller set
+ // the fields directly instead.
+ goog.fx.DragDropEvent.base(this, 'constructor', type);
+
+ /**
+ * Reference to the source goog.fx.AbstractDragDrop object.
+ * @type {goog.fx.AbstractDragDrop}
+ */
+ this.dragSource = source;
+
+ /**
+ * Reference to the source goog.fx.DragDropItem object.
+ * @type {goog.fx.DragDropItem}
+ */
+ this.dragSourceItem = sourceItem;
+
+ /**
+ * Reference to the target goog.fx.AbstractDragDrop object.
+ * @type {goog.fx.AbstractDragDrop|undefined}
+ */
+ this.dropTarget = opt_target;
+
+ /**
+ * Reference to the target goog.fx.DragDropItem object.
+ * @type {goog.fx.DragDropItem|undefined}
+ */
+ this.dropTargetItem = opt_targetItem;
+
+ /**
+ * The actual element of the drop target that is the target for this event.
+ * @type {Element|undefined}
+ */
+ this.dropTargetElement = opt_targetElement;
+
+ /**
+ * X-Position relative to the screen.
+ * @type {number|undefined}
+ */
+ this.clientX = opt_clientX;
+
+ /**
+ * Y-Position relative to the screen.
+ * @type {number|undefined}
+ */
+ this.clientY = opt_clientY;
+
+ /**
+ * X-Position relative to the viewport.
+ * @type {number|undefined}
+ */
+ this.viewportX = opt_x;
+
+ /**
+ * Y-Position relative to the viewport.
+ * @type {number|undefined}
+ */
+ this.viewportY = opt_y;
+
+ /**
+ * The subtarget that is currently active if a subtargeting function
+ * is supplied.
+ * @type {Object|undefined}
+ */
+ this.subtarget = opt_subtarget;
+};
+goog.inherits(goog.fx.DragDropEvent, goog.events.Event);
+
+
+
+/**
+ * Class representing a source or target element for drag and drop operations.
+ *
+ * @param {Element|string} element Dom Node, or string representation of node
+ * id, to be used as drag source/drop target.
+ * @param {Object=} opt_data Data associated with the source/target.
+ * @throws Error If no element argument is provided or if the type is invalid
+ * @extends {goog.events.EventTarget}
+ * @constructor
+ */
+goog.fx.DragDropItem = function(element, opt_data) {
+ goog.fx.DragDropItem.base(this, 'constructor');
+
+ /**
+ * Reference to drag source/target element
+ * @type {Element}
+ */
+ this.element = goog.dom.getElement(element);
+
+ /**
+ * Data associated with element.
+ * @type {Object|undefined}
+ */
+ this.data = opt_data;
+
+ /**
+ * Drag object the item belongs to.
+ * @type {goog.fx.AbstractDragDrop?}
+ * @private
+ */
+ this.parent_ = null;
+
+ /**
+ * Event handler for listeners on events that can initiate a drag.
+ * @type {!goog.events.EventHandler<!goog.fx.DragDropItem>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+ this.registerDisposable(this.eventHandler_);
+
+ if (!this.element) {
+ throw Error('Invalid argument');
+ }
+};
+goog.inherits(goog.fx.DragDropItem, goog.events.EventTarget);
+
+
+/**
+ * The current element being dragged. This is needed because a DragDropItem can
+ * have multiple elements that can be dragged.
+ * @type {Element}
+ * @private
+ */
+goog.fx.DragDropItem.prototype.currentDragElement_ = null;
+
+
+/**
+ * Get the data associated with the source/target.
+ * @return {Object|null|undefined} Data associated with the source/target.
+ */
+goog.fx.DragDropItem.prototype.getData = function() {
+ return this.data;
+};
+
+
+/**
+ * Gets the element that is actually draggable given that the given target was
+ * attempted to be dragged. This should be overriden when the element that was
+ * given actually contains many items that can be dragged. From the target, you
+ * can determine what element should actually be dragged.
+ *
+ * @param {Element} target The target that was attempted to be dragged.
+ * @return {Element} The element that is draggable given the target. If
+ * none are draggable, this will return null.
+ */
+goog.fx.DragDropItem.prototype.getDraggableElement = function(target) {
+ return target;
+};
+
+
+/**
+ * Gets the element that is currently being dragged.
+ *
+ * @return {Element} The element that is currently being dragged.
+ */
+goog.fx.DragDropItem.prototype.getCurrentDragElement = function() {
+ return this.currentDragElement_;
+};
+
+
+/**
+ * Gets all the elements of this item that are potentially draggable/
+ *
+ * @return {!Array<Element>} The draggable elements.
+ */
+goog.fx.DragDropItem.prototype.getDraggableElements = function() {
+ return [this.element];
+};
+
+
+/**
+ * Event handler for mouse down.
+ *
+ * @param {goog.events.BrowserEvent} event Mouse down event.
+ * @private
+ */
+goog.fx.DragDropItem.prototype.mouseDown_ = function(event) {
+ if (!event.isMouseActionButton()) {
+ return;
+ }
+
+ // Get the draggable element for the target.
+ var element = this.getDraggableElement(/** @type {Element} */ (event.target));
+ if (element) {
+ this.maybeStartDrag_(event, element);
+ }
+};
+
+
+/**
+ * Sets the dragdrop to which this item belongs.
+ * @param {goog.fx.AbstractDragDrop} parent The parent dragdrop.
+ */
+goog.fx.DragDropItem.prototype.setParent = function(parent) {
+ this.parent_ = parent;
+};
+
+
+/**
+ * Adds mouse move, mouse out and mouse up handlers.
+ *
+ * @param {goog.events.BrowserEvent} event Mouse down event.
+ * @param {Element} element Element.
+ * @private
+ */
+goog.fx.DragDropItem.prototype.maybeStartDrag_ = function(event, element) {
+ var eventType = goog.events.EventType;
+ this.eventHandler_.
+ listen(element, eventType.MOUSEMOVE, this.mouseMove_, false).
+ listen(element, eventType.MOUSEOUT, this.mouseMove_, false);
+
+ // Capture the MOUSEUP on the document to ensure that we cancel the start
+ // drag handlers even if the mouse up occurs on some other element. This can
+ // happen for instance when the mouse down changes the geometry of the element
+ // clicked on (e.g. through changes in activation styling) such that the mouse
+ // up occurs outside the original element.
+ var doc = goog.dom.getOwnerDocument(element);
+ this.eventHandler_.listen(doc, eventType.MOUSEUP, this.mouseUp_, true);
+
+ this.currentDragElement_ = element;
+
+ this.startPosition_ = new goog.math.Coordinate(
+ event.clientX, event.clientY);
+
+ event.preventDefault();
+};
+
+
+/**
+ * Event handler for mouse move. Starts drag operation if moved more than the
+ * threshold value.
+ *
+ * @param {goog.events.BrowserEvent} event Mouse move or mouse out event.
+ * @private
+ */
+goog.fx.DragDropItem.prototype.mouseMove_ = function(event) {
+ var distance = Math.abs(event.clientX - this.startPosition_.x) +
+ Math.abs(event.clientY - this.startPosition_.y);
+ // Fire dragStart event if the drag distance exceeds the threshold or if the
+ // mouse leave the dragged element.
+ // TODO(user): Consider using the goog.fx.Dragger to track the distance
+ // even after the mouse leaves the dragged element.
+ var currentDragElement = this.currentDragElement_;
+ var distanceAboveThreshold =
+ distance > goog.fx.AbstractDragDrop.initDragDistanceThreshold;
+ var mouseOutOnDragElement = event.type == goog.events.EventType.MOUSEOUT &&
+ event.target == currentDragElement;
+ if (distanceAboveThreshold || mouseOutOnDragElement) {
+ this.eventHandler_.removeAll();
+ this.parent_.startDrag(event, this);
+ }
+};
+
+
+/**
+ * Event handler for mouse up. Removes mouse move, mouse out and mouse up event
+ * handlers.
+ *
+ * @param {goog.events.BrowserEvent} event Mouse up event.
+ * @private
+ */
+goog.fx.DragDropItem.prototype.mouseUp_ = function(event) {
+ this.eventHandler_.removeAll();
+ delete this.startPosition_;
+ this.currentDragElement_ = null;
+};
+
+
+
+/**
+ * Class representing an active drop target
+ *
+ * @param {goog.math.Box} box Box describing the position and dimension of the
+ * target item.
+ * @param {goog.fx.AbstractDragDrop=} opt_target Target that contains the item
+ associated with position.
+ * @param {goog.fx.DragDropItem=} opt_item Item associated with position.
+ * @param {Element=} opt_element Element of item associated with position.
+ * @constructor
+ * @private
+ */
+goog.fx.ActiveDropTarget_ = function(box, opt_target, opt_item, opt_element) {
+
+ /**
+ * Box describing the position and dimension of the target item
+ * @type {goog.math.Box}
+ * @private
+ */
+ this.box_ = box;
+
+ /**
+ * Target that contains the item associated with position
+ * @type {goog.fx.AbstractDragDrop|undefined}
+ * @private
+ */
+ this.target_ = opt_target;
+
+ /**
+ * Item associated with position
+ * @type {goog.fx.DragDropItem|undefined}
+ * @private
+ */
+ this.item_ = opt_item;
+
+ /**
+ * The draggable element of the item associated with position.
+ * @type {Element|undefined}
+ * @private
+ */
+ this.element_ = opt_element;
+};
+
+
+/**
+ * If this target is in a scrollable container this is it.
+ * @type {goog.fx.ScrollableContainer_}
+ * @private
+ */
+goog.fx.ActiveDropTarget_.prototype.scrollableContainer_ = null;
+
+
+
+/**
+ * Class for representing a scrollable container
+ * @param {Element} element the scrollable element.
+ * @constructor
+ * @private
+ */
+goog.fx.ScrollableContainer_ = function(element) {
+
+ /**
+ * The targets that lie within this container.
+ * @type {Array<goog.fx.ActiveDropTarget_>}
+ * @private
+ */
+ this.containedTargets_ = [];
+
+ /**
+ * The element that is this container
+ * @type {Element}
+ * @private
+ */
+ this.element_ = element;
+
+ /**
+ * The saved scroll left location for calculating deltas.
+ * @type {number}
+ * @private
+ */
+ this.savedScrollLeft_ = 0;
+
+ /**
+ * The saved scroll top location for calculating deltas.
+ * @type {number}
+ * @private
+ */
+ this.savedScrollTop_ = 0;
+
+ /**
+ * The space occupied by the container.
+ * @type {goog.math.Box}
+ * @private
+ */
+ this.box_ = null;
+};
[37/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/errorreporter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/errorreporter.js b/externs/GCL/externs/goog/debug/errorreporter.js
new file mode 100644
index 0000000..e869792
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/errorreporter.js
@@ -0,0 +1,434 @@
+// Copyright 2009 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 ErrorReporter class, which creates an error
+ * handler that reports any errors raised to a URL.
+ *
+ */
+
+goog.provide('goog.debug.ErrorReporter');
+goog.provide('goog.debug.ErrorReporter.ExceptionEvent');
+
+goog.require('goog.asserts');
+goog.require('goog.debug');
+goog.require('goog.debug.Error');
+goog.require('goog.debug.ErrorHandler');
+goog.require('goog.debug.entryPointRegistry');
+goog.require('goog.events');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventTarget');
+goog.require('goog.log');
+goog.require('goog.net.XhrIo');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.uri.utils');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Constructs an error reporter. Internal Use Only. To install an error
+ * reporter see the {@see #install} method below.
+ *
+ * @param {string} handlerUrl The URL to which all errors will be reported.
+ * @param {function(!Error, !Object<string, string>)=}
+ * opt_contextProvider When a report is to be sent to the server,
+ * this method will be called, and given an opportunity to modify the
+ * context object before submission to the server.
+ * @param {boolean=} opt_noAutoProtect Whether to automatically add handlers for
+ * onerror and to protect entry points. If apps have other error reporting
+ * facilities, it may make sense for them to set these up themselves and use
+ * the ErrorReporter just for transmission of reports.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.debug.ErrorReporter = function(
+ handlerUrl, opt_contextProvider, opt_noAutoProtect) {
+ goog.debug.ErrorReporter.base(this, 'constructor');
+
+ /**
+ * Context provider, if one was provided.
+ * @type {?function(!Error, !Object<string, string>)}
+ * @private
+ */
+ this.contextProvider_ = opt_contextProvider || null;
+
+ /**
+ * The string prefix of any optional context parameters logged with the error.
+ * @private {string}
+ */
+ this.contextPrefix_ = 'context.';
+
+ /**
+ * The number of bytes after which the ErrorReporter truncates the POST body.
+ * If null, the ErrorReporter won't truncate the body.
+ * @private {?number}
+ */
+ this.truncationLimit_ = null;
+
+ /**
+ * Additional arguments to append to URL before sending XHR.
+ * @private {!Object<string,string>}
+ */
+ this.additionalArguments_ = {};
+
+ /**
+ * XHR sender.
+ * @type {function(string, string, string, (Object|goog.structs.Map)=)}
+ * @private
+ */
+ this.xhrSender_ = goog.debug.ErrorReporter.defaultXhrSender;
+
+ /**
+ * The URL at which all errors caught by this handler will be logged.
+ *
+ * @type {string}
+ * @private
+ */
+ this.handlerUrl_ = handlerUrl;
+
+ if (goog.debug.ErrorReporter.ALLOW_AUTO_PROTECT) {
+ if (!opt_noAutoProtect) {
+ /**
+ * The internal error handler used to catch all errors.
+ *
+ * @private {goog.debug.ErrorHandler}
+ */
+ this.errorHandler_ = null;
+
+ this.setup_();
+ }
+ } else if (!opt_noAutoProtect) {
+ goog.asserts.fail(
+ 'opt_noAutoProtect cannot be false while ' +
+ 'goog.debug.ErrorReporter.ALLOW_AUTO_PROTECT is false. Setting ' +
+ 'ALLOW_AUTO_PROTECT to false removes the necessary auto-protect code ' +
+ 'in compiled/optimized mode.');
+ }
+};
+goog.inherits(goog.debug.ErrorReporter, goog.events.EventTarget);
+
+
+/**
+ * @define {boolean} If true, the code that provides additional entry point
+ * protection and setup is exposed in this file. Set to false to avoid
+ * bringing in a lot of code from ErrorHandler and entryPointRegistry in
+ * compiled mode.
+ */
+goog.define('goog.debug.ErrorReporter.ALLOW_AUTO_PROTECT', true);
+
+
+
+/**
+ * Event broadcast when an exception is logged.
+ * @param {Error} error The exception that was was reported.
+ * @param {!Object<string, string>} context The context values sent to the
+ * server alongside this error.
+ * @constructor
+ * @extends {goog.events.Event}
+ * @final
+ */
+goog.debug.ErrorReporter.ExceptionEvent = function(error, context) {
+ goog.events.Event.call(this, goog.debug.ErrorReporter.ExceptionEvent.TYPE);
+
+ /**
+ * The error that was reported.
+ * @type {Error}
+ */
+ this.error = error;
+
+ /**
+ * Context values sent to the server alongside this report.
+ * @type {!Object<string, string>}
+ */
+ this.context = context;
+};
+goog.inherits(goog.debug.ErrorReporter.ExceptionEvent, goog.events.Event);
+
+
+/**
+ * Event type for notifying of a logged exception.
+ * @type {string}
+ */
+goog.debug.ErrorReporter.ExceptionEvent.TYPE =
+ goog.events.getUniqueId('exception');
+
+
+/**
+ * Extra headers for the error-reporting XHR.
+ * @type {Object|goog.structs.Map|undefined}
+ * @private
+ */
+goog.debug.ErrorReporter.prototype.extraHeaders_;
+
+
+/**
+ * Logging object.
+ *
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.debug.ErrorReporter.logger_ =
+ goog.log.getLogger('goog.debug.ErrorReporter');
+
+
+/**
+ * Installs an error reporter to catch all JavaScript errors raised.
+ *
+ * @param {string} loggingUrl The URL to which the errors caught will be
+ * reported.
+ * @param {function(!Error, !Object<string, string>)=}
+ * opt_contextProvider When a report is to be sent to the server,
+ * this method will be called, and given an opportunity to modify the
+ * context object before submission to the server.
+ * @param {boolean=} opt_noAutoProtect Whether to automatically add handlers for
+ * onerror and to protect entry points. If apps have other error reporting
+ * facilities, it may make sense for them to set these up themselves and use
+ * the ErrorReporter just for transmission of reports.
+ * @return {!goog.debug.ErrorReporter} The error reporter.
+ */
+goog.debug.ErrorReporter.install = function(
+ loggingUrl, opt_contextProvider, opt_noAutoProtect) {
+ var instance = new goog.debug.ErrorReporter(
+ loggingUrl, opt_contextProvider, opt_noAutoProtect);
+ return instance;
+};
+
+
+/**
+ * Default implementation of XHR sender interface.
+ *
+ * @param {string} uri URI to make request to.
+ * @param {string} method Send method.
+ * @param {string} content Post data.
+ * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
+ * request.
+ */
+goog.debug.ErrorReporter.defaultXhrSender = function(uri, method, content,
+ opt_headers) {
+ goog.net.XhrIo.send(uri, null, method, content, opt_headers);
+};
+
+
+/**
+ * Installs exception protection for an entry point function in addition
+ * to those that are protected by default.
+ * Has no effect in IE because window.onerror is used for reporting
+ * exceptions in that case.
+ *
+ * @this {goog.debug.ErrorReporter}
+ * @param {Function} fn An entry point function to be protected.
+ * @return {Function} A protected wrapper function that calls the entry point
+ * function or null if the entry point could not be protected.
+ */
+goog.debug.ErrorReporter.prototype.protectAdditionalEntryPoint =
+ goog.debug.ErrorReporter.ALLOW_AUTO_PROTECT ?
+ function(fn) {
+ if (this.errorHandler_) {
+ return this.errorHandler_.protectEntryPoint(fn);
+ }
+ return null;
+ } :
+ function(fn) {
+ goog.asserts.fail(
+ 'Cannot call protectAdditionalEntryPoint while ALLOW_AUTO_PROTECT ' +
+ 'is false. If ALLOW_AUTO_PROTECT is false, the necessary ' +
+ 'auto-protect code in compiled/optimized mode is removed.');
+ return null;
+ };
+
+
+if (goog.debug.ErrorReporter.ALLOW_AUTO_PROTECT) {
+ /**
+ * Sets up the error reporter.
+ *
+ * @private
+ */
+ goog.debug.ErrorReporter.prototype.setup_ = function() {
+ if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10')) {
+ // Use "onerror" because caught exceptions in IE don't provide line
+ // number.
+ goog.debug.catchErrors(
+ goog.bind(this.handleException, this), false, null);
+ } else {
+ // "onerror" doesn't work with FF2 or Chrome
+ this.errorHandler_ = new goog.debug.ErrorHandler(
+ goog.bind(this.handleException, this));
+
+ this.errorHandler_.protectWindowSetTimeout();
+ this.errorHandler_.protectWindowSetInterval();
+ this.errorHandler_.protectWindowRequestAnimationFrame();
+ goog.debug.entryPointRegistry.monitorAll(this.errorHandler_);
+ }
+ };
+}
+
+
+/**
+ * Add headers to the logging url.
+ * @param {Object|goog.structs.Map} loggingHeaders Extra headers to send
+ * to the logging URL.
+ */
+goog.debug.ErrorReporter.prototype.setLoggingHeaders =
+ function(loggingHeaders) {
+ this.extraHeaders_ = loggingHeaders;
+};
+
+
+/**
+ * Set the function used to send error reports to the server.
+ * @param {function(string, string, string, (Object|goog.structs.Map)=)}
+ * xhrSender If provided, this will be used to send a report to the
+ * server instead of the default method. The function will be given the URI,
+ * HTTP method request content, and (optionally) request headers to be
+ * added.
+ */
+goog.debug.ErrorReporter.prototype.setXhrSender = function(xhrSender) {
+ this.xhrSender_ = xhrSender;
+};
+
+
+/**
+ * Handler for caught exceptions. Sends report to the LoggingServlet and
+ * notifies any listeners.
+ *
+ * @param {Object} e The exception.
+ * @param {!Object<string, string>=} opt_context Context values to optionally
+ * include in the error report.
+ */
+goog.debug.ErrorReporter.prototype.handleException = function(e,
+ opt_context) {
+ var error = /** @type {!Error} */ (goog.debug.normalizeErrorObject(e));
+
+ // Construct the context, possibly from the one provided in the argument, and
+ // pass it to the context provider if there is one.
+ var context = opt_context ? goog.object.clone(opt_context) : {};
+ if (this.contextProvider_) {
+ try {
+ this.contextProvider_(error, context);
+ } catch (err) {
+ goog.log.error(goog.debug.ErrorReporter.logger_,
+ 'Context provider threw an exception: ' + err.message);
+ }
+ }
+ // Truncate message to a reasonable length, since it will be sent in the URL.
+ // The entire URL length historically needed to be 2,083 or less, so leave
+ // some room for the rest of the URL.
+ var message = error.message.substring(0, 1900);
+ if (!(e instanceof goog.debug.Error) || e.reportErrorToServer) {
+ this.sendErrorReport(message, error.fileName, error.lineNumber, error.stack,
+ context);
+ }
+
+ try {
+ this.dispatchEvent(
+ new goog.debug.ErrorReporter.ExceptionEvent(error, context));
+ } catch (ex) {
+ // Swallow exception to avoid infinite recursion.
+ }
+};
+
+
+/**
+ * Sends an error report to the logging URL. This will not consult the context
+ * provider, the report will be sent exactly as specified.
+ *
+ * @param {string} message Error description.
+ * @param {string} fileName URL of the JavaScript file with the error.
+ * @param {number} line Line number of the error.
+ * @param {string=} opt_trace Call stack trace of the error.
+ * @param {!Object<string, string>=} opt_context Context information to include
+ * in the request.
+ */
+goog.debug.ErrorReporter.prototype.sendErrorReport =
+ function(message, fileName, line, opt_trace, opt_context) {
+ try {
+ // Create the logging URL.
+ var requestUrl = goog.uri.utils.appendParams(this.handlerUrl_,
+ 'script', fileName, 'error', message, 'line', line);
+
+ if (!goog.object.isEmpty(this.additionalArguments_)) {
+ requestUrl = goog.uri.utils.appendParamsFromMap(requestUrl,
+ this.additionalArguments_);
+ }
+
+ var queryMap = {};
+ queryMap['trace'] = opt_trace;
+
+ // Copy context into query data map
+ if (opt_context) {
+ for (var entry in opt_context) {
+ queryMap[this.contextPrefix_ + entry] = opt_context[entry];
+ }
+ }
+
+ // Copy query data map into request.
+ var queryData = goog.uri.utils.buildQueryDataFromMap(queryMap);
+
+ // Truncate if truncationLimit set.
+ if (goog.isNumber(this.truncationLimit_)) {
+ queryData = queryData.substring(0, this.truncationLimit_);
+ }
+
+ // Send the request with the contents of the error.
+ this.xhrSender_(requestUrl, 'POST', queryData, this.extraHeaders_);
+ } catch (e) {
+ var logMessage = goog.string.buildString(
+ 'Error occurred in sending an error report.\n\n',
+ 'script:', fileName, '\n',
+ 'line:', line, '\n',
+ 'error:', message, '\n',
+ 'trace:', opt_trace);
+ goog.log.info(goog.debug.ErrorReporter.logger_, logMessage);
+ }
+};
+
+
+/**
+ * @param {string} prefix The prefix to appear prepended to all context
+ * variables in the error report body.
+ */
+goog.debug.ErrorReporter.prototype.setContextPrefix = function(prefix) {
+ this.contextPrefix_ = prefix;
+};
+
+
+/**
+ * @param {?number} limit Size in bytes to begin truncating POST body. Set to
+ * null to prevent truncation. The limit must be >= 0.
+ */
+goog.debug.ErrorReporter.prototype.setTruncationLimit = function(limit) {
+ goog.asserts.assert(!goog.isNumber(limit) || limit >= 0,
+ 'Body limit must be valid number >= 0 or null');
+ this.truncationLimit_ = limit;
+};
+
+
+/**
+ * @param {!Object<string,string>} urlArgs Set of key-value pairs to append
+ * to handlerUrl_ before sending XHR.
+ */
+goog.debug.ErrorReporter.prototype.setAdditionalArguments = function(urlArgs) {
+ this.additionalArguments_ = urlArgs;
+};
+
+
+/** @override */
+goog.debug.ErrorReporter.prototype.disposeInternal = function() {
+ if (goog.debug.ErrorReporter.ALLOW_AUTO_PROTECT) {
+ goog.dispose(this.errorHandler_);
+ }
+ goog.debug.ErrorReporter.base(this, 'disposeInternal');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/fancywindow.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/fancywindow.js b/externs/GCL/externs/goog/debug/fancywindow.js
new file mode 100644
index 0000000..d9aea26
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/fancywindow.js
@@ -0,0 +1,385 @@
+// 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 Definition of the FancyWindow class. Please minimize
+ * dependencies this file has on other closure classes as any dependency it
+ * takes won't be able to use the logging infrastructure.
+ *
+ * This is a pretty hacky implementation, aimed at making debugging of large
+ * applications more manageable.
+ *
+ * @see ../demos/debug.html
+ */
+
+
+goog.provide('goog.debug.FancyWindow');
+
+goog.require('goog.array');
+goog.require('goog.debug.DebugWindow');
+goog.require('goog.debug.LogManager');
+goog.require('goog.debug.Logger');
+goog.require('goog.dom.DomHelper');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.safe');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeStyleSheet');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+goog.require('goog.userAgent');
+
+
+
+// TODO(user): Introduce goog.scope for goog.html.SafeHtml once b/12014412
+// is fixed.
+/**
+ * Provides a Fancy extension to the DebugWindow class. Allows filtering based
+ * on loggers and levels.
+ *
+ * @param {string=} opt_identifier Idenitifier for this logging class.
+ * @param {string=} opt_prefix Prefix pre-pended to messages.
+ * @constructor
+ * @extends {goog.debug.DebugWindow}
+ */
+goog.debug.FancyWindow = function(opt_identifier, opt_prefix) {
+ this.readOptionsFromLocalStorage_();
+ goog.debug.FancyWindow.base(this, 'constructor', opt_identifier, opt_prefix);
+ /** @private {goog.dom.DomHelper} */
+ this.dh_ = null;
+};
+goog.inherits(goog.debug.FancyWindow, goog.debug.DebugWindow);
+
+
+/**
+ * Constant indicating if we are able to use localStorage to persist filters
+ * @type {boolean}
+ */
+goog.debug.FancyWindow.HAS_LOCAL_STORE = (function() {
+ /** @preserveTry */
+ try {
+ return !!window['localStorage'].getItem;
+ } catch (e) {}
+ return false;
+})();
+
+
+/**
+ * Constant defining the prefix to use when storing log levels
+ * @type {string}
+ */
+goog.debug.FancyWindow.LOCAL_STORE_PREFIX = 'fancywindow.sel.';
+
+
+/** @override */
+goog.debug.FancyWindow.prototype.writeBufferToLog = function() {
+ this.lastCall = goog.now();
+ if (this.hasActiveWindow()) {
+ var logel = this.dh_.getElement('log');
+
+ // Work out if scrolling is needed before we add the content
+ var scroll =
+ logel.scrollHeight - (logel.scrollTop + logel.offsetHeight) <= 100;
+
+ for (var i = 0; i < this.outputBuffer.length; i++) {
+ var div = this.dh_.createDom(goog.dom.TagName.DIV, 'logmsg');
+ goog.dom.safe.setInnerHtml(div, this.outputBuffer[i]);
+ logel.appendChild(div);
+ }
+ this.outputBuffer.length = 0;
+ this.resizeStuff_();
+
+ if (scroll) {
+ logel.scrollTop = logel.scrollHeight;
+ }
+ }
+};
+
+
+/** @override */
+goog.debug.FancyWindow.prototype.writeInitialDocument = function() {
+ if (!this.hasActiveWindow()) {
+ return;
+ }
+
+ var doc = this.win.document;
+ doc.open();
+ goog.dom.safe.documentWrite(doc, this.getHtml_());
+ doc.close();
+
+ (goog.userAgent.IE ? doc.body : this.win).onresize =
+ goog.bind(this.resizeStuff_, this);
+
+ // Create a dom helper for the logging window
+ this.dh_ = new goog.dom.DomHelper(doc);
+
+ // Don't use events system to reduce dependencies
+ this.dh_.getElement('openbutton').onclick =
+ goog.bind(this.openOptions_, this);
+ this.dh_.getElement('closebutton').onclick =
+ goog.bind(this.closeOptions_, this);
+ this.dh_.getElement('clearbutton').onclick =
+ goog.bind(this.clear, this);
+ this.dh_.getElement('exitbutton').onclick =
+ goog.bind(this.exit_, this);
+
+ this.writeSavedMessages();
+};
+
+
+/**
+ * Show the options menu.
+ * @return {boolean} false.
+ * @private
+ */
+goog.debug.FancyWindow.prototype.openOptions_ = function() {
+ var el = goog.asserts.assert(this.dh_.getElement('optionsarea'));
+ goog.dom.safe.setInnerHtml(el, goog.html.SafeHtml.EMPTY);
+
+ var loggers = goog.debug.FancyWindow.getLoggers_();
+ var dh = this.dh_;
+ for (var i = 0; i < loggers.length; i++) {
+ var logger = loggers[i];
+ var curlevel = logger.getLevel() ? logger.getLevel().name : 'INHERIT';
+ var div = dh.createDom(goog.dom.TagName.DIV, {},
+ this.getDropDown_('sel' + logger.getName(), curlevel),
+ dh.createDom(goog.dom.TagName.SPAN, {}, logger.getName() || '(root)'));
+ el.appendChild(div);
+ }
+
+ this.dh_.getElement('options').style.display = 'block';
+ return false;
+};
+
+
+/**
+ * Make a drop down for the log levels.
+ * @param {string} id Logger id.
+ * @param {string} selected What log level is currently selected.
+ * @return {Element} The newly created 'select' DOM element.
+ * @private
+ */
+goog.debug.FancyWindow.prototype.getDropDown_ = function(id, selected) {
+ var dh = this.dh_;
+ var sel = dh.createDom(goog.dom.TagName.SELECT, {'id': id});
+ var levels = goog.debug.Logger.Level.PREDEFINED_LEVELS;
+ for (var i = 0; i < levels.length; i++) {
+ var level = levels[i];
+ var option = dh.createDom(goog.dom.TagName.OPTION, {}, level.name);
+ if (selected == level.name) {
+ option.selected = true;
+ }
+ sel.appendChild(option);
+ }
+ sel.appendChild(dh.createDom(goog.dom.TagName.OPTION,
+ {'selected': selected == 'INHERIT'}, 'INHERIT'));
+ return sel;
+};
+
+
+/**
+ * Close the options menu.
+ * @return {boolean} The value false.
+ * @private
+ */
+goog.debug.FancyWindow.prototype.closeOptions_ = function() {
+ this.dh_.getElement('options').style.display = 'none';
+ var loggers = goog.debug.FancyWindow.getLoggers_();
+ var dh = this.dh_;
+ for (var i = 0; i < loggers.length; i++) {
+ var logger = loggers[i];
+ var sel = dh.getElement('sel' + logger.getName());
+ var level = sel.options[sel.selectedIndex].text;
+ if (level == 'INHERIT') {
+ logger.setLevel(null);
+ } else {
+ logger.setLevel(goog.debug.Logger.Level.getPredefinedLevel(level));
+ }
+ }
+ this.writeOptionsToLocalStorage_();
+ return false;
+};
+
+
+/**
+ * Resizes the log elements
+ * @private
+ */
+goog.debug.FancyWindow.prototype.resizeStuff_ = function() {
+ var dh = this.dh_;
+ var logel = dh.getElement('log');
+ var headel = dh.getElement('head');
+ logel.style.top = headel.offsetHeight + 'px';
+ logel.style.height = (dh.getDocument().body.offsetHeight -
+ headel.offsetHeight - (goog.userAgent.IE ? 4 : 0)) + 'px';
+};
+
+
+/**
+ * Handles the user clicking the exit button, disabled the debug window and
+ * closes the popup.
+ * @param {Event} e Event object.
+ * @private
+ */
+goog.debug.FancyWindow.prototype.exit_ = function(e) {
+ this.setEnabled(false);
+ if (this.win) {
+ this.win.close();
+ }
+};
+
+
+/** @override */
+goog.debug.FancyWindow.prototype.getStyleRules = function() {
+ var baseRules = goog.debug.FancyWindow.base(this, 'getStyleRules');
+ var extraRules = goog.html.SafeStyleSheet.fromConstant(goog.string.Const.from(
+ 'html,body{height:100%;width:100%;margin:0px;padding:0px;' +
+ 'background-color:#FFF;overflow:hidden}' +
+ '*{}' +
+ '.logmsg{border-bottom:1px solid #CCC;padding:2px;font:90% monospace}' +
+ '#head{position:absolute;width:100%;font:x-small arial;' +
+ 'border-bottom:2px solid #999;background-color:#EEE;}' +
+ '#head p{margin:0px 5px;}' +
+ '#log{position:absolute;width:100%;background-color:#FFF;}' +
+ '#options{position:absolute;right:0px;width:50%;height:100%;' +
+ 'border-left:1px solid #999;background-color:#DDD;display:none;' +
+ 'padding-left: 5px;font:normal small arial;overflow:auto;}' +
+ '#openbutton,#closebutton{text-decoration:underline;color:#00F;cursor:' +
+ 'pointer;position:absolute;top:0px;right:5px;font:x-small arial;}' +
+ '#clearbutton{text-decoration:underline;color:#00F;cursor:' +
+ 'pointer;position:absolute;top:0px;right:80px;font:x-small arial;}' +
+ '#exitbutton{text-decoration:underline;color:#00F;cursor:' +
+ 'pointer;position:absolute;top:0px;right:50px;font:x-small arial;}' +
+ 'select{font:x-small arial;margin-right:10px;}' +
+ 'hr{border:0;height:5px;background-color:#8c8;color:#8c8;}'));
+ return goog.html.SafeStyleSheet.concat(baseRules, extraRules);
+};
+
+
+/**
+ * Return the default HTML for the debug window
+ * @return {!goog.html.SafeHtml} Html.
+ * @private
+ */
+goog.debug.FancyWindow.prototype.getHtml_ = function() {
+ var SafeHtml = goog.html.SafeHtml;
+ var head = SafeHtml.create('head', {}, SafeHtml.concat(
+ SafeHtml.create('title', {}, 'Logging: ' + this.identifier),
+ SafeHtml.createStyle(this.getStyleRules())));
+
+ var body = SafeHtml.create('body', {}, SafeHtml.concat(
+ SafeHtml.create('div',
+ {'id': 'log', 'style': goog.string.Const.from('overflow:auto')}),
+ SafeHtml.create('div', {'id': 'head'}, SafeHtml.concat(
+ SafeHtml.create('p', {},
+ SafeHtml.create('b', {}, 'Logging: ' + this.identifier)),
+ SafeHtml.create('p', {}, this.welcomeMessage),
+ SafeHtml.create('span', {'id': 'clearbutton'}, 'clear'),
+ SafeHtml.create('span', {'id': 'exitbutton'}, 'exit'),
+ SafeHtml.create('span', {'id': 'openbutton'}, 'options'))),
+ SafeHtml.create('div', {'id': 'options'}, SafeHtml.concat(
+ SafeHtml.create('big', {},
+ SafeHtml.create('b', {}, 'Options:')),
+ SafeHtml.create('div', {'id': 'optionsarea'}),
+ SafeHtml.create('span', {'id': 'closebutton'}, 'save and close')))));
+
+ return SafeHtml.create('html', {}, SafeHtml.concat(head, body));
+};
+
+
+/**
+ * Write logger levels to localStorage if possible.
+ * @private
+ */
+goog.debug.FancyWindow.prototype.writeOptionsToLocalStorage_ = function() {
+ if (!goog.debug.FancyWindow.HAS_LOCAL_STORE) {
+ return;
+ }
+ var loggers = goog.debug.FancyWindow.getLoggers_();
+ var storedKeys = goog.debug.FancyWindow.getStoredKeys_();
+ for (var i = 0; i < loggers.length; i++) {
+ var key = goog.debug.FancyWindow.LOCAL_STORE_PREFIX + loggers[i].getName();
+ var level = loggers[i].getLevel();
+ if (key in storedKeys) {
+ if (!level) {
+ window.localStorage.removeItem(key);
+ } else if (window.localStorage.getItem(key) != level.name) {
+ window.localStorage.setItem(key, level.name);
+ }
+ } else if (level) {
+ window.localStorage.setItem(key, level.name);
+ }
+ }
+};
+
+
+/**
+ * Sync logger levels with any values stored in localStorage.
+ * @private
+ */
+goog.debug.FancyWindow.prototype.readOptionsFromLocalStorage_ = function() {
+ if (!goog.debug.FancyWindow.HAS_LOCAL_STORE) {
+ return;
+ }
+ var storedKeys = goog.debug.FancyWindow.getStoredKeys_();
+ for (var key in storedKeys) {
+ var loggerName = key.replace(goog.debug.FancyWindow.LOCAL_STORE_PREFIX, '');
+ var logger = goog.debug.LogManager.getLogger(loggerName);
+ var curLevel = logger.getLevel();
+ var storedLevel = window.localStorage.getItem(key).toString();
+ if (!curLevel || curLevel.toString() != storedLevel) {
+ logger.setLevel(goog.debug.Logger.Level.getPredefinedLevel(storedLevel));
+ }
+ }
+};
+
+
+/**
+ * Helper function to create a list of locally stored keys. Used to avoid
+ * expensive localStorage.getItem() calls.
+ * @return {!Object} List of keys.
+ * @private
+ */
+goog.debug.FancyWindow.getStoredKeys_ = function() {
+ var storedKeys = {};
+ for (var i = 0, len = window.localStorage.length; i < len; i++) {
+ var key = window.localStorage.key(i);
+ if (key != null && goog.string.startsWith(
+ key, goog.debug.FancyWindow.LOCAL_STORE_PREFIX)) {
+ storedKeys[key] = true;
+ }
+ }
+ return storedKeys;
+};
+
+
+/**
+ * Gets a sorted array of all the loggers registered.
+ * @return {!Array<!goog.debug.Logger>} Array of logger instances.
+ * @private
+ */
+goog.debug.FancyWindow.getLoggers_ = function() {
+ var loggers = goog.object.getValues(goog.debug.LogManager.getLoggers());
+
+ /**
+ * @param {!goog.debug.Logger} a
+ * @param {!goog.debug.Logger} b
+ * @return {number}
+ */
+ var loggerSort = function(a, b) {
+ return goog.array.defaultCompare(a.getName(), b.getName());
+ };
+ goog.array.sort(loggers, loggerSort);
+ return loggers;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/formatter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/formatter.js b/externs/GCL/externs/goog/debug/formatter.js
new file mode 100644
index 0000000..949a652
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/formatter.js
@@ -0,0 +1,387 @@
+// 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 Definition of various formatters for logging. Please minimize
+ * dependencies this file has on other closure classes as any dependency it
+ * takes won't be able to use the logging infrastructure.
+ *
+ */
+
+goog.provide('goog.debug.Formatter');
+goog.provide('goog.debug.HtmlFormatter');
+goog.provide('goog.debug.TextFormatter');
+
+goog.require('goog.debug');
+goog.require('goog.debug.Logger');
+goog.require('goog.debug.RelativeTimeProvider');
+goog.require('goog.html.SafeHtml');
+
+
+
+/**
+ * Base class for Formatters. A Formatter is used to format a LogRecord into
+ * something that can be displayed to the user.
+ *
+ * @param {string=} opt_prefix The prefix to place before text records.
+ * @constructor
+ */
+goog.debug.Formatter = function(opt_prefix) {
+ this.prefix_ = opt_prefix || '';
+
+ /**
+ * A provider that returns the relative start time.
+ * @type {goog.debug.RelativeTimeProvider}
+ * @private
+ */
+ this.startTimeProvider_ =
+ goog.debug.RelativeTimeProvider.getDefaultInstance();
+};
+
+
+/**
+ * Whether to append newlines to the end of formatted log records.
+ * @type {boolean}
+ */
+goog.debug.Formatter.prototype.appendNewline = true;
+
+
+/**
+ * Whether to show absolute time in the DebugWindow.
+ * @type {boolean}
+ */
+goog.debug.Formatter.prototype.showAbsoluteTime = true;
+
+
+/**
+ * Whether to show relative time in the DebugWindow.
+ * @type {boolean}
+ */
+goog.debug.Formatter.prototype.showRelativeTime = true;
+
+
+/**
+ * Whether to show the logger name in the DebugWindow.
+ * @type {boolean}
+ */
+goog.debug.Formatter.prototype.showLoggerName = true;
+
+
+/**
+ * Whether to show the logger exception text.
+ * @type {boolean}
+ */
+goog.debug.Formatter.prototype.showExceptionText = false;
+
+
+/**
+ * Whether to show the severity level.
+ * @type {boolean}
+ */
+goog.debug.Formatter.prototype.showSeverityLevel = false;
+
+
+/**
+ * Formats a record.
+ * @param {goog.debug.LogRecord} logRecord the logRecord to format.
+ * @return {string} The formatted string.
+ */
+goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;
+
+
+/**
+ * Formats a record as SafeHtml.
+ * @param {goog.debug.LogRecord} logRecord the logRecord to format.
+ * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
+ */
+goog.debug.Formatter.prototype.formatRecordAsHtml = goog.abstractMethod;
+
+
+/**
+ * Sets the start time provider. By default, this is the default instance
+ * but can be changed.
+ * @param {goog.debug.RelativeTimeProvider} provider The provider to use.
+ */
+goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
+ this.startTimeProvider_ = provider;
+};
+
+
+/**
+ * Returns the start time provider. By default, this is the default instance
+ * but can be changed.
+ * @return {goog.debug.RelativeTimeProvider} The start time provider.
+ */
+goog.debug.Formatter.prototype.getStartTimeProvider = function() {
+ return this.startTimeProvider_;
+};
+
+
+/**
+ * Resets the start relative time.
+ */
+goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
+ this.startTimeProvider_.reset();
+};
+
+
+/**
+ * Returns a string for the time/date of the LogRecord.
+ * @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.
+ * @return {string} A string representation of the time/date of the LogRecord.
+ * @private
+ */
+goog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {
+ var time = new Date(logRecord.getMillis());
+ return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +
+ goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +
+ goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +
+ goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +
+ goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +
+ goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +
+ goog.debug.Formatter.getTwoDigitString_(
+ Math.floor(time.getMilliseconds() / 10));
+};
+
+
+/**
+ * Returns the number as a two-digit string, meaning it prepends a 0 if the
+ * number if less than 10.
+ * @param {number} n The number to format.
+ * @return {string} A two-digit string representation of {@code n}.
+ * @private
+ */
+goog.debug.Formatter.getTwoDigitString_ = function(n) {
+ if (n < 10) {
+ return '0' + n;
+ }
+ return String(n);
+};
+
+
+/**
+ * Returns a string for the number of seconds relative to the start time.
+ * Prepads with spaces so that anything less than 1000 seconds takes up the
+ * same number of characters for better formatting.
+ * @param {goog.debug.LogRecord} logRecord The log to compare time to.
+ * @param {number} relativeTimeStart The start time to compare to.
+ * @return {string} The number of seconds of the LogRecord relative to the
+ * start time.
+ * @private
+ */
+goog.debug.Formatter.getRelativeTime_ = function(logRecord,
+ relativeTimeStart) {
+ var ms = logRecord.getMillis() - relativeTimeStart;
+ var sec = ms / 1000;
+ var str = sec.toFixed(3);
+
+ var spacesToPrepend = 0;
+ if (sec < 1) {
+ spacesToPrepend = 2;
+ } else {
+ while (sec < 100) {
+ spacesToPrepend++;
+ sec *= 10;
+ }
+ }
+ while (spacesToPrepend-- > 0) {
+ str = ' ' + str;
+ }
+ return str;
+};
+
+
+
+/**
+ * Formatter that returns formatted html. See formatRecord for the classes
+ * it uses for various types of formatted output.
+ *
+ * @param {string=} opt_prefix The prefix to place before text records.
+ * @constructor
+ * @extends {goog.debug.Formatter}
+ */
+goog.debug.HtmlFormatter = function(opt_prefix) {
+ goog.debug.Formatter.call(this, opt_prefix);
+};
+goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);
+
+
+/**
+ * Whether to show the logger exception text
+ * @type {boolean}
+ * @override
+ */
+goog.debug.HtmlFormatter.prototype.showExceptionText = true;
+
+
+/**
+ * Formats a record
+ * @param {goog.debug.LogRecord} logRecord the logRecord to format.
+ * @return {string} The formatted string as html.
+ * @override
+ */
+goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
+ if (!logRecord) {
+ return '';
+ }
+ // OK not to use goog.html.SafeHtml.unwrap() here.
+ return this.formatRecordAsHtml(logRecord).getTypedStringValue();
+};
+
+
+/**
+ * Formats a record.
+ * @param {goog.debug.LogRecord} logRecord the logRecord to format.
+ * @return {!goog.html.SafeHtml} The formatted string as SafeHtml.
+ * @override
+ */
+goog.debug.HtmlFormatter.prototype.formatRecordAsHtml = function(logRecord) {
+ if (!logRecord) {
+ return goog.html.SafeHtml.EMPTY;
+ }
+
+ var className;
+ switch (logRecord.getLevel().value) {
+ case goog.debug.Logger.Level.SHOUT.value:
+ className = 'dbg-sh';
+ break;
+ case goog.debug.Logger.Level.SEVERE.value:
+ className = 'dbg-sev';
+ break;
+ case goog.debug.Logger.Level.WARNING.value:
+ className = 'dbg-w';
+ break;
+ case goog.debug.Logger.Level.INFO.value:
+ className = 'dbg-i';
+ break;
+ case goog.debug.Logger.Level.FINE.value:
+ default:
+ className = 'dbg-f';
+ break;
+ }
+
+ // HTML for user defined prefix, time, logger name, and severity.
+ var sb = [];
+ sb.push(this.prefix_, ' ');
+ if (this.showAbsoluteTime) {
+ sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
+ }
+ if (this.showRelativeTime) {
+ sb.push('[',
+ goog.debug.Formatter.getRelativeTime_(
+ logRecord, this.startTimeProvider_.get()),
+ 's] ');
+ }
+ if (this.showLoggerName) {
+ sb.push('[', logRecord.getLoggerName(), '] ');
+ }
+ if (this.showSeverityLevel) {
+ sb.push('[', logRecord.getLevel().name, '] ');
+ }
+ var fullPrefixHtml =
+ goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(sb.join(''));
+
+ // HTML for exception text and log record.
+ var exceptionHtml = goog.html.SafeHtml.EMPTY;
+ if (this.showExceptionText && logRecord.getException()) {
+ exceptionHtml = goog.html.SafeHtml.concat(
+ goog.html.SafeHtml.create('br'),
+ goog.debug.exposeExceptionAsHtml(logRecord.getException()));
+ }
+ var logRecordHtml = goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
+ logRecord.getMessage());
+ var recordAndExceptionHtml = goog.html.SafeHtml.create(
+ 'span',
+ {'class': className},
+ goog.html.SafeHtml.concat(logRecordHtml, exceptionHtml));
+
+
+ // Combine both pieces of HTML and, if needed, append a final newline.
+ var html;
+ if (this.appendNewline) {
+ html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml,
+ goog.html.SafeHtml.create('br'));
+ } else {
+ html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml);
+ }
+ return html;
+};
+
+
+
+/**
+ * Formatter that returns formatted plain text
+ *
+ * @param {string=} opt_prefix The prefix to place before text records.
+ * @constructor
+ * @extends {goog.debug.Formatter}
+ * @final
+ */
+goog.debug.TextFormatter = function(opt_prefix) {
+ goog.debug.Formatter.call(this, opt_prefix);
+};
+goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);
+
+
+/**
+ * Formats a record as text
+ * @param {goog.debug.LogRecord} logRecord the logRecord to format.
+ * @return {string} The formatted string.
+ * @override
+ */
+goog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {
+ var sb = [];
+ sb.push(this.prefix_, ' ');
+ if (this.showAbsoluteTime) {
+ sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
+ }
+ if (this.showRelativeTime) {
+ sb.push('[', goog.debug.Formatter.getRelativeTime_(logRecord,
+ this.startTimeProvider_.get()), 's] ');
+ }
+
+ if (this.showLoggerName) {
+ sb.push('[', logRecord.getLoggerName(), '] ');
+ }
+ if (this.showSeverityLevel) {
+ sb.push('[', logRecord.getLevel().name, '] ');
+ }
+ sb.push(logRecord.getMessage());
+ if (this.showExceptionText) {
+ var exception = logRecord.getException();
+ if (exception) {
+ var exceptionText = exception instanceof Error ?
+ exception.message :
+ exception.toString();
+ sb.push('\n', exceptionText);
+ }
+ }
+ if (this.appendNewline) {
+ sb.push('\n');
+ }
+ return sb.join('');
+};
+
+
+/**
+ * Formats a record as text
+ * @param {goog.debug.LogRecord} logRecord the logRecord to format.
+ * @return {!goog.html.SafeHtml} The formatted string as SafeHtml. This is
+ * just an HTML-escaped version of the text obtained from formatRecord().
+ * @override
+ */
+goog.debug.TextFormatter.prototype.formatRecordAsHtml = function(logRecord) {
+ return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
+ goog.debug.TextFormatter.prototype.formatRecord(logRecord));
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/fpsdisplay.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/fpsdisplay.js b/externs/GCL/externs/goog/debug/fpsdisplay.js
new file mode 100644
index 0000000..f8f525f
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/fpsdisplay.js
@@ -0,0 +1,165 @@
+// 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 Displays frames per second (FPS) for the current window.
+ * Only supported in browsers that support requestAnimationFrame.
+ * See: https://developer.mozilla.org/en/DOM/window.requestAnimationFrame.
+ *
+ * @see ../demos/fpsdisplay.html
+ */
+
+goog.provide('goog.debug.FpsDisplay');
+
+goog.require('goog.asserts');
+goog.require('goog.async.AnimationDelay');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.ui.Component');
+
+
+
+/**
+ * Displays frames per seconds that the window this component is
+ * rendered in is animating at.
+ *
+ * @param {goog.dom.DomHelper=} opt_domHelper An optional dom helper.
+ * @constructor
+ * @extends {goog.ui.Component}
+ * @final
+ */
+goog.debug.FpsDisplay = function(opt_domHelper) {
+ goog.debug.FpsDisplay.base(this, 'constructor', opt_domHelper);
+};
+goog.inherits(goog.debug.FpsDisplay, goog.ui.Component);
+
+
+/**
+ * CSS class for the FPS display.
+ */
+goog.debug.FpsDisplay.CSS = goog.getCssName('goog-fps-display');
+
+
+/**
+ * The number of samples per FPS report.
+ */
+goog.debug.FpsDisplay.SAMPLES = 10;
+
+
+/**
+ * The current animation.
+ * @type {goog.debug.FpsDisplay.FpsAnimation_}
+ * @private
+ */
+goog.debug.FpsDisplay.prototype.animation_ = null;
+
+
+/** @override */
+goog.debug.FpsDisplay.prototype.createDom = function() {
+ this.setElementInternal(this.getDomHelper().createDom(
+ goog.dom.TagName.DIV, goog.debug.FpsDisplay.CSS));
+};
+
+
+/** @override */
+goog.debug.FpsDisplay.prototype.enterDocument = function() {
+ goog.debug.FpsDisplay.base(this, 'enterDocument');
+ this.animation_ = new goog.debug.FpsDisplay.FpsAnimation_(this.getElement());
+ this.delay_ = new goog.async.AnimationDelay(
+ this.handleDelay_, this.getDomHelper().getWindow(), this);
+ this.delay_.start();
+};
+
+
+/**
+ * @param {number} now The current time.
+ * @private
+ */
+goog.debug.FpsDisplay.prototype.handleDelay_ = function(now) {
+ if (this.isInDocument()) {
+ this.animation_.onAnimationFrame(now);
+ this.delay_.start();
+ }
+};
+
+
+/** @override */
+goog.debug.FpsDisplay.prototype.exitDocument = function() {
+ goog.debug.FpsDisplay.base(this, 'exitDocument');
+ this.animation_ = null;
+ goog.dispose(this.delay_);
+};
+
+
+/**
+ * @return {number} The average frames per second.
+ */
+goog.debug.FpsDisplay.prototype.getFps = function() {
+ goog.asserts.assert(
+ this.isInDocument(), 'Render the FPS display before querying FPS');
+ return this.animation_.lastFps_;
+};
+
+
+
+/**
+ * @param {Element} elem An element to hold the FPS count.
+ * @constructor
+ * @private
+ */
+goog.debug.FpsDisplay.FpsAnimation_ = function(elem) {
+ /**
+ * An element to hold the current FPS rate.
+ * @type {Element}
+ * @private
+ */
+ this.element_ = elem;
+
+ /**
+ * The number of frames observed so far.
+ * @type {number}
+ * @private
+ */
+ this.frameNumber_ = 0;
+};
+
+
+/**
+ * The last time which we reported FPS at.
+ * @type {number}
+ * @private
+ */
+goog.debug.FpsDisplay.FpsAnimation_.prototype.lastTime_ = 0;
+
+
+/**
+ * The last average FPS.
+ * @type {number}
+ * @private
+ */
+goog.debug.FpsDisplay.FpsAnimation_.prototype.lastFps_ = -1;
+
+
+/**
+ * @param {number} now The current time.
+ */
+goog.debug.FpsDisplay.FpsAnimation_.prototype.onAnimationFrame = function(now) {
+ var SAMPLES = goog.debug.FpsDisplay.SAMPLES;
+ if (this.frameNumber_ % SAMPLES == 0) {
+ this.lastFps_ = Math.round((1000 * SAMPLES) / (now - this.lastTime_));
+ goog.dom.setTextContent(this.element_, this.lastFps_);
+ this.lastTime_ = now;
+ }
+ this.frameNumber_++;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/gcdiagnostics.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/gcdiagnostics.js b/externs/GCL/externs/goog/debug/gcdiagnostics.js
new file mode 100644
index 0000000..5e5ba9a
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/gcdiagnostics.js
@@ -0,0 +1,143 @@
+// 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 GcDiagnostics class.
+ *
+ */
+
+goog.provide('goog.debug.GcDiagnostics');
+
+goog.require('goog.debug.Trace');
+goog.require('goog.log');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Class used for singleton goog.debug.GcDiagnostics. Used to hook into
+ * the L2 ActiveX controller to profile garbage collection information in IE.
+ * Can be used in combination with tracers (goog.debug.Trace), to provide object
+ * allocation counts from within the tracers or used alone by invoking start and
+ * stop.
+ *
+ * See http://go/l2binary for the install.
+ * TODO(user): Move the L2 installer somewhere more general.
+ * @constructor
+ * @private
+ */
+goog.debug.GcDiagnostics_ = function() {};
+
+
+/**
+ * Install the GcDiagnostics tool.
+ */
+goog.debug.GcDiagnostics_.prototype.install = function() {
+ if (goog.userAgent.IE) {
+ /** @preserveTry */
+ try {
+ var l2Helper = new ActiveXObject('L2.NativeHelper');
+
+ // If using tracers, use the higher precision timer provided by L2.
+ if (goog.debug.Trace_) {
+ goog.debug.Trace_.now = function() {
+ return l2Helper['getMilliSeconds']();
+ };
+ }
+
+ if (l2Helper['gcTracer']) {
+ l2Helper['gcTracer']['installGcTracing']();
+ this.gcTracer_ = l2Helper['gcTracer'];
+ if (goog.debug.Trace) {
+ // If tracers are in use, register the gcTracer so that per tracer
+ // allocations are recorded.
+ goog.debug.Trace.setGcTracer(this.gcTracer_);
+ }
+ }
+ goog.log.info(this.logger_, 'Installed L2 native helper');
+ } catch (e) {
+ goog.log.info(this.logger_, 'Failed to install L2 native helper: ' + e);
+ }
+ }
+};
+
+
+/**
+ * Logger for the gcDiagnotics
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.debug.GcDiagnostics_.prototype.logger_ =
+ goog.log.getLogger('goog.debug.GcDiagnostics');
+
+
+/**
+ * Starts recording garbage collection information. If a trace is already in
+ * progress, it is ended.
+ */
+goog.debug.GcDiagnostics_.prototype.start = function() {
+ if (this.gcTracer_) {
+ if (this.gcTracer_['isTracing']()) {
+ this.gcTracer_['endGcTracing']();
+ }
+ this.gcTracer_['startGcTracing']();
+ }
+};
+
+
+/**
+ * Stops recording garbage collection information. Logs details on the garbage
+ * collections that occurred between start and stop. If tracers are in use,
+ * adds comments where each GC occurs.
+ */
+goog.debug.GcDiagnostics_.prototype.stop = function() {
+ if (this.gcTracer_ && this.gcTracer_['isTracing']()) {
+ var gcTracer = this.gcTracer_;
+ this.gcTracer_['endGcTracing']();
+
+ var numGCs = gcTracer['getNumTraces']();
+ goog.log.info(this.logger_, '*********GC TRACE*********');
+ goog.log.info(this.logger_, 'GC ran ' + numGCs + ' times.');
+ var totalTime = 0;
+ for (var i = 0; i < numGCs; i++) {
+ var trace = gcTracer['getTrace'](i);
+
+ var msStart = trace['gcStartTime'];
+ var msElapsed = trace['gcElapsedTime'];
+
+ var msRounded = Math.round(msElapsed * 10) / 10;
+ var s = 'GC ' + i + ': ' + msRounded + ' ms, ' +
+ 'numVValAlloc=' + trace['numVValAlloc'] + ', ' +
+ 'numVarAlloc=' + trace['numVarAlloc'] + ', ' +
+ 'numBytesSysAlloc=' + trace['numBytesSysAlloc'];
+ if (goog.debug.Trace) {
+ goog.debug.Trace.addComment(s, null, msStart);
+ }
+ goog.log.info(this.logger_, s);
+ totalTime += msElapsed;
+ }
+ if (goog.debug.Trace) {
+ goog.debug.Trace.addComment('Total GC time was ' + totalTime + ' ms.');
+ }
+ goog.log.info(this.logger_, 'Total GC time was ' + totalTime + ' ms.');
+ goog.log.info(this.logger_, '*********GC TRACE*********');
+ }
+};
+
+
+/**
+ * Singleton GcDiagnostics object
+ * @type {goog.debug.GcDiagnostics_}
+ */
+goog.debug.GcDiagnostics = new goog.debug.GcDiagnostics_();
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/logbuffer.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/logbuffer.js b/externs/GCL/externs/goog/debug/logbuffer.js
new file mode 100644
index 0000000..7e3de4b
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/logbuffer.js
@@ -0,0 +1,148 @@
+// 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 A buffer for log records. The purpose of this is to improve
+ * logging performance by re-using old objects when the buffer becomes full and
+ * to eliminate the need for each app to implement their own log buffer. The
+ * disadvantage to doing this is that log handlers cannot maintain references to
+ * log records and expect that they are not overwriten at a later point.
+ *
+ * @author agrieve@google.com (Andrew Grieve)
+ */
+
+goog.provide('goog.debug.LogBuffer');
+
+goog.require('goog.asserts');
+goog.require('goog.debug.LogRecord');
+
+
+
+/**
+ * Creates the log buffer.
+ * @constructor
+ * @final
+ */
+goog.debug.LogBuffer = function() {
+ goog.asserts.assert(goog.debug.LogBuffer.isBufferingEnabled(),
+ 'Cannot use goog.debug.LogBuffer without defining ' +
+ 'goog.debug.LogBuffer.CAPACITY.');
+ this.clear();
+};
+
+
+/**
+ * A static method that always returns the same instance of LogBuffer.
+ * @return {!goog.debug.LogBuffer} The LogBuffer singleton instance.
+ */
+goog.debug.LogBuffer.getInstance = function() {
+ if (!goog.debug.LogBuffer.instance_) {
+ // This function is written with the return statement after the assignment
+ // to avoid the jscompiler StripCode bug described in http://b/2608064.
+ // After that bug is fixed this can be refactored.
+ goog.debug.LogBuffer.instance_ = new goog.debug.LogBuffer();
+ }
+ return goog.debug.LogBuffer.instance_;
+};
+
+
+/**
+ * @define {number} The number of log records to buffer. 0 means disable
+ * buffering.
+ */
+goog.define('goog.debug.LogBuffer.CAPACITY', 0);
+
+
+/**
+ * The array to store the records.
+ * @type {!Array<!goog.debug.LogRecord|undefined>}
+ * @private
+ */
+goog.debug.LogBuffer.prototype.buffer_;
+
+
+/**
+ * The index of the most recently added record or -1 if there are no records.
+ * @type {number}
+ * @private
+ */
+goog.debug.LogBuffer.prototype.curIndex_;
+
+
+/**
+ * Whether the buffer is at capacity.
+ * @type {boolean}
+ * @private
+ */
+goog.debug.LogBuffer.prototype.isFull_;
+
+
+/**
+ * Adds a log record to the buffer, possibly overwriting the oldest record.
+ * @param {goog.debug.Logger.Level} level One of the level identifiers.
+ * @param {string} msg The string message.
+ * @param {string} loggerName The name of the source logger.
+ * @return {!goog.debug.LogRecord} The log record.
+ */
+goog.debug.LogBuffer.prototype.addRecord = function(level, msg, loggerName) {
+ var curIndex = (this.curIndex_ + 1) % goog.debug.LogBuffer.CAPACITY;
+ this.curIndex_ = curIndex;
+ if (this.isFull_) {
+ var ret = this.buffer_[curIndex];
+ ret.reset(level, msg, loggerName);
+ return ret;
+ }
+ this.isFull_ = curIndex == goog.debug.LogBuffer.CAPACITY - 1;
+ return this.buffer_[curIndex] =
+ new goog.debug.LogRecord(level, msg, loggerName);
+};
+
+
+/**
+ * @return {boolean} Whether the log buffer is enabled.
+ */
+goog.debug.LogBuffer.isBufferingEnabled = function() {
+ return goog.debug.LogBuffer.CAPACITY > 0;
+};
+
+
+/**
+ * Removes all buffered log records.
+ */
+goog.debug.LogBuffer.prototype.clear = function() {
+ this.buffer_ = new Array(goog.debug.LogBuffer.CAPACITY);
+ this.curIndex_ = -1;
+ this.isFull_ = false;
+};
+
+
+/**
+ * Calls the given function for each buffered log record, starting with the
+ * oldest one.
+ * @param {function(!goog.debug.LogRecord)} func The function to call.
+ */
+goog.debug.LogBuffer.prototype.forEachRecord = function(func) {
+ var buffer = this.buffer_;
+ // Corner case: no records.
+ if (!buffer[0]) {
+ return;
+ }
+ var curIndex = this.curIndex_;
+ var i = this.isFull_ ? curIndex : -1;
+ do {
+ i = (i + 1) % goog.debug.LogBuffer.CAPACITY;
+ func(/** @type {!goog.debug.LogRecord} */ (buffer[i]));
+ } while (i != curIndex);
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/logger.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/logger.js b/externs/GCL/externs/goog/debug/logger.js
new file mode 100644
index 0000000..5ced90a
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/logger.js
@@ -0,0 +1,873 @@
+// 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 Definition of the Logger class. Please minimize dependencies
+ * this file has on other closure classes as any dependency it takes won't be
+ * able to use the logging infrastructure.
+ *
+ * @see ../demos/debug.html
+ */
+
+goog.provide('goog.debug.LogManager');
+goog.provide('goog.debug.Loggable');
+goog.provide('goog.debug.Logger');
+goog.provide('goog.debug.Logger.Level');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.debug');
+goog.require('goog.debug.LogBuffer');
+goog.require('goog.debug.LogRecord');
+
+
+/**
+ * A message value that can be handled by a Logger.
+ *
+ * Functions are treated like callbacks, but are only called when the event's
+ * log level is enabled. This is useful for logging messages that are expensive
+ * to construct.
+ *
+ * @typedef {string|function(): string}
+ */
+goog.debug.Loggable;
+
+
+
+/**
+ * The Logger is an object used for logging debug messages. Loggers are
+ * normally named, using a hierarchical dot-separated namespace. Logger names
+ * can be arbitrary strings, but they should normally be based on the package
+ * name or class name of the logged component, such as goog.net.BrowserChannel.
+ *
+ * The Logger object is loosely based on the java class
+ * java.util.logging.Logger. It supports different levels of filtering for
+ * different loggers.
+ *
+ * The logger object should never be instantiated by application code. It
+ * should always use the goog.debug.Logger.getLogger function.
+ *
+ * @constructor
+ * @param {string} name The name of the Logger.
+ * @final
+ */
+goog.debug.Logger = function(name) {
+ /**
+ * Name of the Logger. Generally a dot-separated namespace
+ * @private {string}
+ */
+ this.name_ = name;
+
+ /**
+ * Parent Logger.
+ * @private {goog.debug.Logger}
+ */
+ this.parent_ = null;
+
+ /**
+ * Level that this logger only filters above. Null indicates it should
+ * inherit from the parent.
+ * @private {goog.debug.Logger.Level}
+ */
+ this.level_ = null;
+
+ /**
+ * Map of children loggers. The keys are the leaf names of the children and
+ * the values are the child loggers.
+ * @private {Object}
+ */
+ this.children_ = null;
+
+ /**
+ * Handlers that are listening to this logger.
+ * @private {Array<Function>}
+ */
+ this.handlers_ = null;
+};
+
+
+/** @const */
+goog.debug.Logger.ROOT_LOGGER_NAME = '';
+
+
+/**
+ * @define {boolean} Toggles whether loggers other than the root logger can have
+ * log handlers attached to them and whether they can have their log level
+ * set. Logging is a bit faster when this is set to false.
+ */
+goog.define('goog.debug.Logger.ENABLE_HIERARCHY', true);
+
+
+if (!goog.debug.Logger.ENABLE_HIERARCHY) {
+ /**
+ * @type {!Array<Function>}
+ * @private
+ */
+ goog.debug.Logger.rootHandlers_ = [];
+
+
+ /**
+ * @type {goog.debug.Logger.Level}
+ * @private
+ */
+ goog.debug.Logger.rootLevel_;
+}
+
+
+
+/**
+ * The Level class defines a set of standard logging levels that
+ * can be used to control logging output. The logging Level objects
+ * are ordered and are specified by ordered integers. Enabling logging
+ * at a given level also enables logging at all higher levels.
+ * <p>
+ * Clients should normally use the predefined Level constants such
+ * as Level.SEVERE.
+ * <p>
+ * The levels in descending order are:
+ * <ul>
+ * <li>SEVERE (highest value)
+ * <li>WARNING
+ * <li>INFO
+ * <li>CONFIG
+ * <li>FINE
+ * <li>FINER
+ * <li>FINEST (lowest value)
+ * </ul>
+ * In addition there is a level OFF that can be used to turn
+ * off logging, and a level ALL that can be used to enable
+ * logging of all messages.
+ *
+ * @param {string} name The name of the level.
+ * @param {number} value The numeric value of the level.
+ * @constructor
+ * @final
+ */
+goog.debug.Logger.Level = function(name, value) {
+ /**
+ * The name of the level
+ * @type {string}
+ */
+ this.name = name;
+
+ /**
+ * The numeric value of the level
+ * @type {number}
+ */
+ this.value = value;
+};
+
+
+/**
+ * @return {string} String representation of the logger level.
+ * @override
+ */
+goog.debug.Logger.Level.prototype.toString = function() {
+ return this.name;
+};
+
+
+/**
+ * OFF is a special level that can be used to turn off logging.
+ * This level is initialized to <CODE>Infinity</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.OFF =
+ new goog.debug.Logger.Level('OFF', Infinity);
+
+
+/**
+ * SHOUT is a message level for extra debugging loudness.
+ * This level is initialized to <CODE>1200</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.SHOUT = new goog.debug.Logger.Level('SHOUT', 1200);
+
+
+/**
+ * SEVERE is a message level indicating a serious failure.
+ * This level is initialized to <CODE>1000</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.SEVERE = new goog.debug.Logger.Level('SEVERE', 1000);
+
+
+/**
+ * WARNING is a message level indicating a potential problem.
+ * This level is initialized to <CODE>900</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.WARNING = new goog.debug.Logger.Level('WARNING', 900);
+
+
+/**
+ * INFO is a message level for informational messages.
+ * This level is initialized to <CODE>800</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.INFO = new goog.debug.Logger.Level('INFO', 800);
+
+
+/**
+ * CONFIG is a message level for static configuration messages.
+ * This level is initialized to <CODE>700</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.CONFIG = new goog.debug.Logger.Level('CONFIG', 700);
+
+
+/**
+ * FINE is a message level providing tracing information.
+ * This level is initialized to <CODE>500</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.FINE = new goog.debug.Logger.Level('FINE', 500);
+
+
+/**
+ * FINER indicates a fairly detailed tracing message.
+ * This level is initialized to <CODE>400</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.FINER = new goog.debug.Logger.Level('FINER', 400);
+
+/**
+ * FINEST indicates a highly detailed tracing message.
+ * This level is initialized to <CODE>300</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+
+goog.debug.Logger.Level.FINEST = new goog.debug.Logger.Level('FINEST', 300);
+
+
+/**
+ * ALL indicates that all messages should be logged.
+ * This level is initialized to <CODE>0</CODE>.
+ * @type {!goog.debug.Logger.Level}
+ */
+goog.debug.Logger.Level.ALL = new goog.debug.Logger.Level('ALL', 0);
+
+
+/**
+ * The predefined levels.
+ * @type {!Array<!goog.debug.Logger.Level>}
+ * @final
+ */
+goog.debug.Logger.Level.PREDEFINED_LEVELS = [
+ goog.debug.Logger.Level.OFF,
+ goog.debug.Logger.Level.SHOUT,
+ goog.debug.Logger.Level.SEVERE,
+ goog.debug.Logger.Level.WARNING,
+ goog.debug.Logger.Level.INFO,
+ goog.debug.Logger.Level.CONFIG,
+ goog.debug.Logger.Level.FINE,
+ goog.debug.Logger.Level.FINER,
+ goog.debug.Logger.Level.FINEST,
+ goog.debug.Logger.Level.ALL];
+
+
+/**
+ * A lookup map used to find the level object based on the name or value of
+ * the level object.
+ * @type {Object}
+ * @private
+ */
+goog.debug.Logger.Level.predefinedLevelsCache_ = null;
+
+
+/**
+ * Creates the predefined levels cache and populates it.
+ * @private
+ */
+goog.debug.Logger.Level.createPredefinedLevelsCache_ = function() {
+ goog.debug.Logger.Level.predefinedLevelsCache_ = {};
+ for (var i = 0, level; level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
+ i++) {
+ goog.debug.Logger.Level.predefinedLevelsCache_[level.value] = level;
+ goog.debug.Logger.Level.predefinedLevelsCache_[level.name] = level;
+ }
+};
+
+
+/**
+ * Gets the predefined level with the given name.
+ * @param {string} name The name of the level.
+ * @return {goog.debug.Logger.Level} The level, or null if none found.
+ */
+goog.debug.Logger.Level.getPredefinedLevel = function(name) {
+ if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
+ goog.debug.Logger.Level.createPredefinedLevelsCache_();
+ }
+
+ return goog.debug.Logger.Level.predefinedLevelsCache_[name] || null;
+};
+
+
+/**
+ * Gets the highest predefined level <= #value.
+ * @param {number} value Level value.
+ * @return {goog.debug.Logger.Level} The level, or null if none found.
+ */
+goog.debug.Logger.Level.getPredefinedLevelByValue = function(value) {
+ if (!goog.debug.Logger.Level.predefinedLevelsCache_) {
+ goog.debug.Logger.Level.createPredefinedLevelsCache_();
+ }
+
+ if (value in goog.debug.Logger.Level.predefinedLevelsCache_) {
+ return goog.debug.Logger.Level.predefinedLevelsCache_[value];
+ }
+
+ for (var i = 0; i < goog.debug.Logger.Level.PREDEFINED_LEVELS.length; ++i) {
+ var level = goog.debug.Logger.Level.PREDEFINED_LEVELS[i];
+ if (level.value <= value) {
+ return level;
+ }
+ }
+ return null;
+};
+
+
+/**
+ * Finds or creates a logger for a named subsystem. If a logger has already been
+ * created with the given name it is returned. Otherwise a new logger is
+ * created. If a new logger is created its log level will be configured based
+ * on the LogManager configuration and it will configured to also send logging
+ * output to its parent's handlers. It will be registered in the LogManager
+ * global namespace.
+ *
+ * @param {string} name A name for the logger. This should be a dot-separated
+ * name and should normally be based on the package name or class name of the
+ * subsystem, such as goog.net.BrowserChannel.
+ * @return {!goog.debug.Logger} The named logger.
+ * @deprecated use goog.log instead. http://go/goog-debug-logger-deprecated
+ */
+goog.debug.Logger.getLogger = function(name) {
+ return goog.debug.LogManager.getLogger(name);
+};
+
+
+/**
+ * Logs a message to profiling tools, if available.
+ * {@see https://developers.google.com/web-toolkit/speedtracer/logging-api}
+ * {@see http://msdn.microsoft.com/en-us/library/dd433074(VS.85).aspx}
+ * @param {string} msg The message to log.
+ */
+goog.debug.Logger.logToProfilers = function(msg) {
+ // Using goog.global, as loggers might be used in window-less contexts.
+ if (goog.global['console']) {
+ if (goog.global['console']['timeStamp']) {
+ // Logs a message to Firebug, Web Inspector, SpeedTracer, etc.
+ goog.global['console']['timeStamp'](msg);
+ } else if (goog.global['console']['markTimeline']) {
+ // TODO(user): markTimeline is deprecated. Drop this else clause entirely
+ // after Chrome M14 hits stable.
+ goog.global['console']['markTimeline'](msg);
+ }
+ }
+
+ if (goog.global['msWriteProfilerMark']) {
+ // Logs a message to the Microsoft profiler
+ goog.global['msWriteProfilerMark'](msg);
+ }
+};
+
+
+/**
+ * Gets the name of this logger.
+ * @return {string} The name of this logger.
+ */
+goog.debug.Logger.prototype.getName = function() {
+ return this.name_;
+};
+
+
+/**
+ * Adds a handler to the logger. This doesn't use the event system because
+ * we want to be able to add logging to the event system.
+ * @param {Function} handler Handler function to add.
+ */
+goog.debug.Logger.prototype.addHandler = function(handler) {
+ if (goog.debug.LOGGING_ENABLED) {
+ if (goog.debug.Logger.ENABLE_HIERARCHY) {
+ if (!this.handlers_) {
+ this.handlers_ = [];
+ }
+ this.handlers_.push(handler);
+ } else {
+ goog.asserts.assert(!this.name_,
+ 'Cannot call addHandler on a non-root logger when ' +
+ 'goog.debug.Logger.ENABLE_HIERARCHY is false.');
+ goog.debug.Logger.rootHandlers_.push(handler);
+ }
+ }
+};
+
+
+/**
+ * Removes a handler from the logger. This doesn't use the event system because
+ * we want to be able to add logging to the event system.
+ * @param {Function} handler Handler function to remove.
+ * @return {boolean} Whether the handler was removed.
+ */
+goog.debug.Logger.prototype.removeHandler = function(handler) {
+ if (goog.debug.LOGGING_ENABLED) {
+ var handlers = goog.debug.Logger.ENABLE_HIERARCHY ? this.handlers_ :
+ goog.debug.Logger.rootHandlers_;
+ return !!handlers && goog.array.remove(handlers, handler);
+ } else {
+ return false;
+ }
+};
+
+
+/**
+ * Returns the parent of this logger.
+ * @return {goog.debug.Logger} The parent logger or null if this is the root.
+ */
+goog.debug.Logger.prototype.getParent = function() {
+ return this.parent_;
+};
+
+
+/**
+ * Returns the children of this logger as a map of the child name to the logger.
+ * @return {!Object} The map where the keys are the child leaf names and the
+ * values are the Logger objects.
+ */
+goog.debug.Logger.prototype.getChildren = function() {
+ if (!this.children_) {
+ this.children_ = {};
+ }
+ return this.children_;
+};
+
+
+/**
+ * Set the log level specifying which message levels will be logged by this
+ * logger. Message levels lower than this value will be discarded.
+ * The level value Level.OFF can be used to turn off logging. If the new level
+ * is null, it means that this node should inherit its level from its nearest
+ * ancestor with a specific (non-null) level value.
+ *
+ * @param {goog.debug.Logger.Level} level The new level.
+ */
+goog.debug.Logger.prototype.setLevel = function(level) {
+ if (goog.debug.LOGGING_ENABLED) {
+ if (goog.debug.Logger.ENABLE_HIERARCHY) {
+ this.level_ = level;
+ } else {
+ goog.asserts.assert(!this.name_,
+ 'Cannot call setLevel() on a non-root logger when ' +
+ 'goog.debug.Logger.ENABLE_HIERARCHY is false.');
+ goog.debug.Logger.rootLevel_ = level;
+ }
+ }
+};
+
+
+/**
+ * Gets the log level specifying which message levels will be logged by this
+ * logger. Message levels lower than this value will be discarded.
+ * The level value Level.OFF can be used to turn off logging. If the level
+ * is null, it means that this node should inherit its level from its nearest
+ * ancestor with a specific (non-null) level value.
+ *
+ * @return {goog.debug.Logger.Level} The level.
+ */
+goog.debug.Logger.prototype.getLevel = function() {
+ return goog.debug.LOGGING_ENABLED ?
+ this.level_ : goog.debug.Logger.Level.OFF;
+};
+
+
+/**
+ * Returns the effective level of the logger based on its ancestors' levels.
+ * @return {goog.debug.Logger.Level} The level.
+ */
+goog.debug.Logger.prototype.getEffectiveLevel = function() {
+ if (!goog.debug.LOGGING_ENABLED) {
+ return goog.debug.Logger.Level.OFF;
+ }
+
+ if (!goog.debug.Logger.ENABLE_HIERARCHY) {
+ return goog.debug.Logger.rootLevel_;
+ }
+ if (this.level_) {
+ return this.level_;
+ }
+ if (this.parent_) {
+ return this.parent_.getEffectiveLevel();
+ }
+ goog.asserts.fail('Root logger has no level set.');
+ return null;
+};
+
+
+/**
+ * Checks if a message of the given level would actually be logged by this
+ * logger. This check is based on the Loggers effective level, which may be
+ * inherited from its parent.
+ * @param {goog.debug.Logger.Level} level The level to check.
+ * @return {boolean} Whether the message would be logged.
+ */
+goog.debug.Logger.prototype.isLoggable = function(level) {
+ return goog.debug.LOGGING_ENABLED &&
+ level.value >= this.getEffectiveLevel().value;
+};
+
+
+/**
+ * Logs a message. If the logger is currently enabled for the
+ * given message level then the given message is forwarded to all the
+ * registered output Handler objects.
+ * @param {goog.debug.Logger.Level} level One of the level identifiers.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error|Object=} opt_exception An exception associated with the
+ * message.
+ */
+goog.debug.Logger.prototype.log = function(level, msg, opt_exception) {
+ // java caches the effective level, not sure it's necessary here
+ if (goog.debug.LOGGING_ENABLED && this.isLoggable(level)) {
+ // Message callbacks can be useful when a log message is expensive to build.
+ if (goog.isFunction(msg)) {
+ msg = msg();
+ }
+
+ this.doLogRecord_(this.getLogRecord(level, msg, opt_exception));
+ }
+};
+
+
+/**
+ * Creates a new log record and adds the exception (if present) to it.
+ * @param {goog.debug.Logger.Level} level One of the level identifiers.
+ * @param {string} msg The string message.
+ * @param {Error|Object=} opt_exception An exception associated with the
+ * message.
+ * @return {!goog.debug.LogRecord} A log record.
+ * @suppress {es5Strict}
+ */
+goog.debug.Logger.prototype.getLogRecord = function(
+ level, msg, opt_exception) {
+ if (goog.debug.LogBuffer.isBufferingEnabled()) {
+ var logRecord =
+ goog.debug.LogBuffer.getInstance().addRecord(level, msg, this.name_);
+ } else {
+ logRecord = new goog.debug.LogRecord(level, String(msg), this.name_);
+ }
+ if (opt_exception) {
+ logRecord.setException(opt_exception);
+ }
+ return logRecord;
+};
+
+
+/**
+ * Logs a message at the Logger.Level.SHOUT level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.shout = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a message at the Logger.Level.SEVERE level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.severe = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a message at the Logger.Level.WARNING level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.warning = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a message at the Logger.Level.INFO level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.info = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.INFO, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a message at the Logger.Level.CONFIG level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.config = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a message at the Logger.Level.FINE level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.fine = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.FINE, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a message at the Logger.Level.FINER level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.finer = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.FINER, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a message at the Logger.Level.FINEST level.
+ * If the logger is currently enabled for the given message level then the
+ * given message is forwarded to all the registered output Handler objects.
+ * @param {goog.debug.Loggable} msg The message to log.
+ * @param {Error=} opt_exception An exception associated with the message.
+ */
+goog.debug.Logger.prototype.finest = function(msg, opt_exception) {
+ if (goog.debug.LOGGING_ENABLED) {
+ this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception);
+ }
+};
+
+
+/**
+ * Logs a LogRecord. If the logger is currently enabled for the
+ * given message level then the given message is forwarded to all the
+ * registered output Handler objects.
+ * @param {goog.debug.LogRecord} logRecord A log record to log.
+ */
+goog.debug.Logger.prototype.logRecord = function(logRecord) {
+ if (goog.debug.LOGGING_ENABLED && this.isLoggable(logRecord.getLevel())) {
+ this.doLogRecord_(logRecord);
+ }
+};
+
+
+/**
+ * Logs a LogRecord.
+ * @param {goog.debug.LogRecord} logRecord A log record to log.
+ * @private
+ */
+goog.debug.Logger.prototype.doLogRecord_ = function(logRecord) {
+ goog.debug.Logger.logToProfilers('log:' + logRecord.getMessage());
+ if (goog.debug.Logger.ENABLE_HIERARCHY) {
+ var target = this;
+ while (target) {
+ target.callPublish_(logRecord);
+ target = target.getParent();
+ }
+ } else {
+ for (var i = 0, handler; handler = goog.debug.Logger.rootHandlers_[i++]; ) {
+ handler(logRecord);
+ }
+ }
+};
+
+
+/**
+ * Calls the handlers for publish.
+ * @param {goog.debug.LogRecord} logRecord The log record to publish.
+ * @private
+ */
+goog.debug.Logger.prototype.callPublish_ = function(logRecord) {
+ if (this.handlers_) {
+ for (var i = 0, handler; handler = this.handlers_[i]; i++) {
+ handler(logRecord);
+ }
+ }
+};
+
+
+/**
+ * Sets the parent of this logger. This is used for setting up the logger tree.
+ * @param {goog.debug.Logger} parent The parent logger.
+ * @private
+ */
+goog.debug.Logger.prototype.setParent_ = function(parent) {
+ this.parent_ = parent;
+};
+
+
+/**
+ * Adds a child to this logger. This is used for setting up the logger tree.
+ * @param {string} name The leaf name of the child.
+ * @param {goog.debug.Logger} logger The child logger.
+ * @private
+ */
+goog.debug.Logger.prototype.addChild_ = function(name, logger) {
+ this.getChildren()[name] = logger;
+};
+
+
+/**
+ * There is a single global LogManager object that is used to maintain a set of
+ * shared state about Loggers and log services. This is loosely based on the
+ * java class java.util.logging.LogManager.
+ * @const
+ */
+goog.debug.LogManager = {};
+
+
+/**
+ * Map of logger names to logger objects.
+ *
+ * @type {!Object<string, !goog.debug.Logger>}
+ * @private
+ */
+goog.debug.LogManager.loggers_ = {};
+
+
+/**
+ * The root logger which is the root of the logger tree.
+ * @type {goog.debug.Logger}
+ * @private
+ */
+goog.debug.LogManager.rootLogger_ = null;
+
+
+/**
+ * Initializes the LogManager if not already initialized.
+ */
+goog.debug.LogManager.initialize = function() {
+ if (!goog.debug.LogManager.rootLogger_) {
+ goog.debug.LogManager.rootLogger_ = new goog.debug.Logger(
+ goog.debug.Logger.ROOT_LOGGER_NAME);
+ goog.debug.LogManager.loggers_[goog.debug.Logger.ROOT_LOGGER_NAME] =
+ goog.debug.LogManager.rootLogger_;
+ goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG);
+ }
+};
+
+
+/**
+ * Returns all the loggers.
+ * @return {!Object<string, !goog.debug.Logger>} Map of logger names to logger
+ * objects.
+ */
+goog.debug.LogManager.getLoggers = function() {
+ return goog.debug.LogManager.loggers_;
+};
+
+
+/**
+ * Returns the root of the logger tree namespace, the logger with the empty
+ * string as its name.
+ *
+ * @return {!goog.debug.Logger} The root logger.
+ */
+goog.debug.LogManager.getRoot = function() {
+ goog.debug.LogManager.initialize();
+ return /** @type {!goog.debug.Logger} */ (goog.debug.LogManager.rootLogger_);
+};
+
+
+/**
+ * Finds a named logger.
+ *
+ * @param {string} name A name for the logger. This should be a dot-separated
+ * name and should normally be based on the package name or class name of the
+ * subsystem, such as goog.net.BrowserChannel.
+ * @return {!goog.debug.Logger} The named logger.
+ */
+goog.debug.LogManager.getLogger = function(name) {
+ goog.debug.LogManager.initialize();
+ var ret = goog.debug.LogManager.loggers_[name];
+ return ret || goog.debug.LogManager.createLogger_(name);
+};
+
+
+/**
+ * Creates a function that can be passed to goog.debug.catchErrors. The function
+ * will log all reported errors using the given logger.
+ * @param {goog.debug.Logger=} opt_logger The logger to log the errors to.
+ * Defaults to the root logger.
+ * @return {function(Object)} The created function.
+ */
+goog.debug.LogManager.createFunctionForCatchErrors = function(opt_logger) {
+ return function(info) {
+ var logger = opt_logger || goog.debug.LogManager.getRoot();
+ logger.severe('Error: ' + info.message + ' (' + info.fileName +
+ ' @ Line: ' + info.line + ')');
+ };
+};
+
+
+/**
+ * Creates the named logger. Will also create the parents of the named logger
+ * if they don't yet exist.
+ * @param {string} name The name of the logger.
+ * @return {!goog.debug.Logger} The named logger.
+ * @private
+ */
+goog.debug.LogManager.createLogger_ = function(name) {
+ // find parent logger
+ var logger = new goog.debug.Logger(name);
+ if (goog.debug.Logger.ENABLE_HIERARCHY) {
+ var lastDotIndex = name.lastIndexOf('.');
+ var parentName = name.substr(0, lastDotIndex);
+ var leafName = name.substr(lastDotIndex + 1);
+ var parentLogger = goog.debug.LogManager.getLogger(parentName);
+
+ // tell the parent about the child and the child about the parent
+ parentLogger.addChild_(leafName, logger);
+ logger.setParent_(parentLogger);
+ }
+
+ goog.debug.LogManager.loggers_[name] = logger;
+ return logger;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/logrecord.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/logrecord.js b/externs/GCL/externs/goog/debug/logrecord.js
new file mode 100644
index 0000000..df5f982
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/logrecord.js
@@ -0,0 +1,242 @@
+// 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 Definition of the LogRecord class. Please minimize
+ * dependencies this file has on other closure classes as any dependency it
+ * takes won't be able to use the logging infrastructure.
+ *
+ */
+
+goog.provide('goog.debug.LogRecord');
+
+
+
+/**
+ * LogRecord objects are used to pass logging requests between
+ * the logging framework and individual log Handlers.
+ * @constructor
+ * @param {goog.debug.Logger.Level} level One of the level identifiers.
+ * @param {string} msg The string message.
+ * @param {string} loggerName The name of the source logger.
+ * @param {number=} opt_time Time this log record was created if other than now.
+ * If 0, we use #goog.now.
+ * @param {number=} opt_sequenceNumber Sequence number of this log record. This
+ * should only be passed in when restoring a log record from persistence.
+ */
+goog.debug.LogRecord = function(level, msg, loggerName,
+ opt_time, opt_sequenceNumber) {
+ this.reset(level, msg, loggerName, opt_time, opt_sequenceNumber);
+};
+
+
+/**
+ * Time the LogRecord was created.
+ * @type {number}
+ * @private
+ */
+goog.debug.LogRecord.prototype.time_;
+
+
+/**
+ * Level of the LogRecord
+ * @type {goog.debug.Logger.Level}
+ * @private
+ */
+goog.debug.LogRecord.prototype.level_;
+
+
+/**
+ * Message associated with the record
+ * @type {string}
+ * @private
+ */
+goog.debug.LogRecord.prototype.msg_;
+
+
+/**
+ * Name of the logger that created the record.
+ * @type {string}
+ * @private
+ */
+goog.debug.LogRecord.prototype.loggerName_;
+
+
+/**
+ * Sequence number for the LogRecord. Each record has a unique sequence number
+ * that is greater than all log records created before it.
+ * @type {number}
+ * @private
+ */
+goog.debug.LogRecord.prototype.sequenceNumber_ = 0;
+
+
+/**
+ * Exception associated with the record
+ * @type {Object}
+ * @private
+ */
+goog.debug.LogRecord.prototype.exception_ = null;
+
+
+/**
+ * @define {boolean} Whether to enable log sequence numbers.
+ */
+goog.define('goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS', true);
+
+
+/**
+ * A sequence counter for assigning increasing sequence numbers to LogRecord
+ * objects.
+ * @type {number}
+ * @private
+ */
+goog.debug.LogRecord.nextSequenceNumber_ = 0;
+
+
+/**
+ * Sets all fields of the log record.
+ * @param {goog.debug.Logger.Level} level One of the level identifiers.
+ * @param {string} msg The string message.
+ * @param {string} loggerName The name of the source logger.
+ * @param {number=} opt_time Time this log record was created if other than now.
+ * If 0, we use #goog.now.
+ * @param {number=} opt_sequenceNumber Sequence number of this log record. This
+ * should only be passed in when restoring a log record from persistence.
+ */
+goog.debug.LogRecord.prototype.reset = function(level, msg, loggerName,
+ opt_time, opt_sequenceNumber) {
+ if (goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS) {
+ this.sequenceNumber_ = typeof opt_sequenceNumber == 'number' ?
+ opt_sequenceNumber : goog.debug.LogRecord.nextSequenceNumber_++;
+ }
+
+ this.time_ = opt_time || goog.now();
+ this.level_ = level;
+ this.msg_ = msg;
+ this.loggerName_ = loggerName;
+ delete this.exception_;
+};
+
+
+/**
+ * Get the source Logger's name.
+ *
+ * @return {string} source logger name (may be null).
+ */
+goog.debug.LogRecord.prototype.getLoggerName = function() {
+ return this.loggerName_;
+};
+
+
+/**
+ * Get the exception that is part of the log record.
+ *
+ * @return {Object} the exception.
+ */
+goog.debug.LogRecord.prototype.getException = function() {
+ return this.exception_;
+};
+
+
+/**
+ * Set the exception that is part of the log record.
+ *
+ * @param {Object} exception the exception.
+ */
+goog.debug.LogRecord.prototype.setException = function(exception) {
+ this.exception_ = exception;
+};
+
+
+/**
+ * Get the source Logger's name.
+ *
+ * @param {string} loggerName source logger name (may be null).
+ */
+goog.debug.LogRecord.prototype.setLoggerName = function(loggerName) {
+ this.loggerName_ = loggerName;
+};
+
+
+/**
+ * Get the logging message level, for example Level.SEVERE.
+ * @return {goog.debug.Logger.Level} the logging message level.
+ */
+goog.debug.LogRecord.prototype.getLevel = function() {
+ return this.level_;
+};
+
+
+/**
+ * Set the logging message level, for example Level.SEVERE.
+ * @param {goog.debug.Logger.Level} level the logging message level.
+ */
+goog.debug.LogRecord.prototype.setLevel = function(level) {
+ this.level_ = level;
+};
+
+
+/**
+ * Get the "raw" log message, before localization or formatting.
+ *
+ * @return {string} the raw message string.
+ */
+goog.debug.LogRecord.prototype.getMessage = function() {
+ return this.msg_;
+};
+
+
+/**
+ * Set the "raw" log message, before localization or formatting.
+ *
+ * @param {string} msg the raw message string.
+ */
+goog.debug.LogRecord.prototype.setMessage = function(msg) {
+ this.msg_ = msg;
+};
+
+
+/**
+ * Get event time in milliseconds since 1970.
+ *
+ * @return {number} event time in millis since 1970.
+ */
+goog.debug.LogRecord.prototype.getMillis = function() {
+ return this.time_;
+};
+
+
+/**
+ * Set event time in milliseconds since 1970.
+ *
+ * @param {number} time event time in millis since 1970.
+ */
+goog.debug.LogRecord.prototype.setMillis = function(time) {
+ this.time_ = time;
+};
+
+
+/**
+ * Get the sequence number.
+ * <p>
+ * Sequence numbers are normally assigned in the LogRecord
+ * constructor, which assigns unique sequence numbers to
+ * each new LogRecord in increasing order.
+ * @return {number} the sequence number.
+ */
+goog.debug.LogRecord.prototype.getSequenceNumber = function() {
+ return this.sequenceNumber_;
+};
+
[41/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/fastdatanode.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/fastdatanode.js b/externs/GCL/externs/goog/datasource/fastdatanode.js
new file mode 100644
index 0000000..c14750f
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/fastdatanode.js
@@ -0,0 +1,814 @@
+// 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
+ * Efficient implementation of DataNode API.
+ *
+ * The implementation consists of three concrete classes for modelling
+ * DataNodes with different characteristics: FastDataNode,
+ * FastPrimitiveDataNode and FastListNode.
+ *
+ * FastDataNode is for bean-like or map-like objects that consists of
+ * key/value mappings and where the primary access pattern is by key.
+ *
+ * FastPrimitiveDataNode wraps primitives like strings, boolean, and numbers.
+ *
+ * FastListNode is for array-like data nodes. It also supports key-based
+ * lookups if the data nodes have an "id" property or if child nodes are
+ * explicitly added by name. It is most efficient if these features are not
+ * used.
+ *
+ * FastDataNodes can be constructed from JSON-like objects via the function
+ * goog.ds.FastDataNode.fromJs.
+
+ */
+
+goog.provide('goog.ds.AbstractFastDataNode');
+goog.provide('goog.ds.FastDataNode');
+goog.provide('goog.ds.FastListNode');
+goog.provide('goog.ds.PrimitiveFastDataNode');
+
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.DataNodeList');
+goog.require('goog.ds.EmptyNodeList');
+goog.require('goog.string');
+
+/*
+ * Implementation note: In order to reduce the number of objects,
+ * FastDataNode stores its key/value mappings directly in the FastDataNode
+ * object iself (instead of a separate map). To make this work we have to
+ * sure that there are no name clashes with other attribute names used by
+ * FastDataNode (like dataName and parent). This is especially difficult in
+ * the light of automatic renaming by the JavaScript compiler. For this reason,
+ * all internal attributes start with "__" so that they are not renamed
+ * by the compiler.
+ */
+
+/**
+ * Creates a new abstract data node.
+ * @param {string} dataName Name of the datanode.
+ * @param {goog.ds.DataNode=} opt_parent Parent of this data node.
+ * @constructor
+ * @extends {goog.ds.DataNodeList}
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.AbstractFastDataNode = function(dataName, opt_parent) {
+ if (!dataName) {
+ throw Error('Cannot create a fast data node without a data name');
+ }
+ this['__dataName'] = dataName;
+ this['__parent'] = opt_parent;
+};
+
+
+/**
+ * Return the name of this data node.
+ * @return {string} Name of this data noden.
+ * @override
+ */
+goog.ds.AbstractFastDataNode.prototype.getDataName = function() {
+ return this['__dataName'];
+};
+
+
+/**
+ * Set the name of this data node.
+ * @param {string} value Name.
+ * @override
+ */
+goog.ds.AbstractFastDataNode.prototype.setDataName = function(value) {
+ this['__dataName'] = value;
+};
+
+
+/**
+ * Get the path leading to this data node.
+ * @return {string} Data path.
+ * @override
+ */
+goog.ds.AbstractFastDataNode.prototype.getDataPath = function() {
+ var parentPath;
+ if (this['__parent']) {
+ parentPath = this['__parent'].getDataPath() + goog.ds.STR_PATH_SEPARATOR;
+ } else {
+ parentPath = '';
+ }
+ return parentPath + this.getDataName();
+};
+
+
+
+/**
+ * Creates a new fast data node, using the properties of root.
+ * @param {Object} root JSON-like object to initialize data node from.
+ * @param {string} dataName Name of this data node.
+ * @param {goog.ds.DataNode=} opt_parent Parent of this data node.
+ * @extends {goog.ds.AbstractFastDataNode}
+ * @constructor
+ */
+goog.ds.FastDataNode = function(root, dataName, opt_parent) {
+ goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
+ this.extendWith(root);
+};
+goog.inherits(goog.ds.FastDataNode, goog.ds.AbstractFastDataNode);
+
+
+/**
+ * Add all attributes of object to this data node.
+ * @param {Object} object Object to add attributes from.
+ * @protected
+ */
+goog.ds.FastDataNode.prototype.extendWith = function(object) {
+ for (var key in object) {
+ this[key] = object[key];
+ }
+};
+
+
+/**
+ * Creates a new FastDataNode structure initialized from object. This will
+ * return an instance of the most suitable sub-class of FastDataNode.
+ *
+ * You should not modify object after creating a fast data node from it
+ * or assume that changing object changes the data node. Doing so results
+ * in undefined behaviour.
+ *
+ * @param {Object|number|boolean|string} object Object to initialize data
+ * node from.
+ * @param {string} dataName Name of data node.
+ * @param {goog.ds.DataNode=} opt_parent Parent of data node.
+ * @return {!goog.ds.AbstractFastDataNode} Data node representing object.
+ */
+goog.ds.FastDataNode.fromJs = function(object, dataName, opt_parent) {
+ if (goog.isArray(object)) {
+ return new goog.ds.FastListNode(object, dataName, opt_parent);
+ } else if (goog.isObject(object)) {
+ return new goog.ds.FastDataNode(object, dataName, opt_parent);
+ } else {
+ return new goog.ds.PrimitiveFastDataNode(object || !!object,
+ dataName,
+ opt_parent);
+ }
+};
+
+
+/**
+ * Static instance of an empty list.
+ * @type {!goog.ds.EmptyNodeList}
+ * @private
+ */
+goog.ds.FastDataNode.emptyList_ = new goog.ds.EmptyNodeList();
+
+
+/**
+ * Not supported for normal FastDataNodes.
+ * @param {*} value Value to set data node to.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.set = function(value) {
+ throw new Error('Not implemented yet');
+};
+
+
+/** @override */
+goog.ds.FastDataNode.prototype.getChildNodes = function(opt_selector) {
+ if (!opt_selector || opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
+ return this;
+ } else if (opt_selector.indexOf(goog.ds.STR_WILDCARD) == -1) {
+ var child = this.getChildNode(opt_selector);
+ return child ? new goog.ds.FastListNode([child], '') :
+ new goog.ds.EmptyNodeList();
+ } else {
+ throw Error('Unsupported selector: ' + opt_selector);
+ }
+};
+
+
+/**
+ * Makes sure that a named child is wrapped in a data node structure.
+ * @param {string} name Name of child to wrap.
+ * @private
+ */
+goog.ds.FastDataNode.prototype.wrapChild_ = function(name) {
+ var child = this[name];
+ if (child != null && !child.getDataName) {
+ this[name] = goog.ds.FastDataNode.fromJs(this[name], name, this);
+ }
+};
+
+
+/**
+ * Get a child node by name.
+ * @param {string} name Name of child node.
+ * @param {boolean=} opt_create Whether to create the child if it does not
+ * exist.
+ * @return {goog.ds.DataNode} Child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getChildNode = function(name, opt_create) {
+ this.wrapChild_(name);
+ // this[name] always is a data node object, so using "||" is fine.
+ var child = this[name] || null;
+ if (child == null && opt_create) {
+ child = new goog.ds.FastDataNode({}, name, this);
+ this[name] = child;
+ }
+ return child;
+};
+
+
+/**
+ * Sets a child node. Creates the child if it does not exist.
+ *
+ * Calling this function makes any child nodes previously obtained for name
+ * invalid. You should not use these child nodes but instead obtain a new
+ * instance by calling getChildNode.
+ *
+ * @override
+ */
+goog.ds.FastDataNode.prototype.setChildNode = function(name, value) {
+ if (value != null) {
+ this[name] = value;
+ } else {
+ delete this[name];
+ }
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath() +
+ goog.ds.STR_PATH_SEPARATOR + name);
+ return null;
+};
+
+
+/**
+ * Returns the value of a child node. By using this method you can avoid
+ * the need to create PrimitiveFastData nodes.
+ * @param {string} name Name of child node.
+ * @return {Object} Value of child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getChildNodeValue = function(name) {
+ var child = this[name];
+ if (child != null) {
+ return (child.getDataName ? child.get() : child);
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Returns whether this data node is a list. Always returns false for
+ * instances of FastDataNode but may return true for subclasses.
+ * @return {boolean} Whether this data node is array-like.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.isList = function() {
+ return false;
+};
+
+
+/**
+ * Returns a javascript object representation of this data node. You should
+ * not modify the object returned by this function.
+ * @return {!Object} Javascript object representation of this data node.
+ */
+goog.ds.FastDataNode.prototype.getJsObject = function() {
+ var result = {};
+ for (var key in this) {
+ if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
+ result[key] = (this[key]['__dataName'] ? this[key].getJsObject() :
+ this[key]);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Creates a deep copy of this data node.
+ * @return {goog.ds.FastDataNode} Clone of this data node.
+ */
+goog.ds.FastDataNode.prototype.clone = function() {
+ return /** @type {!goog.ds.FastDataNode} */(goog.ds.FastDataNode.fromJs(
+ this.getJsObject(), this.getDataName()));
+};
+
+
+/*
+ * Implementation of goog.ds.DataNodeList for FastDataNode.
+ */
+
+
+/**
+ * Adds a child to this data node.
+ * @param {goog.ds.DataNode} value Child node to add.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.add = function(value) {
+ this.setChildNode(value.getDataName(), value);
+};
+
+
+/**
+ * Gets the value of this data node (if called without opt_key) or
+ * gets a child node (if called with opt_key).
+ * @param {string=} opt_key Name of child node.
+ * @return {*} This data node or a child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.get = function(opt_key) {
+ if (!goog.isDef(opt_key)) {
+ // if there is no key, DataNode#get was called
+ return this;
+ } else {
+ return this.getChildNode(opt_key);
+ }
+};
+
+
+/**
+ * Gets a child node by index. This method has a complexity of O(n) where
+ * n is the number of children. If you need a faster implementation of this
+ * method, you should use goog.ds.FastListNode.
+ * @param {number} index Index of child node (starting from 0).
+ * @return {goog.ds.DataNode} Child node at specified index.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getByIndex = function(index) {
+ var i = 0;
+ for (var key in this) {
+ if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
+ if (i == index) {
+ this.wrapChild_(key);
+ return this[key];
+ }
+ ++i;
+ }
+ }
+ return null;
+};
+
+
+/**
+ * Gets the number of child nodes. This method has a complexity of O(n) where
+ * n is the number of children. If you need a faster implementation of this
+ * method, you should use goog.ds.FastListNode.
+ * @return {number} Number of child nodes.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.getCount = function() {
+ var count = 0;
+ for (var key in this) {
+ if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
+ ++count;
+ }
+ }
+ // maybe cache this?
+ return count;
+};
+
+
+/**
+ * Sets a child node.
+ * @param {string} name Name of child node.
+ * @param {Object} value Value of child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.setNode = function(name, value) {
+ this.setChildNode(name, value);
+};
+
+
+/**
+ * Removes a child node.
+ * @override
+ */
+goog.ds.FastDataNode.prototype.removeNode = function(name) {
+ delete this[name];
+ return false;
+};
+
+
+
+/**
+ * Creates a new data node wrapping a primitive value.
+ * @param {number|boolean|string} value Value the value to wrap.
+ * @param {string} dataName name Name of this data node.
+ * @param {goog.ds.DataNode=} opt_parent Parent of this data node.
+ * @extends {goog.ds.AbstractFastDataNode}
+ * @constructor
+ * @final
+ */
+goog.ds.PrimitiveFastDataNode = function(value, dataName, opt_parent) {
+ this.value_ = value;
+ goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
+};
+goog.inherits(goog.ds.PrimitiveFastDataNode, goog.ds.AbstractFastDataNode);
+
+
+/**
+ * Returns the value of this data node.
+ * @return {(boolean|number|string)} Value of this data node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.get = function() {
+ return this.value_;
+};
+
+
+/**
+ * Sets this data node to a new value.
+ * @param {*} value Value to set data node to.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.set = function(value) {
+ if (goog.isArray(value) || goog.isObject(value)) {
+ throw Error('can only set PrimitiveFastDataNode to primitive values');
+ }
+ this.value_ = value;
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
+};
+
+
+/**
+ * Returns child nodes of this data node. Always returns an unmodifiable,
+ * empty list.
+ * @return {!goog.ds.DataNodeList} (Empty) list of child nodes.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getChildNodes = function() {
+ return goog.ds.FastDataNode.emptyList_;
+};
+
+
+/**
+ * Get a child node by name. Always returns null.
+ * @param {string} name Name of child node.
+ * @return {goog.ds.DataNode} Child node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getChildNode = function(name) {
+ return null;
+};
+
+
+/**
+ * Returns the value of a child node. Always returns null.
+ * @param {string} name Name of child node.
+ * @return {Object} Value of child node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getChildNodeValue = function(name) {
+ return null;
+};
+
+
+/**
+ * Not supported by primitive data nodes.
+ * @param {string} name Name of child node.
+ * @param {Object} value Value of child node.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.setChildNode =
+ function(name, value) {
+ throw Error('Cannot set a child node for a PrimitiveFastDataNode');
+};
+
+
+/**
+ * Returns whether this data node is a list. Always returns false for
+ * instances of PrimitiveFastDataNode.
+ * @return {boolean} Whether this data node is array-like.
+ * @override
+ */
+goog.ds.PrimitiveFastDataNode.prototype.isList = function() {
+ return false;
+};
+
+
+/**
+ * Returns a javascript object representation of this data node. You should
+ * not modify the object returned by this function.
+ * @return {*} Javascript object representation of this data node.
+ */
+goog.ds.PrimitiveFastDataNode.prototype.getJsObject = function() {
+ return this.value_;
+};
+
+
+/**
+ * Creates a new list node from an array.
+ * @param {Array<?>} values values hold by this list node.
+ * @param {string} dataName name of this node.
+ * @param {goog.ds.DataNode=} opt_parent parent of this node.
+ * @extends {goog.ds.AbstractFastDataNode}
+ * @constructor
+ * @final
+ */
+// TODO(arv): Use interfaces when available. This implements DataNodeList
+// as well.
+goog.ds.FastListNode = function(values, dataName, opt_parent) {
+ this.values_ = [];
+ for (var i = 0; i < values.length; ++i) {
+ var name = values[i].id || ('[' + i + ']');
+ this.values_.push(goog.ds.FastDataNode.fromJs(values[i], name, this));
+ if (values[i].id) {
+ if (!this.map_) {
+ this.map_ = {};
+ }
+ this.map_[values[i].id] = i;
+ }
+ }
+ goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
+};
+goog.inherits(goog.ds.FastListNode, goog.ds.AbstractFastDataNode);
+
+
+/**
+ * Not supported for FastListNodes.
+ * @param {*} value Value to set data node to.
+ * @override
+ */
+goog.ds.FastListNode.prototype.set = function(value) {
+ throw Error('Cannot set a FastListNode to a new value');
+};
+
+
+/**
+ * Returns child nodes of this data node. Currently, only supports
+ * returning all children.
+ * @return {!goog.ds.DataNodeList} List of child nodes.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getChildNodes = function() {
+ return this;
+};
+
+
+/**
+ * Get a child node by name.
+ * @param {string} key Name of child node.
+ * @param {boolean=} opt_create Whether to create the child if it does not
+ * exist.
+ * @return {goog.ds.DataNode} Child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getChildNode = function(key, opt_create) {
+ var index = this.getKeyAsNumber_(key);
+ if (index == null && this.map_) {
+ index = this.map_[key];
+ }
+ if (index != null && this.values_[index]) {
+ return this.values_[index];
+ } else if (opt_create) {
+ this.setChildNode(key, {});
+ return this.getChildNode(key);
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Returns the value of a child node.
+ * @param {string} key Name of child node.
+ * @return {*} Value of child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getChildNodeValue = function(key) {
+ var child = this.getChildNode(key);
+ return (child ? child.get() : null);
+};
+
+
+/**
+ * Tries to interpret key as a numeric index enclosed by square brakcets.
+ * @param {string} key Key that should be interpreted as a number.
+ * @return {?number} Numeric index or null if key is not of the form
+ * described above.
+ * @private
+ */
+goog.ds.FastListNode.prototype.getKeyAsNumber_ = function(key) {
+ if (key.charAt(0) == '[' && key.charAt(key.length - 1) == ']') {
+ return Number(key.substring(1, key.length - 1));
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Sets a child node. Creates the child if it does not exist. To set
+ * children at a certain index, use a key of the form '[index]'. Note, that
+ * you can only set values at existing numeric indices. To add a new node
+ * to this list, you have to use the add method.
+ *
+ * Calling this function makes any child nodes previously obtained for name
+ * invalid. You should not use these child nodes but instead obtain a new
+ * instance by calling getChildNode.
+ *
+ * @override
+ */
+goog.ds.FastListNode.prototype.setChildNode = function(key, value) {
+ var count = this.values_.length;
+ if (value != null) {
+ if (!value.getDataName) {
+ value = goog.ds.FastDataNode.fromJs(value, key, this);
+ }
+ var index = this.getKeyAsNumber_(key);
+ if (index != null) {
+ if (index < 0 || index >= this.values_.length) {
+ throw Error('List index out of bounds: ' + index);
+ }
+ this.values_[key] = value;
+ } else {
+ if (!this.map_) {
+ this.map_ = {};
+ }
+ this.values_.push(value);
+ this.map_[key] = this.values_.length - 1;
+ }
+ } else {
+ this.removeNode(key);
+ }
+ var dm = goog.ds.DataManager.getInstance();
+ dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + key);
+ if (this.values_.length != count) {
+ this.listSizeChanged_();
+ }
+ return null;
+};
+
+
+/**
+ * Fire data changes that are appropriate when the size of this list changes.
+ * Should be called whenever the list size has changed.
+ * @private
+ */
+goog.ds.FastListNode.prototype.listSizeChanged_ = function() {
+ var dm = goog.ds.DataManager.getInstance();
+ dm.fireDataChange(this.getDataPath());
+ dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
+ 'count()');
+};
+
+
+/**
+ * Returns whether this data node is a list. Always returns true.
+ * @return {boolean} Whether this data node is array-like.
+ * @override
+ */
+goog.ds.FastListNode.prototype.isList = function() {
+ return true;
+};
+
+
+/**
+ * Returns a javascript object representation of this data node. You should
+ * not modify the object returned by this function.
+ * @return {!Object} Javascript object representation of this data node.
+ */
+goog.ds.FastListNode.prototype.getJsObject = function() {
+ var result = [];
+ for (var i = 0; i < this.values_.length; ++i) {
+ result.push(this.values_[i].getJsObject());
+ }
+ return result;
+};
+
+
+/*
+ * Implementation of goog.ds.DataNodeList for FastListNode.
+ */
+
+
+/**
+ * Adds a child to this data node
+ * @param {goog.ds.DataNode} value Child node to add.
+ * @override
+ */
+goog.ds.FastListNode.prototype.add = function(value) {
+ if (!value.getDataName) {
+ value = goog.ds.FastDataNode.fromJs(value,
+ String('[' + (this.values_.length) + ']'), this);
+ }
+ this.values_.push(value);
+ var dm = goog.ds.DataManager.getInstance();
+ dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
+ '[' + (this.values_.length - 1) + ']');
+ this.listSizeChanged_();
+};
+
+
+/**
+ * Gets the value of this data node (if called without opt_key) or
+ * gets a child node (if called with opt_key).
+ * @param {string=} opt_key Name of child node.
+ * @return {Array|goog.ds.DataNode} Array of child nodes (if called without
+ * opt_key), or a named child node otherwise.
+ * @override
+ */
+goog.ds.FastListNode.prototype.get = function(opt_key) {
+ // if there are no arguments, DataNode.get was called
+ if (!goog.isDef(opt_key)) {
+ return this.values_;
+ } else {
+ return this.getChildNode(opt_key);
+ }
+};
+
+
+/**
+ * Gets a child node by (numeric) index.
+ * @param {number} index Index of child node (starting from 0).
+ * @return {goog.ds.DataNode} Child node at specified index.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getByIndex = function(index) {
+ var child = this.values_[index];
+ return (child != null ? child : null); // never return undefined
+};
+
+
+/**
+ * Gets the number of child nodes.
+ * @return {number} Number of child nodes.
+ * @override
+ */
+goog.ds.FastListNode.prototype.getCount = function() {
+ return this.values_.length;
+};
+
+
+/**
+ * Sets a child node.
+ * @param {string} name Name of child node.
+ * @param {Object} value Value of child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.setNode = function(name, value) {
+ throw Error('Setting child nodes of a FastListNode is not implemented, yet');
+};
+
+
+/**
+ * Removes a child node.
+ * @override
+ */
+goog.ds.FastListNode.prototype.removeNode = function(name) {
+ var index = this.getKeyAsNumber_(name);
+ if (index == null && this.map_) {
+ index = this.map_[name];
+ }
+ if (index != null) {
+ this.values_.splice(index, 1);
+ if (this.map_) {
+ var keyToDelete = null;
+ for (var key in this.map_) {
+ if (this.map_[key] == index) {
+ keyToDelete = key;
+ } else if (this.map_[key] > index) {
+ --this.map_[key];
+ }
+ }
+ if (keyToDelete) {
+ delete this.map_[keyToDelete];
+ }
+ }
+ var dm = goog.ds.DataManager.getInstance();
+ dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR +
+ '[' + index + ']');
+ this.listSizeChanged_();
+ }
+ return false;
+};
+
+
+/**
+ * Returns the index of a named child nodes. This method only works if
+ * this list uses mixed name/indexed lookup, i.e. if its child node have
+ * an 'id' attribute.
+ * @param {string} name Name of child node to determine index of.
+ * @return {number} Index of child node named name.
+ */
+goog.ds.FastListNode.prototype.indexOf = function(name) {
+ var index = this.getKeyAsNumber_(name);
+ if (index == null && this.map_) {
+ index = this.map_[name];
+ }
+ if (index == null) {
+ throw Error('Cannot determine index for: ' + name);
+ }
+ return /** @type {number} */(index);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/jsdatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/jsdatasource.js b/externs/GCL/externs/goog/datasource/jsdatasource.js
new file mode 100644
index 0000000..ccd469e
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/jsdatasource.js
@@ -0,0 +1,462 @@
+// 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 An implementation of DataNode for wrapping JS data.
+ *
+ */
+
+
+goog.provide('goog.ds.JsDataSource');
+goog.provide('goog.ds.JsPropertyDataSource');
+
+goog.require('goog.ds.BaseDataNode');
+goog.require('goog.ds.BasicNodeList');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.DataNode');
+goog.require('goog.ds.EmptyNodeList');
+goog.require('goog.ds.LoadState');
+
+
+/**
+ * Data source whose backing is JavaScript data
+ *
+ * Names that are reserved for system use and shouldn't be used for data node
+ * names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
+ * undefined if these names are used.
+ *
+ * @param {Object} root The root JS node.
+ * @param {string} dataName The name of this node relative to the parent node.
+ * @param {Object=} opt_parent Optional parent of this JsDataSource.
+ *
+ * implements goog.ds.DataNode.
+ * @constructor
+ * @extends {goog.ds.DataNode}
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.JsDataSource = function(root, dataName, opt_parent) {
+ this.parent_ = opt_parent;
+ this.dataName_ = dataName;
+ this.setRoot(root);
+};
+
+
+/**
+ * The root JS object. Can be null.
+ * @type {*}
+ * @protected
+ * @suppress {underscore|visibility}
+ */
+goog.ds.JsDataSource.prototype.root_;
+
+
+/**
+ * Sets the root JS object
+ * @param {Object} root The root JS object. Can be null.
+ *
+ * @protected
+ */
+goog.ds.JsDataSource.prototype.setRoot = function(root) {
+ this.root_ = root;
+ this.childNodeList_ = null;
+};
+
+
+/**
+ * Set this data source to use list semantics. List data sources:
+ * - Are assumed to have child nodes of all of the same type of data
+ * - Fire data changes on the root node of the list whenever children
+ * are added or removed
+ * @param {?boolean} isList True to use list semantics.
+ * @private
+ */
+goog.ds.JsDataSource.prototype.setIsList_ = function(isList) {
+ this.isList_ = isList;
+};
+
+
+/** @override */
+goog.ds.JsDataSource.prototype.get = function() {
+ return !goog.isObject(this.root_) ? this.root_ : this.getChildNodes();
+};
+
+
+/**
+ * Set the value of the node
+ * @param {*} value The new value of the node.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.set = function(value) {
+ if (value && goog.isObject(this.root_)) {
+ throw Error('Can\'t set group nodes to new values yet');
+ }
+
+ if (this.parent_) {
+ this.parent_.root_[this.dataName_] = value;
+ }
+ this.root_ = value;
+ this.childNodeList_ = null;
+
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
+};
+
+
+/**
+ * TODO(user) revisit lazy creation.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getChildNodes = function(opt_selector) {
+ if (!this.root_) {
+ return new goog.ds.EmptyNodeList();
+ }
+
+ if (!opt_selector || opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
+ this.createChildNodes_(false);
+ return this.childNodeList_;
+ } else if (opt_selector.indexOf(goog.ds.STR_WILDCARD) == -1) {
+ if (this.root_[opt_selector] != null) {
+ return new goog.ds.BasicNodeList([this.getChildNode(opt_selector)]);
+ } else {
+ return new goog.ds.EmptyNodeList();
+ }
+ } else {
+ throw Error('Selector not supported yet (' + opt_selector + ')');
+ }
+
+};
+
+
+/**
+ * Creates the DataNodeList with the child nodes for this element.
+ * Allows for only building list as needed.
+ *
+ * @param {boolean=} opt_force Whether to force recreating child nodes,
+ * defaults to false.
+ * @private
+ */
+goog.ds.JsDataSource.prototype.createChildNodes_ = function(opt_force) {
+ if (this.childNodeList_ && !opt_force) {
+ return;
+ }
+
+ if (!goog.isObject(this.root_)) {
+ this.childNodeList_ = new goog.ds.EmptyNodeList();
+ return;
+ }
+
+ var childNodeList = new goog.ds.BasicNodeList();
+ var newNode;
+ if (goog.isArray(this.root_)) {
+ var len = this.root_.length;
+ for (var i = 0; i < len; i++) {
+ // "id" is reserved node name that will map to a named child node
+ // TODO(user) Configurable logic for choosing id node
+ var node = this.root_[i];
+ var id = node.id;
+ var name = id != null ? String(id) : '[' + i + ']';
+ newNode = new goog.ds.JsDataSource(node, name, this);
+ childNodeList.add(newNode);
+ }
+ } else {
+ for (var name in this.root_) {
+ var obj = this.root_[name];
+ // If the node is already a datasource, then add it.
+ if (obj.getDataName) {
+ childNodeList.add(obj);
+ } else if (!goog.isFunction(obj)) {
+ newNode = new goog.ds.JsDataSource(obj, name, this);
+ childNodeList.add(newNode);
+ }
+ }
+ }
+ this.childNodeList_ = childNodeList;
+};
+
+
+/**
+ * Gets a named child node of the current node
+ * @param {string} name The node name.
+ * @param {boolean=} opt_canCreate If true, can create child node.
+ * @return {goog.ds.DataNode} The child node, or null if no node of
+ * this name exists.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getChildNode = function(name, opt_canCreate) {
+ if (!this.root_) {
+ return null;
+ }
+ var node = /** @type {goog.ds.DataNode} */ (this.getChildNodes().get(name));
+ if (!node && opt_canCreate) {
+ var newObj = {};
+ if (goog.isArray(this.root_)) {
+ newObj['id'] = name;
+ this.root_.push(newObj);
+ } else {
+ this.root_[name] = newObj;
+ }
+ node = new goog.ds.JsDataSource(newObj, name, this);
+ if (this.childNodeList_) {
+ this.childNodeList_.add(node);
+ }
+ }
+ return node;
+};
+
+
+/**
+ * Gets the value of a child node
+ * @param {string} name The node name.
+ * @return {Object} The value of the node, or null if no value or the child
+ * node doesn't exist.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getChildNodeValue = function(name) {
+ if (this.childNodeList_) {
+ var node = this.getChildNodes().get(name);
+ return node ? node.get() : null;
+ } else if (this.root_) {
+ return this.root_[name];
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Sets a named child node of the current node.
+ * If value is null, removes the child node.
+ * @param {string} name The node name.
+ * @param {Object} value The value to set, can be DataNode, object,
+ * property, or null.
+ * @return {Object} The child node, if set.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.setChildNode = function(name, value) {
+ var removedPath = null;
+ var node = null;
+ var addedNode = false;
+
+ // Set node to the DataNode to add - if the value isn't already a DataNode,
+ // creates a JsDataSource or JsPropertyDataSource wrapper
+ if (value != null) {
+ if (value.getDataName) {
+ // The value is a DataNode. We must update its parent.
+ node = value;
+ node.parent_ = this;
+ } else {
+ if (goog.isArray(value) || goog.isObject(value)) {
+ node = new goog.ds.JsDataSource(value, name, this);
+ } else {
+ node = new goog.ds.JsPropertyDataSource(
+ /** @type {goog.ds.DataNode} */ (this.root_), name, this);
+ }
+ }
+ }
+
+ // This logic will get cleaner once we can remove the backing array / object
+ // and just rely on the childNodeList_. This is needed until dependent code
+ // is cleaned up.
+ // TODO(user) Remove backing array / object and just use childNodeList_
+
+ if (goog.isArray(this.root_)) {
+ // To remove by name, need to create a map of the child nodes by ID
+ this.createChildNodes_();
+ var index = this.childNodeList_.indexOf(name);
+ if (value == null) {
+ // Remove the node
+ var nodeToRemove = this.childNodeList_.get(name);
+ if (nodeToRemove) {
+ removedPath = nodeToRemove.getDataPath();
+ }
+ this.root_.splice(index, 1);
+ } else {
+ // Add the node
+ if (index) {
+ this.root_[index] = value;
+ } else {
+ this.root_.push(value);
+ }
+ }
+ if (index == null) {
+ addedNode = true;
+ }
+ this.childNodeList_.setNode(name, /** @type {goog.ds.DataNode} */ (node));
+ } else if (goog.isObject(this.root_)) {
+ if (value == null) {
+ // Remove the node
+ this.createChildNodes_();
+ var nodeToRemove = this.childNodeList_.get(name);
+ if (nodeToRemove) {
+ removedPath = nodeToRemove.getDataPath();
+ }
+ delete this.root_[name];
+ } else {
+ // Add the node
+ if (!this.root_[name]) {
+ addedNode = true;
+ }
+ this.root_[name] = value;
+ }
+ // Only need to update childNodeList_ if has been created already
+ if (this.childNodeList_) {
+ this.childNodeList_.setNode(name, /** @type {goog.ds.DataNode} */ (node));
+ }
+ }
+
+ // Fire the event that the node changed
+ var dm = goog.ds.DataManager.getInstance();
+ if (node) {
+ dm.fireDataChange(node.getDataPath());
+ if (addedNode && this.isList()) {
+ dm.fireDataChange(this.getDataPath());
+ dm.fireDataChange(this.getDataPath() + '/count()');
+ }
+ } else if (removedPath) {
+ dm.fireDataChange(removedPath);
+ if (this.isList()) {
+ dm.fireDataChange(this.getDataPath());
+ dm.fireDataChange(this.getDataPath() + '/count()');
+ }
+ }
+ return node;
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getDataName = function() {
+ return this.dataName_;
+};
+
+
+/**
+ * Setthe name of the node relative to the parent node
+ * @param {string} dataName The name of the node.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.setDataName = function(dataName) {
+ this.dataName_ = dataName;
+};
+
+
+/**
+ * Gets the a qualified data path to this node
+ * @return {string} The data path.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getDataPath = function() {
+ var parentPath = '';
+ if (this.parent_) {
+ parentPath = this.parent_.getDataPath() + goog.ds.STR_PATH_SEPARATOR;
+ }
+
+ return parentPath + this.dataName_;
+};
+
+
+/**
+ * Load or reload the backing data for this node
+ * @override
+ */
+goog.ds.JsDataSource.prototype.load = function() {
+ // Nothing to do
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * TODO(user) Discuss null value handling
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.getLoadState = function() {
+ return (this.root_ == null) ? goog.ds.LoadState.NOT_LOADED :
+ goog.ds.LoadState.LOADED;
+};
+
+
+/**
+ * Whether the value of this node is a homogeneous list of data
+ * @return {boolean} True if a list.
+ * @override
+ */
+goog.ds.JsDataSource.prototype.isList = function() {
+ return this.isList_ != null ? this.isList_ : goog.isArray(this.root_);
+};
+
+
+
+/**
+ * Data source for JavaScript properties that arent objects. Contains reference
+ * to parent object so that you can set the vaule
+ *
+ * @param {goog.ds.DataNode} parent Parent object.
+ * @param {string} dataName Name of this property.
+ * @param {goog.ds.DataNode=} opt_parentDataNode The parent data node. If
+ * omitted, assumes that the parent object is the parent data node.
+ *
+ * @constructor
+ * @extends {goog.ds.BaseDataNode}
+ * @final
+ */
+goog.ds.JsPropertyDataSource = function(parent, dataName, opt_parentDataNode) {
+ goog.ds.BaseDataNode.call(this);
+ this.dataName_ = dataName;
+ this.parent_ = parent;
+ this.parentDataNode_ = opt_parentDataNode || this.parent_;
+};
+goog.inherits(goog.ds.JsPropertyDataSource, goog.ds.BaseDataNode);
+
+
+/**
+ * Get the value of the node
+ * @return {Object} The value of the node, or null if no value.
+ */
+goog.ds.JsPropertyDataSource.prototype.get = function() {
+ return this.parent_[this.dataName_];
+};
+
+
+/**
+ * Set the value of the node
+ * @param {Object} value The new value of the node.
+ * @override
+ */
+goog.ds.JsPropertyDataSource.prototype.set = function(value) {
+ var oldValue = this.parent_[this.dataName_];
+ this.parent_[this.dataName_] = value;
+
+ if (oldValue != value) {
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
+ }
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ * @override
+ */
+goog.ds.JsPropertyDataSource.prototype.getDataName = function() {
+ return this.dataName_;
+};
+
+
+/** @override */
+goog.ds.JsPropertyDataSource.prototype.getParent = function() {
+ return this.parentDataNode_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/jsondatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/jsondatasource.js b/externs/GCL/externs/goog/datasource/jsondatasource.js
new file mode 100644
index 0000000..1621002
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/jsondatasource.js
@@ -0,0 +1,153 @@
+// 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 Implementation of DataNode for wrapping JSON data.
+ *
+ */
+
+
+goog.provide('goog.ds.JsonDataSource');
+
+goog.require('goog.Uri');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.JsDataSource');
+goog.require('goog.ds.LoadState');
+goog.require('goog.ds.logger');
+goog.require('goog.log');
+
+
+
+/**
+ * Data source whose backing is a JSON-like service, in which
+ * retreiving the resource specified by URL with the additional parameter
+ * callback. The resource retreived is executable JavaScript that
+ * makes a call to the named function with a JavaScript object literal
+ * as the only parameter.
+ *
+ * Example URI could be:
+ * http://www.google.com/data/search?q=monkey&callback=mycb
+ * which might return the JS:
+ * mycb({searchresults:
+ * [{uri: 'http://www.monkey.com', title: 'Site About Monkeys'}]});
+ *
+ * TODO(user): Evaluate using goog.net.Jsonp here.
+ *
+ * A URI of an empty string will mean that no request is made
+ * and the data source will be a data source with no child nodes
+ *
+ * @param {string|goog.Uri} uri URI for the request.
+ * @param {string} name Name of the datasource.
+ * @param {string=} opt_callbackParamName The parameter name that is used to
+ * specify the callback. Defaults to 'callback'.
+ *
+ * @extends {goog.ds.JsDataSource}
+ * @constructor
+ * @final
+ */
+goog.ds.JsonDataSource = function(uri, name, opt_callbackParamName) {
+ goog.ds.JsDataSource.call(this, null, name, null);
+ if (uri) {
+ this.uri_ = new goog.Uri(uri);
+ } else {
+ this.uri_ = null;
+ }
+
+ /**
+ * This is the callback parameter name that is added to the uri.
+ * @type {string}
+ * @private
+ */
+ this.callbackParamName_ = opt_callbackParamName || 'callback';
+
+};
+goog.inherits(goog.ds.JsonDataSource, goog.ds.JsDataSource);
+
+
+/**
+ * Default load state is NOT_LOADED
+ * @private
+ */
+goog.ds.JsonDataSource.prototype.loadState_ = goog.ds.LoadState.NOT_LOADED;
+
+
+/**
+ * Map of all data sources, needed for callbacks
+ * Doesn't work unless dataSources is exported (not renamed)
+ */
+goog.ds.JsonDataSource['dataSources'] = {};
+
+
+/**
+ * Load or reload the backing data for this node.
+ * Fires the JsonDataSource
+ * @override
+ */
+goog.ds.JsonDataSource.prototype.load = function() {
+ if (this.uri_) {
+ // NOTE: "dataSources" is expose above by name so that it will not be
+ // renamed. It should therefore be accessed via array notation here so
+ // that it also doesn't get renamed and stops the compiler from complaining
+ goog.ds.JsonDataSource['dataSources'][this.dataName_] = this;
+ goog.log.info(goog.ds.logger, 'Sending JS request for DataSource ' +
+ this.getDataName() + ' to ' + this.uri_);
+
+ this.loadState_ = goog.ds.LoadState.LOADING;
+
+ var uriToCall = new goog.Uri(this.uri_);
+ uriToCall.setParameterValue(this.callbackParamName_,
+ 'JsonReceive.' + this.dataName_);
+
+ goog.global['JsonReceive'][this.dataName_] =
+ goog.bind(this.receiveData, this);
+
+ var scriptEl = goog.dom.createDom(goog.dom.TagName.SCRIPT,
+ {'src': uriToCall});
+ goog.dom.getElementsByTagNameAndClass(
+ goog.dom.TagName.HEAD)[0].appendChild(scriptEl);
+ } else {
+ this.root_ = {};
+ this.loadState_ = goog.ds.LoadState.NOT_LOADED;
+ }
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.JsonDataSource.prototype.getLoadState = function() {
+ return this.loadState_;
+};
+
+
+/**
+ * Receives data from a Json request
+ * @param {Object} obj The JSON data.
+ */
+goog.ds.JsonDataSource.prototype.receiveData = function(obj) {
+ this.setRoot(obj);
+ this.loadState_ = goog.ds.LoadState.LOADED;
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+};
+
+
+/**
+* Temp variable to hold callbacks
+* until BUILD supports multiple externs.js files
+*/
+goog.global['JsonReceive'] = {};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js b/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js
new file mode 100644
index 0000000..bd2a024
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/jsxmlhttpdatasource.js
@@ -0,0 +1,196 @@
+// 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
+ * DataSource implementation that uses XMLHttpRequest as transport, with
+ * response as serialized JS object (not required to be JSON) that can
+ * be evaluated and set to a variable.
+ *
+ * Response can have unexecutable starting/ending text to prevent inclusion
+ * using <script src="...">
+ *
+ */
+
+
+goog.provide('goog.ds.JsXmlHttpDataSource');
+
+goog.require('goog.Uri');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.FastDataNode');
+goog.require('goog.ds.LoadState');
+goog.require('goog.ds.logger');
+goog.require('goog.events');
+goog.require('goog.log');
+goog.require('goog.net.EventType');
+goog.require('goog.net.XhrIo');
+
+
+
+/**
+ * Similar to JsonDataSource, with using XMLHttpRequest for transport
+ * Currently requires the result be a JS object that can be evaluated and
+ * set to a variable and doesn't require strict JSON notation.
+ *
+ * @param {(string|goog.Uri)} uri URI for the request.
+ * @param {string} name Name of the datasource.
+ * @param {string=} opt_startText Text to expect/strip before JS response.
+ * @param {string=} opt_endText Text to expect/strip after JS response.
+ * @param {boolean=} opt_usePost If true, use POST. Defaults to false (GET).
+ *
+ * @extends {goog.ds.FastDataNode}
+ * @constructor
+ * @final
+ */
+goog.ds.JsXmlHttpDataSource = function(uri, name, opt_startText, opt_endText,
+ opt_usePost) {
+ goog.ds.FastDataNode.call(this, {}, name, null);
+ if (uri) {
+ this.uri_ = new goog.Uri(uri);
+ this.xhr_ = new goog.net.XhrIo();
+ this.usePost_ = !!opt_usePost;
+
+ goog.events.listen(this.xhr_, goog.net.EventType.COMPLETE,
+ this.completed_, false, this);
+ } else {
+ this.uri_ = null;
+ }
+ this.startText_ = opt_startText;
+ this.endText_ = opt_endText;
+};
+goog.inherits(goog.ds.JsXmlHttpDataSource, goog.ds.FastDataNode);
+
+
+/**
+ * Delimiter for start of JSON data in response.
+ * null = starts at first character of response
+ * @type {string|undefined}
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.startText_;
+
+
+/**
+ * Delimiter for end of JSON data in response.
+ * null = ends at last character of response
+ * @type {string|undefined}
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.endText_;
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.JsXmlHttpDataSource.prototype.getLoadState = function() {
+ return this.loadState_;
+};
+
+
+/**
+ * Sets the request data. This can be used if it is required to
+ * send a specific body rather than build the body from the query
+ * parameters. Only used in POST requests.
+ * @param {string} data The data to send in the request body.
+ */
+goog.ds.JsXmlHttpDataSource.prototype.setQueryData = function(data) {
+ this.queryData_ = data;
+};
+
+
+/**
+ * Load or reload the backing data for this node.
+ * Fires the JsonDataSource
+ * @override
+ */
+goog.ds.JsXmlHttpDataSource.prototype.load = function() {
+ goog.log.info(goog.ds.logger, 'Sending JS request for DataSource ' +
+ this.getDataName() + ' to ' + this.uri_);
+
+ if (this.uri_) {
+ if (this.usePost_) {
+
+ var queryData;
+ if (!this.queryData_) {
+ queryData = this.uri_.getQueryData().toString();
+ } else {
+ queryData = this.queryData_;
+ }
+
+ var uriNoQuery = this.uri_.clone();
+ uriNoQuery.setQueryData(null);
+ this.xhr_.send(String(uriNoQuery), 'POST', queryData);
+ } else {
+ this.xhr_.send(String(this.uri_));
+ }
+ } else {
+ this.loadState_ = goog.ds.LoadState.NOT_LOADED;
+ }
+};
+
+
+/**
+ * Called on successful request.
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.success_ = function() {
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+};
+
+
+/**
+ * Completed callback. Loads data if successful, otherwise sets
+ * state to FAILED
+ * @param {goog.events.Event} e Event object, Xhr is target.
+ * @private
+ */
+goog.ds.JsXmlHttpDataSource.prototype.completed_ = function(e) {
+ if (this.xhr_.isSuccess()) {
+ goog.log.info(goog.ds.logger,
+ 'Got data for DataSource ' + this.getDataName());
+ var text = this.xhr_.getResponseText();
+
+ // Look for start and end token and trim text
+ if (this.startText_) {
+ var startpos = text.indexOf(this.startText_);
+ text = text.substring(startpos + this.startText_.length);
+ }
+ if (this.endText_) {
+ var endpos = text.lastIndexOf(this.endText_);
+ text = text.substring(0, endpos);
+ }
+
+ // Eval result
+ /** @preserveTry */
+ try {
+ var jsonObj = /** @type {Object} */ (eval('[' + text + '][0]'));
+ this.extendWith(jsonObj);
+ this.loadState_ = goog.ds.LoadState.LOADED;
+ }
+ catch (ex) {
+ // Invalid JS
+ this.loadState_ = goog.ds.LoadState.FAILED;
+ goog.log.error(goog.ds.logger, 'Failed to parse data: ' + ex.message);
+ }
+
+ // Call on a timer to avoid threading issues on IE.
+ goog.global.setTimeout(goog.bind(this.success_, this), 0);
+ } else {
+ goog.log.info(goog.ds.logger, 'Data retrieve failed for DataSource ' +
+ this.getDataName());
+ this.loadState_ = goog.ds.LoadState.FAILED;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/xmldatasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/xmldatasource.js b/externs/GCL/externs/goog/datasource/xmldatasource.js
new file mode 100644
index 0000000..5327269
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/xmldatasource.js
@@ -0,0 +1,417 @@
+// 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
+ * Implementations of DataNode for wrapping XML data.
+ *
+ */
+
+goog.provide('goog.ds.XmlDataSource');
+goog.provide('goog.ds.XmlHttpDataSource');
+
+goog.require('goog.Uri');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.xml');
+goog.require('goog.ds.BasicNodeList');
+goog.require('goog.ds.DataManager');
+goog.require('goog.ds.DataNode');
+goog.require('goog.ds.LoadState');
+goog.require('goog.ds.logger');
+goog.require('goog.net.XhrIo');
+goog.require('goog.string');
+
+
+
+/**
+ * Data source whose backing is an xml node
+ *
+ * @param {Node} node The XML node. Can be null.
+ * @param {goog.ds.XmlDataSource} parent Parent of XML element. Can be null.
+ * @param {string=} opt_name The name of this node relative to the parent node.
+ *
+ * @extends {goog.ds.DataNode}
+ * @constructor
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.XmlDataSource = function(node, parent, opt_name) {
+ this.parent_ = parent;
+ this.dataName_ = opt_name || (node ? node.nodeName : '');
+ this.setNode_(node);
+};
+
+
+/**
+ * Constant to select XML attributes for getChildNodes
+ * @type {string}
+ * @private
+ */
+goog.ds.XmlDataSource.ATTRIBUTE_SELECTOR_ = '@*';
+
+
+/**
+ * Set the current root nodeof the data source.
+ * Can be an attribute node, text node, or element node
+ * @param {Node} node The node. Can be null.
+ *
+ * @private
+ */
+goog.ds.XmlDataSource.prototype.setNode_ = function(node) {
+ this.node_ = node;
+ if (node != null) {
+ switch (node.nodeType) {
+ case goog.dom.NodeType.ATTRIBUTE:
+ case goog.dom.NodeType.TEXT:
+ this.value_ = node.nodeValue;
+ break;
+ case goog.dom.NodeType.ELEMENT:
+ if (node.childNodes.length == 1 &&
+ node.firstChild.nodeType == goog.dom.NodeType.TEXT) {
+ this.value_ = node.firstChild.nodeValue;
+ }
+ }
+ }
+};
+
+
+/**
+ * Creates the DataNodeList with the child nodes for this element.
+ * Allows for only building list as needed.
+ *
+ * @private
+ */
+goog.ds.XmlDataSource.prototype.createChildNodes_ = function() {
+ if (this.childNodeList_) {
+ return;
+ }
+ var childNodeList = new goog.ds.BasicNodeList();
+ if (this.node_ != null) {
+ var childNodes = this.node_.childNodes;
+ for (var i = 0, childNode; childNode = childNodes[i]; i++) {
+ if (childNode.nodeType != goog.dom.NodeType.TEXT ||
+ !goog.ds.XmlDataSource.isEmptyTextNodeValue_(childNode.nodeValue)) {
+ var newNode = new goog.ds.XmlDataSource(childNode,
+ this, childNode.nodeName);
+ childNodeList.add(newNode);
+ }
+ }
+ }
+ this.childNodeList_ = childNodeList;
+};
+
+
+/**
+ * Creates the DataNodeList with the attributes for the element
+ * Allows for only building list as needed.
+ *
+ * @private
+ */
+goog.ds.XmlDataSource.prototype.createAttributes_ = function() {
+ if (this.attributes_) {
+ return;
+ }
+ var attributes = new goog.ds.BasicNodeList();
+ if (this.node_ != null && this.node_.attributes != null) {
+ var atts = this.node_.attributes;
+ for (var i = 0, att; att = atts[i]; i++) {
+ var newNode = new goog.ds.XmlDataSource(att, this, att.nodeName);
+ attributes.add(newNode);
+ }
+ }
+ this.attributes_ = attributes;
+};
+
+
+/**
+ * Get the value of the node
+ * @return {Object} The value of the node, or null if no value.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.get = function() {
+ this.createChildNodes_();
+ return this.value_;
+};
+
+
+/**
+ * Set the value of the node
+ * @param {*} value The new value of the node.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.set = function(value) {
+ throw Error('Can\'t set on XmlDataSource yet');
+};
+
+
+/** @override */
+goog.ds.XmlDataSource.prototype.getChildNodes = function(opt_selector) {
+ if (opt_selector && opt_selector ==
+ goog.ds.XmlDataSource.ATTRIBUTE_SELECTOR_) {
+ this.createAttributes_();
+ return this.attributes_;
+ } else if (opt_selector == null ||
+ opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
+ this.createChildNodes_();
+ return this.childNodeList_;
+ } else {
+ throw Error('Unsupported selector');
+ }
+
+};
+
+
+/**
+ * Gets a named child node of the current node
+ * @param {string} name The node name.
+ * @return {goog.ds.DataNode} The child node, or null if
+ * no node of this name exists.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getChildNode = function(name) {
+ if (goog.string.startsWith(name, goog.ds.STR_ATTRIBUTE_START)) {
+ var att = this.node_.getAttributeNode(name.substring(1));
+ return att ? new goog.ds.XmlDataSource(att, this) : null;
+ } else {
+ return /** @type {goog.ds.DataNode} */ (this.getChildNodes().get(name));
+ }
+};
+
+
+/**
+ * Gets the value of a child node
+ * @param {string} name The node name.
+ * @return {*} The value of the node, or null if no value or the child node
+ * doesn't exist.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getChildNodeValue = function(name) {
+ if (goog.string.startsWith(name, goog.ds.STR_ATTRIBUTE_START)) {
+ var node = this.node_.getAttributeNode(name.substring(1));
+ return node ? node.nodeValue : null;
+ } else {
+ var node = this.getChildNode(name);
+ return node ? node.get() : null;
+ }
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getDataName = function() {
+ return this.dataName_;
+};
+
+
+/**
+ * Setthe name of the node relative to the parent node
+ * @param {string} name The name of the node.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.setDataName = function(name) {
+ this.dataName_ = name;
+};
+
+
+/**
+ * Gets the a qualified data path to this node
+ * @return {string} The data path.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getDataPath = function() {
+ var parentPath = '';
+ if (this.parent_) {
+ parentPath = this.parent_.getDataPath() +
+ (this.dataName_.indexOf(goog.ds.STR_ARRAY_START) != -1 ? '' :
+ goog.ds.STR_PATH_SEPARATOR);
+ }
+
+ return parentPath + this.dataName_;
+};
+
+
+/**
+ * Load or reload the backing data for this node
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.load = function() {
+ // Nothing to do
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.XmlDataSource.prototype.getLoadState = function() {
+ return this.node_ ? goog.ds.LoadState.LOADED : goog.ds.LoadState.NOT_LOADED;
+};
+
+
+/**
+ * Check whether a node is an empty text node. Nodes consisting of only white
+ * space (#x20, #xD, #xA, #x9) can generally be collapsed to a zero length
+ * text string.
+ * @param {string} str String to match.
+ * @return {boolean} True if string equates to empty text node.
+ * @private
+ */
+goog.ds.XmlDataSource.isEmptyTextNodeValue_ = function(str) {
+ return /^[\r\n\t ]*$/.test(str);
+};
+
+
+/**
+ * Creates an XML document with one empty node.
+ * Useful for places where you need a node that
+ * can be queried against.
+ *
+ * @return {Document} Document with one empty node.
+ * @private
+ */
+goog.ds.XmlDataSource.createChildlessDocument_ = function() {
+ return goog.dom.xml.createDocument('nothing');
+};
+
+
+
+/**
+ * Data source whose backing is an XMLHttpRequest,
+ *
+ * A URI of an empty string will mean that no request is made
+ * and the data source will be a single, empty node.
+ *
+ * @param {(string|goog.Uri)} uri URL of the XMLHttpRequest.
+ * @param {string} name Name of the datasource.
+ *
+ * implements goog.ds.XmlHttpDataSource.
+ * @constructor
+ * @extends {goog.ds.XmlDataSource}
+ * @final
+ */
+goog.ds.XmlHttpDataSource = function(uri, name) {
+ goog.ds.XmlDataSource.call(this, null, null, name);
+ if (uri) {
+ this.uri_ = new goog.Uri(uri);
+ } else {
+ this.uri_ = null;
+ }
+};
+goog.inherits(goog.ds.XmlHttpDataSource, goog.ds.XmlDataSource);
+
+
+/**
+ * Default load state is NOT_LOADED
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.loadState_ = goog.ds.LoadState.NOT_LOADED;
+
+
+/**
+ * Load or reload the backing data for this node.
+ * Fires the XMLHttpRequest
+ * @override
+ */
+goog.ds.XmlHttpDataSource.prototype.load = function() {
+ if (this.uri_) {
+ goog.log.info(goog.ds.logger, 'Sending XML request for DataSource ' +
+ this.getDataName() + ' to ' + this.uri_);
+ this.loadState_ = goog.ds.LoadState.LOADING;
+
+ goog.net.XhrIo.send(this.uri_, goog.bind(this.complete_, this));
+ } else {
+ this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
+ this.loadState_ = goog.ds.LoadState.NOT_LOADED;
+ }
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.XmlHttpDataSource.prototype.getLoadState = function() {
+ return this.loadState_;
+};
+
+
+/**
+ * Handles the completion of an XhrIo request. Dispatches to success or load
+ * based on the result.
+ * @param {!goog.events.Event} e The XhrIo event object.
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.complete_ = function(e) {
+ var xhr = /** @type {goog.net.XhrIo} */ (e.target);
+ if (xhr && xhr.isSuccess()) {
+ this.success_(xhr);
+ } else {
+ this.failure_();
+ }
+};
+
+
+/**
+ * Success result. Checks whether valid XML was returned
+ * and sets the XML and loadstate.
+ *
+ * @param {!goog.net.XhrIo} xhr The successful XhrIo object.
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.success_ = function(xhr) {
+ goog.log.info(goog.ds.logger,
+ 'Got data for DataSource ' + this.getDataName());
+ var xml = xhr.getResponseXml();
+
+ // Fix for case where IE returns valid XML as text but
+ // doesn't parse by default
+ if (xml && !xml.hasChildNodes() &&
+ goog.isObject(xhr.getResponseText())) {
+ xml = goog.dom.xml.loadXml(xhr.getResponseText());
+ }
+ // Failure result
+ if (!xml || !xml.hasChildNodes()) {
+ this.loadState_ = goog.ds.LoadState.FAILED;
+ this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
+ } else {
+ this.loadState_ = goog.ds.LoadState.LOADED;
+ this.node_ = xml.documentElement;
+ }
+
+ if (this.getDataName()) {
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+ }
+};
+
+
+/**
+ * Failure result
+ *
+ * @private
+ */
+goog.ds.XmlHttpDataSource.prototype.failure_ = function() {
+ goog.log.info(goog.ds.logger, 'Data retrieve failed for DataSource ' +
+ this.getDataName());
+
+ this.loadState_ = goog.ds.LoadState.FAILED;
+ this.node_ = goog.ds.XmlDataSource.createChildlessDocument_();
+
+ if (this.getDataName()) {
+ goog.ds.DataManager.getInstance().fireDataChange(this.getDataName());
+ }
+};
[45/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/base64.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/base64.js b/externs/GCL/externs/goog/crypt/base64.js
new file mode 100644
index 0000000..9103fa1
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/base64.js
@@ -0,0 +1,286 @@
+// 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 Base64 en/decoding. Not much to say here except that we
+ * work with decoded values in arrays of bytes. By "byte" I mean a number
+ * in [0, 255].
+ *
+ * @author doughtie@google.com (Gavin Doughtie)
+ */
+
+goog.provide('goog.crypt.base64');
+goog.require('goog.crypt');
+goog.require('goog.userAgent');
+
+// Static lookup maps, lazily populated by init_()
+
+
+/**
+ * Maps bytes to characters.
+ * @type {Object}
+ * @private
+ */
+goog.crypt.base64.byteToCharMap_ = null;
+
+
+/**
+ * Maps characters to bytes.
+ * @type {Object}
+ * @private
+ */
+goog.crypt.base64.charToByteMap_ = null;
+
+
+/**
+ * Maps bytes to websafe characters.
+ * @type {Object}
+ * @private
+ */
+goog.crypt.base64.byteToCharMapWebSafe_ = null;
+
+
+/**
+ * Maps websafe characters to bytes.
+ * @type {Object}
+ * @private
+ */
+goog.crypt.base64.charToByteMapWebSafe_ = null;
+
+
+/**
+ * Our default alphabet, shared between
+ * ENCODED_VALS and ENCODED_VALS_WEBSAFE
+ * @type {string}
+ */
+goog.crypt.base64.ENCODED_VALS_BASE =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
+ 'abcdefghijklmnopqrstuvwxyz' +
+ '0123456789';
+
+
+/**
+ * Our default alphabet. Value 64 (=) is special; it means "nothing."
+ * @type {string}
+ */
+goog.crypt.base64.ENCODED_VALS =
+ goog.crypt.base64.ENCODED_VALS_BASE + '+/=';
+
+
+/**
+ * Our websafe alphabet.
+ * @type {string}
+ */
+goog.crypt.base64.ENCODED_VALS_WEBSAFE =
+ goog.crypt.base64.ENCODED_VALS_BASE + '-_.';
+
+
+/**
+ * Whether this browser supports the atob and btoa functions. This extension
+ * started at Mozilla but is now implemented by many browsers. We use the
+ * ASSUME_* variables to avoid pulling in the full useragent detection library
+ * but still allowing the standard per-browser compilations.
+ *
+ * @type {boolean}
+ */
+goog.crypt.base64.HAS_NATIVE_SUPPORT = goog.userAgent.GECKO ||
+ goog.userAgent.WEBKIT ||
+ goog.userAgent.OPERA ||
+ typeof(goog.global.atob) == 'function';
+
+
+/**
+ * Base64-encode an array of bytes.
+ *
+ * @param {Array<number>|Uint8Array} input An array of bytes (numbers with
+ * value in [0, 255]) to encode.
+ * @param {boolean=} opt_webSafe Boolean indicating we should use the
+ * alternative alphabet.
+ * @return {string} The base64 encoded string.
+ */
+goog.crypt.base64.encodeByteArray = function(input, opt_webSafe) {
+ if (!goog.isArrayLike(input)) {
+ throw Error('encodeByteArray takes an array as a parameter');
+ }
+
+ goog.crypt.base64.init_();
+
+ var byteToCharMap = opt_webSafe ?
+ goog.crypt.base64.byteToCharMapWebSafe_ :
+ goog.crypt.base64.byteToCharMap_;
+
+ var output = [];
+
+ for (var i = 0; i < input.length; i += 3) {
+ var byte1 = input[i];
+ var haveByte2 = i + 1 < input.length;
+ var byte2 = haveByte2 ? input[i + 1] : 0;
+ var haveByte3 = i + 2 < input.length;
+ var byte3 = haveByte3 ? input[i + 2] : 0;
+
+ var outByte1 = byte1 >> 2;
+ var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
+ var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6);
+ var outByte4 = byte3 & 0x3F;
+
+ if (!haveByte3) {
+ outByte4 = 64;
+
+ if (!haveByte2) {
+ outByte3 = 64;
+ }
+ }
+
+ output.push(byteToCharMap[outByte1],
+ byteToCharMap[outByte2],
+ byteToCharMap[outByte3],
+ byteToCharMap[outByte4]);
+ }
+
+ return output.join('');
+};
+
+
+/**
+ * Base64-encode a string.
+ *
+ * @param {string} input A string to encode.
+ * @param {boolean=} opt_webSafe If true, we should use the
+ * alternative alphabet.
+ * @return {string} The base64 encoded string.
+ */
+goog.crypt.base64.encodeString = function(input, opt_webSafe) {
+ // Shortcut for Mozilla browsers that implement
+ // a native base64 encoder in the form of "btoa/atob"
+ if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) {
+ return goog.global.btoa(input);
+ }
+ return goog.crypt.base64.encodeByteArray(
+ goog.crypt.stringToByteArray(input), opt_webSafe);
+};
+
+
+/**
+ * Base64-decode a string.
+ *
+ * @param {string} input to decode.
+ * @param {boolean=} opt_webSafe True if we should use the
+ * alternative alphabet.
+ * @return {string} string representing the decoded value.
+ */
+goog.crypt.base64.decodeString = function(input, opt_webSafe) {
+ // Shortcut for Mozilla browsers that implement
+ // a native base64 encoder in the form of "btoa/atob"
+ if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) {
+ return goog.global.atob(input);
+ }
+ return goog.crypt.byteArrayToString(
+ goog.crypt.base64.decodeStringToByteArray(input, opt_webSafe));
+};
+
+
+/**
+ * Base64-decode a string.
+ *
+ * In base-64 decoding, groups of four characters are converted into three
+ * bytes. If the encoder did not apply padding, the input length may not
+ * be a multiple of 4.
+ *
+ * In this case, the last group will have fewer than 4 characters, and
+ * padding will be inferred. If the group has one or two characters, it decodes
+ * to one byte. If the group has three characters, it decodes to two bytes.
+ *
+ * @param {string} input Input to decode.
+ * @param {boolean=} opt_webSafe True if we should use the web-safe alphabet.
+ * @return {!Array<number>} bytes representing the decoded value.
+ */
+goog.crypt.base64.decodeStringToByteArray = function(input, opt_webSafe) {
+ goog.crypt.base64.init_();
+
+ var charToByteMap = opt_webSafe ?
+ goog.crypt.base64.charToByteMapWebSafe_ :
+ goog.crypt.base64.charToByteMap_;
+
+ var output = [];
+
+ for (var i = 0; i < input.length; ) {
+ var byte1 = charToByteMap[input.charAt(i++)];
+
+ var haveByte2 = i < input.length;
+ var byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
+ ++i;
+
+ var haveByte3 = i < input.length;
+ var byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
+ ++i;
+
+ var haveByte4 = i < input.length;
+ var byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
+ ++i;
+
+ if (byte1 == null || byte2 == null ||
+ byte3 == null || byte4 == null) {
+ throw Error();
+ }
+
+ var outByte1 = (byte1 << 2) | (byte2 >> 4);
+ output.push(outByte1);
+
+ if (byte3 != 64) {
+ var outByte2 = ((byte2 << 4) & 0xF0) | (byte3 >> 2);
+ output.push(outByte2);
+
+ if (byte4 != 64) {
+ var outByte3 = ((byte3 << 6) & 0xC0) | byte4;
+ output.push(outByte3);
+ }
+ }
+ }
+
+ return output;
+};
+
+
+/**
+ * Lazy static initialization function. Called before
+ * accessing any of the static map variables.
+ * @private
+ */
+goog.crypt.base64.init_ = function() {
+ if (!goog.crypt.base64.byteToCharMap_) {
+ goog.crypt.base64.byteToCharMap_ = {};
+ goog.crypt.base64.charToByteMap_ = {};
+ goog.crypt.base64.byteToCharMapWebSafe_ = {};
+ goog.crypt.base64.charToByteMapWebSafe_ = {};
+
+ // We want quick mappings back and forth, so we precompute two maps.
+ for (var i = 0; i < goog.crypt.base64.ENCODED_VALS.length; i++) {
+ goog.crypt.base64.byteToCharMap_[i] =
+ goog.crypt.base64.ENCODED_VALS.charAt(i);
+ goog.crypt.base64.charToByteMap_[goog.crypt.base64.byteToCharMap_[i]] = i;
+ goog.crypt.base64.byteToCharMapWebSafe_[i] =
+ goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i);
+ goog.crypt.base64.charToByteMapWebSafe_[
+ goog.crypt.base64.byteToCharMapWebSafe_[i]] = i;
+
+ // Be forgiving when decoding and correctly decode both encodings.
+ if (i >= goog.crypt.base64.ENCODED_VALS_BASE.length) {
+ goog.crypt.base64.charToByteMap_[
+ goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
+ goog.crypt.base64.charToByteMapWebSafe_[
+ goog.crypt.base64.ENCODED_VALS.charAt(i)] = i;
+ }
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/basen.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/basen.js b/externs/GCL/externs/goog/crypt/basen.js
new file mode 100644
index 0000000..2bac248
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/basen.js
@@ -0,0 +1,242 @@
+// 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 Numeric base conversion library. Works for arbitrary bases and
+ * arbitrary length numbers.
+ *
+ * For base-64 conversion use base64.js because it is optimized for the specific
+ * conversion to base-64 while this module is generic. Base-64 is defined here
+ * mostly for demonstration purpose.
+ *
+ * TODO: Make base64 and baseN classes that have common interface. (Perhaps...)
+ *
+ */
+
+goog.provide('goog.crypt.baseN');
+
+
+/**
+ * Base-2, i.e. '01'.
+ * @type {string}
+ */
+goog.crypt.baseN.BASE_BINARY = '01';
+
+
+/**
+ * Base-8, i.e. '01234567'.
+ * @type {string}
+ */
+goog.crypt.baseN.BASE_OCTAL = '01234567';
+
+
+/**
+ * Base-10, i.e. '0123456789'.
+ * @type {string}
+ */
+goog.crypt.baseN.BASE_DECIMAL = '0123456789';
+
+
+/**
+ * Base-16 using lower case, i.e. '0123456789abcdef'.
+ * @type {string}
+ */
+goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL = '0123456789abcdef';
+
+
+/**
+ * Base-16 using upper case, i.e. '0123456789ABCDEF'.
+ * @type {string}
+ */
+goog.crypt.baseN.BASE_UPPERCASE_HEXADECIMAL = '0123456789ABCDEF';
+
+
+/**
+ * The more-known version of the BASE-64 encoding. Uses + and / characters.
+ * @type {string}
+ */
+goog.crypt.baseN.BASE_64 =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+
+
+/**
+ * URL-safe version of the BASE-64 encoding.
+ * @type {string}
+ */
+goog.crypt.baseN.BASE_64_URL_SAFE =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
+
+
+/**
+ * Converts a number from one numeric base to another.
+ *
+ * The bases are represented as strings, which list allowed digits. Each digit
+ * should be unique. The bases can either be user defined, or any of
+ * goog.crypt.baseN.BASE_xxx.
+ *
+ * The number is in human-readable format, most significant digit first, and is
+ * a non-negative integer. Base designators such as $, 0x, d, b or h (at end)
+ * will be interpreted as digits, so avoid them. Leading zeros will be trimmed.
+ *
+ * Note: for huge bases the result may be inaccurate because of overflowing
+ * 64-bit doubles used by JavaScript for integer calculus. This may happen
+ * if the product of the number of digits in the input and output bases comes
+ * close to 10^16, which is VERY unlikely (100M digits in each base), but
+ * may be possible in the future unicode world. (Unicode 3.2 has less than 100K
+ * characters. However, it reserves some more, close to 1M.)
+ *
+ * @param {string} number The number to convert.
+ * @param {string} inputBase The numeric base the number is in (all digits).
+ * @param {string} outputBase Requested numeric base.
+ * @return {string} The converted number.
+ */
+goog.crypt.baseN.recodeString = function(number, inputBase, outputBase) {
+ if (outputBase == '') {
+ throw Error('Empty output base');
+ }
+
+ // Check if number is 0 (special case when we don't want to return '').
+ var isZero = true;
+ for (var i = 0, n = number.length; i < n; i++) {
+ if (number.charAt(i) != inputBase.charAt(0)) {
+ isZero = false;
+ break;
+ }
+ }
+ if (isZero) {
+ return outputBase.charAt(0);
+ }
+
+ var numberDigits = goog.crypt.baseN.stringToArray_(number, inputBase);
+
+ var inputBaseSize = inputBase.length;
+ var outputBaseSize = outputBase.length;
+
+ // result = 0.
+ var result = [];
+
+ // For all digits of number, starting with the most significant ...
+ for (var i = numberDigits.length - 1; i >= 0; i--) {
+
+ // result *= number.base.
+ var carry = 0;
+ for (var j = 0, n = result.length; j < n; j++) {
+ var digit = result[j];
+ // This may overflow for huge bases. See function comment.
+ digit = digit * inputBaseSize + carry;
+ if (digit >= outputBaseSize) {
+ var remainder = digit % outputBaseSize;
+ carry = (digit - remainder) / outputBaseSize;
+ digit = remainder;
+ } else {
+ carry = 0;
+ }
+ result[j] = digit;
+ }
+ while (carry) {
+ var remainder = carry % outputBaseSize;
+ result.push(remainder);
+ carry = (carry - remainder) / outputBaseSize;
+ }
+
+ // result += number[i].
+ carry = numberDigits[i];
+ var j = 0;
+ while (carry) {
+ if (j >= result.length) {
+ // Extend result with a leading zero which will be overwritten below.
+ result.push(0);
+ }
+ var digit = result[j];
+ digit += carry;
+ if (digit >= outputBaseSize) {
+ var remainder = digit % outputBaseSize;
+ carry = (digit - remainder) / outputBaseSize;
+ digit = remainder;
+ } else {
+ carry = 0;
+ }
+ result[j] = digit;
+ j++;
+ }
+ }
+
+ return goog.crypt.baseN.arrayToString_(result, outputBase);
+};
+
+
+/**
+ * Converts a string representation of a number to an array of digit values.
+ *
+ * More precisely, the digit values are indices into the number base, which
+ * is represented as a string, which can either be user defined or one of the
+ * BASE_xxx constants.
+ *
+ * Throws an Error if the number contains a digit not found in the base.
+ *
+ * @param {string} number The string to convert, most significant digit first.
+ * @param {string} base Digits in the base.
+ * @return {!Array<number>} Array of digit values, least significant digit
+ * first.
+ * @private
+ */
+goog.crypt.baseN.stringToArray_ = function(number, base) {
+ var index = {};
+ for (var i = 0, n = base.length; i < n; i++) {
+ index[base.charAt(i)] = i;
+ }
+ var result = [];
+ for (var i = number.length - 1; i >= 0; i--) {
+ var character = number.charAt(i);
+ var digit = index[character];
+ if (typeof digit == 'undefined') {
+ throw Error('Number ' + number +
+ ' contains a character not found in base ' +
+ base + ', which is ' + character);
+ }
+ result.push(digit);
+ }
+ return result;
+};
+
+
+/**
+ * Converts an array representation of a number to a string.
+ *
+ * More precisely, the elements of the input array are indices into the base,
+ * which is represented as a string, which can either be user defined or one of
+ * the BASE_xxx constants.
+ *
+ * Throws an Error if the number contains a digit which is outside the range
+ * 0 ... base.length - 1.
+ *
+ * @param {Array<number>} number Array of digit values, least significant
+ * first.
+ * @param {string} base Digits in the base.
+ * @return {string} Number as a string, most significant digit first.
+ * @private
+ */
+goog.crypt.baseN.arrayToString_ = function(number, base) {
+ var n = number.length;
+ var chars = [];
+ var baseSize = base.length;
+ for (var i = n - 1; i >= 0; i--) {
+ var digit = number[i];
+ if (digit >= baseSize || digit < 0) {
+ throw Error('Number ' + number + ' contains an invalid digit: ' + digit);
+ }
+ chars.push(base.charAt(digit));
+ }
+ return chars.join('');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/blobhasher.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/blobhasher.js b/externs/GCL/externs/goog/crypt/blobhasher.js
new file mode 100644
index 0000000..cb4af79
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/blobhasher.js
@@ -0,0 +1,285 @@
+// 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 Asynchronous hash computer for the Blob interface.
+ *
+ * The Blob interface, part of the HTML5 File API, is supported on Chrome 7+,
+ * Firefox 4.0 and Opera 11. No Blob interface implementation is expected on
+ * Internet Explorer 10. Chrome 11, Firefox 5.0 and the subsequent release of
+ * Opera are supposed to use vendor prefixes due to evolving API, see
+ * http://dev.w3.org/2006/webapi/FileAPI/ for details.
+ *
+ * This implementation currently uses upcoming Chrome and Firefox prefixes,
+ * plus the original Blob.slice specification, as implemented on Chrome 10
+ * and Firefox 4.0.
+ *
+ */
+
+goog.provide('goog.crypt.BlobHasher');
+goog.provide('goog.crypt.BlobHasher.EventType');
+
+goog.require('goog.asserts');
+goog.require('goog.events.EventTarget');
+goog.require('goog.fs');
+goog.require('goog.log');
+
+
+
+/**
+ * Construct the hash computer.
+ *
+ * @param {!goog.crypt.Hash} hashFn The hash function to use.
+ * @param {number=} opt_blockSize Processing block size.
+ * @constructor
+ * @struct
+ * @suppress {checkStructDictInheritance}
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.crypt.BlobHasher = function(hashFn, opt_blockSize) {
+ goog.crypt.BlobHasher.base(this, 'constructor');
+
+ /**
+ * The actual hash function.
+ * @type {!goog.crypt.Hash}
+ * @private
+ */
+ this.hashFn_ = hashFn;
+
+ /**
+ * The blob being processed or null if no blob is being processed.
+ * @type {Blob}
+ * @private
+ */
+ this.blob_ = null;
+
+ /**
+ * Computed hash value.
+ * @type {Array<number>}
+ * @private
+ */
+ this.hashVal_ = null;
+
+ /**
+ * Number of bytes already processed.
+ * @type {number}
+ * @private
+ */
+ this.bytesProcessed_ = 0;
+
+ /**
+ * The number of bytes to hash or Infinity for no limit.
+ * @type {number}
+ * @private
+ */
+ this.hashingLimit_ = Infinity;
+
+ /**
+ * Processing block size.
+ * @type {number}
+ * @private
+ */
+ this.blockSize_ = opt_blockSize || 5000000;
+
+ /**
+ * File reader object. Will be null if no chunk is currently being read.
+ * @type {FileReader}
+ * @private
+ */
+ this.fileReader_ = null;
+
+ /**
+ * The logger used by this object.
+ * @type {goog.log.Logger}
+ * @private
+ */
+ this.logger_ = goog.log.getLogger('goog.crypt.BlobHasher');
+};
+goog.inherits(goog.crypt.BlobHasher, goog.events.EventTarget);
+
+
+/**
+ * Event names for hash computation events
+ * @enum {string}
+ */
+goog.crypt.BlobHasher.EventType = {
+ STARTED: 'started',
+ PROGRESS: 'progress',
+ THROTTLED: 'throttled',
+ COMPLETE: 'complete',
+ ABORT: 'abort',
+ ERROR: 'error'
+};
+
+
+/**
+ * Start the hash computation.
+ * @param {!Blob} blob The blob of data to compute the hash for.
+ */
+goog.crypt.BlobHasher.prototype.hash = function(blob) {
+ this.abort();
+ this.hashFn_.reset();
+ this.blob_ = blob;
+ this.hashVal_ = null;
+ this.bytesProcessed_ = 0;
+ this.dispatchEvent(goog.crypt.BlobHasher.EventType.STARTED);
+
+ this.processNextBlock_();
+};
+
+
+/**
+ * Sets the maximum number of bytes to hash or Infinity for no limit. Can be
+ * called before hash() to throttle the hash computation. The hash computation
+ * can then be continued by repeatedly calling setHashingLimit() with greater
+ * byte offsets. This is useful if you don't need the hash until some time in
+ * the future, for example when uploading a file and you don't need the hash
+ * until the transfer is complete.
+ * @param {number} byteOffset The byte offset to compute the hash up to.
+ * Should be a non-negative integer or Infinity for no limit. Negative
+ * values are not allowed.
+ */
+goog.crypt.BlobHasher.prototype.setHashingLimit = function(byteOffset) {
+ goog.asserts.assert(byteOffset >= 0, 'Hashing limit must be non-negative.');
+ this.hashingLimit_ = byteOffset;
+
+ // Resume processing if a blob is currently being hashed, but no block read
+ // is currently in progress.
+ if (this.blob_ && !this.fileReader_) {
+ this.processNextBlock_();
+ }
+};
+
+
+/**
+ * Abort hash computation.
+ */
+goog.crypt.BlobHasher.prototype.abort = function() {
+ if (this.fileReader_) {
+ this.fileReader_.abort();
+ this.fileReader_ = null;
+ }
+
+ if (this.blob_) {
+ this.blob_ = null;
+ this.dispatchEvent(goog.crypt.BlobHasher.EventType.ABORT);
+ }
+};
+
+
+/**
+ * @return {number} Number of bytes processed so far.
+ */
+goog.crypt.BlobHasher.prototype.getBytesProcessed = function() {
+ return this.bytesProcessed_;
+};
+
+
+/**
+ * @return {Array<number>} The computed hash value or null if not ready.
+ */
+goog.crypt.BlobHasher.prototype.getHash = function() {
+ return this.hashVal_;
+};
+
+
+/**
+ * Helper function setting up the processing for the next block, or finalizing
+ * the computation if all blocks were processed.
+ * @private
+ */
+goog.crypt.BlobHasher.prototype.processNextBlock_ = function() {
+ goog.asserts.assert(this.blob_, 'A hash computation must be in progress.');
+
+ if (this.bytesProcessed_ < this.blob_.size) {
+
+ if (this.hashingLimit_ <= this.bytesProcessed_) {
+ // Throttle limit reached. Wait until we are allowed to hash more bytes.
+ this.dispatchEvent(goog.crypt.BlobHasher.EventType.THROTTLED);
+ return;
+ }
+
+ // We have to reset the FileReader every time, otherwise it fails on
+ // Chrome, including the latest Chrome 12 beta.
+ // http://code.google.com/p/chromium/issues/detail?id=82346
+ this.fileReader_ = new FileReader();
+ this.fileReader_.onload = goog.bind(this.onLoad_, this);
+ this.fileReader_.onerror = goog.bind(this.onError_, this);
+
+ var endOffset = Math.min(this.hashingLimit_, this.blob_.size);
+ var size = Math.min(endOffset - this.bytesProcessed_, this.blockSize_);
+ var chunk = goog.fs.sliceBlob(this.blob_, this.bytesProcessed_,
+ this.bytesProcessed_ + size);
+ if (!chunk || chunk.size != size) {
+ goog.log.error(this.logger_, 'Failed slicing the blob');
+ this.onError_();
+ return;
+ }
+
+ if (this.fileReader_.readAsArrayBuffer) {
+ this.fileReader_.readAsArrayBuffer(chunk);
+ } else if (this.fileReader_.readAsBinaryString) {
+ this.fileReader_.readAsBinaryString(chunk);
+ } else {
+ goog.log.error(this.logger_, 'Failed calling the chunk reader');
+ this.onError_();
+ }
+ } else {
+ this.hashVal_ = this.hashFn_.digest();
+ this.blob_ = null;
+ this.dispatchEvent(goog.crypt.BlobHasher.EventType.COMPLETE);
+ }
+};
+
+
+/**
+ * Handle processing block loaded.
+ * @private
+ */
+goog.crypt.BlobHasher.prototype.onLoad_ = function() {
+ goog.log.info(this.logger_, 'Successfully loaded a chunk');
+
+ var array = null;
+ if (this.fileReader_.result instanceof Array ||
+ goog.isString(this.fileReader_.result)) {
+ array = this.fileReader_.result;
+ } else if (goog.global['ArrayBuffer'] && goog.global['Uint8Array'] &&
+ this.fileReader_.result instanceof ArrayBuffer) {
+ array = new Uint8Array(this.fileReader_.result);
+ }
+ if (!array) {
+ goog.log.error(this.logger_, 'Failed reading the chunk');
+ this.onError_();
+ return;
+ }
+
+ this.hashFn_.update(array);
+ this.bytesProcessed_ += array.length;
+ this.fileReader_ = null;
+ this.dispatchEvent(goog.crypt.BlobHasher.EventType.PROGRESS);
+
+ this.processNextBlock_();
+};
+
+
+/**
+ * Handles error.
+ * @private
+ */
+goog.crypt.BlobHasher.prototype.onError_ = function() {
+ this.fileReader_ = null;
+ this.blob_ = null;
+ this.dispatchEvent(goog.crypt.BlobHasher.EventType.ERROR);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/blockcipher.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/blockcipher.js b/externs/GCL/externs/goog/crypt/blockcipher.js
new file mode 100644
index 0000000..be766f0
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/blockcipher.js
@@ -0,0 +1,52 @@
+// Copyright 2012 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 definition of a block cipher. A block cipher is a
+ * pair of algorithms that implement encryption and decryption of input bytes.
+ *
+ * @see http://en.wikipedia.org/wiki/Block_cipher
+ *
+ * @author nnaze@google.com (Nathan Naze)
+ */
+
+goog.provide('goog.crypt.BlockCipher');
+
+
+
+/**
+ * Interface definition for a block cipher.
+ * @interface
+ */
+goog.crypt.BlockCipher = function() {};
+
+
+/**
+ * Encrypt a plaintext block. The implementation may expect (and assert)
+ * a particular block length.
+ * @param {!Array<number>} input Plaintext array of input bytes.
+ * @return {!Array<number>} Encrypted ciphertext array of bytes. Should be the
+ * same length as input.
+ */
+goog.crypt.BlockCipher.prototype.encrypt;
+
+
+/**
+ * Decrypt a plaintext block. The implementation may expect (and assert)
+ * a particular block length.
+ * @param {!Array<number>} input Ciphertext. Array of input bytes.
+ * @return {!Array<number>} Decrypted plaintext array of bytes. Should be the
+ * same length as input.
+ */
+goog.crypt.BlockCipher.prototype.decrypt;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/cbc.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/cbc.js b/externs/GCL/externs/goog/crypt/cbc.js
new file mode 100644
index 0000000..68a2656
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/cbc.js
@@ -0,0 +1,153 @@
+// Copyright 2012 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 Implementation of CBC mode for block ciphers. See
+ * http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
+ * #Cipher-block_chaining_.28CBC.29. for description.
+ *
+ * @author nnaze@google.com (Nathan Naze)
+ */
+
+goog.provide('goog.crypt.Cbc');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.crypt');
+
+
+
+/**
+ * Implements the CBC mode for block ciphers. See
+ * http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
+ * #Cipher-block_chaining_.28CBC.29
+ *
+ * @param {!goog.crypt.BlockCipher} cipher The block cipher to use.
+ * @param {number=} opt_blockSize The block size of the cipher in bytes.
+ * Defaults to 16 bytes.
+ * @constructor
+ * @final
+ * @struct
+ */
+goog.crypt.Cbc = function(cipher, opt_blockSize) {
+
+ /**
+ * Block cipher.
+ * @type {!goog.crypt.BlockCipher}
+ * @private
+ */
+ this.cipher_ = cipher;
+
+ /**
+ * Block size in bytes.
+ * @type {number}
+ * @private
+ */
+ this.blockSize_ = opt_blockSize || 16;
+};
+
+
+/**
+ * Encrypt a message.
+ *
+ * @param {!Array<number>} plainText Message to encrypt. An array of bytes.
+ * The length should be a multiple of the block size.
+ * @param {!Array<number>} initialVector Initial vector for the CBC mode.
+ * An array of bytes with the same length as the block size.
+ * @return {!Array<number>} Encrypted message.
+ */
+goog.crypt.Cbc.prototype.encrypt = function(plainText, initialVector) {
+
+ goog.asserts.assert(
+ plainText.length % this.blockSize_ == 0,
+ 'Data\'s length must be multiple of block size.');
+
+ goog.asserts.assert(
+ initialVector.length == this.blockSize_,
+ 'Initial vector must be size of one block.');
+
+ // Implementation of
+ // http://en.wikipedia.org/wiki/File:Cbc_encryption.png
+
+ var cipherText = [];
+ var vector = initialVector;
+
+ // Generate each block of the encrypted cypher text.
+ for (var blockStartIndex = 0;
+ blockStartIndex < plainText.length;
+ blockStartIndex += this.blockSize_) {
+
+ // Takes one block from the input message.
+ var plainTextBlock = goog.array.slice(
+ plainText,
+ blockStartIndex,
+ blockStartIndex + this.blockSize_);
+
+ var input = goog.crypt.xorByteArray(plainTextBlock, vector);
+ var resultBlock = this.cipher_.encrypt(input);
+
+ goog.array.extend(cipherText, resultBlock);
+ vector = resultBlock;
+ }
+
+ return cipherText;
+};
+
+
+/**
+ * Decrypt a message.
+ *
+ * @param {!Array<number>} cipherText Message to decrypt. An array of bytes.
+ * The length should be a multiple of the block size.
+ * @param {!Array<number>} initialVector Initial vector for the CBC mode.
+ * An array of bytes with the same length as the block size.
+ * @return {!Array<number>} Decrypted message.
+ */
+goog.crypt.Cbc.prototype.decrypt = function(cipherText, initialVector) {
+
+ goog.asserts.assert(
+ cipherText.length % this.blockSize_ == 0,
+ 'Data\'s length must be multiple of block size.');
+
+ goog.asserts.assert(
+ initialVector.length == this.blockSize_,
+ 'Initial vector must be size of one block.');
+
+ // Implementation of
+ // http://en.wikipedia.org/wiki/File:Cbc_decryption.png
+
+ var plainText = [];
+ var blockStartIndex = 0;
+ var vector = initialVector;
+
+ // Generate each block of the decrypted plain text.
+ while (blockStartIndex < cipherText.length) {
+
+ // Takes one block.
+ var cipherTextBlock = goog.array.slice(
+ cipherText,
+ blockStartIndex,
+ blockStartIndex + this.blockSize_);
+
+ var resultBlock = this.cipher_.decrypt(cipherTextBlock);
+ var plainTextBlock = goog.crypt.xorByteArray(vector, resultBlock);
+
+ goog.array.extend(plainText, plainTextBlock);
+ vector = cipherTextBlock;
+
+ blockStartIndex += this.blockSize_;
+ }
+
+ return plainText;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/crypt.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/crypt.js b/externs/GCL/externs/goog/crypt/crypt.js
new file mode 100644
index 0000000..e8f722a
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/crypt.js
@@ -0,0 +1,173 @@
+// 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 Namespace with crypto related helper functions.
+ */
+
+goog.provide('goog.crypt');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+
+
+/**
+ * Turns a string into an array of bytes; a "byte" being a JS number in the
+ * range 0-255.
+ * @param {string} str String value to arrify.
+ * @return {!Array<number>} Array of numbers corresponding to the
+ * UCS character codes of each character in str.
+ */
+goog.crypt.stringToByteArray = function(str) {
+ var output = [], p = 0;
+ for (var i = 0; i < str.length; i++) {
+ var c = str.charCodeAt(i);
+ while (c > 0xff) {
+ output[p++] = c & 0xff;
+ c >>= 8;
+ }
+ output[p++] = c;
+ }
+ return output;
+};
+
+
+/**
+ * Turns an array of numbers into the string given by the concatenation of the
+ * characters to which the numbers correspond.
+ * @param {Array<number>} bytes Array of numbers representing characters.
+ * @return {string} Stringification of the array.
+ */
+goog.crypt.byteArrayToString = function(bytes) {
+ var CHUNK_SIZE = 8192;
+
+ // Special-case the simple case for speed's sake.
+ if (bytes.length < CHUNK_SIZE) {
+ return String.fromCharCode.apply(null, bytes);
+ }
+
+ // The remaining logic splits conversion by chunks since
+ // Function#apply() has a maximum parameter count.
+ // See discussion: http://goo.gl/LrWmZ9
+
+ var str = '';
+ for (var i = 0; i < bytes.length; i += CHUNK_SIZE) {
+ var chunk = goog.array.slice(bytes, i, i + CHUNK_SIZE);
+ str += String.fromCharCode.apply(null, chunk);
+ }
+ return str;
+};
+
+
+/**
+ * Turns an array of numbers into the hex string given by the concatenation of
+ * the hex values to which the numbers correspond.
+ * @param {Uint8Array|Array<number>} array Array of numbers representing
+ * characters.
+ * @return {string} Hex string.
+ */
+goog.crypt.byteArrayToHex = function(array) {
+ return goog.array.map(array, function(numByte) {
+ var hexByte = numByte.toString(16);
+ return hexByte.length > 1 ? hexByte : '0' + hexByte;
+ }).join('');
+};
+
+
+/**
+ * Converts a hex string into an integer array.
+ * @param {string} hexString Hex string of 16-bit integers (two characters
+ * per integer).
+ * @return {!Array<number>} Array of {0,255} integers for the given string.
+ */
+goog.crypt.hexToByteArray = function(hexString) {
+ goog.asserts.assert(hexString.length % 2 == 0,
+ 'Key string length must be multiple of 2');
+ var arr = [];
+ for (var i = 0; i < hexString.length; i += 2) {
+ arr.push(parseInt(hexString.substring(i, i + 2), 16));
+ }
+ return arr;
+};
+
+
+/**
+ * Converts a JS string to a UTF-8 "byte" array.
+ * @param {string} str 16-bit unicode string.
+ * @return {!Array<number>} UTF-8 byte array.
+ */
+goog.crypt.stringToUtf8ByteArray = function(str) {
+ // TODO(user): Use native implementations if/when available
+ str = str.replace(/\r\n/g, '\n');
+ var out = [], p = 0;
+ for (var i = 0; i < str.length; i++) {
+ var c = str.charCodeAt(i);
+ if (c < 128) {
+ out[p++] = c;
+ } else if (c < 2048) {
+ out[p++] = (c >> 6) | 192;
+ out[p++] = (c & 63) | 128;
+ } else {
+ out[p++] = (c >> 12) | 224;
+ out[p++] = ((c >> 6) & 63) | 128;
+ out[p++] = (c & 63) | 128;
+ }
+ }
+ return out;
+};
+
+
+/**
+ * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode.
+ * @param {Uint8Array|Array<number>} bytes UTF-8 byte array.
+ * @return {string} 16-bit Unicode string.
+ */
+goog.crypt.utf8ByteArrayToString = function(bytes) {
+ // TODO(user): Use native implementations if/when available
+ var out = [], pos = 0, c = 0;
+ while (pos < bytes.length) {
+ var c1 = bytes[pos++];
+ if (c1 < 128) {
+ out[c++] = String.fromCharCode(c1);
+ } else if (c1 > 191 && c1 < 224) {
+ var c2 = bytes[pos++];
+ out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
+ } else {
+ var c2 = bytes[pos++];
+ var c3 = bytes[pos++];
+ out[c++] = String.fromCharCode(
+ (c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
+ }
+ }
+ return out.join('');
+};
+
+
+/**
+ * XOR two byte arrays.
+ * @param {!ArrayBufferView|!Array<number>} bytes1 Byte array 1.
+ * @param {!ArrayBufferView|!Array<number>} bytes2 Byte array 2.
+ * @return {!Array<number>} Resulting XOR of the two byte arrays.
+ */
+goog.crypt.xorByteArray = function(bytes1, bytes2) {
+ goog.asserts.assert(
+ bytes1.length == bytes2.length,
+ 'XOR array lengths must match');
+
+ var result = [];
+ for (var i = 0; i < bytes1.length; i++) {
+ result.push(bytes1[i] ^ bytes2[i]);
+ }
+ return result;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/hash.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/hash.js b/externs/GCL/externs/goog/crypt/hash.js
new file mode 100644
index 0000000..51209be
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/hash.js
@@ -0,0 +1,69 @@
+// 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 Abstract cryptographic hash interface.
+ *
+ * See goog.crypt.Sha1 and goog.crypt.Md5 for sample implementations.
+ *
+ */
+
+goog.provide('goog.crypt.Hash');
+
+
+
+/**
+ * Create a cryptographic hash instance.
+ *
+ * @constructor
+ * @struct
+ */
+goog.crypt.Hash = function() {
+ /**
+ * The block size for the hasher.
+ * @type {number}
+ */
+ this.blockSize = -1;
+};
+
+
+/**
+ * Resets the internal accumulator.
+ */
+goog.crypt.Hash.prototype.reset = goog.abstractMethod;
+
+
+/**
+ * Adds a byte array (array with values in [0-255] range) or a string (might
+ * only contain 8-bit, i.e., Latin1 characters) to the internal accumulator.
+ *
+ * Many hash functions operate on blocks of data and implement optimizations
+ * when a full chunk of data is readily available. Hence it is often preferable
+ * to provide large chunks of data (a kilobyte or more) than to repeatedly
+ * call the update method with few tens of bytes. If this is not possible, or
+ * not feasible, it might be good to provide data in multiplies of hash block
+ * size (often 64 bytes). Please see the implementation and performance tests
+ * of your favourite hash.
+ *
+ * @param {Array<number>|Uint8Array|string} bytes Data used for the update.
+ * @param {number=} opt_length Number of bytes to use.
+ */
+goog.crypt.Hash.prototype.update = goog.abstractMethod;
+
+
+/**
+ * @return {!Array<number>} The finalized hash computed
+ * from the internal accumulator.
+ */
+goog.crypt.Hash.prototype.digest = goog.abstractMethod;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/hash32.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/hash32.js b/externs/GCL/externs/goog/crypt/hash32.js
new file mode 100644
index 0000000..fa24ccf
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/hash32.js
@@ -0,0 +1,184 @@
+// 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 Implementation of 32-bit hashing functions.
+ *
+ * This is a direct port from the Google Java Hash class
+ *
+ */
+
+goog.provide('goog.crypt.hash32');
+
+goog.require('goog.crypt');
+
+
+/**
+ * Default seed used during hashing, digits of pie.
+ * See SEED32 in http://go/base.hash.java
+ * @type {number}
+ */
+goog.crypt.hash32.SEED32 = 314159265;
+
+
+/**
+ * Arbitrary constant used during hashing.
+ * See CONSTANT32 in http://go/base.hash.java
+ * @type {number}
+ */
+goog.crypt.hash32.CONSTANT32 = -1640531527;
+
+
+/**
+ * Hashes a string to a 32-bit value.
+ * @param {string} str String to hash.
+ * @return {number} 32-bit hash.
+ */
+goog.crypt.hash32.encodeString = function(str) {
+ return goog.crypt.hash32.encodeByteArray(goog.crypt.stringToByteArray(str));
+};
+
+
+/**
+ * Hashes a string to a 32-bit value, converting the string to UTF-8 before
+ * doing the encoding.
+ * @param {string} str String to hash.
+ * @return {number} 32-bit hash.
+ */
+goog.crypt.hash32.encodeStringUtf8 = function(str) {
+ return goog.crypt.hash32.encodeByteArray(
+ goog.crypt.stringToUtf8ByteArray(str));
+};
+
+
+/**
+ * Hashes an integer to a 32-bit value.
+ * @param {number} value Number to hash.
+ * @return {number} 32-bit hash.
+ */
+goog.crypt.hash32.encodeInteger = function(value) {
+ // TODO(user): Does this make sense in JavaScript with doubles? Should we
+ // force the value to be in the correct range?
+ return goog.crypt.hash32.mix32_({
+ a: value,
+ b: goog.crypt.hash32.CONSTANT32,
+ c: goog.crypt.hash32.SEED32
+ });
+};
+
+
+/**
+ * Hashes a "byte" array to a 32-bit value using the supplied seed.
+ * @param {Array<number>} bytes Array of bytes.
+ * @param {number=} opt_offset The starting position to use for hash
+ * computation.
+ * @param {number=} opt_length Number of bytes that are used for hashing.
+ * @param {number=} opt_seed The seed.
+ * @return {number} 32-bit hash.
+ */
+goog.crypt.hash32.encodeByteArray = function(
+ bytes, opt_offset, opt_length, opt_seed) {
+ var offset = opt_offset || 0;
+ var length = opt_length || bytes.length;
+ var seed = opt_seed || goog.crypt.hash32.SEED32;
+
+ var mix = {
+ a: goog.crypt.hash32.CONSTANT32,
+ b: goog.crypt.hash32.CONSTANT32,
+ c: seed
+ };
+
+ var keylen;
+ for (keylen = length; keylen >= 12; keylen -= 12, offset += 12) {
+ mix.a += goog.crypt.hash32.wordAt_(bytes, offset);
+ mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4);
+ mix.c += goog.crypt.hash32.wordAt_(bytes, offset + 8);
+ goog.crypt.hash32.mix32_(mix);
+ }
+ // Hash any remaining bytes
+ mix.c += length;
+ switch (keylen) { // deal with rest. Some cases fall through
+ case 11: mix.c += (bytes[offset + 10]) << 24;
+ case 10: mix.c += (bytes[offset + 9] & 0xff) << 16;
+ case 9 : mix.c += (bytes[offset + 8] & 0xff) << 8;
+ // the first byte of c is reserved for the length
+ case 8 :
+ mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4);
+ mix.a += goog.crypt.hash32.wordAt_(bytes, offset);
+ break;
+ case 7 : mix.b += (bytes[offset + 6] & 0xff) << 16;
+ case 6 : mix.b += (bytes[offset + 5] & 0xff) << 8;
+ case 5 : mix.b += (bytes[offset + 4] & 0xff);
+ case 4 :
+ mix.a += goog.crypt.hash32.wordAt_(bytes, offset);
+ break;
+ case 3 : mix.a += (bytes[offset + 2] & 0xff) << 16;
+ case 2 : mix.a += (bytes[offset + 1] & 0xff) << 8;
+ case 1 : mix.a += (bytes[offset + 0] & 0xff);
+ // case 0 : nothing left to add
+ }
+ return goog.crypt.hash32.mix32_(mix);
+};
+
+
+/**
+ * Performs an inplace mix of an object with the integer properties (a, b, c)
+ * and returns the final value of c.
+ * @param {Object} mix Object with properties, a, b, and c.
+ * @return {number} The end c-value for the mixing.
+ * @private
+ */
+goog.crypt.hash32.mix32_ = function(mix) {
+ var a = mix.a, b = mix.b, c = mix.c;
+ a -= b; a -= c; a ^= c >>> 13;
+ b -= c; b -= a; b ^= a << 8;
+ c -= a; c -= b; c ^= b >>> 13;
+ a -= b; a -= c; a ^= c >>> 12;
+ b -= c; b -= a; b ^= a << 16;
+ c -= a; c -= b; c ^= b >>> 5;
+ a -= b; a -= c; a ^= c >>> 3;
+ b -= c; b -= a; b ^= a << 10;
+ c -= a; c -= b; c ^= b >>> 15;
+ mix.a = a; mix.b = b; mix.c = c;
+ return c;
+};
+
+
+/**
+ * Returns the word at a given offset. Treating an array of bytes a word at a
+ * time is far more efficient than byte-by-byte.
+ * @param {Array<number>} bytes Array of bytes.
+ * @param {number} offset Offset in the byte array.
+ * @return {number} Integer value for the word.
+ * @private
+ */
+goog.crypt.hash32.wordAt_ = function(bytes, offset) {
+ var a = goog.crypt.hash32.toSigned_(bytes[offset + 0]);
+ var b = goog.crypt.hash32.toSigned_(bytes[offset + 1]);
+ var c = goog.crypt.hash32.toSigned_(bytes[offset + 2]);
+ var d = goog.crypt.hash32.toSigned_(bytes[offset + 3]);
+ return a + (b << 8) + (c << 16) + (d << 24);
+};
+
+
+/**
+ * Converts an unsigned "byte" to signed, that is, convert a value in the range
+ * (0, 2^8-1) to (-2^7, 2^7-1) in order to be compatible with Java's byte type.
+ * @param {number} n Unsigned "byte" value.
+ * @return {number} Signed "byte" value.
+ * @private
+ */
+goog.crypt.hash32.toSigned_ = function(n) {
+ return n > 127 ? n - 256 : n;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/hmac.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/hmac.js b/externs/GCL/externs/goog/crypt/hmac.js
new file mode 100644
index 0000000..15e0e1d
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/hmac.js
@@ -0,0 +1,160 @@
+// 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 Implementation of HMAC in JavaScript.
+ *
+ * Usage:
+ * var hmac = new goog.crypt.Hmac(new goog.crypt.sha1(), key, 64);
+ * var digest = hmac.getHmac(bytes);
+ *
+ * @author benyu@google.com (Jige Yu) - port to closure
+ */
+
+
+goog.provide('goog.crypt.Hmac');
+
+goog.require('goog.crypt.Hash');
+
+
+
+/**
+ * @constructor
+ * @param {!goog.crypt.Hash} hasher An object to serve as a hash function.
+ * @param {Array<number>} key The secret key to use to calculate the hmac.
+ * Should be an array of not more than {@code blockSize} integers in
+ {0, 255}.
+ * @param {number=} opt_blockSize Optional. The block size {@code hasher} uses.
+ * If not specified, uses the block size from the hasher, or 16 if it is
+ * not specified.
+ * @extends {goog.crypt.Hash}
+ * @final
+ * @struct
+ */
+goog.crypt.Hmac = function(hasher, key, opt_blockSize) {
+ goog.crypt.Hmac.base(this, 'constructor');
+
+ /**
+ * The underlying hasher to calculate hash.
+ *
+ * @type {!goog.crypt.Hash}
+ * @private
+ */
+ this.hasher_ = hasher;
+
+ this.blockSize = opt_blockSize || hasher.blockSize || 16;
+
+ /**
+ * The outer padding array of hmac
+ *
+ * @type {!Array<number>}
+ * @private
+ */
+ this.keyO_ = new Array(this.blockSize);
+
+ /**
+ * The inner padding array of hmac
+ *
+ * @type {!Array<number>}
+ * @private
+ */
+ this.keyI_ = new Array(this.blockSize);
+
+ this.initialize_(key);
+};
+goog.inherits(goog.crypt.Hmac, goog.crypt.Hash);
+
+
+/**
+ * Outer padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
+ *
+ * @type {number}
+ * @private
+ */
+goog.crypt.Hmac.OPAD_ = 0x5c;
+
+
+/**
+ * Inner padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC
+ *
+ * @type {number}
+ * @private
+ */
+goog.crypt.Hmac.IPAD_ = 0x36;
+
+
+/**
+ * Initializes Hmac by precalculating the inner and outer paddings.
+ *
+ * @param {Array<number>} key The secret key to use to calculate the hmac.
+ * Should be an array of not more than {@code blockSize} integers in
+ {0, 255}.
+ * @private
+ */
+goog.crypt.Hmac.prototype.initialize_ = function(key) {
+ if (key.length > this.blockSize) {
+ this.hasher_.update(key);
+ key = this.hasher_.digest();
+ this.hasher_.reset();
+ }
+ // Precalculate padded and xor'd keys.
+ var keyByte;
+ for (var i = 0; i < this.blockSize; i++) {
+ if (i < key.length) {
+ keyByte = key[i];
+ } else {
+ keyByte = 0;
+ }
+ this.keyO_[i] = keyByte ^ goog.crypt.Hmac.OPAD_;
+ this.keyI_[i] = keyByte ^ goog.crypt.Hmac.IPAD_;
+ }
+ // Be ready for an immediate update.
+ this.hasher_.update(this.keyI_);
+};
+
+
+/** @override */
+goog.crypt.Hmac.prototype.reset = function() {
+ this.hasher_.reset();
+ this.hasher_.update(this.keyI_);
+};
+
+
+/** @override */
+goog.crypt.Hmac.prototype.update = function(bytes, opt_length) {
+ this.hasher_.update(bytes, opt_length);
+};
+
+
+/** @override */
+goog.crypt.Hmac.prototype.digest = function() {
+ var temp = this.hasher_.digest();
+ this.hasher_.reset();
+ this.hasher_.update(this.keyO_);
+ this.hasher_.update(temp);
+ return this.hasher_.digest();
+};
+
+
+/**
+ * Calculates an HMAC for a given message.
+ *
+ * @param {Array<number>|Uint8Array|string} message Data to Hmac.
+ * @return {!Array<number>} the digest of the given message.
+ */
+goog.crypt.Hmac.prototype.getHmac = function(message) {
+ this.reset();
+ this.update(message);
+ return this.digest();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/md5.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/md5.js b/externs/GCL/externs/goog/crypt/md5.js
new file mode 100644
index 0000000..56335e1
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/md5.js
@@ -0,0 +1,435 @@
+// 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 MD5 cryptographic hash.
+ * Implementation of http://tools.ietf.org/html/rfc1321 with common
+ * optimizations and tweaks (see http://en.wikipedia.org/wiki/MD5).
+ *
+ * Usage:
+ * var md5 = new goog.crypt.Md5();
+ * md5.update(bytes);
+ * var hash = md5.digest();
+ *
+ * Performance:
+ * Chrome 23 ~680 Mbit/s
+ * Chrome 13 (in a VM) ~250 Mbit/s
+ * Firefox 6.0 (in a VM) ~100 Mbit/s
+ * IE9 (in a VM) ~27 Mbit/s
+ * Firefox 3.6 ~15 Mbit/s
+ * IE8 (in a VM) ~13 Mbit/s
+ *
+ */
+
+goog.provide('goog.crypt.Md5');
+
+goog.require('goog.crypt.Hash');
+
+
+
+/**
+ * MD5 cryptographic hash constructor.
+ * @constructor
+ * @extends {goog.crypt.Hash}
+ * @final
+ * @struct
+ */
+goog.crypt.Md5 = function() {
+ goog.crypt.Md5.base(this, 'constructor');
+
+ this.blockSize = 512 / 8;
+
+ /**
+ * Holds the current values of accumulated A-D variables (MD buffer).
+ * @type {!Array<number>}
+ * @private
+ */
+ this.chain_ = new Array(4);
+
+ /**
+ * A buffer holding the data until the whole block can be processed.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.block_ = new Array(this.blockSize);
+
+ /**
+ * The length of yet-unprocessed data as collected in the block.
+ * @type {number}
+ * @private
+ */
+ this.blockLength_ = 0;
+
+ /**
+ * The total length of the message so far.
+ * @type {number}
+ * @private
+ */
+ this.totalLength_ = 0;
+
+ this.reset();
+};
+goog.inherits(goog.crypt.Md5, goog.crypt.Hash);
+
+
+/**
+ * Integer rotation constants used by the abbreviated implementation.
+ * They are hardcoded in the unrolled implementation, so it is left
+ * here commented out.
+ * @type {Array<number>}
+ * @private
+ *
+goog.crypt.Md5.S_ = [
+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
+];
+ */
+
+/**
+ * Sine function constants used by the abbreviated implementation.
+ * They are hardcoded in the unrolled implementation, so it is left
+ * here commented out.
+ * @type {Array<number>}
+ * @private
+ *
+goog.crypt.Md5.T_ = [
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+];
+ */
+
+
+/** @override */
+goog.crypt.Md5.prototype.reset = function() {
+ this.chain_[0] = 0x67452301;
+ this.chain_[1] = 0xefcdab89;
+ this.chain_[2] = 0x98badcfe;
+ this.chain_[3] = 0x10325476;
+
+ this.blockLength_ = 0;
+ this.totalLength_ = 0;
+};
+
+
+/**
+ * Internal compress helper function. It takes a block of data (64 bytes)
+ * and updates the accumulator.
+ * @param {Array<number>|Uint8Array|string} buf The block to compress.
+ * @param {number=} opt_offset Offset of the block in the buffer.
+ * @private
+ */
+goog.crypt.Md5.prototype.compress_ = function(buf, opt_offset) {
+ if (!opt_offset) {
+ opt_offset = 0;
+ }
+
+ // We allocate the array every time, but it's cheap in practice.
+ var X = new Array(16);
+
+ // Get 16 little endian words. It is not worth unrolling this for Chrome 11.
+ if (goog.isString(buf)) {
+ for (var i = 0; i < 16; ++i) {
+ X[i] = (buf.charCodeAt(opt_offset++)) |
+ (buf.charCodeAt(opt_offset++) << 8) |
+ (buf.charCodeAt(opt_offset++) << 16) |
+ (buf.charCodeAt(opt_offset++) << 24);
+ }
+ } else {
+ for (var i = 0; i < 16; ++i) {
+ X[i] = (buf[opt_offset++]) |
+ (buf[opt_offset++] << 8) |
+ (buf[opt_offset++] << 16) |
+ (buf[opt_offset++] << 24);
+ }
+ }
+
+ var A = this.chain_[0];
+ var B = this.chain_[1];
+ var C = this.chain_[2];
+ var D = this.chain_[3];
+ var sum = 0;
+
+ /*
+ * This is an abbreviated implementation, it is left here commented out for
+ * reference purposes. See below for an unrolled version in use.
+ *
+ var f, n, tmp;
+ for (var i = 0; i < 64; ++i) {
+
+ if (i < 16) {
+ f = (D ^ (B & (C ^ D)));
+ n = i;
+ } else if (i < 32) {
+ f = (C ^ (D & (B ^ C)));
+ n = (5 * i + 1) % 16;
+ } else if (i < 48) {
+ f = (B ^ C ^ D);
+ n = (3 * i + 5) % 16;
+ } else {
+ f = (C ^ (B | (~D)));
+ n = (7 * i) % 16;
+ }
+
+ tmp = D;
+ D = C;
+ C = B;
+ sum = (A + f + goog.crypt.Md5.T_[i] + X[n]) & 0xffffffff;
+ B += ((sum << goog.crypt.Md5.S_[i]) & 0xffffffff) |
+ (sum >>> (32 - goog.crypt.Md5.S_[i]));
+ A = tmp;
+ }
+ */
+
+ /*
+ * This is an unrolled MD5 implementation, which gives ~30% speedup compared
+ * to the abbreviated implementation above, as measured on Chrome 11. It is
+ * important to keep 32-bit croppings to minimum and inline the integer
+ * rotation.
+ */
+ sum = (A + (D ^ (B & (C ^ D))) + X[0] + 0xd76aa478) & 0xffffffff;
+ A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
+ sum = (D + (C ^ (A & (B ^ C))) + X[1] + 0xe8c7b756) & 0xffffffff;
+ D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
+ sum = (C + (B ^ (D & (A ^ B))) + X[2] + 0x242070db) & 0xffffffff;
+ C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
+ sum = (B + (A ^ (C & (D ^ A))) + X[3] + 0xc1bdceee) & 0xffffffff;
+ B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
+ sum = (A + (D ^ (B & (C ^ D))) + X[4] + 0xf57c0faf) & 0xffffffff;
+ A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
+ sum = (D + (C ^ (A & (B ^ C))) + X[5] + 0x4787c62a) & 0xffffffff;
+ D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
+ sum = (C + (B ^ (D & (A ^ B))) + X[6] + 0xa8304613) & 0xffffffff;
+ C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
+ sum = (B + (A ^ (C & (D ^ A))) + X[7] + 0xfd469501) & 0xffffffff;
+ B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
+ sum = (A + (D ^ (B & (C ^ D))) + X[8] + 0x698098d8) & 0xffffffff;
+ A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
+ sum = (D + (C ^ (A & (B ^ C))) + X[9] + 0x8b44f7af) & 0xffffffff;
+ D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
+ sum = (C + (B ^ (D & (A ^ B))) + X[10] + 0xffff5bb1) & 0xffffffff;
+ C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
+ sum = (B + (A ^ (C & (D ^ A))) + X[11] + 0x895cd7be) & 0xffffffff;
+ B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
+ sum = (A + (D ^ (B & (C ^ D))) + X[12] + 0x6b901122) & 0xffffffff;
+ A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25));
+ sum = (D + (C ^ (A & (B ^ C))) + X[13] + 0xfd987193) & 0xffffffff;
+ D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20));
+ sum = (C + (B ^ (D & (A ^ B))) + X[14] + 0xa679438e) & 0xffffffff;
+ C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15));
+ sum = (B + (A ^ (C & (D ^ A))) + X[15] + 0x49b40821) & 0xffffffff;
+ B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10));
+ sum = (A + (C ^ (D & (B ^ C))) + X[1] + 0xf61e2562) & 0xffffffff;
+ A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
+ sum = (D + (B ^ (C & (A ^ B))) + X[6] + 0xc040b340) & 0xffffffff;
+ D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
+ sum = (C + (A ^ (B & (D ^ A))) + X[11] + 0x265e5a51) & 0xffffffff;
+ C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
+ sum = (B + (D ^ (A & (C ^ D))) + X[0] + 0xe9b6c7aa) & 0xffffffff;
+ B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
+ sum = (A + (C ^ (D & (B ^ C))) + X[5] + 0xd62f105d) & 0xffffffff;
+ A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
+ sum = (D + (B ^ (C & (A ^ B))) + X[10] + 0x02441453) & 0xffffffff;
+ D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
+ sum = (C + (A ^ (B & (D ^ A))) + X[15] + 0xd8a1e681) & 0xffffffff;
+ C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
+ sum = (B + (D ^ (A & (C ^ D))) + X[4] + 0xe7d3fbc8) & 0xffffffff;
+ B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
+ sum = (A + (C ^ (D & (B ^ C))) + X[9] + 0x21e1cde6) & 0xffffffff;
+ A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
+ sum = (D + (B ^ (C & (A ^ B))) + X[14] + 0xc33707d6) & 0xffffffff;
+ D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
+ sum = (C + (A ^ (B & (D ^ A))) + X[3] + 0xf4d50d87) & 0xffffffff;
+ C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
+ sum = (B + (D ^ (A & (C ^ D))) + X[8] + 0x455a14ed) & 0xffffffff;
+ B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
+ sum = (A + (C ^ (D & (B ^ C))) + X[13] + 0xa9e3e905) & 0xffffffff;
+ A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27));
+ sum = (D + (B ^ (C & (A ^ B))) + X[2] + 0xfcefa3f8) & 0xffffffff;
+ D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23));
+ sum = (C + (A ^ (B & (D ^ A))) + X[7] + 0x676f02d9) & 0xffffffff;
+ C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18));
+ sum = (B + (D ^ (A & (C ^ D))) + X[12] + 0x8d2a4c8a) & 0xffffffff;
+ B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12));
+ sum = (A + (B ^ C ^ D) + X[5] + 0xfffa3942) & 0xffffffff;
+ A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
+ sum = (D + (A ^ B ^ C) + X[8] + 0x8771f681) & 0xffffffff;
+ D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
+ sum = (C + (D ^ A ^ B) + X[11] + 0x6d9d6122) & 0xffffffff;
+ C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
+ sum = (B + (C ^ D ^ A) + X[14] + 0xfde5380c) & 0xffffffff;
+ B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
+ sum = (A + (B ^ C ^ D) + X[1] + 0xa4beea44) & 0xffffffff;
+ A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
+ sum = (D + (A ^ B ^ C) + X[4] + 0x4bdecfa9) & 0xffffffff;
+ D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
+ sum = (C + (D ^ A ^ B) + X[7] + 0xf6bb4b60) & 0xffffffff;
+ C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
+ sum = (B + (C ^ D ^ A) + X[10] + 0xbebfbc70) & 0xffffffff;
+ B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
+ sum = (A + (B ^ C ^ D) + X[13] + 0x289b7ec6) & 0xffffffff;
+ A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
+ sum = (D + (A ^ B ^ C) + X[0] + 0xeaa127fa) & 0xffffffff;
+ D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
+ sum = (C + (D ^ A ^ B) + X[3] + 0xd4ef3085) & 0xffffffff;
+ C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
+ sum = (B + (C ^ D ^ A) + X[6] + 0x04881d05) & 0xffffffff;
+ B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
+ sum = (A + (B ^ C ^ D) + X[9] + 0xd9d4d039) & 0xffffffff;
+ A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28));
+ sum = (D + (A ^ B ^ C) + X[12] + 0xe6db99e5) & 0xffffffff;
+ D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21));
+ sum = (C + (D ^ A ^ B) + X[15] + 0x1fa27cf8) & 0xffffffff;
+ C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16));
+ sum = (B + (C ^ D ^ A) + X[2] + 0xc4ac5665) & 0xffffffff;
+ B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9));
+ sum = (A + (C ^ (B | (~D))) + X[0] + 0xf4292244) & 0xffffffff;
+ A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
+ sum = (D + (B ^ (A | (~C))) + X[7] + 0x432aff97) & 0xffffffff;
+ D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
+ sum = (C + (A ^ (D | (~B))) + X[14] + 0xab9423a7) & 0xffffffff;
+ C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
+ sum = (B + (D ^ (C | (~A))) + X[5] + 0xfc93a039) & 0xffffffff;
+ B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
+ sum = (A + (C ^ (B | (~D))) + X[12] + 0x655b59c3) & 0xffffffff;
+ A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
+ sum = (D + (B ^ (A | (~C))) + X[3] + 0x8f0ccc92) & 0xffffffff;
+ D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
+ sum = (C + (A ^ (D | (~B))) + X[10] + 0xffeff47d) & 0xffffffff;
+ C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
+ sum = (B + (D ^ (C | (~A))) + X[1] + 0x85845dd1) & 0xffffffff;
+ B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
+ sum = (A + (C ^ (B | (~D))) + X[8] + 0x6fa87e4f) & 0xffffffff;
+ A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
+ sum = (D + (B ^ (A | (~C))) + X[15] + 0xfe2ce6e0) & 0xffffffff;
+ D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
+ sum = (C + (A ^ (D | (~B))) + X[6] + 0xa3014314) & 0xffffffff;
+ C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
+ sum = (B + (D ^ (C | (~A))) + X[13] + 0x4e0811a1) & 0xffffffff;
+ B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
+ sum = (A + (C ^ (B | (~D))) + X[4] + 0xf7537e82) & 0xffffffff;
+ A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26));
+ sum = (D + (B ^ (A | (~C))) + X[11] + 0xbd3af235) & 0xffffffff;
+ D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22));
+ sum = (C + (A ^ (D | (~B))) + X[2] + 0x2ad7d2bb) & 0xffffffff;
+ C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17));
+ sum = (B + (D ^ (C | (~A))) + X[9] + 0xeb86d391) & 0xffffffff;
+ B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11));
+
+ this.chain_[0] = (this.chain_[0] + A) & 0xffffffff;
+ this.chain_[1] = (this.chain_[1] + B) & 0xffffffff;
+ this.chain_[2] = (this.chain_[2] + C) & 0xffffffff;
+ this.chain_[3] = (this.chain_[3] + D) & 0xffffffff;
+};
+
+
+/** @override */
+goog.crypt.Md5.prototype.update = function(bytes, opt_length) {
+ if (!goog.isDef(opt_length)) {
+ opt_length = bytes.length;
+ }
+ var lengthMinusBlock = opt_length - this.blockSize;
+
+ // Copy some object properties to local variables in order to save on access
+ // time from inside the loop (~10% speedup was observed on Chrome 11).
+ var block = this.block_;
+ var blockLength = this.blockLength_;
+ var i = 0;
+
+ // The outer while loop should execute at most twice.
+ while (i < opt_length) {
+ // When we have no data in the block to top up, we can directly process the
+ // input buffer (assuming it contains sufficient data). This gives ~30%
+ // speedup on Chrome 14 and ~70% speedup on Firefox 6.0, but requires that
+ // the data is provided in large chunks (or in multiples of 64 bytes).
+ if (blockLength == 0) {
+ while (i <= lengthMinusBlock) {
+ this.compress_(bytes, i);
+ i += this.blockSize;
+ }
+ }
+
+ if (goog.isString(bytes)) {
+ while (i < opt_length) {
+ block[blockLength++] = bytes.charCodeAt(i++);
+ if (blockLength == this.blockSize) {
+ this.compress_(block);
+ blockLength = 0;
+ // Jump to the outer loop so we use the full-block optimization.
+ break;
+ }
+ }
+ } else {
+ while (i < opt_length) {
+ block[blockLength++] = bytes[i++];
+ if (blockLength == this.blockSize) {
+ this.compress_(block);
+ blockLength = 0;
+ // Jump to the outer loop so we use the full-block optimization.
+ break;
+ }
+ }
+ }
+ }
+
+ this.blockLength_ = blockLength;
+ this.totalLength_ += opt_length;
+};
+
+
+/** @override */
+goog.crypt.Md5.prototype.digest = function() {
+ // This must accommodate at least 1 padding byte (0x80), 8 bytes of
+ // total bitlength, and must end at a 64-byte boundary.
+ var pad = new Array((this.blockLength_ < 56 ?
+ this.blockSize :
+ this.blockSize * 2) - this.blockLength_);
+
+ // Add padding: 0x80 0x00*
+ pad[0] = 0x80;
+ for (var i = 1; i < pad.length - 8; ++i) {
+ pad[i] = 0;
+ }
+ // Add the total number of bits, little endian 64-bit integer.
+ var totalBits = this.totalLength_ * 8;
+ for (var i = pad.length - 8; i < pad.length; ++i) {
+ pad[i] = totalBits & 0xff;
+ totalBits /= 0x100; // Don't use bit-shifting here!
+ }
+ this.update(pad);
+
+ var digest = new Array(16);
+ var n = 0;
+ for (var i = 0; i < 4; ++i) {
+ for (var j = 0; j < 32; j += 8) {
+ digest[n++] = (this.chain_[i] >>> j) & 0xff;
+ }
+ }
+ return digest;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/pbkdf2.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/pbkdf2.js b/externs/GCL/externs/goog/crypt/pbkdf2.js
new file mode 100644
index 0000000..2fd1807
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/pbkdf2.js
@@ -0,0 +1,128 @@
+// Copyright 2012 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 Implementation of PBKDF2 in JavaScript.
+ * @see http://en.wikipedia.org/wiki/PBKDF2
+ *
+ * Currently we only support HMAC-SHA1 as the underlying hash function. To add a
+ * new hash function, add a static method similar to deriveKeyFromPasswordSha1()
+ * and implement the specific computeBlockCallback() using the hash function.
+ *
+ * Usage:
+ * var key = pbkdf2.deriveKeySha1(
+ * stringToByteArray('password'), stringToByteArray('salt'), 1000, 128);
+ *
+ */
+
+goog.provide('goog.crypt.pbkdf2');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.crypt');
+goog.require('goog.crypt.Hmac');
+goog.require('goog.crypt.Sha1');
+
+
+/**
+ * Derives key from password using PBKDF2-SHA1
+ * @param {!Array<number>} password Byte array representation of the password
+ * from which the key is derived.
+ * @param {!Array<number>} initialSalt Byte array representation of the salt.
+ * @param {number} iterations Number of interations when computing the key.
+ * @param {number} keyLength Length of the output key in bits.
+ * Must be multiple of 8.
+ * @return {!Array<number>} Byte array representation of the output key.
+ */
+goog.crypt.pbkdf2.deriveKeySha1 = function(
+ password, initialSalt, iterations, keyLength) {
+ // Length of the HMAC-SHA1 output in bits.
+ var HASH_LENGTH = 160;
+
+ /**
+ * Compute each block of the key using HMAC-SHA1.
+ * @param {!Array<number>} index Byte array representation of the index of
+ * the block to be computed.
+ * @return {!Array<number>} Byte array representation of the output block.
+ */
+ var computeBlock = function(index) {
+ // Initialize the result to be array of 0 such that its xor with the first
+ // block would be the first block.
+ var result = goog.array.repeat(0, HASH_LENGTH / 8);
+ // Initialize the salt of the first iteration to initialSalt || i.
+ var salt = initialSalt.concat(index);
+ var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), password, 64);
+ // Compute and XOR each iteration.
+ for (var i = 0; i < iterations; i++) {
+ // The salt of the next iteration is the result of the current iteration.
+ salt = hmac.getHmac(salt);
+ result = goog.crypt.xorByteArray(result, salt);
+ }
+ return result;
+ };
+
+ return goog.crypt.pbkdf2.deriveKeyFromPassword_(
+ computeBlock, HASH_LENGTH, keyLength);
+};
+
+
+/**
+ * Compute each block of the key using PBKDF2.
+ * @param {Function} computeBlock Function to compute each block of the output
+ * key.
+ * @param {number} hashLength Length of each block in bits. This is determined
+ * by the specific hash function used. Must be multiple of 8.
+ * @param {number} keyLength Length of the output key in bits.
+ * Must be multiple of 8.
+ * @return {!Array<number>} Byte array representation of the output key.
+ * @private
+ */
+goog.crypt.pbkdf2.deriveKeyFromPassword_ =
+ function(computeBlock, hashLength, keyLength) {
+ goog.asserts.assert(keyLength % 8 == 0, 'invalid output key length');
+
+ // Compute and concactate each block of the output key.
+ var numBlocks = Math.ceil(keyLength / hashLength);
+ goog.asserts.assert(numBlocks >= 1, 'invalid number of blocks');
+ var result = [];
+ for (var i = 1; i <= numBlocks; i++) {
+ var indexBytes = goog.crypt.pbkdf2.integerToByteArray_(i);
+ result = result.concat(computeBlock(indexBytes));
+ }
+
+ // Trim the last block if needed.
+ var lastBlockSize = keyLength % hashLength;
+ if (lastBlockSize != 0) {
+ var desiredBytes = ((numBlocks - 1) * hashLength + lastBlockSize) / 8;
+ result.splice(desiredBytes, (hashLength - lastBlockSize) / 8);
+ }
+ return result;
+};
+
+
+/**
+ * Converts an integer number to a 32-bit big endian byte array.
+ * @param {number} n Integer number to be converted.
+ * @return {!Array<number>} Byte Array representation of the 32-bit big endian
+ * encoding of n.
+ * @private
+ */
+goog.crypt.pbkdf2.integerToByteArray_ = function(n) {
+ var result = new Array(4);
+ result[0] = n >> 24 & 0xFF;
+ result[1] = n >> 16 & 0xFF;
+ result[2] = n >> 8 & 0xFF;
+ result[3] = n & 0xFF;
+ return result;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha1.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha1.js b/externs/GCL/externs/goog/crypt/sha1.js
new file mode 100644
index 0000000..b1a5219
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha1.js
@@ -0,0 +1,294 @@
+// 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 SHA-1 cryptographic hash.
+ * Variable names follow the notation in FIPS PUB 180-3:
+ * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
+ *
+ * Usage:
+ * var sha1 = new goog.crypt.sha1();
+ * sha1.update(bytes);
+ * var hash = sha1.digest();
+ *
+ * Performance:
+ * Chrome 23: ~400 Mbit/s
+ * Firefox 16: ~250 Mbit/s
+ *
+ */
+
+goog.provide('goog.crypt.Sha1');
+
+goog.require('goog.crypt.Hash');
+
+
+
+/**
+ * SHA-1 cryptographic hash constructor.
+ *
+ * The properties declared here are discussed in the above algorithm document.
+ * @constructor
+ * @extends {goog.crypt.Hash}
+ * @final
+ * @struct
+ */
+goog.crypt.Sha1 = function() {
+ goog.crypt.Sha1.base(this, 'constructor');
+
+ this.blockSize = 512 / 8;
+
+ /**
+ * Holds the previous values of accumulated variables a-e in the compress_
+ * function.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.chain_ = [];
+
+ /**
+ * A buffer holding the partially computed hash result.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.buf_ = [];
+
+ /**
+ * An array of 80 bytes, each a part of the message to be hashed. Referred to
+ * as the message schedule in the docs.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.W_ = [];
+
+ /**
+ * Contains data needed to pad messages less than 64 bytes.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.pad_ = [];
+
+ this.pad_[0] = 128;
+ for (var i = 1; i < this.blockSize; ++i) {
+ this.pad_[i] = 0;
+ }
+
+ /**
+ * @private {number}
+ */
+ this.inbuf_ = 0;
+
+ /**
+ * @private {number}
+ */
+ this.total_ = 0;
+
+ this.reset();
+};
+goog.inherits(goog.crypt.Sha1, goog.crypt.Hash);
+
+
+/** @override */
+goog.crypt.Sha1.prototype.reset = function() {
+ this.chain_[0] = 0x67452301;
+ this.chain_[1] = 0xefcdab89;
+ this.chain_[2] = 0x98badcfe;
+ this.chain_[3] = 0x10325476;
+ this.chain_[4] = 0xc3d2e1f0;
+
+ this.inbuf_ = 0;
+ this.total_ = 0;
+};
+
+
+/**
+ * Internal compress helper function.
+ * @param {!Array<number>|!Uint8Array|string} buf Block to compress.
+ * @param {number=} opt_offset Offset of the block in the buffer.
+ * @private
+ */
+goog.crypt.Sha1.prototype.compress_ = function(buf, opt_offset) {
+ if (!opt_offset) {
+ opt_offset = 0;
+ }
+
+ var W = this.W_;
+
+ // get 16 big endian words
+ if (goog.isString(buf)) {
+ for (var i = 0; i < 16; i++) {
+ // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS
+ // have a bug that turns the post-increment ++ operator into pre-increment
+ // during JIT compilation. We have code that depends heavily on SHA-1 for
+ // correctness and which is affected by this bug, so I've removed all uses
+ // of post-increment ++ in which the result value is used. We can revert
+ // this change once the Safari bug
+ // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and
+ // most clients have been updated.
+ W[i] = (buf.charCodeAt(opt_offset) << 24) |
+ (buf.charCodeAt(opt_offset + 1) << 16) |
+ (buf.charCodeAt(opt_offset + 2) << 8) |
+ (buf.charCodeAt(opt_offset + 3));
+ opt_offset += 4;
+ }
+ } else {
+ for (var i = 0; i < 16; i++) {
+ W[i] = (buf[opt_offset] << 24) |
+ (buf[opt_offset + 1] << 16) |
+ (buf[opt_offset + 2] << 8) |
+ (buf[opt_offset + 3]);
+ opt_offset += 4;
+ }
+ }
+
+ // expand to 80 words
+ for (var i = 16; i < 80; i++) {
+ var t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
+ W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff;
+ }
+
+ var a = this.chain_[0];
+ var b = this.chain_[1];
+ var c = this.chain_[2];
+ var d = this.chain_[3];
+ var e = this.chain_[4];
+ var f, k;
+
+ // TODO(user): Try to unroll this loop to speed up the computation.
+ for (var i = 0; i < 80; i++) {
+ if (i < 40) {
+ if (i < 20) {
+ f = d ^ (b & (c ^ d));
+ k = 0x5a827999;
+ } else {
+ f = b ^ c ^ d;
+ k = 0x6ed9eba1;
+ }
+ } else {
+ if (i < 60) {
+ f = (b & c) | (d & (b | c));
+ k = 0x8f1bbcdc;
+ } else {
+ f = b ^ c ^ d;
+ k = 0xca62c1d6;
+ }
+ }
+
+ var t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff;
+ e = d;
+ d = c;
+ c = ((b << 30) | (b >>> 2)) & 0xffffffff;
+ b = a;
+ a = t;
+ }
+
+ this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;
+ this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;
+ this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;
+ this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;
+ this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;
+};
+
+
+/** @override */
+goog.crypt.Sha1.prototype.update = function(bytes, opt_length) {
+ // TODO(johnlenz): tighten the function signature and remove this check
+ if (bytes == null) {
+ return;
+ }
+
+ if (!goog.isDef(opt_length)) {
+ opt_length = bytes.length;
+ }
+
+ var lengthMinusBlock = opt_length - this.blockSize;
+ var n = 0;
+ // Using local instead of member variables gives ~5% speedup on Firefox 16.
+ var buf = this.buf_;
+ var inbuf = this.inbuf_;
+
+ // The outer while loop should execute at most twice.
+ while (n < opt_length) {
+ // When we have no data in the block to top up, we can directly process the
+ // input buffer (assuming it contains sufficient data). This gives ~25%
+ // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that
+ // the data is provided in large chunks (or in multiples of 64 bytes).
+ if (inbuf == 0) {
+ while (n <= lengthMinusBlock) {
+ this.compress_(bytes, n);
+ n += this.blockSize;
+ }
+ }
+
+ if (goog.isString(bytes)) {
+ while (n < opt_length) {
+ buf[inbuf] = bytes.charCodeAt(n);
+ ++inbuf;
+ ++n;
+ if (inbuf == this.blockSize) {
+ this.compress_(buf);
+ inbuf = 0;
+ // Jump to the outer loop so we use the full-block optimization.
+ break;
+ }
+ }
+ } else {
+ while (n < opt_length) {
+ buf[inbuf] = bytes[n];
+ ++inbuf;
+ ++n;
+ if (inbuf == this.blockSize) {
+ this.compress_(buf);
+ inbuf = 0;
+ // Jump to the outer loop so we use the full-block optimization.
+ break;
+ }
+ }
+ }
+ }
+
+ this.inbuf_ = inbuf;
+ this.total_ += opt_length;
+};
+
+
+/** @override */
+goog.crypt.Sha1.prototype.digest = function() {
+ var digest = [];
+ var totalBits = this.total_ * 8;
+
+ // Add pad 0x80 0x00*.
+ if (this.inbuf_ < 56) {
+ this.update(this.pad_, 56 - this.inbuf_);
+ } else {
+ this.update(this.pad_, this.blockSize - (this.inbuf_ - 56));
+ }
+
+ // Add # bits.
+ for (var i = this.blockSize - 1; i >= 56; i--) {
+ this.buf_[i] = totalBits & 255;
+ totalBits /= 256; // Don't use bit-shifting here!
+ }
+
+ this.compress_(this.buf_);
+
+ var n = 0;
+ for (var i = 0; i < 5; i++) {
+ for (var j = 24; j >= 0; j -= 8) {
+ digest[n] = (this.chain_[i] >> j) & 255;
+ ++n;
+ }
+ }
+
+ return digest;
+};
[46/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/bootstrap/webworkers.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/bootstrap/webworkers.js b/externs/GCL/externs/goog/bootstrap/webworkers.js
new file mode 100644
index 0000000..7799a0a
--- /dev/null
+++ b/externs/GCL/externs/goog/bootstrap/webworkers.js
@@ -0,0 +1,37 @@
+// 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 A bootstrap for dynamically requiring Closure within an HTML5
+ * Web Worker context. To use this, first set CLOSURE_BASE_PATH to the directory
+ * containing base.js (relative to the main script), then use importScripts to
+ * load this file and base.js (in that order). After this you can use
+ * goog.require for further imports.
+ *
+ * @nocompile
+ */
+
+
+/**
+ * Imports a script using the Web Worker importScript API.
+ *
+ * @param {string} src The script source.
+ * @return {boolean} True if the script was imported, false otherwise.
+ */
+this.CLOSURE_IMPORT_SCRIPT = (function(global) {
+ return function(src) {
+ global['importScripts'](src);
+ return true;
+ };
+})(this);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/color/alpha.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/color/alpha.js b/externs/GCL/externs/goog/color/alpha.js
new file mode 100644
index 0000000..4cd4781
--- /dev/null
+++ b/externs/GCL/externs/goog/color/alpha.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 related to alpha/transparent colors and alpha color
+ * conversion.
+ */
+
+goog.provide('goog.color.alpha');
+
+goog.require('goog.color');
+
+
+/**
+ * Parses an alpha color out of a string.
+ * @param {string} str Color in some format.
+ * @return {{hex: string, type: string}} 'hex' is a string containing
+ * a hex representation of the color, and 'type' is a string
+ * containing the type of color format passed in ('hex', 'rgb', 'named').
+ */
+goog.color.alpha.parse = function(str) {
+ var result = {};
+ str = String(str);
+
+ var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
+ if (goog.color.alpha.isValidAlphaHexColor_(maybeHex)) {
+ result.hex = goog.color.alpha.normalizeAlphaHex_(maybeHex);
+ result.type = 'hex';
+ return result;
+ } else {
+ var rgba = goog.color.alpha.isValidRgbaColor_(str);
+ if (rgba.length) {
+ result.hex = goog.color.alpha.rgbaArrayToHex(rgba);
+ result.type = 'rgba';
+ return result;
+ } else {
+ var hsla = goog.color.alpha.isValidHslaColor_(str);
+ if (hsla.length) {
+ result.hex = goog.color.alpha.hslaArrayToHex(hsla);
+ result.type = 'hsla';
+ return result;
+ }
+ }
+ }
+ throw Error(str + ' is not a valid color string');
+};
+
+
+/**
+ * Converts a hex representation of a color to RGBA.
+ * @param {string} hexColor Color to convert.
+ * @return {string} string of the form 'rgba(R,G,B,A)' which can be used in
+ * styles.
+ */
+goog.color.alpha.hexToRgbaStyle = function(hexColor) {
+ return goog.color.alpha.rgbaStyle_(goog.color.alpha.hexToRgba(hexColor));
+};
+
+
+/**
+ * Gets the hex color part of an alpha hex color. For example, from '#abcdef55'
+ * return '#abcdef'.
+ * @param {string} colorWithAlpha The alpha hex color to get the hex color from.
+ * @return {string} The hex color where the alpha part has been stripped off.
+ */
+goog.color.alpha.extractHexColor = function(colorWithAlpha) {
+ if (goog.color.alpha.isValidAlphaHexColor_(colorWithAlpha)) {
+ var fullColor = goog.color.prependHashIfNecessaryHelper(colorWithAlpha);
+ var normalizedColor = goog.color.alpha.normalizeAlphaHex_(fullColor);
+ return normalizedColor.substring(0, 7);
+ } else {
+ throw Error(colorWithAlpha + ' is not a valid 8-hex color string');
+ }
+};
+
+
+/**
+ * Gets the alpha color part of an alpha hex color. For example, from
+ * '#abcdef55' return '55'. The result is guaranteed to be two characters long.
+ * @param {string} colorWithAlpha The alpha hex color to get the hex color from.
+ * @return {string} The hex color where the alpha part has been stripped off.
+ */
+goog.color.alpha.extractAlpha = function(colorWithAlpha) {
+ if (goog.color.alpha.isValidAlphaHexColor_(colorWithAlpha)) {
+ var fullColor = goog.color.prependHashIfNecessaryHelper(colorWithAlpha);
+ var normalizedColor = goog.color.alpha.normalizeAlphaHex_(fullColor);
+ return normalizedColor.substring(7, 9);
+ } else {
+ throw Error(colorWithAlpha + ' is not a valid 8-hex color string');
+ }
+};
+
+
+/**
+ * Regular expression for extracting the digits in a hex color quadruplet.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.hexQuadrupletRe_ = /#(.)(.)(.)(.)/;
+
+
+/**
+ * Normalize a hex representation of an alpha color.
+ * @param {string} hexColor an alpha hex color string.
+ * @return {string} hex color in the format '#rrggbbaa' with all lowercase
+ * literals.
+ * @private
+ */
+goog.color.alpha.normalizeAlphaHex_ = function(hexColor) {
+ if (!goog.color.alpha.isValidAlphaHexColor_(hexColor)) {
+ throw Error("'" + hexColor + "' is not a valid alpha hex color");
+ }
+ if (hexColor.length == 5) { // of the form #RGBA
+ hexColor = hexColor.replace(goog.color.alpha.hexQuadrupletRe_,
+ '#$1$1$2$2$3$3$4$4');
+ }
+ return hexColor.toLowerCase();
+};
+
+
+/**
+ * Converts an 8-hex representation of a color to RGBA.
+ * @param {string} hexColor Color to convert.
+ * @return {!Array<number>} array containing [r, g, b, a].
+ * r, g, b are ints between 0
+ * and 255, and a is a value between 0 and 1.
+ */
+goog.color.alpha.hexToRgba = function(hexColor) {
+ // TODO(user): Enhance code sharing with goog.color, for example by
+ // adding a goog.color.genericHexToRgb method.
+ hexColor = goog.color.alpha.normalizeAlphaHex_(hexColor);
+ var r = parseInt(hexColor.substr(1, 2), 16);
+ var g = parseInt(hexColor.substr(3, 2), 16);
+ var b = parseInt(hexColor.substr(5, 2), 16);
+ var a = parseInt(hexColor.substr(7, 2), 16);
+
+ return [r, g, b, a / 255];
+};
+
+
+/**
+ * Converts a color from RGBA to hex representation.
+ * @param {number} r Amount of red, int between 0 and 255.
+ * @param {number} g Amount of green, int between 0 and 255.
+ * @param {number} b Amount of blue, int between 0 and 255.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.rgbaToHex = function(r, g, b, a) {
+ var intAlpha = Math.floor(a * 255);
+ if (isNaN(intAlpha) || intAlpha < 0 || intAlpha > 255) {
+ // TODO(user): The CSS spec says the value should be clamped.
+ throw Error('"(' + r + ',' + g + ',' + b + ',' + a +
+ '") is not a valid RGBA color');
+ }
+ var hexA = goog.color.prependZeroIfNecessaryHelper(intAlpha.toString(16));
+ return goog.color.rgbToHex(r, g, b) + hexA;
+};
+
+
+/**
+ * Converts a color from HSLA to hex representation.
+ * @param {number} h Amount of hue, int between 0 and 360.
+ * @param {number} s Amount of saturation, int between 0 and 100.
+ * @param {number} l Amount of lightness, int between 0 and 100.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.hslaToHex = function(h, s, l, a) {
+ var intAlpha = Math.floor(a * 255);
+ if (isNaN(intAlpha) || intAlpha < 0 || intAlpha > 255) {
+ // TODO(user): The CSS spec says the value should be clamped.
+ throw Error('"(' + h + ',' + s + ',' + l + ',' + a +
+ '") is not a valid HSLA color');
+ }
+ var hexA = goog.color.prependZeroIfNecessaryHelper(intAlpha.toString(16));
+ return goog.color.hslToHex(h, s / 100, l / 100) + hexA;
+};
+
+
+/**
+ * Converts a color from RGBA to hex representation.
+ * @param {Array<number>} rgba Array of [r, g, b, a], with r, g, b in [0, 255]
+ * and a in [0, 1].
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.rgbaArrayToHex = function(rgba) {
+ return goog.color.alpha.rgbaToHex(rgba[0], rgba[1], rgba[2], rgba[3]);
+};
+
+
+/**
+ * Converts a color from RGBA to an RGBA style string.
+ * @param {number} r Value of red, in [0, 255].
+ * @param {number} g Value of green, in [0, 255].
+ * @param {number} b Value of blue, in [0, 255].
+ * @param {number} a Value of alpha, in [0, 1].
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ */
+goog.color.alpha.rgbaToRgbaStyle = function(r, g, b, a) {
+ if (isNaN(r) || r < 0 || r > 255 ||
+ isNaN(g) || g < 0 || g > 255 ||
+ isNaN(b) || b < 0 || b > 255 ||
+ isNaN(a) || a < 0 || a > 1) {
+ throw Error('"(' + r + ',' + g + ',' + b + ',' + a +
+ ')" is not a valid RGBA color');
+ }
+ return goog.color.alpha.rgbaStyle_([r, g, b, a]);
+};
+
+
+/**
+ * Converts a color from RGBA to an RGBA style string.
+ * @param {(Array<number>|Float32Array)} rgba Array of [r, g, b, a],
+ * with r, g, b in [0, 255] and a in [0, 1].
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ */
+goog.color.alpha.rgbaArrayToRgbaStyle = function(rgba) {
+ return goog.color.alpha.rgbaToRgbaStyle(rgba[0], rgba[1], rgba[2], rgba[3]);
+};
+
+
+/**
+ * Converts a color from HSLA to hex representation.
+ * @param {Array<number>} hsla Array of [h, s, l, a], where h is an integer in
+ * [0, 360], s and l are integers in [0, 100], and a is in [0, 1].
+ * @return {string} hex representation of the color, such as '#af457eff'.
+ */
+goog.color.alpha.hslaArrayToHex = function(hsla) {
+ return goog.color.alpha.hslaToHex(hsla[0], hsla[1], hsla[2], hsla[3]);
+};
+
+
+/**
+ * Converts a color from HSLA to an RGBA style string.
+ * @param {Array<number>} hsla Array of [h, s, l, a], where h is and integer in
+ * [0, 360], s and l are integers in [0, 100], and a is in [0, 1].
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ */
+goog.color.alpha.hslaArrayToRgbaStyle = function(hsla) {
+ return goog.color.alpha.hslaToRgbaStyle(hsla[0], hsla[1], hsla[2], hsla[3]);
+};
+
+
+/**
+ * Converts a color from HSLA to an RGBA style string.
+ * @param {number} h Amount of hue, int between 0 and 360.
+ * @param {number} s Amount of saturation, int between 0 and 100.
+ * @param {number} l Amount of lightness, int between 0 and 100.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {string} An 'rgba(r,g,b,a)' string ready for use in a CSS rule.
+ * styles.
+ */
+goog.color.alpha.hslaToRgbaStyle = function(h, s, l, a) {
+ return goog.color.alpha.rgbaStyle_(goog.color.alpha.hslaToRgba(h, s, l, a));
+};
+
+
+/**
+ * Converts a color from HSLA color space to RGBA color space.
+ * @param {number} h Amount of hue, int between 0 and 360.
+ * @param {number} s Amount of saturation, int between 0 and 100.
+ * @param {number} l Amount of lightness, int between 0 and 100.
+ * @param {number} a Amount of alpha, float between 0 and 1.
+ * @return {!Array<number>} [r, g, b, a] values for the color, where r, g, b
+ * are integers in [0, 255] and a is a float in [0, 1].
+ */
+goog.color.alpha.hslaToRgba = function(h, s, l, a) {
+ return goog.color.hslToRgb(h, s / 100, l / 100).concat(a);
+};
+
+
+/**
+ * Converts a color from RGBA color space to HSLA color space.
+ * Modified from {@link http://en.wikipedia.org/wiki/HLS_color_space}.
+ * @param {number} r Value of red, in [0, 255].
+ * @param {number} g Value of green, in [0, 255].
+ * @param {number} b Value of blue, in [0, 255].
+ * @param {number} a Value of alpha, in [0, 255].
+ * @return {!Array<number>} [h, s, l, a] values for the color, with h an int in
+ * [0, 360] and s, l and a in [0, 1].
+ */
+goog.color.alpha.rgbaToHsla = function(r, g, b, a) {
+ return goog.color.rgbToHsl(r, g, b).concat(a);
+};
+
+
+/**
+ * Converts a color from RGBA color space to HSLA color space.
+ * @param {Array<number>} rgba [r, g, b, a] values for the color, each in
+ * [0, 255].
+ * @return {!Array<number>} [h, s, l, a] values for the color, with h in
+ * [0, 360] and s, l and a in [0, 1].
+ */
+goog.color.alpha.rgbaArrayToHsla = function(rgba) {
+ return goog.color.alpha.rgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]);
+};
+
+
+/**
+ * Helper for isValidAlphaHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.validAlphaHexColorRe_ = /^#(?:[0-9a-f]{4}){1,2}$/i;
+
+
+/**
+ * Checks if a string is a valid alpha hex color. We expect strings of the
+ * format #RRGGBBAA (ex: #1b3d5f5b) or #RGBA (ex: #3CAF == #33CCAAFF).
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a valid alpha hex color.
+ * @private
+ */
+// TODO(user): Support percentages when goog.color also supports them.
+goog.color.alpha.isValidAlphaHexColor_ = function(str) {
+ return goog.color.alpha.validAlphaHexColorRe_.test(str);
+};
+
+
+/**
+ * Helper for isNormalizedAlphaHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.normalizedAlphaHexColorRe_ = /^#[0-9a-f]{8}$/;
+
+
+/**
+ * Checks if a string is a normalized alpha hex color.
+ * We expect strings of the format #RRGGBBAA (ex: #1b3d5f5b)
+ * using only lowercase letters.
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a normalized hex color.
+ * @private
+ */
+goog.color.alpha.isNormalizedAlphaHexColor_ = function(str) {
+ return goog.color.alpha.normalizedAlphaHexColorRe_.test(str);
+};
+
+
+/**
+ * Regular expression for matching and capturing RGBA style strings. Helper for
+ * isValidRgbaColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.rgbaColorRe_ =
+ /^(?:rgba)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|1|0\.\d{0,10})\)$/i;
+
+
+/**
+ * Regular expression for matching and capturing HSLA style strings. Helper for
+ * isValidHslaColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.alpha.hslaColorRe_ =
+ /^(?:hsla)\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\%,\s?(0|[1-9]\d{0,2})\%,\s?(0|1|0\.\d{0,10})\)$/i;
+
+
+/**
+ * Checks if a string is a valid rgba color. We expect strings of the format
+ * '(r, g, b, a)', or 'rgba(r, g, b, a)', where r, g, b are ints in [0, 255]
+ * and a is a float in [0, 1].
+ * @param {string} str String to check.
+ * @return {!Array<number>} the integers [r, g, b, a] for valid colors or the
+ * empty array for invalid colors.
+ * @private
+ */
+goog.color.alpha.isValidRgbaColor_ = function(str) {
+ // Each component is separate (rather than using a repeater) so we can
+ // capture the match. Also, we explicitly set each component to be either 0,
+ // or start with a non-zero, to prevent octal numbers from slipping through.
+ var regExpResultArray = str.match(goog.color.alpha.rgbaColorRe_);
+ if (regExpResultArray) {
+ var r = Number(regExpResultArray[1]);
+ var g = Number(regExpResultArray[2]);
+ var b = Number(regExpResultArray[3]);
+ var a = Number(regExpResultArray[4]);
+ if (r >= 0 && r <= 255 &&
+ g >= 0 && g <= 255 &&
+ b >= 0 && b <= 255 &&
+ a >= 0 && a <= 1) {
+ return [r, g, b, a];
+ }
+ }
+ return [];
+};
+
+
+/**
+ * Checks if a string is a valid hsla color. We expect strings of the format
+ * 'hsla(h, s, l, a)', where s in an int in [0, 360], s and l are percentages
+ * between 0 and 100 such as '50%' or '70%', and a is a float in [0, 1].
+ * @param {string} str String to check.
+ * @return {!Array<number>} the integers [h, s, l, a] for valid colors or the
+ * empty array for invalid colors.
+ * @private
+ */
+goog.color.alpha.isValidHslaColor_ = function(str) {
+ // Each component is separate (rather than using a repeater) so we can
+ // capture the match. Also, we explicitly set each component to be either 0,
+ // or start with a non-zero, to prevent octal numbers from slipping through.
+ var regExpResultArray = str.match(goog.color.alpha.hslaColorRe_);
+ if (regExpResultArray) {
+ var h = Number(regExpResultArray[1]);
+ var s = Number(regExpResultArray[2]);
+ var l = Number(regExpResultArray[3]);
+ var a = Number(regExpResultArray[4]);
+ if (h >= 0 && h <= 360 &&
+ s >= 0 && s <= 100 &&
+ l >= 0 && l <= 100 &&
+ a >= 0 && a <= 1) {
+ return [h, s, l, a];
+ }
+ }
+ return [];
+};
+
+
+/**
+ * Takes an array of [r, g, b, a] and converts it into a string appropriate for
+ * CSS styles. The alpha channel value is rounded to 3 decimal places to make
+ * sure the produced string is not too long.
+ * @param {Array<number>} rgba [r, g, b, a] with r, g, b in [0, 255] and a
+ * in [0, 1].
+ * @return {string} string of the form 'rgba(r,g,b,a)'.
+ * @private
+ */
+goog.color.alpha.rgbaStyle_ = function(rgba) {
+ var roundedRgba = rgba.slice(0);
+ roundedRgba[3] = Math.round(rgba[3] * 1000) / 1000;
+ return 'rgba(' + roundedRgba.join(',') + ')';
+};
+
+
+/**
+ * Converts from h,s,v,a values to a hex string
+ * @param {number} h Hue, in [0, 1].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} v Value, in [0, 255].
+ * @param {number} a Alpha, in [0, 1].
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.hsvaToHex = function(h, s, v, a) {
+ var alpha = Math.floor(a * 255);
+ return goog.color.hsvArrayToHex([h, s, v]) +
+ goog.color.prependZeroIfNecessaryHelper(alpha.toString(16));
+};
+
+
+/**
+ * Converts from an HSVA array to a hex string
+ * @param {Array<number>} hsva Array of [h, s, v, a] in
+ * [[0, 1], [0, 1], [0, 255], [0, 1]].
+ * @return {string} hex representation of the color.
+ */
+goog.color.alpha.hsvaArrayToHex = function(hsva) {
+ return goog.color.alpha.hsvaToHex(hsva[0], hsva[1], hsva[2], hsva[3]);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/color/color.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/color/color.js b/externs/GCL/externs/goog/color/color.js
new file mode 100644
index 0000000..8220532
--- /dev/null
+++ b/externs/GCL/externs/goog/color/color.js
@@ -0,0 +1,776 @@
+// 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 related to color and color conversion.
+ */
+
+goog.provide('goog.color');
+goog.provide('goog.color.Hsl');
+goog.provide('goog.color.Hsv');
+goog.provide('goog.color.Rgb');
+
+goog.require('goog.color.names');
+goog.require('goog.math');
+
+
+/**
+ * RGB color representation. An array containing three elements [r, g, b],
+ * each an integer in [0, 255], representing the red, green, and blue components
+ * of the color respectively.
+ * @typedef {Array<number>}
+ */
+goog.color.Rgb;
+
+
+/**
+ * HSV color representation. An array containing three elements [h, s, v]:
+ * h (hue) must be an integer in [0, 360], cyclic.
+ * s (saturation) must be a number in [0, 1].
+ * v (value/brightness) must be an integer in [0, 255].
+ * @typedef {Array<number>}
+ */
+goog.color.Hsv;
+
+
+/**
+ * HSL color representation. An array containing three elements [h, s, l]:
+ * h (hue) must be an integer in [0, 360], cyclic.
+ * s (saturation) must be a number in [0, 1].
+ * l (lightness) must be a number in [0, 1].
+ * @typedef {Array<number>}
+ */
+goog.color.Hsl;
+
+
+/**
+ * Parses a color out of a string.
+ * @param {string} str Color in some format.
+ * @return {{hex: string, type: string}} 'hex' is a string containing a hex
+ * representation of the color, 'type' is a string containing the type
+ * of color format passed in ('hex', 'rgb', 'named').
+ */
+goog.color.parse = function(str) {
+ var result = {};
+ str = String(str);
+
+ var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
+ if (goog.color.isValidHexColor_(maybeHex)) {
+ result.hex = goog.color.normalizeHex(maybeHex);
+ result.type = 'hex';
+ return result;
+ } else {
+ var rgb = goog.color.isValidRgbColor_(str);
+ if (rgb.length) {
+ result.hex = goog.color.rgbArrayToHex(rgb);
+ result.type = 'rgb';
+ return result;
+ } else if (goog.color.names) {
+ var hex = goog.color.names[str.toLowerCase()];
+ if (hex) {
+ result.hex = hex;
+ result.type = 'named';
+ return result;
+ }
+ }
+ }
+ throw Error(str + ' is not a valid color string');
+};
+
+
+/**
+ * Determines if the given string can be parsed as a color.
+ * {@see goog.color.parse}.
+ * @param {string} str Potential color string.
+ * @return {boolean} True if str is in a format that can be parsed to a color.
+ */
+goog.color.isValidColor = function(str) {
+ var maybeHex = goog.color.prependHashIfNecessaryHelper(str);
+ return !!(goog.color.isValidHexColor_(maybeHex) ||
+ goog.color.isValidRgbColor_(str).length ||
+ goog.color.names && goog.color.names[str.toLowerCase()]);
+};
+
+
+/**
+ * Parses red, green, blue components out of a valid rgb color string.
+ * Throws Error if the color string is invalid.
+ * @param {string} str RGB representation of a color.
+ * {@see goog.color.isValidRgbColor_}.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.parseRgb = function(str) {
+ var rgb = goog.color.isValidRgbColor_(str);
+ if (!rgb.length) {
+ throw Error(str + ' is not a valid RGB color');
+ }
+ return rgb;
+};
+
+
+/**
+ * Converts a hex representation of a color to RGB.
+ * @param {string} hexColor Color to convert.
+ * @return {string} string of the form 'rgb(R,G,B)' which can be used in
+ * styles.
+ */
+goog.color.hexToRgbStyle = function(hexColor) {
+ return goog.color.rgbStyle_(goog.color.hexToRgb(hexColor));
+};
+
+
+/**
+ * Regular expression for extracting the digits in a hex color triplet.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.hexTripletRe_ = /#(.)(.)(.)/;
+
+
+/**
+ * Normalize an hex representation of a color
+ * @param {string} hexColor an hex color string.
+ * @return {string} hex color in the format '#rrggbb' with all lowercase
+ * literals.
+ */
+goog.color.normalizeHex = function(hexColor) {
+ if (!goog.color.isValidHexColor_(hexColor)) {
+ throw Error("'" + hexColor + "' is not a valid hex color");
+ }
+ if (hexColor.length == 4) { // of the form #RGB
+ hexColor = hexColor.replace(goog.color.hexTripletRe_, '#$1$1$2$2$3$3');
+ }
+ return hexColor.toLowerCase();
+};
+
+
+/**
+ * Converts a hex representation of a color to RGB.
+ * @param {string} hexColor Color to convert.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hexToRgb = function(hexColor) {
+ hexColor = goog.color.normalizeHex(hexColor);
+ var r = parseInt(hexColor.substr(1, 2), 16);
+ var g = parseInt(hexColor.substr(3, 2), 16);
+ var b = parseInt(hexColor.substr(5, 2), 16);
+
+ return [r, g, b];
+};
+
+
+/**
+ * Converts a color from RGB to hex representation.
+ * @param {number} r Amount of red, int between 0 and 255.
+ * @param {number} g Amount of green, int between 0 and 255.
+ * @param {number} b Amount of blue, int between 0 and 255.
+ * @return {string} hex representation of the color.
+ */
+goog.color.rgbToHex = function(r, g, b) {
+ r = Number(r);
+ g = Number(g);
+ b = Number(b);
+ if (isNaN(r) || r < 0 || r > 255 ||
+ isNaN(g) || g < 0 || g > 255 ||
+ isNaN(b) || b < 0 || b > 255) {
+ throw Error('"(' + r + ',' + g + ',' + b + '") is not a valid RGB color');
+ }
+ var hexR = goog.color.prependZeroIfNecessaryHelper(r.toString(16));
+ var hexG = goog.color.prependZeroIfNecessaryHelper(g.toString(16));
+ var hexB = goog.color.prependZeroIfNecessaryHelper(b.toString(16));
+ return '#' + hexR + hexG + hexB;
+};
+
+
+/**
+ * Converts a color from RGB to hex representation.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {string} hex representation of the color.
+ */
+goog.color.rgbArrayToHex = function(rgb) {
+ return goog.color.rgbToHex(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Converts a color from RGB color space to HSL color space.
+ * Modified from {@link http://en.wikipedia.org/wiki/HLS_color_space}.
+ * @param {number} r Value of red, in [0, 255].
+ * @param {number} g Value of green, in [0, 255].
+ * @param {number} b Value of blue, in [0, 255].
+ * @return {!goog.color.Hsl} hsl representation of the color.
+ */
+goog.color.rgbToHsl = function(r, g, b) {
+ // First must normalize r, g, b to be between 0 and 1.
+ var normR = r / 255;
+ var normG = g / 255;
+ var normB = b / 255;
+ var max = Math.max(normR, normG, normB);
+ var min = Math.min(normR, normG, normB);
+ var h = 0;
+ var s = 0;
+
+ // Luminosity is the average of the max and min rgb color intensities.
+ var l = 0.5 * (max + min);
+
+ // The hue and saturation are dependent on which color intensity is the max.
+ // If max and min are equal, the color is gray and h and s should be 0.
+ if (max != min) {
+ if (max == normR) {
+ h = 60 * (normG - normB) / (max - min);
+ } else if (max == normG) {
+ h = 60 * (normB - normR) / (max - min) + 120;
+ } else if (max == normB) {
+ h = 60 * (normR - normG) / (max - min) + 240;
+ }
+
+ if (0 < l && l <= 0.5) {
+ s = (max - min) / (2 * l);
+ } else {
+ s = (max - min) / (2 - 2 * l);
+ }
+ }
+
+ // Make sure the hue falls between 0 and 360.
+ return [Math.round(h + 360) % 360, s, l];
+};
+
+
+/**
+ * Converts a color from RGB color space to HSL color space.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {!goog.color.Hsl} hsl representation of the color.
+ */
+goog.color.rgbArrayToHsl = function(rgb) {
+ return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Helper for hslToRgb.
+ * @param {number} v1 Helper variable 1.
+ * @param {number} v2 Helper variable 2.
+ * @param {number} vH Helper variable 3.
+ * @return {number} Appropriate RGB value, given the above.
+ * @private
+ */
+goog.color.hueToRgb_ = function(v1, v2, vH) {
+ if (vH < 0) {
+ vH += 1;
+ } else if (vH > 1) {
+ vH -= 1;
+ }
+ if ((6 * vH) < 1) {
+ return (v1 + (v2 - v1) * 6 * vH);
+ } else if (2 * vH < 1) {
+ return v2;
+ } else if (3 * vH < 2) {
+ return (v1 + (v2 - v1) * ((2 / 3) - vH) * 6);
+ }
+ return v1;
+};
+
+
+/**
+ * Converts a color from HSL color space to RGB color space.
+ * Modified from {@link http://www.easyrgb.com/math.html}
+ * @param {number} h Hue, in [0, 360].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} l Luminosity, in [0, 1].
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hslToRgb = function(h, s, l) {
+ var r = 0;
+ var g = 0;
+ var b = 0;
+ var normH = h / 360; // normalize h to fall in [0, 1]
+
+ if (s == 0) {
+ r = g = b = l * 255;
+ } else {
+ var temp1 = 0;
+ var temp2 = 0;
+ if (l < 0.5) {
+ temp2 = l * (1 + s);
+ } else {
+ temp2 = l + s - (s * l);
+ }
+ temp1 = 2 * l - temp2;
+ r = 255 * goog.color.hueToRgb_(temp1, temp2, normH + (1 / 3));
+ g = 255 * goog.color.hueToRgb_(temp1, temp2, normH);
+ b = 255 * goog.color.hueToRgb_(temp1, temp2, normH - (1 / 3));
+ }
+
+ return [Math.round(r), Math.round(g), Math.round(b)];
+};
+
+
+/**
+ * Converts a color from HSL color space to RGB color space.
+ * @param {goog.color.Hsl} hsl hsl representation of the color.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hslArrayToRgb = function(hsl) {
+ return goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]);
+};
+
+
+/**
+ * Helper for isValidHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.validHexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i;
+
+
+/**
+ * Checks if a string is a valid hex color. We expect strings of the format
+ * #RRGGBB (ex: #1b3d5f) or #RGB (ex: #3CA == #33CCAA).
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a valid hex color.
+ * @private
+ */
+goog.color.isValidHexColor_ = function(str) {
+ return goog.color.validHexColorRe_.test(str);
+};
+
+
+/**
+ * Helper for isNormalizedHexColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.normalizedHexColorRe_ = /^#[0-9a-f]{6}$/;
+
+
+/**
+ * Checks if a string is a normalized hex color.
+ * We expect strings of the format #RRGGBB (ex: #1b3d5f)
+ * using only lowercase letters.
+ * @param {string} str String to check.
+ * @return {boolean} Whether the string is a normalized hex color.
+ * @private
+ */
+goog.color.isNormalizedHexColor_ = function(str) {
+ return goog.color.normalizedHexColorRe_.test(str);
+};
+
+
+/**
+ * Regular expression for matching and capturing RGB style strings. Helper for
+ * isValidRgbColor_.
+ * @type {RegExp}
+ * @private
+ */
+goog.color.rgbColorRe_ =
+ /^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;
+
+
+/**
+ * Checks if a string is a valid rgb color. We expect strings of the format
+ * '(r, g, b)', or 'rgb(r, g, b)', where each color component is an int in
+ * [0, 255].
+ * @param {string} str String to check.
+ * @return {!goog.color.Rgb} the rgb representation of the color if it is
+ * a valid color, or the empty array otherwise.
+ * @private
+ */
+goog.color.isValidRgbColor_ = function(str) {
+ // Each component is separate (rather than using a repeater) so we can
+ // capture the match. Also, we explicitly set each component to be either 0,
+ // or start with a non-zero, to prevent octal numbers from slipping through.
+ var regExpResultArray = str.match(goog.color.rgbColorRe_);
+ if (regExpResultArray) {
+ var r = Number(regExpResultArray[1]);
+ var g = Number(regExpResultArray[2]);
+ var b = Number(regExpResultArray[3]);
+ if (r >= 0 && r <= 255 &&
+ g >= 0 && g <= 255 &&
+ b >= 0 && b <= 255) {
+ return [r, g, b];
+ }
+ }
+ return [];
+};
+
+
+/**
+ * Takes a hex value and prepends a zero if it's a single digit.
+ * Small helper method for use by goog.color and friends.
+ * @param {string} hex Hex value to prepend if single digit.
+ * @return {string} hex value prepended with zero if it was single digit,
+ * otherwise the same value that was passed in.
+ */
+goog.color.prependZeroIfNecessaryHelper = function(hex) {
+ return hex.length == 1 ? '0' + hex : hex;
+};
+
+
+/**
+ * Takes a string a prepends a '#' sign if one doesn't exist.
+ * Small helper method for use by goog.color and friends.
+ * @param {string} str String to check.
+ * @return {string} The value passed in, prepended with a '#' if it didn't
+ * already have one.
+ */
+goog.color.prependHashIfNecessaryHelper = function(str) {
+ return str.charAt(0) == '#' ? str : '#' + str;
+};
+
+
+/**
+ * Takes an array of [r, g, b] and converts it into a string appropriate for
+ * CSS styles.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {string} string of the form 'rgb(r,g,b)'.
+ * @private
+ */
+goog.color.rgbStyle_ = function(rgb) {
+ return 'rgb(' + rgb.join(',') + ')';
+};
+
+
+/**
+ * Converts an HSV triplet to an RGB array. V is brightness because b is
+ * reserved for blue in RGB.
+ * @param {number} h Hue value in [0, 360].
+ * @param {number} s Saturation value in [0, 1].
+ * @param {number} brightness brightness in [0, 255].
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hsvToRgb = function(h, s, brightness) {
+ var red = 0;
+ var green = 0;
+ var blue = 0;
+ if (s == 0) {
+ red = brightness;
+ green = brightness;
+ blue = brightness;
+ } else {
+ var sextant = Math.floor(h / 60);
+ var remainder = (h / 60) - sextant;
+ var val1 = brightness * (1 - s);
+ var val2 = brightness * (1 - (s * remainder));
+ var val3 = brightness * (1 - (s * (1 - remainder)));
+ switch (sextant) {
+ case 1:
+ red = val2;
+ green = brightness;
+ blue = val1;
+ break;
+ case 2:
+ red = val1;
+ green = brightness;
+ blue = val3;
+ break;
+ case 3:
+ red = val1;
+ green = val2;
+ blue = brightness;
+ break;
+ case 4:
+ red = val3;
+ green = val1;
+ blue = brightness;
+ break;
+ case 5:
+ red = brightness;
+ green = val1;
+ blue = val2;
+ break;
+ case 6:
+ case 0:
+ red = brightness;
+ green = val3;
+ blue = val1;
+ break;
+ }
+ }
+
+ return [Math.floor(red), Math.floor(green), Math.floor(blue)];
+};
+
+
+/**
+ * Converts from RGB values to an array of HSV values.
+ * @param {number} red Red value in [0, 255].
+ * @param {number} green Green value in [0, 255].
+ * @param {number} blue Blue value in [0, 255].
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.rgbToHsv = function(red, green, blue) {
+
+ var max = Math.max(Math.max(red, green), blue);
+ var min = Math.min(Math.min(red, green), blue);
+ var hue;
+ var saturation;
+ var value = max;
+ if (min == max) {
+ hue = 0;
+ saturation = 0;
+ } else {
+ var delta = (max - min);
+ saturation = delta / max;
+
+ if (red == max) {
+ hue = (green - blue) / delta;
+ } else if (green == max) {
+ hue = 2 + ((blue - red) / delta);
+ } else {
+ hue = 4 + ((red - green) / delta);
+ }
+ hue *= 60;
+ if (hue < 0) {
+ hue += 360;
+ }
+ if (hue > 360) {
+ hue -= 360;
+ }
+ }
+
+ return [hue, saturation, value];
+};
+
+
+/**
+ * Converts from an array of RGB values to an array of HSV values.
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.rgbArrayToHsv = function(rgb) {
+ return goog.color.rgbToHsv(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Converts an HSV triplet to an RGB array.
+ * @param {goog.color.Hsv} hsv hsv representation of the color.
+ * @return {!goog.color.Rgb} rgb representation of the color.
+ */
+goog.color.hsvArrayToRgb = function(hsv) {
+ return goog.color.hsvToRgb(hsv[0], hsv[1], hsv[2]);
+};
+
+
+/**
+ * Converts a hex representation of a color to HSL.
+ * @param {string} hex Color to convert.
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.hexToHsl = function(hex) {
+ var rgb = goog.color.hexToRgb(hex);
+ return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
+};
+
+
+/**
+ * Converts from h,s,l values to a hex string
+ * @param {number} h Hue, in [0, 360].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} l Luminosity, in [0, 1].
+ * @return {string} hex representation of the color.
+ */
+goog.color.hslToHex = function(h, s, l) {
+ return goog.color.rgbArrayToHex(goog.color.hslToRgb(h, s, l));
+};
+
+
+/**
+ * Converts from an hsl array to a hex string
+ * @param {goog.color.Hsl} hsl hsl representation of the color.
+ * @return {string} hex representation of the color.
+ */
+goog.color.hslArrayToHex = function(hsl) {
+ return goog.color.rgbArrayToHex(goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]));
+};
+
+
+/**
+ * Converts a hex representation of a color to HSV
+ * @param {string} hex Color to convert.
+ * @return {!goog.color.Hsv} hsv representation of the color.
+ */
+goog.color.hexToHsv = function(hex) {
+ return goog.color.rgbArrayToHsv(goog.color.hexToRgb(hex));
+};
+
+
+/**
+ * Converts from h,s,v values to a hex string
+ * @param {number} h Hue, in [0, 360].
+ * @param {number} s Saturation, in [0, 1].
+ * @param {number} v Value, in [0, 255].
+ * @return {string} hex representation of the color.
+ */
+goog.color.hsvToHex = function(h, s, v) {
+ return goog.color.rgbArrayToHex(goog.color.hsvToRgb(h, s, v));
+};
+
+
+/**
+ * Converts from an HSV array to a hex string
+ * @param {goog.color.Hsv} hsv hsv representation of the color.
+ * @return {string} hex representation of the color.
+ */
+goog.color.hsvArrayToHex = function(hsv) {
+ return goog.color.hsvToHex(hsv[0], hsv[1], hsv[2]);
+};
+
+
+/**
+ * Calculates the Euclidean distance between two color vectors on an HSL sphere.
+ * A demo of the sphere can be found at:
+ * http://en.wikipedia.org/wiki/HSL_color_space
+ * In short, a vector for color (H, S, L) in this system can be expressed as
+ * (S*L'*cos(2*PI*H), S*L'*sin(2*PI*H), L), where L' = abs(L - 0.5), and we
+ * simply calculate the 1-2 distance using these coordinates
+ * @param {goog.color.Hsl} hsl1 First color in hsl representation.
+ * @param {goog.color.Hsl} hsl2 Second color in hsl representation.
+ * @return {number} Distance between the two colors, in the range [0, 1].
+ */
+goog.color.hslDistance = function(hsl1, hsl2) {
+ var sl1, sl2;
+ if (hsl1[2] <= 0.5) {
+ sl1 = hsl1[1] * hsl1[2];
+ } else {
+ sl1 = hsl1[1] * (1.0 - hsl1[2]);
+ }
+
+ if (hsl2[2] <= 0.5) {
+ sl2 = hsl2[1] * hsl2[2];
+ } else {
+ sl2 = hsl2[1] * (1.0 - hsl2[2]);
+ }
+
+ var h1 = hsl1[0] / 360.0;
+ var h2 = hsl2[0] / 360.0;
+ var dh = (h1 - h2) * 2.0 * Math.PI;
+ return (hsl1[2] - hsl2[2]) * (hsl1[2] - hsl2[2]) +
+ sl1 * sl1 + sl2 * sl2 - 2 * sl1 * sl2 * Math.cos(dh);
+};
+
+
+/**
+ * Blend two colors together, using the specified factor to indicate the weight
+ * given to the first color
+ * @param {goog.color.Rgb} rgb1 First color represented in rgb.
+ * @param {goog.color.Rgb} rgb2 Second color represented in rgb.
+ * @param {number} factor The weight to be given to rgb1 over rgb2. Values
+ * should be in the range [0, 1]. If less than 0, factor will be set to 0.
+ * If greater than 1, factor will be set to 1.
+ * @return {!goog.color.Rgb} Combined color represented in rgb.
+ */
+goog.color.blend = function(rgb1, rgb2, factor) {
+ factor = goog.math.clamp(factor, 0, 1);
+
+ return [
+ Math.round(factor * rgb1[0] + (1.0 - factor) * rgb2[0]),
+ Math.round(factor * rgb1[1] + (1.0 - factor) * rgb2[1]),
+ Math.round(factor * rgb1[2] + (1.0 - factor) * rgb2[2])
+ ];
+};
+
+
+/**
+ * Adds black to the specified color, darkening it
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @param {number} factor Number in the range [0, 1]. 0 will do nothing, while
+ * 1 will return black. If less than 0, factor will be set to 0. If greater
+ * than 1, factor will be set to 1.
+ * @return {!goog.color.Rgb} Combined rgb color.
+ */
+goog.color.darken = function(rgb, factor) {
+ var black = [0, 0, 0];
+ return goog.color.blend(black, rgb, factor);
+};
+
+
+/**
+ * Adds white to the specified color, lightening it
+ * @param {goog.color.Rgb} rgb rgb representation of the color.
+ * @param {number} factor Number in the range [0, 1]. 0 will do nothing, while
+ * 1 will return white. If less than 0, factor will be set to 0. If greater
+ * than 1, factor will be set to 1.
+ * @return {!goog.color.Rgb} Combined rgb color.
+ */
+goog.color.lighten = function(rgb, factor) {
+ var white = [255, 255, 255];
+ return goog.color.blend(white, rgb, factor);
+};
+
+
+/**
+ * Find the "best" (highest-contrast) of the suggested colors for the prime
+ * color. Uses W3C formula for judging readability and visual accessibility:
+ * http://www.w3.org/TR/AERT#color-contrast
+ * @param {goog.color.Rgb} prime Color represented as a rgb array.
+ * @param {Array<goog.color.Rgb>} suggestions Array of colors,
+ * each representing a rgb array.
+ * @return {!goog.color.Rgb} Highest-contrast color represented by an array..
+ */
+goog.color.highContrast = function(prime, suggestions) {
+ var suggestionsWithDiff = [];
+ for (var i = 0; i < suggestions.length; i++) {
+ suggestionsWithDiff.push({
+ color: suggestions[i],
+ diff: goog.color.yiqBrightnessDiff_(suggestions[i], prime) +
+ goog.color.colorDiff_(suggestions[i], prime)
+ });
+ }
+ suggestionsWithDiff.sort(function(a, b) {
+ return b.diff - a.diff;
+ });
+ return suggestionsWithDiff[0].color;
+};
+
+
+/**
+ * Calculate brightness of a color according to YIQ formula (brightness is Y).
+ * More info on YIQ here: http://en.wikipedia.org/wiki/YIQ. Helper method for
+ * goog.color.highContrast()
+ * @param {goog.color.Rgb} rgb Color represented by a rgb array.
+ * @return {number} brightness (Y).
+ * @private
+ */
+goog.color.yiqBrightness_ = function(rgb) {
+ return Math.round((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000);
+};
+
+
+/**
+ * Calculate difference in brightness of two colors. Helper method for
+ * goog.color.highContrast()
+ * @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
+ * @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
+ * @return {number} Brightness difference.
+ * @private
+ */
+goog.color.yiqBrightnessDiff_ = function(rgb1, rgb2) {
+ return Math.abs(goog.color.yiqBrightness_(rgb1) -
+ goog.color.yiqBrightness_(rgb2));
+};
+
+
+/**
+ * Calculate color difference between two colors. Helper method for
+ * goog.color.highContrast()
+ * @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
+ * @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
+ * @return {number} Color difference.
+ * @private
+ */
+goog.color.colorDiff_ = function(rgb1, rgb2) {
+ return Math.abs(rgb1[0] - rgb2[0]) + Math.abs(rgb1[1] - rgb2[1]) +
+ Math.abs(rgb1[2] - rgb2[2]);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/color/names.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/color/names.js b/externs/GCL/externs/goog/color/names.js
new file mode 100644
index 0000000..c4b3ac8
--- /dev/null
+++ b/externs/GCL/externs/goog/color/names.js
@@ -0,0 +1,176 @@
+// 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 Names of standard colors with their associated hex values.
+ */
+
+goog.provide('goog.color.names');
+
+
+/**
+ * A map that contains a lot of colors that are recognised by various browsers.
+ * This list is way larger than the minimal one dictated by W3C.
+ * The keys of this map are the lowercase "readable" names of the colors, while
+ * the values are the "hex" values.
+ */
+goog.color.names = {
+ 'aliceblue': '#f0f8ff',
+ 'antiquewhite': '#faebd7',
+ 'aqua': '#00ffff',
+ 'aquamarine': '#7fffd4',
+ 'azure': '#f0ffff',
+ 'beige': '#f5f5dc',
+ 'bisque': '#ffe4c4',
+ 'black': '#000000',
+ 'blanchedalmond': '#ffebcd',
+ 'blue': '#0000ff',
+ 'blueviolet': '#8a2be2',
+ 'brown': '#a52a2a',
+ 'burlywood': '#deb887',
+ 'cadetblue': '#5f9ea0',
+ 'chartreuse': '#7fff00',
+ 'chocolate': '#d2691e',
+ 'coral': '#ff7f50',
+ 'cornflowerblue': '#6495ed',
+ 'cornsilk': '#fff8dc',
+ 'crimson': '#dc143c',
+ 'cyan': '#00ffff',
+ 'darkblue': '#00008b',
+ 'darkcyan': '#008b8b',
+ 'darkgoldenrod': '#b8860b',
+ 'darkgray': '#a9a9a9',
+ 'darkgreen': '#006400',
+ 'darkgrey': '#a9a9a9',
+ 'darkkhaki': '#bdb76b',
+ 'darkmagenta': '#8b008b',
+ 'darkolivegreen': '#556b2f',
+ 'darkorange': '#ff8c00',
+ 'darkorchid': '#9932cc',
+ 'darkred': '#8b0000',
+ 'darksalmon': '#e9967a',
+ 'darkseagreen': '#8fbc8f',
+ 'darkslateblue': '#483d8b',
+ 'darkslategray': '#2f4f4f',
+ 'darkslategrey': '#2f4f4f',
+ 'darkturquoise': '#00ced1',
+ 'darkviolet': '#9400d3',
+ 'deeppink': '#ff1493',
+ 'deepskyblue': '#00bfff',
+ 'dimgray': '#696969',
+ 'dimgrey': '#696969',
+ 'dodgerblue': '#1e90ff',
+ 'firebrick': '#b22222',
+ 'floralwhite': '#fffaf0',
+ 'forestgreen': '#228b22',
+ 'fuchsia': '#ff00ff',
+ 'gainsboro': '#dcdcdc',
+ 'ghostwhite': '#f8f8ff',
+ 'gold': '#ffd700',
+ 'goldenrod': '#daa520',
+ 'gray': '#808080',
+ 'green': '#008000',
+ 'greenyellow': '#adff2f',
+ 'grey': '#808080',
+ 'honeydew': '#f0fff0',
+ 'hotpink': '#ff69b4',
+ 'indianred': '#cd5c5c',
+ 'indigo': '#4b0082',
+ 'ivory': '#fffff0',
+ 'khaki': '#f0e68c',
+ 'lavender': '#e6e6fa',
+ 'lavenderblush': '#fff0f5',
+ 'lawngreen': '#7cfc00',
+ 'lemonchiffon': '#fffacd',
+ 'lightblue': '#add8e6',
+ 'lightcoral': '#f08080',
+ 'lightcyan': '#e0ffff',
+ 'lightgoldenrodyellow': '#fafad2',
+ 'lightgray': '#d3d3d3',
+ 'lightgreen': '#90ee90',
+ 'lightgrey': '#d3d3d3',
+ 'lightpink': '#ffb6c1',
+ 'lightsalmon': '#ffa07a',
+ 'lightseagreen': '#20b2aa',
+ 'lightskyblue': '#87cefa',
+ 'lightslategray': '#778899',
+ 'lightslategrey': '#778899',
+ 'lightsteelblue': '#b0c4de',
+ 'lightyellow': '#ffffe0',
+ 'lime': '#00ff00',
+ 'limegreen': '#32cd32',
+ 'linen': '#faf0e6',
+ 'magenta': '#ff00ff',
+ 'maroon': '#800000',
+ 'mediumaquamarine': '#66cdaa',
+ 'mediumblue': '#0000cd',
+ 'mediumorchid': '#ba55d3',
+ 'mediumpurple': '#9370db',
+ 'mediumseagreen': '#3cb371',
+ 'mediumslateblue': '#7b68ee',
+ 'mediumspringgreen': '#00fa9a',
+ 'mediumturquoise': '#48d1cc',
+ 'mediumvioletred': '#c71585',
+ 'midnightblue': '#191970',
+ 'mintcream': '#f5fffa',
+ 'mistyrose': '#ffe4e1',
+ 'moccasin': '#ffe4b5',
+ 'navajowhite': '#ffdead',
+ 'navy': '#000080',
+ 'oldlace': '#fdf5e6',
+ 'olive': '#808000',
+ 'olivedrab': '#6b8e23',
+ 'orange': '#ffa500',
+ 'orangered': '#ff4500',
+ 'orchid': '#da70d6',
+ 'palegoldenrod': '#eee8aa',
+ 'palegreen': '#98fb98',
+ 'paleturquoise': '#afeeee',
+ 'palevioletred': '#db7093',
+ 'papayawhip': '#ffefd5',
+ 'peachpuff': '#ffdab9',
+ 'peru': '#cd853f',
+ 'pink': '#ffc0cb',
+ 'plum': '#dda0dd',
+ 'powderblue': '#b0e0e6',
+ 'purple': '#800080',
+ 'red': '#ff0000',
+ 'rosybrown': '#bc8f8f',
+ 'royalblue': '#4169e1',
+ 'saddlebrown': '#8b4513',
+ 'salmon': '#fa8072',
+ 'sandybrown': '#f4a460',
+ 'seagreen': '#2e8b57',
+ 'seashell': '#fff5ee',
+ 'sienna': '#a0522d',
+ 'silver': '#c0c0c0',
+ 'skyblue': '#87ceeb',
+ 'slateblue': '#6a5acd',
+ 'slategray': '#708090',
+ 'slategrey': '#708090',
+ 'snow': '#fffafa',
+ 'springgreen': '#00ff7f',
+ 'steelblue': '#4682b4',
+ 'tan': '#d2b48c',
+ 'teal': '#008080',
+ 'thistle': '#d8bfd8',
+ 'tomato': '#ff6347',
+ 'turquoise': '#40e0d0',
+ 'violet': '#ee82ee',
+ 'wheat': '#f5deb3',
+ 'white': '#ffffff',
+ 'whitesmoke': '#f5f5f5',
+ 'yellow': '#ffff00',
+ 'yellowgreen': '#9acd32'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/aes.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/aes.js b/externs/GCL/externs/goog/crypt/aes.js
new file mode 100644
index 0000000..d5a1674
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/aes.js
@@ -0,0 +1,1029 @@
+// Copyright 2012 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 Implementation of AES in JavaScript.
+ * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+ *
+ * @author nnaze@google.com (Nathan Naze) - port to Closure
+ */
+
+goog.provide('goog.crypt.Aes');
+
+goog.require('goog.asserts');
+goog.require('goog.crypt.BlockCipher');
+
+
+
+/**
+ * Implementation of AES in JavaScript.
+ * See http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+ *
+ * WARNING: This is ECB mode only. If you are encrypting something
+ * longer than 16 bytes, or encrypting more than one value with the same key
+ * (so basically, always) you need to use this with a block cipher mode of
+ * operation. See goog.crypt.Cbc.
+ *
+ * See http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation for more
+ * information.
+ *
+ * @constructor
+ * @implements {goog.crypt.BlockCipher}
+ * @param {!Array<number>} key The key as an array of integers in {0, 255}.
+ * The key must have lengths of 16, 24, or 32 integers for 128-,
+ * 192-, or 256-bit encryption, respectively.
+ * @final
+ * @struct
+ */
+goog.crypt.Aes = function(key) {
+ goog.crypt.Aes.assertKeyArray_(key);
+
+ /**
+ * The AES key.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.key_ = key;
+
+ /**
+ * Key length, in words.
+ * @type {number}
+ * @private
+ */
+ this.keyLength_ = this.key_.length / 4;
+
+ /**
+ * Number of rounds. Based on key length per AES spec.
+ * @type {number}
+ * @private
+ */
+ this.numberOfRounds_ = this.keyLength_ + 6;
+
+ /**
+ * 4x4 byte array containing the current state.
+ * @type {!Array<!Array<number>>}
+ * @private
+ */
+ this.state_ = [[], [], [], []];
+
+ /**
+ * Scratch temporary array for calculation.
+ * @type {!Array<!Array<number>>}
+ * @private
+ */
+ this.temp_ = [[], [], [], []];
+
+ /**
+ * The key schedule.
+ * @type {!Array<!Array<number>>}
+ * @private
+ */
+ this.keySchedule_;
+
+ this.keyExpansion_();
+};
+
+
+/**
+ * @define {boolean} Whether to call test method stubs. This can be enabled
+ * for unit testing.
+ */
+goog.define('goog.crypt.Aes.ENABLE_TEST_MODE', false);
+
+
+/**
+ * @override
+ */
+goog.crypt.Aes.prototype.encrypt = function(input) {
+
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testKeySchedule_(0, this.keySchedule_, 0);
+ }
+
+ this.copyInput_(input);
+ this.addRoundKey_(0);
+
+ for (var round = 1; round < this.numberOfRounds_; ++round) {
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testKeySchedule_(round, this.keySchedule_, round);
+ this.testStartRound_(round, this.state_);
+ }
+
+ this.subBytes_(goog.crypt.Aes.SBOX_);
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterSubBytes_(round, this.state_);
+ }
+
+ this.shiftRows_();
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterShiftRows_(round, this.state_);
+ }
+
+ this.mixColumns_();
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterMixColumns_(round, this.state_);
+ }
+
+ this.addRoundKey_(round);
+ }
+
+ this.subBytes_(goog.crypt.Aes.SBOX_);
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterSubBytes_(round, this.state_);
+ }
+
+ this.shiftRows_();
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterShiftRows_(round, this.state_);
+ }
+
+ this.addRoundKey_(this.numberOfRounds_);
+
+ return this.generateOutput_();
+};
+
+
+/**
+ * @override
+ */
+goog.crypt.Aes.prototype.decrypt = function(input) {
+
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testKeySchedule_(0, this.keySchedule_, this.numberOfRounds_);
+ }
+
+ this.copyInput_(input);
+ this.addRoundKey_(this.numberOfRounds_);
+
+ for (var round = 1; round < this.numberOfRounds_; ++round) {
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testKeySchedule_(round, this.keySchedule_,
+ this.numberOfRounds_ - round);
+ this.testStartRound_(round, this.state_);
+ }
+
+ this.invShiftRows_();
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterShiftRows_(round, this.state_);
+ }
+
+ this.subBytes_(goog.crypt.Aes.INV_SBOX_);
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterSubBytes_(round, this.state_);
+ }
+
+ this.addRoundKey_(this.numberOfRounds_ - round);
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterAddRoundKey_(round, this.state_);
+ }
+
+ this.invMixColumns_();
+ }
+
+ this.invShiftRows_();
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterShiftRows_(round, this.state_);
+ }
+
+ this.subBytes_(goog.crypt.Aes.INV_SBOX_);
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testAfterSubBytes_(this.numberOfRounds_, this.state_);
+ }
+
+ if (goog.crypt.Aes.ENABLE_TEST_MODE) {
+ this.testKeySchedule_(this.numberOfRounds_, this.keySchedule_, 0);
+ }
+
+ this.addRoundKey_(0);
+
+ return this.generateOutput_();
+};
+
+
+/**
+ * Block size, in words. Fixed at 4 per AES spec.
+ * @type {number}
+ * @private
+ */
+goog.crypt.Aes.BLOCK_SIZE_ = 4;
+
+
+/**
+ * Asserts that the key's array of integers is in the correct format.
+ * @param {!Array<number>} arr AES key as array of integers.
+ * @private
+ */
+goog.crypt.Aes.assertKeyArray_ = function(arr) {
+ if (goog.asserts.ENABLE_ASSERTS) {
+ goog.asserts.assert(arr.length == 16 || arr.length == 24 ||
+ arr.length == 32,
+ 'Key must have length 16, 24, or 32.');
+ for (var i = 0; i < arr.length; i++) {
+ goog.asserts.assertNumber(arr[i]);
+ goog.asserts.assert(arr[i] >= 0 && arr[i] <= 255);
+ }
+ }
+};
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * at the start of each round *in both functions encrypt() and decrypt()*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testStartRound_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the SubBytes step gets executed *in both functions
+ * encrypt() and decrypt()*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterSubBytes_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the ShiftRows step gets executed *in both functions
+ * encrypt() and decrypt()*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterShiftRows_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the MixColumns step gets executed *but only in the
+ * decrypt() function*.
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterMixColumns_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * each round right after the AddRoundKey step gets executed encrypt().
+ * @param {number} roundNum Round number.
+ * @param {!Array<Array<number>>} Current state.
+ * @private
+ */
+goog.crypt.Aes.prototype.testAfterAddRoundKey_ = goog.nullFunction;
+
+
+/**
+ * Tests can populate this with a callback, and that callback will get called
+ * before each round on the round key. *Gets called in both the encrypt() and
+ * decrypt() functions.*
+ * @param {number} roundNum Round number.
+ * @param {Array<!Array<number>>} Computed key schedule.
+ * @param {number} index The index into the key schedule to test. This is not
+ * necessarily roundNum because the key schedule is used in reverse
+ * in the case of decryption.
+ * @private
+ */
+goog.crypt.Aes.prototype.testKeySchedule_ = goog.nullFunction;
+
+
+/**
+ * Helper to copy input into the AES state matrix.
+ * @param {!Array<number>} input Byte array to copy into the state matrix.
+ * @private
+ */
+goog.crypt.Aes.prototype.copyInput_ = function(input) {
+ var v, p;
+
+ goog.asserts.assert(input.length == goog.crypt.Aes.BLOCK_SIZE_ * 4,
+ 'Expecting input of 4 times block size.');
+
+ for (var r = 0; r < goog.crypt.Aes.BLOCK_SIZE_; r++) {
+ for (var c = 0; c < 4; c++) {
+ p = c * 4 + r;
+ v = input[p];
+
+ goog.asserts.assert(
+ v <= 255 && v >= 0,
+ 'Invalid input. Value %s at position %s is not a byte.', v, p);
+
+ this.state_[r][c] = v;
+ }
+ }
+};
+
+
+/**
+ * Helper to copy the state matrix into an output array.
+ * @return {!Array<number>} Output byte array.
+ * @private
+ */
+goog.crypt.Aes.prototype.generateOutput_ = function() {
+ var output = [];
+ for (var r = 0; r < goog.crypt.Aes.BLOCK_SIZE_; r++) {
+ for (var c = 0; c < 4; c++) {
+ output[c * 4 + r] = this.state_[r][c];
+ }
+ }
+ return output;
+};
+
+
+/**
+ * AES's AddRoundKey procedure. Add the current round key to the state.
+ * @param {number} round The current round.
+ * @private
+ */
+goog.crypt.Aes.prototype.addRoundKey_ = function(round) {
+ for (var r = 0; r < 4; r++) {
+ for (var c = 0; c < 4; c++) {
+ this.state_[r][c] ^= this.keySchedule_[round * 4 + c][r];
+ }
+ }
+};
+
+
+/**
+ * AES's SubBytes procedure. Substitute bytes from the precomputed SBox lookup
+ * into the state.
+ * @param {!Array<number>} box The SBox or invSBox.
+ * @private
+ */
+goog.crypt.Aes.prototype.subBytes_ = function(box) {
+ for (var r = 0; r < 4; r++) {
+ for (var c = 0; c < 4; c++) {
+ this.state_[r][c] = box[this.state_[r][c]];
+ }
+ }
+};
+
+
+/**
+ * AES's ShiftRows procedure. Shift the values in each row to the right. Each
+ * row is shifted one more slot than the one above it.
+ * @private
+ */
+goog.crypt.Aes.prototype.shiftRows_ = function() {
+ for (var r = 1; r < 4; r++) {
+ for (var c = 0; c < 4; c++) {
+ this.temp_[r][c] = this.state_[r][c];
+ }
+ }
+
+ for (var r = 1; r < 4; r++) {
+ for (var c = 0; c < 4; c++) {
+ this.state_[r][c] = this.temp_[r][(c + r) %
+ goog.crypt.Aes.BLOCK_SIZE_];
+ }
+ }
+};
+
+
+/**
+ * AES's InvShiftRows procedure. Shift the values in each row to the right.
+ * @private
+ */
+goog.crypt.Aes.prototype.invShiftRows_ = function() {
+ for (var r = 1; r < 4; r++) {
+ for (var c = 0; c < 4; c++) {
+ this.temp_[r][(c + r) % goog.crypt.Aes.BLOCK_SIZE_] =
+ this.state_[r][c];
+ }
+ }
+
+ for (var r = 1; r < 4; r++) {
+ for (var c = 0; c < 4; c++) {
+ this.state_[r][c] = this.temp_[r][c];
+ }
+ }
+};
+
+
+/**
+ * AES's MixColumns procedure. Mix the columns of the state using magic.
+ * @private
+ */
+goog.crypt.Aes.prototype.mixColumns_ = function() {
+ var s = this.state_;
+ var t = this.temp_[0];
+
+ for (var c = 0; c < 4; c++) {
+ t[0] = s[0][c];
+ t[1] = s[1][c];
+ t[2] = s[2][c];
+ t[3] = s[3][c];
+
+ s[0][c] = (goog.crypt.Aes.MULT_2_[t[0]] ^
+ goog.crypt.Aes.MULT_3_[t[1]] ^ t[2] ^ t[3]);
+ s[1][c] = (t[0] ^ goog.crypt.Aes.MULT_2_[t[1]] ^
+ goog.crypt.Aes.MULT_3_[t[2]] ^ t[3]);
+ s[2][c] = (t[0] ^ t[1] ^ goog.crypt.Aes.MULT_2_[t[2]] ^
+ goog.crypt.Aes.MULT_3_[t[3]]);
+ s[3][c] = (goog.crypt.Aes.MULT_3_[t[0]] ^ t[1] ^ t[2] ^
+ goog.crypt.Aes.MULT_2_[t[3]]);
+ }
+};
+
+
+/**
+ * AES's InvMixColumns procedure.
+ * @private
+ */
+goog.crypt.Aes.prototype.invMixColumns_ = function() {
+ var s = this.state_;
+ var t = this.temp_[0];
+
+ for (var c = 0; c < 4; c++) {
+ t[0] = s[0][c];
+ t[1] = s[1][c];
+ t[2] = s[2][c];
+ t[3] = s[3][c];
+
+ s[0][c] = (
+ goog.crypt.Aes.MULT_E_[t[0]] ^ goog.crypt.Aes.MULT_B_[t[1]] ^
+ goog.crypt.Aes.MULT_D_[t[2]] ^ goog.crypt.Aes.MULT_9_[t[3]]);
+
+ s[1][c] = (
+ goog.crypt.Aes.MULT_9_[t[0]] ^ goog.crypt.Aes.MULT_E_[t[1]] ^
+ goog.crypt.Aes.MULT_B_[t[2]] ^ goog.crypt.Aes.MULT_D_[t[3]]);
+
+ s[2][c] = (
+ goog.crypt.Aes.MULT_D_[t[0]] ^ goog.crypt.Aes.MULT_9_[t[1]] ^
+ goog.crypt.Aes.MULT_E_[t[2]] ^ goog.crypt.Aes.MULT_B_[t[3]]);
+
+ s[3][c] = (
+ goog.crypt.Aes.MULT_B_[t[0]] ^ goog.crypt.Aes.MULT_D_[t[1]] ^
+ goog.crypt.Aes.MULT_9_[t[2]] ^ goog.crypt.Aes.MULT_E_[t[3]]);
+ }
+};
+
+
+/**
+ * AES's KeyExpansion procedure. Create the key schedule from the initial key.
+ * @private
+ */
+goog.crypt.Aes.prototype.keyExpansion_ = function() {
+ this.keySchedule_ = new Array(goog.crypt.Aes.BLOCK_SIZE_ * (
+ this.numberOfRounds_ + 1));
+
+ for (var rowNum = 0; rowNum < this.keyLength_; rowNum++) {
+ this.keySchedule_[rowNum] = [
+ this.key_[4 * rowNum],
+ this.key_[4 * rowNum + 1],
+ this.key_[4 * rowNum + 2],
+ this.key_[4 * rowNum + 3]
+ ];
+ }
+
+ var temp = new Array(4);
+
+ for (var rowNum = this.keyLength_;
+ rowNum < (goog.crypt.Aes.BLOCK_SIZE_ * (this.numberOfRounds_ + 1));
+ rowNum++) {
+ temp[0] = this.keySchedule_[rowNum - 1][0];
+ temp[1] = this.keySchedule_[rowNum - 1][1];
+ temp[2] = this.keySchedule_[rowNum - 1][2];
+ temp[3] = this.keySchedule_[rowNum - 1][3];
+
+ if (rowNum % this.keyLength_ == 0) {
+ this.rotWord_(temp);
+ this.subWord_(temp);
+
+ temp[0] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][0];
+ temp[1] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][1];
+ temp[2] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][2];
+ temp[3] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][3];
+ } else if (this.keyLength_ > 6 && rowNum % this.keyLength_ == 4) {
+ this.subWord_(temp);
+ }
+
+ this.keySchedule_[rowNum] = new Array(4);
+ this.keySchedule_[rowNum][0] =
+ this.keySchedule_[rowNum - this.keyLength_][0] ^ temp[0];
+ this.keySchedule_[rowNum][1] =
+ this.keySchedule_[rowNum - this.keyLength_][1] ^ temp[1];
+ this.keySchedule_[rowNum][2] =
+ this.keySchedule_[rowNum - this.keyLength_][2] ^ temp[2];
+ this.keySchedule_[rowNum][3] =
+ this.keySchedule_[rowNum - this.keyLength_][3] ^ temp[3];
+ }
+};
+
+
+/**
+ * AES's SubWord procedure.
+ * @param {!Array<number>} w Bytes to find the SBox substitution for.
+ * @return {!Array<number>} The substituted bytes.
+ * @private
+ */
+goog.crypt.Aes.prototype.subWord_ = function(w) {
+ w[0] = goog.crypt.Aes.SBOX_[w[0]];
+ w[1] = goog.crypt.Aes.SBOX_[w[1]];
+ w[2] = goog.crypt.Aes.SBOX_[w[2]];
+ w[3] = goog.crypt.Aes.SBOX_[w[3]];
+
+ return w;
+};
+
+
+/**
+ * AES's RotWord procedure.
+ * @param {!Array<number>} w Array of bytes to rotate.
+ * @return {!Array<number>} The rotated bytes.
+ * @private
+ */
+goog.crypt.Aes.prototype.rotWord_ = function(w) {
+ var temp = w[0];
+
+ w[0] = w[1];
+ w[1] = w[2];
+ w[2] = w[3];
+ w[3] = temp;
+
+ return w;
+};
+
+
+/**
+ * Precomputed SBox lookup.
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.SBOX_ = [
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe,
+ 0xd7, 0xab, 0x76,
+
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c,
+ 0xa4, 0x72, 0xc0,
+
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71,
+ 0xd8, 0x31, 0x15,
+
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb,
+ 0x27, 0xb2, 0x75,
+
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
+ 0xe3, 0x2f, 0x84,
+
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a,
+ 0x4c, 0x58, 0xcf,
+
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50,
+ 0x3c, 0x9f, 0xa8,
+
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10,
+ 0xff, 0xf3, 0xd2,
+
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64,
+ 0x5d, 0x19, 0x73,
+
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde,
+ 0x5e, 0x0b, 0xdb,
+
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91,
+ 0x95, 0xe4, 0x79,
+
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65,
+ 0x7a, 0xae, 0x08,
+
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b,
+ 0xbd, 0x8b, 0x8a,
+
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,
+ 0xc1, 0x1d, 0x9e,
+
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce,
+ 0x55, 0x28, 0xdf,
+
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
+ 0x54, 0xbb, 0x16
+];
+
+
+/**
+ * Precomputed InvSBox lookup.
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.INV_SBOX_ = [
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81,
+ 0xf3, 0xd7, 0xfb,
+
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4,
+ 0xde, 0xe9, 0xcb,
+
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42,
+ 0xfa, 0xc3, 0x4e,
+
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d,
+ 0x8b, 0xd1, 0x25,
+
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,
+ 0x65, 0xb6, 0x92,
+
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7,
+ 0x8d, 0x9d, 0x84,
+
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8,
+ 0xb3, 0x45, 0x06,
+
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01,
+ 0x13, 0x8a, 0x6b,
+
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0,
+ 0xb4, 0xe6, 0x73,
+
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c,
+ 0x75, 0xdf, 0x6e,
+
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa,
+ 0x18, 0xbe, 0x1b,
+
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78,
+ 0xcd, 0x5a, 0xf4,
+
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27,
+ 0x80, 0xec, 0x5f,
+
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,
+ 0xc9, 0x9c, 0xef,
+
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83,
+ 0x53, 0x99, 0x61,
+
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
+ 0x21, 0x0c, 0x7d
+];
+
+
+/**
+ * Precomputed RCon lookup.
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.RCON_ = [
+ [0x00, 0x00, 0x00, 0x00],
+ [0x01, 0x00, 0x00, 0x00],
+ [0x02, 0x00, 0x00, 0x00],
+ [0x04, 0x00, 0x00, 0x00],
+ [0x08, 0x00, 0x00, 0x00],
+ [0x10, 0x00, 0x00, 0x00],
+ [0x20, 0x00, 0x00, 0x00],
+ [0x40, 0x00, 0x00, 0x00],
+ [0x80, 0x00, 0x00, 0x00],
+ [0x1b, 0x00, 0x00, 0x00],
+ [0x36, 0x00, 0x00, 0x00]
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 2 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_2_ = [
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16,
+ 0x18, 0x1A, 0x1C, 0x1E,
+
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36,
+ 0x38, 0x3A, 0x3C, 0x3E,
+
+ 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56,
+ 0x58, 0x5A, 0x5C, 0x5E,
+
+ 0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72, 0x74, 0x76,
+ 0x78, 0x7A, 0x7C, 0x7E,
+
+ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x94, 0x96,
+ 0x98, 0x9A, 0x9C, 0x9E,
+
+ 0xA0, 0xA2, 0xA4, 0xA6, 0xA8, 0xAA, 0xAC, 0xAE, 0xB0, 0xB2, 0xB4, 0xB6,
+ 0xB8, 0xBA, 0xBC, 0xBE,
+
+ 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6,
+ 0xD8, 0xDA, 0xDC, 0xDE,
+
+ 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF2, 0xF4, 0xF6,
+ 0xF8, 0xFA, 0xFC, 0xFE,
+
+ 0x1B, 0x19, 0x1F, 0x1D, 0x13, 0x11, 0x17, 0x15, 0x0B, 0x09, 0x0F, 0x0D,
+ 0x03, 0x01, 0x07, 0x05,
+
+ 0x3B, 0x39, 0x3F, 0x3D, 0x33, 0x31, 0x37, 0x35, 0x2B, 0x29, 0x2F, 0x2D,
+ 0x23, 0x21, 0x27, 0x25,
+
+ 0x5B, 0x59, 0x5F, 0x5D, 0x53, 0x51, 0x57, 0x55, 0x4B, 0x49, 0x4F, 0x4D,
+ 0x43, 0x41, 0x47, 0x45,
+
+ 0x7B, 0x79, 0x7F, 0x7D, 0x73, 0x71, 0x77, 0x75, 0x6B, 0x69, 0x6F, 0x6D,
+ 0x63, 0x61, 0x67, 0x65,
+
+ 0x9B, 0x99, 0x9F, 0x9D, 0x93, 0x91, 0x97, 0x95, 0x8B, 0x89, 0x8F, 0x8D,
+ 0x83, 0x81, 0x87, 0x85,
+
+ 0xBB, 0xB9, 0xBF, 0xBD, 0xB3, 0xB1, 0xB7, 0xB5, 0xAB, 0xA9, 0xAF, 0xAD,
+ 0xA3, 0xA1, 0xA7, 0xA5,
+
+ 0xDB, 0xD9, 0xDF, 0xDD, 0xD3, 0xD1, 0xD7, 0xD5, 0xCB, 0xC9, 0xCF, 0xCD,
+ 0xC3, 0xC1, 0xC7, 0xC5,
+
+ 0xFB, 0xF9, 0xFF, 0xFD, 0xF3, 0xF1, 0xF7, 0xF5, 0xEB, 0xE9, 0xEF, 0xED,
+ 0xE3, 0xE1, 0xE7, 0xE5
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 3 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_3_ = [
+ 0x00, 0x03, 0x06, 0x05, 0x0C, 0x0F, 0x0A, 0x09, 0x18, 0x1B, 0x1E, 0x1D,
+ 0x14, 0x17, 0x12, 0x11,
+
+ 0x30, 0x33, 0x36, 0x35, 0x3C, 0x3F, 0x3A, 0x39, 0x28, 0x2B, 0x2E, 0x2D,
+ 0x24, 0x27, 0x22, 0x21,
+
+ 0x60, 0x63, 0x66, 0x65, 0x6C, 0x6F, 0x6A, 0x69, 0x78, 0x7B, 0x7E, 0x7D,
+ 0x74, 0x77, 0x72, 0x71,
+
+ 0x50, 0x53, 0x56, 0x55, 0x5C, 0x5F, 0x5A, 0x59, 0x48, 0x4B, 0x4E, 0x4D,
+ 0x44, 0x47, 0x42, 0x41,
+
+ 0xC0, 0xC3, 0xC6, 0xC5, 0xCC, 0xCF, 0xCA, 0xC9, 0xD8, 0xDB, 0xDE, 0xDD,
+ 0xD4, 0xD7, 0xD2, 0xD1,
+
+ 0xF0, 0xF3, 0xF6, 0xF5, 0xFC, 0xFF, 0xFA, 0xF9, 0xE8, 0xEB, 0xEE, 0xED,
+ 0xE4, 0xE7, 0xE2, 0xE1,
+
+ 0xA0, 0xA3, 0xA6, 0xA5, 0xAC, 0xAF, 0xAA, 0xA9, 0xB8, 0xBB, 0xBE, 0xBD,
+ 0xB4, 0xB7, 0xB2, 0xB1,
+
+ 0x90, 0x93, 0x96, 0x95, 0x9C, 0x9F, 0x9A, 0x99, 0x88, 0x8B, 0x8E, 0x8D,
+ 0x84, 0x87, 0x82, 0x81,
+
+ 0x9B, 0x98, 0x9D, 0x9E, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86,
+ 0x8F, 0x8C, 0x89, 0x8A,
+
+ 0xAB, 0xA8, 0xAD, 0xAE, 0xA7, 0xA4, 0xA1, 0xA2, 0xB3, 0xB0, 0xB5, 0xB6,
+ 0xBF, 0xBC, 0xB9, 0xBA,
+
+ 0xFB, 0xF8, 0xFD, 0xFE, 0xF7, 0xF4, 0xF1, 0xF2, 0xE3, 0xE0, 0xE5, 0xE6,
+ 0xEF, 0xEC, 0xE9, 0xEA,
+
+ 0xCB, 0xC8, 0xCD, 0xCE, 0xC7, 0xC4, 0xC1, 0xC2, 0xD3, 0xD0, 0xD5, 0xD6,
+ 0xDF, 0xDC, 0xD9, 0xDA,
+
+ 0x5B, 0x58, 0x5D, 0x5E, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46,
+ 0x4F, 0x4C, 0x49, 0x4A,
+
+ 0x6B, 0x68, 0x6D, 0x6E, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76,
+ 0x7F, 0x7C, 0x79, 0x7A,
+
+ 0x3B, 0x38, 0x3D, 0x3E, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26,
+ 0x2F, 0x2C, 0x29, 0x2A,
+
+ 0x0B, 0x08, 0x0D, 0x0E, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16,
+ 0x1F, 0x1C, 0x19, 0x1A
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 9 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_9_ = [
+ 0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F, 0x48, 0x41, 0x5A, 0x53,
+ 0x6C, 0x65, 0x7E, 0x77,
+
+ 0x90, 0x99, 0x82, 0x8B, 0xB4, 0xBD, 0xA6, 0xAF, 0xD8, 0xD1, 0xCA, 0xC3,
+ 0xFC, 0xF5, 0xEE, 0xE7,
+
+ 0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04, 0x73, 0x7A, 0x61, 0x68,
+ 0x57, 0x5E, 0x45, 0x4C,
+
+ 0xAB, 0xA2, 0xB9, 0xB0, 0x8F, 0x86, 0x9D, 0x94, 0xE3, 0xEA, 0xF1, 0xF8,
+ 0xC7, 0xCE, 0xD5, 0xDC,
+
+ 0x76, 0x7F, 0x64, 0x6D, 0x52, 0x5B, 0x40, 0x49, 0x3E, 0x37, 0x2C, 0x25,
+ 0x1A, 0x13, 0x08, 0x01,
+
+ 0xE6, 0xEF, 0xF4, 0xFD, 0xC2, 0xCB, 0xD0, 0xD9, 0xAE, 0xA7, 0xBC, 0xB5,
+ 0x8A, 0x83, 0x98, 0x91,
+
+ 0x4D, 0x44, 0x5F, 0x56, 0x69, 0x60, 0x7B, 0x72, 0x05, 0x0C, 0x17, 0x1E,
+ 0x21, 0x28, 0x33, 0x3A,
+
+ 0xDD, 0xD4, 0xCF, 0xC6, 0xF9, 0xF0, 0xEB, 0xE2, 0x95, 0x9C, 0x87, 0x8E,
+ 0xB1, 0xB8, 0xA3, 0xAA,
+
+ 0xEC, 0xE5, 0xFE, 0xF7, 0xC8, 0xC1, 0xDA, 0xD3, 0xA4, 0xAD, 0xB6, 0xBF,
+ 0x80, 0x89, 0x92, 0x9B,
+
+ 0x7C, 0x75, 0x6E, 0x67, 0x58, 0x51, 0x4A, 0x43, 0x34, 0x3D, 0x26, 0x2F,
+ 0x10, 0x19, 0x02, 0x0B,
+
+ 0xD7, 0xDE, 0xC5, 0xCC, 0xF3, 0xFA, 0xE1, 0xE8, 0x9F, 0x96, 0x8D, 0x84,
+ 0xBB, 0xB2, 0xA9, 0xA0,
+
+ 0x47, 0x4E, 0x55, 0x5C, 0x63, 0x6A, 0x71, 0x78, 0x0F, 0x06, 0x1D, 0x14,
+ 0x2B, 0x22, 0x39, 0x30,
+
+ 0x9A, 0x93, 0x88, 0x81, 0xBE, 0xB7, 0xAC, 0xA5, 0xD2, 0xDB, 0xC0, 0xC9,
+ 0xF6, 0xFF, 0xE4, 0xED,
+
+ 0x0A, 0x03, 0x18, 0x11, 0x2E, 0x27, 0x3C, 0x35, 0x42, 0x4B, 0x50, 0x59,
+ 0x66, 0x6F, 0x74, 0x7D,
+
+ 0xA1, 0xA8, 0xB3, 0xBA, 0x85, 0x8C, 0x97, 0x9E, 0xE9, 0xE0, 0xFB, 0xF2,
+ 0xCD, 0xC4, 0xDF, 0xD6,
+
+ 0x31, 0x38, 0x23, 0x2A, 0x15, 0x1C, 0x07, 0x0E, 0x79, 0x70, 0x6B, 0x62,
+ 0x5D, 0x54, 0x4F, 0x46
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 11 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_B_ = [
+ 0x00, 0x0B, 0x16, 0x1D, 0x2C, 0x27, 0x3A, 0x31, 0x58, 0x53, 0x4E, 0x45,
+ 0x74, 0x7F, 0x62, 0x69,
+
+ 0xB0, 0xBB, 0xA6, 0xAD, 0x9C, 0x97, 0x8A, 0x81, 0xE8, 0xE3, 0xFE, 0xF5,
+ 0xC4, 0xCF, 0xD2, 0xD9,
+
+ 0x7B, 0x70, 0x6D, 0x66, 0x57, 0x5C, 0x41, 0x4A, 0x23, 0x28, 0x35, 0x3E,
+ 0x0F, 0x04, 0x19, 0x12,
+
+ 0xCB, 0xC0, 0xDD, 0xD6, 0xE7, 0xEC, 0xF1, 0xFA, 0x93, 0x98, 0x85, 0x8E,
+ 0xBF, 0xB4, 0xA9, 0xA2,
+
+ 0xF6, 0xFD, 0xE0, 0xEB, 0xDA, 0xD1, 0xCC, 0xC7, 0xAE, 0xA5, 0xB8, 0xB3,
+ 0x82, 0x89, 0x94, 0x9F,
+
+ 0x46, 0x4D, 0x50, 0x5B, 0x6A, 0x61, 0x7C, 0x77, 0x1E, 0x15, 0x08, 0x03,
+ 0x32, 0x39, 0x24, 0x2F,
+
+ 0x8D, 0x86, 0x9B, 0x90, 0xA1, 0xAA, 0xB7, 0xBC, 0xD5, 0xDE, 0xC3, 0xC8,
+ 0xF9, 0xF2, 0xEF, 0xE4,
+
+ 0x3D, 0x36, 0x2B, 0x20, 0x11, 0x1A, 0x07, 0x0C, 0x65, 0x6E, 0x73, 0x78,
+ 0x49, 0x42, 0x5F, 0x54,
+
+ 0xF7, 0xFC, 0xE1, 0xEA, 0xDB, 0xD0, 0xCD, 0xC6, 0xAF, 0xA4, 0xB9, 0xB2,
+ 0x83, 0x88, 0x95, 0x9E,
+
+ 0x47, 0x4C, 0x51, 0x5A, 0x6B, 0x60, 0x7D, 0x76, 0x1F, 0x14, 0x09, 0x02,
+ 0x33, 0x38, 0x25, 0x2E,
+
+ 0x8C, 0x87, 0x9A, 0x91, 0xA0, 0xAB, 0xB6, 0xBD, 0xD4, 0xDF, 0xC2, 0xC9,
+ 0xF8, 0xF3, 0xEE, 0xE5,
+
+ 0x3C, 0x37, 0x2A, 0x21, 0x10, 0x1B, 0x06, 0x0D, 0x64, 0x6F, 0x72, 0x79,
+ 0x48, 0x43, 0x5E, 0x55,
+
+ 0x01, 0x0A, 0x17, 0x1C, 0x2D, 0x26, 0x3B, 0x30, 0x59, 0x52, 0x4F, 0x44,
+ 0x75, 0x7E, 0x63, 0x68,
+
+ 0xB1, 0xBA, 0xA7, 0xAC, 0x9D, 0x96, 0x8B, 0x80, 0xE9, 0xE2, 0xFF, 0xF4,
+ 0xC5, 0xCE, 0xD3, 0xD8,
+
+ 0x7A, 0x71, 0x6C, 0x67, 0x56, 0x5D, 0x40, 0x4B, 0x22, 0x29, 0x34, 0x3F,
+ 0x0E, 0x05, 0x18, 0x13,
+
+ 0xCA, 0xC1, 0xDC, 0xD7, 0xE6, 0xED, 0xF0, 0xFB, 0x92, 0x99, 0x84, 0x8F,
+ 0xBE, 0xB5, 0xA8, 0xA3
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 13 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_D_ = [
+ 0x00, 0x0D, 0x1A, 0x17, 0x34, 0x39, 0x2E, 0x23, 0x68, 0x65, 0x72, 0x7F,
+ 0x5C, 0x51, 0x46, 0x4B,
+
+ 0xD0, 0xDD, 0xCA, 0xC7, 0xE4, 0xE9, 0xFE, 0xF3, 0xB8, 0xB5, 0xA2, 0xAF,
+ 0x8C, 0x81, 0x96, 0x9B,
+
+ 0xBB, 0xB6, 0xA1, 0xAC, 0x8F, 0x82, 0x95, 0x98, 0xD3, 0xDE, 0xC9, 0xC4,
+ 0xE7, 0xEA, 0xFD, 0xF0,
+
+ 0x6B, 0x66, 0x71, 0x7C, 0x5F, 0x52, 0x45, 0x48, 0x03, 0x0E, 0x19, 0x14,
+ 0x37, 0x3A, 0x2D, 0x20,
+
+ 0x6D, 0x60, 0x77, 0x7A, 0x59, 0x54, 0x43, 0x4E, 0x05, 0x08, 0x1F, 0x12,
+ 0x31, 0x3C, 0x2B, 0x26,
+
+ 0xBD, 0xB0, 0xA7, 0xAA, 0x89, 0x84, 0x93, 0x9E, 0xD5, 0xD8, 0xCF, 0xC2,
+ 0xE1, 0xEC, 0xFB, 0xF6,
+
+ 0xD6, 0xDB, 0xCC, 0xC1, 0xE2, 0xEF, 0xF8, 0xF5, 0xBE, 0xB3, 0xA4, 0xA9,
+ 0x8A, 0x87, 0x90, 0x9D,
+
+ 0x06, 0x0B, 0x1C, 0x11, 0x32, 0x3F, 0x28, 0x25, 0x6E, 0x63, 0x74, 0x79,
+ 0x5A, 0x57, 0x40, 0x4D,
+
+ 0xDA, 0xD7, 0xC0, 0xCD, 0xEE, 0xE3, 0xF4, 0xF9, 0xB2, 0xBF, 0xA8, 0xA5,
+ 0x86, 0x8B, 0x9C, 0x91,
+
+ 0x0A, 0x07, 0x10, 0x1D, 0x3E, 0x33, 0x24, 0x29, 0x62, 0x6F, 0x78, 0x75,
+ 0x56, 0x5B, 0x4C, 0x41,
+
+ 0x61, 0x6C, 0x7B, 0x76, 0x55, 0x58, 0x4F, 0x42, 0x09, 0x04, 0x13, 0x1E,
+ 0x3D, 0x30, 0x27, 0x2A,
+
+ 0xB1, 0xBC, 0xAB, 0xA6, 0x85, 0x88, 0x9F, 0x92, 0xD9, 0xD4, 0xC3, 0xCE,
+ 0xED, 0xE0, 0xF7, 0xFA,
+
+ 0xB7, 0xBA, 0xAD, 0xA0, 0x83, 0x8E, 0x99, 0x94, 0xDF, 0xD2, 0xC5, 0xC8,
+ 0xEB, 0xE6, 0xF1, 0xFC,
+
+ 0x67, 0x6A, 0x7D, 0x70, 0x53, 0x5E, 0x49, 0x44, 0x0F, 0x02, 0x15, 0x18,
+ 0x3B, 0x36, 0x21, 0x2C,
+
+ 0x0C, 0x01, 0x16, 0x1B, 0x38, 0x35, 0x22, 0x2F, 0x64, 0x69, 0x7E, 0x73,
+ 0x50, 0x5D, 0x4A, 0x47,
+
+ 0xDC, 0xD1, 0xC6, 0xCB, 0xE8, 0xE5, 0xF2, 0xFF, 0xB4, 0xB9, 0xAE, 0xA3,
+ 0x80, 0x8D, 0x9A, 0x97
+];
+
+
+/**
+ * Precomputed lookup of multiplication by 14 in GF(2^8)
+ * @type {!Array<number>}
+ * @private
+ */
+goog.crypt.Aes.MULT_E_ = [
+ 0x00, 0x0E, 0x1C, 0x12, 0x38, 0x36, 0x24, 0x2A, 0x70, 0x7E, 0x6C, 0x62,
+ 0x48, 0x46, 0x54, 0x5A,
+
+ 0xE0, 0xEE, 0xFC, 0xF2, 0xD8, 0xD6, 0xC4, 0xCA, 0x90, 0x9E, 0x8C, 0x82,
+ 0xA8, 0xA6, 0xB4, 0xBA,
+
+ 0xDB, 0xD5, 0xC7, 0xC9, 0xE3, 0xED, 0xFF, 0xF1, 0xAB, 0xA5, 0xB7, 0xB9,
+ 0x93, 0x9D, 0x8F, 0x81,
+
+ 0x3B, 0x35, 0x27, 0x29, 0x03, 0x0D, 0x1F, 0x11, 0x4B, 0x45, 0x57, 0x59,
+ 0x73, 0x7D, 0x6F, 0x61,
+
+ 0xAD, 0xA3, 0xB1, 0xBF, 0x95, 0x9B, 0x89, 0x87, 0xDD, 0xD3, 0xC1, 0xCF,
+ 0xE5, 0xEB, 0xF9, 0xF7,
+
+ 0x4D, 0x43, 0x51, 0x5F, 0x75, 0x7B, 0x69, 0x67, 0x3D, 0x33, 0x21, 0x2F,
+ 0x05, 0x0B, 0x19, 0x17,
+
+ 0x76, 0x78, 0x6A, 0x64, 0x4E, 0x40, 0x52, 0x5C, 0x06, 0x08, 0x1A, 0x14,
+ 0x3E, 0x30, 0x22, 0x2C,
+
+ 0x96, 0x98, 0x8A, 0x84, 0xAE, 0xA0, 0xB2, 0xBC, 0xE6, 0xE8, 0xFA, 0xF4,
+ 0xDE, 0xD0, 0xC2, 0xCC,
+
+ 0x41, 0x4F, 0x5D, 0x53, 0x79, 0x77, 0x65, 0x6B, 0x31, 0x3F, 0x2D, 0x23,
+ 0x09, 0x07, 0x15, 0x1B,
+
+ 0xA1, 0xAF, 0xBD, 0xB3, 0x99, 0x97, 0x85, 0x8B, 0xD1, 0xDF, 0xCD, 0xC3,
+ 0xE9, 0xE7, 0xF5, 0xFB,
+
+ 0x9A, 0x94, 0x86, 0x88, 0xA2, 0xAC, 0xBE, 0xB0, 0xEA, 0xE4, 0xF6, 0xF8,
+ 0xD2, 0xDC, 0xCE, 0xC0,
+
+ 0x7A, 0x74, 0x66, 0x68, 0x42, 0x4C, 0x5E, 0x50, 0x0A, 0x04, 0x16, 0x18,
+ 0x32, 0x3C, 0x2E, 0x20,
+
+ 0xEC, 0xE2, 0xF0, 0xFE, 0xD4, 0xDA, 0xC8, 0xC6, 0x9C, 0x92, 0x80, 0x8E,
+ 0xA4, 0xAA, 0xB8, 0xB6,
+
+ 0x0C, 0x02, 0x10, 0x1E, 0x34, 0x3A, 0x28, 0x26, 0x7C, 0x72, 0x60, 0x6E,
+ 0x44, 0x4A, 0x58, 0x56,
+
+ 0x37, 0x39, 0x2B, 0x25, 0x0F, 0x01, 0x13, 0x1D, 0x47, 0x49, 0x5B, 0x55,
+ 0x7F, 0x71, 0x63, 0x6D,
+
+ 0xD7, 0xD9, 0xCB, 0xC5, 0xEF, 0xE1, 0xF3, 0xFD, 0xA7, 0xA9, 0xBB, 0xB5,
+ 0x9F, 0x91, 0x83, 0x8D
+];
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/arc4.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/arc4.js b/externs/GCL/externs/goog/crypt/arc4.js
new file mode 100644
index 0000000..73c6758
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/arc4.js
@@ -0,0 +1,164 @@
+// 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 ARC4 streamcipher implementation. A description of the
+ * algorithm can be found at:
+ * http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt.
+ *
+ * Usage:
+ * <code>
+ * var arc4 = new goog.crypt.Arc4();
+ * arc4.setKey(key);
+ * arc4.discard(1536);
+ * arc4.crypt(bytes);
+ * </code>
+ *
+ * Note: For converting between strings and byte arrays, goog.crypt.base64 may
+ * be useful.
+ *
+ */
+
+goog.provide('goog.crypt.Arc4');
+
+goog.require('goog.asserts');
+
+
+
+/**
+ * ARC4 streamcipher implementation.
+ * @constructor
+ * @final
+ * @struct
+ */
+goog.crypt.Arc4 = function() {
+ /**
+ * A permutation of all 256 possible bytes.
+ * @type {Array<number>}
+ * @private
+ */
+ this.state_ = [];
+
+ /**
+ * 8 bit index pointer into this.state_.
+ * @type {number}
+ * @private
+ */
+ this.index1_ = 0;
+
+ /**
+ * 8 bit index pointer into this.state_.
+ * @type {number}
+ * @private
+ */
+ this.index2_ = 0;
+};
+
+
+/**
+ * Initialize the cipher for use with new key.
+ * @param {Array<number>} key A byte array containing the key.
+ * @param {number=} opt_length Indicates # of bytes to take from the key.
+ */
+goog.crypt.Arc4.prototype.setKey = function(key, opt_length) {
+ goog.asserts.assertArray(key, 'Key parameter must be a byte array');
+
+ if (!opt_length) {
+ opt_length = key.length;
+ }
+
+ var state = this.state_;
+
+ for (var i = 0; i < 256; ++i) {
+ state[i] = i;
+ }
+
+ var j = 0;
+ for (var i = 0; i < 256; ++i) {
+ j = (j + state[i] + key[i % opt_length]) & 255;
+
+ var tmp = state[i];
+ state[i] = state[j];
+ state[j] = tmp;
+ }
+
+ this.index1_ = 0;
+ this.index2_ = 0;
+};
+
+
+/**
+ * Discards n bytes of the keystream.
+ * These days 1536 is considered a decent amount to drop to get the key state
+ * warmed-up enough for secure usage. This is not done in the constructor to
+ * preserve efficiency for use cases that do not need this.
+ * NOTE: Discard is identical to crypt without actually xoring any data. It's
+ * unfortunate to have this code duplicated, but this was done for performance
+ * reasons. Alternatives which were attempted:
+ * 1. Create a temp array of the correct length and pass it to crypt. This
+ * works but needlessly allocates an array. But more importantly this
+ * requires choosing an array type (Array or Uint8Array) in discard, and
+ * choosing a different type than will be passed to crypt by the client
+ * code hurts the javascript engines ability to optimize crypt (7x hit in
+ * v8).
+ * 2. Make data option in crypt so discard can pass null, this has a huge
+ * perf hit for crypt.
+ * @param {number} length Number of bytes to disregard from the stream.
+ */
+goog.crypt.Arc4.prototype.discard = function(length) {
+ var i = this.index1_;
+ var j = this.index2_;
+ var state = this.state_;
+
+ for (var n = 0; n < length; ++n) {
+ i = (i + 1) & 255;
+ j = (j + state[i]) & 255;
+
+ var tmp = state[i];
+ state[i] = state[j];
+ state[j] = tmp;
+ }
+
+ this.index1_ = i;
+ this.index2_ = j;
+};
+
+
+/**
+ * En- or decrypt (same operation for streamciphers like ARC4)
+ * @param {Array<number>|Uint8Array} data The data to be xor-ed in place.
+ * @param {number=} opt_length The number of bytes to crypt.
+ */
+goog.crypt.Arc4.prototype.crypt = function(data, opt_length) {
+ if (!opt_length) {
+ opt_length = data.length;
+ }
+ var i = this.index1_;
+ var j = this.index2_;
+ var state = this.state_;
+
+ for (var n = 0; n < opt_length; ++n) {
+ i = (i + 1) & 255;
+ j = (j + state[i]) & 255;
+
+ var tmp = state[i];
+ state[i] = state[j];
+ state[j] = tmp;
+
+ data[n] ^= state[(state[i] + state[j]) & 255];
+ }
+
+ this.index1_ = i;
+ this.index2_ = j;
+};
[44/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha2.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha2.js b/externs/GCL/externs/goog/crypt/sha2.js
new file mode 100644
index 0000000..eae5b14
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha2.js
@@ -0,0 +1,338 @@
+// Copyright 2012 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 Base class for SHA-2 cryptographic hash.
+ *
+ * Variable names follow the notation in FIPS PUB 180-3:
+ * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
+ *
+ * Some code similar to SHA1 are borrowed from sha1.js written by mschilder@.
+ *
+ */
+
+goog.provide('goog.crypt.Sha2');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.crypt.Hash');
+
+
+
+/**
+ * SHA-2 cryptographic hash constructor.
+ * This constructor should not be used directly to create the object. Rather,
+ * one should use the constructor of the sub-classes.
+ * @param {number} numHashBlocks The size of output in 16-byte blocks.
+ * @param {!Array<number>} initHashBlocks The hash-specific initialization
+ * @constructor
+ * @extends {goog.crypt.Hash}
+ * @struct
+ */
+goog.crypt.Sha2 = function(numHashBlocks, initHashBlocks) {
+ goog.crypt.Sha2.base(this, 'constructor');
+
+ this.blockSize = goog.crypt.Sha2.BLOCKSIZE_;
+
+ /**
+ * A chunk holding the currently processed message bytes. Once the chunk has
+ * 64 bytes, we feed it into computeChunk_ function and reset this.chunk_.
+ * @private {!Array<number>|!Uint8Array}
+ */
+ this.chunk_ = goog.global['Uint8Array'] ?
+ new Uint8Array(this.blockSize) : new Array(this.blockSize);
+
+ /**
+ * Current number of bytes in this.chunk_.
+ * @private {number}
+ */
+ this.inChunk_ = 0;
+
+ /**
+ * Total number of bytes in currently processed message.
+ * @private {number}
+ */
+ this.total_ = 0;
+
+
+ /**
+ * Holds the previous values of accumulated hash a-h in the computeChunk_
+ * function.
+ * @private {!Array<number>|!Int32Array}
+ */
+ this.hash_ = [];
+
+ /**
+ * The number of output hash blocks (each block is 4 bytes long).
+ * @private {number}
+ */
+ this.numHashBlocks_ = numHashBlocks;
+
+ /**
+ * @private {!Array<number>} initHashBlocks
+ */
+ this.initHashBlocks_ = initHashBlocks;
+
+ /**
+ * Temporary array used in chunk computation. Allocate here as a
+ * member rather than as a local within computeChunk_() as a
+ * performance optimization to reduce the number of allocations and
+ * reduce garbage collection.
+ * @private {!Int32Array|!Array<number>}
+ */
+ this.w_ = goog.global['Int32Array'] ? new Int32Array(64) : new Array(64);
+
+ if (!goog.isDef(goog.crypt.Sha2.Kx_)) {
+ // This is the first time this constructor has been called.
+ if (goog.global['Int32Array']) {
+ // Typed arrays exist
+ goog.crypt.Sha2.Kx_ = new Int32Array(goog.crypt.Sha2.K_);
+ } else {
+ // Typed arrays do not exist
+ goog.crypt.Sha2.Kx_ = goog.crypt.Sha2.K_;
+ }
+ }
+
+ this.reset();
+};
+goog.inherits(goog.crypt.Sha2, goog.crypt.Hash);
+
+
+/**
+ * The block size
+ * @private {number}
+ */
+goog.crypt.Sha2.BLOCKSIZE_ = 512 / 8;
+
+
+/**
+ * Contains data needed to pad messages less than BLOCK_SIZE_ bytes.
+ * @private {!Array<number>}
+ */
+goog.crypt.Sha2.PADDING_ = goog.array.concat(128,
+ goog.array.repeat(0, goog.crypt.Sha2.BLOCKSIZE_ - 1));
+
+
+/** @override */
+goog.crypt.Sha2.prototype.reset = function() {
+ this.inChunk_ = 0;
+ this.total_ = 0;
+ this.hash_ = goog.global['Int32Array'] ?
+ new Int32Array(this.initHashBlocks_) :
+ goog.array.clone(this.initHashBlocks_);
+};
+
+
+/**
+ * Helper function to compute the hashes for a given 512-bit message chunk.
+ * @private
+ */
+goog.crypt.Sha2.prototype.computeChunk_ = function() {
+ var chunk = this.chunk_;
+ goog.asserts.assert(chunk.length == this.blockSize);
+ var rounds = 64;
+
+ // Divide the chunk into 16 32-bit-words.
+ var w = this.w_;
+ var index = 0;
+ var offset = 0;
+ while (offset < chunk.length) {
+ w[index++] = (chunk[offset] << 24) |
+ (chunk[offset + 1] << 16) |
+ (chunk[offset + 2] << 8) |
+ (chunk[offset + 3]);
+ offset = index * 4;
+ }
+
+ // Extend the w[] array to be the number of rounds.
+ for (var i = 16; i < rounds; i++) {
+ var w_15 = w[i - 15] | 0;
+ var s0 = ((w_15 >>> 7) | (w_15 << 25)) ^
+ ((w_15 >>> 18) | (w_15 << 14)) ^
+ (w_15 >>> 3);
+ var w_2 = w[i - 2] | 0;
+ var s1 = ((w_2 >>> 17) | (w_2 << 15)) ^
+ ((w_2 >>> 19) | (w_2 << 13)) ^
+ (w_2 >>> 10);
+
+ // As a performance optimization, construct the sum a pair at a time
+ // with casting to integer (bitwise OR) to eliminate unnecessary
+ // double<->integer conversions.
+ var partialSum1 = ((w[i - 16] | 0) + s0) | 0;
+ var partialSum2 = ((w[i - 7] | 0) + s1) | 0;
+ w[i] = (partialSum1 + partialSum2) | 0;
+ }
+
+ var a = this.hash_[0] | 0;
+ var b = this.hash_[1] | 0;
+ var c = this.hash_[2] | 0;
+ var d = this.hash_[3] | 0;
+ var e = this.hash_[4] | 0;
+ var f = this.hash_[5] | 0;
+ var g = this.hash_[6] | 0;
+ var h = this.hash_[7] | 0;
+ for (var i = 0; i < rounds; i++) {
+ var S0 = ((a >>> 2) | (a << 30)) ^
+ ((a >>> 13) | (a << 19)) ^
+ ((a >>> 22) | (a << 10));
+ var maj = ((a & b) ^ (a & c) ^ (b & c));
+ var t2 = (S0 + maj) | 0;
+ var S1 = ((e >>> 6) | (e << 26)) ^
+ ((e >>> 11) | (e << 21)) ^
+ ((e >>> 25) | (e << 7));
+ var ch = ((e & f) ^ ((~ e) & g));
+
+ // As a performance optimization, construct the sum a pair at a time
+ // with casting to integer (bitwise OR) to eliminate unnecessary
+ // double<->integer conversions.
+ var partialSum1 = (h + S1) | 0;
+ var partialSum2 = (ch + (goog.crypt.Sha2.Kx_[i] | 0)) | 0;
+ var partialSum3 = (partialSum2 + (w[i] | 0)) | 0;
+ var t1 = (partialSum1 + partialSum3) | 0;
+
+ h = g;
+ g = f;
+ f = e;
+ e = (d + t1) | 0;
+ d = c;
+ c = b;
+ b = a;
+ a = (t1 + t2) | 0;
+ }
+
+ this.hash_[0] = (this.hash_[0] + a) | 0;
+ this.hash_[1] = (this.hash_[1] + b) | 0;
+ this.hash_[2] = (this.hash_[2] + c) | 0;
+ this.hash_[3] = (this.hash_[3] + d) | 0;
+ this.hash_[4] = (this.hash_[4] + e) | 0;
+ this.hash_[5] = (this.hash_[5] + f) | 0;
+ this.hash_[6] = (this.hash_[6] + g) | 0;
+ this.hash_[7] = (this.hash_[7] + h) | 0;
+};
+
+
+/** @override */
+goog.crypt.Sha2.prototype.update = function(message, opt_length) {
+ if (!goog.isDef(opt_length)) {
+ opt_length = message.length;
+ }
+ // Process the message from left to right up to |opt_length| bytes.
+ // When we get a 512-bit chunk, compute the hash of it and reset
+ // this.chunk_. The message might not be multiple of 512 bits so we
+ // might end up with a chunk that is less than 512 bits. We store
+ // such partial chunk in this.chunk_ and it will be filled up later
+ // in digest().
+ var n = 0;
+ var inChunk = this.inChunk_;
+
+ // The input message could be either byte array of string.
+ if (goog.isString(message)) {
+ while (n < opt_length) {
+ this.chunk_[inChunk++] = message.charCodeAt(n++);
+ if (inChunk == this.blockSize) {
+ this.computeChunk_();
+ inChunk = 0;
+ }
+ }
+ } else if (goog.isArray(message)) {
+ while (n < opt_length) {
+ var b = message[n++];
+ if (!('number' == typeof b && 0 <= b && 255 >= b && b == (b | 0))) {
+ throw Error('message must be a byte array');
+ }
+ this.chunk_[inChunk++] = b;
+ if (inChunk == this.blockSize) {
+ this.computeChunk_();
+ inChunk = 0;
+ }
+ }
+ } else {
+ throw Error('message must be string or array');
+ }
+
+ // Record the current bytes in chunk to support partial update.
+ this.inChunk_ = inChunk;
+
+ // Record total message bytes we have processed so far.
+ this.total_ += opt_length;
+};
+
+
+/** @override */
+goog.crypt.Sha2.prototype.digest = function() {
+ var digest = [];
+ var totalBits = this.total_ * 8;
+
+ // Append pad 0x80 0x00*.
+ if (this.inChunk_ < 56) {
+ this.update(goog.crypt.Sha2.PADDING_, 56 - this.inChunk_);
+ } else {
+ this.update(goog.crypt.Sha2.PADDING_,
+ this.blockSize - (this.inChunk_ - 56));
+ }
+
+ // Append # bits in the 64-bit big-endian format.
+ for (var i = 63; i >= 56; i--) {
+ this.chunk_[i] = totalBits & 255;
+ totalBits /= 256; // Don't use bit-shifting here!
+ }
+ this.computeChunk_();
+
+ // Finally, output the result digest.
+ var n = 0;
+ for (var i = 0; i < this.numHashBlocks_; i++) {
+ for (var j = 24; j >= 0; j -= 8) {
+ digest[n++] = ((this.hash_[i] >> j) & 255);
+ }
+ }
+ return digest;
+};
+
+
+/**
+ * Constants used in SHA-2.
+ * @const
+ * @private {!Array<number>}
+ */
+goog.crypt.Sha2.K_ = [
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+];
+
+
+/**
+ * Sha2.K as an Int32Array if this JS supports typed arrays; otherwise,
+ * the same array as Sha2.K.
+ *
+ * The compiler cannot remove an Int32Array, even if it is not needed
+ * (There are certain cases where creating an Int32Array is not
+ * side-effect free). Instead, the first time we construct a Sha2
+ * instance, we convert or assign Sha2.K as appropriate.
+ * @private {undefined|!Array<number>|!Int32Array}
+ */
+goog.crypt.Sha2.Kx_;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha224.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha224.js b/externs/GCL/externs/goog/crypt/sha224.js
new file mode 100644
index 0000000..40c59e9
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha224.js
@@ -0,0 +1,50 @@
+// Copyright 2012 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 SHA-224 cryptographic hash.
+ *
+ * Usage:
+ * var sha224 = new goog.crypt.Sha224();
+ * sha224.update(bytes);
+ * var hash = sha224.digest();
+ *
+ */
+
+goog.provide('goog.crypt.Sha224');
+
+goog.require('goog.crypt.Sha2');
+
+
+
+/**
+ * SHA-224 cryptographic hash constructor.
+ *
+ * @constructor
+ * @extends {goog.crypt.Sha2}
+ * @final
+ * @struct
+ */
+goog.crypt.Sha224 = function() {
+ goog.crypt.Sha224.base(this, 'constructor',
+ 7, goog.crypt.Sha224.INIT_HASH_BLOCK_);
+};
+goog.inherits(goog.crypt.Sha224, goog.crypt.Sha2);
+
+
+/** @private {!Array<number>} */
+goog.crypt.Sha224.INIT_HASH_BLOCK_ = [
+ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4];
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha256.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha256.js b/externs/GCL/externs/goog/crypt/sha256.js
new file mode 100644
index 0000000..38dafb0
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha256.js
@@ -0,0 +1,49 @@
+// Copyright 2012 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 SHA-256 cryptographic hash.
+ *
+ * Usage:
+ * var sha256 = new goog.crypt.Sha256();
+ * sha256.update(bytes);
+ * var hash = sha256.digest();
+ *
+ */
+
+goog.provide('goog.crypt.Sha256');
+
+goog.require('goog.crypt.Sha2');
+
+
+
+/**
+ * SHA-256 cryptographic hash constructor.
+ *
+ * @constructor
+ * @extends {goog.crypt.Sha2}
+ * @final
+ * @struct
+ */
+goog.crypt.Sha256 = function() {
+ goog.crypt.Sha256.base(this, 'constructor',
+ 8, goog.crypt.Sha256.INIT_HASH_BLOCK_);
+};
+goog.inherits(goog.crypt.Sha256, goog.crypt.Sha2);
+
+
+/** @private {!Array<number>} */
+goog.crypt.Sha256.INIT_HASH_BLOCK_ = [
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha2_64bit.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha2_64bit.js b/externs/GCL/externs/goog/crypt/sha2_64bit.js
new file mode 100644
index 0000000..077b9c4
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha2_64bit.js
@@ -0,0 +1,550 @@
+// 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 Base class for the 64-bit SHA-2 cryptographic hashes.
+ *
+ * Variable names follow the notation in FIPS PUB 180-3:
+ * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
+ *
+ * This code borrows heavily from the 32-bit SHA2 implementation written by
+ * Yue Zhang (zysxqn@).
+ *
+ * @author fy@google.com (Frank Yellin)
+ */
+
+goog.provide('goog.crypt.Sha2_64bit');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.crypt.Hash');
+goog.require('goog.math.Long');
+
+
+
+/**
+ * Constructs a SHA-2 64-bit cryptographic hash.
+ * This class should not be used. Rather, one should use one of its
+ * subclasses.
+ * @constructor
+ * @param {number} numHashBlocks The size of the output in 16-byte blocks
+ * @param {!Array<number>} initHashBlocks The hash-specific initialization
+ * vector, as a sequence of sixteen 32-bit numbers.
+ * @extends {goog.crypt.Hash}
+ * @struct
+ */
+goog.crypt.Sha2_64bit = function(numHashBlocks, initHashBlocks) {
+ goog.crypt.Sha2_64bit.base(this, 'constructor');
+
+ /**
+ * The number of bytes that are digested in each pass of this hasher.
+ * @const {number}
+ */
+ this.blockSize = goog.crypt.Sha2_64bit.BLOCK_SIZE_;
+
+ /**
+ * A chunk holding the currently processed message bytes. Once the chunk has
+ * {@code this.blocksize} bytes, we feed it into [@code computeChunk_}.
+ * @private {!Uint8Array|!Array<number>}
+ */
+ this.chunk_ = goog.isDef(goog.global.Uint8Array) ?
+ new Uint8Array(goog.crypt.Sha2_64bit.BLOCK_SIZE_) :
+ new Array(goog.crypt.Sha2_64bit.BLOCK_SIZE_);
+
+ /**
+ * Current number of bytes in {@code this.chunk_}.
+ * @private {number}
+ */
+ this.chunkBytes_ = 0;
+
+ /**
+ * Total number of bytes in currently processed message.
+ * @private {number}
+ */
+ this.total_ = 0;
+
+ /**
+ * Holds the previous values of accumulated hash a-h in the
+ * {@code computeChunk_} function.
+ * @private {!Array<!goog.math.Long>}
+ */
+ this.hash_ = [];
+
+ /**
+ * The number of blocks of output produced by this hash function, where each
+ * block is eight bytes long.
+ * @private {number}
+ */
+ this.numHashBlocks_ = numHashBlocks;
+
+ /**
+ * Temporary array used in chunk computation. Allocate here as a
+ * member rather than as a local within computeChunk_() as a
+ * performance optimization to reduce the number of allocations and
+ * reduce garbage collection.
+ * @type {!Array<!goog.math.Long>}
+ * @private
+ */
+ this.w_ = [];
+
+ /**
+ * The value to which {@code this.hash_} should be reset when this
+ * Hasher is reset.
+ * @private @const {!Array<!goog.math.Long>}
+ */
+ this.initHashBlocks_ = goog.crypt.Sha2_64bit.toLongArray_(initHashBlocks);
+
+ /**
+ * If true, we have taken the digest from this hasher, but we have not
+ * yet reset it.
+ *
+ * @private {boolean}
+ */
+ this.needsReset_ = false;
+
+ this.reset();
+};
+goog.inherits(goog.crypt.Sha2_64bit, goog.crypt.Hash);
+
+
+/**
+ * The number of bytes that are digested in each pass of this hasher.
+ * @private @const {number}
+ */
+goog.crypt.Sha2_64bit.BLOCK_SIZE_ = 1024 / 8;
+
+
+/**
+ * Contains data needed to pad messages less than {@code blocksize} bytes.
+ * @private {!Array<number>}
+ */
+goog.crypt.Sha2_64bit.PADDING_ = goog.array.concat(
+ [0x80], goog.array.repeat(0, goog.crypt.Sha2_64bit.BLOCK_SIZE_ - 1));
+
+
+/**
+ * Resets this hash function.
+ * @override
+ */
+goog.crypt.Sha2_64bit.prototype.reset = function() {
+ this.chunkBytes_ = 0;
+ this.total_ = 0;
+ this.hash_ = goog.array.clone(this.initHashBlocks_);
+ this.needsReset_ = false;
+};
+
+
+/** @override */
+goog.crypt.Sha2_64bit.prototype.update = function(message, opt_length) {
+ var length = goog.isDef(opt_length) ? opt_length : message.length;
+
+ // Make sure this hasher is usable.
+ if (this.needsReset_) {
+ throw Error('this hasher needs to be reset');
+ }
+ // Process the message from left to right up to |length| bytes.
+ // When we get a 512-bit chunk, compute the hash of it and reset
+ // this.chunk_. The message might not be multiple of 512 bits so we
+ // might end up with a chunk that is less than 512 bits. We store
+ // such partial chunk in chunk_ and it will be filled up later
+ // in digest().
+ var chunkBytes = this.chunkBytes_;
+
+ // The input message could be either byte array or string.
+ if (goog.isString(message)) {
+ for (var i = 0; i < length; i++) {
+ var b = message.charCodeAt(i);
+ if (b > 255) {
+ throw Error('Characters must be in range [0,255]');
+ }
+ this.chunk_[chunkBytes++] = b;
+ if (chunkBytes == this.blockSize) {
+ this.computeChunk_();
+ chunkBytes = 0;
+ }
+ }
+ } else if (goog.isArray(message)) {
+ for (var i = 0; i < length; i++) {
+ var b = message[i];
+ // Hack: b|0 coerces b to an integer, so the last part confirms that
+ // b has no fractional part.
+ if (!goog.isNumber(b) || b < 0 || b > 255 || b != (b | 0)) {
+ throw Error('message must be a byte array');
+ }
+ this.chunk_[chunkBytes++] = b;
+ if (chunkBytes == this.blockSize) {
+ this.computeChunk_();
+ chunkBytes = 0;
+ }
+ }
+ } else {
+ throw Error('message must be string or array');
+ }
+
+ // Record the current bytes in chunk to support partial update.
+ this.chunkBytes_ = chunkBytes;
+
+ // Record total message bytes we have processed so far.
+ this.total_ += length;
+};
+
+
+/** @override */
+goog.crypt.Sha2_64bit.prototype.digest = function() {
+ if (this.needsReset_) {
+ throw Error('this hasher needs to be reset');
+ }
+ var totalBits = this.total_ * 8;
+
+ // Append pad 0x80 0x00* until this.chunkBytes_ == 112
+ if (this.chunkBytes_ < 112) {
+ this.update(goog.crypt.Sha2_64bit.PADDING_, 112 - this.chunkBytes_);
+ } else {
+ // the rest of this block, plus 112 bytes of next block
+ this.update(goog.crypt.Sha2_64bit.PADDING_,
+ this.blockSize - this.chunkBytes_ + 112);
+ }
+
+ // Append # bits in the 64-bit big-endian format.
+ for (var i = 127; i >= 112; i--) {
+ this.chunk_[i] = totalBits & 255;
+ totalBits /= 256; // Don't use bit-shifting here!
+ }
+ this.computeChunk_();
+
+ // Finally, output the result digest.
+ var n = 0;
+ var digest = new Array(8 * this.numHashBlocks_);
+ for (var i = 0; i < this.numHashBlocks_; i++) {
+ var block = this.hash_[i];
+ var high = block.getHighBits();
+ var low = block.getLowBits();
+ for (var j = 24; j >= 0; j -= 8) {
+ digest[n++] = ((high >> j) & 255);
+ }
+ for (var j = 24; j >= 0; j -= 8) {
+ digest[n++] = ((low >> j) & 255);
+ }
+ }
+
+ // The next call to this hasher must be a reset
+ this.needsReset_ = true;
+ return digest;
+};
+
+
+/**
+ * Updates this hash by processing the 1024-bit message chunk in this.chunk_.
+ * @private
+ */
+goog.crypt.Sha2_64bit.prototype.computeChunk_ = function() {
+ var chunk = this.chunk_;
+ var K_ = goog.crypt.Sha2_64bit.K_;
+
+ // Divide the chunk into 16 64-bit-words.
+ var w = this.w_;
+ for (var i = 0; i < 16; i++) {
+ var offset = i * 8;
+ w[i] = new goog.math.Long(
+ (chunk[offset + 4] << 24) | (chunk[offset + 5] << 16) |
+ (chunk[offset + 6] << 8) | (chunk[offset + 7]),
+ (chunk[offset] << 24) | (chunk[offset + 1] << 16) |
+ (chunk[offset + 2] << 8) | (chunk[offset + 3]));
+
+ }
+
+ // Extend the w[] array to be the number of rounds.
+ for (var i = 16; i < 80; i++) {
+ var s0 = this.sigma0_(w[i - 15]);
+ var s1 = this.sigma1_(w[i - 2]);
+ w[i] = this.sum_(w[i - 16], w[i - 7], s0, s1);
+ }
+
+ var a = this.hash_[0];
+ var b = this.hash_[1];
+ var c = this.hash_[2];
+ var d = this.hash_[3];
+ var e = this.hash_[4];
+ var f = this.hash_[5];
+ var g = this.hash_[6];
+ var h = this.hash_[7];
+ for (var i = 0; i < 80; i++) {
+ var S0 = this.Sigma0_(a);
+ var maj = this.majority_(a, b, c);
+ var t2 = S0.add(maj);
+ var S1 = this.Sigma1_(e);
+ var ch = this.choose_(e, f, g);
+ var t1 = this.sum_(h, S1, ch, K_[i], w[i]);
+ h = g;
+ g = f;
+ f = e;
+ e = d.add(t1);
+ d = c;
+ c = b;
+ b = a;
+ a = t1.add(t2);
+ }
+
+ this.hash_[0] = this.hash_[0].add(a);
+ this.hash_[1] = this.hash_[1].add(b);
+ this.hash_[2] = this.hash_[2].add(c);
+ this.hash_[3] = this.hash_[3].add(d);
+ this.hash_[4] = this.hash_[4].add(e);
+ this.hash_[5] = this.hash_[5].add(f);
+ this.hash_[6] = this.hash_[6].add(g);
+ this.hash_[7] = this.hash_[7].add(h);
+};
+
+
+/**
+ * Calculates the SHA2 64-bit sigma0 function.
+ * rotateRight(value, 1) ^ rotateRight(value, 8) ^ (value >>> 7)
+ *
+ * @private
+ * @param {!goog.math.Long} value
+ * @return {!goog.math.Long}
+ */
+goog.crypt.Sha2_64bit.prototype.sigma0_ = function(value) {
+ var valueLow = value.getLowBits();
+ var valueHigh = value.getHighBits();
+ // Implementation note: We purposely do not use the shift operations defined
+ // in goog.math.Long. Inlining the code for specific values of shifting and
+ // not generating the intermediate results doubles the speed of this code.
+ var low = (valueLow >>> 1) ^ (valueHigh << 31) ^
+ (valueLow >>> 8) ^ (valueHigh << 24) ^
+ (valueLow >>> 7) ^ (valueHigh << 25);
+ var high = (valueHigh >>> 1) ^ (valueLow << 31) ^
+ (valueHigh >>> 8) ^ (valueLow << 24) ^
+ (valueHigh >>> 7);
+ return new goog.math.Long(low, high);
+};
+
+
+/**
+ * Calculates the SHA2 64-bit sigma1 function.
+ * rotateRight(value, 19) ^ rotateRight(value, 61) ^ (value >>> 6)
+ *
+ * @private
+ * @param {!goog.math.Long} value
+ * @return {!goog.math.Long}
+ */
+goog.crypt.Sha2_64bit.prototype.sigma1_ = function(value) {
+ var valueLow = value.getLowBits();
+ var valueHigh = value.getHighBits();
+ // Implementation note: See _sigma0() above
+ var low = (valueLow >>> 19) ^ (valueHigh << 13) ^
+ (valueHigh >>> 29) ^ (valueLow << 3) ^
+ (valueLow >>> 6) ^ (valueHigh << 26);
+ var high = (valueHigh >>> 19) ^ (valueLow << 13) ^
+ (valueLow >>> 29) ^ (valueHigh << 3) ^
+ (valueHigh >>> 6);
+ return new goog.math.Long(low, high);
+};
+
+
+/**
+ * Calculates the SHA2 64-bit Sigma0 function.
+ * rotateRight(value, 28) ^ rotateRight(value, 34) ^ rotateRight(value, 39)
+ *
+ * @private
+ * @param {!goog.math.Long} value
+ * @return {!goog.math.Long}
+ */
+goog.crypt.Sha2_64bit.prototype.Sigma0_ = function(value) {
+ var valueLow = value.getLowBits();
+ var valueHigh = value.getHighBits();
+ // Implementation note: See _sigma0() above
+ var low = (valueLow >>> 28) ^ (valueHigh << 4) ^
+ (valueHigh >>> 2) ^ (valueLow << 30) ^
+ (valueHigh >>> 7) ^ (valueLow << 25);
+ var high = (valueHigh >>> 28) ^ (valueLow << 4) ^
+ (valueLow >>> 2) ^ (valueHigh << 30) ^
+ (valueLow >>> 7) ^ (valueHigh << 25);
+ return new goog.math.Long(low, high);
+};
+
+
+/**
+ * Calculates the SHA2 64-bit Sigma1 function.
+ * rotateRight(value, 14) ^ rotateRight(value, 18) ^ rotateRight(value, 41)
+ *
+ * @private
+ * @param {!goog.math.Long} value
+ * @return {!goog.math.Long}
+ */
+goog.crypt.Sha2_64bit.prototype.Sigma1_ = function(value) {
+ var valueLow = value.getLowBits();
+ var valueHigh = value.getHighBits();
+ // Implementation note: See _sigma0() above
+ var low = (valueLow >>> 14) ^ (valueHigh << 18) ^
+ (valueLow >>> 18) ^ (valueHigh << 14) ^
+ (valueHigh >>> 9) ^ (valueLow << 23);
+ var high = (valueHigh >>> 14) ^ (valueLow << 18) ^
+ (valueHigh >>> 18) ^ (valueLow << 14) ^
+ (valueLow >>> 9) ^ (valueHigh << 23);
+ return new goog.math.Long(low, high);
+};
+
+
+/**
+ * Calculates the SHA-2 64-bit choose function.
+ *
+ * This function uses {@code value} as a mask to choose bits from either
+ * {@code one} if the bit is set or {@code two} if the bit is not set.
+ *
+ * @private
+ * @param {!goog.math.Long} value
+ * @param {!goog.math.Long} one
+ * @param {!goog.math.Long} two
+ * @return {!goog.math.Long}
+ */
+goog.crypt.Sha2_64bit.prototype.choose_ = function(value, one, two) {
+ var valueLow = value.getLowBits();
+ var valueHigh = value.getHighBits();
+ return new goog.math.Long(
+ (valueLow & one.getLowBits()) | (~valueLow & two.getLowBits()),
+ (valueHigh & one.getHighBits()) | (~valueHigh & two.getHighBits()));
+};
+
+
+/**
+ * Calculates the SHA-2 64-bit majority function.
+ * This function returns, for each bit position, the bit held by the majority
+ * of its three arguments.
+ *
+ * @private
+ * @param {!goog.math.Long} one
+ * @param {!goog.math.Long} two
+ * @param {!goog.math.Long} three
+ * @return {!goog.math.Long}
+ */
+goog.crypt.Sha2_64bit.prototype.majority_ = function(one, two, three) {
+ return new goog.math.Long(
+ (one.getLowBits() & two.getLowBits()) |
+ (two.getLowBits() & three.getLowBits()) |
+ (one.getLowBits() & three.getLowBits()),
+ (one.getHighBits() & two.getHighBits()) |
+ (two.getHighBits() & three.getHighBits()) |
+ (one.getHighBits() & three.getHighBits()));
+};
+
+
+/**
+ * Adds two or more goog.math.Long values.
+ *
+ * @private
+ * @param {!goog.math.Long} one first summand
+ * @param {!goog.math.Long} two second summand
+ * @param {...goog.math.Long} var_args more arguments to sum
+ * @return {!goog.math.Long} The resulting sum.
+ */
+goog.crypt.Sha2_64bit.prototype.sum_ = function(one, two, var_args) {
+ // The low bits may be signed, but they represent a 32-bit unsigned quantity.
+ // We must be careful to normalize them.
+ // This doesn't matter for the high bits.
+ // Implementation note: Performance testing shows that this method runs
+ // fastest when the first two arguments are pulled out of the loop.
+ var low = (one.getLowBits() ^ 0x80000000) + (two.getLowBits() ^ 0x80000000);
+ var high = one.getHighBits() + two.getHighBits();
+ for (var i = arguments.length - 1; i >= 2; --i) {
+ low += arguments[i].getLowBits() ^ 0x80000000;
+ high += arguments[i].getHighBits();
+ }
+ // Because of the ^0x80000000, each value we added is 0x80000000 too small.
+ // Add arguments.length * 0x80000000 to the current sum. We can do this
+ // quickly by adding 0x80000000 to low when the number of arguments is
+ // odd, and adding (number of arguments) >> 1 to high.
+ if (arguments.length & 1) {
+ low += 0x80000000;
+ }
+ high += arguments.length >> 1;
+
+ // If low is outside the range [0, 0xFFFFFFFF], its overflow or underflow
+ // should be added to high. We don't actually need to modify low or
+ // normalize high because the goog.math.Long constructor already does that.
+ high += Math.floor(low / 0x100000000);
+ return new goog.math.Long(low, high);
+};
+
+
+/**
+ * Converts an array of 32-bit integers into an array of goog.math.Long
+ * elements.
+ *
+ * @private
+ * @param {!Array<number>} values An array of 32-bit numbers. Its length
+ * must be even. Each pair of numbers represents a 64-bit integer
+ * in big-endian order
+ * @return {!Array<!goog.math.Long>}
+ */
+goog.crypt.Sha2_64bit.toLongArray_ = function(values) {
+ goog.asserts.assert(values.length % 2 == 0);
+ var result = [];
+ for (var i = 0; i < values.length; i += 2) {
+ result.push(new goog.math.Long(values[i + 1], values[i]));
+ }
+ return result;
+};
+
+
+/**
+ * Fixed constants used in SHA-512 variants.
+ *
+ * These values are from Section 4.2.3 of
+ * http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+ * @const
+ * @private {!Array<!goog.math.Long>}
+ */
+goog.crypt.Sha2_64bit.K_ = goog.crypt.Sha2_64bit.toLongArray_([
+ 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
+ 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
+ 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
+ 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
+ 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
+ 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
+ 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
+ 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
+ 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
+ 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
+ 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
+ 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
+ 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
+ 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
+ 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
+ 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
+ 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
+ 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
+ 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
+ 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
+ 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
+ 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
+ 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
+ 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
+ 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
+ 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
+ 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
+ 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
+ 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
+ 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
+ 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
+ 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
+ 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
+ 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
+ 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
+ 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
+ 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
+ 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
+ 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
+ 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
+]);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha384.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha384.js b/externs/GCL/externs/goog/crypt/sha384.js
new file mode 100644
index 0000000..08ad946
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha384.js
@@ -0,0 +1,59 @@
+// 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 SHA-384 cryptographic hash.
+ *
+ * Usage:
+ * var sha384 = new goog.crypt.Sha384();
+ * sha384.update(bytes);
+ * var hash = sha384.digest();
+ *
+ * @author fy@google.com (Frank Yellin)
+ */
+
+goog.provide('goog.crypt.Sha384');
+
+goog.require('goog.crypt.Sha2_64bit');
+
+
+
+/**
+ * Constructs a SHA-384 cryptographic hash.
+ *
+ * @constructor
+ * @extends {goog.crypt.Sha2_64bit}
+ * @final
+ * @struct
+ */
+goog.crypt.Sha384 = function() {
+ goog.crypt.Sha384.base(this, 'constructor', 6 /* numHashBlocks */,
+ goog.crypt.Sha384.INIT_HASH_BLOCK_);
+};
+goog.inherits(goog.crypt.Sha384, goog.crypt.Sha2_64bit);
+
+
+/** @private {!Array<number>} */
+goog.crypt.Sha384.INIT_HASH_BLOCK_ = [
+ // Section 5.3.4 of
+ // csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+ 0xcbbb9d5d, 0xc1059ed8, // H0
+ 0x629a292a, 0x367cd507, // H1
+ 0x9159015a, 0x3070dd17, // H2
+ 0x152fecd8, 0xf70e5939, // H3
+ 0x67332667, 0xffc00b31, // H4
+ 0x8eb44a87, 0x68581511, // H5
+ 0xdb0c2e0d, 0x64f98fa7, // H6
+ 0x47b5481d, 0xbefa4fa4 // H7
+];
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha512.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha512.js b/externs/GCL/externs/goog/crypt/sha512.js
new file mode 100644
index 0000000..9ac2280
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha512.js
@@ -0,0 +1,59 @@
+// 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 SHA-512 cryptographic hash.
+ *
+ * Usage:
+ * var sha512 = new goog.crypt.Sha512();
+ * sha512.update(bytes);
+ * var hash = sha512.digest();
+ *
+ * @author fy@google.com (Frank Yellin)
+ */
+
+goog.provide('goog.crypt.Sha512');
+
+goog.require('goog.crypt.Sha2_64bit');
+
+
+
+/**
+ * Constructs a SHA-512 cryptographic hash.
+ *
+ * @constructor
+ * @extends {goog.crypt.Sha2_64bit}
+ * @final
+ * @struct
+ */
+goog.crypt.Sha512 = function() {
+ goog.crypt.Sha512.base(this, 'constructor', 8 /* numHashBlocks */,
+ goog.crypt.Sha512.INIT_HASH_BLOCK_);
+};
+goog.inherits(goog.crypt.Sha512, goog.crypt.Sha2_64bit);
+
+
+/** @private {!Array<number>} */
+goog.crypt.Sha512.INIT_HASH_BLOCK_ = [
+ // Section 5.3.5 of
+ // csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+ 0x6a09e667, 0xf3bcc908, // H0
+ 0xbb67ae85, 0x84caa73b, // H1
+ 0x3c6ef372, 0xfe94f82b, // H2
+ 0xa54ff53a, 0x5f1d36f1, // H3
+ 0x510e527f, 0xade682d1, // H4
+ 0x9b05688c, 0x2b3e6c1f, // H5
+ 0x1f83d9ab, 0xfb41bd6b, // H6
+ 0x5be0cd19, 0x137e2179 // H7
+];
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/crypt/sha512_256.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/crypt/sha512_256.js b/externs/GCL/externs/goog/crypt/sha512_256.js
new file mode 100644
index 0000000..75a4256
--- /dev/null
+++ b/externs/GCL/externs/goog/crypt/sha512_256.js
@@ -0,0 +1,65 @@
+// 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 SHA-512/256 cryptographic hash.
+ *
+ * WARNING: SHA-256 and SHA-512/256 are different members of the SHA-2
+ * family of hashes. Although both give 32-byte results, the two results
+ * should bear no relationship to each other.
+ *
+ * Please be careful before using this hash function.
+ * <p>
+ * Usage:
+ * var sha512_256 = new goog.crypt.Sha512_256();
+ * sha512_256.update(bytes);
+ * var hash = sha512_256.digest();
+ *
+ * @author fy@google.com (Frank Yellin)
+ */
+
+goog.provide('goog.crypt.Sha512_256');
+
+goog.require('goog.crypt.Sha2_64bit');
+
+
+
+/**
+ * Constructs a SHA-512/256 cryptographic hash.
+ *
+ * @constructor
+ * @extends {goog.crypt.Sha2_64bit}
+ * @final
+ * @struct
+ */
+goog.crypt.Sha512_256 = function() {
+ goog.crypt.Sha512_256.base(this, 'constructor', 4 /* numHashBlocks */,
+ goog.crypt.Sha512_256.INIT_HASH_BLOCK_);
+};
+goog.inherits(goog.crypt.Sha512_256, goog.crypt.Sha2_64bit);
+
+
+/** @private {!Array<number>} */
+goog.crypt.Sha512_256.INIT_HASH_BLOCK_ = [
+ // Section 5.3.6.2 of
+ // csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+ 0x22312194, 0xFC2BF72C, // H0
+ 0x9F555FA3, 0xC84C64C2, // H1
+ 0x2393B86B, 0x6F53B151, // H2
+ 0x96387719, 0x5940EABD, // H3
+ 0x96283EE2, 0xA88EFFE3, // H4
+ 0xBE5E1E25, 0x53863992, // H5
+ 0x2B0199FC, 0x2C85B8AA, // H6
+ 0x0EB72DDC, 0x81C52CA2 // H7
+];
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/autocomplete.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/autocomplete.css b/externs/GCL/externs/goog/css/autocomplete.css
new file mode 100644
index 0000000..033ceba
--- /dev/null
+++ b/externs/GCL/externs/goog/css/autocomplete.css
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styles for goog.ui.ac.AutoComplete and its derivatives.
+ * Note: these styles need some work to get them working properly at various
+ * font sizes other than the default.
+ *
+ * @author pupius@google.com (Daniel Pupius)
+ * @author annams@google.com (Srinivas Annam)
+ */
+
+
+/*
+ * TODO(annams): Rename (here and in renderer.js) to specify class name as
+ * goog-autocomplete-renderer
+ */
+.ac-renderer {
+ font: normal 13px Arial, sans-serif;
+ position: absolute;
+ background: #fff;
+ border: 1px solid #666;
+ -moz-box-shadow: 2px 2px 2px rgba(102, 102, 102, .4);
+ -webkit-box-shadow: 2px 2px 2px rgba(102, 102, 102, .4);
+ width: 300px;
+}
+
+.ac-row {
+ cursor: pointer;
+ padding: .4em;
+}
+
+.ac-highlighted {
+ font-weight: bold;
+}
+
+.ac-active {
+ background-color: #b2b4bf;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/bubble.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/bubble.css b/externs/GCL/externs/goog/css/bubble.css
new file mode 100644
index 0000000..4e8d612
--- /dev/null
+++ b/externs/GCL/externs/goog/css/bubble.css
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+.goog-bubble-font {
+ font-size: 80%;
+ color: #888888;
+}
+
+.goog-bubble-close-button {
+ background-image:url(//ssl.gstatic.com/closure/bubble_close.jpg);
+ background-color: white;
+ background-position: top right;
+ background-repeat: no-repeat;
+ width: 16px;
+ height: 16px;
+}
+
+.goog-bubble-left {
+ background-image:url(//ssl.gstatic.com/closure/bubble_left.gif);
+ background-position:left;
+ background-repeat:repeat-y;
+ width: 4px;
+}
+
+.goog-bubble-right {
+ background-image:url(//ssl.gstatic.com/closure/bubble_right.gif);
+ background-position: right;
+ background-repeat: repeat-y;
+ width: 4px;
+}
+
+.goog-bubble-top-right-anchor {
+ background-image:url(//ssl.gstatic.com/closure/right_anchor_bubble_top.gif);
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 147px;
+ height: 16px;
+}
+
+.goog-bubble-top-left-anchor {
+ background-image:url(//ssl.gstatic.com/closure/left_anchor_bubble_top.gif);
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 147px;
+ height: 16px;
+}
+
+.goog-bubble-top-no-anchor {
+ background-image:url(//ssl.gstatic.com/closure/no_anchor_bubble_top.gif);
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 147px;
+ height: 6px;
+}
+
+.goog-bubble-bottom-right-anchor {
+ background-image:url(//ssl.gstatic.com/closure/right_anchor_bubble_bot.gif);
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 147px;
+ height: 16px;
+}
+
+.goog-bubble-bottom-left-anchor {
+ background-image:url(//ssl.gstatic.com/closure/left_anchor_bubble_bot.gif);
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 147px;
+ height: 16px;
+}
+
+.goog-bubble-bottom-no-anchor {
+ background-image:url(//ssl.gstatic.com/closure/no_anchor_bubble_bot.gif);
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 147px;
+ height: 8px;
+}
+
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/button.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/button.css b/externs/GCL/externs/goog/css/button.css
new file mode 100644
index 0000000..b80a92f
--- /dev/null
+++ b/externs/GCL/externs/goog/css/button.css
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styling for buttons rendered by goog.ui.ButtonRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+.goog-button {
+ color: #036;
+ border-color: #036;
+ background-color: #69c;
+}
+
+/* State: disabled. */
+.goog-button-disabled {
+ border-color: #333;
+ color: #333;
+ background-color: #999;
+}
+
+/* State: hover. */
+.goog-button-hover {
+ color: #369;
+ border-color: #369;
+ background-color: #9cf;
+}
+
+/* State: active. */
+.goog-button-active {
+ color: #69c;
+ border-color: #69c;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/charpicker.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/charpicker.css b/externs/GCL/externs/goog/css/charpicker.css
new file mode 100644
index 0000000..fb33447
--- /dev/null
+++ b/externs/GCL/externs/goog/css/charpicker.css
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pupius@google.com (Daniel Pupius) */
+/* Author: cibu@google.com (Cibu Johny) */
+
+.goog-char-picker {
+ background-color: #ddd;
+ padding: 16px;
+ border: 1px solid #777;
+}
+
+/* goog.ui.HoverCard */
+.goog-char-picker-hovercard {
+ border: solid 5px #ffcc33;
+ min-width: 64px;
+ max-width: 160px;
+ padding: 16px;
+ background-color: white;
+ text-align: center;
+ position: absolute;
+ visibility: hidden;
+}
+
+.goog-char-picker-name {
+ font-size: x-small;
+}
+
+.goog-char-picker-unicode {
+ font-size: x-small;
+ color: GrayText;
+}
+
+.goog-char-picker-char-zoom {
+ font-size: xx-large;
+}
+
+/*
+ * grid
+ */
+.goog-char-picker-grid-container {
+ border: 1px solid #777;
+ background-color: #fff;
+ width: 272px;
+}
+
+.goog-char-picker-grid {
+ overflow: hidden;
+ height: 250px;
+ width: 250px;
+ position: relative;
+}
+
+.goog-stick {
+ width: 1px;
+ overflow: hidden;
+}
+.goog-stickwrap {
+ width: 17px;
+ height: 250px;
+ float: right;
+ overflow: auto;
+}
+
+.goog-char-picker-recents {
+ border: 1px solid #777;
+ background-color: #fff;
+ height: 25px;
+ width: 275px;
+ margin: 0 0 16px 0;
+ position: relative;
+}
+
+.goog-char-picker-notice {
+ font-size: x-small;
+ height: 16px;
+ color: GrayText;
+ margin: 0 0 16px 0;
+}
+
+/*
+ * Hex entry
+ */
+
+.goog-char-picker-uplus {
+}
+
+.goog-char-picker-input-box {
+ width: 96px;
+}
+
+.label-input-label {
+ color: GrayText;
+}
+
+.goog-char-picker-okbutton {
+}
+
+/*
+ * Grid buttons
+ */
+.goog-char-picker-grid .goog-flat-button {
+ position: relative;
+ width: 24px;
+ height: 24px;
+ line-height: 24px;
+ border-bottom: 1px solid #ddd;
+ border-right: 1px solid #ddd;
+ text-align: center;
+ cursor: pointer;
+ outline: none;
+}
+
+.goog-char-picker-grid .goog-flat-button-hover,
+.goog-char-picker-grid .goog-flat-button-focus {
+ background-color: #ffcc33;
+}
+
+/*
+ * goog.ui.Menu
+ */
+
+/* State: resting. */
+.goog-char-picker-button {
+ border-width: 0px;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ background-position: center left;
+}
+
+/* State: resting. */
+.goog-char-picker-menu {
+ background-color: #fff;
+ border-color: #ccc #666 #666 #ccc;
+ border-style: solid;
+ border-width: 1px;
+ cursor: default;
+ margin: 0;
+ outline: none;
+ padding: 0;
+ position: absolute;
+ max-height: 400px;
+ overflow-y: auto;
+ overflow-x: hide;
+}
+
+/*
+ * goog.ui.MenuItem
+ */
+
+/* State: resting. */
+.goog-char-picker-menu .goog-menuitem {
+ color: #000;
+ list-style: none;
+ margin: 0;
+ /* 28px on the left for icon or checkbox; 10ex on the right for shortcut. */
+ padding: 1px 32px 1px 8px;
+ white-space: nowrap;
+}
+
+.goog-char-picker-menu2 .goog-menuitem {
+ color: #000;
+ list-style: none;
+ margin: 0;
+ /* 28px on the left for icon or checkbox; 10ex on the right for shortcut. */
+ padding: 1px 32px 1px 8px;
+ white-space: nowrap;
+}
+
+.goog-char-picker-menu .goog-subtitle {
+ color: #fff !important;
+ background-color: #666;
+ font-weight: bold;
+ list-style: none;
+ margin: 0;
+ /* 28px on the left for icon or checkbox; 10ex on the right for shortcut. */
+ padding: 3px 32px 3px 8px;
+ white-space: nowrap;
+}
+
+/* BiDi override for the resting state. */
+.goog-char-picker-menu .goog-menuitem-rtl {
+ /* Flip left/right padding for BiDi. */
+ padding: 2px 16px 2px 32px !important;
+}
+
+/* State: hover. */
+.goog-char-picker-menu .goog-menuitem-highlight {
+ background-color: #d6e9f8;
+}
+/*
+ * goog.ui.MenuSeparator
+ */
+
+/* State: resting. */
+.goog-char-picker-menu .goog-menuseparator {
+ border-top: 1px solid #ccc;
+ margin: 2px 0;
+ padding: 0;
+}
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/checkbox.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/checkbox.css b/externs/GCL/externs/goog/css/checkbox.css
new file mode 100644
index 0000000..2aed8b5
--- /dev/null
+++ b/externs/GCL/externs/goog/css/checkbox.css
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pallosp@google.com (Peter Pallos) */
+
+/* Sample 3-state checkbox styles. */
+
+.goog-checkbox {
+ border: 1px solid #1C5180;
+ display: -moz-inline-box;
+ display: inline-block;
+ font-size: 1px; /* Fixes the height in IE6 */
+ height: 11px;
+ margin: 0 4px 0 1px;
+ vertical-align: text-bottom;
+ width: 11px;
+}
+
+.goog-checkbox-checked {
+ background: #fff url(//ssl.gstatic.com/closure/check-sprite.gif) no-repeat 2px center;
+}
+
+.goog-checkbox-undetermined {
+ background: #bbb url(//ssl.gstatic.com/closure/check-sprite.gif) no-repeat 2px center;
+}
+
+.goog-checkbox-unchecked {
+ background: #fff;
+}
+
+.goog-checkbox-disabled {
+ border: 1px solid lightgray;
+ background-position: -7px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/colormenubutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/colormenubutton.css b/externs/GCL/externs/goog/css/colormenubutton.css
new file mode 100644
index 0000000..83655dd
--- /dev/null
+++ b/externs/GCL/externs/goog/css/colormenubutton.css
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for buttons created by goog.ui.ColorMenuButtonRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+/* Color indicator. */
+.goog-color-menu-button-indicator {
+ border-bottom: 4px solid #f0f0f0;
+}
+
+/* Thinner padding for color picker buttons, to leave room for the indicator. */
+.goog-color-menu-button .goog-menu-button-inner-box,
+.goog-toolbar-color-menu-button .goog-toolbar-menu-button-inner-box {
+ padding-top: 2px !important;
+ padding-bottom: 2px !important;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/colorpalette.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/colorpalette.css b/externs/GCL/externs/goog/css/colorpalette.css
new file mode 100644
index 0000000..17bed42
--- /dev/null
+++ b/externs/GCL/externs/goog/css/colorpalette.css
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for color palettes.
+ *
+ * @author pupius@google.com (Daniel Pupius)
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+.goog-palette-cell .goog-palette-colorswatch {
+ border: none;
+ font-size: x-small;
+ height: 18px;
+ position: relative;
+ width: 18px;
+}
+
+.goog-palette-cell-hover .goog-palette-colorswatch {
+ border: 1px solid #fff;
+ height: 16px;
+ width: 16px;
+}
+
+.goog-palette-cell-selected .goog-palette-colorswatch {
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -368px 0;
+ border: 1px solid #333;
+ color: #fff;
+ font-weight: bold;
+ height: 16px;
+ width: 16px;
+}
+
+.goog-palette-customcolor {
+ background-color: #fafafa;
+ border: 1px solid #eee;
+ color: #666;
+ font-size: x-small;
+ height: 15px;
+ position: relative;
+ width: 15px;
+}
+
+.goog-palette-cell-hover .goog-palette-customcolor {
+ background-color: #fee;
+ border: 1px solid #f66;
+ color: #f66;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/colorpicker-simplegrid.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/colorpicker-simplegrid.css b/externs/GCL/externs/goog/css/colorpicker-simplegrid.css
new file mode 100644
index 0000000..b98f5dc
--- /dev/null
+++ b/externs/GCL/externs/goog/css/colorpicker-simplegrid.css
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pupius@google.com (Daniel Pupius) */
+
+/*
+ Styles to make the colorpicker look like the old gmail color picker
+ NOTE: without CSS scoping this will override styles defined in palette.css
+*/
+.goog-palette {
+ outline: none;
+ cursor: default;
+}
+
+.goog-palette-table {
+ border: 1px solid #666;
+ border-collapse: collapse;
+}
+
+.goog-palette-cell {
+ height: 13px;
+ width: 15px;
+ margin: 0;
+ border: 0;
+ text-align: center;
+ vertical-align: middle;
+ border-right: 1px solid #666;
+ font-size: 1px;
+}
+
+.goog-palette-colorswatch {
+ position: relative;
+ height: 13px;
+ width: 15px;
+ border: 1px solid #666;
+}
+
+.goog-palette-cell-hover .goog-palette-colorswatch {
+ border: 1px solid #FFF;
+}
+
+.goog-palette-cell-selected .goog-palette-colorswatch {
+ border: 1px solid #000;
+ color: #fff;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/combobox.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/combobox.css b/externs/GCL/externs/goog/css/combobox.css
new file mode 100644
index 0000000..dd1571a
--- /dev/null
+++ b/externs/GCL/externs/goog/css/combobox.css
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pupius@google.com (Daniel Pupius) */
+/* Author: pallosp@google.com (Peter Pallos) */
+
+/* Styles for goog.ui.ComboBox and its derivatives. */
+
+
+.goog-combobox {
+ background: #ddd url(//ssl.gstatic.com/closure/button-bg.gif) repeat-x scroll left top;
+ border: 1px solid #b5b6b5;
+ font: normal small arial, sans-serif;
+}
+
+.goog-combobox input {
+ background-color: #fff;
+ border: 0;
+ border-right: 1px solid #b5b6b5;
+ color: #000;
+ font: normal small arial, sans-serif;
+ margin: 0;
+ padding: 0 0 0 2px;
+ vertical-align: bottom; /* override demo.css */
+ width: 200px;
+}
+
+.goog-combobox input.label-input-label {
+ background-color: #fff;
+ color: #aaa;
+}
+
+.goog-combobox .goog-menu {
+ margin-top: -1px;
+ width: 219px; /* input width + button width + 3 * 1px border */
+ z-index: 1000;
+}
+
+.goog-combobox-button {
+ cursor: pointer;
+ display: inline-block;
+ font-size: 10px;
+ text-align: center;
+ width: 16px;
+}
+
+/* IE6 only hack */
+* html .goog-combobox-button {
+ padding: 0 3px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/common.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/common.css b/externs/GCL/externs/goog/css/common.css
new file mode 100644
index 0000000..de140b8
--- /dev/null
+++ b/externs/GCL/externs/goog/css/common.css
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Cross-browser implementation of the "display: inline-block" CSS property.
+ * See http://www.w3.org/TR/CSS21/visuren.html#propdef-display for details.
+ * Tested on IE 6 & 7, FF 1.5 & 2.0, Safari 2 & 3, Webkit, and Opera 9.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+/*
+ * Default rule; only Safari, Webkit, and Opera handle it without hacks.
+ */
+.goog-inline-block {
+ position: relative;
+ display: -moz-inline-box; /* Ignored by FF3 and later. */
+ display: inline-block;
+}
+
+/*
+ * Pre-IE7 IE hack. On IE, "display: inline-block" only gives the element
+ * layout, but doesn't give it inline behavior. Subsequently setting display
+ * to inline does the trick.
+ */
+* html .goog-inline-block {
+ display: inline;
+}
+
+/*
+ * IE7-only hack. On IE, "display: inline-block" only gives the element
+ * layout, but doesn't give it inline behavior. Subsequently setting display
+ * to inline does the trick.
+ */
+*:first-child+html .goog-inline-block {
+ display: inline;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/css3button.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/css3button.css b/externs/GCL/externs/goog/css/css3button.css
new file mode 100644
index 0000000..a26306f
--- /dev/null
+++ b/externs/GCL/externs/goog/css/css3button.css
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: slightlyoff@google.com (Alex Russell) */
+/* Author: eae@google.com (Emil A Eklund) */
+
+/* Imageless button styles. */
+.goog-css3-button {
+ margin: 0 2px;
+ padding: 3px 6px;
+ text-align: center;
+ vertical-align: middle;
+ white-space: nowrap;
+ cursor: default;
+ outline: none;
+ font-family: Arial, sans-serif;
+ color: #000;
+ border: 1px solid #bbb;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ /* TODO(eae): Change this to -webkit-linear-gradient once
+ https://bugs.webkit.org/show_bug.cgi?id=28152 is resolved. */
+ background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9),
+ to(#e3e3e3));
+ /* @alternate */ background: -moz-linear-gradient(top, #f9f9f9, #e3e3e3);
+}
+
+
+/* Styles for different states (hover, active, focused, open, checked). */
+.goog-css3-button-hover {
+ border-color: #939393 !important;
+}
+
+.goog-css3-button-focused {
+ border-color: #444;
+}
+
+.goog-css3-button-active, .goog-css3-button-open, .goog-css3-button-checked {
+ border-color: #444 !important;
+ background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#e3e3e3),
+ to(#f9f9f9));
+ /* @alternate */ background: -moz-linear-gradient(top, #e3e3e3, #f9f9f9);
+}
+
+.goog-css3-button-disabled {
+ color: #888;
+}
+
+.goog-css3-button-primary {
+ font-weight: bold;
+}
+
+
+/*
+ * Pill (collapsed border) styles.
+ */
+.goog-css3-button-collapse-right {
+ margin-right: 0 !important;
+ border-right: 1px solid #bbb;
+ -webkit-border-top-right-radius: 0px;
+ -webkit-border-bottom-right-radius: 0px;
+ -moz-border-radius-topright: 0px;
+ -moz-border-radius-bottomright: 0px;
+}
+
+.goog-css3-button-collapse-left {
+ border-left: 1px solid #f9f9f9;
+ margin-left: 0 !important;
+ -webkit-border-top-left-radius: 0px;
+ -webkit-border-bottom-left-radius: 0px;
+ -moz-border-radius-topleft: 0px;
+ -moz-border-radius-bottomleft: 0px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/css3menubutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/css3menubutton.css b/externs/GCL/externs/goog/css/css3menubutton.css
new file mode 100644
index 0000000..a020700
--- /dev/null
+++ b/externs/GCL/externs/goog/css/css3menubutton.css
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for buttons created by goog.ui.Css3MenuButtonRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ * @author dalewis@google.com (Darren Lewis)
+ */
+
+/* Dropdown arrow style. */
+.goog-css3-button-dropdown {
+ height: 16px;
+ width: 7px;
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0;
+ vertical-align: top;
+ margin-left: 3px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/custombutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/custombutton.css b/externs/GCL/externs/goog/css/custombutton.css
new file mode 100644
index 0000000..1f17052
--- /dev/null
+++ b/externs/GCL/externs/goog/css/custombutton.css
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styling for custom buttons rendered by goog.ui.CustomButtonRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+.goog-custom-button {
+ margin: 2px;
+ border: 0;
+ padding: 0;
+ font-family: Arial, sans-serif;
+ color: #000;
+ /* Client apps may override the URL at which they serve the image. */
+ background: #ddd url(//ssl.gstatic.com/editor/button-bg.png) repeat-x top left;
+ text-decoration: none;
+ list-style: none;
+ vertical-align: middle;
+ cursor: default;
+ outline: none;
+}
+
+/* Pseudo-rounded corners. */
+.goog-custom-button-outer-box,
+.goog-custom-button-inner-box {
+ border-style: solid;
+ border-color: #aaa;
+ vertical-align: top;
+}
+
+.goog-custom-button-outer-box {
+ margin: 0;
+ border-width: 1px 0;
+ padding: 0;
+}
+
+.goog-custom-button-inner-box {
+ margin: 0 -1px;
+ border-width: 0 1px;
+ padding: 3px 4px;
+ white-space: nowrap; /* Prevents buttons from line breaking on android. */
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-custom-button-inner-box {
+ /* IE6 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+/* Pre-IE7 BiDi fixes. */
+* html .goog-custom-button-rtl .goog-custom-button-outer-box {
+ /* @noflip */ left: -1px;
+}
+* html .goog-custom-button-rtl .goog-custom-button-inner-box {
+ /* @noflip */ right: auto;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-custom-button-inner-box {
+ /* IE7 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+/* IE7 BiDi fix. */
+*:first-child+html .goog-custom-button-rtl .goog-custom-button-inner-box {
+ /* @noflip */ left: 1px;
+}
+
+/* Safari-only hacks. */
+::root .goog-custom-button,
+::root .goog-custom-button-outer-box {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: 0;
+}
+
+::root .goog-custom-button-inner-box {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: normal;
+}
+
+/* State: disabled. */
+.goog-custom-button-disabled {
+ background-image: none !important;
+ opacity: 0.3;
+ -moz-opacity: 0.3;
+ filter: alpha(opacity=30);
+}
+
+.goog-custom-button-disabled .goog-custom-button-outer-box,
+.goog-custom-button-disabled .goog-custom-button-inner-box {
+ color: #333 !important;
+ border-color: #999 !important;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-custom-button-disabled {
+ margin: 2px 1px !important;
+ padding: 0 1px !important;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-custom-button-disabled {
+ margin: 2px 1px !important;
+ padding: 0 1px !important;
+}
+
+/* State: hover. */
+.goog-custom-button-hover .goog-custom-button-outer-box,
+.goog-custom-button-hover .goog-custom-button-inner-box {
+ border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */
+}
+
+/* State: active, checked. */
+.goog-custom-button-active,
+.goog-custom-button-checked {
+ background-color: #bbb;
+ background-position: bottom left;
+}
+
+/* State: focused. */
+.goog-custom-button-focused .goog-custom-button-outer-box,
+.goog-custom-button-focused .goog-custom-button-inner-box {
+ border-color: orange;
+}
+
+/* Pill (collapsed border) styles. */
+.goog-custom-button-collapse-right,
+.goog-custom-button-collapse-right .goog-custom-button-outer-box,
+.goog-custom-button-collapse-right .goog-custom-button-inner-box {
+ margin-right: 0;
+}
+
+.goog-custom-button-collapse-left,
+.goog-custom-button-collapse-left .goog-custom-button-outer-box,
+.goog-custom-button-collapse-left .goog-custom-button-inner-box {
+ margin-left: 0;
+}
+
+.goog-custom-button-collapse-left .goog-custom-button-inner-box {
+ border-left: 1px solid #fff;
+}
+
+.goog-custom-button-collapse-left.goog-custom-button-checked
+.goog-custom-button-inner-box {
+ border-left: 1px solid #ddd;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-custom-button-collapse-left .goog-custom-button-inner-box {
+ left: 0;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-custom-button-collapse-left
+.goog-custom-button-inner-box {
+ left: 0;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/datepicker.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/datepicker.css b/externs/GCL/externs/goog/css/datepicker.css
new file mode 100644
index 0000000..6d5b914
--- /dev/null
+++ b/externs/GCL/externs/goog/css/datepicker.css
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for a goog.ui.DatePicker.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+.goog-date-picker,
+.goog-date-picker th,
+.goog-date-picker td {
+ font: 13px Arial, sans-serif;
+}
+
+.goog-date-picker {
+ -moz-user-focus: normal;
+ -moz-user-select: none;
+ position: relative;
+ border: 1px solid #000;
+ float: left;
+ padding: 2px;
+ color: #000;
+ background: #c3d9ff;
+ cursor: default;
+}
+
+.goog-date-picker th {
+ text-align: center;
+}
+
+.goog-date-picker td {
+ text-align: center;
+ vertical-align: middle;
+ padding: 1px 3px;
+}
+
+
+.goog-date-picker-menu {
+ position: absolute;
+ background: threedface;
+ border: 1px solid gray;
+ -moz-user-focus: normal;
+ z-index: 1;
+ outline: none;
+}
+
+.goog-date-picker-menu ul {
+ list-style: none;
+ margin: 0px;
+ padding: 0px;
+}
+
+.goog-date-picker-menu ul li {
+ cursor: default;
+}
+
+.goog-date-picker-menu-selected {
+ background: #ccf;
+}
+
+.goog-date-picker th {
+ font-size: .9em;
+}
+
+.goog-date-picker td div {
+ float: left;
+}
+
+.goog-date-picker button {
+ padding: 0px;
+ margin: 1px 0;
+ border: 0;
+ color: #20c;
+ font-weight: bold;
+ background: transparent;
+}
+
+.goog-date-picker-date {
+ background: #fff;
+}
+
+.goog-date-picker-week,
+.goog-date-picker-wday {
+ padding: 1px 3px;
+ border: 0;
+ border-color: #a2bbdd;
+ border-style: solid;
+}
+
+.goog-date-picker-week {
+ border-right-width: 1px;
+}
+
+.goog-date-picker-wday {
+ border-bottom-width: 1px;
+}
+
+.goog-date-picker-head td {
+ text-align: center;
+}
+
+/** Use td.className instead of !important */
+td.goog-date-picker-today-cont {
+ text-align: center;
+}
+
+/** Use td.className instead of !important */
+td.goog-date-picker-none-cont {
+ text-align: center;
+}
+
+.goog-date-picker-month {
+ min-width: 11ex;
+ white-space: nowrap;
+}
+
+.goog-date-picker-year {
+ min-width: 6ex;
+ white-space: nowrap;
+}
+
+.goog-date-picker-monthyear {
+ white-space: nowrap;
+}
+
+.goog-date-picker table {
+ border-collapse: collapse;
+}
+
+.goog-date-picker-other-month {
+ color: #888;
+}
+
+.goog-date-picker-wkend-start,
+.goog-date-picker-wkend-end {
+ background: #eee;
+}
+
+/** Use td.className instead of !important */
+td.goog-date-picker-selected {
+ background: #c3d9ff;
+}
+
+.goog-date-picker-today {
+ background: #9ab;
+ font-weight: bold !important;
+ border-color: #246 #9bd #9bd #246;
+ color: #fff;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/dialog.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/dialog.css b/externs/GCL/externs/goog/css/dialog.css
new file mode 100644
index 0000000..6bf9020
--- /dev/null
+++ b/externs/GCL/externs/goog/css/dialog.css
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for goog.ui.Dialog.
+ *
+ * @author ssaviano@google.com (Steven Saviano)
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+.modal-dialog {
+ background: #c1d9ff;
+ border: 1px solid #3a5774;
+ color: #000;
+ padding: 4px;
+ position: absolute;
+}
+
+.modal-dialog a,
+.modal-dialog a:link,
+.modal-dialog a:visited {
+ color: #06c;
+ cursor: pointer;
+}
+
+.modal-dialog-bg {
+ background: #666;
+ left: 0;
+ position: absolute;
+ top: 0;
+}
+
+.modal-dialog-title {
+ background: #e0edfe;
+ color: #000;
+ cursor: pointer;
+ font-size: 120%;
+ font-weight: bold;
+
+ /* Add padding on the right to ensure the close button has room. */
+ padding: 8px 31px 8px 8px;
+
+ position: relative;
+ _zoom: 1; /* Ensures proper width in IE6 RTL. */
+}
+
+.modal-dialog-title-close {
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: #e0edfe url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -528px 0;
+ cursor: default;
+ height: 15px;
+ position: absolute;
+ right: 10px;
+ top: 8px;
+ width: 15px;
+ vertical-align: middle;
+}
+
+.modal-dialog-buttons,
+.modal-dialog-content {
+ background-color: #fff;
+ padding: 8px;
+}
+
+.goog-buttonset-default {
+ font-weight: bold;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/dimensionpicker.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/dimensionpicker.css b/externs/GCL/externs/goog/css/dimensionpicker.css
new file mode 100644
index 0000000..5c51ab8
--- /dev/null
+++ b/externs/GCL/externs/goog/css/dimensionpicker.css
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styling for dimension pickers rendered by goog.ui.DimensionPickerRenderer.
+ *
+ * Author: robbyw@google.com (Robby Walker)
+ * Author: abefettig@google.com (Abe Fettig)
+ */
+
+.goog-dimension-picker {
+ font-size: 18px;
+ padding: 4px;
+}
+
+.goog-dimension-picker div {
+ position: relative;
+}
+
+.goog-dimension-picker div.goog-dimension-picker-highlighted {
+/* Client apps must provide the URL at which they serve the image. */
+ /* background: url(dimension-highlighted.png); */
+ left: 0;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+}
+
+.goog-dimension-picker-unhighlighted {
+ /* Client apps must provide the URL at which they serve the image. */
+ /* background: url(dimension-unhighlighted.png); */
+}
+
+.goog-dimension-picker-status {
+ font-size: 10pt;
+ text-align: center;
+}
+
+.goog-dimension-picker div.goog-dimension-picker-mousecatcher {
+ left: 0;
+ position: absolute !important;
+ top: 0;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/dragdropdetector.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/dragdropdetector.css b/externs/GCL/externs/goog/css/dragdropdetector.css
new file mode 100644
index 0000000..88266d6
--- /dev/null
+++ b/externs/GCL/externs/goog/css/dragdropdetector.css
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styling for the drag drop detector.
+ *
+ * Author: robbyw@google.com (Robby Walker)
+ * Author: wcrosby@google.com (Wayne Crosby)
+ */
+
+.goog-dragdrop-w3c-editable-iframe {
+ position: absolute;
+ width: 100%;
+ height: 10px;
+ top: -150px;
+ left: 0;
+ z-index: 10000;
+ padding: 0;
+ overflow: hidden;
+ opacity: 0;
+ -moz-opacity: 0;
+}
+
+.goog-dragdrop-ie-editable-iframe {
+ width: 100%;
+ height: 5000px;
+}
+
+.goog-dragdrop-ie-input {
+ width: 100%;
+ height: 5000px;
+}
+
+.goog-dragdrop-ie-div {
+ position: absolute;
+ top: -5000px;
+ left: 0;
+ width: 100%;
+ height: 5000px;
+ z-index: 10000;
+ background-color: white;
+ filter: alpha(opacity=0);
+ overflow: hidden;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/editor/bubble.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/editor/bubble.css b/externs/GCL/externs/goog/css/editor/bubble.css
new file mode 100644
index 0000000..c76f98f
--- /dev/null
+++ b/externs/GCL/externs/goog/css/editor/bubble.css
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2005 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Bubble styles.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ * @author nicksantos@google.com (Nick Santos)
+ * @author jparent@google.com (Julie Parent)
+ */
+
+div.tr_bubble {
+ position: absolute;
+
+ background-color: #e0ecff;
+ border: 1px solid #99c0ff;
+ border-radius: 2px;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ font-size: 83%;
+ font-family: Arial, Helvetica, sans-serif;
+ padding: 2px 19px 6px 6px;
+ white-space: nowrap;
+}
+
+.tr_bubble_link {
+ color: #00c;
+ text-decoration: underline;
+ cursor: pointer;
+ font-size: 100%;
+}
+
+.tr_bubble .tr_option-link,
+.tr_bubble #tr_delete-image,
+.tr_bubble #tr_module-options-link {
+ font-size: 83%;
+}
+
+.tr_bubble_closebox {
+ position: absolute;
+ cursor: default;
+ background: url(//ssl.gstatic.com/editor/bubble_closebox.gif) top left no-repeat;
+ padding: 0;
+ margin: 0;
+ width: 10px;
+ height: 10px;
+ top: 3px;
+ right: 5px;
+}
+
+div.tr_bubble_panel {
+ padding: 2px 0 1px;
+}
+
+div.tr_bubble_panel_title {
+ display: none;
+}
+
+div.tr_multi_bubble div.tr_bubble_panel_title {
+ margin-right: 1px;
+ display: block;
+ float: left;
+ width: 50px;
+}
+
+div.tr_multi_bubble div.tr_bubble_panel {
+ padding: 2px 0 1px;
+ margin-right: 50px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/editor/dialog.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/editor/dialog.css b/externs/GCL/externs/goog/css/editor/dialog.css
new file mode 100644
index 0000000..8868a10
--- /dev/null
+++ b/externs/GCL/externs/goog/css/editor/dialog.css
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styles for Editor dialogs and their sub-components.
+ *
+ * @author marcosalmeida@google.com (Marcos Almeida)
+ */
+
+
+.tr-dialog {
+ width: 475px;
+}
+
+.tr-dialog .goog-tab-content {
+ margin: 0;
+ border: 1px solid #6b90da;
+ padding: 4px 8px;
+ background: #fff;
+ overflow: auto;
+}
+
+.tr-tabpane {
+ font-size: 10pt;
+ padding: 1.3ex 0;
+}
+
+.tr-tabpane-caption {
+ font-size: 10pt;
+ margin-bottom: 0.7ex;
+ background-color: #fffaf5;
+ line-height: 1.3em;
+}
+
+.tr-tabpane .goog-tab-content {
+ border: none;
+ padding: 5px 7px 1px;
+}
+
+.tr-tabpane .goog-tab {
+ background-color: #fff;
+ border: none;
+ width: 136px;
+ line-height: 1.3em;
+ margin-bottom: 0.7ex;
+}
+
+.tr-tabpane .goog-tab {
+ text-decoration: underline;
+ color: blue;
+ cursor: pointer;
+}
+
+.tr-tabpane .goog-tab-selected {
+ font-weight: bold;
+ text-decoration: none;
+ color: black;
+}
+
+.tr-tabpane .goog-tab input {
+ margin: -2px 5px 0 0;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/editor/equationeditor.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/editor/equationeditor.css b/externs/GCL/externs/goog/css/editor/equationeditor.css
new file mode 100644
index 0000000..b6aff34
--- /dev/null
+++ b/externs/GCL/externs/goog/css/editor/equationeditor.css
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * The CSS definition for everything inside equation editor dialog.
+ *
+ * Author: yoah@google.com (Yoah Bar-David)
+ * Author: kfk@google.com (Ming Zhang)
+ */
+
+.ee-modal-dialog {
+ width: 475px;
+}
+
+.ee-content {
+ background: #FFF;
+ border: 1px solid #369;
+ overflow: auto;
+ padding: 4px 8px;
+}
+
+.ee-tex {
+ border: 1px solid #000;
+ display: block;
+ height: 7.5em;
+ margin: 4px 0 10px 0;
+ width: 100%;
+}
+
+.ee-section-title {
+ font-weight: bold;
+}
+
+.ee-section-title-floating {
+ float: left;
+}
+
+#ee-section-learn-more {
+ float: right;
+}
+
+.ee-preview-container {
+ border: 1px dashed #ccc;
+ height: 80px;
+ margin: 4px 0 10px 0;
+ width: 100%;
+ overflow: auto;
+}
+
+.ee-warning {
+ color: #F00;
+}
+
+.ee-palette {
+ border: 1px solid #aaa;
+ left: 0;
+ outline: none;
+ position: absolute;
+}
+
+.ee-palette-table {
+ border: 0;
+ border-collapse: separate;
+}
+
+.ee-palette-cell {
+ background: #F0F0F0;
+ border: 1px solid #FFF;
+ margin: 0;
+ padding: 1px;
+}
+
+.ee-palette-cell-hover {
+ background: #E2ECF9 !important;
+ border: 1px solid #000;
+ padding: 1px;
+}
+
+.ee-palette-cell-selected {
+ background: #F0F0F0;
+ border: 1px solid #CCC !important;
+ padding: 1px;
+}
+
+.ee-menu-palette-table {
+ margin-right: 10px;
+}
+
+.ee-menu-palette {
+ outline: none;
+ padding-top: 2px;
+}
+
+.ee-menu-palette-cell {
+ background: #F0F0F0 none repeat scroll 0 0;
+ border-color: #888 #AAA #AAA #888;
+ border-style: solid;
+ border-width: 1px;
+}
+.ee-menu-palette-cell-hover,
+.ee-menu-palette-cell-selected {
+ background: #F0F0F0;
+}
+
+.ee-palette-item,
+.ee-menu-palette-item {
+ background-image: url(//ssl.gstatic.com/editor/ee-palettes.gif);
+}
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/editor/linkdialog.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/editor/linkdialog.css b/externs/GCL/externs/goog/css/editor/linkdialog.css
new file mode 100644
index 0000000..a58a4b2
--- /dev/null
+++ b/externs/GCL/externs/goog/css/editor/linkdialog.css
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/**
+ * Styles for the Editor's Edit Link dialog.
+ *
+ * @author marcosalmeida@google.com (Marcos Almeida)
+ */
+
+
+.tr-link-dialog-explanation-text {
+ font-size: 83%;
+ margin-top: 15px;
+}
+
+.tr-link-dialog-target-input {
+ width: 98%; /* 98% prevents scroll bars in standards mode. */
+ /* Input boxes for URLs and email address should always be LTR. */
+ direction: ltr;
+}
+
+.tr-link-dialog-email-warning {
+ text-align: center;
+ color: #c00;
+ font-weight: bold;
+}
+
+.tr_pseudo-link {
+ color: #00c;
+ text-decoration: underline;
+ cursor: pointer;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/editortoolbar.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/editortoolbar.css b/externs/GCL/externs/goog/css/editortoolbar.css
new file mode 100644
index 0000000..1e26f4f
--- /dev/null
+++ b/externs/GCL/externs/goog/css/editortoolbar.css
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+
+/*
+ * Editor toolbar styles.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+/* Common base style for all icons. */
+.tr-icon {
+ width: 16px;
+ height: 16px;
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat;
+ vertical-align: middle;
+}
+
+.goog-color-menu-button-indicator .tr-icon {
+ height: 14px;
+}
+
+/* Undo (redo when the chrome is right-to-left). */
+.tr-undo,
+.goog-toolbar-button-rtl .tr-redo {
+ background-position: 0;
+}
+
+/* Redo (undo when the chrome is right-to-left). */
+.tr-redo,
+.goog-toolbar-button-rtl .tr-undo {
+ background-position: -16px;
+}
+
+/* Font name. */
+.tr-fontName .goog-toolbar-menu-button-caption {
+ color: #246;
+ width: 16ex;
+ height: 16px;
+ overflow: hidden;
+}
+
+/* Font size. */
+.tr-fontSize .goog-toolbar-menu-button-caption {
+ color: #246;
+ width: 8ex;
+ height: 16px;
+ overflow: hidden;
+}
+
+/* Bold. */
+.tr-bold {
+ background-position: -32px;
+}
+
+/* Italic. */
+.tr-italic {
+ background-position: -48px;
+}
+
+/* Underline. */
+.tr-underline {
+ background-position: -64px;
+}
+
+/* Foreground color. */
+.tr-foreColor {
+ height: 14px;
+ background-position: -80px;
+}
+
+/* Background color. */
+.tr-backColor {
+ height: 14px;
+ background-position: -96px;
+}
+
+/* Link. */
+.tr-link {
+ font-weight: bold;
+ color: #009;
+ text-decoration: underline;
+}
+
+/* Insert image. */
+.tr-image {
+ background-position: -112px;
+}
+
+/* Insert drawing. */
+.tr-newDrawing {
+ background-position: -592px;
+}
+
+/* Insert special character. */
+.tr-spChar {
+ font-weight: bold;
+ color: #900;
+}
+
+/* Increase indent. */
+.tr-indent {
+ background-position: -128px;
+}
+
+/* Increase ident in right-to-left text mode, regardless of chrome direction. */
+.tr-rtl-mode .tr-indent {
+ background-position: -400px;
+}
+
+/* Decrease indent. */
+.tr-outdent {
+ background-position: -144px;
+}
+
+/* Decrease indent in right-to-left text mode, regardless of chrome direction. */
+.tr-rtl-mode .tr-outdent {
+ background-position: -416px;
+}
+
+/* Bullet (unordered) list. */
+.tr-insertUnorderedList {
+ background-position: -160px;
+}
+
+/* Bullet list in right-to-left text mode, regardless of chrome direction. */
+.tr-rtl-mode .tr-insertUnorderedList {
+ background-position: -432px;
+}
+
+/* Number (ordered) list. */
+.tr-insertOrderedList {
+ background-position: -176px;
+}
+
+/* Number list in right-to-left text mode, regardless of chrome direction. */
+.tr-rtl-mode .tr-insertOrderedList {
+ background-position: -448px;
+}
+
+/* Text alignment buttons. */
+.tr-justifyLeft {
+ background-position: -192px;
+}
+.tr-justifyCenter {
+ background-position: -208px;
+}
+.tr-justifyRight {
+ background-position: -224px;
+}
+.tr-justifyFull {
+ background-position: -480px;
+}
+
+/* Blockquote. */
+.tr-BLOCKQUOTE {
+ background-position: -240px;
+}
+
+/* Blockquote in right-to-left text mode, regardless of chrome direction. */
+.tr-rtl-mode .tr-BLOCKQUOTE {
+ background-position: -464px;
+}
+
+/* Remove formatting. */
+.tr-removeFormat {
+ background-position: -256px;
+}
+
+/* Spellcheck. */
+.tr-spell {
+ background-position: -272px;
+}
+
+/* Left-to-right text direction. */
+.tr-ltr {
+ background-position: -288px;
+}
+
+/* Right-to-left text direction. */
+.tr-rtl {
+ background-position: -304px;
+}
+
+/* Insert iGoogle module. */
+.tr-insertModule {
+ background-position: -496px;
+}
+
+/* Strike through text */
+.tr-strikeThrough {
+ background-position: -544px;
+}
+
+/* Subscript */
+.tr-subscript {
+ background-position: -560px;
+}
+
+/* Superscript */
+.tr-superscript {
+ background-position: -576px;
+}
+
+/* Insert drawing. */
+.tr-equation {
+ background-position: -608px;
+}
+
+/* Edit HTML. */
+.tr-editHtml {
+ color: #009;
+}
+
+/* "Format block" menu. */
+.tr-formatBlock .goog-toolbar-menu-button-caption {
+ color: #246;
+ width: 12ex;
+ height: 16px;
+ overflow: hidden;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/filteredmenu.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/filteredmenu.css b/externs/GCL/externs/goog/css/filteredmenu.css
new file mode 100644
index 0000000..b43a113
--- /dev/null
+++ b/externs/GCL/externs/goog/css/filteredmenu.css
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pupius@google.com (Daniel Pupius) */
+
+/* goog.ui.FilteredMenu */
+
+.goog-menu-filter {
+ margin: 2px;
+ border: 1px solid silver;
+ background: white;
+ overflow: hidden;
+}
+
+.goog-menu-filter div {
+ color: gray;
+ position: absolute;
+ padding: 1px;
+}
+
+.goog-menu-filter input {
+ margin: 0;
+ border: 0;
+ background: transparent;
+ width: 100%;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/filterobservingmenuitem.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/filterobservingmenuitem.css b/externs/GCL/externs/goog/css/filterobservingmenuitem.css
new file mode 100644
index 0000000..d48a609
--- /dev/null
+++ b/externs/GCL/externs/goog/css/filterobservingmenuitem.css
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pupius@google.com (Daniel Pupius) */
+
+/* goog.ui.FilterObservingMenuItem */
+
+.goog-filterobsmenuitem {
+ padding: 2px 5px;
+ margin: 0;
+ list-style: none;
+}
+
+.goog-filterobsmenuitem-highlight {
+ background-color: #4279A5;
+ color: #FFF;
+}
+
+.goog-filterobsmenuitem-disabled {
+ color: #999;
+}
[03/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/compactnumberformatsymbols.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/compactnumberformatsymbols.js b/externs/GCL/externs/goog/i18n/compactnumberformatsymbols.js
new file mode 100644
index 0000000..29b4abb
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/compactnumberformatsymbols.js
@@ -0,0 +1,9763 @@
+// 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 Compact number formatting symbols.
+ *
+ * This file is autogenerated by script:
+ * http://go/generate_number_constants.py
+ * using the --for_closure flag.
+ * File generated from CLDR ver. 27.0.1
+ *
+ * To reduce the file size (which may cause issues in some JS
+ * developing environments), this file will only contain locales
+ * that are frequently used by web applications. This is defined as
+ * closure_tier1_locales and will change (most likely addition)
+ * over time. Rest of the data can be found in another file named
+ * "compactnumberformatsymbols_ext.js", which will be generated at
+ * the same time together with this file.
+ *
+ * Before checkin, this file could have been manually edited. This is
+ * to incorporate changes before we could fix CLDR. All manual
+ * modification must be documented in this section, and should be
+ * removed after those changes land to CLDR.
+ */
+
+goog.provide('goog.i18n.CompactNumberFormatSymbols');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_af');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_af_ZA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_am');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_am_ET');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_001');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_EG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_az');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Latn_AZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bg');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bg_BG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_bn_BD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_br');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_br_FR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ca');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_AD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_ES');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_ES_VALENCIA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_FR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_IT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_chr');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_chr_US');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_cs');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_cs_CZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_cy');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_cy_GB');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_da');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_da_DK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_da_GL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_de');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_de_AT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_de_BE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_de_CH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_de_DE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_de_LU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_el');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_el_CY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_el_GR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_001');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_DG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_FM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GB');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MP');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_UM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_US');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ZA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ZW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_419');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_EA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_ES');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_es_IC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_et');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_et_EE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_eu');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_eu_ES');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fa');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fa_IR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fi');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fi_FI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fil');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fil_PH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_FR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GP');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MC');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MF');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MQ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_PM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_RE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_YT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ga');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ga_IE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gl_ES');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw_CH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw_LI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gu');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_gu_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_haw');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_haw_US');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_he');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_he_IL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hi');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hi_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hr');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hr_HR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hu');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hu_HU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hy');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_hy_AM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_id');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_id_ID');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_in');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_is');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_is_IS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_it');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_it_IT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_it_SM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_iw');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ja');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ja_JP');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ka');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ka_GE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kk');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kk_Cyrl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kk_Cyrl_KZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_km');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_km_KH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_kn_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ko');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ko_KR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ky');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ky_Cyrl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ky_Cyrl_KG');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ln');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_CD');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lo');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lo_LA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lt');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lt_LT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lv');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_lv_LV');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mk');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mk_MK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ml');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ml_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mn_Cyrl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mn_Cyrl_MN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mr');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mr_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ms');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn_MY');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mt');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_mt_MT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_my');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_my_MM');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nb');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nb_NO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nb_SJ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ne');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ne_NP');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_NL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_no');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_no_NO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_or');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_or_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pa');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Guru');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Guru_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pl_PL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_BR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_PT');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ro');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ro_RO');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ru');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_RU');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_si');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_si_LK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sk');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sk_SK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sl_SI');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sq');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sq_AL');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_RS');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sv');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sv_SE');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sw');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_sw_TZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ta');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_te');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_te_IN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_th');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_th_TH');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_tl');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_tr');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_tr_TR');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uk');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uk_UA');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ur');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_ur_PK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uz');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Latn');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Latn_UZ');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vi');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_vi_VN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_CN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_HK');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_CN');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_TW');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zu');
+goog.provide('goog.i18n.CompactNumberFormatSymbols_zu_ZA');
+
+
+/**
+ * Compact number formatting symbols for locale af.
+ */
+goog.i18n.CompactNumberFormatSymbols_af = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0'
+ },
+ '10000': {
+ 'other': '0'
+ },
+ '100000': {
+ 'other': '0'
+ },
+ '1000000': {
+ 'other': '0\u00A0m'
+ },
+ '10000000': {
+ 'other': '00\u00A0m'
+ },
+ '100000000': {
+ 'other': '000\u00A0m'
+ },
+ '1000000000': {
+ 'other': '0\u00A0mjd'
+ },
+ '10000000000': {
+ 'other': '00\u00A0mjd'
+ },
+ '100000000000': {
+ 'other': '000\u00A0mjd'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0bn'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0bn'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0bn'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 duisend'
+ },
+ '10000': {
+ 'other': '00 duisend'
+ },
+ '100000': {
+ 'other': '000 duisend'
+ },
+ '1000000': {
+ 'other': '0 miljoen'
+ },
+ '10000000': {
+ 'other': '00 miljoen'
+ },
+ '100000000': {
+ 'other': '000 miljoen'
+ },
+ '1000000000': {
+ 'other': '0 miljard'
+ },
+ '10000000000': {
+ 'other': '00 miljard'
+ },
+ '100000000000': {
+ 'other': '000 miljard'
+ },
+ '1000000000000': {
+ 'other': '0 biljoen'
+ },
+ '10000000000000': {
+ 'other': '00 biljoen'
+ },
+ '100000000000000': {
+ 'other': '000 biljoen'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale af_ZA.
+ */
+goog.i18n.CompactNumberFormatSymbols_af_ZA =
+ goog.i18n.CompactNumberFormatSymbols_af;
+
+
+/**
+ * Compact number formatting symbols for locale am.
+ */
+goog.i18n.CompactNumberFormatSymbols_am = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u123A'
+ },
+ '10000': {
+ 'other': '00\u00A0\u123A'
+ },
+ '100000': {
+ 'other': '000\u00A0\u123A'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u121C\u1275\u122D'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u121C\u1275\u122D'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u121C\u1275\u122D'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u1262'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u1262'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u1262'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u1275'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u1275'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u1275'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u123A'
+ },
+ '10000': {
+ 'other': '00 \u123A'
+ },
+ '100000': {
+ 'other': '000 \u123A'
+ },
+ '1000000': {
+ 'other': '0 \u121A\u120A\u12EE\u1295'
+ },
+ '10000000': {
+ 'other': '00 \u121A\u120A\u12EE\u1295'
+ },
+ '100000000': {
+ 'other': '000 \u121A\u120A\u12EE\u1295'
+ },
+ '1000000000': {
+ 'other': '0 \u1262\u120A\u12EE\u1295'
+ },
+ '10000000000': {
+ 'other': '00 \u1262\u120A\u12EE\u1295'
+ },
+ '100000000000': {
+ 'other': '000 \u1262\u120A\u12EE\u1295'
+ },
+ '1000000000000': {
+ 'other': '0 \u1275\u122A\u120A\u12EE\u1295'
+ },
+ '10000000000000': {
+ 'other': '00 \u1275\u122A\u120A\u12EE\u1295'
+ },
+ '100000000000000': {
+ 'other': '000 \u1275\u122A\u120A\u12EE\u1295'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale am_ET.
+ */
+goog.i18n.CompactNumberFormatSymbols_am_ET =
+ goog.i18n.CompactNumberFormatSymbols_am;
+
+
+/**
+ * Compact number formatting symbols for locale ar.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u0645\u0644\u064A\u0648'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u0628\u0644\u064A\u0648'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0623\u0644\u0641'
+ },
+ '10000': {
+ 'other': '00 \u0623\u0644\u0641'
+ },
+ '100000': {
+ 'other': '000 \u0623\u0644\u0641'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u0644\u064A\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '10000000000': {
+ 'other': '00 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '100000000000': {
+ 'other': '000 \u0628\u0644\u064A\u0648\u0646'
+ },
+ '1000000000000': {
+ 'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '10000000000000': {
+ 'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ },
+ '100000000000000': {
+ 'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ar_001.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_001 =
+ goog.i18n.CompactNumberFormatSymbols_ar;
+
+
+/**
+ * Compact number formatting symbols for locale ar_EG.
+ */
+goog.i18n.CompactNumberFormatSymbols_ar_EG =
+ goog.i18n.CompactNumberFormatSymbols_ar;
+
+
+/**
+ * Compact number formatting symbols for locale az.
+ */
+goog.i18n.CompactNumberFormatSymbols_az = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale az_Latn.
+ */
+goog.i18n.CompactNumberFormatSymbols_az_Latn =
+ goog.i18n.CompactNumberFormatSymbols_az;
+
+
+/**
+ * Compact number formatting symbols for locale az_Latn_AZ.
+ */
+goog.i18n.CompactNumberFormatSymbols_az_Latn_AZ =
+ goog.i18n.CompactNumberFormatSymbols_az;
+
+
+/**
+ * Compact number formatting symbols for locale bg.
+ */
+goog.i18n.CompactNumberFormatSymbols_bg = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0445\u0438\u043B.'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0445\u0438\u043B.'
+ },
+ '100000': {
+ 'other': '000\u00A0\u0445\u0438\u043B.'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u043C\u043B\u043D.'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u043C\u043B\u043D.'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u043C\u043B\u043D.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u043C\u043B\u0440\u0434.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u043C\u043B\u0440\u0434.'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u043C\u043B\u0440\u0434.'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u0442\u0440\u043B\u043D.'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u0442\u0440\u043B\u043D.'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u0442\u0440\u043B\u043D.'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0445\u0438\u043B\u044F\u0434\u0438'
+ },
+ '10000': {
+ 'other': '00 \u0445\u0438\u043B\u044F\u0434\u0438'
+ },
+ '100000': {
+ 'other': '000 \u0445\u0438\u043B\u044F\u0434\u0438'
+ },
+ '1000000': {
+ 'other': '0 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
+ },
+ '10000000': {
+ 'other': '00 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
+ },
+ '100000000': {
+ 'other': '000 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
+ },
+ '1000000000': {
+ 'other': '0 \u043C\u0438\u043B\u0438\u0430\u0440\u0434\u0430'
+ },
+ '10000000000': {
+ 'other': '00 \u043C\u0438\u043B\u0438\u0430\u0440\u0434\u0430'
+ },
+ '100000000000': {
+ 'other': '000 \u043C\u0438\u043B\u0438\u0430\u0440\u0434\u0430'
+ },
+ '1000000000000': {
+ 'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
+ },
+ '10000000000000': {
+ 'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
+ },
+ '100000000000000': {
+ 'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale bg_BG.
+ */
+goog.i18n.CompactNumberFormatSymbols_bg_BG =
+ goog.i18n.CompactNumberFormatSymbols_bg;
+
+
+/**
+ * Compact number formatting symbols for locale bn.
+ */
+goog.i18n.CompactNumberFormatSymbols_bn = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u09B9\u09BE\u099C\u09BE\u09B0'
+ },
+ '10000': {
+ 'other': '00\u00A0\u09B9\u09BE\u099C\u09BE\u09B0'
+ },
+ '100000': {
+ 'other': '0\u00A0\u09B2\u09BE\u0996'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u09B9\u09BE\u099C\u09BE\u09B0'
+ },
+ '10000': {
+ 'other': '00 \u09B9\u09BE\u099C\u09BE\u09B0'
+ },
+ '100000': {
+ 'other': '0 \u09B2\u09BE\u0996'
+ },
+ '1000000': {
+ 'other': '0 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '10000000': {
+ 'other': '00 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '100000000': {
+ 'other': '000 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '1000000000': {
+ 'other': '0 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '10000000000': {
+ 'other': '00 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '100000000000': {
+ 'other': '000 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '1000000000000': {
+ 'other': '0 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '10000000000000': {
+ 'other': '00 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ },
+ '100000000000000': {
+ 'other': '000 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale bn_BD.
+ */
+goog.i18n.CompactNumberFormatSymbols_bn_BD =
+ goog.i18n.CompactNumberFormatSymbols_bn;
+
+
+/**
+ * Compact number formatting symbols for locale br.
+ */
+goog.i18n.CompactNumberFormatSymbols_br = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale br_FR.
+ */
+goog.i18n.CompactNumberFormatSymbols_br_FR =
+ goog.i18n.CompactNumberFormatSymbols_br;
+
+
+/**
+ * Compact number formatting symbols for locale ca.
+ */
+goog.i18n.CompactNumberFormatSymbols_ca = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0m'
+ },
+ '10000': {
+ 'other': '00m'
+ },
+ '100000': {
+ 'other': '000m'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00\u00A0M'
+ },
+ '100000000': {
+ 'other': '000\u00A0M'
+ },
+ '1000000000': {
+ 'other': '0000\u00A0M'
+ },
+ '10000000000': {
+ 'other': '00mM'
+ },
+ '100000000000': {
+ 'other': '000mM'
+ },
+ '1000000000000': {
+ 'other': '0B'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0B'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0B'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 milers'
+ },
+ '10000': {
+ 'other': '00 milers'
+ },
+ '100000': {
+ 'other': '000 milers'
+ },
+ '1000000': {
+ 'other': '0 milions'
+ },
+ '10000000': {
+ 'other': '00 milions'
+ },
+ '100000000': {
+ 'other': '000 milions'
+ },
+ '1000000000': {
+ 'other': '0 milers de milions'
+ },
+ '10000000000': {
+ 'other': '00 milers de milions'
+ },
+ '100000000000': {
+ 'other': '000 milers de milions'
+ },
+ '1000000000000': {
+ 'other': '0 bilions'
+ },
+ '10000000000000': {
+ 'other': '00 bilions'
+ },
+ '100000000000000': {
+ 'other': '000 bilions'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ca_AD.
+ */
+goog.i18n.CompactNumberFormatSymbols_ca_AD =
+ goog.i18n.CompactNumberFormatSymbols_ca;
+
+
+/**
+ * Compact number formatting symbols for locale ca_ES.
+ */
+goog.i18n.CompactNumberFormatSymbols_ca_ES =
+ goog.i18n.CompactNumberFormatSymbols_ca;
+
+
+/**
+ * Compact number formatting symbols for locale ca_ES_VALENCIA.
+ */
+goog.i18n.CompactNumberFormatSymbols_ca_ES_VALENCIA =
+ goog.i18n.CompactNumberFormatSymbols_ca;
+
+
+/**
+ * Compact number formatting symbols for locale ca_FR.
+ */
+goog.i18n.CompactNumberFormatSymbols_ca_FR =
+ goog.i18n.CompactNumberFormatSymbols_ca;
+
+
+/**
+ * Compact number formatting symbols for locale ca_IT.
+ */
+goog.i18n.CompactNumberFormatSymbols_ca_IT =
+ goog.i18n.CompactNumberFormatSymbols_ca;
+
+
+/**
+ * Compact number formatting symbols for locale chr.
+ */
+goog.i18n.CompactNumberFormatSymbols_chr = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale chr_US.
+ */
+goog.i18n.CompactNumberFormatSymbols_chr_US =
+ goog.i18n.CompactNumberFormatSymbols_chr;
+
+
+/**
+ * Compact number formatting symbols for locale cs.
+ */
+goog.i18n.CompactNumberFormatSymbols_cs = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0tis.'
+ },
+ '10000': {
+ 'other': '00\u00A0tis.'
+ },
+ '100000': {
+ 'other': '000\u00A0tis.'
+ },
+ '1000000': {
+ 'other': '0\u00A0mil.'
+ },
+ '10000000': {
+ 'other': '00\u00A0mil.'
+ },
+ '100000000': {
+ 'other': '000\u00A0mil.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0mld.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0mld.'
+ },
+ '100000000000': {
+ 'other': '000\u00A0mld.'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0bil.'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0bil.'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0bil.'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 tis\u00EDc'
+ },
+ '10000': {
+ 'other': '00 tis\u00EDc'
+ },
+ '100000': {
+ 'other': '000 tis\u00EDc'
+ },
+ '1000000': {
+ 'other': '0 milion\u016F'
+ },
+ '10000000': {
+ 'other': '00 milion\u016F'
+ },
+ '100000000': {
+ 'other': '000 milion\u016F'
+ },
+ '1000000000': {
+ 'other': '0 miliard'
+ },
+ '10000000000': {
+ 'other': '00 miliard'
+ },
+ '100000000000': {
+ 'other': '000 miliard'
+ },
+ '1000000000000': {
+ 'other': '0 bilion\u016F'
+ },
+ '10000000000000': {
+ 'other': '00 bilion\u016F'
+ },
+ '100000000000000': {
+ 'other': '000 bilion\u016F'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale cs_CZ.
+ */
+goog.i18n.CompactNumberFormatSymbols_cs_CZ =
+ goog.i18n.CompactNumberFormatSymbols_cs;
+
+
+/**
+ * Compact number formatting symbols for locale cy.
+ */
+goog.i18n.CompactNumberFormatSymbols_cy = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 mil'
+ },
+ '10000': {
+ 'other': '00 mil'
+ },
+ '100000': {
+ 'other': '000 mil'
+ },
+ '1000000': {
+ 'other': '0 miliwn'
+ },
+ '10000000': {
+ 'other': '00 miliwn'
+ },
+ '100000000': {
+ 'other': '000 miliwn'
+ },
+ '1000000000': {
+ 'other': '0 biliwn'
+ },
+ '10000000000': {
+ 'other': '00 biliwn'
+ },
+ '100000000000': {
+ 'other': '000 biliwn'
+ },
+ '1000000000000': {
+ 'other': '0 triliwn'
+ },
+ '10000000000000': {
+ 'other': '00 triliwn'
+ },
+ '100000000000000': {
+ 'other': '000 triliwn'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale cy_GB.
+ */
+goog.i18n.CompactNumberFormatSymbols_cy_GB =
+ goog.i18n.CompactNumberFormatSymbols_cy;
+
+
+/**
+ * Compact number formatting symbols for locale da.
+ */
+goog.i18n.CompactNumberFormatSymbols_da = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0td'
+ },
+ '10000': {
+ 'other': '00\u00A0td'
+ },
+ '100000': {
+ 'other': '000\u00A0td'
+ },
+ '1000000': {
+ 'other': '0\u00A0mio'
+ },
+ '10000000': {
+ 'other': '00\u00A0mio'
+ },
+ '100000000': {
+ 'other': '000\u00A0mio'
+ },
+ '1000000000': {
+ 'other': '0\u00A0mia'
+ },
+ '10000000000': {
+ 'other': '00\u00A0mia'
+ },
+ '100000000000': {
+ 'other': '000\u00A0mia'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0bill'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0bill'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0bill'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 tusind'
+ },
+ '10000': {
+ 'other': '00 tusind'
+ },
+ '100000': {
+ 'other': '000 tusind'
+ },
+ '1000000': {
+ 'other': '0 millioner'
+ },
+ '10000000': {
+ 'other': '00 millioner'
+ },
+ '100000000': {
+ 'other': '000 millioner'
+ },
+ '1000000000': {
+ 'other': '0 milliarder'
+ },
+ '10000000000': {
+ 'other': '00 milliarder'
+ },
+ '100000000000': {
+ 'other': '000 milliarder'
+ },
+ '1000000000000': {
+ 'other': '0 billioner'
+ },
+ '10000000000000': {
+ 'other': '00 billioner'
+ },
+ '100000000000000': {
+ 'other': '000 billioner'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale da_DK.
+ */
+goog.i18n.CompactNumberFormatSymbols_da_DK =
+ goog.i18n.CompactNumberFormatSymbols_da;
+
+
+/**
+ * Compact number formatting symbols for locale da_GL.
+ */
+goog.i18n.CompactNumberFormatSymbols_da_GL =
+ goog.i18n.CompactNumberFormatSymbols_da;
+
+
+/**
+ * Compact number formatting symbols for locale de.
+ */
+goog.i18n.CompactNumberFormatSymbols_de = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0Tsd.'
+ },
+ '10000': {
+ 'other': '00\u00A0Tsd.'
+ },
+ '100000': {
+ 'other': '000\u00A0Tsd.'
+ },
+ '1000000': {
+ 'other': '0\u00A0Mio.'
+ },
+ '10000000': {
+ 'other': '00\u00A0Mio.'
+ },
+ '100000000': {
+ 'other': '000\u00A0Mio.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0Mrd.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0Mrd.'
+ },
+ '100000000000': {
+ 'other': '000\u00A0Mrd.'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0Bio.'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0Bio.'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0Bio.'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 Tausend'
+ },
+ '10000': {
+ 'other': '00 Tausend'
+ },
+ '100000': {
+ 'other': '000 Tausend'
+ },
+ '1000000': {
+ 'other': '0 Millionen'
+ },
+ '10000000': {
+ 'other': '00 Millionen'
+ },
+ '100000000': {
+ 'other': '000 Millionen'
+ },
+ '1000000000': {
+ 'other': '0 Milliarden'
+ },
+ '10000000000': {
+ 'other': '00 Milliarden'
+ },
+ '100000000000': {
+ 'other': '000 Milliarden'
+ },
+ '1000000000000': {
+ 'other': '0 Billionen'
+ },
+ '10000000000000': {
+ 'other': '00 Billionen'
+ },
+ '100000000000000': {
+ 'other': '000 Billionen'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale de_AT.
+ */
+goog.i18n.CompactNumberFormatSymbols_de_AT = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0Tsd.'
+ },
+ '10000': {
+ 'other': '00\u00A0Tsd.'
+ },
+ '100000': {
+ 'other': '000\u00A0Tsd.'
+ },
+ '1000000': {
+ 'other': '0\u00A0Mio.'
+ },
+ '10000000': {
+ 'other': '00\u00A0Mio.'
+ },
+ '100000000': {
+ 'other': '000\u00A0Mio.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0Mrd.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0Mrd.'
+ },
+ '100000000000': {
+ 'other': '000\u00A0Mrd.'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0Bio.'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0Bio.'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0Bio.'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 Tausend'
+ },
+ '10000': {
+ 'other': '00 Tausend'
+ },
+ '100000': {
+ 'other': '000 Tausend'
+ },
+ '1000000': {
+ 'other': '0 Millionen'
+ },
+ '10000000': {
+ 'other': '00 Millionen'
+ },
+ '100000000': {
+ 'other': '000 Millionen'
+ },
+ '1000000000': {
+ 'other': '0 Milliarden'
+ },
+ '10000000000': {
+ 'other': '00 Milliarden'
+ },
+ '100000000000': {
+ 'other': '000 Milliarden'
+ },
+ '1000000000000': {
+ 'other': '0 Billionen'
+ },
+ '10000000000000': {
+ 'other': '00 Billionen'
+ },
+ '100000000000000': {
+ 'other': '000 Billionen'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale de_BE.
+ */
+goog.i18n.CompactNumberFormatSymbols_de_BE =
+ goog.i18n.CompactNumberFormatSymbols_de;
+
+
+/**
+ * Compact number formatting symbols for locale de_CH.
+ */
+goog.i18n.CompactNumberFormatSymbols_de_CH = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0Tsd.'
+ },
+ '10000': {
+ 'other': '00\u00A0Tsd.'
+ },
+ '100000': {
+ 'other': '000\u00A0Tsd.'
+ },
+ '1000000': {
+ 'other': '0\u00A0Mio.'
+ },
+ '10000000': {
+ 'other': '00\u00A0Mio.'
+ },
+ '100000000': {
+ 'other': '000\u00A0Mio.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0Mrd.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0Mrd.'
+ },
+ '100000000000': {
+ 'other': '000\u00A0Mrd.'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0Bio.'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0Bio.'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0Bio.'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 Tausend'
+ },
+ '10000': {
+ 'other': '00 Tausend'
+ },
+ '100000': {
+ 'other': '000 Tausend'
+ },
+ '1000000': {
+ 'other': '0 Millionen'
+ },
+ '10000000': {
+ 'other': '00 Millionen'
+ },
+ '100000000': {
+ 'other': '000 Millionen'
+ },
+ '1000000000': {
+ 'other': '0 Milliarden'
+ },
+ '10000000000': {
+ 'other': '00 Milliarden'
+ },
+ '100000000000': {
+ 'other': '000 Milliarden'
+ },
+ '1000000000000': {
+ 'other': '0 Billionen'
+ },
+ '10000000000000': {
+ 'other': '00 Billionen'
+ },
+ '100000000000000': {
+ 'other': '000 Billionen'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale de_DE.
+ */
+goog.i18n.CompactNumberFormatSymbols_de_DE =
+ goog.i18n.CompactNumberFormatSymbols_de;
+
+
+/**
+ * Compact number formatting symbols for locale de_LU.
+ */
+goog.i18n.CompactNumberFormatSymbols_de_LU =
+ goog.i18n.CompactNumberFormatSymbols_de;
+
+
+/**
+ * Compact number formatting symbols for locale el.
+ */
+goog.i18n.CompactNumberFormatSymbols_el = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u03C7\u03B9\u03BB.'
+ },
+ '10000': {
+ 'other': '00\u00A0\u03C7\u03B9\u03BB.'
+ },
+ '100000': {
+ 'other': '000\u00A0\u03C7\u03B9\u03BB.'
+ },
+ '1000000': {
+ 'other': '0\u00A0\u03B5\u03BA.'
+ },
+ '10000000': {
+ 'other': '00\u00A0\u03B5\u03BA.'
+ },
+ '100000000': {
+ 'other': '000\u00A0\u03B5\u03BA.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u03B4\u03B9\u03C3.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u03B4\u03B9\u03C3.'
+ },
+ '100000000000': {
+ 'other': '000\u00A0\u03B4\u03B9\u03C3.'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u03C4\u03C1\u03B9\u03C3.'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0\u03C4\u03C1\u03B9\u03C3.'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0\u03C4\u03C1\u03B9\u03C3.'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
+ },
+ '10000': {
+ 'other': '00 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
+ },
+ '100000': {
+ 'other': '000 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
+ },
+ '1000000': {
+ 'other': '0 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '10000000': {
+ 'other': '00 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '100000000': {
+ 'other': '000 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '1000000000': {
+ 'other': '0 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '10000000000': {
+ 'other': '00 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '100000000000': {
+ 'other': '000 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '1000000000000': {
+ 'other': '0 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '10000000000000': {
+ 'other': '00 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ },
+ '100000000000000': {
+ 'other': '000 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale el_CY.
+ */
+goog.i18n.CompactNumberFormatSymbols_el_CY =
+ goog.i18n.CompactNumberFormatSymbols_el;
+
+
+/**
+ * Compact number formatting symbols for locale el_GR.
+ */
+goog.i18n.CompactNumberFormatSymbols_el_GR =
+ goog.i18n.CompactNumberFormatSymbols_el;
+
+
+/**
+ * Compact number formatting symbols for locale en.
+ */
+goog.i18n.CompactNumberFormatSymbols_en = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 thousand'
+ },
+ '10000': {
+ 'other': '00 thousand'
+ },
+ '100000': {
+ 'other': '000 thousand'
+ },
+ '1000000': {
+ 'other': '0 million'
+ },
+ '10000000': {
+ 'other': '00 million'
+ },
+ '100000000': {
+ 'other': '000 million'
+ },
+ '1000000000': {
+ 'other': '0 billion'
+ },
+ '10000000000': {
+ 'other': '00 billion'
+ },
+ '100000000000': {
+ 'other': '000 billion'
+ },
+ '1000000000000': {
+ 'other': '0 trillion'
+ },
+ '10000000000000': {
+ 'other': '00 trillion'
+ },
+ '100000000000000': {
+ 'other': '000 trillion'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale en_001.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_001 =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_AS.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_AS =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_AU.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_AU = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 thousand'
+ },
+ '10000': {
+ 'other': '00 thousand'
+ },
+ '100000': {
+ 'other': '000 thousand'
+ },
+ '1000000': {
+ 'other': '0 million'
+ },
+ '10000000': {
+ 'other': '00 million'
+ },
+ '100000000': {
+ 'other': '000 million'
+ },
+ '1000000000': {
+ 'other': '0 billion'
+ },
+ '10000000000': {
+ 'other': '00 billion'
+ },
+ '100000000000': {
+ 'other': '000 billion'
+ },
+ '1000000000000': {
+ 'other': '0 trillion'
+ },
+ '10000000000000': {
+ 'other': '00 trillion'
+ },
+ '100000000000000': {
+ 'other': '000 trillion'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale en_DG.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_DG =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_FM.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_FM =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_GB.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_GB = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 thousand'
+ },
+ '10000': {
+ 'other': '00 thousand'
+ },
+ '100000': {
+ 'other': '000 thousand'
+ },
+ '1000000': {
+ 'other': '0 million'
+ },
+ '10000000': {
+ 'other': '00 million'
+ },
+ '100000000': {
+ 'other': '000 million'
+ },
+ '1000000000': {
+ 'other': '0 billion'
+ },
+ '10000000000': {
+ 'other': '00 billion'
+ },
+ '100000000000': {
+ 'other': '000 billion'
+ },
+ '1000000000000': {
+ 'other': '0 trillion'
+ },
+ '10000000000000': {
+ 'other': '00 trillion'
+ },
+ '100000000000000': {
+ 'other': '000 trillion'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale en_GU.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_GU =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_IE.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_IE = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 thousand'
+ },
+ '10000': {
+ 'other': '00 thousand'
+ },
+ '100000': {
+ 'other': '000 thousand'
+ },
+ '1000000': {
+ 'other': '0 million'
+ },
+ '10000000': {
+ 'other': '00 million'
+ },
+ '100000000': {
+ 'other': '000 million'
+ },
+ '1000000000': {
+ 'other': '0 billion'
+ },
+ '10000000000': {
+ 'other': '00 billion'
+ },
+ '100000000000': {
+ 'other': '000 billion'
+ },
+ '1000000000000': {
+ 'other': '0 trillion'
+ },
+ '10000000000000': {
+ 'other': '00 trillion'
+ },
+ '100000000000000': {
+ 'other': '000 trillion'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale en_IN.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_IN = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 thousand'
+ },
+ '10000': {
+ 'other': '00 thousand'
+ },
+ '100000': {
+ 'other': '000 thousand'
+ },
+ '1000000': {
+ 'other': '0 million'
+ },
+ '10000000': {
+ 'other': '00 million'
+ },
+ '100000000': {
+ 'other': '000 million'
+ },
+ '1000000000': {
+ 'other': '0 billion'
+ },
+ '10000000000': {
+ 'other': '00 billion'
+ },
+ '100000000000': {
+ 'other': '000 billion'
+ },
+ '1000000000000': {
+ 'other': '0 trillion'
+ },
+ '10000000000000': {
+ 'other': '00 trillion'
+ },
+ '100000000000000': {
+ 'other': '000 trillion'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale en_IO.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_IO =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_MH.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_MH =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_MP.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_MP =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_PR.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_PR =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_PW.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_PW =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_SG.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_SG = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 thousand'
+ },
+ '10000': {
+ 'other': '00 thousand'
+ },
+ '100000': {
+ 'other': '000 thousand'
+ },
+ '1000000': {
+ 'other': '0 million'
+ },
+ '10000000': {
+ 'other': '00 million'
+ },
+ '100000000': {
+ 'other': '000 million'
+ },
+ '1000000000': {
+ 'other': '0 billion'
+ },
+ '10000000000': {
+ 'other': '00 billion'
+ },
+ '100000000000': {
+ 'other': '000 billion'
+ },
+ '1000000000000': {
+ 'other': '0 trillion'
+ },
+ '10000000000000': {
+ 'other': '00 trillion'
+ },
+ '100000000000000': {
+ 'other': '000 trillion'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale en_TC.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_TC =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_UM.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_UM =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_US.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_US =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_VG.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_VG =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_VI.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_VI =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale en_ZA.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_ZA = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 thousand'
+ },
+ '10000': {
+ 'other': '00 thousand'
+ },
+ '100000': {
+ 'other': '000 thousand'
+ },
+ '1000000': {
+ 'other': '0 million'
+ },
+ '10000000': {
+ 'other': '00 million'
+ },
+ '100000000': {
+ 'other': '000 million'
+ },
+ '1000000000': {
+ 'other': '0 billion'
+ },
+ '10000000000': {
+ 'other': '00 billion'
+ },
+ '100000000000': {
+ 'other': '000 billion'
+ },
+ '1000000000000': {
+ 'other': '0 trillion'
+ },
+ '10000000000000': {
+ 'other': '00 trillion'
+ },
+ '100000000000000': {
+ 'other': '000 trillion'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale en_ZW.
+ */
+goog.i18n.CompactNumberFormatSymbols_en_ZW =
+ goog.i18n.CompactNumberFormatSymbols_en;
+
+
+/**
+ * Compact number formatting symbols for locale es.
+ */
+goog.i18n.CompactNumberFormatSymbols_es = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0K'
+ },
+ '10000': {
+ 'other': '00\u00A0K'
+ },
+ '100000': {
+ 'other': '000\u00A0K'
+ },
+ '1000000': {
+ 'other': '0\u00A0M'
+ },
+ '10000000': {
+ 'other': '00\u00A0M'
+ },
+ '100000000': {
+ 'other': '000\u00A0M'
+ },
+ '1000000000': {
+ 'other': '0000\u00A0M'
+ },
+ '10000000000': {
+ 'other': '00\u00A0MRD'
+ },
+ '100000000000': {
+ 'other': '000\u00A0MRD'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0B'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0B'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0B'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 mil'
+ },
+ '10000': {
+ 'other': '00 mil'
+ },
+ '100000': {
+ 'other': '000 mil'
+ },
+ '1000000': {
+ 'other': '0 millones'
+ },
+ '10000000': {
+ 'other': '00 millones'
+ },
+ '100000000': {
+ 'other': '000 millones'
+ },
+ '1000000000': {
+ 'other': '0 mil millones'
+ },
+ '10000000000': {
+ 'other': '00 mil millones'
+ },
+ '100000000000': {
+ 'other': '000 mil millones'
+ },
+ '1000000000000': {
+ 'other': '0 billones'
+ },
+ '10000000000000': {
+ 'other': '00 billones'
+ },
+ '100000000000000': {
+ 'other': '000 billones'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale es_419.
+ */
+goog.i18n.CompactNumberFormatSymbols_es_419 = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0'
+ },
+ '10000': {
+ 'other': '00k'
+ },
+ '100000': {
+ 'other': '000k'
+ },
+ '1000000': {
+ 'other': '0\u00A0M'
+ },
+ '10000000': {
+ 'other': '00\u00A0M'
+ },
+ '100000000': {
+ 'other': '000\u00A0M'
+ },
+ '1000000000': {
+ 'other': '0k\u00A0M'
+ },
+ '10000000000': {
+ 'other': '00k\u00A0M'
+ },
+ '100000000000': {
+ 'other': '000k\u00A0M'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0B'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0B'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0B'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 mil'
+ },
+ '10000': {
+ 'other': '00 mil'
+ },
+ '100000': {
+ 'other': '000 mil'
+ },
+ '1000000': {
+ 'other': '0 millones'
+ },
+ '10000000': {
+ 'other': '00 millones'
+ },
+ '100000000': {
+ 'other': '000 millones'
+ },
+ '1000000000': {
+ 'other': '0 mil millones'
+ },
+ '10000000000': {
+ 'other': '00 mil millones'
+ },
+ '100000000000': {
+ 'other': '000 mil millones'
+ },
+ '1000000000000': {
+ 'other': '0 billones'
+ },
+ '10000000000000': {
+ 'other': '00 billones'
+ },
+ '100000000000000': {
+ 'other': '000 billones'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale es_EA.
+ */
+goog.i18n.CompactNumberFormatSymbols_es_EA =
+ goog.i18n.CompactNumberFormatSymbols_es;
+
+
+/**
+ * Compact number formatting symbols for locale es_ES.
+ */
+goog.i18n.CompactNumberFormatSymbols_es_ES =
+ goog.i18n.CompactNumberFormatSymbols_es;
+
+
+/**
+ * Compact number formatting symbols for locale es_IC.
+ */
+goog.i18n.CompactNumberFormatSymbols_es_IC =
+ goog.i18n.CompactNumberFormatSymbols_es;
+
+
+/**
+ * Compact number formatting symbols for locale et.
+ */
+goog.i18n.CompactNumberFormatSymbols_et = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0tuh'
+ },
+ '10000': {
+ 'other': '00\u00A0tuh'
+ },
+ '100000': {
+ 'other': '000\u00A0tuh'
+ },
+ '1000000': {
+ 'other': '0\u00A0mln'
+ },
+ '10000000': {
+ 'other': '00\u00A0mln'
+ },
+ '100000000': {
+ 'other': '000\u00A0mln'
+ },
+ '1000000000': {
+ 'other': '0\u00A0mld'
+ },
+ '10000000000': {
+ 'other': '00\u00A0mld'
+ },
+ '100000000000': {
+ 'other': '000\u00A0mld'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0trl'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0trl'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0trl'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 tuhat'
+ },
+ '10000': {
+ 'other': '00 tuhat'
+ },
+ '100000': {
+ 'other': '000 tuhat'
+ },
+ '1000000': {
+ 'other': '0 miljonit'
+ },
+ '10000000': {
+ 'other': '00 miljonit'
+ },
+ '100000000': {
+ 'other': '000 miljonit'
+ },
+ '1000000000': {
+ 'other': '0 miljardit'
+ },
+ '10000000000': {
+ 'other': '00 miljardit'
+ },
+ '100000000000': {
+ 'other': '000 miljardit'
+ },
+ '1000000000000': {
+ 'other': '0 triljonit'
+ },
+ '10000000000000': {
+ 'other': '00 triljonit'
+ },
+ '100000000000000': {
+ 'other': '000 triljonit'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale et_EE.
+ */
+goog.i18n.CompactNumberFormatSymbols_et_EE =
+ goog.i18n.CompactNumberFormatSymbols_et;
+
+
+/**
+ * Compact number formatting symbols for locale eu.
+ */
+goog.i18n.CompactNumberFormatSymbols_eu = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0000'
+ },
+ '10000': {
+ 'other': '00000'
+ },
+ '100000': {
+ 'other': '000000'
+ },
+ '1000000': {
+ 'other': '0\u00A0M'
+ },
+ '10000000': {
+ 'other': '00\u00A0M'
+ },
+ '100000000': {
+ 'other': '000\u00A0M'
+ },
+ '1000000000': {
+ 'other': '0000\u00A0M'
+ },
+ '10000000000': {
+ 'other': '00000\u00A0M'
+ },
+ '100000000000': {
+ 'other': '000000\u00A0M'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0B'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0B'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0B'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0000'
+ },
+ '10000': {
+ 'other': '00000'
+ },
+ '100000': {
+ 'other': '000000'
+ },
+ '1000000': {
+ 'other': '0 milioi'
+ },
+ '10000000': {
+ 'other': '00 milioi'
+ },
+ '100000000': {
+ 'other': '000 milioi'
+ },
+ '1000000000': {
+ 'other': '0000 milioi'
+ },
+ '10000000000': {
+ 'other': '00000 milioi'
+ },
+ '100000000000': {
+ 'other': '000000 milioi'
+ },
+ '1000000000000': {
+ 'other': '0 bilioi'
+ },
+ '10000000000000': {
+ 'other': '00 bilioi'
+ },
+ '100000000000000': {
+ 'other': '000 bilioi'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale eu_ES.
+ */
+goog.i18n.CompactNumberFormatSymbols_eu_ES =
+ goog.i18n.CompactNumberFormatSymbols_eu;
+
+
+/**
+ * Compact number formatting symbols for locale fa.
+ */
+goog.i18n.CompactNumberFormatSymbols_fa = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0647\u0632\u0627\u0631'
+ },
+ '10000': {
+ 'other': '00 \u0647\u0632\u0627\u0631'
+ },
+ '100000': {
+ 'other': '000 \u0647\u0632\u0627\u0631'
+ },
+ '1000000': {
+ 'other': '0 \u0645\u06CC\u0644\u06CC\u0648\u0646'
+ },
+ '10000000': {
+ 'other': '00 \u0645\u06CC\u0644\u06CC\u0648\u0646'
+ },
+ '100000000': {
+ 'other': '000 \u0645\u06CC\u0644\u06CC\u0648\u0646'
+ },
+ '1000000000': {
+ 'other': '0 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
+ },
+ '10000000000': {
+ 'other': '00 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
+ },
+ '100000000000': {
+ 'other': '000 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
+ },
+ '1000000000000': {
+ 'other': '0 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
+ },
+ '10000000000000': {
+ 'other': '00 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
+ },
+ '100000000000000': {
+ 'other': '000 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale fa_IR.
+ */
+goog.i18n.CompactNumberFormatSymbols_fa_IR =
+ goog.i18n.CompactNumberFormatSymbols_fa;
+
+
+/**
+ * Compact number formatting symbols for locale fi.
+ */
+goog.i18n.CompactNumberFormatSymbols_fi = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0t.'
+ },
+ '10000': {
+ 'other': '00\u00A0t.'
+ },
+ '100000': {
+ 'other': '000\u00A0t.'
+ },
+ '1000000': {
+ 'other': '0\u00A0milj.'
+ },
+ '10000000': {
+ 'other': '00\u00A0milj.'
+ },
+ '100000000': {
+ 'other': '000\u00A0milj.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0mrd.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0mrd.'
+ },
+ '100000000000': {
+ 'other': '000\u00A0mrd.'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0bilj.'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0bilj.'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0bilj.'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 tuhatta'
+ },
+ '10000': {
+ 'other': '00 tuhatta'
+ },
+ '100000': {
+ 'other': '000 tuhatta'
+ },
+ '1000000': {
+ 'other': '0 miljoonaa'
+ },
+ '10000000': {
+ 'other': '00 miljoonaa'
+ },
+ '100000000': {
+ 'other': '000 miljoonaa'
+ },
+ '1000000000': {
+ 'other': '0 miljardia'
+ },
+ '10000000000': {
+ 'other': '00 miljardia'
+ },
+ '100000000000': {
+ 'other': '000 miljardia'
+ },
+ '1000000000000': {
+ 'other': '0 biljoonaa'
+ },
+ '10000000000000': {
+ 'other': '00 biljoonaa'
+ },
+ '100000000000000': {
+ 'other': '000 biljoonaa'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale fi_FI.
+ */
+goog.i18n.CompactNumberFormatSymbols_fi_FI =
+ goog.i18n.CompactNumberFormatSymbols_fi;
+
+
+/**
+ * Compact number formatting symbols for locale fil.
+ */
+goog.i18n.CompactNumberFormatSymbols_fil = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 libo'
+ },
+ '10000': {
+ 'other': '00 libo'
+ },
+ '100000': {
+ 'other': '000 libo'
+ },
+ '1000000': {
+ 'other': '0 milyon'
+ },
+ '10000000': {
+ 'other': '00 milyon'
+ },
+ '100000000': {
+ 'other': '000 milyon'
+ },
+ '1000000000': {
+ 'other': '0 bilyon'
+ },
+ '10000000000': {
+ 'other': '00 bilyon'
+ },
+ '100000000000': {
+ 'other': '000 bilyon'
+ },
+ '1000000000000': {
+ 'other': '0 trilyon'
+ },
+ '10000000000000': {
+ 'other': '00 trilyon'
+ },
+ '100000000000000': {
+ 'other': '000 trilyon'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale fil_PH.
+ */
+goog.i18n.CompactNumberFormatSymbols_fil_PH =
+ goog.i18n.CompactNumberFormatSymbols_fil;
+
+
+/**
+ * Compact number formatting symbols for locale fr.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0k'
+ },
+ '10000': {
+ 'other': '00\u00A0k'
+ },
+ '100000': {
+ 'other': '000\u00A0k'
+ },
+ '1000000': {
+ 'other': '0\u00A0M'
+ },
+ '10000000': {
+ 'other': '00\u00A0M'
+ },
+ '100000000': {
+ 'other': '000\u00A0M'
+ },
+ '1000000000': {
+ 'other': '0\u00A0Md'
+ },
+ '10000000000': {
+ 'other': '00\u00A0Md'
+ },
+ '100000000000': {
+ 'other': '000\u00A0Md'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0Bn'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0Bn'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0Bn'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 mille'
+ },
+ '10000': {
+ 'other': '00 mille'
+ },
+ '100000': {
+ 'other': '000 mille'
+ },
+ '1000000': {
+ 'other': '0 millions'
+ },
+ '10000000': {
+ 'other': '00 millions'
+ },
+ '100000000': {
+ 'other': '000 millions'
+ },
+ '1000000000': {
+ 'other': '0 milliards'
+ },
+ '10000000000': {
+ 'other': '00 milliards'
+ },
+ '100000000000': {
+ 'other': '000 milliards'
+ },
+ '1000000000000': {
+ 'other': '0 billions'
+ },
+ '10000000000000': {
+ 'other': '00 billions'
+ },
+ '100000000000000': {
+ 'other': '000 billions'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale fr_BL.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_BL =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_CA.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_CA = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0k'
+ },
+ '10000': {
+ 'other': '00\u00A0k'
+ },
+ '100000': {
+ 'other': '000\u00A0k'
+ },
+ '1000000': {
+ 'other': '0\u00A0M'
+ },
+ '10000000': {
+ 'other': '00\u00A0M'
+ },
+ '100000000': {
+ 'other': '000\u00A0M'
+ },
+ '1000000000': {
+ 'other': '0\u00A0G'
+ },
+ '10000000000': {
+ 'other': '00\u00A0G'
+ },
+ '100000000000': {
+ 'other': '000\u00A0G'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0T'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0T'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 mille'
+ },
+ '10000': {
+ 'other': '00 mille'
+ },
+ '100000': {
+ 'other': '000 mille'
+ },
+ '1000000': {
+ 'other': '0 millions'
+ },
+ '10000000': {
+ 'other': '00 millions'
+ },
+ '100000000': {
+ 'other': '000 millions'
+ },
+ '1000000000': {
+ 'other': '0 milliards'
+ },
+ '10000000000': {
+ 'other': '00 milliards'
+ },
+ '100000000000': {
+ 'other': '000 milliards'
+ },
+ '1000000000000': {
+ 'other': '0 billions'
+ },
+ '10000000000000': {
+ 'other': '00 billions'
+ },
+ '100000000000000': {
+ 'other': '000 billions'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale fr_FR.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_FR =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_GF.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_GF =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_GP.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_GP =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_MC.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_MC =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_MF.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_MF =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_MQ.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_MQ =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_PM.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_PM =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_RE.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_RE =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale fr_YT.
+ */
+goog.i18n.CompactNumberFormatSymbols_fr_YT =
+ goog.i18n.CompactNumberFormatSymbols_fr;
+
+
+/**
+ * Compact number formatting symbols for locale ga.
+ */
+goog.i18n.CompactNumberFormatSymbols_ga = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0k'
+ },
+ '10000': {
+ 'other': '00k'
+ },
+ '100000': {
+ 'other': '000k'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0B'
+ },
+ '10000000000': {
+ 'other': '00B'
+ },
+ '100000000000': {
+ 'other': '000B'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 m\u00EDle'
+ },
+ '10000': {
+ 'other': '00 m\u00EDle'
+ },
+ '100000': {
+ 'other': '000 m\u00EDle'
+ },
+ '1000000': {
+ 'other': '0 milli\u00FAn'
+ },
+ '10000000': {
+ 'other': '00 milli\u00FAn'
+ },
+ '100000000': {
+ 'other': '000 milli\u00FAn'
+ },
+ '1000000000': {
+ 'other': '0 billi\u00FAn'
+ },
+ '10000000000': {
+ 'other': '00 billi\u00FAn'
+ },
+ '100000000000': {
+ 'other': '000 billi\u00FAn'
+ },
+ '1000000000000': {
+ 'other': '0 trilli\u00FAn'
+ },
+ '10000000000000': {
+ 'other': '00 trilli\u00FAn'
+ },
+ '100000000000000': {
+ 'other': '000 trilli\u00FAn'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale ga_IE.
+ */
+goog.i18n.CompactNumberFormatSymbols_ga_IE =
+ goog.i18n.CompactNumberFormatSymbols_ga;
+
+
+/**
+ * Compact number formatting symbols for locale gl.
+ */
+goog.i18n.CompactNumberFormatSymbols_gl = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0k\u00A0M'
+ },
+ '10000000000': {
+ 'other': '00k\u00A0M'
+ },
+ '100000000000': {
+ 'other': '000k\u00A0M'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0B'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0B'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0B'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 mil'
+ },
+ '10000': {
+ 'other': '00 mil'
+ },
+ '100000': {
+ 'other': '000 mil'
+ },
+ '1000000': {
+ 'other': '0 mill\u00F3ns'
+ },
+ '10000000': {
+ 'other': '00 mill\u00F3ns'
+ },
+ '100000000': {
+ 'other': '000 mill\u00F3ns'
+ },
+ '1000000000': {
+ 'other': '0 mil mill\u00F3ns'
+ },
+ '10000000000': {
+ 'other': '00 mil mill\u00F3ns'
+ },
+ '100000000000': {
+ 'other': '000 mil mill\u00F3ns'
+ },
+ '1000000000000': {
+ 'other': '0 bill\u00F3ns'
+ },
+ '10000000000000': {
+ 'other': '00 bill\u00F3ns'
+ },
+ '100000000000000': {
+ 'other': '000 bill\u00F3ns'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale gl_ES.
+ */
+goog.i18n.CompactNumberFormatSymbols_gl_ES =
+ goog.i18n.CompactNumberFormatSymbols_gl;
+
+
+/**
+ * Compact number formatting symbols for locale gsw.
+ */
+goog.i18n.CompactNumberFormatSymbols_gsw = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0tsd'
+ },
+ '10000': {
+ 'other': '00\u00A0tsd'
+ },
+ '100000': {
+ 'other': '000\u00A0tsd'
+ },
+ '1000000': {
+ 'other': '0\u00A0Mio'
+ },
+ '10000000': {
+ 'other': '00\u00A0Mio'
+ },
+ '100000000': {
+ 'other': '000\u00A0Mio'
+ },
+ '1000000000': {
+ 'other': '0\u00A0Mrd'
+ },
+ '10000000000': {
+ 'other': '00\u00A0Mrd'
+ },
+ '100000000000': {
+ 'other': '000\u00A0Mrd'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0Bio'
+ },
+ '10000000000000': {
+ 'other': '00\u00A0Bio'
+ },
+ '100000000000000': {
+ 'other': '000\u00A0Bio'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 tausend'
+ },
+ '10000': {
+ 'other': '00 tausend'
+ },
+ '100000': {
+ 'other': '000 tausend'
+ },
+ '1000000': {
+ 'other': '0 Millionen'
+ },
+ '10000000': {
+ 'other': '00 Millionen'
+ },
+ '100000000': {
+ 'other': '000 Millionen'
+ },
+ '1000000000': {
+ 'other': '0 Milliarden'
+ },
+ '10000000000': {
+ 'other': '00 Milliarden'
+ },
+ '100000000000': {
+ 'other': '000 Milliarden'
+ },
+ '1000000000000': {
+ 'other': '0 Billionen'
+ },
+ '10000000000000': {
+ 'other': '00 Billionen'
+ },
+ '100000000000000': {
+ 'other': '000 Billionen'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale gsw_CH.
+ */
+goog.i18n.CompactNumberFormatSymbols_gsw_CH =
+ goog.i18n.CompactNumberFormatSymbols_gsw;
+
+
+/**
+ * Compact number formatting symbols for locale gsw_LI.
+ */
+goog.i18n.CompactNumberFormatSymbols_gsw_LI =
+ goog.i18n.CompactNumberFormatSymbols_gsw;
+
+
+/**
+ * Compact number formatting symbols for locale gu.
+ */
+goog.i18n.CompactNumberFormatSymbols_gu = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0AB9\u0A9C\u0ABE\u0AB0'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0AB9\u0A9C\u0ABE\u0AB0'
+ },
+ '100000': {
+ 'other': '0\u00A0\u0AB2\u0ABE\u0A96'
+ },
+ '1000000': {
+ 'other': '00\u00A0\u0AB2\u0ABE\u0A96'
+ },
+ '10000000': {
+ 'other': '0\u00A0\u0A95\u0AB0\u0ACB\u0AA1'
+ },
+ '100000000': {
+ 'other': '00\u00A0\u0A95\u0AB0\u0ACB\u0AA1'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0A85\u0AAC\u0A9C'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0A85\u0AAC\u0A9C'
+ },
+ '100000000000': {
+ 'other': '0\u00A0\u0AA8\u0ABF\u0A96\u0AB0\u0ACD\u0AB5'
+ },
+ '1000000000000': {
+ 'other': '0\u00A0\u0AAE\u0AB9\u0ABE\u0AAA\u0AA6\u0ACD\u0AAE'
+ },
+ '10000000000000': {
+ 'other': '0\u00A0\u0AB6\u0A82\u0A95\u0AC1'
+ },
+ '100000000000000': {
+ 'other': '0\u00A0\u0A9C\u0AB2\u0AA7\u0ABF'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0AB9\u0A9C\u0ABE\u0AB0'
+ },
+ '10000': {
+ 'other': '00 \u0AB9\u0A9C\u0ABE\u0AB0'
+ },
+ '100000': {
+ 'other': '0 \u0AB2\u0ABE\u0A96'
+ },
+ '1000000': {
+ 'other': '00 \u0AB2\u0ABE\u0A96'
+ },
+ '10000000': {
+ 'other': '0 \u0A95\u0AB0\u0ACB\u0AA1'
+ },
+ '100000000': {
+ 'other': '00 \u0A95\u0AB0\u0ACB\u0AA1'
+ },
+ '1000000000': {
+ 'other': '0 \u0A85\u0AAC\u0A9C'
+ },
+ '10000000000': {
+ 'other': '00 \u0A85\u0AAC\u0A9C'
+ },
+ '100000000000': {
+ 'other': '0 \u0AA8\u0ABF\u0A96\u0AB0\u0ACD\u0AB5'
+ },
+ '1000000000000': {
+ 'other': '0 \u0AAE\u0AB9\u0ABE\u0AAA\u0AA6\u0ACD\u0AAE'
+ },
+ '10000000000000': {
+ 'other': '0 \u0AB6\u0A82\u0A95\u0AC1'
+ },
+ '100000000000000': {
+ 'other': '0 \u0A9C\u0AB2\u0AA7\u0ABF'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale gu_IN.
+ */
+goog.i18n.CompactNumberFormatSymbols_gu_IN =
+ goog.i18n.CompactNumberFormatSymbols_gu;
+
+
+/**
+ * Compact number formatting symbols for locale haw.
+ */
+goog.i18n.CompactNumberFormatSymbols_haw = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0K'
+ },
+ '10000': {
+ 'other': '00K'
+ },
+ '100000': {
+ 'other': '000K'
+ },
+ '1000000': {
+ 'other': '0M'
+ },
+ '10000000': {
+ 'other': '00M'
+ },
+ '100000000': {
+ 'other': '000M'
+ },
+ '1000000000': {
+ 'other': '0G'
+ },
+ '10000000000': {
+ 'other': '00G'
+ },
+ '100000000000': {
+ 'other': '000G'
+ },
+ '1000000000000': {
+ 'other': '0T'
+ },
+ '10000000000000': {
+ 'other': '00T'
+ },
+ '100000000000000': {
+ 'other': '000T'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale haw_US.
+ */
+goog.i18n.CompactNumberFormatSymbols_haw_US =
+ goog.i18n.CompactNumberFormatSymbols_haw;
+
+
+/**
+ * Compact number formatting symbols for locale he.
+ */
+goog.i18n.CompactNumberFormatSymbols_he = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '\u200F0\u00A0\u05D0\u05DC\u05E3'
+ },
+ '10000': {
+ 'other': '\u200F00\u00A0\u05D0\u05DC\u05E3'
+ },
+ '100000': {
+ 'other': '\u200F000\u00A0\u05D0\u05DC\u05E3'
+ },
+ '1000000': {
+ 'other': '\u200F0\u00A0\u05DE\u05D9\u05DC\u05F3'
+ },
+ '10000000': {
+ 'other': '\u200F00\u00A0\u05DE\u05D9\u05DC\u05F3'
+ },
+ '100000000': {
+ 'other': '\u200F000\u00A0\u05DE\u05D9\u05DC\u05F3'
+ },
+ '1000000000': {
+ 'other': '\u200F0\u00A0\u05DE\u05DC\u05E8\u05D3'
+ },
+ '10000000000': {
+ 'other': '\u200F00\u00A0\u05DE\u05DC\u05E8\u05D3'
+ },
+ '100000000000': {
+ 'other': '\u200F000\u00A0\u05DE\u05DC\u05E8\u05D3'
+ },
+ '1000000000000': {
+ 'other': '\u200F0\u00A0\u05D1\u05D9\u05DC\u05F3'
+ },
+ '10000000000000': {
+ 'other': '\u200F00\u00A0\u05D1\u05D9\u05DC\u05F3'
+ },
+ '100000000000000': {
+ 'other': '\u200F000\u00A0\u05D1\u05D9\u05DC\u05F3'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '\u200F0 \u05D0\u05DC\u05E3'
+ },
+ '10000': {
+ 'other': '\u200F00 \u05D0\u05DC\u05E3'
+ },
+ '100000': {
+ 'other': '\u200F000 \u05D0\u05DC\u05E3'
+ },
+ '1000000': {
+ 'other': '\u200F0 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
+ },
+ '10000000': {
+ 'other': '\u200F00 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
+ },
+ '100000000': {
+ 'other': '\u200F000 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
+ },
+ '1000000000': {
+ 'other': '\u200F0 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
+ },
+ '10000000000': {
+ 'other': '\u200F00 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
+ },
+ '100000000000': {
+ 'other': '\u200F000 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
+ },
+ '1000000000000': {
+ 'other': '\u200F0 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
+ },
+ '10000000000000': {
+ 'other': '\u200F00 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
+ },
+ '100000000000000': {
+ 'other': '\u200F000 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale he_IL.
+ */
+goog.i18n.CompactNumberFormatSymbols_he_IL =
+ goog.i18n.CompactNumberFormatSymbols_he;
+
+
+/**
+ * Compact number formatting symbols for locale hi.
+ */
+goog.i18n.CompactNumberFormatSymbols_hi = {
+ COMPACT_DECIMAL_SHORT_PATTERN: {
+ '1000': {
+ 'other': '0\u00A0\u0939\u091C\u093C\u093E\u0930'
+ },
+ '10000': {
+ 'other': '00\u00A0\u0939\u091C\u093C\u093E\u0930'
+ },
+ '100000': {
+ 'other': '0\u00A0\u0932\u093E\u0916'
+ },
+ '1000000': {
+ 'other': '00\u00A0\u0932\u093E\u0916'
+ },
+ '10000000': {
+ 'other': '0\u00A0\u0915.'
+ },
+ '100000000': {
+ 'other': '00\u00A0\u0915.'
+ },
+ '1000000000': {
+ 'other': '0\u00A0\u0905.'
+ },
+ '10000000000': {
+ 'other': '00\u00A0\u0905.'
+ },
+ '100000000000': {
+ 'other': '0\u00A0\u0916.'
+ },
+ '1000000000000': {
+ 'other': '00\u00A0\u0916.'
+ },
+ '10000000000000': {
+ 'other': '0\u00A0\u0928\u0940\u0932'
+ },
+ '100000000000000': {
+ 'other': '00\u00A0\u0928\u0940\u0932'
+ }
+ },
+ COMPACT_DECIMAL_LONG_PATTERN: {
+ '1000': {
+ 'other': '0 \u0939\u091C\u093C\u093E\u0930'
+ },
+ '10000': {
+ 'other': '00 \u0939\u091C\u093C\u093E\u0930'
+ },
+ '100000': {
+ 'other': '0 \u0932\u093E\u0916'
+ },
+ '1000000': {
+ 'other': '00 \u0932\u093E\u0916'
+ },
+ '10000000': {
+ 'other': '0 \u0915\u0930\u094B\u0921\u093C'
+ },
+ '100000000': {
+ 'other': '00 \u0915\u0930\u094B\u0921\u093C'
+ },
+ '1000000000': {
+ 'other': '0 \u0905\u0930\u092C'
+ },
+ '10000000000': {
+ 'other': '00 \u0905\u0930\u092C'
+ },
+ '100000000000': {
+ 'other': '0 \u0916\u0930\u092C'
+ },
+ '1000000000000': {
+ 'other': '00 \u0916\u0930\u092C'
+ },
+ '10000000000000': {
+ 'other': '000 \u0916\u0930\u092C'
+ },
+ '100000000000000': {
+ 'other': '0000 \u0916\u0930\u092C'
+ }
+ }
+};
+
+
+/**
+ * Compact number formatting symbols for locale hi_IN.
+ */
+goog.i18n.CompactNumberFormatSymbols_hi_IN =
+ goog.i18n.CompactNumberFormatSymbols_hi;
+
+
+/**
+ * Compact number formatting symbols for locale hr.
<TRUNCATED>
[18/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventtype.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventtype.js b/externs/GCL/externs/goog/events/eventtype.js
new file mode 100644
index 0000000..befc372
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventtype.js
@@ -0,0 +1,233 @@
+// 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 Event Types.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.events.EventType');
+
+goog.require('goog.userAgent');
+
+
+/**
+ * Returns a prefixed event name for the current browser.
+ * @param {string} eventName The name of the event.
+ * @return {string} The prefixed event name.
+ * @suppress {missingRequire|missingProvide}
+ * @private
+ */
+goog.events.getVendorPrefixedName_ = function(eventName) {
+ return goog.userAgent.WEBKIT ? 'webkit' + eventName :
+ (goog.userAgent.OPERA ? 'o' + eventName.toLowerCase() :
+ eventName.toLowerCase());
+};
+
+
+/**
+ * Constants for event names.
+ * @enum {string}
+ */
+goog.events.EventType = {
+ // Mouse events
+ CLICK: 'click',
+ RIGHTCLICK: 'rightclick',
+ DBLCLICK: 'dblclick',
+ MOUSEDOWN: 'mousedown',
+ MOUSEUP: 'mouseup',
+ MOUSEOVER: 'mouseover',
+ MOUSEOUT: 'mouseout',
+ MOUSEMOVE: 'mousemove',
+ MOUSEENTER: 'mouseenter',
+ MOUSELEAVE: 'mouseleave',
+ // Select start is non-standard.
+ // See http://msdn.microsoft.com/en-us/library/ie/ms536969(v=vs.85).aspx.
+ SELECTSTART: 'selectstart', // IE, Safari, Chrome
+
+ // Wheel events
+ // http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents
+ WHEEL: 'wheel',
+
+ // Key events
+ KEYPRESS: 'keypress',
+ KEYDOWN: 'keydown',
+ KEYUP: 'keyup',
+
+ // Focus
+ BLUR: 'blur',
+ FOCUS: 'focus',
+ DEACTIVATE: 'deactivate', // IE only
+ // NOTE: The following two events are not stable in cross-browser usage.
+ // WebKit and Opera implement DOMFocusIn/Out.
+ // IE implements focusin/out.
+ // Gecko implements neither see bug at
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=396927.
+ // The DOM Events Level 3 Draft deprecates DOMFocusIn in favor of focusin:
+ // http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
+ // You can use FOCUS in Capture phase until implementations converge.
+ FOCUSIN: goog.userAgent.IE ? 'focusin' : 'DOMFocusIn',
+ FOCUSOUT: goog.userAgent.IE ? 'focusout' : 'DOMFocusOut',
+
+ // Forms
+ CHANGE: 'change',
+ RESET: 'reset',
+ SELECT: 'select',
+ SUBMIT: 'submit',
+ INPUT: 'input',
+ PROPERTYCHANGE: 'propertychange', // IE only
+
+ // Drag and drop
+ DRAGSTART: 'dragstart',
+ DRAG: 'drag',
+ DRAGENTER: 'dragenter',
+ DRAGOVER: 'dragover',
+ DRAGLEAVE: 'dragleave',
+ DROP: 'drop',
+ DRAGEND: 'dragend',
+
+ // Touch events
+ // Note that other touch events exist, but we should follow the W3C list here.
+ // http://www.w3.org/TR/touch-events/#list-of-touchevent-types
+ TOUCHSTART: 'touchstart',
+ TOUCHMOVE: 'touchmove',
+ TOUCHEND: 'touchend',
+ TOUCHCANCEL: 'touchcancel',
+
+ // Misc
+ BEFOREUNLOAD: 'beforeunload',
+ CONSOLEMESSAGE: 'consolemessage',
+ CONTEXTMENU: 'contextmenu',
+ DOMCONTENTLOADED: 'DOMContentLoaded',
+ ERROR: 'error',
+ HELP: 'help',
+ LOAD: 'load',
+ LOSECAPTURE: 'losecapture',
+ ORIENTATIONCHANGE: 'orientationchange',
+ READYSTATECHANGE: 'readystatechange',
+ RESIZE: 'resize',
+ SCROLL: 'scroll',
+ UNLOAD: 'unload',
+
+ // HTML 5 History events
+ // See http://www.w3.org/TR/html5/history.html#event-definitions
+ HASHCHANGE: 'hashchange',
+ PAGEHIDE: 'pagehide',
+ PAGESHOW: 'pageshow',
+ POPSTATE: 'popstate',
+
+ // Copy and Paste
+ // Support is limited. Make sure it works on your favorite browser
+ // before using.
+ // http://www.quirksmode.org/dom/events/cutcopypaste.html
+ COPY: 'copy',
+ PASTE: 'paste',
+ CUT: 'cut',
+ BEFORECOPY: 'beforecopy',
+ BEFORECUT: 'beforecut',
+ BEFOREPASTE: 'beforepaste',
+
+ // HTML5 online/offline events.
+ // http://www.w3.org/TR/offline-webapps/#related
+ ONLINE: 'online',
+ OFFLINE: 'offline',
+
+ // HTML 5 worker events
+ MESSAGE: 'message',
+ CONNECT: 'connect',
+
+ // CSS animation events.
+ /** @suppress {missingRequire} */
+ ANIMATIONSTART: goog.events.getVendorPrefixedName_('AnimationStart'),
+ /** @suppress {missingRequire} */
+ ANIMATIONEND: goog.events.getVendorPrefixedName_('AnimationEnd'),
+ /** @suppress {missingRequire} */
+ ANIMATIONITERATION: goog.events.getVendorPrefixedName_('AnimationIteration'),
+
+ // CSS transition events. Based on the browser support described at:
+ // https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility
+ /** @suppress {missingRequire} */
+ TRANSITIONEND: goog.events.getVendorPrefixedName_('TransitionEnd'),
+
+ // W3C Pointer Events
+ // http://www.w3.org/TR/pointerevents/
+ POINTERDOWN: 'pointerdown',
+ POINTERUP: 'pointerup',
+ POINTERCANCEL: 'pointercancel',
+ POINTERMOVE: 'pointermove',
+ POINTEROVER: 'pointerover',
+ POINTEROUT: 'pointerout',
+ POINTERENTER: 'pointerenter',
+ POINTERLEAVE: 'pointerleave',
+ GOTPOINTERCAPTURE: 'gotpointercapture',
+ LOSTPOINTERCAPTURE: 'lostpointercapture',
+
+ // IE specific events.
+ // See http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx
+ // Note: these events will be supplanted in IE11.
+ MSGESTURECHANGE: 'MSGestureChange',
+ MSGESTUREEND: 'MSGestureEnd',
+ MSGESTUREHOLD: 'MSGestureHold',
+ MSGESTURESTART: 'MSGestureStart',
+ MSGESTURETAP: 'MSGestureTap',
+ MSGOTPOINTERCAPTURE: 'MSGotPointerCapture',
+ MSINERTIASTART: 'MSInertiaStart',
+ MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture',
+ MSPOINTERCANCEL: 'MSPointerCancel',
+ MSPOINTERDOWN: 'MSPointerDown',
+ MSPOINTERENTER: 'MSPointerEnter',
+ MSPOINTERHOVER: 'MSPointerHover',
+ MSPOINTERLEAVE: 'MSPointerLeave',
+ MSPOINTERMOVE: 'MSPointerMove',
+ MSPOINTEROUT: 'MSPointerOut',
+ MSPOINTEROVER: 'MSPointerOver',
+ MSPOINTERUP: 'MSPointerUp',
+
+ // Native IMEs/input tools events.
+ TEXT: 'text',
+ TEXTINPUT: 'textInput',
+ COMPOSITIONSTART: 'compositionstart',
+ COMPOSITIONUPDATE: 'compositionupdate',
+ COMPOSITIONEND: 'compositionend',
+
+ // Webview tag events
+ // See http://developer.chrome.com/dev/apps/webview_tag.html
+ EXIT: 'exit',
+ LOADABORT: 'loadabort',
+ LOADCOMMIT: 'loadcommit',
+ LOADREDIRECT: 'loadredirect',
+ LOADSTART: 'loadstart',
+ LOADSTOP: 'loadstop',
+ RESPONSIVE: 'responsive',
+ SIZECHANGED: 'sizechanged',
+ UNRESPONSIVE: 'unresponsive',
+
+ // HTML5 Page Visibility API. See details at
+ // {@code goog.labs.dom.PageVisibilityMonitor}.
+ VISIBILITYCHANGE: 'visibilitychange',
+
+ // LocalStorage event.
+ STORAGE: 'storage',
+
+ // DOM Level 2 mutation events (deprecated).
+ DOMSUBTREEMODIFIED: 'DOMSubtreeModified',
+ DOMNODEINSERTED: 'DOMNodeInserted',
+ DOMNODEREMOVED: 'DOMNodeRemoved',
+ DOMNODEREMOVEDFROMDOCUMENT: 'DOMNodeRemovedFromDocument',
+ DOMNODEINSERTEDINTODOCUMENT: 'DOMNodeInsertedIntoDocument',
+ DOMATTRMODIFIED: 'DOMAttrModified',
+ DOMCHARACTERDATAMODIFIED: 'DOMCharacterDataModified'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventwrapper.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventwrapper.js b/externs/GCL/externs/goog/events/eventwrapper.js
new file mode 100644
index 0000000..1581774
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventwrapper.js
@@ -0,0 +1,66 @@
+// Copyright 2009 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 goog.events.EventWrapper interface.
+ *
+ * @author eae@google.com (Emil A Eklund)
+ */
+
+goog.provide('goog.events.EventWrapper');
+
+
+
+/**
+ * Interface for event wrappers.
+ * @interface
+ */
+goog.events.EventWrapper = function() {
+};
+
+
+/**
+ * Adds an event listener using the wrapper on a DOM Node or an object that has
+ * implemented {@link goog.events.EventTarget}. A listener can only be added
+ * once to an object.
+ *
+ * @param {goog.events.ListenableType} src The node to listen to events on.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
+ * method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @param {goog.events.EventHandler=} opt_eventHandler Event handler to add
+ * listener to.
+ */
+goog.events.EventWrapper.prototype.listen = function(src, listener, opt_capt,
+ opt_scope, opt_eventHandler) {
+};
+
+
+/**
+ * Removes an event listener added using goog.events.EventWrapper.listen.
+ *
+ * @param {goog.events.ListenableType} src The node to remove listener from.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
+ * method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @param {goog.events.EventHandler=} opt_eventHandler Event handler to remove
+ * listener from.
+ */
+goog.events.EventWrapper.prototype.unlisten = function(src, listener, opt_capt,
+ opt_scope, opt_eventHandler) {
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/filedrophandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/filedrophandler.js b/externs/GCL/externs/goog/events/filedrophandler.js
new file mode 100644
index 0000000..5678fe3
--- /dev/null
+++ b/externs/GCL/externs/goog/events/filedrophandler.js
@@ -0,0 +1,222 @@
+// 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 Provides a files drag and drop event detector. It works on
+ * HTML5 browsers.
+ *
+ * @see ../demos/filedrophandler.html
+ */
+
+goog.provide('goog.events.FileDropHandler');
+goog.provide('goog.events.FileDropHandler.EventType');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.log');
+goog.require('goog.log.Level');
+
+
+
+/**
+ * A files drag and drop event detector. Gets an {@code element} as parameter
+ * and fires {@code goog.events.FileDropHandler.EventType.DROP} event when files
+ * are dropped in the {@code element}.
+ *
+ * @param {Element|Document} element The element or document to listen on.
+ * @param {boolean=} opt_preventDropOutside Whether to prevent a drop on the
+ * area outside the {@code element}. Default false.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.events.FileDropHandler = function(element, opt_preventDropOutside) {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * Handler for drag/drop events.
+ * @type {!goog.events.EventHandler<!goog.events.FileDropHandler>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ var doc = element;
+ if (opt_preventDropOutside) {
+ doc = goog.dom.getOwnerDocument(element);
+ }
+
+ // Add dragenter listener to the owner document of the element.
+ this.eventHandler_.listen(doc,
+ goog.events.EventType.DRAGENTER,
+ this.onDocDragEnter_);
+
+ // Add dragover listener to the owner document of the element only if the
+ // document is not the element itself.
+ if (doc != element) {
+ this.eventHandler_.listen(doc,
+ goog.events.EventType.DRAGOVER,
+ this.onDocDragOver_);
+ }
+
+ // Add dragover and drop listeners to the element.
+ this.eventHandler_.listen(element,
+ goog.events.EventType.DRAGOVER,
+ this.onElemDragOver_);
+ this.eventHandler_.listen(element,
+ goog.events.EventType.DROP,
+ this.onElemDrop_);
+};
+goog.inherits(goog.events.FileDropHandler, goog.events.EventTarget);
+
+
+/**
+ * Whether the drag event contains files. It is initialized only in the
+ * dragenter event. It is used in all the drag events to prevent default actions
+ * only if the drag contains files. Preventing default actions is necessary to
+ * go from dragenter to dragover and from dragover to drop. However we do not
+ * always want to prevent default actions, e.g. when the user drags text or
+ * links on a text area we should not prevent the browser default action that
+ * inserts the text in the text area. It is also necessary to stop propagation
+ * when handling drag events on the element to prevent them from propagating
+ * to the document.
+ * @private
+ * @type {boolean}
+ */
+goog.events.FileDropHandler.prototype.dndContainsFiles_ = false;
+
+
+/**
+ * A logger, used to help us debug the algorithm.
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.events.FileDropHandler.prototype.logger_ =
+ goog.log.getLogger('goog.events.FileDropHandler');
+
+
+/**
+ * The types of events fired by this class.
+ * @enum {string}
+ */
+goog.events.FileDropHandler.EventType = {
+ DROP: goog.events.EventType.DROP
+};
+
+
+/** @override */
+goog.events.FileDropHandler.prototype.disposeInternal = function() {
+ goog.events.FileDropHandler.superClass_.disposeInternal.call(this);
+ this.eventHandler_.dispose();
+};
+
+
+/**
+ * Dispatches the DROP event.
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ * @private
+ */
+goog.events.FileDropHandler.prototype.dispatch_ = function(e) {
+ goog.log.fine(this.logger_, 'Firing DROP event...');
+ var event = new goog.events.BrowserEvent(e.getBrowserEvent());
+ event.type = goog.events.FileDropHandler.EventType.DROP;
+ this.dispatchEvent(event);
+};
+
+
+/**
+ * Handles dragenter on the document.
+ * @param {goog.events.BrowserEvent} e The dragenter event.
+ * @private
+ */
+goog.events.FileDropHandler.prototype.onDocDragEnter_ = function(e) {
+ goog.log.log(this.logger_, goog.log.Level.FINER,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
+ var dt = e.getBrowserEvent().dataTransfer;
+ // Check whether the drag event contains files.
+ this.dndContainsFiles_ = !!(dt &&
+ ((dt.types &&
+ (goog.array.contains(dt.types, 'Files') ||
+ goog.array.contains(dt.types, 'public.file-url'))) ||
+ (dt.files && dt.files.length > 0)));
+ // If it does
+ if (this.dndContainsFiles_) {
+ // Prevent default actions.
+ e.preventDefault();
+ }
+ goog.log.log(this.logger_, goog.log.Level.FINER,
+ 'dndContainsFiles_: ' + this.dndContainsFiles_);
+};
+
+
+/**
+ * Handles dragging something over the document.
+ * @param {goog.events.BrowserEvent} e The dragover event.
+ * @private
+ */
+goog.events.FileDropHandler.prototype.onDocDragOver_ = function(e) {
+ goog.log.log(this.logger_, goog.log.Level.FINEST,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
+ if (this.dndContainsFiles_) {
+ // Prevent default actions.
+ e.preventDefault();
+ // Disable the drop on the document outside the drop zone.
+ var dt = e.getBrowserEvent().dataTransfer;
+ dt.dropEffect = 'none';
+ }
+};
+
+
+/**
+ * Handles dragging something over the element (drop zone).
+ * @param {goog.events.BrowserEvent} e The dragover event.
+ * @private
+ */
+goog.events.FileDropHandler.prototype.onElemDragOver_ = function(e) {
+ goog.log.log(this.logger_, goog.log.Level.FINEST,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
+ if (this.dndContainsFiles_) {
+ // Prevent default actions and stop the event from propagating further to
+ // the document. Both lines are needed! (See comment above).
+ e.preventDefault();
+ e.stopPropagation();
+ // Allow the drop on the drop zone.
+ var dt = e.getBrowserEvent().dataTransfer;
+ dt.effectAllowed = 'all';
+ dt.dropEffect = 'copy';
+ }
+};
+
+
+/**
+ * Handles dropping something onto the element (drop zone).
+ * @param {goog.events.BrowserEvent} e The drop event.
+ * @private
+ */
+goog.events.FileDropHandler.prototype.onElemDrop_ = function(e) {
+ goog.log.log(this.logger_, goog.log.Level.FINER,
+ '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
+ // If the drag and drop event contains files.
+ if (this.dndContainsFiles_) {
+ // Prevent default actions and stop the event from propagating further to
+ // the document. Both lines are needed! (See comment above).
+ e.preventDefault();
+ e.stopPropagation();
+ // Dispatch DROP event.
+ this.dispatch_(e);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/focushandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/focushandler.js b/externs/GCL/externs/goog/events/focushandler.js
new file mode 100644
index 0000000..f4e1000
--- /dev/null
+++ b/externs/GCL/externs/goog/events/focushandler.js
@@ -0,0 +1,107 @@
+// 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 This event handler allows you to catch focusin and focusout
+ * events on descendants. Unlike the "focus" and "blur" events which do not
+ * propagate consistently, and therefore must be added to the element that is
+ * focused, this allows you to attach one listener to an ancester and you will
+ * be notified when the focus state changes of ony of its descendants.
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/focushandler.html
+ */
+
+goog.provide('goog.events.FocusHandler');
+goog.provide('goog.events.FocusHandler.EventType');
+
+goog.require('goog.events');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventTarget');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * This event handler allows you to catch focus events when descendants gain or
+ * loses focus.
+ * @param {Element|Document} element The node to listen on.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.events.FocusHandler = function(element) {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * This is the element that we will listen to the real focus events on.
+ * @type {Element|Document}
+ * @private
+ */
+ this.element_ = element;
+
+ // In IE we use focusin/focusout and in other browsers we use a capturing
+ // listner for focus/blur
+ var typeIn = goog.userAgent.IE ? 'focusin' : 'focus';
+ var typeOut = goog.userAgent.IE ? 'focusout' : 'blur';
+
+ /**
+ * Store the listen key so it easier to unlisten in dispose.
+ * @private
+ * @type {goog.events.Key}
+ */
+ this.listenKeyIn_ =
+ goog.events.listen(this.element_, typeIn, this, !goog.userAgent.IE);
+
+ /**
+ * Store the listen key so it easier to unlisten in dispose.
+ * @private
+ * @type {goog.events.Key}
+ */
+ this.listenKeyOut_ =
+ goog.events.listen(this.element_, typeOut, this, !goog.userAgent.IE);
+};
+goog.inherits(goog.events.FocusHandler, goog.events.EventTarget);
+
+
+/**
+ * Enum type for the events fired by the focus handler
+ * @enum {string}
+ */
+goog.events.FocusHandler.EventType = {
+ FOCUSIN: 'focusin',
+ FOCUSOUT: 'focusout'
+};
+
+
+/**
+ * This handles the underlying events and dispatches a new event.
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ */
+goog.events.FocusHandler.prototype.handleEvent = function(e) {
+ var be = e.getBrowserEvent();
+ var event = new goog.events.BrowserEvent(be);
+ event.type = e.type == 'focusin' || e.type == 'focus' ?
+ goog.events.FocusHandler.EventType.FOCUSIN :
+ goog.events.FocusHandler.EventType.FOCUSOUT;
+ this.dispatchEvent(event);
+};
+
+
+/** @override */
+goog.events.FocusHandler.prototype.disposeInternal = function() {
+ goog.events.FocusHandler.superClass_.disposeInternal.call(this);
+ goog.events.unlistenByKey(this.listenKeyIn_);
+ goog.events.unlistenByKey(this.listenKeyOut_);
+ delete this.element_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/imehandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/imehandler.js b/externs/GCL/externs/goog/events/imehandler.js
new file mode 100644
index 0000000..661f91f
--- /dev/null
+++ b/externs/GCL/externs/goog/events/imehandler.js
@@ -0,0 +1,369 @@
+// 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 Input Method Editors (IMEs) are OS-level widgets that make
+ * it easier to type non-ascii characters on ascii keyboards (in particular,
+ * characters that require more than one keystroke).
+ *
+ * When the user wants to type such a character, a modal menu pops up and
+ * suggests possible "next" characters in the IME character sequence. After
+ * typing N characters, the user hits "enter" to commit the IME to the field.
+ * N differs from language to language.
+ *
+ * This class offers high-level events for how the user is interacting with the
+ * IME in editable regions.
+ *
+ * Known Issues:
+ *
+ * Firefox always fires an extra pair of compositionstart/compositionend events.
+ * We do not normalize for this.
+ *
+ * Opera does not fire any IME events.
+ *
+ * Spurious UPDATE events are common on all browsers.
+ *
+ * We currently do a bad job detecting when the IME closes on IE, and
+ * make a "best effort" guess on when we know it's closed.
+ *
+ * @author nicksantos@google.com (Nick Santos) (Ported to Closure)
+ */
+
+goog.provide('goog.events.ImeHandler');
+goog.provide('goog.events.ImeHandler.Event');
+goog.provide('goog.events.ImeHandler.EventType');
+
+goog.require('goog.events.Event');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Dispatches high-level events for IMEs.
+ * @param {Element} el The element to listen on.
+ * @extends {goog.events.EventTarget}
+ * @constructor
+ * @final
+ */
+goog.events.ImeHandler = function(el) {
+ goog.events.ImeHandler.base(this, 'constructor');
+
+ /**
+ * The element to listen on.
+ * @type {Element}
+ * @private
+ */
+ this.el_ = el;
+
+ /**
+ * Tracks the keyup event only, because it has a different life-cycle from
+ * other events.
+ * @type {goog.events.EventHandler<!goog.events.ImeHandler>}
+ * @private
+ */
+ this.keyUpHandler_ = new goog.events.EventHandler(this);
+
+ /**
+ * Tracks all the browser events.
+ * @type {goog.events.EventHandler<!goog.events.ImeHandler>}
+ * @private
+ */
+ this.handler_ = new goog.events.EventHandler(this);
+
+ if (goog.events.ImeHandler.USES_COMPOSITION_EVENTS) {
+ this.handler_.
+ listen(el, goog.events.EventType.COMPOSITIONSTART,
+ this.handleCompositionStart_).
+ listen(el, goog.events.EventType.COMPOSITIONEND,
+ this.handleCompositionEnd_).
+ listen(el, goog.events.EventType.COMPOSITIONUPDATE,
+ this.handleTextModifyingInput_);
+ }
+
+ this.handler_.
+ listen(el, goog.events.EventType.TEXTINPUT, this.handleTextInput_).
+ listen(el, goog.events.EventType.TEXT, this.handleTextModifyingInput_).
+ listen(el, goog.events.EventType.KEYDOWN, this.handleKeyDown_);
+};
+goog.inherits(goog.events.ImeHandler, goog.events.EventTarget);
+
+
+/**
+ * Event types fired by ImeHandler. These events do not make any guarantees
+ * about whether they were fired before or after the event in question.
+ * @enum {string}
+ */
+goog.events.ImeHandler.EventType = {
+ // After the IME opens.
+ START: 'startIme',
+
+ // An update to the state of the IME. An 'update' does not necessarily mean
+ // that the text contents of the field were modified in any way.
+ UPDATE: 'updateIme',
+
+ // After the IME closes.
+ END: 'endIme'
+};
+
+
+
+/**
+ * An event fired by ImeHandler.
+ * @param {goog.events.ImeHandler.EventType} type The type.
+ * @param {goog.events.BrowserEvent} reason The trigger for this event.
+ * @constructor
+ * @extends {goog.events.Event}
+ * @final
+ */
+goog.events.ImeHandler.Event = function(type, reason) {
+ goog.events.ImeHandler.Event.base(this, 'constructor', type);
+
+ /**
+ * The event that triggered this.
+ * @type {goog.events.BrowserEvent}
+ */
+ this.reason = reason;
+};
+goog.inherits(goog.events.ImeHandler.Event, goog.events.Event);
+
+
+/**
+ * Whether to use the composition events.
+ * @type {boolean}
+ */
+goog.events.ImeHandler.USES_COMPOSITION_EVENTS =
+ goog.userAgent.GECKO ||
+ (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher(532));
+
+
+/**
+ * Stores whether IME mode is active.
+ * @type {boolean}
+ * @private
+ */
+goog.events.ImeHandler.prototype.imeMode_ = false;
+
+
+/**
+ * The keyCode value of the last keyDown event. This value is used for
+ * identiying whether or not a textInput event is sent by an IME.
+ * @type {number}
+ * @private
+ */
+goog.events.ImeHandler.prototype.lastKeyCode_ = 0;
+
+
+/**
+ * @return {boolean} Whether an IME is active.
+ */
+goog.events.ImeHandler.prototype.isImeMode = function() {
+ return this.imeMode_;
+};
+
+
+/**
+ * Handles the compositionstart event.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleCompositionStart_ =
+ function(e) {
+ this.handleImeActivate_(e);
+};
+
+
+/**
+ * Handles the compositionend event.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleCompositionEnd_ = function(e) {
+ this.handleImeDeactivate_(e);
+};
+
+
+/**
+ * Handles the compositionupdate and text events.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleTextModifyingInput_ =
+ function(e) {
+ if (this.isImeMode()) {
+ this.processImeComposition_(e);
+ }
+};
+
+
+/**
+ * Handles IME activation.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleImeActivate_ = function(e) {
+ if (this.imeMode_) {
+ return;
+ }
+
+ // Listens for keyup events to handle unexpected IME keydown events on older
+ // versions of webkit.
+ //
+ // In those versions, we currently use textInput events deactivate IME
+ // (see handleTextInput_() for the reason). However,
+ // Safari fires a keydown event (as a result of pressing keys to commit IME
+ // text) with keyCode == WIN_IME after textInput event. This activates IME
+ // mode again unnecessarily. To prevent this problem, listens keyup events
+ // which can use to determine whether IME text has been committed.
+ if (goog.userAgent.WEBKIT &&
+ !goog.events.ImeHandler.USES_COMPOSITION_EVENTS) {
+ this.keyUpHandler_.listen(this.el_,
+ goog.events.EventType.KEYUP, this.handleKeyUpSafari4_);
+ }
+
+ this.imeMode_ = true;
+ this.dispatchEvent(
+ new goog.events.ImeHandler.Event(
+ goog.events.ImeHandler.EventType.START, e));
+};
+
+
+/**
+ * Handles the IME compose changes.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.processImeComposition_ = function(e) {
+ this.dispatchEvent(
+ new goog.events.ImeHandler.Event(
+ goog.events.ImeHandler.EventType.UPDATE, e));
+};
+
+
+/**
+ * Handles IME deactivation.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleImeDeactivate_ = function(e) {
+ this.imeMode_ = false;
+ this.keyUpHandler_.removeAll();
+ this.dispatchEvent(
+ new goog.events.ImeHandler.Event(
+ goog.events.ImeHandler.EventType.END, e));
+};
+
+
+/**
+ * Handles a key down event.
+ * @param {!goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleKeyDown_ = function(e) {
+ // Firefox and Chrome have a separate event for IME composition ('text'
+ // and 'compositionupdate', respectively), other browsers do not.
+ if (!goog.events.ImeHandler.USES_COMPOSITION_EVENTS) {
+ var imeMode = this.isImeMode();
+ // If we're in IE and we detect an IME input on keyDown then activate
+ // the IME, otherwise if the imeMode was previously active, deactivate.
+ if (!imeMode && e.keyCode == goog.events.KeyCodes.WIN_IME) {
+ this.handleImeActivate_(e);
+ } else if (imeMode && e.keyCode != goog.events.KeyCodes.WIN_IME) {
+ if (goog.events.ImeHandler.isImeDeactivateKeyEvent_(e)) {
+ this.handleImeDeactivate_(e);
+ }
+ } else if (imeMode) {
+ this.processImeComposition_(e);
+ }
+ }
+
+ // Safari on Mac doesn't send IME events in the right order so that we must
+ // ignore some modifier key events to insert IME text correctly.
+ if (goog.events.ImeHandler.isImeDeactivateKeyEvent_(e)) {
+ this.lastKeyCode_ = e.keyCode;
+ }
+};
+
+
+/**
+ * Handles a textInput event.
+ * @param {!goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleTextInput_ = function(e) {
+ // Some WebKit-based browsers including Safari 4 don't send composition
+ // events. So, we turn down IME mode when it's still there.
+ if (!goog.events.ImeHandler.USES_COMPOSITION_EVENTS &&
+ goog.userAgent.WEBKIT &&
+ this.lastKeyCode_ == goog.events.KeyCodes.WIN_IME &&
+ this.isImeMode()) {
+ this.handleImeDeactivate_(e);
+ }
+};
+
+
+/**
+ * Handles the key up event for any IME activity. This handler is just used to
+ * prevent activating IME unnecessary in Safari at this time.
+ * @param {!goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.events.ImeHandler.prototype.handleKeyUpSafari4_ = function(e) {
+ if (this.isImeMode()) {
+ switch (e.keyCode) {
+ // These keyup events indicates that IME text has been committed or
+ // cancelled. We should turn off IME mode when these keyup events
+ // received.
+ case goog.events.KeyCodes.ENTER:
+ case goog.events.KeyCodes.TAB:
+ case goog.events.KeyCodes.ESC:
+ this.handleImeDeactivate_(e);
+ break;
+ }
+ }
+};
+
+
+/**
+ * Returns whether the given event should be treated as an IME
+ * deactivation trigger.
+ * @param {!goog.events.Event} e The event.
+ * @return {boolean} Whether the given event is an IME deactivate trigger.
+ * @private
+ */
+goog.events.ImeHandler.isImeDeactivateKeyEvent_ = function(e) {
+ // Which key events involve IME deactivation depends on the user's
+ // environment (i.e. browsers, platforms, and IMEs). Usually Shift key
+ // and Ctrl key does not involve IME deactivation, so we currently assume
+ // that these keys are not IME deactivation trigger.
+ switch (e.keyCode) {
+ case goog.events.KeyCodes.SHIFT:
+ case goog.events.KeyCodes.CTRL:
+ return false;
+ default:
+ return true;
+ }
+};
+
+
+/** @override */
+goog.events.ImeHandler.prototype.disposeInternal = function() {
+ this.handler_.dispose();
+ this.keyUpHandler_.dispose();
+ this.el_ = null;
+ goog.events.ImeHandler.base(this, 'disposeInternal');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/inputhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/inputhandler.js b/externs/GCL/externs/goog/events/inputhandler.js
new file mode 100644
index 0000000..b4d8740
--- /dev/null
+++ b/externs/GCL/externs/goog/events/inputhandler.js
@@ -0,0 +1,212 @@
+// 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 An object that encapsulates text changed events for textareas
+ * and input element of type text and password. The event occurs after the value
+ * has been changed. The event does not occur if value was changed
+ * programmatically.<br>
+ * <br>
+ * Note: this does not guarantee the correctness of {@code keyCode} or
+ * {@code charCode}, or attempt to unify them across browsers. See
+ * {@code goog.events.KeyHandler} for that functionality<br>
+ * <br>
+ * Known issues:
+ * <ul>
+ * <li>IE doesn't have native support for input event. WebKit before version 531
+ * doesn't have support for textareas. For those browsers an emulation mode
+ * based on key, clipboard and drop events is used. Thus this event won't
+ * trigger in emulation mode if text was modified by context menu commands
+ * such as 'Undo' and 'Delete'.
+ * </ul>
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/inputhandler.html
+ */
+
+goog.provide('goog.events.InputHandler');
+goog.provide('goog.events.InputHandler.EventType');
+
+goog.require('goog.Timer');
+goog.require('goog.dom.TagName');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * This event handler will dispatch events when the user types into a text
+ * input, password input or a textarea
+ * @param {Element} element The element that you want to listen for input
+ * events on.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.events.InputHandler = function(element) {
+ goog.events.InputHandler.base(this, 'constructor');
+
+ /**
+ * Id of a timer used to postpone firing input event in emulation mode.
+ * @type {?number}
+ * @private
+ */
+ this.timer_ = null;
+
+ /**
+ * The element that you want to listen for input events on.
+ * @type {Element}
+ * @private
+ */
+ this.element_ = element;
+
+ // Determine whether input event should be emulated.
+ // IE8 doesn't support input events. We could use property change events but
+ // they are broken in many ways:
+ // - Fire even if value was changed programmatically.
+ // - Aren't always delivered. For example, if you change value or even width
+ // of input programmatically, next value change made by user won't fire an
+ // event.
+ // IE9 supports input events when characters are inserted, but not deleted.
+ // WebKit before version 531 did not support input events for textareas.
+ var emulateInputEvents = goog.userAgent.IE ||
+ (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('531') &&
+ element.tagName == goog.dom.TagName.TEXTAREA);
+
+ /**
+ * @type {goog.events.EventHandler<!goog.events.InputHandler>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ // Even if input event emulation is enabled, still listen for input events
+ // since they may be partially supported by the browser (such as IE9).
+ // If the input event does fire, we will be able to dispatch synchronously.
+ // (InputHandler events being asynchronous for IE is a common issue for
+ // cases like auto-grow textareas where they result in a quick flash of
+ // scrollbars between the textarea content growing and it being resized to
+ // fit.)
+ this.eventHandler_.listen(
+ this.element_,
+ emulateInputEvents ?
+ ['keydown', 'paste', 'cut', 'drop', 'input'] :
+ 'input',
+ this);
+};
+goog.inherits(goog.events.InputHandler, goog.events.EventTarget);
+
+
+/**
+ * Enum type for the events fired by the input handler
+ * @enum {string}
+ */
+goog.events.InputHandler.EventType = {
+ INPUT: 'input'
+};
+
+
+/**
+ * This handles the underlying events and dispatches a new event as needed.
+ * @param {goog.events.BrowserEvent} e The underlying browser event.
+ */
+goog.events.InputHandler.prototype.handleEvent = function(e) {
+ if (e.type == 'input') {
+ // http://stackoverflow.com/questions/18389732/changing-placeholder-triggers-input-event-in-ie-10
+ // IE 10+ fires an input event when there are inputs with placeholders.
+ // It fires the event with keycode 0, so if we detect it we don't
+ // propagate the input event.
+ if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher(10) &&
+ e.keyCode == 0 && e.charCode == 0) {
+ return;
+ }
+ // This event happens after all the other events we listen to, so cancel
+ // an asynchronous event dispatch if we have it queued up. Otherwise, we
+ // will end up firing an extra event.
+ this.cancelTimerIfSet_();
+
+ this.dispatchEvent(this.createInputEvent_(e));
+ } else {
+ // Filter out key events that don't modify text.
+ if (e.type == 'keydown' &&
+ !goog.events.KeyCodes.isTextModifyingKeyEvent(e)) {
+ return;
+ }
+
+ // It is still possible that pressed key won't modify the value of an
+ // element. Storing old value will help us to detect modification but is
+ // also a little bit dangerous. If value is changed programmatically in
+ // another key down handler, we will detect it as user-initiated change.
+ var valueBeforeKey = e.type == 'keydown' ? this.element_.value : null;
+
+ // In IE on XP, IME the element's value has already changed when we get
+ // keydown events when the user is using an IME. In this case, we can't
+ // check the current value normally, so we assume that it's a modifying key
+ // event. This means that ENTER when used to commit will fire a spurious
+ // input event, but it's better to have a false positive than let some input
+ // slip through the cracks.
+ if (goog.userAgent.IE && e.keyCode == goog.events.KeyCodes.WIN_IME) {
+ valueBeforeKey = null;
+ }
+
+ // Create an input event now, because when we fire it on timer, the
+ // underlying event will already be disposed.
+ var inputEvent = this.createInputEvent_(e);
+
+ // Since key down, paste, cut and drop events are fired before actual value
+ // of the element has changed, we need to postpone dispatching input event
+ // until value is updated.
+ this.cancelTimerIfSet_();
+ this.timer_ = goog.Timer.callOnce(function() {
+ this.timer_ = null;
+ if (this.element_.value != valueBeforeKey) {
+ this.dispatchEvent(inputEvent);
+ }
+ }, 0, this);
+ }
+};
+
+
+/**
+ * Cancels timer if it is set, does nothing otherwise.
+ * @private
+ */
+goog.events.InputHandler.prototype.cancelTimerIfSet_ = function() {
+ if (this.timer_ != null) {
+ goog.Timer.clear(this.timer_);
+ this.timer_ = null;
+ }
+};
+
+
+/**
+ * Creates an input event from the browser event.
+ * @param {goog.events.BrowserEvent} be A browser event.
+ * @return {!goog.events.BrowserEvent} An input event.
+ * @private
+ */
+goog.events.InputHandler.prototype.createInputEvent_ = function(be) {
+ var e = new goog.events.BrowserEvent(be.getBrowserEvent());
+ e.type = goog.events.InputHandler.EventType.INPUT;
+ return e;
+};
+
+
+/** @override */
+goog.events.InputHandler.prototype.disposeInternal = function() {
+ goog.events.InputHandler.base(this, 'disposeInternal');
+ this.eventHandler_.dispose();
+ this.cancelTimerIfSet_();
+ delete this.element_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/keycodes.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/keycodes.js b/externs/GCL/externs/goog/events/keycodes.js
new file mode 100644
index 0000000..ec269ae
--- /dev/null
+++ b/externs/GCL/externs/goog/events/keycodes.js
@@ -0,0 +1,420 @@
+// 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 Constant declarations for common key codes.
+ *
+ * @author eae@google.com (Emil A Eklund)
+ * @see ../demos/keyhandler.html
+ */
+
+goog.provide('goog.events.KeyCodes');
+
+goog.require('goog.userAgent');
+
+
+/**
+ * Key codes for common characters.
+ *
+ * This list is not localized and therefore some of the key codes are not
+ * correct for non US keyboard layouts. See comments below.
+ *
+ * @enum {number}
+ */
+goog.events.KeyCodes = {
+ WIN_KEY_FF_LINUX: 0,
+ MAC_ENTER: 3,
+ BACKSPACE: 8,
+ TAB: 9,
+ NUM_CENTER: 12, // NUMLOCK on FF/Safari Mac
+ ENTER: 13,
+ SHIFT: 16,
+ CTRL: 17,
+ ALT: 18,
+ PAUSE: 19,
+ CAPS_LOCK: 20,
+ ESC: 27,
+ SPACE: 32,
+ PAGE_UP: 33, // also NUM_NORTH_EAST
+ PAGE_DOWN: 34, // also NUM_SOUTH_EAST
+ END: 35, // also NUM_SOUTH_WEST
+ HOME: 36, // also NUM_NORTH_WEST
+ LEFT: 37, // also NUM_WEST
+ UP: 38, // also NUM_NORTH
+ RIGHT: 39, // also NUM_EAST
+ DOWN: 40, // also NUM_SOUTH
+ PRINT_SCREEN: 44,
+ INSERT: 45, // also NUM_INSERT
+ DELETE: 46, // also NUM_DELETE
+ ZERO: 48,
+ ONE: 49,
+ TWO: 50,
+ THREE: 51,
+ FOUR: 52,
+ FIVE: 53,
+ SIX: 54,
+ SEVEN: 55,
+ EIGHT: 56,
+ NINE: 57,
+ FF_SEMICOLON: 59, // Firefox (Gecko) fires this for semicolon instead of 186
+ FF_EQUALS: 61, // Firefox (Gecko) fires this for equals instead of 187
+ FF_DASH: 173, // Firefox (Gecko) fires this for dash instead of 189
+ QUESTION_MARK: 63, // needs localization
+ A: 65,
+ B: 66,
+ C: 67,
+ D: 68,
+ E: 69,
+ F: 70,
+ G: 71,
+ H: 72,
+ I: 73,
+ J: 74,
+ K: 75,
+ L: 76,
+ M: 77,
+ N: 78,
+ O: 79,
+ P: 80,
+ Q: 81,
+ R: 82,
+ S: 83,
+ T: 84,
+ U: 85,
+ V: 86,
+ W: 87,
+ X: 88,
+ Y: 89,
+ Z: 90,
+ META: 91, // WIN_KEY_LEFT
+ WIN_KEY_RIGHT: 92,
+ CONTEXT_MENU: 93,
+ NUM_ZERO: 96,
+ NUM_ONE: 97,
+ NUM_TWO: 98,
+ NUM_THREE: 99,
+ NUM_FOUR: 100,
+ NUM_FIVE: 101,
+ NUM_SIX: 102,
+ NUM_SEVEN: 103,
+ NUM_EIGHT: 104,
+ NUM_NINE: 105,
+ NUM_MULTIPLY: 106,
+ NUM_PLUS: 107,
+ NUM_MINUS: 109,
+ NUM_PERIOD: 110,
+ NUM_DIVISION: 111,
+ F1: 112,
+ F2: 113,
+ F3: 114,
+ F4: 115,
+ F5: 116,
+ F6: 117,
+ F7: 118,
+ F8: 119,
+ F9: 120,
+ F10: 121,
+ F11: 122,
+ F12: 123,
+ NUMLOCK: 144,
+ SCROLL_LOCK: 145,
+
+ // OS-specific media keys like volume controls and browser controls.
+ FIRST_MEDIA_KEY: 166,
+ LAST_MEDIA_KEY: 183,
+
+ SEMICOLON: 186, // needs localization
+ DASH: 189, // needs localization
+ EQUALS: 187, // needs localization
+ COMMA: 188, // needs localization
+ PERIOD: 190, // needs localization
+ SLASH: 191, // needs localization
+ APOSTROPHE: 192, // needs localization
+ TILDE: 192, // needs localization
+ SINGLE_QUOTE: 222, // needs localization
+ OPEN_SQUARE_BRACKET: 219, // needs localization
+ BACKSLASH: 220, // needs localization
+ CLOSE_SQUARE_BRACKET: 221, // needs localization
+ WIN_KEY: 224,
+ MAC_FF_META: 224, // Firefox (Gecko) fires this for the meta key instead of 91
+ MAC_WK_CMD_LEFT: 91, // WebKit Left Command key fired, same as META
+ MAC_WK_CMD_RIGHT: 93, // WebKit Right Command key fired, different from META
+ WIN_IME: 229,
+
+ // "Reserved for future use". Some programs (e.g. the SlingPlayer 2.4 ActiveX
+ // control) fire this as a hacky way to disable screensavers.
+ VK_NONAME: 252,
+
+ // We've seen users whose machines fire this keycode at regular one
+ // second intervals. The common thread among these users is that
+ // they're all using Dell Inspiron laptops, so we suspect that this
+ // indicates a hardware/bios problem.
+ // http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx
+ PHANTOM: 255
+};
+
+
+/**
+ * Returns true if the event contains a text modifying key.
+ * @param {goog.events.BrowserEvent} e A key event.
+ * @return {boolean} Whether it's a text modifying key.
+ */
+goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) {
+ if (e.altKey && !e.ctrlKey ||
+ e.metaKey ||
+ // Function keys don't generate text
+ e.keyCode >= goog.events.KeyCodes.F1 &&
+ e.keyCode <= goog.events.KeyCodes.F12) {
+ return false;
+ }
+
+ // The following keys are quite harmless, even in combination with
+ // CTRL, ALT or SHIFT.
+ switch (e.keyCode) {
+ case goog.events.KeyCodes.ALT:
+ case goog.events.KeyCodes.CAPS_LOCK:
+ case goog.events.KeyCodes.CONTEXT_MENU:
+ case goog.events.KeyCodes.CTRL:
+ case goog.events.KeyCodes.DOWN:
+ case goog.events.KeyCodes.END:
+ case goog.events.KeyCodes.ESC:
+ case goog.events.KeyCodes.HOME:
+ case goog.events.KeyCodes.INSERT:
+ case goog.events.KeyCodes.LEFT:
+ case goog.events.KeyCodes.MAC_FF_META:
+ case goog.events.KeyCodes.META:
+ case goog.events.KeyCodes.NUMLOCK:
+ case goog.events.KeyCodes.NUM_CENTER:
+ case goog.events.KeyCodes.PAGE_DOWN:
+ case goog.events.KeyCodes.PAGE_UP:
+ case goog.events.KeyCodes.PAUSE:
+ case goog.events.KeyCodes.PHANTOM:
+ case goog.events.KeyCodes.PRINT_SCREEN:
+ case goog.events.KeyCodes.RIGHT:
+ case goog.events.KeyCodes.SCROLL_LOCK:
+ case goog.events.KeyCodes.SHIFT:
+ case goog.events.KeyCodes.UP:
+ case goog.events.KeyCodes.VK_NONAME:
+ case goog.events.KeyCodes.WIN_KEY:
+ case goog.events.KeyCodes.WIN_KEY_RIGHT:
+ return false;
+ case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
+ return !goog.userAgent.GECKO;
+ default:
+ return e.keyCode < goog.events.KeyCodes.FIRST_MEDIA_KEY ||
+ e.keyCode > goog.events.KeyCodes.LAST_MEDIA_KEY;
+ }
+};
+
+
+/**
+ * Returns true if the key fires a keypress event in the current browser.
+ *
+ * Accoridng to MSDN [1] IE only fires keypress events for the following keys:
+ * - Letters: A - Z (uppercase and lowercase)
+ * - Numerals: 0 - 9
+ * - Symbols: ! @ # $ % ^ & * ( ) _ - + = < [ ] { } , . / ? \ | ' ` " ~
+ * - System: ESC, SPACEBAR, ENTER
+ *
+ * That's not entirely correct though, for instance there's no distinction
+ * between upper and lower case letters.
+ *
+ * [1] http://msdn2.microsoft.com/en-us/library/ms536939(VS.85).aspx)
+ *
+ * Safari is similar to IE, but does not fire keypress for ESC.
+ *
+ * Additionally, IE6 does not fire keydown or keypress events for letters when
+ * the control or alt keys are held down and the shift key is not. IE7 does
+ * fire keydown in these cases, though, but not keypress.
+ *
+ * @param {number} keyCode A key code.
+ * @param {number=} opt_heldKeyCode Key code of a currently-held key.
+ * @param {boolean=} opt_shiftKey Whether the shift key is held down.
+ * @param {boolean=} opt_ctrlKey Whether the control key is held down.
+ * @param {boolean=} opt_altKey Whether the alt key is held down.
+ * @return {boolean} Whether it's a key that fires a keypress event.
+ */
+goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode,
+ opt_shiftKey, opt_ctrlKey, opt_altKey) {
+ if (!goog.userAgent.IE &&
+ !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) {
+ return true;
+ }
+
+ if (goog.userAgent.MAC && opt_altKey) {
+ return goog.events.KeyCodes.isCharacterKey(keyCode);
+ }
+
+ // Alt but not AltGr which is represented as Alt+Ctrl.
+ if (opt_altKey && !opt_ctrlKey) {
+ return false;
+ }
+
+ // Saves Ctrl or Alt + key for IE and WebKit 525+, which won't fire keypress.
+ // Non-IE browsers and WebKit prior to 525 won't get this far so no need to
+ // check the user agent.
+ if (goog.isNumber(opt_heldKeyCode)) {
+ opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode);
+ }
+ if (!opt_shiftKey &&
+ (opt_heldKeyCode == goog.events.KeyCodes.CTRL ||
+ opt_heldKeyCode == goog.events.KeyCodes.ALT ||
+ goog.userAgent.MAC &&
+ opt_heldKeyCode == goog.events.KeyCodes.META)) {
+ return false;
+ }
+
+ // Some keys with Ctrl/Shift do not issue keypress in WEBKIT.
+ if (goog.userAgent.WEBKIT && opt_ctrlKey && opt_shiftKey) {
+ switch (keyCode) {
+ case goog.events.KeyCodes.BACKSLASH:
+ case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
+ case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
+ case goog.events.KeyCodes.TILDE:
+ case goog.events.KeyCodes.SEMICOLON:
+ case goog.events.KeyCodes.DASH:
+ case goog.events.KeyCodes.EQUALS:
+ case goog.events.KeyCodes.COMMA:
+ case goog.events.KeyCodes.PERIOD:
+ case goog.events.KeyCodes.SLASH:
+ case goog.events.KeyCodes.APOSTROPHE:
+ case goog.events.KeyCodes.SINGLE_QUOTE:
+ return false;
+ }
+ }
+
+ // When Ctrl+<somekey> is held in IE, it only fires a keypress once, but it
+ // continues to fire keydown events as the event repeats.
+ if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) {
+ return false;
+ }
+
+ switch (keyCode) {
+ case goog.events.KeyCodes.ENTER:
+ return true;
+ case goog.events.KeyCodes.ESC:
+ return !goog.userAgent.WEBKIT;
+ }
+
+ return goog.events.KeyCodes.isCharacterKey(keyCode);
+};
+
+
+/**
+ * Returns true if the key produces a character.
+ * This does not cover characters on non-US keyboards (Russian, Hebrew, etc.).
+ *
+ * @param {number} keyCode A key code.
+ * @return {boolean} Whether it's a character key.
+ */
+goog.events.KeyCodes.isCharacterKey = function(keyCode) {
+ if (keyCode >= goog.events.KeyCodes.ZERO &&
+ keyCode <= goog.events.KeyCodes.NINE) {
+ return true;
+ }
+
+ if (keyCode >= goog.events.KeyCodes.NUM_ZERO &&
+ keyCode <= goog.events.KeyCodes.NUM_MULTIPLY) {
+ return true;
+ }
+
+ if (keyCode >= goog.events.KeyCodes.A &&
+ keyCode <= goog.events.KeyCodes.Z) {
+ return true;
+ }
+
+ // Safari sends zero key code for non-latin characters.
+ if (goog.userAgent.WEBKIT && keyCode == 0) {
+ return true;
+ }
+
+ switch (keyCode) {
+ case goog.events.KeyCodes.SPACE:
+ case goog.events.KeyCodes.QUESTION_MARK:
+ case goog.events.KeyCodes.NUM_PLUS:
+ case goog.events.KeyCodes.NUM_MINUS:
+ case goog.events.KeyCodes.NUM_PERIOD:
+ case goog.events.KeyCodes.NUM_DIVISION:
+ case goog.events.KeyCodes.SEMICOLON:
+ case goog.events.KeyCodes.FF_SEMICOLON:
+ case goog.events.KeyCodes.DASH:
+ case goog.events.KeyCodes.EQUALS:
+ case goog.events.KeyCodes.FF_EQUALS:
+ case goog.events.KeyCodes.COMMA:
+ case goog.events.KeyCodes.PERIOD:
+ case goog.events.KeyCodes.SLASH:
+ case goog.events.KeyCodes.APOSTROPHE:
+ case goog.events.KeyCodes.SINGLE_QUOTE:
+ case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
+ case goog.events.KeyCodes.BACKSLASH:
+ case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
+ return true;
+ default:
+ return false;
+ }
+};
+
+
+/**
+ * Normalizes key codes from OS/Browser-specific value to the general one.
+ * @param {number} keyCode The native key code.
+ * @return {number} The normalized key code.
+ */
+goog.events.KeyCodes.normalizeKeyCode = function(keyCode) {
+ if (goog.userAgent.GECKO) {
+ return goog.events.KeyCodes.normalizeGeckoKeyCode(keyCode);
+ } else if (goog.userAgent.MAC && goog.userAgent.WEBKIT) {
+ return goog.events.KeyCodes.normalizeMacWebKitKeyCode(keyCode);
+ } else {
+ return keyCode;
+ }
+};
+
+
+/**
+ * Normalizes key codes from their Gecko-specific value to the general one.
+ * @param {number} keyCode The native key code.
+ * @return {number} The normalized key code.
+ */
+goog.events.KeyCodes.normalizeGeckoKeyCode = function(keyCode) {
+ switch (keyCode) {
+ case goog.events.KeyCodes.FF_EQUALS:
+ return goog.events.KeyCodes.EQUALS;
+ case goog.events.KeyCodes.FF_SEMICOLON:
+ return goog.events.KeyCodes.SEMICOLON;
+ case goog.events.KeyCodes.FF_DASH:
+ return goog.events.KeyCodes.DASH;
+ case goog.events.KeyCodes.MAC_FF_META:
+ return goog.events.KeyCodes.META;
+ case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
+ return goog.events.KeyCodes.WIN_KEY;
+ default:
+ return keyCode;
+ }
+};
+
+
+/**
+ * Normalizes key codes from their Mac WebKit-specific value to the general one.
+ * @param {number} keyCode The native key code.
+ * @return {number} The normalized key code.
+ */
+goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) {
+ switch (keyCode) {
+ case goog.events.KeyCodes.MAC_WK_CMD_RIGHT: // 93
+ return goog.events.KeyCodes.META; // 91
+ default:
+ return keyCode;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/keyhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/keyhandler.js b/externs/GCL/externs/goog/events/keyhandler.js
new file mode 100644
index 0000000..9f20250
--- /dev/null
+++ b/externs/GCL/externs/goog/events/keyhandler.js
@@ -0,0 +1,556 @@
+// 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 This file contains a class for working with keyboard events
+ * that repeat consistently across browsers and platforms. It also unifies the
+ * key code so that it is the same in all browsers and platforms.
+ *
+ * Different web browsers have very different keyboard event handling. Most
+ * importantly is that only certain browsers repeat keydown events:
+ * IE, Opera, FF/Win32, and Safari 3 repeat keydown events.
+ * FF/Mac and Safari 2 do not.
+ *
+ * For the purposes of this code, "Safari 3" means WebKit 525+, when WebKit
+ * decided that they should try to match IE's key handling behavior.
+ * Safari 3.0.4, which shipped with Leopard (WebKit 523), has the
+ * Safari 2 behavior.
+ *
+ * Firefox, Safari, Opera prevent on keypress
+ *
+ * IE prevents on keydown
+ *
+ * Firefox does not fire keypress for shift, ctrl, alt
+ * Firefox does fire keydown for shift, ctrl, alt, meta
+ * Firefox does not repeat keydown for shift, ctrl, alt, meta
+ *
+ * Firefox does not fire keypress for up and down in an input
+ *
+ * Opera fires keypress for shift, ctrl, alt, meta
+ * Opera does not repeat keypress for shift, ctrl, alt, meta
+ *
+ * Safari 2 and 3 do not fire keypress for shift, ctrl, alt
+ * Safari 2 does not fire keydown for shift, ctrl, alt
+ * Safari 3 *does* fire keydown for shift, ctrl, alt
+ *
+ * IE provides the keycode for keyup/down events and the charcode (in the
+ * keycode field) for keypress.
+ *
+ * Mozilla provides the keycode for keyup/down and the charcode for keypress
+ * unless it's a non text modifying key in which case the keycode is provided.
+ *
+ * Safari 3 provides the keycode and charcode for all events.
+ *
+ * Opera provides the keycode for keyup/down event and either the charcode or
+ * the keycode (in the keycode field) for keypress events.
+ *
+ * Firefox x11 doesn't fire keydown events if a another key is already held down
+ * until the first key is released. This can cause a key event to be fired with
+ * a keyCode for the first key and a charCode for the second key.
+ *
+ * Safari in keypress
+ *
+ * charCode keyCode which
+ * ENTER: 13 13 13
+ * F1: 63236 63236 63236
+ * F8: 63243 63243 63243
+ * ...
+ * p: 112 112 112
+ * P: 80 80 80
+ *
+ * Firefox, keypress:
+ *
+ * charCode keyCode which
+ * ENTER: 0 13 13
+ * F1: 0 112 0
+ * F8: 0 119 0
+ * ...
+ * p: 112 0 112
+ * P: 80 0 80
+ *
+ * Opera, Mac+Win32, keypress:
+ *
+ * charCode keyCode which
+ * ENTER: undefined 13 13
+ * F1: undefined 112 0
+ * F8: undefined 119 0
+ * ...
+ * p: undefined 112 112
+ * P: undefined 80 80
+ *
+ * IE7, keydown
+ *
+ * charCode keyCode which
+ * ENTER: undefined 13 undefined
+ * F1: undefined 112 undefined
+ * F8: undefined 119 undefined
+ * ...
+ * p: undefined 80 undefined
+ * P: undefined 80 undefined
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @author eae@google.com (Emil A Eklund)
+ * @see ../demos/keyhandler.html
+ */
+
+goog.provide('goog.events.KeyEvent');
+goog.provide('goog.events.KeyHandler');
+goog.provide('goog.events.KeyHandler.EventType');
+
+goog.require('goog.events');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A wrapper around an element that you want to listen to keyboard events on.
+ * @param {Element|Document=} opt_element The element or document to listen on.
+ * @param {boolean=} opt_capture Whether to listen for browser events in
+ * capture phase (defaults to false).
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.events.KeyHandler = function(opt_element, opt_capture) {
+ goog.events.EventTarget.call(this);
+
+ if (opt_element) {
+ this.attach(opt_element, opt_capture);
+ }
+};
+goog.inherits(goog.events.KeyHandler, goog.events.EventTarget);
+
+
+/**
+ * This is the element that we will listen to the real keyboard events on.
+ * @type {Element|Document|null}
+ * @private
+ */
+goog.events.KeyHandler.prototype.element_ = null;
+
+
+/**
+ * The key for the key press listener.
+ * @type {goog.events.Key}
+ * @private
+ */
+goog.events.KeyHandler.prototype.keyPressKey_ = null;
+
+
+/**
+ * The key for the key down listener.
+ * @type {goog.events.Key}
+ * @private
+ */
+goog.events.KeyHandler.prototype.keyDownKey_ = null;
+
+
+/**
+ * The key for the key up listener.
+ * @type {goog.events.Key}
+ * @private
+ */
+goog.events.KeyHandler.prototype.keyUpKey_ = null;
+
+
+/**
+ * Used to detect keyboard repeat events.
+ * @private
+ * @type {number}
+ */
+goog.events.KeyHandler.prototype.lastKey_ = -1;
+
+
+/**
+ * Keycode recorded for key down events. As most browsers don't report the
+ * keycode in the key press event we need to record it in the key down phase.
+ * @private
+ * @type {number}
+ */
+goog.events.KeyHandler.prototype.keyCode_ = -1;
+
+
+/**
+ * Alt key recorded for key down events. FF on Mac does not report the alt key
+ * flag in the key press event, we need to record it in the key down phase.
+ * @type {boolean}
+ * @private
+ */
+goog.events.KeyHandler.prototype.altKey_ = false;
+
+
+/**
+ * Enum type for the events fired by the key handler
+ * @enum {string}
+ */
+goog.events.KeyHandler.EventType = {
+ KEY: 'key'
+};
+
+
+/**
+ * An enumeration of key codes that Safari 2 does incorrectly
+ * @type {Object}
+ * @private
+ */
+goog.events.KeyHandler.safariKey_ = {
+ '3': goog.events.KeyCodes.ENTER, // 13
+ '12': goog.events.KeyCodes.NUMLOCK, // 144
+ '63232': goog.events.KeyCodes.UP, // 38
+ '63233': goog.events.KeyCodes.DOWN, // 40
+ '63234': goog.events.KeyCodes.LEFT, // 37
+ '63235': goog.events.KeyCodes.RIGHT, // 39
+ '63236': goog.events.KeyCodes.F1, // 112
+ '63237': goog.events.KeyCodes.F2, // 113
+ '63238': goog.events.KeyCodes.F3, // 114
+ '63239': goog.events.KeyCodes.F4, // 115
+ '63240': goog.events.KeyCodes.F5, // 116
+ '63241': goog.events.KeyCodes.F6, // 117
+ '63242': goog.events.KeyCodes.F7, // 118
+ '63243': goog.events.KeyCodes.F8, // 119
+ '63244': goog.events.KeyCodes.F9, // 120
+ '63245': goog.events.KeyCodes.F10, // 121
+ '63246': goog.events.KeyCodes.F11, // 122
+ '63247': goog.events.KeyCodes.F12, // 123
+ '63248': goog.events.KeyCodes.PRINT_SCREEN, // 44
+ '63272': goog.events.KeyCodes.DELETE, // 46
+ '63273': goog.events.KeyCodes.HOME, // 36
+ '63275': goog.events.KeyCodes.END, // 35
+ '63276': goog.events.KeyCodes.PAGE_UP, // 33
+ '63277': goog.events.KeyCodes.PAGE_DOWN, // 34
+ '63289': goog.events.KeyCodes.NUMLOCK, // 144
+ '63302': goog.events.KeyCodes.INSERT // 45
+};
+
+
+/**
+ * An enumeration of key identifiers currently part of the W3C draft for DOM3
+ * and their mappings to keyCodes.
+ * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set
+ * This is currently supported in Safari and should be platform independent.
+ * @type {Object}
+ * @private
+ */
+goog.events.KeyHandler.keyIdentifier_ = {
+ 'Up': goog.events.KeyCodes.UP, // 38
+ 'Down': goog.events.KeyCodes.DOWN, // 40
+ 'Left': goog.events.KeyCodes.LEFT, // 37
+ 'Right': goog.events.KeyCodes.RIGHT, // 39
+ 'Enter': goog.events.KeyCodes.ENTER, // 13
+ 'F1': goog.events.KeyCodes.F1, // 112
+ 'F2': goog.events.KeyCodes.F2, // 113
+ 'F3': goog.events.KeyCodes.F3, // 114
+ 'F4': goog.events.KeyCodes.F4, // 115
+ 'F5': goog.events.KeyCodes.F5, // 116
+ 'F6': goog.events.KeyCodes.F6, // 117
+ 'F7': goog.events.KeyCodes.F7, // 118
+ 'F8': goog.events.KeyCodes.F8, // 119
+ 'F9': goog.events.KeyCodes.F9, // 120
+ 'F10': goog.events.KeyCodes.F10, // 121
+ 'F11': goog.events.KeyCodes.F11, // 122
+ 'F12': goog.events.KeyCodes.F12, // 123
+ 'U+007F': goog.events.KeyCodes.DELETE, // 46
+ 'Home': goog.events.KeyCodes.HOME, // 36
+ 'End': goog.events.KeyCodes.END, // 35
+ 'PageUp': goog.events.KeyCodes.PAGE_UP, // 33
+ 'PageDown': goog.events.KeyCodes.PAGE_DOWN, // 34
+ 'Insert': goog.events.KeyCodes.INSERT // 45
+};
+
+
+/**
+ * If true, the KeyEvent fires on keydown. Otherwise, it fires on keypress.
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.events.KeyHandler.USES_KEYDOWN_ = goog.userAgent.IE ||
+ goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525');
+
+
+/**
+ * If true, the alt key flag is saved during the key down and reused when
+ * handling the key press. FF on Mac does not set the alt flag in the key press
+ * event.
+ * @type {boolean}
+ * @private
+ */
+goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_ = goog.userAgent.MAC &&
+ goog.userAgent.GECKO;
+
+
+/**
+ * Records the keycode for browsers that only returns the keycode for key up/
+ * down events. For browser/key combinations that doesn't trigger a key pressed
+ * event it also fires the patched key event.
+ * @param {goog.events.BrowserEvent} e The key down event.
+ * @private
+ */
+goog.events.KeyHandler.prototype.handleKeyDown_ = function(e) {
+ // Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window
+ // before we've caught a key-up event. If the last-key was one of these we
+ // reset the state.
+ if (goog.userAgent.WEBKIT) {
+ if (this.lastKey_ == goog.events.KeyCodes.CTRL && !e.ctrlKey ||
+ this.lastKey_ == goog.events.KeyCodes.ALT && !e.altKey ||
+ goog.userAgent.MAC &&
+ this.lastKey_ == goog.events.KeyCodes.META && !e.metaKey) {
+ this.lastKey_ = -1;
+ this.keyCode_ = -1;
+ }
+ }
+
+ if (this.lastKey_ == -1) {
+ if (e.ctrlKey && e.keyCode != goog.events.KeyCodes.CTRL) {
+ this.lastKey_ = goog.events.KeyCodes.CTRL;
+ } else if (e.altKey && e.keyCode != goog.events.KeyCodes.ALT) {
+ this.lastKey_ = goog.events.KeyCodes.ALT;
+ } else if (e.metaKey && e.keyCode != goog.events.KeyCodes.META) {
+ this.lastKey_ = goog.events.KeyCodes.META;
+ }
+ }
+
+ if (goog.events.KeyHandler.USES_KEYDOWN_ &&
+ !goog.events.KeyCodes.firesKeyPressEvent(e.keyCode,
+ this.lastKey_, e.shiftKey, e.ctrlKey, e.altKey)) {
+ this.handleEvent(e);
+ } else {
+ this.keyCode_ = goog.events.KeyCodes.normalizeKeyCode(e.keyCode);
+ if (goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_) {
+ this.altKey_ = e.altKey;
+ }
+ }
+};
+
+
+/**
+ * Resets the stored previous values. Needed to be called for webkit which will
+ * not generate a key up for meta key operations. This should only be called
+ * when having finished with repeat key possiblities.
+ */
+goog.events.KeyHandler.prototype.resetState = function() {
+ this.lastKey_ = -1;
+ this.keyCode_ = -1;
+};
+
+
+/**
+ * Clears the stored previous key value, resetting the key repeat status. Uses
+ * -1 because the Safari 3 Windows beta reports 0 for certain keys (like Home
+ * and End.)
+ * @param {goog.events.BrowserEvent} e The keyup event.
+ * @private
+ */
+goog.events.KeyHandler.prototype.handleKeyup_ = function(e) {
+ this.resetState();
+ this.altKey_ = e.altKey;
+};
+
+
+/**
+ * Handles the events on the element.
+ * @param {goog.events.BrowserEvent} e The keyboard event sent from the
+ * browser.
+ */
+goog.events.KeyHandler.prototype.handleEvent = function(e) {
+ var be = e.getBrowserEvent();
+ var keyCode, charCode;
+ var altKey = be.altKey;
+
+ // IE reports the character code in the keyCode field for keypress events.
+ // There are two exceptions however, Enter and Escape.
+ if (goog.userAgent.IE && e.type == goog.events.EventType.KEYPRESS) {
+ keyCode = this.keyCode_;
+ charCode = keyCode != goog.events.KeyCodes.ENTER &&
+ keyCode != goog.events.KeyCodes.ESC ?
+ be.keyCode : 0;
+
+ // Safari reports the character code in the keyCode field for keypress
+ // events but also has a charCode field.
+ } else if (goog.userAgent.WEBKIT &&
+ e.type == goog.events.EventType.KEYPRESS) {
+ keyCode = this.keyCode_;
+ charCode = be.charCode >= 0 && be.charCode < 63232 &&
+ goog.events.KeyCodes.isCharacterKey(keyCode) ?
+ be.charCode : 0;
+
+ // Opera reports the keycode or the character code in the keyCode field.
+ } else if (goog.userAgent.OPERA && !goog.userAgent.WEBKIT) {
+ keyCode = this.keyCode_;
+ charCode = goog.events.KeyCodes.isCharacterKey(keyCode) ?
+ be.keyCode : 0;
+
+ // Mozilla reports the character code in the charCode field.
+ } else {
+ keyCode = be.keyCode || this.keyCode_;
+ charCode = be.charCode || 0;
+ if (goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_) {
+ altKey = this.altKey_;
+ }
+ // On the Mac, shift-/ triggers a question mark char code and no key code
+ // (normalized to WIN_KEY), so we synthesize the latter.
+ if (goog.userAgent.MAC &&
+ charCode == goog.events.KeyCodes.QUESTION_MARK &&
+ keyCode == goog.events.KeyCodes.WIN_KEY) {
+ keyCode = goog.events.KeyCodes.SLASH;
+ }
+ }
+
+ keyCode = goog.events.KeyCodes.normalizeKeyCode(keyCode);
+ var key = keyCode;
+ var keyIdentifier = be.keyIdentifier;
+
+ // Correct the key value for certain browser-specific quirks.
+ if (keyCode) {
+ if (keyCode >= 63232 && keyCode in goog.events.KeyHandler.safariKey_) {
+ // NOTE(nicksantos): Safari 3 has fixed this problem,
+ // this is only needed for Safari 2.
+ key = goog.events.KeyHandler.safariKey_[keyCode];
+ } else {
+
+ // Safari returns 25 for Shift+Tab instead of 9.
+ if (keyCode == 25 && e.shiftKey) {
+ key = 9;
+ }
+ }
+ } else if (keyIdentifier &&
+ keyIdentifier in goog.events.KeyHandler.keyIdentifier_) {
+ // This is needed for Safari Windows because it currently doesn't give a
+ // keyCode/which for non printable keys.
+ key = goog.events.KeyHandler.keyIdentifier_[keyIdentifier];
+ }
+
+ // If we get the same keycode as a keydown/keypress without having seen a
+ // keyup event, then this event was caused by key repeat.
+ var repeat = key == this.lastKey_;
+ this.lastKey_ = key;
+
+ var event = new goog.events.KeyEvent(key, charCode, repeat, be);
+ event.altKey = altKey;
+ this.dispatchEvent(event);
+};
+
+
+/**
+ * Returns the element listened on for the real keyboard events.
+ * @return {Element|Document|null} The element listened on for the real
+ * keyboard events.
+ */
+goog.events.KeyHandler.prototype.getElement = function() {
+ return this.element_;
+};
+
+
+/**
+ * Adds the proper key event listeners to the element.
+ * @param {Element|Document} element The element to listen on.
+ * @param {boolean=} opt_capture Whether to listen for browser events in
+ * capture phase (defaults to false).
+ */
+goog.events.KeyHandler.prototype.attach = function(element, opt_capture) {
+ if (this.keyUpKey_) {
+ this.detach();
+ }
+
+ this.element_ = element;
+
+ this.keyPressKey_ = goog.events.listen(this.element_,
+ goog.events.EventType.KEYPRESS,
+ this,
+ opt_capture);
+
+ // Most browsers (Safari 2 being the notable exception) doesn't include the
+ // keyCode in keypress events (IE has the char code in the keyCode field and
+ // Mozilla only included the keyCode if there's no charCode). Thus we have to
+ // listen for keydown to capture the keycode.
+ this.keyDownKey_ = goog.events.listen(this.element_,
+ goog.events.EventType.KEYDOWN,
+ this.handleKeyDown_,
+ opt_capture,
+ this);
+
+
+ this.keyUpKey_ = goog.events.listen(this.element_,
+ goog.events.EventType.KEYUP,
+ this.handleKeyup_,
+ opt_capture,
+ this);
+};
+
+
+/**
+ * Removes the listeners that may exist.
+ */
+goog.events.KeyHandler.prototype.detach = function() {
+ if (this.keyPressKey_) {
+ goog.events.unlistenByKey(this.keyPressKey_);
+ goog.events.unlistenByKey(this.keyDownKey_);
+ goog.events.unlistenByKey(this.keyUpKey_);
+ this.keyPressKey_ = null;
+ this.keyDownKey_ = null;
+ this.keyUpKey_ = null;
+ }
+ this.element_ = null;
+ this.lastKey_ = -1;
+ this.keyCode_ = -1;
+};
+
+
+/** @override */
+goog.events.KeyHandler.prototype.disposeInternal = function() {
+ goog.events.KeyHandler.superClass_.disposeInternal.call(this);
+ this.detach();
+};
+
+
+
+/**
+ * This class is used for the goog.events.KeyHandler.EventType.KEY event and
+ * it overrides the key code with the fixed key code.
+ * @param {number} keyCode The adjusted key code.
+ * @param {number} charCode The unicode character code.
+ * @param {boolean} repeat Whether this event was generated by keyboard repeat.
+ * @param {Event} browserEvent Browser event object.
+ * @constructor
+ * @extends {goog.events.BrowserEvent}
+ * @final
+ */
+goog.events.KeyEvent = function(keyCode, charCode, repeat, browserEvent) {
+ goog.events.BrowserEvent.call(this, browserEvent);
+ this.type = goog.events.KeyHandler.EventType.KEY;
+
+ /**
+ * Keycode of key press.
+ * @type {number}
+ */
+ this.keyCode = keyCode;
+
+ /**
+ * Unicode character code.
+ * @type {number}
+ */
+ this.charCode = charCode;
+
+ /**
+ * True if this event was generated by keyboard auto-repeat (i.e., the user is
+ * holding the key down.)
+ * @type {boolean}
+ */
+ this.repeat = repeat;
+};
+goog.inherits(goog.events.KeyEvent, goog.events.BrowserEvent);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/keynames.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/keynames.js b/externs/GCL/externs/goog/events/keynames.js
new file mode 100644
index 0000000..b8e36af
--- /dev/null
+++ b/externs/GCL/externs/goog/events/keynames.js
@@ -0,0 +1,139 @@
+// 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 Constant declarations for common key codes.
+ *
+ * @author eae@google.com (Emil A Eklund)
+ */
+
+goog.provide('goog.events.KeyNames');
+
+
+/**
+ * Key names for common characters. These should be used with keyup/keydown
+ * events, since the .keyCode property on those is meant to indicate the
+ * *physical key* the user held down on the keyboard. Hence the mapping uses
+ * only the unshifted version of each key (e.g. no '#', since that's shift+3).
+ * Keypress events on the other hand generate (mostly) ASCII codes since they
+ * correspond to *characters* the user typed.
+ *
+ * For further reference: http://unixpapa.com/js/key.html
+ *
+ * This list is not localized and therefore some of the key codes are not
+ * correct for non-US keyboard layouts.
+ *
+ * @see goog.events.KeyCodes
+ * @enum {string}
+ */
+goog.events.KeyNames = {
+ 8: 'backspace',
+ 9: 'tab',
+ 13: 'enter',
+ 16: 'shift',
+ 17: 'ctrl',
+ 18: 'alt',
+ 19: 'pause',
+ 20: 'caps-lock',
+ 27: 'esc',
+ 32: 'space',
+ 33: 'pg-up',
+ 34: 'pg-down',
+ 35: 'end',
+ 36: 'home',
+ 37: 'left',
+ 38: 'up',
+ 39: 'right',
+ 40: 'down',
+ 45: 'insert',
+ 46: 'delete',
+ 48: '0',
+ 49: '1',
+ 50: '2',
+ 51: '3',
+ 52: '4',
+ 53: '5',
+ 54: '6',
+ 55: '7',
+ 56: '8',
+ 57: '9',
+ 59: 'semicolon',
+ 61: 'equals',
+ 65: 'a',
+ 66: 'b',
+ 67: 'c',
+ 68: 'd',
+ 69: 'e',
+ 70: 'f',
+ 71: 'g',
+ 72: 'h',
+ 73: 'i',
+ 74: 'j',
+ 75: 'k',
+ 76: 'l',
+ 77: 'm',
+ 78: 'n',
+ 79: 'o',
+ 80: 'p',
+ 81: 'q',
+ 82: 'r',
+ 83: 's',
+ 84: 't',
+ 85: 'u',
+ 86: 'v',
+ 87: 'w',
+ 88: 'x',
+ 89: 'y',
+ 90: 'z',
+ 93: 'context',
+ 96: 'num-0',
+ 97: 'num-1',
+ 98: 'num-2',
+ 99: 'num-3',
+ 100: 'num-4',
+ 101: 'num-5',
+ 102: 'num-6',
+ 103: 'num-7',
+ 104: 'num-8',
+ 105: 'num-9',
+ 106: 'num-multiply',
+ 107: 'num-plus',
+ 109: 'num-minus',
+ 110: 'num-period',
+ 111: 'num-division',
+ 112: 'f1',
+ 113: 'f2',
+ 114: 'f3',
+ 115: 'f4',
+ 116: 'f5',
+ 117: 'f6',
+ 118: 'f7',
+ 119: 'f8',
+ 120: 'f9',
+ 121: 'f10',
+ 122: 'f11',
+ 123: 'f12',
+ 186: 'semicolon',
+ 187: 'equals',
+ 189: 'dash',
+ 188: ',',
+ 190: '.',
+ 191: '/',
+ 192: '`',
+ 219: 'open-square-bracket',
+ 220: '\\',
+ 221: 'close-square-bracket',
+ 222: 'single-quote',
+ 224: 'win'
+};
[26/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/field.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/field.js b/externs/GCL/externs/goog/editor/field.js
new file mode 100644
index 0000000..349aca8
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/field.js
@@ -0,0 +1,2750 @@
+// 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.
+// All Rights Reserved.
+
+/**
+ * @fileoverview Class to encapsulate an editable field. Always uses an
+ * iframe to contain the editable area, never inherits the style of the
+ * surrounding page, and is always a fixed height.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ * @see ../demos/editor/editor.html
+ * @see ../demos/editor/field_basic.html
+ */
+
+goog.provide('goog.editor.Field');
+goog.provide('goog.editor.Field.EventType');
+
+goog.require('goog.a11y.aria');
+goog.require('goog.a11y.aria.Role');
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.async.Delay');
+goog.require('goog.dom');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.icontent');
+goog.require('goog.editor.icontent.FieldFormatInfo');
+goog.require('goog.editor.icontent.FieldStyleInfo');
+goog.require('goog.editor.node');
+goog.require('goog.editor.range');
+goog.require('goog.events');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.functions');
+goog.require('goog.log');
+goog.require('goog.log.Level');
+goog.require('goog.string');
+goog.require('goog.string.Unicode');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+goog.require('goog.userAgent.product');
+
+
+
+/**
+ * This class encapsulates an editable field.
+ *
+ * event: load Fires when the field is loaded
+ * event: unload Fires when the field is unloaded (made not editable)
+ *
+ * event: beforechange Fires before the content of the field might change
+ *
+ * event: delayedchange Fires a short time after field has changed. If multiple
+ * change events happen really close to each other only
+ * the last one will trigger the delayedchange event.
+ *
+ * event: beforefocus Fires before the field becomes active
+ * event: focus Fires when the field becomes active. Fires after the blur event
+ * event: blur Fires when the field becomes inactive
+ *
+ * TODO: figure out if blur or beforefocus fires first in IE and make FF match
+ *
+ * @param {string} id An identifer for the field. This is used to find the
+ * field and the element associated with this field.
+ * @param {Document=} opt_doc The document that the element with the given
+ * id can be found in. If not provided, the default document is used.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.editor.Field = function(id, opt_doc) {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * The id for this editable field, which must match the id of the element
+ * associated with this field.
+ * @type {string}
+ */
+ this.id = id;
+
+ /**
+ * The hash code for this field. Should be equal to the id.
+ * @type {string}
+ * @private
+ */
+ this.hashCode_ = id;
+
+ /**
+ * Dom helper for the editable node.
+ * @type {goog.dom.DomHelper}
+ * @protected
+ */
+ this.editableDomHelper = null;
+
+ /**
+ * Map of class id to registered plugin.
+ * @type {Object}
+ * @private
+ */
+ this.plugins_ = {};
+
+
+ /**
+ * Plugins registered on this field, indexed by the goog.editor.Plugin.Op
+ * that they support.
+ * @type {Object<Array<goog.editor.Plugin>>}
+ * @private
+ */
+ this.indexedPlugins_ = {};
+
+ for (var op in goog.editor.Plugin.OPCODE) {
+ this.indexedPlugins_[op] = [];
+ }
+
+
+ /**
+ * Additional styles to install for the editable field.
+ * @type {string}
+ * @protected
+ */
+ this.cssStyles = '';
+
+ // The field will not listen to change events until it has finished loading
+ this.stoppedEvents_ = {};
+ this.stopEvent(goog.editor.Field.EventType.CHANGE);
+ this.stopEvent(goog.editor.Field.EventType.DELAYEDCHANGE);
+ this.isModified_ = false;
+ this.isEverModified_ = false;
+ this.delayedChangeTimer_ = new goog.async.Delay(this.dispatchDelayedChange_,
+ goog.editor.Field.DELAYED_CHANGE_FREQUENCY, this);
+
+ this.debouncedEvents_ = {};
+ for (var key in goog.editor.Field.EventType) {
+ this.debouncedEvents_[goog.editor.Field.EventType[key]] = 0;
+ }
+
+ if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
+ this.changeTimerGecko_ = new goog.async.Delay(this.handleChange,
+ goog.editor.Field.CHANGE_FREQUENCY, this);
+ }
+
+ /**
+ * @type {goog.events.EventHandler<!goog.editor.Field>}
+ * @protected
+ */
+ this.eventRegister = new goog.events.EventHandler(this);
+
+ // Wrappers around this field, to be disposed when the field is disposed.
+ this.wrappers_ = [];
+
+ this.loadState_ = goog.editor.Field.LoadState_.UNEDITABLE;
+
+ var doc = opt_doc || document;
+
+ /**
+ * @type {!goog.dom.DomHelper}
+ * @protected
+ */
+ this.originalDomHelper = goog.dom.getDomHelper(doc);
+
+ /**
+ * @type {Element}
+ * @protected
+ */
+ this.originalElement = this.originalDomHelper.getElement(this.id);
+
+ /**
+ * @private {boolean}
+ */
+ this.followLinkInNewWindow_ =
+ goog.editor.BrowserFeature.FOLLOWS_EDITABLE_LINKS;
+
+ // Default to the same window as the field is in.
+ this.appWindow_ = this.originalDomHelper.getWindow();
+};
+goog.inherits(goog.editor.Field, goog.events.EventTarget);
+
+
+/**
+ * The editable dom node.
+ * @type {Element}
+ * TODO(user): Make this private!
+ */
+goog.editor.Field.prototype.field = null;
+
+
+/**
+ * The original node that is being made editable, or null if it has
+ * not yet been found.
+ * @type {Element}
+ * @protected
+ */
+goog.editor.Field.prototype.originalElement = null;
+
+
+/**
+ * Logging object.
+ * @type {goog.log.Logger}
+ * @protected
+ */
+goog.editor.Field.prototype.logger =
+ goog.log.getLogger('goog.editor.Field');
+
+
+/**
+ * Event types that can be stopped/started.
+ * @enum {string}
+ */
+goog.editor.Field.EventType = {
+ /**
+ * Dispatched when the command state of the selection may have changed. This
+ * event should be listened to for updating toolbar state.
+ */
+ COMMAND_VALUE_CHANGE: 'cvc',
+ /**
+ * Dispatched when the field is loaded and ready to use.
+ */
+ LOAD: 'load',
+ /**
+ * Dispatched when the field is fully unloaded and uneditable.
+ */
+ UNLOAD: 'unload',
+ /**
+ * Dispatched before the field contents are changed.
+ */
+ BEFORECHANGE: 'beforechange',
+ /**
+ * Dispatched when the field contents change, in FF only.
+ * Used for internal resizing, please do not use.
+ */
+ CHANGE: 'change',
+ /**
+ * Dispatched on a slight delay after changes are made.
+ * Use for autosave, or other times your app needs to know
+ * that the field contents changed.
+ */
+ DELAYEDCHANGE: 'delayedchange',
+ /**
+ * Dispatched before focus in moved into the field.
+ */
+ BEFOREFOCUS: 'beforefocus',
+ /**
+ * Dispatched when focus is moved into the field.
+ */
+ FOCUS: 'focus',
+ /**
+ * Dispatched when the field is blurred.
+ */
+ BLUR: 'blur',
+ /**
+ * Dispatched before tab is handled by the field. This is a legacy way
+ * of controlling tab behavior. Use trog.plugins.AbstractTabHandler now.
+ */
+ BEFORETAB: 'beforetab',
+ /**
+ * Dispatched after the iframe containing the field is resized, so that UI
+ * components which contain it can respond.
+ */
+ IFRAME_RESIZED: 'ifrsz',
+ /**
+ * Dispatched when the selection changes.
+ * Use handleSelectionChange from plugin API instead of listening
+ * directly to this event.
+ */
+ SELECTIONCHANGE: 'selectionchange'
+};
+
+
+/**
+ * The load state of the field.
+ * @enum {number}
+ * @private
+ */
+goog.editor.Field.LoadState_ = {
+ UNEDITABLE: 0,
+ LOADING: 1,
+ EDITABLE: 2
+};
+
+
+/**
+ * The amount of time that a debounce blocks an event.
+ * TODO(nicksantos): As of 9/30/07, this is only used for blocking
+ * a keyup event after a keydown. We might need to tweak this for other
+ * types of events. Maybe have a per-event debounce time?
+ * @type {number}
+ * @private
+ */
+goog.editor.Field.DEBOUNCE_TIME_MS_ = 500;
+
+
+/**
+ * There is at most one "active" field at a time. By "active" field, we mean
+ * a field that has focus and is being used.
+ * @type {?string}
+ * @private
+ */
+goog.editor.Field.activeFieldId_ = null;
+
+
+/**
+ * Whether this field is in "modal interaction" mode. This usually
+ * means that it's being edited by a dialog.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.Field.prototype.inModalMode_ = false;
+
+
+/**
+ * The window where dialogs and bubbles should be rendered.
+ * @type {!Window}
+ * @private
+ */
+goog.editor.Field.prototype.appWindow_;
+
+
+/**
+ * The dom helper for the node to be made editable.
+ * @type {goog.dom.DomHelper}
+ * @protected
+ */
+goog.editor.Field.prototype.originalDomHelper;
+
+
+/**
+ * Target node to be used when dispatching SELECTIONCHANGE asynchronously on
+ * mouseup (to avoid IE quirk). Should be set just before starting the timer and
+ * nulled right after consuming.
+ * @type {Node}
+ * @private
+ */
+goog.editor.Field.prototype.selectionChangeTarget_;
+
+
+/**
+ * Flag controlling wether to capture mouse up events on the window or not.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.Field.prototype.useWindowMouseUp_ = false;
+
+
+/**
+ * FLag indicating the handling of a mouse event sequence.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.Field.prototype.waitingForMouseUp_ = false;
+
+
+/**
+ * Sets the active field id.
+ * @param {?string} fieldId The active field id.
+ */
+goog.editor.Field.setActiveFieldId = function(fieldId) {
+ goog.editor.Field.activeFieldId_ = fieldId;
+};
+
+
+/**
+ * @return {?string} The id of the active field.
+ */
+goog.editor.Field.getActiveFieldId = function() {
+ return goog.editor.Field.activeFieldId_;
+};
+
+
+/**
+ * Sets flag to control whether to use window mouse up after seeing
+ * a mouse down operation on the field.
+ * @param {boolean} flag True to track window mouse up.
+ */
+goog.editor.Field.prototype.setUseWindowMouseUp = function(flag) {
+ goog.asserts.assert(!flag || !this.usesIframe(),
+ 'procssing window mouse up should only be enabled when not using iframe');
+ this.useWindowMouseUp_ = flag;
+};
+
+
+/**
+ * @return {boolean} Whether we're in modal interaction mode. When this
+ * returns true, another plugin is interacting with the field contents
+ * in a synchronous way, and expects you not to make changes to
+ * the field's DOM structure or selection.
+ */
+goog.editor.Field.prototype.inModalMode = function() {
+ return this.inModalMode_;
+};
+
+
+/**
+ * @param {boolean} inModalMode Sets whether we're in modal interaction mode.
+ */
+goog.editor.Field.prototype.setModalMode = function(inModalMode) {
+ this.inModalMode_ = inModalMode;
+};
+
+
+/**
+ * Returns a string usable as a hash code for this field. For field's
+ * that were created with an id, the hash code is guaranteed to be the id.
+ * TODO(user): I think we can get rid of this. Seems only used from editor.
+ * @return {string} The hash code for this editable field.
+ */
+goog.editor.Field.prototype.getHashCode = function() {
+ return this.hashCode_;
+};
+
+
+/**
+ * Returns the editable DOM element or null if this field
+ * is not editable.
+ * <p>On IE or Safari this is the element with contentEditable=true
+ * (in whitebox mode, the iFrame body).
+ * <p>On Gecko this is the iFrame body
+ * TODO(user): How do we word this for subclass version?
+ * @return {Element} The editable DOM element, defined as above.
+ */
+goog.editor.Field.prototype.getElement = function() {
+ return this.field;
+};
+
+
+/**
+ * Returns original DOM element that is being made editable by Trogedit or
+ * null if that element has not yet been found in the appropriate document.
+ * @return {Element} The original element.
+ */
+goog.editor.Field.prototype.getOriginalElement = function() {
+ return this.originalElement;
+};
+
+
+/**
+ * Registers a keyboard event listener on the field. This is necessary for
+ * Gecko since the fields are contained in an iFrame and there is no way to
+ * auto-propagate key events up to the main window.
+ * @param {string|Array<string>} type Event type to listen for or array of
+ * event types, for example goog.events.EventType.KEYDOWN.
+ * @param {Function} listener Function to be used as the listener.
+ * @param {boolean=} opt_capture Whether to use capture phase (optional,
+ * defaults to false).
+ * @param {Object=} opt_handler Object in whose scope to call the listener.
+ */
+goog.editor.Field.prototype.addListener = function(type, listener, opt_capture,
+ opt_handler) {
+ var elem = this.getElement();
+ // On Gecko, keyboard events only reliably fire on the document element when
+ // using an iframe.
+ if (goog.editor.BrowserFeature.USE_DOCUMENT_FOR_KEY_EVENTS && elem &&
+ this.usesIframe()) {
+ elem = elem.ownerDocument;
+ }
+ if (opt_handler) {
+ this.eventRegister.listenWithScope(
+ elem, type, listener, opt_capture, opt_handler);
+ } else {
+ this.eventRegister.listen(elem, type, listener, opt_capture);
+ }
+};
+
+
+/**
+ * Returns the registered plugin with the given classId.
+ * @param {string} classId classId of the plugin.
+ * @return {goog.editor.Plugin} Registered plugin with the given classId.
+ */
+goog.editor.Field.prototype.getPluginByClassId = function(classId) {
+ return this.plugins_[classId];
+};
+
+
+/**
+ * Registers the plugin with the editable field.
+ * @param {goog.editor.Plugin} plugin The plugin to register.
+ */
+goog.editor.Field.prototype.registerPlugin = function(plugin) {
+ var classId = plugin.getTrogClassId();
+ if (this.plugins_[classId]) {
+ goog.log.error(this.logger,
+ 'Cannot register the same class of plugin twice.');
+ }
+ this.plugins_[classId] = plugin;
+
+ // Only key events and execute should have these has* functions with a custom
+ // handler array since they need to be very careful about performance.
+ // The rest of the plugin hooks should be event-based.
+ for (var op in goog.editor.Plugin.OPCODE) {
+ var opcode = goog.editor.Plugin.OPCODE[op];
+ if (plugin[opcode]) {
+ this.indexedPlugins_[op].push(plugin);
+ }
+ }
+ plugin.registerFieldObject(this);
+
+ // By default we enable all plugins for fields that are currently loaded.
+ if (this.isLoaded()) {
+ plugin.enable(this);
+ }
+};
+
+
+/**
+ * Unregisters the plugin with this field.
+ * @param {goog.editor.Plugin} plugin The plugin to unregister.
+ */
+goog.editor.Field.prototype.unregisterPlugin = function(plugin) {
+ var classId = plugin.getTrogClassId();
+ if (!this.plugins_[classId]) {
+ goog.log.error(this.logger,
+ 'Cannot unregister a plugin that isn\'t registered.');
+ }
+ delete this.plugins_[classId];
+
+ for (var op in goog.editor.Plugin.OPCODE) {
+ var opcode = goog.editor.Plugin.OPCODE[op];
+ if (plugin[opcode]) {
+ goog.array.remove(this.indexedPlugins_[op], plugin);
+ }
+ }
+
+ plugin.unregisterFieldObject(this);
+};
+
+
+/**
+ * Sets the value that will replace the style attribute of this field's
+ * element when the field is made non-editable. This method is called with the
+ * current value of the style attribute when the field is made editable.
+ * @param {string} cssText The value of the style attribute.
+ */
+goog.editor.Field.prototype.setInitialStyle = function(cssText) {
+ this.cssText = cssText;
+};
+
+
+/**
+ * Reset the properties on the original field element to how it was before
+ * it was made editable.
+ */
+goog.editor.Field.prototype.resetOriginalElemProperties = function() {
+ var field = this.getOriginalElement();
+ field.removeAttribute('contentEditable');
+ field.removeAttribute('g_editable');
+ field.removeAttribute('role');
+
+ if (!this.id) {
+ field.removeAttribute('id');
+ } else {
+ field.id = this.id;
+ }
+
+ field.className = this.savedClassName_ || '';
+
+ var cssText = this.cssText;
+ if (!cssText) {
+ field.removeAttribute('style');
+ } else {
+ goog.dom.setProperties(field, {'style' : cssText});
+ }
+
+ if (goog.isString(this.originalFieldLineHeight_)) {
+ goog.style.setStyle(field, 'lineHeight', this.originalFieldLineHeight_);
+ this.originalFieldLineHeight_ = null;
+ }
+};
+
+
+/**
+ * Checks the modified state of the field.
+ * Note: Changes that take place while the goog.editor.Field.EventType.CHANGE
+ * event is stopped do not effect the modified state.
+ * @param {boolean=} opt_useIsEverModified Set to true to check if the field
+ * has ever been modified since it was created, otherwise checks if the field
+ * has been modified since the last goog.editor.Field.EventType.DELAYEDCHANGE
+ * event was dispatched.
+ * @return {boolean} Whether the field has been modified.
+ */
+goog.editor.Field.prototype.isModified = function(opt_useIsEverModified) {
+ return opt_useIsEverModified ? this.isEverModified_ : this.isModified_;
+};
+
+
+/**
+ * Number of milliseconds after a change when the change event should be fired.
+ * @type {number}
+ */
+goog.editor.Field.CHANGE_FREQUENCY = 15;
+
+
+/**
+ * Number of milliseconds between delayed change events.
+ * @type {number}
+ */
+goog.editor.Field.DELAYED_CHANGE_FREQUENCY = 250;
+
+
+/**
+ * @return {boolean} Whether the field is implemented as an iframe.
+ */
+goog.editor.Field.prototype.usesIframe = goog.functions.TRUE;
+
+
+/**
+ * @return {boolean} Whether the field should be rendered with a fixed
+ * height, or should expand to fit its contents.
+ */
+goog.editor.Field.prototype.isFixedHeight = goog.functions.TRUE;
+
+
+/**
+ * @return {boolean} Whether the field should be refocused on input.
+ * This is a workaround for the iOS bug that text input doesn't work
+ * when the main window listens touch events.
+ */
+goog.editor.Field.prototype.shouldRefocusOnInputMobileSafari =
+ goog.functions.FALSE;
+
+
+/**
+ * Map of keyCodes (not charCodes) that cause changes in the field contents.
+ * @type {Object}
+ * @private
+ */
+goog.editor.Field.KEYS_CAUSING_CHANGES_ = {
+ 46: true, // DEL
+ 8: true // BACKSPACE
+};
+
+if (!goog.userAgent.IE) {
+ // Only IE doesn't change the field by default upon tab.
+ // TODO(user): This really isn't right now that we have tab plugins.
+ goog.editor.Field.KEYS_CAUSING_CHANGES_[9] = true; // TAB
+}
+
+
+/**
+ * Map of keyCodes (not charCodes) that when used in conjunction with the
+ * Ctrl key cause changes in the field contents. These are the keys that are
+ * not handled by basic formatting trogedit plugins.
+ * @type {Object}
+ * @private
+ */
+goog.editor.Field.CTRL_KEYS_CAUSING_CHANGES_ = {
+ 86: true, // V
+ 88: true // X
+};
+
+if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
+ // In IE and Webkit, input from IME (Input Method Editor) does not generate a
+ // keypress event so we have to rely on the keydown event. This way we have
+ // false positives while the user is using keyboard to select the
+ // character to input, but it is still better than the false negatives
+ // that ignores user's final input at all.
+ goog.editor.Field.KEYS_CAUSING_CHANGES_[229] = true; // from IME;
+}
+
+
+/**
+ * Returns true if the keypress generates a change in contents.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @param {boolean} testAllKeys True to test for all types of generating keys.
+ * False to test for only the keys found in
+ * goog.editor.Field.KEYS_CAUSING_CHANGES_.
+ * @return {boolean} Whether the keypress generates a change in contents.
+ * @private
+ */
+goog.editor.Field.isGeneratingKey_ = function(e, testAllKeys) {
+ if (goog.editor.Field.isSpecialGeneratingKey_(e)) {
+ return true;
+ }
+
+ return !!(testAllKeys && !(e.ctrlKey || e.metaKey) &&
+ (!goog.userAgent.GECKO || e.charCode));
+};
+
+
+/**
+ * Returns true if the keypress generates a change in the contents.
+ * due to a special key listed in goog.editor.Field.KEYS_CAUSING_CHANGES_
+ * @param {goog.events.BrowserEvent} e The event.
+ * @return {boolean} Whether the keypress generated a change in the contents.
+ * @private
+ */
+goog.editor.Field.isSpecialGeneratingKey_ = function(e) {
+ var testCtrlKeys = (e.ctrlKey || e.metaKey) &&
+ e.keyCode in goog.editor.Field.CTRL_KEYS_CAUSING_CHANGES_;
+ var testRegularKeys = !(e.ctrlKey || e.metaKey) &&
+ e.keyCode in goog.editor.Field.KEYS_CAUSING_CHANGES_;
+
+ return testCtrlKeys || testRegularKeys;
+};
+
+
+/**
+ * Sets the application window.
+ * @param {!Window} appWindow The window where dialogs and bubbles should be
+ * rendered.
+ */
+goog.editor.Field.prototype.setAppWindow = function(appWindow) {
+ this.appWindow_ = appWindow;
+};
+
+
+/**
+ * Returns the "application" window, where dialogs and bubbles
+ * should be rendered.
+ * @return {!Window} The window.
+ */
+goog.editor.Field.prototype.getAppWindow = function() {
+ return this.appWindow_;
+};
+
+
+/**
+ * Sets the zIndex that the field should be based off of.
+ * TODO(user): Get rid of this completely. Here for Sites.
+ * Should this be set directly on UI plugins?
+ *
+ * @param {number} zindex The base zIndex of the editor.
+ */
+goog.editor.Field.prototype.setBaseZindex = function(zindex) {
+ this.baseZindex_ = zindex;
+};
+
+
+/**
+ * Returns the zindex of the base level of the field.
+ *
+ * @return {number} The base zindex of the editor.
+ */
+goog.editor.Field.prototype.getBaseZindex = function() {
+ return this.baseZindex_ || 0;
+};
+
+
+/**
+ * Sets up the field object and window util of this field, and enables this
+ * editable field with all registered plugins.
+ * This is essential to the initialization of the field.
+ * It must be called when the field becomes fully loaded and editable.
+ * @param {Element} field The field property.
+ * @protected
+ */
+goog.editor.Field.prototype.setupFieldObject = function(field) {
+ this.loadState_ = goog.editor.Field.LoadState_.EDITABLE;
+ this.field = field;
+ this.editableDomHelper = goog.dom.getDomHelper(field);
+ this.isModified_ = false;
+ this.isEverModified_ = false;
+ field.setAttribute('g_editable', 'true');
+ goog.a11y.aria.setRole(field, goog.a11y.aria.Role.TEXTBOX);
+};
+
+
+/**
+ * Help make the field not editable by setting internal data structures to null,
+ * and disabling this field with all registered plugins.
+ * @private
+ */
+goog.editor.Field.prototype.tearDownFieldObject_ = function() {
+ this.loadState_ = goog.editor.Field.LoadState_.UNEDITABLE;
+
+ for (var classId in this.plugins_) {
+ var plugin = this.plugins_[classId];
+ if (!plugin.activeOnUneditableFields()) {
+ plugin.disable(this);
+ }
+ }
+
+ this.field = null;
+ this.editableDomHelper = null;
+};
+
+
+/**
+ * Initialize listeners on the field.
+ * @private
+ */
+goog.editor.Field.prototype.setupChangeListeners_ = function() {
+ if ((goog.userAgent.product.IPHONE || goog.userAgent.product.IPAD) &&
+ this.usesIframe() && this.shouldRefocusOnInputMobileSafari()) {
+ // This is a workaround for the iOS bug that text input doesn't work
+ // when the main window listens touch events.
+ var editWindow = this.getEditableDomHelper().getWindow();
+ this.boundRefocusListenerMobileSafari_ =
+ goog.bind(editWindow.focus, editWindow);
+ editWindow.addEventListener(goog.events.EventType.KEYDOWN,
+ this.boundRefocusListenerMobileSafari_, false);
+ editWindow.addEventListener(goog.events.EventType.TOUCHEND,
+ this.boundRefocusListenerMobileSafari_, false);
+ }
+ if (goog.userAgent.OPERA && this.usesIframe()) {
+ // We can't use addListener here because we need to listen on the window,
+ // and removing listeners on window objects from the event register throws
+ // an exception if the window is closed.
+ this.boundFocusListenerOpera_ =
+ goog.bind(this.dispatchFocusAndBeforeFocus_, this);
+ this.boundBlurListenerOpera_ =
+ goog.bind(this.dispatchBlur, this);
+ var editWindow = this.getEditableDomHelper().getWindow();
+ editWindow.addEventListener(goog.events.EventType.FOCUS,
+ this.boundFocusListenerOpera_, false);
+ editWindow.addEventListener(goog.events.EventType.BLUR,
+ this.boundBlurListenerOpera_, false);
+ } else {
+ if (goog.editor.BrowserFeature.SUPPORTS_FOCUSIN) {
+ this.addListener(goog.events.EventType.FOCUS, this.dispatchFocus_);
+ this.addListener(goog.events.EventType.FOCUSIN,
+ this.dispatchBeforeFocus_);
+ } else {
+ this.addListener(goog.events.EventType.FOCUS,
+ this.dispatchFocusAndBeforeFocus_);
+ }
+ this.addListener(goog.events.EventType.BLUR, this.dispatchBlur,
+ goog.editor.BrowserFeature.USE_MUTATION_EVENTS);
+ }
+
+ if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
+ // Ways to detect changes in Mozilla:
+ //
+ // keypress - check event.charCode (only typable characters has a
+ // charCode), but also keyboard commands lile Ctrl+C will
+ // return a charCode.
+ // dragdrop - fires when the user drops something. This does not necessary
+ // lead to a change but we cannot detect if it will or not
+ //
+ // Known Issues: We cannot detect cut and paste using menus
+ // We cannot detect when someone moves something out of the
+ // field using drag and drop.
+ //
+ this.setupMutationEventHandlersGecko();
+ } else {
+ // Ways to detect that a change is about to happen in other browsers.
+ // (IE and Safari have these events. Opera appears to work, but we haven't
+ // researched it.)
+ //
+ // onbeforepaste
+ // onbeforecut
+ // ondrop - happens when the user drops something on the editable text
+ // field the value at this time does not contain the dropped text
+ // ondragleave - when the user drags something from the current document.
+ // This might not cause a change if the action was copy
+ // instead of move
+ // onkeypress - IE only fires keypress events if the key will generate
+ // output. It will not trigger for delete and backspace
+ // onkeydown - For delete and backspace
+ //
+ // known issues: IE triggers beforepaste just by opening the edit menu
+ // delete at the end should not cause beforechange
+ // backspace at the beginning should not cause beforechange
+ // see above in ondragleave
+ // TODO(user): Why don't we dispatchBeforeChange from the
+ // handleDrop event for all browsers?
+ this.addListener(['beforecut', 'beforepaste', 'drop', 'dragend'],
+ this.dispatchBeforeChange);
+ this.addListener(['cut', 'paste'],
+ goog.functions.lock(this.dispatchChange));
+ this.addListener('drop', this.handleDrop_);
+ }
+
+ // TODO(user): Figure out why we use dragend vs dragdrop and
+ // document this better.
+ var dropEventName = goog.userAgent.WEBKIT ? 'dragend' : 'dragdrop';
+ this.addListener(dropEventName, this.handleDrop_);
+
+ this.addListener(goog.events.EventType.KEYDOWN, this.handleKeyDown_);
+ this.addListener(goog.events.EventType.KEYPRESS, this.handleKeyPress_);
+ this.addListener(goog.events.EventType.KEYUP, this.handleKeyUp_);
+
+ this.selectionChangeTimer_ =
+ new goog.async.Delay(this.handleSelectionChangeTimer_,
+ goog.editor.Field.SELECTION_CHANGE_FREQUENCY_, this);
+
+ if (this.followLinkInNewWindow_) {
+ this.addListener(
+ goog.events.EventType.CLICK, goog.editor.Field.cancelLinkClick_);
+ }
+
+ this.addListener(goog.events.EventType.MOUSEDOWN, this.handleMouseDown_);
+ if (this.useWindowMouseUp_) {
+ this.eventRegister.listen(this.editableDomHelper.getDocument(),
+ goog.events.EventType.MOUSEUP, this.handleMouseUp_);
+ this.addListener(goog.events.EventType.DRAGSTART, this.handleDragStart_);
+ } else {
+ this.addListener(goog.events.EventType.MOUSEUP, this.handleMouseUp_);
+ }
+};
+
+
+/**
+ * Frequency to check for selection changes.
+ * @type {number}
+ * @private
+ */
+goog.editor.Field.SELECTION_CHANGE_FREQUENCY_ = 250;
+
+
+/**
+ * Stops all listeners and timers.
+ * @protected
+ */
+goog.editor.Field.prototype.clearListeners = function() {
+ if (this.eventRegister) {
+ this.eventRegister.removeAll();
+ }
+
+ if ((goog.userAgent.product.IPHONE || goog.userAgent.product.IPAD) &&
+ this.usesIframe() && this.shouldRefocusOnInputMobileSafari()) {
+ try {
+ var editWindow = this.getEditableDomHelper().getWindow();
+ editWindow.removeEventListener(goog.events.EventType.KEYDOWN,
+ this.boundRefocusListenerMobileSafari_, false);
+ editWindow.removeEventListener(goog.events.EventType.TOUCHEND,
+ this.boundRefocusListenerMobileSafari_, false);
+ } catch (e) {
+ // The editWindow no longer exists, or has been navigated to a different-
+ // origin URL. Either way, the event listeners have already been removed
+ // for us.
+ }
+ delete this.boundRefocusListenerMobileSafari_;
+ }
+ if (goog.userAgent.OPERA && this.usesIframe()) {
+ try {
+ var editWindow = this.getEditableDomHelper().getWindow();
+ editWindow.removeEventListener(goog.events.EventType.FOCUS,
+ this.boundFocusListenerOpera_, false);
+ editWindow.removeEventListener(goog.events.EventType.BLUR,
+ this.boundBlurListenerOpera_, false);
+ } catch (e) {
+ // The editWindow no longer exists, or has been navigated to a different-
+ // origin URL. Either way, the event listeners have already been removed
+ // for us.
+ }
+ delete this.boundFocusListenerOpera_;
+ delete this.boundBlurListenerOpera_;
+ }
+
+ if (this.changeTimerGecko_) {
+ this.changeTimerGecko_.stop();
+ }
+ this.delayedChangeTimer_.stop();
+};
+
+
+/** @override */
+goog.editor.Field.prototype.disposeInternal = function() {
+ if (this.isLoading() || this.isLoaded()) {
+ goog.log.warning(this.logger, 'Disposing a field that is in use.');
+ }
+
+ if (this.getOriginalElement()) {
+ this.execCommand(goog.editor.Command.CLEAR_LOREM);
+ }
+
+ this.tearDownFieldObject_();
+ this.clearListeners();
+ this.clearFieldLoadListener_();
+ this.originalDomHelper = null;
+
+ if (this.eventRegister) {
+ this.eventRegister.dispose();
+ this.eventRegister = null;
+ }
+
+ this.removeAllWrappers();
+
+ if (goog.editor.Field.getActiveFieldId() == this.id) {
+ goog.editor.Field.setActiveFieldId(null);
+ }
+
+ for (var classId in this.plugins_) {
+ var plugin = this.plugins_[classId];
+ if (plugin.isAutoDispose()) {
+ plugin.dispose();
+ }
+ }
+ delete(this.plugins_);
+
+ goog.editor.Field.superClass_.disposeInternal.call(this);
+};
+
+
+/**
+ * Attach an wrapper to this field, to be thrown out when the field
+ * is disposed.
+ * @param {goog.Disposable} wrapper The wrapper to attach.
+ */
+goog.editor.Field.prototype.attachWrapper = function(wrapper) {
+ this.wrappers_.push(wrapper);
+};
+
+
+/**
+ * Removes all wrappers and destroys them.
+ */
+goog.editor.Field.prototype.removeAllWrappers = function() {
+ var wrapper;
+ while (wrapper = this.wrappers_.pop()) {
+ wrapper.dispose();
+ }
+};
+
+
+/**
+ * Sets whether activating a hyperlink in this editable field will open a new
+ * window or not.
+ * @param {boolean} followLinkInNewWindow
+ */
+goog.editor.Field.prototype.setFollowLinkInNewWindow =
+ function(followLinkInNewWindow) {
+ this.followLinkInNewWindow_ = followLinkInNewWindow;
+};
+
+
+/**
+ * List of mutation events in Gecko browsers.
+ * @type {Array<string>}
+ * @protected
+ */
+goog.editor.Field.MUTATION_EVENTS_GECKO = [
+ 'DOMNodeInserted',
+ 'DOMNodeRemoved',
+ 'DOMNodeRemovedFromDocument',
+ 'DOMNodeInsertedIntoDocument',
+ 'DOMCharacterDataModified'
+];
+
+
+/**
+ * Mutation events tell us when something has changed for mozilla.
+ * @protected
+ */
+goog.editor.Field.prototype.setupMutationEventHandlersGecko = function() {
+ // Always use DOMSubtreeModified on Gecko when not using an iframe so that
+ // DOM mutations outside the Field do not trigger handleMutationEventGecko_.
+ if (goog.editor.BrowserFeature.HAS_DOM_SUBTREE_MODIFIED_EVENT ||
+ !this.usesIframe()) {
+ this.eventRegister.listen(this.getElement(), 'DOMSubtreeModified',
+ this.handleMutationEventGecko_);
+ } else {
+ var doc = this.getEditableDomHelper().getDocument();
+ this.eventRegister.listen(doc, goog.editor.Field.MUTATION_EVENTS_GECKO,
+ this.handleMutationEventGecko_, true);
+
+ // DOMAttrModified fires for a lot of events we want to ignore. This goes
+ // through a different handler so that we can ignore many of these.
+ this.eventRegister.listen(doc, 'DOMAttrModified',
+ goog.bind(this.handleDomAttrChange, this,
+ this.handleMutationEventGecko_),
+ true);
+ }
+};
+
+
+/**
+ * Handle before change key events and fire the beforetab event if appropriate.
+ * This needs to happen on keydown in IE and keypress in FF.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @return {boolean} Whether to still perform the default key action. Only set
+ * to true if the actual event has already been canceled.
+ * @private
+ */
+goog.editor.Field.prototype.handleBeforeChangeKeyEvent_ = function(e) {
+ // There are two reasons to block a key:
+ var block =
+ // #1: to intercept a tab
+ // TODO: possibly don't allow clients to intercept tabs outside of LIs and
+ // maybe tables as well?
+ (e.keyCode == goog.events.KeyCodes.TAB && !this.dispatchBeforeTab_(e)) ||
+ // #2: to block a Firefox-specific bug where Macs try to navigate
+ // back a page when you hit command+left arrow or comamnd-right arrow.
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=341886
+ // This was fixed in Firefox 29, but still exists in older versions.
+ (goog.userAgent.GECKO && e.metaKey &&
+ !goog.userAgent.isVersionOrHigher(29) &&
+ (e.keyCode == goog.events.KeyCodes.LEFT ||
+ e.keyCode == goog.events.KeyCodes.RIGHT));
+
+ if (block) {
+ e.preventDefault();
+ return false;
+ } else {
+ // In Gecko we have both keyCode and charCode. charCode is for human
+ // readable characters like a, b and c. However pressing ctrl+c and so on
+ // also causes charCode to be set.
+
+ // TODO(arv): Del at end of field or backspace at beginning should be
+ // ignored.
+ this.gotGeneratingKey_ = e.charCode ||
+ goog.editor.Field.isGeneratingKey_(e, goog.userAgent.GECKO);
+ if (this.gotGeneratingKey_) {
+ this.dispatchBeforeChange();
+ // TODO(robbyw): Should we return the value of the above?
+ }
+ }
+
+ return true;
+};
+
+
+/**
+ * Keycodes that result in a selectionchange event (e.g. the cursor moving).
+ * @type {!Object<number, number>}
+ */
+goog.editor.Field.SELECTION_CHANGE_KEYCODES = {
+ 8: 1, // backspace
+ 9: 1, // tab
+ 13: 1, // enter
+ 33: 1, // page up
+ 34: 1, // page down
+ 35: 1, // end
+ 36: 1, // home
+ 37: 1, // left
+ 38: 1, // up
+ 39: 1, // right
+ 40: 1, // down
+ 46: 1 // delete
+};
+
+
+/**
+ * Map of keyCodes (not charCodes) that when used in conjunction with the
+ * Ctrl key cause selection changes in the field contents. These are the keys
+ * that are not handled by the basic formatting trogedit plugins. Note that
+ * combinations like Ctrl-left etc are already handled in
+ * SELECTION_CHANGE_KEYCODES
+ * @type {Object}
+ * @private
+ */
+goog.editor.Field.CTRL_KEYS_CAUSING_SELECTION_CHANGES_ = {
+ 65: true, // A
+ 86: true, // V
+ 88: true // X
+};
+
+
+/**
+ * Map of keyCodes (not charCodes) that might need to be handled as a keyboard
+ * shortcut (even when ctrl/meta key is not pressed) by some plugin. Currently
+ * it is a small list. If it grows too big we can optimize it by using ranges
+ * or extending it from SELECTION_CHANGE_KEYCODES
+ * @type {Object}
+ * @private
+ */
+goog.editor.Field.POTENTIAL_SHORTCUT_KEYCODES_ = {
+ 8: 1, // backspace
+ 9: 1, // tab
+ 13: 1, // enter
+ 27: 1, // esc
+ 33: 1, // page up
+ 34: 1, // page down
+ 37: 1, // left
+ 38: 1, // up
+ 39: 1, // right
+ 40: 1 // down
+};
+
+
+/**
+ * Calls all the plugins of the given operation, in sequence, with the
+ * given arguments. This is short-circuiting: once one plugin cancels
+ * the event, no more plugins will be invoked.
+ * @param {goog.editor.Plugin.Op} op A plugin op.
+ * @param {...*} var_args The arguments to the plugin.
+ * @return {boolean} True if one of the plugins cancel the event, false
+ * otherwise.
+ * @private
+ */
+goog.editor.Field.prototype.invokeShortCircuitingOp_ = function(op, var_args) {
+ var plugins = this.indexedPlugins_[op];
+ var argList = goog.array.slice(arguments, 1);
+ for (var i = 0; i < plugins.length; ++i) {
+ // If the plugin returns true, that means it handled the event and
+ // we shouldn't propagate to the other plugins.
+ var plugin = plugins[i];
+ if ((plugin.isEnabled(this) ||
+ goog.editor.Plugin.IRREPRESSIBLE_OPS[op]) &&
+ plugin[goog.editor.Plugin.OPCODE[op]].apply(plugin, argList)) {
+ // Only one plugin is allowed to handle the event. If for some reason
+ // a plugin wants to handle it and still allow other plugins to handle
+ // it, it shouldn't return true.
+ return true;
+ }
+ }
+
+ return false;
+};
+
+
+/**
+ * Invoke this operation on all plugins with the given arguments.
+ * @param {goog.editor.Plugin.Op} op A plugin op.
+ * @param {...*} var_args The arguments to the plugin.
+ * @private
+ */
+goog.editor.Field.prototype.invokeOp_ = function(op, var_args) {
+ var plugins = this.indexedPlugins_[op];
+ var argList = goog.array.slice(arguments, 1);
+ for (var i = 0; i < plugins.length; ++i) {
+ var plugin = plugins[i];
+ if (plugin.isEnabled(this) ||
+ goog.editor.Plugin.IRREPRESSIBLE_OPS[op]) {
+ plugin[goog.editor.Plugin.OPCODE[op]].apply(plugin, argList);
+ }
+ }
+};
+
+
+/**
+ * Reduce this argument over all plugins. The result of each plugin invocation
+ * will be passed to the next plugin invocation. See goog.array.reduce.
+ * @param {goog.editor.Plugin.Op} op A plugin op.
+ * @param {string} arg The argument to reduce. For now, we assume it's a
+ * string, but we should widen this later if there are reducing
+ * plugins that don't operate on strings.
+ * @param {...*} var_args Any extra arguments to pass to the plugin. These args
+ * will not be reduced.
+ * @return {string} The reduced argument.
+ * @private
+ */
+goog.editor.Field.prototype.reduceOp_ = function(op, arg, var_args) {
+ var plugins = this.indexedPlugins_[op];
+ var argList = goog.array.slice(arguments, 1);
+ for (var i = 0; i < plugins.length; ++i) {
+ var plugin = plugins[i];
+ if (plugin.isEnabled(this) ||
+ goog.editor.Plugin.IRREPRESSIBLE_OPS[op]) {
+ argList[0] = plugin[goog.editor.Plugin.OPCODE[op]].apply(
+ plugin, argList);
+ }
+ }
+ return argList[0];
+};
+
+
+/**
+ * Prepare the given contents, then inject them into the editable field.
+ * @param {?string} contents The contents to prepare.
+ * @param {Element} field The field element.
+ * @protected
+ */
+goog.editor.Field.prototype.injectContents = function(contents, field) {
+ var styles = {};
+ var newHtml = this.getInjectableContents(contents, styles);
+ goog.style.setStyle(field, styles);
+ goog.editor.node.replaceInnerHtml(field, newHtml);
+};
+
+
+/**
+ * Returns prepared contents that can be injected into the editable field.
+ * @param {?string} contents The contents to prepare.
+ * @param {Object} styles A map that will be populated with styles that should
+ * be applied to the field element together with the contents.
+ * @return {string} The prepared contents.
+ */
+goog.editor.Field.prototype.getInjectableContents = function(contents, styles) {
+ return this.reduceOp_(
+ goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, contents || '', styles);
+};
+
+
+/**
+ * Handles keydown on the field.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.editor.Field.prototype.handleKeyDown_ = function(e) {
+ if (!goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
+ if (!this.handleBeforeChangeKeyEvent_(e)) {
+ return;
+ }
+ }
+
+ if (!this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.KEYDOWN, e) &&
+ goog.editor.BrowserFeature.USES_KEYDOWN) {
+ this.handleKeyboardShortcut_(e);
+ }
+};
+
+
+/**
+ * Handles keypress on the field.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.editor.Field.prototype.handleKeyPress_ = function(e) {
+ if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
+ if (!this.handleBeforeChangeKeyEvent_(e)) {
+ return;
+ }
+ } else {
+ // In IE only keys that generate output trigger keypress
+ // In Mozilla charCode is set for keys generating content.
+ this.gotGeneratingKey_ = true;
+ this.dispatchBeforeChange();
+ }
+
+ if (!this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.KEYPRESS, e) &&
+ !goog.editor.BrowserFeature.USES_KEYDOWN) {
+ this.handleKeyboardShortcut_(e);
+ }
+};
+
+
+/**
+ * Handles keyup on the field.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.editor.Field.prototype.handleKeyUp_ = function(e) {
+ if (!goog.editor.BrowserFeature.USE_MUTATION_EVENTS &&
+ (this.gotGeneratingKey_ ||
+ goog.editor.Field.isSpecialGeneratingKey_(e))) {
+ // The special keys won't have set the gotGeneratingKey flag, so we check
+ // for them explicitly
+ this.handleChange();
+ }
+
+ this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.KEYUP, e);
+
+ if (this.isEventStopped(goog.editor.Field.EventType.SELECTIONCHANGE)) {
+ return;
+ }
+
+ if (goog.editor.Field.SELECTION_CHANGE_KEYCODES[e.keyCode] ||
+ ((e.ctrlKey || e.metaKey) &&
+ goog.editor.Field.CTRL_KEYS_CAUSING_SELECTION_CHANGES_[e.keyCode])) {
+ this.selectionChangeTimer_.start();
+ }
+};
+
+
+/**
+ * Handles keyboard shortcuts on the field. Note that we bake this into our
+ * handleKeyPress/handleKeyDown rather than using goog.events.KeyHandler or
+ * goog.ui.KeyboardShortcutHandler for performance reasons. Since these
+ * are handled on every key stroke, we do not want to be going out to the
+ * event system every time.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.editor.Field.prototype.handleKeyboardShortcut_ = function(e) {
+ // Alt key is used for i18n languages to enter certain characters. like
+ // control + alt + z (used for IMEs) and control + alt + s for Polish.
+ // So we don't invoke handleKeyboardShortcut at all for alt keys.
+ if (e.altKey) {
+ return;
+ }
+
+ var isModifierPressed = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
+ if (isModifierPressed ||
+ goog.editor.Field.POTENTIAL_SHORTCUT_KEYCODES_[e.keyCode]) {
+ // TODO(user): goog.events.KeyHandler uses much more complicated logic
+ // to determine key. Consider changing to what they do.
+ var key = e.charCode || e.keyCode;
+
+ if (key == 17) { // Ctrl key
+ // In IE and Webkit pressing Ctrl key itself results in this event.
+ return;
+ }
+
+ var stringKey = String.fromCharCode(key).toLowerCase();
+ if (this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.SHORTCUT,
+ e, stringKey, isModifierPressed)) {
+ e.preventDefault();
+ // We don't call stopPropagation as some other handler outside of
+ // trogedit might need it.
+ }
+ }
+};
+
+
+/**
+ * Executes an editing command as per the registered plugins.
+ * @param {string} command The command to execute.
+ * @param {...*} var_args Any additional parameters needed to execute the
+ * command.
+ * @return {*} False if the command wasn't handled, otherwise, the result of
+ * the command.
+ */
+goog.editor.Field.prototype.execCommand = function(command, var_args) {
+ var args = arguments;
+ var result;
+
+ var plugins = this.indexedPlugins_[goog.editor.Plugin.Op.EXEC_COMMAND];
+ for (var i = 0; i < plugins.length; ++i) {
+ // If the plugin supports the command, that means it handled the
+ // event and we shouldn't propagate to the other plugins.
+ var plugin = plugins[i];
+ if (plugin.isEnabled(this) && plugin.isSupportedCommand(command)) {
+ result = plugin.execCommand.apply(plugin, args);
+ break;
+ }
+ }
+
+ return result;
+};
+
+
+/**
+ * Gets the value of command(s).
+ * @param {string|Array<string>} commands String name(s) of the command.
+ * @return {*} Value of each command. Returns false (or array of falses)
+ * if designMode is off or the field is otherwise uneditable, and
+ * there are no activeOnUneditable plugins for the command.
+ */
+goog.editor.Field.prototype.queryCommandValue = function(commands) {
+ var isEditable = this.isLoaded() && this.isSelectionEditable();
+ if (goog.isString(commands)) {
+ return this.queryCommandValueInternal_(commands, isEditable);
+ } else {
+ var state = {};
+ for (var i = 0; i < commands.length; i++) {
+ state[commands[i]] = this.queryCommandValueInternal_(commands[i],
+ isEditable);
+ }
+ return state;
+ }
+};
+
+
+/**
+ * Gets the value of this command.
+ * @param {string} command The command to check.
+ * @param {boolean} isEditable Whether the field is currently editable.
+ * @return {*} The state of this command. Null if not handled.
+ * False if the field is uneditable and there are no handlers for
+ * uneditable commands.
+ * @private
+ */
+goog.editor.Field.prototype.queryCommandValueInternal_ = function(command,
+ isEditable) {
+ var plugins = this.indexedPlugins_[goog.editor.Plugin.Op.QUERY_COMMAND];
+ for (var i = 0; i < plugins.length; ++i) {
+ var plugin = plugins[i];
+ if (plugin.isEnabled(this) && plugin.isSupportedCommand(command) &&
+ (isEditable || plugin.activeOnUneditableFields())) {
+ return plugin.queryCommandValue(command);
+ }
+ }
+ return isEditable ? null : false;
+};
+
+
+/**
+ * Fires a change event only if the attribute change effects the editiable
+ * field. We ignore events that are internal browser events (ie scrollbar
+ * state change)
+ * @param {Function} handler The function to call if this is not an internal
+ * browser event.
+ * @param {goog.events.BrowserEvent} browserEvent The browser event.
+ * @protected
+ */
+goog.editor.Field.prototype.handleDomAttrChange =
+ function(handler, browserEvent) {
+ if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
+ return;
+ }
+
+ var e = browserEvent.getBrowserEvent();
+
+ // For XUL elements, since we don't care what they are doing
+ try {
+ if (e.originalTarget.prefix || e.originalTarget.nodeName == 'scrollbar') {
+ return;
+ }
+ } catch (ex1) {
+ // Some XUL nodes don't like you reading their properties. If we got
+ // the exception, this implies a XUL node so we can return.
+ return;
+ }
+
+ // Check if prev and new values are different, sometimes this fires when
+ // nothing has really changed.
+ if (e.prevValue == e.newValue) {
+ return;
+ }
+ handler.call(this, e);
+};
+
+
+/**
+ * Handle a mutation event.
+ * @param {goog.events.BrowserEvent|Event} e The browser event.
+ * @private
+ */
+goog.editor.Field.prototype.handleMutationEventGecko_ = function(e) {
+ if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
+ return;
+ }
+
+ e = e.getBrowserEvent ? e.getBrowserEvent() : e;
+ // For people with firebug, firebug sets this property on elements it is
+ // inserting into the dom.
+ if (e.target.firebugIgnore) {
+ return;
+ }
+
+ this.isModified_ = true;
+ this.isEverModified_ = true;
+ this.changeTimerGecko_.start();
+};
+
+
+/**
+ * Handle drop events. Deal with focus/selection issues and set the document
+ * as changed.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.editor.Field.prototype.handleDrop_ = function(e) {
+ if (goog.userAgent.IE) {
+ // TODO(user): This should really be done in the loremipsum plugin.
+ this.execCommand(goog.editor.Command.CLEAR_LOREM, true);
+ }
+
+ // TODO(user): I just moved this code to this location, but I wonder why
+ // it is only done for this case. Investigate.
+ if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
+ this.dispatchFocusAndBeforeFocus_();
+ }
+
+ this.dispatchChange();
+};
+
+
+/**
+ * @return {HTMLIFrameElement} The iframe that's body is editable.
+ * @protected
+ */
+goog.editor.Field.prototype.getEditableIframe = function() {
+ var dh;
+ if (this.usesIframe() && (dh = this.getEditableDomHelper())) {
+ // If the iframe has been destroyed, the dh could still exist since the
+ // node may not be gc'ed, but fetching the window can fail.
+ var win = dh.getWindow();
+ return /** @type {HTMLIFrameElement} */ (win && win.frameElement);
+ }
+ return null;
+};
+
+
+/**
+ * @return {goog.dom.DomHelper?} The dom helper for the editable node.
+ */
+goog.editor.Field.prototype.getEditableDomHelper = function() {
+ return this.editableDomHelper;
+};
+
+
+/**
+ * @return {goog.dom.AbstractRange?} Closure range object wrapping the selection
+ * in this field or null if this field is not currently editable.
+ */
+goog.editor.Field.prototype.getRange = function() {
+ var win = this.editableDomHelper && this.editableDomHelper.getWindow();
+ return win && goog.dom.Range.createFromWindow(win);
+};
+
+
+/**
+ * Dispatch a selection change event, optionally caused by the given browser
+ * event or selecting the given target.
+ * @param {goog.events.BrowserEvent=} opt_e Optional browser event causing this
+ * event.
+ * @param {Node=} opt_target The node the selection changed to.
+ */
+goog.editor.Field.prototype.dispatchSelectionChangeEvent = function(
+ opt_e, opt_target) {
+ if (this.isEventStopped(goog.editor.Field.EventType.SELECTIONCHANGE)) {
+ return;
+ }
+
+ // The selection is editable only if the selection is inside the
+ // editable field.
+ var range = this.getRange();
+ var rangeContainer = range && range.getContainerElement();
+ this.isSelectionEditable_ = !!rangeContainer &&
+ goog.dom.contains(this.getElement(), rangeContainer);
+
+ this.dispatchCommandValueChange();
+ this.dispatchEvent({
+ type: goog.editor.Field.EventType.SELECTIONCHANGE,
+ originalType: opt_e && opt_e.type
+ });
+
+ this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.SELECTION,
+ opt_e, opt_target);
+};
+
+
+/**
+ * Dispatch a selection change event using a browser event that was
+ * asynchronously saved earlier.
+ * @private
+ */
+goog.editor.Field.prototype.handleSelectionChangeTimer_ = function() {
+ var t = this.selectionChangeTarget_;
+ this.selectionChangeTarget_ = null;
+ this.dispatchSelectionChangeEvent(undefined, t);
+};
+
+
+/**
+ * This dispatches the beforechange event on the editable field
+ */
+goog.editor.Field.prototype.dispatchBeforeChange = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.BEFORECHANGE)) {
+ return;
+ }
+
+ this.dispatchEvent(goog.editor.Field.EventType.BEFORECHANGE);
+};
+
+
+/**
+ * This dispatches the beforetab event on the editable field. If this event is
+ * cancelled, then the default tab behavior is prevented.
+ * @param {goog.events.BrowserEvent} e The tab event.
+ * @private
+ * @return {boolean} The result of dispatchEvent.
+ */
+goog.editor.Field.prototype.dispatchBeforeTab_ = function(e) {
+ return this.dispatchEvent({
+ type: goog.editor.Field.EventType.BEFORETAB,
+ shiftKey: e.shiftKey,
+ altKey: e.altKey,
+ ctrlKey: e.ctrlKey
+ });
+};
+
+
+/**
+ * Temporarily ignore change events. If the time has already been set, it will
+ * fire immediately now. Further setting of the timer is stopped and
+ * dispatching of events is stopped until startChangeEvents is called.
+ * @param {boolean=} opt_stopChange Whether to ignore base change events.
+ * @param {boolean=} opt_stopDelayedChange Whether to ignore delayed change
+ * events.
+ */
+goog.editor.Field.prototype.stopChangeEvents = function(opt_stopChange,
+ opt_stopDelayedChange) {
+ if (opt_stopChange) {
+ if (this.changeTimerGecko_) {
+ this.changeTimerGecko_.fireIfActive();
+ }
+
+ this.stopEvent(goog.editor.Field.EventType.CHANGE);
+ }
+ if (opt_stopDelayedChange) {
+ this.clearDelayedChange();
+ this.stopEvent(goog.editor.Field.EventType.DELAYEDCHANGE);
+ }
+};
+
+
+/**
+ * Start change events again and fire once if desired.
+ * @param {boolean=} opt_fireChange Whether to fire the change event
+ * immediately.
+ * @param {boolean=} opt_fireDelayedChange Whether to fire the delayed change
+ * event immediately.
+ */
+goog.editor.Field.prototype.startChangeEvents = function(opt_fireChange,
+ opt_fireDelayedChange) {
+
+ if (!opt_fireChange && this.changeTimerGecko_) {
+ // In the case where change events were stopped and we're not firing
+ // them on start, the user was trying to suppress all change or delayed
+ // change events. Clear the change timer now while the events are still
+ // stopped so that its firing doesn't fire a stopped change event, or
+ // queue up a delayed change event that we were trying to stop.
+ this.changeTimerGecko_.fireIfActive();
+ }
+
+ this.startEvent(goog.editor.Field.EventType.CHANGE);
+ this.startEvent(goog.editor.Field.EventType.DELAYEDCHANGE);
+ if (opt_fireChange) {
+ this.handleChange();
+ }
+
+ if (opt_fireDelayedChange) {
+ this.dispatchDelayedChange_();
+ }
+};
+
+
+/**
+ * Stops the event of the given type from being dispatched.
+ * @param {goog.editor.Field.EventType} eventType type of event to stop.
+ */
+goog.editor.Field.prototype.stopEvent = function(eventType) {
+ this.stoppedEvents_[eventType] = 1;
+};
+
+
+/**
+ * Re-starts the event of the given type being dispatched, if it had
+ * previously been stopped with stopEvent().
+ * @param {goog.editor.Field.EventType} eventType type of event to start.
+ */
+goog.editor.Field.prototype.startEvent = function(eventType) {
+ // Toggling this bit on/off instead of deleting it/re-adding it
+ // saves array allocations.
+ this.stoppedEvents_[eventType] = 0;
+};
+
+
+/**
+ * Block an event for a short amount of time. Intended
+ * for the situation where an event pair fires in quick succession
+ * (e.g., mousedown/mouseup, keydown/keyup, focus/blur),
+ * and we want the second event in the pair to get "debounced."
+ *
+ * WARNING: This should never be used to solve race conditions or for
+ * mission-critical actions. It should only be used for UI improvements,
+ * where it's okay if the behavior is non-deterministic.
+ *
+ * @param {goog.editor.Field.EventType} eventType type of event to debounce.
+ */
+goog.editor.Field.prototype.debounceEvent = function(eventType) {
+ this.debouncedEvents_[eventType] = goog.now();
+};
+
+
+/**
+ * Checks if the event of the given type has stopped being dispatched
+ * @param {goog.editor.Field.EventType} eventType type of event to check.
+ * @return {boolean} true if the event has been stopped with stopEvent().
+ * @protected
+ */
+goog.editor.Field.prototype.isEventStopped = function(eventType) {
+ return !!this.stoppedEvents_[eventType] ||
+ (this.debouncedEvents_[eventType] &&
+ (goog.now() - this.debouncedEvents_[eventType] <=
+ goog.editor.Field.DEBOUNCE_TIME_MS_));
+};
+
+
+/**
+ * Calls a function to manipulate the dom of this field. This method should be
+ * used whenever Trogedit clients need to modify the dom of the field, so that
+ * delayed change events are handled appropriately. Extra delayed change events
+ * will cause undesired states to be added to the undo-redo stack. This method
+ * will always fire at most one delayed change event, depending on the value of
+ * {@code opt_preventDelayedChange}.
+ *
+ * @param {function()} func The function to call that will manipulate the dom.
+ * @param {boolean=} opt_preventDelayedChange Whether delayed change should be
+ * prevented after calling {@code func}. Defaults to always firing
+ * delayed change.
+ * @param {Object=} opt_handler Object in whose scope to call the listener.
+ */
+goog.editor.Field.prototype.manipulateDom = function(func,
+ opt_preventDelayedChange, opt_handler) {
+
+ this.stopChangeEvents(true, true);
+ // We don't want any problems with the passed in function permanently
+ // stopping change events. That would break Trogedit.
+ try {
+ func.call(opt_handler);
+ } finally {
+ // If the field isn't loaded then change and delayed change events will be
+ // started as part of the onload behavior.
+ if (this.isLoaded()) {
+ // We assume that func always modified the dom and so fire a single change
+ // event. Delayed change is only fired if not prevented by the user.
+ if (opt_preventDelayedChange) {
+ this.startEvent(goog.editor.Field.EventType.CHANGE);
+ this.handleChange();
+ this.startEvent(goog.editor.Field.EventType.DELAYEDCHANGE);
+ } else {
+ this.dispatchChange();
+ }
+ }
+ }
+};
+
+
+/**
+ * Dispatches a command value change event.
+ * @param {Array<string>=} opt_commands Commands whose state has
+ * changed.
+ */
+goog.editor.Field.prototype.dispatchCommandValueChange =
+ function(opt_commands) {
+ if (opt_commands) {
+ this.dispatchEvent({
+ type: goog.editor.Field.EventType.COMMAND_VALUE_CHANGE,
+ commands: opt_commands
+ });
+ } else {
+ this.dispatchEvent(goog.editor.Field.EventType.COMMAND_VALUE_CHANGE);
+ }
+};
+
+
+/**
+ * Dispatches the appropriate set of change events. This only fires
+ * synchronous change events in blended-mode, iframe-using mozilla. It just
+ * starts the appropriate timer for goog.editor.Field.EventType.DELAYEDCHANGE.
+ * This also starts up change events again if they were stopped.
+ *
+ * @param {boolean=} opt_noDelay True if
+ * goog.editor.Field.EventType.DELAYEDCHANGE should be fired syncronously.
+ */
+goog.editor.Field.prototype.dispatchChange = function(opt_noDelay) {
+ this.startChangeEvents(true, opt_noDelay);
+};
+
+
+/**
+ * Handle a change in the Editable Field. Marks the field has modified,
+ * dispatches the change event on the editable field (moz only), starts the
+ * timer for the delayed change event. Note that these actions only occur if
+ * the proper events are not stopped.
+ */
+goog.editor.Field.prototype.handleChange = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
+ return;
+ }
+
+ // Clear the changeTimerGecko_ if it's active, since any manual call to
+ // handle change is equiavlent to changeTimerGecko_.fire().
+ if (this.changeTimerGecko_) {
+ this.changeTimerGecko_.stop();
+ }
+
+ this.isModified_ = true;
+ this.isEverModified_ = true;
+
+ if (this.isEventStopped(goog.editor.Field.EventType.DELAYEDCHANGE)) {
+ return;
+ }
+
+ this.delayedChangeTimer_.start();
+};
+
+
+/**
+ * Dispatch a delayed change event.
+ * @private
+ */
+goog.editor.Field.prototype.dispatchDelayedChange_ = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.DELAYEDCHANGE)) {
+ return;
+ }
+ // Clear the delayedChangeTimer_ if it's active, since any manual call to
+ // dispatchDelayedChange_ is equivalent to delayedChangeTimer_.fire().
+ this.delayedChangeTimer_.stop();
+ this.isModified_ = false;
+ this.dispatchEvent(goog.editor.Field.EventType.DELAYEDCHANGE);
+};
+
+
+/**
+ * Don't wait for the timer and just fire the delayed change event if it's
+ * pending.
+ */
+goog.editor.Field.prototype.clearDelayedChange = function() {
+ // The changeTimerGecko_ will queue up a delayed change so to fully clear
+ // delayed change we must also clear this timer.
+ if (this.changeTimerGecko_) {
+ this.changeTimerGecko_.fireIfActive();
+ }
+ this.delayedChangeTimer_.fireIfActive();
+};
+
+
+/**
+ * Dispatch beforefocus and focus for FF. Note that both of these actually
+ * happen in the document's "focus" event. Unfortunately, we don't actually
+ * have a way of getting in before the focus event in FF (boo! hiss!).
+ * In IE, we use onfocusin for before focus and onfocus for focus.
+ * @private
+ */
+goog.editor.Field.prototype.dispatchFocusAndBeforeFocus_ = function() {
+ this.dispatchBeforeFocus_();
+ this.dispatchFocus_();
+};
+
+
+/**
+ * Dispatches a before focus event.
+ * @private
+ */
+goog.editor.Field.prototype.dispatchBeforeFocus_ = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.BEFOREFOCUS)) {
+ return;
+ }
+
+ this.execCommand(goog.editor.Command.CLEAR_LOREM, true);
+ this.dispatchEvent(goog.editor.Field.EventType.BEFOREFOCUS);
+};
+
+
+/**
+ * Dispatches a focus event.
+ * @private
+ */
+goog.editor.Field.prototype.dispatchFocus_ = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.FOCUS)) {
+ return;
+ }
+ goog.editor.Field.setActiveFieldId(this.id);
+
+ this.isSelectionEditable_ = true;
+
+ this.dispatchEvent(goog.editor.Field.EventType.FOCUS);
+
+ if (goog.editor.BrowserFeature.
+ PUTS_CURSOR_BEFORE_FIRST_BLOCK_ELEMENT_ON_FOCUS) {
+ // If the cursor is at the beginning of the field, make sure that it is
+ // in the first user-visible line break, e.g.,
+ // no selection: <div><p>...</p></div> --> <div><p>|cursor|...</p></div>
+ // <div>|cursor|<p>...</p></div> --> <div><p>|cursor|...</p></div>
+ // <body>|cursor|<p>...</p></body> --> <body><p>|cursor|...</p></body>
+ var field = this.getElement();
+ var range = this.getRange();
+
+ if (range) {
+ var focusNode = range.getFocusNode();
+ if (range.getFocusOffset() == 0 && (!focusNode || focusNode == field ||
+ focusNode.tagName == goog.dom.TagName.BODY)) {
+ goog.editor.range.selectNodeStart(field);
+ }
+ }
+ }
+
+ if (!goog.editor.BrowserFeature.CLEARS_SELECTION_WHEN_FOCUS_LEAVES &&
+ this.usesIframe()) {
+ var parent = this.getEditableDomHelper().getWindow().parent;
+ parent.getSelection().removeAllRanges();
+ }
+};
+
+
+/**
+ * Dispatches a blur event.
+ * @protected
+ */
+goog.editor.Field.prototype.dispatchBlur = function() {
+ if (this.isEventStopped(goog.editor.Field.EventType.BLUR)) {
+ return;
+ }
+
+ // Another field may have already been registered as active, so only
+ // clear out the active field id if we still think this field is active.
+ if (goog.editor.Field.getActiveFieldId() == this.id) {
+ goog.editor.Field.setActiveFieldId(null);
+ }
+
+ this.isSelectionEditable_ = false;
+ this.dispatchEvent(goog.editor.Field.EventType.BLUR);
+};
+
+
+/**
+ * @return {boolean} Whether the selection is editable.
+ */
+goog.editor.Field.prototype.isSelectionEditable = function() {
+ return this.isSelectionEditable_;
+};
+
+
+/**
+ * Event handler for clicks in browsers that will follow a link when the user
+ * clicks, even if it's editable. We stop the click manually
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.editor.Field.cancelLinkClick_ = function(e) {
+ if (goog.dom.getAncestorByTagNameAndClass(
+ /** @type {Node} */ (e.target), goog.dom.TagName.A)) {
+ e.preventDefault();
+ }
+};
+
+
+/**
+ * Handle mouse down inside the editable field.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.editor.Field.prototype.handleMouseDown_ = function(e) {
+ goog.editor.Field.setActiveFieldId(this.id);
+
+ // Open links in a new window if the user control + clicks.
+ if (goog.userAgent.IE) {
+ var targetElement = e.target;
+ if (targetElement &&
+ targetElement.tagName == goog.dom.TagName.A && e.ctrlKey) {
+ this.originalDomHelper.getWindow().open(targetElement.href);
+ }
+ }
+ this.waitingForMouseUp_ = true;
+};
+
+
+/**
+ * Handle drag start. Needs to cancel listening for the mouse up event on the
+ * window.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.editor.Field.prototype.handleDragStart_ = function(e) {
+ this.waitingForMouseUp_ = false;
+};
+
+
+/**
+ * Handle mouse up inside the editable field.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.editor.Field.prototype.handleMouseUp_ = function(e) {
+ if (this.useWindowMouseUp_ && !this.waitingForMouseUp_) {
+ return;
+ }
+ this.waitingForMouseUp_ = false;
+
+ /*
+ * We fire a selection change event immediately for listeners that depend on
+ * the native browser event object (e). On IE, a listener that tries to
+ * retrieve the selection with goog.dom.Range may see an out-of-date
+ * selection range.
+ */
+ this.dispatchSelectionChangeEvent(e);
+ if (goog.userAgent.IE) {
+ /*
+ * Fire a second selection change event for listeners that need an
+ * up-to-date selection range. Save the event's target to be sent with it
+ * (it's safer than saving a copy of the event itself).
+ */
+ this.selectionChangeTarget_ = /** @type {Node} */ (e.target);
+ this.selectionChangeTimer_.start();
+ }
+};
+
+
+/**
+ * Retrieve the HTML contents of a field.
+ *
+ * Do NOT just get the innerHTML of a field directly--there's a lot of
+ * processing that needs to happen.
+ * @return {string} The scrubbed contents of the field.
+ */
+goog.editor.Field.prototype.getCleanContents = function() {
+ if (this.queryCommandValue(goog.editor.Command.USING_LOREM)) {
+ return goog.string.Unicode.NBSP;
+ }
+
+ if (!this.isLoaded()) {
+ // The field is uneditable, so it's ok to read contents directly.
+ var elem = this.getOriginalElement();
+ if (!elem) {
+ goog.log.log(this.logger, goog.log.Level.SHOUT,
+ "Couldn't get the field element to read the contents");
+ }
+ return elem.innerHTML;
+ }
+
+ var fieldCopy = this.getFieldCopy();
+
+ // Allow the plugins to handle their cleanup.
+ this.invokeOp_(goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM, fieldCopy);
+ return this.reduceOp_(
+ goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML, fieldCopy.innerHTML);
+};
+
+
+/**
+ * Get the copy of the editable field element, which has the innerHTML set
+ * correctly.
+ * @return {!Element} The copy of the editable field.
+ * @protected
+ */
+goog.editor.Field.prototype.getFieldCopy = function() {
+ var field = this.getElement();
+ // Deep cloneNode strips some script tag contents in IE, so we do this.
+ var fieldCopy = /** @type {Element} */(field.cloneNode(false));
+
+ // For some reason, when IE sets innerHtml of the cloned node, it strips
+ // script tags that fall at the beginning of an element. Appending a
+ // non-breaking space prevents this.
+ var html = field.innerHTML;
+ if (goog.userAgent.IE && html.match(/^\s*<script/i)) {
+ html = goog.string.Unicode.NBSP + html;
+ }
+ fieldCopy.innerHTML = html;
+ return fieldCopy;
+};
+
+
+/**
+ * Sets the contents of the field.
+ * @param {boolean} addParas Boolean to specify whether to add paragraphs
+ * to long fields.
+ * @param {?string} html html to insert. If html=null, then this defaults
+ * to a nsbp for mozilla and an empty string for IE.
+ * @param {boolean=} opt_dontFireDelayedChange True to make this content change
+ * not fire a delayed change event.
+ * @param {boolean=} opt_applyLorem Whether to apply lorem ipsum styles.
+ */
+goog.editor.Field.prototype.setHtml = function(
+ addParas, html, opt_dontFireDelayedChange, opt_applyLorem) {
+ if (this.isLoading()) {
+ goog.log.error(this.logger, "Can't set html while loading Trogedit");
+ return;
+ }
+
+ // Clear the lorem ipsum style, always.
+ if (opt_applyLorem) {
+ this.execCommand(goog.editor.Command.CLEAR_LOREM);
+ }
+
+ if (html && addParas) {
+ html = '<p>' + html + '</p>';
+ }
+
+ // If we don't want change events to fire, we have to turn off change events
+ // before setting the field contents, since that causes mutation events.
+ if (opt_dontFireDelayedChange) {
+ this.stopChangeEvents(false, true);
+ }
+
+ this.setInnerHtml_(html);
+
+ // Set the lorem ipsum style, if the element is empty.
+ if (opt_applyLorem) {
+ this.execCommand(goog.editor.Command.UPDATE_LOREM);
+ }
+
+ // TODO(user): This check should probably be moved to isEventStopped and
+ // startEvent.
+ if (this.isLoaded()) {
+ if (opt_dontFireDelayedChange) { // Turn back on change events
+ // We must fire change timer if necessary before restarting change events!
+ // Otherwise, the change timer firing after we restart events will cause
+ // the delayed change we were trying to stop. Flow:
+ // Stop delayed change
+ // setInnerHtml_, this starts the change timer
+ // start delayed change
+ // change timer fires
+ // starts delayed change timer since event was not stopped
+ // delayed change fires for the delayed change we tried to stop.
+ if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
+ this.changeTimerGecko_.fireIfActive();
+ }
+ this.startChangeEvents();
+ } else { // Mark the document as changed and fire change events.
+ this.dispatchChange();
+ }
+ }
+};
+
+
+/**
+ * Sets the inner HTML of the field. Works on both editable and
+ * uneditable fields.
+ * @param {?string} html The new inner HTML of the field.
+ * @private
+ */
+goog.editor.Field.prototype.setInnerHtml_ = function(html) {
+ var field = this.getElement();
+ if (field) {
+ // Safari will put <style> tags into *new* <head> elements. When setting
+ // HTML, we need to remove these spare <head>s to make sure there's a
+ // clean slate, but keep the first <head>.
+ // Note: We punt on this issue for the non iframe case since
+ // we don't want to screw with the main document.
+ if (this.usesIframe() && goog.editor.BrowserFeature.MOVES_STYLE_TO_HEAD) {
+ var heads = field.ownerDocument.getElementsByTagName(
+ goog.dom.TagName.HEAD);
+ for (var i = heads.length - 1; i >= 1; --i) {
+ heads[i].parentNode.removeChild(heads[i]);
+ }
+ }
+ } else {
+ field = this.getOriginalElement();
+ }
+
+ if (field) {
+ this.injectContents(html, field);
+ }
+};
+
+
+/**
+ * Attemps to turn on designMode for a document. This function can fail under
+ * certain circumstances related to the load event, and will throw an exception.
+ * @protected
+ */
+goog.editor.Field.prototype.turnOnDesignModeGecko = function() {
+ var doc = this.getEditableDomHelper().getDocument();
+
+ // NOTE(nicksantos): This will fail under certain conditions, like
+ // when the node has display: none. It's up to clients to ensure that
+ // their fields are valid when they try to make them editable.
+ doc.designMode = 'on';
+
+ if (goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS) {
+ doc.execCommand('styleWithCSS', false, false);
+ }
+};
+
+
+/**
+ * Installs styles if needed. Only writes styles when they can't be written
+ * inline directly into the field.
+ * @protected
+ */
+goog.editor.Field.prototype.installStyles = function() {
+ if (this.cssStyles && this.shouldLoadAsynchronously()) {
+ goog.style.installStyles(this.cssStyles, this.getElement());
+ }
+};
+
+
+/**
+ * Signal that the field is loaded and ready to use. Change events now are
+ * in effect.
+ * @private
+ */
+goog.editor.Field.prototype.dispatchLoadEvent_ = function() {
+ var field = this.getElement();
+
+ this.installStyles();
+ this.startChangeEvents();
+ goog.log.info(this.logger, 'Dispatching load ' + this.id);
+ this.dispatchEvent(goog.editor.Field.EventType.LOAD);
+};
+
+
+/**
+ * @return {boolean} Whether the field is uneditable.
+ */
+goog.editor.Field.prototype.isUneditable = function() {
+ return this.loadState_ == goog.editor.Field.LoadState_.UNEDITABLE;
+};
+
+
+/**
+ * @return {boolean} Whether the field has finished loading.
+ */
+goog.editor.Field.prototype.isLoaded = function() {
+ return this.loadState_ == goog.editor.Field.LoadState_.EDITABLE;
+};
+
+
+/**
+ * @return {boolean} Whether the field is in the process of loading.
+ */
+goog.editor.Field.prototype.isLoading = function() {
+ return this.loadState_ == goog.editor.Field.LoadState_.LOADING;
+};
+
+
+/**
+ * Gives the field focus.
+ */
+goog.editor.Field.prototype.focus = function() {
+ if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE &&
+ this.usesIframe()) {
+ // In designMode, only the window itself can be focused; not the element.
+ this.getEditableDomHelper().getWindow().focus();
+ } else {
+ if (goog.userAgent.OPERA) {
+ // Opera will scroll to the bottom of the focused document, even
+ // if it is contained in an iframe that is scrolled to the top and
+ // the bottom flows past the end of it. To prevent this,
+ // save the scroll position of the document containing the editor
+ // iframe, then restore it after the focus.
+ var scrollX = this.appWindow_.pageXOffset;
+ var scrollY = this.appWindow_.pageYOffset;
+ }
+ this.getElement().focus();
+ if (goog.userAgent.OPERA) {
+ this.appWindow_.scrollTo(
+ /** @type {number} */ (scrollX), /** @type {number} */ (scrollY));
+ }
+ }
+};
+
+
+/**
+ * Gives the field focus and places the cursor at the start of the field.
+ */
+goog.editor.Field.prototype.focusAndPlaceCursorAtStart = function() {
+ // NOTE(user): Excluding Gecko to maintain existing behavior post refactoring
+ // placeCursorAtStart into its own method. In Gecko browsers that currently
+ // have a selection the existing selection will be restored, otherwise it
+ // will go to the start.
+ // TODO(user): Refactor the code using this and related methods. We should
+ // only mess with the selection in the case where there is not an existing
+ // selection in the field.
+ if (goog.editor.BrowserFeature.HAS_IE_RANGES || !goog.userAgent.GECKO) {
+ this.placeCursorAtStart();
+ }
+ this.focus();
+};
+
+
+/**
+ * Place the cursor at the start of this field. It's recommended that you only
+ * use this method (and manipulate the selection in general) when there is not
+ * an existing selection in the field.
+ */
+goog.editor.Field.prototype.placeCursorAtStart = function() {
+ this.placeCursorAtStartOrEnd_(true);
+};
+
+
+/**
+ * Place the cursor at the start of this field. It's recommended that you only
+ * use this method (and manipulate the selection in general) when there is not
+ * an existing selection in the field.
+ */
+goog.editor.Field.prototype.placeCursorAtEnd = function() {
+ this.placeCursorAtStartOrEnd_(false);
+};
+
+
+/**
+ * Helper method to place the cursor at the start or end of this field.
+ * @param {boolean} isStart True for start, false for end.
+ * @private
+ */
+goog.editor.Field.prototype.placeCursorAtStartOrEnd_ = function(isStart) {
+ var field = this.getElement();
+ if (field) {
+ var cursorPosition = isStart ? goog.editor.node.getLeftMostLeaf(field) :
+ goog.editor.node.getRightMostLeaf(field);
+ if (field == cursorPosition) {
+ // The rightmost leaf we found was the field element itself (which likely
+ // means the field element is empty). We can't place the cursor next to
+ // the field element, so just place it at the beginning.
+ goog.dom.Range.createCaret(field, 0).select();
+ } else {
+ goog.editor.range.placeCursorNextTo(cursorPosition, isStart);
+ }
+ this.dispatchSelectionChangeEvent();
+ }
+};
+
+
+/**
+ * Restore a saved range, and set the focus on the field.
+ * If no range is specified, we simply set the focus.
+ * @param {goog.dom.SavedRange=} opt_range A previously saved selected range.
+ */
+goog.editor.Field.prototype.restoreSavedRange = function(opt_range) {
+ if (goog.userAgent.IE) {
+ this.focus();
+ }
+ if (opt_range) {
+ opt_range.restore();
+ }
+ if (!goog.userAgent.IE) {
+ this.focus();
+ }
+};
+
+
+/**
+ * Makes a field editable.
+ *
+ * @param {string=} opt_iframeSrc URL to set the iframe src to if necessary.
+ */
+goog.editor.Field.prototype.makeEditable = function(opt_iframeSrc) {
+ this.loadState_ = goog.editor.Field.LoadState_.LOADING;
+
+ var field = this.getOriginalElement();
+
+ // TODO: In the fieldObj, save the field's id, className, cssText
+ // in order to reset it on closeField. That way, we can muck with the field's
+ // css, id, class and restore to how it was at the end.
+ this.nodeName = field.nodeName;
+ this.savedClassName_ = field.className;
+ this.setInitialStyle(field.style.cssText);
+
+ field.className += ' editable';
+
+ this.makeEditableInternal(opt_iframeSrc);
+};
+
+
+/**
+ * Handles actually making something editable - creating necessary nodes,
+ * injecting content, etc.
+ * @param {string=} opt_iframeSrc URL to set the iframe src to if necessary.
+ * @protected
+ */
+goog.editor.Field.prototype.makeEditableInternal = function(opt_iframeSrc) {
+ this.makeIframeField_(opt_iframeSrc);
+};
+
+
+/**
+ * Handle the loading of the field (e.g. once the field is ready to setup).
+ * TODO(user): this should probably just be moved into dispatchLoadEvent_.
+ * @protected
+ */
+goog.editor.Field.prototype.handleFieldLoad = function() {
+ if (goog.userAgent.IE) {
+ // This sometimes fails if the selection is invalid. This can happen, for
+ // example, if you attach a CLICK handler to the field that causes the
+ // field to be removed from the DOM and replaced with an editor
+ // -- however, listening to another event like MOUSEDOWN does not have this
+ // issue since no mouse selection has happened at that time.
+ goog.dom.Range.clearSelection(this.editableDomHelper.getWindow());
+ }
+
+ if (goog.editor.Field.getActiveFieldId() != this.id) {
+ this.execCommand(goog.editor.Command.UPDATE_LOREM);
+ }
+
+ this.setupChangeListeners_();
+ this.dispatchLoadEvent_();
+
+ // Enabling plugins after we fire the load event so that clients have a
+ // chance to set initial field contents before we start mucking with
+ // everything.
+ for (var classId in this.plugins_) {
+ this.plugins_[classId].enable(this);
+ }
+};
+
+
+/**
+ * Closes the field and cancels all pending change timers. Note that this
+ * means that if a change event has not fired yet, it will not fire. Clients
+ * should check fieldOj.isModified() if they depend on the final change event.
+ * Throws an error if the field is already uneditable.
+ *
+ * @param {boolean=} opt_skipRestore True to prevent copying of editable field
+ * contents back into the original node.
+ */
+goog.editor.Field.prototype.makeUneditable = function(opt_skipRestore) {
+ if (this.isUneditable()) {
+ throw Error('makeUneditable: Field is already uneditable');
+ }
+
+ // Fire any events waiting on a timeout.
+ // Clearing delayed change also clears changeTimerGecko_.
+ this.clearDelayedChange();
+ this.selectionChangeTimer_.fireIfActive();
+ this.execCommand(goog.editor.Command.CLEAR_LOREM);
+
+ var html = null;
+ if (!opt_skipRestore && this.getElement()) {
+ // Rest of cleanup is simpler if field was never initialized.
+ html = this.getCleanContents();
+ }
+
+ // First clean up anything that happens in makeFieldEditable
+ // (i.e. anything that needs cleanup even if field has not loaded).
+ this.clearFieldLoadListener_();
+
+ var field = this.getOriginalElement();
+ if (goog.editor.Field.getActiveFieldId() == field.id) {
+ goog.editor.Field.setActiveFieldId(null);
+ }
+
+ // Clear all listeners before removing the nodes from the dom - if
+ // there are listeners on the iframe window, Firefox throws errors trying
+ // to unlisten once the iframe is no longer in the dom.
+ this.clearListeners();
+
+ // For fields that have loaded, clean up anything that happened in
+ // handleFieldOpen or later.
+ // If html is provided, copy it back and reset the properties on the field
+ // so that the original node will have the same properties as it did before
+ // it was made editable.
+ if (goog.isString(html)) {
+ goog.editor.node.replaceInnerHtml(field, html);
+ this.resetOriginalElemProperties();
+ }
+
+ this.restoreDom();
+ this.tearDownFieldObject_();
+
+ // On Safari, make sure to un-focus the field so that the
+ // native "current field" highlight style gets removed.
+ if (goog.userAgent.WEBKIT) {
+ field.blur();
+ }
+
+ this.execCommand(goog.editor.Command.UPDATE_LOREM);
+ this.dispatchEvent(goog.editor.Field.EventType.UNLOAD);
+};
+
+
+/**
+ * Restores the dom to how it was before being made editable.
+ * @protected
+ */
+goog.editor.Field.prototype.restoreDom = function() {
+ // TODO(user): Consider only removing the iframe if we are
+ // restoring the original node, aka, if opt_html.
+ var field = this.getOriginalElement();
+ // TODO(robbyw): Consider throwing an error if !field.
+ if (field) {
+ // If the field is in the process of loading when it starts getting torn
+ // up, the iframe will not exist.
+ var iframe = this.getEditableIframe();
+ if (iframe) {
+ goog.dom.replaceNode(field, iframe);
+ }
+ }
+};
+
+
+/**
+ * Returns true if the field needs to be loaded asynchrnously.
+ * @return {boolean} True if loads are async.
+ * @protected
+ */
+goog.editor.Field.prototype.shouldLoadAsynchronously = function() {
+ if (!goog.isDef(this.isHttps_)) {
+ this.isHttps_ = false;
+
+ if (goog.userAgent.IE && this.usesIframe()) {
+ // IE iframes need to load asynchronously if they are in https as we need
+ // to set an actual src on the iframe and wait for it to load.
+
+ // Find the top-most window we have access to and see if it's https.
+ // Technically this could fail if we have an http frame in an https frame
+ // on the same domain (or vice versa), but walking up the window heirarchy
+ // to find the first window that has an http* protocol seems like
+ // overkill.
+ var win = this.originalDomHelper.getWindow();
+ while (win != win.parent) {
+ try {
+ win = win.parent;
+ } catch (e) {
+ break;
+ }
+ }
+ var loc = win.location;
+ this.isHttps_ = loc.protocol == 'https:' &&
+ loc.search.indexOf('nocheckhttps') == -1;
+ }
+ }
+ return this.isHttps_;
+};
+
+
+/**
+ * Start the editable iframe creation process for Mozilla or IE whitebox.
+ * The iframes load asynchronously.
+ *
+ * @param {string=} opt_iframeSrc URL to set the iframe src to if necessary.
+ * @private
+ */
+goog.editor.Field.prototype.makeIframeField_ = function(opt_iframeSrc) {
+ var field = this.getOriginalElement();
+ // TODO(robbyw): Consider throwing an error if !field.
+ if (field) {
+ var html = field.innerHTML;
+
+ // Invoke prepareContentsHtml on all plugins to prepare html for editing.
+ // Make sure this is done before calling this.attachFrame which removes the
+ // original element from DOM tree. Plugins may assume that the original
+ // element is still in its original position in DOM.
+ var styles = {};
+ html = this.reduceOp_(goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML,
+ html, styles);
+
+ var iframe = /** @type {!HTMLIFrameElement} */(
+ this.originalDomHelper.createDom(goog.dom.TagName.IFRAME,
+ this.getIframeAttributes()));
+
+ // TODO(nicksantos): Figure out if this is ever needed in SAFARI?
+ // In IE over HTTPS we need to wait for a load event before we set up the
+ // iframe, this is to prevent a security prompt or access is denied
+ // errors.
+ // NOTE(user): This hasn't been confirmed. isHttps_ allows a query
+ // param, nocheckhttps, which we can use to ascertain if this is actually
+ // needed. It was originally thought to be needed for IE6 SP1, but
+ // errors have been seen in IE7 as well.
+ if (this.shouldLoadAsynchronously()) {
+ // onLoad is the function to call once the iframe is ready to continue
+ // loading.
+ var onLoad = goog.bind(this.iframeFieldLoadHandler, this, iframe,
+ html, styles);
+
+ this.fieldLoadListenerKey_ = goog.events.listen(iframe,
+ goog.events.EventType.LOAD, onLoad, true);
+
+ if (opt_iframeSrc) {
+ iframe.src = opt_iframeSrc;
+ }
+ }
+
+ this.attachIframe(iframe);
+
+ // Only continue if its not IE HTTPS in which case we're waiting for load.
+ if (!this.shouldLoadAsynchronously()) {
+ this.iframeFieldLoadHandler(iframe, html, styles);
+ }
+ }
+};
+
+
+/**
+ * Given the original field element, and the iframe that is destined to
+ * become the editable field, styles them appropriately and add the iframe
+ * to the dom.
+ *
+ * @param {HTMLIFrameElement} iframe The iframe element.
+ * @protected
+ */
+goog.editor.Field.prototype.attachIframe = function(iframe) {
+ var field = this.getOriginalElement();
+ // TODO(user): Why do we do these two lines .. and why whitebox only?
+ iframe.className = field.className;
+ iframe.id = field.id;
+ goog.dom.replaceNode(iframe, field);
+};
+
+
+/**
+ * @param {Object} extraStyles A map of extra styles.
+ * @return {!goog.editor.icontent.FieldFormatInfo} The FieldFormatInfo
+ * object for this field's configuration.
+ * @protected
+ */
+goog.editor.Field.prototype.getFieldFormatInfo = function(extraStyles) {
+ var originalElement = this.getOriginalElement();
+ var isStandardsMode = goog.editor.node.isStandardsMode(originalElement);
+
+ return new goog.editor.icontent.FieldFormatInfo(
+ this.id,
+ isStandardsMode,
+ false,
+ false,
+ extraStyles);
+};
+
+
+/**
+ * Writes the html content into the iframe. Handles writing any aditional
+ * styling as well.
+ * @param {HTMLIFrameElement} iframe Iframe to write contents into.
+ * @param {string} innerHtml The html content to write into the iframe.
+ * @param {Object} extraStyles A map of extra style attributes.
+ * @protected
+ */
+goog.editor.Field.prototype.writeIframeContent = function(
+ iframe, innerHtml, extraStyles) {
+ var formatInfo = this.getFieldFormatInfo(extraStyles);
+
+ if (this.shouldLoadAsynchronously()) {
+ var doc = goog.dom.getFrameContentDocument(iframe);
+ goog.editor.icontent.writeHttpsInitialIframe(formatInfo, doc, innerHtml);
+ } else {
+ var styleInfo = new goog.editor.icontent.FieldStyleInfo(
+ this.getElement(), this.cssStyles);
+ goog.editor.icontent.writeNormalInitialIframe(formatInfo, innerHtml,
+ styleInfo, iframe);
+ }
+};
+
+
+/**
+ * The function to call when the editable iframe loads.
+ *
+ * @param {HTMLIFrameElement} iframe Iframe that just loaded.
+ * @param {string} innerHtml Html to put inside the body of the iframe.
+ * @param {Object} styles Property-value map of CSS styles to install on
+ * editable field.
+ * @protected
+ */
+goog.editor.Field.prototype.iframeFieldLoadHandler = function(iframe,
+ innerHtml, styles) {
+ this.clearFieldLoadListener_();
+
+ iframe.allowTransparency = 'true';
+ this.writeIframeContent(iframe, innerHtml, styles);
+ var doc = goog.dom.getFrameContentDocument(iframe);
+
+ // Make sure to get this pointer after the doc.write as the doc.write
+ // clobbers all the document contents.
+ var body = doc.body;
+ this.setupFieldObject(body);
+
+ if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE &&
+ this.usesIframe()) {
+ this.turnOnDesignModeGecko();
+ }
+
+ this.handleFieldLoad();
+};
+
+
+/**
+ * Clears fieldLoadListener for a field. Must be called even (especially?) if
+ * the field is not yet loaded and therefore not in this.fieldMap_
+ * @private
+ */
+goog.editor.Field.prototype.clearFieldLoadListener_ = function() {
+ if (this.fieldLoadListenerKey_) {
+ goog.events.unlistenByKey(this.fieldLoadListenerKey_);
+ this.fieldLoadListenerKey_ = null;
+ }
+};
+
+
+/**
+ * @return {!Object} Get the HTML attributes for this field's iframe.
+ * @protected
+ */
+goog.editor.Field.
<TRUNCATED>
[22/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/linkdialogplugin.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/linkdialogplugin.js b/externs/GCL/externs/goog/editor/plugins/linkdialogplugin.js
new file mode 100644
index 0000000..9c804a6
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/linkdialogplugin.js
@@ -0,0 +1,438 @@
+// 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 A plugin for the LinkDialog.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.LinkDialogPlugin');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.plugins.AbstractDialogPlugin');
+goog.require('goog.events.EventHandler');
+goog.require('goog.functions');
+goog.require('goog.ui.editor.AbstractDialog');
+goog.require('goog.ui.editor.LinkDialog');
+goog.require('goog.uri.utils');
+
+
+
+/**
+ * A plugin that opens the link dialog.
+ * @constructor
+ * @extends {goog.editor.plugins.AbstractDialogPlugin}
+ */
+goog.editor.plugins.LinkDialogPlugin = function() {
+ goog.editor.plugins.LinkDialogPlugin.base(
+ this, 'constructor', goog.editor.Command.MODAL_LINK_EDITOR);
+
+ /**
+ * Event handler for this object.
+ * @type {goog.events.EventHandler<!goog.editor.plugins.LinkDialogPlugin>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+
+ /**
+ * A list of whitelisted URL schemes which are safe to open.
+ * @type {Array<string>}
+ * @private
+ */
+ this.safeToOpenSchemes_ = ['http', 'https', 'ftp'];
+};
+goog.inherits(goog.editor.plugins.LinkDialogPlugin,
+ goog.editor.plugins.AbstractDialogPlugin);
+
+
+/**
+ * Link object that the dialog is editing.
+ * @type {goog.editor.Link}
+ * @protected
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.currentLink_;
+
+
+/**
+ * Optional warning to show about email addresses.
+ * @type {goog.html.SafeHtml}
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.emailWarning_;
+
+
+/**
+ * Whether to show a checkbox where the user can choose to have the link open in
+ * a new window.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.showOpenLinkInNewWindow_ = false;
+
+
+/**
+ * Whether the "open link in new window" checkbox should be checked when the
+ * dialog is shown, and also whether it was checked last time the dialog was
+ * closed.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.isOpenLinkInNewWindowChecked_ =
+ false;
+
+
+/**
+ * Weather to show a checkbox where the user can choose to add 'rel=nofollow'
+ * attribute added to the link.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.showRelNoFollow_ = false;
+
+
+/**
+ * Whether to stop referrer leaks. Defaults to false.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.stopReferrerLeaks_ = false;
+
+
+/**
+ * Whether to block opening links with a non-whitelisted URL scheme.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.blockOpeningUnsafeSchemes_ =
+ true;
+
+
+/** @override */
+goog.editor.plugins.LinkDialogPlugin.prototype.getTrogClassId =
+ goog.functions.constant('LinkDialogPlugin');
+
+
+/**
+ * Tells the plugin whether to block URLs with schemes not in the whitelist.
+ * If blocking is enabled, this plugin will stop the 'Test Link' popup
+ * window from being created. Blocking doesn't affect link creation--if the
+ * user clicks the 'OK' button with an unsafe URL, the link will still be
+ * created as normal.
+ * @param {boolean} blockOpeningUnsafeSchemes Whether to block non-whitelisted
+ * schemes.
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.setBlockOpeningUnsafeSchemes =
+ function(blockOpeningUnsafeSchemes) {
+ this.blockOpeningUnsafeSchemes_ = blockOpeningUnsafeSchemes;
+};
+
+
+/**
+ * Sets a whitelist of allowed URL schemes that are safe to open.
+ * Schemes should all be in lowercase. If the plugin is set to block opening
+ * unsafe schemes, user-entered URLs will be converted to lowercase and checked
+ * against this list. The whitelist has no effect if blocking is not enabled.
+ * @param {Array<string>} schemes String array of URL schemes to allow (http,
+ * https, etc.).
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.setSafeToOpenSchemes =
+ function(schemes) {
+ this.safeToOpenSchemes_ = schemes;
+};
+
+
+/**
+ * Tells the dialog to show a checkbox where the user can choose to have the
+ * link open in a new window.
+ * @param {boolean} startChecked Whether to check the checkbox the first
+ * time the dialog is shown. Subesquent times the checkbox will remember its
+ * previous state.
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.showOpenLinkInNewWindow =
+ function(startChecked) {
+ this.showOpenLinkInNewWindow_ = true;
+ this.isOpenLinkInNewWindowChecked_ = startChecked;
+};
+
+
+/**
+ * Tells the dialog to show a checkbox where the user can choose to have
+ * 'rel=nofollow' attribute added to the link.
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.showRelNoFollow = function() {
+ this.showRelNoFollow_ = true;
+};
+
+
+/**
+ * Returns whether the"open link in new window" checkbox was checked last time
+ * the dialog was closed.
+ * @return {boolean} Whether the"open link in new window" checkbox was checked
+ * last time the dialog was closed.
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.
+ getOpenLinkInNewWindowCheckedState = function() {
+ return this.isOpenLinkInNewWindowChecked_;
+};
+
+
+/**
+ * Tells the plugin to stop leaking the page's url via the referrer header when
+ * the "test this link" link is clicked. When the user clicks on a link, the
+ * browser makes a request for the link url, passing the url of the current page
+ * in the request headers. If the user wants the current url to be kept secret
+ * (e.g. an unpublished document), the owner of the url that was clicked will
+ * see the secret url in the request headers, and it will no longer be a secret.
+ * Calling this method will not send a referrer header in the request, just as
+ * if the user had opened a blank window and typed the url in themselves.
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.stopReferrerLeaks = function() {
+ this.stopReferrerLeaks_ = true;
+};
+
+
+/**
+ * Sets the warning message to show to users about including email addresses on
+ * public web pages.
+ * @param {!goog.html.SafeHtml} emailWarning Warning message to show users about
+ * including email addresses on the web.
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.setEmailWarning = function(
+ emailWarning) {
+ this.emailWarning_ = emailWarning;
+};
+
+
+/**
+ * Handles execCommand by opening the dialog.
+ * @param {string} command The command to execute.
+ * @param {*=} opt_arg {@link A goog.editor.Link} object representing the link
+ * being edited.
+ * @return {*} Always returns true, indicating the dialog was shown.
+ * @protected
+ * @override
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.execCommandInternal = function(
+ command, opt_arg) {
+ this.currentLink_ = /** @type {goog.editor.Link} */(opt_arg);
+ return goog.editor.plugins.LinkDialogPlugin.base(
+ this, 'execCommandInternal', command, opt_arg);
+};
+
+
+/**
+ * Handles when the dialog closes.
+ * @param {goog.events.Event} e The AFTER_HIDE event object.
+ * @override
+ * @protected
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.handleAfterHide = function(e) {
+ goog.editor.plugins.LinkDialogPlugin.base(this, 'handleAfterHide', e);
+ this.currentLink_ = null;
+};
+
+
+/**
+ * @return {goog.events.EventHandler<T>} The event handler.
+ * @protected
+ * @this T
+ * @template T
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.getEventHandler = function() {
+ return this.eventHandler_;
+};
+
+
+/**
+ * @return {goog.editor.Link} The link being edited.
+ * @protected
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.getCurrentLink = function() {
+ return this.currentLink_;
+};
+
+
+/**
+ * Creates a new instance of the dialog and registers for the relevant events.
+ * @param {goog.dom.DomHelper} dialogDomHelper The dom helper to be used to
+ * create the dialog.
+ * @param {*=} opt_link The target link (should be a goog.editor.Link).
+ * @return {!goog.ui.editor.LinkDialog} The dialog.
+ * @override
+ * @protected
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.createDialog = function(
+ dialogDomHelper, opt_link) {
+ var dialog = new goog.ui.editor.LinkDialog(dialogDomHelper,
+ /** @type {goog.editor.Link} */ (opt_link));
+ if (this.emailWarning_) {
+ dialog.setEmailWarning(this.emailWarning_);
+ }
+ if (this.showOpenLinkInNewWindow_) {
+ dialog.showOpenLinkInNewWindow(this.isOpenLinkInNewWindowChecked_);
+ }
+ if (this.showRelNoFollow_) {
+ dialog.showRelNoFollow();
+ }
+ dialog.setStopReferrerLeaks(this.stopReferrerLeaks_);
+ this.eventHandler_.
+ listen(dialog, goog.ui.editor.AbstractDialog.EventType.OK,
+ this.handleOk).
+ listen(dialog, goog.ui.editor.AbstractDialog.EventType.CANCEL,
+ this.handleCancel_).
+ listen(dialog, goog.ui.editor.LinkDialog.EventType.BEFORE_TEST_LINK,
+ this.handleBeforeTestLink);
+ return dialog;
+};
+
+
+/** @override */
+goog.editor.plugins.LinkDialogPlugin.prototype.disposeInternal = function() {
+ goog.editor.plugins.LinkDialogPlugin.base(this, 'disposeInternal');
+ this.eventHandler_.dispose();
+};
+
+
+/**
+ * Handles the OK event from the dialog by updating the link in the field.
+ * @param {goog.ui.editor.LinkDialog.OkEvent} e OK event object.
+ * @protected
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.handleOk = function(e) {
+ // We're not restoring the original selection, so clear it out.
+ this.disposeOriginalSelection();
+
+ this.currentLink_.setTextAndUrl(e.linkText, e.linkUrl);
+ if (this.showOpenLinkInNewWindow_) {
+ // Save checkbox state for next time.
+ this.isOpenLinkInNewWindowChecked_ = e.openInNewWindow;
+ }
+
+ var anchor = this.currentLink_.getAnchor();
+ this.touchUpAnchorOnOk_(anchor, e);
+ var extraAnchors = this.currentLink_.getExtraAnchors();
+ for (var i = 0; i < extraAnchors.length; ++i) {
+ extraAnchors[i].href = anchor.href;
+ this.touchUpAnchorOnOk_(extraAnchors[i], e);
+ }
+
+ // Place cursor to the right of the modified link.
+ this.currentLink_.placeCursorRightOf();
+
+ this.getFieldObject().focus();
+
+ this.getFieldObject().dispatchSelectionChangeEvent();
+ this.getFieldObject().dispatchChange();
+
+ this.eventHandler_.removeAll();
+};
+
+
+/**
+ * Apply the necessary properties to a link upon Ok being clicked in the dialog.
+ * @param {HTMLAnchorElement} anchor The anchor to set properties on.
+ * @param {goog.events.Event} e Event object.
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.touchUpAnchorOnOk_ =
+ function(anchor, e) {
+ if (this.showOpenLinkInNewWindow_) {
+ if (e.openInNewWindow) {
+ anchor.target = '_blank';
+ } else {
+ if (anchor.target == '_blank') {
+ anchor.target = '';
+ }
+ // If user didn't indicate to open in a new window but the link already
+ // had a target other than '_blank', let's leave what they had before.
+ }
+ }
+
+ if (this.showRelNoFollow_) {
+ var alreadyPresent = goog.ui.editor.LinkDialog.hasNoFollow(anchor.rel);
+ if (alreadyPresent && !e.noFollow) {
+ anchor.rel = goog.ui.editor.LinkDialog.removeNoFollow(anchor.rel);
+ } else if (!alreadyPresent && e.noFollow) {
+ anchor.rel = anchor.rel ? anchor.rel + ' nofollow' : 'nofollow';
+ }
+ }
+};
+
+
+/**
+ * Handles the CANCEL event from the dialog by clearing the anchor if needed.
+ * @param {goog.events.Event} e Event object.
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.handleCancel_ = function(e) {
+ if (this.currentLink_.isNew()) {
+ goog.dom.flattenElement(this.currentLink_.getAnchor());
+ var extraAnchors = this.currentLink_.getExtraAnchors();
+ for (var i = 0; i < extraAnchors.length; ++i) {
+ goog.dom.flattenElement(extraAnchors[i]);
+ }
+ // Make sure listeners know the anchor was flattened out.
+ this.getFieldObject().dispatchChange();
+ }
+
+ this.eventHandler_.removeAll();
+};
+
+
+/**
+ * Handles the BeforeTestLink event fired when the 'test' link is clicked.
+ * @param {goog.ui.editor.LinkDialog.BeforeTestLinkEvent} e BeforeTestLink event
+ * object.
+ * @protected
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.handleBeforeTestLink =
+ function(e) {
+ if (!this.shouldOpenUrl(e.url)) {
+ /** @desc Message when the user tries to test (preview) a link, but the
+ * link cannot be tested. */
+ var MSG_UNSAFE_LINK = goog.getMsg('This link cannot be tested.');
+ alert(MSG_UNSAFE_LINK);
+ e.preventDefault();
+ }
+};
+
+
+/**
+ * Checks whether the plugin should open the given url in a new window.
+ * @param {string} url The url to check.
+ * @return {boolean} If the plugin should open the given url in a new window.
+ * @protected
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.shouldOpenUrl = function(url) {
+ return !this.blockOpeningUnsafeSchemes_ || this.isSafeSchemeToOpen_(url);
+};
+
+
+/**
+ * Determines whether or not a url has a scheme which is safe to open.
+ * Schemes like javascript are unsafe due to the possibility of XSS.
+ * @param {string} url A url.
+ * @return {boolean} Whether the url has a safe scheme.
+ * @private
+ */
+goog.editor.plugins.LinkDialogPlugin.prototype.isSafeSchemeToOpen_ =
+ function(url) {
+ var scheme = goog.uri.utils.getScheme(url) || 'http';
+ return goog.array.contains(this.safeToOpenSchemes_, scheme.toLowerCase());
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/linkshortcutplugin.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/linkshortcutplugin.js b/externs/GCL/externs/goog/editor/plugins/linkshortcutplugin.js
new file mode 100644
index 0000000..b77910c
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/linkshortcutplugin.js
@@ -0,0 +1,61 @@
+// 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 Adds a keyboard shortcut for the link command.
+ *
+ */
+
+goog.provide('goog.editor.plugins.LinkShortcutPlugin');
+
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Plugin');
+
+
+
+/**
+ * Plugin to add a keyboard shortcut for the link command
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.LinkShortcutPlugin = function() {
+ goog.editor.plugins.LinkShortcutPlugin.base(this, 'constructor');
+};
+goog.inherits(goog.editor.plugins.LinkShortcutPlugin, goog.editor.Plugin);
+
+
+/** @override */
+goog.editor.plugins.LinkShortcutPlugin.prototype.getTrogClassId = function() {
+ return 'LinkShortcutPlugin';
+};
+
+
+/**
+ * @override
+ */
+goog.editor.plugins.LinkShortcutPlugin.prototype.handleKeyboardShortcut =
+ function(e, key, isModifierPressed) {
+ if (isModifierPressed && key == 'k' && !e.shiftKey) {
+ var link = /** @type {goog.editor.Link?} */ (
+ this.getFieldObject().execCommand(goog.editor.Command.LINK));
+ if (link) {
+ link.finishLinkCreation(this.getFieldObject());
+ }
+ return true;
+ }
+
+ return false;
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/listtabhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/listtabhandler.js b/externs/GCL/externs/goog/editor/plugins/listtabhandler.js
new file mode 100644
index 0000000..03f78ca
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/listtabhandler.js
@@ -0,0 +1,68 @@
+// 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 Editor plugin to handle tab keys in lists to indent and
+ * outdent.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.ListTabHandler');
+
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.plugins.AbstractTabHandler');
+goog.require('goog.iter');
+
+
+
+/**
+ * Plugin to handle tab keys in lists to indent and outdent.
+ * @constructor
+ * @extends {goog.editor.plugins.AbstractTabHandler}
+ * @final
+ */
+goog.editor.plugins.ListTabHandler = function() {
+ goog.editor.plugins.AbstractTabHandler.call(this);
+};
+goog.inherits(goog.editor.plugins.ListTabHandler,
+ goog.editor.plugins.AbstractTabHandler);
+
+
+/** @override */
+goog.editor.plugins.ListTabHandler.prototype.getTrogClassId = function() {
+ return 'ListTabHandler';
+};
+
+
+/** @override */
+goog.editor.plugins.ListTabHandler.prototype.handleTabKey = function(e) {
+ var range = this.getFieldObject().getRange();
+ if (goog.dom.getAncestorByTagNameAndClass(range.getContainerElement(),
+ goog.dom.TagName.LI) ||
+ goog.iter.some(range, function(node) {
+ return node.tagName == goog.dom.TagName.LI;
+ })) {
+ this.getFieldObject().execCommand(e.shiftKey ?
+ goog.editor.Command.OUTDENT :
+ goog.editor.Command.INDENT);
+ e.preventDefault();
+ return true;
+ }
+
+ return false;
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/loremipsum.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/loremipsum.js b/externs/GCL/externs/goog/editor/plugins/loremipsum.js
new file mode 100644
index 0000000..90ba31d
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/loremipsum.js
@@ -0,0 +1,192 @@
+// 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 A plugin that fills the field with lorem ipsum text when it's
+ * empty and does not have the focus. Applies to both editable and uneditable
+ * fields.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.plugins.LoremIpsum');
+
+goog.require('goog.asserts');
+goog.require('goog.dom');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Field');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.node');
+goog.require('goog.functions');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A plugin that manages lorem ipsum state of editable fields.
+ * @param {string} message The lorem ipsum message.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.LoremIpsum = function(message) {
+ goog.editor.Plugin.call(this);
+
+ /**
+ * The lorem ipsum message.
+ * @type {string}
+ * @private
+ */
+ this.message_ = message;
+};
+goog.inherits(goog.editor.plugins.LoremIpsum, goog.editor.Plugin);
+
+
+/** @override */
+goog.editor.plugins.LoremIpsum.prototype.getTrogClassId =
+ goog.functions.constant('LoremIpsum');
+
+
+/** @override */
+goog.editor.plugins.LoremIpsum.prototype.activeOnUneditableFields =
+ goog.functions.TRUE;
+
+
+/**
+ * Whether the field is currently filled with lorem ipsum text.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LoremIpsum.prototype.usingLorem_ = false;
+
+
+/**
+ * Handles queryCommandValue.
+ * @param {string} command The command to query.
+ * @return {boolean} The result.
+ * @override
+ */
+goog.editor.plugins.LoremIpsum.prototype.queryCommandValue = function(command) {
+ return command == goog.editor.Command.USING_LOREM && this.usingLorem_;
+};
+
+
+/**
+ * Handles execCommand.
+ * @param {string} command The command to execute.
+ * Should be CLEAR_LOREM or UPDATE_LOREM.
+ * @param {*=} opt_placeCursor Whether to place the cursor in the field
+ * after clearing lorem. Should be a boolean.
+ * @override
+ */
+goog.editor.plugins.LoremIpsum.prototype.execCommand = function(command,
+ opt_placeCursor) {
+ if (command == goog.editor.Command.CLEAR_LOREM) {
+ this.clearLorem_(!!opt_placeCursor);
+ } else if (command == goog.editor.Command.UPDATE_LOREM) {
+ this.updateLorem_();
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.LoremIpsum.prototype.isSupportedCommand =
+ function(command) {
+ return command == goog.editor.Command.CLEAR_LOREM ||
+ command == goog.editor.Command.UPDATE_LOREM ||
+ command == goog.editor.Command.USING_LOREM;
+};
+
+
+/**
+ * Set the lorem ipsum text in a goog.editor.Field if needed.
+ * @private
+ */
+goog.editor.plugins.LoremIpsum.prototype.updateLorem_ = function() {
+ // Try to apply lorem ipsum if:
+ // 1) We have lorem ipsum text
+ // 2) There's not a dialog open, as that screws
+ // with the dialog's ability to properly restore the selection
+ // on dialog close (since the DOM nodes would get clobbered in FF)
+ // 3) We're not using lorem already
+ // 4) The field is not currently active (doesn't have focus).
+ var fieldObj = this.getFieldObject();
+ if (!this.usingLorem_ &&
+ !fieldObj.inModalMode() &&
+ goog.editor.Field.getActiveFieldId() != fieldObj.id) {
+ var field = fieldObj.getElement();
+ if (!field) {
+ // Fallback on the original element. This is needed by
+ // fields managed by click-to-edit.
+ field = fieldObj.getOriginalElement();
+ }
+
+ goog.asserts.assert(field);
+ if (goog.editor.node.isEmpty(field)) {
+ this.usingLorem_ = true;
+
+ // Save the old font style so it can be restored when we
+ // clear the lorem ipsum style.
+ this.oldFontStyle_ = field.style.fontStyle;
+ field.style.fontStyle = 'italic';
+ fieldObj.setHtml(true, this.message_, true);
+ }
+ }
+};
+
+
+/**
+ * Clear an EditableField's lorem ipsum and put in initial text if needed.
+ *
+ * If using click-to-edit mode (where Trogedit manages whether the field
+ * is editable), this works for both editable and uneditable fields.
+ *
+ * TODO(user): Is this really necessary? See TODO below.
+ * @param {boolean=} opt_placeCursor Whether to place the cursor in the field
+ * after clearing lorem.
+ * @private
+ */
+goog.editor.plugins.LoremIpsum.prototype.clearLorem_ = function(
+ opt_placeCursor) {
+ // Don't mess with lorem state when a dialog is open as that screws
+ // with the dialog's ability to properly restore the selection
+ // on dialog close (since the DOM nodes would get clobbered)
+ var fieldObj = this.getFieldObject();
+ if (this.usingLorem_ && !fieldObj.inModalMode()) {
+ var field = fieldObj.getElement();
+ if (!field) {
+ // Fallback on the original element. This is needed by
+ // fields managed by click-to-edit.
+ field = fieldObj.getOriginalElement();
+ }
+
+ goog.asserts.assert(field);
+ this.usingLorem_ = false;
+ field.style.fontStyle = this.oldFontStyle_;
+ fieldObj.setHtml(true, null, true);
+
+ // TODO(nicksantos): I'm pretty sure that this is a hack, but talk to
+ // Julie about why this is necessary and what to do with it. Really,
+ // we need to figure out where it's necessary and remove it where it's
+ // not. Safari never places the cursor on its own willpower.
+ if (opt_placeCursor && fieldObj.isLoaded()) {
+ if (goog.userAgent.WEBKIT) {
+ goog.dom.getOwnerDocument(fieldObj.getElement()).body.focus();
+ fieldObj.focusAndPlaceCursorAtStart();
+ } else if (goog.userAgent.OPERA) {
+ fieldObj.placeCursorAtStart();
+ }
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/removeformatting.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/removeformatting.js b/externs/GCL/externs/goog/editor/plugins/removeformatting.js
new file mode 100644
index 0000000..dd73a31
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/removeformatting.js
@@ -0,0 +1,780 @@
+// 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.
+// All Rights Reserved.
+
+/**
+ * @fileoverview Plugin to handle Remove Formatting.
+ *
+ */
+
+goog.provide('goog.editor.plugins.RemoveFormatting');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.node');
+goog.require('goog.editor.range');
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A plugin to handle removing formatting from selected text.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.RemoveFormatting = function() {
+ goog.editor.Plugin.call(this);
+
+ /**
+ * Optional function to perform remove formatting in place of the
+ * provided removeFormattingWorker_.
+ * @type {?function(string): string}
+ * @private
+ */
+ this.optRemoveFormattingFunc_ = null;
+};
+goog.inherits(goog.editor.plugins.RemoveFormatting, goog.editor.Plugin);
+
+
+/**
+ * The editor command this plugin in handling.
+ * @type {string}
+ */
+goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND =
+ '+removeFormat';
+
+
+/**
+ * Regular expression that matches a block tag name.
+ * @type {RegExp}
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.BLOCK_RE_ =
+ /^(DIV|TR|LI|BLOCKQUOTE|H\d|PRE|XMP)/;
+
+
+/**
+ * Appends a new line to a string buffer.
+ * @param {Array<string>} sb The string buffer to add to.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.appendNewline_ = function(sb) {
+ sb.push('<br>');
+};
+
+
+/**
+ * Create a new range delimited by the start point of the first range and
+ * the end point of the second range.
+ * @param {goog.dom.AbstractRange} startRange Use the start point of this
+ * range as the beginning of the new range.
+ * @param {goog.dom.AbstractRange} endRange Use the end point of this
+ * range as the end of the new range.
+ * @return {!goog.dom.AbstractRange} The new range.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.createRangeDelimitedByRanges_ = function(
+ startRange, endRange) {
+ return goog.dom.Range.createFromNodes(
+ startRange.getStartNode(), startRange.getStartOffset(),
+ endRange.getEndNode(), endRange.getEndOffset());
+};
+
+
+/** @override */
+goog.editor.plugins.RemoveFormatting.prototype.getTrogClassId = function() {
+ return 'RemoveFormatting';
+};
+
+
+/** @override */
+goog.editor.plugins.RemoveFormatting.prototype.isSupportedCommand = function(
+ command) {
+ return command ==
+ goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND;
+};
+
+
+/** @override */
+goog.editor.plugins.RemoveFormatting.prototype.execCommandInternal =
+ function(command, var_args) {
+ if (command ==
+ goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND) {
+ this.removeFormatting_();
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.RemoveFormatting.prototype.handleKeyboardShortcut =
+ function(e, key, isModifierPressed) {
+ if (!isModifierPressed) {
+ return false;
+ }
+
+ if (key == ' ') {
+ this.getFieldObject().execCommand(
+ goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND);
+ return true;
+ }
+
+ return false;
+};
+
+
+/**
+ * Removes formatting from the current selection. Removes basic formatting
+ * (B/I/U) using the browser's execCommand. Then extracts the html from the
+ * selection to convert, calls either a client's specified removeFormattingFunc
+ * callback or trogedit's general built-in removeFormattingWorker_,
+ * and then replaces the current selection with the converted text.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.removeFormatting_ = function() {
+ var range = this.getFieldObject().getRange();
+ if (range.isCollapsed()) {
+ return;
+ }
+
+ // Get the html to format and send it off for formatting. Built in
+ // removeFormat only strips some inline elements and some inline CSS styles
+ var convFunc = this.optRemoveFormattingFunc_ ||
+ goog.bind(this.removeFormattingWorker_, this);
+ this.convertSelectedHtmlText_(convFunc);
+
+ // Do the execCommand last as it needs block elements removed to work
+ // properly on background/fontColor in FF. There are, unfortunately, still
+ // cases where background/fontColor are not removed here.
+ var doc = this.getFieldDomHelper().getDocument();
+ doc.execCommand('RemoveFormat', false, undefined);
+
+ if (goog.editor.BrowserFeature.ADDS_NBSPS_IN_REMOVE_FORMAT) {
+ // WebKit converts spaces to non-breaking spaces when doing a RemoveFormat.
+ // See: https://bugs.webkit.org/show_bug.cgi?id=14062
+ this.convertSelectedHtmlText_(function(text) {
+ // This loses anything that might have legitimately been a non-breaking
+ // space, but that's better than the alternative of only having non-
+ // breaking spaces.
+ // Old versions of WebKit (Safari 3, Chrome 1) incorrectly match /u00A0
+ // and newer versions properly match .
+ var nbspRegExp =
+ goog.userAgent.isVersionOrHigher('528') ? / /g : /\u00A0/g;
+ return text.replace(nbspRegExp, ' ');
+ });
+ }
+};
+
+
+/**
+ * Finds the nearest ancestor of the node that is a table.
+ * @param {Node} nodeToCheck Node to search from.
+ * @return {Node} The table, or null if one was not found.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.getTableAncestor_ = function(
+ nodeToCheck) {
+ var fieldElement = this.getFieldObject().getElement();
+ while (nodeToCheck && nodeToCheck != fieldElement) {
+ if (nodeToCheck.tagName == goog.dom.TagName.TABLE) {
+ return nodeToCheck;
+ }
+ nodeToCheck = nodeToCheck.parentNode;
+ }
+ return null;
+};
+
+
+/**
+ * Replaces the contents of the selection with html. Does its best to maintain
+ * the original selection. Also does its best to result in a valid DOM.
+ *
+ * TODO(user): See if there's any way to make this work on Ranges, and then
+ * move it into goog.editor.range. The Firefox implementation uses execCommand
+ * on the document, so must work on the actual selection.
+ *
+ * @param {string} html The html string to insert into the range.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.pasteHtml_ = function(html) {
+ var range = this.getFieldObject().getRange();
+
+ var dh = this.getFieldDomHelper();
+ // Use markers to set the extent of the selection so that we can reselect it
+ // afterwards. This works better than builtin range manipulation in FF and IE
+ // because their implementations are so self-inconsistent and buggy.
+ var startSpanId = goog.string.createUniqueString();
+ var endSpanId = goog.string.createUniqueString();
+ html = '<span id="' + startSpanId + '"></span>' + html +
+ '<span id="' + endSpanId + '"></span>';
+ var dummyNodeId = goog.string.createUniqueString();
+ var dummySpanText = '<span id="' + dummyNodeId + '"></span>';
+
+ if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
+ // IE's selection often doesn't include the outermost tags.
+ // We want to use pasteHTML to replace the range contents with the newly
+ // unformatted text, so we have to check to make sure we aren't just
+ // pasting into some stray tags. To do this, we first clear out the
+ // contents of the range and then delete all empty nodes parenting the now
+ // empty range. This way, the pasted contents are never re-embedded into
+ // formated nodes. Pasting purely empty html does not work, since IE moves
+ // the selection inside the next node, so we insert a dummy span.
+ var textRange = range.getTextRange(0).getBrowserRangeObject();
+ textRange.pasteHTML(dummySpanText);
+ var parent;
+ while ((parent = textRange.parentElement()) &&
+ goog.editor.node.isEmpty(parent) &&
+ !goog.editor.node.isEditableContainer(parent)) {
+ var tag = parent.nodeName;
+ // We can't remove these table tags as it will invalidate the table dom.
+ if (tag == goog.dom.TagName.TD ||
+ tag == goog.dom.TagName.TR ||
+ tag == goog.dom.TagName.TH) {
+ break;
+ }
+
+ goog.dom.removeNode(parent);
+ }
+ textRange.pasteHTML(html);
+ var dummySpan = dh.getElement(dummyNodeId);
+ // If we entered the while loop above, the node has already been removed
+ // since it was a child of parent and parent was removed.
+ if (dummySpan) {
+ goog.dom.removeNode(dummySpan);
+ }
+ } else if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
+ // insertHtml and range.insertNode don't merge blocks correctly.
+ // (e.g. if your selection spans two paragraphs)
+ dh.getDocument().execCommand('insertImage', false, dummyNodeId);
+ var dummyImageNodePattern = new RegExp('<[^<]*' + dummyNodeId + '[^>]*>');
+ var parent = this.getFieldObject().getRange().getContainerElement();
+ if (parent.nodeType == goog.dom.NodeType.TEXT) {
+ // Opera sometimes returns a text node here.
+ // TODO(user): perhaps we should modify getParentContainer?
+ parent = parent.parentNode;
+ }
+
+ // We have to search up the DOM because in some cases, notably when
+ // selecting li's within a list, execCommand('insertImage') actually splits
+ // tags in such a way that parent that used to contain the selection does
+ // not contain inserted image.
+ while (!dummyImageNodePattern.test(parent.innerHTML)) {
+ parent = parent.parentNode;
+ }
+
+ // Like the IE case above, sometimes the selection does not include the
+ // outermost tags. For Gecko, we have already expanded the range so that
+ // it does, so we can just replace the dummy image with the final html.
+ // For WebKit, we use the same approach as we do with IE - we
+ // inject a dummy span where we will eventually place the contents, and
+ // remove parentNodes of the span while they are empty.
+
+ if (goog.userAgent.GECKO) {
+ goog.editor.node.replaceInnerHtml(parent,
+ parent.innerHTML.replace(dummyImageNodePattern, html));
+ } else {
+ goog.editor.node.replaceInnerHtml(parent,
+ parent.innerHTML.replace(dummyImageNodePattern, dummySpanText));
+ var dummySpan = dh.getElement(dummyNodeId);
+ parent = dummySpan;
+ while ((parent = dummySpan.parentNode) &&
+ goog.editor.node.isEmpty(parent) &&
+ !goog.editor.node.isEditableContainer(parent)) {
+ var tag = parent.nodeName;
+ // We can't remove these table tags as it will invalidate the table dom.
+ if (tag == goog.dom.TagName.TD ||
+ tag == goog.dom.TagName.TR ||
+ tag == goog.dom.TagName.TH) {
+ break;
+ }
+
+ // We can't just remove parent since dummySpan is inside it, and we need
+ // to keep dummy span around for the replacement. So we move the
+ // dummySpan up as we go.
+ goog.dom.insertSiblingAfter(dummySpan, parent);
+ goog.dom.removeNode(parent);
+ }
+ goog.editor.node.replaceInnerHtml(parent,
+ parent.innerHTML.replace(new RegExp(dummySpanText, 'i'), html));
+ }
+ }
+
+ var startSpan = dh.getElement(startSpanId);
+ var endSpan = dh.getElement(endSpanId);
+ goog.dom.Range.createFromNodes(startSpan, 0, endSpan,
+ endSpan.childNodes.length).select();
+ goog.dom.removeNode(startSpan);
+ goog.dom.removeNode(endSpan);
+};
+
+
+/**
+ * Gets the html inside the selection to send off for further processing.
+ *
+ * TODO(user): Make this general so that it can be moved into
+ * goog.editor.range. The main reason it can't be moved is becuase we need to
+ * get the range before we do the execCommand and continue to operate on that
+ * same range (reasons are documented above).
+ *
+ * @param {goog.dom.AbstractRange} range The selection.
+ * @return {string} The html string to format.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.getHtmlText_ = function(range) {
+ var div = this.getFieldDomHelper().createDom(goog.dom.TagName.DIV);
+ var textRange = range.getBrowserRangeObject();
+
+ if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
+ // Get the text to convert.
+ div.appendChild(textRange.cloneContents());
+ } else if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
+ // Trim the whitespace on the ends of the range, so that it the container
+ // will be the container of only the text content that we are changing.
+ // This gets around issues in IE where the spaces are included in the
+ // selection, but ignored sometimes by execCommand, and left orphaned.
+ var rngText = range.getText();
+
+ // BRs get reported as \r\n, but only count as one character for moves.
+ // Adjust the string so our move counter is correct.
+ rngText = rngText.replace(/\r\n/g, '\r');
+
+ var rngTextLength = rngText.length;
+ var left = rngTextLength - goog.string.trimLeft(rngText).length;
+ var right = rngTextLength - goog.string.trimRight(rngText).length;
+
+ textRange.moveStart('character', left);
+ textRange.moveEnd('character', -right);
+
+ var htmlText = textRange.htmlText;
+ // Check if in pretag and fix up formatting so that new lines are preserved.
+ if (textRange.queryCommandValue('formatBlock') == 'Formatted') {
+ htmlText = goog.string.newLineToBr(textRange.htmlText);
+ }
+ div.innerHTML = htmlText;
+ }
+
+ // Get the innerHTML of the node instead of just returning the text above
+ // so that its properly html escaped.
+ return div.innerHTML;
+};
+
+
+/**
+ * Move the range so that it doesn't include any partially selected tables.
+ * @param {goog.dom.AbstractRange} range The range to adjust.
+ * @param {Node} startInTable Table node that the range starts in.
+ * @param {Node} endInTable Table node that the range ends in.
+ * @return {!goog.dom.SavedCaretRange} Range to use to restore the
+ * selection after we run our custom remove formatting.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.adjustRangeForTables_ =
+ function(range, startInTable, endInTable) {
+ // Create placeholders for the current selection so we can restore it
+ // later.
+ var savedCaretRange = goog.editor.range.saveUsingNormalizedCarets(range);
+
+ var startNode = range.getStartNode();
+ var startOffset = range.getStartOffset();
+ var endNode = range.getEndNode();
+ var endOffset = range.getEndOffset();
+ var dh = this.getFieldDomHelper();
+
+ // Move start after the table.
+ if (startInTable) {
+ var textNode = dh.createTextNode('');
+ goog.dom.insertSiblingAfter(textNode, startInTable);
+ startNode = textNode;
+ startOffset = 0;
+ }
+ // Move end before the table.
+ if (endInTable) {
+ var textNode = dh.createTextNode('');
+ goog.dom.insertSiblingBefore(textNode, endInTable);
+ endNode = textNode;
+ endOffset = 0;
+ }
+
+ goog.dom.Range.createFromNodes(startNode, startOffset,
+ endNode, endOffset).select();
+
+ return savedCaretRange;
+};
+
+
+/**
+ * Remove a caret from the dom and hide it in a safe place, so it can
+ * be restored later via restoreCaretsFromCave.
+ * @param {goog.dom.SavedCaretRange} caretRange The caret range to
+ * get the carets from.
+ * @param {boolean} isStart Whether this is the start or end caret.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.putCaretInCave_ = function(
+ caretRange, isStart) {
+ var cavedCaret = goog.dom.removeNode(caretRange.getCaret(isStart));
+ if (isStart) {
+ this.startCaretInCave_ = cavedCaret;
+ } else {
+ this.endCaretInCave_ = cavedCaret;
+ }
+};
+
+
+/**
+ * Restore carets that were hidden away by adding them back into the dom.
+ * Note: this does not restore to the original dom location, as that
+ * will likely have been modified with remove formatting. The only
+ * guarentees here are that start will still be before end, and that
+ * they will be in the editable region. This should only be used when
+ * you don't actually intend to USE the caret again.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.restoreCaretsFromCave_ =
+ function() {
+ // To keep start before end, we put the end caret at the bottom of the field
+ // and the start caret at the start of the field.
+ var field = this.getFieldObject().getElement();
+ if (this.startCaretInCave_) {
+ field.insertBefore(this.startCaretInCave_, field.firstChild);
+ this.startCaretInCave_ = null;
+ }
+ if (this.endCaretInCave_) {
+ field.appendChild(this.endCaretInCave_);
+ this.endCaretInCave_ = null;
+ }
+};
+
+
+/**
+ * Gets the html inside the current selection, passes it through the given
+ * conversion function, and puts it back into the selection.
+ *
+ * @param {function(string): string} convertFunc A conversion function that
+ * transforms an html string to new html string.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.convertSelectedHtmlText_ =
+ function(convertFunc) {
+ var range = this.getFieldObject().getRange();
+
+ // For multiple ranges, it is really hard to do our custom remove formatting
+ // without invalidating other ranges. So instead of always losing the
+ // content, this solution at least lets the browser do its own remove
+ // formatting which works correctly most of the time.
+ if (range.getTextRangeCount() > 1) {
+ return;
+ }
+
+ if (goog.userAgent.GECKO) {
+ // Determine if we need to handle tables, since they are special cases.
+ // If the selection is entirely within a table, there is no extra
+ // formatting removal we can do. If a table is fully selected, we will
+ // just blow it away. If a table is only partially selected, we can
+ // perform custom remove formatting only on the non table parts, since we
+ // we can't just remove the parts and paste back into it (eg. we can't
+ // inject html where a TR used to be).
+ // If the selection contains the table and more, this is automatically
+ // handled, but if just the table is selected, it can be tricky to figure
+ // this case out, because of the numerous ways selections can be formed -
+ // ex. if a table has a single tr with a single td with a single text node
+ // in it, and the selection is (textNode: 0), (textNode: nextNode.length)
+ // then the entire table is selected, even though the start and end aren't
+ // the table itself. We are truly inside a table if the expanded endpoints
+ // are still inside the table.
+
+ // Expand the selection to include any outermost tags that weren't included
+ // in the selection, but have the same visible selection. Stop expanding
+ // if we reach the top level field.
+ var expandedRange = goog.editor.range.expand(range,
+ this.getFieldObject().getElement());
+
+ var startInTable = this.getTableAncestor_(expandedRange.getStartNode());
+ var endInTable = this.getTableAncestor_(expandedRange.getEndNode());
+
+ if (startInTable || endInTable) {
+ if (startInTable == endInTable) {
+ // We are fully contained in the same table, there is no extra
+ // remove formatting that we can do, just return and run browser
+ // formatting only.
+ return;
+ }
+
+ // Adjust the range to not contain any partially selected tables, since
+ // we don't want to run our custom remove formatting on them.
+ var savedCaretRange = this.adjustRangeForTables_(range,
+ startInTable, endInTable);
+
+ // Hack alert!!
+ // If start is not in a table, then the saved caret will get sent out
+ // for uber remove formatting, and it will get blown away. This is
+ // fine, except that we need to be able to re-create a range from the
+ // savedCaretRange later on. So, we just remove it from the dom, and
+ // put it back later so we can create a range later (not exactly in the
+ // same spot, but don't worry we don't actually try to use it later)
+ // and then it will be removed when we dispose the range.
+ if (!startInTable) {
+ this.putCaretInCave_(savedCaretRange, true);
+ }
+ if (!endInTable) {
+ this.putCaretInCave_(savedCaretRange, false);
+ }
+
+ // Re-fetch the range, and re-expand it, since we just modified it.
+ range = this.getFieldObject().getRange();
+ expandedRange = goog.editor.range.expand(range,
+ this.getFieldObject().getElement());
+ }
+
+ expandedRange.select();
+ range = expandedRange;
+ }
+
+ // Convert the selected text to the format-less version, paste back into
+ // the selection.
+ var text = this.getHtmlText_(range);
+ this.pasteHtml_(convertFunc(text));
+
+ if (goog.userAgent.GECKO && savedCaretRange) {
+ // If we moved the selection, move it back so the user can't tell we did
+ // anything crazy and so the browser removeFormat that we call next
+ // will operate on the entire originally selected range.
+ range = this.getFieldObject().getRange();
+ this.restoreCaretsFromCave_();
+ var realSavedCaretRange = savedCaretRange.toAbstractRange();
+ var startRange = startInTable ? realSavedCaretRange : range;
+ var endRange = endInTable ? realSavedCaretRange : range;
+ var restoredRange =
+ goog.editor.plugins.RemoveFormatting.createRangeDelimitedByRanges_(
+ startRange, endRange);
+ restoredRange.select();
+ savedCaretRange.dispose();
+ }
+};
+
+
+/**
+ * Does a best-effort attempt at clobbering all formatting that the
+ * browser's execCommand couldn't clobber without being totally inefficient.
+ * Attempts to convert visual line breaks to BRs. Leaves anchors that contain an
+ * href and images.
+ * Adapted from Gmail's MessageUtil's htmlToPlainText. http://go/messageutil.js
+ * @param {string} html The original html of the message.
+ * @return {string} The unformatted html, which is just text, br's, anchors and
+ * images.
+ * @private
+ */
+goog.editor.plugins.RemoveFormatting.prototype.removeFormattingWorker_ =
+ function(html) {
+ var el = goog.dom.createElement(goog.dom.TagName.DIV);
+ el.innerHTML = html;
+
+ // Put everything into a string buffer to avoid lots of expensive string
+ // concatenation along the way.
+ var sb = [];
+ var stack = [el.childNodes, 0];
+
+ // Keep separate stacks for places where we need to keep track of
+ // how deeply embedded we are. These are analogous to the general stack.
+ var preTagStack = [];
+ var preTagLevel = 0; // Length of the prestack.
+ var tableStack = [];
+ var tableLevel = 0;
+
+ // sp = stack pointer, pointing to the stack array.
+ // decrement by 2 since the stack alternates node lists and
+ // processed node counts
+ for (var sp = 0; sp >= 0; sp -= 2) {
+ // Check if we should pop the table level.
+ var changedLevel = false;
+ while (tableLevel > 0 && sp <= tableStack[tableLevel - 1]) {
+ tableLevel--;
+ changedLevel = true;
+ }
+ if (changedLevel) {
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ }
+
+
+ // Check if we should pop the <pre>/<xmp> level.
+ changedLevel = false;
+ while (preTagLevel > 0 && sp <= preTagStack[preTagLevel - 1]) {
+ preTagLevel--;
+ changedLevel = true;
+ }
+ if (changedLevel) {
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ }
+
+ // The list of of nodes to process at the current stack level.
+ var nodeList = stack[sp];
+ // The number of nodes processed so far, stored in the stack immediately
+ // following the node list for that stack level.
+ var numNodesProcessed = stack[sp + 1];
+
+ while (numNodesProcessed < nodeList.length) {
+ var node = nodeList[numNodesProcessed++];
+ var nodeName = node.nodeName;
+
+ var formatted = this.getValueForNode(node);
+ if (goog.isDefAndNotNull(formatted)) {
+ sb.push(formatted);
+ continue;
+ }
+
+ // TODO(user): Handle case 'EMBED' and case 'OBJECT'.
+ switch (nodeName) {
+ case '#text':
+ // Note that IE does not preserve whitespace in the dom
+ // values, even in a pre tag, so this is useless for IE.
+ var nodeValue = preTagLevel > 0 ?
+ node.nodeValue :
+ goog.string.stripNewlines(node.nodeValue);
+ nodeValue = goog.string.htmlEscape(nodeValue);
+ sb.push(nodeValue);
+ continue;
+
+ case goog.dom.TagName.P:
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ break; // break (not continue) so that child nodes are processed.
+
+ case goog.dom.TagName.BR:
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ continue;
+
+ case goog.dom.TagName.TABLE:
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ tableStack[tableLevel++] = sp;
+ break;
+
+ case goog.dom.TagName.PRE:
+ case 'XMP':
+ // This doesn't fully handle xmp, since
+ // it doesn't actually ignore tags within the xmp tag.
+ preTagStack[preTagLevel++] = sp;
+ break;
+
+ case goog.dom.TagName.STYLE:
+ case goog.dom.TagName.SCRIPT:
+ case goog.dom.TagName.SELECT:
+ continue;
+
+ case goog.dom.TagName.A:
+ if (node.href && node.href != '') {
+ sb.push("<a href='");
+ sb.push(node.href);
+ sb.push("'>");
+ sb.push(this.removeFormattingWorker_(node.innerHTML));
+ sb.push('</a>');
+ continue; // Children taken care of.
+ } else {
+ break; // Take care of the children.
+ }
+
+ case goog.dom.TagName.IMG:
+ sb.push("<img src='");
+ sb.push(node.src);
+ sb.push("'");
+ // border=0 is a common way to not show a blue border around an image
+ // that is wrapped by a link. If we remove that, the blue border will
+ // show up, which to the user looks like adding format, not removing.
+ if (node.border == '0') {
+ sb.push(" border='0'");
+ }
+ sb.push('>');
+ continue;
+
+ case goog.dom.TagName.TD:
+ // Don't add a space for the first TD, we only want spaces to
+ // separate td's.
+ if (node.previousSibling) {
+ sb.push(' ');
+ }
+ break;
+
+ case goog.dom.TagName.TR:
+ // Don't add a newline for the first TR.
+ if (node.previousSibling) {
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ }
+ break;
+
+ case goog.dom.TagName.DIV:
+ var parent = node.parentNode;
+ if (parent.firstChild == node &&
+ goog.editor.plugins.RemoveFormatting.BLOCK_RE_.test(
+ parent.tagName)) {
+ // If a DIV is the first child of another element that itself is a
+ // block element, the DIV does not add a new line.
+ break;
+ }
+ // Otherwise, the DIV does add a new line. Fall through.
+
+ default:
+ if (goog.editor.plugins.RemoveFormatting.BLOCK_RE_.test(nodeName)) {
+ goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
+ }
+ }
+
+ // Recurse down the node.
+ var children = node.childNodes;
+ if (children.length > 0) {
+ // Push the current state on the stack.
+ stack[sp++] = nodeList;
+ stack[sp++] = numNodesProcessed;
+
+ // Iterate through the children nodes.
+ nodeList = children;
+ numNodesProcessed = 0;
+ }
+ }
+ }
+
+ // Replace with white space.
+ return goog.string.normalizeSpaces(sb.join(''));
+};
+
+
+/**
+ * Handle per node special processing if neccessary. If this function returns
+ * null then standard cleanup is applied. Otherwise this node and all children
+ * are assumed to be cleaned.
+ * NOTE(user): If an alternate RemoveFormatting processor is provided
+ * (setRemoveFormattingFunc()), this will no longer work.
+ * @param {Element} node The node to clean.
+ * @return {?string} The HTML strig representation of the cleaned data.
+ */
+goog.editor.plugins.RemoveFormatting.prototype.getValueForNode = function(
+ node) {
+ return null;
+};
+
+
+/**
+ * Sets a function to be used for remove formatting.
+ * @param {function(string): string} removeFormattingFunc - A function that
+ * takes a string of html and returns a string of html that does any other
+ * formatting changes desired. Use this only if trogedit's behavior doesn't
+ * meet your needs.
+ */
+goog.editor.plugins.RemoveFormatting.prototype.setRemoveFormattingFunc =
+ function(removeFormattingFunc) {
+ this.optRemoveFormattingFunc_ = removeFormattingFunc;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/spacestabhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/spacestabhandler.js b/externs/GCL/externs/goog/editor/plugins/spacestabhandler.js
new file mode 100644
index 0000000..47fcf7a
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/spacestabhandler.js
@@ -0,0 +1,92 @@
+// 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 Editor plugin to handle tab keys not in lists to add 4 spaces.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.SpacesTabHandler');
+
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.plugins.AbstractTabHandler');
+goog.require('goog.editor.range');
+
+
+
+/**
+ * Plugin to handle tab keys when not in lists to add 4 spaces.
+ * @constructor
+ * @extends {goog.editor.plugins.AbstractTabHandler}
+ * @final
+ */
+goog.editor.plugins.SpacesTabHandler = function() {
+ goog.editor.plugins.AbstractTabHandler.call(this);
+};
+goog.inherits(goog.editor.plugins.SpacesTabHandler,
+ goog.editor.plugins.AbstractTabHandler);
+
+
+/** @override */
+goog.editor.plugins.SpacesTabHandler.prototype.getTrogClassId = function() {
+ return 'SpacesTabHandler';
+};
+
+
+/** @override */
+goog.editor.plugins.SpacesTabHandler.prototype.handleTabKey = function(e) {
+ var dh = this.getFieldDomHelper();
+ var range = this.getFieldObject().getRange();
+ if (!goog.editor.range.intersectsTag(range, goog.dom.TagName.LI)) {
+ // In the shift + tab case we don't want to insert spaces, but we don't
+ // want focus to move either so skip the spacing logic and just prevent
+ // default.
+ if (!e.shiftKey) {
+ // Not in a list but we want to insert 4 spaces.
+
+ // Stop change events while we make multiple field changes.
+ this.getFieldObject().stopChangeEvents(true, true);
+
+ // Inserting nodes below completely messes up the selection, doing the
+ // deletion here before it's messed up. Only delete if text is selected,
+ // otherwise we would remove the character to the right of the cursor.
+ if (!range.isCollapsed()) {
+ dh.getDocument().execCommand('delete', false, null);
+ // Safari 3 has some DOM exceptions if we don't reget the range here,
+ // doing it all the time just to be safe.
+ range = this.getFieldObject().getRange();
+ }
+
+ // Emulate tab by removing selection and inserting 4 spaces
+ // Two breaking spaces in a row can be collapsed by the browser into one
+ // space. Inserting the string below because it is guaranteed to never
+ // collapse to less than four spaces, regardless of what is adjacent to
+ // the inserted spaces. This might make line wrapping slightly
+ // sub-optimal around a grouping of non-breaking spaces.
+ var elem = dh.createDom(goog.dom.TagName.SPAN, null,
+ '\u00a0\u00a0 \u00a0');
+ elem = range.insertNode(elem, false);
+
+ this.getFieldObject().dispatchChange();
+ goog.editor.range.placeCursorNextTo(elem, false);
+ this.getFieldObject().dispatchSelectionChangeEvent();
+ }
+
+ e.preventDefault();
+ return true;
+ }
+
+ return false;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/tableeditor.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/tableeditor.js b/externs/GCL/externs/goog/editor/plugins/tableeditor.js
new file mode 100644
index 0000000..be7cad0
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/tableeditor.js
@@ -0,0 +1,475 @@
+// 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 Plugin that enables table editing.
+ *
+ * @see ../../demos/editor/tableeditor.html
+ */
+
+goog.provide('goog.editor.plugins.TableEditor');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.Table');
+goog.require('goog.editor.node');
+goog.require('goog.editor.range');
+goog.require('goog.object');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Plugin that adds support for table creation and editing commands.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.TableEditor = function() {
+ goog.editor.plugins.TableEditor.base(this, 'constructor');
+
+ /**
+ * The array of functions that decide whether a table element could be
+ * editable by the user or not.
+ * @type {Array<function(Element):boolean>}
+ * @private
+ */
+ this.isTableEditableFunctions_ = [];
+
+ /**
+ * The pre-bound function that decides whether a table element could be
+ * editable by the user or not overall.
+ * @type {function(Node):boolean}
+ * @private
+ */
+ this.isUserEditableTableBound_ = goog.bind(this.isUserEditableTable_, this);
+};
+goog.inherits(goog.editor.plugins.TableEditor, goog.editor.Plugin);
+
+
+/** @override */
+// TODO(user): remove this once there's a sensible default
+// implementation in the base Plugin.
+goog.editor.plugins.TableEditor.prototype.getTrogClassId = function() {
+ return String(goog.getUid(this.constructor));
+};
+
+
+/**
+ * Commands supported by goog.editor.plugins.TableEditor.
+ * @enum {string}
+ */
+goog.editor.plugins.TableEditor.COMMAND = {
+ TABLE: '+table',
+ INSERT_ROW_AFTER: '+insertRowAfter',
+ INSERT_ROW_BEFORE: '+insertRowBefore',
+ INSERT_COLUMN_AFTER: '+insertColumnAfter',
+ INSERT_COLUMN_BEFORE: '+insertColumnBefore',
+ REMOVE_ROWS: '+removeRows',
+ REMOVE_COLUMNS: '+removeColumns',
+ SPLIT_CELL: '+splitCell',
+ MERGE_CELLS: '+mergeCells',
+ REMOVE_TABLE: '+removeTable'
+};
+
+
+/**
+ * Inverse map of execCommand strings to
+ * {@link goog.editor.plugins.TableEditor.COMMAND} constants. Used to
+ * determine whether a string corresponds to a command this plugin handles
+ * in O(1) time.
+ * @type {Object}
+ * @private
+ */
+goog.editor.plugins.TableEditor.SUPPORTED_COMMANDS_ =
+ goog.object.transpose(goog.editor.plugins.TableEditor.COMMAND);
+
+
+/**
+ * Whether the string corresponds to a command this plugin handles.
+ * @param {string} command Command string to check.
+ * @return {boolean} Whether the string corresponds to a command
+ * this plugin handles.
+ * @override
+ */
+goog.editor.plugins.TableEditor.prototype.isSupportedCommand =
+ function(command) {
+ return command in goog.editor.plugins.TableEditor.SUPPORTED_COMMANDS_;
+};
+
+
+/** @override */
+goog.editor.plugins.TableEditor.prototype.enable = function(fieldObject) {
+ goog.editor.plugins.TableEditor.base(this, 'enable', fieldObject);
+
+ // enableObjectResizing is supported only for Gecko.
+ // You can refer to http://qooxdoo.org/contrib/project/htmlarea/html_editing
+ // for a compatibility chart.
+ if (goog.userAgent.GECKO) {
+ var doc = this.getFieldDomHelper().getDocument();
+ doc.execCommand('enableObjectResizing', false, 'true');
+ }
+};
+
+
+/**
+ * Returns the currently selected table.
+ * @return {Element?} The table in which the current selection is
+ * contained, or null if there isn't such a table.
+ * @private
+ */
+goog.editor.plugins.TableEditor.prototype.getCurrentTable_ = function() {
+ var selectedElement = this.getFieldObject().getRange().getContainer();
+ return this.getAncestorTable_(selectedElement);
+};
+
+
+/**
+ * Finds the first user-editable table element in the input node's ancestors.
+ * @param {Node?} node The node to start with.
+ * @return {Element?} The table element that is closest ancestor of the node.
+ * @private
+ */
+goog.editor.plugins.TableEditor.prototype.getAncestorTable_ = function(node) {
+ var ancestor = goog.dom.getAncestor(node, this.isUserEditableTableBound_,
+ true);
+ if (goog.editor.node.isEditable(ancestor)) {
+ return /** @type {Element?} */(ancestor);
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Returns the current value of a given command. Currently this plugin
+ * only returns a value for goog.editor.plugins.TableEditor.COMMAND.TABLE.
+ * @override
+ */
+goog.editor.plugins.TableEditor.prototype.queryCommandValue =
+ function(command) {
+ if (command == goog.editor.plugins.TableEditor.COMMAND.TABLE) {
+ return !!this.getCurrentTable_();
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.TableEditor.prototype.execCommandInternal = function(
+ command, opt_arg) {
+ var result = null;
+ // TD/TH in which to place the cursor, if the command destroys the current
+ // cursor position.
+ var cursorCell = null;
+ var range = this.getFieldObject().getRange();
+ if (command == goog.editor.plugins.TableEditor.COMMAND.TABLE) {
+ // Don't create a table if the cursor isn't in an editable region.
+ if (!goog.editor.range.isEditable(range)) {
+ return null;
+ }
+ // Create the table.
+ var tableProps = opt_arg || {width: 4, height: 2};
+ var doc = this.getFieldDomHelper().getDocument();
+ var table = goog.editor.Table.createDomTable(
+ doc, tableProps.width, tableProps.height);
+ range.replaceContentsWithNode(table);
+ // In IE, replaceContentsWithNode uses pasteHTML, so we lose our reference
+ // to the inserted table.
+ // TODO(user): use the reference to the table element returned from
+ // replaceContentsWithNode.
+ if (!goog.userAgent.IE) {
+ cursorCell = table.getElementsByTagName(goog.dom.TagName.TD)[0];
+ }
+ } else {
+ var cellSelection = new goog.editor.plugins.TableEditor.CellSelection_(
+ range, goog.bind(this.getAncestorTable_, this));
+ var table = cellSelection.getTable();
+ if (!table) {
+ return null;
+ }
+ switch (command) {
+ case goog.editor.plugins.TableEditor.COMMAND.INSERT_ROW_BEFORE:
+ table.insertRow(cellSelection.getFirstRowIndex());
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.INSERT_ROW_AFTER:
+ table.insertRow(cellSelection.getLastRowIndex() + 1);
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.INSERT_COLUMN_BEFORE:
+ table.insertColumn(cellSelection.getFirstColumnIndex());
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.INSERT_COLUMN_AFTER:
+ table.insertColumn(cellSelection.getLastColumnIndex() + 1);
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.REMOVE_ROWS:
+ var startRow = cellSelection.getFirstRowIndex();
+ var endRow = cellSelection.getLastRowIndex();
+ if (startRow == 0 && endRow == (table.rows.length - 1)) {
+ // Instead of deleting all rows, delete the entire table.
+ return this.execCommandInternal(
+ goog.editor.plugins.TableEditor.COMMAND.REMOVE_TABLE);
+ }
+ var startColumn = cellSelection.getFirstColumnIndex();
+ var rowCount = (endRow - startRow) + 1;
+ for (var i = 0; i < rowCount; i++) {
+ table.removeRow(startRow);
+ }
+ if (table.rows.length > 0) {
+ // Place cursor in the previous/first row.
+ var closestRow = Math.min(startRow, table.rows.length - 1);
+ cursorCell = table.rows[closestRow].columns[startColumn].element;
+ }
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.REMOVE_COLUMNS:
+ var startCol = cellSelection.getFirstColumnIndex();
+ var endCol = cellSelection.getLastColumnIndex();
+ if (startCol == 0 && endCol == (table.rows[0].columns.length - 1)) {
+ // Instead of deleting all columns, delete the entire table.
+ return this.execCommandInternal(
+ goog.editor.plugins.TableEditor.COMMAND.REMOVE_TABLE);
+ }
+ var startRow = cellSelection.getFirstRowIndex();
+ var removeCount = (endCol - startCol) + 1;
+ for (var i = 0; i < removeCount; i++) {
+ table.removeColumn(startCol);
+ }
+ var currentRow = table.rows[startRow];
+ if (currentRow) {
+ // Place cursor in the previous/first column.
+ var closestCol = Math.min(startCol, currentRow.columns.length - 1);
+ cursorCell = currentRow.columns[closestCol].element;
+ }
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.MERGE_CELLS:
+ if (cellSelection.isRectangle()) {
+ table.mergeCells(cellSelection.getFirstRowIndex(),
+ cellSelection.getFirstColumnIndex(),
+ cellSelection.getLastRowIndex(),
+ cellSelection.getLastColumnIndex());
+ }
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.SPLIT_CELL:
+ if (cellSelection.containsSingleCell()) {
+ table.splitCell(cellSelection.getFirstRowIndex(),
+ cellSelection.getFirstColumnIndex());
+ }
+ break;
+ case goog.editor.plugins.TableEditor.COMMAND.REMOVE_TABLE:
+ table.element.parentNode.removeChild(table.element);
+ break;
+ default:
+ }
+ }
+ if (cursorCell) {
+ range = goog.dom.Range.createFromNodeContents(cursorCell);
+ range.collapse(false);
+ range.select();
+ }
+ return result;
+};
+
+
+/**
+ * Checks whether the element is a table editable by the user.
+ * @param {Node} element The element in question.
+ * @return {boolean} Whether the element is a table editable by the user.
+ * @private
+ */
+goog.editor.plugins.TableEditor.prototype.isUserEditableTable_ =
+ function(element) {
+ // Default implementation.
+ if (element.tagName != goog.dom.TagName.TABLE) {
+ return false;
+ }
+
+ // Check for extra user-editable filters.
+ return goog.array.every(this.isTableEditableFunctions_, function(func) {
+ return func(/** @type {Element} */ (element));
+ });
+};
+
+
+/**
+ * Adds a function to filter out non-user-editable tables.
+ * @param {function(Element):boolean} func A function to decide whether the
+ * table element could be editable by the user or not.
+ */
+goog.editor.plugins.TableEditor.prototype.addIsTableEditableFunction =
+ function(func) {
+ goog.array.insert(this.isTableEditableFunctions_, func);
+};
+
+
+
+/**
+ * Class representing the selected cell objects within a single table.
+ * @param {goog.dom.AbstractRange} range Selected range from which to calculate
+ * selected cells.
+ * @param {function(Element):Element?} getParentTableFunction A function that
+ * finds the user-editable table from a given element.
+ * @constructor
+ * @private
+ */
+goog.editor.plugins.TableEditor.CellSelection_ =
+ function(range, getParentTableFunction) {
+ this.cells_ = [];
+
+ // Mozilla lets users select groups of cells, with each cell showing
+ // up as a separate range in the selection. goog.dom.Range doesn't
+ // currently support this.
+ // TODO(user): support this case in range.js
+ var selectionContainer = range.getContainerElement();
+ var elementInSelection = function(node) {
+ // TODO(user): revert to the more liberal containsNode(node, true),
+ // which will match partially-selected cells. We're using
+ // containsNode(node, false) at the moment because otherwise it's
+ // broken in WebKit due to a closure range bug.
+ return selectionContainer == node ||
+ selectionContainer.parentNode == node ||
+ range.containsNode(node, false);
+ };
+
+ var parentTableElement = selectionContainer &&
+ getParentTableFunction(selectionContainer);
+ if (!parentTableElement) {
+ return;
+ }
+
+ var parentTable = new goog.editor.Table(parentTableElement);
+ // It's probably not possible to select a table with no cells, but
+ // do a sanity check anyway.
+ if (!parentTable.rows.length || !parentTable.rows[0].columns.length) {
+ return;
+ }
+ // Loop through cells to calculate dimensions for this CellSelection.
+ for (var i = 0, row; row = parentTable.rows[i]; i++) {
+ for (var j = 0, cell; cell = row.columns[j]; j++) {
+ if (elementInSelection(cell.element)) {
+ // Update dimensions based on cell.
+ if (!this.cells_.length) {
+ this.firstRowIndex_ = cell.startRow;
+ this.lastRowIndex_ = cell.endRow;
+ this.firstColIndex_ = cell.startCol;
+ this.lastColIndex_ = cell.endCol;
+ } else {
+ this.firstRowIndex_ = Math.min(this.firstRowIndex_, cell.startRow);
+ this.lastRowIndex_ = Math.max(this.lastRowIndex_, cell.endRow);
+ this.firstColIndex_ = Math.min(this.firstColIndex_, cell.startCol);
+ this.lastColIndex_ = Math.max(this.lastColIndex_, cell.endCol);
+ }
+ this.cells_.push(cell);
+ }
+ }
+ }
+ this.parentTable_ = parentTable;
+};
+
+
+/**
+ * Returns the EditableTable object of which this selection's cells are a
+ * subset.
+ * @return {!goog.editor.Table} the table.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.getTable =
+ function() {
+ return this.parentTable_;
+};
+
+
+/**
+ * Returns the row index of the uppermost cell in this selection.
+ * @return {number} The row index.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.getFirstRowIndex =
+ function() {
+ return this.firstRowIndex_;
+};
+
+
+/**
+ * Returns the row index of the lowermost cell in this selection.
+ * @return {number} The row index.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.getLastRowIndex =
+ function() {
+ return this.lastRowIndex_;
+};
+
+
+/**
+ * Returns the column index of the farthest left cell in this selection.
+ * @return {number} The column index.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.getFirstColumnIndex =
+ function() {
+ return this.firstColIndex_;
+};
+
+
+/**
+ * Returns the column index of the farthest right cell in this selection.
+ * @return {number} The column index.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.getLastColumnIndex =
+ function() {
+ return this.lastColIndex_;
+};
+
+
+/**
+ * Returns the cells in this selection.
+ * @return {!Array<Element>} Cells in this selection.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.getCells = function() {
+ return this.cells_;
+};
+
+
+/**
+ * Returns a boolean value indicating whether or not the cells in this
+ * selection form a rectangle.
+ * @return {boolean} Whether the selection forms a rectangle.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.isRectangle =
+ function() {
+ // TODO(user): check for missing cells. Right now this returns
+ // whether all cells in the selection are in the rectangle, but doesn't
+ // verify that every expected cell is present.
+ if (!this.cells_.length) {
+ return false;
+ }
+ var firstCell = this.cells_[0];
+ var lastCell = this.cells_[this.cells_.length - 1];
+ return !(this.firstRowIndex_ < firstCell.startRow ||
+ this.lastRowIndex_ > lastCell.endRow ||
+ this.firstColIndex_ < firstCell.startCol ||
+ this.lastColIndex_ > lastCell.endCol);
+};
+
+
+/**
+ * Returns a boolean value indicating whether or not there is exactly
+ * one cell in this selection. Note that this may not be the same as checking
+ * whether getCells().length == 1; if there is a single cell with
+ * rowSpan/colSpan set it will appear multiple times.
+ * @return {boolean} Whether there is exatly one cell in this selection.
+ */
+goog.editor.plugins.TableEditor.CellSelection_.prototype.containsSingleCell =
+ function() {
+ var cellCount = this.cells_.length;
+ return cellCount > 0 &&
+ (this.cells_[0] == this.cells_[cellCount - 1]);
+};
[27/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/tagname.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/tagname.js b/externs/GCL/externs/goog/dom/tagname.js
new file mode 100644
index 0000000..ad44d85
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/tagname.js
@@ -0,0 +1,160 @@
+// 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 Defines the goog.dom.TagName enum. This enumerates
+ * all HTML tag names specified in either the the W3C HTML 4.01 index of
+ * elements or the HTML5 draft specification.
+ *
+ * References:
+ * http://www.w3.org/TR/html401/index/elements.html
+ * http://dev.w3.org/html5/spec/section-index.html
+ *
+ */
+goog.provide('goog.dom.TagName');
+
+
+/**
+ * Enum of all html tag names specified by the W3C HTML4.01 and HTML5
+ * specifications.
+ * @enum {string}
+ */
+goog.dom.TagName = {
+ A: 'A',
+ ABBR: 'ABBR',
+ ACRONYM: 'ACRONYM',
+ ADDRESS: 'ADDRESS',
+ APPLET: 'APPLET',
+ AREA: 'AREA',
+ ARTICLE: 'ARTICLE',
+ ASIDE: 'ASIDE',
+ AUDIO: 'AUDIO',
+ B: 'B',
+ BASE: 'BASE',
+ BASEFONT: 'BASEFONT',
+ BDI: 'BDI',
+ BDO: 'BDO',
+ BIG: 'BIG',
+ BLOCKQUOTE: 'BLOCKQUOTE',
+ BODY: 'BODY',
+ BR: 'BR',
+ BUTTON: 'BUTTON',
+ CANVAS: 'CANVAS',
+ CAPTION: 'CAPTION',
+ CENTER: 'CENTER',
+ CITE: 'CITE',
+ CODE: 'CODE',
+ COL: 'COL',
+ COLGROUP: 'COLGROUP',
+ COMMAND: 'COMMAND',
+ DATA: 'DATA',
+ DATALIST: 'DATALIST',
+ DD: 'DD',
+ DEL: 'DEL',
+ DETAILS: 'DETAILS',
+ DFN: 'DFN',
+ DIALOG: 'DIALOG',
+ DIR: 'DIR',
+ DIV: 'DIV',
+ DL: 'DL',
+ DT: 'DT',
+ EM: 'EM',
+ EMBED: 'EMBED',
+ FIELDSET: 'FIELDSET',
+ FIGCAPTION: 'FIGCAPTION',
+ FIGURE: 'FIGURE',
+ FONT: 'FONT',
+ FOOTER: 'FOOTER',
+ FORM: 'FORM',
+ FRAME: 'FRAME',
+ FRAMESET: 'FRAMESET',
+ H1: 'H1',
+ H2: 'H2',
+ H3: 'H3',
+ H4: 'H4',
+ H5: 'H5',
+ H6: 'H6',
+ HEAD: 'HEAD',
+ HEADER: 'HEADER',
+ HGROUP: 'HGROUP',
+ HR: 'HR',
+ HTML: 'HTML',
+ I: 'I',
+ IFRAME: 'IFRAME',
+ IMG: 'IMG',
+ INPUT: 'INPUT',
+ INS: 'INS',
+ ISINDEX: 'ISINDEX',
+ KBD: 'KBD',
+ KEYGEN: 'KEYGEN',
+ LABEL: 'LABEL',
+ LEGEND: 'LEGEND',
+ LI: 'LI',
+ LINK: 'LINK',
+ MAP: 'MAP',
+ MARK: 'MARK',
+ MATH: 'MATH',
+ MENU: 'MENU',
+ META: 'META',
+ METER: 'METER',
+ NAV: 'NAV',
+ NOFRAMES: 'NOFRAMES',
+ NOSCRIPT: 'NOSCRIPT',
+ OBJECT: 'OBJECT',
+ OL: 'OL',
+ OPTGROUP: 'OPTGROUP',
+ OPTION: 'OPTION',
+ OUTPUT: 'OUTPUT',
+ P: 'P',
+ PARAM: 'PARAM',
+ PRE: 'PRE',
+ PROGRESS: 'PROGRESS',
+ Q: 'Q',
+ RP: 'RP',
+ RT: 'RT',
+ RUBY: 'RUBY',
+ S: 'S',
+ SAMP: 'SAMP',
+ SCRIPT: 'SCRIPT',
+ SECTION: 'SECTION',
+ SELECT: 'SELECT',
+ SMALL: 'SMALL',
+ SOURCE: 'SOURCE',
+ SPAN: 'SPAN',
+ STRIKE: 'STRIKE',
+ STRONG: 'STRONG',
+ STYLE: 'STYLE',
+ SUB: 'SUB',
+ SUMMARY: 'SUMMARY',
+ SUP: 'SUP',
+ SVG: 'SVG',
+ TABLE: 'TABLE',
+ TBODY: 'TBODY',
+ TD: 'TD',
+ TEMPLATE: 'TEMPLATE',
+ TEXTAREA: 'TEXTAREA',
+ TFOOT: 'TFOOT',
+ TH: 'TH',
+ THEAD: 'THEAD',
+ TIME: 'TIME',
+ TITLE: 'TITLE',
+ TR: 'TR',
+ TRACK: 'TRACK',
+ TT: 'TT',
+ U: 'U',
+ UL: 'UL',
+ VAR: 'VAR',
+ VIDEO: 'VIDEO',
+ WBR: 'WBR'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/tags.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/tags.js b/externs/GCL/externs/goog/dom/tags.js
new file mode 100644
index 0000000..159abe0
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/tags.js
@@ -0,0 +1,42 @@
+// 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 Utilities for HTML element tag names.
+ */
+goog.provide('goog.dom.tags');
+
+goog.require('goog.object');
+
+
+/**
+ * The void elements specified by
+ * http://www.w3.org/TR/html-markup/syntax.html#void-elements.
+ * @const
+ * @type {!Object}
+ * @private
+ */
+goog.dom.tags.VOID_TAGS_ = goog.object.createSet(('area,base,br,col,command,' +
+ 'embed,hr,img,input,keygen,link,meta,param,source,track,wbr').split(','));
+
+
+/**
+ * Checks whether the tag is void (with no contents allowed and no legal end
+ * tag), for example 'br'.
+ * @param {string} tagName The tag name in lower case.
+ * @return {boolean}
+ */
+goog.dom.tags.isVoidTag = function(tagName) {
+ return goog.dom.tags.VOID_TAGS_[tagName] === true;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/textrange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/textrange.js b/externs/GCL/externs/goog/dom/textrange.js
new file mode 100644
index 0000000..f5cfee0
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/textrange.js
@@ -0,0 +1,615 @@
+// 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 text ranges in HTML documents.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.TextRange');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.AbstractRange');
+goog.require('goog.dom.RangeType');
+goog.require('goog.dom.SavedRange');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.TextRangeIterator');
+goog.require('goog.dom.browserrange');
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Create a new text selection with no properties. Do not use this constructor:
+ * use one of the goog.dom.Range.createFrom* methods instead.
+ * @constructor
+ * @extends {goog.dom.AbstractRange}
+ * @final
+ */
+goog.dom.TextRange = function() {
+ /**
+ * The browser specific range wrapper. This can be null if one of the other
+ * representations of the range is specified.
+ * @private {goog.dom.browserrange.AbstractRange?}
+ */
+ this.browserRangeWrapper_ = null;
+
+ /**
+ * The start node of the range. This can be null if one of the other
+ * representations of the range is specified.
+ * @private {Node}
+ */
+ this.startNode_ = null;
+
+ /**
+ * The start offset of the range. This can be null if one of the other
+ * representations of the range is specified.
+ * @private {?number}
+ */
+ this.startOffset_ = null;
+
+ /**
+ * The end node of the range. This can be null if one of the other
+ * representations of the range is specified.
+ * @private {Node}
+ */
+ this.endNode_ = null;
+
+ /**
+ * The end offset of the range. This can be null if one of the other
+ * representations of the range is specified.
+ * @private {?number}
+ */
+ this.endOffset_ = null;
+
+ /**
+ * Whether the focus node is before the anchor node.
+ * @private {boolean}
+ */
+ this.isReversed_ = false;
+};
+goog.inherits(goog.dom.TextRange, goog.dom.AbstractRange);
+
+
+/**
+ * Create a new range wrapper from the given browser range object. Do not use
+ * this method directly - please use goog.dom.Range.createFrom* instead.
+ * @param {Range|TextRange} range The browser range object.
+ * @param {boolean=} opt_isReversed Whether the focus node is before the anchor
+ * node.
+ * @return {!goog.dom.TextRange} A range wrapper object.
+ */
+goog.dom.TextRange.createFromBrowserRange = function(range, opt_isReversed) {
+ return goog.dom.TextRange.createFromBrowserRangeWrapper_(
+ goog.dom.browserrange.createRange(range), opt_isReversed);
+};
+
+
+/**
+ * Create a new range wrapper from the given browser range wrapper.
+ * @param {goog.dom.browserrange.AbstractRange} browserRange The browser range
+ * wrapper.
+ * @param {boolean=} opt_isReversed Whether the focus node is before the anchor
+ * node.
+ * @return {!goog.dom.TextRange} A range wrapper object.
+ * @private
+ */
+goog.dom.TextRange.createFromBrowserRangeWrapper_ = function(browserRange,
+ opt_isReversed) {
+ var range = new goog.dom.TextRange();
+
+ // Initialize the range as a browser range wrapper type range.
+ range.browserRangeWrapper_ = browserRange;
+ range.isReversed_ = !!opt_isReversed;
+
+ return range;
+};
+
+
+/**
+ * Create a new range wrapper that selects the given node's text. Do not use
+ * this method directly - please use goog.dom.Range.createFrom* instead.
+ * @param {Node} node The node to select.
+ * @param {boolean=} opt_isReversed Whether the focus node is before the anchor
+ * node.
+ * @return {!goog.dom.TextRange} A range wrapper object.
+ */
+goog.dom.TextRange.createFromNodeContents = function(node, opt_isReversed) {
+ return goog.dom.TextRange.createFromBrowserRangeWrapper_(
+ goog.dom.browserrange.createRangeFromNodeContents(node),
+ opt_isReversed);
+};
+
+
+/**
+ * Create a new range wrapper that selects the area between the given nodes,
+ * accounting for the given offsets. Do not use this method directly - please
+ * use goog.dom.Range.createFrom* instead.
+ * @param {Node} anchorNode The node to start with.
+ * @param {number} anchorOffset The offset within the node to start.
+ * @param {Node} focusNode The node to end with.
+ * @param {number} focusOffset The offset within the node to end.
+ * @return {!goog.dom.TextRange} A range wrapper object.
+ */
+goog.dom.TextRange.createFromNodes = function(anchorNode, anchorOffset,
+ focusNode, focusOffset) {
+ var range = new goog.dom.TextRange();
+ range.isReversed_ = /** @suppress {missingRequire} */ (
+ goog.dom.Range.isReversed(anchorNode, anchorOffset,
+ focusNode, focusOffset));
+
+ // Avoid selecting terminal elements directly
+ if (goog.dom.isElement(anchorNode) && !goog.dom.canHaveChildren(anchorNode)) {
+ var parent = anchorNode.parentNode;
+ anchorOffset = goog.array.indexOf(parent.childNodes, anchorNode);
+ anchorNode = parent;
+ }
+
+ if (goog.dom.isElement(focusNode) && !goog.dom.canHaveChildren(focusNode)) {
+ var parent = focusNode.parentNode;
+ focusOffset = goog.array.indexOf(parent.childNodes, focusNode);
+ focusNode = parent;
+ }
+
+ // Initialize the range as a W3C style range.
+ if (range.isReversed_) {
+ range.startNode_ = focusNode;
+ range.startOffset_ = focusOffset;
+ range.endNode_ = anchorNode;
+ range.endOffset_ = anchorOffset;
+ } else {
+ range.startNode_ = anchorNode;
+ range.startOffset_ = anchorOffset;
+ range.endNode_ = focusNode;
+ range.endOffset_ = focusOffset;
+ }
+
+ return range;
+};
+
+
+// Method implementations
+
+
+/**
+ * @return {!goog.dom.TextRange} A clone of this range.
+ * @override
+ */
+goog.dom.TextRange.prototype.clone = function() {
+ var range = new goog.dom.TextRange();
+ range.browserRangeWrapper_ =
+ this.browserRangeWrapper_ && this.browserRangeWrapper_.clone();
+ range.startNode_ = this.startNode_;
+ range.startOffset_ = this.startOffset_;
+ range.endNode_ = this.endNode_;
+ range.endOffset_ = this.endOffset_;
+ range.isReversed_ = this.isReversed_;
+
+ return range;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getType = function() {
+ return goog.dom.RangeType.TEXT;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getBrowserRangeObject = function() {
+ return this.getBrowserRangeWrapper_().getBrowserRange();
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.setBrowserRangeObject = function(nativeRange) {
+ // Test if it's a control range by seeing if a control range only method
+ // exists.
+ if (goog.dom.AbstractRange.isNativeControlRange(nativeRange)) {
+ return false;
+ }
+ this.browserRangeWrapper_ = goog.dom.browserrange.createRange(
+ nativeRange);
+ this.clearCachedValues_();
+ return true;
+};
+
+
+/**
+ * Clear all cached values.
+ * @private
+ */
+goog.dom.TextRange.prototype.clearCachedValues_ = function() {
+ this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getTextRangeCount = function() {
+ return 1;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getTextRange = function(i) {
+ return this;
+};
+
+
+/**
+ * @return {!goog.dom.browserrange.AbstractRange} The range wrapper object.
+ * @private
+ */
+goog.dom.TextRange.prototype.getBrowserRangeWrapper_ = function() {
+ return this.browserRangeWrapper_ ||
+ (this.browserRangeWrapper_ = goog.dom.browserrange.createRangeFromNodes(
+ this.getStartNode(), this.getStartOffset(),
+ this.getEndNode(), this.getEndOffset()));
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getContainer = function() {
+ return this.getBrowserRangeWrapper_().getContainer();
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getStartNode = function() {
+ return this.startNode_ ||
+ (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode());
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getStartOffset = function() {
+ return this.startOffset_ != null ? this.startOffset_ :
+ (this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset());
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getStartPosition = function() {
+ return this.isReversed() ?
+ this.getBrowserRangeWrapper_().getEndPosition() :
+ this.getBrowserRangeWrapper_().getStartPosition();
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getEndNode = function() {
+ return this.endNode_ ||
+ (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode());
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getEndOffset = function() {
+ return this.endOffset_ != null ? this.endOffset_ :
+ (this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset());
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getEndPosition = function() {
+ return this.isReversed() ?
+ this.getBrowserRangeWrapper_().getStartPosition() :
+ this.getBrowserRangeWrapper_().getEndPosition();
+};
+
+
+/**
+ * Moves a TextRange to the provided nodes and offsets.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the node to start.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the node to end.
+ * @param {boolean} isReversed Whether the range is reversed.
+ */
+goog.dom.TextRange.prototype.moveToNodes = function(startNode, startOffset,
+ endNode, endOffset,
+ isReversed) {
+ this.startNode_ = startNode;
+ this.startOffset_ = startOffset;
+ this.endNode_ = endNode;
+ this.endOffset_ = endOffset;
+ this.isReversed_ = isReversed;
+ this.browserRangeWrapper_ = null;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.isReversed = function() {
+ return this.isReversed_;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.containsRange = function(otherRange,
+ opt_allowPartial) {
+ var otherRangeType = otherRange.getType();
+ if (otherRangeType == goog.dom.RangeType.TEXT) {
+ return this.getBrowserRangeWrapper_().containsRange(
+ otherRange.getBrowserRangeWrapper_(), opt_allowPartial);
+ } else if (otherRangeType == goog.dom.RangeType.CONTROL) {
+ var elements = otherRange.getElements();
+ var fn = opt_allowPartial ? goog.array.some : goog.array.every;
+ return fn(elements, function(el) {
+ return this.containsNode(el, opt_allowPartial);
+ }, this);
+ }
+ return false;
+};
+
+
+/**
+ * Tests if the given node is in a document.
+ * @param {Node} node The node to check.
+ * @return {boolean} Whether the given node is in the given document.
+ */
+goog.dom.TextRange.isAttachedNode = function(node) {
+ if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
+ var returnValue = false;
+ /** @preserveTry */
+ try {
+ returnValue = node.parentNode;
+ } catch (e) {
+ // IE sometimes throws Invalid Argument errors when a node is detached.
+ // Note: trying to return a value from the above try block can cause IE
+ // to crash. It is necessary to use the local returnValue
+ }
+ return !!returnValue;
+ } else {
+ return goog.dom.contains(node.ownerDocument.body, node);
+ }
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.isRangeInDocument = function() {
+ // Ensure any cached nodes are in the document. IE also allows ranges to
+ // become detached, so we check if the range is still in the document as
+ // well for IE.
+ return (!this.startNode_ ||
+ goog.dom.TextRange.isAttachedNode(this.startNode_)) &&
+ (!this.endNode_ ||
+ goog.dom.TextRange.isAttachedNode(this.endNode_)) &&
+ (!(goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) ||
+ this.getBrowserRangeWrapper_().isRangeInDocument());
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.isCollapsed = function() {
+ return this.getBrowserRangeWrapper_().isCollapsed();
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getText = function() {
+ return this.getBrowserRangeWrapper_().getText();
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getHtmlFragment = function() {
+ // TODO(robbyw): Generalize the code in browserrange so it is static and
+ // just takes an iterator. This would mean we don't always have to create a
+ // browser range.
+ return this.getBrowserRangeWrapper_().getHtmlFragment();
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getValidHtml = function() {
+ return this.getBrowserRangeWrapper_().getValidHtml();
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.getPastableHtml = function() {
+ // TODO(robbyw): Get any attributes the table or tr has.
+
+ var html = this.getValidHtml();
+
+ if (html.match(/^\s*<td\b/i)) {
+ // Match html starting with a TD.
+ html = '<table><tbody><tr>' + html + '</tr></tbody></table>';
+ } else if (html.match(/^\s*<tr\b/i)) {
+ // Match html starting with a TR.
+ html = '<table><tbody>' + html + '</tbody></table>';
+ } else if (html.match(/^\s*<tbody\b/i)) {
+ // Match html starting with a TBODY.
+ html = '<table>' + html + '</table>';
+ } else if (html.match(/^\s*<li\b/i)) {
+ // Match html starting with an LI.
+ var container = this.getContainer();
+ var tagType = goog.dom.TagName.UL;
+ while (container) {
+ if (container.tagName == goog.dom.TagName.OL) {
+ tagType = goog.dom.TagName.OL;
+ break;
+ } else if (container.tagName == goog.dom.TagName.UL) {
+ break;
+ }
+ container = container.parentNode;
+ }
+ html = goog.string.buildString('<', tagType, '>', html, '</', tagType, '>');
+ }
+
+ return html;
+};
+
+
+/**
+ * Returns a TextRangeIterator 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.TextRangeIterator} An iterator over tags in the range.
+ * @override
+ */
+goog.dom.TextRange.prototype.__iterator__ = function(opt_keys) {
+ return new goog.dom.TextRangeIterator(this.getStartNode(),
+ this.getStartOffset(), this.getEndNode(), this.getEndOffset());
+};
+
+
+// RANGE ACTIONS
+
+
+/** @override */
+goog.dom.TextRange.prototype.select = function() {
+ this.getBrowserRangeWrapper_().select(this.isReversed_);
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.removeContents = function() {
+ this.getBrowserRangeWrapper_().removeContents();
+ this.clearCachedValues_();
+};
+
+
+/**
+ * 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.TextRange.prototype.surroundContents = function(element) {
+ var output = this.getBrowserRangeWrapper_().surroundContents(element);
+ this.clearCachedValues_();
+ return output;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.insertNode = function(node, before) {
+ var output = this.getBrowserRangeWrapper_().insertNode(node, before);
+ this.clearCachedValues_();
+ return output;
+};
+
+
+/** @override */
+goog.dom.TextRange.prototype.surroundWithNodes = function(startNode, endNode) {
+ this.getBrowserRangeWrapper_().surroundWithNodes(startNode, endNode);
+ this.clearCachedValues_();
+};
+
+
+// SAVE/RESTORE
+
+
+/** @override */
+goog.dom.TextRange.prototype.saveUsingDom = function() {
+ return new goog.dom.DomSavedTextRange_(this);
+};
+
+
+// RANGE MODIFICATION
+
+
+/** @override */
+goog.dom.TextRange.prototype.collapse = function(toAnchor) {
+ var toStart = this.isReversed() ? !toAnchor : toAnchor;
+
+ if (this.browserRangeWrapper_) {
+ this.browserRangeWrapper_.collapse(toStart);
+ }
+
+ if (toStart) {
+ this.endNode_ = this.startNode_;
+ this.endOffset_ = this.startOffset_;
+ } else {
+ this.startNode_ = this.endNode_;
+ this.startOffset_ = this.endOffset_;
+ }
+
+ // Collapsed ranges can't be reversed
+ this.isReversed_ = false;
+};
+
+
+// SAVED RANGE OBJECTS
+
+
+
+/**
+ * A SavedRange implementation using DOM endpoints.
+ * @param {goog.dom.AbstractRange} range The range to save.
+ * @constructor
+ * @extends {goog.dom.SavedRange}
+ * @private
+ */
+goog.dom.DomSavedTextRange_ = function(range) {
+ goog.dom.DomSavedTextRange_.base(this, 'constructor');
+
+ /**
+ * The anchor node.
+ * @type {Node}
+ * @private
+ */
+ this.anchorNode_ = range.getAnchorNode();
+
+ /**
+ * The anchor node offset.
+ * @type {number}
+ * @private
+ */
+ this.anchorOffset_ = range.getAnchorOffset();
+
+ /**
+ * The focus node.
+ * @type {Node}
+ * @private
+ */
+ this.focusNode_ = range.getFocusNode();
+
+ /**
+ * The focus node offset.
+ * @type {number}
+ * @private
+ */
+ this.focusOffset_ = range.getFocusOffset();
+};
+goog.inherits(goog.dom.DomSavedTextRange_, goog.dom.SavedRange);
+
+
+/**
+ * @return {!goog.dom.AbstractRange} The restored range.
+ * @override
+ */
+goog.dom.DomSavedTextRange_.prototype.restoreInternal = function() {
+ return /** @suppress {missingRequire} */ (
+ goog.dom.Range.createFromNodes(this.anchorNode_, this.anchorOffset_,
+ this.focusNode_, this.focusOffset_));
+};
+
+
+/** @override */
+goog.dom.DomSavedTextRange_.prototype.disposeInternal = function() {
+ goog.dom.DomSavedTextRange_.superClass_.disposeInternal.call(this);
+
+ this.anchorNode_ = null;
+ this.focusNode_ = null;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/textrangeiterator.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/textrangeiterator.js b/externs/GCL/externs/goog/dom/textrangeiterator.js
new file mode 100644
index 0000000..efb5221
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/textrangeiterator.js
@@ -0,0 +1,239 @@
+// 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 Iterator between two DOM text range positions.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.TextRangeIterator');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.RangeIterator');
+goog.require('goog.dom.TagName');
+goog.require('goog.iter.StopIteration');
+
+
+
+/**
+ * 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} startNode The starting node position.
+ * @param {number} startOffset The offset in to startNode. If startNode is
+ * an element, indicates an offset in to childNodes. If startNode is a
+ * text node, indicates an offset in to nodeValue.
+ * @param {Node} endNode The ending node position.
+ * @param {number} endOffset The offset in to endNode. If endNode is
+ * an element, indicates an offset in to childNodes. If endNode is a
+ * text node, indicates an offset in to nodeValue.
+ * @param {boolean=} opt_reverse Whether to traverse nodes in reverse.
+ * @constructor
+ * @extends {goog.dom.RangeIterator}
+ * @final
+ */
+goog.dom.TextRangeIterator = function(startNode, startOffset, endNode,
+ endOffset, opt_reverse) {
+ /**
+ * The first node in the selection.
+ * @private {Node}
+ */
+ this.startNode_ = null;
+
+ /**
+ * The last node in the selection.
+ * @private {Node}
+ */
+ this.endNode_ = null;
+
+ /**
+ * The offset within the first node in the selection.
+ * @private {number}
+ */
+ this.startOffset_ = 0;
+
+ /**
+ * The offset within the last node in the selection.
+ * @private {number}
+ */
+ this.endOffset_ = 0;
+
+ var goNext;
+
+ if (startNode) {
+ this.startNode_ = startNode;
+ this.startOffset_ = startOffset;
+ this.endNode_ = endNode;
+ this.endOffset_ = endOffset;
+
+ // Skip to the offset nodes - being careful to special case BRs since these
+ // have no children but still can appear as the startContainer of a range.
+ if (startNode.nodeType == goog.dom.NodeType.ELEMENT &&
+ startNode.tagName != goog.dom.TagName.BR) {
+ var startChildren = startNode.childNodes;
+ var candidate = startChildren[startOffset];
+ if (candidate) {
+ this.startNode_ = candidate;
+ this.startOffset_ = 0;
+ } else {
+ if (startChildren.length) {
+ this.startNode_ =
+ /** @type {Node} */ (goog.array.peek(startChildren));
+ }
+ goNext = true;
+ }
+ }
+
+ if (endNode.nodeType == goog.dom.NodeType.ELEMENT) {
+ this.endNode_ = endNode.childNodes[endOffset];
+ if (this.endNode_) {
+ this.endOffset_ = 0;
+ } else {
+ // The offset was past the last element.
+ this.endNode_ = endNode;
+ }
+ }
+ }
+
+ goog.dom.TextRangeIterator.base(
+ this, 'constructor', opt_reverse ? this.endNode_ : this.startNode_,
+ opt_reverse);
+
+ if (goNext) {
+ try {
+ this.next();
+ } catch (e) {
+ if (e != goog.iter.StopIteration) {
+ throw e;
+ }
+ }
+ }
+};
+goog.inherits(goog.dom.TextRangeIterator, goog.dom.RangeIterator);
+
+
+/** @override */
+goog.dom.TextRangeIterator.prototype.getStartTextOffset = function() {
+ // Offsets only apply to text nodes. If our current node is the start node,
+ // return the saved offset. Otherwise, return 0.
+ return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 :
+ this.node == this.startNode_ ? this.startOffset_ : 0;
+};
+
+
+/** @override */
+goog.dom.TextRangeIterator.prototype.getEndTextOffset = function() {
+ // Offsets only apply to text nodes. If our current node is the end node,
+ // return the saved offset. Otherwise, return the length of the node.
+ return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 :
+ this.node == this.endNode_ ? this.endOffset_ : this.node.nodeValue.length;
+};
+
+
+/** @override */
+goog.dom.TextRangeIterator.prototype.getStartNode = function() {
+ return this.startNode_;
+};
+
+
+/**
+ * Change the start node of the iterator.
+ * @param {Node} node The new start node.
+ */
+goog.dom.TextRangeIterator.prototype.setStartNode = function(node) {
+ if (!this.isStarted()) {
+ this.setPosition(node);
+ }
+
+ this.startNode_ = node;
+ this.startOffset_ = 0;
+};
+
+
+/** @override */
+goog.dom.TextRangeIterator.prototype.getEndNode = function() {
+ return this.endNode_;
+};
+
+
+/**
+ * Change the end node of the iterator.
+ * @param {Node} node The new end node.
+ */
+goog.dom.TextRangeIterator.prototype.setEndNode = function(node) {
+ this.endNode_ = node;
+ this.endOffset_ = 0;
+};
+
+
+/** @override */
+goog.dom.TextRangeIterator.prototype.isLast = function() {
+ return this.isStarted() && this.node == this.endNode_ &&
+ (!this.endOffset_ || !this.isStartTag());
+};
+
+
+/**
+ * Move to the next position in the selection.
+ * Throws {@code goog.iter.StopIteration} when it passes the end of the range.
+ * @return {Node} The node at the next position.
+ * @override
+ */
+goog.dom.TextRangeIterator.prototype.next = function() {
+ if (this.isLast()) {
+ throw goog.iter.StopIteration;
+ }
+
+ // Call the super function.
+ return goog.dom.TextRangeIterator.superClass_.next.call(this);
+};
+
+
+/** @override */
+goog.dom.TextRangeIterator.prototype.skipTag = function() {
+ goog.dom.TextRangeIterator.superClass_.skipTag.apply(this);
+
+ // If the node we are skipping contains the end node, we just skipped past
+ // the end, so we stop the iteration.
+ if (goog.dom.contains(this.node, this.endNode_)) {
+ throw goog.iter.StopIteration;
+ }
+};
+
+
+/** @override */
+goog.dom.TextRangeIterator.prototype.copyFrom = function(other) {
+ this.startNode_ = other.startNode_;
+ this.endNode_ = other.endNode_;
+ this.startOffset_ = other.startOffset_;
+ this.endOffset_ = other.endOffset_;
+ this.isReversed_ = other.isReversed_;
+
+ goog.dom.TextRangeIterator.superClass_.copyFrom.call(this, other);
+};
+
+
+/**
+ * @return {!goog.dom.TextRangeIterator} An identical iterator.
+ * @override
+ */
+goog.dom.TextRangeIterator.prototype.clone = function() {
+ var copy = new goog.dom.TextRangeIterator(this.startNode_,
+ this.startOffset_, this.endNode_, this.endOffset_, this.isReversed_);
+ copy.copyFrom(this);
+ return copy;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/vendor.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/vendor.js b/externs/GCL/externs/goog/dom/vendor.js
new file mode 100644
index 0000000..7c1123e
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/vendor.js
@@ -0,0 +1,96 @@
+// Copyright 2012 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 Vendor prefix getters.
+ */
+
+goog.provide('goog.dom.vendor');
+
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+/**
+ * Returns the JS vendor prefix used in CSS properties. Different vendors
+ * use different methods of changing the case of the property names.
+ *
+ * @return {?string} The JS vendor prefix or null if there is none.
+ */
+goog.dom.vendor.getVendorJsPrefix = function() {
+ if (goog.userAgent.WEBKIT) {
+ return 'Webkit';
+ } else if (goog.userAgent.GECKO) {
+ return 'Moz';
+ } else if (goog.userAgent.IE) {
+ return 'ms';
+ } else if (goog.userAgent.OPERA) {
+ return 'O';
+ }
+
+ return null;
+};
+
+
+/**
+ * Returns the vendor prefix used in CSS properties.
+ *
+ * @return {?string} The vendor prefix or null if there is none.
+ */
+goog.dom.vendor.getVendorPrefix = function() {
+ if (goog.userAgent.WEBKIT) {
+ return '-webkit';
+ } else if (goog.userAgent.GECKO) {
+ return '-moz';
+ } else if (goog.userAgent.IE) {
+ return '-ms';
+ } else if (goog.userAgent.OPERA) {
+ return '-o';
+ }
+
+ return null;
+};
+
+
+/**
+ * @param {string} propertyName A property name.
+ * @param {!Object=} opt_object If provided, we verify if the property exists in
+ * the object.
+ * @return {?string} A vendor prefixed property name, or null if it does not
+ * exist.
+ */
+goog.dom.vendor.getPrefixedPropertyName = function(propertyName, opt_object) {
+ // We first check for a non-prefixed property, if available.
+ if (opt_object && propertyName in opt_object) {
+ return propertyName;
+ }
+ var prefix = goog.dom.vendor.getVendorJsPrefix();
+ if (prefix) {
+ prefix = prefix.toLowerCase();
+ var prefixedPropertyName = prefix + goog.string.toTitleCase(propertyName);
+ return (!goog.isDef(opt_object) || prefixedPropertyName in opt_object) ?
+ prefixedPropertyName : null;
+ }
+ return null;
+};
+
+
+/**
+ * @param {string} eventType An event type.
+ * @return {string} A lower-cased vendor prefixed event type.
+ */
+goog.dom.vendor.getPrefixedEventType = function(eventType) {
+ var prefix = goog.dom.vendor.getVendorJsPrefix() || '';
+ return (prefix + eventType).toLowerCase();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/viewportsizemonitor.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/viewportsizemonitor.js b/externs/GCL/externs/goog/dom/viewportsizemonitor.js
new file mode 100644
index 0000000..2f5f30e
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/viewportsizemonitor.js
@@ -0,0 +1,165 @@
+// 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 Utility class that monitors viewport size changes.
+ *
+ * @author attila@google.com (Attila Bodis)
+ * @see ../demos/viewportsizemonitor.html
+ */
+
+goog.provide('goog.dom.ViewportSizeMonitor');
+
+goog.require('goog.dom');
+goog.require('goog.events');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.math.Size');
+
+
+
+/**
+ * This class can be used to monitor changes in the viewport size. Instances
+ * dispatch a {@link goog.events.EventType.RESIZE} event when the viewport size
+ * changes. Handlers can call {@link goog.dom.ViewportSizeMonitor#getSize} to
+ * get the new viewport size.
+ *
+ * Use this class if you want to execute resize/reflow logic each time the
+ * user resizes the browser window. This class is guaranteed to only dispatch
+ * {@code RESIZE} events when the pixel dimensions of the viewport change.
+ * (Internet Explorer fires resize events if any element on the page is resized,
+ * even if the viewport dimensions are unchanged, which can lead to infinite
+ * resize loops.)
+ *
+ * Example usage:
+ * <pre>
+ * var vsm = new goog.dom.ViewportSizeMonitor();
+ * goog.events.listen(vsm, goog.events.EventType.RESIZE, function(e) {
+ * alert('Viewport size changed to ' + vsm.getSize());
+ * });
+ * </pre>
+ *
+ * Manually verified on IE6, IE7, FF2, Opera 11, Safari 4 and Chrome.
+ *
+ * @param {Window=} opt_window The window to monitor; defaults to the window in
+ * which this code is executing.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.dom.ViewportSizeMonitor = function(opt_window) {
+ goog.dom.ViewportSizeMonitor.base(this, 'constructor');
+
+ /**
+ * The window to monitor. Defaults to the window in which the code is running.
+ * @private {Window}
+ */
+ this.window_ = opt_window || window;
+
+ /**
+ * Event listener key for window the window resize handler, as returned by
+ * {@link goog.events.listen}.
+ * @private {goog.events.Key}
+ */
+ this.listenerKey_ = goog.events.listen(this.window_,
+ goog.events.EventType.RESIZE, this.handleResize_, false, this);
+
+ /**
+ * The most recently recorded size of the viewport, in pixels.
+ * @private {goog.math.Size}
+ */
+ this.size_ = goog.dom.getViewportSize(this.window_);
+};
+goog.inherits(goog.dom.ViewportSizeMonitor, goog.events.EventTarget);
+
+
+/**
+ * Returns a viewport size monitor for the given window. A new one is created
+ * if it doesn't exist already. This prevents the unnecessary creation of
+ * multiple spooling monitors for a window.
+ * @param {Window=} opt_window The window to monitor; defaults to the window in
+ * which this code is executing.
+ * @return {!goog.dom.ViewportSizeMonitor} Monitor for the given window.
+ */
+goog.dom.ViewportSizeMonitor.getInstanceForWindow = function(opt_window) {
+ var currentWindow = opt_window || window;
+ var uid = goog.getUid(currentWindow);
+
+ return goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] =
+ goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] ||
+ new goog.dom.ViewportSizeMonitor(currentWindow);
+};
+
+
+/**
+ * Removes and disposes a viewport size monitor for the given window if one
+ * exists.
+ * @param {Window=} opt_window The window whose monitor should be removed;
+ * defaults to the window in which this code is executing.
+ */
+goog.dom.ViewportSizeMonitor.removeInstanceForWindow = function(opt_window) {
+ var uid = goog.getUid(opt_window || window);
+
+ goog.dispose(goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid]);
+ delete goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid];
+};
+
+
+/**
+ * Map of window hash code to viewport size monitor for that window, if
+ * created.
+ * @type {Object<number,goog.dom.ViewportSizeMonitor>}
+ * @private
+ */
+goog.dom.ViewportSizeMonitor.windowInstanceMap_ = {};
+
+
+/**
+ * Returns the most recently recorded size of the viewport, in pixels. May
+ * return null if no window resize event has been handled yet.
+ * @return {goog.math.Size} The viewport dimensions, in pixels.
+ */
+goog.dom.ViewportSizeMonitor.prototype.getSize = function() {
+ // Return a clone instead of the original to preserve encapsulation.
+ return this.size_ ? this.size_.clone() : null;
+};
+
+
+/** @override */
+goog.dom.ViewportSizeMonitor.prototype.disposeInternal = function() {
+ goog.dom.ViewportSizeMonitor.superClass_.disposeInternal.call(this);
+
+ if (this.listenerKey_) {
+ goog.events.unlistenByKey(this.listenerKey_);
+ this.listenerKey_ = null;
+ }
+
+ this.window_ = null;
+ this.size_ = null;
+};
+
+
+/**
+ * Handles window resize events by measuring the dimensions of the
+ * viewport and dispatching a {@link goog.events.EventType.RESIZE} event if the
+ * current dimensions are different from the previous ones.
+ * @param {goog.events.Event} event The window resize event to handle.
+ * @private
+ */
+goog.dom.ViewportSizeMonitor.prototype.handleResize_ = function(event) {
+ var size = goog.dom.getViewportSize(this.window_);
+ if (!goog.math.Size.equals(size, this.size_)) {
+ this.size_ = size;
+ this.dispatchEvent(goog.events.EventType.RESIZE);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/xml.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/xml.js b/externs/GCL/externs/goog/dom/xml.js
new file mode 100644
index 0000000..59f123a
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/xml.js
@@ -0,0 +1,204 @@
+// 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
+ * XML utilities.
+ *
+ */
+
+goog.provide('goog.dom.xml');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+
+
+/**
+ * Max XML size for MSXML2. Used to prevent potential DoS attacks.
+ * @type {number}
+ */
+goog.dom.xml.MAX_XML_SIZE_KB = 2 * 1024; // In kB
+
+
+/**
+ * Max XML size for MSXML2. Used to prevent potential DoS attacks.
+ * @type {number}
+ */
+goog.dom.xml.MAX_ELEMENT_DEPTH = 256; // Same default as MSXML6.
+
+
+/**
+ * Creates an XML document appropriate for the current JS runtime
+ * @param {string=} opt_rootTagName The root tag name.
+ * @param {string=} opt_namespaceUri Namespace URI of the document element.
+ * @return {Document} The new document.
+ */
+goog.dom.xml.createDocument = function(opt_rootTagName, opt_namespaceUri) {
+ if (opt_namespaceUri && !opt_rootTagName) {
+ throw Error("Can't create document with namespace and no root tag");
+ }
+ if (document.implementation && document.implementation.createDocument) {
+ return document.implementation.createDocument(opt_namespaceUri || '',
+ opt_rootTagName || '',
+ null);
+ } else if (typeof ActiveXObject != 'undefined') {
+ var doc = goog.dom.xml.createMsXmlDocument_();
+ if (doc) {
+ if (opt_rootTagName) {
+ doc.appendChild(doc.createNode(goog.dom.NodeType.ELEMENT,
+ opt_rootTagName,
+ opt_namespaceUri || ''));
+ }
+ return doc;
+ }
+ }
+ throw Error('Your browser does not support creating new documents');
+};
+
+
+/**
+ * Creates an XML document from a string
+ * @param {string} xml The text.
+ * @return {Document} XML document from the text.
+ */
+goog.dom.xml.loadXml = function(xml) {
+ if (typeof DOMParser != 'undefined') {
+ return new DOMParser().parseFromString(xml, 'application/xml');
+ } else if (typeof ActiveXObject != 'undefined') {
+ var doc = goog.dom.xml.createMsXmlDocument_();
+ doc.loadXML(xml);
+ return doc;
+ }
+ throw Error('Your browser does not support loading xml documents');
+};
+
+
+/**
+ * Serializes an XML document or subtree to string.
+ * @param {Document|Element} xml The document or the root node of the subtree.
+ * @return {string} The serialized XML.
+ */
+goog.dom.xml.serialize = function(xml) {
+ // Compatible with Firefox, Opera and WebKit.
+ if (typeof XMLSerializer != 'undefined') {
+ return new XMLSerializer().serializeToString(xml);
+ }
+ // Compatible with Internet Explorer.
+ var text = xml.xml;
+ if (text) {
+ return text;
+ }
+ throw Error('Your browser does not support serializing XML documents');
+};
+
+
+/**
+ * Selects a single node using an Xpath expression and a root node
+ * @param {Node} node The root node.
+ * @param {string} path Xpath selector.
+ * @return {Node} The selected node, or null if no matching node.
+ */
+goog.dom.xml.selectSingleNode = function(node, path) {
+ if (typeof node.selectSingleNode != 'undefined') {
+ var doc = goog.dom.getOwnerDocument(node);
+ if (typeof doc.setProperty != 'undefined') {
+ doc.setProperty('SelectionLanguage', 'XPath');
+ }
+ return node.selectSingleNode(path);
+ } else if (document.implementation.hasFeature('XPath', '3.0')) {
+ var doc = goog.dom.getOwnerDocument(node);
+ var resolver = doc.createNSResolver(doc.documentElement);
+ var result = doc.evaluate(path, node, resolver,
+ XPathResult.FIRST_ORDERED_NODE_TYPE, null);
+ return result.singleNodeValue;
+ }
+ return null;
+};
+
+
+/**
+ * Selects multiple nodes using an Xpath expression and a root node
+ * @param {Node} node The root node.
+ * @param {string} path Xpath selector.
+ * @return {(NodeList|Array<Node>)} The selected nodes, or empty array if no
+ * matching nodes.
+ */
+goog.dom.xml.selectNodes = function(node, path) {
+ if (typeof node.selectNodes != 'undefined') {
+ var doc = goog.dom.getOwnerDocument(node);
+ if (typeof doc.setProperty != 'undefined') {
+ doc.setProperty('SelectionLanguage', 'XPath');
+ }
+ return node.selectNodes(path);
+ } else if (document.implementation.hasFeature('XPath', '3.0')) {
+ var doc = goog.dom.getOwnerDocument(node);
+ var resolver = doc.createNSResolver(doc.documentElement);
+ var nodes = doc.evaluate(path, node, resolver,
+ XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ var results = [];
+ var count = nodes.snapshotLength;
+ for (var i = 0; i < count; i++) {
+ results.push(nodes.snapshotItem(i));
+ }
+ return results;
+ } else {
+ return [];
+ }
+};
+
+
+/**
+ * Sets multiple attributes on an element. Differs from goog.dom.setProperties
+ * in that it exclusively uses the element's setAttributes method. Use this
+ * when you need to ensure that the exact property is available as an attribute
+ * and can be read later by the native getAttribute method.
+ * @param {!Element} element XML or DOM element to set attributes on.
+ * @param {!Object<string, string>} attributes Map of property:value pairs.
+ */
+goog.dom.xml.setAttributes = function(element, attributes) {
+ for (var key in attributes) {
+ if (attributes.hasOwnProperty(key)) {
+ element.setAttribute(key, attributes[key]);
+ }
+ }
+};
+
+
+/**
+ * Creates an instance of the MSXML2.DOMDocument.
+ * @return {Document} The new document.
+ * @private
+ */
+goog.dom.xml.createMsXmlDocument_ = function() {
+ var doc = new ActiveXObject('MSXML2.DOMDocument');
+ if (doc) {
+ // Prevent potential vulnerabilities exposed by MSXML2, see
+ // http://b/1707300 and http://wiki/Main/ISETeamXMLAttacks for details.
+ doc.resolveExternals = false;
+ doc.validateOnParse = false;
+ // Add a try catch block because accessing these properties will throw an
+ // error on unsupported MSXML versions. This affects Windows machines
+ // running IE6 or IE7 that are on XP SP2 or earlier without MSXML updates.
+ // See http://msdn.microsoft.com/en-us/library/ms766391(VS.85).aspx for
+ // specific details on which MSXML versions support these properties.
+ try {
+ doc.setProperty('ProhibitDTD', true);
+ doc.setProperty('MaxXMLSize', goog.dom.xml.MAX_XML_SIZE_KB);
+ doc.setProperty('MaxElementDepth', goog.dom.xml.MAX_ELEMENT_DEPTH);
+ } catch (e) {
+ // No-op.
+ }
+ }
+ return doc;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/browserfeature2.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/browserfeature2.js b/externs/GCL/externs/goog/editor/browserfeature2.js
new file mode 100644
index 0000000..10ac05e
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/browserfeature2.js
@@ -0,0 +1,273 @@
+// 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 Trogedit constants for browser features and quirks that should
+ * be used by the rich text editor.
+ */
+
+goog.provide('goog.editor.BrowserFeature');
+
+goog.require('goog.editor.defines');
+goog.require('goog.userAgent');
+goog.require('goog.userAgent.product');
+goog.require('goog.userAgent.product.isVersion');
+
+
+/**
+ * Maps browser quirks to boolean values, detailing what the current
+ * browser supports.
+ * @const
+ */
+goog.editor.BrowserFeature = {
+ // Whether this browser uses the IE TextRange object.
+ HAS_IE_RANGES: goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9),
+
+ // Whether this browser uses the W3C standard Range object.
+ // Assumes IE higher versions will be compliance with W3C standard.
+ HAS_W3C_RANGES: goog.userAgent.GECKO || goog.userAgent.WEBKIT ||
+ goog.userAgent.OPERA ||
+ (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9)),
+
+ // Has the contentEditable attribute, which makes nodes editable.
+ //
+ // NOTE(nicksantos): FF3 has contentEditable, but there are 3 major reasons
+ // why we don't use it:
+ // 1) In FF3, we listen for key events on the document, and we'd have to
+ // filter them properly. See TR_Browser.USE_DOCUMENT_FOR_KEY_EVENTS.
+ // 2) In FF3, we listen for focus/blur events on the document, which
+ // simply doesn't make sense in contentEditable. focus/blur
+ // on contentEditable elements still has some quirks, which we're
+ // talking to Firefox-team about.
+ // 3) We currently use Mutation events in FF3 to detect changes,
+ // and these are dispatched on the document only.
+ // If we ever hope to support FF3/contentEditable, all 3 of these issues
+ // will need answers. Most just involve refactoring at our end.
+ HAS_CONTENT_EDITABLE: goog.userAgent.IE || goog.userAgent.WEBKIT ||
+ goog.userAgent.OPERA ||
+ (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 &&
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9')),
+
+ // Whether to use mutation event types to detect changes
+ // in the field contents.
+ USE_MUTATION_EVENTS: goog.userAgent.GECKO,
+
+ // Whether the browser has a functional DOMSubtreeModified event.
+ // TODO(user): Enable for all FF3 once we're confident this event fires
+ // reliably. Currently it's only enabled if using contentEditable in FF as
+ // we have no other choice in that case but to use this event.
+ HAS_DOM_SUBTREE_MODIFIED_EVENT: goog.userAgent.WEBKIT ||
+ (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 &&
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9')),
+
+ // Whether nodes can be copied from one document to another
+ HAS_DOCUMENT_INDEPENDENT_NODES: goog.userAgent.GECKO,
+
+ // Whether the cursor goes before or inside the first block element on
+ // focus, e.g., <body><p>foo</p></body>. FF will put the cursor before the
+ // paragraph on focus, which is wrong.
+ PUTS_CURSOR_BEFORE_FIRST_BLOCK_ELEMENT_ON_FOCUS: goog.userAgent.GECKO,
+
+ // Whether the selection of one frame is cleared when another frame
+ // is focused.
+ CLEARS_SELECTION_WHEN_FOCUS_LEAVES:
+ goog.userAgent.IE || goog.userAgent.WEBKIT || goog.userAgent.OPERA,
+
+ // Whether "unselectable" is supported as an element style.
+ HAS_UNSELECTABLE_STYLE: goog.userAgent.GECKO || goog.userAgent.WEBKIT,
+
+ // Whether this browser's "FormatBlock" command does not suck.
+ FORMAT_BLOCK_WORKS_FOR_BLOCKQUOTES: goog.userAgent.GECKO ||
+ goog.userAgent.WEBKIT || goog.userAgent.OPERA,
+
+ // Whether this browser's "FormatBlock" command may create multiple
+ // blockquotes.
+ CREATES_MULTIPLE_BLOCKQUOTES:
+ (goog.userAgent.WEBKIT &&
+ !goog.userAgent.isVersionOrHigher('534.16')) ||
+ goog.userAgent.OPERA,
+
+ // Whether this browser's "FormatBlock" command will wrap blockquotes
+ // inside of divs, instead of replacing divs with blockquotes.
+ WRAPS_BLOCKQUOTE_IN_DIVS: goog.userAgent.OPERA,
+
+ // Whether the readystatechange event is more reliable than load.
+ PREFERS_READY_STATE_CHANGE_EVENT: goog.userAgent.IE,
+
+ // Whether hitting the tab key will fire a keypress event.
+ // see http://www.quirksmode.org/js/keys.html
+ TAB_FIRES_KEYPRESS: !goog.userAgent.IE,
+
+ // Has a standards mode quirk where width=100% doesn't do the right thing,
+ // but width=99% does.
+ // TODO(user|user): This should be fixable by less hacky means
+ NEEDS_99_WIDTH_IN_STANDARDS_MODE: goog.userAgent.IE,
+
+ // Whether keyboard events only reliably fire on the document.
+ // On Gecko without contentEditable, keyboard events only fire reliably on the
+ // document element. With contentEditable, the field itself is focusable,
+ // which means that it will fire key events. This does not apply if
+ // application is using ContentEditableField or otherwise overriding Field
+ // not to use an iframe.
+ USE_DOCUMENT_FOR_KEY_EVENTS: goog.userAgent.GECKO &&
+ !goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3,
+
+ // Whether this browser shows non-standard attributes in innerHTML.
+ SHOWS_CUSTOM_ATTRS_IN_INNER_HTML: goog.userAgent.IE,
+
+ // Whether this browser shrinks empty nodes away to nothing.
+ // (If so, we need to insert some space characters into nodes that
+ // shouldn't be collapsed)
+ COLLAPSES_EMPTY_NODES:
+ goog.userAgent.GECKO || goog.userAgent.WEBKIT || goog.userAgent.OPERA,
+
+ // Whether we must convert <strong> and <em> tags to <b>, <i>.
+ CONVERT_TO_B_AND_I_TAGS: goog.userAgent.GECKO || goog.userAgent.OPERA,
+
+ // Whether this browser likes to tab through images in contentEditable mode,
+ // and we like to disable this feature.
+ TABS_THROUGH_IMAGES: goog.userAgent.IE,
+
+ // Whether this browser unescapes urls when you extract it from the href tag.
+ UNESCAPES_URLS_WITHOUT_ASKING: goog.userAgent.IE &&
+ !goog.userAgent.isVersionOrHigher('7.0'),
+
+ // Whether this browser supports execCommand("styleWithCSS") to toggle between
+ // inserting html tags or inline styling for things like bold, italic, etc.
+ HAS_STYLE_WITH_CSS:
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.8') ||
+ goog.userAgent.WEBKIT || goog.userAgent.OPERA,
+
+ // Whether clicking on an editable link will take you to that site.
+ FOLLOWS_EDITABLE_LINKS: goog.userAgent.WEBKIT ||
+ goog.userAgent.IE && goog.userAgent.isVersionOrHigher('9'),
+
+ // Whether this browser has document.activeElement available.
+ HAS_ACTIVE_ELEMENT:
+ goog.userAgent.IE || goog.userAgent.OPERA ||
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9'),
+
+ // Whether this browser supports the setCapture method on DOM elements.
+ HAS_SET_CAPTURE: goog.userAgent.IE,
+
+ // Whether this browser can't set background color when the selection
+ // is collapsed.
+ EATS_EMPTY_BACKGROUND_COLOR: goog.userAgent.GECKO ||
+ goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('527'),
+
+ // Whether this browser supports the "focusin" or "DOMFocusIn" event
+ // consistently.
+ // NOTE(nicksantos): FF supports DOMFocusIn, but doesn't seem to do so
+ // consistently.
+ SUPPORTS_FOCUSIN: goog.userAgent.IE || goog.userAgent.OPERA,
+
+ // Whether clicking on an image will cause the selection to move to the image.
+ // Note: Gecko moves the selection, but it won't always go to the image.
+ // For example, if the image is wrapped in a div, and you click on the img,
+ // anchorNode = focusNode = div, anchorOffset = 0, focusOffset = 1, so this
+ // is another way of "selecting" the image, but there are too many special
+ // cases like this so we will do the work manually.
+ SELECTS_IMAGES_ON_CLICK: goog.userAgent.IE || goog.userAgent.OPERA,
+
+ // Whether this browser moves <style> tags into new <head> elements.
+ MOVES_STYLE_TO_HEAD: goog.userAgent.WEBKIT,
+
+ // Whether this browser collapses the selection in a contenteditable when the
+ // mouse is pressed in a non-editable portion of the same frame, even if
+ // Event.preventDefault is called. This field is deprecated and unused -- only
+ // old versions of Opera have this bug.
+ COLLAPSES_SELECTION_ONMOUSEDOWN: false,
+
+ // Whether the user can actually create a selection in this browser with the
+ // caret in the MIDDLE of the selection by double-clicking.
+ CARET_INSIDE_SELECTION: goog.userAgent.OPERA,
+
+ // Whether the browser focuses <body contenteditable> automatically when
+ // the user clicks on <html>. This field is deprecated and unused -- only old
+ // versions of Opera don't have this behavior.
+ FOCUSES_EDITABLE_BODY_ON_HTML_CLICK: true,
+
+ // Whether to use keydown for key listening (uses keypress otherwise). Taken
+ // from goog.events.KeyHandler.
+ USES_KEYDOWN: goog.userAgent.IE ||
+ goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'),
+
+ // Whether this browser converts spaces to non-breaking spaces when calling
+ // execCommand's RemoveFormat.
+ // See: https://bugs.webkit.org/show_bug.cgi?id=14062
+ ADDS_NBSPS_IN_REMOVE_FORMAT:
+ goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('531'),
+
+ // Whether the browser will get stuck inside a link. That is, if your cursor
+ // is after a link and you type, does your text go inside the link tag.
+ // Bug: http://bugs.webkit.org/show_bug.cgi?id=17697
+ GETS_STUCK_IN_LINKS:
+ goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('528'),
+
+ // Whether the browser corrupts empty text nodes in Node#normalize,
+ // removing them from the Document instead of merging them.
+ NORMALIZE_CORRUPTS_EMPTY_TEXT_NODES: goog.userAgent.GECKO &&
+ goog.userAgent.isVersionOrHigher('1.9') || goog.userAgent.IE ||
+ goog.userAgent.OPERA ||
+ goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('531'),
+
+ // Whether the browser corrupts all text nodes in Node#normalize,
+ // removing them from the Document instead of merging them.
+ NORMALIZE_CORRUPTS_ALL_TEXT_NODES: goog.userAgent.IE,
+
+ // Browsers where executing subscript then superscript (or vv) will cause both
+ // to be applied in a nested fashion instead of the first being overwritten by
+ // the second.
+ NESTS_SUBSCRIPT_SUPERSCRIPT: goog.userAgent.IE || goog.userAgent.GECKO ||
+ goog.userAgent.OPERA,
+
+ // Whether this browser can place a cursor in an empty element natively.
+ CAN_SELECT_EMPTY_ELEMENT: !goog.userAgent.IE && !goog.userAgent.WEBKIT,
+
+ FORGETS_FORMATTING_WHEN_LISTIFYING: goog.userAgent.GECKO ||
+ goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('526'),
+
+ LEAVES_P_WHEN_REMOVING_LISTS: goog.userAgent.IE || goog.userAgent.OPERA,
+
+ CAN_LISTIFY_BR: !goog.userAgent.IE && !goog.userAgent.OPERA,
+
+ // See bug 1286408. When somewhere inside your selection there is an element
+ // with a style attribute that sets the font size, if you change the font
+ // size, the browser creates a font tag, but the font size in the style attr
+ // overrides the font tag. Only webkit removes that font size from the style
+ // attr.
+ DOESNT_OVERRIDE_FONT_SIZE_IN_STYLE_ATTR: !goog.userAgent.WEBKIT,
+
+ // Implements this spec about dragging files from the filesystem to the
+ // browser: http://www.whatwg/org/specs/web-apps/current-work/#dnd
+ SUPPORTS_HTML5_FILE_DRAGGING: (goog.userAgent.product.CHROME &&
+ goog.userAgent.product.isVersion('4')) ||
+ (goog.userAgent.product.SAFARI &&
+ goog.userAgent.isVersionOrHigher('533')) ||
+ (goog.userAgent.GECKO &&
+ goog.userAgent.isVersionOrHigher('2.0')) ||
+ (goog.userAgent.IE &&
+ goog.userAgent.isVersionOrHigher('10')),
+
+ // Version of Opera that supports the opera-defaultBlock execCommand to change
+ // the default block inserted when [return] is pressed. Note that this only is
+ // used if the caret is not already in a block that can be repeated.
+ // TODO(user): Link to public documentation of this feature if Opera puts
+ // something up about it.
+ SUPPORTS_OPERA_DEFAULTBLOCK_COMMAND:
+ goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher('11.10'),
+
+ SUPPORTS_FILE_PASTING: goog.userAgent.product.CHROME &&
+ goog.userAgent.product.isVersion('12')
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/clicktoeditwrapper.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/clicktoeditwrapper.js b/externs/GCL/externs/goog/editor/clicktoeditwrapper.js
new file mode 100644
index 0000000..1623f0d
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/clicktoeditwrapper.js
@@ -0,0 +1,423 @@
+// 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 wrapper around a goog.editor.Field
+ * that listens to mouse events on the specified un-editable field, and makes
+ * the field editable if the user clicks on it. Clients are still responsible
+ * for determining when to make the field un-editable again.
+ *
+ * Clients can still determine when the field has loaded by listening to
+ * field's load event.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.ClickToEditWrapper');
+
+goog.require('goog.Disposable');
+goog.require('goog.dom');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Field');
+goog.require('goog.editor.range');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventType');
+
+
+
+/**
+ * Initialize the wrapper, and begin listening to mouse events immediately.
+ * @param {goog.editor.Field} fieldObj The editable field being wrapped.
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+goog.editor.ClickToEditWrapper = function(fieldObj) {
+ goog.Disposable.call(this);
+
+ /**
+ * The field this wrapper interacts with.
+ * @type {goog.editor.Field}
+ * @private
+ */
+ this.fieldObj_ = fieldObj;
+
+ /**
+ * DOM helper for the field's original element.
+ * @type {goog.dom.DomHelper}
+ * @private
+ */
+ this.originalDomHelper_ = goog.dom.getDomHelper(
+ fieldObj.getOriginalElement());
+
+ /**
+ * @type {goog.dom.SavedCaretRange}
+ * @private
+ */
+ this.savedCaretRange_ = null;
+
+ /**
+ * Event handler for field related events.
+ * @type {!goog.events.EventHandler<!goog.editor.ClickToEditWrapper>}
+ * @private
+ */
+ this.fieldEventHandler_ = new goog.events.EventHandler(this);
+
+ /**
+ * Bound version of the finishMouseUp method.
+ * @type {Function}
+ * @private
+ */
+ this.finishMouseUpBound_ = goog.bind(this.finishMouseUp_, this);
+
+ /**
+ * Event handler for mouse events.
+ * @type {!goog.events.EventHandler<!goog.editor.ClickToEditWrapper>}
+ * @private
+ */
+ this.mouseEventHandler_ = new goog.events.EventHandler(this);
+
+ // Start listening to mouse events immediately if necessary.
+ if (!this.fieldObj_.isLoaded()) {
+ this.enterDocument();
+ }
+
+ this.fieldEventHandler_.
+ // Whenever the field is made editable, we need to check if there
+ // are any carets in it, and if so, use them to render the selection.
+ listen(
+ this.fieldObj_, goog.editor.Field.EventType.LOAD,
+ this.renderSelection_).
+ // Whenever the field is made uneditable, we need to set up
+ // the click-to-edit listeners.
+ listen(
+ this.fieldObj_, goog.editor.Field.EventType.UNLOAD,
+ this.enterDocument);
+};
+goog.inherits(goog.editor.ClickToEditWrapper, goog.Disposable);
+
+
+
+/** @return {goog.editor.Field} The field. */
+goog.editor.ClickToEditWrapper.prototype.getFieldObject = function() {
+ return this.fieldObj_;
+};
+
+
+/** @return {goog.dom.DomHelper} The dom helper of the uneditable element. */
+goog.editor.ClickToEditWrapper.prototype.getOriginalDomHelper = function() {
+ return this.originalDomHelper_;
+};
+
+
+/** @override */
+goog.editor.ClickToEditWrapper.prototype.disposeInternal = function() {
+ goog.editor.ClickToEditWrapper.base(this, 'disposeInternal');
+ this.exitDocument();
+
+ if (this.savedCaretRange_) {
+ this.savedCaretRange_.dispose();
+ }
+
+ this.fieldEventHandler_.dispose();
+ this.mouseEventHandler_.dispose();
+ this.savedCaretRange_ = null;
+ delete this.fieldEventHandler_;
+ delete this.mouseEventHandler_;
+};
+
+
+/**
+ * Initialize listeners when the uneditable field is added to the document.
+ * Also sets up lorem ipsum text.
+ */
+goog.editor.ClickToEditWrapper.prototype.enterDocument = function() {
+ if (this.isInDocument_) {
+ return;
+ }
+
+ this.isInDocument_ = true;
+
+ this.mouseEventTriggeredLoad_ = false;
+ var field = this.fieldObj_.getOriginalElement();
+
+ // To do artificial selection preservation, we have to listen to mouseup,
+ // get the current selection, and re-select the same text in the iframe.
+ //
+ // NOTE(nicksantos): Artificial selection preservation is needed in all cases
+ // where we set the field contents by setting innerHTML. There are a few
+ // rare cases where we don't need it. But these cases are highly
+ // implementation-specific, and computationally hard to detect (bidi
+ // and ig modules both set innerHTML), so we just do it in all cases.
+ this.savedAnchorClicked_ = null;
+ this.mouseEventHandler_.
+ listen(field, goog.events.EventType.MOUSEUP, this.handleMouseUp_).
+ listen(field, goog.events.EventType.CLICK, this.handleClick_);
+
+ // manage lorem ipsum text, if necessary
+ this.fieldObj_.execCommand(goog.editor.Command.UPDATE_LOREM);
+};
+
+
+/**
+ * Destroy listeners when the field is removed from the document.
+ */
+goog.editor.ClickToEditWrapper.prototype.exitDocument = function() {
+ this.mouseEventHandler_.removeAll();
+ this.isInDocument_ = false;
+};
+
+
+/**
+ * Returns the uneditable field element if the field is not yet editable
+ * (equivalent to EditableField.getOriginalElement()), and the editable DOM
+ * element if the field is currently editable (equivalent to
+ * EditableField.getElement()).
+ * @return {Element} The element containing the editable field contents.
+ */
+goog.editor.ClickToEditWrapper.prototype.getElement = function() {
+ return this.fieldObj_.isLoaded() ?
+ this.fieldObj_.getElement() : this.fieldObj_.getOriginalElement();
+};
+
+
+/**
+ * True if a mouse event should be handled, false if it should be ignored.
+ * @param {goog.events.BrowserEvent} e The mouse event.
+ * @return {boolean} Wether or not this mouse event should be handled.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.prototype.shouldHandleMouseEvent_ = function(e) {
+ return e.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&
+ !(e.shiftKey || e.ctrlKey || e.altKey || e.metaKey);
+};
+
+
+/**
+ * Handle mouse click events on the field.
+ * @param {goog.events.BrowserEvent} e The click event.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.prototype.handleClick_ = function(e) {
+ // If the user clicked on a link in an uneditable field,
+ // we want to cancel the click.
+ var anchorAncestor = goog.dom.getAncestorByTagNameAndClass(
+ /** @type {Node} */ (e.target),
+ goog.dom.TagName.A);
+ if (anchorAncestor) {
+ e.preventDefault();
+
+ if (!goog.editor.BrowserFeature.HAS_ACTIVE_ELEMENT) {
+ this.savedAnchorClicked_ = anchorAncestor;
+ }
+ }
+};
+
+
+/**
+ * Handle a mouse up event on the field.
+ * @param {goog.events.BrowserEvent} e The mouseup event.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.prototype.handleMouseUp_ = function(e) {
+ // Only respond to the left mouse button.
+ if (this.shouldHandleMouseEvent_(e)) {
+ // We need to get the selection when the user mouses up, but the
+ // selection doesn't actually change until after the mouseup event has
+ // propagated. So we need to do this asynchronously.
+ this.originalDomHelper_.getWindow().setTimeout(this.finishMouseUpBound_, 0);
+ }
+};
+
+
+/**
+ * A helper function for handleMouseUp_ -- does the actual work
+ * when the event is finished propagating.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.prototype.finishMouseUp_ = function() {
+ // Make sure that the field is still not editable.
+ if (!this.fieldObj_.isLoaded()) {
+ if (this.savedCaretRange_) {
+ this.savedCaretRange_.dispose();
+ this.savedCaretRange_ = null;
+ }
+
+ if (!this.fieldObj_.queryCommandValue(goog.editor.Command.USING_LOREM)) {
+ // We need carets (blank span nodes) to maintain the selection when
+ // the html is copied into an iframe. However, because our code
+ // clears the selection to make the behavior consistent, we need to do
+ // this even when we're not using an iframe.
+ this.insertCarets_();
+ }
+
+ this.ensureFieldEditable_();
+ }
+
+ this.exitDocument();
+ this.savedAnchorClicked_ = null;
+};
+
+
+/**
+ * Ensure that the field is editable. If the field is not editable,
+ * make it so, and record the fact that it was done by a user mouse event.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.prototype.ensureFieldEditable_ = function() {
+ if (!this.fieldObj_.isLoaded()) {
+ this.mouseEventTriggeredLoad_ = true;
+ this.makeFieldEditable(this.fieldObj_);
+ }
+};
+
+
+/**
+ * Once the field has loaded in an iframe, re-create the selection
+ * as marked by the carets.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.prototype.renderSelection_ = function() {
+ if (this.savedCaretRange_) {
+ // Make sure that the restoration document is inside the iframe
+ // if we're using one.
+ this.savedCaretRange_.setRestorationDocument(
+ this.fieldObj_.getEditableDomHelper().getDocument());
+
+ var startCaret = this.savedCaretRange_.getCaret(true);
+ var endCaret = this.savedCaretRange_.getCaret(false);
+ var hasCarets = startCaret && endCaret;
+ }
+
+ // There are two reasons why we might want to focus the field:
+ // 1) makeFieldEditable was triggered by the click-to-edit wrapper.
+ // In this case, the mouse event should have triggered a focus, but
+ // the editor might have taken the focus away to create lorem ipsum
+ // text or create an iframe for the field. So we make sure the focus
+ // is restored.
+ // 2) somebody placed carets, and we need to select those carets. The field
+ // needs focus to ensure that the selection appears.
+ if (this.mouseEventTriggeredLoad_ || hasCarets) {
+ this.focusOnFieldObj(this.fieldObj_);
+ }
+
+ if (hasCarets) {
+
+ this.savedCaretRange_.restore();
+ this.fieldObj_.dispatchSelectionChangeEvent();
+
+ // NOTE(nicksantos): Bubbles aren't actually enabled until the end
+ // if the load sequence, so if the user clicked on a link, the bubble
+ // will not pop up.
+ }
+
+ if (this.savedCaretRange_) {
+ this.savedCaretRange_.dispose();
+ this.savedCaretRange_ = null;
+ }
+
+ this.mouseEventTriggeredLoad_ = false;
+};
+
+
+/**
+ * Focus on the field object.
+ * @param {goog.editor.Field} field The field to focus.
+ * @protected
+ */
+goog.editor.ClickToEditWrapper.prototype.focusOnFieldObj = function(field) {
+ field.focusAndPlaceCursorAtStart();
+};
+
+
+/**
+ * Make the field object editable.
+ * @param {goog.editor.Field} field The field to make editable.
+ * @protected
+ */
+goog.editor.ClickToEditWrapper.prototype.makeFieldEditable = function(field) {
+ field.makeEditable();
+};
+
+
+//================================================================
+// Caret-handling methods
+
+
+/**
+ * Gets a saved caret range for the given range.
+ * @param {goog.dom.AbstractRange} range A range wrapper.
+ * @return {goog.dom.SavedCaretRange} The range, saved with carets, or null
+ * if the range wrapper was null.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.createCaretRange_ = function(range) {
+ return range && goog.editor.range.saveUsingNormalizedCarets(range);
+};
+
+
+/**
+ * Inserts the carets, given the current selection.
+ *
+ * Note that for all practical purposes, a cursor position is just
+ * a selection with the start and end at the same point.
+ * @private
+ */
+goog.editor.ClickToEditWrapper.prototype.insertCarets_ = function() {
+ var fieldElement = this.fieldObj_.getOriginalElement();
+
+ this.savedCaretRange_ = null;
+ var originalWindow = this.originalDomHelper_.getWindow();
+ if (goog.dom.Range.hasSelection(originalWindow)) {
+ var range = goog.dom.Range.createFromWindow(originalWindow);
+ range = range && goog.editor.range.narrow(range, fieldElement);
+ this.savedCaretRange_ =
+ goog.editor.ClickToEditWrapper.createCaretRange_(range);
+ }
+
+ if (!this.savedCaretRange_) {
+ // We couldn't figure out where to put the carets.
+ // But in FF2/IE6+, this could mean that the user clicked on a
+ // 'special' node, (e.g., a link or an unselectable item). So the
+ // selection appears to be null or the full page, even though the user did
+ // click on something. In IE, we can determine the real selection via
+ // document.activeElement. In FF, we have to be more hacky.
+ var specialNodeClicked;
+ if (goog.editor.BrowserFeature.HAS_ACTIVE_ELEMENT) {
+ specialNodeClicked = goog.dom.getActiveElement(
+ this.originalDomHelper_.getDocument());
+ } else {
+ specialNodeClicked = this.savedAnchorClicked_;
+ }
+
+ var isFieldElement = function(node) {
+ return node == fieldElement;
+ };
+ if (specialNodeClicked &&
+ goog.dom.getAncestor(specialNodeClicked, isFieldElement, true)) {
+ // Insert the cursor at the beginning of the active element to be
+ // consistent with the behavior in FF1.5, where clicking on a
+ // link makes the current selection equal to the cursor position
+ // directly before that link.
+ //
+ // TODO(nicksantos): Is there a way to more accurately place the cursor?
+ this.savedCaretRange_ = goog.editor.ClickToEditWrapper.createCaretRange_(
+ goog.dom.Range.createFromNodes(
+ specialNodeClicked, 0, specialNodeClicked, 0));
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/command.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/command.js b/externs/GCL/externs/goog/editor/command.js
new file mode 100644
index 0000000..2996b8c
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/command.js
@@ -0,0 +1,76 @@
+// Copyright 2009 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 Commands that the editor can execute.
+ * @see ../demos/editor/editor.html
+ */
+goog.provide('goog.editor.Command');
+
+
+/**
+ * Commands that the editor can excute via execCommand or queryCommandValue.
+ * @enum {string}
+ */
+goog.editor.Command = {
+ // Prepend all the strings of built in execCommands with a plus to ensure
+ // that there's no conflict if a client wants to use the
+ // browser's execCommand.
+ UNDO: '+undo',
+ REDO: '+redo',
+ LINK: '+link',
+ FORMAT_BLOCK: '+formatBlock',
+ INDENT: '+indent',
+ OUTDENT: '+outdent',
+ REMOVE_FORMAT: '+removeFormat',
+ STRIKE_THROUGH: '+strikeThrough',
+ HORIZONTAL_RULE: '+insertHorizontalRule',
+ SUBSCRIPT: '+subscript',
+ SUPERSCRIPT: '+superscript',
+ UNDERLINE: '+underline',
+ BOLD: '+bold',
+ ITALIC: '+italic',
+ FONT_SIZE: '+fontSize',
+ FONT_FACE: '+fontName',
+ FONT_COLOR: '+foreColor',
+ EMOTICON: '+emoticon',
+ EQUATION: '+equation',
+ BACKGROUND_COLOR: '+backColor',
+ ORDERED_LIST: '+insertOrderedList',
+ UNORDERED_LIST: '+insertUnorderedList',
+ TABLE: '+table',
+ JUSTIFY_CENTER: '+justifyCenter',
+ JUSTIFY_FULL: '+justifyFull',
+ JUSTIFY_RIGHT: '+justifyRight',
+ JUSTIFY_LEFT: '+justifyLeft',
+ BLOCKQUOTE: '+BLOCKQUOTE', // This is a nodename. Should be all caps.
+ DIR_LTR: 'ltr', // should be exactly 'ltr' as it becomes dir attribute value
+ DIR_RTL: 'rtl', // same here
+ IMAGE: 'image',
+ EDIT_HTML: 'editHtml',
+ UPDATE_LINK_BUBBLE: 'updateLinkBubble',
+
+ // queryCommandValue only: returns the default tag name used in the field.
+ // DIV should be considered the default if no plugin responds.
+ DEFAULT_TAG: '+defaultTag',
+
+ // TODO(nicksantos): Try to give clients an API so that they don't need
+ // these execCommands.
+ CLEAR_LOREM: 'clearlorem',
+ UPDATE_LOREM: 'updatelorem',
+ USING_LOREM: 'usinglorem',
+
+ // Modal editor commands (usually dialogs).
+ MODAL_LINK_EDITOR: 'link'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/contenteditablefield.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/contenteditablefield.js b/externs/GCL/externs/goog/editor/contenteditablefield.js
new file mode 100644
index 0000000..a30d245
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/contenteditablefield.js
@@ -0,0 +1,108 @@
+// Copyright 2012 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Class to encapsulate an editable field that blends into the
+ * style of the page and never uses an iframe. The field's height can be
+ * controlled by CSS styles like min-height, max-height, and overflow. This is
+ * a goog.editor.Field, but overrides everything iframe related to use
+ * contentEditable divs. This is essentially a much lighter alternative to
+ * goog.editor.SeamlessField, but only works in Firefox 3+, and only works
+ * *well* in Firefox 12+ due to
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=669026.
+ *
+ * @author gboyer@google.com (Garrett Boyer)
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+
+goog.provide('goog.editor.ContentEditableField');
+
+goog.require('goog.asserts');
+goog.require('goog.editor.Field');
+goog.require('goog.log');
+
+
+
+/**
+ * This class encapsulates an editable field that is just a contentEditable
+ * div.
+ *
+ * To see events fired by this object, please see the base class.
+ *
+ * @param {string} id An identifer for the field. This is used to find the
+ * field and the element associated with this field.
+ * @param {Document=} opt_doc The document that the element with the given
+ * id can be found in.
+ * @constructor
+ * @extends {goog.editor.Field}
+ */
+goog.editor.ContentEditableField = function(id, opt_doc) {
+ goog.editor.Field.call(this, id, opt_doc);
+};
+goog.inherits(goog.editor.ContentEditableField, goog.editor.Field);
+
+
+/**
+ * @override
+ */
+goog.editor.ContentEditableField.prototype.logger =
+ goog.log.getLogger('goog.editor.ContentEditableField');
+
+
+/** @override */
+goog.editor.ContentEditableField.prototype.usesIframe = function() {
+ // Never uses an iframe in any browser.
+ return false;
+};
+
+
+// Overridden to improve dead code elimination only.
+/** @override */
+goog.editor.ContentEditableField.prototype.turnOnDesignModeGecko =
+ goog.nullFunction;
+
+
+/** @override */
+goog.editor.ContentEditableField.prototype.installStyles = function() {
+ goog.asserts.assert(!this.cssStyles, 'ContentEditableField does not support' +
+ ' CSS styles; instead just write plain old CSS on the main page.');
+};
+
+
+/** @override */
+goog.editor.ContentEditableField.prototype.makeEditableInternal = function(
+ opt_iframeSrc) {
+ var field = this.getOriginalElement();
+ if (field) {
+ this.setupFieldObject(field);
+ // TODO(gboyer): Allow clients/plugins to override with 'plaintext-only'
+ // for WebKit.
+ field.contentEditable = true;
+
+ this.injectContents(field.innerHTML, field);
+
+ this.handleFieldLoad();
+ }
+};
+
+
+/**
+ * @override
+ *
+ * ContentEditableField does not make any changes to the DOM when it is made
+ * editable other than setting contentEditable to true.
+ */
+goog.editor.ContentEditableField.prototype.restoreDom =
+ goog.nullFunction;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/defines.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/defines.js b/externs/GCL/externs/goog/editor/defines.js
new file mode 100644
index 0000000..1bf57ba
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/defines.js
@@ -0,0 +1,34 @@
+// 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 Text editor constants for compile time feature selection.
+ *
+ */
+
+goog.provide('goog.editor.defines');
+
+
+/**
+ * @define {boolean} Use contentEditable in FF.
+ * There are a number of known bugs when the only content in your field is
+ * inline (e.g. just text, no block elements):
+ * -indent is a noop and then DOMSubtreeModified events stop firing until
+ * the structure of the DOM is changed (e.g. make something bold).
+ * -inserting lists inserts just a NBSP, no list!
+ * Once those two are fixed, we should have one client guinea pig it and put
+ * it through a QA run. If we can file the bugs with Mozilla, there's a chance
+ * they'll fix them for a dot release of Firefox 3.
+ */
+goog.define('goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3', false);
[29/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/fontsizemonitor.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/fontsizemonitor.js b/externs/GCL/externs/goog/dom/fontsizemonitor.js
new file mode 100644
index 0000000..6c7c8b4
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/fontsizemonitor.js
@@ -0,0 +1,162 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A class that can be used to listen to font size changes.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.dom.FontSizeMonitor');
+goog.provide('goog.dom.FontSizeMonitor.EventType');
+
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.events');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.userAgent');
+
+
+// TODO(arv): Move this to goog.events instead.
+
+
+
+/**
+ * This class can be used to monitor changes in font size. Instances will
+ * dispatch a {@code goog.dom.FontSizeMonitor.EventType.CHANGE} event.
+ * Example usage:
+ * <pre>
+ * var fms = new goog.dom.FontSizeMonitor();
+ * goog.events.listen(fms, goog.dom.FontSizeMonitor.EventType.CHANGE,
+ * function(e) {
+ * alert('Font size was changed');
+ * });
+ * </pre>
+ * @param {goog.dom.DomHelper=} opt_domHelper DOM helper object that is used to
+ * determine where to insert the DOM nodes used to determine when the font
+ * size changes.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.dom.FontSizeMonitor = function(opt_domHelper) {
+ goog.events.EventTarget.call(this);
+
+ var dom = opt_domHelper || goog.dom.getDomHelper();
+
+ /**
+ * Offscreen iframe which we use to detect resize events.
+ * @type {Element}
+ * @private
+ */
+ this.sizeElement_ = dom.createDom(
+ // The size of the iframe is expressed in em, which are font size relative
+ // which will cause the iframe to be resized when the font size changes.
+ // The actual values are not relevant as long as we can ensure that the
+ // iframe has a non zero size and is completely off screen.
+ goog.userAgent.IE ? goog.dom.TagName.DIV : goog.dom.TagName.IFRAME, {
+ 'style': 'position:absolute;width:9em;height:9em;top:-99em',
+ 'tabIndex': -1,
+ 'aria-hidden': 'true'
+ });
+ var p = dom.getDocument().body;
+ p.insertBefore(this.sizeElement_, p.firstChild);
+
+ /**
+ * The object that we listen to resize events on.
+ * @type {Element|Window}
+ * @private
+ */
+ var resizeTarget = this.resizeTarget_ =
+ goog.userAgent.IE ? this.sizeElement_ :
+ goog.dom.getFrameContentWindow(
+ /** @type {HTMLIFrameElement} */ (this.sizeElement_));
+
+ // We need to open and close the document to get Firefox 2 to work. We must
+ // not do this for IE in case we are using HTTPS since accessing the document
+ // on an about:blank iframe in IE using HTTPS raises a Permission Denied
+ // error.
+ if (goog.userAgent.GECKO) {
+ var doc = resizeTarget.document;
+ doc.open();
+ doc.close();
+ }
+
+ // Listen to resize event on the window inside the iframe.
+ goog.events.listen(resizeTarget, goog.events.EventType.RESIZE,
+ this.handleResize_, false, this);
+
+ /**
+ * Last measured width of the iframe element.
+ * @type {number}
+ * @private
+ */
+ this.lastWidth_ = this.sizeElement_.offsetWidth;
+};
+goog.inherits(goog.dom.FontSizeMonitor, goog.events.EventTarget);
+
+
+/**
+ * The event types that the FontSizeMonitor fires.
+ * @enum {string}
+ */
+goog.dom.FontSizeMonitor.EventType = {
+ // TODO(arv): Change value to 'change' after updating the callers.
+ CHANGE: 'fontsizechange'
+};
+
+
+/**
+ * Constant for the change event.
+ * @type {string}
+ * @deprecated Use {@code goog.dom.FontSizeMonitor.EventType.CHANGE} instead.
+ */
+goog.dom.FontSizeMonitor.CHANGE_EVENT =
+ goog.dom.FontSizeMonitor.EventType.CHANGE;
+
+
+/** @override */
+goog.dom.FontSizeMonitor.prototype.disposeInternal = function() {
+ goog.dom.FontSizeMonitor.superClass_.disposeInternal.call(this);
+
+ goog.events.unlisten(this.resizeTarget_, goog.events.EventType.RESIZE,
+ this.handleResize_, false, this);
+ this.resizeTarget_ = null;
+
+ // Firefox 2 crashes if the iframe is removed during the unload phase.
+ if (!goog.userAgent.GECKO ||
+ goog.userAgent.isVersionOrHigher('1.9')) {
+ goog.dom.removeNode(this.sizeElement_);
+ }
+ delete this.sizeElement_;
+};
+
+
+/**
+ * Handles the onresize event of the iframe and dispatches a change event in
+ * case its size really changed.
+ * @param {goog.events.BrowserEvent} e The event object.
+ * @private
+ */
+goog.dom.FontSizeMonitor.prototype.handleResize_ = function(e) {
+ // Only dispatch the event if the size really changed. Some newer browsers do
+ // not really change the font-size, instead they zoom the whole page. This
+ // does trigger window resize events on the iframe but the logical pixel size
+ // remains the same (the device pixel size changes but that is irrelevant).
+ var currentWidth = this.sizeElement_.offsetWidth;
+ if (this.lastWidth_ != currentWidth) {
+ this.lastWidth_ = currentWidth;
+ this.dispatchEvent(goog.dom.FontSizeMonitor.EventType.CHANGE);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/forms.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/forms.js b/externs/GCL/externs/goog/dom/forms.js
new file mode 100644
index 0000000..75dc2e5
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/forms.js
@@ -0,0 +1,417 @@
+// 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 manipulating a form and elements.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.dom.forms');
+
+goog.require('goog.dom.InputType');
+goog.require('goog.dom.TagName');
+goog.require('goog.structs.Map');
+
+
+/**
+ * Returns form data as a map of name to value arrays. This doesn't
+ * support file inputs.
+ * @param {HTMLFormElement} form The form.
+ * @return {!goog.structs.Map.<string, !Array.<string>>} A map of the form data
+ * as field name to arrays of values.
+ */
+goog.dom.forms.getFormDataMap = function(form) {
+ var map = new goog.structs.Map();
+ goog.dom.forms.getFormDataHelper_(form, map,
+ goog.dom.forms.addFormDataToMap_);
+ return map;
+};
+
+
+/**
+ * Returns the form data as an application/x-www-url-encoded string. This
+ * doesn't support file inputs.
+ * @param {HTMLFormElement} form The form.
+ * @return {string} An application/x-www-url-encoded string.
+ */
+goog.dom.forms.getFormDataString = function(form) {
+ var sb = [];
+ goog.dom.forms.getFormDataHelper_(form, sb,
+ goog.dom.forms.addFormDataToStringBuffer_);
+ return sb.join('&');
+};
+
+
+/**
+ * Returns the form data as a map or an application/x-www-url-encoded
+ * string. This doesn't support file inputs.
+ * @param {HTMLFormElement} form The form.
+ * @param {Object} result The object form data is being put in.
+ * @param {Function} fnAppend Function that takes {@code result}, an element
+ * name, and an element value, and adds the name/value pair to the result
+ * object.
+ * @private
+ */
+goog.dom.forms.getFormDataHelper_ = function(form, result, fnAppend) {
+ var els = form.elements;
+ for (var el, i = 0; el = els[i]; i++) {
+ if (// Make sure we don't include elements that are not part of the form.
+ // Some browsers include non-form elements. Check for 'form' property.
+ // See http://code.google.com/p/closure-library/issues/detail?id=227
+ // and
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#the-input-element
+ (el.form != form) ||
+ el.disabled ||
+ // HTMLFieldSetElement has a form property but no value.
+ el.tagName == goog.dom.TagName.FIELDSET) {
+ continue;
+ }
+
+ var name = el.name;
+ switch (el.type.toLowerCase()) {
+ case goog.dom.InputType.FILE:
+ // file inputs are not supported
+ case goog.dom.InputType.SUBMIT:
+ case goog.dom.InputType.RESET:
+ case goog.dom.InputType.BUTTON:
+ // don't submit these
+ break;
+ case goog.dom.InputType.SELECT_MULTIPLE:
+ var values = goog.dom.forms.getValue(el);
+ if (values != null) {
+ for (var value, j = 0; value = values[j]; j++) {
+ fnAppend(result, name, value);
+ }
+ }
+ break;
+ default:
+ var value = goog.dom.forms.getValue(el);
+ if (value != null) {
+ fnAppend(result, name, value);
+ }
+ }
+ }
+
+ // input[type=image] are not included in the elements collection
+ var inputs = form.getElementsByTagName(goog.dom.TagName.INPUT);
+ for (var input, i = 0; input = inputs[i]; i++) {
+ if (input.form == form &&
+ input.type.toLowerCase() == goog.dom.InputType.IMAGE) {
+ name = input.name;
+ fnAppend(result, name, input.value);
+ fnAppend(result, name + '.x', '0');
+ fnAppend(result, name + '.y', '0');
+ }
+ }
+};
+
+
+/**
+ * Adds the name/value pair to the map.
+ * @param {!goog.structs.Map.<string, !Array.<string>>} map The map to add to.
+ * @param {string} name The name.
+ * @param {string} value The value.
+ * @private
+ */
+goog.dom.forms.addFormDataToMap_ = function(map, name, value) {
+ var array = map.get(name);
+ if (!array) {
+ array = [];
+ map.set(name, array);
+ }
+ array.push(value);
+};
+
+
+/**
+ * Adds a name/value pair to an string buffer array in the form 'name=value'.
+ * @param {Array<string>} sb The string buffer array for storing data.
+ * @param {string} name The name.
+ * @param {string} value The value.
+ * @private
+ */
+goog.dom.forms.addFormDataToStringBuffer_ = function(sb, name, value) {
+ sb.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
+};
+
+
+/**
+ * Whether the form has a file input.
+ * @param {HTMLFormElement} form The form.
+ * @return {boolean} Whether the form has a file input.
+ */
+goog.dom.forms.hasFileInput = function(form) {
+ var els = form.elements;
+ for (var el, i = 0; el = els[i]; i++) {
+ if (!el.disabled && el.type &&
+ el.type.toLowerCase() == goog.dom.InputType.FILE) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Enables or disables either all elements in a form or a single form element.
+ * @param {Element} el The element, either a form or an element within a form.
+ * @param {boolean} disabled Whether the element should be disabled.
+ */
+goog.dom.forms.setDisabled = function(el, disabled) {
+ // disable all elements in a form
+ if (el.tagName == goog.dom.TagName.FORM) {
+ var els = el.elements;
+ for (var i = 0; el = els[i]; i++) {
+ goog.dom.forms.setDisabled(el, disabled);
+ }
+ } else {
+ // makes sure to blur buttons, multi-selects, and any elements which
+ // maintain keyboard/accessibility focus when disabled
+ if (disabled == true) {
+ el.blur();
+ }
+ el.disabled = disabled;
+ }
+};
+
+
+/**
+ * Focuses, and optionally selects the content of, a form element.
+ * @param {Element} el The form element.
+ */
+goog.dom.forms.focusAndSelect = function(el) {
+ el.focus();
+ if (el.select) {
+ el.select();
+ }
+};
+
+
+/**
+ * Whether a form element has a value.
+ * @param {Element} el The element.
+ * @return {boolean} Whether the form has a value.
+ */
+goog.dom.forms.hasValue = function(el) {
+ var value = goog.dom.forms.getValue(el);
+ return !!value;
+};
+
+
+/**
+ * Whether a named form field has a value.
+ * @param {HTMLFormElement} form The form element.
+ * @param {string} name Name of an input to the form.
+ * @return {boolean} Whether the form has a value.
+ */
+goog.dom.forms.hasValueByName = function(form, name) {
+ var value = goog.dom.forms.getValueByName(form, name);
+ return !!value;
+};
+
+
+/**
+ * Gets the current value of any element with a type.
+ * @param {Element} el The element.
+ * @return {string|Array<string>|null} The current value of the element
+ * (or null).
+ */
+goog.dom.forms.getValue = function(el) {
+ var type = el.type;
+ if (!goog.isDef(type)) {
+ return null;
+ }
+ switch (type.toLowerCase()) {
+ case goog.dom.InputType.CHECKBOX:
+ case goog.dom.InputType.RADIO:
+ return goog.dom.forms.getInputChecked_(el);
+ case goog.dom.InputType.SELECT_ONE:
+ return goog.dom.forms.getSelectSingle_(el);
+ case goog.dom.InputType.SELECT_MULTIPLE:
+ return goog.dom.forms.getSelectMultiple_(el);
+ default:
+ return goog.isDef(el.value) ? el.value : null;
+ }
+};
+
+
+/**
+ * Alias for goog.dom.form.element.getValue
+ * @type {Function}
+ * @deprecated Use {@link goog.dom.forms.getValue} instead.
+ * @suppress {missingProvide}
+ */
+goog.dom.$F = goog.dom.forms.getValue;
+
+
+/**
+ * Returns the value of the named form field. In the case of radio buttons,
+ * returns the value of the checked button with the given name.
+ *
+ * @param {HTMLFormElement} form The form element.
+ * @param {string} name Name of an input to the form.
+ *
+ * @return {Array<string>|string|null} The value of the form element, or
+ * null if the form element does not exist or has no value.
+ */
+goog.dom.forms.getValueByName = function(form, name) {
+ var els = form.elements[name];
+
+ if (els) {
+ if (els.type) {
+ return goog.dom.forms.getValue(els);
+ } else {
+ for (var i = 0; i < els.length; i++) {
+ var val = goog.dom.forms.getValue(els[i]);
+ if (val) {
+ return val;
+ }
+ }
+ }
+ }
+ return null;
+};
+
+
+/**
+ * Gets the current value of a checkable input element.
+ * @param {Element} el The element.
+ * @return {?string} The value of the form element (or null).
+ * @private
+ */
+goog.dom.forms.getInputChecked_ = function(el) {
+ return el.checked ? el.value : null;
+};
+
+
+/**
+ * Gets the current value of a select-one element.
+ * @param {Element} el The element.
+ * @return {?string} The value of the form element (or null).
+ * @private
+ */
+goog.dom.forms.getSelectSingle_ = function(el) {
+ var selectedIndex = el.selectedIndex;
+ return selectedIndex >= 0 ? el.options[selectedIndex].value : null;
+};
+
+
+/**
+ * Gets the current value of a select-multiple element.
+ * @param {Element} el The element.
+ * @return {Array<string>?} The value of the form element (or null).
+ * @private
+ */
+goog.dom.forms.getSelectMultiple_ = function(el) {
+ var values = [];
+ for (var option, i = 0; option = el.options[i]; i++) {
+ if (option.selected) {
+ values.push(option.value);
+ }
+ }
+ return values.length ? values : null;
+};
+
+
+/**
+ * Sets the current value of any element with a type.
+ * @param {Element} el The element.
+ * @param {*=} opt_value The value to give to the element, which will be coerced
+ * by the browser in the default case using toString. This value should be
+ * an array for setting the value of select multiple elements.
+ */
+goog.dom.forms.setValue = function(el, opt_value) {
+ var type = el.type;
+ if (goog.isDef(type)) {
+ switch (type.toLowerCase()) {
+ case goog.dom.InputType.CHECKBOX:
+ case goog.dom.InputType.RADIO:
+ goog.dom.forms.setInputChecked_(el,
+ /** @type {string} */ (opt_value));
+ break;
+ case goog.dom.InputType.SELECT_ONE:
+ goog.dom.forms.setSelectSingle_(el,
+ /** @type {string} */ (opt_value));
+ break;
+ case goog.dom.InputType.SELECT_MULTIPLE:
+ goog.dom.forms.setSelectMultiple_(el,
+ /** @type {Array<string>} */ (opt_value));
+ break;
+ default:
+ el.value = goog.isDefAndNotNull(opt_value) ? opt_value : '';
+ }
+ }
+};
+
+
+/**
+ * Sets a checkable input element's checked property.
+ * #TODO(user): This seems potentially unintuitive since it doesn't set
+ * the value property but my hunch is that the primary use case is to check a
+ * checkbox, not to reset its value property.
+ * @param {Element} el The element.
+ * @param {string|boolean=} opt_value The value, sets the element checked if
+ * val is set.
+ * @private
+ */
+goog.dom.forms.setInputChecked_ = function(el, opt_value) {
+ el.checked = opt_value;
+};
+
+
+/**
+ * Sets the value of a select-one element.
+ * @param {Element} el The element.
+ * @param {string=} opt_value The value of the selected option element.
+ * @private
+ */
+goog.dom.forms.setSelectSingle_ = function(el, opt_value) {
+ // unset any prior selections
+ el.selectedIndex = -1;
+ if (goog.isString(opt_value)) {
+ for (var option, i = 0; option = el.options[i]; i++) {
+ if (option.value == opt_value) {
+ option.selected = true;
+ break;
+ }
+ }
+ }
+};
+
+
+/**
+ * Sets the value of a select-multiple element.
+ * @param {Element} el The element.
+ * @param {Array<string>|string=} opt_value The value of the selected option
+ * element(s).
+ * @private
+ */
+goog.dom.forms.setSelectMultiple_ = function(el, opt_value) {
+ // reset string opt_values as an array
+ if (goog.isString(opt_value)) {
+ opt_value = [opt_value];
+ }
+ for (var option, i = 0; option = el.options[i]; i++) {
+ // we have to reset the other options to false for select-multiple
+ option.selected = false;
+ if (opt_value) {
+ for (var value, j = 0; value = opt_value[j]; j++) {
+ if (option.value == value) {
+ option.selected = true;
+ }
+ }
+ }
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/fullscreen.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/fullscreen.js b/externs/GCL/externs/goog/dom/fullscreen.js
new file mode 100644
index 0000000..1954213
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/fullscreen.js
@@ -0,0 +1,144 @@
+// Copyright 2012 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 Functions for managing full screen status of the DOM.
+ *
+ */
+
+goog.provide('goog.dom.fullscreen');
+goog.provide('goog.dom.fullscreen.EventType');
+
+goog.require('goog.dom');
+goog.require('goog.userAgent');
+
+
+/**
+ * Event types for full screen.
+ * @enum {string}
+ */
+goog.dom.fullscreen.EventType = {
+ /** Dispatched by the Document when the fullscreen status changes. */
+ CHANGE: (function() {
+ if (goog.userAgent.WEBKIT) {
+ return 'webkitfullscreenchange';
+ }
+ if (goog.userAgent.GECKO) {
+ return 'mozfullscreenchange';
+ }
+ if (goog.userAgent.IE) {
+ return 'MSFullscreenChange';
+ }
+ // Opera 12-14, and W3C standard (Draft):
+ // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
+ return 'fullscreenchange';
+ })()
+};
+
+
+/**
+ * Determines if full screen is supported.
+ * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being
+ * queried. If not provided, use the current DOM.
+ * @return {boolean} True iff full screen is supported.
+ */
+goog.dom.fullscreen.isSupported = function(opt_domHelper) {
+ var doc = goog.dom.fullscreen.getDocument_(opt_domHelper);
+ var body = doc.body;
+ return !!(body.webkitRequestFullscreen ||
+ (body.mozRequestFullScreen && doc.mozFullScreenEnabled) ||
+ (body.msRequestFullscreen && doc.msFullscreenEnabled) ||
+ (body.requestFullscreen && doc.fullscreenEnabled));
+};
+
+
+/**
+ * Requests putting the element in full screen.
+ * @param {!Element} element The element to put full screen.
+ */
+goog.dom.fullscreen.requestFullScreen = function(element) {
+ if (element.webkitRequestFullscreen) {
+ element.webkitRequestFullscreen();
+ } else if (element.mozRequestFullScreen) {
+ element.mozRequestFullScreen();
+ } else if (element.msRequestFullscreen) {
+ element.msRequestFullscreen();
+ } else if (element.requestFullscreen) {
+ element.requestFullscreen();
+ }
+};
+
+
+/**
+ * Requests putting the element in full screen with full keyboard access.
+ * @param {!Element} element The element to put full screen.
+ */
+goog.dom.fullscreen.requestFullScreenWithKeys = function(
+ element) {
+ if (element.mozRequestFullScreenWithKeys) {
+ element.mozRequestFullScreenWithKeys();
+ } else if (element.webkitRequestFullscreen) {
+ element.webkitRequestFullscreen();
+ } else {
+ goog.dom.fullscreen.requestFullScreen(element);
+ }
+};
+
+
+/**
+ * Exits full screen.
+ * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being
+ * queried. If not provided, use the current DOM.
+ */
+goog.dom.fullscreen.exitFullScreen = function(opt_domHelper) {
+ var doc = goog.dom.fullscreen.getDocument_(opt_domHelper);
+ if (doc.webkitCancelFullScreen) {
+ doc.webkitCancelFullScreen();
+ } else if (doc.mozCancelFullScreen) {
+ doc.mozCancelFullScreen();
+ } else if (doc.msExitFullscreen) {
+ doc.msExitFullscreen();
+ } else if (doc.exitFullscreen) {
+ doc.exitFullscreen();
+ }
+};
+
+
+/**
+ * Determines if the document is full screen.
+ * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being
+ * queried. If not provided, use the current DOM.
+ * @return {boolean} Whether the document is full screen.
+ */
+goog.dom.fullscreen.isFullScreen = function(opt_domHelper) {
+ var doc = goog.dom.fullscreen.getDocument_(opt_domHelper);
+ // IE 11 doesn't have similar boolean property, so check whether
+ // document.msFullscreenElement is null instead.
+ return !!(doc.webkitIsFullScreen || doc.mozFullScreen ||
+ doc.msFullscreenElement || doc.fullscreenElement);
+};
+
+
+/**
+ * Gets the document object of the dom.
+ * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being
+ * queried. If not provided, use the current DOM.
+ * @return {!Document} The dom document.
+ * @private
+ */
+goog.dom.fullscreen.getDocument_ = function(opt_domHelper) {
+ return opt_domHelper ?
+ opt_domHelper.getDocument() :
+ goog.dom.getDomHelper().getDocument();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/iframe.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/iframe.js b/externs/GCL/externs/goog/dom/iframe.js
new file mode 100644
index 0000000..a22b8b7
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/iframe.js
@@ -0,0 +1,216 @@
+// 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 creating and working with iframes
+ * cross-browser.
+ * @author gboyer@google.com (Garry Boyer)
+ */
+
+
+goog.provide('goog.dom.iframe');
+
+goog.require('goog.dom');
+goog.require('goog.dom.safe');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeStyle');
+goog.require('goog.html.legacyconversions');
+goog.require('goog.userAgent');
+
+
+/**
+ * Safe source for a blank iframe.
+ *
+ * Intentionally not about:blank, which gives mixed content warnings in IE6
+ * over HTTPS.
+ *
+ * @type {string}
+ */
+goog.dom.iframe.BLANK_SOURCE = 'javascript:""';
+
+
+/**
+ * Safe source for a new blank iframe that may not cause a new load of the
+ * iframe. This is different from {@code goog.dom.iframe.BLANK_SOURCE} in that
+ * it will allow an iframe to be loaded synchronously in more browsers, notably
+ * Gecko, following the javascript protocol spec.
+ *
+ * NOTE: This should not be used to replace the source of an existing iframe.
+ * The new src value will be ignored, per the spec.
+ *
+ * Due to cross-browser differences, the load is not guaranteed to be
+ * synchronous. If code depends on the load of the iframe,
+ * then {@code goog.net.IframeLoadMonitor} or a similar technique should be
+ * used.
+ *
+ * According to
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#javascript-protocol
+ * the 'javascript:""' URL should trigger a new load of the iframe, which may be
+ * asynchronous. A void src, such as 'javascript:undefined', does not change
+ * the browsing context document's, and thus should not trigger another load.
+ *
+ * Intentionally not about:blank, which also triggers a load.
+ *
+ * NOTE: 'javascript:' URL handling spec compliance varies per browser. IE
+ * throws an error with 'javascript:undefined'. Webkit browsers will reload the
+ * iframe when setting this source on an existing iframe.
+ *
+ * @type {string}
+ */
+goog.dom.iframe.BLANK_SOURCE_NEW_FRAME = goog.userAgent.IE ?
+ 'javascript:""' :
+ 'javascript:undefined';
+
+
+/**
+ * Styles to help ensure an undecorated iframe.
+ * @type {string}
+ * @private
+ */
+goog.dom.iframe.STYLES_ = 'border:0;vertical-align:bottom;';
+
+
+/**
+ * Creates a completely blank iframe element.
+ *
+ * The iframe will not caused mixed-content warnings for IE6 under HTTPS.
+ * The iframe will also have no borders or padding, so that the styled width
+ * and height will be the actual width and height of the iframe.
+ *
+ * This function currently only attempts to create a blank iframe. There
+ * are no guarantees to the contents of the iframe or whether it is rendered
+ * in quirks mode.
+ *
+ * @param {goog.dom.DomHelper} domHelper The dom helper to use.
+ * @param {!goog.html.SafeStyle|string=} opt_styles CSS styles for the
+ * iframe. If possible pass a SafeStyle; string is supported for
+ * backwards-compatibility only and uses goog.html.legacyconversions.
+ * @return {!HTMLIFrameElement} A completely blank iframe.
+ */
+goog.dom.iframe.createBlank = function(domHelper, opt_styles) {
+ var styles;
+ if (goog.isString(opt_styles)) {
+ styles = goog.html.legacyconversions.safeStyleFromString(opt_styles)
+ .getTypedStringValue();
+ } else if (opt_styles instanceof goog.html.SafeStyle) {
+ // SafeStyle has to be converted back to a string for now, since there's
+ // no safe alternative to createDom().
+ styles = goog.html.SafeStyle.unwrap(opt_styles);
+ } else { // undefined.
+ styles = '';
+ }
+ return /** @type {!HTMLIFrameElement} */ (domHelper.createDom('iframe', {
+ 'frameborder': 0,
+ // Since iframes are inline elements, we must align to bottom to
+ // compensate for the line descent.
+ 'style': goog.dom.iframe.STYLES_ + styles,
+ 'src': goog.dom.iframe.BLANK_SOURCE
+ }));
+};
+
+
+/**
+ * Writes the contents of a blank iframe that has already been inserted
+ * into the document. If possible use {@link #writeSafeContent},
+ * this function exists for backwards-compatibility only and uses
+ * goog.html.legacyconversions.
+ * @param {!HTMLIFrameElement} iframe An iframe with no contents, such as
+ * one created by goog.dom.iframe.createBlank, but already appended to
+ * a parent document.
+ * @param {string} content Content to write to the iframe, from doctype to
+ * the HTML close tag.
+ */
+goog.dom.iframe.writeContent = function(iframe, content) {
+ goog.dom.iframe.writeSafeContent(
+ iframe, goog.html.legacyconversions.safeHtmlFromString(content));
+};
+
+
+/**
+ * Writes the contents of a blank iframe that has already been inserted
+ * into the document.
+ * @param {!HTMLIFrameElement} iframe An iframe with no contents, such as
+ * one created by {@link #createBlank}, but already appended to
+ * a parent document.
+ * @param {!goog.html.SafeHtml} content Content to write to the iframe,
+ * from doctype to the HTML close tag.
+ */
+goog.dom.iframe.writeSafeContent = function(iframe, content) {
+ var doc = goog.dom.getFrameContentDocument(iframe);
+ doc.open();
+ goog.dom.safe.documentWrite(doc, content);
+ doc.close();
+};
+
+
+// TODO(gboyer): Provide a higher-level API for the most common use case, so
+// that you can just provide a list of stylesheets and some content HTML.
+/**
+ * Creates a same-domain iframe containing preloaded content.
+ *
+ * This is primarily useful for DOM sandboxing. One use case is to embed
+ * a trusted Javascript app with potentially conflicting CSS styles. The
+ * second case is to reduce the cost of layout passes by the browser -- for
+ * example, you can perform sandbox sizing of characters in an iframe while
+ * manipulating a heavy DOM in the main window. The iframe and parent frame
+ * can access each others' properties and functions without restriction.
+ *
+ * @param {!Element} parentElement The parent element in which to append the
+ * iframe.
+ * @param {!goog.html.SafeHtml|string=} opt_headContents Contents to go into
+ * the iframe's head. If possible pass a SafeHtml; string is supported for
+ * backwards-compatibility only and uses goog.html.legacyconversions.
+ * @param {!goog.html.SafeHtml|string=} opt_bodyContents Contents to go into
+ * the iframe's body. If possible pass a SafeHtml; string is supported for
+ * backwards-compatibility only and uses goog.html.legacyconversions.
+ * @param {!goog.html.SafeStyle|string=} opt_styles CSS styles for the iframe
+ * itself, before adding to the parent element. If possible pass a
+ * SafeStyle; string is supported for backwards-compatibility only and
+ * uses goog.html.legacyconversions.
+ * @param {boolean=} opt_quirks Whether to use quirks mode (false by default).
+ * @return {!HTMLIFrameElement} An iframe that has the specified contents.
+ */
+goog.dom.iframe.createWithContent = function(
+ parentElement, opt_headContents, opt_bodyContents, opt_styles, opt_quirks) {
+ var domHelper = goog.dom.getDomHelper(parentElement);
+
+ if (goog.isString(opt_headContents)) {
+ opt_headContents =
+ goog.html.legacyconversions.safeHtmlFromString(opt_headContents);
+ }
+ if (goog.isString(opt_bodyContents)) {
+ opt_bodyContents =
+ goog.html.legacyconversions.safeHtmlFromString(opt_bodyContents);
+ }
+ if (goog.isString(opt_styles)) {
+ opt_styles =
+ goog.html.legacyconversions.safeStyleFromString(opt_styles);
+ }
+
+ var content = goog.html.SafeHtml.create('html', {}, goog.html.SafeHtml.concat(
+ goog.html.SafeHtml.create('head', {}, opt_headContents),
+ goog.html.SafeHtml.create('body', {}, opt_bodyContents)));
+ if (!opt_quirks) {
+ content =
+ goog.html.SafeHtml.concat(goog.html.SafeHtml.DOCTYPE_HTML, content);
+ }
+
+ var iframe = goog.dom.iframe.createBlank(domHelper, opt_styles);
+
+ // Cannot manipulate iframe content until it is in a document.
+ parentElement.appendChild(iframe);
+ goog.dom.iframe.writeSafeContent(iframe, content);
+
+ return iframe;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/inputtype.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/inputtype.js b/externs/GCL/externs/goog/dom/inputtype.js
new file mode 100644
index 0000000..f5db6c8
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/inputtype.js
@@ -0,0 +1,66 @@
+// Copyright 2015 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 Defines the goog.dom.InputType enum. This enumerates
+ * all input element types (for INPUT, BUTTON, SELECT and TEXTAREA
+ * elements) in either the the W3C HTML 4.01 index of elements or the
+ * HTML5 draft specification.
+ *
+ * References:
+ * http://www.w3.org/TR/html401/sgml/dtd.html#InputType
+ * http://www.w3.org/TR/html-markup/input.html#input
+ * https://html.spec.whatwg.org/multipage/forms.html#dom-input-type
+ * https://html.spec.whatwg.org/multipage/forms.html#dom-button-type
+ * https://html.spec.whatwg.org/multipage/forms.html#dom-select-type
+ * https://html.spec.whatwg.org/multipage/forms.html#dom-textarea-type
+ *
+ */
+goog.provide('goog.dom.InputType');
+
+
+/**
+ * Enum of all input types (for INPUT, BUTTON, SELECT and TEXTAREA elements)
+ * specified by the W3C HTML4.01 and HTML5 specifications.
+ * @enum {string}
+ */
+goog.dom.InputType = {
+ BUTTON: 'button',
+ CHECKBOX: 'checkbox',
+ COLOR: 'color',
+ DATE: 'date',
+ DATETIME: 'datetime',
+ DATETIME_LOCAL: 'datetime-local',
+ EMAIL: 'email',
+ FILE: 'file',
+ HIDDEN: 'hidden',
+ IMAGE: 'image',
+ MENU: 'menu',
+ MONTH: 'month',
+ NUMBER: 'number',
+ PASSWORD: 'password',
+ RADIO: 'radio',
+ RANGE: 'range',
+ RESET: 'reset',
+ SEARCH: 'search',
+ SELECT_MULTIPLE: 'select-multiple',
+ SELECT_ONE: 'select-one',
+ SUBMIT: 'submit',
+ TEL: 'tel',
+ TEXT: 'text',
+ TEXTAREA: 'textarea',
+ TIME: 'time',
+ URL: 'url',
+ WEEK: 'week'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/iter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/iter.js b/externs/GCL/externs/goog/dom/iter.js
new file mode 100644
index 0000000..7516414
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/iter.js
@@ -0,0 +1,129 @@
+// 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 Iterators over DOM nodes.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.iter.AncestorIterator');
+goog.provide('goog.dom.iter.ChildIterator');
+goog.provide('goog.dom.iter.SiblingIterator');
+
+goog.require('goog.iter.Iterator');
+goog.require('goog.iter.StopIteration');
+
+
+
+/**
+ * Iterator over a Node's siblings.
+ * @param {Node} node The node to start with.
+ * @param {boolean=} opt_includeNode Whether to return the given node as the
+ * first return value from next.
+ * @param {boolean=} opt_reverse Whether to traverse siblings in reverse
+ * document order.
+ * @constructor
+ * @extends {goog.iter.Iterator}
+ */
+goog.dom.iter.SiblingIterator = function(node, opt_includeNode, opt_reverse) {
+ /**
+ * The current node, or null if iteration is finished.
+ * @type {Node}
+ * @private
+ */
+ this.node_ = node;
+
+ /**
+ * Whether to iterate in reverse.
+ * @type {boolean}
+ * @private
+ */
+ this.reverse_ = !!opt_reverse;
+
+ if (node && !opt_includeNode) {
+ this.next();
+ }
+};
+goog.inherits(goog.dom.iter.SiblingIterator, goog.iter.Iterator);
+
+
+/** @override */
+goog.dom.iter.SiblingIterator.prototype.next = function() {
+ var node = this.node_;
+ if (!node) {
+ throw goog.iter.StopIteration;
+ }
+ this.node_ = this.reverse_ ? node.previousSibling : node.nextSibling;
+ return node;
+};
+
+
+
+/**
+ * Iterator over an Element's children.
+ * @param {Element} element The element to iterate over.
+ * @param {boolean=} opt_reverse Optionally traverse children from last to
+ * first.
+ * @param {number=} opt_startIndex Optional starting index.
+ * @constructor
+ * @extends {goog.dom.iter.SiblingIterator}
+ * @final
+ */
+goog.dom.iter.ChildIterator = function(element, opt_reverse, opt_startIndex) {
+ if (!goog.isDef(opt_startIndex)) {
+ opt_startIndex = opt_reverse && element.childNodes.length ?
+ element.childNodes.length - 1 : 0;
+ }
+ goog.dom.iter.SiblingIterator.call(this, element.childNodes[opt_startIndex],
+ true, opt_reverse);
+};
+goog.inherits(goog.dom.iter.ChildIterator, goog.dom.iter.SiblingIterator);
+
+
+
+/**
+ * Iterator over a Node's ancestors, stopping after the document body.
+ * @param {Node} node The node to start with.
+ * @param {boolean=} opt_includeNode Whether to return the given node as the
+ * first return value from next.
+ * @constructor
+ * @extends {goog.iter.Iterator}
+ * @final
+ */
+goog.dom.iter.AncestorIterator = function(node, opt_includeNode) {
+ /**
+ * The current node, or null if iteration is finished.
+ * @type {Node}
+ * @private
+ */
+ this.node_ = node;
+
+ if (node && !opt_includeNode) {
+ this.next();
+ }
+};
+goog.inherits(goog.dom.iter.AncestorIterator, goog.iter.Iterator);
+
+
+/** @override */
+goog.dom.iter.AncestorIterator.prototype.next = function() {
+ var node = this.node_;
+ if (!node) {
+ throw goog.iter.StopIteration;
+ }
+ this.node_ = node.parentNode;
+ return node;
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/multirange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/multirange.js b/externs/GCL/externs/goog/dom/multirange.js
new file mode 100644
index 0000000..9a57d25
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/multirange.js
@@ -0,0 +1,510 @@
+// 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 W3C multi-part ranges.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.MultiRange');
+goog.provide('goog.dom.MultiRangeIterator');
+
+goog.require('goog.array');
+goog.require('goog.dom.AbstractMultiRange');
+goog.require('goog.dom.AbstractRange');
+goog.require('goog.dom.RangeIterator');
+goog.require('goog.dom.RangeType');
+goog.require('goog.dom.SavedRange');
+goog.require('goog.dom.TextRange');
+goog.require('goog.iter.StopIteration');
+goog.require('goog.log');
+
+
+
+/**
+ * Creates a new multi part range with no properties. Do not use this
+ * constructor: use one of the goog.dom.Range.createFrom* methods instead.
+ * @constructor
+ * @extends {goog.dom.AbstractMultiRange}
+ * @final
+ */
+goog.dom.MultiRange = function() {
+ /**
+ * Logging object.
+ * @private {goog.log.Logger}
+ */
+ this.logger_ = goog.log.getLogger('goog.dom.MultiRange');
+
+ /**
+ * Array of browser sub-ranges comprising this multi-range.
+ * @private {Array<Range>}
+ */
+ this.browserRanges_ = [];
+
+ /**
+ * Lazily initialized array of range objects comprising this multi-range.
+ * @private {Array<goog.dom.TextRange>}
+ */
+ this.ranges_ = [];
+
+ /**
+ * Lazily computed sorted version of ranges_, sorted by start point.
+ * @private {Array<goog.dom.TextRange>?}
+ */
+ this.sortedRanges_ = null;
+
+ /**
+ * Lazily computed container node.
+ * @private {Node}
+ */
+ this.container_ = null;
+};
+goog.inherits(goog.dom.MultiRange, goog.dom.AbstractMultiRange);
+
+
+/**
+ * Creates a new range wrapper from the given browser selection object. Do not
+ * use this method directly - please use goog.dom.Range.createFrom* instead.
+ * @param {Selection} selection The browser selection object.
+ * @return {!goog.dom.MultiRange} A range wrapper object.
+ */
+goog.dom.MultiRange.createFromBrowserSelection = function(selection) {
+ var range = new goog.dom.MultiRange();
+ for (var i = 0, len = selection.rangeCount; i < len; i++) {
+ range.browserRanges_.push(selection.getRangeAt(i));
+ }
+ return range;
+};
+
+
+/**
+ * Creates a new range wrapper from the given browser ranges. Do not
+ * use this method directly - please use goog.dom.Range.createFrom* instead.
+ * @param {Array<Range>} browserRanges The browser ranges.
+ * @return {!goog.dom.MultiRange} A range wrapper object.
+ */
+goog.dom.MultiRange.createFromBrowserRanges = function(browserRanges) {
+ var range = new goog.dom.MultiRange();
+ range.browserRanges_ = goog.array.clone(browserRanges);
+ return range;
+};
+
+
+/**
+ * Creates a new range wrapper from the given goog.dom.TextRange objects. Do
+ * not use this method directly - please use goog.dom.Range.createFrom* instead.
+ * @param {Array<goog.dom.TextRange>} textRanges The text range objects.
+ * @return {!goog.dom.MultiRange} A range wrapper object.
+ */
+goog.dom.MultiRange.createFromTextRanges = function(textRanges) {
+ var range = new goog.dom.MultiRange();
+ range.ranges_ = textRanges;
+ range.browserRanges_ = goog.array.map(textRanges, function(range) {
+ return range.getBrowserRangeObject();
+ });
+ return range;
+};
+
+
+// Method implementations
+
+
+/**
+ * Clears cached values. Should be called whenever this.browserRanges_ is
+ * modified.
+ * @private
+ */
+goog.dom.MultiRange.prototype.clearCachedValues_ = function() {
+ this.ranges_ = [];
+ this.sortedRanges_ = null;
+ this.container_ = null;
+};
+
+
+/**
+ * @return {!goog.dom.MultiRange} A clone of this range.
+ * @override
+ */
+goog.dom.MultiRange.prototype.clone = function() {
+ return goog.dom.MultiRange.createFromBrowserRanges(this.browserRanges_);
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getType = function() {
+ return goog.dom.RangeType.MULTI;
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getBrowserRangeObject = function() {
+ // NOTE(robbyw): This method does not make sense for multi-ranges.
+ if (this.browserRanges_.length > 1) {
+ goog.log.warning(this.logger_,
+ 'getBrowserRangeObject called on MultiRange with more than 1 range');
+ }
+ return this.browserRanges_[0];
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.setBrowserRangeObject = function(nativeRange) {
+ // TODO(robbyw): Look in to adding setBrowserSelectionObject.
+ return false;
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getTextRangeCount = function() {
+ return this.browserRanges_.length;
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getTextRange = function(i) {
+ if (!this.ranges_[i]) {
+ this.ranges_[i] = goog.dom.TextRange.createFromBrowserRange(
+ this.browserRanges_[i]);
+ }
+ return this.ranges_[i];
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getContainer = function() {
+ if (!this.container_) {
+ var nodes = [];
+ for (var i = 0, len = this.getTextRangeCount(); i < len; i++) {
+ nodes.push(this.getTextRange(i).getContainer());
+ }
+ this.container_ = goog.dom.findCommonAncestor.apply(null, nodes);
+ }
+ return this.container_;
+};
+
+
+/**
+ * @return {!Array<goog.dom.TextRange>} An array of sub-ranges, sorted by start
+ * point.
+ */
+goog.dom.MultiRange.prototype.getSortedRanges = function() {
+ if (!this.sortedRanges_) {
+ this.sortedRanges_ = this.getTextRanges();
+ this.sortedRanges_.sort(function(a, b) {
+ var aStartNode = a.getStartNode();
+ var aStartOffset = a.getStartOffset();
+ var bStartNode = b.getStartNode();
+ var bStartOffset = b.getStartOffset();
+
+ if (aStartNode == bStartNode && aStartOffset == bStartOffset) {
+ return 0;
+ }
+
+ return goog.dom.Range.isReversed(aStartNode, aStartOffset, bStartNode,
+ bStartOffset) ? 1 : -1;
+ });
+ }
+ return this.sortedRanges_;
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getStartNode = function() {
+ return this.getSortedRanges()[0].getStartNode();
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getStartOffset = function() {
+ return this.getSortedRanges()[0].getStartOffset();
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getEndNode = function() {
+ // NOTE(robbyw): This may return the wrong node if any subranges overlap.
+ return goog.array.peek(this.getSortedRanges()).getEndNode();
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getEndOffset = function() {
+ // NOTE(robbyw): This may return the wrong value if any subranges overlap.
+ return goog.array.peek(this.getSortedRanges()).getEndOffset();
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.isRangeInDocument = function() {
+ return goog.array.every(this.getTextRanges(), function(range) {
+ return range.isRangeInDocument();
+ });
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.isCollapsed = function() {
+ return this.browserRanges_.length == 0 ||
+ this.browserRanges_.length == 1 && this.getTextRange(0).isCollapsed();
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getText = function() {
+ return goog.array.map(this.getTextRanges(), function(range) {
+ return range.getText();
+ }).join('');
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getHtmlFragment = function() {
+ return this.getValidHtml();
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getValidHtml = function() {
+ // NOTE(robbyw): This does not behave well if the sub-ranges overlap.
+ return goog.array.map(this.getTextRanges(), function(range) {
+ return range.getValidHtml();
+ }).join('');
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.getPastableHtml = function() {
+ // TODO(robbyw): This should probably do something smart like group TR and TD
+ // selections in to the same table.
+ return this.getValidHtml();
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.__iterator__ = function(opt_keys) {
+ return new goog.dom.MultiRangeIterator(this);
+};
+
+
+// RANGE ACTIONS
+
+
+/** @override */
+goog.dom.MultiRange.prototype.select = function() {
+ var selection = goog.dom.AbstractRange.getBrowserSelectionForWindow(
+ this.getWindow());
+ selection.removeAllRanges();
+ for (var i = 0, len = this.getTextRangeCount(); i < len; i++) {
+ selection.addRange(this.getTextRange(i).getBrowserRangeObject());
+ }
+};
+
+
+/** @override */
+goog.dom.MultiRange.prototype.removeContents = function() {
+ goog.array.forEach(this.getTextRanges(), function(range) {
+ range.removeContents();
+ });
+};
+
+
+// SAVE/RESTORE
+
+
+/** @override */
+goog.dom.MultiRange.prototype.saveUsingDom = function() {
+ return new goog.dom.DomSavedMultiRange_(this);
+};
+
+
+// RANGE MODIFICATION
+
+
+/**
+ * Collapses this range to a single point, either the first or last point
+ * depending on the parameter. This will result in the number of ranges in this
+ * multi range becoming 1.
+ * @param {boolean} toAnchor Whether to collapse to the anchor.
+ * @override
+ */
+goog.dom.MultiRange.prototype.collapse = function(toAnchor) {
+ if (!this.isCollapsed()) {
+ var range = toAnchor ? this.getTextRange(0) : this.getTextRange(
+ this.getTextRangeCount() - 1);
+
+ this.clearCachedValues_();
+ range.collapse(toAnchor);
+ this.ranges_ = [range];
+ this.sortedRanges_ = [range];
+ this.browserRanges_ = [range.getBrowserRangeObject()];
+ }
+};
+
+
+// SAVED RANGE OBJECTS
+
+
+
+/**
+ * A SavedRange implementation using DOM endpoints.
+ * @param {goog.dom.MultiRange} range The range to save.
+ * @constructor
+ * @extends {goog.dom.SavedRange}
+ * @private
+ */
+goog.dom.DomSavedMultiRange_ = function(range) {
+ /**
+ * Array of saved ranges.
+ * @type {Array<goog.dom.SavedRange>}
+ * @private
+ */
+ this.savedRanges_ = goog.array.map(range.getTextRanges(), function(range) {
+ return range.saveUsingDom();
+ });
+};
+goog.inherits(goog.dom.DomSavedMultiRange_, goog.dom.SavedRange);
+
+
+/**
+ * @return {!goog.dom.MultiRange} The restored range.
+ * @override
+ */
+goog.dom.DomSavedMultiRange_.prototype.restoreInternal = function() {
+ var ranges = goog.array.map(this.savedRanges_, function(savedRange) {
+ return savedRange.restore();
+ });
+ return goog.dom.MultiRange.createFromTextRanges(ranges);
+};
+
+
+/** @override */
+goog.dom.DomSavedMultiRange_.prototype.disposeInternal = function() {
+ goog.dom.DomSavedMultiRange_.superClass_.disposeInternal.call(this);
+
+ goog.array.forEach(this.savedRanges_, function(savedRange) {
+ savedRange.dispose();
+ });
+ delete this.savedRanges_;
+};
+
+
+// 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 {goog.dom.MultiRange} range The range to traverse.
+ * @constructor
+ * @extends {goog.dom.RangeIterator}
+ * @final
+ */
+goog.dom.MultiRangeIterator = function(range) {
+ /**
+ * The list of range iterators left to traverse.
+ * @private {Array<goog.dom.RangeIterator>}
+ */
+ this.iterators_ = null;
+
+ /**
+ * The index of the current sub-iterator being traversed.
+ * @private {number}
+ */
+ this.currentIdx_ = 0;
+
+ if (range) {
+ this.iterators_ = goog.array.map(
+ range.getSortedRanges(),
+ function(r) {
+ return goog.iter.toIterator(r);
+ });
+ }
+
+ goog.dom.MultiRangeIterator.base(
+ this, 'constructor', range ? this.getStartNode() : null, false);
+};
+goog.inherits(goog.dom.MultiRangeIterator, goog.dom.RangeIterator);
+
+
+/** @override */
+goog.dom.MultiRangeIterator.prototype.getStartTextOffset = function() {
+ return this.iterators_[this.currentIdx_].getStartTextOffset();
+};
+
+
+/** @override */
+goog.dom.MultiRangeIterator.prototype.getEndTextOffset = function() {
+ return this.iterators_[this.currentIdx_].getEndTextOffset();
+};
+
+
+/** @override */
+goog.dom.MultiRangeIterator.prototype.getStartNode = function() {
+ return this.iterators_[0].getStartNode();
+};
+
+
+/** @override */
+goog.dom.MultiRangeIterator.prototype.getEndNode = function() {
+ return goog.array.peek(this.iterators_).getEndNode();
+};
+
+
+/** @override */
+goog.dom.MultiRangeIterator.prototype.isLast = function() {
+ return this.iterators_[this.currentIdx_].isLast();
+};
+
+
+/** @override */
+goog.dom.MultiRangeIterator.prototype.next = function() {
+ /** @preserveTry */
+ try {
+ var it = this.iterators_[this.currentIdx_];
+ var next = it.next();
+ this.setPosition(it.node, it.tagType, it.depth);
+ return next;
+ } catch (ex) {
+ if (ex !== goog.iter.StopIteration ||
+ this.iterators_.length - 1 == this.currentIdx_) {
+ throw ex;
+ } else {
+ // In case we got a StopIteration, increment counter and try again.
+ this.currentIdx_++;
+ return this.next();
+ }
+ }
+};
+
+
+/** @override */
+goog.dom.MultiRangeIterator.prototype.copyFrom = function(other) {
+ this.iterators_ = goog.array.clone(other.iterators_);
+ goog.dom.MultiRangeIterator.superClass_.copyFrom.call(this, other);
+};
+
+
+/**
+ * @return {!goog.dom.MultiRangeIterator} An identical iterator.
+ * @override
+ */
+goog.dom.MultiRangeIterator.prototype.clone = function() {
+ var copy = new goog.dom.MultiRangeIterator(null);
+ copy.copyFrom(this);
+ return copy;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/nodeiterator.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/nodeiterator.js b/externs/GCL/externs/goog/dom/nodeiterator.js
new file mode 100644
index 0000000..bca563c
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/nodeiterator.js
@@ -0,0 +1,87 @@
+// 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.NodeIterator');
+
+goog.require('goog.dom.TagIterator');
+
+
+
+/**
+ * A DOM tree traversal iterator.
+ *
+ * Starting with the given node, the iterator walks the DOM in order, reporting
+ * events for each node. The iterator acts as a prefix iterator:
+ *
+ * <pre>
+ * <div>1<span>2</span>3</div>
+ * </pre>
+ *
+ * Will return the following nodes:
+ *
+ * <code>[div, 1, span, 2, 3]</code>
+ *
+ * With the following depths
+ *
+ * <code>[1, 1, 2, 2, 1]</code>
+ *
+ * Imagining <code>|</code> represents iterator position, the traversal stops at
+ * each of the following locations:
+ *
+ * <pre><div>|1|<span>|2|</span>3|</div></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 last move.
+ *
+ * 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. 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 {number=} opt_depth The starting tree depth.
+ * @constructor
+ * @extends {goog.dom.TagIterator}
+ * @final
+ */
+goog.dom.NodeIterator = function(opt_node, opt_reversed,
+ opt_unconstrained, opt_depth) {
+ goog.dom.TagIterator.call(this, opt_node, opt_reversed, opt_unconstrained,
+ null, opt_depth);
+};
+goog.inherits(goog.dom.NodeIterator, goog.dom.TagIterator);
+
+
+/**
+ * Moves 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.NodeIterator.prototype.next = function() {
+ do {
+ goog.dom.NodeIterator.superClass_.next.call(this);
+ } while (this.isEndTag());
+
+ return this.node;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/nodeoffset.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/nodeoffset.js b/externs/GCL/externs/goog/dom/nodeoffset.js
new file mode 100644
index 0000000..9a65dbe
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/nodeoffset.js
@@ -0,0 +1,114 @@
+// 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 Object to store the offset from one node to another in a way
+ * that works on any similar DOM structure regardless of whether it is the same
+ * actual nodes.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.NodeOffset');
+
+goog.require('goog.Disposable');
+goog.require('goog.dom.TagName');
+
+
+
+/**
+ * Object to store the offset from one node to another in a way that works on
+ * any similar DOM structure regardless of whether it is the same actual nodes.
+ * @param {Node} node The node to get the offset for.
+ * @param {Node} baseNode The node to calculate the offset from.
+ * @extends {goog.Disposable}
+ * @constructor
+ * @final
+ */
+goog.dom.NodeOffset = function(node, baseNode) {
+ goog.Disposable.call(this);
+
+ /**
+ * A stack of childNode offsets.
+ * @type {Array<number>}
+ * @private
+ */
+ this.offsetStack_ = [];
+
+ /**
+ * A stack of childNode names.
+ * @type {Array<string>}
+ * @private
+ */
+ this.nameStack_ = [];
+
+ while (node && node.nodeName != goog.dom.TagName.BODY && node != baseNode) {
+ // Compute the sibling offset.
+ var siblingOffset = 0;
+ var sib = node.previousSibling;
+ while (sib) {
+ sib = sib.previousSibling;
+ ++siblingOffset;
+ }
+ this.offsetStack_.unshift(siblingOffset);
+ this.nameStack_.unshift(node.nodeName);
+
+ node = node.parentNode;
+ }
+};
+goog.inherits(goog.dom.NodeOffset, goog.Disposable);
+
+
+/**
+ * @return {string} A string representation of this object.
+ * @override
+ */
+goog.dom.NodeOffset.prototype.toString = function() {
+ var strs = [];
+ var name;
+ for (var i = 0; name = this.nameStack_[i]; i++) {
+ strs.push(this.offsetStack_[i] + ',' + name);
+ }
+ return strs.join('\n');
+};
+
+
+/**
+ * Walk the dom and find the node relative to baseNode. Returns null on
+ * failure.
+ * @param {Node} baseNode The node to start walking from. Should be equivalent
+ * to the node passed in to the constructor, in that it should have the
+ * same contents.
+ * @return {Node} The node relative to baseNode, or null on failure.
+ */
+goog.dom.NodeOffset.prototype.findTargetNode = function(baseNode) {
+ var name;
+ var curNode = baseNode;
+ for (var i = 0; name = this.nameStack_[i]; ++i) {
+ curNode = curNode.childNodes[this.offsetStack_[i]];
+
+ // Sanity check and make sure the element names match.
+ if (!curNode || curNode.nodeName != name) {
+ return null;
+ }
+ }
+ return curNode;
+};
+
+
+/** @override */
+goog.dom.NodeOffset.prototype.disposeInternal = function() {
+ delete this.offsetStack_;
+ delete this.nameStack_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/nodetype.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/nodetype.js b/externs/GCL/externs/goog/dom/nodetype.js
new file mode 100644
index 0000000..cccb470
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/nodetype.js
@@ -0,0 +1,48 @@
+// 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 Definition of goog.dom.NodeType.
+ */
+
+goog.provide('goog.dom.NodeType');
+
+
+/**
+ * Constants for the nodeType attribute in the Node interface.
+ *
+ * These constants match those specified in the Node interface. These are
+ * usually present on the Node object in recent browsers, but not in older
+ * browsers (specifically, early IEs) and thus are given here.
+ *
+ * In some browsers (early IEs), these are not defined on the Node object,
+ * so they are provided here.
+ *
+ * See http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247
+ * @enum {number}
+ */
+goog.dom.NodeType = {
+ ELEMENT: 1,
+ ATTRIBUTE: 2,
+ TEXT: 3,
+ CDATA_SECTION: 4,
+ ENTITY_REFERENCE: 5,
+ ENTITY: 6,
+ PROCESSING_INSTRUCTION: 7,
+ COMMENT: 8,
+ DOCUMENT: 9,
+ DOCUMENT_TYPE: 10,
+ DOCUMENT_FRAGMENT: 11,
+ NOTATION: 12
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/abstractpattern.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/abstractpattern.js b/externs/GCL/externs/goog/dom/pattern/abstractpattern.js
new file mode 100644
index 0000000..e785f76
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/abstractpattern.js
@@ -0,0 +1,58 @@
+// 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 base class.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.AbstractPattern');
+
+goog.require('goog.dom.pattern.MatchType');
+
+
+
+/**
+ * Base pattern class for DOM matching.
+ *
+ * @constructor
+ */
+goog.dom.pattern.AbstractPattern = function() {
+ /**
+ * The first node matched by this pattern.
+ * @type {Node}
+ */
+ this.matchedNode = null;
+};
+
+
+/**
+ * Reset any internal state this pattern keeps.
+ */
+goog.dom.pattern.AbstractPattern.prototype.reset = function() {
+ // The base implementation does nothing.
+};
+
+
+/**
+ * Test whether this pattern matches the given token.
+ *
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} {@code MATCH} if the pattern matches.
+ */
+goog.dom.pattern.AbstractPattern.prototype.matchToken = function(token, type) {
+ 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/allchildren.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/allchildren.js b/externs/GCL/externs/goog/dom/pattern/allchildren.js
new file mode 100644
index 0000000..36abae4
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/allchildren.js
@@ -0,0 +1,72 @@
+// 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 any children of a tag.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.AllChildren');
+
+goog.require('goog.dom.pattern.AbstractPattern');
+goog.require('goog.dom.pattern.MatchType');
+
+
+
+/**
+ * Pattern object that matches any nodes at or below the current tree depth.
+ *
+ * @constructor
+ * @extends {goog.dom.pattern.AbstractPattern}
+ */
+goog.dom.pattern.AllChildren = function() {
+ /**
+ * Tracks the matcher's depth to detect the end of the tag.
+ *
+ * @private {number}
+ */
+ this.depth_ = 0;
+};
+goog.inherits(goog.dom.pattern.AllChildren, goog.dom.pattern.AbstractPattern);
+
+
+/**
+ * Test whether the given token is on the same level.
+ *
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the
+ * same level or deeper and {@code BACKTRACK_MATCH} if not.
+ * @override
+ */
+goog.dom.pattern.AllChildren.prototype.matchToken = function(token, type) {
+ this.depth_ += type;
+
+ if (this.depth_ >= 0) {
+ return goog.dom.pattern.MatchType.MATCHING;
+ } else {
+ this.depth_ = 0;
+ return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
+ }
+};
+
+
+/**
+ * Reset any internal state this pattern keeps.
+ * @override
+ */
+goog.dom.pattern.AllChildren.prototype.reset = function() {
+ this.depth_ = 0;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/callback/callback.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/callback/callback.js b/externs/GCL/externs/goog/dom/pattern/callback/callback.js
new file mode 100644
index 0000000..7d7aa60
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/callback/callback.js
@@ -0,0 +1,82 @@
+// 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 Useful callback functions for the DOM matcher.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.callback');
+
+goog.require('goog.dom');
+goog.require('goog.dom.TagWalkType');
+goog.require('goog.iter');
+
+
+/**
+ * Callback function for use in {@link goog.dom.pattern.Matcher.addPattern}
+ * that removes the matched node from the tree. Should be used in conjunciton
+ * with a {@link goog.dom.pattern.StartTag} pattern.
+ *
+ * @param {Node} node The node matched by the pattern.
+ * @param {goog.dom.TagIterator} position The position where the match
+ * finished.
+ * @return {boolean} Returns true to indicate tree changes were made.
+ */
+goog.dom.pattern.callback.removeNode = function(node, position) {
+ // Find out which position would be next.
+ position.setPosition(node, goog.dom.TagWalkType.END_TAG);
+
+ goog.iter.nextOrValue(position, null);
+
+ // Remove the node.
+ goog.dom.removeNode(node);
+
+ // Correct for the depth change.
+ position.depth -= 1;
+
+ // Indicate that we made position/tree changes.
+ return true;
+};
+
+
+/**
+ * Callback function for use in {@link goog.dom.pattern.Matcher.addPattern}
+ * that removes the matched node from the tree and replaces it with its
+ * children. Should be used in conjunction with a
+ * {@link goog.dom.pattern.StartTag} pattern.
+ *
+ * @param {Element} node The node matched by the pattern.
+ * @param {goog.dom.TagIterator} position The position where the match
+ * finished.
+ * @return {boolean} Returns true to indicate tree changes were made.
+ */
+goog.dom.pattern.callback.flattenElement = function(node, position) {
+ // Find out which position would be next.
+ position.setPosition(node, node.firstChild ?
+ goog.dom.TagWalkType.START_TAG :
+ goog.dom.TagWalkType.END_TAG);
+
+ goog.iter.nextOrValue(position, null);
+
+ // Flatten the node.
+ goog.dom.flattenElement(node);
+
+ // Correct for the depth change.
+ position.depth -= 1;
+
+ // Indicate that we made position/tree changes.
+ return true;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/callback/counter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/callback/counter.js b/externs/GCL/externs/goog/dom/pattern/callback/counter.js
new file mode 100644
index 0000000..7e9a7aa
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/callback/counter.js
@@ -0,0 +1,69 @@
+// 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 Callback object that counts matches.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.callback.Counter');
+
+
+
+/**
+ * Callback class for counting matches.
+ * @constructor
+ * @final
+ */
+goog.dom.pattern.callback.Counter = function() {
+ /**
+ * The count of objects matched so far.
+ *
+ * @type {number}
+ */
+ this.count = 0;
+
+ /**
+ * The callback function. Suitable as a callback for
+ * {@link goog.dom.pattern.Matcher}.
+ * @private {Function}
+ */
+ this.callback_ = null;
+};
+
+
+/**
+ * Get a bound callback function that is suitable as a callback for
+ * {@link goog.dom.pattern.Matcher}.
+ *
+ * @return {!Function} A callback function.
+ */
+goog.dom.pattern.callback.Counter.prototype.getCallback = function() {
+ if (!this.callback_) {
+ this.callback_ = goog.bind(function() {
+ this.count++;
+ return false;
+ }, this);
+ }
+ return this.callback_;
+};
+
+
+/**
+ * Reset the counter.
+ */
+goog.dom.pattern.callback.Counter.prototype.reset = function() {
+ this.count = 0;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/childmatches.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/childmatches.js b/externs/GCL/externs/goog/dom/pattern/childmatches.js
new file mode 100644
index 0000000..72d6674
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/childmatches.js
@@ -0,0 +1,145 @@
+// 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 any children of a tag, and
+ * specifically collect those that match a child pattern.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.ChildMatches');
+
+goog.require('goog.dom.pattern.AllChildren');
+goog.require('goog.dom.pattern.MatchType');
+
+
+
+/**
+ * Pattern object that matches any nodes at or below the current tree depth.
+ *
+ * @param {goog.dom.pattern.AbstractPattern} childPattern Pattern to collect
+ * child matches of.
+ * @param {number=} opt_minimumMatches Enforce a minimum nuber of matches.
+ * Defaults to 0.
+ * @constructor
+ * @extends {goog.dom.pattern.AllChildren}
+ * @final
+ */
+goog.dom.pattern.ChildMatches = function(childPattern, opt_minimumMatches) {
+ /**
+ * The child pattern to collect matches from.
+ *
+ * @private {goog.dom.pattern.AbstractPattern}
+ */
+ this.childPattern_ = childPattern;
+
+ /**
+ * Array of matched child nodes.
+ *
+ * @type {Array<Node>}
+ */
+ this.matches = [];
+
+ /**
+ * Minimum number of matches.
+ *
+ * @private {number}
+ */
+ this.minimumMatches_ = opt_minimumMatches || 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.dom.pattern.ChildMatches.base(this, 'constructor');
+};
+goog.inherits(goog.dom.pattern.ChildMatches, goog.dom.pattern.AllChildren);
+
+
+/**
+ * Test whether the given token is on the same level.
+ *
+ * @param {Node} token Token to match against.
+ * @param {goog.dom.TagWalkType} type The type of token.
+ * @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the
+ * same level or deeper and {@code BACKTRACK_MATCH} if not.
+ * @override
+ */
+goog.dom.pattern.ChildMatches.prototype.matchToken = function(token, type) {
+ // Defer resets so we maintain our matches array until the last possible time.
+ if (this.needsReset_) {
+ this.reset();
+ }
+
+ // Call the super-method to ensure we stay in the child tree.
+ var status =
+ goog.dom.pattern.AllChildren.prototype.matchToken.apply(this, arguments);
+
+ switch (status) {
+ case goog.dom.pattern.MatchType.MATCHING:
+ var backtrack = false;
+
+ switch (this.childPattern_.matchToken(token, type)) {
+ case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
+ backtrack = true;
+ case goog.dom.pattern.MatchType.MATCH:
+ // Collect the match.
+ this.matches.push(this.childPattern_.matchedNode);
+ break;
+
+ default:
+ // Keep trying if we haven't hit a terminal state.
+ break;
+ }
+
+ if (backtrack) {
+ // The only interesting result is a MATCH, since BACKTRACK_MATCH means
+ // we are hitting an infinite loop on something like a Repeat(0).
+ if (this.childPattern_.matchToken(token, type) ==
+ goog.dom.pattern.MatchType.MATCH) {
+ this.matches.push(this.childPattern_.matchedNode);
+ }
+ }
+ return goog.dom.pattern.MatchType.MATCHING;
+
+ case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
+ // TODO(robbyw): this should return something like BACKTRACK_NO_MATCH
+ // when we don't meet our minimum.
+ this.needsReset_ = true;
+ return (this.matches.length >= this.minimumMatches_) ?
+ goog.dom.pattern.MatchType.BACKTRACK_MATCH :
+ goog.dom.pattern.MatchType.NO_MATCH;
+
+ default:
+ this.needsReset_ = true;
+ return status;
+ }
+};
+
+
+/**
+ * Reset any internal state this pattern keeps.
+ * @override
+ */
+goog.dom.pattern.ChildMatches.prototype.reset = function() {
+ this.needsReset_ = false;
+ this.matches.length = 0;
+ this.childPattern_.reset();
+ goog.dom.pattern.AllChildren.prototype.reset.call(this);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/endtag.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/endtag.js b/externs/GCL/externs/goog/dom/pattern/endtag.js
new file mode 100644
index 0000000..409f952
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/endtag.js
@@ -0,0 +1,54 @@
+// 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 end of a tag.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.EndTag');
+
+goog.require('goog.dom.TagWalkType');
+goog.require('goog.dom.pattern.Tag');
+
+
+
+/**
+ * Pattern object that matches a closing 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}
+ * @final
+ */
+goog.dom.pattern.EndTag = function(tag, opt_attrs, opt_styles, opt_test) {
+ goog.dom.pattern.Tag.call(
+ this,
+ tag,
+ goog.dom.TagWalkType.END_TAG,
+ opt_attrs,
+ opt_styles,
+ opt_test);
+};
+goog.inherits(goog.dom.pattern.EndTag, goog.dom.pattern.Tag);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/fulltag.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/fulltag.js b/externs/GCL/externs/goog/dom/pattern/fulltag.js
new file mode 100644
index 0000000..d12ded1
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/fulltag.js
@@ -0,0 +1,88 @@
+// 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.FullTag');
+
+goog.require('goog.dom.pattern.MatchType');
+goog.require('goog.dom.pattern.StartTag');
+goog.require('goog.dom.pattern.Tag');
+
+
+
+/**
+ * Pattern object that matches a full tag including all its children.
+ *
+ * @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.StartTag}
+ * @final
+ */
+goog.dom.pattern.FullTag = function(tag, opt_attrs, opt_styles, opt_test) {
+ /**
+ * Tracks the matcher's depth to detect the end of the tag.
+ *
+ * @private {number}
+ */
+ this.depth_ = 0;
+
+ goog.dom.pattern.FullTag.base(
+ this, 'constructor', tag, opt_attrs, opt_styles, opt_test);
+};
+goog.inherits(goog.dom.pattern.FullTag, goog.dom.pattern.StartTag);
+
+
+/**
+ * Test whether the given token is a start 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> at the end of our
+ * tag, <code>MATCHING</code> if we are within the tag, and
+ * <code>NO_MATCH</code> if the starting tag does not match.
+ * @override
+ */
+goog.dom.pattern.FullTag.prototype.matchToken = function(token, type) {
+ if (!this.depth_) {
+ // If we have not yet started, make sure we match as a StartTag.
+ if (goog.dom.pattern.Tag.prototype.matchToken.call(this, token, type)) {
+ this.depth_ = type;
+ return goog.dom.pattern.MatchType.MATCHING;
+
+ } else {
+ return goog.dom.pattern.MatchType.NO_MATCH;
+ }
+ } else {
+ this.depth_ += type;
+
+ return this.depth_ ?
+ goog.dom.pattern.MatchType.MATCHING :
+ goog.dom.pattern.MatchType.MATCH;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/pattern/matcher.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/pattern/matcher.js b/externs/GCL/externs/goog/dom/pattern/matcher.js
new file mode 100644
index 0000000..ea4a1e5
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/pattern/matcher.js
@@ -0,0 +1,144 @@
+// 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 matcher. Allows for simple searching of DOM
+ * using patterns descended from {@link goog.dom.pattern.AbstractPattern}.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.dom.pattern.Matcher');
+
+goog.require('goog.dom.TagIterator');
+goog.require('goog.dom.pattern.MatchType');
+goog.require('goog.iter');
+
+
+// TODO(robbyw): Allow for backtracks of size > 1.
+
+
+
+/**
+ * Given a set of patterns and a root node, this class tests the patterns in
+ * parallel.
+ *
+ * It is not (yet) a smart matcher - it doesn't do any advanced backtracking.
+ * Given the pattern <code>DIV, SPAN</code> the matcher will not match
+ * <code>DIV, DIV, SPAN</code> because it starts matching at the first
+ * <code>DIV</code>, fails to match <code>SPAN</code> at the second, and never
+ * backtracks to try again.
+ *
+ * It is also possible to have a set of complex patterns that when matched in
+ * parallel will miss some possible matches. Running multiple times will catch
+ * all matches eventually.
+ *
+ * @constructor
+ * @final
+ */
+goog.dom.pattern.Matcher = function() {
+ /**
+ * Array of patterns to attempt to match in parallel.
+ *
+ * @private {Array<goog.dom.pattern.AbstractPattern>}
+ */
+ this.patterns_ = [];
+
+ /**
+ * Array of callbacks to call when a pattern is matched. The indexing is the
+ * same as the {@link #patterns_} array.
+ *
+ * @private {Array<Function>}
+ */
+ this.callbacks_ = [];
+};
+
+
+/**
+ * Adds a pattern to be matched. The callback can return an object whose keys
+ * are processing instructions.
+ *
+ * @param {goog.dom.pattern.AbstractPattern} pattern The pattern to add.
+ * @param {Function} callback Function to call when a match is found. Uses
+ * the above semantics.
+ */
+goog.dom.pattern.Matcher.prototype.addPattern = function(pattern, callback) {
+ this.patterns_.push(pattern);
+ this.callbacks_.push(callback);
+};
+
+
+/**
+ * Resets all the patterns.
+ *
+ * @private
+ */
+goog.dom.pattern.Matcher.prototype.reset_ = function() {
+ for (var i = 0, len = this.patterns_.length; i < len; i++) {
+ this.patterns_[i].reset();
+ }
+};
+
+
+/**
+ * Test the given node against all patterns.
+ *
+ * @param {goog.dom.TagIterator} position A position in a node walk that is
+ * located at the token to process.
+ * @return {boolean} Whether a pattern modified the position or tree
+ * and its callback resulted in DOM structure or position modification.
+ * @private
+ */
+goog.dom.pattern.Matcher.prototype.matchToken_ = function(position) {
+ for (var i = 0, len = this.patterns_.length; i < len; i++) {
+ var pattern = this.patterns_[i];
+ switch (pattern.matchToken(position.node, position.tagType)) {
+ case goog.dom.pattern.MatchType.MATCH:
+ case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
+ var callback = this.callbacks_[i];
+
+ // Callbacks are allowed to modify the current position, but must
+ // return true if the do.
+ if (callback(pattern.matchedNode, position, pattern)) {
+ return true;
+ }
+
+ default:
+ // Do nothing.
+ break;
+ }
+ }
+
+ return false;
+};
+
+
+/**
+ * Match the set of patterns against a match tree.
+ *
+ * @param {Node} node The root node of the tree to match.
+ */
+goog.dom.pattern.Matcher.prototype.match = function(node) {
+ var position = new goog.dom.TagIterator(node);
+
+ this.reset_();
+
+ goog.iter.forEach(position, function() {
+ while (this.matchToken_(position)) {
+ // Since we've moved, our old pattern statuses don't make sense any more.
+ // Reset them.
+ this.reset_();
+ }
+ }, this);
+};
[42/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/cssom/iframe/style.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/cssom/iframe/style.js b/externs/GCL/externs/goog/cssom/iframe/style.js
new file mode 100644
index 0000000..24c8c05
--- /dev/null
+++ b/externs/GCL/externs/goog/cssom/iframe/style.js
@@ -0,0 +1,1016 @@
+// 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.
+// All Rights Reserved.
+
+/**
+ * @fileoverview Provides utility routines for copying modified
+ * {@code CSSRule} objects from the parent document into iframes so that any
+ * content in the iframe will be styled as if it was inline in the parent
+ * document.
+ *
+ * <p>
+ * For example, you might have this CSS rule:
+ *
+ * #content .highlighted { background-color: yellow; }
+ *
+ * And this DOM structure:
+ *
+ * <div id="content">
+ * <iframe />
+ * </div>
+ *
+ * Then inside the iframe you have:
+ *
+ * <body>
+ * <div class="highlighted">
+ * </body>
+ *
+ * If you copied the CSS rule directly into the iframe, it wouldn't match the
+ * .highlighted div. So we rewrite the original stylesheets based on the
+ * context where the iframe is going to be inserted. In this case the CSS
+ * selector would be rewritten to:
+ *
+ * body .highlighted { background-color: yellow; }
+ * </p>
+ *
+ */
+
+
+goog.provide('goog.cssom.iframe.style');
+
+goog.require('goog.asserts');
+goog.require('goog.cssom');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.classlist');
+goog.require('goog.string');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+
+
+/**
+ * Regexp that matches "a", "a:link", "a:visited", etc.
+ * @type {RegExp}
+ * @private
+ */
+goog.cssom.iframe.style.selectorPartAnchorRegex_ =
+ /a(:(link|visited|active|hover))?/;
+
+
+/**
+ * Delimiter between selectors (h1, h2)
+ * @type {string}
+ * @private
+ */
+goog.cssom.iframe.style.SELECTOR_DELIMITER_ = ',';
+
+
+/**
+ * Delimiter between selector parts (.main h1)
+ * @type {string}
+ * @private
+ */
+goog.cssom.iframe.style.SELECTOR_PART_DELIMITER_ = ' ';
+
+
+/**
+ * Delimiter marking the start of a css rules section ( h1 { )
+ * @type {string}
+ * @private
+ */
+goog.cssom.iframe.style.DECLARATION_START_DELIMITER_ = '{';
+
+
+/**
+ * Delimiter marking the end of a css rules section ( } )
+ * @type {string}
+ * @private
+ */
+goog.cssom.iframe.style.DECLARATION_END_DELIMITER_ = '}\n';
+
+
+
+/**
+ * Class representing a CSS rule set. A rule set is something like this:
+ * h1, h2 { font-family: Arial; color: red; }
+ * @constructor
+ * @private
+ */
+goog.cssom.iframe.style.CssRuleSet_ = function() {
+ /**
+ * Text of the declarations inside the rule set.
+ * For example: 'font-family: Arial; color: red;'
+ * @type {string}
+ */
+ this.declarationText = '';
+
+ /**
+ * Array of CssSelector objects, one for each selector.
+ * Example: [h1, h2]
+ * @type {Array<goog.cssom.iframe.style.CssSelector_>}
+ */
+ this.selectors = [];
+};
+
+
+/**
+ * Initializes the rule set from a {@code CSSRule}.
+ *
+ * @param {CSSRule} cssRule The {@code CSSRule} to initialize from.
+ * @return {boolean} True if initialization succeeded. We only support
+ * {@code CSSStyleRule} and {@code CSSFontFaceRule} objects.
+ */
+goog.cssom.iframe.style.CssRuleSet_.prototype.initializeFromCssRule =
+ function(cssRule) {
+ var ruleStyle = cssRule.style; // Cache object for performance.
+ if (!ruleStyle) {
+ return false;
+ }
+ var selector;
+ var declarations = '';
+ if (ruleStyle &&
+ (selector = cssRule.selectorText) &&
+ (declarations = ruleStyle.cssText)) {
+ // IE get confused about cssText context if a stylesheet uses the
+ // mid-pass hack, and it ends up with an open comment (/*) but no
+ // closing comment. This will effectively comment out large parts
+ // of generated stylesheets later. This errs on the safe side by
+ // always tacking on an empty comment to force comments to be closed
+ // We used to check for a troublesome open comment using a regular
+ // expression, but it's faster not to check and always do this.
+ if (goog.userAgent.IE) {
+ declarations += '/* */';
+ }
+ } else if (cssRule.cssText) {
+ var cssSelectorMatch = /([^\{]+)\{/;
+ var endTagMatch = /\}[^\}]*$/g;
+ // cssRule.cssText contains both selector and declarations:
+ // parse them out.
+ selector = cssSelectorMatch.exec(cssRule.cssText)[1];
+ // Remove selector, {, and trailing }.
+ declarations = cssRule.cssText.replace(cssSelectorMatch, '').replace(
+ endTagMatch, '');
+ }
+ if (selector) {
+ this.setSelectorsFromString(selector);
+ this.declarationText = declarations;
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Parses a selectors string (which may contain multiple comma-delimited
+ * selectors) and loads the results into this.selectors.
+ * @param {string} selectorsString String containing selectors.
+ */
+goog.cssom.iframe.style.CssRuleSet_.prototype.setSelectorsFromString =
+ function(selectorsString) {
+ this.selectors = [];
+ var selectors = selectorsString.split(/,\s*/gm);
+ for (var i = 0; i < selectors.length; i++) {
+ var selector = selectors[i];
+ if (selector.length > 0) {
+ this.selectors.push(new goog.cssom.iframe.style.CssSelector_(selector));
+ }
+ }
+};
+
+
+/**
+ * Make a copy of this ruleset.
+ * @return {!goog.cssom.iframe.style.CssRuleSet_} A new CssRuleSet containing
+ * the same data as this one.
+ */
+goog.cssom.iframe.style.CssRuleSet_.prototype.clone = function() {
+ var newRuleSet = new goog.cssom.iframe.style.CssRuleSet_();
+ newRuleSet.selectors = this.selectors.concat();
+ newRuleSet.declarationText = this.declarationText;
+ return newRuleSet;
+};
+
+
+/**
+ * Set the declaration text with properties from a given object.
+ * @param {Object} sourceObject Object whose properties and values should
+ * be used to generate the declaration text.
+ * @param {boolean=} opt_important Whether !important should be added to each
+ * declaration.
+ */
+goog.cssom.iframe.style.CssRuleSet_.prototype.setDeclarationTextFromObject =
+ function(sourceObject, opt_important) {
+ var stringParts = [];
+ // TODO(user): for ... in is costly in IE6 (extra garbage collection).
+ for (var prop in sourceObject) {
+ var value = sourceObject[prop];
+ if (value) {
+ stringParts.push(prop,
+ ':',
+ value, (opt_important ? ' !important' : ''),
+ ';');
+ }
+ }
+ this.declarationText = stringParts.join('');
+};
+
+
+/**
+ * Serializes this CssRuleSet_ into an array as a series of strings.
+ * The array can then be join()-ed to get a string representation
+ * of this ruleset.
+ * @param {Array<string>} array The array to which to append strings.
+ */
+goog.cssom.iframe.style.CssRuleSet_.prototype.writeToArray = function(array) {
+ var selectorCount = this.selectors.length;
+ var matchesAnchorTag = false;
+ for (var i = 0; i < selectorCount; i++) {
+ var selectorParts = this.selectors[i].parts;
+ var partCount = selectorParts.length;
+ for (var j = 0; j < partCount; j++) {
+ array.push(selectorParts[j].inputString_,
+ goog.cssom.iframe.style.SELECTOR_PART_DELIMITER_);
+ }
+ if (i < (selectorCount - 1)) {
+ array.push(goog.cssom.iframe.style.SELECTOR_DELIMITER_);
+ }
+ if (goog.userAgent.GECKO &&
+ !goog.userAgent.isVersionOrHigher('1.9a')) {
+ // In Gecko pre-1.9 (Firefox 2 and lower) we need to add !important
+ // to rulesets that match "A" tags, otherwise Gecko's built-in
+ // stylesheet will take precedence when designMode is on.
+ matchesAnchorTag = matchesAnchorTag ||
+ goog.cssom.iframe.style.selectorPartAnchorRegex_.test(
+ selectorParts[partCount - 1].inputString_);
+ }
+ }
+ var declarationText = this.declarationText;
+ if (matchesAnchorTag) {
+ declarationText = goog.cssom.iframe.style.makeColorRuleImportant_(
+ declarationText);
+ }
+ array.push(goog.cssom.iframe.style.DECLARATION_START_DELIMITER_,
+ declarationText,
+ goog.cssom.iframe.style.DECLARATION_END_DELIMITER_);
+};
+
+
+/**
+ * Regexp that matches "color: value;".
+ * @type {RegExp}
+ * @private
+ */
+goog.cssom.iframe.style.colorImportantReplaceRegex_ =
+ /(^|;|{)\s*color:([^;]+);/g;
+
+
+/**
+ * Adds !important to a css color: rule
+ * @param {string} cssText Text of the CSS rule(s) to modify.
+ * @return {string} Text with !important added to the color: rule if found.
+ * @private
+ */
+goog.cssom.iframe.style.makeColorRuleImportant_ = function(cssText) {
+ // Replace to insert a "! important" string.
+ return cssText.replace(goog.cssom.iframe.style.colorImportantReplaceRegex_,
+ '$1 color: $2 ! important; ');
+};
+
+
+
+/**
+ * Represents a single CSS selector, as described in
+ * http://www.w3.org/TR/REC-CSS2/selector.html
+ * Currently UNSUPPORTED are the following selector features:
+ * <ul>
+ * <li>pseudo-classes (:hover)
+ * <li>child selectors (div > h1)
+ * <li>adjacent sibling selectors (div + h1)
+ * <li>attribute selectors (input[type=submit])
+ * </ul>
+ * @param {string=} opt_selectorString String containing selectors to parse.
+ * @constructor
+ * @private
+ */
+goog.cssom.iframe.style.CssSelector_ = function(opt_selectorString) {
+
+ /**
+ * Object to track ancestry matches to speed up repeatedly testing this
+ * CssSelector against the same NodeAncestry object.
+ * @type {Object}
+ * @private
+ */
+ this.ancestryMatchCache_ = {};
+ if (opt_selectorString) {
+ this.setPartsFromString_(opt_selectorString);
+ }
+};
+
+
+/**
+ * Parses a selector string into individual parts.
+ * @param {string} selectorString A string containing a CSS selector.
+ * @private
+ */
+goog.cssom.iframe.style.CssSelector_.prototype.setPartsFromString_ =
+ function(selectorString) {
+ var parts = [];
+ var selectorPartStrings = selectorString.split(/\s+/gm);
+ for (var i = 0; i < selectorPartStrings.length; i++) {
+ if (!selectorPartStrings[i]) {
+ continue; // Skip empty strings.
+ }
+ var part = new goog.cssom.iframe.style.CssSelectorPart_(
+ selectorPartStrings[i]);
+ parts.push(part);
+ }
+ this.parts = parts;
+};
+
+
+/**
+ * Tests to see what part of a DOM element hierarchy would be matched by
+ * this selector, and returns the indexes of the matching element and matching
+ * selector part.
+ * <p>
+ * For example, given this hierarchy:
+ * document > html > body > div.content > div.sidebar > p
+ * and this CSS selector:
+ * body div.sidebar h1
+ * This would return {elementIndex: 4, selectorPartIndex: 1},
+ * indicating that the element at index 4 matched
+ * the css selector at index 1.
+ * </p>
+ * @param {goog.cssom.iframe.style.NodeAncestry_} elementAncestry Object
+ * representing an element and its ancestors.
+ * @return {Object} Object with the properties elementIndex and
+ * selectorPartIndex, or null if there was no match.
+ */
+goog.cssom.iframe.style.CssSelector_.prototype.matchElementAncestry =
+ function(elementAncestry) {
+
+ var ancestryUid = elementAncestry.uid;
+ if (this.ancestryMatchCache_[ancestryUid]) {
+ return this.ancestryMatchCache_[ancestryUid];
+ }
+
+ // Walk through the selector parts and see how far down the element hierarchy
+ // we can go while matching the selector parts.
+ var elementIndex = 0;
+ var match = null;
+ var selectorPart = null;
+ var lastSelectorPart = null;
+ var ancestorNodes = elementAncestry.nodes;
+ var ancestorNodeCount = ancestorNodes.length;
+
+ for (var i = 0; i <= this.parts.length; i++) {
+ selectorPart = this.parts[i];
+ while (elementIndex < ancestorNodeCount) {
+ var currentElementInfo = ancestorNodes[elementIndex];
+ if (selectorPart &&
+ selectorPart.testElement(currentElementInfo)) {
+ match = {
+ elementIndex: elementIndex,
+ selectorPartIndex: i
+ };
+ elementIndex++;
+ break;
+ } else if (lastSelectorPart &&
+ lastSelectorPart.testElement(currentElementInfo)) {
+ match = {
+ elementIndex: elementIndex,
+ selectorPartIndex: i - 1
+ };
+ }
+ elementIndex++;
+ }
+ lastSelectorPart = selectorPart;
+ }
+ this.ancestryMatchCache_[ancestryUid] = match;
+ return match;
+};
+
+
+
+/**
+ * Represents one part of a CSS Selector. For example in the selector
+ * 'body #foo .bar', body, #foo, and .bar would be considered selector parts.
+ * In the official CSS spec these are called "simple selectors".
+ * @param {string} selectorPartString A string containing the selector part
+ * in css format.
+ * @constructor
+ * @private
+ */
+goog.cssom.iframe.style.CssSelectorPart_ = function(selectorPartString) {
+ // Only one CssSelectorPart instance should exist for a given string.
+ var cacheEntry = goog.cssom.iframe.style.CssSelectorPart_.instances_[
+ selectorPartString];
+ if (cacheEntry) {
+ return cacheEntry;
+ }
+
+ // Optimization to avoid the more-expensive lookahead.
+ var identifiers;
+ if (selectorPartString.match(/[#\.]/)) {
+ // Lookahead regexp, won't work on IE 5.0.
+ identifiers = selectorPartString.split(/(?=[#\.])/);
+ } else {
+ identifiers = [selectorPartString];
+ }
+ var properties = {};
+ for (var i = 0; i < identifiers.length; i++) {
+ var identifier = identifiers[i];
+ if (identifier.charAt(0) == '.') {
+ properties.className = identifier.substring(1, identifier.length);
+ } else if (identifier.charAt(0) == '#') {
+ properties.id = identifier.substring(1, identifier.length);
+ } else {
+ properties.tagName = identifier.toUpperCase();
+ }
+ }
+ this.inputString_ = selectorPartString;
+ this.matchProperties_ = properties;
+ this.testedElements_ = {};
+ goog.cssom.iframe.style.CssSelectorPart_.instances_[selectorPartString] =
+ this;
+};
+
+
+/**
+ * Cache of existing CssSelectorPart_ instances.
+ * @type {Object}
+ * @private
+ */
+goog.cssom.iframe.style.CssSelectorPart_.instances_ = {};
+
+
+/**
+ * Test whether an element matches this selector part, considered in isolation.
+ * @param {Object} elementInfo Element properties to test.
+ * @return {boolean} Whether the element matched.
+ */
+goog.cssom.iframe.style.CssSelectorPart_.prototype.testElement =
+ function(elementInfo) {
+
+ var elementUid = elementInfo.uid;
+ var cachedMatch = this.testedElements_[elementUid];
+ if (typeof cachedMatch != 'undefined') {
+ return cachedMatch;
+ }
+
+ var matchProperties = this.matchProperties_;
+ var testTag = matchProperties.tagName;
+ var testClass = matchProperties.className;
+ var testId = matchProperties.id;
+
+ var matched = true;
+ if (testTag && testTag != '*' && testTag != elementInfo.nodeName) {
+ matched = false;
+ } else if (testId && testId != elementInfo.id) {
+ matched = false;
+ } else if (testClass &&
+ !elementInfo.classNames[testClass]) {
+ matched = false;
+ }
+
+ this.testedElements_[elementUid] = matched;
+ return matched;
+};
+
+
+
+/**
+ * Represents an element and all its parent/ancestor nodes.
+ * This class exists as an optimization so we run tests on an element
+ * hierarchy multiple times without walking the dom each time.
+ * @param {Element} el The DOM element whose ancestry should be stored.
+ * @constructor
+ * @private
+ */
+goog.cssom.iframe.style.NodeAncestry_ = function(el) {
+ var node = el;
+ var nodeUid = goog.getUid(node);
+
+ // Return an existing object from the cache if one exits for this node.
+ var ancestry = goog.cssom.iframe.style.NodeAncestry_.instances_[nodeUid];
+ if (ancestry) {
+ return ancestry;
+ }
+
+ var nodes = [];
+ do {
+ var nodeInfo = {
+ id: node.id,
+ nodeName: node.nodeName
+ };
+ nodeInfo.uid = goog.getUid(nodeInfo);
+ var className = node.className;
+ var classNamesLookup = {};
+ if (className) {
+ var classNames = goog.dom.classlist.get(goog.asserts.assertElement(node));
+ for (var i = 0; i < classNames.length; i++) {
+ classNamesLookup[classNames[i]] = 1;
+ }
+ }
+ nodeInfo.classNames = classNamesLookup;
+ nodes.unshift(nodeInfo);
+ } while (node = node.parentNode);
+
+ /**
+ * Array of nodes in order of hierarchy from the top of the document
+ * to the node passed to the constructor
+ * @type {Array<Node>}
+ */
+ this.nodes = nodes;
+
+ this.uid = goog.getUid(this);
+ goog.cssom.iframe.style.NodeAncestry_.instances_[nodeUid] = this;
+};
+
+
+/**
+ * Object for caching existing NodeAncestry instances.
+ * @private
+ */
+goog.cssom.iframe.style.NodeAncestry_.instances_ = {};
+
+
+/**
+ * Throw away all cached dom information. Call this if you've modified
+ * the structure or class/id attributes of your document and you want
+ * to recalculate the currently applied CSS rules.
+ */
+goog.cssom.iframe.style.resetDomCache = function() {
+ goog.cssom.iframe.style.NodeAncestry_.instances_ = {};
+};
+
+
+/**
+ * Inspects a document and returns all active rule sets
+ * @param {Document} doc The document from which to read CSS rules.
+ * @return {!Array<goog.cssom.iframe.style.CssRuleSet_>} An array of CssRuleSet
+ * objects representing all the active rule sets in the document.
+ * @private
+ */
+goog.cssom.iframe.style.getRuleSetsFromDocument_ = function(doc) {
+ var ruleSets = [];
+ var styleSheets = goog.cssom.getAllCssStyleSheets(doc.styleSheets);
+ for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++) {
+ var domRuleSets = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
+ if (domRuleSets && domRuleSets.length) {
+ for (var j = 0, n = domRuleSets.length; j < n; j++) {
+ var ruleSet = new goog.cssom.iframe.style.CssRuleSet_();
+ if (ruleSet.initializeFromCssRule(domRuleSets[j])) {
+ ruleSets.push(ruleSet);
+ }
+ }
+ }
+ }
+ return ruleSets;
+};
+
+
+/**
+ * Static object to cache rulesets read from documents. Inspecting all
+ * active css rules is an expensive operation, so its best to only do
+ * it once and then cache the results.
+ * @type {Object}
+ * @private
+ */
+goog.cssom.iframe.style.ruleSetCache_ = {};
+
+
+/**
+ * Cache of ruleset objects keyed by document unique ID.
+ * @type {Object}
+ * @private
+ */
+goog.cssom.iframe.style.ruleSetCache_.ruleSetCache_ = {};
+
+
+/**
+ * Loads ruleset definitions from a document. If the cache already
+ * has rulesets for this document the cached version will be replaced.
+ * @param {Document} doc The document from which to load rulesets.
+ */
+goog.cssom.iframe.style.ruleSetCache_.loadRuleSetsForDocument = function(doc) {
+ var docUid = goog.getUid(doc);
+ goog.cssom.iframe.style.ruleSetCache_.ruleSetCache_[docUid] =
+ goog.cssom.iframe.style.getRuleSetsFromDocument_(doc);
+};
+
+
+/**
+ * Retrieves the array of css rulesets for this document. A cached
+ * version will be used when possible.
+ * @param {Document} doc The document for which to get rulesets.
+ * @return {!Array<goog.cssom.iframe.style.CssRuleSet_>} An array of CssRuleSet
+ * objects representing the css rule sets in the supplied document.
+ */
+goog.cssom.iframe.style.ruleSetCache_.getRuleSetsForDocument = function(doc) {
+ var docUid = goog.getUid(doc);
+ var cache = goog.cssom.iframe.style.ruleSetCache_.ruleSetCache_;
+ if (!cache[docUid]) {
+ goog.cssom.iframe.style.ruleSetCache_.loadRuleSetsForDocument(doc);
+ }
+ // Build a cloned copy of rulesets array, so if object in the returned array
+ // get modified future calls will still return the original unmodified
+ // versions.
+ var ruleSets = cache[docUid];
+ var ruleSetsCopy = [];
+ for (var i = 0; i < ruleSets.length; i++) {
+ ruleSetsCopy.push(ruleSets[i].clone());
+ }
+ return ruleSetsCopy;
+};
+
+
+/**
+ * Array of CSS properties that are inherited by child nodes, according to
+ * the CSS 2.1 spec. Properties that may be set to relative values, such
+ * as font-size, and line-height, are omitted.
+ * @type {Array<string>}
+ * @private
+ */
+goog.cssom.iframe.style.inheritedProperties_ = [
+ 'color',
+ 'visibility',
+ 'quotes',
+ 'list-style-type',
+ 'list-style-image',
+ 'list-style-position',
+ 'list-style',
+ 'page-break-inside',
+ 'orphans',
+ 'widows',
+ 'font-family',
+ 'font-style',
+ 'font-variant',
+ 'font-weight',
+ 'text-indent',
+ 'text-align',
+ 'text-transform',
+ 'white-space',
+ 'caption-side',
+ 'border-collapse',
+ 'border-spacing',
+ 'empty-cells',
+ 'cursor'
+];
+
+
+/**
+ * Array of CSS 2.1 properties that directly effect text nodes.
+ * @type {Array<string>}
+ * @private
+ */
+goog.cssom.iframe.style.textProperties_ = [
+ 'font-family',
+ 'font-size',
+ 'font-weight',
+ 'font-variant',
+ 'font-style',
+ 'color',
+ 'text-align',
+ 'text-decoration',
+ 'text-indent',
+ 'text-transform',
+ 'letter-spacing',
+ 'white-space',
+ 'word-spacing'
+];
+
+
+/**
+ * Reads the current css rules from element's document, and returns them
+ * rewriting selectors so that any rules that formerly applied to element will
+ * be applied to doc.body. This makes it possible to replace a block in a page
+ * with an iframe and preserve the css styling of the contents.
+ *
+ * @param {Element} element The element for which context should be calculated.
+ * @param {boolean=} opt_forceRuleSetCacheUpdate Flag to force the internal
+ * cache of rulesets to refresh itself before we read the same.
+ * @param {boolean=} opt_copyBackgroundContext Flag indicating that if the
+ * {@code element} has a transparent background, background rules
+ * from the nearest ancestor element(s) that have background-color
+ * and/or background-image set should be copied.
+ * @return {string} String containing all CSS rules present in the original
+ * document, with modified selectors.
+ * @see goog.cssom.iframe.style.getBackgroundContext.
+ */
+goog.cssom.iframe.style.getElementContext = function(
+ element,
+ opt_forceRuleSetCacheUpdate,
+ opt_copyBackgroundContext) {
+ var sourceDocument = element.ownerDocument;
+ if (opt_forceRuleSetCacheUpdate) {
+ goog.cssom.iframe.style.ruleSetCache_.loadRuleSetsForDocument(
+ sourceDocument);
+ }
+ var ruleSets = goog.cssom.iframe.style.ruleSetCache_.
+ getRuleSetsForDocument(sourceDocument);
+
+ var elementAncestry = new goog.cssom.iframe.style.NodeAncestry_(element);
+ var bodySelectorPart = new goog.cssom.iframe.style.CssSelectorPart_('body');
+
+ for (var i = 0; i < ruleSets.length; i++) {
+ var ruleSet = ruleSets[i];
+ var selectors = ruleSet.selectors;
+ // Cache selectors.length since we may be adding rules in the loop.
+ var ruleCount = selectors.length;
+ for (var j = 0; j < ruleCount; j++) {
+ var selector = selectors[j];
+ // Test whether all or part of this selector would match
+ // this element or one of its ancestors
+ var match = selector.matchElementAncestry(elementAncestry);
+ if (match) {
+ var ruleIndex = match.selectorPartIndex;
+ var selectorParts = selector.parts;
+ var lastSelectorPartIndex = selectorParts.length - 1;
+ var selectorCopy;
+ if (match.elementIndex == elementAncestry.nodes.length - 1 ||
+ ruleIndex < lastSelectorPartIndex) {
+ // Either the first part(s) of the selector matched this element,
+ // or the first part(s) of the selector matched a parent element
+ // and there are more parts of the selector that could target
+ // children of this element.
+ // So we inject a new selector, replacing the part that matched this
+ // element with 'body' so it will continue to match.
+ var selectorPartsCopy = selectorParts.concat();
+ selectorPartsCopy.splice(0,
+ ruleIndex + 1,
+ bodySelectorPart);
+ selectorCopy = new goog.cssom.iframe.style.CssSelector_();
+ selectorCopy.parts = selectorPartsCopy;
+ selectors.push(selectorCopy);
+ } else if (ruleIndex > 0 && ruleIndex == lastSelectorPartIndex) {
+ // The rule didn't match this element, but the entire rule did
+ // match an ancestor element. In this case we want to copy
+ // just the last part of the rule, to give it a chance to be applied
+ // to additional matching elements inside this element.
+ // Example DOM structure: body > div.funky > ul > li#editme
+ // Example CSS selector: .funky ul
+ // New CSS selector: body ul
+ selectorCopy = new goog.cssom.iframe.style.CssSelector_();
+ selectorCopy.parts = [
+ bodySelectorPart,
+ selectorParts[lastSelectorPartIndex]
+ ];
+ selectors.push(selectorCopy);
+ }
+ }
+ }
+ }
+
+ // Insert a new ruleset, setting the current inheritable styles of this
+ // element as the defaults for everything under in the frame.
+ var defaultPropertiesRuleSet = new goog.cssom.iframe.style.CssRuleSet_();
+ var computedStyle = goog.cssom.iframe.style.getComputedStyleObject_(element);
+
+ // Copy inheritable styles so they are applied to everything under HTML.
+ var htmlSelector = new goog.cssom.iframe.style.CssSelector_();
+ htmlSelector.parts = [new goog.cssom.iframe.style.CssSelectorPart_('html')];
+ defaultPropertiesRuleSet.selectors = [htmlSelector];
+ var defaultProperties = {};
+ for (var i = 0, prop;
+ prop = goog.cssom.iframe.style.inheritedProperties_[i];
+ i++) {
+ defaultProperties[prop] = computedStyle[goog.string.toCamelCase(prop)];
+ }
+ defaultPropertiesRuleSet.setDeclarationTextFromObject(defaultProperties);
+ ruleSets.push(defaultPropertiesRuleSet);
+
+ var bodyRuleSet = new goog.cssom.iframe.style.CssRuleSet_();
+ var bodySelector = new goog.cssom.iframe.style.CssSelector_();
+ bodySelector.parts = [new goog.cssom.iframe.style.CssSelectorPart_('body')];
+ // Core set of sane property values for BODY, to prevent copied
+ // styles from completely breaking the display.
+ var bodyProperties = {
+ position: 'relative',
+ top: '0',
+ left: '0',
+ right: 'auto', // Override any existing right value so 'left' works.
+ display: 'block',
+ visibility: 'visible'
+ };
+ // Text formatting property values, to keep text nodes directly under BODY
+ // looking right.
+ for (i = 0; prop = goog.cssom.iframe.style.textProperties_[i]; i++) {
+ bodyProperties[prop] = computedStyle[goog.string.toCamelCase(prop)];
+ }
+ if (opt_copyBackgroundContext &&
+ goog.cssom.iframe.style.isTransparentValue_(
+ computedStyle['backgroundColor'])) {
+ // opt_useAncestorBackgroundRules means that, if the original element
+ // has a transparent backgorund, background properties rules should be
+ // added to explicitly make the body have the same background appearance
+ // as in the original element, even if its positioned somewhere else
+ // in the DOM.
+ var bgProperties =
+ goog.cssom.iframe.style.getBackgroundContext(element);
+ bodyProperties['background-color'] = bgProperties['backgroundColor'];
+ var elementBgImage = computedStyle['backgroundImage'];
+ if (!elementBgImage || elementBgImage == 'none') {
+ bodyProperties['background-image'] = bgProperties['backgroundImage'];
+ bodyProperties['background-repeat'] = bgProperties['backgroundRepeat'];
+ bodyProperties['background-position'] =
+ bgProperties['backgroundPosition'];
+ }
+ }
+
+ bodyRuleSet.setDeclarationTextFromObject(bodyProperties, true);
+ bodyRuleSet.selectors = [bodySelector];
+ ruleSets.push(bodyRuleSet);
+
+ // Write outputTextParts to doc.
+ var ruleSetStrings = [];
+ ruleCount = ruleSets.length;
+ for (i = 0; i < ruleCount; i++) {
+ ruleSets[i].writeToArray(ruleSetStrings);
+ }
+ return ruleSetStrings.join('');
+};
+
+
+/**
+ * Tests whether a value is equivalent to 'transparent'.
+ * @param {string} colorValue The value to test.
+ * @return {boolean} Whether the value is transparent.
+ * @private
+ */
+goog.cssom.iframe.style.isTransparentValue_ = function(colorValue) {
+ return colorValue == 'transparent' || colorValue == 'rgba(0, 0, 0, 0)';
+};
+
+
+/**
+ * Returns an object containing the set of computedStyle/currentStyle
+ * values for the given element. Note that this should be used with
+ * caution as it ignores the fact that currentStyle and computedStyle
+ * are not the same for certain properties.
+ *
+ * @param {Element} element The element whose computed style to return.
+ * @return {Object} Object containing style properties and values.
+ * @private
+ */
+goog.cssom.iframe.style.getComputedStyleObject_ = function(element) {
+ // Return an object containing the element's computedStyle/currentStyle.
+ // The resulting object can be re-used to read multiple properties, which
+ // is faster than calling goog.style.getComputedStyle every time.
+ return element.currentStyle ||
+ goog.dom.getOwnerDocument(element).defaultView.getComputedStyle(
+ element, '') || {};
+};
+
+
+/**
+ * RegExp that splits a value like "10px" or "-1em" into parts.
+ * @private
+ * @type {RegExp}
+ */
+goog.cssom.iframe.style.valueWithUnitsRegEx_ = /^(-?)([0-9]+)([a-z]*|%)/;
+
+
+/**
+ * Given an object containing a set of styles, returns a two-element array
+ * containing the values of background-position-x and background-position-y.
+ * @param {Object} styleObject Object from which to read style properties.
+ * @return {Array<string>} The background-position values in the order [x, y].
+ * @private
+ */
+goog.cssom.iframe.style.getBackgroundXYValues_ = function(styleObject) {
+ // Gecko only has backgroundPosition, containing both values.
+ // IE has only backgroundPositionX/backgroundPositionY.
+ // WebKit has both.
+ if (styleObject['backgroundPositionY']) {
+ return [styleObject['backgroundPositionX'],
+ styleObject['backgroundPositionY']];
+ } else {
+ return (styleObject['backgroundPosition'] || '0 0').split(' ');
+ }
+};
+
+
+/**
+ * Generates a set of CSS properties that can be used to make another
+ * element's background look like the background of a given element.
+ * This is useful when you want to copy the CSS context of an element,
+ * but the element's background is transparent. In the original context
+ * you would see the ancestor's backround color/image showing through,
+ * but in the new context there might be a something different underneath.
+ * Note that this assumes the element you're copying context from has a
+ * fairly standard positioning/layout - it assumes that when the element
+ * has a transparent background what you're going to see through it is its
+ * ancestors.
+ * @param {Element} element The element from which to copy background styles.
+ * @return {!Object} Object containing background* properties.
+ */
+goog.cssom.iframe.style.getBackgroundContext = function(element) {
+ var propertyValues = {
+ 'backgroundImage': 'none'
+ };
+ var ancestor = element;
+ var currentIframeWindow;
+ // Walk up the DOM tree to find the ancestor nodes whose backgrounds
+ // may be visible underneath this element. Background-image and
+ // background-color don't have to come from the same node, but as soon
+ // an element with background-color is found there's no need to continue
+ // because backgrounds farther up the chain won't be visible.
+ // (This implementation is not sophisticated enough to handle opacity,
+ // or multple layered partially-transparent background images.)
+ while ((ancestor = ancestor.parentNode) &&
+ ancestor.nodeType == goog.dom.NodeType.ELEMENT) {
+ var computedStyle = goog.cssom.iframe.style.getComputedStyleObject_(
+ /** @type {!Element} */ (ancestor));
+ // Copy background color if a non-transparent value is found.
+ var backgroundColorValue = computedStyle['backgroundColor'];
+ if (!goog.cssom.iframe.style.isTransparentValue_(backgroundColorValue)) {
+ propertyValues['backgroundColor'] = backgroundColorValue;
+ }
+ // If a background image value is found, copy background-image,
+ // background-repeat, and background-position.
+ if (computedStyle['backgroundImage'] &&
+ computedStyle['backgroundImage'] != 'none') {
+ propertyValues['backgroundImage'] = computedStyle['backgroundImage'];
+ propertyValues['backgroundRepeat'] = computedStyle['backgroundRepeat'];
+ // Calculate the offset between the original element and the element
+ // providing the background image, so the background position can be
+ // adjusted.
+ var relativePosition;
+ if (currentIframeWindow) {
+ relativePosition = goog.style.getFramedPageOffset(
+ element, currentIframeWindow);
+ var frameElement = currentIframeWindow.frameElement;
+ var iframeRelativePosition = goog.style.getRelativePosition(
+ /** @type {!Element} */ (frameElement),
+ /** @type {!Element} */ (ancestor));
+ var iframeBorders = goog.style.getBorderBox(frameElement);
+ relativePosition.x += iframeRelativePosition.x + iframeBorders.left;
+ relativePosition.y += iframeRelativePosition.y + iframeBorders.top;
+ } else {
+ relativePosition = goog.style.getRelativePosition(
+ element, /** @type {Element} */ (ancestor));
+ }
+ var backgroundXYValues = goog.cssom.iframe.style.getBackgroundXYValues_(
+ computedStyle);
+ // Parse background-repeat-* values in the form "10px", and adjust them.
+ for (var i = 0; i < 2; i++) {
+ var positionValue = backgroundXYValues[i];
+ var coordinate = i == 0 ? 'X' : 'Y';
+ var positionProperty = 'backgroundPosition' + coordinate;
+ // relative position to its ancestor.
+ var positionValueParts =
+ goog.cssom.iframe.style.valueWithUnitsRegEx_.exec(positionValue);
+ if (positionValueParts) {
+ var value = parseInt(
+ positionValueParts[1] + positionValueParts[2], 10);
+ var units = positionValueParts[3];
+ // This only attempts to handle pixel values for now (plus
+ // '0anything', which is equivalent to 0px).
+ // TODO(user) Convert non-pixel values to pixels when possible.
+ if (value == 0 || units == 'px') {
+ value -= (coordinate == 'X' ?
+ relativePosition.x : relativePosition.y);
+ }
+ positionValue = value + units;
+ }
+ propertyValues[positionProperty] = positionValue;
+ }
+ propertyValues['backgroundPosition'] =
+ propertyValues['backgroundPositionX'] + ' ' +
+ propertyValues['backgroundPositionY'];
+ }
+ if (propertyValues['backgroundColor']) {
+ break;
+ }
+ if (ancestor.tagName == goog.dom.TagName.HTML) {
+ try {
+ currentIframeWindow = goog.dom.getWindow(
+ /** @type {Document} */ (ancestor.parentNode));
+ // This could theoretically throw a security exception if the parent
+ // iframe is in a different domain.
+ ancestor = currentIframeWindow.frameElement;
+ if (!ancestor) {
+ // Loop has reached the top level window.
+ break;
+ }
+ } catch (e) {
+ // We don't have permission to go up to the parent window, stop here.
+ break;
+ }
+ }
+ }
+ return propertyValues;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/cssom/iframe/style_test_import.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/cssom/iframe/style_test_import.css b/externs/GCL/externs/goog/cssom/iframe/style_test_import.css
new file mode 100644
index 0000000..d2c603f
--- /dev/null
+++ b/externs/GCL/externs/goog/cssom/iframe/style_test_import.css
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+div div strong {
+ font-style: italic;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/datamanager.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/datamanager.js b/externs/GCL/externs/goog/datasource/datamanager.js
new file mode 100644
index 0000000..5eccd20
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/datamanager.js
@@ -0,0 +1,561 @@
+// 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
+ * Central class for registering and accessing data sources
+ * Also handles processing of data events.
+ *
+ * There is a shared global instance that most client code should access via
+ * goog.ds.DataManager.getInstance(). However you can also create your own
+ * DataManager using new
+ *
+ * Implements DataNode to provide the top element in a data registry
+ * Prepends '$' to top level data names in path to denote they are root object
+ *
+ */
+goog.provide('goog.ds.DataManager');
+
+goog.require('goog.ds.BasicNodeList');
+goog.require('goog.ds.DataNode');
+goog.require('goog.ds.Expr');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.structs');
+goog.require('goog.structs.Map');
+
+
+
+/**
+ * Create a DataManger
+ * @extends {goog.ds.DataNode}
+ * @constructor
+ * @final
+ */
+goog.ds.DataManager = function() {
+ this.dataSources_ = new goog.ds.BasicNodeList();
+ this.autoloads_ = new goog.structs.Map();
+ this.listenerMap_ = {};
+ this.listenersByFunction_ = {};
+ this.aliases_ = {};
+ this.eventCount_ = 0;
+ this.indexedListenersByFunction_ = {};
+};
+
+
+/**
+ * Global instance
+ * @private
+ */
+goog.ds.DataManager.instance_ = null;
+goog.inherits(goog.ds.DataManager, goog.ds.DataNode);
+
+
+/**
+ * Get the global instance
+ * @return {!goog.ds.DataManager} The data manager singleton.
+ */
+goog.ds.DataManager.getInstance = function() {
+ if (!goog.ds.DataManager.instance_) {
+ goog.ds.DataManager.instance_ = new goog.ds.DataManager();
+ }
+ return goog.ds.DataManager.instance_;
+};
+
+
+/**
+ * Clears the global instance (for unit tests to reset state).
+ */
+goog.ds.DataManager.clearInstance = function() {
+ goog.ds.DataManager.instance_ = null;
+};
+
+
+/**
+ * Add a data source
+ * @param {goog.ds.DataNode} ds The data source.
+ * @param {boolean=} opt_autoload Whether to automatically load the data,
+ * defaults to false.
+ * @param {string=} opt_name Optional name, can also get name
+ * from the datasource.
+ */
+goog.ds.DataManager.prototype.addDataSource = function(ds, opt_autoload,
+ opt_name) {
+ var autoload = !!opt_autoload;
+ var name = opt_name || ds.getDataName();
+ if (!goog.string.startsWith(name, '$')) {
+ name = '$' + name;
+ }
+ ds.setDataName(name);
+ this.dataSources_.add(ds);
+ this.autoloads_.set(name, autoload);
+};
+
+
+/**
+ * Create an alias for a data path, very similar to assigning a variable.
+ * For example, you can set $CurrentContact -> $Request/Contacts[5], and all
+ * references to $CurrentContact will be procesed on $Request/Contacts[5].
+ *
+ * Aliases will hide datasources of the same name.
+ *
+ * @param {string} name Alias name, must be a top level path ($Foo).
+ * @param {string} dataPath Data path being aliased.
+ */
+goog.ds.DataManager.prototype.aliasDataSource = function(name, dataPath) {
+ if (!this.aliasListener_) {
+ this.aliasListener_ = goog.bind(this.listenForAlias_, this);
+ }
+ if (this.aliases_[name]) {
+ var oldPath = this.aliases_[name].getSource();
+ this.removeListeners(this.aliasListener_, oldPath + '/...', name);
+ }
+ this.aliases_[name] = goog.ds.Expr.create(dataPath);
+ this.addListener(this.aliasListener_, dataPath + '/...', name);
+ this.fireDataChange(name);
+};
+
+
+/**
+ * Listener function for matches of paths that have been aliased.
+ * Fires a data change on the alias as well.
+ *
+ * @param {string} dataPath Path of data event fired.
+ * @param {string} name Name of the alias.
+ * @private
+ */
+goog.ds.DataManager.prototype.listenForAlias_ = function(dataPath, name) {
+ var aliasedExpr = this.aliases_[name];
+
+ if (aliasedExpr) {
+ // If it's a subpath, appends the subpath to the alias name
+ // otherwise just fires on the top level alias
+ var aliasedPath = aliasedExpr.getSource();
+ if (dataPath.indexOf(aliasedPath) == 0) {
+ this.fireDataChange(name + dataPath.substring(aliasedPath.length));
+ } else {
+ this.fireDataChange(name);
+ }
+ }
+};
+
+
+/**
+ * Gets a named child node of the current node.
+ *
+ * @param {string} name The node name.
+ * @return {goog.ds.DataNode} The child node,
+ * or null if no node of this name exists.
+ */
+goog.ds.DataManager.prototype.getDataSource = function(name) {
+ if (this.aliases_[name]) {
+ return this.aliases_[name].getNode();
+ } else {
+ return this.dataSources_.get(name);
+ }
+};
+
+
+/**
+ * Get the value of the node
+ * @return {!Object} The value of the node.
+ * @override
+ */
+goog.ds.DataManager.prototype.get = function() {
+ return this.dataSources_;
+};
+
+
+/** @override */
+goog.ds.DataManager.prototype.set = function(value) {
+ throw Error('Can\'t set on DataManager');
+};
+
+
+/** @override */
+goog.ds.DataManager.prototype.getChildNodes = function(opt_selector) {
+ if (opt_selector) {
+ return new goog.ds.BasicNodeList(
+ [this.getChildNode(/** @type {string} */(opt_selector))]);
+ } else {
+ return this.dataSources_;
+ }
+};
+
+
+/**
+ * Gets a named child node of the current node
+ * @param {string} name The node name.
+ * @return {goog.ds.DataNode} The child node,
+ * or null if no node of this name exists.
+ * @override
+ */
+goog.ds.DataManager.prototype.getChildNode = function(name) {
+ return this.getDataSource(name);
+};
+
+
+/** @override */
+goog.ds.DataManager.prototype.getChildNodeValue = function(name) {
+ var ds = this.getDataSource(name);
+ return ds ? ds.get() : null;
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ * @override
+ */
+goog.ds.DataManager.prototype.getDataName = function() {
+ return '';
+};
+
+
+/**
+ * Gets the a qualified data path to this node
+ * @return {string} The data path.
+ * @override
+ */
+goog.ds.DataManager.prototype.getDataPath = function() {
+ return '';
+};
+
+
+/**
+ * Load or reload the backing data for this node
+ * only loads datasources flagged with autoload
+ * @override
+ */
+goog.ds.DataManager.prototype.load = function() {
+ var len = this.dataSources_.getCount();
+ for (var i = 0; i < len; i++) {
+ var ds = this.dataSources_.getByIndex(i);
+ var autoload = this.autoloads_.get(ds.getDataName());
+ if (autoload) {
+ ds.load();
+ }
+ }
+};
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ * @override
+ */
+goog.ds.DataManager.prototype.getLoadState = goog.abstractMethod;
+
+
+/**
+ * Whether the value of this node is a homogeneous list of data
+ * @return {boolean} True if a list.
+ * @override
+ */
+goog.ds.DataManager.prototype.isList = function() {
+ return false;
+};
+
+
+/**
+ * Get the total count of events fired (mostly for debugging)
+ * @return {number} Count of events.
+ */
+goog.ds.DataManager.prototype.getEventCount = function() {
+ return this.eventCount_;
+};
+
+
+/**
+ * Adds a listener
+ * Listeners should fire when any data with path that has dataPath as substring
+ * is changed.
+ * TODO(user) Look into better listener handling
+ *
+ * @param {Function} fn Callback function, signature function(dataPath, id).
+ * @param {string} dataPath Fully qualified data path.
+ * @param {string=} opt_id A value passed back to the listener when the dataPath
+ * is matched.
+ */
+goog.ds.DataManager.prototype.addListener = function(fn, dataPath, opt_id) {
+ // maxAncestor sets how distant an ancestor you can be of the fired event
+ // and still fire (you always fire if you are a descendant).
+ // 0 means you don't fire if you are an ancestor
+ // 1 means you only fire if you are parent
+ // 1000 means you will fire if you are ancestor (effectively infinite)
+ var maxAncestors = 0;
+ if (goog.string.endsWith(dataPath, '/...')) {
+ maxAncestors = 1000;
+ dataPath = dataPath.substring(0, dataPath.length - 4);
+ } else if (goog.string.endsWith(dataPath, '/*')) {
+ maxAncestors = 1;
+ dataPath = dataPath.substring(0, dataPath.length - 2);
+ }
+
+ opt_id = opt_id || '';
+ var key = dataPath + ':' + opt_id + ':' + goog.getUid(fn);
+ var listener = {dataPath: dataPath, id: opt_id, fn: fn};
+ var expr = goog.ds.Expr.create(dataPath);
+
+ var fnUid = goog.getUid(fn);
+ if (!this.listenersByFunction_[fnUid]) {
+ this.listenersByFunction_[fnUid] = {};
+ }
+ this.listenersByFunction_[fnUid][key] = {listener: listener, items: []};
+
+ while (expr) {
+ var listenerSpec = {listener: listener, maxAncestors: maxAncestors};
+ var matchingListeners = this.listenerMap_[expr.getSource()];
+ if (matchingListeners == null) {
+ matchingListeners = {};
+ this.listenerMap_[expr.getSource()] = matchingListeners;
+ }
+ matchingListeners[key] = listenerSpec;
+ maxAncestors = 0;
+ expr = expr.getParent();
+ this.listenersByFunction_[fnUid][key].items.push(
+ {key: key, obj: matchingListeners});
+ }
+};
+
+
+/**
+ * Adds an indexed listener.
+ *
+ * Indexed listeners allow for '*' in data paths. If a * exists, will match
+ * all values and return the matched values in an array to the callback.
+ *
+ * Currently uses a promiscuous match algorithm: Matches everything before the
+ * first '*', and then does a regex match for all of the returned events.
+ * Although this isn't optimized, it is still an improvement as you can collapse
+ * 100's of listeners into a single regex match
+ *
+ * @param {Function} fn Callback function, signature (dataPath, id, indexes).
+ * @param {string} dataPath Fully qualified data path.
+ * @param {string=} opt_id A value passed back to the listener when the dataPath
+ * is matched.
+ */
+goog.ds.DataManager.prototype.addIndexedListener = function(fn, dataPath,
+ opt_id) {
+ var firstStarPos = dataPath.indexOf('*');
+ // Just need a regular listener
+ if (firstStarPos == -1) {
+ this.addListener(fn, dataPath, opt_id);
+ return;
+ }
+
+ var listenPath = dataPath.substring(0, firstStarPos) + '...';
+
+ // Create regex that matches * to any non '\' character
+ var ext = '$';
+ if (goog.string.endsWith(dataPath, '/...')) {
+ dataPath = dataPath.substring(0, dataPath.length - 4);
+ ext = '';
+ }
+ var regExpPath = goog.string.regExpEscape(dataPath);
+ var matchRegExp = regExpPath.replace(/\\\*/g, '([^\\\/]+)') + ext;
+
+ // Matcher function applies the regex and calls back the original function
+ // if the regex matches, passing in an array of the matched values
+ var matchRegExpRe = new RegExp(matchRegExp);
+ var matcher = function(path, id) {
+ var match = matchRegExpRe.exec(path);
+ if (match) {
+ match.shift();
+ fn(path, opt_id, match);
+ }
+ };
+ this.addListener(matcher, listenPath, opt_id);
+
+ // Add the indexed listener to the map so that we can remove it later.
+ var fnUid = goog.getUid(fn);
+ if (!this.indexedListenersByFunction_[fnUid]) {
+ this.indexedListenersByFunction_[fnUid] = {};
+ }
+ var key = dataPath + ':' + opt_id;
+ this.indexedListenersByFunction_[fnUid][key] = {
+ listener: {dataPath: listenPath, fn: matcher, id: opt_id}
+ };
+};
+
+
+/**
+ * Removes indexed listeners with a given callback function, and optional
+ * matching datapath and matching id.
+ *
+ * @param {Function} fn Callback function, signature function(dataPath, id).
+ * @param {string=} opt_dataPath Fully qualified data path.
+ * @param {string=} opt_id A value passed back to the listener when the dataPath
+ * is matched.
+ */
+goog.ds.DataManager.prototype.removeIndexedListeners = function(
+ fn, opt_dataPath, opt_id) {
+ this.removeListenersByFunction_(
+ this.indexedListenersByFunction_, true, fn, opt_dataPath, opt_id);
+};
+
+
+/**
+ * Removes listeners with a given callback function, and optional
+ * matching dataPath and matching id
+ *
+ * @param {Function} fn Callback function, signature function(dataPath, id).
+ * @param {string=} opt_dataPath Fully qualified data path.
+ * @param {string=} opt_id A value passed back to the listener when the dataPath
+ * is matched.
+ */
+goog.ds.DataManager.prototype.removeListeners = function(fn, opt_dataPath,
+ opt_id) {
+
+ // Normalize data path root
+ if (opt_dataPath && goog.string.endsWith(opt_dataPath, '/...')) {
+ opt_dataPath = opt_dataPath.substring(0, opt_dataPath.length - 4);
+ } else if (opt_dataPath && goog.string.endsWith(opt_dataPath, '/*')) {
+ opt_dataPath = opt_dataPath.substring(0, opt_dataPath.length - 2);
+ }
+
+ this.removeListenersByFunction_(
+ this.listenersByFunction_, false, fn, opt_dataPath, opt_id);
+};
+
+
+/**
+ * Removes listeners with a given callback function, and optional
+ * matching dataPath and matching id from the given listenersByFunction
+ * data structure.
+ *
+ * @param {Object} listenersByFunction The listeners by function.
+ * @param {boolean} indexed Indicates whether the listenersByFunction are
+ * indexed or not.
+ * @param {Function} fn Callback function, signature function(dataPath, id).
+ * @param {string=} opt_dataPath Fully qualified data path.
+ * @param {string=} opt_id A value passed back to the listener when the dataPath
+ * is matched.
+ * @private
+ */
+goog.ds.DataManager.prototype.removeListenersByFunction_ = function(
+ listenersByFunction, indexed, fn, opt_dataPath, opt_id) {
+ var fnUid = goog.getUid(fn);
+ var functionMatches = listenersByFunction[fnUid];
+ if (functionMatches != null) {
+ for (var key in functionMatches) {
+ var functionMatch = functionMatches[key];
+ var listener = functionMatch.listener;
+ if ((!opt_dataPath || opt_dataPath == listener.dataPath) &&
+ (!opt_id || opt_id == listener.id)) {
+ if (indexed) {
+ this.removeListeners(
+ listener.fn, listener.dataPath, listener.id);
+ }
+ if (functionMatch.items) {
+ for (var i = 0; i < functionMatch.items.length; i++) {
+ var item = functionMatch.items[i];
+ delete item.obj[item.key];
+ }
+ }
+ delete functionMatches[key];
+ }
+ }
+ }
+};
+
+
+/**
+ * Get the total number of listeners (per expression listened to, so may be
+ * more than number of times addListener() has been called
+ * @return {number} Number of listeners.
+ */
+goog.ds.DataManager.prototype.getListenerCount = function() {
+ var count = 0;
+ goog.object.forEach(this.listenerMap_, function(matchingListeners) {
+ count += goog.structs.getCount(matchingListeners);
+ });
+ return count;
+};
+
+
+/**
+ * Disables the sending of all data events during the execution of the given
+ * callback. This provides a way to avoid useless notifications of small changes
+ * when you will eventually send a data event manually that encompasses them
+ * all.
+ *
+ * Note that this function can not be called reentrantly.
+ *
+ * @param {Function} callback Zero-arg function to execute.
+ */
+goog.ds.DataManager.prototype.runWithoutFiringDataChanges = function(callback) {
+ if (this.disableFiring_) {
+ throw Error('Can not nest calls to runWithoutFiringDataChanges');
+ }
+
+ this.disableFiring_ = true;
+ try {
+ callback();
+ } finally {
+ this.disableFiring_ = false;
+ }
+};
+
+
+/**
+ * Fire a data change event to all listeners
+ *
+ * If the path matches the path of a listener, the listener will fire
+ *
+ * If your path is the parent of a listener, the listener will fire. I.e.
+ * if $Contacts/bob@bob.com changes, then we will fire listener for
+ * $Contacts/bob@bob.com/Name as well, as the assumption is that when
+ * a parent changes, all children are invalidated.
+ *
+ * If your path is the child of a listener, the listener may fire, depending
+ * on the ancestor depth.
+ *
+ * A listener for $Contacts might only be interested if the contact name changes
+ * (i.e. $Contacts doesn't fire on $Contacts/bob@bob.com/Name),
+ * while a listener for a specific contact might
+ * (i.e. $Contacts/bob@bob.com would fire on $Contacts/bob@bob.com/Name).
+ * Adding "/..." to a lisetener path listens to all children, and adding "/*" to
+ * a listener path listens only to direct children
+ *
+ * @param {string} dataPath Fully qualified data path.
+ */
+goog.ds.DataManager.prototype.fireDataChange = function(dataPath) {
+ if (this.disableFiring_) {
+ return;
+ }
+
+ var expr = goog.ds.Expr.create(dataPath);
+ var ancestorDepth = 0;
+
+ // Look for listeners for expression and all its parents.
+ // Parents of listener expressions are all added to the listenerMap as well,
+ // so this will evaluate inner loop every time the dataPath is a child or
+ // an ancestor of the original listener path
+ while (expr) {
+ var matchingListeners = this.listenerMap_[expr.getSource()];
+ if (matchingListeners) {
+ for (var id in matchingListeners) {
+ var match = matchingListeners[id];
+ var listener = match.listener;
+ if (ancestorDepth <= match.maxAncestors) {
+ listener.fn(dataPath, listener.id);
+ }
+ }
+ }
+ ancestorDepth++;
+ expr = expr.getParent();
+ }
+ this.eventCount_++;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/datasource.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/datasource.js b/externs/GCL/externs/goog/datasource/datasource.js
new file mode 100644
index 0000000..4cb0db6
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/datasource.js
@@ -0,0 +1,658 @@
+// 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 Generic rich data access API.
+ *
+ * Abstraction for data sources that allows listening for changes at different
+ * levels of the data tree and updating the data via XHR requests
+ *
+ */
+
+
+goog.provide('goog.ds.BaseDataNode');
+goog.provide('goog.ds.BasicNodeList');
+goog.provide('goog.ds.DataNode');
+goog.provide('goog.ds.DataNodeList');
+goog.provide('goog.ds.EmptyNodeList');
+goog.provide('goog.ds.LoadState');
+goog.provide('goog.ds.SortedNodeList');
+goog.provide('goog.ds.Util');
+goog.provide('goog.ds.logger');
+
+goog.require('goog.array');
+goog.require('goog.log');
+
+
+
+/**
+ * Interface for node in rich data tree.
+ *
+ * Names that are reserved for system use and shouldn't be used for data node
+ * names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
+ * undefined if these names are used.
+ *
+ * @constructor
+ */
+goog.ds.DataNode = function() {};
+
+
+/**
+ * Get the value of the node
+ * @param {...?} var_args Do not check arity of arguments, because
+ * some subclasses require args.
+ * @return {*} The value of the node, or null if no value.
+ */
+goog.ds.DataNode.prototype.get = goog.abstractMethod;
+
+
+/**
+ * Set the value of the node
+ * @param {*} value The new value of the node.
+ */
+goog.ds.DataNode.prototype.set = goog.abstractMethod;
+
+
+/**
+ * Gets all of the child nodes of the current node.
+ * Should return an empty DataNode list if no child nodes.
+ * @param {string=} opt_selector String selector to choose child nodes.
+ * @return {!goog.ds.DataNodeList} The child nodes.
+ */
+goog.ds.DataNode.prototype.getChildNodes = goog.abstractMethod;
+
+
+/**
+ * Gets a named child node of the current node
+ * @param {string} name The node name.
+ * @param {boolean=} opt_canCreate Whether to create a child node if it does not
+ * exist.
+ * @return {goog.ds.DataNode} The child node, or null
+ * if no node of this name exists.
+ */
+goog.ds.DataNode.prototype.getChildNode = goog.abstractMethod;
+
+
+/**
+ * Gets the value of a child node
+ * @param {string} name The node name.
+ * @return {*} The value of the node, or null if no value or the child node
+ * doesn't exist.
+ */
+goog.ds.DataNode.prototype.getChildNodeValue = goog.abstractMethod;
+
+
+/**
+ * Sets a named child node of the current node.
+ *
+ * @param {string} name The node name.
+ * @param {Object} value The value to set, can be DataNode, object, property,
+ * or null. If value is null, removes the child node.
+ * @return {Object} The child node, if the node was set.
+ */
+goog.ds.DataNode.prototype.setChildNode = goog.abstractMethod;
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ */
+goog.ds.DataNode.prototype.getDataName = goog.abstractMethod;
+
+
+/**
+ * Set the name of the node relative to the parent node
+ * @param {string} name The name of the node.
+ */
+goog.ds.DataNode.prototype.setDataName = goog.abstractMethod;
+
+
+/**
+ * Gets the a qualified data path to this node
+ * @return {string} The data path.
+ */
+goog.ds.DataNode.prototype.getDataPath = goog.abstractMethod;
+
+
+/**
+ * Load or reload the backing data for this node
+ */
+goog.ds.DataNode.prototype.load = goog.abstractMethod;
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ */
+goog.ds.DataNode.prototype.getLoadState = goog.abstractMethod;
+
+
+/**
+ * Whether the value of this node is a homogeneous list of data
+ * @return {boolean} True if a list.
+ */
+goog.ds.DataNode.prototype.isList = goog.abstractMethod;
+
+
+/**
+ * Enum for load state of a DataNode.
+ * @enum {string}
+ */
+goog.ds.LoadState = {
+ LOADED: 'LOADED',
+ LOADING: 'LOADING',
+ FAILED: 'FAILED',
+ NOT_LOADED: 'NOT_LOADED'
+};
+
+
+
+/**
+ * Base class for data node functionality, has default implementations for
+ * many of the functions.
+ *
+ * implements {goog.ds.DataNode}
+ * @constructor
+ */
+goog.ds.BaseDataNode = function() {};
+
+
+/**
+ * Set the value of the node
+ * @param {Object} value The new value of the node.
+ */
+goog.ds.BaseDataNode.prototype.set = goog.abstractMethod;
+
+
+/**
+ * Gets all of the child nodes of the current node.
+ * Should return an empty DataNode list if no child nodes.
+ * @param {string=} opt_selector String selector to choose child nodes.
+ * @return {!goog.ds.DataNodeList} The child nodes.
+ */
+goog.ds.BaseDataNode.prototype.getChildNodes = function(opt_selector) {
+ return new goog.ds.EmptyNodeList();
+};
+
+
+/**
+ * Gets a named child node of the current node
+ * @param {string} name The node name.
+ * @param {boolean=} opt_canCreate Whether you can create the child node if
+ * it doesn't exist already.
+ * @return {goog.ds.DataNode} The child node, or null if no node of
+ * this name exists and opt_create is false.
+ */
+goog.ds.BaseDataNode.prototype.getChildNode = function(name, opt_canCreate) {
+ return null;
+};
+
+
+/**
+ * Gets the value of a child node
+ * @param {string} name The node name.
+ * @return {Object} The value of the node, or null if no value or the
+ * child node doesn't exist.
+ */
+goog.ds.BaseDataNode.prototype.getChildNodeValue = function(name) {
+ return null;
+};
+
+
+/**
+ * Get the name of the node relative to the parent node
+ * @return {string} The name of the node.
+ */
+goog.ds.BaseDataNode.prototype.getDataName = goog.abstractMethod;
+
+
+/**
+ * Gets the a qualified data path to this node
+ * @return {string} The data path.
+ */
+goog.ds.BaseDataNode.prototype.getDataPath = function() {
+ var parentPath = '';
+ var myName = this.getDataName();
+ if (this.getParent && this.getParent()) {
+ parentPath = this.getParent().getDataPath() +
+ (myName.indexOf(goog.ds.STR_ARRAY_START) != -1 ? '' :
+ goog.ds.STR_PATH_SEPARATOR);
+ }
+
+ return parentPath + myName;
+};
+
+
+/**
+ * Load or reload the backing data for this node
+ */
+goog.ds.BaseDataNode.prototype.load = goog.nullFunction;
+
+
+/**
+ * Gets the state of the backing data for this node
+ * @return {goog.ds.LoadState} The state.
+ */
+goog.ds.BaseDataNode.prototype.getLoadState = function() {
+ return goog.ds.LoadState.LOADED;
+};
+
+
+/**
+ * Gets the parent node. Subclasses implement this function
+ * @type {Function}
+ * @protected
+ */
+goog.ds.BaseDataNode.prototype.getParent = null;
+
+
+/**
+ * Interface for node list in rich data tree.
+ *
+ * Has both map and list-style accessors
+ *
+ * @constructor
+ * @extends {goog.ds.DataNode}
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.DataNodeList = function() {};
+
+
+/**
+ * Add a node to the node list.
+ * If the node has a dataName, uses this for the key in the map.
+ *
+ * @param {goog.ds.DataNode} node The node to add.
+ */
+goog.ds.DataNodeList.prototype.add = goog.abstractMethod;
+
+
+/**
+ * Get a node by string key.
+ * Returns null if node doesn't exist.
+ *
+ * @param {string} key String lookup key.
+ * @return {*} The node, or null if doesn't exist.
+ * @override
+ */
+goog.ds.DataNodeList.prototype.get = goog.abstractMethod;
+
+
+/**
+ * Get a node by index
+ * Returns null if the index is out of range
+ *
+ * @param {number} index The index of the node.
+ * @return {goog.ds.DataNode} The node, or null if doesn't exist.
+ */
+goog.ds.DataNodeList.prototype.getByIndex = goog.abstractMethod;
+
+
+/**
+ * Gets the size of the node list
+ *
+ * @return {number} The size of the list.
+ */
+goog.ds.DataNodeList.prototype.getCount = goog.abstractMethod;
+
+
+/**
+ * Sets a node in the list of a given name
+ * @param {string} name Name of the node.
+ * @param {goog.ds.DataNode} node The node.
+ */
+goog.ds.DataNodeList.prototype.setNode = goog.abstractMethod;
+
+
+/**
+ * Removes a node in the list of a given name
+ * @param {string} name Name of the node.
+ * @return {boolean} True if node existed and was deleted.
+ */
+goog.ds.DataNodeList.prototype.removeNode = goog.abstractMethod;
+
+
+/**
+ * Simple node list implementation with underlying array and map
+ * implements goog.ds.DataNodeList.
+ *
+ * Names that are reserved for system use and shouldn't be used for data node
+ * names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
+ * undefined if these names are used.
+ *
+ * @param {Array<goog.ds.DataNode>=} opt_nodes optional nodes to add to list.
+ * @constructor
+ * @extends {goog.ds.DataNodeList}
+ */
+// TODO(arv): Use interfaces when available.
+goog.ds.BasicNodeList = function(opt_nodes) {
+ this.map_ = {};
+ this.list_ = [];
+ this.indexMap_ = {};
+ if (opt_nodes) {
+ for (var i = 0, node; node = opt_nodes[i]; i++) {
+ this.add(node);
+ }
+ }
+};
+
+
+/**
+ * Add a node to the node list.
+ * If the node has a dataName, uses this for the key in the map.
+ * TODO(user) Remove function as well
+ *
+ * @param {goog.ds.DataNode} node The node to add.
+ * @override
+ */
+goog.ds.BasicNodeList.prototype.add = function(node) {
+ this.list_.push(node);
+ var dataName = node.getDataName();
+ if (dataName) {
+ this.map_[dataName] = node;
+ this.indexMap_[dataName] = this.list_.length - 1;
+ }
+};
+
+
+/**
+ * Get a node by string key.
+ * Returns null if node doesn't exist.
+ *
+ * @param {string} key String lookup key.
+ * @return {goog.ds.DataNode} The node, or null if doesn't exist.
+ * @override
+ */
+goog.ds.BasicNodeList.prototype.get = function(key) {
+ return this.map_[key] || null;
+};
+
+
+/**
+ * Get a node by index
+ * Returns null if the index is out of range
+ *
+ * @param {number} index The index of the node.
+ * @return {goog.ds.DataNode} The node, or null if doesn't exist.
+ * @override
+ */
+goog.ds.BasicNodeList.prototype.getByIndex = function(index) {
+ return this.list_[index] || null;
+};
+
+
+/**
+ * Gets the size of the node list
+ *
+ * @return {number} The size of the list.
+ * @override
+ */
+goog.ds.BasicNodeList.prototype.getCount = function() {
+ return this.list_.length;
+};
+
+
+/**
+ * Sets a node in the list of a given name
+ * @param {string} name Name of the node.
+ * @param {goog.ds.DataNode} node The node.
+ * @override
+ */
+goog.ds.BasicNodeList.prototype.setNode = function(name, node) {
+ if (node == null) {
+ this.removeNode(name);
+ } else {
+ var existingNode = this.indexMap_[name];
+ if (existingNode != null) {
+ this.map_[name] = node;
+ this.list_[existingNode] = node;
+ } else {
+ this.add(node);
+ }
+ }
+};
+
+
+/**
+ * Removes a node in the list of a given name
+ * @param {string} name Name of the node.
+ * @return {boolean} True if node existed and was deleted.
+ * @override
+ */
+goog.ds.BasicNodeList.prototype.removeNode = function(name) {
+ var existingNode = this.indexMap_[name];
+ if (existingNode != null) {
+ this.list_.splice(existingNode, 1);
+ delete this.map_[name];
+ delete this.indexMap_[name];
+ for (var index in this.indexMap_) {
+ if (this.indexMap_[index] > existingNode) {
+ this.indexMap_[index]--;
+ }
+ }
+ }
+ return existingNode != null;
+};
+
+
+/**
+ * Get the index of a named node
+ * @param {string} name The name of the node to get the index of.
+ * @return {number|undefined} The index.
+ */
+goog.ds.BasicNodeList.prototype.indexOf = function(name) {
+ return this.indexMap_[name];
+};
+
+
+/**
+ * Immulatable empty node list
+ * @extends {goog.ds.BasicNodeList}
+ * @constructor
+ * @final
+ */
+
+goog.ds.EmptyNodeList = function() {
+ goog.ds.BasicNodeList.call(this);
+};
+goog.inherits(goog.ds.EmptyNodeList, goog.ds.BasicNodeList);
+
+
+/**
+ * Add a node to the node list.
+ * If the node has a dataName, uses this for the key in the map.
+ *
+ * @param {goog.ds.DataNode} node The node to add.
+ * @override
+ */
+goog.ds.EmptyNodeList.prototype.add = function(node) {
+ throw Error('Can\'t add to EmptyNodeList');
+};
+
+
+
+/**
+ * Node list implementation which maintains sort order during insertion and
+ * modification operations based on a comparison function.
+ *
+ * The SortedNodeList does not guarantee sort order will be maintained if
+ * the underlying data nodes are modified externally.
+ *
+ * Names that are reserved for system use and shouldn't be used for data node
+ * names: eval, toSource, toString, unwatch, valueOf, watch. Behavior is
+ * undefined if these names are used.
+ *
+ * @param {Function} compareFn Comparison function by which the
+ * node list is sorted. Should take 2 arguments to compare, and return a
+ * negative integer, zero, or a positive integer depending on whether the
+ * first argument is less than, equal to, or greater than the second.
+ * @param {Array<goog.ds.DataNode>=} opt_nodes optional nodes to add to list;
+ * these are assumed to be in sorted order.
+ * @extends {goog.ds.BasicNodeList}
+ * @constructor
+ */
+goog.ds.SortedNodeList = function(compareFn, opt_nodes) {
+ this.compareFn_ = compareFn;
+ goog.ds.BasicNodeList.call(this, opt_nodes);
+};
+goog.inherits(goog.ds.SortedNodeList, goog.ds.BasicNodeList);
+
+
+/**
+ * Add a node to the node list, maintaining sort order.
+ * If the node has a dataName, uses this for the key in the map.
+ *
+ * @param {goog.ds.DataNode} node The node to add.
+ * @override
+ */
+goog.ds.SortedNodeList.prototype.add = function(node) {
+ if (!this.compareFn_) {
+ this.append(node);
+ return;
+ }
+
+ var searchLoc = goog.array.binarySearch(this.list_, node, this.compareFn_);
+
+ // if there is another node that is "equal" according to the comparison
+ // function, insert before that one; otherwise insert at the location
+ // goog.array.binarySearch indicated
+ if (searchLoc < 0) {
+ searchLoc = -(searchLoc + 1);
+ }
+
+ // update any indexes that are after the insertion point
+ for (var index in this.indexMap_) {
+ if (this.indexMap_[index] >= searchLoc) {
+ this.indexMap_[index]++;
+ }
+ }
+
+ goog.array.insertAt(this.list_, node, searchLoc);
+ var dataName = node.getDataName();
+ if (dataName) {
+ this.map_[dataName] = node;
+ this.indexMap_[dataName] = searchLoc;
+ }
+};
+
+
+/**
+ * Adds the given node to the end of the SortedNodeList. This should
+ * only be used when the caller can guarantee that the sort order will
+ * be maintained according to this SortedNodeList's compareFn (e.g.
+ * when initializing a new SortedNodeList from a list of nodes that has
+ * already been sorted).
+ * @param {goog.ds.DataNode} node The node to append.
+ */
+goog.ds.SortedNodeList.prototype.append = function(node) {
+ goog.ds.SortedNodeList.superClass_.add.call(this, node);
+};
+
+
+/**
+ * Sets a node in the list of a given name, maintaining sort order.
+ * @param {string} name Name of the node.
+ * @param {goog.ds.DataNode} node The node.
+ * @override
+ */
+goog.ds.SortedNodeList.prototype.setNode = function(name, node) {
+ if (node == null) {
+ this.removeNode(name);
+ } else {
+ var existingNode = this.indexMap_[name];
+ if (existingNode != null) {
+ if (this.compareFn_) {
+ var compareResult = this.compareFn_(this.list_[existingNode], node);
+ if (compareResult == 0) {
+ // the new node can just replace the old one
+ this.map_[name] = node;
+ this.list_[existingNode] = node;
+ } else {
+ // remove the old node, then add the new one
+ this.removeNode(name);
+ this.add(node);
+ }
+ }
+ } else {
+ this.add(node);
+ }
+ }
+};
+
+
+/**
+ * The character denoting an attribute.
+ * @type {string}
+ */
+goog.ds.STR_ATTRIBUTE_START = '@';
+
+
+/**
+ * The character denoting all children.
+ * @type {string}
+ */
+goog.ds.STR_ALL_CHILDREN_SELECTOR = '*';
+
+
+/**
+ * The wildcard character.
+ * @type {string}
+ */
+goog.ds.STR_WILDCARD = '*';
+
+
+/**
+ * The character denoting path separation.
+ * @type {string}
+ */
+goog.ds.STR_PATH_SEPARATOR = '/';
+
+
+/**
+ * The character denoting the start of an array.
+ * @type {string}
+ */
+goog.ds.STR_ARRAY_START = '[';
+
+
+/**
+ * Shared logger instance for data package
+ * @type {goog.log.Logger}
+ */
+goog.ds.logger = goog.log.getLogger('goog.ds');
+
+
+/**
+ * Create a data node that references another data node,
+ * useful for pointer-like functionality.
+ * All functions will return same values as the original node except for
+ * getDataName()
+ * @param {!goog.ds.DataNode} node The original node.
+ * @param {string} name The new name.
+ * @return {!goog.ds.DataNode} The new data node.
+ */
+goog.ds.Util.makeReferenceNode = function(node, name) {
+ /**
+ * @constructor
+ * @extends {goog.ds.DataNode}
+ * @final
+ */
+ var nodeCreator = function() {};
+ nodeCreator.prototype = node;
+ var newNode = new nodeCreator();
+ newNode.getDataName = function() {
+ return name;
+ };
+ return newNode;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/datasource/expr.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/datasource/expr.js b/externs/GCL/externs/goog/datasource/expr.js
new file mode 100644
index 0000000..c384fd1
--- /dev/null
+++ b/externs/GCL/externs/goog/datasource/expr.js
@@ -0,0 +1,545 @@
+// 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
+ * Expression evaluation utilities. Expression format is very similar to XPath.
+ *
+ * Expression details:
+ * - Of format A/B/C, which will evaluate getChildNode('A').getChildNode('B').
+ * getChildNodes('C')|getChildNodeValue('C')|getChildNode('C') depending on
+ * call
+ * - If expression ends with '/name()', will get the name() of the node
+ * referenced by the preceding path.
+ * - If expression ends with '/count()', will get the count() of the nodes that
+ * match the expression referenced by the preceding path.
+ * - If expression ends with '?', the value is OK to evaluate to null. This is
+ * not enforced by the expression evaluation functions, instead it is
+ * provided as a flag for client code which may ignore depending on usage
+ * - If expression has [INDEX], will use getChildNodes().getByIndex(INDEX)
+ *
+ */
+
+
+goog.provide('goog.ds.Expr');
+
+goog.require('goog.ds.BasicNodeList');
+goog.require('goog.ds.EmptyNodeList');
+goog.require('goog.string');
+
+
+
+/**
+ * Create a new expression. An expression uses a string expression language, and
+ * from this string and a passed in DataNode can evaluate to a value, DataNode,
+ * or a DataNodeList.
+ *
+ * @param {string=} opt_expr The string expression.
+ * @constructor
+ * @final
+ */
+goog.ds.Expr = function(opt_expr) {
+ if (opt_expr) {
+ this.setSource_(opt_expr);
+ }
+};
+
+
+/**
+ * Set the source expression text & parse
+ *
+ * @param {string} expr The string expression source.
+ * @param {Array=} opt_parts Array of the parts of an expression.
+ * @param {goog.ds.Expr=} opt_childExpr Optional child of this expression,
+ * passed in as a hint for processing.
+ * @param {goog.ds.Expr=} opt_prevExpr Optional preceding expression
+ * (i.e. $A/B/C is previous expression to B/C) passed in as a hint for
+ * processing.
+ * @private
+ */
+goog.ds.Expr.prototype.setSource_ = function(expr, opt_parts,
+ opt_childExpr, opt_prevExpr) {
+ this.src_ = expr;
+
+ if (!opt_childExpr && !opt_prevExpr) {
+ // Check whether it can be empty
+ if (goog.string.endsWith(expr, goog.ds.Expr.String_.CAN_BE_EMPTY)) {
+ this.canBeEmpty_ = true;
+ expr = expr.substring(0, expr.length - 1);
+ }
+
+ // Check whether this is an node function
+ if (goog.string.endsWith(expr, '()')) {
+ if (goog.string.endsWith(expr, goog.ds.Expr.String_.NAME_EXPR) ||
+ goog.string.endsWith(expr, goog.ds.Expr.String_.COUNT_EXPR) ||
+ goog.string.endsWith(expr, goog.ds.Expr.String_.POSITION_EXPR)) {
+ var lastPos = expr.lastIndexOf(goog.ds.Expr.String_.SEPARATOR);
+ if (lastPos != -1) {
+ this.exprFn_ = expr.substring(lastPos + 1);
+ expr = expr.substring(0, lastPos);
+ } else {
+ this.exprFn_ = expr;
+ expr = goog.ds.Expr.String_.CURRENT_NODE_EXPR;
+ }
+ if (this.exprFn_ == goog.ds.Expr.String_.COUNT_EXPR) {
+ this.isCount_ = true;
+ }
+ }
+ }
+ }
+
+ // Split into component parts
+ this.parts_ = opt_parts || expr.split('/');
+ this.size_ = this.parts_.length;
+ this.last_ = this.parts_[this.size_ - 1];
+ this.root_ = this.parts_[0];
+
+ if (this.size_ == 1) {
+ this.rootExpr_ = this;
+ this.isAbsolute_ = goog.string.startsWith(expr, '$');
+ } else {
+ this.rootExpr_ = goog.ds.Expr.createInternal_(this.root_, null,
+ this, null);
+ this.isAbsolute_ = this.rootExpr_.isAbsolute_;
+ this.root_ = this.rootExpr_.root_;
+ }
+
+ if (this.size_ == 1 && !this.isAbsolute_) {
+ // Check whether expression maps to current node, for convenience
+ this.isCurrent_ = (expr == goog.ds.Expr.String_.CURRENT_NODE_EXPR ||
+ expr == goog.ds.Expr.String_.EMPTY_EXPR);
+
+ // Whether this expression is just an attribute (i.e. '@foo')
+ this.isJustAttribute_ =
+ goog.string.startsWith(expr, goog.ds.Expr.String_.ATTRIBUTE_START);
+
+ // Check whether this is a common node expression
+ this.isAllChildNodes_ = expr == goog.ds.Expr.String_.ALL_CHILD_NODES_EXPR;
+ this.isAllAttributes_ = expr == goog.ds.Expr.String_.ALL_ATTRIBUTES_EXPR;
+ this.isAllElements_ = expr == goog.ds.Expr.String_.ALL_ELEMENTS_EXPR;
+ }
+};
+
+
+/**
+ * Get the source data path for the expression
+ * @return {string} The path.
+ */
+goog.ds.Expr.prototype.getSource = function() {
+ return this.src_;
+};
+
+
+/**
+ * Gets the last part of the expression.
+ * @return {?string} Last part of the expression.
+ */
+goog.ds.Expr.prototype.getLast = function() {
+ return this.last_;
+};
+
+
+/**
+ * Gets the parent expression of this expression, or null if this is top level
+ * @return {goog.ds.Expr} The parent.
+ */
+goog.ds.Expr.prototype.getParent = function() {
+ if (!this.parentExprSet_) {
+ if (this.size_ > 1) {
+ this.parentExpr_ = goog.ds.Expr.createInternal_(null,
+ this.parts_.slice(0, this.parts_.length - 1), this, null);
+ }
+ this.parentExprSet_ = true;
+ }
+ return this.parentExpr_;
+};
+
+
+/**
+ * Gets the parent expression of this expression, or null if this is top level
+ * @return {goog.ds.Expr} The parent.
+ */
+goog.ds.Expr.prototype.getNext = function() {
+ if (!this.nextExprSet_) {
+ if (this.size_ > 1) {
+ this.nextExpr_ = goog.ds.Expr.createInternal_(null, this.parts_.slice(1),
+ null, this);
+ }
+ this.nextExprSet_ = true;
+ }
+ return this.nextExpr_;
+};
+
+
+/**
+ * Evaluate an expression on a data node, and return a value
+ * Recursively walks through child nodes to evaluate
+ * TODO(user) Support other expression functions
+ *
+ * @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
+ * If not provided, evaluates against DataManager global root.
+ * @return {*} Value of the node, or null if doesn't exist.
+ */
+goog.ds.Expr.prototype.getValue = function(opt_ds) {
+ if (opt_ds == null) {
+ opt_ds = goog.ds.DataManager.getInstance();
+ } else if (this.isAbsolute_) {
+ opt_ds = opt_ds.getDataRoot ? opt_ds.getDataRoot() :
+ goog.ds.DataManager.getInstance();
+ }
+
+ if (this.isCount_) {
+ var nodes = this.getNodes(opt_ds);
+ return nodes.getCount();
+ }
+
+ if (this.size_ == 1) {
+ return opt_ds.getChildNodeValue(this.root_);
+ } else if (this.size_ == 0) {
+ return opt_ds.get();
+ }
+
+ var nextDs = opt_ds.getChildNode(this.root_);
+
+ if (nextDs == null) {
+ return null;
+ } else {
+ return this.getNext().getValue(nextDs);
+ }
+};
+
+
+/**
+ * Evaluate an expression on a data node, and return matching nodes
+ * Recursively walks through child nodes to evaluate
+ *
+ * @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
+ * If not provided, evaluates against data root.
+ * @param {boolean=} opt_canCreate If true, will try to create new nodes.
+ * @return {goog.ds.DataNodeList} Matching nodes.
+ */
+goog.ds.Expr.prototype.getNodes = function(opt_ds, opt_canCreate) {
+ return /** @type {goog.ds.DataNodeList} */(this.getNodes_(opt_ds,
+ false, opt_canCreate));
+};
+
+
+/**
+ * Evaluate an expression on a data node, and return the first matching node
+ * Recursively walks through child nodes to evaluate
+ *
+ * @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
+ * If not provided, evaluates against DataManager global root.
+ * @param {boolean=} opt_canCreate If true, will try to create new nodes.
+ * @return {goog.ds.DataNode} Matching nodes, or null if doesn't exist.
+ */
+goog.ds.Expr.prototype.getNode = function(opt_ds, opt_canCreate) {
+ return /** @type {goog.ds.DataNode} */(this.getNodes_(opt_ds,
+ true, opt_canCreate));
+};
+
+
+/**
+ * Evaluate an expression on a data node, and return the first matching node
+ * Recursively walks through child nodes to evaluate
+ *
+ * @param {goog.ds.DataNode=} opt_ds Optional datasource to evaluate against.
+ * If not provided, evaluates against DataManager global root.
+ * @param {boolean=} opt_selectOne Whether to return single matching DataNode
+ * or matching nodes in DataNodeList.
+ * @param {boolean=} opt_canCreate If true, will try to create new nodes.
+ * @return {goog.ds.DataNode|goog.ds.DataNodeList} Matching node or nodes,
+ * depending on value of opt_selectOne.
+ * @private
+ */
+goog.ds.Expr.prototype.getNodes_ = function(opt_ds, opt_selectOne,
+ opt_canCreate) {
+ if (opt_ds == null) {
+ opt_ds = goog.ds.DataManager.getInstance();
+ } else if (this.isAbsolute_) {
+ opt_ds = opt_ds.getDataRoot ? opt_ds.getDataRoot() :
+ goog.ds.DataManager.getInstance();
+ }
+
+ if (this.size_ == 0 && opt_selectOne) {
+ return opt_ds;
+ } else if (this.size_ == 0 && !opt_selectOne) {
+ return new goog.ds.BasicNodeList([opt_ds]);
+ } else if (this.size_ == 1) {
+ if (opt_selectOne) {
+ return opt_ds.getChildNode(this.root_, opt_canCreate);
+ }
+ else {
+ var possibleListChild = opt_ds.getChildNode(this.root_);
+ if (possibleListChild && possibleListChild.isList()) {
+ return possibleListChild.getChildNodes();
+ } else {
+ return opt_ds.getChildNodes(this.root_);
+ }
+ }
+ } else {
+ var nextDs = opt_ds.getChildNode(this.root_, opt_canCreate);
+ if (nextDs == null && opt_selectOne) {
+ return null;
+ } else if (nextDs == null && !opt_selectOne) {
+ return new goog.ds.EmptyNodeList();
+ }
+ return this.getNext().getNodes_(nextDs, opt_selectOne, opt_canCreate);
+ }
+};
+
+
+/**
+ * Whether the expression can be null.
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.ds.Expr.prototype.canBeEmpty_ = false;
+
+
+/**
+ * The parsed paths in the expression
+ *
+ * @type {Array<string>}
+ * @private
+ */
+goog.ds.Expr.prototype.parts_ = [];
+
+
+/**
+ * Number of paths in the expression
+ *
+ * @type {?number}
+ * @private
+ */
+goog.ds.Expr.prototype.size_ = null;
+
+
+/**
+ * The root node path in the expression
+ *
+ * @type {string}
+ * @private
+ */
+goog.ds.Expr.prototype.root_;
+
+
+/**
+ * The last path in the expression
+ *
+ * @type {?string}
+ * @private
+ */
+goog.ds.Expr.prototype.last_ = null;
+
+
+/**
+ * Whether the expression evaluates to current node
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.ds.Expr.prototype.isCurrent_ = false;
+
+
+/**
+ * Whether the expression is just an attribute
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.ds.Expr.prototype.isJustAttribute_ = false;
+
+
+/**
+ * Does this expression select all DOM-style child nodes (element and text)
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.ds.Expr.prototype.isAllChildNodes_ = false;
+
+
+/**
+ * Does this expression select all DOM-style attribute nodes (starts with '@')
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.ds.Expr.prototype.isAllAttributes_ = false;
+
+
+/**
+ * Does this expression select all DOM-style element child nodes
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.ds.Expr.prototype.isAllElements_ = false;
+
+
+/**
+ * The function used by this expression
+ *
+ * @type {?string}
+ * @private
+ */
+goog.ds.Expr.prototype.exprFn_ = null;
+
+
+/**
+ * Cached value for the parent expression.
+ * @type {goog.ds.Expr?}
+ * @private
+ */
+goog.ds.Expr.prototype.parentExpr_ = null;
+
+
+/**
+ * Cached value for the next expression.
+ * @type {goog.ds.Expr?}
+ * @private
+ */
+goog.ds.Expr.prototype.nextExpr_ = null;
+
+
+/**
+ * Create an expression from a string, can use cached values
+ *
+ * @param {string} expr The expression string.
+ * @return {goog.ds.Expr} The expression object.
+ */
+goog.ds.Expr.create = function(expr) {
+ var result = goog.ds.Expr.cache_[expr];
+
+ if (result == null) {
+ result = new goog.ds.Expr(expr);
+ goog.ds.Expr.cache_[expr] = result;
+ }
+ return result;
+};
+
+
+/**
+ * Create an expression from a string, can use cached values
+ * Uses hints from related expressions to help in creation
+ *
+ * @param {?string=} opt_expr The string expression source.
+ * @param {Array=} opt_parts Array of the parts of an expression.
+ * @param {goog.ds.Expr=} opt_childExpr Optional child of this expression,
+ * passed in as a hint for processing.
+ * @param {goog.ds.Expr=} opt_prevExpr Optional preceding expression
+ * (i.e. $A/B/C is previous expression to B/C) passed in as a hint for
+ * processing.
+ * @return {goog.ds.Expr} The expression object.
+ * @private
+ */
+goog.ds.Expr.createInternal_ = function(opt_expr, opt_parts, opt_childExpr,
+ opt_prevExpr) {
+ var expr = opt_expr || opt_parts.join('/');
+ var result = goog.ds.Expr.cache_[expr];
+
+ if (result == null) {
+ result = new goog.ds.Expr();
+ result.setSource_(expr, opt_parts, opt_childExpr, opt_prevExpr);
+ goog.ds.Expr.cache_[expr] = result;
+ }
+ return result;
+};
+
+
+/**
+ * Cache of pre-parsed expressions
+ * @private
+ */
+goog.ds.Expr.cache_ = {};
+
+
+/**
+ * Commonly used strings in expressions.
+ * @enum {string}
+ * @private
+ */
+goog.ds.Expr.String_ = {
+ SEPARATOR: '/',
+ CURRENT_NODE_EXPR: '.',
+ EMPTY_EXPR: '',
+ ATTRIBUTE_START: '@',
+ ALL_CHILD_NODES_EXPR: '*|text()',
+ ALL_ATTRIBUTES_EXPR: '@*',
+ ALL_ELEMENTS_EXPR: '*',
+ NAME_EXPR: 'name()',
+ COUNT_EXPR: 'count()',
+ POSITION_EXPR: 'position()',
+ INDEX_START: '[',
+ INDEX_END: ']',
+ CAN_BE_EMPTY: '?'
+};
+
+
+/**
+ * Standard expressions
+ */
+
+
+/**
+ * The current node
+ */
+goog.ds.Expr.CURRENT = goog.ds.Expr.create(
+ goog.ds.Expr.String_.CURRENT_NODE_EXPR);
+
+
+/**
+ * For DOM interop - all DOM child nodes (text + element).
+ * Text nodes have dataName #text
+ */
+goog.ds.Expr.ALL_CHILD_NODES =
+ goog.ds.Expr.create(goog.ds.Expr.String_.ALL_CHILD_NODES_EXPR);
+
+
+/**
+ * For DOM interop - all DOM element child nodes
+ */
+goog.ds.Expr.ALL_ELEMENTS =
+ goog.ds.Expr.create(goog.ds.Expr.String_.ALL_ELEMENTS_EXPR);
+
+
+/**
+ * For DOM interop - all DOM attribute nodes
+ * Attribute nodes have dataName starting with "@"
+ */
+goog.ds.Expr.ALL_ATTRIBUTES =
+ goog.ds.Expr.create(goog.ds.Expr.String_.ALL_ATTRIBUTES_EXPR);
+
+
+/**
+ * Get the dataName of a node
+ */
+goog.ds.Expr.NAME = goog.ds.Expr.create(goog.ds.Expr.String_.NAME_EXPR);
+
+
+/**
+ * Get the count of nodes matching an expression
+ */
+goog.ds.Expr.COUNT = goog.ds.Expr.create(goog.ds.Expr.String_.COUNT_EXPR);
+
+
+/**
+ * Get the position of the "current" node in the current node list
+ * This will only apply for datasources that support the concept of a current
+ * node (none exist yet). This is similar to XPath position() and concept of
+ * current node
+ */
+goog.ds.Expr.POSITION = goog.ds.Expr.create(goog.ds.Expr.String_.POSITION_EXPR);
[05/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/charpickerdata.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/charpickerdata.js b/externs/GCL/externs/goog/i18n/charpickerdata.js
new file mode 100644
index 0000000..edb6b26
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/charpickerdata.js
@@ -0,0 +1,3666 @@
+// 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 Character lists and their classifications used by character
+ * picker widget. Autogenerated from Unicode data:
+ * https://sites/cibu/character-picker.
+ */
+
+goog.provide('goog.i18n.CharPickerData');
+
+
+
+/**
+ * Object holding two level character organization and character listing.
+ * @constructor
+ */
+goog.i18n.CharPickerData = function() {};
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SYMBOL = goog.getMsg('Symbol');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ARROWS = goog.getMsg('Arrows');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BRAILLE = goog.getMsg('Braille');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CONTROL_PICTURES =
+ goog.getMsg('Control Pictures');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CURRENCY = goog.getMsg('Currency');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_EMOTICONS = goog.getMsg('Emoticons');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GAME_PIECES = goog.getMsg('Game Pieces');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GENDER_AND_GENEALOGICAL =
+ goog.getMsg('Gender and Genealogical');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GEOMETRIC_SHAPES =
+ goog.getMsg('Geometric Shapes');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_KEYBOARD_AND_UI =
+ goog.getMsg('Keyboard and UI');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LATIN_1_SUPPLEMENT =
+ goog.getMsg('Latin 1 Supplement');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MATH = goog.getMsg('Math');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MATH_ALPHANUMERIC =
+ goog.getMsg('Math Alphanumeric');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MISCELLANEOUS = goog.getMsg('Miscellaneous');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MUSICAL = goog.getMsg('Musical');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_STARS_ASTERISKS =
+ goog.getMsg('Stars/Asterisks');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SUBSCRIPT = goog.getMsg('Subscript');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SUPERSCRIPT = goog.getMsg('Superscript');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TECHNICAL = goog.getMsg('Technical');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TRANSPORT_AND_MAP =
+ goog.getMsg('Transport And Map');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_WEATHER_AND_ASTROLOGICAL =
+ goog.getMsg('Weather and Astrological');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_YIJING_TAI_XUAN_JING =
+ goog.getMsg('Yijing / Tai Xuan Jing');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HISTORIC = goog.getMsg('Historic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY = goog.getMsg('Compatibility');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_EMOJI = goog.getMsg('Emoji');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_PEOPLE_AND_EMOTIONS =
+ goog.getMsg('People and Emotions');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ANIMALS_PLANTS_AND_FOOD =
+ goog.getMsg('Animals, Plants and Food');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OBJECTS = goog.getMsg('Objects');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SPORTS_CELEBRATIONS_AND_ACTIVITIES =
+ goog.getMsg('Sports, Celebrations and Activities');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TRANSPORT_MAPS_AND_SIGNAGE =
+ goog.getMsg('Transport, Maps and Signage');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_WEATHER_SCENES_AND_ZODIAC_SIGNS =
+ goog.getMsg('Weather, Scenes and Zodiac signs');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ENCLOSED = goog.getMsg('Enclosed');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MARKS = goog.getMsg('Marks');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SYMBOLS = goog.getMsg('Symbols');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_PUNCTUATION = goog.getMsg('Punctuation');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ASCII_BASED = goog.getMsg('ASCII Based');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_DASH_CONNECTOR = goog.getMsg('Dash/Connector');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OTHER = goog.getMsg('Other');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_PAIRED = goog.getMsg('Paired');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_NUMBER = goog.getMsg('Number');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_DECIMAL = goog.getMsg('Decimal');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ENCLOSED_DOTTED =
+ goog.getMsg('Enclosed/Dotted');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_FRACTIONS_RELATED =
+ goog.getMsg('Fractions/Related');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_FORMAT_WHITESPACE =
+ goog.getMsg('Format & Whitespace');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_FORMAT = goog.getMsg('Format');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_VARIATION_SELECTOR =
+ goog.getMsg('Variation Selector');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_WHITESPACE = goog.getMsg('Whitespace');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MODIFIER = goog.getMsg('Modifier');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ENCLOSING = goog.getMsg('Enclosing');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_NONSPACING = goog.getMsg('Nonspacing');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SPACING = goog.getMsg('Spacing');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LATIN = goog.getMsg('Latin');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_COMMON = goog.getMsg('Common');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_FLIPPED_MIRRORED =
+ goog.getMsg('Flipped/Mirrored');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_PHONETICS_IPA = goog.getMsg('Phonetics (IPA)');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_PHONETICS_X_IPA =
+ goog.getMsg('Phonetics (X-IPA)');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OTHER_EUROPEAN_SCRIPTS =
+ goog.getMsg('Other European Scripts');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ARMENIAN = goog.getMsg('Armenian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CYRILLIC = goog.getMsg('Cyrillic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GEORGIAN = goog.getMsg('Georgian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GREEK = goog.getMsg('Greek');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CYPRIOT = goog.getMsg('Cypriot');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GLAGOLITIC = goog.getMsg('Glagolitic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GOTHIC = goog.getMsg('Gothic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LINEAR_B = goog.getMsg('Linear B');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OGHAM = goog.getMsg('Ogham');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OLD_ITALIC = goog.getMsg('Old Italic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_RUNIC = goog.getMsg('Runic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SHAVIAN = goog.getMsg('Shavian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_AMERICAN_SCRIPTS =
+ goog.getMsg('American Scripts');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CANADIAN_ABORIGINAL =
+ goog.getMsg('Canadian Aboriginal');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CHEROKEE = goog.getMsg('Cherokee');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_DESERET = goog.getMsg('Deseret');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_AFRICAN_SCRIPTS =
+ goog.getMsg('African Scripts');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_EGYPTIAN_HIEROGLYPHS =
+ goog.getMsg('Egyptian Hieroglyphs');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ETHIOPIC = goog.getMsg('Ethiopic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MEROITIC_CURSIVE =
+ goog.getMsg('Meroitic Cursive');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MEROITIC_HIEROGLYPHS =
+ goog.getMsg('Meroitic Hieroglyphs');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_NKO = goog.getMsg('Nko');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TIFINAGH = goog.getMsg('Tifinagh');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_VAI = goog.getMsg('Vai');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BAMUM = goog.getMsg('Bamum');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_COPTIC = goog.getMsg('Coptic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OSMANYA = goog.getMsg('Osmanya');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MIDDLE_EASTERN_SCRIPTS =
+ goog.getMsg('Middle Eastern Scripts');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ARABIC = goog.getMsg('Arabic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HEBREW = goog.getMsg('Hebrew');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_IMPERIAL_ARAMAIC =
+ goog.getMsg('Imperial Aramaic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_INSCRIPTIONAL_PAHLAVI =
+ goog.getMsg('Inscriptional Pahlavi');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_INSCRIPTIONAL_PARTHIAN =
+ goog.getMsg('Inscriptional Parthian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MANDAIC = goog.getMsg('Mandaic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OLD_SOUTH_ARABIAN =
+ goog.getMsg('Old South Arabian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SAMARITAN = goog.getMsg('Samaritan');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SYRIAC = goog.getMsg('Syriac');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_AVESTAN = goog.getMsg('Avestan');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CARIAN = goog.getMsg('Carian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CUNEIFORM = goog.getMsg('Cuneiform');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LYCIAN = goog.getMsg('Lycian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LYDIAN = goog.getMsg('Lydian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OLD_PERSIAN = goog.getMsg('Old Persian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_PHOENICIAN = goog.getMsg('Phoenician');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_UGARITIC = goog.getMsg('Ugaritic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SOUTH_ASIAN_SCRIPTS =
+ goog.getMsg('South Asian Scripts');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BENGALI = goog.getMsg('Bengali');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CHAKMA = goog.getMsg('Chakma');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_DEVANAGARI = goog.getMsg('Devanagari');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GUJARATI = goog.getMsg('Gujarati');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_GURMUKHI = goog.getMsg('Gurmukhi');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_KANNADA = goog.getMsg('Kannada');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LEPCHA = goog.getMsg('Lepcha');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LIMBU = goog.getMsg('Limbu');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MALAYALAM = goog.getMsg('Malayalam');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MEETEI_MAYEK = goog.getMsg('Meetei Mayek');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OL_CHIKI = goog.getMsg('Ol Chiki');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_ORIYA = goog.getMsg('Oriya');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SAURASHTRA = goog.getMsg('Saurashtra');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SINHALA = goog.getMsg('Sinhala');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SORA_SOMPENG = goog.getMsg('Sora Sompeng');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TAMIL = goog.getMsg('Tamil');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TELUGU = goog.getMsg('Telugu');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_THAANA = goog.getMsg('Thaana');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TIBETAN = goog.getMsg('Tibetan');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BRAHMI = goog.getMsg('Brahmi');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_KAITHI = goog.getMsg('Kaithi');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_KHAROSHTHI = goog.getMsg('Kharoshthi');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SHARADA = goog.getMsg('Sharada');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SYLOTI_NAGRI = goog.getMsg('Syloti Nagri');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TAKRI = goog.getMsg('Takri');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SOUTHEAST_ASIAN_SCRIPTS =
+ goog.getMsg('Southeast Asian Scripts');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BALINESE = goog.getMsg('Balinese');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BATAK = goog.getMsg('Batak');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CHAM = goog.getMsg('Cham');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_JAVANESE = goog.getMsg('Javanese');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_KAYAH_LI = goog.getMsg('Kayah Li');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_KHMER = goog.getMsg('Khmer');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LAO = goog.getMsg('Lao');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MYANMAR = goog.getMsg('Myanmar');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_NEW_TAI_LUE = goog.getMsg('New Tai Lue');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TAI_LE = goog.getMsg('Tai Le');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TAI_THAM = goog.getMsg('Tai Tham');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TAI_VIET = goog.getMsg('Tai Viet');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_THAI = goog.getMsg('Thai');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BUGINESE = goog.getMsg('Buginese');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BUHID = goog.getMsg('Buhid');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HANUNOO = goog.getMsg('Hanunoo');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_REJANG = goog.getMsg('Rejang');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_SUNDANESE = goog.getMsg('Sundanese');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TAGALOG = goog.getMsg('Tagalog');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_TAGBANWA = goog.getMsg('Tagbanwa');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HANGUL = goog.getMsg('Hangul');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OTHER_EAST_ASIAN_SCRIPTS =
+ goog.getMsg('Other East Asian Scripts');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_BOPOMOFO = goog.getMsg('Bopomofo');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HIRAGANA = goog.getMsg('Hiragana');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_KATAKANA = goog.getMsg('Katakana');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LISU = goog.getMsg('Lisu');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MIAO = goog.getMsg('Miao');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_MONGOLIAN = goog.getMsg('Mongolian');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_OLD_TURKIC = goog.getMsg('Old Turkic');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_PHAGS_PA = goog.getMsg('Phags Pa');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_YI = goog.getMsg('Yi');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_1_STROKE_RADICALS =
+ goog.getMsg('Han 1-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_LESS_COMMON = goog.getMsg('Less Common');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_2_STROKE_RADICALS =
+ goog.getMsg('Han 2-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_3_STROKE_RADICALS =
+ goog.getMsg('Han 3-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_4_STROKE_RADICALS =
+ goog.getMsg('Han 4-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_5_STROKE_RADICALS =
+ goog.getMsg('Han 5-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_6_STROKE_RADICALS =
+ goog.getMsg('Han 6-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_7_STROKE_RADICALS =
+ goog.getMsg('Han 7-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_8_STROKE_RADICALS =
+ goog.getMsg('Han 8-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_9_STROKE_RADICALS =
+ goog.getMsg('Han 9-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_10_STROKE_RADICALS =
+ goog.getMsg('Han 10-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_11_17_STROKE_RADICALS =
+ goog.getMsg('Han 11..17-Stroke Radicals');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_HAN_OTHER = goog.getMsg('Han - Other');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_CJK_STROKES = goog.getMsg('CJK Strokes');
+
+
+/**
+ * @desc Name for a symbol or character category. Used in a pull-down list
+ * shown to a document editing user trying to insert a special character.
+ * Newlines are not allowed; translation should be a noun and as consise as
+ * possible. More details:
+ * docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
+ * @type {string}
+ */
+goog.i18n.CharPickerData.MSG_CP_IDEOGRAPHIC_DESCRIPTION =
+ goog.getMsg('Ideographic Description');
+
+
+/**
+ * Top catagory names of character organization.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.prototype.categories = [
+ goog.i18n.CharPickerData.MSG_CP_SYMBOL,
+ goog.i18n.CharPickerData.MSG_CP_EMOJI,
+ goog.i18n.CharPickerData.MSG_CP_PUNCTUATION,
+ goog.i18n.CharPickerData.MSG_CP_NUMBER,
+ goog.i18n.CharPickerData.MSG_CP_FORMAT_WHITESPACE,
+ goog.i18n.CharPickerData.MSG_CP_MODIFIER,
+ goog.i18n.CharPickerData.MSG_CP_LATIN,
+ goog.i18n.CharPickerData.MSG_CP_OTHER_EUROPEAN_SCRIPTS,
+ goog.i18n.CharPickerData.MSG_CP_AMERICAN_SCRIPTS,
+ goog.i18n.CharPickerData.MSG_CP_AFRICAN_SCRIPTS,
+ goog.i18n.CharPickerData.MSG_CP_MIDDLE_EASTERN_SCRIPTS,
+ goog.i18n.CharPickerData.MSG_CP_SOUTH_ASIAN_SCRIPTS,
+ goog.i18n.CharPickerData.MSG_CP_SOUTHEAST_ASIAN_SCRIPTS,
+ goog.i18n.CharPickerData.MSG_CP_HANGUL,
+ goog.i18n.CharPickerData.MSG_CP_OTHER_EAST_ASIAN_SCRIPTS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_1_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_2_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_3_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_4_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_5_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_6_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_7_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_8_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_9_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_10_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_11_17_STROKE_RADICALS,
+ goog.i18n.CharPickerData.MSG_CP_HAN_OTHER
+];
+
+
+/**
+ * Names of subcategories. Each message this array is the
+ * name for the corresponding subcategory specified in
+ * {@code goog.i18n.CharPickerData.subcategories}.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_SYMBOL = [
+ goog.i18n.CharPickerData.MSG_CP_ARROWS,
+ goog.i18n.CharPickerData.MSG_CP_BRAILLE,
+ goog.i18n.CharPickerData.MSG_CP_CONTROL_PICTURES,
+ goog.i18n.CharPickerData.MSG_CP_CURRENCY,
+ goog.i18n.CharPickerData.MSG_CP_EMOTICONS,
+ goog.i18n.CharPickerData.MSG_CP_GAME_PIECES,
+ goog.i18n.CharPickerData.MSG_CP_GENDER_AND_GENEALOGICAL,
+ goog.i18n.CharPickerData.MSG_CP_GEOMETRIC_SHAPES,
+ goog.i18n.CharPickerData.MSG_CP_KEYBOARD_AND_UI,
+ goog.i18n.CharPickerData.MSG_CP_LATIN_1_SUPPLEMENT,
+ goog.i18n.CharPickerData.MSG_CP_MATH,
+ goog.i18n.CharPickerData.MSG_CP_MATH_ALPHANUMERIC,
+ goog.i18n.CharPickerData.MSG_CP_MISCELLANEOUS,
+ goog.i18n.CharPickerData.MSG_CP_MUSICAL,
+ goog.i18n.CharPickerData.MSG_CP_STARS_ASTERISKS,
+ goog.i18n.CharPickerData.MSG_CP_SUBSCRIPT,
+ goog.i18n.CharPickerData.MSG_CP_SUPERSCRIPT,
+ goog.i18n.CharPickerData.MSG_CP_TECHNICAL,
+ goog.i18n.CharPickerData.MSG_CP_TRANSPORT_AND_MAP,
+ goog.i18n.CharPickerData.MSG_CP_WEATHER_AND_ASTROLOGICAL,
+ goog.i18n.CharPickerData.MSG_CP_YIJING_TAI_XUAN_JING,
+ goog.i18n.CharPickerData.MSG_CP_HISTORIC,
+ goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
+];
+
+
+/**
+ * List of characters in base88 encoding scheme. Each base88 encoded
+ * charater string represents corresponding subcategory specified in
+ * {@code goog.i18n.CharPickerData.subcategories}. Encoding
+ * scheme is described in {@code goog.i18n.CharListDecompressor}.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.CHARLIST_OF_SYMBOL = [
+ '2>807AnTMm6e6HDk%`O728F1f4V1PNF2WF1G}58?]514M]Ol1%2l2^3X1U:1Un2Mb>$0MD-(068k11I3706:%MwiZ06',
+ ';oA0FN',
+ '(j90d3',
+ 'H3XBMQQ10HB(2106uPM]N:qol202S20t2^.Z0^xM0:91E]J6O6',
+ ';(i1-5W?',
+ 'Q6A06f5#1H2,]4MeEY[W1@3W}891N1GF1GN18N1P%k',
+ '2JA0sOc',
+ 'oG90nMcPTFNfFEQE10t2H3kQ7X1sj>$0OW6*F%E',
+ '(P90UGv771.Uv46%7Y^Y1F2mc]1M+<Z1',
+ '9FP1',
+ ':3f1En5894WX3:2v+]lEQ?60f2E11OH1P1M]1U11UfCf111MuUmH6Ue6WGGu:26G8:2NO$M:16H8%2V28H211cvg.]4s9AnU#5PNdkX4-1Gc24P1P2:2P2:2P2:2P2:2P2g>50M8V2868G8,8M88mW888E868G8888868GM8k8M8M88,8d1eE8U8d1%46bf$0:;c8%Ef1Ev2:28]BmMbp)02p8071WO6WUw+w0',
+ '9G6e:-EGX26G6(k70Ocm,]AWG,8OUmOO68E86uMeU^`Q1t78V686GG6GM8|88k8-58MGs8k8d28M8U8Ok8-UGF28F28#28F28#28F28#28F28#28F28sGd4rLS1H1',
+ '1FGW8I(90EHB686WU8l1$Uv4?8En1E8|:29168U8718k8kG8M868688686e686888,148MO8|8E]7wV10k2tN1cYf806813692W]3%68X2f2|O6G86%1P5m6%5$6%468e[E8c11126v1MH2|%F9DuM8E86m8UTN%065j#0M',
+ ';DA0k2mO1NM[d3GV5eEms$6ut2WN493@5OA;80sD790UOc$sGk%2MfDE',
+ ';OA0v5-3g510E^jW1WV1:l',
+ 'Qq80N1871QC30',
+ 'XFu6e6^X80O?vE82+Y16T+g1Ug2709+H12F30QjW0PC6',
+ 'gM90sW#1G6$l7H1!%2N2O?ml1]6?',
+ 'g?i1N6',
+ 'Q4A0F1mv3}1v8,uUe^zX171',
+ 'w8A0sf7c2WA0#5A>E1-7',
+ 'I{)0%4!P7|%4}3A,$0dA',
+ '(PD0M(ZU16H1-3e!u6'
+];
+
+
+/**
+ * Names of subcategories. Each message this array is the
+ * name for the corresponding subcategory specified in
+ * {@code goog.i18n.CharPickerData.subcategories}.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_EMOJI = [
+ goog.i18n.CharPickerData.MSG_CP_PEOPLE_AND_EMOTIONS,
+ goog.i18n.CharPickerData.MSG_CP_ANIMALS_PLANTS_AND_FOOD,
+ goog.i18n.CharPickerData.MSG_CP_OBJECTS,
+ goog.i18n.CharPickerData.MSG_CP_SPORTS_CELEBRATIONS_AND_ACTIVITIES,
+ goog.i18n.CharPickerData.MSG_CP_TRANSPORT_MAPS_AND_SIGNAGE,
+ goog.i18n.CharPickerData.MSG_CP_WEATHER_SCENES_AND_ZODIAC_SIGNS,
+ goog.i18n.CharPickerData.MSG_CP_ENCLOSED,
+ goog.i18n.CharPickerData.MSG_CP_MARKS,
+ goog.i18n.CharPickerData.MSG_CP_SYMBOLS
+];
+
+
+/**
+ * List of characters in base88 encoding scheme. Each base88 encoded
+ * charater string represents corresponding subcategory specified in
+ * {@code goog.i18n.CharPickerData.subcategories}. Encoding
+ * scheme is described in {@code goog.i18n.CharListDecompressor}.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.CHARLIST_OF_EMOJI = [
+ '^6A0n2:IE]7Y>X18N1%1-28EOO8871G|%U-5W?',
+ 'I6A0A_X1c8N6eXBt5',
+ ';O906PJG]m1C1Amew)X16:It1]2W68E8X168[8d68MP171P1!1372',
+ '2DA0s%76o]W1@3nAN1GF1GN18N1Xzd191N38U9I',
+ '(DA0v1O]2694t1m72$2>X1d1%DvXUvBN6',
+ 'Q4A0F1mv4|HAUe98(rX1@2]k',
+ 'Y#90;v308ICU1d2W-3H9EH1-3e!u6',
+ ';5A09M9188:48WE8n5EH2',
+ 'Y%C0(wV1P7N3[EP1M'
+];
+
+
+/**
+ * Names of subcategories. Each message this array is the
+ * name for the corresponding subcategory specified in
+ * {@code goog.i18n.CharPickerData.subcategories}.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_PUNCTUATION = [
+ goog.i18n.CharPickerData.MSG_CP_ASCII_BASED,
+ goog.i18n.CharPickerData.MSG_CP_DASH_CONNECTOR,
+ goog.i18n.CharPickerData.MSG_CP_OTHER,
+ goog.i18n.CharPickerData.MSG_CP_PAIRED,
+ goog.i18n.CharPickerData.MSG_CP_HISTORIC,
+ goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
+];
+
+
+/**
+ * List of characters in base88 encoding scheme. Each base88 encoded
+ * charater string represents corresponding subcategory specified in
+ * {@code goog.i18n.CharPickerData.subcategories}. Encoding
+ * scheme is described in {@code goog.i18n.CharListDecompressor}.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.CHARLIST_OF_PUNCTUATION = [
+ ':2M8EG886[6O6f2H6eP16u',
+ '14f4gX80c%36%1gu30:26Q3t0XG',
+ '(s70:<.MOEmEGGG8OEms88Iu3068G6n1!',
+ 'n36f48v2894X1;P80sP26[6]46P16nvMPF6f3c1^F1H76:2,va@1%5M]26;7106G,fh,Gs2Ms06nPcXF6f48v288686',
+ 'gm808kQT30MnN72v1U8U(%t0Eb(t0',
+ 'Ig80e91E91686W8$EH1X36P162pw0,12-1G|8F18W86nDE8c8M[6O6X2E8f2886'
+];
+
+
+/**
+ * Names of subcategories. Each message this array is the
+ * name for the corresponding subcategory specified in
+ * {@code goog.i18n.CharPickerData.subcategories}.
+ * @type {!Array<string>}
+ */
+goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_NUMBER = [
+ goog.i18n.CharPickerData.MSG_CP_DECIMAL,
+ goog.i18n.CharPickerData.MSG_CP_ENCLOSED_DOTTED,
+ goog.i18n.CharPickerData.MSG_CP_FRACTIONS_RELATED,
+ goog.i18n.CharPickerData.MSG_CP_OTHER,
+ goog.i18n.CharPickerData.MSG_CP_HISTORIC,
+ goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
+];
+
+
+/**
+ *
<TRUNCATED>
[19/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/browserevent.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/browserevent.js b/externs/GCL/externs/goog/events/browserevent.js
new file mode 100644
index 0000000..f0773ce
--- /dev/null
+++ b/externs/GCL/externs/goog/events/browserevent.js
@@ -0,0 +1,386 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A patched, standardized event object for browser events.
+ *
+ * <pre>
+ * The patched event object contains the following members:
+ * - type {string} Event type, e.g. 'click'
+ * - target {Object} The element that actually triggered the event
+ * - currentTarget {Object} The element the listener is attached to
+ * - relatedTarget {Object} For mouseover and mouseout, the previous object
+ * - offsetX {number} X-coordinate relative to target
+ * - offsetY {number} Y-coordinate relative to target
+ * - clientX {number} X-coordinate relative to viewport
+ * - clientY {number} Y-coordinate relative to viewport
+ * - screenX {number} X-coordinate relative to the edge of the screen
+ * - screenY {number} Y-coordinate relative to the edge of the screen
+ * - button {number} Mouse button. Use isButton() to test.
+ * - keyCode {number} Key-code
+ * - ctrlKey {boolean} Was ctrl key depressed
+ * - altKey {boolean} Was alt key depressed
+ * - shiftKey {boolean} Was shift key depressed
+ * - metaKey {boolean} Was meta key depressed
+ * - defaultPrevented {boolean} Whether the default action has been prevented
+ * - state {Object} History state object
+ *
+ * NOTE: The keyCode member contains the raw browser keyCode. For normalized
+ * key and character code use {@link goog.events.KeyHandler}.
+ * </pre>
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.events.BrowserEvent');
+goog.provide('goog.events.BrowserEvent.MouseButton');
+
+goog.require('goog.events.BrowserFeature');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventType');
+goog.require('goog.reflect');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Accepts a browser event object and creates a patched, cross browser event
+ * object.
+ * The content of this object will not be initialized if no event object is
+ * provided. If this is the case, init() needs to be invoked separately.
+ * @param {Event=} opt_e Browser event object.
+ * @param {EventTarget=} opt_currentTarget Current target for event.
+ * @constructor
+ * @extends {goog.events.Event}
+ */
+goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
+ goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : '');
+
+ /**
+ * Target that fired the event.
+ * @override
+ * @type {Node}
+ */
+ this.target = null;
+
+ /**
+ * Node that had the listener attached.
+ * @override
+ * @type {Node|undefined}
+ */
+ this.currentTarget = null;
+
+ /**
+ * For mouseover and mouseout events, the related object for the event.
+ * @type {Node}
+ */
+ this.relatedTarget = null;
+
+ /**
+ * X-coordinate relative to target.
+ * @type {number}
+ */
+ this.offsetX = 0;
+
+ /**
+ * Y-coordinate relative to target.
+ * @type {number}
+ */
+ this.offsetY = 0;
+
+ /**
+ * X-coordinate relative to the window.
+ * @type {number}
+ */
+ this.clientX = 0;
+
+ /**
+ * Y-coordinate relative to the window.
+ * @type {number}
+ */
+ this.clientY = 0;
+
+ /**
+ * X-coordinate relative to the monitor.
+ * @type {number}
+ */
+ this.screenX = 0;
+
+ /**
+ * Y-coordinate relative to the monitor.
+ * @type {number}
+ */
+ this.screenY = 0;
+
+ /**
+ * Which mouse button was pressed.
+ * @type {number}
+ */
+ this.button = 0;
+
+ /**
+ * Keycode of key press.
+ * @type {number}
+ */
+ this.keyCode = 0;
+
+ /**
+ * Keycode of key press.
+ * @type {number}
+ */
+ this.charCode = 0;
+
+ /**
+ * Whether control was pressed at time of event.
+ * @type {boolean}
+ */
+ this.ctrlKey = false;
+
+ /**
+ * Whether alt was pressed at time of event.
+ * @type {boolean}
+ */
+ this.altKey = false;
+
+ /**
+ * Whether shift was pressed at time of event.
+ * @type {boolean}
+ */
+ this.shiftKey = false;
+
+ /**
+ * Whether the meta key was pressed at time of event.
+ * @type {boolean}
+ */
+ this.metaKey = false;
+
+ /**
+ * History state object, only set for PopState events where it's a copy of the
+ * state object provided to pushState or replaceState.
+ * @type {Object}
+ */
+ this.state = null;
+
+ /**
+ * Whether the default platform modifier key was pressed at time of event.
+ * (This is control for all platforms except Mac, where it's Meta.)
+ * @type {boolean}
+ */
+ this.platformModifierKey = false;
+
+ /**
+ * The browser event object.
+ * @private {Event}
+ */
+ this.event_ = null;
+
+ if (opt_e) {
+ this.init(opt_e, opt_currentTarget);
+ }
+};
+goog.inherits(goog.events.BrowserEvent, goog.events.Event);
+
+
+/**
+ * Normalized button constants for the mouse.
+ * @enum {number}
+ */
+goog.events.BrowserEvent.MouseButton = {
+ LEFT: 0,
+ MIDDLE: 1,
+ RIGHT: 2
+};
+
+
+/**
+ * Static data for mapping mouse buttons.
+ * @type {!Array<number>}
+ */
+goog.events.BrowserEvent.IEButtonMap = [
+ 1, // LEFT
+ 4, // MIDDLE
+ 2 // RIGHT
+];
+
+
+/**
+ * Accepts a browser event object and creates a patched, cross browser event
+ * object.
+ * @param {Event} e Browser event object.
+ * @param {EventTarget=} opt_currentTarget Current target for event.
+ */
+goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
+ var type = this.type = e.type;
+
+ // TODO(nicksantos): Change this.target to type EventTarget.
+ this.target = /** @type {Node} */ (e.target) || e.srcElement;
+
+ // TODO(nicksantos): Change this.currentTarget to type EventTarget.
+ this.currentTarget = /** @type {Node} */ (opt_currentTarget);
+
+ var relatedTarget = /** @type {Node} */ (e.relatedTarget);
+ if (relatedTarget) {
+ // There's a bug in FireFox where sometimes, relatedTarget will be a
+ // chrome element, and accessing any property of it will get a permission
+ // denied exception. See:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=497780
+ if (goog.userAgent.GECKO) {
+ if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) {
+ relatedTarget = null;
+ }
+ }
+ // TODO(arv): Use goog.events.EventType when it has been refactored into its
+ // own file.
+ } else if (type == goog.events.EventType.MOUSEOVER) {
+ relatedTarget = e.fromElement;
+ } else if (type == goog.events.EventType.MOUSEOUT) {
+ relatedTarget = e.toElement;
+ }
+
+ this.relatedTarget = relatedTarget;
+
+ // Webkit emits a lame warning whenever layerX/layerY is accessed.
+ // http://code.google.com/p/chromium/issues/detail?id=101733
+ this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ?
+ e.offsetX : e.layerX;
+ this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ?
+ e.offsetY : e.layerY;
+
+ this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;
+ this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;
+ this.screenX = e.screenX || 0;
+ this.screenY = e.screenY || 0;
+
+ this.button = e.button;
+
+ this.keyCode = e.keyCode || 0;
+ this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);
+ this.ctrlKey = e.ctrlKey;
+ this.altKey = e.altKey;
+ this.shiftKey = e.shiftKey;
+ this.metaKey = e.metaKey;
+ this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
+ this.state = e.state;
+ this.event_ = e;
+ if (e.defaultPrevented) {
+ this.preventDefault();
+ }
+};
+
+
+/**
+ * Tests to see which button was pressed during the event. This is really only
+ * useful in IE and Gecko browsers. And in IE, it's only useful for
+ * mousedown/mouseup events, because click only fires for the left mouse button.
+ *
+ * Safari 2 only reports the left button being clicked, and uses the value '1'
+ * instead of 0. Opera only reports a mousedown event for the middle button, and
+ * no mouse events for the right button. Opera has default behavior for left and
+ * middle click that can only be overridden via a configuration setting.
+ *
+ * There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html.
+ *
+ * @param {goog.events.BrowserEvent.MouseButton} button The button
+ * to test for.
+ * @return {boolean} True if button was pressed.
+ */
+goog.events.BrowserEvent.prototype.isButton = function(button) {
+ if (!goog.events.BrowserFeature.HAS_W3C_BUTTON) {
+ if (this.type == 'click') {
+ return button == goog.events.BrowserEvent.MouseButton.LEFT;
+ } else {
+ return !!(this.event_.button &
+ goog.events.BrowserEvent.IEButtonMap[button]);
+ }
+ } else {
+ return this.event_.button == button;
+ }
+};
+
+
+/**
+ * Whether this has an "action"-producing mouse button.
+ *
+ * By definition, this includes left-click on windows/linux, and left-click
+ * without the ctrl key on Macs.
+ *
+ * @return {boolean} The result.
+ */
+goog.events.BrowserEvent.prototype.isMouseActionButton = function() {
+ // Webkit does not ctrl+click to be a right-click, so we
+ // normalize it to behave like Gecko and Opera.
+ return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&
+ !(goog.userAgent.WEBKIT && goog.userAgent.MAC && this.ctrlKey);
+};
+
+
+/**
+ * @override
+ */
+goog.events.BrowserEvent.prototype.stopPropagation = function() {
+ goog.events.BrowserEvent.superClass_.stopPropagation.call(this);
+ if (this.event_.stopPropagation) {
+ this.event_.stopPropagation();
+ } else {
+ this.event_.cancelBubble = true;
+ }
+};
+
+
+/**
+ * @override
+ */
+goog.events.BrowserEvent.prototype.preventDefault = function() {
+ goog.events.BrowserEvent.superClass_.preventDefault.call(this);
+ var be = this.event_;
+ if (!be.preventDefault) {
+ be.returnValue = false;
+ if (goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT) {
+ /** @preserveTry */
+ try {
+ // Most keys can be prevented using returnValue. Some special keys
+ // require setting the keyCode to -1 as well:
+ //
+ // In IE7:
+ // F3, F5, F10, F11, Ctrl+P, Crtl+O, Ctrl+F (these are taken from IE6)
+ //
+ // In IE8:
+ // Ctrl+P, Crtl+O, Ctrl+F (F1-F12 cannot be stopped through the event)
+ //
+ // We therefore do this for all function keys as well as when Ctrl key
+ // is pressed.
+ var VK_F1 = 112;
+ var VK_F12 = 123;
+ if (be.ctrlKey || be.keyCode >= VK_F1 && be.keyCode <= VK_F12) {
+ be.keyCode = -1;
+ }
+ } catch (ex) {
+ // IE throws an 'access denied' exception when trying to change
+ // keyCode in some situations (e.g. srcElement is input[type=file],
+ // or srcElement is an anchor tag rewritten by parent's innerHTML).
+ // Do nothing in this case.
+ }
+ }
+ } else {
+ be.preventDefault();
+ }
+};
+
+
+/**
+ * @return {Event} The underlying browser event object.
+ */
+goog.events.BrowserEvent.prototype.getBrowserEvent = function() {
+ return this.event_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/browserfeature3.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/browserfeature3.js b/externs/GCL/externs/goog/events/browserfeature3.js
new file mode 100644
index 0000000..61b9d60
--- /dev/null
+++ b/externs/GCL/externs/goog/events/browserfeature3.js
@@ -0,0 +1,85 @@
+// Copyright 2010 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Browser capability checks for the events package.
+ *
+ */
+
+
+goog.provide('goog.events.BrowserFeature');
+
+goog.require('goog.userAgent');
+
+
+/**
+ * Enum of browser capabilities.
+ * @enum {boolean}
+ */
+goog.events.BrowserFeature = {
+ /**
+ * Whether the button attribute of the event is W3C compliant. False in
+ * Internet Explorer prior to version 9; document-version dependent.
+ */
+ HAS_W3C_BUTTON: !goog.userAgent.IE ||
+ goog.userAgent.isDocumentModeOrHigher(9),
+
+ /**
+ * Whether the browser supports full W3C event model.
+ */
+ HAS_W3C_EVENT_SUPPORT: !goog.userAgent.IE ||
+ goog.userAgent.isDocumentModeOrHigher(9),
+
+ /**
+ * To prevent default in IE7-8 for certain keydown events we need set the
+ * keyCode to -1.
+ */
+ SET_KEY_CODE_TO_PREVENT_DEFAULT: goog.userAgent.IE &&
+ !goog.userAgent.isVersionOrHigher('9'),
+
+ /**
+ * Whether the {@code navigator.onLine} property is supported.
+ */
+ HAS_NAVIGATOR_ONLINE_PROPERTY: !goog.userAgent.WEBKIT ||
+ goog.userAgent.isVersionOrHigher('528'),
+
+ /**
+ * Whether HTML5 network online/offline events are supported.
+ */
+ HAS_HTML5_NETWORK_EVENT_SUPPORT:
+ goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9b') ||
+ goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8') ||
+ goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher('9.5') ||
+ goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('528'),
+
+ /**
+ * Whether HTML5 network events fire on document.body, or otherwise the
+ * window.
+ */
+ HTML5_NETWORK_EVENTS_FIRE_ON_BODY:
+ goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('8') ||
+ goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'),
+
+ /**
+ * Whether touch is enabled in the browser.
+ */
+ TOUCH_ENABLED:
+ ('ontouchstart' in goog.global ||
+ !!(goog.global['document'] &&
+ document.documentElement &&
+ 'ontouchstart' in document.documentElement) ||
+ // IE10 uses non-standard touch events, so it has a different check.
+ !!(goog.global['navigator'] &&
+ goog.global['navigator']['msMaxTouchPoints']))
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/event.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/event.js b/externs/GCL/externs/goog/events/event.js
new file mode 100644
index 0000000..b671289
--- /dev/null
+++ b/externs/GCL/externs/goog/events/event.js
@@ -0,0 +1,143 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A base class for event objects.
+ *
+ */
+
+
+goog.provide('goog.events.Event');
+goog.provide('goog.events.EventLike');
+
+/**
+ * goog.events.Event no longer depends on goog.Disposable. Keep requiring
+ * goog.Disposable here to not break projects which assume this dependency.
+ * @suppress {extraRequire}
+ */
+goog.require('goog.Disposable');
+goog.require('goog.events.EventId');
+
+
+/**
+ * A typedef for event like objects that are dispatchable via the
+ * goog.events.dispatchEvent function. strings are treated as the type for a
+ * goog.events.Event. Objects are treated as an extension of a new
+ * goog.events.Event with the type property of the object being used as the type
+ * of the Event.
+ * @typedef {string|Object|goog.events.Event|goog.events.EventId}
+ */
+goog.events.EventLike;
+
+
+
+/**
+ * A base class for event objects, so that they can support preventDefault and
+ * stopPropagation.
+ *
+ * @param {string|!goog.events.EventId} type Event Type.
+ * @param {Object=} opt_target Reference to the object that is the target of
+ * this event. It has to implement the {@code EventTarget} interface
+ * declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}.
+ * @constructor
+ */
+goog.events.Event = function(type, opt_target) {
+ /**
+ * Event type.
+ * @type {string}
+ */
+ this.type = type instanceof goog.events.EventId ? String(type) : type;
+
+ /**
+ * TODO(tbreisacher): The type should probably be
+ * EventTarget|goog.events.EventTarget.
+ *
+ * Target of the event.
+ * @type {Object|undefined}
+ */
+ this.target = opt_target;
+
+ /**
+ * Object that had the listener attached.
+ * @type {Object|undefined}
+ */
+ this.currentTarget = this.target;
+
+ /**
+ * Whether to cancel the event in internal capture/bubble processing for IE.
+ * @type {boolean}
+ * @public
+ * @suppress {underscore|visibility} Technically public, but referencing this
+ * outside this package is strongly discouraged.
+ */
+ this.propagationStopped_ = false;
+
+ /**
+ * Whether the default action has been prevented.
+ * This is a property to match the W3C specification at
+ * {@link http://www.w3.org/TR/DOM-Level-3-Events/
+ * #events-event-type-defaultPrevented}.
+ * Must be treated as read-only outside the class.
+ * @type {boolean}
+ */
+ this.defaultPrevented = false;
+
+ /**
+ * Return value for in internal capture/bubble processing for IE.
+ * @type {boolean}
+ * @public
+ * @suppress {underscore|visibility} Technically public, but referencing this
+ * outside this package is strongly discouraged.
+ */
+ this.returnValue_ = true;
+};
+
+
+/**
+ * Stops event propagation.
+ */
+goog.events.Event.prototype.stopPropagation = function() {
+ this.propagationStopped_ = true;
+};
+
+
+/**
+ * Prevents the default action, for example a link redirecting to a url.
+ */
+goog.events.Event.prototype.preventDefault = function() {
+ this.defaultPrevented = true;
+ this.returnValue_ = false;
+};
+
+
+/**
+ * Stops the propagation of the event. It is equivalent to
+ * {@code e.stopPropagation()}, but can be used as the callback argument of
+ * {@link goog.events.listen} without declaring another function.
+ * @param {!goog.events.Event} e An event.
+ */
+goog.events.Event.stopPropagation = function(e) {
+ e.stopPropagation();
+};
+
+
+/**
+ * Prevents the default action. It is equivalent to
+ * {@code e.preventDefault()}, but can be used as the callback argument of
+ * {@link goog.events.listen} without declaring another function.
+ * @param {!goog.events.Event} e An event.
+ */
+goog.events.Event.preventDefault = function(e) {
+ e.preventDefault();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventhandler.js b/externs/GCL/externs/goog/events/eventhandler.js
new file mode 100644
index 0000000..16b1ad0
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventhandler.js
@@ -0,0 +1,459 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Class to create objects which want to handle multiple events
+ * and have their listeners easily cleaned up via a dispose method.
+ *
+ * Example:
+ * <pre>
+ * function Something() {
+ * Something.base(this);
+ *
+ * ... set up object ...
+ *
+ * // Add event listeners
+ * this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);
+ * this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);
+ * this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);
+ * this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);
+ * this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);
+ * }
+ * goog.inherits(Something, goog.events.EventHandler);
+ *
+ * Something.prototype.disposeInternal = function() {
+ * Something.base(this, 'disposeInternal');
+ * goog.dom.removeNode(this.container);
+ * };
+ *
+ *
+ * // Then elsewhere:
+ *
+ * var activeSomething = null;
+ * function openSomething() {
+ * activeSomething = new Something();
+ * }
+ *
+ * function closeSomething() {
+ * if (activeSomething) {
+ * activeSomething.dispose(); // Remove event listeners
+ * activeSomething = null;
+ * }
+ * }
+ * </pre>
+ *
+ */
+
+goog.provide('goog.events.EventHandler');
+
+goog.require('goog.Disposable');
+goog.require('goog.events');
+goog.require('goog.object');
+
+goog.forwardDeclare('goog.events.EventWrapper');
+
+
+
+/**
+ * Super class for objects that want to easily manage a number of event
+ * listeners. It allows a short cut to listen and also provides a quick way
+ * to remove all events listeners belonging to this object.
+ * @param {SCOPE=} opt_scope Object in whose scope to call the listeners.
+ * @constructor
+ * @extends {goog.Disposable}
+ * @template SCOPE
+ */
+goog.events.EventHandler = function(opt_scope) {
+ goog.Disposable.call(this);
+ // TODO(mknichel): Rename this to this.scope_ and fix the classes in google3
+ // that access this private variable. :(
+ this.handler_ = opt_scope;
+
+ /**
+ * Keys for events that are being listened to.
+ * @type {!Object<!goog.events.Key>}
+ * @private
+ */
+ this.keys_ = {};
+};
+goog.inherits(goog.events.EventHandler, goog.Disposable);
+
+
+/**
+ * Utility array used to unify the cases of listening for an array of types
+ * and listening for a single event, without using recursion or allocating
+ * an array each time.
+ * @type {!Array<string>}
+ * @const
+ * @private
+ */
+goog.events.EventHandler.typeArray_ = [];
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted then the
+ * EventHandler's handleEvent method will be used.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
+ * opt_fn Optional callback function to be used as the listener or an object
+ * with handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listen = function(
+ src, type, opt_fn, opt_capture) {
+ return this.listen_(src, type, opt_fn, opt_capture);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted then the
+ * EventHandler's handleEvent method will be used.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
+ * null|undefined} fn Optional callback function to be used as the
+ * listener or an object with handleEvent function.
+ * @param {boolean|undefined} capture Optional whether to use capture phase.
+ * @param {T} scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template T,EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listenWithScope = function(
+ src, type, fn, capture, scope) {
+ // TODO(mknichel): Deprecate this function.
+ return this.listen_(src, type, fn, capture, scope);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted then the
+ * EventHandler's handleEvent method will be used.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @param {Object=} opt_scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ * @private
+ */
+goog.events.EventHandler.prototype.listen_ = function(src, type, opt_fn,
+ opt_capture,
+ opt_scope) {
+ if (!goog.isArray(type)) {
+ if (type) {
+ goog.events.EventHandler.typeArray_[0] = type.toString();
+ }
+ type = goog.events.EventHandler.typeArray_;
+ }
+ for (var i = 0; i < type.length; i++) {
+ var listenerObj = goog.events.listen(
+ src, type[i], opt_fn || this.handleEvent,
+ opt_capture || false,
+ opt_scope || this.handler_ || this);
+
+ if (!listenerObj) {
+ // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
+ // (goog.events.CaptureSimulationMode) in IE8-, it will return null
+ // value.
+ return this;
+ }
+
+ var key = listenerObj.key;
+ this.keys_[key] = listenerObj;
+ }
+
+ return this;
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted, then the
+ * EventHandler's handleEvent method will be used. After the event has fired the
+ * event listener is removed from the target. If an array of event types is
+ * provided, each event type will be listened to once.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listenOnce = function(
+ src, type, opt_fn, opt_capture) {
+ return this.listenOnce_(src, type, opt_fn, opt_capture);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted, then the
+ * EventHandler's handleEvent method will be used. After the event has fired the
+ * event listener is removed from the target. If an array of event types is
+ * provided, each event type will be listened to once.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
+ * null|undefined} fn Optional callback function to be used as the
+ * listener or an object with handleEvent function.
+ * @param {boolean|undefined} capture Optional whether to use capture phase.
+ * @param {T} scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template T,EVENTOBJ
+ */
+goog.events.EventHandler.prototype.listenOnceWithScope = function(
+ src, type, fn, capture, scope) {
+ // TODO(mknichel): Deprecate this function.
+ return this.listenOnce_(src, type, fn, capture, scope);
+};
+
+
+/**
+ * Listen to an event on a Listenable. If the function is omitted, then the
+ * EventHandler's handleEvent method will be used. After the event has fired
+ * the event listener is removed from the target. If an array of event types is
+ * provided, each event type will be listened to once.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type to listen for or array of event types.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @param {Object=} opt_scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template EVENTOBJ
+ * @private
+ */
+goog.events.EventHandler.prototype.listenOnce_ = function(
+ src, type, opt_fn, opt_capture, opt_scope) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ this.listenOnce_(src, type[i], opt_fn, opt_capture, opt_scope);
+ }
+ } else {
+ var listenerObj = goog.events.listenOnce(
+ src, type, opt_fn || this.handleEvent, opt_capture,
+ opt_scope || this.handler_ || this);
+ if (!listenerObj) {
+ // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
+ // (goog.events.CaptureSimulationMode) in IE8-, it will return null
+ // value.
+ return this;
+ }
+
+ var key = listenerObj.key;
+ this.keys_[key] = listenerObj;
+ }
+
+ return this;
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.EventTarget}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The node to listen to
+ * events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener
+ * Callback method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ */
+goog.events.EventHandler.prototype.listenWithWrapper = function(
+ src, wrapper, listener, opt_capt) {
+ // TODO(mknichel): Remove the opt_scope from this function and then
+ // templatize it.
+ return this.listenWithWrapper_(src, wrapper, listener, opt_capt);
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.EventTarget}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The node to listen to
+ * events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}
+ * listener Optional callback function to be used as the
+ * listener or an object with handleEvent function.
+ * @param {boolean|undefined} capture Optional whether to use capture phase.
+ * @param {T} scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @template T
+ */
+goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(
+ src, wrapper, listener, capture, scope) {
+ // TODO(mknichel): Deprecate this function.
+ return this.listenWithWrapper_(src, wrapper, listener, capture, scope);
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.EventTarget}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The node to listen to
+ * events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
+ * method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
+ * chaining of calls.
+ * @private
+ */
+goog.events.EventHandler.prototype.listenWithWrapper_ = function(
+ src, wrapper, listener, opt_capt, opt_scope) {
+ wrapper.listen(src, listener, opt_capt, opt_scope || this.handler_ || this,
+ this);
+ return this;
+};
+
+
+/**
+ * @return {number} Number of listeners registered by this handler.
+ */
+goog.events.EventHandler.prototype.getListenerCount = function() {
+ var count = 0;
+ for (var key in this.keys_) {
+ if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {
+ count++;
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Unlistens on an event.
+ * @param {goog.events.ListenableType} src Event source.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types to unlisten to.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
+ * Optional callback function to be used as the listener or an object with
+ * handleEvent function.
+ * @param {boolean=} opt_capture Optional whether to use capture phase.
+ * @param {Object=} opt_scope Object in whose scope to call the listener.
+ * @return {!goog.events.EventHandler} This object, allowing for chaining of
+ * calls.
+ * @template EVENTOBJ
+ */
+goog.events.EventHandler.prototype.unlisten = function(src, type, opt_fn,
+ opt_capture,
+ opt_scope) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ this.unlisten(src, type[i], opt_fn, opt_capture, opt_scope);
+ }
+ } else {
+ var listener = goog.events.getListener(src, type,
+ opt_fn || this.handleEvent,
+ opt_capture, opt_scope || this.handler_ || this);
+
+ if (listener) {
+ goog.events.unlistenByKey(listener);
+ delete this.keys_[listener.key];
+ }
+ }
+
+ return this;
+};
+
+
+/**
+ * Removes an event listener which was added with listenWithWrapper().
+ *
+ * @param {EventTarget|goog.events.EventTarget} src The target to stop
+ * listening to events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to remove.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase of the
+ * event.
+ * @param {Object=} opt_scope Element in whose scope to call the listener.
+ * @return {!goog.events.EventHandler} This object, allowing for chaining of
+ * calls.
+ */
+goog.events.EventHandler.prototype.unlistenWithWrapper = function(src, wrapper,
+ listener, opt_capt, opt_scope) {
+ wrapper.unlisten(src, listener, opt_capt,
+ opt_scope || this.handler_ || this, this);
+ return this;
+};
+
+
+/**
+ * Unlistens to all events.
+ */
+goog.events.EventHandler.prototype.removeAll = function() {
+ goog.object.forEach(this.keys_, goog.events.unlistenByKey);
+ this.keys_ = {};
+};
+
+
+/**
+ * Disposes of this EventHandler and removes all listeners that it registered.
+ * @override
+ * @protected
+ */
+goog.events.EventHandler.prototype.disposeInternal = function() {
+ goog.events.EventHandler.superClass_.disposeInternal.call(this);
+ this.removeAll();
+};
+
+
+/**
+ * Default event handler
+ * @param {goog.events.Event} e Event object.
+ */
+goog.events.EventHandler.prototype.handleEvent = function(e) {
+ throw Error('EventHandler.handleEvent not implemented');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventid.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventid.js b/externs/GCL/externs/goog/events/eventid.js
new file mode 100644
index 0000000..9a4822e
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventid.js
@@ -0,0 +1,47 @@
+// Copyright 2013 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+goog.provide('goog.events.EventId');
+
+
+
+/**
+ * A templated class that is used when registering for events. Typical usage:
+ * <code>
+ * /** @type {goog.events.EventId<MyEventObj>}
+ * var myEventId = new goog.events.EventId(
+ * goog.events.getUniqueId(('someEvent'));
+ *
+ * // No need to cast or declare here since the compiler knows the correct
+ * // type of 'evt' (MyEventObj).
+ * something.listen(myEventId, function(evt) {});
+ * </code>
+ *
+ * @param {string} eventId
+ * @template T
+ * @constructor
+ * @struct
+ * @final
+ */
+goog.events.EventId = function(eventId) {
+ /** @const */ this.id = eventId;
+};
+
+
+/**
+ * @override
+ */
+goog.events.EventId.prototype.toString = function() {
+ return this.id;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/events.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/events.js b/externs/GCL/externs/goog/events/events.js
new file mode 100644
index 0000000..39cc405
--- /dev/null
+++ b/externs/GCL/externs/goog/events/events.js
@@ -0,0 +1,983 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview An event manager for both native browser event
+ * targets and custom JavaScript event targets
+ * ({@code goog.events.Listenable}). This provides an abstraction
+ * over browsers' event systems.
+ *
+ * It also provides a simulation of W3C event model's capture phase in
+ * Internet Explorer (IE 8 and below). Caveat: the simulation does not
+ * interact well with listeners registered directly on the elements
+ * (bypassing goog.events) or even with listeners registered via
+ * goog.events in a separate JS binary. In these cases, we provide
+ * no ordering guarantees.
+ *
+ * The listeners will receive a "patched" event object. Such event object
+ * contains normalized values for certain event properties that differs in
+ * different browsers.
+ *
+ * Example usage:
+ * <pre>
+ * goog.events.listen(myNode, 'click', function(e) { alert('woo') });
+ * goog.events.listen(myNode, 'mouseover', mouseHandler, true);
+ * goog.events.unlisten(myNode, 'mouseover', mouseHandler, true);
+ * goog.events.removeAll(myNode);
+ * </pre>
+ *
+ * in IE and event object patching]
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * @see ../demos/events.html
+ * @see ../demos/event-propagation.html
+ * @see ../demos/stopevent.html
+ */
+
+// IMPLEMENTATION NOTES:
+// goog.events stores an auxiliary data structure on each EventTarget
+// source being listened on. This allows us to take advantage of GC,
+// having the data structure GC'd when the EventTarget is GC'd. This
+// GC behavior is equivalent to using W3C DOM Events directly.
+
+goog.provide('goog.events');
+goog.provide('goog.events.CaptureSimulationMode');
+goog.provide('goog.events.Key');
+goog.provide('goog.events.ListenableType');
+
+goog.require('goog.asserts');
+goog.require('goog.debug.entryPointRegistry');
+goog.require('goog.events.BrowserEvent');
+goog.require('goog.events.BrowserFeature');
+goog.require('goog.events.Listenable');
+goog.require('goog.events.ListenerMap');
+
+goog.forwardDeclare('goog.debug.ErrorHandler');
+goog.forwardDeclare('goog.events.EventWrapper');
+
+
+/**
+ * @typedef {number|goog.events.ListenableKey}
+ */
+goog.events.Key;
+
+
+/**
+ * @typedef {EventTarget|goog.events.Listenable}
+ */
+goog.events.ListenableType;
+
+
+/**
+ * Property name on a native event target for the listener map
+ * associated with the event target.
+ * @private @const {string}
+ */
+goog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0);
+
+
+/**
+ * String used to prepend to IE event types.
+ * @const
+ * @private
+ */
+goog.events.onString_ = 'on';
+
+
+/**
+ * Map of computed "on<eventname>" strings for IE event types. Caching
+ * this removes an extra object allocation in goog.events.listen which
+ * improves IE6 performance.
+ * @const
+ * @dict
+ * @private
+ */
+goog.events.onStringMap_ = {};
+
+
+/**
+ * @enum {number} Different capture simulation mode for IE8-.
+ */
+goog.events.CaptureSimulationMode = {
+ /**
+ * Does not perform capture simulation. Will asserts in IE8- when you
+ * add capture listeners.
+ */
+ OFF_AND_FAIL: 0,
+
+ /**
+ * Does not perform capture simulation, silently ignore capture
+ * listeners.
+ */
+ OFF_AND_SILENT: 1,
+
+ /**
+ * Performs capture simulation.
+ */
+ ON: 2
+};
+
+
+/**
+ * @define {number} The capture simulation mode for IE8-. By default,
+ * this is ON.
+ */
+goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2);
+
+
+/**
+ * Estimated count of total native listeners.
+ * @private {number}
+ */
+goog.events.listenerCountEstimate_ = 0;
+
+
+/**
+ * Adds an event listener for a specific event on a native event
+ * target (such as a DOM element) or an object that has implemented
+ * {@link goog.events.Listenable}. A listener can only be added once
+ * to an object and if it is added again the key for the listener is
+ * returned. Note that if the existing listener is a one-off listener
+ * (registered via listenOnce), it will no longer be a one-off
+ * listener after a call to listen().
+ *
+ * @param {EventTarget|goog.events.Listenable} src The node to listen
+ * to events on.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
+ * listener Callback method, or an object with a handleEvent function.
+ * WARNING: passing an Object is now softly deprecated.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {T=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.Key} Unique key for the listener.
+ * @template T,EVENTOBJ
+ */
+goog.events.listen = function(src, type, listener, opt_capt, opt_handler) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ goog.events.listen(src, type[i], listener, opt_capt, opt_handler);
+ }
+ return null;
+ }
+
+ listener = goog.events.wrapListener(listener);
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.listen(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, opt_capt, opt_handler);
+ } else {
+ return goog.events.listen_(
+ /** @type {!EventTarget} */ (src),
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, /* callOnce */ false, opt_capt, opt_handler);
+ }
+};
+
+
+/**
+ * Adds an event listener for a specific event on a native event
+ * target. A listener can only be added once to an object and if it
+ * is added again the key for the listener is returned.
+ *
+ * Note that a one-off listener will not change an existing listener,
+ * if any. On the other hand a normal listener will change existing
+ * one-off listener to become a normal listener.
+ *
+ * @param {EventTarget} src The node to listen to events on.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {!Function} listener Callback function.
+ * @param {boolean} callOnce Whether the listener is a one-off
+ * listener or otherwise.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.ListenableKey} Unique key for the listener.
+ * @private
+ */
+goog.events.listen_ = function(
+ src, type, listener, callOnce, opt_capt, opt_handler) {
+ if (!type) {
+ throw Error('Invalid event type');
+ }
+
+ var capture = !!opt_capt;
+ if (capture && !goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
+ if (goog.events.CAPTURE_SIMULATION_MODE ==
+ goog.events.CaptureSimulationMode.OFF_AND_FAIL) {
+ goog.asserts.fail('Can not register capture listener in IE8-.');
+ return null;
+ } else if (goog.events.CAPTURE_SIMULATION_MODE ==
+ goog.events.CaptureSimulationMode.OFF_AND_SILENT) {
+ return null;
+ }
+ }
+
+ var listenerMap = goog.events.getListenerMap_(src);
+ if (!listenerMap) {
+ src[goog.events.LISTENER_MAP_PROP_] = listenerMap =
+ new goog.events.ListenerMap(src);
+ }
+
+ var listenerObj = listenerMap.add(
+ type, listener, callOnce, opt_capt, opt_handler);
+
+ // If the listenerObj already has a proxy, it has been set up
+ // previously. We simply return.
+ if (listenerObj.proxy) {
+ return listenerObj;
+ }
+
+ var proxy = goog.events.getProxy();
+ listenerObj.proxy = proxy;
+
+ proxy.src = src;
+ proxy.listener = listenerObj;
+
+ // Attach the proxy through the browser's API
+ if (src.addEventListener) {
+ src.addEventListener(type.toString(), proxy, capture);
+ } else {
+ // The else above used to be else if (src.attachEvent) and then there was
+ // another else statement that threw an exception warning the developer
+ // they made a mistake. This resulted in an extra object allocation in IE6
+ // due to a wrapper object that had to be implemented around the element
+ // and so was removed.
+ src.attachEvent(goog.events.getOnString_(type.toString()), proxy);
+ }
+
+ goog.events.listenerCountEstimate_++;
+ return listenerObj;
+};
+
+
+/**
+ * Helper function for returning a proxy function.
+ * @return {!Function} A new or reused function object.
+ */
+goog.events.getProxy = function() {
+ var proxyCallbackFunction = goog.events.handleBrowserEvent_;
+ // Use a local var f to prevent one allocation.
+ var f = goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT ?
+ function(eventObject) {
+ return proxyCallbackFunction.call(f.src, f.listener, eventObject);
+ } :
+ function(eventObject) {
+ var v = proxyCallbackFunction.call(f.src, f.listener, eventObject);
+ // NOTE(chrishenry): In IE, we hack in a capture phase. However, if
+ // there is inline event handler which tries to prevent default (for
+ // example <a href="..." onclick="return false">...</a>) in a
+ // descendant element, the prevent default will be overridden
+ // by this listener if this listener were to return true. Hence, we
+ // return undefined.
+ if (!v) return v;
+ };
+ return f;
+};
+
+
+/**
+ * Adds an event listener for a specific event on a native event
+ * target (such as a DOM element) or an object that has implemented
+ * {@link goog.events.Listenable}. After the event has fired the event
+ * listener is removed from the target.
+ *
+ * If an existing listener already exists, listenOnce will do
+ * nothing. In particular, if the listener was previously registered
+ * via listen(), listenOnce() will not turn the listener into a
+ * one-off listener. Similarly, if there is already an existing
+ * one-off listener, listenOnce does not modify the listeners (it is
+ * still a once listener).
+ *
+ * @param {EventTarget|goog.events.Listenable} src The node to listen
+ * to events on.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types.
+ * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
+ * listener Callback method.
+ * @param {boolean=} opt_capt Fire in capture phase?.
+ * @param {T=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.Key} Unique key for the listener.
+ * @template T,EVENTOBJ
+ */
+goog.events.listenOnce = function(src, type, listener, opt_capt, opt_handler) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ goog.events.listenOnce(src, type[i], listener, opt_capt, opt_handler);
+ }
+ return null;
+ }
+
+ listener = goog.events.wrapListener(listener);
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.listenOnce(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, opt_capt, opt_handler);
+ } else {
+ return goog.events.listen_(
+ /** @type {!EventTarget} */ (src),
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, /* callOnce */ true, opt_capt, opt_handler);
+ }
+};
+
+
+/**
+ * Adds an event listener with a specific event wrapper on a DOM Node or an
+ * object that has implemented {@link goog.events.Listenable}. A listener can
+ * only be added once to an object.
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target to
+ * listen to events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener
+ * Callback method, or an object with a handleEvent function.
+ * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
+ * false).
+ * @param {T=} opt_handler Element in whose scope to call the listener.
+ * @template T
+ */
+goog.events.listenWithWrapper = function(src, wrapper, listener, opt_capt,
+ opt_handler) {
+ wrapper.listen(src, listener, opt_capt, opt_handler);
+};
+
+
+/**
+ * Removes an event listener which was added with listen().
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target to stop
+ * listening to events on.
+ * @param {string|Array<string>|
+ * !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
+ * type Event type or array of event types to unlisten to.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to remove.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase of the
+ * event.
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ * @return {?boolean} indicating whether the listener was there to remove.
+ * @template EVENTOBJ
+ */
+goog.events.unlisten = function(src, type, listener, opt_capt, opt_handler) {
+ if (goog.isArray(type)) {
+ for (var i = 0; i < type.length; i++) {
+ goog.events.unlisten(src, type[i], listener, opt_capt, opt_handler);
+ }
+ return null;
+ }
+
+ listener = goog.events.wrapListener(listener);
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.unlisten(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, opt_capt, opt_handler);
+ }
+
+ if (!src) {
+ // TODO(chrishenry): We should tighten the API to only accept
+ // non-null objects, or add an assertion here.
+ return false;
+ }
+
+ var capture = !!opt_capt;
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (src));
+ if (listenerMap) {
+ var listenerObj = listenerMap.getListener(
+ /** @type {string|!goog.events.EventId} */ (type),
+ listener, capture, opt_handler);
+ if (listenerObj) {
+ return goog.events.unlistenByKey(listenerObj);
+ }
+ }
+
+ return false;
+};
+
+
+/**
+ * Removes an event listener which was added with listen() by the key
+ * returned by listen().
+ *
+ * @param {goog.events.Key} key The key returned by listen() for this
+ * event listener.
+ * @return {boolean} indicating whether the listener was there to remove.
+ */
+goog.events.unlistenByKey = function(key) {
+ // TODO(chrishenry): Remove this check when tests that rely on this
+ // are fixed.
+ if (goog.isNumber(key)) {
+ return false;
+ }
+
+ var listener = /** @type {goog.events.ListenableKey} */ (key);
+ if (!listener || listener.removed) {
+ return false;
+ }
+
+ var src = listener.src;
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.unlistenByKey(listener);
+ }
+
+ var type = listener.type;
+ var proxy = listener.proxy;
+ if (src.removeEventListener) {
+ src.removeEventListener(type, proxy, listener.capture);
+ } else if (src.detachEvent) {
+ src.detachEvent(goog.events.getOnString_(type), proxy);
+ }
+ goog.events.listenerCountEstimate_--;
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (src));
+ // TODO(chrishenry): Try to remove this conditional and execute the
+ // first branch always. This should be safe.
+ if (listenerMap) {
+ listenerMap.removeByKey(listener);
+ if (listenerMap.getTypeCount() == 0) {
+ // Null the src, just because this is simple to do (and useful
+ // for IE <= 7).
+ listenerMap.src = null;
+ // We don't use delete here because IE does not allow delete
+ // on a window object.
+ src[goog.events.LISTENER_MAP_PROP_] = null;
+ }
+ } else {
+ listener.markAsRemoved();
+ }
+
+ return true;
+};
+
+
+/**
+ * Removes an event listener which was added with listenWithWrapper().
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target to stop
+ * listening to events on.
+ * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to remove.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase of the
+ * event.
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ */
+goog.events.unlistenWithWrapper = function(src, wrapper, listener, opt_capt,
+ opt_handler) {
+ wrapper.unlisten(src, listener, opt_capt, opt_handler);
+};
+
+
+/**
+ * Removes all listeners from an object. You can also optionally
+ * remove listeners of a particular type.
+ *
+ * @param {Object|undefined} obj Object to remove listeners from. Must be an
+ * EventTarget or a goog.events.Listenable.
+ * @param {string|!goog.events.EventId=} opt_type Type of event to remove.
+ * Default is all types.
+ * @return {number} Number of listeners removed.
+ */
+goog.events.removeAll = function(obj, opt_type) {
+ // TODO(chrishenry): Change the type of obj to
+ // (!EventTarget|!goog.events.Listenable).
+
+ if (!obj) {
+ return 0;
+ }
+
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.removeAllListeners(opt_type);
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (obj));
+ if (!listenerMap) {
+ return 0;
+ }
+
+ var count = 0;
+ var typeStr = opt_type && opt_type.toString();
+ for (var type in listenerMap.listeners) {
+ if (!typeStr || type == typeStr) {
+ // Clone so that we don't need to worry about unlistenByKey
+ // changing the content of the ListenerMap.
+ var listeners = listenerMap.listeners[type].concat();
+ for (var i = 0; i < listeners.length; ++i) {
+ if (goog.events.unlistenByKey(listeners[i])) {
+ ++count;
+ }
+ }
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Gets the listeners for a given object, type and capture phase.
+ *
+ * @param {Object} obj Object to get listeners for.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {boolean} capture Capture phase?.
+ * @return {Array<goog.events.Listener>} Array of listener objects.
+ */
+goog.events.getListeners = function(obj, type, capture) {
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.getListeners(type, capture);
+ } else {
+ if (!obj) {
+ // TODO(chrishenry): We should tighten the API to accept
+ // !EventTarget|goog.events.Listenable, and add an assertion here.
+ return [];
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (obj));
+ return listenerMap ? listenerMap.getListeners(type, capture) : [];
+ }
+};
+
+
+/**
+ * Gets the goog.events.Listener for the event or null if no such listener is
+ * in use.
+ *
+ * @param {EventTarget|goog.events.Listenable} src The target from
+ * which to get listeners.
+ * @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event.
+ * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The
+ * listener function to get.
+ * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
+ * whether the listener is fired during the
+ * capture or bubble phase of the event.
+ * @param {Object=} opt_handler Element in whose scope to call the listener.
+ * @return {goog.events.ListenableKey} the found listener or null if not found.
+ * @template EVENTOBJ
+ */
+goog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {
+ // TODO(chrishenry): Change type from ?string to string, or add assertion.
+ type = /** @type {string} */ (type);
+ listener = goog.events.wrapListener(listener);
+ var capture = !!opt_capt;
+ if (goog.events.Listenable.isImplementedBy(src)) {
+ return src.getListener(type, listener, capture, opt_handler);
+ }
+
+ if (!src) {
+ // TODO(chrishenry): We should tighten the API to only accept
+ // non-null objects, or add an assertion here.
+ return null;
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (src));
+ if (listenerMap) {
+ return listenerMap.getListener(type, listener, capture, opt_handler);
+ }
+ return null;
+};
+
+
+/**
+ * Returns whether an event target has any active listeners matching the
+ * specified signature. If either the type or capture parameters are
+ * unspecified, the function will match on the remaining criteria.
+ *
+ * @param {EventTarget|goog.events.Listenable} obj Target to get
+ * listeners for.
+ * @param {string|!goog.events.EventId=} opt_type Event type.
+ * @param {boolean=} opt_capture Whether to check for capture or bubble-phase
+ * listeners.
+ * @return {boolean} Whether an event target has one or more listeners matching
+ * the requested type and/or capture phase.
+ */
+goog.events.hasListener = function(obj, opt_type, opt_capture) {
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.hasListener(opt_type, opt_capture);
+ }
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {!EventTarget} */ (obj));
+ return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);
+};
+
+
+/**
+ * Provides a nice string showing the normalized event objects public members
+ * @param {Object} e Event Object.
+ * @return {string} String of the public members of the normalized event object.
+ */
+goog.events.expose = function(e) {
+ var str = [];
+ for (var key in e) {
+ if (e[key] && e[key].id) {
+ str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')');
+ } else {
+ str.push(key + ' = ' + e[key]);
+ }
+ }
+ return str.join('\n');
+};
+
+
+/**
+ * Returns a string with on prepended to the specified type. This is used for IE
+ * which expects "on" to be prepended. This function caches the string in order
+ * to avoid extra allocations in steady state.
+ * @param {string} type Event type.
+ * @return {string} The type string with 'on' prepended.
+ * @private
+ */
+goog.events.getOnString_ = function(type) {
+ if (type in goog.events.onStringMap_) {
+ return goog.events.onStringMap_[type];
+ }
+ return goog.events.onStringMap_[type] = goog.events.onString_ + type;
+};
+
+
+/**
+ * Fires an object's listeners of a particular type and phase
+ *
+ * @param {Object} obj Object whose listeners to call.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {boolean} capture Which event phase.
+ * @param {Object} eventObject Event object to be passed to listener.
+ * @return {boolean} True if all listeners returned true else false.
+ */
+goog.events.fireListeners = function(obj, type, capture, eventObject) {
+ if (goog.events.Listenable.isImplementedBy(obj)) {
+ return obj.fireListeners(type, capture, eventObject);
+ }
+
+ return goog.events.fireListeners_(obj, type, capture, eventObject);
+};
+
+
+/**
+ * Fires an object's listeners of a particular type and phase.
+ * @param {Object} obj Object whose listeners to call.
+ * @param {string|!goog.events.EventId} type Event type.
+ * @param {boolean} capture Which event phase.
+ * @param {Object} eventObject Event object to be passed to listener.
+ * @return {boolean} True if all listeners returned true else false.
+ * @private
+ */
+goog.events.fireListeners_ = function(obj, type, capture, eventObject) {
+ /** @type {boolean} */
+ var retval = true;
+
+ var listenerMap = goog.events.getListenerMap_(
+ /** @type {EventTarget} */ (obj));
+ if (listenerMap) {
+ // TODO(chrishenry): Original code avoids array creation when there
+ // is no listener, so we do the same. If this optimization turns
+ // out to be not required, we can replace this with
+ // listenerMap.getListeners(type, capture) instead, which is simpler.
+ var listenerArray = listenerMap.listeners[type.toString()];
+ if (listenerArray) {
+ listenerArray = listenerArray.concat();
+ for (var i = 0; i < listenerArray.length; i++) {
+ var listener = listenerArray[i];
+ // We might not have a listener if the listener was removed.
+ if (listener && listener.capture == capture && !listener.removed) {
+ var result = goog.events.fireListener(listener, eventObject);
+ retval = retval && (result !== false);
+ }
+ }
+ }
+ }
+ return retval;
+};
+
+
+/**
+ * Fires a listener with a set of arguments
+ *
+ * @param {goog.events.Listener} listener The listener object to call.
+ * @param {Object} eventObject The event object to pass to the listener.
+ * @return {boolean} Result of listener.
+ */
+goog.events.fireListener = function(listener, eventObject) {
+ var listenerFn = listener.listener;
+ var listenerHandler = listener.handler || listener.src;
+
+ if (listener.callOnce) {
+ goog.events.unlistenByKey(listener);
+ }
+ return listenerFn.call(listenerHandler, eventObject);
+};
+
+
+/**
+ * Gets the total number of listeners currently in the system.
+ * @return {number} Number of listeners.
+ * @deprecated This returns estimated count, now that Closure no longer
+ * stores a central listener registry. We still return an estimation
+ * to keep existing listener-related tests passing. In the near future,
+ * this function will be removed.
+ */
+goog.events.getTotalListenerCount = function() {
+ return goog.events.listenerCountEstimate_;
+};
+
+
+/**
+ * Dispatches an event (or event like object) and calls all listeners
+ * listening for events of this type. The type of the event is decided by the
+ * type property on the event object.
+ *
+ * If any of the listeners returns false OR calls preventDefault then this
+ * function will return false. If one of the capture listeners calls
+ * stopPropagation, then the bubble listeners won't fire.
+ *
+ * @param {goog.events.Listenable} src The event target.
+ * @param {goog.events.EventLike} e Event object.
+ * @return {boolean} If anyone called preventDefault on the event object (or
+ * if any of the handlers returns false) this will also return false.
+ * If there are no handlers, or if all handlers return true, this returns
+ * true.
+ */
+goog.events.dispatchEvent = function(src, e) {
+ goog.asserts.assert(
+ goog.events.Listenable.isImplementedBy(src),
+ 'Can not use goog.events.dispatchEvent with ' +
+ 'non-goog.events.Listenable instance.');
+ return src.dispatchEvent(e);
+};
+
+
+/**
+ * Installs exception protection for the browser event entry point using the
+ * given error handler.
+ *
+ * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
+ * protect the entry point.
+ */
+goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
+ goog.events.handleBrowserEvent_ = errorHandler.protectEntryPoint(
+ goog.events.handleBrowserEvent_);
+};
+
+
+/**
+ * Handles an event and dispatches it to the correct listeners. This
+ * function is a proxy for the real listener the user specified.
+ *
+ * @param {goog.events.Listener} listener The listener object.
+ * @param {Event=} opt_evt Optional event object that gets passed in via the
+ * native event handlers.
+ * @return {boolean} Result of the event handler.
+ * @this {EventTarget} The object or Element that fired the event.
+ * @private
+ */
+goog.events.handleBrowserEvent_ = function(listener, opt_evt) {
+ if (listener.removed) {
+ return true;
+ }
+
+ // Synthesize event propagation if the browser does not support W3C
+ // event model.
+ if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
+ var ieEvent = opt_evt ||
+ /** @type {Event} */ (goog.getObjectByName('window.event'));
+ var evt = new goog.events.BrowserEvent(ieEvent, this);
+ /** @type {boolean} */
+ var retval = true;
+
+ if (goog.events.CAPTURE_SIMULATION_MODE ==
+ goog.events.CaptureSimulationMode.ON) {
+ // If we have not marked this event yet, we should perform capture
+ // simulation.
+ if (!goog.events.isMarkedIeEvent_(ieEvent)) {
+ goog.events.markIeEvent_(ieEvent);
+
+ var ancestors = [];
+ for (var parent = evt.currentTarget; parent;
+ parent = parent.parentNode) {
+ ancestors.push(parent);
+ }
+
+ // Fire capture listeners.
+ var type = listener.type;
+ for (var i = ancestors.length - 1; !evt.propagationStopped_ && i >= 0;
+ i--) {
+ evt.currentTarget = ancestors[i];
+ var result = goog.events.fireListeners_(ancestors[i], type, true, evt);
+ retval = retval && result;
+ }
+
+ // Fire bubble listeners.
+ //
+ // We can technically rely on IE to perform bubble event
+ // propagation. However, it turns out that IE fires events in
+ // opposite order of attachEvent registration, which broke
+ // some code and tests that rely on the order. (While W3C DOM
+ // Level 2 Events TR leaves the event ordering unspecified,
+ // modern browsers and W3C DOM Level 3 Events Working Draft
+ // actually specify the order as the registration order.)
+ for (var i = 0; !evt.propagationStopped_ && i < ancestors.length; i++) {
+ evt.currentTarget = ancestors[i];
+ var result = goog.events.fireListeners_(ancestors[i], type, false, evt);
+ retval = retval && result;
+ }
+ }
+ } else {
+ retval = goog.events.fireListener(listener, evt);
+ }
+ return retval;
+ }
+
+ // Otherwise, simply fire the listener.
+ return goog.events.fireListener(
+ listener, new goog.events.BrowserEvent(opt_evt, this));
+};
+
+
+/**
+ * This is used to mark the IE event object so we do not do the Closure pass
+ * twice for a bubbling event.
+ * @param {Event} e The IE browser event.
+ * @private
+ */
+goog.events.markIeEvent_ = function(e) {
+ // Only the keyCode and the returnValue can be changed. We use keyCode for
+ // non keyboard events.
+ // event.returnValue is a bit more tricky. It is undefined by default. A
+ // boolean false prevents the default action. In a window.onbeforeunload and
+ // the returnValue is non undefined it will be alerted. However, we will only
+ // modify the returnValue for keyboard events. We can get a problem if non
+ // closure events sets the keyCode or the returnValue
+
+ var useReturnValue = false;
+
+ if (e.keyCode == 0) {
+ // We cannot change the keyCode in case that srcElement is input[type=file].
+ // We could test that that is the case but that would allocate 3 objects.
+ // If we use try/catch we will only allocate extra objects in the case of a
+ // failure.
+ /** @preserveTry */
+ try {
+ e.keyCode = -1;
+ return;
+ } catch (ex) {
+ useReturnValue = true;
+ }
+ }
+
+ if (useReturnValue ||
+ /** @type {boolean|undefined} */ (e.returnValue) == undefined) {
+ e.returnValue = true;
+ }
+};
+
+
+/**
+ * This is used to check if an IE event has already been handled by the Closure
+ * system so we do not do the Closure pass twice for a bubbling event.
+ * @param {Event} e The IE browser event.
+ * @return {boolean} True if the event object has been marked.
+ * @private
+ */
+goog.events.isMarkedIeEvent_ = function(e) {
+ return e.keyCode < 0 || e.returnValue != undefined;
+};
+
+
+/**
+ * Counter to create unique event ids.
+ * @private {number}
+ */
+goog.events.uniqueIdCounter_ = 0;
+
+
+/**
+ * Creates a unique event id.
+ *
+ * @param {string} identifier The identifier.
+ * @return {string} A unique identifier.
+ * @idGenerator
+ */
+goog.events.getUniqueId = function(identifier) {
+ return identifier + '_' + goog.events.uniqueIdCounter_++;
+};
+
+
+/**
+ * @param {EventTarget} src The source object.
+ * @return {goog.events.ListenerMap} A listener map for the given
+ * source object, or null if none exists.
+ * @private
+ */
+goog.events.getListenerMap_ = function(src) {
+ var listenerMap = src[goog.events.LISTENER_MAP_PROP_];
+ // IE serializes the property as well (e.g. when serializing outer
+ // HTML). So we must check that the value is of the correct type.
+ return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;
+};
+
+
+/**
+ * Expando property for listener function wrapper for Object with
+ * handleEvent.
+ * @private @const {string}
+ */
+goog.events.LISTENER_WRAPPER_PROP_ = '__closure_events_fn_' +
+ ((Math.random() * 1e9) >>> 0);
+
+
+/**
+ * @param {Object|Function} listener The listener function or an
+ * object that contains handleEvent method.
+ * @return {!Function} Either the original function or a function that
+ * calls obj.handleEvent. If the same listener is passed to this
+ * function more than once, the same function is guaranteed to be
+ * returned.
+ */
+goog.events.wrapListener = function(listener) {
+ goog.asserts.assert(listener, 'Listener can not be null.');
+
+ if (goog.isFunction(listener)) {
+ return listener;
+ }
+
+ goog.asserts.assert(
+ listener.handleEvent, 'An object listener must have handleEvent method.');
+ if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) {
+ listener[goog.events.LISTENER_WRAPPER_PROP_] =
+ function(e) { return listener.handleEvent(e); };
+ }
+ return listener[goog.events.LISTENER_WRAPPER_PROP_];
+};
+
+
+// Register the browser event handler as an entry point, so that
+// it can be monitored for exception handling, etc.
+goog.debug.entryPointRegistry.register(
+ /**
+ * @param {function(!Function): !Function} transformer The transforming
+ * function.
+ */
+ function(transformer) {
+ goog.events.handleBrowserEvent_ = transformer(
+ goog.events.handleBrowserEvent_);
+ });
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/events/eventtarget.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/events/eventtarget.js b/externs/GCL/externs/goog/events/eventtarget.js
new file mode 100644
index 0000000..7408c7e
--- /dev/null
+++ b/externs/GCL/externs/goog/events/eventtarget.js
@@ -0,0 +1,394 @@
+// Copyright 2005 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A disposable implementation of a custom
+ * listenable/event target. See also: documentation for
+ * {@code goog.events.Listenable}.
+ *
+ * @author arv@google.com (Erik Arvidsson) [Original implementation]
+ * @see ../demos/eventtarget.html
+ * @see goog.events.Listenable
+ */
+
+goog.provide('goog.events.EventTarget');
+
+goog.require('goog.Disposable');
+goog.require('goog.asserts');
+goog.require('goog.events');
+goog.require('goog.events.Event');
+goog.require('goog.events.Listenable');
+goog.require('goog.events.ListenerMap');
+goog.require('goog.object');
+
+
+
+/**
+ * An implementation of {@code goog.events.Listenable} with full W3C
+ * EventTarget-like support (capture/bubble mechanism, stopping event
+ * propagation, preventing default actions).
+ *
+ * You may subclass this class to turn your class into a Listenable.
+ *
+ * Unless propagation is stopped, an event dispatched by an
+ * EventTarget will bubble to the parent returned by
+ * {@code getParentEventTarget}. To set the parent, call
+ * {@code setParentEventTarget}. Subclasses that don't support
+ * changing the parent can override the setter to throw an error.
+ *
+ * Example usage:
+ * <pre>
+ * var source = new goog.events.EventTarget();
+ * function handleEvent(e) {
+ * alert('Type: ' + e.type + '; Target: ' + e.target);
+ * }
+ * source.listen('foo', handleEvent);
+ * // Or: goog.events.listen(source, 'foo', handleEvent);
+ * ...
+ * source.dispatchEvent('foo'); // will call handleEvent
+ * ...
+ * source.unlisten('foo', handleEvent);
+ * // Or: goog.events.unlisten(source, 'foo', handleEvent);
+ * </pre>
+ *
+ * @constructor
+ * @extends {goog.Disposable}
+ * @implements {goog.events.Listenable}
+ */
+goog.events.EventTarget = function() {
+ goog.Disposable.call(this);
+
+ /**
+ * Maps of event type to an array of listeners.
+ * @private {!goog.events.ListenerMap}
+ */
+ this.eventTargetListeners_ = new goog.events.ListenerMap(this);
+
+ /**
+ * The object to use for event.target. Useful when mixing in an
+ * EventTarget to another object.
+ * @private {!Object}
+ */
+ this.actualEventTarget_ = this;
+
+ /**
+ * Parent event target, used during event bubbling.
+ *
+ * TODO(chrishenry): Change this to goog.events.Listenable. This
+ * currently breaks people who expect getParentEventTarget to return
+ * goog.events.EventTarget.
+ *
+ * @private {goog.events.EventTarget}
+ */
+ this.parentEventTarget_ = null;
+};
+goog.inherits(goog.events.EventTarget, goog.Disposable);
+goog.events.Listenable.addImplementation(goog.events.EventTarget);
+
+
+/**
+ * An artificial cap on the number of ancestors you can have. This is mainly
+ * for loop detection.
+ * @const {number}
+ * @private
+ */
+goog.events.EventTarget.MAX_ANCESTORS_ = 1000;
+
+
+/**
+ * Returns the parent of this event target to use for bubbling.
+ *
+ * @return {goog.events.EventTarget} The parent EventTarget or null if
+ * there is no parent.
+ * @override
+ */
+goog.events.EventTarget.prototype.getParentEventTarget = function() {
+ return this.parentEventTarget_;
+};
+
+
+/**
+ * Sets the parent of this event target to use for capture/bubble
+ * mechanism.
+ * @param {goog.events.EventTarget} parent Parent listenable (null if none).
+ */
+goog.events.EventTarget.prototype.setParentEventTarget = function(parent) {
+ this.parentEventTarget_ = parent;
+};
+
+
+/**
+ * Adds an event listener to the event target. The same handler can only be
+ * added once per the type. Even if you add the same handler multiple times
+ * using the same type then it will only be called once when the event is
+ * dispatched.
+ *
+ * @param {string} type The type of the event to listen for.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
+ * to handle the event. The handler can also be an object that implements
+ * the handleEvent method which takes the event object as argument.
+ * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase
+ * of the event.
+ * @param {Object=} opt_handlerScope Object in whose scope to call
+ * the listener.
+ * @deprecated Use {@code #listen} instead, when possible. Otherwise, use
+ * {@code goog.events.listen} if you are passing Object
+ * (instead of Function) as handler.
+ */
+goog.events.EventTarget.prototype.addEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);
+};
+
+
+/**
+ * Removes an event listener from the event target. The handler must be the
+ * same object as the one added. If the handler has not been added then
+ * nothing is done.
+ *
+ * @param {string} type The type of the event to listen for.
+ * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
+ * to handle the event. The handler can also be an object that implements
+ * the handleEvent method which takes the event object as argument.
+ * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
+ * whether the listener is fired during the capture or bubble phase
+ * of the event.
+ * @param {Object=} opt_handlerScope Object in whose scope to call
+ * the listener.
+ * @deprecated Use {@code #unlisten} instead, when possible. Otherwise, use
+ * {@code goog.events.unlisten} if you are passing Object
+ * (instead of Function) as handler.
+ */
+goog.events.EventTarget.prototype.removeEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.dispatchEvent = function(e) {
+ this.assertInitialized_();
+
+ var ancestorsTree, ancestor = this.getParentEventTarget();
+ if (ancestor) {
+ ancestorsTree = [];
+ var ancestorCount = 1;
+ for (; ancestor; ancestor = ancestor.getParentEventTarget()) {
+ ancestorsTree.push(ancestor);
+ goog.asserts.assert(
+ (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),
+ 'infinite loop');
+ }
+ }
+
+ return goog.events.EventTarget.dispatchEventInternal_(
+ this.actualEventTarget_, e, ancestorsTree);
+};
+
+
+/**
+ * Removes listeners from this object. Classes that extend EventTarget may
+ * need to override this method in order to remove references to DOM Elements
+ * and additional listeners.
+ * @override
+ */
+goog.events.EventTarget.prototype.disposeInternal = function() {
+ goog.events.EventTarget.superClass_.disposeInternal.call(this);
+
+ this.removeAllListeners();
+ this.parentEventTarget_ = null;
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.listen = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ this.assertInitialized_();
+ return this.eventTargetListeners_.add(
+ String(type), listener, false /* callOnce */, opt_useCapture,
+ opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.listenOnce = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ return this.eventTargetListeners_.add(
+ String(type), listener, true /* callOnce */, opt_useCapture,
+ opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.unlisten = function(
+ type, listener, opt_useCapture, opt_listenerScope) {
+ return this.eventTargetListeners_.remove(
+ String(type), listener, opt_useCapture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.unlistenByKey = function(key) {
+ return this.eventTargetListeners_.removeByKey(key);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {
+ // TODO(chrishenry): Previously, removeAllListeners can be called on
+ // uninitialized EventTarget, so we preserve that behavior. We
+ // should remove this when usages that rely on that fact are purged.
+ if (!this.eventTargetListeners_) {
+ return 0;
+ }
+ return this.eventTargetListeners_.removeAll(opt_type);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.fireListeners = function(
+ type, capture, eventObject) {
+ // TODO(chrishenry): Original code avoids array creation when there
+ // is no listener, so we do the same. If this optimization turns
+ // out to be not required, we can replace this with
+ // getListeners(type, capture) instead, which is simpler.
+ var listenerArray = this.eventTargetListeners_.listeners[String(type)];
+ if (!listenerArray) {
+ return true;
+ }
+ listenerArray = listenerArray.concat();
+
+ var rv = true;
+ for (var i = 0; i < listenerArray.length; ++i) {
+ var listener = listenerArray[i];
+ // We might not have a listener if the listener was removed.
+ if (listener && !listener.removed && listener.capture == capture) {
+ var listenerFn = listener.listener;
+ var listenerHandler = listener.handler || listener.src;
+
+ if (listener.callOnce) {
+ this.unlistenByKey(listener);
+ }
+ rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;
+ }
+ }
+
+ return rv && eventObject.returnValue_ != false;
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.getListeners = function(type, capture) {
+ return this.eventTargetListeners_.getListeners(String(type), capture);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.getListener = function(
+ type, listener, capture, opt_listenerScope) {
+ return this.eventTargetListeners_.getListener(
+ String(type), listener, capture, opt_listenerScope);
+};
+
+
+/** @override */
+goog.events.EventTarget.prototype.hasListener = function(
+ opt_type, opt_capture) {
+ var id = goog.isDef(opt_type) ? String(opt_type) : undefined;
+ return this.eventTargetListeners_.hasListener(id, opt_capture);
+};
+
+
+/**
+ * Sets the target to be used for {@code event.target} when firing
+ * event. Mainly used for testing. For example, see
+ * {@code goog.testing.events.mixinListenable}.
+ * @param {!Object} target The target.
+ */
+goog.events.EventTarget.prototype.setTargetForTesting = function(target) {
+ this.actualEventTarget_ = target;
+};
+
+
+/**
+ * Asserts that the event target instance is initialized properly.
+ * @private
+ */
+goog.events.EventTarget.prototype.assertInitialized_ = function() {
+ goog.asserts.assert(
+ this.eventTargetListeners_,
+ 'Event target is not initialized. Did you call the superclass ' +
+ '(goog.events.EventTarget) constructor?');
+};
+
+
+/**
+ * Dispatches the given event on the ancestorsTree.
+ *
+ * @param {!Object} target The target to dispatch on.
+ * @param {goog.events.Event|Object|string} e The event object.
+ * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors
+ * tree of the target, in reverse order from the closest ancestor
+ * to the root event target. May be null if the target has no ancestor.
+ * @return {boolean} If anyone called preventDefault on the event object (or
+ * if any of the listeners returns false) this will also return false.
+ * @private
+ */
+goog.events.EventTarget.dispatchEventInternal_ = function(
+ target, e, opt_ancestorsTree) {
+ var type = e.type || /** @type {string} */ (e);
+
+ // If accepting a string or object, create a custom event object so that
+ // preventDefault and stopPropagation work with the event.
+ if (goog.isString(e)) {
+ e = new goog.events.Event(e, target);
+ } else if (!(e instanceof goog.events.Event)) {
+ var oldEvent = e;
+ e = new goog.events.Event(type, target);
+ goog.object.extend(e, oldEvent);
+ } else {
+ e.target = e.target || target;
+ }
+
+ var rv = true, currentTarget;
+
+ // Executes all capture listeners on the ancestors, if any.
+ if (opt_ancestorsTree) {
+ for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0;
+ i--) {
+ currentTarget = e.currentTarget = opt_ancestorsTree[i];
+ rv = currentTarget.fireListeners(type, true, e) && rv;
+ }
+ }
+
+ // Executes capture and bubble listeners on the target.
+ if (!e.propagationStopped_) {
+ currentTarget = e.currentTarget = target;
+ rv = currentTarget.fireListeners(type, true, e) && rv;
+ if (!e.propagationStopped_) {
+ rv = currentTarget.fireListeners(type, false, e) && rv;
+ }
+ }
+
+ // Executes all bubble listeners on the ancestors, if any.
+ if (opt_ancestorsTree) {
+ for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) {
+ currentTarget = e.currentTarget = opt_ancestorsTree[i];
+ rv = currentTarget.fireListeners(type, false, e) && rv;
+ }
+ }
+
+ return rv;
+};
[40/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/date/date.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/date/date.js b/externs/GCL/externs/goog/date/date.js
new file mode 100644
index 0000000..1f17b36
--- /dev/null
+++ b/externs/GCL/externs/goog/date/date.js
@@ -0,0 +1,1761 @@
+// 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 Functions and objects for date representation and manipulation.
+ *
+ * @author eae@google.com (Emil A Eklund)
+ */
+
+goog.provide('goog.date');
+goog.provide('goog.date.Date');
+goog.provide('goog.date.DateTime');
+goog.provide('goog.date.Interval');
+goog.provide('goog.date.month');
+goog.provide('goog.date.weekDay');
+
+goog.require('goog.asserts');
+/** @suppress {extraRequire} */
+goog.require('goog.date.DateLike');
+goog.require('goog.i18n.DateTimeSymbols');
+goog.require('goog.string');
+
+
+/**
+ * Constants for weekdays.
+ * @enum {number}
+ */
+goog.date.weekDay = {
+ MON: 0,
+ TUE: 1,
+ WED: 2,
+ THU: 3,
+ FRI: 4,
+ SAT: 5,
+ SUN: 6
+};
+
+
+/**
+ * Constants for months.
+ * @enum {number}
+ */
+goog.date.month = {
+ JAN: 0,
+ FEB: 1,
+ MAR: 2,
+ APR: 3,
+ MAY: 4,
+ JUN: 5,
+ JUL: 6,
+ AUG: 7,
+ SEP: 8,
+ OCT: 9,
+ NOV: 10,
+ DEC: 11
+};
+
+
+/**
+ * Formats a month/year string.
+ * Example: "January 2008"
+ *
+ * @param {string} monthName The month name to use in the result.
+ * @param {number} yearNum The numeric year to use in the result.
+ * @return {string} A formatted month/year string.
+ */
+goog.date.formatMonthAndYear = function(monthName, yearNum) {
+ /** @desc Month/year format given the month name and the numeric year. */
+ var MSG_MONTH_AND_YEAR = goog.getMsg(
+ '{$monthName} {$yearNum}',
+ { 'monthName' : monthName, 'yearNum' : yearNum });
+ return MSG_MONTH_AND_YEAR;
+};
+
+
+/**
+ * Regular expression for splitting date parts from ISO 8601 styled string.
+ * Examples: '20060210' or '2005-02-22' or '20050222' or '2005-08'
+ * or '2005-W22' or '2005W22' or '2005-W22-4', etc.
+ * For explanation and more examples, see:
+ * {@link http://en.wikipedia.org/wiki/ISO_8601}
+ *
+ * @type {RegExp}
+ * @private
+ */
+goog.date.splitDateStringRegex_ = new RegExp(
+ '^(\\d{4})(?:(?:-?(\\d{2})(?:-?(\\d{2}))?)|' +
+ '(?:-?(\\d{3}))|(?:-?W(\\d{2})(?:-?([1-7]))?))?$');
+
+
+/**
+ * Regular expression for splitting time parts from ISO 8601 styled string.
+ * Examples: '18:46:39.994' or '184639.994'
+ *
+ * @type {RegExp}
+ * @private
+ */
+goog.date.splitTimeStringRegex_ =
+ /^(\d{2})(?::?(\d{2})(?::?(\d{2})(\.\d+)?)?)?$/;
+
+
+/**
+ * Regular expression for splitting timezone parts from ISO 8601 styled string.
+ * Example: The part after the '+' in '18:46:39+07:00'. Or '09:30Z' (UTC).
+ *
+ * @type {RegExp}
+ * @private
+ */
+goog.date.splitTimezoneStringRegex_ = /Z|(?:([-+])(\d{2})(?::?(\d{2}))?)$/;
+
+
+/**
+ * Regular expression for splitting duration parts from ISO 8601 styled string.
+ * Example: '-P1Y2M3DT4H5M6.7S'
+ *
+ * @type {RegExp}
+ * @private
+ */
+goog.date.splitDurationRegex_ = new RegExp(
+ '^(-)?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)D)?' +
+ '(T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+(?:\\.\\d+)?)S)?)?$');
+
+
+/**
+ * Number of milliseconds in a day.
+ * @type {number}
+ */
+goog.date.MS_PER_DAY = 24 * 60 * 60 * 1000;
+
+
+/**
+ * Returns whether the given year is a leap year.
+ *
+ * @param {number} year Year part of date.
+ * @return {boolean} Whether the given year is a leap year.
+ */
+goog.date.isLeapYear = function(year) {
+ // Leap year logic; the 4-100-400 rule
+ return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
+};
+
+
+/**
+ * Returns whether the given year is a long ISO year.
+ * See {@link http://www.phys.uu.nl/~vgent/calendar/isocalendar_text3.htm}.
+ *
+ * @param {number} year Full year part of date.
+ * @return {boolean} Whether the given year is a long ISO year.
+ */
+goog.date.isLongIsoYear = function(year) {
+ var n = 5 * year + 12 - 4 * (Math.floor(year / 100) - Math.floor(year / 400));
+ n += Math.floor((year - 100) / 400) - Math.floor((year - 102) / 400);
+ n += Math.floor((year - 200) / 400) - Math.floor((year - 199) / 400);
+
+ return n % 28 < 5;
+};
+
+
+/**
+ * Returns the number of days for a given month.
+ *
+ * @param {number} year Year part of date.
+ * @param {number} month Month part of date.
+ * @return {number} The number of days for the given month.
+ */
+goog.date.getNumberOfDaysInMonth = function(year, month) {
+ switch (month) {
+ case goog.date.month.FEB:
+ return goog.date.isLeapYear(year) ? 29 : 28;
+ case goog.date.month.JUN:
+ case goog.date.month.SEP:
+ case goog.date.month.NOV:
+ case goog.date.month.APR:
+ return 30;
+ }
+ return 31;
+};
+
+
+/**
+ * Returns true if the 2 dates are in the same day.
+ * @param {goog.date.DateLike} date The time to check.
+ * @param {goog.date.DateLike=} opt_now The current time.
+ * @return {boolean} Whether the dates are on the same day.
+ */
+goog.date.isSameDay = function(date, opt_now) {
+ var now = opt_now || new Date(goog.now());
+ return date.getDate() == now.getDate() &&
+ goog.date.isSameMonth(date, now);
+};
+
+
+/**
+ * Returns true if the 2 dates are in the same month.
+ * @param {goog.date.DateLike} date The time to check.
+ * @param {goog.date.DateLike=} opt_now The current time.
+ * @return {boolean} Whether the dates are in the same calendar month.
+ */
+goog.date.isSameMonth = function(date, opt_now) {
+ var now = opt_now || new Date(goog.now());
+ return date.getMonth() == now.getMonth() &&
+ goog.date.isSameYear(date, now);
+};
+
+
+/**
+ * Returns true if the 2 dates are in the same year.
+ * @param {goog.date.DateLike} date The time to check.
+ * @param {goog.date.DateLike=} opt_now The current time.
+ * @return {boolean} Whether the dates are in the same calendar year.
+ */
+goog.date.isSameYear = function(date, opt_now) {
+ var now = opt_now || new Date(goog.now());
+ return date.getFullYear() == now.getFullYear();
+};
+
+
+/**
+ * Static function for week number calculation. ISO 8601 implementation.
+ *
+ * @param {number} year Year part of date.
+ * @param {number} month Month part of date (0-11).
+ * @param {number} date Day part of date (1-31).
+ * @param {number=} opt_weekDay Cut off weekday, defaults to Thursday.
+ * @param {number=} opt_firstDayOfWeek First day of the week, defaults to
+ * Monday.
+ * Monday=0, Sunday=6.
+ * @return {number} The week number (1-53).
+ */
+goog.date.getWeekNumber = function(year, month, date, opt_weekDay,
+ opt_firstDayOfWeek) {
+ var d = new Date(year, month, date);
+
+ // Default to Thursday for cut off as per ISO 8601.
+ var cutoff = opt_weekDay || goog.date.weekDay.THU;
+
+ // Default to Monday for first day of the week as per ISO 8601.
+ var firstday = opt_firstDayOfWeek || goog.date.weekDay.MON;
+
+ // The d.getDay() has to be converted first to ISO weekday (Monday=0).
+ var isoday = (d.getDay() + 6) % 7;
+
+ // Position of given day in the picker grid w.r.t. first day of week
+ var daypos = (isoday - firstday + 7) % 7;
+
+ // Position of cut off day in the picker grid w.r.t. first day of week
+ var cutoffpos = (cutoff - firstday + 7) % 7;
+
+ // Unix timestamp of the midnight of the cutoff day in the week of 'd'.
+ // There might be +-1 hour shift in the result due to the daylight saving,
+ // but it doesn't affect the year.
+ var cutoffSameWeek = d.valueOf() +
+ (cutoffpos - daypos) * goog.date.MS_PER_DAY;
+
+ // Unix timestamp of January 1 in the year of 'cutoffSameWeek'.
+ var jan1 = new Date(new Date(cutoffSameWeek).getFullYear(), 0, 1).valueOf();
+
+ // Number of week. The round() eliminates the effect of daylight saving.
+ return Math.floor(Math.round(
+ (cutoffSameWeek - jan1) / goog.date.MS_PER_DAY) / 7) + 1;
+};
+
+
+/**
+ * @param {T} date1 A datelike object.
+ * @param {S} date2 Another datelike object.
+ * @return {T|S} The earlier of them in time.
+ * @template T,S
+ */
+goog.date.min = function(date1, date2) {
+ return date1 < date2 ? date1 : date2;
+};
+
+
+/**
+ * @param {T} date1 A datelike object.
+ * @param {S} date2 Another datelike object.
+ * @return {T|S} The later of them in time.
+ * @template T,S
+ */
+goog.date.max = function(date1, date2) {
+ return date1 > date2 ? date1 : date2;
+};
+
+
+/**
+ * Creates a DateTime from a datetime string expressed in ISO 8601 format.
+ *
+ * @param {string} formatted A date or datetime expressed in ISO 8601 format.
+ * @return {goog.date.DateTime} Parsed date or null if parse fails.
+ */
+goog.date.fromIsoString = function(formatted) {
+ var ret = new goog.date.DateTime(2000);
+ return goog.date.setIso8601DateTime(ret, formatted) ? ret : null;
+};
+
+
+/**
+ * Parses a datetime string expressed in ISO 8601 format. Overwrites the date
+ * and optionally the time part of the given object with the parsed values.
+ *
+ * @param {!goog.date.DateTime} dateTime Object whose fields will be set.
+ * @param {string} formatted A date or datetime expressed in ISO 8601 format.
+ * @return {boolean} Whether the parsing succeeded.
+ */
+goog.date.setIso8601DateTime = function(dateTime, formatted) {
+ formatted = goog.string.trim(formatted);
+ var delim = formatted.indexOf('T') == -1 ? ' ' : 'T';
+ var parts = formatted.split(delim);
+ return goog.date.setIso8601DateOnly_(dateTime, parts[0]) &&
+ (parts.length < 2 || goog.date.setIso8601TimeOnly_(dateTime, parts[1]));
+};
+
+
+/**
+ * Sets date fields based on an ISO 8601 format string.
+ *
+ * @param {!goog.date.DateTime} d Object whose fields will be set.
+ * @param {string} formatted A date expressed in ISO 8601 format.
+ * @return {boolean} Whether the parsing succeeded.
+ * @private
+ */
+goog.date.setIso8601DateOnly_ = function(d, formatted) {
+ // split the formatted ISO date string into its date fields
+ var parts = formatted.match(goog.date.splitDateStringRegex_);
+ if (!parts) {
+ return false;
+ }
+
+ var year = Number(parts[1]);
+ var month = Number(parts[2]);
+ var date = Number(parts[3]);
+ var dayOfYear = Number(parts[4]);
+ var week = Number(parts[5]);
+ // ISO weekdays start with 1, native getDay() values start with 0
+ var dayOfWeek = Number(parts[6]) || 1;
+
+ d.setFullYear(year);
+
+ if (dayOfYear) {
+ d.setDate(1);
+ d.setMonth(0);
+ var offset = dayOfYear - 1; // offset, so 1-indexed, i.e., skip day 1
+ d.add(new goog.date.Interval(goog.date.Interval.DAYS, offset));
+ } else if (week) {
+ goog.date.setDateFromIso8601Week_(d, week, dayOfWeek);
+ } else {
+ if (month) {
+ d.setDate(1);
+ d.setMonth(month - 1);
+ }
+ if (date) {
+ d.setDate(date);
+ }
+ }
+
+ return true;
+};
+
+
+/**
+ * Sets date fields based on an ISO 8601 week string.
+ * See {@link http://en.wikipedia.org/wiki/ISO_week_date}, "Relation with the
+ * Gregorian Calendar". The first week of a new ISO year is the week with the
+ * majority of its days in the new Gregorian year. I.e., ISO Week 1's Thursday
+ * is in that year. ISO weeks always start on Monday. So ISO Week 1 can
+ * contain a few days from the previous Gregorian year. And ISO weeks always
+ * end on Sunday, so the last ISO week (Week 52 or 53) can have a few days from
+ * the following Gregorian year.
+ * Example: '1997-W01' lasts from 1996-12-30 to 1997-01-05. January 1, 1997 is
+ * a Wednesday. So W01's Monday is Dec.30, 1996, and Sunday is January 5, 1997.
+ *
+ * @param {goog.date.DateTime} d Object whose fields will be set.
+ * @param {number} week ISO week number.
+ * @param {number} dayOfWeek ISO day of week.
+ * @private
+ */
+goog.date.setDateFromIso8601Week_ = function(d, week, dayOfWeek) {
+ // calculate offset for first week
+ d.setMonth(0);
+ d.setDate(1);
+ var jsDay = d.getDay();
+ // switch Sunday (0) to index 7; ISO days are 1-indexed
+ var jan1WeekDay = jsDay || 7;
+
+ var THURSDAY = 4;
+ if (jan1WeekDay <= THURSDAY) {
+ // was extended back to Monday
+ var startDelta = 1 - jan1WeekDay; // e.g., Thu(4) ==> -3
+ } else {
+ // was extended forward to Monday
+ startDelta = 8 - jan1WeekDay; // e.g., Fri(5) ==> +3
+ }
+
+ // find the absolute number of days to offset from the start of year
+ // to arrive close to the Gregorian equivalent (pending adjustments above)
+ // Note: decrement week multiplier by one because 1st week is
+ // represented by dayOfWeek value
+ var absoluteDays = Number(dayOfWeek) + (7 * (Number(week) - 1));
+
+ // convert from ISO weekday format to Gregorian calendar date
+ // note: subtract 1 because 1-indexed; offset should not include 1st of month
+ var delta = startDelta + absoluteDays - 1;
+ var interval = new goog.date.Interval(goog.date.Interval.DAYS, delta);
+ d.add(interval);
+};
+
+
+/**
+ * Sets time fields based on an ISO 8601 format string.
+ * Note: only time fields, not date fields.
+ *
+ * @param {!goog.date.DateTime} d Object whose fields will be set.
+ * @param {string} formatted A time expressed in ISO 8601 format.
+ * @return {boolean} Whether the parsing succeeded.
+ * @private
+ */
+goog.date.setIso8601TimeOnly_ = function(d, formatted) {
+ // first strip timezone info from the end
+ var parts = formatted.match(goog.date.splitTimezoneStringRegex_);
+
+ var offset = 0; // local time if no timezone info
+ if (parts) {
+ if (parts[0] != 'Z') {
+ offset = parts[2] * 60 + Number(parts[3]);
+ offset *= parts[1] == '-' ? 1 : -1;
+ }
+ offset -= d.getTimezoneOffset();
+ formatted = formatted.substr(0, formatted.length - parts[0].length);
+ }
+
+ // then work out the time
+ parts = formatted.match(goog.date.splitTimeStringRegex_);
+ if (!parts) {
+ return false;
+ }
+
+ d.setHours(Number(parts[1]));
+ d.setMinutes(Number(parts[2]) || 0);
+ d.setSeconds(Number(parts[3]) || 0);
+ d.setMilliseconds(parts[4] ? parts[4] * 1000 : 0);
+
+ if (offset != 0) {
+ // adjust the date and time according to the specified timezone
+ d.setTime(d.getTime() + offset * 60000);
+ }
+
+ return true;
+};
+
+
+
+/**
+ * Class representing a date/time interval. Used for date calculations.
+ * <pre>
+ * new goog.date.Interval(0, 1) // One month
+ * new goog.date.Interval(0, 0, 3, 1) // Three days and one hour
+ * new goog.date.Interval(goog.date.Interval.DAYS, 1) // One day
+ * </pre>
+ *
+ * @param {number|string=} opt_years Years or string representing date part.
+ * @param {number=} opt_months Months or number of whatever date part specified
+ * by first parameter.
+ * @param {number=} opt_days Days.
+ * @param {number=} opt_hours Hours.
+ * @param {number=} opt_minutes Minutes.
+ * @param {number=} opt_seconds Seconds.
+ * @constructor
+ * @struct
+ * @final
+ */
+goog.date.Interval = function(opt_years, opt_months, opt_days, opt_hours,
+ opt_minutes, opt_seconds) {
+ if (goog.isString(opt_years)) {
+ var type = opt_years;
+ var interval = /** @type {number} */ (opt_months);
+ this.years = type == goog.date.Interval.YEARS ? interval : 0;
+ this.months = type == goog.date.Interval.MONTHS ? interval : 0;
+ this.days = type == goog.date.Interval.DAYS ? interval : 0;
+ this.hours = type == goog.date.Interval.HOURS ? interval : 0;
+ this.minutes = type == goog.date.Interval.MINUTES ? interval : 0;
+ this.seconds = type == goog.date.Interval.SECONDS ? interval : 0;
+ } else {
+ this.years = /** @type {number} */ (opt_years) || 0;
+ this.months = opt_months || 0;
+ this.days = opt_days || 0;
+ this.hours = opt_hours || 0;
+ this.minutes = opt_minutes || 0;
+ this.seconds = opt_seconds || 0;
+ }
+};
+
+
+/**
+ * Parses an XML Schema duration (ISO 8601 extended).
+ * @see http://www.w3.org/TR/xmlschema-2/#duration
+ *
+ * @param {string} duration An XML schema duration in textual format.
+ * Recurring durations and weeks are not supported.
+ * @return {goog.date.Interval} The duration as a goog.date.Interval or null
+ * if the parse fails.
+ */
+goog.date.Interval.fromIsoString = function(duration) {
+ var parts = duration.match(goog.date.splitDurationRegex_);
+ if (!parts) {
+ return null;
+ }
+
+ var timeEmpty = !(parts[6] || parts[7] || parts[8]);
+ var dateTimeEmpty = timeEmpty && !(parts[2] || parts[3] || parts[4]);
+ if (dateTimeEmpty || timeEmpty && parts[5]) {
+ return null;
+ }
+
+ var negative = parts[1];
+ var years = parseInt(parts[2], 10) || 0;
+ var months = parseInt(parts[3], 10) || 0;
+ var days = parseInt(parts[4], 10) || 0;
+ var hours = parseInt(parts[6], 10) || 0;
+ var minutes = parseInt(parts[7], 10) || 0;
+ var seconds = parseFloat(parts[8]) || 0;
+ return negative ? new goog.date.Interval(-years, -months, -days,
+ -hours, -minutes, -seconds) :
+ new goog.date.Interval(years, months, days,
+ hours, minutes, seconds);
+};
+
+
+/**
+ * Serializes goog.date.Interval into XML Schema duration (ISO 8601 extended).
+ * @see http://www.w3.org/TR/xmlschema-2/#duration
+ *
+ * @param {boolean=} opt_verbose Include zero fields in the duration string.
+ * @return {?string} An XML schema duration in ISO 8601 extended format,
+ * or null if the interval contains both positive and negative fields.
+ */
+goog.date.Interval.prototype.toIsoString = function(opt_verbose) {
+ var minField = Math.min(this.years, this.months, this.days,
+ this.hours, this.minutes, this.seconds);
+ var maxField = Math.max(this.years, this.months, this.days,
+ this.hours, this.minutes, this.seconds);
+ if (minField < 0 && maxField > 0) {
+ return null;
+ }
+
+ // Return 0 seconds if all fields are zero.
+ if (!opt_verbose && minField == 0 && maxField == 0) {
+ return 'PT0S';
+ }
+
+ var res = [];
+
+ // Add sign and 'P' prefix.
+ if (minField < 0) {
+ res.push('-');
+ }
+ res.push('P');
+
+ // Add date.
+ if (this.years || opt_verbose) {
+ res.push(Math.abs(this.years) + 'Y');
+ }
+ if (this.months || opt_verbose) {
+ res.push(Math.abs(this.months) + 'M');
+ }
+ if (this.days || opt_verbose) {
+ res.push(Math.abs(this.days) + 'D');
+ }
+
+ // Add time.
+ if (this.hours || this.minutes || this.seconds || opt_verbose) {
+ res.push('T');
+ if (this.hours || opt_verbose) {
+ res.push(Math.abs(this.hours) + 'H');
+ }
+ if (this.minutes || opt_verbose) {
+ res.push(Math.abs(this.minutes) + 'M');
+ }
+ if (this.seconds || opt_verbose) {
+ res.push(Math.abs(this.seconds) + 'S');
+ }
+ }
+
+ return res.join('');
+};
+
+
+/**
+ * Tests whether the given interval is equal to this interval.
+ * Note, this is a simple field-by-field comparison, it doesn't
+ * account for comparisons like "12 months == 1 year".
+ *
+ * @param {goog.date.Interval} other The interval to test.
+ * @return {boolean} Whether the intervals are equal.
+ */
+goog.date.Interval.prototype.equals = function(other) {
+ return other.years == this.years &&
+ other.months == this.months &&
+ other.days == this.days &&
+ other.hours == this.hours &&
+ other.minutes == this.minutes &&
+ other.seconds == this.seconds;
+};
+
+
+/**
+ * @return {!goog.date.Interval} A clone of the interval object.
+ */
+goog.date.Interval.prototype.clone = function() {
+ return new goog.date.Interval(
+ this.years, this.months, this.days,
+ this.hours, this.minutes, this.seconds);
+};
+
+
+/**
+ * Years constant for the date parts.
+ * @type {string}
+ */
+goog.date.Interval.YEARS = 'y';
+
+
+/**
+ * Months constant for the date parts.
+ * @type {string}
+ */
+goog.date.Interval.MONTHS = 'm';
+
+
+/**
+ * Days constant for the date parts.
+ * @type {string}
+ */
+goog.date.Interval.DAYS = 'd';
+
+
+/**
+ * Hours constant for the date parts.
+ * @type {string}
+ */
+goog.date.Interval.HOURS = 'h';
+
+
+/**
+ * Minutes constant for the date parts.
+ * @type {string}
+ */
+goog.date.Interval.MINUTES = 'n';
+
+
+/**
+ * Seconds constant for the date parts.
+ * @type {string}
+ */
+goog.date.Interval.SECONDS = 's';
+
+
+/**
+ * @return {boolean} Whether all fields of the interval are zero.
+ */
+goog.date.Interval.prototype.isZero = function() {
+ return this.years == 0 &&
+ this.months == 0 &&
+ this.days == 0 &&
+ this.hours == 0 &&
+ this.minutes == 0 &&
+ this.seconds == 0;
+};
+
+
+/**
+ * @return {!goog.date.Interval} Negative of this interval.
+ */
+goog.date.Interval.prototype.getInverse = function() {
+ return this.times(-1);
+};
+
+
+/**
+ * Calculates n * (this interval) by memberwise multiplication.
+ * @param {number} n An integer.
+ * @return {!goog.date.Interval} n * this.
+ */
+goog.date.Interval.prototype.times = function(n) {
+ return new goog.date.Interval(this.years * n,
+ this.months * n,
+ this.days * n,
+ this.hours * n,
+ this.minutes * n,
+ this.seconds * n);
+};
+
+
+/**
+ * Gets the total number of seconds in the time interval. Assumes that months
+ * and years are empty.
+ * @return {number} Total number of seconds in the interval.
+ */
+goog.date.Interval.prototype.getTotalSeconds = function() {
+ goog.asserts.assert(this.years == 0 && this.months == 0);
+ return ((this.days * 24 + this.hours) * 60 + this.minutes) * 60 +
+ this.seconds;
+};
+
+
+/**
+ * Adds the Interval in the argument to this Interval field by field.
+ *
+ * @param {goog.date.Interval} interval The Interval to add.
+ */
+goog.date.Interval.prototype.add = function(interval) {
+ this.years += interval.years;
+ this.months += interval.months;
+ this.days += interval.days;
+ this.hours += interval.hours;
+ this.minutes += interval.minutes;
+ this.seconds += interval.seconds;
+};
+
+
+
+/**
+ * Class representing a date. Defaults to current date if none is specified.
+ *
+ * Implements most methods of the native js Date object (except the time related
+ * ones, {@see goog.date.DateTime}) and can be used interchangeably with it just
+ * as if goog.date.Date was a synonym of Date. To make this more transparent,
+ * Closure APIs should accept goog.date.DateLike instead of the real Date
+ * object.
+ *
+ * To allow goog.date.Date objects to be passed as arguments to methods
+ * expecting Date objects this class is marked as extending the built in Date
+ * object even though that's not strictly true.
+ *
+ * @param {number|goog.date.DateLike=} opt_year Four digit year or a date-like
+ * object. If not set, the created object will contain the date
+ * determined by goog.now().
+ * @param {number=} opt_month Month, 0 = Jan, 11 = Dec.
+ * @param {number=} opt_date Date of month, 1 - 31.
+ * @constructor
+ * @struct
+ * @see goog.date.DateTime
+ */
+goog.date.Date = function(opt_year, opt_month, opt_date) {
+ /** @protected {!Date} The wrapped date or datetime. */
+ this.date;
+ // goog.date.DateTime assumes that only this.date is added in this ctor.
+ if (goog.isNumber(opt_year)) {
+ this.date = this.buildDate_(opt_year, opt_month || 0, opt_date || 1);
+ this.maybeFixDst_(opt_date || 1);
+ } else if (goog.isObject(opt_year)) {
+ this.date = this.buildDate_(opt_year.getFullYear(), opt_year.getMonth(),
+ opt_year.getDate());
+ this.maybeFixDst_(opt_year.getDate());
+ } else {
+ this.date = new Date(goog.now());
+ this.date.setHours(0);
+ this.date.setMinutes(0);
+ this.date.setSeconds(0);
+ this.date.setMilliseconds(0);
+ }
+};
+
+
+/**
+ * new Date(y, m, d) treats years in the interval [0, 100) as two digit years,
+ * adding 1900 to them. This method ensures that calling the date constructor
+ * as a copy constructor returns a value that is equal to the passed in
+ * date value by explicitly setting the full year.
+ * @private
+ * @param {number} fullYear The full year (including century).
+ * @param {number} month The month, from 0-11.
+ * @param {number} date The day of the month.
+ * @return {!Date} The constructed Date object.
+ */
+goog.date.Date.prototype.buildDate_ = function(fullYear, month, date) {
+ var d = new Date(fullYear, month, date);
+ if (fullYear >= 0 && fullYear < 100) {
+ // Can't just setFullYear as new Date() can flip over for e.g. month = 13.
+ d.setFullYear(d.getFullYear() - 1900);
+ }
+ return d;
+};
+
+
+/**
+ * First day of week. 0 = Mon, 6 = Sun.
+ * @type {number}
+ * @private
+ */
+goog.date.Date.prototype.firstDayOfWeek_ =
+ goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK;
+
+
+/**
+ * The cut off weekday used for week number calculations. 0 = Mon, 6 = Sun.
+ * @type {number}
+ * @private
+ */
+goog.date.Date.prototype.firstWeekCutOffDay_ =
+ goog.i18n.DateTimeSymbols.FIRSTWEEKCUTOFFDAY;
+
+
+/**
+ * @return {!goog.date.Date} A clone of the date object.
+ */
+goog.date.Date.prototype.clone = function() {
+ var date = new goog.date.Date(this.date);
+ date.firstDayOfWeek_ = this.firstDayOfWeek_;
+ date.firstWeekCutOffDay_ = this.firstWeekCutOffDay_;
+
+ return date;
+};
+
+
+/**
+ * @return {number} The four digit year of date.
+ */
+goog.date.Date.prototype.getFullYear = function() {
+ return this.date.getFullYear();
+};
+
+
+/**
+ * Alias for getFullYear.
+ *
+ * @return {number} The four digit year of date.
+ * @see #getFullyear
+ */
+goog.date.Date.prototype.getYear = function() {
+ return this.getFullYear();
+};
+
+
+/**
+ * @return {goog.date.month} The month of date, 0 = Jan, 11 = Dec.
+ */
+goog.date.Date.prototype.getMonth = function() {
+ return /** @type {goog.date.month} */ (this.date.getMonth());
+};
+
+
+/**
+ * @return {number} The date of month.
+ */
+goog.date.Date.prototype.getDate = function() {
+ return this.date.getDate();
+};
+
+
+/**
+ * Returns the number of milliseconds since 1 January 1970 00:00:00.
+ *
+ * @return {number} The number of milliseconds since 1 January 1970 00:00:00.
+ */
+goog.date.Date.prototype.getTime = function() {
+ return this.date.getTime();
+};
+
+
+/**
+ * @return {number} The day of week, US style. 0 = Sun, 6 = Sat.
+ */
+goog.date.Date.prototype.getDay = function() {
+ return this.date.getDay();
+};
+
+
+/**
+ * @return {goog.date.weekDay} The day of week, ISO style. 0 = Mon, 6 = Sun.
+ */
+goog.date.Date.prototype.getIsoWeekday = function() {
+ return /** @type {goog.date.weekDay} */ ((this.getDay() + 6) % 7);
+};
+
+
+/**
+ * @return {number} The day of week according to firstDayOfWeek setting.
+ */
+goog.date.Date.prototype.getWeekday = function() {
+ return (this.getIsoWeekday() - this.firstDayOfWeek_ + 7) % 7;
+};
+
+
+/**
+ * @return {number} The four digit year of date according to universal time.
+ */
+goog.date.Date.prototype.getUTCFullYear = function() {
+ return this.date.getUTCFullYear();
+};
+
+
+/**
+ * @return {goog.date.month} The month of date according to universal time,
+ * 0 = Jan, 11 = Dec.
+ */
+goog.date.Date.prototype.getUTCMonth = function() {
+ return /** @type {goog.date.month} */ (this.date.getUTCMonth());
+};
+
+
+/**
+ * @return {number} The date of month according to universal time.
+ */
+goog.date.Date.prototype.getUTCDate = function() {
+ return this.date.getUTCDate();
+};
+
+
+/**
+ * @return {number} The day of week according to universal time, US style.
+ * 0 = Sun, 1 = Mon, 6 = Sat.
+ */
+goog.date.Date.prototype.getUTCDay = function() {
+ return this.date.getDay();
+};
+
+
+/**
+ * @return {number} The hours value according to universal time.
+ */
+goog.date.Date.prototype.getUTCHours = function() {
+ return this.date.getUTCHours();
+};
+
+
+/**
+ * @return {number} The hours value according to universal time.
+ */
+goog.date.Date.prototype.getUTCMinutes = function() {
+ return this.date.getUTCMinutes();
+};
+
+
+/**
+ * @return {goog.date.weekDay} The day of week according to universal time, ISO
+ * style. 0 = Mon, 6 = Sun.
+ */
+goog.date.Date.prototype.getUTCIsoWeekday = function() {
+ return /** @type {goog.date.weekDay} */ ((this.date.getUTCDay() + 6) % 7);
+};
+
+
+/**
+ * @return {number} The day of week according to universal time and
+ * firstDayOfWeek setting.
+ */
+goog.date.Date.prototype.getUTCWeekday = function() {
+ return (this.getUTCIsoWeekday() - this.firstDayOfWeek_ + 7) % 7;
+};
+
+
+/**
+ * @return {number} The first day of the week. 0 = Mon, 6 = Sun.
+ */
+goog.date.Date.prototype.getFirstDayOfWeek = function() {
+ return this.firstDayOfWeek_;
+};
+
+
+/**
+ * @return {number} The cut off weekday used for week number calculations.
+ * 0 = Mon, 6 = Sun.
+ */
+goog.date.Date.prototype.getFirstWeekCutOffDay = function() {
+ return this.firstWeekCutOffDay_;
+};
+
+
+/**
+ * @return {number} The number of days for the selected month.
+ */
+goog.date.Date.prototype.getNumberOfDaysInMonth = function() {
+ return goog.date.getNumberOfDaysInMonth(this.getFullYear(), this.getMonth());
+};
+
+
+/**
+ * @return {number} The week number.
+ */
+goog.date.Date.prototype.getWeekNumber = function() {
+ return goog.date.getWeekNumber(
+ this.getFullYear(), this.getMonth(), this.getDate(),
+ this.firstWeekCutOffDay_, this.firstDayOfWeek_);
+};
+
+
+/**
+ * @return {number} The day of year.
+ */
+goog.date.Date.prototype.getDayOfYear = function() {
+ var dayOfYear = this.getDate();
+ var year = this.getFullYear();
+ for (var m = this.getMonth() - 1; m >= 0; m--) {
+ dayOfYear += goog.date.getNumberOfDaysInMonth(year, m);
+ }
+
+ return dayOfYear;
+};
+
+
+/**
+ * Returns timezone offset. The timezone offset is the delta in minutes between
+ * UTC and your local time. E.g., UTC+10 returns -600. Daylight savings time
+ * prevents this value from being constant.
+ *
+ * @return {number} The timezone offset.
+ */
+goog.date.Date.prototype.getTimezoneOffset = function() {
+ return this.date.getTimezoneOffset();
+};
+
+
+/**
+ * Returns timezone offset as a string. Returns offset in [+-]HH:mm format or Z
+ * for UTC.
+ *
+ * @return {string} The timezone offset as a string.
+ */
+goog.date.Date.prototype.getTimezoneOffsetString = function() {
+ var tz;
+ var offset = this.getTimezoneOffset();
+
+ if (offset == 0) {
+ tz = 'Z';
+ } else {
+ var n = Math.abs(offset) / 60;
+ var h = Math.floor(n);
+ var m = (n - h) * 60;
+ tz = (offset > 0 ? '-' : '+') +
+ goog.string.padNumber(h, 2) + ':' +
+ goog.string.padNumber(m, 2);
+ }
+
+ return tz;
+};
+
+
+/**
+ * Sets the date.
+ *
+ * @param {goog.date.Date} date Date object to set date from.
+ */
+goog.date.Date.prototype.set = function(date) {
+ this.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
+};
+
+
+/**
+ * Sets the year part of the date.
+ *
+ * @param {number} year Four digit year.
+ */
+goog.date.Date.prototype.setFullYear = function(year) {
+ this.date.setFullYear(year);
+};
+
+
+/**
+ * Alias for setFullYear.
+ *
+ * @param {number} year Four digit year.
+ * @see #setFullYear
+ */
+goog.date.Date.prototype.setYear = function(year) {
+ this.setFullYear(year);
+};
+
+
+/**
+ * Sets the month part of the date.
+ *
+ * TODO(nnaze): Update type to goog.date.month.
+ *
+ * @param {number} month The month, where 0 = Jan, 11 = Dec.
+ */
+goog.date.Date.prototype.setMonth = function(month) {
+ this.date.setMonth(month);
+};
+
+
+/**
+ * Sets the day part of the date.
+ *
+ * @param {number} date The day part.
+ */
+goog.date.Date.prototype.setDate = function(date) {
+ this.date.setDate(date);
+};
+
+
+/**
+ * Sets the value of the date object as expressed in the number of milliseconds
+ * since 1 January 1970 00:00:00.
+ *
+ * @param {number} ms Number of milliseconds since 1 Jan 1970.
+ */
+goog.date.Date.prototype.setTime = function(ms) {
+ this.date.setTime(ms);
+};
+
+
+/**
+ * Sets the year part of the date according to universal time.
+ *
+ * @param {number} year Four digit year.
+ */
+goog.date.Date.prototype.setUTCFullYear = function(year) {
+ this.date.setUTCFullYear(year);
+};
+
+
+/**
+ * Sets the month part of the date according to universal time.
+ *
+ * @param {number} month The month, where 0 = Jan, 11 = Dec.
+ */
+goog.date.Date.prototype.setUTCMonth = function(month) {
+ this.date.setUTCMonth(month);
+};
+
+
+/**
+ * Sets the day part of the date according to universal time.
+ *
+ * @param {number} date The UTC date.
+ */
+goog.date.Date.prototype.setUTCDate = function(date) {
+ this.date.setUTCDate(date);
+};
+
+
+/**
+ * Sets the first day of week.
+ *
+ * @param {number} day 0 = Mon, 6 = Sun.
+ */
+goog.date.Date.prototype.setFirstDayOfWeek = function(day) {
+ this.firstDayOfWeek_ = day;
+};
+
+
+/**
+ * Sets cut off weekday used for week number calculations. 0 = Mon, 6 = Sun.
+ *
+ * @param {number} day The cut off weekday.
+ */
+goog.date.Date.prototype.setFirstWeekCutOffDay = function(day) {
+ this.firstWeekCutOffDay_ = day;
+};
+
+
+/**
+ * Performs date calculation by adding the supplied interval to the date.
+ *
+ * @param {goog.date.Interval} interval Date interval to add.
+ */
+goog.date.Date.prototype.add = function(interval) {
+ if (interval.years || interval.months) {
+ // As months have different number of days adding a month to Jan 31 by just
+ // setting the month would result in a date in early March rather than Feb
+ // 28 or 29. Doing it this way overcomes that problem.
+
+ // adjust year and month, accounting for both directions
+ var month = this.getMonth() + interval.months + interval.years * 12;
+ var year = this.getYear() + Math.floor(month / 12);
+ month %= 12;
+ if (month < 0) {
+ month += 12;
+ }
+
+ var daysInTargetMonth = goog.date.getNumberOfDaysInMonth(year, month);
+ var date = Math.min(daysInTargetMonth, this.getDate());
+
+ // avoid inadvertently causing rollovers to adjacent months
+ this.setDate(1);
+
+ this.setFullYear(year);
+ this.setMonth(month);
+ this.setDate(date);
+ }
+
+ if (interval.days) {
+ // Convert the days to milliseconds and add it to the UNIX timestamp.
+ // Taking noon helps to avoid 1 day error due to the daylight saving.
+ var noon = new Date(this.getYear(), this.getMonth(), this.getDate(), 12);
+ var result = new Date(noon.getTime() + interval.days * 86400000);
+
+ // Set date to 1 to prevent rollover caused by setting the year or month.
+ this.setDate(1);
+ this.setFullYear(result.getFullYear());
+ this.setMonth(result.getMonth());
+ this.setDate(result.getDate());
+
+ this.maybeFixDst_(result.getDate());
+ }
+};
+
+
+/**
+ * Returns ISO 8601 string representation of date.
+ *
+ * @param {boolean=} opt_verbose Whether the verbose format should be used
+ * instead of the default compact one.
+ * @param {boolean=} opt_tz Whether the timezone offset should be included
+ * in the string.
+ * @return {string} ISO 8601 string representation of date.
+ */
+goog.date.Date.prototype.toIsoString = function(opt_verbose, opt_tz) {
+ var str = [
+ this.getFullYear(),
+ goog.string.padNumber(this.getMonth() + 1, 2),
+ goog.string.padNumber(this.getDate(), 2)
+ ];
+
+ return str.join((opt_verbose) ? '-' : '') +
+ (opt_tz ? this.getTimezoneOffsetString() : '');
+};
+
+
+/**
+ * Returns ISO 8601 string representation of date according to universal time.
+ *
+ * @param {boolean=} opt_verbose Whether the verbose format should be used
+ * instead of the default compact one.
+ * @param {boolean=} opt_tz Whether the timezone offset should be included in
+ * the string.
+ * @return {string} ISO 8601 string representation of date according to
+ * universal time.
+ */
+goog.date.Date.prototype.toUTCIsoString = function(opt_verbose, opt_tz) {
+ var str = [
+ this.getUTCFullYear(),
+ goog.string.padNumber(this.getUTCMonth() + 1, 2),
+ goog.string.padNumber(this.getUTCDate(), 2)
+ ];
+
+ return str.join((opt_verbose) ? '-' : '') + (opt_tz ? 'Z' : '');
+};
+
+
+/**
+ * Tests whether given date is equal to this Date.
+ * Note: This ignores units more precise than days (hours and below)
+ * and also ignores timezone considerations.
+ *
+ * @param {goog.date.Date} other The date to compare.
+ * @return {boolean} Whether the given date is equal to this one.
+ */
+goog.date.Date.prototype.equals = function(other) {
+ return !!(other &&
+ this.getYear() == other.getYear() &&
+ this.getMonth() == other.getMonth() &&
+ this.getDate() == other.getDate());
+};
+
+
+/**
+ * Overloaded toString method for object.
+ * @return {string} ISO 8601 string representation of date.
+ * @override
+ */
+goog.date.Date.prototype.toString = function() {
+ return this.toIsoString();
+};
+
+
+/**
+ * Fixes date to account for daylight savings time in browsers that fail to do
+ * so automatically.
+ * @param {number} expected Expected date.
+ * @private
+ */
+goog.date.Date.prototype.maybeFixDst_ = function(expected) {
+ if (this.getDate() != expected) {
+ var dir = this.getDate() < expected ? 1 : -1;
+ this.date.setUTCHours(this.date.getUTCHours() + dir);
+ }
+};
+
+
+/**
+ * @return {number} Value of wrapped date.
+ * @override
+ */
+goog.date.Date.prototype.valueOf = function() {
+ return this.date.valueOf();
+};
+
+
+/**
+ * Compares two dates. May be used as a sorting function.
+ * @see goog.array.sort
+ * @param {!goog.date.DateLike} date1 Date to compare.
+ * @param {!goog.date.DateLike} date2 Date to compare.
+ * @return {number} Comparison result. 0 if dates are the same, less than 0 if
+ * date1 is earlier than date2, greater than 0 if date1 is later than date2.
+ */
+goog.date.Date.compare = function(date1, date2) {
+ return date1.getTime() - date2.getTime();
+};
+
+
+
+/**
+ * Class representing a date and time. Defaults to current date and time if none
+ * is specified.
+ *
+ * Implements most methods of the native js Date object and can be used
+ * interchangeably with it just as if goog.date.DateTime was a subclass of Date.
+ *
+ * @param {number|Object=} opt_year Four digit year or a date-like object. If
+ * not set, the created object will contain the date determined by
+ * goog.now().
+ * @param {number=} opt_month Month, 0 = Jan, 11 = Dec.
+ * @param {number=} opt_date Date of month, 1 - 31.
+ * @param {number=} opt_hours Hours, 0 - 23.
+ * @param {number=} opt_minutes Minutes, 0 - 59.
+ * @param {number=} opt_seconds Seconds, 0 - 61.
+ * @param {number=} opt_milliseconds Milliseconds, 0 - 999.
+ * @constructor
+ * @struct
+ * @extends {goog.date.Date}
+ */
+goog.date.DateTime = function(opt_year, opt_month, opt_date, opt_hours,
+ opt_minutes, opt_seconds, opt_milliseconds) {
+ if (goog.isNumber(opt_year)) {
+ this.date = new Date(opt_year, opt_month || 0, opt_date || 1,
+ opt_hours || 0, opt_minutes || 0, opt_seconds || 0,
+ opt_milliseconds || 0);
+ } else {
+ this.date = new Date(opt_year ? opt_year.getTime() : goog.now());
+ }
+};
+goog.inherits(goog.date.DateTime, goog.date.Date);
+
+
+/**
+ * @param {number} timestamp Number of milliseconds since Epoch.
+ * @return {!goog.date.DateTime}
+ */
+goog.date.DateTime.fromTimestamp = function(timestamp) {
+ var date = new goog.date.DateTime();
+ date.setTime(timestamp);
+ return date;
+};
+
+
+/**
+ * Creates a DateTime from a datetime string expressed in RFC 822 format.
+ *
+ * @param {string} formatted A date or datetime expressed in RFC 822 format.
+ * @return {goog.date.DateTime} Parsed date or null if parse fails.
+ */
+goog.date.DateTime.fromRfc822String = function(formatted) {
+ var date = new Date(formatted);
+ return !isNaN(date.getTime()) ? new goog.date.DateTime(date) : null;
+};
+
+
+/**
+ * Returns the hours part of the datetime.
+ *
+ * @return {number} An integer between 0 and 23, representing the hour.
+ */
+goog.date.DateTime.prototype.getHours = function() {
+ return this.date.getHours();
+};
+
+
+/**
+ * Returns the minutes part of the datetime.
+ *
+ * @return {number} An integer between 0 and 59, representing the minutes.
+ */
+goog.date.DateTime.prototype.getMinutes = function() {
+ return this.date.getMinutes();
+};
+
+
+/**
+ * Returns the seconds part of the datetime.
+ *
+ * @return {number} An integer between 0 and 59, representing the seconds.
+ */
+goog.date.DateTime.prototype.getSeconds = function() {
+ return this.date.getSeconds();
+};
+
+
+/**
+ * Returns the milliseconds part of the datetime.
+ *
+ * @return {number} An integer between 0 and 999, representing the milliseconds.
+ */
+goog.date.DateTime.prototype.getMilliseconds = function() {
+ return this.date.getMilliseconds();
+};
+
+
+/**
+ * Returns the day of week according to universal time, US style.
+ *
+ * @return {goog.date.weekDay} Day of week, 0 = Sun, 1 = Mon, 6 = Sat.
+ * @override
+ */
+goog.date.DateTime.prototype.getUTCDay = function() {
+ return /** @type {goog.date.weekDay} */ (this.date.getUTCDay());
+};
+
+
+/**
+ * Returns the hours part of the datetime according to universal time.
+ *
+ * @return {number} An integer between 0 and 23, representing the hour.
+ * @override
+ */
+goog.date.DateTime.prototype.getUTCHours = function() {
+ return this.date.getUTCHours();
+};
+
+
+/**
+ * Returns the minutes part of the datetime according to universal time.
+ *
+ * @return {number} An integer between 0 and 59, representing the minutes.
+ * @override
+ */
+goog.date.DateTime.prototype.getUTCMinutes = function() {
+ return this.date.getUTCMinutes();
+};
+
+
+/**
+ * Returns the seconds part of the datetime according to universal time.
+ *
+ * @return {number} An integer between 0 and 59, representing the seconds.
+ */
+goog.date.DateTime.prototype.getUTCSeconds = function() {
+ return this.date.getUTCSeconds();
+};
+
+
+/**
+ * Returns the milliseconds part of the datetime according to universal time.
+ *
+ * @return {number} An integer between 0 and 999, representing the milliseconds.
+ */
+goog.date.DateTime.prototype.getUTCMilliseconds = function() {
+ return this.date.getUTCMilliseconds();
+};
+
+
+/**
+ * Sets the hours part of the datetime.
+ *
+ * @param {number} hours An integer between 0 and 23, representing the hour.
+ */
+goog.date.DateTime.prototype.setHours = function(hours) {
+ this.date.setHours(hours);
+};
+
+
+/**
+ * Sets the minutes part of the datetime.
+ *
+ * @param {number} minutes Integer between 0 and 59, representing the minutes.
+ */
+goog.date.DateTime.prototype.setMinutes = function(minutes) {
+ this.date.setMinutes(minutes);
+};
+
+
+/**
+ * Sets the seconds part of the datetime.
+ *
+ * @param {number} seconds Integer between 0 and 59, representing the seconds.
+ */
+goog.date.DateTime.prototype.setSeconds = function(seconds) {
+ this.date.setSeconds(seconds);
+};
+
+
+/**
+ * Sets the seconds part of the datetime.
+ *
+ * @param {number} ms Integer between 0 and 999, representing the milliseconds.
+ */
+goog.date.DateTime.prototype.setMilliseconds = function(ms) {
+ this.date.setMilliseconds(ms);
+};
+
+
+/**
+ * Sets the hours part of the datetime according to universal time.
+ *
+ * @param {number} hours An integer between 0 and 23, representing the hour.
+ */
+goog.date.DateTime.prototype.setUTCHours = function(hours) {
+ this.date.setUTCHours(hours);
+};
+
+
+/**
+ * Sets the minutes part of the datetime according to universal time.
+ *
+ * @param {number} minutes Integer between 0 and 59, representing the minutes.
+ */
+goog.date.DateTime.prototype.setUTCMinutes = function(minutes) {
+ this.date.setUTCMinutes(minutes);
+};
+
+
+/**
+ * Sets the seconds part of the datetime according to universal time.
+ *
+ * @param {number} seconds Integer between 0 and 59, representing the seconds.
+ */
+goog.date.DateTime.prototype.setUTCSeconds = function(seconds) {
+ this.date.setUTCSeconds(seconds);
+};
+
+
+/**
+ * Sets the seconds part of the datetime according to universal time.
+ *
+ * @param {number} ms Integer between 0 and 999, representing the milliseconds.
+ */
+goog.date.DateTime.prototype.setUTCMilliseconds = function(ms) {
+ this.date.setUTCMilliseconds(ms);
+};
+
+
+/**
+ * @return {boolean} Whether the datetime is aligned to midnight.
+ */
+goog.date.DateTime.prototype.isMidnight = function() {
+ return this.getHours() == 0 && this.getMinutes() == 0 &&
+ this.getSeconds() == 0 && this.getMilliseconds() == 0;
+};
+
+
+/**
+ * Performs date calculation by adding the supplied interval to the date.
+ *
+ * @param {goog.date.Interval} interval Date interval to add.
+ * @override
+ */
+goog.date.DateTime.prototype.add = function(interval) {
+ goog.date.Date.prototype.add.call(this, interval);
+
+ if (interval.hours) {
+ this.setHours(this.date.getHours() + interval.hours);
+ }
+ if (interval.minutes) {
+ this.setMinutes(this.date.getMinutes() + interval.minutes);
+ }
+ if (interval.seconds) {
+ this.setSeconds(this.date.getSeconds() + interval.seconds);
+ }
+};
+
+
+/**
+ * Returns ISO 8601 string representation of date/time.
+ *
+ * @param {boolean=} opt_verbose Whether the verbose format should be used
+ * instead of the default compact one.
+ * @param {boolean=} opt_tz Whether the timezone offset should be included
+ * in the string.
+ * @return {string} ISO 8601 string representation of date/time.
+ * @override
+ */
+goog.date.DateTime.prototype.toIsoString = function(opt_verbose, opt_tz) {
+ var dateString = goog.date.Date.prototype.toIsoString.call(this, opt_verbose);
+
+ if (opt_verbose) {
+ return dateString + ' ' +
+ goog.string.padNumber(this.getHours(), 2) + ':' +
+ goog.string.padNumber(this.getMinutes(), 2) + ':' +
+ goog.string.padNumber(this.getSeconds(), 2) +
+ (opt_tz ? this.getTimezoneOffsetString() : '');
+ }
+
+ return dateString + 'T' +
+ goog.string.padNumber(this.getHours(), 2) +
+ goog.string.padNumber(this.getMinutes(), 2) +
+ goog.string.padNumber(this.getSeconds(), 2) +
+ (opt_tz ? this.getTimezoneOffsetString() : '');
+};
+
+
+/**
+ * Returns XML Schema 2 string representation of date/time.
+ * The return value is also ISO 8601 compliant.
+ *
+ * @param {boolean=} opt_timezone Should the timezone offset be included in the
+ * string?.
+ * @return {string} XML Schema 2 string representation of date/time.
+ */
+goog.date.DateTime.prototype.toXmlDateTime = function(opt_timezone) {
+ return goog.date.Date.prototype.toIsoString.call(this, true) + 'T' +
+ goog.string.padNumber(this.getHours(), 2) + ':' +
+ goog.string.padNumber(this.getMinutes(), 2) + ':' +
+ goog.string.padNumber(this.getSeconds(), 2) +
+ (opt_timezone ? this.getTimezoneOffsetString() : '');
+};
+
+
+/**
+ * Returns ISO 8601 string representation of date/time according to universal
+ * time.
+ *
+ * @param {boolean=} opt_verbose Whether the opt_verbose format should be
+ * returned instead of the default compact one.
+ * @param {boolean=} opt_tz Whether the the timezone offset should be included
+ * in the string.
+ * @return {string} ISO 8601 string representation of date/time according to
+ * universal time.
+ * @override
+ */
+goog.date.DateTime.prototype.toUTCIsoString = function(opt_verbose, opt_tz) {
+ var dateStr = goog.date.Date.prototype.toUTCIsoString.call(this, opt_verbose);
+
+ if (opt_verbose) {
+ return dateStr + ' ' +
+ goog.string.padNumber(this.getUTCHours(), 2) + ':' +
+ goog.string.padNumber(this.getUTCMinutes(), 2) + ':' +
+ goog.string.padNumber(this.getUTCSeconds(), 2) +
+ (opt_tz ? 'Z' : '');
+ }
+
+ return dateStr + 'T' +
+ goog.string.padNumber(this.getUTCHours(), 2) +
+ goog.string.padNumber(this.getUTCMinutes(), 2) +
+ goog.string.padNumber(this.getUTCSeconds(), 2) +
+ (opt_tz ? 'Z' : '');
+};
+
+
+/**
+ * Tests whether given datetime is exactly equal to this DateTime.
+ *
+ * @param {goog.date.Date} other The datetime to compare.
+ * @return {boolean} Whether the given datetime is exactly equal to this one.
+ * @override
+ */
+goog.date.DateTime.prototype.equals = function(other) {
+ return this.getTime() == other.getTime();
+};
+
+
+/**
+ * Overloaded toString method for object.
+ * @return {string} ISO 8601 string representation of date/time.
+ * @override
+ */
+goog.date.DateTime.prototype.toString = function() {
+ return this.toIsoString();
+};
+
+
+/**
+ * Generates time label for the datetime, e.g., '5:30am'.
+ * By default this does not pad hours (e.g., to '05:30') and it does add
+ * an am/pm suffix.
+ * TODO(user): i18n -- hardcoding time format like this is bad. E.g., in CJK
+ * locales, need Chinese characters for hour and minute units.
+ * @param {boolean=} opt_padHours Whether to pad hours, e.g., '05:30' vs '5:30'.
+ * @param {boolean=} opt_showAmPm Whether to show the 'am' and 'pm' suffix.
+ * @param {boolean=} opt_omitZeroMinutes E.g., '5:00pm' becomes '5pm',
+ * but '5:01pm' remains '5:01pm'.
+ * @return {string} The time label.
+ */
+goog.date.DateTime.prototype.toUsTimeString = function(opt_padHours,
+ opt_showAmPm,
+ opt_omitZeroMinutes) {
+ var hours = this.getHours();
+
+ // show am/pm marker by default
+ if (!goog.isDef(opt_showAmPm)) {
+ opt_showAmPm = true;
+ }
+
+ // 12pm
+ var isPM = hours == 12;
+
+ // change from 1-24 to 1-12 basis
+ if (hours > 12) {
+ hours -= 12;
+ isPM = true;
+ }
+
+ // midnight is expressed as "12am", but if am/pm marker omitted, keep as '0'
+ if (hours == 0 && opt_showAmPm) {
+ hours = 12;
+ }
+
+ var label = opt_padHours ? goog.string.padNumber(hours, 2) : String(hours);
+ var minutes = this.getMinutes();
+ if (!opt_omitZeroMinutes || minutes > 0) {
+ label += ':' + goog.string.padNumber(minutes, 2);
+ }
+
+ // by default, show am/pm suffix
+ if (opt_showAmPm) {
+ /**
+ * @desc Suffix for morning times.
+ */
+ var MSG_TIME_AM = goog.getMsg('am');
+
+ /**
+ * @desc Suffix for afternoon times.
+ */
+ var MSG_TIME_PM = goog.getMsg('pm');
+
+ label += isPM ? MSG_TIME_PM : MSG_TIME_AM;
+ }
+ return label;
+};
+
+
+/**
+ * Generates time label for the datetime in standard ISO 24-hour time format.
+ * E.g., '06:00:00' or '23:30:15'.
+ * @param {boolean=} opt_showSeconds Whether to shows seconds. Defaults to TRUE.
+ * @return {string} The time label.
+ */
+goog.date.DateTime.prototype.toIsoTimeString = function(opt_showSeconds) {
+ var hours = this.getHours();
+ var label = goog.string.padNumber(hours, 2) +
+ ':' +
+ goog.string.padNumber(this.getMinutes(), 2);
+ if (!goog.isDef(opt_showSeconds) || opt_showSeconds) {
+ label += ':' + goog.string.padNumber(this.getSeconds(), 2);
+ }
+ return label;
+};
+
+
+/**
+ * @return {!goog.date.DateTime} A clone of the datetime object.
+ * @override
+ */
+goog.date.DateTime.prototype.clone = function() {
+ var date = new goog.date.DateTime(this.date);
+ date.setFirstDayOfWeek(this.getFirstDayOfWeek());
+ date.setFirstWeekCutOffDay(this.getFirstWeekCutOffDay());
+ return date;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/date/datelike.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/date/datelike.js b/externs/GCL/externs/goog/date/datelike.js
new file mode 100644
index 0000000..ed18576
--- /dev/null
+++ b/externs/GCL/externs/goog/date/datelike.js
@@ -0,0 +1,27 @@
+// 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 Typedefs for working with dates.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.date.DateLike');
+
+
+/**
+ * @typedef {(Date|goog.date.Date)}
+ */
+goog.date.DateLike;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/date/daterange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/date/daterange.js b/externs/GCL/externs/goog/date/daterange.js
new file mode 100644
index 0000000..262001e
--- /dev/null
+++ b/externs/GCL/externs/goog/date/daterange.js
@@ -0,0 +1,430 @@
+// 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 Date range data structure. Based loosely on
+ * com.google.common.util.DateRange.
+ *
+ */
+
+goog.provide('goog.date.DateRange');
+goog.provide('goog.date.DateRange.Iterator');
+goog.provide('goog.date.DateRange.StandardDateRangeKeys');
+
+goog.require('goog.date.Date');
+goog.require('goog.date.Interval');
+goog.require('goog.iter.Iterator');
+goog.require('goog.iter.StopIteration');
+
+
+
+/**
+ * Constructs a date range.
+ * @constructor
+ * @struct
+ * @param {goog.date.Date} startDate The first date in the range.
+ * @param {goog.date.Date} endDate The last date in the range.
+ * @final
+ */
+goog.date.DateRange = function(startDate, endDate) {
+ /**
+ * The first date in the range.
+ * @type {goog.date.Date}
+ * @private
+ */
+ this.startDate_ = startDate;
+
+ /**
+ * The last date in the range.
+ * @type {goog.date.Date}
+ * @private
+ */
+ this.endDate_ = endDate;
+};
+
+
+/**
+ * The first possible day, as far as this class is concerned.
+ * @type {goog.date.Date}
+ */
+goog.date.DateRange.MINIMUM_DATE = new goog.date.Date(0, 0, 1);
+
+
+/**
+ * The last possible day, as far as this class is concerned.
+ * @type {goog.date.Date}
+ */
+goog.date.DateRange.MAXIMUM_DATE = new goog.date.Date(9999, 11, 31);
+
+
+/**
+ * @return {goog.date.Date} The first date in the range.
+ */
+goog.date.DateRange.prototype.getStartDate = function() {
+ return this.startDate_;
+};
+
+
+/**
+ * @return {goog.date.Date} The last date in the range.
+ */
+goog.date.DateRange.prototype.getEndDate = function() {
+ return this.endDate_;
+};
+
+
+/**
+ * Tests if a date falls within this range.
+ *
+ * @param {goog.date.Date} date The date to test.
+ * @return {boolean} Whether the date is in the range.
+ */
+goog.date.DateRange.prototype.contains = function(date) {
+ return date.valueOf() >= this.startDate_.valueOf() &&
+ date.valueOf() <= this.endDate_.valueOf();
+};
+
+
+/**
+ * @return {!goog.iter.Iterator} An iterator over the date range.
+ */
+goog.date.DateRange.prototype.iterator = function() {
+ return new goog.date.DateRange.Iterator(this);
+};
+
+
+/**
+ * Tests two {@link goog.date.DateRange} objects for equality.
+ * @param {goog.date.DateRange} a A date range.
+ * @param {goog.date.DateRange} b A date range.
+ * @return {boolean} Whether |a| is the same range as |b|.
+ */
+goog.date.DateRange.equals = function(a, b) {
+ // Test for same object reference; type conversion is irrelevant.
+ if (a === b) {
+ return true;
+ }
+
+ if (a == null || b == null) {
+ return false;
+ }
+
+ return a.startDate_.equals(b.startDate_) && a.endDate_.equals(b.endDate_);
+};
+
+
+/**
+ * Calculates a date that is a number of days after a date. Does not modify its
+ * input.
+ * @param {goog.date.Date} date The input date.
+ * @param {number} offset Number of days.
+ * @return {!goog.date.Date} The date that is |offset| days after |date|.
+ * @private
+ */
+goog.date.DateRange.offsetInDays_ = function(date, offset) {
+ var newDate = date.clone();
+ newDate.add(new goog.date.Interval(goog.date.Interval.DAYS, offset));
+ return newDate;
+};
+
+
+/**
+ * Calculates the Monday before a date. If the input is a Monday, returns the
+ * input. Does not modify its input.
+ * @param {goog.date.Date} date The input date.
+ * @return {!goog.date.Date} If |date| is a Monday, return |date|; otherwise
+ * return the Monday before |date|.
+ * @private
+ */
+goog.date.DateRange.currentOrLastMonday_ = function(date) {
+ var newDate = date.clone();
+ newDate.add(new goog.date.Interval(goog.date.Interval.DAYS,
+ -newDate.getIsoWeekday()));
+ return newDate;
+};
+
+
+/**
+ * Calculates a date that is a number of months after the first day in the
+ * month that contains its input. Does not modify its input.
+ * @param {goog.date.Date} date The input date.
+ * @param {number} offset Number of months.
+ * @return {!goog.date.Date} The date that is |offset| months after the first
+ * day in the month that contains |date|.
+ * @private
+ */
+goog.date.DateRange.offsetInMonths_ = function(date, offset) {
+ var newDate = date.clone();
+ newDate.setDate(1);
+ newDate.add(new goog.date.Interval(goog.date.Interval.MONTHS, offset));
+ return newDate;
+};
+
+
+/**
+ * Returns the range from yesterday to yesterday.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that includes only yesterday.
+ */
+goog.date.DateRange.yesterday = function(opt_today) {
+ var today = goog.date.DateRange.cloneOrCreate_(opt_today);
+ var yesterday = goog.date.DateRange.offsetInDays_(today, -1);
+ return new goog.date.DateRange(yesterday, yesterday);
+};
+
+
+/**
+ * Returns the range from today to today.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that includes only today.
+ */
+goog.date.DateRange.today = function(opt_today) {
+ var today = goog.date.DateRange.cloneOrCreate_(opt_today);
+ return new goog.date.DateRange(today, today);
+};
+
+
+/**
+ * Returns the range that includes the seven days that end yesterday.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that includes the seven days that
+ * end yesterday.
+ */
+goog.date.DateRange.last7Days = function(opt_today) {
+ var today = goog.date.DateRange.cloneOrCreate_(opt_today);
+ var yesterday = goog.date.DateRange.offsetInDays_(today, -1);
+ return new goog.date.DateRange(goog.date.DateRange.offsetInDays_(today, -7),
+ yesterday);
+};
+
+
+/**
+ * Returns the range that starts the first of this month and ends the last day
+ * of this month.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that starts the first of this month
+ * and ends the last day of this month.
+ */
+goog.date.DateRange.thisMonth = function(opt_today) {
+ var today = goog.date.DateRange.cloneOrCreate_(opt_today);
+ return new goog.date.DateRange(
+ goog.date.DateRange.offsetInMonths_(today, 0),
+ goog.date.DateRange.offsetInDays_(
+ goog.date.DateRange.offsetInMonths_(today, 1),
+ -1));
+};
+
+
+/**
+ * Returns the range that starts the first of last month and ends the last day
+ * of last month.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that starts the first of last month
+ * and ends the last day of last month.
+ */
+goog.date.DateRange.lastMonth = function(opt_today) {
+ var today = goog.date.DateRange.cloneOrCreate_(opt_today);
+ return new goog.date.DateRange(
+ goog.date.DateRange.offsetInMonths_(today, -1),
+ goog.date.DateRange.offsetInDays_(
+ goog.date.DateRange.offsetInMonths_(today, 0),
+ -1));
+};
+
+
+/**
+ * Returns the seven-day range that starts on the first day of the week
+ * (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) on or before today.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that starts the Monday on or before
+ * today and ends the Sunday on or after today.
+ */
+goog.date.DateRange.thisWeek = function(opt_today) {
+ var today = goog.date.DateRange.cloneOrCreate_(opt_today);
+ var iso = today.getIsoWeekday();
+ var firstDay = today.getFirstDayOfWeek();
+ var i18nFirstDay = (iso >= firstDay) ? iso - firstDay : iso + (7 - firstDay);
+ var start = goog.date.DateRange.offsetInDays_(today, -i18nFirstDay);
+ var end = goog.date.DateRange.offsetInDays_(start, 6);
+ return new goog.date.DateRange(start, end);
+};
+
+
+/**
+ * Returns the seven-day range that ends the day before the first day of
+ * the week (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) that
+ * contains today.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that starts seven days before the
+ * Monday on or before today and ends the Sunday on or before yesterday.
+ */
+goog.date.DateRange.lastWeek = function(opt_today) {
+ var thisWeek = goog.date.DateRange.thisWeek(opt_today);
+ var start = goog.date.DateRange.offsetInDays_(thisWeek.getStartDate(), -7);
+ var end = goog.date.DateRange.offsetInDays_(thisWeek.getEndDate(), -7);
+ return new goog.date.DateRange(start, end);
+};
+
+
+/**
+ * Returns the range that starts seven days before the Monday on or before
+ * today and ends the Friday before today.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that starts seven days before the
+ * Monday on or before today and ends the Friday before today.
+ */
+goog.date.DateRange.lastBusinessWeek = function(opt_today) {
+ // TODO(user): should be i18nized.
+ var today = goog.date.DateRange.cloneOrCreate_(opt_today);
+ var start = goog.date.DateRange.offsetInDays_(today,
+ - 7 - today.getIsoWeekday());
+ var end = goog.date.DateRange.offsetInDays_(start, 4);
+ return new goog.date.DateRange(start, end);
+};
+
+
+/**
+ * Returns the range that includes all days between January 1, 1900 and
+ * December 31, 9999.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The range that includes all days between
+ * January 1, 1900 and December 31, 9999.
+ */
+goog.date.DateRange.allTime = function(opt_today) {
+ return new goog.date.DateRange(
+ goog.date.DateRange.MINIMUM_DATE,
+ goog.date.DateRange.MAXIMUM_DATE);
+};
+
+
+/**
+ * Standard date range keys. Equivalent to the enum IDs in
+ * DateRange.java http://go/datarange.java
+ *
+ * @enum {string}
+ */
+goog.date.DateRange.StandardDateRangeKeys = {
+ YESTERDAY: 'yesterday',
+ TODAY: 'today',
+ LAST_7_DAYS: 'last7days',
+ THIS_MONTH: 'thismonth',
+ LAST_MONTH: 'lastmonth',
+ THIS_WEEK: 'thisweek',
+ LAST_WEEK: 'lastweek',
+ LAST_BUSINESS_WEEK: 'lastbusinessweek',
+ ALL_TIME: 'alltime'
+};
+
+
+/**
+ * @param {string} dateRangeKey A standard date range key.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.DateRange} The date range that corresponds to that key.
+ * @throws {Error} If no standard date range with that key exists.
+ */
+goog.date.DateRange.standardDateRange = function(dateRangeKey, opt_today) {
+ switch (dateRangeKey) {
+ case goog.date.DateRange.StandardDateRangeKeys.YESTERDAY:
+ return goog.date.DateRange.yesterday(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.TODAY:
+ return goog.date.DateRange.today(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.LAST_7_DAYS:
+ return goog.date.DateRange.last7Days(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.THIS_MONTH:
+ return goog.date.DateRange.thisMonth(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.LAST_MONTH:
+ return goog.date.DateRange.lastMonth(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.THIS_WEEK:
+ return goog.date.DateRange.thisWeek(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.LAST_WEEK:
+ return goog.date.DateRange.lastWeek(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.LAST_BUSINESS_WEEK:
+ return goog.date.DateRange.lastBusinessWeek(opt_today);
+
+ case goog.date.DateRange.StandardDateRangeKeys.ALL_TIME:
+ return goog.date.DateRange.allTime(opt_today);
+
+ default:
+ throw Error('no such date range key: ' + dateRangeKey);
+ }
+};
+
+
+/**
+ * Clones or creates new.
+ * @param {goog.date.Date=} opt_today The date to consider today.
+ * Defaults to today.
+ * @return {!goog.date.Date} cloned or new.
+ * @private
+ */
+goog.date.DateRange.cloneOrCreate_ = function(opt_today) {
+ return opt_today ? opt_today.clone() : new goog.date.Date();
+};
+
+
+
+/**
+ * Creates an iterator over the dates in a {@link goog.date.DateRange}.
+ * @constructor
+ * @struct
+ * @suppress {checkStructDictInheritance}
+ * @extends {goog.iter.Iterator}
+ * @param {goog.date.DateRange} dateRange The date range to iterate.
+ * @final
+ */
+goog.date.DateRange.Iterator = function(dateRange) {
+ /**
+ * The next date.
+ * @type {goog.date.Date}
+ * @private
+ */
+ this.nextDate_ = dateRange.getStartDate().clone();
+
+ /**
+ * The end date, expressed as an integer: YYYYMMDD.
+ * @type {number}
+ * @private
+ */
+ this.endDate_ = Number(dateRange.getEndDate().toIsoString());
+};
+goog.inherits(goog.date.DateRange.Iterator, goog.iter.Iterator);
+
+
+/** @override */
+goog.date.DateRange.Iterator.prototype.next = function() {
+ if (Number(this.nextDate_.toIsoString()) > this.endDate_) {
+ throw goog.iter.StopIteration;
+ }
+
+ var rv = this.nextDate_.clone();
+ this.nextDate_.add(new goog.date.Interval(goog.date.Interval.DAYS, 1));
+ return rv;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/date/duration.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/date/duration.js b/externs/GCL/externs/goog/date/duration.js
new file mode 100644
index 0000000..62ad584
--- /dev/null
+++ b/externs/GCL/externs/goog/date/duration.js
@@ -0,0 +1,153 @@
+// 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 Functions for formatting duration values. Such as "3 days"
+ * "3 hours", "14 minutes", "2 hours 45 minutes".
+ *
+ */
+
+goog.provide('goog.date.duration');
+
+goog.require('goog.i18n.DateTimeFormat');
+goog.require('goog.i18n.MessageFormat');
+
+
+/**
+ * Number of milliseconds in a minute.
+ * @type {number}
+ * @private
+ */
+goog.date.duration.MINUTE_MS_ = 60000;
+
+
+/**
+ * Number of milliseconds in an hour.
+ * @type {number}
+ * @private
+ */
+goog.date.duration.HOUR_MS_ = 3600000;
+
+
+/**
+ * Number of milliseconds in a day.
+ * @type {number}
+ * @private
+ */
+goog.date.duration.DAY_MS_ = 86400000;
+
+
+/**
+ * Accepts a duration in milliseconds and outputs an absolute duration time in
+ * form of "1 day", "2 hours", "20 minutes", "2 days 1 hour 15 minutes" etc.
+ * @param {number} durationMs Duration in milliseconds.
+ * @return {string} The formatted duration.
+ */
+goog.date.duration.format = function(durationMs) {
+ var ms = Math.abs(durationMs);
+
+ // Handle durations shorter than 1 minute.
+ if (ms < goog.date.duration.MINUTE_MS_) {
+ /**
+ * @desc Duration time of zero minutes.
+ */
+ var MSG_ZERO_MINUTES = goog.getMsg('0 minutes');
+ return MSG_ZERO_MINUTES;
+ }
+
+ var days = Math.floor(ms / goog.date.duration.DAY_MS_);
+ ms %= goog.date.duration.DAY_MS_;
+
+ var hours = Math.floor(ms / goog.date.duration.HOUR_MS_);
+ ms %= goog.date.duration.HOUR_MS_;
+
+ var minutes = Math.floor(ms / goog.date.duration.MINUTE_MS_);
+
+ // Localized number representations.
+ var daysText = goog.i18n.DateTimeFormat.localizeNumbers(days);
+ var hoursText = goog.i18n.DateTimeFormat.localizeNumbers(hours);
+ var minutesText = goog.i18n.DateTimeFormat.localizeNumbers(minutes);
+
+ // We need a space after the days if there are hours or minutes to come.
+ var daysSeparator = days * (hours + minutes) ? ' ' : '';
+ // We need a space after the hours if there are minutes to come.
+ var hoursSeparator = hours * minutes ? ' ' : '';
+
+ /**
+ * @desc The days part of the duration message: 1 day, 5 days.
+ */
+ var MSG_DURATION_DAYS = goog.getMsg(
+ '{COUNT, plural, ' +
+ '=0 {}' +
+ '=1 {{TEXT} day}' +
+ 'other {{TEXT} days}}');
+ /**
+ * @desc The hours part of the duration message: 1 hour, 5 hours.
+ */
+ var MSG_DURATION_HOURS = goog.getMsg(
+ '{COUNT, plural, ' +
+ '=0 {}' +
+ '=1 {{TEXT} hour}' +
+ 'other {{TEXT} hours}}');
+ /**
+ * @desc The minutes part of the duration message: 1 minute, 5 minutes.
+ */
+ var MSG_DURATION_MINUTES = goog.getMsg(
+ '{COUNT, plural, ' +
+ '=0 {}' +
+ '=1 {{TEXT} minute}' +
+ 'other {{TEXT} minutes}}');
+
+ var daysPart = goog.date.duration.getDurationMessagePart_(
+ MSG_DURATION_DAYS, days, daysText);
+ var hoursPart = goog.date.duration.getDurationMessagePart_(
+ MSG_DURATION_HOURS, hours, hoursText);
+ var minutesPart = goog.date.duration.getDurationMessagePart_(
+ MSG_DURATION_MINUTES, minutes, minutesText);
+
+ /**
+ * @desc Duration time text concatenated from the individual time unit message
+ * parts. The separator will be a space (e.g. '1 day 2 hours 24 minutes') or
+ * nothing in case one/two of the duration parts is empty (
+ * e.g. '1 hour 30 minutes', '3 days 15 minutes', '2 hours').
+ */
+ var MSG_CONCATENATED_DURATION_TEXT = goog.getMsg(
+ '{$daysPart}{$daysSeparator}{$hoursPart}{$hoursSeparator}{$minutesPart}',
+ {
+ 'daysPart': daysPart,
+ 'daysSeparator': daysSeparator,
+ 'hoursPart': hoursPart,
+ 'hoursSeparator': hoursSeparator,
+ 'minutesPart': minutesPart
+ });
+
+ return MSG_CONCATENATED_DURATION_TEXT;
+};
+
+
+/**
+ * Gets a duration message part for a time unit.
+ * @param {string} pattern The pattern to apply.
+ * @param {number} count The number of units.
+ * @param {string} text The string to use for amount of units in the message.
+ * @return {string} The formatted message part.
+ * @private
+ */
+goog.date.duration.getDurationMessagePart_ = function(pattern, count, text) {
+ var formatter = new goog.i18n.MessageFormat(pattern);
+ return formatter.format({
+ 'COUNT': count,
+ 'TEXT': text
+ });
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/date/relative.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/date/relative.js b/externs/GCL/externs/goog/date/relative.js
new file mode 100644
index 0000000..890dcc1
--- /dev/null
+++ b/externs/GCL/externs/goog/date/relative.js
@@ -0,0 +1,490 @@
+// Copyright 2009 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 Functions for formatting relative dates. Such as "3 days ago"
+ * "3 hours ago", "14 minutes ago", "12 days ago", "Today", "Yesterday".
+ *
+ * For better quality localization of plurals ("hours"/"minutes"/"days") and
+ * to use local digits, goog.date.relativeWithPlurals can be loaded in addition
+ * to this namespace.
+ *
+ */
+
+goog.provide('goog.date.relative');
+goog.provide('goog.date.relative.TimeDeltaFormatter');
+goog.provide('goog.date.relative.Unit');
+
+goog.require('goog.i18n.DateTimeFormat');
+goog.require('goog.i18n.DateTimePatterns');
+
+
+/**
+ * Number of milliseconds in a minute.
+ * @type {number}
+ * @private
+ */
+goog.date.relative.MINUTE_MS_ = 60000;
+
+
+/**
+ * Number of milliseconds in a day.
+ * @type {number}
+ * @private
+ */
+goog.date.relative.DAY_MS_ = 86400000;
+
+
+/**
+ * Enumeration used to identify time units internally.
+ * @enum {number}
+ */
+goog.date.relative.Unit = {
+ MINUTES: 0,
+ HOURS: 1,
+ DAYS: 2
+};
+
+
+/**
+ * Full date formatter.
+ * @type {goog.i18n.DateTimeFormat}
+ * @private
+ */
+goog.date.relative.fullDateFormatter_;
+
+
+/**
+ * Short time formatter.
+ * @type {goog.i18n.DateTimeFormat}
+ * @private
+ */
+goog.date.relative.shortTimeFormatter_;
+
+
+/**
+ * Month-date formatter.
+ * @type {goog.i18n.DateTimeFormat}
+ * @private
+ */
+goog.date.relative.monthDateFormatter_;
+
+
+/**
+ * @typedef {function(number, boolean, goog.date.relative.Unit): string}
+ */
+goog.date.relative.TimeDeltaFormatter;
+
+
+/**
+ * Handles formatting of time deltas.
+ * @private {goog.date.relative.TimeDeltaFormatter}
+ */
+goog.date.relative.formatTimeDelta_;
+
+
+/**
+ * Sets a different formatting function for time deltas ("3 days ago").
+ * While its visibility is public, this function is Closure-internal and should
+ * not be used in application code.
+ * @param {goog.date.relative.TimeDeltaFormatter} formatter The function to use
+ * for formatting time deltas (i.e. relative times).
+ */
+goog.date.relative.setTimeDeltaFormatter = function(formatter) {
+ goog.date.relative.formatTimeDelta_ = formatter;
+};
+
+
+/**
+ * Returns a date in month format, e.g. Mar 15.
+ * @param {Date} date The date object.
+ * @return {string} The formatted string.
+ * @private
+ */
+goog.date.relative.formatMonth_ = function(date) {
+ if (!goog.date.relative.monthDateFormatter_) {
+ goog.date.relative.monthDateFormatter_ = new goog.i18n.DateTimeFormat(
+ goog.i18n.DateTimePatterns.MONTH_DAY_ABBR);
+ }
+ return goog.date.relative.monthDateFormatter_.format(date);
+};
+
+
+/**
+ * Returns a date in short-time format, e.g. 2:50 PM.
+ * @param {Date|goog.date.DateTime} date The date object.
+ * @return {string} The formatted string.
+ * @private
+ */
+goog.date.relative.formatShortTime_ = function(date) {
+ if (!goog.date.relative.shortTimeFormatter_) {
+ goog.date.relative.shortTimeFormatter_ = new goog.i18n.DateTimeFormat(
+ goog.i18n.DateTimeFormat.Format.SHORT_TIME);
+ }
+ return goog.date.relative.shortTimeFormatter_.format(date);
+};
+
+
+/**
+ * Returns a date in full date format, e.g. Tuesday, March 24, 2009.
+ * @param {Date|goog.date.DateTime} date The date object.
+ * @return {string} The formatted string.
+ * @private
+ */
+goog.date.relative.formatFullDate_ = function(date) {
+ if (!goog.date.relative.fullDateFormatter_) {
+ goog.date.relative.fullDateFormatter_ = new goog.i18n.DateTimeFormat(
+ goog.i18n.DateTimeFormat.Format.FULL_DATE);
+ }
+ return goog.date.relative.fullDateFormatter_.format(date);
+};
+
+
+/**
+ * Accepts a timestamp in milliseconds and outputs a relative time in the form
+ * of "1 hour ago", "1 day ago", "in 1 hour", "in 2 days" etc. If the date
+ * delta is over 2 weeks, then the output string will be empty.
+ * @param {number} dateMs Date in milliseconds.
+ * @return {string} The formatted date.
+ */
+goog.date.relative.format = function(dateMs) {
+ var now = goog.now();
+ var delta = Math.floor((now - dateMs) / goog.date.relative.MINUTE_MS_);
+
+ var future = false;
+
+ if (delta < 0) {
+ future = true;
+ delta *= -1;
+ }
+
+ if (delta < 60) { // Minutes.
+ return goog.date.relative.formatTimeDelta_(
+ delta, future, goog.date.relative.Unit.MINUTES);
+
+ } else {
+ delta = Math.floor(delta / 60);
+ if (delta < 24) { // Hours.
+ return goog.date.relative.formatTimeDelta_(
+ delta, future, goog.date.relative.Unit.HOURS);
+
+ } else {
+ // We can be more than 24 hours apart but still only 1 day apart, so we
+ // compare the closest time from today against the target time to find
+ // the number of days in the delta.
+ var midnight = new Date(goog.now());
+ midnight.setHours(0);
+ midnight.setMinutes(0);
+ midnight.setSeconds(0);
+ midnight.setMilliseconds(0);
+
+ // Convert to days ago.
+ delta = Math.ceil(
+ (midnight.getTime() - dateMs) / goog.date.relative.DAY_MS_);
+
+ if (future) {
+ delta *= -1;
+ }
+
+ // Uses days for less than 2-weeks.
+ if (delta < 14) {
+ return goog.date.relative.formatTimeDelta_(
+ delta, future, goog.date.relative.Unit.DAYS);
+
+ } else {
+ // For messages older than 2 weeks do not show anything. The client
+ // should decide the date format to show.
+ return '';
+ }
+ }
+ }
+};
+
+
+/**
+ * Accepts a timestamp in milliseconds and outputs a relative time in the form
+ * of "1 hour ago", "1 day ago". All future times will be returned as 0 minutes
+ * ago.
+ *
+ * This is provided for compatibility with users of the previous incarnation of
+ * the above {@see #format} method who relied on it protecting against
+ * future dates.
+ *
+ * @param {number} dateMs Date in milliseconds.
+ * @return {string} The formatted date.
+ */
+goog.date.relative.formatPast = function(dateMs) {
+ var now = goog.now();
+ if (now < dateMs) {
+ dateMs = now;
+ }
+ return goog.date.relative.format(dateMs);
+};
+
+
+/**
+ * Accepts a timestamp in milliseconds and outputs a relative day. i.e. "Today",
+ * "Yesterday", "Tomorrow", or "Sept 15".
+ *
+ * @param {number} dateMs Date in milliseconds.
+ * @param {function(!Date):string=} opt_formatter Formatter for the date.
+ * Defaults to form 'MMM dd'.
+ * @return {string} The formatted date.
+ */
+goog.date.relative.formatDay = function(dateMs, opt_formatter) {
+ var today = new Date(goog.now());
+
+ today.setHours(0);
+ today.setMinutes(0);
+ today.setSeconds(0);
+ today.setMilliseconds(0);
+
+ var yesterday = new Date(today.getTime() - goog.date.relative.DAY_MS_);
+ var tomorrow = new Date(today.getTime() + goog.date.relative.DAY_MS_);
+ var dayAfterTomorrow = new Date(today.getTime() +
+ 2 * goog.date.relative.DAY_MS_);
+
+ var message;
+ if (dateMs >= tomorrow.getTime() && dateMs < dayAfterTomorrow.getTime()) {
+ /** @desc Tomorrow. */
+ var MSG_TOMORROW = goog.getMsg('Tomorrow');
+ message = MSG_TOMORROW;
+ } else if (dateMs >= today.getTime() && dateMs < tomorrow.getTime()) {
+ /** @desc Today. */
+ var MSG_TODAY = goog.getMsg('Today');
+ message = MSG_TODAY;
+ } else if (dateMs >= yesterday.getTime() && dateMs < today.getTime()) {
+ /** @desc Yesterday. */
+ var MSG_YESTERDAY = goog.getMsg('Yesterday');
+ message = MSG_YESTERDAY;
+ } else {
+ // If we don't have a special relative term for this date, then return the
+ // short date format (or a custom-formatted date).
+ var formatFunction = opt_formatter || goog.date.relative.formatMonth_;
+ message = formatFunction(new Date(dateMs));
+ }
+ return message;
+};
+
+
+/**
+ * Formats a date, adding the relative date in parenthesis. If the date is less
+ * than 24 hours then the time will be printed, otherwise the full-date will be
+ * used. Examples:
+ * 2:20 PM (1 minute ago)
+ * Monday, February 27, 2009 (4 days ago)
+ * Tuesday, March 20, 2005 // Too long ago for a relative date.
+ *
+ * @param {Date|goog.date.DateTime} date A date object.
+ * @param {string=} opt_shortTimeMsg An optional short time message can be
+ * provided if available, so that it's not recalculated in this function.
+ * @param {string=} opt_fullDateMsg An optional date message can be
+ * provided if available, so that it's not recalculated in this function.
+ * @return {string} The date string in the above form.
+ */
+goog.date.relative.getDateString = function(
+ date, opt_shortTimeMsg, opt_fullDateMsg) {
+ return goog.date.relative.getDateString_(
+ date, goog.date.relative.format, opt_shortTimeMsg, opt_fullDateMsg);
+};
+
+
+/**
+ * Formats a date, adding the relative date in parenthesis. Functions the same
+ * as #getDateString but ensures that the date is always seen to be in the past.
+ * If the date is in the future, it will be shown as 0 minutes ago.
+ *
+ * This is provided for compatibility with users of the previous incarnation of
+ * the above {@see #getDateString} method who relied on it protecting against
+ * future dates.
+ *
+ * @param {Date|goog.date.DateTime} date A date object.
+ * @param {string=} opt_shortTimeMsg An optional short time message can be
+ * provided if available, so that it's not recalculated in this function.
+ * @param {string=} opt_fullDateMsg An optional date message can be
+ * provided if available, so that it's not recalculated in this function.
+ * @return {string} The date string in the above form.
+ */
+goog.date.relative.getPastDateString = function(
+ date, opt_shortTimeMsg, opt_fullDateMsg) {
+ return goog.date.relative.getDateString_(
+ date, goog.date.relative.formatPast, opt_shortTimeMsg, opt_fullDateMsg);
+};
+
+
+/**
+ * Formats a date, adding the relative date in parenthesis. If the date is less
+ * than 24 hours then the time will be printed, otherwise the full-date will be
+ * used. Examples:
+ * 2:20 PM (1 minute ago)
+ * Monday, February 27, 2009 (4 days ago)
+ * Tuesday, March 20, 2005 // Too long ago for a relative date.
+ *
+ * @param {Date|goog.date.DateTime} date A date object.
+ * @param {function(number) : string} relativeFormatter Function to use when
+ * formatting the relative date.
+ * @param {string=} opt_shortTimeMsg An optional short time message can be
+ * provided if available, so that it's not recalculated in this function.
+ * @param {string=} opt_fullDateMsg An optional date message can be
+ * provided if available, so that it's not recalculated in this function.
+ * @return {string} The date string in the above form.
+ * @private
+ */
+goog.date.relative.getDateString_ = function(
+ date, relativeFormatter, opt_shortTimeMsg, opt_fullDateMsg) {
+ var dateMs = date.getTime();
+
+ var relativeDate = relativeFormatter(dateMs);
+
+ if (relativeDate) {
+ relativeDate = ' (' + relativeDate + ')';
+ }
+
+ var delta = Math.floor((goog.now() - dateMs) / goog.date.relative.MINUTE_MS_);
+ if (delta < 60 * 24) {
+ // TODO(user): this call raises an exception if date is a goog.date.Date.
+ return (opt_shortTimeMsg || goog.date.relative.formatShortTime_(date)) +
+ relativeDate;
+ } else {
+ return (opt_fullDateMsg || goog.date.relative.formatFullDate_(date)) +
+ relativeDate;
+ }
+};
+
+
+/*
+ * TODO(user):
+ *
+ * I think that this whole relative formatting should move to DateTimeFormat.
+ * But we would have to wait for the next version of CLDR, which is cleaning
+ * the data for relative dates (even ICU has incomplete support for this).
+ */
+/**
+ * Gets a localized relative date string for a given delta and unit.
+ * @param {number} delta Number of minutes/hours/days.
+ * @param {boolean} future Whether the delta is in the future.
+ * @param {goog.date.relative.Unit} unit The units the delta is in.
+ * @return {string} The message.
+ * @private
+ */
+goog.date.relative.getMessage_ = function(delta, future, unit) {
+ var deltaFormatted = goog.i18n.DateTimeFormat.localizeNumbers(delta);
+ if (!future && unit == goog.date.relative.Unit.MINUTES) {
+ /**
+ * @desc Relative date indicating how many minutes ago something happened
+ * (singular).
+ */
+ var MSG_MINUTES_AGO_SINGULAR =
+ goog.getMsg('{$num} minute ago', {'num' : deltaFormatted});
+
+ /**
+ * @desc Relative date indicating how many minutes ago something happened
+ * (plural).
+ */
+ var MSG_MINUTES_AGO_PLURAL =
+ goog.getMsg('{$num} minutes ago', {'num' : deltaFormatted});
+
+ return delta == 1 ? MSG_MINUTES_AGO_SINGULAR : MSG_MINUTES_AGO_PLURAL;
+
+ } else if (future && unit == goog.date.relative.Unit.MINUTES) {
+ /**
+ * @desc Relative date indicating in how many minutes something happens
+ * (singular).
+ */
+ var MSG_IN_MINUTES_SINGULAR =
+ goog.getMsg('in {$num} minute', {'num' : deltaFormatted});
+
+ /**
+ * @desc Relative date indicating in how many minutes something happens
+ * (plural).
+ */
+ var MSG_IN_MINUTES_PLURAL =
+ goog.getMsg('in {$num} minutes', {'num' : deltaFormatted});
+
+ return delta == 1 ? MSG_IN_MINUTES_SINGULAR : MSG_IN_MINUTES_PLURAL;
+
+ } else if (!future && unit == goog.date.relative.Unit.HOURS) {
+ /**
+ * @desc Relative date indicating how many hours ago something happened
+ * (singular).
+ */
+ var MSG_HOURS_AGO_SINGULAR =
+ goog.getMsg('{$num} hour ago', {'num' : deltaFormatted});
+
+ /**
+ * @desc Relative date indicating how many hours ago something happened
+ * (plural).
+ */
+ var MSG_HOURS_AGO_PLURAL =
+ goog.getMsg('{$num} hours ago', {'num' : deltaFormatted});
+
+ return delta == 1 ? MSG_HOURS_AGO_SINGULAR : MSG_HOURS_AGO_PLURAL;
+
+ } else if (future && unit == goog.date.relative.Unit.HOURS) {
+ /**
+ * @desc Relative date indicating in how many hours something happens
+ * (singular).
+ */
+ var MSG_IN_HOURS_SINGULAR =
+ goog.getMsg('in {$num} hour', {'num' : deltaFormatted});
+
+ /**
+ * @desc Relative date indicating in how many hours something happens
+ * (plural).
+ */
+ var MSG_IN_HOURS_PLURAL =
+ goog.getMsg('in {$num} hours', {'num' : deltaFormatted});
+
+ return delta == 1 ? MSG_IN_HOURS_SINGULAR : MSG_IN_HOURS_PLURAL;
+
+ } else if (!future && unit == goog.date.relative.Unit.DAYS) {
+ /**
+ * @desc Relative date indicating how many days ago something happened
+ * (singular).
+ */
+ var MSG_DAYS_AGO_SINGULAR =
+ goog.getMsg('{$num} day ago', {'num' : deltaFormatted});
+
+ /**
+ * @desc Relative date indicating how many days ago something happened
+ * (plural).
+ */
+ var MSG_DAYS_AGO_PLURAL =
+ goog.getMsg('{$num} days ago', {'num' : deltaFormatted});
+
+ return delta == 1 ? MSG_DAYS_AGO_SINGULAR : MSG_DAYS_AGO_PLURAL;
+
+ } else if (future && unit == goog.date.relative.Unit.DAYS) {
+ /**
+ * @desc Relative date indicating in how many days something happens
+ * (singular).
+ */
+ var MSG_IN_DAYS_SINGULAR =
+ goog.getMsg('in {$num} day', {'num' : deltaFormatted});
+
+ /**
+ * @desc Relative date indicating in how many days something happens
+ * (plural).
+ */
+ var MSG_IN_DAYS_PLURAL =
+ goog.getMsg('in {$num} days', {'num' : deltaFormatted});
+
+ return delta == 1 ? MSG_IN_DAYS_SINGULAR : MSG_IN_DAYS_PLURAL;
+
+ } else {
+ return '';
+ }
+};
+
+goog.date.relative.setTimeDeltaFormatter(goog.date.relative.getMessage_);
[08/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/history/html5history.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/history/html5history.js b/externs/GCL/externs/goog/history/html5history.js
new file mode 100644
index 0000000..038d711
--- /dev/null
+++ b/externs/GCL/externs/goog/history/html5history.js
@@ -0,0 +1,303 @@
+// 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 HTML5 based history implementation, compatible with
+ * goog.History.
+ *
+ * TODO(user): There should really be a history interface and multiple
+ * implementations.
+ *
+ */
+
+
+goog.provide('goog.history.Html5History');
+goog.provide('goog.history.Html5History.TokenTransformer');
+
+goog.require('goog.asserts');
+goog.require('goog.events');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.history.Event');
+
+
+
+/**
+ * An implementation compatible with goog.History that uses the HTML5
+ * history APIs.
+ *
+ * @param {Window=} opt_win The window to listen/dispatch history events on.
+ * @param {goog.history.Html5History.TokenTransformer=} opt_transformer
+ * The token transformer that is used to create URL from the token
+ * when storing token without using hash fragment.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.history.Html5History = function(opt_win, opt_transformer) {
+ goog.events.EventTarget.call(this);
+ goog.asserts.assert(goog.history.Html5History.isSupported(opt_win),
+ 'HTML5 history is not supported.');
+
+ /**
+ * The window object to use for history tokens. Typically the top window.
+ * @type {Window}
+ * @private
+ */
+ this.window_ = opt_win || window;
+
+ /**
+ * The token transformer that is used to create URL from the token
+ * when storing token without using hash fragment.
+ * @type {goog.history.Html5History.TokenTransformer}
+ * @private
+ */
+ this.transformer_ = opt_transformer || null;
+
+ goog.events.listen(this.window_, goog.events.EventType.POPSTATE,
+ this.onHistoryEvent_, false, this);
+ goog.events.listen(this.window_, goog.events.EventType.HASHCHANGE,
+ this.onHistoryEvent_, false, this);
+};
+goog.inherits(goog.history.Html5History, goog.events.EventTarget);
+
+
+/**
+ * Returns whether Html5History is supported.
+ * @param {Window=} opt_win Optional window to check.
+ * @return {boolean} Whether html5 history is supported.
+ */
+goog.history.Html5History.isSupported = function(opt_win) {
+ var win = opt_win || window;
+ return !!(win.history && win.history.pushState);
+};
+
+
+/**
+ * Status of when the object is active and dispatching events.
+ * @type {boolean}
+ * @private
+ */
+goog.history.Html5History.prototype.enabled_ = false;
+
+
+/**
+ * Whether to use the fragment to store the token, defaults to true.
+ * @type {boolean}
+ * @private
+ */
+goog.history.Html5History.prototype.useFragment_ = true;
+
+
+/**
+ * If useFragment is false the path will be used, the path prefix will be
+ * prepended to all tokens. Defaults to '/'.
+ * @type {string}
+ * @private
+ */
+goog.history.Html5History.prototype.pathPrefix_ = '/';
+
+
+/**
+ * Starts or stops the History. When enabled, the History object
+ * will immediately fire an event for the current location. The caller can set
+ * up event listeners between the call to the constructor and the call to
+ * setEnabled.
+ *
+ * @param {boolean} enable Whether to enable history.
+ */
+goog.history.Html5History.prototype.setEnabled = function(enable) {
+ if (enable == this.enabled_) {
+ return;
+ }
+
+ this.enabled_ = enable;
+
+ if (enable) {
+ this.dispatchEvent(new goog.history.Event(this.getToken(), false));
+ }
+};
+
+
+/**
+ * Returns the current token.
+ * @return {string} The current token.
+ */
+goog.history.Html5History.prototype.getToken = function() {
+ if (this.useFragment_) {
+ var loc = this.window_.location.href;
+ var index = loc.indexOf('#');
+ return index < 0 ? '' : loc.substring(index + 1);
+ } else {
+ return this.transformer_ ?
+ this.transformer_.retrieveToken(
+ this.pathPrefix_, this.window_.location) :
+ this.window_.location.pathname.substr(this.pathPrefix_.length);
+ }
+};
+
+
+/**
+ * Sets the history state.
+ * @param {string} token The history state identifier.
+ * @param {string=} opt_title Optional title to associate with history entry.
+ */
+goog.history.Html5History.prototype.setToken = function(token, opt_title) {
+ if (token == this.getToken()) {
+ return;
+ }
+
+ // Per externs/gecko_dom.js document.title can be null.
+ this.window_.history.pushState(null,
+ opt_title || this.window_.document.title || '', this.getUrl_(token));
+ this.dispatchEvent(new goog.history.Event(token, false));
+};
+
+
+/**
+ * Replaces the current history state without affecting the rest of the history
+ * stack.
+ * @param {string} token The history state identifier.
+ * @param {string=} opt_title Optional title to associate with history entry.
+ */
+goog.history.Html5History.prototype.replaceToken = function(token, opt_title) {
+ // Per externs/gecko_dom.js document.title can be null.
+ this.window_.history.replaceState(null,
+ opt_title || this.window_.document.title || '', this.getUrl_(token));
+ this.dispatchEvent(new goog.history.Event(token, false));
+};
+
+
+/** @override */
+goog.history.Html5History.prototype.disposeInternal = function() {
+ goog.events.unlisten(this.window_, goog.events.EventType.POPSTATE,
+ this.onHistoryEvent_, false, this);
+ if (this.useFragment_) {
+ goog.events.unlisten(this.window_, goog.events.EventType.HASHCHANGE,
+ this.onHistoryEvent_, false, this);
+ }
+};
+
+
+/**
+ * Sets whether to use the fragment to store tokens.
+ * @param {boolean} useFragment Whether to use the fragment.
+ */
+goog.history.Html5History.prototype.setUseFragment = function(useFragment) {
+ if (this.useFragment_ != useFragment) {
+ if (useFragment) {
+ goog.events.listen(this.window_, goog.events.EventType.HASHCHANGE,
+ this.onHistoryEvent_, false, this);
+ } else {
+ goog.events.unlisten(this.window_, goog.events.EventType.HASHCHANGE,
+ this.onHistoryEvent_, false, this);
+ }
+ this.useFragment_ = useFragment;
+ }
+};
+
+
+/**
+ * Sets the path prefix to use if storing tokens in the path. The path
+ * prefix should start and end with slash.
+ * @param {string} pathPrefix Sets the path prefix.
+ */
+goog.history.Html5History.prototype.setPathPrefix = function(pathPrefix) {
+ this.pathPrefix_ = pathPrefix;
+};
+
+
+/**
+ * Gets the path prefix.
+ * @return {string} The path prefix.
+ */
+goog.history.Html5History.prototype.getPathPrefix = function() {
+ return this.pathPrefix_;
+};
+
+
+/**
+ * Gets the URL to set when calling history.pushState
+ * @param {string} token The history token.
+ * @return {string} The URL.
+ * @private
+ */
+goog.history.Html5History.prototype.getUrl_ = function(token) {
+ if (this.useFragment_) {
+ return '#' + token;
+ } else {
+ return this.transformer_ ?
+ this.transformer_.createUrl(
+ token, this.pathPrefix_, this.window_.location) :
+ this.pathPrefix_ + token + this.window_.location.search;
+ }
+};
+
+
+/**
+ * Handles history events dispatched by the browser.
+ * @param {goog.events.BrowserEvent} e The browser event object.
+ * @private
+ */
+goog.history.Html5History.prototype.onHistoryEvent_ = function(e) {
+ if (this.enabled_) {
+ this.dispatchEvent(new goog.history.Event(this.getToken(), true));
+ }
+};
+
+
+
+/**
+ * A token transformer that can create a URL from a history
+ * token. This is used by {@code goog.history.Html5History} to create
+ * URL when storing token without the hash fragment.
+ *
+ * Given a {@code window.location} object containing the location
+ * created by {@code createUrl}, the token transformer allows
+ * retrieval of the token back via {@code retrieveToken}.
+ *
+ * @interface
+ */
+goog.history.Html5History.TokenTransformer = function() {};
+
+
+/**
+ * Retrieves a history token given the path prefix and
+ * {@code window.location} object.
+ *
+ * @param {string} pathPrefix The path prefix to use when storing token
+ * in a path; always begin with a slash.
+ * @param {Location} location The {@code window.location} object.
+ * Treat this object as read-only.
+ * @return {string} token The history token.
+ */
+goog.history.Html5History.TokenTransformer.prototype.retrieveToken = function(
+ pathPrefix, location) {};
+
+
+/**
+ * Creates a URL to be pushed into HTML5 history stack when storing
+ * token without using hash fragment.
+ *
+ * @param {string} token The history token.
+ * @param {string} pathPrefix The path prefix to use when storing token
+ * in a path; always begin with a slash.
+ * @param {Location} location The {@code window.location} object.
+ * Treat this object as read-only.
+ * @return {string} url The complete URL string from path onwards
+ * (without {@code protocol://host:port} part); must begin with a
+ * slash.
+ */
+goog.history.Html5History.TokenTransformer.prototype.createUrl = function(
+ token, pathPrefix, location) {};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/flash.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/flash.js b/externs/GCL/externs/goog/html/flash.js
new file mode 100644
index 0000000..9f72665
--- /dev/null
+++ b/externs/GCL/externs/goog/html/flash.js
@@ -0,0 +1,177 @@
+// 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 SafeHtml factory methods for creating object and embed tags
+ * for loading Flash files.
+ */
+
+goog.provide('goog.html.flash');
+
+goog.require('goog.asserts');
+goog.require('goog.html.SafeHtml');
+
+
+/**
+ * Attributes and param tag name attributes not allowed to be overriden
+ * when calling createObject() and createObjectForOldIe().
+ *
+ * While values that should be specified as params are probably not
+ * recognized as attributes, we block them anyway just to be sure.
+ * @const {!Array<string>}
+ * @private
+ */
+goog.html.flash.FORBIDDEN_ATTRS_AND_PARAMS_ON_FLASH_ = [
+ 'classid', // Used on old IE.
+ 'data', // Used in <object> to specify a URL.
+ 'movie', // Used on old IE.
+ 'type', // Used in <object> on for non-IE/modern IE.
+ 'typemustmatch' // Always set to a fixed value.
+];
+
+
+goog.html.flash.createEmbed = function(src, opt_attributes) {
+ var fixedAttributes = {
+ 'src': src,
+ 'type': 'application/x-shockwave-flash',
+ 'pluginspage': 'https://www.macromedia.com/go/getflashplayer'
+ };
+ var defaultAttributes = {
+ 'allownetworking': 'none',
+ 'allowscriptaccess': 'never'
+ };
+ var attributes = goog.html.SafeHtml.combineAttributes(
+ fixedAttributes, defaultAttributes, opt_attributes);
+ return goog.html.SafeHtml.
+ createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('embed', attributes);
+};
+
+
+goog.html.flash.createObject = function(
+ data, opt_params, opt_attributes) {
+ goog.html.flash.verifyKeysNotInMaps(
+ goog.html.flash.FORBIDDEN_ATTRS_AND_PARAMS_ON_FLASH_,
+ opt_attributes,
+ opt_params);
+
+ var paramTags = goog.html.flash.combineParams(
+ {
+ 'allownetworking': 'none',
+ 'allowscriptaccess': 'never'
+ },
+ opt_params);
+ var fixedAttributes = {
+ 'data': data,
+ 'type': 'application/x-shockwave-flash',
+ 'typemustmatch': ''
+ };
+ var attributes = goog.html.SafeHtml.combineAttributes(
+ fixedAttributes, {}, opt_attributes);
+
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'object', attributes, paramTags);
+};
+
+
+goog.html.flash.createObjectForOldIe = function(
+ movie, opt_params, opt_attributes) {
+ goog.html.flash.verifyKeysNotInMaps(
+ goog.html.flash.FORBIDDEN_ATTRS_AND_PARAMS_ON_FLASH_,
+ opt_attributes,
+ opt_params);
+
+ var paramTags = goog.html.flash.combineParams(
+ {
+ 'allownetworking': 'none',
+ 'allowscriptaccess': 'never',
+ 'movie': movie
+ },
+ opt_params);
+ var fixedAttributes =
+ {'classid': 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000'};
+ var attributes = goog.html.SafeHtml.combineAttributes(
+ fixedAttributes, {}, opt_attributes);
+
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'object', attributes, paramTags);
+};
+
+
+/**
+ * @param {!Object<string, string|!goog.string.TypedString>} defaultParams
+ * @param {!Object<string, string>=}
+ * opt_params Optional params passed to create*().
+ * @return {!Array<!goog.html.SafeHtml>} Combined params.
+ * @throws {Error} If opt_attributes contains an attribute with the same name
+ * as an attribute in fixedAttributes.
+ * @package
+ */
+goog.html.flash.combineParams = function(defaultParams, opt_params) {
+ var combinedParams = {};
+ var name;
+
+ for (name in defaultParams) {
+ goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case');
+ combinedParams[name] = defaultParams[name];
+ }
+ for (name in opt_params) {
+ var nameLower = name.toLowerCase();
+ if (nameLower in defaultParams) {
+ delete combinedParams[nameLower];
+ }
+ combinedParams[name] = opt_params[name];
+ }
+
+ var paramTags = [];
+ for (name in combinedParams) {
+ paramTags.push(
+ goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'param', {'name': name, 'value': combinedParams[name]}));
+
+ }
+ return paramTags;
+};
+
+
+/**
+ * Checks that keys are not present as keys in maps.
+ * @param {!Array<string>} keys Keys that must not be present, lower-case.
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
+ * opt_attributes Optional attributes passed to create*().
+ * @param {!Object<string, string>=} opt_params Optional params passed to
+ * createObject*().
+ * @throws {Error} If any of keys exist as a key, ignoring case, in
+ * opt_attributes or opt_params.
+ * @package
+ */
+goog.html.flash.verifyKeysNotInMaps = function(
+ keys, opt_attributes, opt_params) {
+ var verifyNotInMap = function(keys, map, type) {
+ for (var keyMap in map) {
+ var keyMapLower = keyMap.toLowerCase();
+ for (var i = 0; i < keys.length; i++) {
+ var keyToCheck = keys[i];
+ goog.asserts.assert(keyToCheck.toLowerCase() == keyToCheck);
+ if (keyMapLower == keyToCheck) {
+ throw Error('Cannot override "' + keyToCheck + '" ' + type +
+ ', got "' + keyMap + '" with value "' + map[keyMap] + '"');
+ }
+ }
+ }
+ };
+
+ verifyNotInMap(keys, opt_attributes, 'attribute');
+ verifyNotInMap(keys, opt_params, 'param');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/legacyconversions.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/legacyconversions.js b/externs/GCL/externs/goog/html/legacyconversions.js
new file mode 100644
index 0000000..89a4c6d
--- /dev/null
+++ b/externs/GCL/externs/goog/html/legacyconversions.js
@@ -0,0 +1,200 @@
+// 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 Conversions from plain string to goog.html types for use in
+ * legacy APIs that do not use goog.html types.
+ *
+ * This file provides conversions to create values of goog.html types from plain
+ * strings. These conversions are intended for use in legacy APIs that consume
+ * HTML in the form of plain string types, but whose implementations use
+ * goog.html types internally (and expose such types in an augmented, HTML-type-
+ * safe API).
+ *
+ * IMPORTANT: No new code should use the conversion functions in this file.
+ *
+ * The conversion functions in this file are guarded with global flag
+ * (goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS). If set to false, it
+ * effectively "locks in" an entire application to only use HTML-type-safe APIs.
+ *
+ * Intended use of the functions in this file are as follows:
+ *
+ * Many Closure and application-specific classes expose methods that consume
+ * values that in the class' implementation are forwarded to DOM APIs that can
+ * result in security vulnerabilities. For example, goog.ui.Dialog's setContent
+ * method consumes a string that is assigned to an element's innerHTML property;
+ * if this string contains untrusted (attacker-controlled) data, this can result
+ * in a cross-site-scripting vulnerability.
+ *
+ * Widgets such as goog.ui.Dialog are being augmented to expose safe APIs
+ * expressed in terms of goog.html types. For instance, goog.ui.Dialog has a
+ * method setSafeHtmlContent that consumes an object of type goog.html.SafeHtml,
+ * a type whose contract guarantees that its value is safe to use in HTML
+ * context, i.e. can be safely assigned to .innerHTML. An application that only
+ * uses this API is forced to only supply values of this type, i.e. values that
+ * are safe.
+ *
+ * However, the legacy method setContent cannot (for the time being) be removed
+ * from goog.ui.Dialog, due to a large number of existing callers. The
+ * implementation of goog.ui.Dialog has been refactored to use
+ * goog.html.SafeHtml throughout. This in turn requires that the value consumed
+ * by its setContent method is converted to goog.html.SafeHtml in an unchecked
+ * conversion. The conversion function is provided by this file:
+ * goog.html.legacyconversions.safeHtmlFromString.
+ *
+ * Note that the semantics of the conversions in goog.html.legacyconversions are
+ * very different from the ones provided by goog.html.uncheckedconversions: The
+ * latter are for use in code where it has been established through manual
+ * security review that the value produced by a piece of code must always
+ * satisfy the SafeHtml contract (e.g., the output of a secure HTML sanitizer).
+ * In uses of goog.html.legacyconversions, this guarantee is not given -- the
+ * value in question originates in unreviewed legacy code and there is no
+ * guarantee that it satisfies the SafeHtml contract.
+ *
+ * To establish correctness with confidence, application code should be
+ * refactored to use SafeHtml instead of plain string to represent HTML markup,
+ * and to use goog.html-typed APIs (e.g., goog.ui.Dialog#setSafeHtmlContent
+ * instead of goog.ui.Dialog#setContent).
+ *
+ * To prevent introduction of new vulnerabilities, application owners can
+ * effectively disable unsafe legacy APIs by compiling with the define
+ * goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS set to false. When
+ * set, this define causes the conversion methods in this file to
+ * unconditionally throw an exception.
+ *
+ * Note that new code should always be compiled with
+ * ALLOW_LEGACY_CONVERSIONS=false. At some future point, the default for this
+ * define may change to false.
+ */
+
+
+goog.provide('goog.html.legacyconversions');
+
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeStyle');
+goog.require('goog.html.SafeUrl');
+goog.require('goog.html.TrustedResourceUrl');
+
+
+/**
+ * @define {boolean} Whether conversion from string to goog.html types for
+ * legacy API purposes is permitted.
+ *
+ * If false, the conversion functions in this file unconditionally throw an
+ * exception.
+ */
+goog.define('goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS', true);
+
+
+/**
+ * Performs an "unchecked conversion" from string to SafeHtml for legacy API
+ * purposes.
+ *
+ * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
+ * and instead this function unconditionally throws an exception.
+ *
+ * @param {string} html A string to be converted to SafeHtml.
+ * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml
+ * object.
+ */
+goog.html.legacyconversions.safeHtmlFromString = function(html) {
+ goog.html.legacyconversions.throwIfConversionsDisallowed();
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ html, null /* dir */);
+};
+
+
+/**
+ * Performs an "unchecked conversion" from string to SafeStyle for legacy API
+ * purposes.
+ *
+ * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
+ * and instead this function unconditionally throws an exception.
+ *
+ * @param {string} style A string to be converted to SafeStyle.
+ * @return {!goog.html.SafeStyle} The value of style, wrapped in a SafeStyle
+ * object.
+ */
+goog.html.legacyconversions.safeStyleFromString = function(style) {
+ goog.html.legacyconversions.throwIfConversionsDisallowed();
+ return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
+ style);
+};
+
+
+/**
+ * Performs an "unchecked conversion" from string to TrustedResourceUrl for
+ * legacy API purposes.
+ *
+ * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
+ * and instead this function unconditionally throws an exception.
+ *
+ * @param {string} url A string to be converted to TrustedResourceUrl.
+ * @return {!goog.html.TrustedResourceUrl} The value of url, wrapped in a
+ * TrustedResourceUrl object.
+ */
+goog.html.legacyconversions.trustedResourceUrlFromString = function(url) {
+ goog.html.legacyconversions.throwIfConversionsDisallowed();
+ return goog.html.TrustedResourceUrl.
+ createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
+};
+
+
+/**
+ * Performs an "unchecked conversion" from string to SafeUrl for legacy API
+ * purposes.
+ *
+ * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
+ * and instead this function unconditionally throws an exception.
+ *
+ * @param {string} url A string to be converted to SafeUrl.
+ * @return {!goog.html.SafeUrl} The value of url, wrapped in a SafeUrl
+ * object.
+ */
+goog.html.legacyconversions.safeUrlFromString = function(url) {
+ goog.html.legacyconversions.throwIfConversionsDisallowed();
+ return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
+};
+
+
+/**
+ * @private {function(): undefined}
+ */
+goog.html.legacyconversions.reportCallback_ = goog.nullFunction;
+
+
+/**
+ * Sets a function that will be called every time a legacy conversion is
+ * performed. The function is called with no parameters but it can use
+ * goog.debug.getStacktrace to get a stacktrace.
+ *
+ * @param {function(): undefined} callback Error callback as defined above.
+ */
+goog.html.legacyconversions.setReportCallback = function(callback) {
+ goog.html.legacyconversions.reportCallback_ = callback;
+};
+
+
+/**
+ * Throws an exception if ALLOW_LEGACY_CONVERSIONS is false. This is useful
+ * for legacy APIs which consume HTML in the form of plain string types, but
+ * do not provide an alternative HTML-type-safe API.
+ */
+goog.html.legacyconversions.throwIfConversionsDisallowed = function() {
+ if (!goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS) {
+ throw Error(
+ 'Error: Legacy conversion from string to goog.html types is disabled');
+ }
+ goog.html.legacyconversions.reportCallback_();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/safehtml.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/safehtml.js b/externs/GCL/externs/goog/html/safehtml.js
new file mode 100644
index 0000000..ef6a2ae
--- /dev/null
+++ b/externs/GCL/externs/goog/html/safehtml.js
@@ -0,0 +1,756 @@
+// 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 The SafeHtml type and its builders.
+ *
+ * TODO(user): Link to document stating type contract.
+ */
+
+goog.provide('goog.html.SafeHtml');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.tags');
+goog.require('goog.html.SafeStyle');
+goog.require('goog.html.SafeStyleSheet');
+goog.require('goog.html.SafeUrl');
+goog.require('goog.html.TrustedResourceUrl');
+goog.require('goog.i18n.bidi.Dir');
+goog.require('goog.i18n.bidi.DirectionalString');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+goog.require('goog.string.TypedString');
+
+
+
+/**
+ * A string that is safe to use in HTML context in DOM APIs and HTML documents.
+ *
+ * A SafeHtml is a string-like object that carries the security type contract
+ * that its value as a string will not cause untrusted script execution when
+ * evaluated as HTML in a browser.
+ *
+ * Values of this type are guaranteed to be safe to use in HTML contexts,
+ * such as, assignment to the innerHTML DOM property, or interpolation into
+ * a HTML template in HTML PC_DATA context, in the sense that the use will not
+ * result in a Cross-Site-Scripting vulnerability.
+ *
+ * Instances of this type must be created via the factory methods
+ * ({@code goog.html.SafeHtml.create}, {@code goog.html.SafeHtml.htmlEscape}),
+ * etc and not by invoking its constructor. The constructor intentionally
+ * takes no parameters and the type is immutable; hence only a default instance
+ * corresponding to the empty string can be obtained via constructor invocation.
+ *
+ * @see goog.html.SafeHtml#create
+ * @see goog.html.SafeHtml#htmlEscape
+ * @constructor
+ * @final
+ * @struct
+ * @implements {goog.i18n.bidi.DirectionalString}
+ * @implements {goog.string.TypedString}
+ */
+goog.html.SafeHtml = function() {
+ /**
+ * The contained value of this SafeHtml. The field has a purposely ugly
+ * name to make (non-compiled) code that attempts to directly access this
+ * field stand out.
+ * @private {string}
+ */
+ this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = '';
+
+ /**
+ * A type marker used to implement additional run-time type checking.
+ * @see goog.html.SafeHtml#unwrap
+ * @const
+ * @private
+ */
+ this.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
+ goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
+
+ /**
+ * This SafeHtml's directionality, or null if unknown.
+ * @private {?goog.i18n.bidi.Dir}
+ */
+ this.dir_ = null;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.SafeHtml.prototype.implementsGoogI18nBidiDirectionalString = true;
+
+
+/** @override */
+goog.html.SafeHtml.prototype.getDirection = function() {
+ return this.dir_;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.SafeHtml.prototype.implementsGoogStringTypedString = true;
+
+
+/**
+ * Returns this SafeHtml's value a string.
+ *
+ * IMPORTANT: In code where it is security relevant that an object's type is
+ * indeed {@code SafeHtml}, use {@code goog.html.SafeHtml.unwrap} instead of
+ * this method. If in doubt, assume that it's security relevant. In particular,
+ * note that goog.html functions which return a goog.html type do not guarantee
+ * that the returned instance is of the right type. For example:
+ *
+ * <pre>
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
+ * // instanceof goog.html.SafeHtml.
+ * </pre>
+ *
+ * @see goog.html.SafeHtml#unwrap
+ * @override
+ */
+goog.html.SafeHtml.prototype.getTypedStringValue = function() {
+ return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
+};
+
+
+if (goog.DEBUG) {
+ /**
+ * Returns a debug string-representation of this value.
+ *
+ * To obtain the actual string value wrapped in a SafeHtml, use
+ * {@code goog.html.SafeHtml.unwrap}.
+ *
+ * @see goog.html.SafeHtml#unwrap
+ * @override
+ */
+ goog.html.SafeHtml.prototype.toString = function() {
+ return 'SafeHtml{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ +
+ '}';
+ };
+}
+
+
+/**
+ * Performs a runtime check that the provided object is indeed a SafeHtml
+ * object, and returns its value.
+ * @param {!goog.html.SafeHtml} safeHtml The object to extract from.
+ * @return {string} The SafeHtml object's contained string, unless the run-time
+ * type check fails. In that case, {@code unwrap} returns an innocuous
+ * string, or, if assertions are enabled, throws
+ * {@code goog.asserts.AssertionError}.
+ */
+goog.html.SafeHtml.unwrap = function(safeHtml) {
+ // Perform additional run-time type-checking to ensure that safeHtml is indeed
+ // an instance of the expected type. This provides some additional protection
+ // against security bugs due to application code that disables type checks.
+ // Specifically, the following checks are performed:
+ // 1. The object is an instance of the expected type.
+ // 2. The object is not an instance of a subclass.
+ // 3. The object carries a type marker for the expected type. "Faking" an
+ // object requires a reference to the type marker, which has names intended
+ // to stand out in code reviews.
+ if (safeHtml instanceof goog.html.SafeHtml &&
+ safeHtml.constructor === goog.html.SafeHtml &&
+ safeHtml.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
+ return safeHtml.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
+ } else {
+ goog.asserts.fail('expected object of type SafeHtml, got \'' +
+ safeHtml + '\'');
+ return 'type_error:SafeHtml';
+ }
+};
+
+
+/**
+ * Shorthand for union of types that can sensibly be converted to strings
+ * or might already be SafeHtml (as SafeHtml is a goog.string.TypedString).
+ * @private
+ * @typedef {string|number|boolean|!goog.string.TypedString|
+ * !goog.i18n.bidi.DirectionalString}
+ */
+goog.html.SafeHtml.TextOrHtml_;
+
+
+/**
+ * Returns HTML-escaped text as a SafeHtml object.
+ *
+ * If text is of a type that implements
+ * {@code goog.i18n.bidi.DirectionalString}, the directionality of the new
+ * {@code SafeHtml} object is set to {@code text}'s directionality, if known.
+ * Otherwise, the directionality of the resulting SafeHtml is unknown (i.e.,
+ * {@code null}).
+ *
+ * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If
+ * the parameter is of type SafeHtml it is returned directly (no escaping
+ * is done).
+ * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml.
+ */
+goog.html.SafeHtml.htmlEscape = function(textOrHtml) {
+ if (textOrHtml instanceof goog.html.SafeHtml) {
+ return textOrHtml;
+ }
+ var dir = null;
+ if (textOrHtml.implementsGoogI18nBidiDirectionalString) {
+ dir = textOrHtml.getDirection();
+ }
+ var textAsString;
+ if (textOrHtml.implementsGoogStringTypedString) {
+ textAsString = textOrHtml.getTypedStringValue();
+ } else {
+ textAsString = String(textOrHtml);
+ }
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ goog.string.htmlEscape(textAsString), dir);
+};
+
+
+/**
+ * Returns HTML-escaped text as a SafeHtml object, with newlines changed to
+ * <br>.
+ * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If
+ * the parameter is of type SafeHtml it is returned directly (no escaping
+ * is done).
+ * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml.
+ */
+goog.html.SafeHtml.htmlEscapePreservingNewlines = function(textOrHtml) {
+ if (textOrHtml instanceof goog.html.SafeHtml) {
+ return textOrHtml;
+ }
+ var html = goog.html.SafeHtml.htmlEscape(textOrHtml);
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ goog.string.newLineToBr(goog.html.SafeHtml.unwrap(html)),
+ html.getDirection());
+};
+
+
+/**
+ * Returns HTML-escaped text as a SafeHtml object, with newlines changed to
+ * <br> and escaping whitespace to preserve spatial formatting. Character
+ * entity #160 is used to make it safer for XML.
+ * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If
+ * the parameter is of type SafeHtml it is returned directly (no escaping
+ * is done).
+ * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml.
+ */
+goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces = function(
+ textOrHtml) {
+ if (textOrHtml instanceof goog.html.SafeHtml) {
+ return textOrHtml;
+ }
+ var html = goog.html.SafeHtml.htmlEscape(textOrHtml);
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ goog.string.whitespaceEscape(goog.html.SafeHtml.unwrap(html)),
+ html.getDirection());
+};
+
+
+/**
+ * Coerces an arbitrary object into a SafeHtml object.
+ *
+ * If {@code textOrHtml} is already of type {@code goog.html.SafeHtml}, the same
+ * object is returned. Otherwise, {@code textOrHtml} is coerced to string, and
+ * HTML-escaped. If {@code textOrHtml} is of a type that implements
+ * {@code goog.i18n.bidi.DirectionalString}, its directionality, if known, is
+ * preserved.
+ *
+ * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text or SafeHtml to
+ * coerce.
+ * @return {!goog.html.SafeHtml} The resulting SafeHtml object.
+ * @deprecated Use goog.html.SafeHtml.htmlEscape.
+ */
+goog.html.SafeHtml.from = goog.html.SafeHtml.htmlEscape;
+
+
+/**
+ * @const
+ * @private
+ */
+goog.html.SafeHtml.VALID_NAMES_IN_TAG_ = /^[a-zA-Z0-9-]+$/;
+
+
+/**
+ * Set of attributes containing URL as defined at
+ * http://www.w3.org/TR/html5/index.html#attributes-1.
+ * @private @const {!Object<string,boolean>}
+ */
+goog.html.SafeHtml.URL_ATTRIBUTES_ = goog.object.createSet('action', 'cite',
+ 'data', 'formaction', 'href', 'manifest', 'poster', 'src');
+
+
+/**
+ * Tags which are unsupported via create(). They might be supported via a
+ * tag-specific create method. These are tags which might require a
+ * TrustedResourceUrl in one of their attributes or a restricted type for
+ * their content.
+ * @private @const {!Object<string,boolean>}
+ */
+goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_ = goog.object.createSet(
+ goog.dom.TagName.EMBED, goog.dom.TagName.IFRAME, goog.dom.TagName.LINK,
+ goog.dom.TagName.OBJECT, goog.dom.TagName.SCRIPT, goog.dom.TagName.STYLE,
+ goog.dom.TagName.TEMPLATE);
+
+
+/**
+ * @typedef {string|number|goog.string.TypedString|
+ * goog.html.SafeStyle.PropertyMap}
+ * @private
+ */
+goog.html.SafeHtml.AttributeValue_;
+
+
+/**
+ * Creates a SafeHtml content consisting of a tag with optional attributes and
+ * optional content.
+ *
+ * For convenience tag names and attribute names are accepted as regular
+ * strings, instead of goog.string.Const. Nevertheless, you should not pass
+ * user-controlled values to these parameters. Note that these parameters are
+ * syntactically validated at runtime, and invalid values will result in
+ * an exception.
+ *
+ * Example usage:
+ *
+ * goog.html.SafeHtml.create('br');
+ * goog.html.SafeHtml.create('div', {'class': 'a'});
+ * goog.html.SafeHtml.create('p', {}, 'a');
+ * goog.html.SafeHtml.create('p', {}, goog.html.SafeHtml.create('br'));
+ *
+ * goog.html.SafeHtml.create('span', {
+ * 'style': {'margin': '0'}
+ * });
+ *
+ * To guarantee SafeHtml's type contract is upheld there are restrictions on
+ * attribute values and tag names.
+ *
+ * - For attributes which contain script code (on*), a goog.string.Const is
+ * required.
+ * - For attributes which contain style (style), a goog.html.SafeStyle or a
+ * goog.html.SafeStyle.PropertyMap is required.
+ * - For attributes which are interpreted as URLs (e.g. src, href) a
+ * goog.html.SafeUrl or goog.string.Const is required.
+ * - For tags which can load code, more specific goog.html.SafeHtml.create*()
+ * functions must be used. Tags which can load code and are not supported by
+ * this function are embed, iframe, link, object, script, style, and template.
+ *
+ * @param {string} tagName The name of the tag. Only tag names consisting of
+ * [a-zA-Z0-9-] are allowed. Tag names documented above are disallowed.
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
+ * opt_attributes Mapping from attribute names to their values. Only
+ * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
+ * undefined causes the attribute to be omitted.
+ * @param {!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to
+ * HTML-escape and put inside the tag. This must be empty for void tags
+ * like <br>. Array elements are concatenated.
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
+ * @throws {Error} If invalid tag name, attribute name, or attribute value is
+ * provided.
+ * @throws {goog.asserts.AssertionError} If content for void tag is provided.
+ */
+goog.html.SafeHtml.create = function(tagName, opt_attributes, opt_content) {
+ if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(tagName)) {
+ throw Error('Invalid tag name <' + tagName + '>.');
+ }
+ if (tagName.toUpperCase() in goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_) {
+ throw Error('Tag name <' + tagName + '> is not allowed for SafeHtml.');
+ }
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ tagName, opt_attributes, opt_content);
+};
+
+
+/**
+ * Creates a SafeHtml representing an iframe tag.
+ *
+ * By default the sandbox attribute is set to an empty value, which is the most
+ * secure option, as it confers the iframe the least privileges. If this
+ * is too restrictive then granting individual privileges is the preferable
+ * option. Unsetting the attribute entirely is the least secure option and
+ * should never be done unless it's stricly necessary.
+ *
+ * @param {goog.html.TrustedResourceUrl=} opt_src The value of the src
+ * attribute. If null or undefined src will not be set.
+ * @param {goog.html.SafeHtml=} opt_srcdoc The value of the srcdoc attribute.
+ * If null or undefined srcdoc will not be set.
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
+ * opt_attributes Mapping from attribute names to their values. Only
+ * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
+ * undefined causes the attribute to be omitted.
+ * @param {!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to
+ * HTML-escape and put inside the tag. Array elements are concatenated.
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
+ * @throws {Error} If invalid tag name, attribute name, or attribute value is
+ * provided. If opt_attributes contains the src or srcdoc attributes.
+ */
+goog.html.SafeHtml.createIframe = function(
+ opt_src, opt_srcdoc, opt_attributes, opt_content) {
+ var fixedAttributes = {};
+ fixedAttributes['src'] = opt_src || null;
+ fixedAttributes['srcdoc'] = opt_srcdoc || null;
+ var defaultAttributes = {'sandbox': ''};
+ var attributes = goog.html.SafeHtml.combineAttributes(
+ fixedAttributes, defaultAttributes, opt_attributes);
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'iframe', attributes, opt_content);
+};
+
+
+/**
+ * Creates a SafeHtml representing a style tag. The type attribute is set
+ * to "text/css".
+ * @param {!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>}
+ * styleSheet Content to put inside the tag. Array elements are
+ * concatenated.
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
+ * opt_attributes Mapping from attribute names to their values. Only
+ * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
+ * undefined causes the attribute to be omitted.
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
+ * @throws {Error} If invalid attribute name or attribute value is provided. If
+ * opt_attributes contains the type attribute.
+ */
+goog.html.SafeHtml.createStyle = function(styleSheet, opt_attributes) {
+ var fixedAttributes = {'type': 'text/css'};
+ var defaultAttributes = {};
+ var attributes = goog.html.SafeHtml.combineAttributes(
+ fixedAttributes, defaultAttributes, opt_attributes);
+
+ var content = '';
+ styleSheet = goog.array.concat(styleSheet);
+ for (var i = 0; i < styleSheet.length; i++) {
+ content += goog.html.SafeStyleSheet.unwrap(styleSheet[i]);
+ }
+ // Convert to SafeHtml so that it's not HTML-escaped.
+ var htmlContent = goog.html.SafeHtml
+ .createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ content, goog.i18n.bidi.Dir.NEUTRAL);
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'style', attributes, htmlContent);
+};
+
+
+/**
+ * @param {string} tagName The tag name.
+ * @param {string} name The attribute name.
+ * @param {!goog.html.SafeHtml.AttributeValue_} value The attribute value.
+ * @return {string} A "name=value" string.
+ * @throws {Error} If attribute value is unsafe for the given tag and attribute.
+ * @private
+ */
+goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) {
+ // If it's goog.string.Const, allow any valid attribute name.
+ if (value instanceof goog.string.Const) {
+ value = goog.string.Const.unwrap(value);
+ } else if (name.toLowerCase() == 'style') {
+ value = goog.html.SafeHtml.getStyleValue_(value);
+ } else if (/^on/i.test(name)) {
+ // TODO(jakubvrana): Disallow more attributes with a special meaning.
+ throw Error('Attribute "' + name +
+ '" requires goog.string.Const value, "' + value + '" given.');
+ // URL attributes handled differently accroding to tag.
+ } else if (name.toLowerCase() in goog.html.SafeHtml.URL_ATTRIBUTES_) {
+ if (value instanceof goog.html.TrustedResourceUrl) {
+ value = goog.html.TrustedResourceUrl.unwrap(value);
+ } else if (value instanceof goog.html.SafeUrl) {
+ value = goog.html.SafeUrl.unwrap(value);
+ } else {
+ // TODO(user): Allow strings and sanitize them automatically,
+ // so that it's consistent with accepting a map directly for "style".
+ throw Error('Attribute "' + name + '" on tag "' + tagName +
+ '" requires goog.html.SafeUrl or goog.string.Const value, "' +
+ value + '" given.');
+ }
+ }
+
+ // Accept SafeUrl, TrustedResourceUrl, etc. for attributes which only require
+ // HTML-escaping.
+ if (value.implementsGoogStringTypedString) {
+ // Ok to call getTypedStringValue() since there's no reliance on the type
+ // contract for security here.
+ value = value.getTypedStringValue();
+ }
+
+ goog.asserts.assert(goog.isString(value) || goog.isNumber(value),
+ 'String or number value expected, got ' +
+ (typeof value) + ' with value: ' + value);
+ return name + '="' + goog.string.htmlEscape(String(value)) + '"';
+};
+
+
+/**
+ * Gets value allowed in "style" attribute.
+ * @param {goog.html.SafeHtml.AttributeValue_} value It could be SafeStyle or a
+ * map which will be passed to goog.html.SafeStyle.create.
+ * @return {string} Unwrapped value.
+ * @throws {Error} If string value is given.
+ * @private
+ */
+goog.html.SafeHtml.getStyleValue_ = function(value) {
+ if (!goog.isObject(value)) {
+ throw Error('The "style" attribute requires goog.html.SafeStyle or map ' +
+ 'of style properties, ' + (typeof value) + ' given: ' + value);
+ }
+ if (!(value instanceof goog.html.SafeStyle)) {
+ // Process the property bag into a style object.
+ value = goog.html.SafeStyle.create(value);
+ }
+ return goog.html.SafeStyle.unwrap(value);
+};
+
+
+/**
+ * Creates a SafeHtml content with known directionality consisting of a tag with
+ * optional attributes and optional content.
+ * @param {!goog.i18n.bidi.Dir} dir Directionality.
+ * @param {string} tagName
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=} opt_attributes
+ * @param {!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
+ */
+goog.html.SafeHtml.createWithDir = function(dir, tagName, opt_attributes,
+ opt_content) {
+ var html = goog.html.SafeHtml.create(tagName, opt_attributes, opt_content);
+ html.dir_ = dir;
+ return html;
+};
+
+
+/**
+ * Creates a new SafeHtml object by concatenating values.
+ * @param {...(!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>)} var_args Values to concatenate.
+ * @return {!goog.html.SafeHtml}
+ */
+goog.html.SafeHtml.concat = function(var_args) {
+ var dir = goog.i18n.bidi.Dir.NEUTRAL;
+ var content = '';
+
+ /**
+ * @param {!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>} argument
+ */
+ var addArgument = function(argument) {
+ if (goog.isArray(argument)) {
+ goog.array.forEach(argument, addArgument);
+ } else {
+ var html = goog.html.SafeHtml.htmlEscape(argument);
+ content += goog.html.SafeHtml.unwrap(html);
+ var htmlDir = html.getDirection();
+ if (dir == goog.i18n.bidi.Dir.NEUTRAL) {
+ dir = htmlDir;
+ } else if (htmlDir != goog.i18n.bidi.Dir.NEUTRAL && dir != htmlDir) {
+ dir = null;
+ }
+ }
+ };
+
+ goog.array.forEach(arguments, addArgument);
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ content, dir);
+};
+
+
+/**
+ * Creates a new SafeHtml object with known directionality by concatenating the
+ * values.
+ * @param {!goog.i18n.bidi.Dir} dir Directionality.
+ * @param {...(!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>)} var_args Elements of array
+ * arguments would be processed recursively.
+ * @return {!goog.html.SafeHtml}
+ */
+goog.html.SafeHtml.concatWithDir = function(dir, var_args) {
+ var html = goog.html.SafeHtml.concat(goog.array.slice(arguments, 1));
+ html.dir_ = dir;
+ return html;
+};
+
+
+/**
+ * Type marker for the SafeHtml type, used to implement additional run-time
+ * type checking.
+ * @const
+ * @private
+ */
+goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
+
+
+/**
+ * Package-internal utility method to create SafeHtml instances.
+ *
+ * @param {string} html The string to initialize the SafeHtml object with.
+ * @param {?goog.i18n.bidi.Dir} dir The directionality of the SafeHtml to be
+ * constructed, or null if unknown.
+ * @return {!goog.html.SafeHtml} The initialized SafeHtml object.
+ * @package
+ */
+goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse = function(
+ html, dir) {
+ return new goog.html.SafeHtml().initSecurityPrivateDoNotAccessOrElse_(
+ html, dir);
+};
+
+
+/**
+ * Called from createSafeHtmlSecurityPrivateDoNotAccessOrElse(). This
+ * method exists only so that the compiler can dead code eliminate static
+ * fields (like EMPTY) when they're not accessed.
+ * @param {string} html
+ * @param {?goog.i18n.bidi.Dir} dir
+ * @return {!goog.html.SafeHtml}
+ * @private
+ */
+goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
+ html, dir) {
+ this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = html;
+ this.dir_ = dir;
+ return this;
+};
+
+
+/**
+ * Like create() but does not restrict which tags can be constructed.
+ *
+ * @param {string} tagName Tag name. Set or validated by caller.
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=} opt_attributes
+ * @param {(!goog.html.SafeHtml.TextOrHtml_|
+ * !Array<!goog.html.SafeHtml.TextOrHtml_>)=} opt_content
+ * @return {!goog.html.SafeHtml}
+ * @throws {Error} If invalid or unsafe attribute name or value is provided.
+ * @throws {goog.asserts.AssertionError} If content for void tag is provided.
+ * @package
+ */
+goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse =
+ function(tagName, opt_attributes, opt_content) {
+ var dir = null;
+ var result = '<' + tagName;
+
+ if (opt_attributes) {
+ for (var name in opt_attributes) {
+ if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(name)) {
+ throw Error('Invalid attribute name "' + name + '".');
+ }
+ var value = opt_attributes[name];
+ if (!goog.isDefAndNotNull(value)) {
+ continue;
+ }
+ result += ' ' +
+ goog.html.SafeHtml.getAttrNameAndValue_(tagName, name, value);
+ }
+ }
+
+ var content = opt_content;
+ if (!goog.isDefAndNotNull(content)) {
+ content = [];
+ } else if (!goog.isArray(content)) {
+ content = [content];
+ }
+
+ if (goog.dom.tags.isVoidTag(tagName.toLowerCase())) {
+ goog.asserts.assert(!content.length,
+ 'Void tag <' + tagName + '> does not allow content.');
+ result += '>';
+ } else {
+ var html = goog.html.SafeHtml.concat(content);
+ result += '>' + goog.html.SafeHtml.unwrap(html) + '</' + tagName + '>';
+ dir = html.getDirection();
+ }
+
+ var dirAttribute = opt_attributes && opt_attributes['dir'];
+ if (dirAttribute) {
+ if (/^(ltr|rtl|auto)$/i.test(dirAttribute)) {
+ // If the tag has the "dir" attribute specified then its direction is
+ // neutral because it can be safely used in any context.
+ dir = goog.i18n.bidi.Dir.NEUTRAL;
+ } else {
+ dir = null;
+ }
+ }
+
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ result, dir);
+};
+
+
+/**
+ * @param {!Object<string, string>} fixedAttributes
+ * @param {!Object<string, string>} defaultAttributes
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
+ * opt_attributes Optional attributes passed to create*().
+ * @return {!Object<string, goog.html.SafeHtml.AttributeValue_>}
+ * @throws {Error} If opt_attributes contains an attribute with the same name
+ * as an attribute in fixedAttributes.
+ * @package
+ */
+goog.html.SafeHtml.combineAttributes = function(
+ fixedAttributes, defaultAttributes, opt_attributes) {
+ var combinedAttributes = {};
+ var name;
+
+ for (name in fixedAttributes) {
+ goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case');
+ combinedAttributes[name] = fixedAttributes[name];
+ }
+ for (name in defaultAttributes) {
+ goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case');
+ combinedAttributes[name] = defaultAttributes[name];
+ }
+
+ for (name in opt_attributes) {
+ var nameLower = name.toLowerCase();
+ if (nameLower in fixedAttributes) {
+ throw Error('Cannot override "' + nameLower + '" attribute, got "' +
+ name + '" with value "' + opt_attributes[name] + '"');
+ }
+ if (nameLower in defaultAttributes) {
+ delete combinedAttributes[nameLower];
+ }
+ combinedAttributes[name] = opt_attributes[name];
+ }
+
+ return combinedAttributes;
+};
+
+
+/**
+ * A SafeHtml instance corresponding to the HTML doctype: "<!DOCTYPE html>".
+ * @const {!goog.html.SafeHtml}
+ */
+goog.html.SafeHtml.DOCTYPE_HTML =
+ goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ '<!DOCTYPE html>', goog.i18n.bidi.Dir.NEUTRAL);
+
+
+/**
+ * A SafeHtml instance corresponding to the empty string.
+ * @const {!goog.html.SafeHtml}
+ */
+goog.html.SafeHtml.EMPTY =
+ goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ '', goog.i18n.bidi.Dir.NEUTRAL);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/safescript.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/safescript.js b/externs/GCL/externs/goog/html/safescript.js
new file mode 100644
index 0000000..83995aa
--- /dev/null
+++ b/externs/GCL/externs/goog/html/safescript.js
@@ -0,0 +1,234 @@
+// 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 The SafeScript type and its builders.
+ *
+ * TODO(user): Link to document stating type contract.
+ */
+
+goog.provide('goog.html.SafeScript');
+
+goog.require('goog.asserts');
+goog.require('goog.string.Const');
+goog.require('goog.string.TypedString');
+
+
+
+/**
+ * A string-like object which represents JavaScript code and that carries the
+ * security type contract that its value, as a string, will not cause execution
+ * of unconstrained attacker controlled code (XSS) when evaluated as JavaScript
+ * in a browser.
+ *
+ * Instances of this type must be created via the factory method
+ * {@code goog.html.SafeScript.fromConstant} and not by invoking its
+ * constructor. The constructor intentionally takes no parameters and the type
+ * is immutable; hence only a default instance corresponding to the empty string
+ * can be obtained via constructor invocation.
+ *
+ * A SafeScript's string representation can safely be interpolated as the
+ * content of a script element within HTML. The SafeScript string should not be
+ * escaped before interpolation.
+ *
+ * Note that the SafeScript might contain text that is attacker-controlled but
+ * that text should have been interpolated with appropriate escaping,
+ * sanitization and/or validation into the right location in the script, such
+ * that it is highly constrained in its effect (for example, it had to match a
+ * set of whitelisted words).
+ *
+ * A SafeScript can be constructed via security-reviewed unchecked
+ * conversions. In this case producers of SafeScript must ensure themselves that
+ * the SafeScript does not contain unsafe script. Note in particular that
+ * {@code <} is dangerous, even when inside JavaScript strings, and so should
+ * always be forbidden or JavaScript escaped in user controlled input. For
+ * example, if {@code </script><script>evil</script>"} were
+ * interpolated inside a JavaScript string, it would break out of the context
+ * of the original script element and {@code evil} would execute. Also note
+ * that within an HTML script (raw text) element, HTML character references,
+ * such as "<" are not allowed. See
+ * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements.
+ *
+ * @see goog.html.SafeScript#fromConstant
+ * @constructor
+ * @final
+ * @struct
+ * @implements {goog.string.TypedString}
+ */
+goog.html.SafeScript = function() {
+ /**
+ * The contained value of this SafeScript. The field has a purposely
+ * ugly name to make (non-compiled) code that attempts to directly access this
+ * field stand out.
+ * @private {string}
+ */
+ this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = '';
+
+ /**
+ * A type marker used to implement additional run-time type checking.
+ * @see goog.html.SafeScript#unwrap
+ * @const
+ * @private
+ */
+ this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
+ goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.SafeScript.prototype.implementsGoogStringTypedString = true;
+
+
+/**
+ * Type marker for the SafeScript type, used to implement additional
+ * run-time type checking.
+ * @const
+ * @private
+ */
+goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
+
+
+/**
+ * Creates a SafeScript object from a compile-time constant string.
+ *
+ * @param {!goog.string.Const} script A compile-time-constant string from which
+ * to create a SafeScript.
+ * @return {!goog.html.SafeScript} A SafeScript object initialized to
+ * {@code script}.
+ */
+goog.html.SafeScript.fromConstant = function(script) {
+ var scriptString = goog.string.Const.unwrap(script);
+ if (scriptString.length === 0) {
+ return goog.html.SafeScript.EMPTY;
+ }
+ return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(
+ scriptString);
+};
+
+
+/**
+ * Returns this SafeScript's value as a string.
+ *
+ * IMPORTANT: In code where it is security relevant that an object's type is
+ * indeed {@code SafeScript}, use {@code goog.html.SafeScript.unwrap} instead of
+ * this method. If in doubt, assume that it's security relevant. In particular,
+ * note that goog.html functions which return a goog.html type do not guarantee
+ * the returned instance is of the right type. For example:
+ *
+ * <pre>
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
+ * // instanceof goog.html.SafeHtml.
+ * </pre>
+ *
+ * @see goog.html.SafeScript#unwrap
+ * @override
+ */
+goog.html.SafeScript.prototype.getTypedStringValue = function() {
+ return this.privateDoNotAccessOrElseSafeScriptWrappedValue_;
+};
+
+
+if (goog.DEBUG) {
+ /**
+ * Returns a debug string-representation of this value.
+ *
+ * To obtain the actual string value wrapped in a SafeScript, use
+ * {@code goog.html.SafeScript.unwrap}.
+ *
+ * @see goog.html.SafeScript#unwrap
+ * @override
+ */
+ goog.html.SafeScript.prototype.toString = function() {
+ return 'SafeScript{' +
+ this.privateDoNotAccessOrElseSafeScriptWrappedValue_ + '}';
+ };
+}
+
+
+/**
+ * Performs a runtime check that the provided object is indeed a
+ * SafeScript object, and returns its value.
+ *
+ * @param {!goog.html.SafeScript} safeScript The object to extract from.
+ * @return {string} The safeScript object's contained string, unless
+ * the run-time type check fails. In that case, {@code unwrap} returns an
+ * innocuous string, or, if assertions are enabled, throws
+ * {@code goog.asserts.AssertionError}.
+ */
+goog.html.SafeScript.unwrap = function(safeScript) {
+ // Perform additional Run-time type-checking to ensure that
+ // safeScript is indeed an instance of the expected type. This
+ // provides some additional protection against security bugs due to
+ // application code that disables type checks.
+ // Specifically, the following checks are performed:
+ // 1. The object is an instance of the expected type.
+ // 2. The object is not an instance of a subclass.
+ // 3. The object carries a type marker for the expected type. "Faking" an
+ // object requires a reference to the type marker, which has names intended
+ // to stand out in code reviews.
+ if (safeScript instanceof goog.html.SafeScript &&
+ safeScript.constructor === goog.html.SafeScript &&
+ safeScript.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
+ return safeScript.privateDoNotAccessOrElseSafeScriptWrappedValue_;
+ } else {
+ goog.asserts.fail(
+ 'expected object of type SafeScript, got \'' + safeScript + '\'');
+ return 'type_error:SafeScript';
+ }
+};
+
+
+/**
+ * Package-internal utility method to create SafeScript instances.
+ *
+ * @param {string} script The string to initialize the SafeScript object with.
+ * @return {!goog.html.SafeScript} The initialized SafeScript object.
+ * @package
+ */
+goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse =
+ function(script) {
+ return new goog.html.SafeScript().initSecurityPrivateDoNotAccessOrElse_(
+ script);
+};
+
+
+/**
+ * Called from createSafeScriptSecurityPrivateDoNotAccessOrElse(). This
+ * method exists only so that the compiler can dead code eliminate static
+ * fields (like EMPTY) when they're not accessed.
+ * @param {string} script
+ * @return {!goog.html.SafeScript}
+ * @private
+ */
+goog.html.SafeScript.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
+ script) {
+ this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = script;
+ return this;
+};
+
+
+/**
+ * A SafeScript instance corresponding to the empty string.
+ * @const {!goog.html.SafeScript}
+ */
+goog.html.SafeScript.EMPTY =
+ goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse('');
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/safestyle.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/safestyle.js b/externs/GCL/externs/goog/html/safestyle.js
new file mode 100644
index 0000000..2f9f288
--- /dev/null
+++ b/externs/GCL/externs/goog/html/safestyle.js
@@ -0,0 +1,442 @@
+// 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 The SafeStyle type and its builders.
+ *
+ * TODO(user): Link to document stating type contract.
+ */
+
+goog.provide('goog.html.SafeStyle');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+goog.require('goog.string.TypedString');
+
+
+
+/**
+ * A string-like object which represents a sequence of CSS declarations
+ * ({@code propertyName1: propertyvalue1; propertyName2: propertyValue2; ...})
+ * and that carries the security type contract that its value, as a string,
+ * will not cause untrusted script execution (XSS) when evaluated as CSS in a
+ * browser.
+ *
+ * Instances of this type must be created via the factory methods
+ * ({@code goog.html.SafeStyle.create} or
+ * {@code goog.html.SafeStyle.fromConstant}) and not by invoking its
+ * constructor. The constructor intentionally takes no parameters and the type
+ * is immutable; hence only a default instance corresponding to the empty string
+ * can be obtained via constructor invocation.
+ *
+ * A SafeStyle's string representation ({@link #getSafeStyleString()}) can
+ * safely:
+ * <ul>
+ * <li>Be interpolated as the entire content of a *quoted* HTML style
+ * attribute, or before already existing properties. The SafeStyle string
+ * *must be HTML-attribute-escaped* (where " and ' are escaped) before
+ * interpolation.
+ * <li>Be interpolated as the entire content of a {}-wrapped block within a
+ * stylesheet, or before already existing properties. The SafeStyle string
+ * should not be escaped before interpolation. SafeStyle's contract also
+ * guarantees that the string will not be able to introduce new properties
+ * or elide existing ones.
+ * <li>Be assigned to the style property of a DOM node. The SafeStyle string
+ * should not be escaped before being assigned to the property.
+ * </ul>
+ *
+ * A SafeStyle may never contain literal angle brackets. Otherwise, it could
+ * be unsafe to place a SafeStyle into a <style> tag (where it can't
+ * be HTML escaped). For example, if the SafeStyle containing
+ * "{@code font: 'foo <style/><script>evil</script>'}" were
+ * interpolated within a <style> tag, this would then break out of the
+ * style context into HTML.
+ *
+ * A SafeStyle may contain literal single or double quotes, and as such the
+ * entire style string must be escaped when used in a style attribute (if
+ * this were not the case, the string could contain a matching quote that
+ * would escape from the style attribute).
+ *
+ * Values of this type must be composable, i.e. for any two values
+ * {@code style1} and {@code style2} of this type,
+ * {@code goog.html.SafeStyle.unwrap(style1) +
+ * goog.html.SafeStyle.unwrap(style2)} must itself be a value that satisfies
+ * the SafeStyle type constraint. This requirement implies that for any value
+ * {@code style} of this type, {@code goog.html.SafeStyle.unwrap(style)} must
+ * not end in a "property value" or "property name" context. For example,
+ * a value of {@code background:url("} or {@code font-} would not satisfy the
+ * SafeStyle contract. This is because concatenating such strings with a
+ * second value that itself does not contain unsafe CSS can result in an
+ * overall string that does. For example, if {@code javascript:evil())"} is
+ * appended to {@code background:url("}, the resulting string may result in
+ * the execution of a malicious script.
+ *
+ * TODO(user): Consider whether we should implement UTF-8 interchange
+ * validity checks and blacklisting of newlines (including Unicode ones) and
+ * other whitespace characters (\t, \f). Document here if so and also update
+ * SafeStyle.fromConstant().
+ *
+ * The following example values comply with this type's contract:
+ * <ul>
+ * <li><pre>width: 1em;</pre>
+ * <li><pre>height:1em;</pre>
+ * <li><pre>width: 1em;height: 1em;</pre>
+ * <li><pre>background:url('http://url');</pre>
+ * </ul>
+ * In addition, the empty string is safe for use in a CSS attribute.
+ *
+ * The following example values do NOT comply with this type's contract:
+ * <ul>
+ * <li><pre>background: red</pre> (missing a trailing semi-colon)
+ * <li><pre>background:</pre> (missing a value and a trailing semi-colon)
+ * <li><pre>1em</pre> (missing an attribute name, which provides context for
+ * the value)
+ * </ul>
+ *
+ * @see goog.html.SafeStyle#create
+ * @see goog.html.SafeStyle#fromConstant
+ * @see http://www.w3.org/TR/css3-syntax/
+ * @constructor
+ * @final
+ * @struct
+ * @implements {goog.string.TypedString}
+ */
+goog.html.SafeStyle = function() {
+ /**
+ * The contained value of this SafeStyle. The field has a purposely
+ * ugly name to make (non-compiled) code that attempts to directly access this
+ * field stand out.
+ * @private {string}
+ */
+ this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = '';
+
+ /**
+ * A type marker used to implement additional run-time type checking.
+ * @see goog.html.SafeStyle#unwrap
+ * @const
+ * @private
+ */
+ this.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
+ goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.SafeStyle.prototype.implementsGoogStringTypedString = true;
+
+
+/**
+ * Type marker for the SafeStyle type, used to implement additional
+ * run-time type checking.
+ * @const
+ * @private
+ */
+goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
+
+
+/**
+ * Creates a SafeStyle object from a compile-time constant string.
+ *
+ * {@code style} should be in the format
+ * {@code name: value; [name: value; ...]} and must not have any < or >
+ * characters in it. This is so that SafeStyle's contract is preserved,
+ * allowing the SafeStyle to correctly be interpreted as a sequence of CSS
+ * declarations and without affecting the syntactic structure of any
+ * surrounding CSS and HTML.
+ *
+ * This method performs basic sanity checks on the format of {@code style}
+ * but does not constrain the format of {@code name} and {@code value}, except
+ * for disallowing tag characters.
+ *
+ * @param {!goog.string.Const} style A compile-time-constant string from which
+ * to create a SafeStyle.
+ * @return {!goog.html.SafeStyle} A SafeStyle object initialized to
+ * {@code style}.
+ */
+goog.html.SafeStyle.fromConstant = function(style) {
+ var styleString = goog.string.Const.unwrap(style);
+ if (styleString.length === 0) {
+ return goog.html.SafeStyle.EMPTY;
+ }
+ goog.html.SafeStyle.checkStyle_(styleString);
+ goog.asserts.assert(goog.string.endsWith(styleString, ';'),
+ 'Last character of style string is not \';\': ' + styleString);
+ goog.asserts.assert(goog.string.contains(styleString, ':'),
+ 'Style string must contain at least one \':\', to ' +
+ 'specify a "name: value" pair: ' + styleString);
+ return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
+ styleString);
+};
+
+
+/**
+ * Checks if the style definition is valid.
+ * @param {string} style
+ * @private
+ */
+goog.html.SafeStyle.checkStyle_ = function(style) {
+ goog.asserts.assert(!/[<>]/.test(style),
+ 'Forbidden characters in style string: ' + style);
+};
+
+
+/**
+ * Returns this SafeStyle's value as a string.
+ *
+ * IMPORTANT: In code where it is security relevant that an object's type is
+ * indeed {@code SafeStyle}, use {@code goog.html.SafeStyle.unwrap} instead of
+ * this method. If in doubt, assume that it's security relevant. In particular,
+ * note that goog.html functions which return a goog.html type do not guarantee
+ * the returned instance is of the right type. For example:
+ *
+ * <pre>
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
+ * // instanceof goog.html.SafeHtml.
+ * </pre>
+ *
+ * @see goog.html.SafeStyle#unwrap
+ * @override
+ */
+goog.html.SafeStyle.prototype.getTypedStringValue = function() {
+ return this.privateDoNotAccessOrElseSafeStyleWrappedValue_;
+};
+
+
+if (goog.DEBUG) {
+ /**
+ * Returns a debug string-representation of this value.
+ *
+ * To obtain the actual string value wrapped in a SafeStyle, use
+ * {@code goog.html.SafeStyle.unwrap}.
+ *
+ * @see goog.html.SafeStyle#unwrap
+ * @override
+ */
+ goog.html.SafeStyle.prototype.toString = function() {
+ return 'SafeStyle{' +
+ this.privateDoNotAccessOrElseSafeStyleWrappedValue_ + '}';
+ };
+}
+
+
+/**
+ * Performs a runtime check that the provided object is indeed a
+ * SafeStyle object, and returns its value.
+ *
+ * @param {!goog.html.SafeStyle} safeStyle The object to extract from.
+ * @return {string} The safeStyle object's contained string, unless
+ * the run-time type check fails. In that case, {@code unwrap} returns an
+ * innocuous string, or, if assertions are enabled, throws
+ * {@code goog.asserts.AssertionError}.
+ */
+goog.html.SafeStyle.unwrap = function(safeStyle) {
+ // Perform additional Run-time type-checking to ensure that
+ // safeStyle is indeed an instance of the expected type. This
+ // provides some additional protection against security bugs due to
+ // application code that disables type checks.
+ // Specifically, the following checks are performed:
+ // 1. The object is an instance of the expected type.
+ // 2. The object is not an instance of a subclass.
+ // 3. The object carries a type marker for the expected type. "Faking" an
+ // object requires a reference to the type marker, which has names intended
+ // to stand out in code reviews.
+ if (safeStyle instanceof goog.html.SafeStyle &&
+ safeStyle.constructor === goog.html.SafeStyle &&
+ safeStyle.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
+ return safeStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
+ } else {
+ goog.asserts.fail(
+ 'expected object of type SafeStyle, got \'' + safeStyle + '\'');
+ return 'type_error:SafeStyle';
+ }
+};
+
+
+/**
+ * Package-internal utility method to create SafeStyle instances.
+ *
+ * @param {string} style The string to initialize the SafeStyle object with.
+ * @return {!goog.html.SafeStyle} The initialized SafeStyle object.
+ * @package
+ */
+goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse =
+ function(style) {
+ return new goog.html.SafeStyle().initSecurityPrivateDoNotAccessOrElse_(style);
+};
+
+
+/**
+ * Called from createSafeStyleSecurityPrivateDoNotAccessOrElse(). This
+ * method exists only so that the compiler can dead code eliminate static
+ * fields (like EMPTY) when they're not accessed.
+ * @param {string} style
+ * @return {!goog.html.SafeStyle}
+ * @private
+ */
+goog.html.SafeStyle.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
+ style) {
+ this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = style;
+ return this;
+};
+
+
+/**
+ * A SafeStyle instance corresponding to the empty string.
+ * @const {!goog.html.SafeStyle}
+ */
+goog.html.SafeStyle.EMPTY =
+ goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse('');
+
+
+/**
+ * The innocuous string generated by goog.html.SafeUrl.create when passed
+ * an unsafe value.
+ * @const {string}
+ */
+goog.html.SafeStyle.INNOCUOUS_STRING = 'zClosurez';
+
+
+/**
+ * Mapping of property names to their values.
+ * @typedef {!Object<string, goog.string.Const|string>}
+ */
+goog.html.SafeStyle.PropertyMap;
+
+
+/**
+ * Creates a new SafeStyle object from the properties specified in the map.
+ * @param {goog.html.SafeStyle.PropertyMap} map Mapping of property names to
+ * their values, for example {'margin': '1px'}. Names must consist of
+ * [-_a-zA-Z0-9]. Values might be strings consisting of
+ * [-,.'"%_!# a-zA-Z0-9], where " and ' must be properly balanced.
+ * Other values must be wrapped in goog.string.Const. Null value causes
+ * skipping the property.
+ * @return {!goog.html.SafeStyle}
+ * @throws {Error} If invalid name is provided.
+ * @throws {goog.asserts.AssertionError} If invalid value is provided. With
+ * disabled assertions, invalid value is replaced by
+ * goog.html.SafeStyle.INNOCUOUS_STRING.
+ */
+goog.html.SafeStyle.create = function(map) {
+ var style = '';
+ for (var name in map) {
+ if (!/^[-_a-zA-Z0-9]+$/.test(name)) {
+ throw Error('Name allows only [-_a-zA-Z0-9], got: ' + name);
+ }
+ var value = map[name];
+ if (value == null) {
+ continue;
+ }
+ if (value instanceof goog.string.Const) {
+ value = goog.string.Const.unwrap(value);
+ // These characters can be used to change context and we don't want that
+ // even with const values.
+ goog.asserts.assert(!/[{;}]/.test(value), 'Value does not allow [{;}].');
+ } else if (!goog.html.SafeStyle.VALUE_RE_.test(value)) {
+ goog.asserts.fail(
+ 'String value allows only [-,."\'%_!# a-zA-Z0-9], got: ' + value);
+ value = goog.html.SafeStyle.INNOCUOUS_STRING;
+ } else if (!goog.html.SafeStyle.hasBalancedQuotes_(value)) {
+ goog.asserts.fail('String value requires balanced quotes, got: ' + value);
+ value = goog.html.SafeStyle.INNOCUOUS_STRING;
+ }
+ style += name + ':' + value + ';';
+ }
+ if (!style) {
+ return goog.html.SafeStyle.EMPTY;
+ }
+ goog.html.SafeStyle.checkStyle_(style);
+ return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
+ style);
+};
+
+
+/**
+ * Checks that quotes (" and ') are properly balanced inside a string. Assumes
+ * that neither escape (\) nor any other character that could result in
+ * breaking out of a string parsing context are allowed;
+ * see http://www.w3.org/TR/css3-syntax/#string-token-diagram.
+ * @param {string} value Untrusted CSS property value.
+ * @return {boolean} True if property value is safe with respect to quote
+ * balancedness.
+ * @private
+ */
+goog.html.SafeStyle.hasBalancedQuotes_ = function(value) {
+ var outsideSingle = true;
+ var outsideDouble = true;
+ for (var i = 0; i < value.length; i++) {
+ var c = value.charAt(i);
+ if (c == "'" && outsideDouble) {
+ outsideSingle = !outsideSingle;
+ } else if (c == '"' && outsideSingle) {
+ outsideDouble = !outsideDouble;
+ }
+ }
+ return outsideSingle && outsideDouble;
+};
+
+
+// Keep in sync with the error string in create().
+/**
+ * Regular expression for safe values.
+ *
+ * Quotes (" and ') are allowed, but a check must be done elsewhere to ensure
+ * they're balanced.
+ *
+ * ',' allows multiple values to be assigned to the same property
+ * (e.g. background-attachment or font-family) and hence could allow
+ * multiple values to get injected, but that should pose no risk of XSS.
+ * @const {!RegExp}
+ * @private
+ */
+goog.html.SafeStyle.VALUE_RE_ = /^[-,."'%_!# a-zA-Z0-9]+$/;
+
+
+/**
+ * Creates a new SafeStyle object by concatenating the values.
+ * @param {...(!goog.html.SafeStyle|!Array<!goog.html.SafeStyle>)} var_args
+ * SafeStyles to concatenate.
+ * @return {!goog.html.SafeStyle}
+ */
+goog.html.SafeStyle.concat = function(var_args) {
+ var style = '';
+
+ /**
+ * @param {!goog.html.SafeStyle|!Array<!goog.html.SafeStyle>} argument
+ */
+ var addArgument = function(argument) {
+ if (goog.isArray(argument)) {
+ goog.array.forEach(argument, addArgument);
+ } else {
+ style += goog.html.SafeStyle.unwrap(argument);
+ }
+ };
+
+ goog.array.forEach(arguments, addArgument);
+ if (!style) {
+ return goog.html.SafeStyle.EMPTY;
+ }
+ return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
+ style);
+};
[35/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/sprite.png
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/sprite.png b/externs/GCL/externs/goog/demos/emoji/sprite.png
new file mode 100644
index 0000000..f16efa9
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/sprite.png differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/sprite2.png
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/sprite2.png b/externs/GCL/externs/goog/demos/emoji/sprite2.png
new file mode 100644
index 0000000..399d524
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/sprite2.png differ
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/emoji/unknown.gif
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/emoji/unknown.gif b/externs/GCL/externs/goog/demos/emoji/unknown.gif
new file mode 100644
index 0000000..7f0b804
Binary files /dev/null and b/externs/GCL/externs/goog/demos/emoji/unknown.gif differ
[09/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/vmlelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/vmlelement.js b/externs/GCL/externs/goog/graphics/vmlelement.js
new file mode 100644
index 0000000..9e72b13
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/vmlelement.js
@@ -0,0 +1,438 @@
+// 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 Thin wrappers around the DOM element returned from
+ * the different draw methods of the graphics. This is the VML implementation.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.graphics.VmlEllipseElement');
+goog.provide('goog.graphics.VmlGroupElement');
+goog.provide('goog.graphics.VmlImageElement');
+goog.provide('goog.graphics.VmlPathElement');
+goog.provide('goog.graphics.VmlRectElement');
+goog.provide('goog.graphics.VmlTextElement');
+
+
+goog.require('goog.dom');
+goog.require('goog.graphics.EllipseElement');
+goog.require('goog.graphics.GroupElement');
+goog.require('goog.graphics.ImageElement');
+goog.require('goog.graphics.PathElement');
+goog.require('goog.graphics.RectElement');
+goog.require('goog.graphics.TextElement');
+
+
+/**
+ * Returns the VML element corresponding to this object. This method is added
+ * to several classes below. Note that the return value of this method may
+ * change frequently in IE8, so it should not be cached externally.
+ * @return {Element} The VML element corresponding to this object.
+ * @this {goog.graphics.VmlGroupElement|goog.graphics.VmlEllipseElement|
+ * goog.graphics.VmlRectElement|goog.graphics.VmlPathElement|
+ * goog.graphics.VmlTextElement|goog.graphics.VmlImageElement}
+ * @private
+ */
+goog.graphics.vmlGetElement_ = function() {
+ this.element_ = this.getGraphics().getVmlElement(this.id_) || this.element_;
+ return this.element_;
+};
+
+
+
+/**
+ * Thin wrapper for VML group elements.
+ * This is an implementation of the goog.graphics.GroupElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.VmlGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.graphics.GroupElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.VmlGroupElement = function(element, graphics) {
+ this.id_ = element.id;
+ goog.graphics.GroupElement.call(this, element, graphics);
+};
+goog.inherits(goog.graphics.VmlGroupElement, goog.graphics.GroupElement);
+
+
+/** @override */
+goog.graphics.VmlGroupElement.prototype.getElement =
+ goog.graphics.vmlGetElement_;
+
+
+/**
+ * Remove all drawing elements from the group.
+ * @override
+ */
+goog.graphics.VmlGroupElement.prototype.clear = function() {
+ goog.dom.removeChildren(this.getElement());
+};
+
+
+/**
+ * @return {boolean} True if this group is the root canvas element.
+ * @private
+ */
+goog.graphics.VmlGroupElement.prototype.isRootElement_ = function() {
+ return this.getGraphics().getCanvasElement() == this;
+};
+
+
+/**
+ * Set the size of the group element.
+ * @param {number|string} width The width of the group element.
+ * @param {number|string} height The height of the group element.
+ * @override
+ */
+goog.graphics.VmlGroupElement.prototype.setSize = function(width, height) {
+ var element = this.getElement();
+
+ var style = element.style;
+ style.width = /** @suppress {missingRequire} */ (
+ goog.graphics.VmlGraphics.toSizePx(width));
+ style.height = /** @suppress {missingRequire} */ (
+ goog.graphics.VmlGraphics.toSizePx(height));
+
+ element.coordsize = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toSizeCoord(width) +
+ ' ' +
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toSizeCoord(height);
+
+ // Don't overwrite the root element's origin.
+ if (!this.isRootElement_()) {
+ element.coordorigin = '0 0';
+ }
+};
+
+
+
+/**
+ * Thin wrapper for VML ellipse elements.
+ * This is an implementation of the goog.graphics.EllipseElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.VmlGraphics} graphics The graphics creating
+ * this element.
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.EllipseElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.VmlEllipseElement = function(element, graphics,
+ cx, cy, rx, ry, stroke, fill) {
+ this.id_ = element.id;
+
+ goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill);
+
+ // Store center and radius for future calls to setRadius or setCenter.
+
+ /**
+ * X coordinate of the ellipse center.
+ * @type {number}
+ */
+ this.cx = cx;
+
+
+ /**
+ * Y coordinate of the ellipse center.
+ * @type {number}
+ */
+ this.cy = cy;
+
+
+ /**
+ * Radius length for the x-axis.
+ * @type {number}
+ */
+ this.rx = rx;
+
+
+ /**
+ * Radius length for the y-axis.
+ * @type {number}
+ */
+ this.ry = ry;
+};
+goog.inherits(goog.graphics.VmlEllipseElement, goog.graphics.EllipseElement);
+
+
+/** @override */
+goog.graphics.VmlEllipseElement.prototype.getElement =
+ goog.graphics.vmlGetElement_;
+
+
+/**
+ * Update the center point of the ellipse.
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @override
+ */
+goog.graphics.VmlEllipseElement.prototype.setCenter = function(cx, cy) {
+ this.cx = cx;
+ this.cy = cy;
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.setPositionAndSize(this.getElement(),
+ cx - this.rx, cy - this.ry, this.rx * 2, this.ry * 2);
+};
+
+
+/**
+ * Update the radius of the ellipse.
+ * @param {number} rx Center X coordinate.
+ * @param {number} ry Center Y coordinate.
+ * @override
+ */
+goog.graphics.VmlEllipseElement.prototype.setRadius = function(rx, ry) {
+ this.rx = rx;
+ this.ry = ry;
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.setPositionAndSize(this.getElement(),
+ this.cx - rx, this.cy - ry, rx * 2, ry * 2);
+};
+
+
+
+/**
+ * Thin wrapper for VML rectangle elements.
+ * This is an implementation of the goog.graphics.RectElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.VmlGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.RectElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.VmlRectElement = function(element, graphics, stroke, fill) {
+ this.id_ = element.id;
+ goog.graphics.RectElement.call(this, element, graphics, stroke, fill);
+};
+goog.inherits(goog.graphics.VmlRectElement, goog.graphics.RectElement);
+
+
+/** @override */
+goog.graphics.VmlRectElement.prototype.getElement =
+ goog.graphics.vmlGetElement_;
+
+
+/**
+ * Update the position of the rectangle.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @override
+ */
+goog.graphics.VmlRectElement.prototype.setPosition = function(x, y) {
+ var style = this.getElement().style;
+
+ style.left = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(x);
+ style.top = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(y);
+};
+
+
+/**
+ * Update the size of the rectangle.
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @override
+ */
+goog.graphics.VmlRectElement.prototype.setSize = function(width, height) {
+ var style = this.getElement().style;
+ style.width = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toSizePx(width);
+ style.height = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toSizePx(height);
+};
+
+
+
+/**
+ * Thin wrapper for VML path elements.
+ * This is an implementation of the goog.graphics.PathElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.VmlGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.PathElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.VmlPathElement = function(element, graphics, stroke, fill) {
+ this.id_ = element.id;
+ goog.graphics.PathElement.call(this, element, graphics, stroke, fill);
+};
+goog.inherits(goog.graphics.VmlPathElement, goog.graphics.PathElement);
+
+
+/** @override */
+goog.graphics.VmlPathElement.prototype.getElement =
+ goog.graphics.vmlGetElement_;
+
+
+/**
+ * Update the underlying path.
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @override
+ */
+goog.graphics.VmlPathElement.prototype.setPath = function(path) {
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.setAttribute(
+ this.getElement(), 'path',
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.getVmlPath(path));
+};
+
+
+
+/**
+ * Thin wrapper for VML text elements.
+ * This is an implementation of the goog.graphics.TextElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.VmlGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.TextElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.VmlTextElement = function(element, graphics, stroke, fill) {
+ this.id_ = element.id;
+ goog.graphics.TextElement.call(this, element, graphics, stroke, fill);
+};
+goog.inherits(goog.graphics.VmlTextElement, goog.graphics.TextElement);
+
+
+/** @override */
+goog.graphics.VmlTextElement.prototype.getElement =
+ goog.graphics.vmlGetElement_;
+
+
+/**
+ * Update the displayed text of the element.
+ * @param {string} text The text to draw.
+ * @override
+ */
+goog.graphics.VmlTextElement.prototype.setText = function(text) {
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.setAttribute(this.getElement().childNodes[1],
+ 'string', text);
+};
+
+
+
+/**
+ * Thin wrapper for VML image elements.
+ * This is an implementation of the goog.graphics.ImageElement interface.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.VmlGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.graphics.ImageElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.VmlImageElement = function(element, graphics) {
+ this.id_ = element.id;
+ goog.graphics.ImageElement.call(this, element, graphics);
+};
+goog.inherits(goog.graphics.VmlImageElement, goog.graphics.ImageElement);
+
+
+/** @override */
+goog.graphics.VmlImageElement.prototype.getElement =
+ goog.graphics.vmlGetElement_;
+
+
+/**
+ * Update the position of the image.
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @override
+ */
+goog.graphics.VmlImageElement.prototype.setPosition = function(x, y) {
+ var style = this.getElement().style;
+
+ style.left = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(x);
+ style.top = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(y);
+};
+
+
+/**
+ * Update the size of the image.
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @override
+ */
+goog.graphics.VmlImageElement.prototype.setSize = function(width, height) {
+ var style = this.getElement().style;
+ style.width = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(width);
+ style.height = /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.toPosPx(height);
+};
+
+
+/**
+ * Update the source of the image.
+ * @param {string} src Source of the image.
+ * @override
+ */
+goog.graphics.VmlImageElement.prototype.setSource = function(src) {
+ /** @suppress {missingRequire} */
+ goog.graphics.VmlGraphics.setAttribute(this.getElement(), 'src', src);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/vmlgraphics.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/vmlgraphics.js b/externs/GCL/externs/goog/graphics/vmlgraphics.js
new file mode 100644
index 0000000..5e0cd66
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/vmlgraphics.js
@@ -0,0 +1,948 @@
+// 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 VmlGraphics sub class that uses VML to draw the graphics.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.VmlGraphics');
+
+
+goog.require('goog.array');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.safe');
+goog.require('goog.events');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventType');
+goog.require('goog.graphics.AbstractGraphics');
+goog.require('goog.graphics.LinearGradient');
+goog.require('goog.graphics.Path');
+goog.require('goog.graphics.SolidFill');
+goog.require('goog.graphics.VmlEllipseElement');
+goog.require('goog.graphics.VmlGroupElement');
+goog.require('goog.graphics.VmlImageElement');
+goog.require('goog.graphics.VmlPathElement');
+goog.require('goog.graphics.VmlRectElement');
+goog.require('goog.graphics.VmlTextElement');
+goog.require('goog.html.uncheckedconversions');
+goog.require('goog.math');
+goog.require('goog.math.Size');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+goog.require('goog.style');
+
+
+
+/**
+ * A Graphics implementation for drawing using VML.
+ * @param {string|number} width The (non-zero) width in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {string|number} height The (non-zero) height in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {?number=} opt_coordWidth The coordinate width - if
+ * omitted or null, defaults to same as width.
+ * @param {?number=} opt_coordHeight The coordinate height - if
+ * omitted or null, defaults to same as height.
+ * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
+ * document we want to render in.
+ * @constructor
+ * @extends {goog.graphics.AbstractGraphics}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.VmlGraphics = function(width, height,
+ opt_coordWidth, opt_coordHeight,
+ opt_domHelper) {
+ goog.graphics.AbstractGraphics.call(this, width, height,
+ opt_coordWidth, opt_coordHeight,
+ opt_domHelper);
+ this.handler_ = new goog.events.EventHandler(this);
+ this.registerDisposable(this.handler_);
+};
+goog.inherits(goog.graphics.VmlGraphics, goog.graphics.AbstractGraphics);
+
+
+/**
+ * The prefix to use for VML elements
+ * @private
+ * @type {string}
+ */
+goog.graphics.VmlGraphics.VML_PREFIX_ = 'g_vml_';
+
+
+/**
+ * The VML namespace URN
+ * @private
+ * @type {string}
+ */
+goog.graphics.VmlGraphics.VML_NS_ = 'urn:schemas-microsoft-com:vml';
+
+
+/**
+ * The VML behavior URL.
+ * @private
+ * @type {string}
+ */
+goog.graphics.VmlGraphics.VML_IMPORT_ = '#default#VML';
+
+
+/**
+ * Whether the document is using IE8 standards mode, and therefore needs hacks.
+ * @private
+ * @type {boolean}
+ */
+goog.graphics.VmlGraphics.IE8_MODE_ =
+ goog.global.document && goog.global.document.documentMode &&
+ goog.global.document.documentMode >= 8;
+
+
+/**
+ * The coordinate multiplier to allow sub-pixel rendering
+ * @type {number}
+ */
+goog.graphics.VmlGraphics.COORD_MULTIPLIER = 100;
+
+
+/**
+ * Converts the given size to a css size. If it is a percentage, leaves it
+ * alone. Otherwise assumes px.
+ *
+ * @param {number|string} size The size to use.
+ * @return {string} The position adjusted for COORD_MULTIPLIER.
+ */
+goog.graphics.VmlGraphics.toCssSize = function(size) {
+ return goog.isString(size) && goog.string.endsWith(size, '%') ?
+ size : parseFloat(size.toString()) + 'px';
+};
+
+
+/**
+ * Multiplies positioning coordinates by COORD_MULTIPLIER to allow sub-pixel
+ * coordinates. Also adds a half pixel offset to match SVG.
+ *
+ * This function is internal for the VML supporting classes, and
+ * should not be used externally.
+ *
+ * @param {number|string} number A position in pixels.
+ * @return {number} The position adjusted for COORD_MULTIPLIER.
+ */
+goog.graphics.VmlGraphics.toPosCoord = function(number) {
+ return Math.round((parseFloat(number.toString()) - 0.5) *
+ goog.graphics.VmlGraphics.COORD_MULTIPLIER);
+};
+
+
+/**
+ * Add a "px" suffix to a number of pixels, and multiplies all coordinates by
+ * COORD_MULTIPLIER to allow sub-pixel coordinates.
+ *
+ * This function is internal for the VML supporting classes, and
+ * should not be used externally.
+ *
+ * @param {number|string} number A position in pixels.
+ * @return {string} The position with suffix 'px'.
+ */
+goog.graphics.VmlGraphics.toPosPx = function(number) {
+ return goog.graphics.VmlGraphics.toPosCoord(number) + 'px';
+};
+
+
+/**
+ * Multiplies the width or height coordinate by COORD_MULTIPLIER to allow
+ * sub-pixel coordinates.
+ *
+ * This function is internal for the VML supporting classes, and
+ * should not be used externally.
+ *
+ * @param {string|number} number A size in units.
+ * @return {number} The size multiplied by the correct factor.
+ */
+goog.graphics.VmlGraphics.toSizeCoord = function(number) {
+ return Math.round(parseFloat(number.toString()) *
+ goog.graphics.VmlGraphics.COORD_MULTIPLIER);
+};
+
+
+/**
+ * Add a "px" suffix to a number of pixels, and multiplies all coordinates by
+ * COORD_MULTIPLIER to allow sub-pixel coordinates.
+ *
+ * This function is internal for the VML supporting classes, and
+ * should not be used externally.
+ *
+ * @param {number|string} number A size in pixels.
+ * @return {string} The size with suffix 'px'.
+ */
+goog.graphics.VmlGraphics.toSizePx = function(number) {
+ return goog.graphics.VmlGraphics.toSizeCoord(number) + 'px';
+};
+
+
+/**
+ * Sets an attribute on the given VML element, in the way best suited to the
+ * current version of IE. Should only be used in the goog.graphics package.
+ * @param {Element} element The element to set an attribute
+ * on.
+ * @param {string} name The name of the attribute to set.
+ * @param {string} value The value to set it to.
+ */
+goog.graphics.VmlGraphics.setAttribute = function(element, name, value) {
+ if (goog.graphics.VmlGraphics.IE8_MODE_) {
+ element[name] = value;
+ } else {
+ element.setAttribute(name, value);
+ }
+};
+
+
+/**
+ * Event handler.
+ * @type {goog.events.EventHandler}
+ * @private
+ */
+goog.graphics.VmlGraphics.prototype.handler_;
+
+
+/**
+ * Creates a VML element. Used internally and by different VML classes.
+ * @param {string} tagName The type of element to create.
+ * @return {!Element} The created element.
+ */
+goog.graphics.VmlGraphics.prototype.createVmlElement = function(tagName) {
+ var element =
+ this.dom_.createElement(goog.graphics.VmlGraphics.VML_PREFIX_ + ':' +
+ tagName);
+ element.id = goog.string.createUniqueString();
+ return element;
+};
+
+
+/**
+ * Returns the VML element with the given id that is a child of this graphics
+ * object.
+ * Should be considered package private, and not used externally.
+ * @param {string} id The element id to find.
+ * @return {Element} The element with the given id, or null if none is found.
+ */
+goog.graphics.VmlGraphics.prototype.getVmlElement = function(id) {
+ return this.dom_.getElement(id);
+};
+
+
+/**
+ * Resets the graphics so they will display properly on IE8. Noop in older
+ * versions.
+ * @private
+ */
+goog.graphics.VmlGraphics.prototype.updateGraphics_ = function() {
+ if (goog.graphics.VmlGraphics.IE8_MODE_ && this.isInDocument()) {
+ // There's a risk of mXSS here, as the browser is not guaranteed to
+ // return the HTML that was originally written, when innerHTML is read.
+ // However, given that this a deprecated API and affects only IE, it seems
+ // an acceptable risk.
+ var html = goog.html.uncheckedconversions
+ .safeHtmlFromStringKnownToSatisfyTypeContract(
+ goog.string.Const.from('Assign innerHTML to itself'),
+ this.getElement().innerHTML);
+ goog.dom.safe.setInnerHtml(
+ /** @type {!Element} */ (this.getElement()), html);
+ }
+};
+
+
+/**
+ * Appends an element.
+ *
+ * @param {goog.graphics.Element} element The element wrapper.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ * @private
+ */
+goog.graphics.VmlGraphics.prototype.append_ = function(element, opt_group) {
+ var parent = opt_group || this.canvasElement;
+ parent.getElement().appendChild(element.getElement());
+ this.updateGraphics_();
+};
+
+
+/**
+ * Sets the fill for the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
+ * @param {goog.graphics.Fill?} fill The fill object.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.setElementFill = function(element, fill) {
+ var vmlElement = element.getElement();
+ goog.graphics.VmlGraphics.removeFill_(vmlElement);
+ if (fill instanceof goog.graphics.SolidFill) {
+ // NOTE(arv): VML does not understand 'transparent' so hard code support
+ // for it.
+ if (fill.getColor() == 'transparent') {
+ vmlElement.filled = false;
+ } else if (fill.getOpacity() != 1) {
+ vmlElement.filled = true;
+ // Set opacity (number 0-1 is translated to percent)
+ var fillNode = this.createVmlElement('fill');
+ fillNode.opacity = Math.round(fill.getOpacity() * 100) + '%';
+ fillNode.color = fill.getColor();
+ vmlElement.appendChild(fillNode);
+ } else {
+ vmlElement.filled = true;
+ vmlElement.fillcolor = fill.getColor();
+ }
+ } else if (fill instanceof goog.graphics.LinearGradient) {
+ vmlElement.filled = true;
+ // Add a 'fill' element
+ var gradient = this.createVmlElement('fill');
+ gradient.color = fill.getColor1();
+ gradient.color2 = fill.getColor2();
+ if (goog.isNumber(fill.getOpacity1())) {
+ gradient.opacity = fill.getOpacity1();
+ }
+ if (goog.isNumber(fill.getOpacity2())) {
+ gradient.opacity2 = fill.getOpacity2();
+ }
+ var angle = goog.math.angle(fill.getX1(), fill.getY1(),
+ fill.getX2(), fill.getY2());
+ // Our angles start from 0 to the right, and grow clockwise.
+ // MSIE starts from 0 to top, and grows anti-clockwise.
+ angle = Math.round(goog.math.standardAngle(270 - angle));
+ gradient.angle = angle;
+ gradient.type = 'gradient';
+ vmlElement.appendChild(gradient);
+ } else {
+ vmlElement.filled = false;
+ }
+ this.updateGraphics_();
+};
+
+
+/**
+ * Sets the stroke for the given element.
+ * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
+ * @param {goog.graphics.Stroke?} stroke The stroke object.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.setElementStroke = function(element,
+ stroke) {
+ var vmlElement = element.getElement();
+ if (stroke) {
+ vmlElement.stroked = true;
+
+ var width = stroke.getWidth();
+ if (goog.isString(width) && width.indexOf('px') == -1) {
+ width = parseFloat(width);
+ } else {
+ width = width * this.getPixelScaleX();
+ }
+
+ var strokeElement = vmlElement.getElementsByTagName('stroke')[0];
+ if (!strokeElement) {
+ strokeElement = strokeElement || this.createVmlElement('stroke');
+ vmlElement.appendChild(strokeElement);
+ }
+ strokeElement.opacity = stroke.getOpacity();
+ strokeElement.weight = width + 'px';
+ strokeElement.color = stroke.getColor();
+ } else {
+ vmlElement.stroked = false;
+ }
+ this.updateGraphics_();
+};
+
+
+/**
+ * Set the translation and rotation of an element.
+ *
+ * If a more general affine transform is needed than this provides
+ * (e.g. skew and scale) then use setElementAffineTransform.
+ * @param {number} x The x coordinate of the translation transform.
+ * @param {number} y The y coordinate of the translation transform.
+ * @param {number} angle The angle of the rotation transform.
+ * @param {number} centerX The horizontal center of the rotation transform.
+ * @param {number} centerY The vertical center of the rotation transform.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.setElementTransform = function(element, x,
+ y, angle, centerX, centerY) {
+ var el = element.getElement();
+
+ el.style.left = goog.graphics.VmlGraphics.toPosPx(x);
+ el.style.top = goog.graphics.VmlGraphics.toPosPx(y);
+ if (angle || el.rotation) {
+ el.rotation = angle;
+ el.coordsize = goog.graphics.VmlGraphics.toSizeCoord(centerX * 2) + ' ' +
+ goog.graphics.VmlGraphics.toSizeCoord(centerY * 2);
+ }
+};
+
+
+/**
+ * Set the transformation of an element.
+ * @param {!goog.graphics.Element} element The element wrapper.
+ * @param {!goog.graphics.AffineTransform} affineTransform The
+ * transformation applied to this element.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.setElementAffineTransform = function(
+ element, affineTransform) {
+ var t = affineTransform;
+ var vmlElement = element.getElement();
+ goog.graphics.VmlGraphics.removeSkew_(vmlElement);
+ var skewNode = this.createVmlElement('skew');
+ skewNode.on = 'true';
+ // Move the transform origin to 0px,0px of the graphics.
+ // In VML, 0,0 means the center of the element, -0.5,-0.5 left top conner of
+ // it.
+ skewNode.origin =
+ (-vmlElement.style.pixelLeft / vmlElement.style.pixelWidth - 0.5) + ',' +
+ (-vmlElement.style.pixelTop / vmlElement.style.pixelHeight - 0.5);
+ skewNode.offset = t.getTranslateX().toFixed(1) + 'px,' +
+ t.getTranslateY().toFixed(1) + 'px';
+ skewNode.matrix = [t.getScaleX().toFixed(6), t.getShearX().toFixed(6),
+ t.getShearY().toFixed(6), t.getScaleY().toFixed(6),
+ 0, 0].join(',');
+ vmlElement.appendChild(skewNode);
+ this.updateGraphics_();
+};
+
+
+/**
+ * Removes the skew information from a dom element.
+ * @param {Element} element DOM element.
+ * @private
+ */
+goog.graphics.VmlGraphics.removeSkew_ = function(element) {
+ goog.array.forEach(element.childNodes, function(child) {
+ if (child.tagName == 'skew') {
+ element.removeChild(child);
+ }
+ });
+};
+
+
+/**
+ * Removes the fill information from a dom element.
+ * @param {Element} element DOM element.
+ * @private
+ */
+goog.graphics.VmlGraphics.removeFill_ = function(element) {
+ element.fillcolor = '';
+ goog.array.forEach(element.childNodes, function(child) {
+ if (child.tagName == 'fill') {
+ element.removeChild(child);
+ }
+ });
+};
+
+
+/**
+ * Set top, left, width and height for an element.
+ * This function is internal for the VML supporting classes, and
+ * should not be used externally.
+ *
+ * @param {Element} element DOM element.
+ * @param {number} left Left ccordinate in pixels.
+ * @param {number} top Top ccordinate in pixels.
+ * @param {number} width Width in pixels.
+ * @param {number} height Height in pixels.
+ */
+goog.graphics.VmlGraphics.setPositionAndSize = function(
+ element, left, top, width, height) {
+ var style = element.style;
+ style.position = 'absolute';
+ style.left = goog.graphics.VmlGraphics.toPosPx(left);
+ style.top = goog.graphics.VmlGraphics.toPosPx(top);
+ style.width = goog.graphics.VmlGraphics.toSizePx(width);
+ style.height = goog.graphics.VmlGraphics.toSizePx(height);
+
+ if (element.tagName == 'shape') {
+ element.coordsize = goog.graphics.VmlGraphics.toSizeCoord(width) + ' ' +
+ goog.graphics.VmlGraphics.toSizeCoord(height);
+ }
+};
+
+
+/**
+ * Creates an element spanning the surface.
+ *
+ * @param {string} type The type of element to create.
+ * @return {!Element} The created, positioned, and sized element.
+ * @private
+ */
+goog.graphics.VmlGraphics.prototype.createFullSizeElement_ = function(type) {
+ var element = this.createVmlElement(type);
+ var size = this.getCoordSize();
+ goog.graphics.VmlGraphics.setPositionAndSize(element, 0, 0, size.width,
+ size.height);
+ return element;
+};
+
+
+/**
+ * IE magic - if this "no-op" line is not here, the if statement below will
+ * fail intermittently. The eval is used to prevent the JsCompiler from
+ * stripping this piece of code, which it quite reasonably thinks is doing
+ * nothing. Put it in try-catch block to prevent "Unspecified Error" when
+ * this statement is executed in a defer JS in IE.
+ * More info here:
+ * http://www.mail-archive.com/users@openlayers.org/msg01838.html
+ */
+try {
+ eval('document.namespaces');
+} catch (ex) {}
+
+
+/**
+ * Creates the DOM representation of the graphics area.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.createDom = function() {
+ var doc = this.dom_.getDocument();
+
+ // Add the namespace.
+ if (!doc.namespaces[goog.graphics.VmlGraphics.VML_PREFIX_]) {
+ if (goog.graphics.VmlGraphics.IE8_MODE_) {
+ doc.namespaces.add(goog.graphics.VmlGraphics.VML_PREFIX_,
+ goog.graphics.VmlGraphics.VML_NS_,
+ goog.graphics.VmlGraphics.VML_IMPORT_);
+ } else {
+ doc.namespaces.add(goog.graphics.VmlGraphics.VML_PREFIX_,
+ goog.graphics.VmlGraphics.VML_NS_);
+ }
+
+ // We assume that we only need to add the CSS if the namespace was not
+ // present
+ var ss = doc.createStyleSheet();
+ ss.cssText = goog.graphics.VmlGraphics.VML_PREFIX_ + '\\:*' +
+ '{behavior:url(#default#VML)}';
+ }
+
+ // Outer a DIV with overflow hidden for clipping.
+ // All inner elements are absolutly positioned on-top of this div.
+ var pixelWidth = this.width;
+ var pixelHeight = this.height;
+ var divElement = this.dom_.createDom(goog.dom.TagName.DIV, {
+ 'style': 'overflow:hidden;position:relative;width:' +
+ goog.graphics.VmlGraphics.toCssSize(pixelWidth) + ';height:' +
+ goog.graphics.VmlGraphics.toCssSize(pixelHeight)
+ });
+
+ this.setElementInternal(divElement);
+
+ var group = this.createVmlElement('group');
+ var style = group.style;
+
+ style.position = 'absolute';
+ style.left = style.top = 0;
+ style.width = this.width;
+ style.height = this.height;
+ if (this.coordWidth) {
+ group.coordsize =
+ goog.graphics.VmlGraphics.toSizeCoord(this.coordWidth) + ' ' +
+ goog.graphics.VmlGraphics.toSizeCoord(
+ /** @type {number} */ (this.coordHeight));
+ } else {
+ group.coordsize = goog.graphics.VmlGraphics.toSizeCoord(pixelWidth) + ' ' +
+ goog.graphics.VmlGraphics.toSizeCoord(pixelHeight);
+ }
+
+ if (goog.isDef(this.coordLeft)) {
+ group.coordorigin = goog.graphics.VmlGraphics.toSizeCoord(this.coordLeft) +
+ ' ' + goog.graphics.VmlGraphics.toSizeCoord(this.coordTop);
+ } else {
+ group.coordorigin = '0 0';
+ }
+ divElement.appendChild(group);
+
+ this.canvasElement = new goog.graphics.VmlGroupElement(group, this);
+
+ goog.events.listen(divElement, goog.events.EventType.RESIZE, goog.bind(
+ this.handleContainerResize_, this));
+};
+
+
+/**
+ * Changes the canvas element size to match the container element size.
+ * @private
+ */
+goog.graphics.VmlGraphics.prototype.handleContainerResize_ = function() {
+ var size = goog.style.getSize(this.getElement());
+ var style = this.canvasElement.getElement().style;
+
+ if (size.width) {
+ style.width = size.width + 'px';
+ style.height = size.height + 'px';
+ } else {
+ var current = this.getElement();
+ while (current && current.currentStyle &&
+ current.currentStyle.display != 'none') {
+ current = current.parentNode;
+ }
+ if (current && current.currentStyle) {
+ this.handler_.listen(current, 'propertychange',
+ this.handleContainerResize_);
+ }
+ }
+
+ this.dispatchEvent(goog.events.EventType.RESIZE);
+};
+
+
+/**
+ * Handle property changes on hidden ancestors.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.graphics.VmlGraphics.prototype.handlePropertyChange_ = function(e) {
+ var prop = e.getBrowserEvent().propertyName;
+ if (prop == 'display' || prop == 'className') {
+ this.handler_.unlisten(/** @type {Element} */(e.target),
+ 'propertychange', this.handlePropertyChange_);
+ this.handleContainerResize_();
+ }
+};
+
+
+/**
+ * Changes the coordinate system position.
+ * @param {number} left The coordinate system left bound.
+ * @param {number} top The coordinate system top bound.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.setCoordOrigin = function(left, top) {
+ this.coordLeft = left;
+ this.coordTop = top;
+
+ this.canvasElement.getElement().coordorigin =
+ goog.graphics.VmlGraphics.toSizeCoord(this.coordLeft) + ' ' +
+ goog.graphics.VmlGraphics.toSizeCoord(this.coordTop);
+};
+
+
+/**
+ * Changes the coordinate size.
+ * @param {number} coordWidth The coordinate width.
+ * @param {number} coordHeight The coordinate height.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.setCoordSize = function(coordWidth,
+ coordHeight) {
+ goog.graphics.VmlGraphics.superClass_.setCoordSize.apply(this, arguments);
+
+ this.canvasElement.getElement().coordsize =
+ goog.graphics.VmlGraphics.toSizeCoord(coordWidth) + ' ' +
+ goog.graphics.VmlGraphics.toSizeCoord(coordHeight);
+};
+
+
+/**
+ * Change the size of the canvas.
+ * @param {number} pixelWidth The width in pixels.
+ * @param {number} pixelHeight The height in pixels.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.setSize = function(pixelWidth,
+ pixelHeight) {
+ goog.style.setSize(this.getElement(), pixelWidth, pixelHeight);
+};
+
+
+/**
+ * @return {!goog.math.Size} Returns the number of pixels spanned by the
+ * surface.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.getPixelSize = function() {
+ var el = this.getElement();
+ // The following relies on the fact that the size can never be 0.
+ return new goog.math.Size(el.style.pixelWidth || el.offsetWidth || 1,
+ el.style.pixelHeight || el.offsetHeight || 1);
+};
+
+
+/**
+ * Remove all drawing elements from the graphics.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.clear = function() {
+ this.canvasElement.clear();
+};
+
+
+/**
+ * Draw an ellipse.
+ *
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.EllipseElement} The newly created element.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.drawEllipse = function(cx, cy, rx, ry,
+ stroke, fill, opt_group) {
+ var element = this.createVmlElement('oval');
+ goog.graphics.VmlGraphics.setPositionAndSize(element, cx - rx, cy - ry,
+ rx * 2, ry * 2);
+ var wrapper = new goog.graphics.VmlEllipseElement(element, this,
+ cx, cy, rx, ry, stroke, fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw a rectangle.
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of rectangle.
+ * @param {number} height Height of rectangle.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the
+ * stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.RectElement} The newly created element.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.drawRect = function(x, y, width, height,
+ stroke, fill, opt_group) {
+ var element = this.createVmlElement('rect');
+ goog.graphics.VmlGraphics.setPositionAndSize(element, x, y, width, height);
+ var wrapper = new goog.graphics.VmlRectElement(element, this, stroke, fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw an image.
+ *
+ * @param {number} x X coordinate (left).
+ * @param {number} y Y coordinate (top).
+ * @param {number} width Width of image.
+ * @param {number} height Height of image.
+ * @param {string} src Source of the image.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.ImageElement} The newly created element.
+ */
+goog.graphics.VmlGraphics.prototype.drawImage = function(x, y, width, height,
+ src, opt_group) {
+ var element = this.createVmlElement('image');
+ goog.graphics.VmlGraphics.setPositionAndSize(element, x, y, width, height);
+ goog.graphics.VmlGraphics.setAttribute(element, 'src', src);
+ var wrapper = new goog.graphics.VmlImageElement(element, this);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw a text string vertically centered on a given line.
+ *
+ * @param {string} text The text to draw.
+ * @param {number} x1 X coordinate of start of line.
+ * @param {number} y1 Y coordinate of start of line.
+ * @param {number} x2 X coordinate of end of line.
+ * @param {number} y2 Y coordinate of end of line.
+ * @param {?string} align Horizontal alignment: left (default), center, right.
+ * @param {goog.graphics.Font} font Font describing the font properties.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.TextElement} The newly created element.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.drawTextOnLine = function(
+ text, x1, y1, x2, y2, align, font, stroke, fill, opt_group) {
+ var shape = this.createFullSizeElement_('shape');
+
+ var pathElement = this.createVmlElement('path');
+ var path = 'M' + goog.graphics.VmlGraphics.toPosCoord(x1) + ',' +
+ goog.graphics.VmlGraphics.toPosCoord(y1) + 'L' +
+ goog.graphics.VmlGraphics.toPosCoord(x2) + ',' +
+ goog.graphics.VmlGraphics.toPosCoord(y2) + 'E';
+ goog.graphics.VmlGraphics.setAttribute(pathElement, 'v', path);
+ goog.graphics.VmlGraphics.setAttribute(pathElement, 'textpathok', 'true');
+
+ var textPathElement = this.createVmlElement('textpath');
+ textPathElement.setAttribute('on', 'true');
+ var style = textPathElement.style;
+ style.fontSize = font.size * this.getPixelScaleX();
+ style.fontFamily = font.family;
+ if (align != null) {
+ style['v-text-align'] = align;
+ }
+ if (font.bold) {
+ style.fontWeight = 'bold';
+ }
+ if (font.italic) {
+ style.fontStyle = 'italic';
+ }
+ goog.graphics.VmlGraphics.setAttribute(textPathElement, 'string', text);
+
+ shape.appendChild(pathElement);
+ shape.appendChild(textPathElement);
+ var wrapper = new goog.graphics.VmlTextElement(shape, this, stroke, fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Draw a path.
+ *
+ * @param {!goog.graphics.Path} path The path object to draw.
+ * @param {goog.graphics.Stroke?} stroke Stroke object describing the stroke.
+ * @param {goog.graphics.Fill?} fill Fill object describing the fill.
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.PathElement} The newly created element.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.drawPath = function(path, stroke, fill,
+ opt_group) {
+ var element = this.createFullSizeElement_('shape');
+ goog.graphics.VmlGraphics.setAttribute(element, 'path',
+ goog.graphics.VmlGraphics.getVmlPath(path));
+
+ var wrapper = new goog.graphics.VmlPathElement(element, this, stroke, fill);
+ this.append_(wrapper, opt_group);
+ return wrapper;
+};
+
+
+/**
+ * Returns a string representation of a logical path suitable for use in
+ * a VML element.
+ *
+ * @param {goog.graphics.Path} path The logical path.
+ * @return {string} The VML path representation.
+ * @suppress {deprecated} goog.graphics is deprecated.
+ */
+goog.graphics.VmlGraphics.getVmlPath = function(path) {
+ var list = [];
+ path.forEachSegment(function(segment, args) {
+ switch (segment) {
+ case goog.graphics.Path.Segment.MOVETO:
+ list.push('m');
+ Array.prototype.push.apply(list, goog.array.map(args,
+ goog.graphics.VmlGraphics.toSizeCoord));
+ break;
+ case goog.graphics.Path.Segment.LINETO:
+ list.push('l');
+ Array.prototype.push.apply(list, goog.array.map(args,
+ goog.graphics.VmlGraphics.toSizeCoord));
+ break;
+ case goog.graphics.Path.Segment.CURVETO:
+ list.push('c');
+ Array.prototype.push.apply(list, goog.array.map(args,
+ goog.graphics.VmlGraphics.toSizeCoord));
+ break;
+ case goog.graphics.Path.Segment.CLOSE:
+ list.push('x');
+ break;
+ case goog.graphics.Path.Segment.ARCTO:
+ var toAngle = args[2] + args[3];
+ var cx = goog.graphics.VmlGraphics.toSizeCoord(
+ args[4] - goog.math.angleDx(toAngle, args[0]));
+ var cy = goog.graphics.VmlGraphics.toSizeCoord(
+ args[5] - goog.math.angleDy(toAngle, args[1]));
+ var rx = goog.graphics.VmlGraphics.toSizeCoord(args[0]);
+ var ry = goog.graphics.VmlGraphics.toSizeCoord(args[1]);
+ // VML angles are in fd units (see http://www.w3.org/TR/NOTE-VML) and
+ // are positive counter-clockwise.
+ var fromAngle = Math.round(args[2] * -65536);
+ var extent = Math.round(args[3] * -65536);
+ list.push('ae', cx, cy, rx, ry, fromAngle, extent);
+ break;
+ }
+ });
+ return list.join(' ');
+};
+
+
+/**
+ * Create an empty group of drawing elements.
+ *
+ * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
+ * to append to. If not specified, appends to the main canvas.
+ *
+ * @return {!goog.graphics.GroupElement} The newly created group.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.createGroup = function(opt_group) {
+ var element = this.createFullSizeElement_('group');
+ var parent = opt_group || this.canvasElement;
+ parent.getElement().appendChild(element);
+ return new goog.graphics.VmlGroupElement(element, this);
+};
+
+
+/**
+ * Measure and return the width (in pixels) of a given text string.
+ * Text measurement is needed to make sure a text can fit in the allocated
+ * area. The way text length is measured is by writing it into a div that is
+ * after the visible area, measure the div width, and immediatly erase the
+ * written value.
+ *
+ * @param {string} text The text string to measure.
+ * @param {goog.graphics.Font} font The font object describing the font style.
+ *
+ * @return {number} The width in pixels of the text strings.
+ * @override
+ */
+goog.graphics.VmlGraphics.prototype.getTextWidth = function(text, font) {
+ // TODO(arv): Implement
+ return 0;
+};
+
+
+/** @override */
+goog.graphics.VmlGraphics.prototype.enterDocument = function() {
+ goog.graphics.VmlGraphics.superClass_.enterDocument.call(this);
+ this.handleContainerResize_();
+ this.updateGraphics_();
+};
+
+
+/**
+ * Disposes of the component by removing event handlers, detacing DOM nodes from
+ * the document body, and removing references to them.
+ * @override
+ * @protected
+ */
+goog.graphics.VmlGraphics.prototype.disposeInternal = function() {
+ this.canvasElement = null;
+ goog.graphics.VmlGraphics.superClass_.disposeInternal.call(this);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/history/event.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/history/event.js b/externs/GCL/externs/goog/history/event.js
new file mode 100644
index 0000000..19250df
--- /dev/null
+++ b/externs/GCL/externs/goog/history/event.js
@@ -0,0 +1,55 @@
+// 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 The event object dispatched when the history changes.
+ *
+ */
+
+
+goog.provide('goog.history.Event');
+
+goog.require('goog.events.Event');
+goog.require('goog.history.EventType');
+
+
+
+/**
+ * Event object dispatched after the history state has changed.
+ * @param {string} token The string identifying the new history state.
+ * @param {boolean} isNavigation True if the event was triggered by a browser
+ * action, such as forward or back, clicking on a link, editing the URL, or
+ * calling {@code window.history.(go|back|forward)}.
+ * False if the token has been changed by a {@code setToken} or
+ * {@code replaceToken} call.
+ * @constructor
+ * @extends {goog.events.Event}
+ * @final
+ */
+goog.history.Event = function(token, isNavigation) {
+ goog.events.Event.call(this, goog.history.EventType.NAVIGATE);
+
+ /**
+ * The current history state.
+ * @type {string}
+ */
+ this.token = token;
+
+ /**
+ * Whether the event was triggered by browser navigation.
+ * @type {boolean}
+ */
+ this.isNavigation = isNavigation;
+};
+goog.inherits(goog.history.Event, goog.events.Event);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/history/eventtype.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/history/eventtype.js b/externs/GCL/externs/goog/history/eventtype.js
new file mode 100644
index 0000000..4268df3
--- /dev/null
+++ b/externs/GCL/externs/goog/history/eventtype.js
@@ -0,0 +1,30 @@
+// 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 Event types for goog.history.
+ *
+ */
+
+
+goog.provide('goog.history.EventType');
+
+
+/**
+ * Event types for goog.history.
+ * @enum {string}
+ */
+goog.history.EventType = {
+ NAVIGATE: 'navigate'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/history/history.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/history/history.js b/externs/GCL/externs/goog/history/history.js
new file mode 100644
index 0000000..af82ba0
--- /dev/null
+++ b/externs/GCL/externs/goog/history/history.js
@@ -0,0 +1,1005 @@
+// 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 Browser history stack management class.
+ *
+ * The goog.History object allows a page to create history state without leaving
+ * the current document. This allows users to, for example, hit the browser's
+ * back button without leaving the current page.
+ *
+ * The history object can be instantiated in one of two modes. In user visible
+ * mode, the current history state is shown in the browser address bar as a
+ * document location fragment (the portion of the URL after the '#'). These
+ * addresses can be bookmarked, copied and pasted into another browser, and
+ * modified directly by the user like any other URL.
+ *
+ * If the history object is created in invisible mode, the user can still
+ * affect the state using the browser forward and back buttons, but the current
+ * state is not displayed in the browser address bar. These states are not
+ * bookmarkable or editable.
+ *
+ * It is possible to use both types of history object on the same page, but not
+ * currently recommended due to browser deficiencies.
+ *
+ * Tested to work in:
+ * <ul>
+ * <li>Firefox 1.0-4.0
+ * <li>Internet Explorer 5.5-9.0
+ * <li>Opera 9+
+ * <li>Safari 4+
+ * </ul>
+ *
+ * @author brenneman@google.com (Shawn Brenneman)
+ * @see ../demos/history1.html
+ * @see ../demos/history2.html
+ */
+
+/* Some browser specific implementation notes:
+ *
+ * Firefox (through version 2.0.0.1):
+ *
+ * Ideally, navigating inside the hidden iframe could be done using
+ * about:blank#state instead of a real page on the server. Setting the hash on
+ * about:blank creates history entries, but the hash is not recorded and is lost
+ * when the user hits the back button. This is true in Opera as well. A blank
+ * HTML page must be provided for invisible states to be recorded in the iframe
+ * hash.
+ *
+ * After leaving the page with the History object and returning to it (by
+ * hitting the back button from another site), the last state of the iframe is
+ * overwritten. The most recent state is saved in a hidden input field so the
+ * previous state can be restored.
+ *
+ * Firefox does not store the previous value of dynamically generated input
+ * elements. To save the state, the hidden element must be in the HTML document,
+ * either in the original source or added with document.write. If a reference
+ * to the input element is not provided as a constructor argument, then the
+ * history object creates one using document.write, in which case the history
+ * object must be created from a script in the body element of the page.
+ *
+ * Manually editing the address field to a different hash link prevents further
+ * updates to the address bar. The page continues to work as normal, but the
+ * address shown will be incorrect until the page is reloaded.
+ *
+ * NOTE(user): It should be noted that Firefox will URL encode any non-regular
+ * ascii character, along with |space|, ", <, and >, when added to the fragment.
+ * If you expect these characters in your tokens you should consider that
+ * setToken('<b>') would result in the history fragment "%3Cb%3E", and
+ * "espére" would show "esp%E8re". (IE allows unicode characters in the
+ * fragment)
+ *
+ * TODO(user): Should we encapsulate this escaping into the API for visible
+ * history and encode all characters that aren't supported by Firefox? It also
+ * needs to be optional so apps can elect to handle the escaping themselves.
+ *
+ *
+ * Internet Explorer (through version 7.0):
+ *
+ * IE does not modify the history stack when the document fragment is changed.
+ * We create history entries instead by using document.open and document.write
+ * into a hidden iframe.
+ *
+ * IE destroys the history stack when navigating from /foo.html#someFragment to
+ * /foo.html. The workaround is to always append the # to the URL. This is
+ * somewhat unfortunate when loading the page without any # specified, because
+ * a second "click" sound will play on load as the fragment is automatically
+ * appended. If the hash is always present, this can be avoided.
+ *
+ * Manually editing the hash in the address bar in IE6 and then hitting the back
+ * button can replace the page with a blank page. This is a Bad User Experience,
+ * but probably not preventable.
+ *
+ * IE also has a bug when the page is loaded via a server redirect, setting
+ * a new hash value on the window location will force a page reload. This will
+ * happen the first time setToken is called with a new token. The only known
+ * workaround is to force a client reload early, for example by setting
+ * window.location.hash = window.location.hash, which will otherwise be a no-op.
+ *
+ * Internet Explorer 8.0, Webkit 532.1 and Gecko 1.9.2:
+ *
+ * IE8 has introduced the support to the HTML5 onhashchange event, which means
+ * we don't have to do any polling to detect fragment changes. Chrome and
+ * Firefox have added it on their newer builds, wekbit 532.1 and gecko 1.9.2.
+ * http://www.w3.org/TR/html5/history.html
+ * NOTE(goto): it is important to note that the document needs to have the
+ * <!DOCTYPE html> tag to enable the IE8 HTML5 mode. If the tag is not present,
+ * IE8 will enter IE7 compatibility mode (which can also be enabled manually).
+ *
+ * Opera (through version 9.02):
+ *
+ * Navigating through pages at a rate faster than some threshhold causes Opera
+ * to cancel all outstanding timeouts and intervals, including the location
+ * polling loop. Since this condition cannot be detected, common input events
+ * are captured to cause the loop to restart.
+ *
+ * location.replace is adding a history entry inside setHash_, despite
+ * documentation that suggests it should not.
+ *
+ *
+ * Safari (through version 2.0.4):
+ *
+ * After hitting the back button, the location.hash property is no longer
+ * readable from JavaScript. This is fixed in later WebKit builds, but not in
+ * currently shipping Safari. For now, the only recourse is to disable history
+ * states in Safari. Pages are still navigable via the History object, but the
+ * back button cannot restore previous states.
+ *
+ * Safari sets history states on navigation to a hashlink, but doesn't allow
+ * polling of the hash, so following actual anchor links in the page will create
+ * useless history entries. Using location.replace does not seem to prevent
+ * this. Not a terribly good user experience, but fixed in later Webkits.
+ *
+ *
+ * WebKit (nightly version 420+):
+ *
+ * This almost works. Returning to a page with an invisible history object does
+ * not restore the old state, however, and there is no pageshow event that fires
+ * in this browser. Holding off on finding a solution for now.
+ *
+ *
+ * HTML5 capable browsers (Firefox 4, Chrome, Safari 5)
+ *
+ * No known issues. The goog.history.Html5History class provides a simpler
+ * implementation more suitable for recent browsers. These implementations
+ * should be merged so the history class automatically invokes the correct
+ * implementation.
+ */
+
+
+goog.provide('goog.History');
+goog.provide('goog.History.Event');
+goog.provide('goog.History.EventType');
+
+goog.require('goog.Timer');
+goog.require('goog.asserts');
+goog.require('goog.dom');
+goog.require('goog.dom.InputType');
+goog.require('goog.dom.safe');
+/** @suppress {extraRequire} */
+goog.require('goog.events.Event');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.history.Event');
+goog.require('goog.history.EventType');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.TrustedResourceUrl');
+goog.require('goog.html.legacyconversions');
+goog.require('goog.labs.userAgent.device');
+goog.require('goog.memoize');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A history management object. Can be instantiated in user-visible mode (uses
+ * the address fragment to manage state) or in hidden mode. This object should
+ * be created from a script in the document body before the document has
+ * finished loading.
+ *
+ * To store the hidden states in browsers other than IE, a hidden iframe is
+ * used. It must point to a valid html page on the same domain (which can and
+ * probably should be blank.)
+ *
+ * Sample instantiation and usage:
+ *
+ * <pre>
+ * // Instantiate history to use the address bar for state.
+ * var h = new goog.History();
+ * goog.events.listen(h, goog.history.EventType.NAVIGATE, navCallback);
+ * h.setEnabled(true);
+ *
+ * // Any changes to the location hash will call the following function.
+ * function navCallback(e) {
+ * alert('Navigated to state "' + e.token + '"');
+ * }
+ *
+ * // The history token can also be set from code directly.
+ * h.setToken('foo');
+ * </pre>
+ *
+ * @param {boolean=} opt_invisible True to use hidden history states instead of
+ * the user-visible location hash.
+ * @param {!goog.html.TrustedResourceUrl|string=} opt_blankPageUrl A URL to a
+ * blank page on the same server. Required if opt_invisible is true. If
+ * possible pass a TrustedResourceUrl; string is supported for
+ * backwards-compatibility only and uses goog.html.legacyconversions.
+ * This URL is also used as the src for the iframe used to track history
+ * state in IE (if not specified the iframe is not given a src attribute).
+ * Access is Denied error may occur in IE7 if the window's URL's scheme
+ * is https, and this URL is not specified.
+ * @param {HTMLInputElement=} opt_input The hidden input element to be used to
+ * store the history token. If not provided, a hidden input element will
+ * be created using document.write.
+ * @param {HTMLIFrameElement=} opt_iframe The hidden iframe that will be used by
+ * IE for pushing history state changes, or by all browsers if opt_invisible
+ * is true. If not provided, a hidden iframe element will be created using
+ * document.write.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.History = function(opt_invisible, opt_blankPageUrl, opt_input,
+ opt_iframe) {
+ goog.events.EventTarget.call(this);
+
+ if (opt_invisible && !opt_blankPageUrl) {
+ throw Error('Can\'t use invisible history without providing a blank page.');
+ }
+
+ var input;
+ if (opt_input) {
+ input = opt_input;
+ } else {
+ var inputId = 'history_state' + goog.History.historyCount_;
+ var inputHtml = goog.html.SafeHtml.create('input',
+ {type: goog.dom.InputType.TEXT, name: inputId, id: inputId,
+ style: goog.string.Const.from('display:none')});
+ goog.dom.safe.documentWrite(document, inputHtml);
+ input = goog.dom.getElement(inputId);
+ }
+
+ /**
+ * An input element that stores the current iframe state. Used to restore
+ * the state when returning to the page on non-IE browsers.
+ * @type {HTMLInputElement}
+ * @private
+ */
+ this.hiddenInput_ = /** @type {HTMLInputElement} */ (input);
+
+ /**
+ * The window whose location contains the history token fragment. This is
+ * the window that contains the hidden input. It's typically the top window.
+ * It is not necessarily the same window that the js code is loaded in.
+ * @type {Window}
+ * @private
+ */
+ this.window_ = opt_input ?
+ goog.dom.getWindow(goog.dom.getOwnerDocument(opt_input)) : window;
+
+ var iframeSrc;
+ if (goog.isString(opt_blankPageUrl)) {
+ iframeSrc = goog.html.legacyconversions.trustedResourceUrlFromString(
+ opt_blankPageUrl);
+ } else {
+ iframeSrc = opt_blankPageUrl;
+ }
+
+ /**
+ * The base URL for the hidden iframe. Must refer to a document in the
+ * same domain as the main page.
+ * @type {!goog.html.TrustedResourceUrl|undefined}
+ * @private
+ */
+ this.iframeSrc_ = iframeSrc;
+
+ if (goog.userAgent.IE && !opt_blankPageUrl) {
+ if (window.location.protocol == 'https') {
+ this.iframeSrc_ = goog.html.TrustedResourceUrl.fromConstant(
+ goog.string.Const.from('https:///'));
+ } else {
+ this.iframeSrc_ = goog.html.TrustedResourceUrl.fromConstant(
+ goog.string.Const.from('javascript:""'));
+ }
+ }
+
+ /**
+ * A timer for polling the current history state for changes.
+ * @type {goog.Timer}
+ * @private
+ */
+ this.timer_ = new goog.Timer(goog.History.PollingType.NORMAL);
+ this.registerDisposable(this.timer_);
+
+ /**
+ * True if the state tokens are displayed in the address bar, false for hidden
+ * history states.
+ * @type {boolean}
+ * @private
+ */
+ this.userVisible_ = !opt_invisible;
+
+ /**
+ * An object to keep track of the history event listeners.
+ * @type {goog.events.EventHandler<!goog.History>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ if (opt_invisible || goog.History.LEGACY_IE) {
+ var iframe;
+ if (opt_iframe) {
+ iframe = opt_iframe;
+ } else {
+ var iframeId = 'history_iframe' + goog.History.historyCount_;
+ // Using a "sandbox" attribute on the iframe might be possible, but
+ // this HTML didn't initially have it and when it was refactored
+ // to SafeHtml it was kept without it.
+ var iframeHtml = goog.html.SafeHtml.createIframe(this.iframeSrc_, null,
+ {id: iframeId, style: goog.string.Const.from('display:none'),
+ sandbox: undefined});
+ goog.dom.safe.documentWrite(document, iframeHtml);
+ iframe = goog.dom.getElement(iframeId);
+ }
+
+ /**
+ * Internet Explorer uses a hidden iframe for all history changes. Other
+ * browsers use the iframe only for pushing invisible states.
+ * @type {HTMLIFrameElement}
+ * @private
+ */
+ this.iframe_ = /** @type {HTMLIFrameElement} */ (iframe);
+
+ /**
+ * Whether the hidden iframe has had a document written to it yet in this
+ * session.
+ * @type {boolean}
+ * @private
+ */
+ this.unsetIframe_ = true;
+ }
+
+ if (goog.History.LEGACY_IE) {
+ // IE relies on the hidden input to restore the history state from previous
+ // sessions, but input values are only restored after window.onload. Set up
+ // a callback to poll the value after the onload event.
+ this.eventHandler_.listen(this.window_,
+ goog.events.EventType.LOAD,
+ this.onDocumentLoaded);
+
+ /**
+ * IE-only variable for determining if the document has loaded.
+ * @type {boolean}
+ * @protected
+ */
+ this.documentLoaded = false;
+
+ /**
+ * IE-only variable for storing whether the history object should be enabled
+ * once the document finishes loading.
+ * @type {boolean}
+ * @private
+ */
+ this.shouldEnable_ = false;
+ }
+
+ // Set the initial history state.
+ if (this.userVisible_) {
+ this.setHash_(this.getToken(), true);
+ } else {
+ this.setIframeToken_(this.hiddenInput_.value);
+ }
+
+ goog.History.historyCount_++;
+};
+goog.inherits(goog.History, goog.events.EventTarget);
+
+
+/**
+ * Status of when the object is active and dispatching events.
+ * @type {boolean}
+ * @private
+ */
+goog.History.prototype.enabled_ = false;
+
+
+/**
+ * Whether the object is performing polling with longer intervals. This can
+ * occur for instance when setting the location of the iframe when in invisible
+ * mode and the server that is hosting the blank html page is down. In FF, this
+ * will cause the location of the iframe to no longer be accessible, with
+ * permision denied exceptions being thrown on every access of the history
+ * token. When this occurs, the polling interval is elongated. This causes
+ * exceptions to be thrown at a lesser rate while allowing for the history
+ * object to resurrect itself when the html page becomes accessible.
+ * @type {boolean}
+ * @private
+ */
+goog.History.prototype.longerPolling_ = false;
+
+
+/**
+ * The last token set by the history object, used to poll for changes.
+ * @type {?string}
+ * @private
+ */
+goog.History.prototype.lastToken_ = null;
+
+
+/**
+ * Whether the browser supports HTML5 history management's onhashchange event.
+ * {@link http://www.w3.org/TR/html5/history.html}. IE 9 in compatibility mode
+ * indicates that onhashchange is in window, but testing reveals the event
+ * isn't actually fired.
+ * @return {boolean} Whether onhashchange is supported.
+ */
+goog.History.isOnHashChangeSupported = goog.memoize(function() {
+ return goog.userAgent.IE ?
+ goog.userAgent.isDocumentModeOrHigher(8) :
+ 'onhashchange' in goog.global;
+});
+
+
+/**
+ * Whether the current browser is Internet Explorer prior to version 8. Many IE
+ * specific workarounds developed before version 8 are unnecessary in more
+ * current versions.
+ * @type {boolean}
+ */
+goog.History.LEGACY_IE = goog.userAgent.IE &&
+ !goog.userAgent.isDocumentModeOrHigher(8);
+
+
+/**
+ * Whether the browser always requires the hash to be present. Internet Explorer
+ * before version 8 will reload the HTML page if the hash is omitted.
+ * @type {boolean}
+ */
+goog.History.HASH_ALWAYS_REQUIRED = goog.History.LEGACY_IE;
+
+
+/**
+ * If not null, polling in the user invisible mode will be disabled until this
+ * token is seen. This is used to prevent a race condition where the iframe
+ * hangs temporarily while the location is changed.
+ * @type {?string}
+ * @private
+ */
+goog.History.prototype.lockedToken_ = null;
+
+
+/** @override */
+goog.History.prototype.disposeInternal = function() {
+ goog.History.superClass_.disposeInternal.call(this);
+ this.eventHandler_.dispose();
+ this.setEnabled(false);
+};
+
+
+/**
+ * Starts or stops the History polling loop. When enabled, the History object
+ * will immediately fire an event for the current location. The caller can set
+ * up event listeners between the call to the constructor and the call to
+ * setEnabled.
+ *
+ * On IE, actual startup may be delayed until the iframe and hidden input
+ * element have been loaded and can be polled. This behavior is transparent to
+ * the caller.
+ *
+ * @param {boolean} enable Whether to enable the history polling loop.
+ */
+goog.History.prototype.setEnabled = function(enable) {
+
+ if (enable == this.enabled_) {
+ return;
+ }
+
+ if (goog.History.LEGACY_IE && !this.documentLoaded) {
+ // Wait until the document has actually loaded before enabling the
+ // object or any saved state from a previous session will be lost.
+ this.shouldEnable_ = enable;
+ return;
+ }
+
+ if (enable) {
+ if (goog.userAgent.OPERA) {
+ // Capture events for common user input so we can restart the timer in
+ // Opera if it fails. Yes, this is distasteful. See operaDefibrillator_.
+ this.eventHandler_.listen(this.window_.document,
+ goog.History.INPUT_EVENTS_,
+ this.operaDefibrillator_);
+ } else if (goog.userAgent.GECKO) {
+ // Firefox will not restore the correct state after navigating away from
+ // and then back to the page with the history object. This can be fixed
+ // by restarting the history object on the pageshow event.
+ this.eventHandler_.listen(this.window_, 'pageshow', this.onShow_);
+ }
+
+ // TODO(user): make HTML5 and invisible history work by listening to the
+ // iframe # changes instead of the window.
+ if (goog.History.isOnHashChangeSupported() &&
+ this.userVisible_) {
+ this.eventHandler_.listen(
+ this.window_, goog.events.EventType.HASHCHANGE, this.onHashChange_);
+ this.enabled_ = true;
+ this.dispatchEvent(new goog.history.Event(this.getToken(), false));
+ } else if (!(goog.userAgent.IE && !goog.labs.userAgent.device.isMobile()) ||
+ this.documentLoaded) {
+ // Start dispatching history events if all necessary loading has
+ // completed (always true for browsers other than IE.)
+ this.eventHandler_.listen(this.timer_, goog.Timer.TICK,
+ goog.bind(this.check_, this, true));
+
+ this.enabled_ = true;
+
+ // Initialize last token at startup except on IE < 8, where the last token
+ // must only be set in conjunction with IFRAME updates, or the IFRAME will
+ // start out of sync and remove any pre-existing URI fragment.
+ if (!goog.History.LEGACY_IE) {
+ this.lastToken_ = this.getToken();
+ this.dispatchEvent(new goog.history.Event(this.getToken(), false));
+ }
+
+ this.timer_.start();
+ }
+
+ } else {
+ this.enabled_ = false;
+ this.eventHandler_.removeAll();
+ this.timer_.stop();
+ }
+};
+
+
+/**
+ * Callback for the window onload event in IE. This is necessary to read the
+ * value of the hidden input after restoring a history session. The value of
+ * input elements is not viewable until after window onload for some reason (the
+ * iframe state is similarly unavailable during the loading phase.) If
+ * setEnabled is called before the iframe has completed loading, the history
+ * object will actually be enabled at this point.
+ * @protected
+ */
+goog.History.prototype.onDocumentLoaded = function() {
+ this.documentLoaded = true;
+
+ if (this.hiddenInput_.value) {
+ // Any saved value in the hidden input can only be read after the document
+ // has been loaded due to an IE limitation. Restore the previous state if
+ // it has been set.
+ this.setIframeToken_(this.hiddenInput_.value, true);
+ }
+
+ this.setEnabled(this.shouldEnable_);
+};
+
+
+/**
+ * Handler for the Gecko pageshow event. Restarts the history object so that the
+ * correct state can be restored in the hash or iframe.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.History.prototype.onShow_ = function(e) {
+ // NOTE(user): persisted is a property passed in the pageshow event that
+ // indicates whether the page is being persisted from the cache or is being
+ // loaded for the first time.
+ if (e.getBrowserEvent()['persisted']) {
+ this.setEnabled(false);
+ this.setEnabled(true);
+ }
+};
+
+
+/**
+ * Handles HTML5 onhashchange events on browsers where it is supported.
+ * This is very similar to {@link #check_}, except that it is not executed
+ * continuously. It is only used when
+ * {@code goog.History.isOnHashChangeSupported()} is true.
+ * @param {goog.events.BrowserEvent} e The browser event.
+ * @private
+ */
+goog.History.prototype.onHashChange_ = function(e) {
+ var hash = this.getLocationFragment_(this.window_);
+ if (hash != this.lastToken_) {
+ this.update_(hash, true);
+ }
+};
+
+
+/**
+ * @return {string} The current token.
+ */
+goog.History.prototype.getToken = function() {
+ if (this.lockedToken_ != null) {
+ return this.lockedToken_;
+ } else if (this.userVisible_) {
+ return this.getLocationFragment_(this.window_);
+ } else {
+ return this.getIframeToken_() || '';
+ }
+};
+
+
+/**
+ * Sets the history state. When user visible states are used, the URL fragment
+ * will be set to the provided token. Sometimes it is necessary to set the
+ * history token before the document title has changed, in this case IE's
+ * history drop down can be out of sync with the token. To get around this
+ * problem, the app can pass in a title to use with the hidden iframe.
+ * @param {string} token The history state identifier.
+ * @param {string=} opt_title Optional title used when setting the hidden iframe
+ * title in IE.
+ */
+goog.History.prototype.setToken = function(token, opt_title) {
+ this.setHistoryState_(token, false, opt_title);
+};
+
+
+/**
+ * Replaces the current history state without affecting the rest of the history
+ * stack.
+ * @param {string} token The history state identifier.
+ * @param {string=} opt_title Optional title used when setting the hidden iframe
+ * title in IE.
+ */
+goog.History.prototype.replaceToken = function(token, opt_title) {
+ this.setHistoryState_(token, true, opt_title);
+};
+
+
+/**
+ * Gets the location fragment for the current URL. We don't use location.hash
+ * directly as the browser helpfully urlDecodes the string for us which can
+ * corrupt the tokens. For example, if we want to store: label/%2Froot it would
+ * be returned as label//root.
+ * @param {Window} win The window object to use.
+ * @return {string} The fragment.
+ * @private
+ */
+goog.History.prototype.getLocationFragment_ = function(win) {
+ var href = win.location.href;
+ var index = href.indexOf('#');
+ return index < 0 ? '' : href.substring(index + 1);
+};
+
+
+/**
+ * Sets the history state. When user visible states are used, the URL fragment
+ * will be set to the provided token. Setting opt_replace to true will cause the
+ * navigation to occur, but will replace the current history entry without
+ * affecting the length of the stack.
+ *
+ * @param {string} token The history state identifier.
+ * @param {boolean} replace Set to replace the current history entry instead of
+ * appending a new history state.
+ * @param {string=} opt_title Optional title used when setting the hidden iframe
+ * title in IE.
+ * @private
+ */
+goog.History.prototype.setHistoryState_ = function(token, replace, opt_title) {
+ if (this.getToken() != token) {
+ if (this.userVisible_) {
+ this.setHash_(token, replace);
+
+ if (!goog.History.isOnHashChangeSupported()) {
+ if (goog.userAgent.IE && !goog.labs.userAgent.device.isMobile()) {
+ // IE must save state using the iframe.
+ this.setIframeToken_(token, replace, opt_title);
+ }
+ }
+
+ // This condition needs to be called even if
+ // goog.History.isOnHashChangeSupported() is true so the NAVIGATE event
+ // fires sychronously.
+ if (this.enabled_) {
+ this.check_(false);
+ }
+ } else {
+ // Fire the event immediately so that setting history is synchronous, but
+ // set a suspendToken so that polling doesn't trigger a 'back'.
+ this.setIframeToken_(token, replace);
+ this.lockedToken_ = this.lastToken_ = this.hiddenInput_.value = token;
+ this.dispatchEvent(new goog.history.Event(token, false));
+ }
+ }
+};
+
+
+/**
+ * Sets or replaces the URL fragment. The token does not need to be URL encoded
+ * according to the URL specification, though certain characters (like newline)
+ * are automatically stripped.
+ *
+ * If opt_replace is not set, non-IE browsers will append a new entry to the
+ * history list. Setting the hash does not affect the history stack in IE
+ * (unless there is a pre-existing named anchor for that hash.)
+ *
+ * Older versions of Webkit cannot query the location hash, but it still can be
+ * set. If we detect one of these versions, always replace instead of creating
+ * new history entries.
+ *
+ * window.location.replace replaces the current state from the history stack.
+ * http://www.whatwg.org/specs/web-apps/current-work/#dom-location-replace
+ * http://www.whatwg.org/specs/web-apps/current-work/#replacement-enabled
+ *
+ * @param {string} token The new string to set.
+ * @param {boolean=} opt_replace Set to true to replace the current token
+ * without appending a history entry.
+ * @private
+ */
+goog.History.prototype.setHash_ = function(token, opt_replace) {
+ // If the page uses a BASE element, setting location.hash directly will
+ // navigate away from the current document. Also, the original URL path may
+ // possibly change from HTML5 history pushState. To account for these, the
+ // full path is always specified.
+ var loc = this.window_.location;
+ var url = loc.href.split('#')[0];
+
+ // If a hash has already been set, then removing it programmatically will
+ // reload the page. Once there is a hash, we won't remove it.
+ var hasHash = goog.string.contains(loc.href, '#');
+
+ if (goog.History.HASH_ALWAYS_REQUIRED || hasHash || token) {
+ url += '#' + token;
+ }
+
+ if (url != loc.href) {
+ if (opt_replace) {
+ loc.replace(url);
+ } else {
+ loc.href = url;
+ }
+ }
+};
+
+
+/**
+ * Sets the hidden iframe state. On IE, this is accomplished by writing a new
+ * document into the iframe. In Firefox, the iframe's URL fragment stores the
+ * state instead.
+ *
+ * Older versions of webkit cannot set the iframe, so ignore those browsers.
+ *
+ * @param {string} token The new string to set.
+ * @param {boolean=} opt_replace Set to true to replace the current iframe state
+ * without appending a new history entry.
+ * @param {string=} opt_title Optional title used when setting the hidden iframe
+ * title in IE.
+ * @private
+ */
+goog.History.prototype.setIframeToken_ = function(token,
+ opt_replace,
+ opt_title) {
+ if (this.unsetIframe_ || token != this.getIframeToken_()) {
+
+ this.unsetIframe_ = false;
+ token = goog.string.urlEncode(token);
+
+ if (goog.userAgent.IE) {
+ // Caching the iframe document results in document permission errors after
+ // leaving the page and returning. Access it anew each time instead.
+ var doc = goog.dom.getFrameContentDocument(this.iframe_);
+
+ doc.open('text/html', opt_replace ? 'replace' : undefined);
+ var iframeSourceHtml = goog.html.SafeHtml.concat(
+ goog.html.SafeHtml.create('title', {},
+ (opt_title || this.window_.document.title)),
+ goog.html.SafeHtml.create('body', {}, token));
+ goog.dom.safe.documentWrite(doc, iframeSourceHtml);
+ doc.close();
+ } else {
+ goog.asserts.assertInstanceof(
+ this.iframeSrc_, goog.html.TrustedResourceUrl,
+ 'this.iframeSrc_ must be set on calls to setIframeToken_');
+ var url = goog.html.TrustedResourceUrl.unwrap(
+ /** @type {!goog.html.TrustedResourceUrl} */ (this.iframeSrc_)) +
+ '#' + token;
+
+ // In Safari, it is possible for the contentWindow of the iframe to not
+ // be present when the page is loading after a reload.
+ var contentWindow = this.iframe_.contentWindow;
+ if (contentWindow) {
+ if (opt_replace) {
+ contentWindow.location.replace(url);
+ } else {
+ contentWindow.location.href = url;
+ }
+ }
+ }
+ }
+};
+
+
+/**
+ * Return the current state string from the hidden iframe. On internet explorer,
+ * this is stored as a string in the document body. Other browsers use the
+ * location hash of the hidden iframe.
+ *
+ * Older versions of webkit cannot access the iframe location, so always return
+ * null in that case.
+ *
+ * @return {?string} The state token saved in the iframe (possibly null if the
+ * iframe has never loaded.).
+ * @private
+ */
+goog.History.prototype.getIframeToken_ = function() {
+ if (goog.userAgent.IE) {
+ var doc = goog.dom.getFrameContentDocument(this.iframe_);
+ return doc.body ? goog.string.urlDecode(doc.body.innerHTML) : null;
+ } else {
+ // In Safari, it is possible for the contentWindow of the iframe to not
+ // be present when the page is loading after a reload.
+ var contentWindow = this.iframe_.contentWindow;
+ if (contentWindow) {
+ var hash;
+ /** @preserveTry */
+ try {
+ // Iframe tokens are urlEncoded
+ hash = goog.string.urlDecode(this.getLocationFragment_(contentWindow));
+ } catch (e) {
+ // An exception will be thrown if the location of the iframe can not be
+ // accessed (permission denied). This can occur in FF if the the server
+ // that is hosting the blank html page goes down and then a new history
+ // token is set. The iframe will navigate to an error page, and the
+ // location of the iframe can no longer be accessed. Due to the polling,
+ // this will cause constant exceptions to be thrown. In this case,
+ // we enable longer polling. We do not have to attempt to reset the
+ // iframe token because (a) we already fired the NAVIGATE event when
+ // setting the token, (b) we can rely on the locked token for current
+ // state, and (c) the token is still in the history and
+ // accesible on forward/back.
+ if (!this.longerPolling_) {
+ this.setLongerPolling_(true);
+ }
+
+ return null;
+ }
+
+ // There was no exception when getting the hash so turn off longer polling
+ // if it is on.
+ if (this.longerPolling_) {
+ this.setLongerPolling_(false);
+ }
+
+ return hash || null;
+ } else {
+ return null;
+ }
+ }
+};
+
+
+/**
+ * Checks the state of the document fragment and the iframe title to detect
+ * navigation changes. If {@code goog.HistoryisOnHashChangeSupported()} is
+ * {@code false}, then this runs approximately twenty times per second.
+ * @param {boolean} isNavigation True if the event was initiated by a browser
+ * action, false if it was caused by a setToken call. See
+ * {@link goog.history.Event}.
+ * @private
+ */
+goog.History.prototype.check_ = function(isNavigation) {
+ if (this.userVisible_) {
+ var hash = this.getLocationFragment_(this.window_);
+ if (hash != this.lastToken_) {
+ this.update_(hash, isNavigation);
+ }
+ }
+
+ // Old IE uses the iframe for both visible and non-visible versions.
+ if (!this.userVisible_ || goog.History.LEGACY_IE) {
+ var token = this.getIframeToken_() || '';
+ if (this.lockedToken_ == null || token == this.lockedToken_) {
+ this.lockedToken_ = null;
+ if (token != this.lastToken_) {
+ this.update_(token, isNavigation);
+ }
+ }
+ }
+};
+
+
+/**
+ * Updates the current history state with a given token. Called after a change
+ * to the location or the iframe state is detected by poll_.
+ *
+ * @param {string} token The new history state.
+ * @param {boolean} isNavigation True if the event was initiated by a browser
+ * action, false if it was caused by a setToken call. See
+ * {@link goog.history.Event}.
+ * @private
+ */
+goog.History.prototype.update_ = function(token, isNavigation) {
+ this.lastToken_ = this.hiddenInput_.value = token;
+
+ if (this.userVisible_) {
+ if (goog.History.LEGACY_IE) {
+ this.setIframeToken_(token);
+ }
+
+ this.setHash_(token);
+ } else {
+ this.setIframeToken_(token);
+ }
+
+ this.dispatchEvent(new goog.history.Event(this.getToken(), isNavigation));
+};
+
+
+/**
+ * Sets if the history oject should use longer intervals when polling.
+ *
+ * @param {boolean} longerPolling Whether to enable longer polling.
+ * @private
+ */
+goog.History.prototype.setLongerPolling_ = function(longerPolling) {
+ if (this.longerPolling_ != longerPolling) {
+ this.timer_.setInterval(longerPolling ?
+ goog.History.PollingType.LONG : goog.History.PollingType.NORMAL);
+ }
+ this.longerPolling_ = longerPolling;
+};
+
+
+/**
+ * Opera cancels all outstanding timeouts and intervals after any rapid
+ * succession of navigation events, including the interval used to detect
+ * navigation events. This function restarts the interval so that navigation can
+ * continue. Ideally, only events which would be likely to cause a navigation
+ * change (mousedown and keydown) would be bound to this function. Since Opera
+ * seems to ignore keydown events while the alt key is pressed (such as
+ * alt-left or right arrow), this function is also bound to the much more
+ * frequent mousemove event. This way, when the update loop freezes, it will
+ * unstick itself as the user wiggles the mouse in frustration.
+ * @private
+ */
+goog.History.prototype.operaDefibrillator_ = function() {
+ this.timer_.stop();
+ this.timer_.start();
+};
+
+
+/**
+ * List of user input event types registered in Opera to restart the history
+ * timer (@see goog.History#operaDefibrillator_).
+ * @type {Array<string>}
+ * @private
+ */
+goog.History.INPUT_EVENTS_ = [
+ goog.events.EventType.MOUSEDOWN,
+ goog.events.EventType.KEYDOWN,
+ goog.events.EventType.MOUSEMOVE
+];
+
+
+/**
+ * Counter for the number of goog.History objects that have been instantiated.
+ * Used to create unique IDs.
+ * @type {number}
+ * @private
+ */
+goog.History.historyCount_ = 0;
+
+
+/**
+ * Types of polling. The values are in ms of the polling interval.
+ * @enum {number}
+ */
+goog.History.PollingType = {
+ NORMAL: 150,
+ LONG: 10000
+};
+
+
+/**
+ * Constant for the history change event type.
+ * @enum {string}
+ * @deprecated Use goog.history.EventType.
+ */
+goog.History.EventType = goog.history.EventType;
+
+
+
+/**
+ * Constant for the history change event type.
+ * @param {string} token The string identifying the new history state.
+ * @extends {goog.events.Event}
+ * @constructor
+ * @deprecated Use goog.history.Event.
+ * @final
+ */
+goog.History.Event = goog.history.Event;
[11/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/element.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/element.js b/externs/GCL/externs/goog/graphics/element.js
new file mode 100644
index 0000000..5a7bc8f
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/element.js
@@ -0,0 +1,164 @@
+// 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 thin wrapper around the DOM element returned from
+ * the different draw methods of the graphics implementation, and
+ * all interfaces that the various element types support.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.Element');
+
+goog.require('goog.asserts');
+goog.require('goog.events');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.Listenable');
+goog.require('goog.graphics.AffineTransform');
+goog.require('goog.math');
+
+
+
+/**
+ * Base class for a thin wrapper around the DOM element returned from
+ * the different draw methods of the graphics.
+ * You should not construct objects from this constructor. The graphics
+ * will return the object for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.Element = function(element, graphics) {
+ goog.events.EventTarget.call(this);
+ this.element_ = element;
+ this.graphics_ = graphics;
+ // Overloading EventTarget field to state that this is not a custom event.
+ // TODO(user) Should be handled in EventTarget.js (see bug 846824).
+ this[goog.events.Listenable.IMPLEMENTED_BY_PROP] = false;
+};
+goog.inherits(goog.graphics.Element, goog.events.EventTarget);
+
+
+/**
+ * The graphics object that contains this element.
+ * @type {goog.graphics.AbstractGraphics?}
+ * @private
+ */
+goog.graphics.Element.prototype.graphics_ = null;
+
+
+/**
+ * The native browser element this class wraps.
+ * @type {Element}
+ * @private
+ */
+goog.graphics.Element.prototype.element_ = null;
+
+
+/**
+ * The transformation applied to this element.
+ * @type {goog.graphics.AffineTransform?}
+ * @private
+ */
+goog.graphics.Element.prototype.transform_ = null;
+
+
+/**
+ * Returns the underlying object.
+ * @return {Element} The underlying element.
+ */
+goog.graphics.Element.prototype.getElement = function() {
+ return this.element_;
+};
+
+
+/**
+ * Returns the graphics.
+ * @return {goog.graphics.AbstractGraphics} The graphics that created the
+ * element.
+ */
+goog.graphics.Element.prototype.getGraphics = function() {
+ return this.graphics_;
+};
+
+
+/**
+ * Set the translation and rotation of the element.
+ *
+ * If a more general affine transform is needed than this provides
+ * (e.g. skew and scale) then use setTransform.
+ * @param {number} x The x coordinate of the translation transform.
+ * @param {number} y The y coordinate of the translation transform.
+ * @param {number} rotate The angle of the rotation transform.
+ * @param {number} centerX The horizontal center of the rotation transform.
+ * @param {number} centerY The vertical center of the rotation transform.
+ */
+goog.graphics.Element.prototype.setTransformation = function(x, y, rotate,
+ centerX, centerY) {
+ this.transform_ = goog.graphics.AffineTransform.getRotateInstance(
+ goog.math.toRadians(rotate), centerX, centerY).translate(x, y);
+ this.getGraphics().setElementTransform(this, x, y, rotate, centerX, centerY);
+};
+
+
+/**
+ * @return {!goog.graphics.AffineTransform} The transformation applied to
+ * this element.
+ */
+goog.graphics.Element.prototype.getTransform = function() {
+ return this.transform_ ? this.transform_.clone() :
+ new goog.graphics.AffineTransform();
+};
+
+
+/**
+ * Set the affine transform of the element.
+ * @param {!goog.graphics.AffineTransform} affineTransform The
+ * transformation applied to this element.
+ */
+goog.graphics.Element.prototype.setTransform = function(affineTransform) {
+ this.transform_ = affineTransform.clone();
+ this.getGraphics().setElementAffineTransform(this, affineTransform);
+};
+
+
+/** @override */
+goog.graphics.Element.prototype.addEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.listen(this.element_, type, handler, opt_capture,
+ opt_handlerScope);
+};
+
+
+/** @override */
+goog.graphics.Element.prototype.removeEventListener = function(
+ type, handler, opt_capture, opt_handlerScope) {
+ goog.events.unlisten(this.element_, type, handler, opt_capture,
+ opt_handlerScope);
+};
+
+
+/** @override */
+goog.graphics.Element.prototype.disposeInternal = function() {
+ goog.graphics.Element.superClass_.disposeInternal.call(this);
+ goog.asserts.assert(this.element_);
+ goog.events.removeAll(this.element_);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ellipseelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ellipseelement.js b/externs/GCL/externs/goog/graphics/ellipseelement.js
new file mode 100644
index 0000000..975b462
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ellipseelement.js
@@ -0,0 +1,63 @@
+// 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 thin wrapper around the DOM element for ellipses.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.EllipseElement');
+
+goog.require('goog.graphics.StrokeAndFillElement');
+
+
+
+/**
+ * Interface for a graphics ellipse element.
+ * You should not construct objects from this constructor. The graphics
+ * will return an implementation of this interface for you.
+ * @param {Element} element The DOM element to wrap.
+ * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
+ * this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
+ * @param {goog.graphics.Fill?} fill The fill to use for this element.
+ * @constructor
+ * @extends {goog.graphics.StrokeAndFillElement}
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.EllipseElement = function(element, graphics, stroke, fill) {
+ goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
+ fill);
+};
+goog.inherits(goog.graphics.EllipseElement, goog.graphics.StrokeAndFillElement);
+
+
+/**
+ * Update the center point of the ellipse.
+ * @param {number} cx Center X coordinate.
+ * @param {number} cy Center Y coordinate.
+ */
+goog.graphics.EllipseElement.prototype.setCenter = goog.abstractMethod;
+
+
+/**
+ * Update the radius of the ellipse.
+ * @param {number} rx Radius length for the x-axis.
+ * @param {number} ry Radius length for the y-axis.
+ */
+goog.graphics.EllipseElement.prototype.setRadius = goog.abstractMethod;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/coordinates.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/coordinates.js b/externs/GCL/externs/goog/graphics/ext/coordinates.js
new file mode 100644
index 0000000..42385fe
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/coordinates.js
@@ -0,0 +1,159 @@
+// 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 Graphics utility functions for advanced coordinates.
+ *
+ * This file assists the use of advanced coordinates in goog.graphics. Coords
+ * can be specified as simple numbers which will correspond to units in the
+ * graphics element's coordinate space. Alternately, coords can be expressed
+ * in pixels, meaning no matter what tranformations or coordinate system changes
+ * are present, the number of pixel changes will remain constant. Coords can
+ * also be expressed as percentages of their parent's size.
+ *
+ * This file also allows for elements to have margins, expressable in any of
+ * the ways described above.
+ *
+ * Additional pieces of advanced coordinate functionality can (soon) be found in
+ * element.js and groupelement.js.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.graphics.ext.coordinates');
+
+goog.require('goog.string');
+
+
+/**
+ * Cache of boolean values. For a given string (key), is it special? (value)
+ * @type {Object}
+ * @private
+ */
+goog.graphics.ext.coordinates.specialCoordinateCache_ = {};
+
+
+/**
+ * Determines if the given coordinate is a percent based coordinate or an
+ * expression with a percent based component.
+ * @param {string} coord The coordinate to test.
+ * @return {boolean} Whether the coordinate contains the string '%'.
+ * @private
+ */
+goog.graphics.ext.coordinates.isPercent_ = function(coord) {
+ return goog.string.contains(coord, '%');
+};
+
+
+/**
+ * Determines if the given coordinate is a pixel based coordinate or an
+ * expression with a pixel based component.
+ * @param {string} coord The coordinate to test.
+ * @return {boolean} Whether the coordinate contains the string 'px'.
+ * @private
+ */
+goog.graphics.ext.coordinates.isPixels_ = function(coord) {
+ return goog.string.contains(coord, 'px');
+};
+
+
+/**
+ * Determines if the given coordinate is special - i.e. not just a number.
+ * @param {string|number|null} coord The coordinate to test.
+ * @return {boolean} Whether the coordinate is special.
+ */
+goog.graphics.ext.coordinates.isSpecial = function(coord) {
+ var cache = goog.graphics.ext.coordinates.specialCoordinateCache_;
+
+ if (!(coord in cache)) {
+ cache[coord] = goog.isString(coord) && (
+ goog.graphics.ext.coordinates.isPercent_(coord) ||
+ goog.graphics.ext.coordinates.isPixels_(coord));
+ }
+
+ return cache[coord];
+};
+
+
+/**
+ * Returns the value of the given expression in the given context.
+ *
+ * Should be treated as package scope.
+ *
+ * @param {string|number} coord The coordinate to convert.
+ * @param {number} size The size of the parent element.
+ * @param {number} scale The ratio of pixels to units.
+ * @return {number} The number of coordinate space units that corresponds to
+ * this coordinate.
+ */
+goog.graphics.ext.coordinates.computeValue = function(coord, size, scale) {
+ var number = parseFloat(String(coord));
+ if (goog.isString(coord)) {
+ if (goog.graphics.ext.coordinates.isPercent_(coord)) {
+ return number * size / 100;
+ } else if (goog.graphics.ext.coordinates.isPixels_(coord)) {
+ return number / scale;
+ }
+ }
+
+ return number;
+};
+
+
+/**
+ * Converts the given coordinate to a number value in units.
+ *
+ * Should be treated as package scope.
+ *
+ * @param {string|number} coord The coordinate to retrieve the value for.
+ * @param {boolean|undefined} forMaximum Whether we are computing the largest
+ * value this coordinate would be in a parent of no size. The container
+ * size in this case should be set to the size of the current element.
+ * @param {number} containerSize The unit value of the size of the container of
+ * this element. Should be set to the minimum width of this element if
+ * forMaximum is true.
+ * @param {number} scale The ratio of pixels to units.
+ * @param {Object=} opt_cache Optional (but highly recommend) object to store
+ * cached computations in. The calling class should manage clearing out
+ * the cache when the scale or containerSize changes.
+ * @return {number} The correct number of coordinate space units.
+ */
+goog.graphics.ext.coordinates.getValue = function(coord, forMaximum,
+ containerSize, scale, opt_cache) {
+ if (!goog.isNumber(coord)) {
+ var cacheString = opt_cache && ((forMaximum ? 'X' : '') + coord);
+
+ if (opt_cache && cacheString in opt_cache) {
+ coord = opt_cache[cacheString];
+ } else {
+ if (goog.graphics.ext.coordinates.isSpecial(
+ /** @type {string} */ (coord))) {
+ coord = goog.graphics.ext.coordinates.computeValue(coord,
+ containerSize, scale);
+ } else {
+ // Simple coordinates just need to be converted from a string to a
+ // number.
+ coord = parseFloat(/** @type {string} */ (coord));
+ }
+
+ // Cache the result.
+ if (opt_cache) {
+ opt_cache[cacheString] = coord;
+ }
+ }
+ }
+
+ return coord;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/element.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/element.js b/externs/GCL/externs/goog/graphics/ext/element.js
new file mode 100644
index 0000000..546c8c3
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/element.js
@@ -0,0 +1,963 @@
+// 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 thicker wrapper around the DOM element returned from
+ * the different draw methods of the graphics implementation, and
+ * all interfaces that the various element types support.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.graphics.ext.Element');
+
+goog.require('goog.events.EventTarget');
+goog.require('goog.functions');
+goog.require('goog.graphics.ext.coordinates');
+
+
+
+/**
+ * Base class for a wrapper around the goog.graphics wrapper that enables
+ * more advanced functionality.
+ * @param {goog.graphics.ext.Group?} group Parent for this element.
+ * @param {goog.graphics.Element} wrapper The thin wrapper to wrap.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.graphics.ext.Element = function(group, wrapper) {
+ goog.events.EventTarget.call(this);
+ this.wrapper_ = wrapper;
+ this.graphics_ = group ? group.getGraphics() : this;
+
+ this.xPosition_ = new goog.graphics.ext.Element.Position_(this, true);
+ this.yPosition_ = new goog.graphics.ext.Element.Position_(this, false);
+
+ // Handle parent / child relationships.
+ if (group) {
+ this.parent_ = group;
+ this.parent_.addChild(this);
+ }
+};
+goog.inherits(goog.graphics.ext.Element, goog.events.EventTarget);
+
+
+/**
+ * The graphics object that contains this element.
+ * @type {goog.graphics.ext.Graphics|goog.graphics.ext.Element}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.graphics_;
+
+
+/**
+ * The goog.graphics wrapper this class wraps.
+ * @type {goog.graphics.Element}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.wrapper_;
+
+
+/**
+ * The group or surface containing this element.
+ * @type {goog.graphics.ext.Group|undefined}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.parent_;
+
+
+/**
+ * Whether or not computation of this element's position or size depends on its
+ * parent's size.
+ * @type {boolean}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.parentDependent_ = false;
+
+
+/**
+ * Whether the element has pending transformations.
+ * @type {boolean}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.needsTransform_ = false;
+
+
+/**
+ * The current angle of rotation, expressed in degrees.
+ * @type {number}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.rotation_ = 0;
+
+
+/**
+ * Object representing the x position and size of the element.
+ * @type {goog.graphics.ext.Element.Position_}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.xPosition_;
+
+
+/**
+ * Object representing the y position and size of the element.
+ * @type {goog.graphics.ext.Element.Position_}
+ * @private
+ */
+goog.graphics.ext.Element.prototype.yPosition_;
+
+
+/** @return {goog.graphics.Element} The underlying thin wrapper. */
+goog.graphics.ext.Element.prototype.getWrapper = function() {
+ return this.wrapper_;
+};
+
+
+/**
+ * @return {goog.graphics.ext.Element|goog.graphics.ext.Graphics} The graphics
+ * surface the element is a part of.
+ */
+goog.graphics.ext.Element.prototype.getGraphics = function() {
+ return this.graphics_;
+};
+
+
+/**
+ * Returns the graphics implementation.
+ * @return {goog.graphics.AbstractGraphics} The underlying graphics
+ * implementation drawing this element's wrapper.
+ * @protected
+ */
+goog.graphics.ext.Element.prototype.getGraphicsImplementation = function() {
+ return this.graphics_.getImplementation();
+};
+
+
+/**
+ * @return {goog.graphics.ext.Group|undefined} The parent of this element.
+ */
+goog.graphics.ext.Element.prototype.getParent = function() {
+ return this.parent_;
+};
+
+
+// GENERAL POSITIONING
+
+
+/**
+ * Internal convenience method for setting position - either as a left/top,
+ * center/middle, or right/bottom value. Only one should be specified.
+ * @param {goog.graphics.ext.Element.Position_} position The position object to
+ * set the value on.
+ * @param {number|string} value The value of the coordinate.
+ * @param {goog.graphics.ext.Element.PositionType_} type The type of the
+ * coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ * @private
+ */
+goog.graphics.ext.Element.prototype.setPosition_ = function(position, value,
+ type, opt_chain) {
+ position.setPosition(value, type);
+ this.computeIsParentDependent_(position);
+
+ this.needsTransform_ = true;
+ if (!opt_chain) {
+ this.transform();
+ }
+};
+
+
+/**
+ * Sets the width/height of the element.
+ * @param {goog.graphics.ext.Element.Position_} position The position object to
+ * set the value on.
+ * @param {string|number} size The new width/height value.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ * @private
+ */
+goog.graphics.ext.Element.prototype.setSize_ = function(position, size,
+ opt_chain) {
+ if (position.setSize(size)) {
+ this.needsTransform_ = true;
+
+ this.computeIsParentDependent_(position);
+
+ if (!opt_chain) {
+ this.reset();
+ }
+ } else if (!opt_chain && this.isPendingTransform()) {
+ this.reset();
+ }
+};
+
+
+/**
+ * Sets the minimum width/height of the element.
+ * @param {goog.graphics.ext.Element.Position_} position The position object to
+ * set the value on.
+ * @param {string|number} minSize The minimum width/height of the element.
+ * @private
+ */
+goog.graphics.ext.Element.prototype.setMinSize_ = function(position, minSize) {
+ position.setMinSize(minSize);
+ this.needsTransform_ = true;
+ this.computeIsParentDependent_(position);
+};
+
+
+// HORIZONTAL POSITIONING
+
+
+/**
+ * @return {number} The distance from the left edge of this element to the left
+ * edge of its parent, specified in units of the parent's coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getLeft = function() {
+ return this.xPosition_.getStart();
+};
+
+
+/**
+ * Sets the left coordinate of the element. Overwrites any previous value of
+ * left, center, or right for this element.
+ * @param {string|number} left The left coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setLeft = function(left, opt_chain) {
+ this.setPosition_(this.xPosition_,
+ left,
+ goog.graphics.ext.Element.PositionType_.START,
+ opt_chain);
+};
+
+
+/**
+ * @return {number} The right coordinate of the element, in units of the
+ * parent's coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getRight = function() {
+ return this.xPosition_.getEnd();
+};
+
+
+/**
+ * Sets the right coordinate of the element. Overwrites any previous value of
+ * left, center, or right for this element.
+ * @param {string|number} right The right coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setRight = function(right, opt_chain) {
+ this.setPosition_(this.xPosition_,
+ right,
+ goog.graphics.ext.Element.PositionType_.END,
+ opt_chain);
+};
+
+
+/**
+ * @return {number} The center coordinate of the element, in units of the
+ * parent's coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getCenter = function() {
+ return this.xPosition_.getMiddle();
+};
+
+
+/**
+ * Sets the center coordinate of the element. Overwrites any previous value of
+ * left, center, or right for this element.
+ * @param {string|number} center The center coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setCenter = function(center, opt_chain) {
+ this.setPosition_(this.xPosition_,
+ center,
+ goog.graphics.ext.Element.PositionType_.MIDDLE,
+ opt_chain);
+};
+
+
+// VERTICAL POSITIONING
+
+
+/**
+ * @return {number} The distance from the top edge of this element to the top
+ * edge of its parent, specified in units of the parent's coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getTop = function() {
+ return this.yPosition_.getStart();
+};
+
+
+/**
+ * Sets the top coordinate of the element. Overwrites any previous value of
+ * top, middle, or bottom for this element.
+ * @param {string|number} top The top coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setTop = function(top, opt_chain) {
+ this.setPosition_(this.yPosition_,
+ top,
+ goog.graphics.ext.Element.PositionType_.START,
+ opt_chain);
+};
+
+
+/**
+ * @return {number} The bottom coordinate of the element, in units of the
+ * parent's coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getBottom = function() {
+ return this.yPosition_.getEnd();
+};
+
+
+/**
+ * Sets the bottom coordinate of the element. Overwrites any previous value of
+ * top, middle, or bottom for this element.
+ * @param {string|number} bottom The bottom coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setBottom = function(bottom, opt_chain) {
+ this.setPosition_(this.yPosition_,
+ bottom,
+ goog.graphics.ext.Element.PositionType_.END,
+ opt_chain);
+};
+
+
+/**
+ * @return {number} The middle coordinate of the element, in units of the
+ * parent's coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getMiddle = function() {
+ return this.yPosition_.getMiddle();
+};
+
+
+/**
+ * Sets the middle coordinate of the element. Overwrites any previous value of
+ * top, middle, or bottom for this element
+ * @param {string|number} middle The middle coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setMiddle = function(middle, opt_chain) {
+ this.setPosition_(this.yPosition_,
+ middle,
+ goog.graphics.ext.Element.PositionType_.MIDDLE,
+ opt_chain);
+};
+
+
+// DIMENSIONS
+
+
+/**
+ * @return {number} The width of the element, in units of the parent's
+ * coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getWidth = function() {
+ return this.xPosition_.getSize();
+};
+
+
+/**
+ * Sets the width of the element.
+ * @param {string|number} width The new width value.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setWidth = function(width, opt_chain) {
+ this.setSize_(this.xPosition_, width, opt_chain);
+};
+
+
+/**
+ * @return {number} The minimum width of the element, in units of the parent's
+ * coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getMinWidth = function() {
+ return this.xPosition_.getMinSize();
+};
+
+
+/**
+ * Sets the minimum width of the element.
+ * @param {string|number} minWidth The minimum width of the element.
+ */
+goog.graphics.ext.Element.prototype.setMinWidth = function(minWidth) {
+ this.setMinSize_(this.xPosition_, minWidth);
+};
+
+
+/**
+ * @return {number} The height of the element, in units of the parent's
+ * coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getHeight = function() {
+ return this.yPosition_.getSize();
+};
+
+
+/**
+ * Sets the height of the element.
+ * @param {string|number} height The new height value.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setHeight = function(height, opt_chain) {
+ this.setSize_(this.yPosition_, height, opt_chain);
+};
+
+
+/**
+ * @return {number} The minimum height of the element, in units of the parent's
+ * coordinate system.
+ */
+goog.graphics.ext.Element.prototype.getMinHeight = function() {
+ return this.yPosition_.getMinSize();
+};
+
+
+/**
+ * Sets the minimum height of the element.
+ * @param {string|number} minHeight The minimum height of the element.
+ */
+goog.graphics.ext.Element.prototype.setMinHeight = function(minHeight) {
+ this.setMinSize_(this.yPosition_, minHeight);
+};
+
+
+// BOUNDS SHORTCUTS
+
+
+/**
+ * Shortcut for setting the left and top position.
+ * @param {string|number} left The left coordinate.
+ * @param {string|number} top The top coordinate.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setPosition = function(left, top,
+ opt_chain) {
+ this.setLeft(left, true);
+ this.setTop(top, opt_chain);
+};
+
+
+/**
+ * Shortcut for setting the width and height.
+ * @param {string|number} width The new width value.
+ * @param {string|number} height The new height value.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setSize = function(width, height,
+ opt_chain) {
+ this.setWidth(width, true);
+ this.setHeight(height, opt_chain);
+};
+
+
+/**
+ * Shortcut for setting the left, top, width, and height.
+ * @param {string|number} left The left coordinate.
+ * @param {string|number} top The top coordinate.
+ * @param {string|number} width The new width value.
+ * @param {string|number} height The new height value.
+ * @param {boolean=} opt_chain Optional flag to specify this function is part
+ * of a chain of calls and therefore transformations should be set as
+ * pending but not yet performed.
+ */
+goog.graphics.ext.Element.prototype.setBounds = function(left, top, width,
+ height, opt_chain) {
+ this.setLeft(left, true);
+ this.setTop(top, true);
+ this.setWidth(width, true);
+ this.setHeight(height, opt_chain);
+};
+
+
+// MAXIMUM BOUNDS
+
+
+/**
+ * @return {number} An estimate of the maximum x extent this element would have
+ * in a parent of no width.
+ */
+goog.graphics.ext.Element.prototype.getMaxX = function() {
+ return this.xPosition_.getMaxPosition();
+};
+
+
+/**
+ * @return {number} An estimate of the maximum y extent this element would have
+ * in a parent of no height.
+ */
+goog.graphics.ext.Element.prototype.getMaxY = function() {
+ return this.yPosition_.getMaxPosition();
+};
+
+
+// RESET
+
+
+/**
+ * Reset the element. This is called when the element changes size, or when
+ * the coordinate system changes in a way that would affect pixel based
+ * rendering
+ */
+goog.graphics.ext.Element.prototype.reset = function() {
+ this.xPosition_.resetCache();
+ this.yPosition_.resetCache();
+
+ this.redraw();
+
+ this.needsTransform_ = true;
+ this.transform();
+};
+
+
+/**
+ * Overridable function for subclass specific reset.
+ * @protected
+ */
+goog.graphics.ext.Element.prototype.redraw = goog.nullFunction;
+
+
+// PARENT DEPENDENCY
+
+
+/**
+ * Computes whether the element is still parent dependent.
+ * @param {goog.graphics.ext.Element.Position_} position The recently changed
+ * position object.
+ * @private
+ */
+goog.graphics.ext.Element.prototype.computeIsParentDependent_ = function(
+ position) {
+ this.parentDependent_ = position.isParentDependent() ||
+ this.xPosition_.isParentDependent() ||
+ this.yPosition_.isParentDependent() ||
+ this.checkParentDependent();
+};
+
+
+/**
+ * Returns whether this element's bounds depend on its parents.
+ *
+ * This function should be treated as if it has package scope.
+ * @return {boolean} Whether this element's bounds depend on its parents.
+ */
+goog.graphics.ext.Element.prototype.isParentDependent = function() {
+ return this.parentDependent_;
+};
+
+
+/**
+ * Overridable function for subclass specific parent dependency.
+ * @return {boolean} Whether this shape's bounds depends on its parent's.
+ * @protected
+ */
+goog.graphics.ext.Element.prototype.checkParentDependent =
+ goog.functions.FALSE;
+
+
+// ROTATION
+
+
+/**
+ * Set the rotation of this element.
+ * @param {number} angle The angle of rotation, in degrees.
+ */
+goog.graphics.ext.Element.prototype.setRotation = function(angle) {
+ if (this.rotation_ != angle) {
+ this.rotation_ = angle;
+
+ this.needsTransform_ = true;
+ this.transform();
+ }
+};
+
+
+/**
+ * @return {number} The angle of rotation of this element, in degrees.
+ */
+goog.graphics.ext.Element.prototype.getRotation = function() {
+ return this.rotation_;
+};
+
+
+// TRANSFORMS
+
+
+/**
+ * Called by the parent when the parent has transformed.
+ *
+ * Should be treated as package scope.
+ */
+goog.graphics.ext.Element.prototype.parentTransform = function() {
+ this.needsTransform_ = this.needsTransform_ || this.parentDependent_;
+};
+
+
+/**
+ * @return {boolean} Whether this element has pending transforms.
+ */
+goog.graphics.ext.Element.prototype.isPendingTransform = function() {
+ return this.needsTransform_;
+};
+
+
+/**
+ * Performs a pending transform.
+ * @protected
+ */
+goog.graphics.ext.Element.prototype.transform = function() {
+ if (this.isPendingTransform()) {
+ this.needsTransform_ = false;
+
+ this.wrapper_.setTransformation(
+ this.getLeft(),
+ this.getTop(),
+ this.rotation_,
+ (this.getWidth() || 1) / 2,
+ (this.getHeight() || 1) / 2);
+
+ // TODO(robbyw): this._fireEvent('transform', [ this ]);
+ }
+};
+
+
+// PIXEL SCALE
+
+
+/**
+ * @return {number} Returns the number of pixels per unit in the x direction.
+ */
+goog.graphics.ext.Element.prototype.getPixelScaleX = function() {
+ return this.getGraphics().getPixelScaleX();
+};
+
+
+/**
+ * @return {number} Returns the number of pixels per unit in the y direction.
+ */
+goog.graphics.ext.Element.prototype.getPixelScaleY = function() {
+ return this.getGraphics().getPixelScaleY();
+};
+
+
+// EVENT HANDLING
+
+
+/** @override */
+goog.graphics.ext.Element.prototype.disposeInternal = function() {
+ goog.graphics.ext.Element.superClass_.disposeInternal.call();
+ this.wrapper_.dispose();
+};
+
+
+// INTERNAL POSITION OBJECT
+
+
+/**
+ * Position specification types. Start corresponds to left/top, middle to
+ * center/middle, and end to right/bottom.
+ * @enum {number}
+ * @private
+ */
+goog.graphics.ext.Element.PositionType_ = {
+ START: 0,
+ MIDDLE: 1,
+ END: 2
+};
+
+
+
+/**
+ * Manages a position and size, either horizontal or vertical.
+ * @param {goog.graphics.ext.Element} element The element the position applies
+ * to.
+ * @param {boolean} horizontal Whether the position is horizontal or vertical.
+ * @constructor
+ * @private
+ */
+goog.graphics.ext.Element.Position_ = function(element, horizontal) {
+ this.element_ = element;
+ this.horizontal_ = horizontal;
+};
+
+
+/**
+ * @return {!Object} The coordinate value computation cache.
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.getCoordinateCache_ = function() {
+ return this.coordinateCache_ || (this.coordinateCache_ = {});
+};
+
+
+/**
+ * @return {number} The size of the parent's coordinate space.
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.getParentSize_ = function() {
+ var parent = this.element_.getParent();
+ return this.horizontal_ ?
+ parent.getCoordinateWidth() :
+ parent.getCoordinateHeight();
+};
+
+
+/**
+ * @return {number} The minimum width/height of the element.
+ */
+goog.graphics.ext.Element.Position_.prototype.getMinSize = function() {
+ return this.getValue_(this.minSize_);
+};
+
+
+/**
+ * Sets the minimum width/height of the element.
+ * @param {string|number} minSize The minimum width/height of the element.
+ */
+goog.graphics.ext.Element.Position_.prototype.setMinSize = function(minSize) {
+ this.minSize_ = minSize;
+ this.resetCache();
+};
+
+
+/**
+ * @return {number} The width/height of the element.
+ */
+goog.graphics.ext.Element.Position_.prototype.getSize = function() {
+ return Math.max(this.getValue_(this.size_), this.getMinSize());
+};
+
+
+/**
+ * Sets the width/height of the element.
+ * @param {string|number} size The width/height of the element.
+ * @return {boolean} Whether the value was changed.
+ */
+goog.graphics.ext.Element.Position_.prototype.setSize = function(size) {
+ if (size != this.size_) {
+ this.size_ = size;
+ this.resetCache();
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Converts the given x coordinate to a number value in units.
+ * @param {string|number} v The coordinate to retrieve the value for.
+ * @param {boolean=} opt_forMaximum Whether we are computing the largest value
+ * this coordinate would be in a parent of no size.
+ * @return {number} The correct number of coordinate space units.
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.getValue_ = function(v,
+ opt_forMaximum) {
+ if (!goog.graphics.ext.coordinates.isSpecial(v)) {
+ return parseFloat(String(v));
+ }
+
+ var cache = this.getCoordinateCache_();
+ var scale = this.horizontal_ ?
+ this.element_.getPixelScaleX() :
+ this.element_.getPixelScaleY();
+
+ var containerSize;
+ if (opt_forMaximum) {
+ containerSize = goog.graphics.ext.coordinates.computeValue(
+ this.size_ || 0, 0, scale);
+ } else {
+ var parent = this.element_.getParent();
+ containerSize = this.horizontal_ ? parent.getWidth() : parent.getHeight();
+ }
+
+ return goog.graphics.ext.coordinates.getValue(v, opt_forMaximum,
+ containerSize, scale, cache);
+};
+
+
+/**
+ * @return {number} The distance from the left/top edge of this element to the
+ * left/top edge of its parent, specified in units of the parent's
+ * coordinate system.
+ */
+goog.graphics.ext.Element.Position_.prototype.getStart = function() {
+ if (this.cachedValue_ == null) {
+ var value = this.getValue_(this.distance_);
+ if (this.distanceType_ == goog.graphics.ext.Element.PositionType_.START) {
+ this.cachedValue_ = value;
+ } else if (this.distanceType_ ==
+ goog.graphics.ext.Element.PositionType_.MIDDLE) {
+ this.cachedValue_ = value + (this.getParentSize_() - this.getSize()) / 2;
+ } else {
+ this.cachedValue_ = this.getParentSize_() - value - this.getSize();
+ }
+ }
+
+ return this.cachedValue_;
+};
+
+
+/**
+ * @return {number} The middle coordinate of the element, in units of the
+ * parent's coordinate system.
+ */
+goog.graphics.ext.Element.Position_.prototype.getMiddle = function() {
+ return this.distanceType_ == goog.graphics.ext.Element.PositionType_.MIDDLE ?
+ this.getValue_(this.distance_) :
+ (this.getParentSize_() - this.getSize()) / 2 - this.getStart();
+};
+
+
+/**
+ * @return {number} The end coordinate of the element, in units of the
+ * parent's coordinate system.
+ */
+goog.graphics.ext.Element.Position_.prototype.getEnd = function() {
+ return this.distanceType_ == goog.graphics.ext.Element.PositionType_.END ?
+ this.getValue_(this.distance_) :
+ this.getParentSize_() - this.getStart() - this.getSize();
+};
+
+
+/**
+ * Sets the position, either as a left/top, center/middle, or right/bottom
+ * value.
+ * @param {number|string} value The value of the coordinate.
+ * @param {goog.graphics.ext.Element.PositionType_} type The type of the
+ * coordinate.
+ */
+goog.graphics.ext.Element.Position_.prototype.setPosition = function(value,
+ type) {
+ this.distance_ = value;
+ this.distanceType_ = type;
+
+ // Clear cached value.
+ this.cachedValue_ = null;
+};
+
+
+/**
+ * @return {number} An estimate of the maximum x/y extent this element would
+ * have in a parent of no width/height.
+ */
+goog.graphics.ext.Element.Position_.prototype.getMaxPosition = function() {
+ // TODO(robbyw): Handle transformed or rotated coordinates
+ // TODO(robbyw): Handle pixel based sizes?
+
+ return this.getValue_(this.distance_ || 0) + (
+ goog.graphics.ext.coordinates.isSpecial(this.size_) ? 0 : this.getSize());
+};
+
+
+/**
+ * Resets the caches of position values and coordinate values.
+ */
+goog.graphics.ext.Element.Position_.prototype.resetCache = function() {
+ this.coordinateCache_ = null;
+ this.cachedValue_ = null;
+};
+
+
+/**
+ * @return {boolean} Whether the size or position of this element depends on
+ * the size of the parent element.
+ */
+goog.graphics.ext.Element.Position_.prototype.isParentDependent = function() {
+ return this.distanceType_ != goog.graphics.ext.Element.PositionType_.START ||
+ goog.graphics.ext.coordinates.isSpecial(this.size_) ||
+ goog.graphics.ext.coordinates.isSpecial(this.minSize_) ||
+ goog.graphics.ext.coordinates.isSpecial(this.distance_);
+};
+
+
+/**
+ * The lazy loaded distance from the parent's top/left edge to this element's
+ * top/left edge expressed in the parent's coordinate system. We cache this
+ * because it is most freqeuently requested by the element and it is easy to
+ * compute middle and end values from it.
+ * @type {?number}
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.cachedValue_ = null;
+
+
+/**
+ * A cache of computed x coordinates.
+ * @type {Object}
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.coordinateCache_ = null;
+
+
+/**
+ * The minimum width/height of this element, as specified by the caller.
+ * @type {string|number}
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.minSize_ = 0;
+
+
+/**
+ * The width/height of this object, as specified by the caller.
+ * @type {string|number}
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.size_ = 0;
+
+
+/**
+ * The coordinate of this object, as specified by the caller. The type of
+ * coordinate is specified by distanceType_.
+ * @type {string|number}
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.distance_ = 0;
+
+
+/**
+ * The coordinate type specified by distance_.
+ * @type {goog.graphics.ext.Element.PositionType_}
+ * @private
+ */
+goog.graphics.ext.Element.Position_.prototype.distanceType_ =
+ goog.graphics.ext.Element.PositionType_.START;
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/ellipse.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/ellipse.js b/externs/GCL/externs/goog/graphics/ext/ellipse.js
new file mode 100644
index 0000000..db77524
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/ellipse.js
@@ -0,0 +1,60 @@
+// 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 thick wrapper around ellipses.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.Ellipse');
+
+goog.require('goog.graphics.ext.StrokeAndFillElement');
+
+
+
+/**
+ * Wrapper for a graphics ellipse element.
+ * @param {goog.graphics.ext.Group} group Parent for this element.
+ * @constructor
+ * @extends {goog.graphics.ext.StrokeAndFillElement}
+ * @final
+ */
+goog.graphics.ext.Ellipse = function(group) {
+ // Initialize with some stock values.
+ var wrapper = group.getGraphicsImplementation().drawEllipse(1, 1, 2, 2, null,
+ null, group.getWrapper());
+ goog.graphics.ext.StrokeAndFillElement.call(this, group, wrapper);
+};
+goog.inherits(goog.graphics.ext.Ellipse,
+ goog.graphics.ext.StrokeAndFillElement);
+
+
+/**
+ * Redraw the ellipse. Called when the coordinate system is changed.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.Ellipse.prototype.redraw = function() {
+ goog.graphics.ext.Ellipse.superClass_.redraw.call(this);
+
+ // Our position is already transformed in transform_, but because this is an
+ // ellipse we need to position the center.
+ var xRadius = this.getWidth() / 2;
+ var yRadius = this.getHeight() / 2;
+ var wrapper = this.getWrapper();
+ wrapper.setCenter(xRadius, yRadius);
+ wrapper.setRadius(xRadius, yRadius);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/ext.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/ext.js b/externs/GCL/externs/goog/graphics/ext/ext.js
new file mode 100644
index 0000000..b3ff4e3
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/ext.js
@@ -0,0 +1,31 @@
+// 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 Extended graphics namespace.
+ * @suppress {extraRequire} All the requires in this file are "extra"
+ * because this file is not actually using them.
+ */
+
+
+goog.provide('goog.graphics.ext');
+
+goog.require('goog.graphics.ext.Ellipse');
+goog.require('goog.graphics.ext.Graphics');
+goog.require('goog.graphics.ext.Group');
+goog.require('goog.graphics.ext.Image');
+goog.require('goog.graphics.ext.Rectangle');
+goog.require('goog.graphics.ext.Shape');
+goog.require('goog.graphics.ext.coordinates');
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/graphics.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/graphics.js b/externs/GCL/externs/goog/graphics/ext/graphics.js
new file mode 100644
index 0000000..a3c1a54
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/graphics.js
@@ -0,0 +1,218 @@
+// 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 Graphics surface type.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.Graphics');
+
+goog.require('goog.events');
+goog.require('goog.events.EventType');
+goog.require('goog.graphics');
+goog.require('goog.graphics.ext.Group');
+
+
+
+/**
+ * Wrapper for a graphics surface.
+ * @param {string|number} width The width in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {string|number} height The height in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {?number=} opt_coordWidth The coordinate width - if
+ * omitted or null, defaults to same as width.
+ * @param {?number=} opt_coordHeight The coordinate height. - if
+ * omitted or null, defaults to same as height.
+ * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
+ * document we want to render in.
+ * @param {boolean=} opt_isSimple Flag used to indicate the graphics object will
+ * be drawn to in a single pass, and the fastest implementation for this
+ * scenario should be favored. NOTE: Setting to true may result in
+ * degradation of text support.
+ * @constructor
+ * @extends {goog.graphics.ext.Group}
+ * @final
+ */
+goog.graphics.ext.Graphics = function(width, height, opt_coordWidth,
+ opt_coordHeight, opt_domHelper, opt_isSimple) {
+ var surface = opt_isSimple ?
+ goog.graphics.createSimpleGraphics(width, height,
+ opt_coordWidth, opt_coordHeight, opt_domHelper) :
+ goog.graphics.createGraphics(width, height,
+ opt_coordWidth, opt_coordHeight, opt_domHelper);
+ this.implementation_ = surface;
+
+ goog.graphics.ext.Group.call(this, null, surface.getCanvasElement());
+
+ goog.events.listen(surface, goog.events.EventType.RESIZE,
+ this.updateChildren, false, this);
+};
+goog.inherits(goog.graphics.ext.Graphics, goog.graphics.ext.Group);
+
+
+/**
+ * The root level graphics implementation.
+ * @type {goog.graphics.AbstractGraphics}
+ * @private
+ */
+goog.graphics.ext.Graphics.prototype.implementation_;
+
+
+/**
+ * @return {goog.graphics.AbstractGraphics} The graphics implementation layer.
+ */
+goog.graphics.ext.Graphics.prototype.getImplementation = function() {
+ return this.implementation_;
+};
+
+
+/**
+ * Changes the coordinate size.
+ * @param {number} coordWidth The coordinate width.
+ * @param {number} coordHeight The coordinate height.
+ */
+goog.graphics.ext.Graphics.prototype.setCoordSize = function(coordWidth,
+ coordHeight) {
+ this.implementation_.setCoordSize(coordWidth, coordHeight);
+ goog.graphics.ext.Graphics.superClass_.setSize.call(this, coordWidth,
+ coordHeight);
+};
+
+
+/**
+ * @return {goog.math.Size} The coordinate size.
+ */
+goog.graphics.ext.Graphics.prototype.getCoordSize = function() {
+ return this.implementation_.getCoordSize();
+};
+
+
+/**
+ * Changes the coordinate system position.
+ * @param {number} left The coordinate system left bound.
+ * @param {number} top The coordinate system top bound.
+ */
+goog.graphics.ext.Graphics.prototype.setCoordOrigin = function(left, top) {
+ this.implementation_.setCoordOrigin(left, top);
+};
+
+
+/**
+ * @return {!goog.math.Coordinate} The coordinate system position.
+ */
+goog.graphics.ext.Graphics.prototype.getCoordOrigin = function() {
+ return this.implementation_.getCoordOrigin();
+};
+
+
+/**
+ * Change the size of the canvas.
+ * @param {number} pixelWidth The width in pixels.
+ * @param {number} pixelHeight The height in pixels.
+ */
+goog.graphics.ext.Graphics.prototype.setPixelSize = function(pixelWidth,
+ pixelHeight) {
+ this.implementation_.setSize(pixelWidth, pixelHeight);
+
+ var coordSize = this.getCoordSize();
+ goog.graphics.ext.Graphics.superClass_.setSize.call(this, coordSize.width,
+ coordSize.height);
+};
+
+
+/**
+ * @return {goog.math.Size?} Returns the number of pixels spanned by the
+ * surface, or null if the size could not be computed due to the size being
+ * specified in percentage points and the component not being in the
+ * document.
+ */
+goog.graphics.ext.Graphics.prototype.getPixelSize = function() {
+ return this.implementation_.getPixelSize();
+};
+
+
+/**
+ * @return {number} The coordinate width of the canvas.
+ * @override
+ */
+goog.graphics.ext.Graphics.prototype.getWidth = function() {
+ return this.implementation_.getCoordSize().width;
+};
+
+
+/**
+ * @return {number} The coordinate width of the canvas.
+ * @override
+ */
+goog.graphics.ext.Graphics.prototype.getHeight = function() {
+ return this.implementation_.getCoordSize().height;
+};
+
+
+/**
+ * @return {number} Returns the number of pixels per unit in the x direction.
+ * @override
+ */
+goog.graphics.ext.Graphics.prototype.getPixelScaleX = function() {
+ return this.implementation_.getPixelScaleX();
+};
+
+
+/**
+ * @return {number} Returns the number of pixels per unit in the y direction.
+ * @override
+ */
+goog.graphics.ext.Graphics.prototype.getPixelScaleY = function() {
+ return this.implementation_.getPixelScaleY();
+};
+
+
+/**
+ * @return {Element} The root element of the graphics surface.
+ */
+goog.graphics.ext.Graphics.prototype.getElement = function() {
+ return this.implementation_.getElement();
+};
+
+
+/**
+ * Renders the underlying graphics.
+ *
+ * @param {Element} parentElement Parent element to render the component into.
+ */
+goog.graphics.ext.Graphics.prototype.render = function(parentElement) {
+ this.implementation_.render(parentElement);
+};
+
+
+/**
+ * Never transform a surface.
+ * @override
+ */
+goog.graphics.ext.Graphics.prototype.transform = goog.nullFunction;
+
+
+/**
+ * Called from the parent class, this method resets any pre-computed positions
+ * and sizes.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.Graphics.prototype.redraw = function() {
+ this.transformChildren();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/group.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/group.js b/externs/GCL/externs/goog/graphics/ext/group.js
new file mode 100644
index 0000000..03479ad
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/group.js
@@ -0,0 +1,216 @@
+// 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 thicker wrapper around graphics groups.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.Group');
+
+goog.require('goog.array');
+goog.require('goog.graphics.ext.Element');
+
+
+
+/**
+ * Wrapper for a graphics group.
+ * @param {goog.graphics.ext.Group} group Parent for this element. Can
+ * be null if this is a Graphics instance.
+ * @param {goog.graphics.GroupElement=} opt_wrapper The thin wrapper
+ * to wrap. If omitted, a new group will be created. Must be included
+ * when group is null.
+ * @constructor
+ * @extends {goog.graphics.ext.Element}
+ */
+goog.graphics.ext.Group = function(group, opt_wrapper) {
+ opt_wrapper = opt_wrapper || group.getGraphicsImplementation().createGroup(
+ group.getWrapper());
+ goog.graphics.ext.Element.call(this, group, opt_wrapper);
+
+ /**
+ * Array of child elements this group contains.
+ * @type {Array<goog.graphics.ext.Element>}
+ * @private
+ */
+ this.children_ = [];
+};
+goog.inherits(goog.graphics.ext.Group, goog.graphics.ext.Element);
+
+
+/**
+ * Add an element to the group. This should be treated as package local, as
+ * it is called by the draw* methods.
+ * @param {!goog.graphics.ext.Element} element The element to add.
+ * @param {boolean=} opt_chain Whether this addition is part of a longer set
+ * of element additions.
+ */
+goog.graphics.ext.Group.prototype.addChild = function(element, opt_chain) {
+ if (!goog.array.contains(this.children_, element)) {
+ this.children_.push(element);
+ }
+
+ var transformed = this.growToFit_(element);
+
+ if (element.isParentDependent()) {
+ element.parentTransform();
+ }
+
+ if (!opt_chain && element.isPendingTransform()) {
+ element.reset();
+ }
+
+ if (transformed) {
+ this.reset();
+ }
+};
+
+
+/**
+ * Remove an element from the group.
+ * @param {goog.graphics.ext.Element} element The element to remove.
+ */
+goog.graphics.ext.Group.prototype.removeChild = function(element) {
+ goog.array.remove(this.children_, element);
+
+ // TODO(robbyw): shape.fireEvent('delete')
+
+ this.getGraphicsImplementation().removeElement(element.getWrapper());
+};
+
+
+/**
+ * Calls the given function on each of this component's children in order. If
+ * {@code opt_obj} is provided, it will be used as the 'this' object in the
+ * function when called. The function should take two arguments: the child
+ * component and its 0-based index. The return value is ignored.
+ * @param {Function} f The function to call for every child component; should
+ * take 2 arguments (the child and its index).
+ * @param {Object=} opt_obj Used as the 'this' object in f when called.
+ */
+goog.graphics.ext.Group.prototype.forEachChild = function(f, opt_obj) {
+ if (this.children_) {
+ goog.array.forEach(this.children_, f, opt_obj);
+ }
+};
+
+
+/**
+ * @return {goog.graphics.GroupElement} The underlying thin wrapper.
+ * @override
+ */
+goog.graphics.ext.Group.prototype.getWrapper;
+
+
+/**
+ * Reset the element.
+ * @override
+ */
+goog.graphics.ext.Group.prototype.reset = function() {
+ goog.graphics.ext.Group.superClass_.reset.call(this);
+
+ this.updateChildren();
+};
+
+
+/**
+ * Called from the parent class, this method resets any pre-computed positions
+ * and sizes.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.Group.prototype.redraw = function() {
+ this.getWrapper().setSize(this.getWidth(), this.getHeight());
+ this.transformChildren();
+};
+
+
+/**
+ * Transform the children that need to be transformed.
+ * @protected
+ */
+goog.graphics.ext.Group.prototype.transformChildren = function() {
+ this.forEachChild(function(child) {
+ if (child.isParentDependent()) {
+ child.parentTransform();
+ }
+ });
+};
+
+
+/**
+ * As part of the reset process, update child elements.
+ */
+goog.graphics.ext.Group.prototype.updateChildren = function() {
+ this.forEachChild(function(child) {
+ if (child.isParentDependent() || child.isPendingTransform()) {
+ child.reset();
+ } else if (child.updateChildren) {
+ child.updateChildren();
+ }
+ });
+};
+
+
+/**
+ * When adding an element, grow this group's bounds to fit it.
+ * @param {!goog.graphics.ext.Element} element The added element.
+ * @return {boolean} Whether the size of this group changed.
+ * @private
+ */
+goog.graphics.ext.Group.prototype.growToFit_ = function(element) {
+ var transformed = false;
+
+ var x = element.getMaxX();
+ if (x > this.getWidth()) {
+ this.setMinWidth(x);
+ transformed = true;
+ }
+
+ var y = element.getMaxY();
+ if (y > this.getHeight()) {
+ this.setMinHeight(y);
+ transformed = true;
+ }
+
+ return transformed;
+};
+
+
+/**
+ * @return {number} The width of the element's coordinate space.
+ */
+goog.graphics.ext.Group.prototype.getCoordinateWidth = function() {
+ return this.getWidth();
+};
+
+
+/**
+ * @return {number} The height of the element's coordinate space.
+ */
+goog.graphics.ext.Group.prototype.getCoordinateHeight = function() {
+ return this.getHeight();
+};
+
+
+/**
+ * Remove all drawing elements from the group.
+ */
+goog.graphics.ext.Group.prototype.clear = function() {
+ while (this.children_.length) {
+ this.removeChild(this.children_[0]);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/image.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/image.js b/externs/GCL/externs/goog/graphics/ext/image.js
new file mode 100644
index 0000000..ec24e1d
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/image.js
@@ -0,0 +1,64 @@
+// 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 thick wrapper around images.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.Image');
+
+goog.require('goog.graphics.ext.Element');
+
+
+
+/**
+ * Wrapper for a graphics image element.
+ * @param {goog.graphics.ext.Group} group Parent for this element.
+ * @param {string} src The path to the image to display.
+ * @constructor
+ * @extends {goog.graphics.ext.Element}
+ * @final
+ */
+goog.graphics.ext.Image = function(group, src) {
+ // Initialize with some stock values.
+ var wrapper = group.getGraphicsImplementation().drawImage(0, 0, 1, 1, src,
+ group.getWrapper());
+ goog.graphics.ext.Element.call(this, group, wrapper);
+};
+goog.inherits(goog.graphics.ext.Image, goog.graphics.ext.Element);
+
+
+/**
+ * Redraw the image. Called when the coordinate system is changed.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.Image.prototype.redraw = function() {
+ goog.graphics.ext.Image.superClass_.redraw.call(this);
+
+ // Our position is already handled bu transform_.
+ this.getWrapper().setSize(this.getWidth(), this.getHeight());
+};
+
+
+/**
+ * Update the source of the image.
+ * @param {string} src Source of the image.
+ */
+goog.graphics.ext.Image.prototype.setSource = function(src) {
+ this.getWrapper().setSource(src);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/path.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/path.js b/externs/GCL/externs/goog/graphics/ext/path.js
new file mode 100644
index 0000000..de550aa
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/path.js
@@ -0,0 +1,142 @@
+// 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 thick wrapper around paths.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.Path');
+
+goog.require('goog.graphics.AffineTransform');
+goog.require('goog.graphics.Path');
+goog.require('goog.math.Rect');
+
+
+
+/**
+ * Creates a path object
+ * @constructor
+ * @extends {goog.graphics.Path}
+ * @final
+ */
+goog.graphics.ext.Path = function() {
+ goog.graphics.Path.call(this);
+};
+goog.inherits(goog.graphics.ext.Path, goog.graphics.Path);
+
+
+/**
+ * Optional cached or user specified bounding box. A user may wish to
+ * precompute a bounding box to save time and include more accurate
+ * computations.
+ * @type {goog.math.Rect?}
+ * @private
+ */
+goog.graphics.ext.Path.prototype.bounds_ = null;
+
+
+/**
+ * Clones the path.
+ * @return {!goog.graphics.ext.Path} A clone of this path.
+ * @override
+ */
+goog.graphics.ext.Path.prototype.clone = function() {
+ var output = /** @type {goog.graphics.ext.Path} */
+ (goog.graphics.ext.Path.superClass_.clone.call(this));
+ output.bounds_ = this.bounds_ && this.bounds_.clone();
+ return output;
+};
+
+
+/**
+ * Transforms the path. Only simple paths are transformable. Attempting
+ * to transform a non-simple path will throw an error.
+ * @param {!goog.graphics.AffineTransform} tx The transformation to perform.
+ * @return {!goog.graphics.ext.Path} The path itself.
+ * @override
+ */
+goog.graphics.ext.Path.prototype.transform = function(tx) {
+ goog.graphics.ext.Path.superClass_.transform.call(this, tx);
+
+ // Make sure the precomputed bounds are cleared when the path is transformed.
+ this.bounds_ = null;
+
+ return this;
+};
+
+
+/**
+ * Modify the bounding box of the path. This may cause the path to be
+ * simplified (i.e. arcs converted to curves) as a side-effect.
+ * @param {number} deltaX How far to translate the x coordinates.
+ * @param {number} deltaY How far to translate the y coordinates.
+ * @param {number} xFactor After translation, all x coordinates are multiplied
+ * by this number.
+ * @param {number} yFactor After translation, all y coordinates are multiplied
+ * by this number.
+ * @return {!goog.graphics.ext.Path} The path itself.
+ */
+goog.graphics.ext.Path.prototype.modifyBounds = function(deltaX, deltaY,
+ xFactor, yFactor) {
+ if (!this.isSimple()) {
+ var simple = goog.graphics.Path.createSimplifiedPath(this);
+ this.clear();
+ this.appendPath(simple);
+ }
+
+ return this.transform(goog.graphics.AffineTransform.getScaleInstance(
+ xFactor, yFactor).translate(deltaX, deltaY));
+};
+
+
+/**
+ * Set the precomputed bounds.
+ * @param {goog.math.Rect?} bounds The bounds to use, or set to null to clear
+ * and recompute on the next call to getBoundingBox.
+ */
+goog.graphics.ext.Path.prototype.useBoundingBox = function(bounds) {
+ this.bounds_ = bounds && bounds.clone();
+};
+
+
+/**
+ * @return {goog.math.Rect?} The bounding box of the path, or null if the
+ * path is empty.
+ */
+goog.graphics.ext.Path.prototype.getBoundingBox = function() {
+ if (!this.bounds_ && !this.isEmpty()) {
+ var minY;
+ var minX = minY = Number.POSITIVE_INFINITY;
+ var maxY;
+ var maxX = maxY = Number.NEGATIVE_INFINITY;
+
+ var simplePath = this.isSimple() ? this :
+ goog.graphics.Path.createSimplifiedPath(this);
+ simplePath.forEachSegment(function(type, points) {
+ for (var i = 0, len = points.length; i < len; i += 2) {
+ minX = Math.min(minX, points[i]);
+ maxX = Math.max(maxX, points[i]);
+ minY = Math.min(minY, points[i + 1]);
+ maxY = Math.max(maxY, points[i + 1]);
+ }
+ });
+
+ this.bounds_ = new goog.math.Rect(minX, minY, maxX - minX, maxY - minY);
+ }
+
+ return this.bounds_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/rectangle.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/rectangle.js b/externs/GCL/externs/goog/graphics/ext/rectangle.js
new file mode 100644
index 0000000..d05c8b1
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/rectangle.js
@@ -0,0 +1,55 @@
+// 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 thick wrapper around rectangles.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.Rectangle');
+
+goog.require('goog.graphics.ext.StrokeAndFillElement');
+
+
+
+/**
+ * Wrapper for a graphics rectangle element.
+ * @param {goog.graphics.ext.Group} group Parent for this element.
+ * @constructor
+ * @extends {goog.graphics.ext.StrokeAndFillElement}
+ * @final
+ */
+goog.graphics.ext.Rectangle = function(group) {
+ // Initialize with some stock values.
+ var wrapper = group.getGraphicsImplementation().drawRect(0, 0, 1, 1, null,
+ null, group.getWrapper());
+ goog.graphics.ext.StrokeAndFillElement.call(this, group, wrapper);
+};
+goog.inherits(goog.graphics.ext.Rectangle,
+ goog.graphics.ext.StrokeAndFillElement);
+
+
+/**
+ * Redraw the rectangle. Called when the coordinate system is changed.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.Rectangle.prototype.redraw = function() {
+ goog.graphics.ext.Rectangle.superClass_.redraw.call(this);
+
+ // Our position is already handled by transform_.
+ this.getWrapper().setSize(this.getWidth(), this.getHeight());
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/shape.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/shape.js b/externs/GCL/externs/goog/graphics/ext/shape.js
new file mode 100644
index 0000000..3f80e82
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/shape.js
@@ -0,0 +1,145 @@
+// 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 thick wrapper around shapes with custom paths.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.Shape');
+
+goog.require('goog.graphics.ext.StrokeAndFillElement');
+
+
+
+/**
+ * Wrapper for a graphics shape element.
+ * @param {goog.graphics.ext.Group} group Parent for this element.
+ * @param {!goog.graphics.ext.Path} path The path to draw.
+ * @param {boolean=} opt_autoSize Optional flag to specify the path should
+ * automatically resize to fit the element. Defaults to false.
+ * @constructor
+ * @extends {goog.graphics.ext.StrokeAndFillElement}
+ * @final
+ */
+goog.graphics.ext.Shape = function(group, path, opt_autoSize) {
+ this.autoSize_ = !!opt_autoSize;
+
+ var graphics = group.getGraphicsImplementation();
+ var wrapper = graphics.drawPath(path, null, null,
+ group.getWrapper());
+ goog.graphics.ext.StrokeAndFillElement.call(this, group, wrapper);
+ this.setPath(path);
+};
+goog.inherits(goog.graphics.ext.Shape, goog.graphics.ext.StrokeAndFillElement);
+
+
+/**
+ * Whether or not to automatically resize the shape's path when the element
+ * itself is resized.
+ * @type {boolean}
+ * @private
+ */
+goog.graphics.ext.Shape.prototype.autoSize_ = false;
+
+
+/**
+ * The original path, specified by the caller.
+ * @type {goog.graphics.Path}
+ * @private
+ */
+goog.graphics.ext.Shape.prototype.path_;
+
+
+/**
+ * The bounding box of the original path.
+ * @type {goog.math.Rect?}
+ * @private
+ */
+goog.graphics.ext.Shape.prototype.boundingBox_ = null;
+
+
+/**
+ * The scaled path.
+ * @type {goog.graphics.Path}
+ * @private
+ */
+goog.graphics.ext.Shape.prototype.scaledPath_;
+
+
+/**
+ * Get the path drawn by this shape.
+ * @return {goog.graphics.Path?} The path drawn by this shape.
+ */
+goog.graphics.ext.Shape.prototype.getPath = function() {
+ return this.path_;
+};
+
+
+/**
+ * Set the path to draw.
+ * @param {goog.graphics.ext.Path} path The path to draw.
+ */
+goog.graphics.ext.Shape.prototype.setPath = function(path) {
+ this.path_ = path;
+
+ if (this.autoSize_) {
+ this.boundingBox_ = path.getBoundingBox();
+ }
+
+ this.scaleAndSetPath_();
+};
+
+
+/**
+ * Scale the internal path to fit.
+ * @private
+ */
+goog.graphics.ext.Shape.prototype.scaleAndSetPath_ = function() {
+ this.scaledPath_ = this.boundingBox_ ? this.path_.clone().modifyBounds(
+ -this.boundingBox_.left, -this.boundingBox_.top,
+ this.getWidth() / (this.boundingBox_.width || 1),
+ this.getHeight() / (this.boundingBox_.height || 1)) : this.path_;
+
+ var wrapper = this.getWrapper();
+ if (wrapper) {
+ wrapper.setPath(this.scaledPath_);
+ }
+};
+
+
+/**
+ * Redraw the ellipse. Called when the coordinate system is changed.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.Shape.prototype.redraw = function() {
+ goog.graphics.ext.Shape.superClass_.redraw.call(this);
+ if (this.autoSize_) {
+ this.scaleAndSetPath_();
+ }
+};
+
+
+/**
+ * @return {boolean} Whether the shape is parent dependent.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.Shape.prototype.checkParentDependent = function() {
+ return this.autoSize_ ||
+ goog.graphics.ext.Shape.superClass_.checkParentDependent.call(this);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/ext/strokeandfillelement.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/ext/strokeandfillelement.js b/externs/GCL/externs/goog/graphics/ext/strokeandfillelement.js
new file mode 100644
index 0000000..4ad69f3
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/ext/strokeandfillelement.js
@@ -0,0 +1,70 @@
+// 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 thick wrapper around elements with stroke and fill.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.graphics.ext.StrokeAndFillElement');
+
+goog.require('goog.graphics.ext.Element');
+
+
+
+/**
+ * Interface for a graphics element that has a stroke and fill.
+ * This is the base interface for ellipse, rectangle and other
+ * shape interfaces.
+ * You should not construct objects from this constructor. Use a subclass.
+ * @param {goog.graphics.ext.Group} group Parent for this element.
+ * @param {goog.graphics.StrokeAndFillElement} wrapper The thin wrapper to wrap.
+ * @constructor
+ * @extends {goog.graphics.ext.Element}
+ */
+goog.graphics.ext.StrokeAndFillElement = function(group, wrapper) {
+ goog.graphics.ext.Element.call(this, group, wrapper);
+};
+goog.inherits(goog.graphics.ext.StrokeAndFillElement,
+ goog.graphics.ext.Element);
+
+
+/**
+ * Sets the fill for this element.
+ * @param {goog.graphics.Fill?} fill The fill object.
+ */
+goog.graphics.ext.StrokeAndFillElement.prototype.setFill = function(fill) {
+ this.getWrapper().setFill(fill);
+};
+
+
+/**
+ * Sets the stroke for this element.
+ * @param {goog.graphics.Stroke?} stroke The stroke object.
+ */
+goog.graphics.ext.StrokeAndFillElement.prototype.setStroke = function(stroke) {
+ this.getWrapper().setStroke(stroke);
+};
+
+
+/**
+ * Redraw the rectangle. Called when the coordinate system is changed.
+ * @protected
+ * @override
+ */
+goog.graphics.ext.StrokeAndFillElement.prototype.redraw = function() {
+ this.getWrapper().reapplyStroke();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/fill.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/fill.js b/externs/GCL/externs/goog/graphics/fill.js
new file mode 100644
index 0000000..92e460e
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/fill.js
@@ -0,0 +1,46 @@
+// 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 Represents a fill goog.graphics.
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.graphics.Fill');
+
+
+
+/**
+ * Creates a fill object
+ * @constructor
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.Fill = function() {};
+
+
+/**
+ * @return {string} The start color of a gradient fill.
+ */
+goog.graphics.Fill.prototype.getColor1 = goog.abstractMethod;
+
+
+/**
+ * @return {string} The end color of a gradient fill.
+ */
+goog.graphics.Fill.prototype.getColor2 = goog.abstractMethod;
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/font.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/font.js b/externs/GCL/externs/goog/graphics/font.js
new file mode 100644
index 0000000..f58bf41
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/font.js
@@ -0,0 +1,64 @@
+// 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 Represents a font to be used with a Renderer.
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/graphics/basicelements.html
+ */
+
+
+goog.provide('goog.graphics.Font');
+
+
+
+/**
+ * This class represents a font to be used with a renderer.
+ * @param {number} size The font size.
+ * @param {string} family The font family.
+ * @constructor
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ * @final
+ */
+goog.graphics.Font = function(size, family) {
+ /**
+ * Font size.
+ * @type {number}
+ */
+ this.size = size;
+ // TODO(arv): Is this in pixels or drawing units based on the coord size?
+
+ /**
+ * The name of the font family to use, can be a comma separated string.
+ * @type {string}
+ */
+ this.family = family;
+};
+
+
+/**
+ * Indication if text should be bolded
+ * @type {boolean}
+ */
+goog.graphics.Font.prototype.bold = false;
+
+
+/**
+ * Indication if text should be in italics
+ * @type {boolean}
+ */
+goog.graphics.Font.prototype.italic = false;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/graphics/graphics.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/graphics/graphics.js b/externs/GCL/externs/goog/graphics/graphics.js
new file mode 100644
index 0000000..0bde5b5
--- /dev/null
+++ b/externs/GCL/externs/goog/graphics/graphics.js
@@ -0,0 +1,142 @@
+// 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 Graphics utility functions and factory methods.
+ * @author arv@google.com (Erik Arvidsson)
+ * @see ../demos/graphics/advancedcoordinates.html
+ * @see ../demos/graphics/advancedcoordinates2.html
+ * @see ../demos/graphics/basicelements.html
+ * @see ../demos/graphics/events.html
+ * @see ../demos/graphics/modifyelements.html
+ * @see ../demos/graphics/tiger.html
+ */
+
+
+goog.provide('goog.graphics');
+
+goog.require('goog.dom');
+goog.require('goog.graphics.CanvasGraphics');
+goog.require('goog.graphics.SvgGraphics');
+goog.require('goog.graphics.VmlGraphics');
+goog.require('goog.userAgent');
+
+
+/**
+ * Returns an instance of goog.graphics.AbstractGraphics that knows how to draw
+ * for the current platform (A factory for the proper Graphics implementation)
+ * @param {string|number} width The width in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {string|number} height The height in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {?number=} opt_coordWidth The optional coordinate width - if
+ * omitted or null, defaults to same as width.
+ * @param {?number=} opt_coordHeight The optional coordinate height - if
+ * omitted or null, defaults to same as height.
+ * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
+ * document we want to render in.
+ * @return {!goog.graphics.AbstractGraphics} The created instance.
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.createGraphics = function(width, height, opt_coordWidth,
+ opt_coordHeight, opt_domHelper) {
+ var graphics;
+ // On IE9 and above, SVG is available, except in compatibility mode.
+ // We check createElementNS on document object that is not exist in
+ // compatibility mode.
+ if (goog.userAgent.IE &&
+ (!goog.userAgent.isVersionOrHigher('9') ||
+ !(opt_domHelper || goog.dom.getDomHelper()).
+ getDocument().createElementNS)) {
+ graphics = new goog.graphics.VmlGraphics(width, height,
+ opt_coordWidth, opt_coordHeight, opt_domHelper);
+ } else if (goog.userAgent.WEBKIT &&
+ (!goog.userAgent.isVersionOrHigher('420') ||
+ goog.userAgent.MOBILE)) {
+ graphics = new goog.graphics.CanvasGraphics(width, height,
+ opt_coordWidth, opt_coordHeight, opt_domHelper);
+ } else {
+ graphics = new goog.graphics.SvgGraphics(width, height,
+ opt_coordWidth, opt_coordHeight, opt_domHelper);
+ }
+
+ // Create the dom now, because all drawing methods require that the
+ // main dom element (the canvas) has been already created.
+ graphics.createDom();
+
+ return graphics;
+};
+
+
+/**
+ * Returns an instance of goog.graphics.AbstractGraphics that knows how to draw
+ * for the current platform (A factory for the proper Graphics implementation)
+ * @param {string|number} width The width in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {string|number} height The height in pixels. Strings
+ * expressing percentages of parent with (e.g. '80%') are also accepted.
+ * @param {?number=} opt_coordWidth The optional coordinate width, defaults to
+ * same as width.
+ * @param {?number=} opt_coordHeight The optional coordinate height, defaults to
+ * same as height.
+ * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
+ * document we want to render in.
+ * @return {!goog.graphics.AbstractGraphics} The created instance.
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.createSimpleGraphics = function(width, height,
+ opt_coordWidth, opt_coordHeight, opt_domHelper) {
+ if (goog.userAgent.MAC && goog.userAgent.GECKO &&
+ !goog.userAgent.isVersionOrHigher('1.9a')) {
+ // Canvas is 6x faster than SVG on Mac FF 2.0
+ var graphics = new goog.graphics.CanvasGraphics(
+ width, height, opt_coordWidth, opt_coordHeight,
+ opt_domHelper);
+ graphics.createDom();
+ return graphics;
+ }
+
+ // Otherwise, defer to normal graphics object creation.
+ return goog.graphics.createGraphics(width, height, opt_coordWidth,
+ opt_coordHeight, opt_domHelper);
+};
+
+
+/**
+ * Static function to check if the current browser has Graphics support.
+ * @return {boolean} True if the current browser has Graphics support.
+ * @deprecated goog.graphics is deprecated. It existed to abstract over browser
+ * differences before the canvas tag was widely supported. See
+ * http://en.wikipedia.org/wiki/Canvas_element for details.
+ */
+goog.graphics.isBrowserSupported = function() {
+ if (goog.userAgent.IE) {
+ return goog.userAgent.isVersionOrHigher('5.5');
+ }
+ if (goog.userAgent.GECKO) {
+ return goog.userAgent.isVersionOrHigher('1.8');
+ }
+ if (goog.userAgent.OPERA) {
+ return goog.userAgent.isVersionOrHigher('9.0');
+ }
+ if (goog.userAgent.WEBKIT) {
+ return goog.userAgent.isVersionOrHigher('412');
+ }
+ return false;
+};
[34/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/demos/graphics/tigerdata.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/demos/graphics/tigerdata.js b/externs/GCL/externs/goog/demos/graphics/tigerdata.js
new file mode 100644
index 0000000..633c55c
--- /dev/null
+++ b/externs/GCL/externs/goog/demos/graphics/tigerdata.js
@@ -0,0 +1,2841 @@
+// 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 This data is generated from an SVG image of a tiger.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+var tigerData = [{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [77.696, 284.285]},
+ {t: 'C', p: [77.696, 284.285, 77.797, 286.179, 76.973, 286.16]},
+ {t: 'C', p: [76.149, 286.141, 59.695, 238.066, 39.167, 240.309]},
+ {t: 'C', p: [39.167, 240.309, 56.95, 232.956, 77.696, 284.285]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [81.226, 281.262]},
+ {t: 'C', p: [81.226, 281.262, 80.677, 283.078, 79.908, 282.779]},
+ {t: 'C', p: [79.14, 282.481, 80.023, 231.675, 59.957, 226.801]},
+ {t: 'C', p: [59.957, 226.801, 79.18, 225.937, 81.226, 281.262]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [108.716, 323.59]},
+ {t: 'C', p: [108.716, 323.59, 110.352, 324.55, 109.882, 325.227]},
+ {t: 'C', p: [109.411, 325.904, 60.237, 313.102, 50.782, 331.459]},
+ {t: 'C', p: [50.782, 331.459, 54.461, 312.572, 108.716, 323.59]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [105.907, 333.801]},
+ {t: 'C', p: [105.907, 333.801, 107.763, 334.197, 107.529, 334.988]},
+ {t: 'C', p: [107.296, 335.779, 56.593, 339.121, 53.403, 359.522]},
+ {t: 'C', p: [53.403, 359.522, 50.945, 340.437, 105.907, 333.801]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [101.696, 328.276]},
+ {t: 'C', p: [101.696, 328.276, 103.474, 328.939, 103.128, 329.687]},
+ {t: 'C', p: [102.782, 330.435, 52.134, 326.346, 46.002, 346.064]},
+ {t: 'C', p: [46.002, 346.064, 46.354, 326.825, 101.696, 328.276]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [90.991, 310.072]},
+ {t: 'C', p: [90.991, 310.072, 92.299, 311.446, 91.66, 311.967]},
+ {t: 'C', p: [91.021, 312.488, 47.278, 286.634, 33.131, 301.676]},
+ {t: 'C', p: [33.131, 301.676, 41.872, 284.533, 90.991, 310.072]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [83.446, 314.263]},
+ {t: 'C', p: [83.446, 314.263, 84.902, 315.48, 84.326, 316.071]},
+ {t: 'C', p: [83.75, 316.661, 37.362, 295.922, 25.008, 312.469]},
+ {t: 'C', p: [25.008, 312.469, 31.753, 294.447, 83.446, 314.263]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [80.846, 318.335]},
+ {t: 'C', p: [80.846, 318.335, 82.454, 319.343, 81.964, 320.006]},
+ {t: 'C', p: [81.474, 320.669, 32.692, 306.446, 22.709, 324.522]},
+ {t: 'C', p: [22.709, 324.522, 26.934, 305.749, 80.846, 318.335]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [91.58, 318.949]},
+ {t: 'C', p: [91.58, 318.949, 92.702, 320.48, 92.001, 320.915]},
+ {t: 'C', p: [91.3, 321.35, 51.231, 290.102, 35.273, 303.207]},
+ {t: 'C', p: [35.273, 303.207, 46.138, 287.326, 91.58, 318.949]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [71.8, 290]},
+ {t: 'C', p: [71.8, 290, 72.4, 291.8, 71.6, 292]},
+ {t: 'C', p: [70.8, 292.2, 42.2, 250.2, 22.999, 257.8]},
+ {t: 'C', p: [22.999, 257.8, 38.2, 246, 71.8, 290]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [72.495, 296.979]},
+ {t: 'C', p: [72.495, 296.979, 73.47, 298.608, 72.731, 298.975]},
+ {t: 'C', p: [71.993, 299.343, 35.008, 264.499, 17.899, 276.061]},
+ {t: 'C', p: [17.899, 276.061, 30.196, 261.261, 72.495, 296.979]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: {c: '#000', w: 0.172},
+ p: [{t: 'M', p: [72.38, 301.349]},
+ {t: 'C', p: [72.38, 301.349, 73.502, 302.88, 72.801, 303.315]},
+ {t: 'C', p: [72.1, 303.749, 32.031, 272.502, 16.073, 285.607]},
+ {t: 'C', p: [16.073, 285.607, 26.938, 269.726, 72.38, 301.349]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: '#000', p: [{t: 'M', p: [70.17, 303.065]},
+ {t: 'C', p: [70.673, 309.113, 71.661, 315.682, 73.4, 318.801]},
+ {t: 'C', p: [73.4, 318.801, 69.8, 331.201, 78.6, 344.401]},
+ {t: 'C', p: [78.6, 344.401, 78.2, 351.601, 79.8, 354.801]},
+ {t: 'C', p: [79.8, 354.801, 83.8, 363.201, 88.6, 364.001]},
+ {t: 'C', p: [92.484, 364.648, 101.207, 367.717, 111.068, 369.121]},
+ {t: 'C', p: [111.068, 369.121, 128.2, 383.201, 125, 396.001]},
+ {t: 'C', p: [125, 396.001, 124.6, 412.401, 121, 414.001]},
+ {t: 'C', p: [121, 414.001, 132.6, 402.801, 123, 419.601]},
+ {t: 'L', p: [118.6, 438.401]},
+ {t: 'C', p: [118.6, 438.401, 144.2, 416.801, 128.6, 435.201]},
+ {t: 'L', p: [118.6, 461.201]},
+ {t: 'C', p: [118.6, 461.201, 138.2, 442.801, 131, 451.201]},
+ {t: 'L', p: [127.8, 460.001]},
+ {t: 'C', p: [127.8, 460.001, 171, 432.801, 140.2, 462.401]},
+ {t: 'C', p: [140.2, 462.401, 148.2, 458.801, 152.6, 461.601]},
+ {t: 'C', p: [152.6, 461.601, 159.4, 460.401, 158.6, 462.001]},
+ {t: 'C', p: [158.6, 462.001, 137.8, 472.401, 134.2, 490.801]},
+ {t: 'C', p: [134.2, 490.801, 142.6, 480.801, 139.4, 491.601]},
+ {t: 'L', p: [139.8, 503.201]},
+ {t: 'C', p: [139.8, 503.201, 143.8, 481.601, 143.4, 519.201]},
+ {t: 'C', p: [143.4, 519.201, 162.6, 501.201, 151, 522.001]},
+ {t: 'L', p: [151, 538.801]},
+ {t: 'C', p: [151, 538.801, 166.2, 522.401, 159.8, 535.201]},
+ {t: 'C', p: [159.8, 535.201, 169.8, 526.401, 165.8, 541.601]},
+ {t: 'C', p: [165.8, 541.601, 165, 552.001, 169.4, 540.801]},
+ {t: 'C', p: [169.4, 540.801, 185.4, 510.201, 179.4, 536.401]},
+ {t: 'C', p: [179.4, 536.401, 178.6, 555.601, 183.4, 540.801]},
+ {t: 'C', p: [183.4, 540.801, 183.8, 551.201, 193, 558.401]},
+ {t: 'C', p: [193, 558.401, 191.8, 507.601, 204.6, 543.601]},
+ {t: 'L', p: [208.6, 560.001]},
+ {t: 'C', p: [208.6, 560.001, 211.4, 550.801, 211, 545.601]},
+ {t: 'C', p: [211, 545.601, 225.8, 529.201, 219, 553.601]},
+ {t: 'C', p: [219, 553.601, 234.2, 530.801, 231, 544.001]},
+ {t: 'C', p: [231, 544.001, 223.4, 560.001, 225, 564.801]},
+ {t: 'C', p: [225, 564.801, 241.8, 530.001, 243, 528.401]},
+ {t: 'C', p: [243, 528.401, 241, 570.802, 251.8, 534.801]},
+ {t: 'C', p: [251.8, 534.801, 257.4, 546.801, 254.6, 551.201]},
+ {t: 'C', p: [254.6, 551.201, 262.6, 543.201, 261.8, 540.001]},
+ {t: 'C', p: [261.8, 540.001, 266.4, 531.801, 269.2, 545.401]},
+ {t: 'C', p: [269.2, 545.401, 271, 554.801, 272.6, 551.601]},
+ {t: 'C', p: [272.6, 551.601, 276.6, 575.602, 277.8, 552.801]},
+ {t: 'C', p: [277.8, 552.801, 279.4, 539.201, 272.2, 527.601]},
+ {t: 'C', p: [272.2, 527.601, 273, 524.401, 270.2, 520.401]},
+ {t: 'C', p: [270.2, 520.401, 283.8, 542.001, 276.6, 513.201]},
+ {t: 'C', p: [276.6, 513.201, 287.801, 521.201, 289.001, 521.201]},
+ {t: 'C', p: [289.001, 521.201, 275.4, 498.001, 284.2, 502.801]},
+ {t: 'C', p: [284.2, 502.801, 279, 492.401, 297.001, 504.401]},
+ {t: 'C', p: [297.001, 504.401, 281, 488.401, 298.601, 498.001]},
+ {t: 'C', p: [298.601, 498.001, 306.601, 504.401, 299.001, 494.401]},
+ {t: 'C', p: [299.001, 494.401, 284.6, 478.401, 306.601, 496.401]},
+ {t: 'C', p: [306.601, 496.401, 318.201, 512.801, 319.001, 515.601]},
+ {t: 'C', p: [319.001, 515.601, 309.001, 486.401, 304.601, 483.601]},
+ {t: 'C', p: [304.601, 483.601, 313.001, 447.201, 354.201, 462.801]},
+ {t: 'C', p: [354.201, 462.801, 361.001, 480.001, 365.401, 461.601]},
+ {t: 'C', p: [365.401, 461.601, 378.201, 455.201, 389.401, 482.801]},
+ {t: 'C', p: [389.401, 482.801, 393.401, 469.201, 392.601, 466.401]},
+ {t: 'C', p: [392.601, 466.401, 399.401, 467.601, 398.601, 466.401]},
+ {t: 'C', p: [398.601, 466.401, 411.801, 470.801, 413.001, 470.001]},
+ {t: 'C', p: [413.001, 470.001, 419.801, 476.801, 420.201, 473.201]},
+ {t: 'C', p: [420.201, 473.201, 429.401, 476.001, 427.401, 472.401]},
+ {t: 'C', p: [427.401, 472.401, 436.201, 488.001, 436.601, 491.601]},
+ {t: 'L', p: [439.001, 477.601]},
+ {t: 'L', p: [441.001, 480.401]},
+ {t: 'C', p: [441.001, 480.401, 442.601, 472.801, 441.801, 471.601]},
+ {t: 'C', p: [441.001, 470.401, 461.801, 478.401, 466.601, 499.201]},
+ {t: 'L', p: [468.601, 507.601]},
+ {t: 'C', p: [468.601, 507.601, 474.601, 492.801, 473.001, 488.801]},
+ {t: 'C', p: [473.001, 488.801, 478.201, 489.601, 478.601, 494.001]},
+ {t: 'C', p: [478.601, 494.001, 482.601, 470.801, 477.801, 464.801]},
+ {t: 'C', p: [477.801, 464.801, 482.201, 464.001, 483.401, 467.601]},
+ {t: 'L', p: [483.401, 460.401]},
+ {t: 'C', p: [483.401, 460.401, 490.601, 461.201, 490.601, 458.801]},
+ {t: 'C', p: [490.601, 458.801, 495.001, 454.801, 497.001, 459.601]},
+ {t: 'C', p: [497.001, 459.601, 484.601, 424.401, 503.001, 443.601]},
+ {t: 'C', p: [503.001, 443.601, 510.201, 454.401, 506.601, 435.601]},
+ {t: 'C', p: [503.001, 416.801, 499.001, 415.201, 503.801, 414.801]},
+ {t: 'C', p: [503.801, 414.801, 504.601, 411.201, 502.601, 409.601]},
+ {t: 'C', p: [500.601, 408.001, 503.801, 409.601, 503.801, 409.601]},
+ {t: 'C', p: [503.801, 409.601, 508.601, 413.601, 503.401, 391.601]},
+ {t: 'C', p: [503.401, 391.601, 509.801, 393.201, 497.801, 364.001]},
+ {t: 'C', p: [497.801, 364.001, 500.601, 361.601, 496.601, 353.201]},
+ {t: 'C', p: [496.601, 353.201, 504.601, 357.601, 507.401, 356.001]},
+ {t: 'C', p: [507.401, 356.001, 507.001, 354.401, 503.801, 350.401]},
+ {t: 'C', p: [503.801, 350.401, 482.201, 295.6, 502.601, 317.601]},
+ {t: 'C', p: [502.601, 317.601, 514.451, 331.151, 508.051, 308.351]},
+ {t: 'C', p: [508.051, 308.351, 498.94, 284.341, 499.717, 280.045]},
+ {t: 'L', p: [70.17, 303.065]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: '#000', p: [{t: 'M', p: [499.717, 280.245]},
+ {t: 'C', p: [500.345, 280.426, 502.551, 281.55, 503.801, 283.2]},
+ {t: 'C', p: [503.801, 283.2, 510.601, 294, 505.401, 275.6]},
+ {t: 'C', p: [505.401, 275.6, 496.201, 246.8, 505.001, 258]},
+ {t: 'C', p: [505.001, 258, 511.001, 265.2, 507.801, 251.6]},
+ {t: 'C', p: [503.936, 235.173, 501.401, 228.8, 501.401, 228.8]},
+ {t: 'C', p: [501.401, 228.8, 513.001, 233.6, 486.201, 194]},
+ {t: 'L', p: [495.001, 197.6]},
+ {t: 'C', p: [495.001, 197.6, 475.401, 158, 453.801, 152.8]},
+ {t: 'L', p: [445.801, 146.8]},
+ {t: 'C', p: [445.801, 146.8, 484.201, 108.8, 471.401, 72]},
+ {t: 'C', p: [471.401, 72, 464.601, 66.8, 455.001, 76]},
+ {t: 'C', p: [455.001, 76, 448.601, 80.8, 442.601, 79.2]},
+ {t: 'C', p: [442.601, 79.2, 411.801, 80.4, 409.801, 80.4]},
+ {t: 'C', p: [407.801, 80.4, 373.001, 43.2, 307.401, 60.8]},
+ {t: 'C', p: [307.401, 60.8, 302.201, 62.8, 297.801, 61.6]},
+ {t: 'C', p: [297.801, 61.6, 279.4, 45.6, 230.6, 68.4]},
+ {t: 'C', p: [230.6, 68.4, 220.6, 70.4, 219, 70.4]},
+ {t: 'C', p: [217.4, 70.4, 214.6, 70.4, 206.6, 76.8]},
+ {t: 'C', p: [198.6, 83.2, 198.2, 84, 196.2, 85.6]},
+ {t: 'C', p: [196.2, 85.6, 179.8, 96.8, 175, 97.6]},
+ {t: 'C', p: [175, 97.6, 163.4, 104, 159, 114]},
+ {t: 'L', p: [155.4, 115.2]},
+ {t: 'C', p: [155.4, 115.2, 153.8, 122.4, 153.4, 123.6]},
+ {t: 'C', p: [153.4, 123.6, 148.6, 127.2, 147.8, 132.8]},
+ {t: 'C', p: [147.8, 132.8, 139, 138.8, 139.4, 143.2]},
+ {t: 'C', p: [139.4, 143.2, 137.8, 148.4, 137, 153.2]},
+ {t: 'C', p: [137, 153.2, 129.8, 158, 130.6, 160.8]},
+ {t: 'C', p: [130.6, 160.8, 123, 174.8, 124.2, 181.6]},
+ {t: 'C', p: [124.2, 181.6, 117.8, 181.2, 115, 183.6]},
+ {t: 'C', p: [115, 183.6, 114.2, 188.4, 112.6, 188.8]},
+ {t: 'C', p: [112.6, 188.8, 109.8, 190, 112.2, 194]},
+ {t: 'C', p: [112.2, 194, 110.6, 196.8, 110.2, 198.4]},
+ {t: 'C', p: [110.2, 198.4, 111, 201.2, 106.6, 206.8]},
+ {t: 'C', p: [106.6, 206.8, 100.2, 225.6, 102.2, 230.8]},
+ {t: 'C', p: [102.2, 230.8, 102.6, 235.6, 99.8, 237.2]},
+ {t: 'C', p: [99.8, 237.2, 96.2, 236.8, 104.6, 248.8]},
+ {t: 'C', p: [104.6, 248.8, 105.4, 250, 102.2, 252.4]},
+ {t: 'C', p: [102.2, 252.4, 85, 256, 82.6, 272.4]},
+ {t: 'C', p: [82.6, 272.4, 69, 287.2, 69, 292.4]},
+ {t: 'C', p: [69, 294.705, 69.271, 297.852, 69.97, 302.465]},
+ {t: 'C', p: [69.97, 302.465, 69.4, 310.801, 97, 311.601]},
+ {t: 'C', p: [124.6, 312.401, 499.717, 280.245, 499.717, 280.245]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [84.4, 302.6]},
+ {t: 'C', p: [59.4, 263.2, 73.8, 319.601, 73.8, 319.601]},
+ {t: 'C', p: [82.6, 354.001, 212.2, 316.401, 212.2, 316.401]},
+ {t: 'C', p: [212.2, 316.401, 381.001, 286, 392.201, 282]},
+ {t: 'C', p: [403.401, 278, 498.601, 284.4, 498.601, 284.4]},
+ {t: 'L', p: [493.001, 267.6]},
+ {t: 'C', p: [428.201, 221.2, 409.001, 244.4, 395.401, 240.4]},
+ {t: 'C', p: [381.801, 236.4, 384.201, 246, 381.001, 246.8]},
+ {t: 'C', p: [377.801, 247.6, 338.601, 222.8, 332.201, 223.6]},
+ {t: 'C', p: [325.801, 224.4, 300.459, 200.649, 315.401, 232.4]},
+ {t: 'C', p: [331.401, 266.4, 257, 271.6, 240.2, 260.4]},
+ {t: 'C', p: [223.4, 249.2, 247.4, 278.8, 247.4, 278.8]},
+ {t: 'C', p: [265.8, 298.8, 231.4, 282, 231.4, 282]},
+ {t: 'C', p: [197, 269.2, 173, 294.8, 169.8, 295.6]},
+ {t: 'C', p: [166.6, 296.4, 161.8, 299.6, 161, 293.2]},
+ {t: 'C', p: [160.2, 286.8, 152.69, 270.099, 121, 296.4]},
+ {t: 'C', p: [101, 313.001, 87.2, 291, 87.2, 291]},
+ {t: 'L', p: [84.4, 302.6]},
+ {t: 'z', p: []}]},
+
+{f: '#e87f3a', s: null, p: [{t: 'M', p: [333.51, 225.346]},
+ {t: 'C', p: [327.11, 226.146, 301.743, 202.407, 316.71, 234.146]},
+ {t: 'C', p: [333.31, 269.346, 258.31, 273.346, 241.51, 262.146]},
+ {t: 'C', p: [224.709, 250.946, 248.71, 280.546, 248.71, 280.546]},
+ {t: 'C', p: [267.11, 300.546, 232.709, 283.746, 232.709, 283.746]},
+ {t: 'C', p: [198.309, 270.946, 174.309, 296.546, 171.109, 297.346]},
+ {t: 'C', p: [167.909, 298.146, 163.109, 301.346, 162.309, 294.946]},
+ {t: 'C', p: [161.509, 288.546, 154.13, 272.012, 122.309, 298.146]},
+ {t: 'C', p: [101.073, 315.492, 87.582, 294.037, 87.582, 294.037]},
+ {t: 'L', p: [84.382, 304.146]},
+ {t: 'C', p: [59.382, 264.346, 74.454, 322.655, 74.454, 322.655]},
+ {t: 'C', p: [83.255, 357.056, 213.509, 318.146, 213.509, 318.146]},
+ {t: 'C', p: [213.509, 318.146, 382.31, 287.746, 393.51, 283.746]},
+ {t: 'C', p: [404.71, 279.746, 499.038, 286.073, 499.038, 286.073]},
+ {t: 'L', p: [493.51, 268.764]},
+ {t: 'C', p: [428.71, 222.364, 410.31, 246.146, 396.71, 242.146]},
+ {t: 'C', p: [383.11, 238.146, 385.51, 247.746, 382.31, 248.546]},
+ {t: 'C', p: [379.11, 249.346, 339.91, 224.546, 333.51, 225.346]},
+ {t: 'z', p: []}]},
+
+{f: '#ea8c4d', s: null, p: [{t: 'M', p: [334.819, 227.091]},
+ {t: 'C', p: [328.419, 227.891, 303.685, 203.862, 318.019, 235.891]},
+ {t: 'C', p: [334.219, 272.092, 259.619, 275.092, 242.819, 263.892]},
+ {t: 'C', p: [226.019, 252.692, 250.019, 282.292, 250.019, 282.292]},
+ {t: 'C', p: [268.419, 302.292, 234.019, 285.492, 234.019, 285.492]},
+ {t: 'C', p: [199.619, 272.692, 175.618, 298.292, 172.418, 299.092]},
+ {t: 'C', p: [169.218, 299.892, 164.418, 303.092, 163.618, 296.692]},
+ {t: 'C', p: [162.818, 290.292, 155.57, 273.925, 123.618, 299.892]},
+ {t: 'C', p: [101.145, 317.983, 87.964, 297.074, 87.964, 297.074]},
+ {t: 'L', p: [84.364, 305.692]},
+ {t: 'C', p: [60.564, 266.692, 75.109, 325.71, 75.109, 325.71]},
+ {t: 'C', p: [83.909, 360.11, 214.819, 319.892, 214.819, 319.892]},
+ {t: 'C', p: [214.819, 319.892, 383.619, 289.492, 394.819, 285.492]},
+ {t: 'C', p: [406.019, 281.492, 499.474, 287.746, 499.474, 287.746]},
+ {t: 'L', p: [494.02, 269.928]},
+ {t: 'C', p: [429.219, 223.528, 411.619, 247.891, 398.019, 243.891]},
+ {t: 'C', p: [384.419, 239.891, 386.819, 249.491, 383.619, 250.292]},
+ {t: 'C', p: [380.419, 251.092, 341.219, 226.291, 334.819, 227.091]},
+ {t: 'z', p: []}]},
+
+{f: '#ec9961', s: null, p: [{t: 'M', p: [336.128, 228.837]},
+ {t: 'C', p: [329.728, 229.637, 304.999, 205.605, 319.328, 237.637]},
+ {t: 'C', p: [336.128, 275.193, 260.394, 276.482, 244.128, 265.637]},
+ {t: 'C', p: [227.328, 254.437, 251.328, 284.037, 251.328, 284.037]},
+ {t: 'C', p: [269.728, 304.037, 235.328, 287.237, 235.328, 287.237]},
+ {t: 'C', p: [200.928, 274.437, 176.928, 300.037, 173.728, 300.837]},
+ {t: 'C', p: [170.528, 301.637, 165.728, 304.837, 164.928, 298.437]},
+ {t: 'C', p: [164.128, 292.037, 157.011, 275.839, 124.927, 301.637]},
+ {t: 'C', p: [101.218, 320.474, 88.345, 300.11, 88.345, 300.11]},
+ {t: 'L', p: [84.345, 307.237]},
+ {t: 'C', p: [62.545, 270.437, 75.764, 328.765, 75.764, 328.765]},
+ {t: 'C', p: [84.564, 363.165, 216.128, 321.637, 216.128, 321.637]},
+ {t: 'C', p: [216.128, 321.637, 384.928, 291.237, 396.129, 287.237]},
+ {t: 'C', p: [407.329, 283.237, 499.911, 289.419, 499.911, 289.419]},
+ {t: 'L', p: [494.529, 271.092]},
+ {t: 'C', p: [429.729, 224.691, 412.929, 249.637, 399.329, 245.637]},
+ {t: 'C', p: [385.728, 241.637, 388.128, 251.237, 384.928, 252.037]},
+ {t: 'C', p: [381.728, 252.837, 342.528, 228.037, 336.128, 228.837]},
+ {t: 'z', p: []}]},
+
+{f: '#eea575', s: null, p: [{t: 'M', p: [337.438, 230.583]},
+ {t: 'C', p: [331.037, 231.383, 306.814, 207.129, 320.637, 239.383]},
+ {t: 'C', p: [337.438, 278.583, 262.237, 278.583, 245.437, 267.383]},
+ {t: 'C', p: [228.637, 256.183, 252.637, 285.783, 252.637, 285.783]},
+ {t: 'C', p: [271.037, 305.783, 236.637, 288.983, 236.637, 288.983]},
+ {t: 'C', p: [202.237, 276.183, 178.237, 301.783, 175.037, 302.583]},
+ {t: 'C', p: [171.837, 303.383, 167.037, 306.583, 166.237, 300.183]},
+ {t: 'C', p: [165.437, 293.783, 158.452, 277.752, 126.237, 303.383]},
+ {t: 'C', p: [101.291, 322.965, 88.727, 303.146, 88.727, 303.146]},
+ {t: 'L', p: [84.327, 308.783]},
+ {t: 'C', p: [64.527, 273.982, 76.418, 331.819, 76.418, 331.819]},
+ {t: 'C', p: [85.218, 366.22, 217.437, 323.383, 217.437, 323.383]},
+ {t: 'C', p: [217.437, 323.383, 386.238, 292.983, 397.438, 288.983]},
+ {t: 'C', p: [408.638, 284.983, 500.347, 291.092, 500.347, 291.092]},
+ {t: 'L', p: [495.038, 272.255]},
+ {t: 'C', p: [430.238, 225.855, 414.238, 251.383, 400.638, 247.383]},
+ {t: 'C', p: [387.038, 243.383, 389.438, 252.983, 386.238, 253.783]},
+ {t: 'C', p: [383.038, 254.583, 343.838, 229.783, 337.438, 230.583]},
+ {t: 'z', p: []}]},
+
+{f: '#f1b288', s: null, p: [{t: 'M', p: [338.747, 232.328]},
+ {t: 'C', p: [332.347, 233.128, 306.383, 209.677, 321.947, 241.128]},
+ {t: 'C', p: [341.147, 279.928, 263.546, 280.328, 246.746, 269.128]},
+ {t: 'C', p: [229.946, 257.928, 253.946, 287.528, 253.946, 287.528]},
+ {t: 'C', p: [272.346, 307.528, 237.946, 290.728, 237.946, 290.728]},
+ {t: 'C', p: [203.546, 277.928, 179.546, 303.528, 176.346, 304.328]},
+ {t: 'C', p: [173.146, 305.128, 168.346, 308.328, 167.546, 301.928]},
+ {t: 'C', p: [166.746, 295.528, 159.892, 279.665, 127.546, 305.128]},
+ {t: 'C', p: [101.364, 325.456, 89.109, 306.183, 89.109, 306.183]},
+ {t: 'L', p: [84.309, 310.328]},
+ {t: 'C', p: [66.309, 277.128, 77.073, 334.874, 77.073, 334.874]},
+ {t: 'C', p: [85.873, 369.274, 218.746, 325.128, 218.746, 325.128]},
+ {t: 'C', p: [218.746, 325.128, 387.547, 294.728, 398.747, 290.728]},
+ {t: 'C', p: [409.947, 286.728, 500.783, 292.764, 500.783, 292.764]},
+ {t: 'L', p: [495.547, 273.419]},
+ {t: 'C', p: [430.747, 227.019, 415.547, 253.128, 401.947, 249.128]},
+ {t: 'C', p: [388.347, 245.128, 390.747, 254.728, 387.547, 255.528]},
+ {t: 'C', p: [384.347, 256.328, 345.147, 231.528, 338.747, 232.328]},
+ {t: 'z', p: []}]},
+
+{f: '#f3bf9c', s: null, p: [{t: 'M', p: [340.056, 234.073]},
+ {t: 'C', p: [333.655, 234.873, 307.313, 211.613, 323.255, 242.873]},
+ {t: 'C', p: [343.656, 282.874, 264.855, 282.074, 248.055, 270.874]},
+ {t: 'C', p: [231.255, 259.674, 255.255, 289.274, 255.255, 289.274]},
+ {t: 'C', p: [273.655, 309.274, 239.255, 292.474, 239.255, 292.474]},
+ {t: 'C', p: [204.855, 279.674, 180.855, 305.274, 177.655, 306.074]},
+ {t: 'C', p: [174.455, 306.874, 169.655, 310.074, 168.855, 303.674]},
+ {t: 'C', p: [168.055, 297.274, 161.332, 281.578, 128.855, 306.874]},
+ {t: 'C', p: [101.436, 327.947, 89.491, 309.219, 89.491, 309.219]},
+ {t: 'L', p: [84.291, 311.874]},
+ {t: 'C', p: [68.291, 281.674, 77.727, 337.929, 77.727, 337.929]},
+ {t: 'C', p: [86.527, 372.329, 220.055, 326.874, 220.055, 326.874]},
+ {t: 'C', p: [220.055, 326.874, 388.856, 296.474, 400.056, 292.474]},
+ {t: 'C', p: [411.256, 288.474, 501.22, 294.437, 501.22, 294.437]},
+ {t: 'L', p: [496.056, 274.583]},
+ {t: 'C', p: [431.256, 228.183, 416.856, 254.874, 403.256, 250.874]},
+ {t: 'C', p: [389.656, 246.873, 392.056, 256.474, 388.856, 257.274]},
+ {t: 'C', p: [385.656, 258.074, 346.456, 233.273, 340.056, 234.073]},
+ {t: 'z', p: []}]},
+
+{f: '#f5ccb0', s: null, p: [{t: 'M', p: [341.365, 235.819]},
+ {t: 'C', p: [334.965, 236.619, 307.523, 213.944, 324.565, 244.619]},
+ {t: 'C', p: [346.565, 284.219, 266.164, 283.819, 249.364, 272.619]},
+ {t: 'C', p: [232.564, 261.419, 256.564, 291.019, 256.564, 291.019]},
+ {t: 'C', p: [274.964, 311.019, 240.564, 294.219, 240.564, 294.219]},
+ {t: 'C', p: [206.164, 281.419, 182.164, 307.019, 178.964, 307.819]},
+ {t: 'C', p: [175.764, 308.619, 170.964, 311.819, 170.164, 305.419]},
+ {t: 'C', p: [169.364, 299.019, 162.773, 283.492, 130.164, 308.619]},
+ {t: 'C', p: [101.509, 330.438, 89.873, 312.256, 89.873, 312.256]},
+ {t: 'L', p: [84.273, 313.419]},
+ {t: 'C', p: [69.872, 285.019, 78.382, 340.983, 78.382, 340.983]},
+ {t: 'C', p: [87.182, 375.384, 221.364, 328.619, 221.364, 328.619]},
+ {t: 'C', p: [221.364, 328.619, 390.165, 298.219, 401.365, 294.219]},
+ {t: 'C', p: [412.565, 290.219, 501.656, 296.11, 501.656, 296.11]},
+ {t: 'L', p: [496.565, 275.746]},
+ {t: 'C', p: [431.765, 229.346, 418.165, 256.619, 404.565, 252.619]},
+ {t: 'C', p: [390.965, 248.619, 393.365, 258.219, 390.165, 259.019]},
+ {t: 'C', p: [386.965, 259.819, 347.765, 235.019, 341.365, 235.819]},
+ {t: 'z', p: []}]},
+
+{f: '#f8d8c4', s: null, p: [{t: 'M', p: [342.674, 237.565]},
+ {t: 'C', p: [336.274, 238.365, 308.832, 215.689, 325.874, 246.365]},
+ {t: 'C', p: [347.874, 285.965, 267.474, 285.565, 250.674, 274.365]},
+ {t: 'C', p: [233.874, 263.165, 257.874, 292.765, 257.874, 292.765]},
+ {t: 'C', p: [276.274, 312.765, 241.874, 295.965, 241.874, 295.965]},
+ {t: 'C', p: [207.473, 283.165, 183.473, 308.765, 180.273, 309.565]},
+ {t: 'C', p: [177.073, 310.365, 172.273, 313.565, 171.473, 307.165]},
+ {t: 'C', p: [170.673, 300.765, 164.214, 285.405, 131.473, 310.365]},
+ {t: 'C', p: [101.582, 332.929, 90.255, 315.293, 90.255, 315.293]},
+ {t: 'L', p: [84.255, 314.965]},
+ {t: 'C', p: [70.654, 288.564, 79.037, 344.038, 79.037, 344.038]},
+ {t: 'C', p: [87.837, 378.438, 222.673, 330.365, 222.673, 330.365]},
+ {t: 'C', p: [222.673, 330.365, 391.474, 299.965, 402.674, 295.965]},
+ {t: 'C', p: [413.874, 291.965, 502.093, 297.783, 502.093, 297.783]},
+ {t: 'L', p: [497.075, 276.91]},
+ {t: 'C', p: [432.274, 230.51, 419.474, 258.365, 405.874, 254.365]},
+ {t: 'C', p: [392.274, 250.365, 394.674, 259.965, 391.474, 260.765]},
+ {t: 'C', p: [388.274, 261.565, 349.074, 236.765, 342.674, 237.565]},
+ {t: 'z', p: []}]},
+
+{f: '#fae5d7', s: null, p: [{t: 'M', p: [343.983, 239.31]},
+ {t: 'C', p: [337.583, 240.11, 310.529, 217.223, 327.183, 248.11]},
+ {t: 'C', p: [349.183, 288.91, 268.783, 287.31, 251.983, 276.11]},
+ {t: 'C', p: [235.183, 264.91, 259.183, 294.51, 259.183, 294.51]},
+ {t: 'C', p: [277.583, 314.51, 243.183, 297.71, 243.183, 297.71]},
+ {t: 'C', p: [208.783, 284.91, 184.783, 310.51, 181.583, 311.31]},
+ {t: 'C', p: [178.382, 312.11, 173.582, 315.31, 172.782, 308.91]},
+ {t: 'C', p: [171.982, 302.51, 165.654, 287.318, 132.782, 312.11]},
+ {t: 'C', p: [101.655, 335.42, 90.637, 318.329, 90.637, 318.329]},
+ {t: 'L', p: [84.236, 316.51]},
+ {t: 'C', p: [71.236, 292.51, 79.691, 347.093, 79.691, 347.093]},
+ {t: 'C', p: [88.491, 381.493, 223.983, 332.11, 223.983, 332.11]},
+ {t: 'C', p: [223.983, 332.11, 392.783, 301.71, 403.983, 297.71]},
+ {t: 'C', p: [415.183, 293.71, 502.529, 299.456, 502.529, 299.456]},
+ {t: 'L', p: [497.583, 278.074]},
+ {t: 'C', p: [432.783, 231.673, 420.783, 260.11, 407.183, 256.11]},
+ {t: 'C', p: [393.583, 252.11, 395.983, 261.71, 392.783, 262.51]},
+ {t: 'C', p: [389.583, 263.31, 350.383, 238.51, 343.983, 239.31]},
+ {t: 'z', p: []}]},
+
+{f: '#fcf2eb', s: null, p: [{t: 'M', p: [345.292, 241.055]},
+ {t: 'C', p: [338.892, 241.855, 312.917, 218.411, 328.492, 249.855]},
+ {t: 'C', p: [349.692, 292.656, 270.092, 289.056, 253.292, 277.856]},
+ {t: 'C', p: [236.492, 266.656, 260.492, 296.256, 260.492, 296.256]},
+ {t: 'C', p: [278.892, 316.256, 244.492, 299.456, 244.492, 299.456]},
+ {t: 'C', p: [210.092, 286.656, 186.092, 312.256, 182.892, 313.056]},
+ {t: 'C', p: [179.692, 313.856, 174.892, 317.056, 174.092, 310.656]},
+ {t: 'C', p: [173.292, 304.256, 167.095, 289.232, 134.092, 313.856]},
+ {t: 'C', p: [101.727, 337.911, 91.018, 321.365, 91.018, 321.365]},
+ {t: 'L', p: [84.218, 318.056]},
+ {t: 'C', p: [71.418, 294.856, 80.346, 350.147, 80.346, 350.147]},
+ {t: 'C', p: [89.146, 384.547, 225.292, 333.856, 225.292, 333.856]},
+ {t: 'C', p: [225.292, 333.856, 394.093, 303.456, 405.293, 299.456]},
+ {t: 'C', p: [416.493, 295.456, 502.965, 301.128, 502.965, 301.128]},
+ {t: 'L', p: [498.093, 279.237]},
+ {t: 'C', p: [433.292, 232.837, 422.093, 261.856, 408.493, 257.856]},
+ {t: 'C', p: [394.893, 253.855, 397.293, 263.456, 394.093, 264.256]},
+ {t: 'C', p: [390.892, 265.056, 351.692, 240.255, 345.292, 241.055]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: null, p: [{t: 'M', p: [84.2, 319.601]},
+ {t: 'C', p: [71.4, 297.6, 81, 353.201, 81, 353.201]},
+ {t: 'C', p: [89.8, 387.601, 226.6, 335.601, 226.6, 335.601]},
+ {t: 'C', p: [226.6, 335.601, 395.401, 305.2, 406.601, 301.2]},
+ {t: 'C', p: [417.801, 297.2, 503.401, 302.8, 503.401, 302.8]},
+ {t: 'L', p: [498.601, 280.4]},
+ {t: 'C', p: [433.801, 234, 423.401, 263.6, 409.801, 259.6]},
+ {t: 'C', p: [396.201, 255.6, 398.601, 265.2, 395.401, 266]},
+ {t: 'C', p: [392.201, 266.8, 353.001, 242, 346.601, 242.8]},
+ {t: 'C', p: [340.201, 243.6, 314.981, 219.793, 329.801, 251.6]},
+ {t: 'C', p: [352.028, 299.307, 269.041, 289.227, 254.6, 279.6]},
+ {t: 'C', p: [237.8, 268.4, 261.8, 298, 261.8, 298]},
+ {t: 'C', p: [280.2, 318.001, 245.8, 301.2, 245.8, 301.2]},
+ {t: 'C', p: [211.4, 288.4, 187.4, 314.001, 184.2, 314.801]},
+ {t: 'C', p: [181, 315.601, 176.2, 318.801, 175.4, 312.401]},
+ {t: 'C', p: [174.6, 306, 168.535, 291.144, 135.4, 315.601]},
+ {t: 'C', p: [101.8, 340.401, 91.4, 324.401, 91.4, 324.401]},
+ {t: 'L', p: [84.2, 319.601]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [125.8, 349.601]},
+ {t: 'C', p: [125.8, 349.601, 118.6, 361.201, 139.4, 374.401]},
+ {t: 'C', p: [139.4, 374.401, 140.8, 375.801, 122.8, 371.601]},
+ {t: 'C', p: [122.8, 371.601, 116.6, 369.601, 115, 359.201]},
+ {t: 'C', p: [115, 359.201, 110.2, 354.801, 105.4, 349.201]},
+ {t: 'C', p: [100.6, 343.601, 125.8, 349.601, 125.8, 349.601]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [265.8, 302]},
+ {t: 'C', p: [265.8, 302, 283.498, 328.821, 282.9, 333.601]},
+ {t: 'C', p: [281.6, 344.001, 281.4, 353.601, 284.6, 357.601]},
+ {t: 'C', p: [287.801, 361.601, 296.601, 394.801, 296.601, 394.801]},
+ {t: 'C', p: [296.601, 394.801, 296.201, 396.001, 308.601, 358.001]},
+ {t: 'C', p: [308.601, 358.001, 320.201, 342.001, 300.201, 323.601]},
+ {t: 'C', p: [300.201, 323.601, 265, 294.8, 265.8, 302]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [145.8, 376.401]},
+ {t: 'C', p: [145.8, 376.401, 157, 383.601, 142.6, 414.801]},
+ {t: 'L', p: [149, 412.401]},
+ {t: 'C', p: [149, 412.401, 148.2, 423.601, 145, 426.001]},
+ {t: 'L', p: [152.2, 422.801]},
+ {t: 'C', p: [152.2, 422.801, 157, 430.801, 153, 435.601]},
+ {t: 'C', p: [153, 435.601, 169.8, 443.601, 169, 450.001]},
+ {t: 'C', p: [169, 450.001, 175.4, 442.001, 171.4, 435.601]},
+ {t: 'C', p: [167.4, 429.201, 160.2, 433.201, 161, 414.801]},
+ {t: 'L', p: [152.2, 418.001]},
+ {t: 'C', p: [152.2, 418.001, 157.8, 409.201, 157.8, 402.801]},
+ {t: 'L', p: [149.8, 405.201]},
+ {t: 'C', p: [149.8, 405.201, 165.269, 378.623, 154.6, 377.201]},
+ {t: 'C', p: [148.6, 376.401, 145.8, 376.401, 145.8, 376.401]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [178.2, 393.201]},
+ {t: 'C', p: [178.2, 393.201, 181, 388.801, 178.2, 389.601]},
+ {t: 'C', p: [175.4, 390.401, 144.2, 405.201, 138.2, 414.801]},
+ {t: 'C', p: [138.2, 414.801, 172.6, 390.401, 178.2, 393.201]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [188.6, 401.201]},
+ {t: 'C', p: [188.6, 401.201, 191.4, 396.801, 188.6, 397.601]},
+ {t: 'C', p: [185.8, 398.401, 154.6, 413.201, 148.6, 422.801]},
+ {t: 'C', p: [148.6, 422.801, 183, 398.401, 188.6, 401.201]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [201.8, 386.001]},
+ {t: 'C', p: [201.8, 386.001, 204.6, 381.601, 201.8, 382.401]},
+ {t: 'C', p: [199, 383.201, 167.8, 398.001, 161.8, 407.601]},
+ {t: 'C', p: [161.8, 407.601, 196.2, 383.201, 201.8, 386.001]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [178.6, 429.601]},
+ {t: 'C', p: [178.6, 429.601, 178.6, 423.601, 175.8, 424.401]},
+ {t: 'C', p: [173, 425.201, 137, 442.801, 131, 452.401]},
+ {t: 'C', p: [131, 452.401, 173, 426.801, 178.6, 429.601]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [179.8, 418.801]},
+ {t: 'C', p: [179.8, 418.801, 181, 414.001, 178.2, 414.801]},
+ {t: 'C', p: [176.2, 414.801, 149.8, 426.401, 143.8, 436.001]},
+ {t: 'C', p: [143.8, 436.001, 173.4, 414.401, 179.8, 418.801]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [165.4, 466.401]},
+ {t: 'L', p: [155.4, 474.001]},
+ {t: 'C', p: [155.4, 474.001, 165.8, 466.401, 169.4, 467.601]},
+ {t: 'C', p: [169.4, 467.601, 162.6, 478.801, 161.8, 484.001]},
+ {t: 'C', p: [161.8, 484.001, 172.2, 471.201, 177.8, 471.601]},
+ {t: 'C', p: [177.8, 471.601, 185.4, 472.001, 185.4, 482.801]},
+ {t: 'C', p: [185.4, 482.801, 191, 472.401, 194.2, 472.801]},
+ {t: 'C', p: [194.2, 472.801, 195.4, 479.201, 194.2, 486.001]},
+ {t: 'C', p: [194.2, 486.001, 198.2, 478.401, 202.2, 480.001]},
+ {t: 'C', p: [202.2, 480.001, 208.6, 478.001, 207.8, 489.601]},
+ {t: 'C', p: [207.8, 489.601, 207.8, 500.001, 207, 502.801]},
+ {t: 'C', p: [207, 502.801, 212.6, 476.401, 215, 476.001]},
+ {t: 'C', p: [215, 476.001, 223, 474.801, 227.8, 483.601]},
+ {t: 'C', p: [227.8, 483.601, 223.8, 476.001, 228.6, 478.001]},
+ {t: 'C', p: [228.6, 478.001, 239.4, 479.601, 242.6, 486.401]},
+ {t: 'C', p: [242.6, 486.401, 235.8, 474.401, 241.4, 477.601]},
+ {t: 'C', p: [241.4, 477.601, 248.2, 477.601, 249.4, 484.001]},
+ {t: 'C', p: [249.4, 484.001, 257.8, 505.201, 259.8, 506.801]},
+ {t: 'C', p: [259.8, 506.801, 252.2, 485.201, 253.8, 485.201]},
+ {t: 'C', p: [253.8, 485.201, 251.8, 473.201, 257, 488.001]},
+ {t: 'C', p: [257, 488.001, 253.8, 474.001, 259.4, 474.801]},
+ {t: 'C', p: [265, 475.601, 269.4, 485.601, 277.8, 483.201]},
+ {t: 'C', p: [277.8, 483.201, 287.401, 488.801, 289.401, 419.601]},
+ {t: 'L', p: [165.4, 466.401]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [170.2, 373.601]},
+ {t: 'C', p: [170.2, 373.601, 185, 367.601, 225, 373.601]},
+ {t: 'C', p: [225, 373.601, 232.2, 374.001, 239, 365.201]},
+ {t: 'C', p: [245.8, 356.401, 272.6, 349.201, 279, 351.201]},
+ {t: 'L', p: [288.601, 357.601]},
+ {t: 'L', p: [289.401, 358.801]},
+ {t: 'C', p: [289.401, 358.801, 301.801, 369.201, 302.201, 376.801]},
+ {t: 'C', p: [302.601, 384.401, 287.801, 432.401, 278.2, 448.401]},
+ {t: 'C', p: [268.6, 464.401, 259, 476.801, 239.8, 474.401]},
+ {t: 'C', p: [239.8, 474.401, 219, 470.401, 193.4, 474.401]},
+ {t: 'C', p: [193.4, 474.401, 164.2, 472.801, 161.4, 464.801]},
+ {t: 'C', p: [158.6, 456.801, 172.6, 441.601, 172.6, 441.601]},
+ {t: 'C', p: [172.6, 441.601, 177, 433.201, 175.8, 418.801]},
+ {t: 'C', p: [174.6, 404.401, 175, 376.401, 170.2, 373.601]},
+ {t: 'z', p: []}]},
+
+{f: '#e5668c', s: null, p: [{t: 'M', p: [192.2, 375.601]},
+ {t: 'C', p: [200.6, 394.001, 171, 459.201, 171, 459.201]},
+ {t: 'C', p: [169, 460.801, 183.66, 466.846, 193.8, 464.401]},
+ {t: 'C', p: [204.746, 461.763, 245, 466.001, 245, 466.001]},
+ {t: 'C', p: [268.6, 450.401, 281.4, 406.001, 281.4, 406.001]},
+ {t: 'C', p: [281.4, 406.001, 291.801, 382.001, 274.2, 378.801]},
+ {t: 'C', p: [256.6, 375.601, 192.2, 375.601, 192.2, 375.601]},
+ {t: 'z', p: []}]},
+
+{f: '#b23259', s: null, p: [{t: 'M', p: [190.169, 406.497]},
+ {t: 'C', p: [193.495, 393.707, 195.079, 381.906, 192.2, 375.601]},
+ {t: 'C', p: [192.2, 375.601, 254.6, 382.001, 265.8, 361.201]},
+ {t: 'C', p: [270.041, 353.326, 284.801, 384.001, 284.4, 393.601]},
+ {t: 'C', p: [284.4, 393.601, 221.4, 408.001, 206.6, 396.801]},
+ {t: 'L', p: [190.169, 406.497]},
+ {t: 'z', p: []}]},
+
+{f: '#a5264c', s: null, p: [{t: 'M', p: [194.6, 422.801]},
+ {t: 'C', p: [194.6, 422.801, 196.6, 430.001, 194.2, 434.001]},
+ {t: 'C', p: [194.2, 434.001, 192.6, 434.801, 191.4, 435.201]},
+ {t: 'C', p: [191.4, 435.201, 192.6, 438.801, 198.6, 440.401]},
+ {t: 'C', p: [198.6, 440.401, 200.6, 444.801, 203, 445.201]},
+ {t: 'C', p: [205.4, 445.601, 210.2, 451.201, 214.2, 450.001]},
+ {t: 'C', p: [218.2, 448.801, 229.4, 444.801, 229.4, 444.801]},
+ {t: 'C', p: [229.4, 444.801, 235, 441.601, 243.8, 445.201]},
+ {t: 'C', p: [243.8, 445.201, 246.175, 444.399, 246.6, 440.401]},
+ {t: 'C', p: [247.1, 435.701, 250.2, 432.001, 252.2, 430.001]},
+ {t: 'C', p: [254.2, 428.001, 263.8, 415.201, 262.6, 414.801]},
+ {t: 'C', p: [261.4, 414.401, 194.6, 422.801, 194.6, 422.801]},
+ {t: 'z', p: []}]},
+
+{f: '#ff727f', s: '#000', p: [{t: 'M', p: [190.2, 374.401]},
+ {t: 'C', p: [190.2, 374.401, 187.4, 396.801, 190.6, 405.201]},
+ {t: 'C', p: [193.8, 413.601, 193, 415.601, 192.2, 419.601]},
+ {t: 'C', p: [191.4, 423.601, 195.8, 433.601, 201.4, 439.601]},
+ {t: 'L', p: [213.4, 441.201]},
+ {t: 'C', p: [213.4, 441.201, 228.6, 437.601, 237.8, 440.401]},
+ {t: 'C', p: [237.8, 440.401, 246.794, 441.744, 250.2, 426.801]},
+ {t: 'C', p: [250.2, 426.801, 255, 420.401, 262.2, 417.601]},
+ {t: 'C', p: [269.4, 414.801, 276.6, 373.201, 272.6, 365.201]},
+ {t: 'C', p: [268.6, 357.201, 254.2, 352.801, 238.2, 368.401]},
+ {t: 'C', p: [222.2, 384.001, 220.2, 367.201, 190.2, 374.401]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [191.8, 449.201]},
+ {t: 'C', p: [191.8, 449.201, 191, 447.201, 186.6, 446.801]},
+ {t: 'C', p: [186.6, 446.801, 164.2, 443.201, 155.8, 430.801]},
+ {t: 'C', p: [155.8, 430.801, 149, 425.201, 153.4, 436.801]},
+ {t: 'C', p: [153.4, 436.801, 163.8, 457.201, 170.6, 460.001]},
+ {t: 'C', p: [170.6, 460.001, 187, 464.001, 191.8, 449.201]},
+ {t: 'z', p: []}]},
+
+{f: '#cc3f4c', s: null, p: [{t: 'M', p: [271.742, 385.229]},
+ {t: 'C', p: [272.401, 377.323, 274.354, 368.709, 272.6, 365.201]},
+ {t: 'C', p: [266.154, 352.307, 249.181, 357.695, 238.2, 368.401]},
+ {t: 'C', p: [222.2, 384.001, 220.2, 367.201, 190.2, 374.401]},
+ {t: 'C', p: [190.2, 374.401, 188.455, 388.364, 189.295, 398.376]},
+ {t: 'C', p: [189.295, 398.376, 226.6, 386.801, 227.4, 392.401]},
+ {t: 'C', p: [227.4, 392.401, 229, 389.201, 238.2, 389.201]},
+ {t: 'C', p: [247.4, 389.201, 270.142, 388.029, 271.742, 385.229]},
+ {t: 'z', p: []}]},
+
+{f: null, s: {c: '#a51926', w: 2},
+ p: [{t: 'M', p: [228.6, 375.201]},
+ {t: 'C', p: [228.6, 375.201, 233.4, 380.001, 229.8, 389.601]},
+ {t: 'C', p: [229.8, 389.601, 215.4, 405.601, 217.4, 419.601]}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [180.6, 460.001]},
+ {t: 'C', p: [180.6, 460.001, 176.2, 447.201, 185, 454.001]},
+ {t: 'C', p: [185, 454.001, 189.8, 456.001, 188.6, 457.601]},
+ {t: 'C', p: [187.4, 459.201, 181.8, 463.201, 180.6, 460.001]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [185.64, 461.201]},
+ {t: 'C', p: [185.64, 461.201, 182.12, 450.961, 189.16, 456.401]},
+ {t: 'C', p: [189.16, 456.401, 193.581, 458.849, 192.04, 459.281]},
+ {t: 'C', p: [187.48, 460.561, 192.04, 463.121, 185.64, 461.201]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [190.44, 461.201]},
+ {t: 'C', p: [190.44, 461.201, 186.92, 450.961, 193.96, 456.401]},
+ {t: 'C', p: [193.96, 456.401, 198.335, 458.711, 196.84, 459.281]},
+ {t: 'C', p: [193.48, 460.561, 196.84, 463.121, 190.44, 461.201]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [197.04, 461.401]},
+ {t: 'C', p: [197.04, 461.401, 193.52, 451.161, 200.56, 456.601]},
+ {t: 'C', p: [200.56, 456.601, 204.943, 458.933, 203.441, 459.481]},
+ {t: 'C', p: [200.48, 460.561, 203.441, 463.321, 197.04, 461.401]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [203.52, 461.321]},
+ {t: 'C', p: [203.52, 461.321, 200, 451.081, 207.041, 456.521]},
+ {t: 'C', p: [207.041, 456.521, 210.881, 458.121, 209.921, 459.401]},
+ {t: 'C', p: [208.961, 460.681, 209.921, 463.241, 203.52, 461.321]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [210.2, 462.001]},
+ {t: 'C', p: [210.2, 462.001, 205.4, 449.601, 214.6, 456.001]},
+ {t: 'C', p: [214.6, 456.001, 219.4, 458.001, 218.2, 459.601]},
+ {t: 'C', p: [217, 461.201, 218.2, 464.401, 210.2, 462.001]},
+ {t: 'z', p: []}]},
+
+{f: null, s: {c: '#a5264c', w: 2},
+ p: [{t: 'M', p: [181.8, 444.801]},
+ {t: 'C', p: [181.8, 444.801, 195, 442.001, 201, 445.201]},
+ {t: 'C', p: [201, 445.201, 207, 446.401, 208.2, 446.001]},
+ {t: 'C', p: [209.4, 445.601, 212.6, 445.201, 212.6, 445.201]}]},
+
+{f: null, s: {c: '#a5264c', w: 2},
+ p: [{t: 'M', p: [215.8, 453.601]},
+ {t: 'C', p: [215.8, 453.601, 227.8, 440.001, 239.8, 444.401]},
+ {t: 'C', p: [246.816, 446.974, 245.8, 443.601, 246.6, 440.801]},
+ {t: 'C', p: [247.4, 438.001, 247.6, 433.801, 252.6, 430.801]}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [233, 437.601]},
+ {t: 'C', p: [233, 437.601, 229, 426.801, 226.2, 439.601]},
+ {t: 'C', p: [223.4, 452.401, 220.2, 456.001, 218.6, 458.801]},
+ {t: 'C', p: [218.6, 458.801, 218.6, 464.001, 227, 463.601]},
+ {t: 'C', p: [227, 463.601, 237.8, 463.201, 238.2, 460.401]},
+ {t: 'C', p: [238.6, 457.601, 237, 446.001, 233, 437.601]},
+ {t: 'z', p: []}]},
+
+{f: null, s: {c: '#a5264c', w: 2},
+ p: [{t: 'M', p: [247, 444.801]},
+ {t: 'C', p: [247, 444.801, 250.6, 442.401, 253, 443.601]}]},
+
+{f: null, s: {c: '#a5264c', w: 2},
+ p: [{t: 'M', p: [253.5, 428.401]},
+ {t: 'C', p: [253.5, 428.401, 256.4, 423.501, 261.2, 422.701]}]},
+
+{f: '#b2b2b2', s: null, p: [{t: 'M', p: [174.2, 465.201]},
+ {t: 'C', p: [174.2, 465.201, 192.2, 468.401, 196.6, 466.801]},
+ {t: 'C', p: [196.6, 466.801, 205.4, 466.801, 197, 468.801]},
+ {t: 'C', p: [197, 468.801, 184.2, 468.801, 176.2, 467.601]},
+ {t: 'C', p: [176.2, 467.601, 164.6, 462.001, 174.2, 465.201]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [188.2, 372.001]},
+ {t: 'C', p: [188.2, 372.001, 205.8, 372.001, 207.8, 372.801]},
+ {t: 'C', p: [207.8, 372.801, 215, 403.601, 211.4, 411.201]},
+ {t: 'C', p: [211.4, 411.201, 210.2, 414.001, 207.4, 408.401]},
+ {t: 'C', p: [207.4, 408.401, 189, 375.601, 185.8, 373.601]},
+ {t: 'C', p: [182.6, 371.601, 187, 372.001, 188.2, 372.001]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [111.1, 369.301]},
+ {t: 'C', p: [111.1, 369.301, 120, 371.001, 132.6, 373.601]},
+ {t: 'C', p: [132.6, 373.601, 137.4, 396.001, 140.6, 400.801]},
+ {t: 'C', p: [143.8, 405.601, 140.2, 405.601, 136.6, 402.801]},
+ {t: 'C', p: [133, 400.001, 118.2, 386.001, 116.2, 381.601]},
+ {t: 'C', p: [114.2, 377.201, 111.1, 369.301, 111.1, 369.301]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [132.961, 373.818]},
+ {t: 'C', p: [132.961, 373.818, 138.761, 375.366, 139.77, 377.581]},
+ {t: 'C', p: [140.778, 379.795, 138.568, 383.092, 138.568, 383.092]},
+ {t: 'C', p: [138.568, 383.092, 137.568, 386.397, 136.366, 384.235]},
+ {t: 'C', p: [135.164, 382.072, 132.292, 374.412, 132.961, 373.818]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [133, 373.601]},
+ {t: 'C', p: [133, 373.601, 136.6, 378.801, 140.2, 378.801]},
+ {t: 'C', p: [143.8, 378.801, 144.182, 378.388, 147, 379.001]},
+ {t: 'C', p: [151.6, 380.001, 151.2, 378.001, 157.8, 379.201]},
+ {t: 'C', p: [160.44, 379.681, 163, 378.801, 165.8, 380.001]},
+ {t: 'C', p: [168.6, 381.201, 171.8, 380.401, 173, 378.401]},
+ {t: 'C', p: [174.2, 376.401, 179, 372.201, 179, 372.201]},
+ {t: 'C', p: [179, 372.201, 166.2, 374.001, 163.4, 374.801]},
+ {t: 'C', p: [163.4, 374.801, 141, 376.001, 133, 373.601]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [177.6, 373.801]},
+ {t: 'C', p: [177.6, 373.801, 171.15, 377.301, 170.75, 379.701]},
+ {t: 'C', p: [170.35, 382.101, 176, 385.801, 176, 385.801]},
+ {t: 'C', p: [176, 385.801, 178.75, 390.401, 179.35, 388.001]},
+ {t: 'C', p: [179.95, 385.601, 178.4, 374.201, 177.6, 373.801]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [140.115, 379.265]},
+ {t: 'C', p: [140.115, 379.265, 147.122, 390.453, 147.339, 379.242]},
+ {t: 'C', p: [147.339, 379.242, 147.896, 377.984, 146.136, 377.962]},
+ {t: 'C', p: [140.061, 377.886, 141.582, 373.784, 140.115, 379.265]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [147.293, 379.514]},
+ {t: 'C', p: [147.293, 379.514, 155.214, 390.701, 154.578, 379.421]},
+ {t: 'C', p: [154.578, 379.421, 154.585, 379.089, 152.832, 378.936]},
+ {t: 'C', p: [148.085, 378.522, 148.43, 374.004, 147.293, 379.514]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [154.506, 379.522]},
+ {t: 'C', p: [154.506, 379.522, 162.466, 390.15, 161.797, 380.484]},
+ {t: 'C', p: [161.797, 380.484, 161.916, 379.251, 160.262, 378.95]},
+ {t: 'C', p: [156.37, 378.244, 156.159, 374.995, 154.506, 379.522]},
+ {t: 'z', p: []}]},
+
+{f: '#ffc', s: {c: '#000', w: 0.5},
+ p: [{t: 'M', p: [161.382, 379.602]},
+ {t: 'C', p: [161.382, 379.602, 169.282, 391.163, 169.63, 381.382]},
+ {t: 'C', p: [169.63, 381.382, 171.274, 380.004, 169.528, 379.782]},
+ {t: 'C', p: [163.71, 379.042, 164.508, 374.588, 161.382, 379.602]},
+ {t: 'z', p: []}]},
+
+{f: '#e5e5b2', s: null, p: [{t: 'M', p: [125.208, 383.132]},
+ {t: 'L', p: [117.55, 381.601]},
+ {t: 'C', p: [114.95, 376.601, 112.85, 370.451, 112.85, 370.451]},
+ {t: 'C', p: [112.85, 370.451, 119.2, 371.451, 131.7, 374.251]},
+ {t: 'C', p: [131.7, 374.251, 132.576, 377.569, 134.048, 383.364]},
+ {t: 'L', p: [125.208, 383.132]},
+ {t: 'z', p: []}]},
+
+{f: '#e5e5b2', s: null, p: [{t: 'M', p: [190.276, 378.47]},
+ {t: 'C', p: [188.61, 375.964, 187.293, 374.206, 186.643, 373.8]},
+ {t: 'C', p: [183.63, 371.917, 187.773, 372.294, 188.902, 372.294]},
+ {t: 'C', p: [188.902, 372.294, 205.473, 372.294, 207.356, 373.047]},
+ {t: 'C', p: [207.356, 373.047, 207.88, 375.289, 208.564, 378.68]},
+ {t: 'C', p: [208.564, 378.68, 198.476, 376.67, 190.276, 378.47]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [243.88, 240.321]},
+ {t: 'C', p: [271.601, 244.281, 297.121, 208.641, 298.881, 198.96]},
+ {t: 'C', p: [300.641, 189.28, 290.521, 177.4, 290.521, 177.4]},
+ {t: 'C', p: [291.841, 174.32, 287.001, 160.24, 281.721, 151]},
+ {t: 'C', p: [276.441, 141.76, 260.54, 142.734, 243, 141.76]},
+ {t: 'C', p: [227.16, 140.88, 208.68, 164.2, 207.36, 165.96]},
+ {t: 'C', p: [206.04, 167.72, 212.2, 206.001, 213.52, 211.721]},
+ {t: 'C', p: [214.84, 217.441, 212.2, 243.841, 212.2, 243.841]},
+ {t: 'C', p: [246.44, 234.741, 216.16, 236.361, 243.88, 240.321]},
+ {t: 'z', p: []}]},
+
+{f: '#ea8e51', s: null, p: [{t: 'M', p: [208.088, 166.608]},
+ {t: 'C', p: [206.792, 168.336, 212.84, 205.921, 214.136, 211.537]},
+ {t: 'C', p: [215.432, 217.153, 212.84, 243.073, 212.84, 243.073]},
+ {t: 'C', p: [245.512, 234.193, 216.728, 235.729, 243.944, 239.617]},
+ {t: 'C', p: [271.161, 243.505, 296.217, 208.513, 297.945, 199.008]},
+ {t: 'C', p: [299.673, 189.504, 289.737, 177.84, 289.737, 177.84]},
+ {t: 'C', p: [291.033, 174.816, 286.281, 160.992, 281.097, 151.92]},
+ {t: 'C', p: [275.913, 142.848, 260.302, 143.805, 243.08, 142.848]},
+ {t: 'C', p: [227.528, 141.984, 209.384, 164.88, 208.088, 166.608]},
+ {t: 'z', p: []}]},
+
+{f: '#efaa7c', s: null, p: [{t: 'M', p: [208.816, 167.256]},
+ {t: 'C', p: [207.544, 168.952, 213.48, 205.841, 214.752, 211.353]},
+ {t: 'C', p: [216.024, 216.865, 213.48, 242.305, 213.48, 242.305]},
+ {t: 'C', p: [244.884, 233.145, 217.296, 235.097, 244.008, 238.913]},
+ {t: 'C', p: [270.721, 242.729, 295.313, 208.385, 297.009, 199.056]},
+ {t: 'C', p: [298.705, 189.728, 288.953, 178.28, 288.953, 178.28]},
+ {t: 'C', p: [290.225, 175.312, 285.561, 161.744, 280.473, 152.84]},
+ {t: 'C', p: [275.385, 143.936, 260.063, 144.875, 243.16, 143.936]},
+ {t: 'C', p: [227.896, 143.088, 210.088, 165.56, 208.816, 167.256]},
+ {t: 'z', p: []}]},
+
+{f: '#f4c6a8', s: null, p: [{t: 'M', p: [209.544, 167.904]},
+ {t: 'C', p: [208.296, 169.568, 214.12, 205.761, 215.368, 211.169]},
+ {t: 'C', p: [216.616, 216.577, 214.12, 241.537, 214.12, 241.537]},
+ {t: 'C', p: [243.556, 232.497, 217.864, 234.465, 244.072, 238.209]},
+ {t: 'C', p: [270.281, 241.953, 294.409, 208.257, 296.073, 199.105]},
+ {t: 'C', p: [297.737, 189.952, 288.169, 178.72, 288.169, 178.72]},
+ {t: 'C', p: [289.417, 175.808, 284.841, 162.496, 279.849, 153.76]},
+ {t: 'C', p: [274.857, 145.024, 259.824, 145.945, 243.24, 145.024]},
+ {t: 'C', p: [228.264, 144.192, 210.792, 166.24, 209.544, 167.904]},
+ {t: 'z', p: []}]},
+
+{f: '#f9e2d3', s: null, p: [{t: 'M', p: [210.272, 168.552]},
+ {t: 'C', p: [209.048, 170.184, 214.76, 205.681, 215.984, 210.985]},
+ {t: 'C', p: [217.208, 216.289, 214.76, 240.769, 214.76, 240.769]},
+ {t: 'C', p: [242.628, 231.849, 218.432, 233.833, 244.136, 237.505]},
+ {t: 'C', p: [269.841, 241.177, 293.505, 208.129, 295.137, 199.152]},
+ {t: 'C', p: [296.769, 190.176, 287.385, 179.16, 287.385, 179.16]},
+ {t: 'C', p: [288.609, 176.304, 284.121, 163.248, 279.225, 154.68]},
+ {t: 'C', p: [274.329, 146.112, 259.585, 147.015, 243.32, 146.112]},
+ {t: 'C', p: [228.632, 145.296, 211.496, 166.92, 210.272, 168.552]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: null, p: [{t: 'M', p: [244.2, 236.8]},
+ {t: 'C', p: [269.4, 240.4, 292.601, 208, 294.201, 199.2]},
+ {t: 'C', p: [295.801, 190.4, 286.601, 179.6, 286.601, 179.6]},
+ {t: 'C', p: [287.801, 176.8, 283.4, 164, 278.6, 155.6]},
+ {t: 'C', p: [273.8, 147.2, 259.346, 148.086, 243.4, 147.2]},
+ {t: 'C', p: [229, 146.4, 212.2, 167.6, 211, 169.2]},
+ {t: 'C', p: [209.8, 170.8, 215.4, 205.6, 216.6, 210.8]},
+ {t: 'C', p: [217.8, 216, 215.4, 240, 215.4, 240]},
+ {t: 'C', p: [240.9, 231.4, 219, 233.2, 244.2, 236.8]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [290.601, 202.8]},
+ {t: 'C', p: [290.601, 202.8, 262.8, 210.4, 251.2, 208.8]},
+ {t: 'C', p: [251.2, 208.8, 235.4, 202.2, 226.6, 224]},
+ {t: 'C', p: [226.6, 224, 223, 231.2, 221, 233.2]},
+ {t: 'C', p: [219, 235.2, 290.601, 202.8, 290.601, 202.8]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [294.401, 200.6]},
+ {t: 'C', p: [294.401, 200.6, 265.4, 212.8, 255.4, 212.4]},
+ {t: 'C', p: [255.4, 212.4, 239, 207.8, 230.6, 222.4]},
+ {t: 'C', p: [230.6, 222.4, 222.2, 231.6, 219, 233.2]},
+ {t: 'C', p: [219, 233.2, 218.6, 234.8, 225, 230.8]},
+ {t: 'L', p: [235.4, 236]},
+ {t: 'C', p: [235.4, 236, 250.2, 245.6, 259.8, 229.6]},
+ {t: 'C', p: [259.8, 229.6, 263.8, 218.4, 263.8, 216.4]},
+ {t: 'C', p: [263.8, 214.4, 285, 208.8, 286.601, 208.4]},
+ {t: 'C', p: [288.201, 208, 294.801, 203.8, 294.401, 200.6]},
+ {t: 'z', p: []}]},
+
+{f: '#99cc32', s: null, p: [{t: 'M', p: [247, 236.514]},
+ {t: 'C', p: [240.128, 236.514, 231.755, 232.649, 231.755, 226.4]},
+ {t: 'C', p: [231.755, 220.152, 240.128, 213.887, 247, 213.887]},
+ {t: 'C', p: [253.874, 213.887, 259.446, 218.952, 259.446, 225.2]},
+ {t: 'C', p: [259.446, 231.449, 253.874, 236.514, 247, 236.514]},
+ {t: 'z', p: []}]},
+
+{f: '#659900', s: null, p: [{t: 'M', p: [243.377, 219.83]},
+ {t: 'C', p: [238.531, 220.552, 233.442, 222.055, 233.514, 221.839]},
+ {t: 'C', p: [235.054, 217.22, 241.415, 213.887, 247, 213.887]},
+ {t: 'C', p: [251.296, 213.887, 255.084, 215.865, 257.32, 218.875]},
+ {t: 'C', p: [257.32, 218.875, 252.004, 218.545, 243.377, 219.83]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: null, p: [{t: 'M', p: [255.4, 219.6]},
+ {t: 'C', p: [255.4, 219.6, 251, 216.4, 251, 218.6]},
+ {t: 'C', p: [251, 218.6, 254.6, 223, 255.4, 219.6]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [245.4, 227.726]},
+ {t: 'C', p: [242.901, 227.726, 240.875, 225.7, 240.875, 223.2]},
+ {t: 'C', p: [240.875, 220.701, 242.901, 218.675, 245.4, 218.675]},
+ {t: 'C', p: [247.9, 218.675, 249.926, 220.701, 249.926, 223.2]},
+ {t: 'C', p: [249.926, 225.7, 247.9, 227.726, 245.4, 227.726]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [141.4, 214.4]},
+ {t: 'C', p: [141.4, 214.4, 138.2, 193.2, 140.6, 188.8]},
+ {t: 'C', p: [140.6, 188.8, 151.4, 178.8, 151, 175.2]},
+ {t: 'C', p: [151, 175.2, 150.6, 157.2, 149.4, 156.4]},
+ {t: 'C', p: [148.2, 155.6, 140.6, 149.6, 134.6, 156]},
+ {t: 'C', p: [134.6, 156, 124.2, 174, 125, 180.4]},
+ {t: 'L', p: [125, 182.4]},
+ {t: 'C', p: [125, 182.4, 117.4, 182, 115.8, 184]},
+ {t: 'C', p: [115.8, 184, 114.6, 189.2, 113.4, 189.6]},
+ {t: 'C', p: [113.4, 189.6, 110.6, 192, 112.6, 194.8]},
+ {t: 'C', p: [112.6, 194.8, 110.6, 197.2, 111, 201.2]},
+ {t: 'L', p: [118.6, 205.2]},
+ {t: 'C', p: [118.6, 205.2, 120.6, 219.6, 131.4, 224.8]},
+ {t: 'C', p: [136.236, 227.129, 139.4, 220.4, 141.4, 214.4]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: null, p: [{t: 'M', p: [140.4, 212.56]},
+ {t: 'C', p: [140.4, 212.56, 137.52, 193.48, 139.68, 189.52]},
+ {t: 'C', p: [139.68, 189.52, 149.4, 180.52, 149.04, 177.28]},
+ {t: 'C', p: [149.04, 177.28, 148.68, 161.08, 147.6, 160.36]},
+ {t: 'C', p: [146.52, 159.64, 139.68, 154.24, 134.28, 160]},
+ {t: 'C', p: [134.28, 160, 124.92, 176.2, 125.64, 181.96]},
+ {t: 'L', p: [125.64, 183.76]},
+ {t: 'C', p: [125.64, 183.76, 118.8, 183.4, 117.36, 185.2]},
+ {t: 'C', p: [117.36, 185.2, 116.28, 189.88, 115.2, 190.24]},
+ {t: 'C', p: [115.2, 190.24, 112.68, 192.4, 114.48, 194.92]},
+ {t: 'C', p: [114.48, 194.92, 112.68, 197.08, 113.04, 200.68]},
+ {t: 'L', p: [119.88, 204.28]},
+ {t: 'C', p: [119.88, 204.28, 121.68, 217.24, 131.4, 221.92]},
+ {t: 'C', p: [135.752, 224.015, 138.6, 217.96, 140.4, 212.56]},
+ {t: 'z', p: []}]},
+
+{f: '#eb955c', s: null, p: [{t: 'M', p: [148.95, 157.39]},
+ {t: 'C', p: [147.86, 156.53, 140.37, 150.76, 134.52, 157]},
+ {t: 'C', p: [134.52, 157, 124.38, 174.55, 125.16, 180.79]},
+ {t: 'L', p: [125.16, 182.74]},
+ {t: 'C', p: [125.16, 182.74, 117.75, 182.35, 116.19, 184.3]},
+ {t: 'C', p: [116.19, 184.3, 115.02, 189.37, 113.85, 189.76]},
+ {t: 'C', p: [113.85, 189.76, 111.12, 192.1, 113.07, 194.83]},
+ {t: 'C', p: [113.07, 194.83, 111.12, 197.17, 111.51, 201.07]},
+ {t: 'L', p: [118.92, 204.97]},
+ {t: 'C', p: [118.92, 204.97, 120.87, 219.01, 131.4, 224.08]},
+ {t: 'C', p: [136.114, 226.35, 139.2, 219.79, 141.15, 213.94]},
+ {t: 'C', p: [141.15, 213.94, 138.03, 193.27, 140.37, 188.98]},
+ {t: 'C', p: [140.37, 188.98, 150.9, 179.23, 150.51, 175.72]},
+ {t: 'C', p: [150.51, 175.72, 150.12, 158.17, 148.95, 157.39]},
+ {t: 'z', p: []}]},
+
+{f: '#f2b892', s: null, p: [{t: 'M', p: [148.5, 158.38]},
+ {t: 'C', p: [147.52, 157.46, 140.14, 151.92, 134.44, 158]},
+ {t: 'C', p: [134.44, 158, 124.56, 175.1, 125.32, 181.18]},
+ {t: 'L', p: [125.32, 183.08]},
+ {t: 'C', p: [125.32, 183.08, 118.1, 182.7, 116.58, 184.6]},
+ {t: 'C', p: [116.58, 184.6, 115.44, 189.54, 114.3, 189.92]},
+ {t: 'C', p: [114.3, 189.92, 111.64, 192.2, 113.54, 194.86]},
+ {t: 'C', p: [113.54, 194.86, 111.64, 197.14, 112.02, 200.94]},
+ {t: 'L', p: [119.24, 204.74]},
+ {t: 'C', p: [119.24, 204.74, 121.14, 218.42, 131.4, 223.36]},
+ {t: 'C', p: [135.994, 225.572, 139, 219.18, 140.9, 213.48]},
+ {t: 'C', p: [140.9, 213.48, 137.86, 193.34, 140.14, 189.16]},
+ {t: 'C', p: [140.14, 189.16, 150.4, 179.66, 150.02, 176.24]},
+ {t: 'C', p: [150.02, 176.24, 149.64, 159.14, 148.5, 158.38]},
+ {t: 'z', p: []}]},
+
+{f: '#f8dcc8', s: null, p: [{t: 'M', p: [148.05, 159.37]},
+ {t: 'C', p: [147.18, 158.39, 139.91, 153.08, 134.36, 159]},
+ {t: 'C', p: [134.36, 159, 124.74, 175.65, 125.48, 181.57]},
+ {t: 'L', p: [125.48, 183.42]},
+ {t: 'C', p: [125.48, 183.42, 118.45, 183.05, 116.97, 184.9]},
+ {t: 'C', p: [116.97, 184.9, 115.86, 189.71, 114.75, 190.08]},
+ {t: 'C', p: [114.75, 190.08, 112.16, 192.3, 114.01, 194.89]},
+ {t: 'C', p: [114.01, 194.89, 112.16, 197.11, 112.53, 200.81]},
+ {t: 'L', p: [119.56, 204.51]},
+ {t: 'C', p: [119.56, 204.51, 121.41, 217.83, 131.4, 222.64]},
+ {t: 'C', p: [135.873, 224.794, 138.8, 218.57, 140.65, 213.02]},
+ {t: 'C', p: [140.65, 213.02, 137.69, 193.41, 139.91, 189.34]},
+ {t: 'C', p: [139.91, 189.34, 149.9, 180.09, 149.53, 176.76]},
+ {t: 'C', p: [149.53, 176.76, 149.16, 160.11, 148.05, 159.37]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: null, p: [{t: 'M', p: [140.4, 212.46]},
+ {t: 'C', p: [140.4, 212.46, 137.52, 193.48, 139.68, 189.52]},
+ {t: 'C', p: [139.68, 189.52, 149.4, 180.52, 149.04, 177.28]},
+ {t: 'C', p: [149.04, 177.28, 148.68, 161.08, 147.6, 160.36]},
+ {t: 'C', p: [146.84, 159.32, 139.68, 154.24, 134.28, 160]},
+ {t: 'C', p: [134.28, 160, 124.92, 176.2, 125.64, 181.96]},
+ {t: 'L', p: [125.64, 183.76]},
+ {t: 'C', p: [125.64, 183.76, 118.8, 183.4, 117.36, 185.2]},
+ {t: 'C', p: [117.36, 185.2, 116.28, 189.88, 115.2, 190.24]},
+ {t: 'C', p: [115.2, 190.24, 112.68, 192.4, 114.48, 194.92]},
+ {t: 'C', p: [114.48, 194.92, 112.68, 197.08, 113.04, 200.68]},
+ {t: 'L', p: [119.88, 204.28]},
+ {t: 'C', p: [119.88, 204.28, 121.68, 217.24, 131.4, 221.92]},
+ {t: 'C', p: [135.752, 224.015, 138.6, 217.86, 140.4, 212.46]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [137.3, 206.2]},
+ {t: 'C', p: [137.3, 206.2, 115.7, 196, 114.8, 195.2]},
+ {t: 'C', p: [114.8, 195.2, 123.9, 203.4, 124.7, 203.4]},
+ {t: 'C', p: [125.5, 203.4, 137.3, 206.2, 137.3, 206.2]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [120.2, 200]},
+ {t: 'C', p: [120.2, 200, 138.6, 203.6, 138.6, 208]},
+ {t: 'C', p: [138.6, 210.912, 138.357, 224.331, 133, 222.8]},
+ {t: 'C', p: [124.6, 220.4, 128.2, 206, 120.2, 200]},
+ {t: 'z', p: []}]},
+
+{f: '#99cc32', s: null, p: [{t: 'M', p: [128.6, 203.8]},
+ {t: 'C', p: [128.6, 203.8, 137.578, 205.274, 138.6, 208]},
+ {t: 'C', p: [139.2, 209.6, 139.863, 217.908, 134.4, 219]},
+ {t: 'C', p: [129.848, 219.911, 127.618, 209.69, 128.6, 203.8]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [214.595, 246.349]},
+ {t: 'C', p: [214.098, 244.607, 215.409, 244.738, 217.2, 244.2]},
+ {t: 'C', p: [219.2, 243.6, 231.4, 239.8, 232.2, 237.2]},
+ {t: 'C', p: [233, 234.6, 246.2, 239, 246.2, 239]},
+ {t: 'C', p: [248, 239.8, 252.4, 242.4, 252.4, 242.4]},
+ {t: 'C', p: [257.2, 243.6, 263.8, 244, 263.8, 244]},
+ {t: 'C', p: [266.2, 245, 269.6, 247.8, 269.6, 247.8]},
+ {t: 'C', p: [284.2, 258, 296.601, 250.8, 296.601, 250.8]},
+ {t: 'C', p: [316.601, 244.2, 310.601, 227, 310.601, 227]},
+ {t: 'C', p: [307.601, 218, 310.801, 214.6, 310.801, 214.6]},
+ {t: 'C', p: [311.001, 210.8, 318.201, 217.2, 318.201, 217.2]},
+ {t: 'C', p: [320.801, 221.4, 321.601, 226.4, 321.601, 226.4]},
+ {t: 'C', p: [329.601, 237.6, 326.201, 219.8, 326.201, 219.8]},
+ {t: 'C', p: [326.401, 218.8, 323.601, 215.2, 323.601, 214]},
+ {t: 'C', p: [323.601, 212.8, 321.801, 209.4, 321.801, 209.4]},
+ {t: 'C', p: [318.801, 206, 321.201, 199, 321.201, 199]},
+ {t: 'C', p: [323.001, 185.2, 320.801, 187, 320.801, 187]},
+ {t: 'C', p: [319.601, 185.2, 310.401, 195.2, 310.401, 195.2]},
+ {t: 'C', p: [308.201, 198.6, 302.201, 200.2, 302.201, 200.2]},
+ {t: 'C', p: [299.401, 202, 296.001, 200.6, 296.001, 200.6]},
+ {t: 'C', p: [293.401, 200.2, 287.801, 207.2, 287.801, 207.2]},
+ {t: 'C', p: [290.601, 207, 293.001, 211.4, 295.401, 211.6]},
+ {t: 'C', p: [297.801, 211.8, 299.601, 209.2, 301.201, 208.6]},
+ {t: 'C', p: [302.801, 208, 305.601, 213.8, 305.601, 213.8]},
+ {t: 'C', p: [306.001, 216.4, 300.401, 221.2, 300.401, 221.2]},
+ {t: 'C', p: [300.001, 225.8, 298.401, 224.2, 298.401, 224.2]},
+ {t: 'C', p: [295.401, 223.6, 294.201, 227.4, 293.201, 232]},
+ {t: 'C', p: [292.201, 236.6, 288.001, 237, 288.001, 237]},
+ {t: 'C', p: [286.401, 244.4, 285.2, 241.4, 285.2, 241.4]},
+ {t: 'C', p: [285, 235.8, 279, 241.6, 279, 241.6]},
+ {t: 'C', p: [277.8, 243.6, 273.2, 241.4, 273.2, 241.4]},
+ {t: 'C', p: [266.4, 239.4, 268.8, 237.4, 268.8, 237.4]},
+ {t: 'C', p: [270.6, 235.2, 281.8, 237.4, 281.8, 237.4]},
+ {t: 'C', p: [284, 235.8, 276, 231.8, 276, 231.8]},
+ {t: 'C', p: [275.4, 230, 276.4, 225.6, 276.4, 225.6]},
+ {t: 'C', p: [277.6, 222.4, 284.4, 216.8, 284.4, 216.8]},
+ {t: 'C', p: [293.801, 215.6, 291.001, 214, 291.001, 214]},
+ {t: 'C', p: [284.801, 208.8, 279, 216.4, 279, 216.4]},
+ {t: 'C', p: [276.8, 222.6, 259.4, 237.6, 259.4, 237.6]},
+ {t: 'C', p: [254.6, 241, 257.2, 234.2, 253.2, 237.6]},
+ {t: 'C', p: [249.2, 241, 228.6, 232, 228.6, 232]},
+ {t: 'C', p: [217.038, 230.807, 214.306, 246.549, 210.777, 243.429]},
+ {t: 'C', p: [210.777, 243.429, 216.195, 251.949, 214.595, 246.349]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [409.401, 80]},
+ {t: 'C', p: [409.401, 80, 383.801, 88, 381.001, 106.8]},
+ {t: 'C', p: [381.001, 106.8, 378.601, 129.6, 399.001, 147.2]},
+ {t: 'C', p: [399.001, 147.2, 399.401, 153.6, 401.401, 156.8]},
+ {t: 'C', p: [401.401, 156.8, 399.801, 161.6, 418.601, 154]},
+ {t: 'L', p: [445.801, 145.6]},
+ {t: 'C', p: [445.801, 145.6, 452.201, 143.2, 457.401, 134.4]},
+ {t: 'C', p: [462.601, 125.6, 477.801, 106.8, 474.201, 81.6]},
+ {t: 'C', p: [474.201, 81.6, 475.401, 70.4, 469.401, 70]},
+ {t: 'C', p: [469.401, 70, 461.001, 68.4, 453.801, 76]},
+ {t: 'C', p: [453.801, 76, 447.001, 79.2, 444.601, 78.8]},
+ {t: 'L', p: [409.401, 80]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [464.022, 79.01]},
+ {t: 'C', p: [464.022, 79.01, 466.122, 70.08, 461.282, 74.92]},
+ {t: 'C', p: [461.282, 74.92, 454.242, 80.64, 446.761, 80.64]},
+ {t: 'C', p: [446.761, 80.64, 432.241, 82.84, 427.841, 96.04]},
+ {t: 'C', p: [427.841, 96.04, 423.881, 122.88, 431.801, 128.6]},
+ {t: 'C', p: [431.801, 128.6, 436.641, 136.08, 443.681, 129.48]},
+ {t: 'C', p: [450.722, 122.88, 466.222, 92.65, 464.022, 79.01]},
+ {t: 'z', p: []}]},
+
+{f: '#323232', s: null, p: [{t: 'M', p: [463.648, 79.368]},
+ {t: 'C', p: [463.648, 79.368, 465.738, 70.624, 460.986, 75.376]},
+ {t: 'C', p: [460.986, 75.376, 454.074, 80.992, 446.729, 80.992]},
+ {t: 'C', p: [446.729, 80.992, 432.473, 83.152, 428.153, 96.112]},
+ {t: 'C', p: [428.153, 96.112, 424.265, 122.464, 432.041, 128.08]},
+ {t: 'C', p: [432.041, 128.08, 436.793, 135.424, 443.705, 128.944]},
+ {t: 'C', p: [450.618, 122.464, 465.808, 92.76, 463.648, 79.368]},
+ {t: 'z', p: []}]},
+
+{f: '#666', s: null, p: [{t: 'M', p: [463.274, 79.726]},
+ {t: 'C', p: [463.274, 79.726, 465.354, 71.168, 460.69, 75.832]},
+ {t: 'C', p: [460.69, 75.832, 453.906, 81.344, 446.697, 81.344]},
+ {t: 'C', p: [446.697, 81.344, 432.705, 83.464, 428.465, 96.184]},
+ {t: 'C', p: [428.465, 96.184, 424.649, 122.048, 432.281, 127.56]},
+ {t: 'C', p: [432.281, 127.56, 436.945, 134.768, 443.729, 128.408]},
+ {t: 'C', p: [450.514, 122.048, 465.394, 92.87, 463.274, 79.726]},
+ {t: 'z', p: []}]},
+
+{f: '#999', s: null, p: [{t: 'M', p: [462.9, 80.084]},
+ {t: 'C', p: [462.9, 80.084, 464.97, 71.712, 460.394, 76.288]},
+ {t: 'C', p: [460.394, 76.288, 453.738, 81.696, 446.665, 81.696]},
+ {t: 'C', p: [446.665, 81.696, 432.937, 83.776, 428.777, 96.256]},
+ {t: 'C', p: [428.777, 96.256, 425.033, 121.632, 432.521, 127.04]},
+ {t: 'C', p: [432.521, 127.04, 437.097, 134.112, 443.753, 127.872]},
+ {t: 'C', p: [450.41, 121.632, 464.98, 92.98, 462.9, 80.084]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [462.526, 80.442]},
+ {t: 'C', p: [462.526, 80.442, 464.586, 72.256, 460.098, 76.744]},
+ {t: 'C', p: [460.098, 76.744, 453.569, 82.048, 446.633, 82.048]},
+ {t: 'C', p: [446.633, 82.048, 433.169, 84.088, 429.089, 96.328]},
+ {t: 'C', p: [429.089, 96.328, 425.417, 121.216, 432.761, 126.52]},
+ {t: 'C', p: [432.761, 126.52, 437.249, 133.456, 443.777, 127.336]},
+ {t: 'C', p: [450.305, 121.216, 464.566, 93.09, 462.526, 80.442]},
+ {t: 'z', p: []}]},
+
+{f: '#fff', s: null, p: [{t: 'M', p: [462.151, 80.8]},
+ {t: 'C', p: [462.151, 80.8, 464.201, 72.8, 459.801, 77.2]},
+ {t: 'C', p: [459.801, 77.2, 453.401, 82.4, 446.601, 82.4]},
+ {t: 'C', p: [446.601, 82.4, 433.401, 84.4, 429.401, 96.4]},
+ {t: 'C', p: [429.401, 96.4, 425.801, 120.8, 433.001, 126]},
+ {t: 'C', p: [433.001, 126, 437.401, 132.8, 443.801, 126.8]},
+ {t: 'C', p: [450.201, 120.8, 464.151, 93.2, 462.151, 80.8]},
+ {t: 'z', p: []}]},
+
+{f: '#992600', s: null, p: [{t: 'M', p: [250.6, 284]},
+ {t: 'C', p: [250.6, 284, 230.2, 264.8, 222.2, 264]},
+ {t: 'C', p: [222.2, 264, 187.8, 260, 173, 278]},
+ {t: 'C', p: [173, 278, 190.6, 257.6, 218.2, 263.2]},
+ {t: 'C', p: [218.2, 263.2, 196.6, 258.8, 184.2, 262]},
+ {t: 'C', p: [184.2, 262, 167.4, 262, 157.8, 276]},
+ {t: 'L', p: [155, 280.8]},
+ {t: 'C', p: [155, 280.8, 159, 266, 177.4, 260]},
+ {t: 'C', p: [177.4, 260, 200.2, 255.2, 211, 260]},
+ {t: 'C', p: [211, 260, 189.4, 253.2, 179.4, 255.2]},
+ {t: 'C', p: [179.4, 255.2, 149, 252.8, 136.2, 279.2]},
+ {t: 'C', p: [136.2, 279.2, 140.2, 264.8, 155, 257.6]},
+ {t: 'C', p: [155, 257.6, 168.6, 248.8, 189, 251.6]},
+ {t: 'C', p: [189, 251.6, 203.4, 254.8, 208.6, 257.2]},
+ {t: 'C', p: [213.8, 259.6, 212.6, 256.8, 204.2, 252]},
+ {t: 'C', p: [204.2, 252, 198.6, 242, 184.6, 242.4]},
+ {t: 'C', p: [184.6, 242.4, 141.8, 246, 131.4, 258]},
+ {t: 'C', p: [131.4, 258, 145, 246.8, 155.4, 244]},
+ {t: 'C', p: [155.4, 244, 177.8, 236, 186.2, 236.8]},
+ {t: 'C', p: [186.2, 236.8, 211, 237.8, 218.6, 233.8]},
+ {t: 'C', p: [218.6, 233.8, 207.4, 238.8, 210.6, 242]},
+ {t: 'C', p: [213.8, 245.2, 220.6, 252.8, 220.6, 254]},
+ {t: 'C', p: [220.6, 255.2, 244.8, 277.3, 248.4, 281.7]},
+ {t: 'L', p: [250.6, 284]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [389, 478]},
+ {t: 'C', p: [389, 478, 373.5, 441.5, 361, 432]},
+ {t: 'C', p: [361, 432, 387, 448, 390.5, 466]},
+ {t: 'C', p: [390.5, 466, 390.5, 476, 389, 478]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [436, 485.5]},
+ {t: 'C', p: [436, 485.5, 409.5, 430.5, 391, 406.5]},
+ {t: 'C', p: [391, 406.5, 434.5, 444, 439.5, 470.5]},
+ {t: 'L', p: [440, 476]},
+ {t: 'L', p: [437, 473.5]},
+ {t: 'C', p: [437, 473.5, 436.5, 482.5, 436, 485.5]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [492.5, 437]},
+ {t: 'C', p: [492.5, 437, 430, 377.5, 428.5, 375]},
+ {t: 'C', p: [428.5, 375, 489, 441, 492, 448.5]},
+ {t: 'C', p: [492, 448.5, 490, 439.5, 492.5, 437]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [304, 480.5]},
+ {t: 'C', p: [304, 480.5, 323.5, 428.5, 342.5, 451]},
+ {t: 'C', p: [342.5, 451, 357.5, 461, 357, 464]},
+ {t: 'C', p: [357, 464, 353, 457.5, 335, 458]},
+ {t: 'C', p: [335, 458, 316, 455, 304, 480.5]},
+ {t: 'z', p: []}]},
+
+{f: '#ccc', s: null, p: [{t: 'M', p: [494.5, 353]},
+ {t: 'C', p: [494.5, 353, 449.5, 324.5, 442, 323]},
+ {t: 'C', p: [430.193, 320.639, 491.5, 352, 496.5, 362.5]},
+ {t: 'C', p: [496.5, 362.5, 498.5, 360, 494.5, 353]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [343.801, 459.601]},
+ {t: 'C', p: [343.801, 459.601, 364.201, 457.601, 371.001, 450.801]},
+ {t: 'L', p: [375.401, 454.401]},
+ {t: 'L', p: [393.001, 416.001]},
+ {t: 'L', p: [396.601, 421.201]},
+ {t: 'C', p: [396.601, 421.201, 411.001, 406.401, 410.201, 398.401]},
+ {t: 'C', p: [409.401, 390.401, 423.001, 404.401, 423.001, 404.401]},
+ {t: 'C', p: [423.001, 404.401, 422.201, 392.801, 429.401, 399.601]},
+ {t: 'C', p: [429.401, 399.601, 427.001, 384.001, 435.401, 392.001]},
+ {t: 'C', p: [435.401, 392.001, 424.864, 361.844, 447.401, 387.601]},
+ {t: 'C', p: [453.001, 394.001, 448.601, 387.201, 448.601, 387.201]},
+ {t: 'C', p: [448.601, 387.201, 422.601, 339.201, 444.201, 353.601]},
+ {t: 'C', p: [444.201, 353.601, 446.201, 330.801, 445.001, 326.401]},
+ {t: 'C', p: [443.801, 322.001, 441.801, 299.6, 437.001, 294.4]},
+ {t: 'C', p: [432.201, 289.2, 437.401, 287.6, 443.001, 292.8]},
+ {t: 'C', p: [443.001, 292.8, 431.801, 268.8, 445.001, 280.8]},
+ {t: 'C', p: [445.001, 280.8, 441.401, 265.6, 437.001, 262.8]},
+ {t: 'C', p: [437.001, 262.8, 431.401, 245.6, 446.601, 256.4]},
+ {t: 'C', p: [446.601, 256.4, 442.201, 244, 439.001, 240.8]},
+ {t: 'C', p: [439.001, 240.8, 427.401, 213.2, 434.601, 218]},
+ {t: 'L', p: [439.001, 221.6]},
+ {t: 'C', p: [439.001, 221.6, 432.201, 207.6, 438.601, 212]},
+ {t: 'C', p: [445.001, 216.4, 445.001, 216, 445.001, 216]},
+ {t: 'C', p: [445.001, 216, 423.801, 182.8, 444.201, 200.4]},
+ {t: 'C', p: [444.201, 200.4, 436.042, 186.482, 432.601, 179.6]},
+ {t: 'C', p: [432.601, 179.6, 413.801, 159.2, 428.201, 165.6]},
+ {t: 'L', p: [433.001, 167.2]},
+ {t: 'C', p: [433.001, 167.2, 424.201, 157.2, 416.201, 155.6]},
+ {t: 'C', p: [408.201, 154, 418.601, 147.6, 425.001, 149.6]},
+ {t: 'C', p: [431.401, 151.6, 447.001, 159.2, 447.001, 159.2]},
+ {t: 'C', p: [447.001, 159.2, 459.801, 178, 463.801, 178.4]},
+ {t: 'C', p: [463.801, 178.4, 443.801, 170.8, 449.801, 178.8]},
+ {t: 'C', p: [449.801, 178.8, 464.201, 192.8, 457.001, 192.4]},
+ {t: 'C', p: [457.001, 192.4, 451.001, 199.6, 455.801, 208.4]},
+ {t: 'C', p: [455.801, 208.4, 437.342, 190.009, 452.201, 215.6]},
+ {t: 'L', p: [459.001, 232]},
+ {t: 'C', p: [459.001, 232, 434.601, 207.2, 445.801, 229.2]},
+ {t: 'C', p: [445.801, 229.2, 463.001, 252.8, 465.001, 253.2]},
+ {t: 'C', p: [467.001, 253.6, 471.401, 262.4, 471.401, 262.4]},
+ {t: 'L', p: [467.001, 260.4]},
+ {t: 'L', p: [472.201, 269.2]},
+ {t: 'C', p: [472.201, 269.2, 461.001, 257.2, 467.001, 270.4]},
+ {t: 'L', p: [472.601, 284.8]},
+ {t: 'C', p: [472.601, 284.8, 452.201, 262.8, 465.801, 292.4]},
+ {t: 'C', p: [465.801, 292.4, 449.401, 287.2, 458.201, 304.4]},
+ {t: 'C', p: [458.201, 304.4, 456.601, 320.401, 457.001, 325.601]},
+ {t: 'C', p: [457.401, 330.801, 458.601, 359.201, 454.201, 367.201]},
+ {t: 'C', p: [449.801, 375.201, 460.201, 394.401, 462.201, 398.401]},
+ {t: 'C', p: [464.201, 402.401, 467.801, 413.201, 459.001, 404.001]},
+ {t: 'C', p: [450.201, 394.801, 454.601, 400.401, 456.601, 409.201]},
+ {t: 'C', p: [458.601, 418.001, 464.601, 433.601, 463.801, 439.201]},
+ {t: 'C', p: [463.801, 439.201, 462.601, 440.401, 459.401, 436.801]},
+ {t: 'C', p: [459.401, 436.801, 444.601, 414.001, 446.201, 428.401]},
+ {t: 'C', p: [446.201, 428.401, 445.001, 436.401, 441.801, 445.201]},
+ {t: 'C', p: [441.801, 445.201, 438.601, 456.001, 438.601, 447.201]},
+ {t: 'C', p: [438.601, 447.201, 435.401, 430.401, 432.601, 438.001]},
+ {t: 'C', p: [429.801, 445.601, 426.201, 451.601, 423.401, 454.001]},
+ {t: 'C', p: [420.601, 456.401, 415.401, 433.601, 414.201, 444.001]},
+ {t: 'C', p: [414.201, 444.001, 402.201, 431.601, 397.401, 448.001]},
+ {t: 'L', p: [385.801, 464.401]},
+ {t: 'C', p: [385.801, 464.401, 385.401, 452.001, 384.201, 458.001]},
+ {t: 'C', p: [384.201, 458.001, 354.201, 464.001, 343.801, 459.601]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [309.401, 102.8]},
+ {t: 'C', p: [309.401, 102.8, 297.801, 94.8, 293.801, 95.2]},
+ {t: 'C', p: [289.801, 95.6, 321.401, 86.4, 362.601, 114]},
+ {t: 'C', p: [362.601, 114, 367.401, 116.8, 371.001, 116.4]},
+ {t: 'C', p: [371.001, 116.4, 374.201, 118.8, 371.401, 122.4]},
+ {t: 'C', p: [371.401, 122.4, 362.601, 132, 373.801, 143.2]},
+ {t: 'C', p: [373.801, 143.2, 392.201, 150, 386.601, 141.2]},
+ {t: 'C', p: [386.601, 141.2, 397.401, 145.2, 399.801, 149.2]},
+ {t: 'C', p: [402.201, 153.2, 401.001, 149.2, 401.001, 149.2]},
+ {t: 'C', p: [401.001, 149.2, 394.601, 142, 388.601, 136.8]},
+ {t: 'C', p: [388.601, 136.8, 383.401, 134.8, 380.601, 126.4]},
+ {t: 'C', p: [377.801, 118, 375.401, 108, 379.801, 104.8]},
+ {t: 'C', p: [379.801, 104.8, 375.801, 109.2, 376.601, 105.2]},
+ {t: 'C', p: [377.401, 101.2, 381.001, 97.6, 382.601, 97.2]},
+ {t: 'C', p: [384.201, 96.8, 400.601, 81, 407.401, 80.6]},
+ {t: 'C', p: [407.401, 80.6, 398.201, 82, 395.201, 81]},
+ {t: 'C', p: [392.201, 80, 365.601, 68.6, 359.601, 67.4]},
+ {t: 'C', p: [359.601, 67.4, 342.801, 60.8, 354.801, 62.8]},
+ {t: 'C', p: [354.801, 62.8, 390.601, 66.6, 408.801, 79.8]},
+ {t: 'C', p: [408.801, 79.8, 401.601, 71.4, 383.201, 64.4]},
+ {t: 'C', p: [383.201, 64.4, 361.001, 51.8, 325.801, 56.8]},
+ {t: 'C', p: [325.801, 56.8, 308.001, 60, 300.201, 61.8]},
+ {t: 'C', p: [300.201, 61.8, 297.601, 61.2, 297.001, 60.8]},
+ {t: 'C', p: [296.401, 60.4, 284.6, 51.4, 257, 58.4]},
+ {t: 'C', p: [257, 58.4, 240, 63, 231.4, 67.8]},
+ {t: 'C', p: [231.4, 67.8, 216.2, 69, 212.6, 72.2]},
+ {t: 'C', p: [212.6, 72.2, 194, 86.8, 192, 87.6]},
+ {t: 'C', p: [190, 88.4, 178.6, 96, 177.8, 96.4]},
+ {t: 'C', p: [177.8, 96.4, 202.4, 89.8, 204.8, 87.4]},
+ {t: 'C', p: [207.2, 85, 224.6, 82.4, 227, 83.8]},
+ {t: 'C', p: [229.4, 85.2, 237.8, 84.6, 228.2, 85.2]},
+ {t: 'C', p: [228.2, 85.2, 303.801, 100, 304.601, 102]},
+ {t: 'C', p: [305.401, 104, 309.401, 102.8, 309.401, 102.8]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [380.801, 93.6]},
+ {t: 'C', p: [380.801, 93.6, 370.601, 86.2, 368.601, 86.2]},
+ {t: 'C', p: [366.601, 86.2, 354.201, 76, 350.001, 76.4]},
+ {t: 'C', p: [345.801, 76.8, 333.601, 66.8, 306.201, 75]},
+ {t: 'C', p: [306.201, 75, 305.601, 73, 309.201, 72.2]},
+ {t: 'C', p: [309.201, 72.2, 315.601, 70, 316.001, 69.4]},
+ {t: 'C', p: [316.001, 69.4, 336.201, 65.2, 343.401, 68.8]},
+ {t: 'C', p: [343.401, 68.8, 352.601, 71.4, 358.801, 77.6]},
+ {t: 'C', p: [358.801, 77.6, 370.001, 80.8, 373.201, 79.8]},
+ {t: 'C', p: [373.201, 79.8, 382.001, 82, 382.401, 83.8]},
+ {t: 'C', p: [382.401, 83.8, 388.201, 86.8, 386.401, 89.4]},
+ {t: 'C', p: [386.401, 89.4, 386.801, 91, 380.801, 93.6]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [368.33, 91.491]},
+ {t: 'C', p: [369.137, 92.123, 370.156, 92.221, 370.761, 93.03]},
+ {t: 'C', p: [370.995, 93.344, 370.706, 93.67, 370.391, 93.767]},
+ {t: 'C', p: [369.348, 94.084, 368.292, 93.514, 367.15, 94.102]},
+ {t: 'C', p: [366.748, 94.309, 366.106, 94.127, 365.553, 93.978]},
+ {t: 'C', p: [363.921, 93.537, 362.092, 93.512, 360.401, 94.2]},
+ {t: 'C', p: [358.416, 93.071, 356.056, 93.655, 353.975, 92.654]},
+ {t: 'C', p: [353.917, 92.627, 353.695, 92.973, 353.621, 92.946]},
+ {t: 'C', p: [350.575, 91.801, 346.832, 92.084, 344.401, 89.8]},
+ {t: 'C', p: [341.973, 89.388, 339.616, 88.926, 337.188, 88.246]},
+ {t: 'C', p: [335.37, 87.737, 333.961, 86.748, 332.341, 85.916]},
+ {t: 'C', p: [330.964, 85.208, 329.507, 84.686, 327.973, 84.314]},
+ {t: 'C', p: [326.11, 83.862, 324.279, 83.974, 322.386, 83.454]},
+ {t: 'C', p: [322.293, 83.429, 322.101, 83.773, 322.019, 83.746]},
+ {t: 'C', p: [321.695, 83.638, 321.405, 83.055, 321.234, 83.108]},
+ {t: 'C', p: [319.553, 83.63, 318.065, 82.658, 316.401, 83]},
+ {t: 'C', p: [315.223, 81.776, 313.495, 82.021, 311.949, 81.579]},
+ {t: 'C', p: [308.985, 80.731, 305.831, 82.001, 302.801, 81]},
+ {t: 'C', p: [306.914, 79.158, 311.601, 80.39, 315.663, 78.321]},
+ {t: 'C', p: [317.991, 77.135, 320.653, 78.237, 323.223, 77.477]},
+ {t: 'C', p: [323.71, 77.333, 324.401, 77.131, 324.801, 77.8]},
+ {t: 'C', p: [324.935, 77.665, 325.117, 77.426, 325.175, 77.454]},
+ {t: 'C', p: [327.625, 78.611, 329.94, 79.885, 332.422, 80.951]},
+ {t: 'C', p: [332.763, 81.097, 333.295, 80.865, 333.547, 81.067]},
+ {t: 'C', p: [335.067, 82.283, 337.01, 82.18, 338.401, 83.4]},
+ {t: 'C', p: [340.099, 82.898, 341.892, 83.278, 343.621, 82.654]},
+ {t: 'C', p: [343.698, 82.627, 343.932, 82.968, 343.965, 82.946]},
+ {t: 'C', p: [345.095, 82.198, 346.25, 82.469, 347.142, 82.773]},
+ {t: 'C', p: [347.48, 82.888, 348.143, 83.135, 348.448, 83.209]},
+ {t: 'C', p: [349.574, 83.485, 350.43, 83.965, 351.609, 84.148]},
+ {t: 'C', p: [351.723, 84.166, 351.908, 83.826, 351.98, 83.854]},
+ {t: 'C', p: [353.103, 84.292, 354.145, 84.236, 354.801, 85.4]},
+ {t: 'C', p: [354.936, 85.265, 355.101, 85.027, 355.183, 85.054]},
+ {t: 'C', p: [356.21, 85.392, 356.859, 86.147, 357.96, 86.388]},
+ {t: 'C', p: [358.445, 86.494, 359.057, 87.12, 359.633, 87.296]},
+ {t: 'C', p: [362.025, 88.027, 363.868, 89.556, 366.062, 90.451]},
+ {t: 'C', p: [366.821, 90.761, 367.697, 90.995, 368.33, 91.491]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [291.696, 77.261]},
+ {t: 'C', p: [289.178, 75.536, 286.81, 74.43, 284.368, 72.644]},
+ {t: 'C', p: [284.187, 72.511, 283.827, 72.681, 283.625, 72.559]},
+ {t: 'C', p: [282.618, 71.95, 281.73, 71.369, 280.748, 70.673]},
+ {t: 'C', p: [280.209, 70.291, 279.388, 70.302, 278.88, 70.044]},
+ {t: 'C', p: [276.336, 68.752, 273.707, 68.194, 271.2, 67]},
+ {t: 'C', p: [271.882, 66.362, 273.004, 66.606, 273.6, 65.8]},
+ {t: 'C', p: [273.795, 66.08, 274.033, 66.364, 274.386, 66.173]},
+ {t: 'C', p: [276.064, 65.269, 277.914, 65.116, 279.59, 65.206]},
+ {t: 'C', p: [281.294, 65.298, 283.014, 65.603, 284.789, 65.875]},
+ {t: 'C', p: [285.096, 65.922, 285.295, 66.445, 285.618, 66.542]},
+ {t: 'C', p: [287.846, 67.205, 290.235, 66.68, 292.354, 67.518]},
+ {t: 'C', p: [293.945, 68.147, 295.515, 68.97, 296.754, 70.245]},
+ {t: 'C', p: [297.006, 70.505, 296.681, 70.806, 296.401, 71]},
+ {t: 'C', p: [296.789, 70.891, 297.062, 71.097, 297.173, 71.41]},
+ {t: 'C', p: [297.257, 71.649, 297.257, 71.951, 297.173, 72.19]},
+ {t: 'C', p: [297.061, 72.502, 296.782, 72.603, 296.408, 72.654]},
+ {t: 'C', p: [295.001, 72.844, 296.773, 71.464, 296.073, 71.912]},
+ {t: 'C', p: [294.8, 72.726, 295.546, 74.132, 294.801, 75.4]},
+ {t: 'C', p: [294.521, 75.206, 294.291, 74.988, 294.401, 74.6]},
+ {t: 'C', p: [294.635, 75.122, 294.033, 75.412, 293.865, 75.728]},
+ {t: 'C', p: [293.48, 76.453, 292.581, 77.868, 291.696, 77.261]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [259.198, 84.609]},
+ {t: 'C', p: [256.044, 83.815, 252.994, 83.93, 249.978, 82.654]},
+ {t: 'C', p: [249.911, 82.626, 249.688, 82.973, 249.624, 82.946]},
+ {t: 'C', p: [248.258, 82.352, 247.34, 81.386, 246.264, 80.34]},
+ {t: 'C', p: [245.351, 79.452, 243.693, 79.839, 242.419, 79.352]},
+ {t: 'C', p: [242.095, 79.228, 241.892, 78.716, 241.591, 78.677]},
+ {t: 'C', p: [240.372, 78.52, 239.445, 77.571, 238.4, 77]},
+ {t: 'C', p: [240.736, 76.205, 243.147, 76.236, 245.609, 75.852]},
+ {t: 'C', p: [245.722, 75.834, 245.867, 76.155, 246, 76.155]},
+ {t: 'C', p: [246.136, 76.155, 246.266, 75.934, 246.4, 75.8]},
+ {t: 'C', p: [246.595, 76.08, 246.897, 76.406, 247.154, 76.152]},
+ {t: 'C', p: [247.702, 75.612, 248.258, 75.802, 248.798, 75.842]},
+ {t: 'C', p: [248.942, 75.852, 249.067, 76.155, 249.2, 76.155]},
+ {t: 'C', p: [249.336, 76.155, 249.467, 75.844, 249.6, 75.844]},
+ {t: 'C', p: [249.736, 75.845, 249.867, 76.155, 250, 76.155]},
+ {t: 'C', p: [250.136, 76.155, 250.266, 75.934, 250.4, 75.8]},
+ {t: 'C', p: [251.092, 76.582, 251.977, 76.028, 252.799, 76.207]},
+ {t: 'C', p: [253.837, 76.434, 254.104, 77.582, 255.178, 77.88]},
+ {t: 'C', p: [259.893, 79.184, 264.03, 81.329, 268.393, 83.416]},
+ {t: 'C', p: [268.7, 83.563, 268.91, 83.811, 268.8, 84.2]},
+ {t: 'C', p: [269.067, 84.2, 269.38, 84.112, 269.57, 84.244]},
+ {t: 'C', p: [270.628, 84.976, 271.669, 85.524, 272.366, 86.622]},
+ {t: 'C', p: [272.582, 86.961, 272.253, 87.368, 272.02, 87.316]},
+ {t: 'C', p: [267.591, 86.321, 263.585, 85.713, 259.198, 84.609]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [245.338, 128.821]},
+ {t: 'C', p: [243.746, 127.602, 243.162, 125.571, 242.034, 123.779]},
+ {t: 'C', p: [241.82, 123.439, 242.094, 123.125, 242.411, 123.036]},
+ {t: 'C', p: [242.971, 122.877, 243.514, 123.355, 243.923, 123.557]},
+ {t: 'C', p: [245.668, 124.419, 247.203, 125.661, 249.2, 125.8]},
+ {t: 'C', p: [251.19, 128.034, 255.45, 128.419, 255.457, 131.8]},
+ {t: 'C', p: [255.458, 132.659, 254.03, 131.741, 253.6, 132.6]},
+ {t: 'C', p: [251.149, 131.597, 248.76, 131.7, 246.38, 130.233]},
+ {t: 'C', p: [245.763, 129.852, 246.093, 129.399, 245.338, 128.821]},
+ {t: 'z', p: []}]},
+
+{f: '#cc7226', s: null, p: [{t: 'M', p: [217.8, 76.244]},
+ {t: 'C', p: [217.935, 76.245, 224.966, 76.478, 224.949, 76.592]},
+ {t: 'C', p: [224.904, 76.901, 217.174, 77.95, 216.81, 77.78]},
+ {t: 'C', p: [216.646, 77.704, 209.134, 80.134, 209, 80]},
+ {t: 'C', p: [209.268, 79.865, 217.534, 76.244, 217.8, 76.244]},
+ {t: 'z', p: []}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [233.2, 86]},
+ {t: 'C', p: [233.2, 86, 218.4, 87.8, 214, 89]},
+ {t: 'C', p: [209.6, 90.2, 191, 97.8, 188, 99.8]},
+ {t: 'C', p: [188, 99.8, 174.6, 105.2, 157.6, 125.2]},
+ {t: 'C', p: [157.6, 125.2, 165.2, 121.8, 167.4, 119]},
+ {t: 'C', p: [167.4, 119, 181, 106.4, 180.8, 109]},
+ {t: 'C', p: [180.8, 109, 193, 100.4, 192.4, 102.6]},
+ {t: 'C', p: [192.4, 102.6, 216.8, 91.4, 214.8, 94.6]},
+ {t: 'C', p: [214.8, 94.6, 236.4, 90, 235.4, 92]},
+ {t: 'C', p: [235.4, 92, 254.2, 96.4, 251.4, 96.6]},
+ {t: 'C', p: [251.4, 96.6, 245.6, 97.8, 252, 101.4]},
+ {t: 'C', p: [252, 101.4, 248.6, 105.8, 243.2, 101.8]},
+ {t: 'C', p: [237.8, 97.8, 240.8, 100, 235.8, 101]},
+ {t: 'C', p: [235.8, 101, 233.2, 101.8, 228.6, 97.8]},
+ {t: 'C', p: [228.6, 97.8, 223, 93.2, 214.2, 96.8]},
+ {t: 'C', p: [214.2, 96.8, 183.6, 109.4, 181.6, 110]},
+ {t: 'C', p: [181.6, 110, 178, 112.8, 175.6, 116.4]},
+ {t: 'C', p: [175.6, 116.4, 169.8, 120.8, 166.8, 122.2]},
+ {t: 'C', p: [166.8, 122.2, 154, 133.8, 152.8, 135.2]},
+ {t: 'C', p: [152.8, 135.2, 149.4, 140.4, 148.6, 140.8]},
+ {t: 'C', p: [148.6, 140.8, 155, 137, 157, 135]},
+ {t: 'C', p: [157, 135, 171, 125, 176.4, 124.2]},
+ {t: 'C', p: [176.4, 124.2, 180.8, 121.2, 181.6, 119.8]},
+ {t: 'C', p: [181.6, 119.8, 196, 110.6, 200.2, 110.6]},
+ {t: 'C', p: [200.2, 110.6, 209.4, 115.8, 211.8, 108.8]},
+ {t: 'C', p: [211.8, 108.8, 217.6, 107, 223.2, 108.2]},
+ {t: 'C', p: [223.2, 108.2, 226.4, 105.6, 225.6, 103.4]},
+ {t: 'C', p: [225.6, 103.4, 227.2, 101.6, 228.2, 105.4]},
+ {t: 'C', p: [228.2, 105.4, 231.6, 109, 236.4, 107]},
+ {t: 'C', p: [236.4, 107, 240.4, 106.8, 238.4, 109.2]},
+ {t: 'C', p: [238.4, 109.2, 234, 113, 222.2, 113.2]},
+ {t: 'C', p: [222.2, 113.2, 209.8, 113.8, 193.4, 121.4]},
+ {t: 'C', p: [193.4, 121.4, 163.6, 131.8, 154.4, 142.2]},
+ {t: 'C', p: [154.4, 142.2, 148, 151, 142.6, 152.2]},
+ {t: 'C', p: [142.6, 152.2, 136.8, 153, 130.8, 160.4]},
+ {t: 'C', p: [130.8, 160.4, 140.6, 154.6, 149.6, 154.6]},
+ {t: 'C', p: [149.6, 154.6, 153.6, 152.2, 149.8, 155.8]},
+ {t: 'C', p: [149.8, 155.8, 146.2, 163.4, 147.8, 168.8]},
+ {t: 'C', p: [147.8, 168.8, 147.2, 174, 146.4, 175.6]},
+ {t: 'C', p: [146.4, 175.6, 138.6, 188.4, 138.6, 190.8]},
+ {t: 'C', p: [138.6, 193.2, 139.8, 203, 140.2, 203.6]},
+ {t: 'C', p: [140.6, 204.2, 139.2, 202, 143, 204.4]},
+ {t: 'C', p: [146.8, 206.8, 149.6, 208.4, 150.4, 211.2]},
+ {t: 'C', p: [151.2, 214, 148.4, 205.8, 148.2, 204]},
+ {t: 'C', p: [148, 202.2, 143.8, 195, 144.6, 192.6]},
+ {t: 'C', p: [144.6, 192.6, 145.6, 193.6, 146.4, 195]},
+ {t: 'C', p: [146.4, 195, 145.8, 194.4, 146.4, 190.8]},
+ {t: 'C', p: [146.4, 190.8, 147.2, 185.6, 148.6, 182.4]},
+ {t: 'C', p: [150, 179.2, 152, 175.4, 152.4, 174.6]},
+ {t: 'C', p: [152.8, 173.8, 152.8, 168, 154.2, 170.6]},
+ {t: 'L', p: [157.6, 173.2]},
+ {t: 'C', p: [157.6, 173.2, 154.8, 170.6, 157, 168.4]},
+ {t: 'C', p: [157, 168.4, 156, 162.8, 157.8, 160.2]},
+ {t: 'C', p: [157.8, 160.2, 164.8, 151.8, 166.4, 150.8]},
+ {t: 'C', p: [168, 149.8, 166.6, 150.2, 166.6, 150.2]},
+ {t: 'C', p: [166.6, 150.2, 172.6, 146, 166.8, 147.6]},
+ {t: 'C', p: [166.8, 147.6, 162.8, 149.2, 159.8, 149.2]},
+ {t: 'C', p: [159.8, 149.2, 152.2, 151.2, 156.2, 147]},
+ {t: 'C', p: [160.2, 142.8, 170.2, 137.4, 174, 137.6]},
+ {t: 'L', p: [174.8, 139.2]},
+ {t: 'L', p: [186, 136.8]},
+ {t: 'L', p: [184.8, 137.6]},
+ {t: 'C', p: [184.8, 137.6, 184.6, 137.4, 188.8, 137]},
+ {t: 'C', p: [193, 136.6, 198.8, 138, 200.2, 136.2]},
+ {t: 'C', p: [201.6, 134.4, 205, 133.4, 204.6, 134.8]},
+ {t: 'C', p: [204.2, 136.2, 204, 138.2, 204, 138.2]},
+ {t: 'C', p: [204, 138.2, 209, 132.4, 208.4, 134.6]},
+ {t: 'C', p: [207.8, 136.8, 199.6, 142, 198.2, 148.2]},
+ {t: 'L', p: [208.6, 140]},
+ {t: 'L', p: [212.2, 137]},
+ {t: 'C', p: [212.2, 137, 215.8, 139.2, 216, 137.6]},
+ {t: 'C', p: [216.2, 136, 220.8, 130.2, 222, 130.4]},
+ {t: 'C', p: [223.2, 130.6, 225.2, 127.8, 225, 130.4]},
+ {t: 'C', p: [224.8, 133, 232.4, 138.4, 232.4, 138.4]},
+ {t: 'C', p: [232.4, 138.4, 235.6, 136.6, 237, 138]},
+ {t: 'C', p: [238.4, 139.4, 242.6, 118.2, 242.6, 118.2]},
+ {t: 'L', p: [267.6, 107.6]},
+ {t: 'L', p: [311.201, 104.2]},
+ {t: 'L', p: [294.201, 97.4]},
+ {t: 'L', p: [233.2, 86]},
+ {t: 'z', p: []}]},
+
+{f: null, s: {c: '#4c0000', w: 2},
+ p: [{t: 'M', p: [251.4, 285]},
+ {t: 'C', p: [251.4, 285, 236.4, 268.2, 228, 265.6]},
+ {t: 'C', p: [228, 265.6, 214.6, 258.8, 190, 266.6]}]},
+
+{f: null, s: {c: '#4c0000', w: 2},
+ p: [{t: 'M', p: [224.8, 264.2]},
+ {t: 'C', p: [224.8, 264.2, 199.6, 256.2, 184.2, 260.4]},
+ {t: 'C', p: [184.2, 260.4, 165.8, 262.4, 157.4, 276.2]}]},
+
+{f: null, s: {c: '#4c0000', w: 2},
+ p: [{t: 'M', p: [221.2, 263]},
+ {t: 'C', p: [221.2, 263, 204.2, 255.8, 189.4, 253.6]},
+ {t: 'C', p: [189.4, 253.6, 172.8, 251, 156.2, 258.2]},
+ {t: 'C', p: [156.2, 258.2, 144, 264.2, 138.6, 274.4]}]},
+
+{f: null, s: {c: '#4c0000', w: 2},
+ p: [{t: 'M', p: [222.2, 263.4]},
+ {t: 'C', p: [222.2, 263.4, 206.8, 252.4, 205.8, 251]},
+ {t: 'C', p: [205.8, 251, 198.8, 240, 185.8, 239.6]},
+ {t: 'C', p: [185.8, 239.6, 164.4, 240.4, 147.2, 248.4]}]},
+
+{f: '#000', s: null, p: [{t: 'M', p: [220.895, 254.407]},
+ {t: 'C', p: [222.437, 255.87, 249.4, 284.8, 249.4, 284.8]},
+ {t: 'C', p: [284.6, 321.401, 256.6, 287.2, 256.6, 287.2]},
+ {t: 'C', p: [249, 282.4, 239.8, 263.6, 239.8, 263.6]},
+ {t: 'C', p: [238.6, 260.8, 253.8, 270.8, 253.8, 270.8]},
+ {t: 'C', p: [257.8, 271.6, 271.4, 290.8, 271.4, 290.8]},
+ {t: 'C', p: [264.6, 288.4, 269.4, 295.6, 269.4, 295.6]},
+ {t: 'C', p: [272.2, 297.6, 292.601, 313.201, 292.601, 313.201]},
+ {t: 'C', p: [296.201, 317.201, 300.201, 318.801, 300.201, 318.801]},
+ {t: 'C', p: [314.201, 313.601, 307.801, 326.801, 307.801, 326.801]},
+ {t: 'C', p: [310.201, 333.601, 315.801, 322.001, 315.801, 322.001]},
+ {t: 'C', p: [327.001, 305.2, 310.601, 307.601, 310.601, 307.601]},
+ {t: 'C', p: [280.6, 310.401, 273.8, 294.4, 273.8, 294.4]},
+ {t: 'C', p: [271.4, 292, 280.2, 294.4, 280.2, 294.4]},
+ {t: 'C', p: [288.601, 296.4, 273, 282, 273, 282]},
+ {t: 'C', p: [275.4, 282, 284.6, 288.8, 284.6, 288.8]},
+ {t: 'C', p: [295.001, 298, 297.001, 296, 297.001, 296]},
+ {t: 'C', p: [315.001, 287.2, 325.401, 294.8, 325.401, 294.8]},
+ {t: 'C', p: [327.401, 296.4, 321.801, 303.2, 323.401, 308.401]},
+ {t: 'C', p: [325.001, 313.601, 329.801, 326.001, 329.801, 326.001]},
+ {t: 'C', p: [327.401, 327.601, 327.801, 338.401, 327.801, 338.401]},
+ {t: 'C', p: [344.601, 361.601, 335.001, 359.601, 335.001, 359.601]},
+ {t: 'C', p: [319.401, 359.201, 334.201, 366.801, 334.201, 366.801]},
+ {t: 'C', p: [337.401, 368.801, 346.201, 376.001, 346.201, 376.001]},
+ {t: 'C', p: [343.401, 374.801, 341.801, 380.001, 341.801, 380.001]},
+ {t: 'C', p: [346.601, 384.001, 343.801, 388.801, 343.801, 388.801]},
+ {t: 'C', p: [337.801, 390.001, 336.601, 394.001, 336.601, 394.001]},
+ {t: 'C', p: [343.401, 402.001, 333.401, 402.401, 333.401, 402.401]},
+ {t: 'C', p: [337.001, 406.801, 332.201, 418.801, 332.201, 418.801]},
+ {t: 'C', p: [327.401, 418.801, 321.001, 424.401, 321.001, 424.401]},
+ {t: 'C', p: [323.401, 429.201, 313.001, 434.801, 313.001, 434.801]},
+ {t: 'C', p: [304.601, 436.401, 307.401, 443.201, 307.401, 443.201]},
+ {t: 'C', p: [299.401, 449.201, 297.001, 465.201, 297.001, 465.201]},
+ {t: 'C', p: [296.201, 475.601, 293.801, 478.801, 299.001, 476.801]},
+ {t: 'C', p: [304.201, 474.801, 303.401, 462.401, 303.401, 462.401]},
+ {t: 'C', p: [298.601, 446.801, 341.401, 430.801, 341.401, 430.801]},
+ {t: 'C', p: [345.401, 429.201, 346.201, 424.001, 346.201, 424.001]},
+ {t: 'C', p: [348.201, 424.401, 357.001, 432.001, 357.001, 432.001]},
+ {t: 'C', p: [364.601, 443.201, 365.001, 434.001, 365.001, 434.001]},
+ {t: 'C', p: [366.201, 430.401, 364.601, 424.401, 364.601, 424.401]},
+ {t: 'C', p: [370.601, 402.801, 356.601, 396.401, 356.601, 396.401]},
+ {t: 'C', p: [346.601, 362.801, 360.601, 371.201, 360.601, 371.201]},
+ {t: 'C', p: [363.401, 376.801, 374.201, 382.001, 374.201, 382.001]},
+ {t: 'L', p: [377.801, 379.601]},
+ {t: 'C', p: [376.201, 374.801, 384.601, 368.801, 384.601, 368.801]},
+ {t: 'C', p: [387.401, 375.201, 393.401, 367.201, 393.401, 367.201]},
+ {t: 'C', p: [397.001, 342.801, 409.401, 357.201, 409.401, 357.201]},
+ {t: 'C', p: [413.401, 358.401, 414.601, 351.601, 414.601, 351.601]},
+ {t: 'C', p: [418.201, 341.201, 414.601, 327.601, 414.601, 327.601]},
+ {t: 'C', p: [418.201, 327.201, 427.801, 333.201, 427.801, 333.201]},
+ {t: 'C', p: [430.601, 329.601, 421.401, 312.801, 425.401, 315.201]},
+ {t: 'C', p: [429.401, 317.601, 433.801, 319.201, 433.801, 319.201]},
+ {t: 'C', p: [434.601, 317.201, 424.601, 304.801, 424.601, 304.801]},
+ {t: 'C', p: [420.201, 302, 415.001, 281.6, 415.001, 281.6]},
+ {t: 'C', p: [422.201, 285.2, 412.201, 270, 412.201, 270]},
+ {t: 'C', p: [412.201, 266.8, 418.201, 255.6, 418.201, 255.6]},
+ {t: 'C', p: [417.401, 248.8, 418.201, 249.2, 418.201, 249.2]},
+ {t: 'C', p: [421.001, 250.4, 429.001, 252, 422.201, 245.6]},
+ {t: 'C', p: [415.401, 239.2, 423.001, 234.4, 423.001, 234.4]},
+ {t: 'C', p: [427.401, 231.6, 413.801, 232, 413.801, 232]},
+ {t: 'C', p: [408.601, 227.6, 409.001, 223.6, 409.001, 223.6]},
+ {t: 'C', p: [417.001, 225.6, 402.601, 211.2, 400.201, 207.6]},
+ {t: 'C', p: [397.801, 204, 407.401, 198.8, 407.401, 198.8]},
+ {t: 'C', p: [420.601, 195.2, 409.001, 192, 409.001, 192]},
+ {t: 'C', p: [389.401, 192.4, 400.201, 181.6, 400.201, 181.6]},
+ {t: 'C', p: [406.201, 182, 404.601, 179.6, 404.601, 179.6]},
+ {t: 'C', p: [399.401, 178.4, 389.801, 172, 389.801, 172]},
+ {t: 'C', p: [385.801, 168.4, 389.401, 169.2, 389.401, 169.2]},
+ {t: 'C', p: [406.201, 170.4, 377.401, 159.2, 377.401, 159.2]},
+ {t: 'C', p: [385.401, 159.2, 367.401, 148.8, 367.401, 148.8]},
+ {t: 'C', p: [365.401, 147.2, 362.201, 139.6, 362.201, 139.6]},
+ {t: 'C', p: [356.201, 134.4, 351.401, 127.6, 351.401, 127.6]},
+ {t: 'C', p: [351.001, 123.2, 346.201, 118.4, 346.201, 118.4]},
+ {t: 'C', p: [334.601, 104.8, 329.001, 105.2, 329.001, 105.2]},
+ {t: 'C', p: [314.201, 101.6, 309.001, 102.4, 309.001, 102.4]},
+ {t: 'L', p: [256.2, 106.8]},
+ {t: 'C', p: [229.8, 119.6, 237.6, 140.6, 237.6, 140.6]},
+ {t: 'C', p: [244, 149, 253.2, 145.2, 253.2, 145.2]},
+ {t: 'C', p: [257.8, 139, 269.4, 141.2, 269.4, 141.2]},
+ {t: 'C', p: [289.801, 144.4, 287.201, 140.8, 287.201, 140.8]},
+ {t: 'C', p: [284.801, 136.2, 268.6, 130, 268.4, 129.4]},
+ {t: 'C', p: [268.2, 128.8, 259.4, 125.4, 259.4, 125.4]},
+ {t: 'C', p: [256.4, 124.2, 252, 115, 252, 115]},
+ {t: 'C', p: [248.8, 111.6, 264.6, 117.4, 264.6, 117.4]},
+ {t: 'C', p: [263.4, 118.4, 270.8, 122.4, 270.8, 122.4]},
+ {t: 'C', p: [288.201, 121.4, 298.801, 132.2, 298.801, 132.2]},
+ {t: 'C', p: [309.601, 148.8, 309.801, 140.6, 309.801, 140.6]},
+ {t: 'C', p: [312.601, 131.2, 300.801, 110, 300.801, 110]},
+ {t: 'C', p: [301.201, 108, 309.401, 114.6, 309.401, 114.6]},
+ {t: 'C', p: [310.801, 112.6, 311.601, 118.4, 311.601, 118.4]},
+ {t: 'C', p: [311.801, 120.8, 315.601, 128.8, 315.601, 128.8]},
+ {t: 'C', p: [318.401, 141.8, 322.001, 134.4, 322.001, 134.4]},
+ {t: 'L', p: [326.601, 143.8]},
+ {t: 'C', p: [328.001, 146.4, 322.001, 154, 322.001, 154]},
+ {t: 'C', p: [321.801, 156.8, 322.601, 156.6, 317.001, 164.2]},
+ {t: 'C', p: [311.401, 171.8, 314.801, 176.2, 314.801, 176.2]},
+ {t: 'C', p: [313.401, 182.8, 322.201, 182.4, 322.201, 182.4]},
+ {t: 'C', p: [324.801, 184.6, 328.201, 184.6, 328.201, 184.6]},
+ {t: 'C', p: [330.001, 186.6, 332.401, 186, 332.401, 186]},
+ {t: 'C', p: [334.001, 182.2, 340.201, 184.2, 340.201, 184.2]},
+ {t: 'C', p: [341.601, 181.8, 349.801, 181.4, 349.801, 181.4]},
+ {t: 'C', p: [350.801, 178.8, 351.201, 177.2, 354.601, 176.6]},
+ {t: 'C', p: [358.001, 176, 333.401, 133, 333.401, 133]},
+ {t: 'C', p: [339.801, 132.2, 331.601, 119.8, 331.601, 119.8]},
+ {t: 'C', p: [329.401, 113.2, 340.801, 127.8, 343.001, 129.2]},
+ {t: 'C', p: [345.201, 130.6, 346.201, 132.8, 344.601, 132.6]},
+ {t: 'C', p: [343.001, 132.4, 341.201, 134.6, 342.601, 134.8]},
+ {t: 'C', p: [344.001, 135, 357.001, 150, 360.401, 160.2]},
+ {t: 'C', p: [363.801, 170.4, 369.801, 174.4, 376.001, 180.4]},
+ {t: 'C', p: [382.201, 186.4, 381.401, 210.6, 381.401, 210.6]},
+ {t: 'C', p: [381.001, 219.4, 387.001, 230, 387.001, 230]},
+ {t: 'C', p: [389.001, 233.8, 384.801, 252, 384.801, 252]},
+ {t:
<TRUNCATED>
[39/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/date/relativewithplurals.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/date/relativewithplurals.js b/externs/GCL/externs/goog/date/relativewithplurals.js
new file mode 100644
index 0000000..09a697e
--- /dev/null
+++ b/externs/GCL/externs/goog/date/relativewithplurals.js
@@ -0,0 +1,120 @@
+// Copyright 2009 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 Code to make goog.date.relative plurals-aware.
+ */
+
+goog.provide('goog.date.relativeWithPlurals');
+
+goog.require('goog.date.relative');
+goog.require('goog.date.relative.Unit');
+goog.require('goog.i18n.MessageFormat');
+
+
+/**
+ * Gets a localized relative date string for a given delta and unit.
+ * @param {number} delta Number of minutes/hours/days.
+ * @param {boolean} future Whether the delta is in the future.
+ * @param {goog.date.relative.Unit} unit The units the delta is in.
+ * @return {string} The message.
+ * @private
+ */
+goog.date.relativeWithPlurals.formatTimeDelta_ =
+ function(delta, future, unit) {
+ if (!future && unit == goog.date.relative.Unit.MINUTES) {
+ /**
+ * @desc Relative date indicating how many minutes ago something happened.
+ */
+ var MSG_MINUTES_AGO_ICU =
+ goog.getMsg('{NUM, plural, ' +
+ '=0 {# minutes ago}' +
+ '=1 {# minute ago}' +
+ 'other {# minutes ago}}');
+
+ return new goog.i18n.MessageFormat(MSG_MINUTES_AGO_ICU).
+ format({'NUM': delta});
+
+ } else if (future && unit == goog.date.relative.Unit.MINUTES) {
+ /**
+ * @desc Relative date indicating in how many minutes something happens.
+ */
+ var MSG_IN_MINUTES_ICU =
+ goog.getMsg('{NUM, plural, ' +
+ '=0 {in # minutes}' +
+ '=1 {in # minute}' +
+ 'other {in # minutes}}');
+
+ return new goog.i18n.MessageFormat(MSG_IN_MINUTES_ICU).
+ format({'NUM': delta});
+
+ } else if (!future && unit == goog.date.relative.Unit.HOURS) {
+ /**
+ * @desc Relative date indicating how many hours ago something happened.
+ */
+ var MSG_HOURS_AGO_ICU =
+ goog.getMsg('{NUM, plural, ' +
+ '=0 {# hours ago}' +
+ '=1 {# hour ago}' +
+ 'other {# hours ago}}');
+
+ return new goog.i18n.MessageFormat(MSG_HOURS_AGO_ICU).
+ format({'NUM': delta});
+
+ } else if (future && unit == goog.date.relative.Unit.HOURS) {
+ /**
+ * @desc Relative date indicating in how many hours something happens.
+ */
+ var MSG_IN_HOURS_ICU =
+ goog.getMsg('{NUM, plural, ' +
+ '=0 {in # hours}' +
+ '=1 {in # hour}' +
+ 'other {in # hours}}');
+
+ return new goog.i18n.MessageFormat(MSG_IN_HOURS_ICU).
+ format({'NUM': delta});
+
+ } else if (!future && unit == goog.date.relative.Unit.DAYS) {
+ /**
+ * @desc Relative date indicating how many days ago something happened.
+ */
+ var MSG_DAYS_AGO_ICU =
+ goog.getMsg('{NUM, plural, ' +
+ '=0 {# days ago}' +
+ '=1 {# day ago}' +
+ 'other {# days ago}}');
+
+ return new goog.i18n.MessageFormat(MSG_DAYS_AGO_ICU).
+ format({'NUM': delta});
+
+ } else if (future && unit == goog.date.relative.Unit.DAYS) {
+ /**
+ * @desc Relative date indicating in how many days something happens.
+ */
+ var MSG_IN_DAYS_ICU =
+ goog.getMsg('{NUM, plural, ' +
+ '=0 {in # days}' +
+ '=1 {in # day}' +
+ 'other {in # days}}');
+
+ return new goog.i18n.MessageFormat(MSG_IN_DAYS_ICU).
+ format({'NUM': delta});
+
+ } else {
+ return '';
+ }
+};
+
+goog.date.relative.setTimeDeltaFormatter(
+ goog.date.relativeWithPlurals.formatTimeDelta_);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/date/utcdatetime.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/date/utcdatetime.js b/externs/GCL/externs/goog/date/utcdatetime.js
new file mode 100644
index 0000000..eeffb31
--- /dev/null
+++ b/externs/GCL/externs/goog/date/utcdatetime.js
@@ -0,0 +1,191 @@
+// Copyright 2009 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 Locale independent date/time class.
+ *
+ */
+
+goog.provide('goog.date.UtcDateTime');
+
+goog.require('goog.date');
+goog.require('goog.date.Date');
+goog.require('goog.date.DateTime');
+goog.require('goog.date.Interval');
+
+
+
+/**
+ * Class representing a date/time in GMT+0 time zone, without daylight saving.
+ * Defaults to current date and time if none is specified. The get... and the
+ * getUTC... methods are equivalent.
+ *
+ * @param {number|goog.date.DateLike=} opt_year Four digit UTC year or a
+ * date-like object. If not set, the created object will contain the
+ * date determined by goog.now().
+ * @param {number=} opt_month UTC month, 0 = Jan, 11 = Dec.
+ * @param {number=} opt_date UTC date of month, 1 - 31.
+ * @param {number=} opt_hours UTC hours, 0 - 23.
+ * @param {number=} opt_minutes UTC minutes, 0 - 59.
+ * @param {number=} opt_seconds UTC seconds, 0 - 59.
+ * @param {number=} opt_milliseconds UTC milliseconds, 0 - 999.
+ * @constructor
+ * @struct
+ * @extends {goog.date.DateTime}
+ */
+goog.date.UtcDateTime = function(opt_year, opt_month, opt_date, opt_hours,
+ opt_minutes, opt_seconds, opt_milliseconds) {
+ var timestamp;
+ if (goog.isNumber(opt_year)) {
+ timestamp = Date.UTC(opt_year, opt_month || 0, opt_date || 1,
+ opt_hours || 0, opt_minutes || 0, opt_seconds || 0,
+ opt_milliseconds || 0);
+ } else {
+ timestamp = opt_year ? opt_year.getTime() : goog.now();
+ }
+ this.date = new Date(timestamp);
+};
+goog.inherits(goog.date.UtcDateTime, goog.date.DateTime);
+
+
+/**
+ * @param {number} timestamp Number of milliseconds since Epoch.
+ * @return {!goog.date.UtcDateTime}
+ */
+goog.date.UtcDateTime.fromTimestamp = function(timestamp) {
+ var date = new goog.date.UtcDateTime();
+ date.setTime(timestamp);
+ return date;
+};
+
+
+/**
+ * Creates a DateTime from a UTC datetime string expressed in ISO 8601 format.
+ *
+ * @param {string} formatted A date or datetime expressed in ISO 8601 format.
+ * @return {goog.date.UtcDateTime} Parsed date or null if parse fails.
+ */
+goog.date.UtcDateTime.fromIsoString = function(formatted) {
+ var ret = new goog.date.UtcDateTime(2000);
+ return goog.date.setIso8601DateTime(ret, formatted) ? ret : null;
+};
+
+
+/**
+ * Clones the UtcDateTime object.
+ *
+ * @return {!goog.date.UtcDateTime} A clone of the datetime object.
+ * @override
+ */
+goog.date.UtcDateTime.prototype.clone = function() {
+ var date = new goog.date.UtcDateTime(this.date);
+ date.setFirstDayOfWeek(this.getFirstDayOfWeek());
+ date.setFirstWeekCutOffDay(this.getFirstWeekCutOffDay());
+ return date;
+};
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.add = function(interval) {
+ if (interval.years || interval.months) {
+ var yearsMonths = new goog.date.Interval(interval.years, interval.months);
+ goog.date.Date.prototype.add.call(this, yearsMonths);
+ }
+ var daysAndTimeMillis = 1000 * (
+ interval.seconds + 60 * (
+ interval.minutes + 60 * (
+ interval.hours + 24 * interval.days)));
+ this.date = new Date(this.date.getTime() + daysAndTimeMillis);
+};
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getTimezoneOffset = function() {
+ return 0;
+};
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getFullYear =
+ goog.date.DateTime.prototype.getUTCFullYear;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getMonth =
+ goog.date.DateTime.prototype.getUTCMonth;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getDate =
+ goog.date.DateTime.prototype.getUTCDate;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getHours =
+ goog.date.DateTime.prototype.getUTCHours;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getMinutes =
+ goog.date.DateTime.prototype.getUTCMinutes;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getSeconds =
+ goog.date.DateTime.prototype.getUTCSeconds;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getMilliseconds =
+ goog.date.DateTime.prototype.getUTCMilliseconds;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.getDay =
+ goog.date.DateTime.prototype.getUTCDay;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.setFullYear =
+ goog.date.DateTime.prototype.setUTCFullYear;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.setMonth =
+ goog.date.DateTime.prototype.setUTCMonth;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.setDate =
+ goog.date.DateTime.prototype.setUTCDate;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.setHours =
+ goog.date.DateTime.prototype.setUTCHours;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.setMinutes =
+ goog.date.DateTime.prototype.setUTCMinutes;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.setSeconds =
+ goog.date.DateTime.prototype.setUTCSeconds;
+
+
+/** @override */
+goog.date.UtcDateTime.prototype.setMilliseconds =
+ goog.date.DateTime.prototype.setUTCMilliseconds;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/cursor.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/cursor.js b/externs/GCL/externs/goog/db/cursor.js
new file mode 100644
index 0000000..d8a4da7
--- /dev/null
+++ b/externs/GCL/externs/goog/db/cursor.js
@@ -0,0 +1,215 @@
+// Copyright 2012 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 Wrapper for a IndexedDB cursor.
+ *
+ */
+
+
+goog.provide('goog.db.Cursor');
+
+goog.require('goog.async.Deferred');
+goog.require('goog.db.Error');
+goog.require('goog.debug');
+goog.require('goog.events.EventTarget');
+
+
+
+/**
+ * Creates a new IDBCursor wrapper object. Should not be created directly,
+ * access cursor through object store.
+ * @see goog.db.ObjectStore#openCursor
+ *
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.db.Cursor = function() {
+ goog.db.Cursor.base(this, 'constructor');
+};
+goog.inherits(goog.db.Cursor, goog.events.EventTarget);
+
+
+/**
+ * Underlying IndexedDB cursor object.
+ *
+ * @type {IDBCursor}
+ * @private
+ */
+goog.db.Cursor.prototype.cursor_ = null;
+
+
+/**
+ * Advances the cursor to the next position along its direction. When new data
+ * is available, the NEW_DATA event will be fired. If the cursor has reached the
+ * end of the range it will fire the COMPLETE event. If opt_key is specified it
+ * will advance to the key it matches in its direction.
+ *
+ * This wraps the native #continue method on the underlying object.
+ *
+ * @param {IDBKeyType=} opt_key The optional key to advance to.
+ */
+goog.db.Cursor.prototype.next = function(opt_key) {
+ if (opt_key) {
+ this.cursor_['continue'](opt_key);
+ } else {
+ this.cursor_['continue']();
+ }
+};
+
+
+/**
+ * Updates the value at the current position of the cursor in the object store.
+ * If the cursor points to a value that has just been deleted, a new value is
+ * created.
+ *
+ * @param {*} value The value to be stored.
+ * @return {!goog.async.Deferred} The resulting deferred request.
+ */
+goog.db.Cursor.prototype.update = function(value) {
+ var msg = 'updating via cursor with value ';
+ var d = new goog.async.Deferred();
+ var request;
+
+ try {
+ request = this.cursor_.update(value);
+ } catch (err) {
+ msg += goog.debug.deepExpose(value);
+ d.errback(goog.db.Error.fromException(err, msg));
+ return d;
+ }
+ request.onsuccess = function(ev) {
+ d.callback();
+ };
+ request.onerror = function(ev) {
+ msg += goog.debug.deepExpose(value);
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * Deletes the value at the cursor's position, without changing the cursor's
+ * position. Once the value is deleted, the cursor's value is set to null.
+ *
+ * @return {!goog.async.Deferred} The resulting deferred request.
+ */
+goog.db.Cursor.prototype.remove = function() {
+ var msg = 'deleting via cursor';
+ var d = new goog.async.Deferred();
+ var request;
+
+ try {
+ request = this.cursor_['delete']();
+ } catch (err) {
+ d.errback(goog.db.Error.fromException(err, msg));
+ return d;
+ }
+ request.onsuccess = function(ev) {
+ d.callback();
+ };
+ request.onerror = function(ev) {
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * @return {*} The value for the value at the cursor's position. Undefined
+ * if no current value, or null if value has just been deleted.
+ */
+goog.db.Cursor.prototype.getValue = function() {
+ return this.cursor_['value'];
+};
+
+
+/**
+ * @return {IDBKeyType} The key for the value at the cursor's position. If
+ * the cursor is outside its range, this is undefined.
+ */
+goog.db.Cursor.prototype.getKey = function() {
+ return this.cursor_.key;
+};
+
+
+/**
+ * Opens a value cursor from IDBObjectStore or IDBIndex over the specified key
+ * range. Returns a cursor object which is able to iterate over the given range.
+ * @param {!(IDBObjectStore|IDBIndex)} source Data source to open cursor.
+ * @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
+ * over the whole data source.
+ * @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
+ * moves in a forward direction with duplicates.
+ * @return {!goog.db.Cursor} The cursor.
+ * @throws {goog.db.Error} If there was a problem opening the cursor.
+ */
+goog.db.Cursor.openCursor = function(source, opt_range, opt_direction) {
+ var cursor = new goog.db.Cursor();
+ var request;
+
+ try {
+ var range = opt_range ? opt_range.range() : null;
+ if (opt_direction) {
+ request = source.openCursor(range, opt_direction);
+ } else {
+ request = source.openCursor(range);
+ }
+ } catch (ex) {
+ cursor.dispose();
+ throw goog.db.Error.fromException(ex, source.name);
+ }
+ request.onsuccess = function(e) {
+ cursor.cursor_ = e.target.result || null;
+ if (cursor.cursor_) {
+ cursor.dispatchEvent(goog.db.Cursor.EventType.NEW_DATA);
+ } else {
+ cursor.dispatchEvent(goog.db.Cursor.EventType.COMPLETE);
+ }
+ };
+ request.onerror = function(e) {
+ cursor.dispatchEvent(goog.db.Cursor.EventType.ERROR);
+ };
+ return cursor;
+};
+
+
+/**
+ * Possible cursor directions.
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBCursor
+ *
+ * @enum {string}
+ */
+goog.db.Cursor.Direction = {
+ NEXT: 'next',
+ NEXT_NO_DUPLICATE: 'nextunique',
+ PREV: 'prev',
+ PREV_NO_DUPLICATE: 'prevunique'
+};
+
+
+/**
+ * Event types that the cursor can dispatch. COMPLETE events are dispatched when
+ * a cursor is depleted of values, a NEW_DATA event if there is new data
+ * available, and ERROR if an error occurred.
+ *
+ * @enum {string}
+ */
+goog.db.Cursor.EventType = {
+ COMPLETE: 'c',
+ ERROR: 'e',
+ NEW_DATA: 'n'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/db.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/db.js b/externs/GCL/externs/goog/db/db.js
new file mode 100644
index 0000000..17149c4
--- /dev/null
+++ b/externs/GCL/externs/goog/db/db.js
@@ -0,0 +1,185 @@
+// 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 Wrappers for the HTML5 IndexedDB. The wrappers export nearly
+ * the same interface as the standard API, but return goog.async.Deferred
+ * objects instead of request objects and use Closure events. The wrapper works
+ * and has been tested on Chrome version 22+. It may work on older Chrome
+ * versions, but they aren't explicitly supported.
+ *
+ * Example usage:
+ *
+ * <code>
+ * goog.db.openDatabase('mydb', 1, function(ev, db, tx) {
+ * db.createObjectStore('mystore');
+ * }).addCallback(function(db) {
+ * var putTx = db.createTransaction(
+ * [],
+ * goog.db.Transaction.TransactionMode.READ_WRITE);
+ * var store = putTx.objectStore('mystore');
+ * store.put('value', 'key');
+ * goog.listen(putTx, goog.db.Transaction.EventTypes.COMPLETE, function() {
+ * var getTx = db.createTransaction([]);
+ * var request = getTx.objectStore('mystore').get('key');
+ * request.addCallback(function(result) {
+ * ...
+ * });
+ * });
+ * </code>
+ *
+ */
+
+
+goog.provide('goog.db');
+goog.provide('goog.db.BlockedCallback');
+goog.provide('goog.db.UpgradeNeededCallback');
+
+goog.require('goog.asserts');
+goog.require('goog.async.Deferred');
+goog.require('goog.db.Error');
+goog.require('goog.db.IndexedDb');
+goog.require('goog.db.Transaction');
+
+
+/**
+ * The IndexedDB factory object.
+ *
+ * @type {IDBFactory}
+ * @private
+ */
+goog.db.indexedDb_ = goog.global.indexedDB || goog.global.mozIndexedDB ||
+ goog.global.webkitIndexedDB || goog.global.moz_indexedDB;
+
+
+/**
+ * A callback that's called if a blocked event is received. When a database is
+ * supposed to be deleted or upgraded (i.e. versionchange), and there are open
+ * connections to this database, a block event will be fired to prevent the
+ * operations from going through until all such open connections are closed.
+ * This callback can be used to notify users that they should close other tabs
+ * that have open connections, or to close the connections manually. Databases
+ * can also listen for the {@link goog.db.IndexedDb.EventType.VERSION_CHANGE}
+ * event to automatically close themselves when they're blocking such
+ * operations.
+ *
+ * This is passed a VersionChangeEvent that has the version of the database
+ * before it was deleted, and "null" as the new version.
+ *
+ * @typedef {function(!goog.db.IndexedDb.VersionChangeEvent)}
+ */
+goog.db.BlockedCallback;
+
+
+/**
+ * A callback that's called when opening a database whose internal version is
+ * lower than the version passed to {@link goog.db.openDatabase}.
+ *
+ * This callback is passed three arguments: a VersionChangeEvent with both the
+ * old version and the new version of the database; the database that's being
+ * opened, for which you can create and delete object stores; and the version
+ * change transaction, with which you can abort the version change.
+ *
+ * Note that the transaction is not active, which means that it can't be used to
+ * make changes to the database. However, since there is a transaction running,
+ * you can't create another one via {@link goog.db.IndexedDb.createTransaction}.
+ * This means that it's not possible to manipulate the database other than
+ * creating or removing object stores in this callback.
+ *
+ * @typedef {function(!goog.db.IndexedDb.VersionChangeEvent,
+ * !goog.db.IndexedDb,
+ * !goog.db.Transaction)}
+ */
+goog.db.UpgradeNeededCallback;
+
+
+/**
+ * Opens a database connection and wraps it.
+ *
+ * @param {string} name The name of the database to open.
+ * @param {number=} opt_version The expected version of the database. If this is
+ * larger than the actual version, opt_onUpgradeNeeded will be called
+ * (possibly after opt_onBlocked; see {@link goog.db.BlockedCallback}). If
+ * this is passed, opt_onUpgradeNeeded must be passed as well.
+ * @param {goog.db.UpgradeNeededCallback=} opt_onUpgradeNeeded Called if
+ * opt_version is greater than the old version of the database. If
+ * opt_version is passed, this must be passed as well.
+ * @param {goog.db.BlockedCallback=} opt_onBlocked Called if there are active
+ * connections to the database.
+ * @return {!goog.async.Deferred} The deferred database object.
+ */
+goog.db.openDatabase = function(name, opt_version, opt_onUpgradeNeeded,
+ opt_onBlocked) {
+ goog.asserts.assert(
+ goog.isDef(opt_version) == goog.isDef(opt_onUpgradeNeeded),
+ 'opt_version must be passed to goog.db.openDatabase if and only if ' +
+ 'opt_onUpgradeNeeded is also passed');
+
+ var d = new goog.async.Deferred();
+ var openRequest = opt_version ?
+ goog.db.indexedDb_.open(name, opt_version) :
+ goog.db.indexedDb_.open(name);
+ openRequest.onsuccess = function(ev) {
+ var db = new goog.db.IndexedDb(ev.target.result);
+ d.callback(db);
+ };
+ openRequest.onerror = function(ev) {
+ var msg = 'opening database ' + name;
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ openRequest.onupgradeneeded = function(ev) {
+ if (!opt_onUpgradeNeeded) return;
+ var db = new goog.db.IndexedDb(ev.target.result);
+ opt_onUpgradeNeeded(
+ new goog.db.IndexedDb.VersionChangeEvent(ev.oldVersion, ev.newVersion),
+ db,
+ new goog.db.Transaction(ev.target.transaction, db));
+ };
+ openRequest.onblocked = function(ev) {
+ if (opt_onBlocked) {
+ opt_onBlocked(new goog.db.IndexedDb.VersionChangeEvent(
+ ev.oldVersion, ev.newVersion));
+ }
+ };
+ return d;
+};
+
+
+/**
+ * Deletes a database once all open connections have been closed.
+ *
+ * @param {string} name The name of the database to delete.
+ * @param {goog.db.BlockedCallback=} opt_onBlocked Called if there are active
+ * connections to the database.
+ * @return {!goog.async.Deferred} A deferred object that will fire once the
+ * database is deleted.
+ */
+goog.db.deleteDatabase = function(name, opt_onBlocked) {
+ var d = new goog.async.Deferred();
+ var deleteRequest = goog.db.indexedDb_.deleteDatabase(name);
+ deleteRequest.onsuccess = function(ev) {
+ d.callback();
+ };
+ deleteRequest.onerror = function(ev) {
+ var msg = 'deleting database ' + name;
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ deleteRequest.onblocked = function(ev) {
+ if (opt_onBlocked) {
+ opt_onBlocked(new goog.db.IndexedDb.VersionChangeEvent(
+ ev.oldVersion, ev.newVersion));
+ }
+ };
+ return d;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/error1.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/error1.js b/externs/GCL/externs/goog/db/error1.js
new file mode 100644
index 0000000..9589f89
--- /dev/null
+++ b/externs/GCL/externs/goog/db/error1.js
@@ -0,0 +1,364 @@
+// 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 Error classes for the IndexedDB wrapper.
+ *
+ */
+
+
+goog.provide('goog.db.Error');
+goog.provide('goog.db.Error.ErrorCode');
+goog.provide('goog.db.Error.ErrorName');
+goog.provide('goog.db.Error.VersionChangeBlockedError');
+
+goog.require('goog.debug.Error');
+
+
+
+/**
+ * A database error. Since the stack trace can be unhelpful in an asynchronous
+ * context, the error provides a message about where it was produced.
+ *
+ * @param {number|!DOMError} error The DOMError instance returned by the
+ * browser for Chrome22+, or an error code for previous versions.
+ * @param {string} context A description of where the error occured.
+ * @param {string=} opt_message Additional message.
+ * @constructor
+ * @extends {goog.debug.Error}
+ * @final
+ */
+goog.db.Error = function(error, context, opt_message) {
+ var errorCode = null;
+ var internalError = null;
+ if (goog.isNumber(error)) {
+ errorCode = error;
+ internalError = {name: goog.db.Error.getName(errorCode)};
+ } else {
+ internalError = error;
+ errorCode = goog.db.Error.getCode(error.name);
+ }
+
+ /**
+ * The code for this error.
+ *
+ * @type {number}
+ */
+ this.code = errorCode;
+
+ /**
+ * The DOMException as returned by the browser.
+ *
+ * @type {!DOMError}
+ * @private
+ */
+ this.error_ = /** @type {!DOMError} */ (internalError);
+
+ var msg = 'Error ' + context + ': ' + this.getName();
+ if (opt_message) {
+ msg += ', ' + opt_message;
+ }
+ goog.db.Error.base(this, 'constructor', msg);
+};
+goog.inherits(goog.db.Error, goog.debug.Error);
+
+
+/**
+ * @return {string} The name of the error.
+ */
+goog.db.Error.prototype.getName = function() {
+ return this.error_.name;
+};
+
+
+
+/**
+ * A specific kind of database error. If a Version Change is unable to proceed
+ * due to other open database connections, it will block and this error will be
+ * thrown.
+ *
+ * @constructor
+ * @extends {goog.debug.Error}
+ * @final
+ */
+goog.db.Error.VersionChangeBlockedError = function() {
+ goog.db.Error.VersionChangeBlockedError.base(
+ this, 'constructor', 'Version change blocked');
+};
+goog.inherits(goog.db.Error.VersionChangeBlockedError, goog.debug.Error);
+
+
+/**
+ * Synthetic error codes for database errors, for use when IndexedDB
+ * support is not available. This numbering differs in practice
+ * from the browser implementations, but it is not meant to be reliable:
+ * this object merely ensures that goog.db.Error is loadable on platforms
+ * that do not support IndexedDB.
+ *
+ * @enum {number}
+ * @private
+ */
+goog.db.Error.DatabaseErrorCode_ = {
+ UNKNOWN_ERR: 1,
+ NON_TRANSIENT_ERR: 2,
+ NOT_FOUND_ERR: 3,
+ CONSTRAINT_ERR: 4,
+ DATA_ERR: 5,
+ NOT_ALLOWED_ERR: 6,
+ TRANSACTION_INACTIVE_ERR: 7,
+ ABORT_ERR: 8,
+ READ_ONLY_ERR: 9,
+ TRANSIENT_ERR: 10,
+ TIMEOUT_ERR: 11,
+ QUOTA_ERR: 12,
+ INVALID_ACCESS_ERR: 13,
+ INVALID_STATE_ERR: 14
+};
+
+
+/**
+ * Error codes for database errors.
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBDatabaseException
+ *
+ * @enum {number}
+ */
+goog.db.Error.ErrorCode = {
+ UNKNOWN_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).UNKNOWN_ERR,
+ NON_TRANSIENT_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).NON_TRANSIENT_ERR,
+ NOT_FOUND_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).NOT_FOUND_ERR,
+ CONSTRAINT_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).CONSTRAINT_ERR,
+ DATA_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).DATA_ERR,
+ NOT_ALLOWED_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).NOT_ALLOWED_ERR,
+ TRANSACTION_INACTIVE_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).TRANSACTION_INACTIVE_ERR,
+ ABORT_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).ABORT_ERR,
+ READ_ONLY_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).READ_ONLY_ERR,
+ TIMEOUT_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).TIMEOUT_ERR,
+ QUOTA_ERR: (goog.global.IDBDatabaseException ||
+ goog.global.webkitIDBDatabaseException ||
+ goog.db.Error.DatabaseErrorCode_).QUOTA_ERR,
+ INVALID_ACCESS_ERR: (goog.global.DOMException ||
+ goog.db.Error.DatabaseErrorCode_).INVALID_ACCESS_ERR,
+ INVALID_STATE_ERR: (goog.global.DOMException ||
+ goog.db.Error.DatabaseErrorCode_).INVALID_STATE_ERR
+};
+
+
+/**
+ * Translates an error code into a more useful message.
+ *
+ * @param {number} code Error code.
+ * @return {string} A debug message.
+ */
+goog.db.Error.getMessage = function(code) {
+ switch (code) {
+ case goog.db.Error.ErrorCode.UNKNOWN_ERR:
+ return 'Unknown error';
+ case goog.db.Error.ErrorCode.NON_TRANSIENT_ERR:
+ return 'Invalid operation';
+ case goog.db.Error.ErrorCode.NOT_FOUND_ERR:
+ return 'Required database object not found';
+ case goog.db.Error.ErrorCode.CONSTRAINT_ERR:
+ return 'Constraint unsatisfied';
+ case goog.db.Error.ErrorCode.DATA_ERR:
+ return 'Invalid data';
+ case goog.db.Error.ErrorCode.NOT_ALLOWED_ERR:
+ return 'Operation disallowed';
+ case goog.db.Error.ErrorCode.TRANSACTION_INACTIVE_ERR:
+ return 'Transaction not active';
+ case goog.db.Error.ErrorCode.ABORT_ERR:
+ return 'Request aborted';
+ case goog.db.Error.ErrorCode.READ_ONLY_ERR:
+ return 'Modifying operation not allowed in a read-only transaction';
+ case goog.db.Error.ErrorCode.TIMEOUT_ERR:
+ return 'Transaction timed out';
+ case goog.db.Error.ErrorCode.QUOTA_ERR:
+ return 'Database storage space quota exceeded';
+ case goog.db.Error.ErrorCode.INVALID_ACCESS_ERR:
+ return 'Invalid operation';
+ case goog.db.Error.ErrorCode.INVALID_STATE_ERR:
+ return 'Invalid state';
+ default:
+ return 'Unrecognized exception with code ' + code;
+ }
+};
+
+
+/**
+ * Names of all possible errors as returned from the browser.
+ * @see http://www.w3.org/TR/IndexedDB/#exceptions
+ * @enum {string}
+ */
+goog.db.Error.ErrorName = {
+ ABORT_ERR: 'AbortError',
+ CONSTRAINT_ERR: 'ConstraintError',
+ DATA_CLONE_ERR: 'DataCloneError',
+ DATA_ERR: 'DataError',
+ INVALID_ACCESS_ERR: 'InvalidAccessError',
+ INVALID_STATE_ERR: 'InvalidStateError',
+ NOT_FOUND_ERR: 'NotFoundError',
+ QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
+ READ_ONLY_ERR: 'ReadOnlyError',
+ SYNTAX_ERROR: 'SyntaxError',
+ TIMEOUT_ERR: 'TimeoutError',
+ TRANSACTION_INACTIVE_ERR: 'TransactionInactiveError',
+ UNKNOWN_ERR: 'UnknownError',
+ VERSION_ERR: 'VersionError'
+};
+
+
+/**
+ * Translates an error name to an error code. This is purely kept for backwards
+ * compatibility with Chrome21.
+ *
+ * @param {string} name The name of the erorr.
+ * @return {number} The error code corresponding to the error.
+ */
+goog.db.Error.getCode = function(name) {
+ switch (name) {
+ case goog.db.Error.ErrorName.UNKNOWN_ERR:
+ return goog.db.Error.ErrorCode.UNKNOWN_ERR;
+ case goog.db.Error.ErrorName.NOT_FOUND_ERR:
+ return goog.db.Error.ErrorCode.NOT_FOUND_ERR;
+ case goog.db.Error.ErrorName.CONSTRAINT_ERR:
+ return goog.db.Error.ErrorCode.CONSTRAINT_ERR;
+ case goog.db.Error.ErrorName.DATA_ERR:
+ return goog.db.Error.ErrorCode.DATA_ERR;
+ case goog.db.Error.ErrorName.TRANSACTION_INACTIVE_ERR:
+ return goog.db.Error.ErrorCode.TRANSACTION_INACTIVE_ERR;
+ case goog.db.Error.ErrorName.ABORT_ERR:
+ return goog.db.Error.ErrorCode.ABORT_ERR;
+ case goog.db.Error.ErrorName.READ_ONLY_ERR:
+ return goog.db.Error.ErrorCode.READ_ONLY_ERR;
+ case goog.db.Error.ErrorName.TIMEOUT_ERR:
+ return goog.db.Error.ErrorCode.TIMEOUT_ERR;
+ case goog.db.Error.ErrorName.QUOTA_EXCEEDED_ERR:
+ return goog.db.Error.ErrorCode.QUOTA_ERR;
+ case goog.db.Error.ErrorName.INVALID_ACCESS_ERR:
+ return goog.db.Error.ErrorCode.INVALID_ACCESS_ERR;
+ case goog.db.Error.ErrorName.INVALID_STATE_ERR:
+ return goog.db.Error.ErrorCode.INVALID_STATE_ERR;
+ default:
+ return goog.db.Error.ErrorCode.UNKNOWN_ERR;
+ }
+};
+
+
+/**
+ * Converts an error code used by the old spec, to an error name used by the
+ * latest spec.
+ * @see http://www.w3.org/TR/IndexedDB/#exceptions
+ *
+ * @param {!goog.db.Error.ErrorCode|number} code The error code to convert.
+ * @return {!goog.db.Error.ErrorName} The corresponding name of the error.
+ */
+goog.db.Error.getName = function(code) {
+ switch (code) {
+ case goog.db.Error.ErrorCode.UNKNOWN_ERR:
+ return goog.db.Error.ErrorName.UNKNOWN_ERR;
+ case goog.db.Error.ErrorCode.NOT_FOUND_ERR:
+ return goog.db.Error.ErrorName.NOT_FOUND_ERR;
+ case goog.db.Error.ErrorCode.CONSTRAINT_ERR:
+ return goog.db.Error.ErrorName.CONSTRAINT_ERR;
+ case goog.db.Error.ErrorCode.DATA_ERR:
+ return goog.db.Error.ErrorName.DATA_ERR;
+ case goog.db.Error.ErrorCode.TRANSACTION_INACTIVE_ERR:
+ return goog.db.Error.ErrorName.TRANSACTION_INACTIVE_ERR;
+ case goog.db.Error.ErrorCode.ABORT_ERR:
+ return goog.db.Error.ErrorName.ABORT_ERR;
+ case goog.db.Error.ErrorCode.READ_ONLY_ERR:
+ return goog.db.Error.ErrorName.READ_ONLY_ERR;
+ case goog.db.Error.ErrorCode.TIMEOUT_ERR:
+ return goog.db.Error.ErrorName.TIMEOUT_ERR;
+ case goog.db.Error.ErrorCode.QUOTA_ERR:
+ return goog.db.Error.ErrorName.QUOTA_EXCEEDED_ERR;
+ case goog.db.Error.ErrorCode.INVALID_ACCESS_ERR:
+ return goog.db.Error.ErrorName.INVALID_ACCESS_ERR;
+ case goog.db.Error.ErrorCode.INVALID_STATE_ERR:
+ return goog.db.Error.ErrorName.INVALID_STATE_ERR;
+ default:
+ return goog.db.Error.ErrorName.UNKNOWN_ERR;
+ }
+};
+
+
+/**
+ * Constructs an goog.db.Error instance from an IDBRequest. This abstraction is
+ * necessary to provide backwards compatibility with Chrome21.
+ *
+ * @param {!IDBRequest} request The request that failed.
+ * @param {string} message The error message to add to err if it's wrapped.
+ * @return {!goog.db.Error} The error that caused the failure.
+ */
+goog.db.Error.fromRequest = function(request, message) {
+ if ('error' in request) {
+ // Chrome 21 and before.
+ return new goog.db.Error(request.error, message);
+ } else if ('name' in request) {
+ // Chrome 22+.
+ var errorName = goog.db.Error.getName(request.errorCode);
+ return new goog.db.Error(
+ /**@type {!DOMError} */ ({name: errorName}), message);
+ } else {
+ return new goog.db.Error(/** @type {!DOMError} */ (
+ {name: goog.db.Error.ErrorName.UNKNOWN_ERR}), message);
+ }
+};
+
+
+/**
+ * Constructs an goog.db.Error instance from an DOMException. This abstraction
+ * is necessary to provide backwards compatibility with Chrome21.
+ *
+ * @param {!IDBDatabaseException} ex The exception that was thrown.
+ * @param {string} message The error message to add to err if it's wrapped.
+ * @return {!goog.db.Error} The error that caused the failure.
+ * @suppress {invalidCasts} The cast from IDBDatabaseException to DOMError
+ * is invalid and will not compile.
+ */
+goog.db.Error.fromException = function(ex, message) {
+ if ('name' in ex) {
+ // Chrome 22+.
+ var errorMessage = message + ': ' + ex.message;
+ return new goog.db.Error(/** @type {!DOMError} */ (ex), errorMessage);
+ } else if ('code' in ex) {
+ // Chrome 21 and before.
+ var errorName = goog.db.Error.getName(ex.code);
+ var errorMessage = message + ': ' + ex.message;
+ return new goog.db.Error(
+ /** @type {!DOMError} */ ({name: errorName}), errorMessage);
+ } else {
+ return new goog.db.Error(/** @type {!DOMError} */ (
+ {name: goog.db.Error.ErrorName.UNKNOWN_ERR}), message);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/index.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/index.js b/externs/GCL/externs/goog/db/index.js
new file mode 100644
index 0000000..7951e24
--- /dev/null
+++ b/externs/GCL/externs/goog/db/index.js
@@ -0,0 +1,246 @@
+// 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 Wrapper for an IndexedDB index.
+ *
+ */
+
+
+goog.provide('goog.db.Index');
+
+goog.require('goog.async.Deferred');
+goog.require('goog.db.Cursor');
+goog.require('goog.db.Error');
+goog.require('goog.debug');
+
+
+
+/**
+ * Creates an IDBIndex wrapper object. Indexes are associated with object
+ * stores and provide methods for looking up objects based on their non-key
+ * properties. Should not be created directly, access through the object store
+ * it belongs to.
+ * @see goog.db.ObjectStore#getIndex
+ *
+ * @param {!IDBIndex} index Underlying IDBIndex object.
+ * @constructor
+ * @final
+ */
+goog.db.Index = function(index) {
+ /**
+ * Underlying IndexedDB index object.
+ *
+ * @type {!IDBIndex}
+ * @private
+ */
+ this.index_ = index;
+};
+
+
+/**
+ * @return {string} Name of the index.
+ */
+goog.db.Index.prototype.getName = function() {
+ return this.index_.name;
+};
+
+
+/**
+ * @return {string} Key path of the index.
+ */
+goog.db.Index.prototype.getKeyPath = function() {
+ return this.index_.keyPath;
+};
+
+
+/**
+ * @return {boolean} True if the index enforces that there is only one object
+ * for each unique value it indexes on.
+ */
+goog.db.Index.prototype.isUnique = function() {
+ return this.index_.unique;
+};
+
+
+/**
+ * Helper function for get and getKey.
+ *
+ * @param {string} fn Function name to call on the index to get the request.
+ * @param {string} msg Message to give to the error.
+ * @param {IDBKeyType} key The key to look up in the index.
+ * @return {!goog.async.Deferred} The resulting deferred object.
+ * @private
+ */
+goog.db.Index.prototype.get_ = function(fn, msg, key) {
+ var d = new goog.async.Deferred();
+ var request;
+ try {
+ request = this.index_[fn](key);
+ } catch (err) {
+ msg += ' with key ' + goog.debug.deepExpose(key);
+ d.errback(goog.db.Error.fromException(err, msg));
+ return d;
+ }
+ request.onsuccess = function(ev) {
+ d.callback(ev.target.result);
+ };
+ request.onerror = function(ev) {
+ msg += ' with key ' + goog.debug.deepExpose(key);
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * Fetches a single object from the object store. Even if there are multiple
+ * objects that match the given key, this method will get only one of them.
+ *
+ * @param {IDBKeyType} key Key to look up in the index.
+ * @return {!goog.async.Deferred} The deferred object for the given record.
+ */
+goog.db.Index.prototype.get = function(key) {
+ return this.get_('get', 'getting from index ' + this.getName(), key);
+};
+
+
+/**
+ * Looks up a single object from the object store and gives back the key that
+ * it's listed under in the object store. Even if there are multiple records
+ * that match the given key, this method returns the first.
+ *
+ * @param {IDBKeyType} key Key to look up in the index.
+ * @return {!goog.async.Deferred} The deferred key for the record that matches
+ * the key.
+ */
+goog.db.Index.prototype.getKey = function(key) {
+ return this.get_('getKey', 'getting key from index ' + this.getName(), key);
+};
+
+
+/**
+ * Helper function for getAll and getAllKeys.
+ *
+ * @param {string} fn Function name to call on the index to get the request.
+ * @param {string} msg Message to give to the error.
+ * @param {IDBKeyType=} opt_key Key to look up in the index.
+ * @return {!goog.async.Deferred} The resulting deferred array of objects.
+ * @private
+ */
+goog.db.Index.prototype.getAll_ = function(fn, msg, opt_key) {
+ // This is the most common use of IDBKeyRange. If more specific uses of
+ // cursors are needed then a full wrapper should be created.
+ var IDBKeyRange = goog.global.IDBKeyRange || goog.global.webkitIDBKeyRange;
+ var d = new goog.async.Deferred();
+ var request;
+ try {
+ if (opt_key) {
+ request = this.index_[fn](IDBKeyRange.only(opt_key));
+ } else {
+ request = this.index_[fn]();
+ }
+ } catch (err) {
+ if (opt_key) {
+ msg += ' for key ' + goog.debug.deepExpose(opt_key);
+ }
+ d.errback(goog.db.Error.fromException(err, msg));
+ return d;
+ }
+ var result = [];
+ request.onsuccess = function(ev) {
+ var cursor = ev.target.result;
+ if (cursor) {
+ result.push(cursor.value);
+ cursor['continue']();
+ } else {
+ d.callback(result);
+ }
+ };
+ request.onerror = function(ev) {
+ if (opt_key) {
+ msg += ' for key ' + goog.debug.deepExpose(opt_key);
+ }
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * Gets all indexed objects. If the key is provided, gets all indexed objects
+ * that match the key instead.
+ *
+ * @param {IDBKeyType=} opt_key Key to look up in the index.
+ * @return {!goog.async.Deferred} A deferred array of objects that match the
+ * key.
+ */
+goog.db.Index.prototype.getAll = function(opt_key) {
+ return this.getAll_(
+ 'openCursor',
+ 'getting all from index ' + this.getName(),
+ opt_key);
+};
+
+
+/**
+ * Gets the keys to look up all the indexed objects. If the key is provided,
+ * gets all records for objects that match the key instead.
+ *
+ * @param {IDBKeyType=} opt_key Key to look up in the index.
+ * @return {!goog.async.Deferred} A deferred array of keys for objects that
+ * match the key.
+ */
+goog.db.Index.prototype.getAllKeys = function(opt_key) {
+ return this.getAll_(
+ 'openKeyCursor',
+ 'getting all keys from index ' + this.getName(),
+ opt_key);
+};
+
+
+/**
+ * Opens a cursor over the specified key range. Returns a cursor object which is
+ * able to iterate over the given range.
+ *
+ * Example usage:
+ *
+ * <code>
+ * var cursor = index.openCursor(goog.db.Range.bound('a', 'c'));
+ *
+ * var key = goog.events.listen(
+ * cursor, goog.db.Cursor.EventType.NEW_DATA,
+ * function() {
+ * // Do something with data.
+ * cursor.next();
+ * });
+ *
+ * goog.events.listenOnce(
+ * cursor, goog.db.Cursor.EventType.COMPLETE,
+ * function() {
+ * // Clean up listener, and perform a finishing operation on the data.
+ * goog.events.unlistenByKey(key);
+ * });
+ * </code>
+ *
+ * @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
+ * over the whole object store.
+ * @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
+ * moves in a forward direction with duplicates.
+ * @return {!goog.db.Cursor} The cursor.
+ * @throws {goog.db.Error} If there was a problem opening the cursor.
+ */
+goog.db.Index.prototype.openCursor = function(opt_range, opt_direction) {
+ return goog.db.Cursor.openCursor(this.index_, opt_range, opt_direction);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/indexeddb.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/indexeddb.js b/externs/GCL/externs/goog/db/indexeddb.js
new file mode 100644
index 0000000..33ad3aa
--- /dev/null
+++ b/externs/GCL/externs/goog/db/indexeddb.js
@@ -0,0 +1,353 @@
+// 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 Wrapper for an IndexedDB database.
+ *
+ */
+
+
+goog.provide('goog.db.IndexedDb');
+
+goog.require('goog.async.Deferred');
+goog.require('goog.db.Error');
+goog.require('goog.db.ObjectStore');
+goog.require('goog.db.Transaction');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+
+
+
+/**
+ * Creates an IDBDatabase wrapper object. The database object has methods for
+ * setting the version to change the structure of the database and for creating
+ * transactions to get or modify the stored records. Should not be created
+ * directly, call {@link goog.db.openDatabase} to set up the connection.
+ *
+ * @param {!IDBDatabase} db Underlying IndexedDB database object.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.db.IndexedDb = function(db) {
+ goog.db.IndexedDb.base(this, 'constructor');
+
+ /**
+ * Underlying IndexedDB database object.
+ *
+ * @type {!IDBDatabase}
+ * @private
+ */
+ this.db_ = db;
+
+ /**
+ * Internal event handler that listens to IDBDatabase events.
+ * @type {!goog.events.EventHandler<!goog.db.IndexedDb>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ this.eventHandler_.listen(
+ this.db_,
+ goog.db.IndexedDb.EventType.ABORT,
+ goog.bind(
+ this.dispatchEvent,
+ this,
+ goog.db.IndexedDb.EventType.ABORT));
+ this.eventHandler_.listen(
+ this.db_,
+ goog.db.IndexedDb.EventType.ERROR,
+ this.dispatchError_);
+ this.eventHandler_.listen(
+ this.db_,
+ goog.db.IndexedDb.EventType.VERSION_CHANGE,
+ this.dispatchVersionChange_);
+ this.eventHandler_.listen(
+ this.db_,
+ goog.db.IndexedDb.EventType.CLOSE,
+ goog.bind(
+ this.dispatchEvent,
+ this,
+ goog.db.IndexedDb.EventType.CLOSE));
+};
+goog.inherits(goog.db.IndexedDb, goog.events.EventTarget);
+
+
+/**
+ * True iff the database connection is open.
+ *
+ * @type {boolean}
+ * @private
+ */
+goog.db.IndexedDb.prototype.open_ = true;
+
+
+/**
+ * Dispatches a wrapped error event based on the given event.
+ *
+ * @param {Event} ev The error event given to the underlying IDBDatabase.
+ * @private
+ */
+goog.db.IndexedDb.prototype.dispatchError_ = function(ev) {
+ this.dispatchEvent({
+ type: goog.db.IndexedDb.EventType.ERROR,
+ errorCode: /** @type {IDBRequest} */ (ev.target).errorCode
+ });
+};
+
+
+/**
+ * Dispatches a wrapped version change event based on the given event.
+ *
+ * @param {Event} ev The version change event given to the underlying
+ * IDBDatabase.
+ * @private
+ */
+goog.db.IndexedDb.prototype.dispatchVersionChange_ = function(ev) {
+ this.dispatchEvent(new goog.db.IndexedDb.VersionChangeEvent(
+ ev.oldVersion, ev.newVersion));
+};
+
+
+/**
+ * Closes the database connection. Metadata queries can still be made after this
+ * method is called, but otherwise this wrapper should not be used further.
+ */
+goog.db.IndexedDb.prototype.close = function() {
+ if (this.open_) {
+ this.db_.close();
+ this.open_ = false;
+ }
+};
+
+
+/**
+ * @return {boolean} Whether a connection is open and the database can be used.
+ */
+goog.db.IndexedDb.prototype.isOpen = function() {
+ return this.open_;
+};
+
+
+/**
+ * @return {string} The name of this database.
+ */
+goog.db.IndexedDb.prototype.getName = function() {
+ return this.db_.name;
+};
+
+
+/**
+ * @return {string} The current database version.
+ */
+goog.db.IndexedDb.prototype.getVersion = function() {
+ return this.db_.version;
+};
+
+
+/**
+ * @return {DOMStringList} List of object stores in this database.
+ */
+goog.db.IndexedDb.prototype.getObjectStoreNames = function() {
+ return this.db_.objectStoreNames;
+};
+
+
+/**
+ * Creates an object store in this database. Can only be called inside a
+ * {@link goog.db.UpgradeNeededCallback} or the callback for the Deferred
+ * returned from #setVersion.
+ *
+ * @param {string} name Name for the new object store.
+ * @param {Object=} opt_params Options object. The available options are:
+ * keyPath, which is a string and determines what object attribute
+ * to use as the key when storing objects in this object store; and
+ * autoIncrement, which is a boolean, which defaults to false and determines
+ * whether the object store should automatically generate keys for stored
+ * objects. If keyPath is not provided and autoIncrement is false, then all
+ * insert operations must provide a key as a parameter.
+ * @return {!goog.db.ObjectStore} The newly created object store.
+ * @throws {goog.db.Error} If there's a problem creating the object store.
+ */
+goog.db.IndexedDb.prototype.createObjectStore = function(name, opt_params) {
+ try {
+ return new goog.db.ObjectStore(this.db_.createObjectStore(
+ name, opt_params));
+ } catch (ex) {
+ throw goog.db.Error.fromException(ex, 'creating object store ' + name);
+ }
+};
+
+
+/**
+ * Deletes an object store. Can only be called inside a
+ * {@link goog.db.UpgradeNeededCallback} or the callback for the Deferred
+ * returned from #setVersion.
+ *
+ * @param {string} name Name of the object store to delete.
+ * @throws {goog.db.Error} If there's a problem deleting the object store.
+ */
+goog.db.IndexedDb.prototype.deleteObjectStore = function(name) {
+ try {
+ this.db_.deleteObjectStore(name);
+ } catch (ex) {
+ throw goog.db.Error.fromException(ex, 'deleting object store ' + name);
+ }
+};
+
+
+/**
+ * Updates the version of the database and returns a Deferred transaction.
+ * The database's structure can be changed inside this Deferred's callback, but
+ * nowhere else. This means adding or deleting object stores, and adding or
+ * deleting indexes. The version change will not succeed unless there are no
+ * other connections active for this database anywhere. A new database
+ * connection should be opened after the version change is finished to pick
+ * up changes.
+ *
+ * This is deprecated, and only supported on Chrome prior to version 25. New
+ * applications should use the version parameter to {@link goog.db.openDatabase}
+ * instead.
+ *
+ * @param {string} version The new version of the database.
+ * @return {!goog.async.Deferred} The deferred transaction for changing the
+ * version.
+ */
+goog.db.IndexedDb.prototype.setVersion = function(version) {
+ var self = this;
+ var d = new goog.async.Deferred();
+ var request = this.db_.setVersion(version);
+ request.onsuccess = function(ev) {
+ // the transaction is in the result field (the transaction field is null
+ // for version change requests)
+ d.callback(new goog.db.Transaction(ev.target.result, self));
+ };
+ request.onerror = function(ev) {
+ // If a version change is blocked, onerror and onblocked may both fire.
+ // Check d.hasFired() to avoid an AlreadyCalledError.
+ if (!d.hasFired()) {
+ d.errback(goog.db.Error.fromRequest(ev.target, 'setting version'));
+ }
+ };
+ request.onblocked = function(ev) {
+ // If a version change is blocked, onerror and onblocked may both fire.
+ // Check d.hasFired() to avoid an AlreadyCalledError.
+ if (!d.hasFired()) {
+ d.errback(new goog.db.Error.VersionChangeBlockedError());
+ }
+ };
+ return d;
+};
+
+
+/**
+ * Creates a new transaction.
+ *
+ * @param {!Array<string>} storeNames A list of strings that contains the
+ * transaction's scope, the object stores that this transaction can operate
+ * on.
+ * @param {goog.db.Transaction.TransactionMode=} opt_mode The mode of the
+ * transaction. If not present, the default is READ_ONLY. For VERSION_CHANGE
+ * transactions call {@link goog.db.IndexedDB#setVersion} instead.
+ * @return {!goog.db.Transaction} The wrapper for the newly created transaction.
+ * @throws {goog.db.Error} If there's a problem creating the transaction.
+ */
+goog.db.IndexedDb.prototype.createTransaction = function(storeNames, opt_mode) {
+ try {
+ // IndexedDB on Chrome 22+ requires that opt_mode not be passed rather than
+ // be explicitly passed as undefined.
+ var transaction = opt_mode ?
+ this.db_.transaction(storeNames, opt_mode) :
+ this.db_.transaction(storeNames);
+ return new goog.db.Transaction(transaction, this);
+ } catch (ex) {
+ throw goog.db.Error.fromException(ex, 'creating transaction');
+ }
+};
+
+
+/** @override */
+goog.db.IndexedDb.prototype.disposeInternal = function() {
+ goog.db.IndexedDb.base(this, 'disposeInternal');
+ this.eventHandler_.dispose();
+};
+
+
+/**
+ * Event types fired by a database.
+ *
+ * @enum {string} The event types for the web socket.
+ */
+goog.db.IndexedDb.EventType = {
+
+ /**
+ * Fired when a transaction is aborted and the event bubbles to its database.
+ */
+ ABORT: 'abort',
+
+ /**
+ * Fired when the database connection is forcibly closed by the browser,
+ * without an explicit call to IDBDatabase#close. This behavior is not in the
+ * spec yet but will be added since it is necessary, see
+ * https://www.w3.org/Bugs/Public/show_bug.cgi?id=22540.
+ */
+ CLOSE: 'close',
+
+ /**
+ * Fired when a transaction has an error.
+ */
+ ERROR: 'error',
+
+ /**
+ * Fired when someone (possibly in another window) is attempting to modify the
+ * structure of the database. Since a change can only be made when there are
+ * no active database connections, this usually means that the database should
+ * be closed so that the other client can make its changes.
+ */
+ VERSION_CHANGE: 'versionchange'
+};
+
+
+
+/**
+ * Event representing a (possibly attempted) change in the database structure.
+ *
+ * At time of writing, no Chrome versions support oldVersion or newVersion. See
+ * http://crbug.com/153122.
+ *
+ * @param {number} oldVersion The previous version of the database.
+ * @param {number} newVersion The version the database is being or has been
+ * updated to.
+ * @constructor
+ * @extends {goog.events.Event}
+ * @final
+ */
+goog.db.IndexedDb.VersionChangeEvent = function(oldVersion, newVersion) {
+ goog.db.IndexedDb.VersionChangeEvent.base(
+ this, 'constructor', goog.db.IndexedDb.EventType.VERSION_CHANGE);
+
+ /**
+ * The previous version of the database.
+ * @type {number}
+ */
+ this.oldVersion = oldVersion;
+
+ /**
+ * The version the database is being or has been updated to.
+ * @type {number}
+ */
+ this.newVersion = newVersion;
+};
+goog.inherits(goog.db.IndexedDb.VersionChangeEvent, goog.events.Event);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/keyrange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/keyrange.js b/externs/GCL/externs/goog/db/keyrange.js
new file mode 100644
index 0000000..d1e4099
--- /dev/null
+++ b/externs/GCL/externs/goog/db/keyrange.js
@@ -0,0 +1,118 @@
+// Copyright 2012 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 Wrapper for a IndexedDB key range.
+ *
+ */
+
+
+goog.provide('goog.db.KeyRange');
+
+
+
+/**
+ * Creates a new IDBKeyRange wrapper object. Should not be created directly,
+ * instead use one of the static factory methods. For example:
+ * @see goog.db.KeyRange.bound
+ * @see goog.db.KeyRange.lowerBound
+ *
+ * @param {!IDBKeyRange} range Underlying IDBKeyRange object.
+ * @constructor
+ * @final
+ */
+goog.db.KeyRange = function(range) {
+ /**
+ * Underlying IDBKeyRange object.
+ *
+ * @type {!IDBKeyRange}
+ * @private
+ */
+ this.range_ = range;
+};
+
+
+/**
+ * The IDBKeyRange.
+ * @type {!Object}
+ * @private
+ */
+goog.db.KeyRange.IDB_KEY_RANGE_ = goog.global.IDBKeyRange ||
+ goog.global.webkitIDBKeyRange;
+
+
+/**
+ * Creates a new key range for a single value.
+ *
+ * @param {IDBKeyType} key The single value in the range.
+ * @return {!goog.db.KeyRange} The key range.
+ */
+goog.db.KeyRange.only = function(key) {
+ return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.only(key));
+};
+
+
+/**
+ * Creates a key range with upper and lower bounds.
+ *
+ * @param {IDBKeyType} lower The value of the lower bound.
+ * @param {IDBKeyType} upper The value of the upper bound.
+ * @param {boolean=} opt_lowerOpen If true, the range excludes the lower bound
+ * value.
+ * @param {boolean=} opt_upperOpen If true, the range excludes the upper bound
+ * value.
+ * @return {!goog.db.KeyRange} The key range.
+ */
+goog.db.KeyRange.bound = function(lower, upper, opt_lowerOpen, opt_upperOpen) {
+ return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.bound(
+ lower, upper, opt_lowerOpen, opt_upperOpen));
+};
+
+
+/**
+ * Creates a key range with a lower bound only, finishes at the last record.
+ *
+ * @param {IDBKeyType} lower The value of the lower bound.
+ * @param {boolean=} opt_lowerOpen If true, the range excludes the lower bound
+ * value.
+ * @return {!goog.db.KeyRange} The key range.
+ */
+goog.db.KeyRange.lowerBound = function(lower, opt_lowerOpen) {
+ return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.lowerBound(
+ lower, opt_lowerOpen));
+};
+
+
+/**
+ * Creates a key range with a upper bound only, starts at the first record.
+ *
+ * @param {IDBKeyType} upper The value of the upper bound.
+ * @param {boolean=} opt_upperOpen If true, the range excludes the upper bound
+ * value.
+ * @return {!goog.db.KeyRange} The key range.
+ */
+goog.db.KeyRange.upperBound = function(upper, opt_upperOpen) {
+ return new goog.db.KeyRange(goog.db.KeyRange.IDB_KEY_RANGE_.upperBound(
+ upper, opt_upperOpen));
+};
+
+
+/**
+ * Returns underlying key range object. This is used in ObjectStore's openCursor
+ * and count methods.
+ * @return {!IDBKeyRange}
+ */
+goog.db.KeyRange.prototype.range = function() {
+ return this.range_;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/objectstore.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/objectstore.js b/externs/GCL/externs/goog/db/objectstore.js
new file mode 100644
index 0000000..dbaae37
--- /dev/null
+++ b/externs/GCL/externs/goog/db/objectstore.js
@@ -0,0 +1,400 @@
+// 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 Wrapper for an IndexedDB object store.
+ *
+ */
+
+
+goog.provide('goog.db.ObjectStore');
+
+goog.require('goog.async.Deferred');
+goog.require('goog.db.Cursor');
+goog.require('goog.db.Error');
+goog.require('goog.db.Index');
+goog.require('goog.debug');
+goog.require('goog.events');
+
+
+
+/**
+ * Creates an IDBObjectStore wrapper object. Object stores have methods for
+ * storing and retrieving records, and are accessed through a transaction
+ * object. They also have methods for creating indexes associated with the
+ * object store. They can only be created when setting the version of the
+ * database. Should not be created directly, access object stores through
+ * transactions.
+ * @see goog.db.IndexedDb#setVersion
+ * @see goog.db.Transaction#objectStore
+ *
+ * @param {!IDBObjectStore} store The backing IndexedDb object.
+ * @constructor
+ *
+ * TODO(arthurhsu): revisit msg in exception and errors in this class. In newer
+ * Chrome (v22+) the error/request come with a DOM error string that is
+ * already very descriptive.
+ * @final
+ */
+goog.db.ObjectStore = function(store) {
+ /**
+ * Underlying IndexedDB object store object.
+ *
+ * @type {!IDBObjectStore}
+ * @private
+ */
+ this.store_ = store;
+};
+
+
+/**
+ * @return {string} The name of the object store.
+ */
+goog.db.ObjectStore.prototype.getName = function() {
+ return this.store_.name;
+};
+
+
+/**
+ * Helper function for put and add.
+ *
+ * @param {string} fn Function name to call on the object store.
+ * @param {string} msg Message to give to the error.
+ * @param {*} value Value to insert into the object store.
+ * @param {IDBKeyType=} opt_key The key to use.
+ * @return {!goog.async.Deferred} The resulting deferred request.
+ * @private
+ */
+goog.db.ObjectStore.prototype.insert_ = function(fn, msg, value, opt_key) {
+ // TODO(user): refactor wrapping an IndexedDB request in a Deferred by
+ // creating a higher-level abstraction for it (mostly affects here and
+ // goog.db.Index)
+ var d = new goog.async.Deferred();
+ var request;
+ try {
+ // put or add with (value, undefined) throws an error, so we need to check
+ // for undefined ourselves
+ if (opt_key) {
+ request = this.store_[fn](value, opt_key);
+ } else {
+ request = this.store_[fn](value);
+ }
+ } catch (ex) {
+ msg += goog.debug.deepExpose(value);
+ if (opt_key) {
+ msg += ', with key ' + goog.debug.deepExpose(opt_key);
+ }
+ d.errback(goog.db.Error.fromException(ex, msg));
+ return d;
+ }
+ request.onsuccess = function(ev) {
+ d.callback();
+ };
+ request.onerror = function(ev) {
+ msg += goog.debug.deepExpose(value);
+ if (opt_key) {
+ msg += ', with key ' + goog.debug.deepExpose(opt_key);
+ }
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * Adds an object to the object store. Replaces existing objects with the
+ * same key.
+ *
+ * @param {*} value The value to put.
+ * @param {IDBKeyType=} opt_key The key to use. Cannot be used if the
+ * keyPath was specified for the object store. If the keyPath was not
+ * specified but autoIncrement was not enabled, it must be used.
+ * @return {!goog.async.Deferred} The deferred put request.
+ */
+goog.db.ObjectStore.prototype.put = function(value, opt_key) {
+ return this.insert_(
+ 'put',
+ 'putting into ' + this.getName() + ' with value',
+ value,
+ opt_key);
+};
+
+
+/**
+ * Adds an object to the object store. Requires that there is no object with
+ * the same key already present.
+ *
+ * @param {*} value The value to add.
+ * @param {IDBKeyType=} opt_key The key to use. Cannot be used if the
+ * keyPath was specified for the object store. If the keyPath was not
+ * specified but autoIncrement was not enabled, it must be used.
+ * @return {!goog.async.Deferred} The deferred add request.
+ */
+goog.db.ObjectStore.prototype.add = function(value, opt_key) {
+ return this.insert_(
+ 'add',
+ 'adding into ' + this.getName() + ' with value ',
+ value,
+ opt_key);
+};
+
+
+/**
+ * Removes an object from the store. No-op if there is no object present with
+ * the given key.
+ *
+ * @param {IDBKeyType} key The key to remove objects under.
+ * @return {!goog.async.Deferred} The deferred remove request.
+ */
+goog.db.ObjectStore.prototype.remove = function(key) {
+ var d = new goog.async.Deferred();
+ var request;
+ try {
+ request = this.store_['delete'](key);
+ } catch (err) {
+ var msg = 'removing from ' + this.getName() + ' with key ' +
+ goog.debug.deepExpose(key);
+ d.errback(goog.db.Error.fromException(err, msg));
+ return d;
+ }
+ request.onsuccess = function(ev) {
+ d.callback();
+ };
+ var self = this;
+ request.onerror = function(ev) {
+ var msg = 'removing from ' + self.getName() + ' with key ' +
+ goog.debug.deepExpose(key);
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * Gets an object from the store. If no object is present with that key
+ * the result is {@code undefined}.
+ *
+ * @param {IDBKeyType} key The key to look up.
+ * @return {!goog.async.Deferred} The deferred get request.
+ */
+goog.db.ObjectStore.prototype.get = function(key) {
+ var d = new goog.async.Deferred();
+ var request;
+ try {
+ request = this.store_.get(key);
+ } catch (err) {
+ var msg = 'getting from ' + this.getName() + ' with key ' +
+ goog.debug.deepExpose(key);
+ d.errback(goog.db.Error.fromException(err, msg));
+ return d;
+ }
+ request.onsuccess = function(ev) {
+ d.callback(ev.target.result);
+ };
+ var self = this;
+ request.onerror = function(ev) {
+ var msg = 'getting from ' + self.getName() + ' with key ' +
+ goog.debug.deepExpose(key);
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * Gets all objects from the store and returns them as an array.
+ *
+ * @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
+ * over the whole object store.
+ * @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
+ * moves in a forward direction with duplicates.
+ * @return {!goog.async.Deferred} The deferred getAll request.
+ */
+goog.db.ObjectStore.prototype.getAll = function(opt_range, opt_direction) {
+ var d = new goog.async.Deferred();
+ var cursor;
+ try {
+ cursor = this.openCursor(opt_range, opt_direction);
+ } catch (err) {
+ d.errback(err);
+ return d;
+ }
+
+ var result = [];
+ var key = goog.events.listen(
+ cursor, goog.db.Cursor.EventType.NEW_DATA, function() {
+ result.push(cursor.getValue());
+ cursor.next();
+ });
+
+ goog.events.listenOnce(cursor, [
+ goog.db.Cursor.EventType.ERROR,
+ goog.db.Cursor.EventType.COMPLETE
+ ], function(evt) {
+ cursor.dispose();
+ if (evt.type == goog.db.Cursor.EventType.COMPLETE) {
+ d.callback(result);
+ } else {
+ d.errback();
+ }
+ });
+ return d;
+};
+
+
+/**
+ * Opens a cursor over the specified key range. Returns a cursor object which is
+ * able to iterate over the given range.
+ *
+ * Example usage:
+ *
+ * <code>
+ * var cursor = objectStore.openCursor(goog.db.Range.bound('a', 'c'));
+ *
+ * var key = goog.events.listen(
+ * cursor, goog.db.Cursor.EventType.NEW_DATA, function() {
+ * // Do something with data.
+ * cursor.next();
+ * });
+ *
+ * goog.events.listenOnce(
+ * cursor, goog.db.Cursor.EventType.COMPLETE, function() {
+ * // Clean up listener, and perform a finishing operation on the data.
+ * goog.events.unlistenByKey(key);
+ * });
+ * </code>
+ *
+ * @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
+ * over the whole object store.
+ * @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
+ * moves in a forward direction with duplicates.
+ * @return {!goog.db.Cursor} The cursor.
+ * @throws {goog.db.Error} If there was a problem opening the cursor.
+ */
+goog.db.ObjectStore.prototype.openCursor = function(opt_range, opt_direction) {
+ return goog.db.Cursor.openCursor(this.store_, opt_range, opt_direction);
+};
+
+
+/**
+ * Deletes all objects from the store.
+ *
+ * @return {!goog.async.Deferred} The deferred clear request.
+ */
+goog.db.ObjectStore.prototype.clear = function() {
+ var msg = 'clearing store ' + this.getName();
+ var d = new goog.async.Deferred();
+ var request;
+ try {
+ request = this.store_.clear();
+ } catch (err) {
+ d.errback(goog.db.Error.fromException(err, msg));
+ return d;
+ }
+ request.onsuccess = function(ev) {
+ d.callback();
+ };
+ request.onerror = function(ev) {
+ d.errback(goog.db.Error.fromRequest(ev.target, msg));
+ };
+ return d;
+};
+
+
+/**
+ * Creates an index in this object store. Can only be called inside the callback
+ * for the Deferred returned from goog.db.IndexedDb#setVersion.
+ *
+ * @param {string} name Name of the index to create.
+ * @param {string} keyPath Attribute to index on.
+ * @param {!Object=} opt_parameters Optional parameters object. The only
+ * available option is unique, which defaults to false. If unique is true,
+ * the index will enforce that there is only ever one object in the object
+ * store for each unique value it indexes on.
+ * @return {!goog.db.Index} The newly created, wrapped index.
+ * @throws {goog.db.Error} In case of an error creating the index.
+ */
+goog.db.ObjectStore.prototype.createIndex = function(
+ name, keyPath, opt_parameters) {
+ try {
+ return new goog.db.Index(this.store_.createIndex(
+ name, keyPath, opt_parameters));
+ } catch (ex) {
+ var msg = 'creating new index ' + name + ' with key path ' + keyPath;
+ throw goog.db.Error.fromException(ex, msg);
+ }
+};
+
+
+/**
+ * Gets an index.
+ *
+ * @param {string} name Name of the index to fetch.
+ * @return {!goog.db.Index} The requested wrapped index.
+ * @throws {goog.db.Error} In case of an error getting the index.
+ */
+goog.db.ObjectStore.prototype.getIndex = function(name) {
+ try {
+ return new goog.db.Index(this.store_.index(name));
+ } catch (ex) {
+ var msg = 'getting index ' + name;
+ throw goog.db.Error.fromException(ex, msg);
+ }
+};
+
+
+/**
+ * Deletes an index from the object store. Can only be called inside the
+ * callback for the Deferred returned from goog.db.IndexedDb#setVersion.
+ *
+ * @param {string} name Name of the index to delete.
+ * @throws {goog.db.Error} In case of an error deleting the index.
+ */
+goog.db.ObjectStore.prototype.deleteIndex = function(name) {
+ try {
+ this.store_.deleteIndex(name);
+ } catch (ex) {
+ var msg = 'deleting index ' + name;
+ throw goog.db.Error.fromException(ex, msg);
+ }
+};
+
+
+/**
+ * Gets number of records within a key range.
+ *
+ * @param {!goog.db.KeyRange=} opt_range The key range. If undefined, this will
+ * count all records in the object store.
+ * @return {!goog.async.Deferred} The deferred number of records.
+ */
+goog.db.ObjectStore.prototype.count = function(opt_range) {
+ var d = new goog.async.Deferred();
+
+ try {
+ var range = opt_range ? opt_range.range() : null;
+ var request = this.store_.count(range);
+ request.onsuccess = function(ev) {
+ d.callback(ev.target.result);
+ };
+ var self = this;
+ request.onerror = function(ev) {
+ d.errback(goog.db.Error.fromRequest(ev.target, self.getName()));
+ };
+ } catch (ex) {
+ d.errback(goog.db.Error.fromException(ex, this.getName()));
+ }
+
+ return d;
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/db/transaction.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/db/transaction.js b/externs/GCL/externs/goog/db/transaction.js
new file mode 100644
index 0000000..8206a25
--- /dev/null
+++ b/externs/GCL/externs/goog/db/transaction.js
@@ -0,0 +1,223 @@
+// 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 Wrapper for an IndexedDB transaction.
+ *
+ */
+
+
+goog.provide('goog.db.Transaction');
+goog.provide('goog.db.Transaction.TransactionMode');
+
+goog.require('goog.async.Deferred');
+goog.require('goog.db.Error');
+goog.require('goog.db.ObjectStore');
+goog.require('goog.events');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+
+
+
+/**
+ * Creates a new transaction. Transactions contain methods for accessing object
+ * stores and are created from the database object. Should not be created
+ * directly, open a database and call createTransaction on it.
+ * @see goog.db.IndexedDb#createTransaction
+ *
+ * @param {!IDBTransaction} tx IndexedDB transaction to back this wrapper.
+ * @param {!goog.db.IndexedDb} db The database that this transaction modifies.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.db.Transaction = function(tx, db) {
+ goog.db.Transaction.base(this, 'constructor');
+
+ /**
+ * Underlying IndexedDB transaction object.
+ *
+ * @type {!IDBTransaction}
+ * @private
+ */
+ this.tx_ = tx;
+
+ /**
+ * The database that this transaction modifies.
+ *
+ * @type {!goog.db.IndexedDb}
+ * @private
+ */
+ this.db_ = db;
+
+ /**
+ * Event handler for this transaction.
+ *
+ * @type {!goog.events.EventHandler<!goog.db.Transaction>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ // TODO(user): remove these casts once the externs file is updated to
+ // correctly reflect that IDBTransaction extends EventTarget
+ this.eventHandler_.listen(
+ /** @type {!EventTarget} */ (this.tx_),
+ 'complete',
+ goog.bind(
+ this.dispatchEvent,
+ this,
+ goog.db.Transaction.EventTypes.COMPLETE));
+ this.eventHandler_.listen(
+ /** @type {!EventTarget} */ (this.tx_),
+ 'abort',
+ goog.bind(
+ this.dispatchEvent,
+ this,
+ goog.db.Transaction.EventTypes.ABORT));
+ this.eventHandler_.listen(
+ /** @type {!EventTarget} */ (this.tx_),
+ 'error',
+ this.dispatchError_);
+};
+goog.inherits(goog.db.Transaction, goog.events.EventTarget);
+
+
+/**
+ * Dispatches an error event based on the given event, wrapping the error
+ * if necessary.
+ *
+ * @param {Event} ev The error event given to the underlying IDBTransaction.
+ * @private
+ */
+goog.db.Transaction.prototype.dispatchError_ = function(ev) {
+ if (ev.target instanceof goog.db.Error) {
+ this.dispatchEvent({
+ type: goog.db.Transaction.EventTypes.ERROR,
+ target: ev.target
+ });
+ } else {
+ this.dispatchEvent({
+ type: goog.db.Transaction.EventTypes.ERROR,
+ target: goog.db.Error.fromRequest(
+ /** @type {!IDBRequest} */ (ev.target), 'in transaction')
+ });
+ }
+};
+
+
+/**
+ * Event types the Transaction can dispatch. COMPLETE events are dispatched
+ * when the transaction is committed. If a transaction is aborted it dispatches
+ * both an ABORT event and an ERROR event with the ABORT_ERR code. Error events
+ * are dispatched on any error.
+ *
+ * @enum {string}
+ */
+goog.db.Transaction.EventTypes = {
+ COMPLETE: 'complete',
+ ABORT: 'abort',
+ ERROR: 'error'
+};
+
+
+/**
+ * @return {goog.db.Transaction.TransactionMode} The transaction's mode.
+ */
+goog.db.Transaction.prototype.getMode = function() {
+ return /** @type {goog.db.Transaction.TransactionMode} */ (this.tx_.mode);
+};
+
+
+/**
+ * @return {!goog.db.IndexedDb} The database that this transaction modifies.
+ */
+goog.db.Transaction.prototype.getDatabase = function() {
+ return this.db_;
+};
+
+
+/**
+ * Opens an object store to do operations on in this transaction. The requested
+ * object store must be one that is in this transaction's scope.
+ * @see goog.db.IndexedDb#createTransaction
+ *
+ * @param {string} name The name of the requested object store.
+ * @return {!goog.db.ObjectStore} The wrapped object store.
+ * @throws {goog.db.Error} In case of error getting the object store.
+ */
+goog.db.Transaction.prototype.objectStore = function(name) {
+ try {
+ return new goog.db.ObjectStore(this.tx_.objectStore(name));
+ } catch (ex) {
+ throw goog.db.Error.fromException(ex, 'getting object store ' + name);
+ }
+};
+
+
+/**
+ * @return {!goog.async.Deferred} A deferred that will fire once the
+ * transaction is complete. It fires the errback chain if an error occurs
+ * in the transaction, or if it is aborted.
+ */
+goog.db.Transaction.prototype.wait = function() {
+ var d = new goog.async.Deferred();
+ goog.events.listenOnce(
+ this, goog.db.Transaction.EventTypes.COMPLETE, goog.bind(d.callback, d));
+ var errorKey;
+ var abortKey = goog.events.listenOnce(
+ this, goog.db.Transaction.EventTypes.ABORT, function() {
+ goog.events.unlistenByKey(errorKey);
+ d.errback(new goog.db.Error(goog.db.Error.ErrorCode.ABORT_ERR,
+ 'waiting for transaction to complete'));
+ });
+ errorKey = goog.events.listenOnce(
+ this, goog.db.Transaction.EventTypes.ERROR, function(e) {
+ goog.events.unlistenByKey(abortKey);
+ d.errback(e.target);
+ });
+
+ var db = this.getDatabase();
+ return d.addCallback(function() {
+ return db;
+ });
+};
+
+
+/**
+ * Aborts this transaction. No pending operations will be applied to the
+ * database. Dispatches an ABORT event.
+ */
+goog.db.Transaction.prototype.abort = function() {
+ this.tx_.abort();
+};
+
+
+/** @override */
+goog.db.Transaction.prototype.disposeInternal = function() {
+ goog.db.Transaction.base(this, 'disposeInternal');
+ this.eventHandler_.dispose();
+};
+
+
+/**
+ * The three possible transaction modes.
+ * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBTransaction
+ *
+ * @enum {string}
+ */
+goog.db.Transaction.TransactionMode = {
+ READ_ONLY: 'readonly',
+ READ_WRITE: 'readwrite',
+ VERSION_CHANGE: 'versionchange'
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/debug/console.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/debug/console.js b/externs/GCL/externs/goog/debug/console.js
new file mode 100644
index 0000000..89c6cce
--- /dev/null
+++ b/externs/GCL/externs/goog/debug/console.js
@@ -0,0 +1,207 @@
+// 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 Simple logger that logs to the window console if available.
+ *
+ * Has an autoInstall option which can be put into initialization code, which
+ * will start logging if "Debug=true" is in document.location.href
+ *
+ */
+
+goog.provide('goog.debug.Console');
+
+goog.require('goog.debug.LogManager');
+goog.require('goog.debug.Logger');
+goog.require('goog.debug.TextFormatter');
+
+
+
+/**
+ * Create and install a log handler that logs to window.console if available
+ * @constructor
+ */
+goog.debug.Console = function() {
+ this.publishHandler_ = goog.bind(this.addLogRecord, this);
+
+ /**
+ * Formatter for formatted output.
+ * @type {!goog.debug.TextFormatter}
+ * @private
+ */
+ this.formatter_ = new goog.debug.TextFormatter();
+ this.formatter_.showAbsoluteTime = false;
+ this.formatter_.showExceptionText = false;
+ // The console logging methods automatically append a newline.
+ this.formatter_.appendNewline = false;
+
+ this.isCapturing_ = false;
+ this.logBuffer_ = '';
+
+ /**
+ * Loggers that we shouldn't output.
+ * @type {!Object<boolean>}
+ * @private
+ */
+ this.filteredLoggers_ = {};
+};
+
+
+/**
+ * Returns the text formatter used by this console
+ * @return {!goog.debug.TextFormatter} The text formatter.
+ */
+goog.debug.Console.prototype.getFormatter = function() {
+ return this.formatter_;
+};
+
+
+/**
+ * Sets whether we are currently capturing logger output.
+ * @param {boolean} capturing Whether to capture logger output.
+ */
+goog.debug.Console.prototype.setCapturing = function(capturing) {
+ if (capturing == this.isCapturing_) {
+ return;
+ }
+
+ // attach or detach handler from the root logger
+ var rootLogger = goog.debug.LogManager.getRoot();
+ if (capturing) {
+ rootLogger.addHandler(this.publishHandler_);
+ } else {
+ rootLogger.removeHandler(this.publishHandler_);
+ this.logBuffer = '';
+ }
+ this.isCapturing_ = capturing;
+};
+
+
+/**
+ * Adds a log record.
+ * @param {goog.debug.LogRecord} logRecord The log entry.
+ */
+goog.debug.Console.prototype.addLogRecord = function(logRecord) {
+
+ // Check to see if the log record is filtered or not.
+ if (this.filteredLoggers_[logRecord.getLoggerName()]) {
+ return;
+ }
+
+ var record = this.formatter_.formatRecord(logRecord);
+ var console = goog.debug.Console.console_;
+ if (console) {
+ switch (logRecord.getLevel()) {
+ case goog.debug.Logger.Level.SHOUT:
+ goog.debug.Console.logToConsole_(console, 'info', record);
+ break;
+ case goog.debug.Logger.Level.SEVERE:
+ goog.debug.Console.logToConsole_(console, 'error', record);
+ break;
+ case goog.debug.Logger.Level.WARNING:
+ goog.debug.Console.logToConsole_(console, 'warn', record);
+ break;
+ default:
+ goog.debug.Console.logToConsole_(console, 'debug', record);
+ break;
+ }
+ } else {
+ this.logBuffer_ += record;
+ }
+};
+
+
+/**
+ * Adds a logger name to be filtered.
+ * @param {string} loggerName the logger name to add.
+ */
+goog.debug.Console.prototype.addFilter = function(loggerName) {
+ this.filteredLoggers_[loggerName] = true;
+};
+
+
+/**
+ * Removes a logger name to be filtered.
+ * @param {string} loggerName the logger name to remove.
+ */
+goog.debug.Console.prototype.removeFilter = function(loggerName) {
+ delete this.filteredLoggers_[loggerName];
+};
+
+
+/**
+ * Global console logger instance
+ * @type {goog.debug.Console}
+ */
+goog.debug.Console.instance = null;
+
+
+/**
+ * The console to which to log. This is a property so it can be mocked out in
+ * this unit test for goog.debug.Console. Using goog.global, as console might be
+ * used in window-less contexts.
+ * @type {Object}
+ * @private
+ */
+goog.debug.Console.console_ = goog.global['console'];
+
+
+/**
+ * Sets the console to which to log.
+ * @param {!Object} console The console to which to log.
+ */
+goog.debug.Console.setConsole = function(console) {
+ goog.debug.Console.console_ = console;
+};
+
+
+/**
+ * Install the console and start capturing if "Debug=true" is in the page URL
+ */
+goog.debug.Console.autoInstall = function() {
+ if (!goog.debug.Console.instance) {
+ goog.debug.Console.instance = new goog.debug.Console();
+ }
+
+ if (goog.global.location &&
+ goog.global.location.href.indexOf('Debug=true') != -1) {
+ goog.debug.Console.instance.setCapturing(true);
+ }
+};
+
+
+/**
+ * Show an alert with all of the captured debug information.
+ * Information is only captured if console is not available
+ */
+goog.debug.Console.show = function() {
+ alert(goog.debug.Console.instance.logBuffer_);
+};
+
+
+/**
+ * Logs the record to the console using the given function. If the function is
+ * not available on the console object, the log function is used instead.
+ * @param {!Object} console The console object.
+ * @param {string} fnName The name of the function to use.
+ * @param {string} record The record to log.
+ * @private
+ */
+goog.debug.Console.logToConsole_ = function(console, fnName, record) {
+ if (console[fnName]) {
+ console[fnName](record);
+ } else {
+ console.log(record);
+ }
+};
[06/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/bidiformatter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/bidiformatter.js b/externs/GCL/externs/goog/i18n/bidiformatter.js
new file mode 100644
index 0000000..0583f5b
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/bidiformatter.js
@@ -0,0 +1,596 @@
+// Copyright 2009 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 Utility for formatting text for display in a potentially
+ * opposite-directionality context without garbling.
+ * Mostly a port of http://go/formatter.cc.
+ */
+
+
+goog.provide('goog.i18n.BidiFormatter');
+
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.legacyconversions');
+goog.require('goog.i18n.bidi');
+goog.require('goog.i18n.bidi.Dir');
+goog.require('goog.i18n.bidi.Format');
+
+
+
+/**
+ * Utility class for formatting text for display in a potentially
+ * opposite-directionality context without garbling. Provides the following
+ * functionality:
+ *
+ * 1. BiDi Wrapping
+ * When text in one language is mixed into a document in another, opposite-
+ * directionality language, e.g. when an English business name is embedded in a
+ * Hebrew web page, both the inserted string and the text following it may be
+ * displayed incorrectly unless the inserted string is explicitly separated
+ * from the surrounding text in a "wrapper" that declares its directionality at
+ * the start and then resets it back at the end. This wrapping can be done in
+ * HTML mark-up (e.g. a 'span dir="rtl"' tag) or - only in contexts where
+ * mark-up can not be used - in Unicode BiDi formatting codes (LRE|RLE and PDF).
+ * Providing such wrapping services is the basic purpose of the BiDi formatter.
+ *
+ * 2. Directionality estimation
+ * How does one know whether a string about to be inserted into surrounding
+ * text has the same directionality? Well, in many cases, one knows that this
+ * must be the case when writing the code doing the insertion, e.g. when a
+ * localized message is inserted into a localized page. In such cases there is
+ * no need to involve the BiDi formatter at all. In the remaining cases, e.g.
+ * when the string is user-entered or comes from a database, the language of
+ * the string (and thus its directionality) is not known a priori, and must be
+ * estimated at run-time. The BiDi formatter does this automatically.
+ *
+ * 3. Escaping
+ * When wrapping plain text - i.e. text that is not already HTML or HTML-
+ * escaped - in HTML mark-up, the text must first be HTML-escaped to prevent XSS
+ * attacks and other nasty business. This of course is always true, but the
+ * escaping can not be done after the string has already been wrapped in
+ * mark-up, so the BiDi formatter also serves as a last chance and includes
+ * escaping services.
+ *
+ * Thus, in a single call, the formatter will escape the input string as
+ * specified, determine its directionality, and wrap it as necessary. It is
+ * then up to the caller to insert the return value in the output.
+ *
+ * See http://wiki/Main/TemplatesAndBiDi for more information.
+ *
+ * @param {goog.i18n.bidi.Dir|number|boolean|null} contextDir The context
+ * directionality, in one of the following formats:
+ * 1. A goog.i18n.bidi.Dir constant. NEUTRAL is treated the same as null,
+ * i.e. unknown, for backward compatibility with legacy calls.
+ * 2. A number (positive = LTR, negative = RTL, 0 = unknown).
+ * 3. A boolean (true = RTL, false = LTR).
+ * 4. A null for unknown directionality.
+ * @param {boolean=} opt_alwaysSpan Whether {@link #spanWrap} should always
+ * use a 'span' tag, even when the input directionality is neutral or
+ * matches the context, so that the DOM structure of the output does not
+ * depend on the combination of directionalities. Default: false.
+ * @constructor
+ * @final
+ */
+goog.i18n.BidiFormatter = function(contextDir, opt_alwaysSpan) {
+ /**
+ * The overall directionality of the context in which the formatter is being
+ * used.
+ * @type {?goog.i18n.bidi.Dir}
+ * @private
+ */
+ this.contextDir_ = goog.i18n.bidi.toDir(contextDir, true /* opt_noNeutral */);
+
+ /**
+ * Whether {@link #spanWrap} and similar methods should always use the same
+ * span structure, regardless of the combination of directionalities, for a
+ * stable DOM structure.
+ * @type {boolean}
+ * @private
+ */
+ this.alwaysSpan_ = !!opt_alwaysSpan;
+};
+
+
+/**
+ * @return {?goog.i18n.bidi.Dir} The context directionality.
+ */
+goog.i18n.BidiFormatter.prototype.getContextDir = function() {
+ return this.contextDir_;
+};
+
+
+/**
+ * @return {boolean} Whether alwaysSpan is set.
+ */
+goog.i18n.BidiFormatter.prototype.getAlwaysSpan = function() {
+ return this.alwaysSpan_;
+};
+
+
+/**
+ * @param {goog.i18n.bidi.Dir|number|boolean|null} contextDir The context
+ * directionality, in one of the following formats:
+ * 1. A goog.i18n.bidi.Dir constant. NEUTRAL is treated the same as null,
+ * i.e. unknown.
+ * 2. A number (positive = LTR, negative = RTL, 0 = unknown).
+ * 3. A boolean (true = RTL, false = LTR).
+ * 4. A null for unknown directionality.
+ */
+goog.i18n.BidiFormatter.prototype.setContextDir = function(contextDir) {
+ this.contextDir_ = goog.i18n.bidi.toDir(contextDir, true /* opt_noNeutral */);
+};
+
+
+/**
+ * @param {boolean} alwaysSpan Whether {@link #spanWrap} should always use a
+ * 'span' tag, even when the input directionality is neutral or matches the
+ * context, so that the DOM structure of the output does not depend on the
+ * combination of directionalities.
+ */
+goog.i18n.BidiFormatter.prototype.setAlwaysSpan = function(alwaysSpan) {
+ this.alwaysSpan_ = alwaysSpan;
+};
+
+
+/**
+ * Returns the directionality of input argument {@code str}.
+ * Identical to {@link goog.i18n.bidi.estimateDirection}.
+ *
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}.
+ */
+goog.i18n.BidiFormatter.prototype.estimateDirection =
+ goog.i18n.bidi.estimateDirection;
+
+
+/**
+ * Returns true if two given directionalities are opposite.
+ * Note: the implementation is based on the numeric values of the Dir enum.
+ *
+ * @param {?goog.i18n.bidi.Dir} dir1 1st directionality.
+ * @param {?goog.i18n.bidi.Dir} dir2 2nd directionality.
+ * @return {boolean} Whether the directionalities are opposite.
+ * @private
+ */
+goog.i18n.BidiFormatter.prototype.areDirectionalitiesOpposite_ = function(dir1,
+ dir2) {
+ return dir1 * dir2 < 0;
+};
+
+
+/**
+ * Returns a unicode BiDi mark matching the context directionality (LRM or
+ * RLM) if {@code opt_dirReset}, and if either the directionality or the exit
+ * directionality of {@code str} is opposite to the context directionality.
+ * Otherwise returns the empty string.
+ *
+ * @param {string} str The input text.
+ * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @param {boolean=} opt_dirReset Whether to perform the reset. Default: false.
+ * @return {string} A unicode BiDi mark or the empty string.
+ * @private
+ */
+goog.i18n.BidiFormatter.prototype.dirResetIfNeeded_ = function(str, dir,
+ opt_isHtml, opt_dirReset) {
+ // endsWithRtl and endsWithLtr are called only if needed (short-circuit).
+ if (opt_dirReset &&
+ (this.areDirectionalitiesOpposite_(dir, this.contextDir_) ||
+ (this.contextDir_ == goog.i18n.bidi.Dir.LTR &&
+ goog.i18n.bidi.endsWithRtl(str, opt_isHtml)) ||
+ (this.contextDir_ == goog.i18n.bidi.Dir.RTL &&
+ goog.i18n.bidi.endsWithLtr(str, opt_isHtml)))) {
+ return this.contextDir_ == goog.i18n.bidi.Dir.LTR ?
+ goog.i18n.bidi.Format.LRM : goog.i18n.bidi.Format.RLM;
+ } else {
+ return '';
+ }
+};
+
+
+/**
+ * Returns "rtl" if {@code str}'s estimated directionality is RTL, and "ltr" if
+ * it is LTR. In case it's NEUTRAL, returns "rtl" if the context directionality
+ * is RTL, and "ltr" otherwise.
+ * Needed for GXP, which can't handle dirAttr.
+ * Example use case:
+ * <td expr:dir='bidiFormatter.dirAttrValue(foo)'>
+ * <gxp:eval expr='foo'>
+ * </td>
+ *
+ * @param {string} str Text whose directionality is to be estimated.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @return {string} "rtl" or "ltr", according to the logic described above.
+ */
+goog.i18n.BidiFormatter.prototype.dirAttrValue = function(str, opt_isHtml) {
+ return this.knownDirAttrValue(this.estimateDirection(str, opt_isHtml));
+};
+
+
+/**
+ * Returns "rtl" if the given directionality is RTL, and "ltr" if it is LTR. In
+ * case it's NEUTRAL, returns "rtl" if the context directionality is RTL, and
+ * "ltr" otherwise.
+ *
+ * @param {goog.i18n.bidi.Dir} dir A directionality.
+ * @return {string} "rtl" or "ltr", according to the logic described above.
+ */
+goog.i18n.BidiFormatter.prototype.knownDirAttrValue = function(dir) {
+ var resolvedDir = dir == goog.i18n.bidi.Dir.NEUTRAL ? this.contextDir_ : dir;
+ return resolvedDir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr';
+};
+
+
+/**
+ * Returns 'dir="ltr"' or 'dir="rtl"', depending on {@code str}'s estimated
+ * directionality, if it is not the same as the context directionality.
+ * Otherwise, returns the empty string.
+ *
+ * @param {string} str Text whose directionality is to be estimated.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @return {string} 'dir="rtl"' for RTL text in non-RTL context; 'dir="ltr"' for
+ * LTR text in non-LTR context; else, the empty string.
+ */
+goog.i18n.BidiFormatter.prototype.dirAttr = function(str, opt_isHtml) {
+ return this.knownDirAttr(this.estimateDirection(str, opt_isHtml));
+};
+
+
+/**
+ * Returns 'dir="ltr"' or 'dir="rtl"', depending on the given directionality, if
+ * it is not the same as the context directionality. Otherwise, returns the
+ * empty string.
+ *
+ * @param {goog.i18n.bidi.Dir} dir A directionality.
+ * @return {string} 'dir="rtl"' for RTL text in non-RTL context; 'dir="ltr"' for
+ * LTR text in non-LTR context; else, the empty string.
+ */
+goog.i18n.BidiFormatter.prototype.knownDirAttr = function(dir) {
+ if (dir != this.contextDir_) {
+ return dir == goog.i18n.bidi.Dir.RTL ? 'dir="rtl"' :
+ dir == goog.i18n.bidi.Dir.LTR ? 'dir="ltr"' : '';
+ }
+ return '';
+};
+
+
+/**
+ * Formats a string of unknown directionality for use in HTML output of the
+ * context directionality, so an opposite-directionality string is neither
+ * garbled nor garbles what follows it.
+ * The algorithm: estimates the directionality of input argument {@code html}.
+ * In case its directionality doesn't match the context directionality, wraps it
+ * with a 'span' tag and adds a "dir" attribute (either 'dir="rtl"' or
+ * 'dir="ltr"'). If setAlwaysSpan(true) was used, the input is always wrapped
+ * with 'span', skipping just the dir attribute when it's not needed.
+ *
+ * If {@code opt_dirReset}, and if the overall directionality or the exit
+ * directionality of {@code str} are opposite to the context directionality, a
+ * trailing unicode BiDi mark matching the context directionality is appened
+ * (LRM or RLM).
+ *
+ * @param {!goog.html.SafeHtml} html The input HTML.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code html}. Default: true.
+ * @return {!goog.html.SafeHtml} Input text after applying the processing.
+ */
+goog.i18n.BidiFormatter.prototype.spanWrapSafeHtml = function(html,
+ opt_dirReset) {
+ return this.spanWrapSafeHtmlWithKnownDir(null, html, opt_dirReset);
+};
+
+
+/**
+ * String version of {@link #spanWrapSafeHtml}.
+ *
+ * If !{@code opt_isHtml}, HTML-escapes {@code str} regardless of wrapping.
+ *
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code str}. Default: true.
+ * @return {string} Input text after applying the above processing.
+ */
+goog.i18n.BidiFormatter.prototype.spanWrap = function(str, opt_isHtml,
+ opt_dirReset) {
+ return this.spanWrapWithKnownDir(null, str, opt_isHtml, opt_dirReset);
+};
+
+
+/**
+ * Formats a string of given directionality for use in HTML output of the
+ * context directionality, so an opposite-directionality string is neither
+ * garbled nor garbles what follows it.
+ * The algorithm: If {@code dir} doesn't match the context directionality, wraps
+ * {@code html} with a 'span' tag and adds a "dir" attribute (either 'dir="rtl"'
+ * or 'dir="ltr"'). If setAlwaysSpan(true) was used, the input is always wrapped
+ * with 'span', skipping just the dir attribute when it's not needed.
+ *
+ * If {@code opt_dirReset}, and if {@code dir} or the exit directionality of
+ * {@code html} are opposite to the context directionality, a trailing unicode
+ * BiDi mark matching the context directionality is appened (LRM or RLM).
+ *
+ * @param {?goog.i18n.bidi.Dir} dir {@code html}'s overall directionality, or
+ * null if unknown and needs to be estimated.
+ * @param {!goog.html.SafeHtml} html The input HTML.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code html}. Default: true.
+ * @return {!goog.html.SafeHtml} Input text after applying the processing.
+ */
+goog.i18n.BidiFormatter.prototype.spanWrapSafeHtmlWithKnownDir = function(dir,
+ html, opt_dirReset) {
+ if (dir == null) {
+ dir = this.estimateDirection(goog.html.SafeHtml.unwrap(html), true);
+ }
+ return this.spanWrapWithKnownDir_(dir, html, opt_dirReset);
+};
+
+
+/**
+ * String version of {@link #spanWrapSafeHtmlWithKnownDir}.
+ *
+ * If !{@code opt_isHtml}, HTML-escapes {@code str} regardless of wrapping.
+ *
+ * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or
+ * null if unknown and needs to be estimated.
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code str}. Default: true.
+ * @return {string} Input text after applying the above processing.
+ */
+goog.i18n.BidiFormatter.prototype.spanWrapWithKnownDir = function(dir, str,
+ opt_isHtml, opt_dirReset) {
+ // We're calling legacy conversions, but quickly unwrapping it.
+ var html = opt_isHtml ? goog.html.legacyconversions.safeHtmlFromString(str) :
+ goog.html.SafeHtml.htmlEscape(str);
+ return goog.html.SafeHtml.unwrap(
+ this.spanWrapSafeHtmlWithKnownDir(dir, html, opt_dirReset));
+};
+
+
+/**
+ * The internal implementation of spanWrapSafeHtmlWithKnownDir for non-null dir,
+ * to help the compiler optimize.
+ *
+ * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality.
+ * @param {!goog.html.SafeHtml} html The input HTML.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code str}. Default: true.
+ * @return {!goog.html.SafeHtml} Input text after applying the above processing.
+ * @private
+ */
+goog.i18n.BidiFormatter.prototype.spanWrapWithKnownDir_ = function(dir, html,
+ opt_dirReset) {
+ opt_dirReset = opt_dirReset || (opt_dirReset == undefined);
+
+ var result;
+ // Whether to add the "dir" attribute.
+ var dirCondition =
+ dir != goog.i18n.bidi.Dir.NEUTRAL && dir != this.contextDir_;
+ if (this.alwaysSpan_ || dirCondition) { // Wrap is needed
+ var dirAttribute;
+ if (dirCondition) {
+ dirAttribute = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr';
+ }
+ result = goog.html.SafeHtml.create('span', {'dir': dirAttribute}, html);
+ } else {
+ result = html;
+ }
+ var str = goog.html.SafeHtml.unwrap(html);
+ result = goog.html.SafeHtml.concatWithDir(goog.i18n.bidi.Dir.NEUTRAL, result,
+ this.dirResetIfNeeded_(str, dir, true, opt_dirReset));
+ return result;
+};
+
+
+/**
+ * Formats a string of unknown directionality for use in plain-text output of
+ * the context directionality, so an opposite-directionality string is neither
+ * garbled nor garbles what follows it.
+ * As opposed to {@link #spanWrap}, this makes use of unicode BiDi formatting
+ * characters. In HTML, its *only* valid use is inside of elements that do not
+ * allow mark-up, e.g. an 'option' tag.
+ * The algorithm: estimates the directionality of input argument {@code str}.
+ * In case it doesn't match the context directionality, wraps it with Unicode
+ * BiDi formatting characters: RLE{@code str}PDF for RTL text, and
+ * LRE{@code str}PDF for LTR text.
+ *
+ * If {@code opt_dirReset}, and if the overall directionality or the exit
+ * directionality of {@code str} are opposite to the context directionality, a
+ * trailing unicode BiDi mark matching the context directionality is appended
+ * (LRM or RLM).
+ *
+ * Does *not* do HTML-escaping regardless of the value of {@code opt_isHtml}.
+ * The return value can be HTML-escaped as necessary.
+ *
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code str}. Default: true.
+ * @return {string} Input text after applying the above processing.
+ */
+goog.i18n.BidiFormatter.prototype.unicodeWrap = function(str, opt_isHtml,
+ opt_dirReset) {
+ return this.unicodeWrapWithKnownDir(null, str, opt_isHtml, opt_dirReset);
+};
+
+
+/**
+ * Formats a string of given directionality for use in plain-text output of the
+ * context directionality, so an opposite-directionality string is neither
+ * garbled nor garbles what follows it.
+ * As opposed to {@link #spanWrapWithKnownDir}, makes use of unicode BiDi
+ * formatting characters. In HTML, its *only* valid use is inside of elements
+ * that do not allow mark-up, e.g. an 'option' tag.
+ * The algorithm: If {@code dir} doesn't match the context directionality, wraps
+ * {@code str} with Unicode BiDi formatting characters: RLE{@code str}PDF for
+ * RTL text, and LRE{@code str}PDF for LTR text.
+ *
+ * If {@code opt_dirReset}, and if the overall directionality or the exit
+ * directionality of {@code str} are opposite to the context directionality, a
+ * trailing unicode BiDi mark matching the context directionality is appended
+ * (LRM or RLM).
+ *
+ * Does *not* do HTML-escaping regardless of the value of {@code opt_isHtml}.
+ * The return value can be HTML-escaped as necessary.
+ *
+ * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or
+ * null if unknown and needs to be estimated.
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code str}. Default: true.
+ * @return {string} Input text after applying the above processing.
+ */
+goog.i18n.BidiFormatter.prototype.unicodeWrapWithKnownDir = function(dir, str,
+ opt_isHtml, opt_dirReset) {
+ if (dir == null) {
+ dir = this.estimateDirection(str, opt_isHtml);
+ }
+ return this.unicodeWrapWithKnownDir_(dir, str, opt_isHtml, opt_dirReset);
+};
+
+
+/**
+ * The internal implementation of unicodeWrapWithKnownDir for non-null dir, to
+ * help the compiler optimize.
+ *
+ * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality.
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
+ * matching the context directionality, when needed, to prevent the possible
+ * garbling of whatever may follow {@code str}. Default: true.
+ * @return {string} Input text after applying the above processing.
+ * @private
+ */
+goog.i18n.BidiFormatter.prototype.unicodeWrapWithKnownDir_ = function(dir, str,
+ opt_isHtml, opt_dirReset) {
+ opt_dirReset = opt_dirReset || (opt_dirReset == undefined);
+ var result = [];
+ if (dir != goog.i18n.bidi.Dir.NEUTRAL && dir != this.contextDir_) {
+ result.push(dir == goog.i18n.bidi.Dir.RTL ? goog.i18n.bidi.Format.RLE :
+ goog.i18n.bidi.Format.LRE);
+ result.push(str);
+ result.push(goog.i18n.bidi.Format.PDF);
+ } else {
+ result.push(str);
+ }
+
+ result.push(this.dirResetIfNeeded_(str, dir, opt_isHtml, opt_dirReset));
+ return result.join('');
+};
+
+
+/**
+ * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM)
+ * if the directionality or the exit directionality of {@code str} are opposite
+ * to the context directionality. Otherwise returns the empty string.
+ *
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @return {string} A Unicode bidi mark matching the global directionality or
+ * the empty string.
+ */
+goog.i18n.BidiFormatter.prototype.markAfter = function(str, opt_isHtml) {
+ return this.markAfterKnownDir(null, str, opt_isHtml);
+};
+
+
+/**
+ * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM)
+ * if the given directionality or the exit directionality of {@code str} are
+ * opposite to the context directionality. Otherwise returns the empty string.
+ *
+ * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or
+ * null if unknown and needs to be estimated.
+ * @param {string} str The input text.
+ * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
+ * Default: false.
+ * @return {string} A Unicode bidi mark matching the global directionality or
+ * the empty string.
+ */
+goog.i18n.BidiFormatter.prototype.markAfterKnownDir = function(
+ dir, str, opt_isHtml) {
+ if (dir == null) {
+ dir = this.estimateDirection(str, opt_isHtml);
+ }
+ return this.dirResetIfNeeded_(str, dir, opt_isHtml, true);
+};
+
+
+/**
+ * Returns the Unicode BiDi mark matching the context directionality (LRM for
+ * LTR context directionality, RLM for RTL context directionality), or the
+ * empty string for neutral / unknown context directionality.
+ *
+ * @return {string} LRM for LTR context directionality and RLM for RTL context
+ * directionality.
+ */
+goog.i18n.BidiFormatter.prototype.mark = function() {
+ switch (this.contextDir_) {
+ case (goog.i18n.bidi.Dir.LTR):
+ return goog.i18n.bidi.Format.LRM;
+ case (goog.i18n.bidi.Dir.RTL):
+ return goog.i18n.bidi.Format.RLM;
+ default:
+ return '';
+ }
+};
+
+
+/**
+ * Returns 'right' for RTL context directionality. Otherwise (LTR or neutral /
+ * unknown context directionality) returns 'left'.
+ *
+ * @return {string} 'right' for RTL context directionality and 'left' for other
+ * context directionality.
+ */
+goog.i18n.BidiFormatter.prototype.startEdge = function() {
+ return this.contextDir_ == goog.i18n.bidi.Dir.RTL ?
+ goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT;
+};
+
+
+/**
+ * Returns 'left' for RTL context directionality. Otherwise (LTR or neutral /
+ * unknown context directionality) returns 'right'.
+ *
+ * @return {string} 'left' for RTL context directionality and 'right' for other
+ * context directionality.
+ */
+goog.i18n.BidiFormatter.prototype.endEdge = function() {
+ return this.contextDir_ == goog.i18n.bidi.Dir.RTL ?
+ goog.i18n.bidi.LEFT : goog.i18n.bidi.RIGHT;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/charlistdecompressor.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/charlistdecompressor.js b/externs/GCL/externs/goog/i18n/charlistdecompressor.js
new file mode 100644
index 0000000..48fae13
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/charlistdecompressor.js
@@ -0,0 +1,158 @@
+// Copyright 2009 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 The decompressor for Base88 compressed character lists.
+ *
+ * The compression is by base 88 encoding the delta between two adjacent
+ * characters in ths list. The deltas can be positive or negative. Also, there
+ * would be character ranges. These three types of values
+ * are given enum values 0, 1 and 2 respectively. Initial 3 bits are used for
+ * encoding the type and total length of the encoded value. Length enums 0, 1
+ * and 2 represents lengths 1, 2 and 4. So (value * 8 + type * 3 + length enum)
+ * is encoded in base 88 by following characters for numbers from 0 to 87:
+ * 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ (continued in next line)
+ * abcdefghijklmnopqrstuvwxyz!#$%()*+,-.:;<=>?@[]^_`{|}~
+ *
+ * Value uses 0 based counting. That is value for the range [a, b] is 0 and
+ * that of [a, c] is 1. Simillarly, the delta of "ab" is 0.
+ *
+ * Following python script can be used to compress character lists taken
+ * standard input: http://go/charlistcompressor.py
+ *
+ */
+
+goog.provide('goog.i18n.CharListDecompressor');
+
+goog.require('goog.array');
+goog.require('goog.i18n.uChar');
+
+
+
+/**
+ * Class to decompress base88 compressed character list.
+ * @constructor
+ * @final
+ */
+goog.i18n.CharListDecompressor = function() {
+ this.buildCharMap_('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr' +
+ 'stuvwxyz!#$%()*+,-.:;<=>?@[]^_`{|}~');
+};
+
+
+/**
+ * 1-1 mapping from ascii characters used in encoding to an integer in the
+ * range 0 to 87.
+ * @type {Object}
+ * @private
+ */
+goog.i18n.CharListDecompressor.prototype.charMap_ = null;
+
+
+/**
+ * Builds the map from ascii characters used for the base88 scheme to number
+ * each character represents.
+ * @param {string} str The string of characters used in base88 scheme.
+ * @private
+ */
+goog.i18n.CharListDecompressor.prototype.buildCharMap_ = function(str) {
+ if (!this.charMap_) {
+ this.charMap_ = {};
+ for (var i = 0; i < str.length; i++) {
+ this.charMap_[str.charAt(i)] = i;
+ }
+ }
+};
+
+
+/**
+ * Gets the number encoded in base88 scheme by a substring of given length
+ * and placed at the a given position of the string.
+ * @param {string} str String containing sequence of characters encoding a
+ * number in base 88 scheme.
+ * @param {number} start Starting position of substring encoding the number.
+ * @param {number} leng Length of the substring encoding the number.
+ * @return {number} The encoded number.
+ * @private
+ */
+goog.i18n.CharListDecompressor.prototype.getCodeAt_ = function(str, start,
+ leng) {
+ var result = 0;
+ for (var i = 0; i < leng; i++) {
+ var c = this.charMap_[str.charAt(start + i)];
+ result += c * Math.pow(88, i);
+ }
+ return result;
+};
+
+
+/**
+ * Add character(s) specified by the value and type to given list and return
+ * the next character in the sequence.
+ * @param {Array<string>} list The list of characters to which the specified
+ * characters are appended.
+ * @param {number} lastcode The last codepoint that was added to the list.
+ * @param {number} value The value component that representing the delta or
+ * range.
+ * @param {number} type The type component that representing whether the value
+ * is a positive or negative delta or range.
+ * @return {number} Last codepoint that is added to the list.
+ * @private
+ */
+goog.i18n.CharListDecompressor.prototype.addChars_ = function(list, lastcode,
+ value, type) {
+ if (type == 0) {
+ lastcode += value + 1;
+ goog.array.extend(list, goog.i18n.uChar.fromCharCode(lastcode));
+ } else if (type == 1) {
+ lastcode -= value + 1;
+ goog.array.extend(list, goog.i18n.uChar.fromCharCode(lastcode));
+ } else if (type == 2) {
+ for (var i = 0; i <= value; i++) {
+ lastcode++;
+ goog.array.extend(list, goog.i18n.uChar.fromCharCode(lastcode));
+ }
+ }
+ return lastcode;
+};
+
+
+/**
+ * Gets the list of characters specified in the given string by base 88 scheme.
+ * @param {string} str The string encoding character list.
+ * @return {!Array<string>} The list of characters specified by the given
+ * string in base 88 scheme.
+ */
+goog.i18n.CharListDecompressor.prototype.toCharList = function(str) {
+ var metasize = 8;
+ var result = [];
+ var lastcode = 0;
+ var i = 0;
+ while (i < str.length) {
+ var c = this.charMap_[str.charAt(i)];
+ var meta = c % metasize;
+ var type = Math.floor(meta / 3);
+ var leng = (meta % 3) + 1;
+ if (leng == 3) {
+ leng++;
+ }
+ var code = this.getCodeAt_(str, i, leng);
+ var value = Math.floor(code / metasize);
+ lastcode = this.addChars_(result, lastcode, value, type);
+
+ i += leng;
+ }
+ return result;
+};
+
[33/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
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 arv@google.com (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 nnaze@google.com (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 robbyw@google.com (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 robbyw@google.com (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 robbyw@google.com (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;
[25/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/focus.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/focus.js b/externs/GCL/externs/goog/editor/focus.js
new file mode 100644
index 0000000..4253b3c
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/focus.js
@@ -0,0 +1,32 @@
+// Copyright 2009 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 Utilties to handle focusing related to rich text editing.
+ *
+ */
+
+goog.provide('goog.editor.focus');
+
+goog.require('goog.dom.selection');
+
+
+/**
+ * Change focus to the given input field and set cursor to end of current text.
+ * @param {Element} inputElem Input DOM element.
+ */
+goog.editor.focus.focusInputField = function(inputElem) {
+ inputElem.focus();
+ goog.dom.selection.setCursorPosition(inputElem, inputElem.value.length);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/icontent.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/icontent.js b/externs/GCL/externs/goog/editor/icontent.js
new file mode 100644
index 0000000..fac433a
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/icontent.js
@@ -0,0 +1,300 @@
+// 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.
+// All Rights Reserved.
+
+/**
+ * @fileoverview Static functions for writing the contents of an iframe-based
+ * editable field. These vary significantly from browser to browser. Uses
+ * strings and document.write instead of DOM manipulation, because
+ * iframe-loading is a performance bottleneck.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.icontent');
+goog.provide('goog.editor.icontent.FieldFormatInfo');
+goog.provide('goog.editor.icontent.FieldStyleInfo');
+
+goog.require('goog.dom');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.style');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A data structure for storing simple rendering info about a field.
+ *
+ * @param {string} fieldId The id of the field.
+ * @param {boolean} standards Whether the field should be rendered in
+ * standards mode.
+ * @param {boolean} blended Whether the field is in blended mode.
+ * @param {boolean} fixedHeight Whether the field is in fixedHeight mode.
+ * @param {Object=} opt_extraStyles Other style attributes for the field,
+ * represented as a map of strings.
+ * @constructor
+ * @final
+ */
+goog.editor.icontent.FieldFormatInfo = function(fieldId, standards, blended,
+ fixedHeight, opt_extraStyles) {
+ this.fieldId_ = fieldId;
+ this.standards_ = standards;
+ this.blended_ = blended;
+ this.fixedHeight_ = fixedHeight;
+ this.extraStyles_ = opt_extraStyles || {};
+};
+
+
+
+/**
+ * A data structure for storing simple info about the styles of a field.
+ * Only needed in Firefox/Blended mode.
+ * @param {Element} wrapper The wrapper div around a field.
+ * @param {string} css The css for a field.
+ * @constructor
+ * @final
+ */
+goog.editor.icontent.FieldStyleInfo = function(wrapper, css) {
+ this.wrapper_ = wrapper;
+ this.css_ = css;
+};
+
+
+/**
+ * Whether to always use standards-mode iframes.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.icontent.useStandardsModeIframes_ = false;
+
+
+/**
+ * Sets up goog.editor.icontent to always use standards-mode iframes.
+ */
+goog.editor.icontent.forceStandardsModeIframes = function() {
+ goog.editor.icontent.useStandardsModeIframes_ = true;
+};
+
+
+/**
+ * Generate the initial iframe content.
+ * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about
+ * the field.
+ * @param {string} bodyHtml The HTML to insert as the iframe body.
+ * @param {goog.editor.icontent.FieldStyleInfo?} style Style info about
+ * the field, if needed.
+ * @return {string} The initial IFRAME content HTML.
+ * @private
+ */
+goog.editor.icontent.getInitialIframeContent_ =
+ function(info, bodyHtml, style) {
+ var html = [];
+
+ if (info.blended_ && info.standards_ ||
+ goog.editor.icontent.useStandardsModeIframes_) {
+ html.push('<!DOCTYPE HTML>');
+ }
+
+ // <HTML>
+ // NOTE(user): Override min-widths that may be set for all
+ // HTML/BODY nodes. A similar workaround is below for the <body> tag. This
+ // can happen if the host page includes a rule like this in its CSS:
+ //
+ // html, body {min-width: 500px}
+ //
+ // In this case, the iframe's <html> and/or <body> may be affected. This was
+ // part of the problem observed in http://b/5674613. (The other part of that
+ // problem had to do with the presence of a spurious horizontal scrollbar,
+ // which caused the editor height to be computed incorrectly.)
+ html.push('<html style="background:none transparent;min-width:0;');
+
+ // Make sure that the HTML element's height has the
+ // correct value as the body element's percentage height is made relative
+ // to the HTML element's height.
+ // For fixed-height it should be 100% since we want the body to fill the
+ // whole height. For growing fields it should be auto since we want the
+ // body to size to its content.
+ if (info.blended_) {
+ html.push('height:', info.fixedHeight_ ? '100%' : 'auto');
+ }
+ html.push('">');
+
+ // <HEAD><STYLE>
+
+ // IE/Safari whitebox need styles set only iff the client specifically
+ // requested them.
+ html.push('<head><style>');
+ if (style && style.css_) {
+ html.push(style.css_);
+ }
+
+ // Firefox blended needs to inherit all the css from the original page.
+ // Firefox standards mode needs to set extra style for images.
+ if (goog.userAgent.GECKO && info.standards_) {
+ // Standards mode will collapse broken images. This means that they
+ // can never be removed from the field. This style forces the images
+ // to render as a broken image icon, sized based on the width and height
+ // of the image.
+ // TODO(user): Make sure we move this into a contentEditable code
+ // path if there ever is one for FF.
+ html.push(' img {-moz-force-broken-image-icon: 1;}');
+ }
+
+ html.push('</style></head>');
+
+ // <BODY>
+ // Hidefocus is needed to ensure that IE7 doesn't show the dotted, focus
+ // border when you tab into the field.
+ html.push('<body g_editable="true" hidefocus="true" ');
+ if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
+ html.push('contentEditable ');
+ }
+
+ html.push('class="editable ');
+
+ // TODO: put the field's original ID on the body and stop using ID as a
+ // way of getting the pointer to the field in the iframe now that it's
+ // always the body.
+ html.push('" id="', info.fieldId_, '" style="min-width:0;');
+
+ if (goog.userAgent.GECKO && info.blended_) {
+ // IMPORTANT: Apply the css from the body then all of the clearing
+ // CSS to make sure the clearing CSS overrides (e.g. if the body
+ // has a 3px margin, we want to make sure to override it with 0px.
+ html.push(
+
+ // margin should not be applied to blended mode because the margin is
+ // outside the iframe
+ // In whitebox mode, we want to leave the margin to the default so
+ // there is a nice margin around the text.
+ ';width:100%;border:0;margin:0;background:none transparent;',
+
+ // In standards-mode, height 100% makes the body size to its
+ // parent html element, but in quirks mode, we want auto because
+ // 100% makes it size to the containing window even if the html
+ // element is smaller.
+ // TODO: Fixed height, standards mode, CSS_WRITING, with margins on the
+ // paragraphs has a scrollbar when it doesn't need it. Putting the
+ // height to auto seems to fix it. Figure out if we should always
+ // just use auto?
+ ';height:', info.standards_ ? '100%' : 'auto');
+
+ // Only do this for mozilla. IE6 standards mode has a rendering bug when
+ // there are scrollbars and the body's overflow property is auto
+ if (info.fixedHeight_) {
+ html.push(';overflow:auto');
+ } else {
+ html.push(';overflow-y:hidden;overflow-x:auto');
+ }
+ }
+
+ // Hide the native focus rect in Opera.
+ if (goog.userAgent.OPERA) {
+ html.push(';outline:hidden');
+ }
+
+ for (var key in info.extraStyles_) {
+ html.push(';' + key + ':' + info.extraStyles_[key]);
+ }
+
+ html.push('">', bodyHtml, '</body></html>');
+
+ return html.join('');
+};
+
+
+/**
+ * Write the initial iframe content in normal mode.
+ * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about
+ * the field.
+ * @param {string} bodyHtml The HTML to insert as the iframe body.
+ * @param {goog.editor.icontent.FieldStyleInfo?} style Style info about
+ * the field, if needed.
+ * @param {HTMLIFrameElement} iframe The iframe.
+ */
+goog.editor.icontent.writeNormalInitialBlendedIframe =
+ function(info, bodyHtml, style, iframe) {
+ // Firefox blended needs to inherit all the css from the original page.
+ // Firefox standards mode needs to set extra style for images.
+ if (info.blended_) {
+ var field = style.wrapper_;
+ // If there is padding on the original field, then the iFrame will be
+ // positioned inside the padding by default. We don't want this, as it
+ // causes the contents to appear to shift, and also causes the
+ // scrollbars to appear inside the padding.
+ //
+ // To compensate, we set the iframe margins to offset the padding.
+ var paddingBox = goog.style.getPaddingBox(field);
+ if (paddingBox.top || paddingBox.left ||
+ paddingBox.right || paddingBox.bottom) {
+ goog.style.setStyle(iframe, 'margin',
+ (-paddingBox.top) + 'px ' +
+ (-paddingBox.right) + 'px ' +
+ (-paddingBox.bottom) + 'px ' +
+ (-paddingBox.left) + 'px');
+ }
+ }
+
+ goog.editor.icontent.writeNormalInitialIframe(
+ info, bodyHtml, style, iframe);
+};
+
+
+/**
+ * Write the initial iframe content in normal mode.
+ * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about
+ * the field.
+ * @param {string} bodyHtml The HTML to insert as the iframe body.
+ * @param {goog.editor.icontent.FieldStyleInfo?} style Style info about
+ * the field, if needed.
+ * @param {HTMLIFrameElement} iframe The iframe.
+ */
+goog.editor.icontent.writeNormalInitialIframe =
+ function(info, bodyHtml, style, iframe) {
+
+ var html = goog.editor.icontent.getInitialIframeContent_(
+ info, bodyHtml, style);
+
+ var doc = goog.dom.getFrameContentDocument(iframe);
+ doc.open();
+ doc.write(html);
+ doc.close();
+};
+
+
+/**
+ * Write the initial iframe content in IE/HTTPS mode.
+ * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about
+ * the field.
+ * @param {Document} doc The iframe document.
+ * @param {string} bodyHtml The HTML to insert as the iframe body.
+ */
+goog.editor.icontent.writeHttpsInitialIframe = function(info, doc, bodyHtml) {
+ var body = doc.body;
+
+ // For HTTPS we already have a document with a doc type and a body element
+ // and don't want to create a new history entry which can cause data loss if
+ // the user clicks the back button.
+ if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
+ body.contentEditable = true;
+ }
+ body.className = 'editable';
+ body.setAttribute('g_editable', true);
+ body.hideFocus = true;
+ body.id = info.fieldId_;
+
+ goog.style.setStyle(body, info.extraStyles_);
+ body.innerHTML = bodyHtml;
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/link.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/link.js b/externs/GCL/externs/goog/editor/link.js
new file mode 100644
index 0000000..72f6c52
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/link.js
@@ -0,0 +1,390 @@
+// 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 utility class for managing editable links.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.Link');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.node');
+goog.require('goog.editor.range');
+goog.require('goog.string');
+goog.require('goog.string.Unicode');
+goog.require('goog.uri.utils');
+goog.require('goog.uri.utils.ComponentIndex');
+
+
+
+/**
+ * Wrap an editable link.
+ * @param {HTMLAnchorElement} anchor The anchor element.
+ * @param {boolean} isNew Whether this is a new link.
+ * @constructor
+ * @final
+ */
+goog.editor.Link = function(anchor, isNew) {
+ /**
+ * The link DOM element.
+ * @type {HTMLAnchorElement}
+ * @private
+ */
+ this.anchor_ = anchor;
+
+ /**
+ * Whether this link represents a link just added to the document.
+ * @type {boolean}
+ * @private
+ */
+ this.isNew_ = isNew;
+
+
+ /**
+ * Any extra anchors created by the browser from a selection in the same
+ * operation that created the primary link
+ * @type {!Array<HTMLAnchorElement>}
+ * @private
+ */
+ this.extraAnchors_ = [];
+};
+
+
+/**
+ * @return {HTMLAnchorElement} The anchor element.
+ */
+goog.editor.Link.prototype.getAnchor = function() {
+ return this.anchor_;
+};
+
+
+/**
+ * @return {!Array<HTMLAnchorElement>} The extra anchor elements, if any,
+ * created by the browser from a selection.
+ */
+goog.editor.Link.prototype.getExtraAnchors = function() {
+ return this.extraAnchors_;
+};
+
+
+/**
+ * @return {string} The inner text for the anchor.
+ */
+goog.editor.Link.prototype.getCurrentText = function() {
+ if (!this.currentText_) {
+ var anchor = this.getAnchor();
+
+ var leaf = goog.editor.node.getLeftMostLeaf(anchor);
+ if (leaf.tagName && leaf.tagName == goog.dom.TagName.IMG) {
+ this.currentText_ = leaf.getAttribute('alt');
+ } else {
+ this.currentText_ = goog.dom.getRawTextContent(this.getAnchor());
+ }
+ }
+ return this.currentText_;
+};
+
+
+/**
+ * @return {boolean} Whether the link is new.
+ */
+goog.editor.Link.prototype.isNew = function() {
+ return this.isNew_;
+};
+
+
+/**
+ * Set the url without affecting the isNew() status of the link.
+ * @param {string} url A URL.
+ */
+goog.editor.Link.prototype.initializeUrl = function(url) {
+ this.getAnchor().href = url;
+};
+
+
+/**
+ * Removes the link, leaving its contents in the document. Note that this
+ * object will no longer be usable/useful after this call.
+ */
+goog.editor.Link.prototype.removeLink = function() {
+ goog.dom.flattenElement(this.anchor_);
+ this.anchor_ = null;
+ while (this.extraAnchors_.length) {
+ goog.dom.flattenElement(/** @type {Element} */(this.extraAnchors_.pop()));
+ }
+};
+
+
+/**
+ * Change the link.
+ * @param {string} newText New text for the link. If the link contains all its
+ * text in one descendent, newText will only replace the text in that
+ * one node. Otherwise, we'll change the innerHTML of the whole
+ * link to newText.
+ * @param {string} newUrl A new URL.
+ */
+goog.editor.Link.prototype.setTextAndUrl = function(newText, newUrl) {
+ var anchor = this.getAnchor();
+ anchor.href = newUrl;
+
+ // If the text did not change, don't update link text.
+ var currentText = this.getCurrentText();
+ if (newText != currentText) {
+ var leaf = goog.editor.node.getLeftMostLeaf(anchor);
+
+ if (leaf.tagName && leaf.tagName == goog.dom.TagName.IMG) {
+ leaf.setAttribute('alt', newText ? newText : '');
+ } else {
+ if (leaf.nodeType == goog.dom.NodeType.TEXT) {
+ leaf = leaf.parentNode;
+ }
+
+ if (goog.dom.getRawTextContent(leaf) != currentText) {
+ leaf = anchor;
+ }
+
+ goog.dom.removeChildren(leaf);
+ var domHelper = goog.dom.getDomHelper(leaf);
+ goog.dom.appendChild(leaf, domHelper.createTextNode(newText));
+ }
+
+ // The text changed, so force getCurrentText to recompute.
+ this.currentText_ = null;
+ }
+
+ this.isNew_ = false;
+};
+
+
+/**
+ * Places the cursor to the right of the anchor.
+ * Note that this is different from goog.editor.range's placeCursorNextTo
+ * in that it specifically handles the placement of a cursor in browsers
+ * that trap you in links, by adding a space when necessary and placing the
+ * cursor after that space.
+ */
+goog.editor.Link.prototype.placeCursorRightOf = function() {
+ var anchor = this.getAnchor();
+ // If the browser gets stuck in a link if we place the cursor next to it,
+ // we'll place the cursor after a space instead.
+ if (goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS) {
+ var spaceNode;
+ var nextSibling = anchor.nextSibling;
+
+ // Check if there is already a space after the link. Only handle the
+ // simple case - the next node is a text node that starts with a space.
+ if (nextSibling &&
+ nextSibling.nodeType == goog.dom.NodeType.TEXT &&
+ (goog.string.startsWith(nextSibling.data, goog.string.Unicode.NBSP) ||
+ goog.string.startsWith(nextSibling.data, ' '))) {
+ spaceNode = nextSibling;
+ } else {
+ // If there isn't an obvious space to use, create one after the link.
+ var dh = goog.dom.getDomHelper(anchor);
+ spaceNode = dh.createTextNode(goog.string.Unicode.NBSP);
+ goog.dom.insertSiblingAfter(spaceNode, anchor);
+ }
+
+ // Move the selection after the space.
+ var range = goog.dom.Range.createCaret(spaceNode, 1);
+ range.select();
+ } else {
+ goog.editor.range.placeCursorNextTo(anchor, false);
+ }
+};
+
+
+/**
+ * Updates the cursor position and link bubble for this link.
+ * @param {goog.editor.Field} field The field in which the link is created.
+ * @param {string} url The link url.
+ * @private
+ */
+goog.editor.Link.prototype.updateLinkDisplay_ = function(field, url) {
+ this.initializeUrl(url);
+ this.placeCursorRightOf();
+ field.execCommand(goog.editor.Command.UPDATE_LINK_BUBBLE);
+};
+
+
+/**
+ * @return {string?} The modified string for the link if the link
+ * text appears to be a valid link. Returns null if this is not
+ * a valid link address.
+ */
+goog.editor.Link.prototype.getValidLinkFromText = function() {
+ var text = goog.string.trim(this.getCurrentText());
+ if (goog.editor.Link.isLikelyUrl(text)) {
+ if (text.search(/:/) < 0) {
+ return 'http://' + goog.string.trimLeft(text);
+ }
+ return text;
+ } else if (goog.editor.Link.isLikelyEmailAddress(text)) {
+ return 'mailto:' + text;
+ }
+ return null;
+};
+
+
+/**
+ * After link creation, finish creating the link depending on the type
+ * of link being created.
+ * @param {goog.editor.Field} field The field where this link is being created.
+ */
+goog.editor.Link.prototype.finishLinkCreation = function(field) {
+ var linkFromText = this.getValidLinkFromText();
+ if (linkFromText) {
+ this.updateLinkDisplay_(field, linkFromText);
+ } else {
+ field.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, this);
+ }
+};
+
+
+/**
+ * Initialize a new link.
+ * @param {HTMLAnchorElement} anchor The anchor element.
+ * @param {string} url The initial URL.
+ * @param {string=} opt_target The target.
+ * @param {Array<HTMLAnchorElement>=} opt_extraAnchors Extra anchors created
+ * by the browser when parsing a selection.
+ * @return {!goog.editor.Link} The link.
+ */
+goog.editor.Link.createNewLink = function(anchor, url, opt_target,
+ opt_extraAnchors) {
+ var link = new goog.editor.Link(anchor, true);
+ link.initializeUrl(url);
+
+ if (opt_target) {
+ anchor.target = opt_target;
+ }
+ if (opt_extraAnchors) {
+ link.extraAnchors_ = opt_extraAnchors;
+ }
+
+ return link;
+};
+
+
+/**
+ * Initialize a new link using text in anchor, or empty string if there is no
+ * likely url in the anchor.
+ * @param {HTMLAnchorElement} anchor The anchor element with likely url content.
+ * @param {string=} opt_target The target.
+ * @return {!goog.editor.Link} The link.
+ */
+goog.editor.Link.createNewLinkFromText = function(anchor, opt_target) {
+ var link = new goog.editor.Link(anchor, true);
+ var text = link.getValidLinkFromText();
+ link.initializeUrl(text ? text : '');
+ if (opt_target) {
+ anchor.target = opt_target;
+ }
+ return link;
+};
+
+
+/**
+ * Returns true if str could be a URL, false otherwise
+ *
+ * Ex: TR_Util.isLikelyUrl_("http://www.google.com") == true
+ * TR_Util.isLikelyUrl_("www.google.com") == true
+ *
+ * @param {string} str String to check if it looks like a URL.
+ * @return {boolean} Whether str could be a URL.
+ */
+goog.editor.Link.isLikelyUrl = function(str) {
+ // Whitespace means this isn't a domain.
+ if (/\s/.test(str)) {
+ return false;
+ }
+
+ if (goog.editor.Link.isLikelyEmailAddress(str)) {
+ return false;
+ }
+
+ // Add a scheme if the url doesn't have one - this helps the parser.
+ var addedScheme = false;
+ if (!/^[^:\/?#.]+:/.test(str)) {
+ str = 'http://' + str;
+ addedScheme = true;
+ }
+
+ // Parse the domain.
+ var parts = goog.uri.utils.split(str);
+
+ // Relax the rules for special schemes.
+ var scheme = parts[goog.uri.utils.ComponentIndex.SCHEME];
+ if (goog.array.indexOf(['mailto', 'aim'], scheme) != -1) {
+ return true;
+ }
+
+ // Require domains to contain a '.', unless the domain is fully qualified and
+ // forbids domains from containing invalid characters.
+ var domain = parts[goog.uri.utils.ComponentIndex.DOMAIN];
+ if (!domain || (addedScheme && domain.indexOf('.') == -1) ||
+ (/[^\w\d\-\u0100-\uffff.%]/.test(domain))) {
+ return false;
+ }
+
+ // Require http and ftp paths to start with '/'.
+ var path = parts[goog.uri.utils.ComponentIndex.PATH];
+ return !path || path.indexOf('/') == 0;
+};
+
+
+/**
+ * Regular expression that matches strings that could be an email address.
+ * @type {RegExp}
+ * @private
+ */
+goog.editor.Link.LIKELY_EMAIL_ADDRESS_ = new RegExp(
+ '^' + // Test from start of string
+ '[\\w-]+(\\.[\\w-]+)*' + // Dot-delimited alphanumerics and dashes (name)
+ '\\@' + // @
+ '([\\w-]+\\.)+' + // Alphanumerics, dashes and dots (domain)
+ '(\\d+|\\w\\w+)$', // Domain ends in at least one number or 2 letters
+ 'i');
+
+
+/**
+ * Returns true if str could be an email address, false otherwise
+ *
+ * Ex: goog.editor.Link.isLikelyEmailAddress_("some word") == false
+ * goog.editor.Link.isLikelyEmailAddress_("foo@foo.com") == true
+ *
+ * @param {string} str String to test for being email address.
+ * @return {boolean} Whether "str" looks like an email address.
+ */
+goog.editor.Link.isLikelyEmailAddress = function(str) {
+ return goog.editor.Link.LIKELY_EMAIL_ADDRESS_.test(str);
+};
+
+
+/**
+ * Determines whether or not a url is an email link.
+ * @param {string} url A url.
+ * @return {boolean} Whether the url is a mailto link.
+ */
+goog.editor.Link.isMailto = function(url) {
+ return !!url && goog.string.startsWith(url, 'mailto:');
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/node.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/node.js b/externs/GCL/externs/goog/editor/node.js
new file mode 100644
index 0000000..006936d
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/node.js
@@ -0,0 +1,484 @@
+// 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 Utilties for working with DOM nodes related to rich text
+ * editing. Many of these are not general enough to go into goog.dom.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.node');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.iter.ChildIterator');
+goog.require('goog.dom.iter.SiblingIterator');
+goog.require('goog.iter');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.string.Unicode');
+goog.require('goog.userAgent');
+
+
+/**
+ * Names of all block-level tags
+ * @type {Object}
+ * @private
+ */
+goog.editor.node.BLOCK_TAG_NAMES_ = goog.object.createSet(
+ goog.dom.TagName.ADDRESS,
+ goog.dom.TagName.ARTICLE,
+ goog.dom.TagName.ASIDE,
+ goog.dom.TagName.BLOCKQUOTE,
+ goog.dom.TagName.BODY,
+ goog.dom.TagName.CAPTION,
+ goog.dom.TagName.CENTER,
+ goog.dom.TagName.COL,
+ goog.dom.TagName.COLGROUP,
+ goog.dom.TagName.DETAILS,
+ goog.dom.TagName.DIR,
+ goog.dom.TagName.DIV,
+ goog.dom.TagName.DL,
+ goog.dom.TagName.DD,
+ goog.dom.TagName.DT,
+ goog.dom.TagName.FIELDSET,
+ goog.dom.TagName.FIGCAPTION,
+ goog.dom.TagName.FIGURE,
+ goog.dom.TagName.FOOTER,
+ goog.dom.TagName.FORM,
+ goog.dom.TagName.H1,
+ goog.dom.TagName.H2,
+ goog.dom.TagName.H3,
+ goog.dom.TagName.H4,
+ goog.dom.TagName.H5,
+ goog.dom.TagName.H6,
+ goog.dom.TagName.HEADER,
+ goog.dom.TagName.HGROUP,
+ goog.dom.TagName.HR,
+ goog.dom.TagName.ISINDEX,
+ goog.dom.TagName.OL,
+ goog.dom.TagName.LI,
+ goog.dom.TagName.MAP,
+ goog.dom.TagName.MENU,
+ goog.dom.TagName.NAV,
+ goog.dom.TagName.OPTGROUP,
+ goog.dom.TagName.OPTION,
+ goog.dom.TagName.P,
+ goog.dom.TagName.PRE,
+ goog.dom.TagName.SECTION,
+ goog.dom.TagName.SUMMARY,
+ goog.dom.TagName.TABLE,
+ goog.dom.TagName.TBODY,
+ goog.dom.TagName.TD,
+ goog.dom.TagName.TFOOT,
+ goog.dom.TagName.TH,
+ goog.dom.TagName.THEAD,
+ goog.dom.TagName.TR,
+ goog.dom.TagName.UL);
+
+
+/**
+ * Names of tags that have intrinsic content.
+ * TODO(robbyw): What about object, br, input, textarea, button, isindex,
+ * hr, keygen, select, table, tr, td?
+ * @type {Object}
+ * @private
+ */
+goog.editor.node.NON_EMPTY_TAGS_ = goog.object.createSet(
+ goog.dom.TagName.IMG, goog.dom.TagName.IFRAME, goog.dom.TagName.EMBED);
+
+
+/**
+ * Check if the node is in a standards mode document.
+ * @param {Node} node The node to test.
+ * @return {boolean} Whether the node is in a standards mode document.
+ */
+goog.editor.node.isStandardsMode = function(node) {
+ return goog.dom.getDomHelper(node).isCss1CompatMode();
+};
+
+
+/**
+ * Get the right-most non-ignorable leaf node of the given node.
+ * @param {Node} parent The parent ndoe.
+ * @return {Node} The right-most non-ignorable leaf node.
+ */
+goog.editor.node.getRightMostLeaf = function(parent) {
+ var temp;
+ while (temp = goog.editor.node.getLastChild(parent)) {
+ parent = temp;
+ }
+ return parent;
+};
+
+
+/**
+ * Get the left-most non-ignorable leaf node of the given node.
+ * @param {Node} parent The parent ndoe.
+ * @return {Node} The left-most non-ignorable leaf node.
+ */
+goog.editor.node.getLeftMostLeaf = function(parent) {
+ var temp;
+ while (temp = goog.editor.node.getFirstChild(parent)) {
+ parent = temp;
+ }
+ return parent;
+};
+
+
+/**
+ * Version of firstChild that skips nodes that are entirely
+ * whitespace and comments.
+ * @param {Node} parent The reference node.
+ * @return {Node} The first child of sibling that is important according to
+ * goog.editor.node.isImportant, or null if no such node exists.
+ */
+goog.editor.node.getFirstChild = function(parent) {
+ return goog.editor.node.getChildHelper_(parent, false);
+};
+
+
+/**
+ * Version of lastChild that skips nodes that are entirely whitespace or
+ * comments. (Normally lastChild is a property of all DOM nodes that gives the
+ * last of the nodes contained directly in the reference node.)
+ * @param {Node} parent The reference node.
+ * @return {Node} The last child of sibling that is important according to
+ * goog.editor.node.isImportant, or null if no such node exists.
+ */
+goog.editor.node.getLastChild = function(parent) {
+ return goog.editor.node.getChildHelper_(parent, true);
+};
+
+
+/**
+ * Version of previoussibling that skips nodes that are entirely
+ * whitespace or comments. (Normally previousSibling is a property
+ * of all DOM nodes that gives the sibling node, the node that is
+ * a child of the same parent, that occurs immediately before the
+ * reference node.)
+ * @param {Node} sibling The reference node.
+ * @return {Node} The closest previous sibling to sibling that is
+ * important according to goog.editor.node.isImportant, or null if no such
+ * node exists.
+ */
+goog.editor.node.getPreviousSibling = function(sibling) {
+ return /** @type {Node} */ (goog.editor.node.getFirstValue_(
+ goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling, false, true),
+ goog.editor.node.isImportant)));
+};
+
+
+/**
+ * Version of nextSibling that skips nodes that are entirely whitespace or
+ * comments.
+ * @param {Node} sibling The reference node.
+ * @return {Node} The closest next sibling to sibling that is important
+ * according to goog.editor.node.isImportant, or null if no
+ * such node exists.
+ */
+goog.editor.node.getNextSibling = function(sibling) {
+ return /** @type {Node} */ (goog.editor.node.getFirstValue_(
+ goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling),
+ goog.editor.node.isImportant)));
+};
+
+
+/**
+ * Internal helper for lastChild/firstChild that skips nodes that are entirely
+ * whitespace or comments.
+ * @param {Node} parent The reference node.
+ * @param {boolean} isReversed Whether children should be traversed forward
+ * or backward.
+ * @return {Node} The first/last child of sibling that is important according
+ * to goog.editor.node.isImportant, or null if no such node exists.
+ * @private
+ */
+goog.editor.node.getChildHelper_ = function(parent, isReversed) {
+ return (!parent || parent.nodeType != goog.dom.NodeType.ELEMENT) ? null :
+ /** @type {Node} */ (goog.editor.node.getFirstValue_(goog.iter.filter(
+ new goog.dom.iter.ChildIterator(
+ /** @type {!Element} */ (parent), isReversed),
+ goog.editor.node.isImportant)));
+};
+
+
+/**
+ * Utility function that returns the first value from an iterator or null if
+ * the iterator is empty.
+ * @param {goog.iter.Iterator} iterator The iterator to get a value from.
+ * @return {*} The first value from the iterator.
+ * @private
+ */
+goog.editor.node.getFirstValue_ = function(iterator) {
+ /** @preserveTry */
+ try {
+ return iterator.next();
+ } catch (e) {
+ return null;
+ }
+};
+
+
+/**
+ * Determine if a node should be returned by the iterator functions.
+ * @param {Node} node An object implementing the DOM1 Node interface.
+ * @return {boolean} Whether the node is an element, or a text node that
+ * is not all whitespace.
+ */
+goog.editor.node.isImportant = function(node) {
+ // Return true if the node is not either a TextNode or an ElementNode.
+ return node.nodeType == goog.dom.NodeType.ELEMENT ||
+ node.nodeType == goog.dom.NodeType.TEXT &&
+ !goog.editor.node.isAllNonNbspWhiteSpace(node);
+};
+
+
+/**
+ * Determine whether a node's text content is entirely whitespace.
+ * @param {Node} textNode A node implementing the CharacterData interface (i.e.,
+ * a Text, Comment, or CDATASection node.
+ * @return {boolean} Whether the text content of node is whitespace,
+ * otherwise false.
+ */
+goog.editor.node.isAllNonNbspWhiteSpace = function(textNode) {
+ return goog.string.isBreakingWhitespace(textNode.nodeValue);
+};
+
+
+/**
+ * Returns true if the node contains only whitespace and is not and does not
+ * contain any images, iframes or embed tags.
+ * @param {Node} node The node to check.
+ * @param {boolean=} opt_prohibitSingleNbsp By default, this function treats a
+ * single nbsp as empty. Set this to true to treat this case as non-empty.
+ * @return {boolean} Whether the node contains only whitespace.
+ */
+goog.editor.node.isEmpty = function(node, opt_prohibitSingleNbsp) {
+ var nodeData = goog.dom.getRawTextContent(node);
+
+ if (node.getElementsByTagName) {
+ for (var tag in goog.editor.node.NON_EMPTY_TAGS_) {
+ if (node.tagName == tag || node.getElementsByTagName(tag).length > 0) {
+ return false;
+ }
+ }
+ }
+ return (!opt_prohibitSingleNbsp && nodeData == goog.string.Unicode.NBSP) ||
+ goog.string.isBreakingWhitespace(nodeData);
+};
+
+
+/**
+ * Returns the length of the text in node if it is a text node, or the number
+ * of children of the node, if it is an element. Useful for range-manipulation
+ * code where you need to know the offset for the right side of the node.
+ * @param {Node} node The node to get the length of.
+ * @return {number} The length of the node.
+ */
+goog.editor.node.getLength = function(node) {
+ return node.length || node.childNodes.length;
+};
+
+
+/**
+ * Search child nodes using a predicate function and return the first node that
+ * satisfies the condition.
+ * @param {Node} parent The parent node to search.
+ * @param {function(Node):boolean} hasProperty A function that takes a child
+ * node as a parameter and returns true if it meets the criteria.
+ * @return {?number} The index of the node found, or null if no node is found.
+ */
+goog.editor.node.findInChildren = function(parent, hasProperty) {
+ for (var i = 0, len = parent.childNodes.length; i < len; i++) {
+ if (hasProperty(parent.childNodes[i])) {
+ return i;
+ }
+ }
+ return null;
+};
+
+
+/**
+ * Search ancestor nodes using a predicate function and returns the topmost
+ * ancestor in the chain of consecutive ancestors that satisfies the condition.
+ *
+ * @param {Node} node The node whose ancestors have to be searched.
+ * @param {function(Node): boolean} hasProperty A function that takes a parent
+ * node as a parameter and returns true if it meets the criteria.
+ * @return {Node} The topmost ancestor or null if no ancestor satisfies the
+ * predicate function.
+ */
+goog.editor.node.findHighestMatchingAncestor = function(node, hasProperty) {
+ var parent = node.parentNode;
+ var ancestor = null;
+ while (parent && hasProperty(parent)) {
+ ancestor = parent;
+ parent = parent.parentNode;
+ }
+ return ancestor;
+};
+
+
+/**
+* Checks if node is a block-level html element. The <tt>display</tt> css
+ * property is ignored.
+ * @param {Node} node The node to test.
+ * @return {boolean} Whether the node is a block-level node.
+ */
+goog.editor.node.isBlockTag = function(node) {
+ return !!goog.editor.node.BLOCK_TAG_NAMES_[node.tagName];
+};
+
+
+/**
+ * Skips siblings of a node that are empty text nodes.
+ * @param {Node} node A node. May be null.
+ * @return {Node} The node or the first sibling of the node that is not an
+ * empty text node. May be null.
+ */
+goog.editor.node.skipEmptyTextNodes = function(node) {
+ while (node && node.nodeType == goog.dom.NodeType.TEXT &&
+ !node.nodeValue) {
+ node = node.nextSibling;
+ }
+ return node;
+};
+
+
+/**
+ * Checks if an element is a top-level editable container (meaning that
+ * it itself is not editable, but all its child nodes are editable).
+ * @param {Node} element The element to test.
+ * @return {boolean} Whether the element is a top-level editable container.
+ */
+goog.editor.node.isEditableContainer = function(element) {
+ return element.getAttribute &&
+ element.getAttribute('g_editable') == 'true';
+};
+
+
+/**
+ * Checks if a node is inside an editable container.
+ * @param {Node} node The node to test.
+ * @return {boolean} Whether the node is in an editable container.
+ */
+goog.editor.node.isEditable = function(node) {
+ return !!goog.dom.getAncestor(node, goog.editor.node.isEditableContainer);
+};
+
+
+/**
+ * Finds the top-most DOM node inside an editable field that is an ancestor
+ * (or self) of a given DOM node and meets the specified criteria.
+ * @param {Node} node The DOM node where the search starts.
+ * @param {function(Node) : boolean} criteria A function that takes a DOM node
+ * as a parameter and returns a boolean to indicate whether the node meets
+ * the criteria or not.
+ * @return {Node} The DOM node if found, or null.
+ */
+goog.editor.node.findTopMostEditableAncestor = function(node, criteria) {
+ var targetNode = null;
+ while (node && !goog.editor.node.isEditableContainer(node)) {
+ if (criteria(node)) {
+ targetNode = node;
+ }
+ node = node.parentNode;
+ }
+ return targetNode;
+};
+
+
+/**
+ * Splits off a subtree.
+ * @param {!Node} currentNode The starting splitting point.
+ * @param {Node=} opt_secondHalf The initial leftmost leaf the new subtree.
+ * If null, siblings after currentNode will be placed in the subtree, but
+ * no additional node will be.
+ * @param {Node=} opt_root The top of the tree where splitting stops at.
+ * @return {!Node} The new subtree.
+ */
+goog.editor.node.splitDomTreeAt = function(currentNode,
+ opt_secondHalf, opt_root) {
+ var parent;
+ while (currentNode != opt_root && (parent = currentNode.parentNode)) {
+ opt_secondHalf = goog.editor.node.getSecondHalfOfNode_(parent, currentNode,
+ opt_secondHalf);
+ currentNode = parent;
+ }
+ return /** @type {!Node} */(opt_secondHalf);
+};
+
+
+/**
+ * Creates a clone of node, moving all children after startNode to it.
+ * When firstChild is not null or undefined, it is also appended to the clone
+ * as the first child.
+ * @param {!Node} node The node to clone.
+ * @param {!Node} startNode All siblings after this node will be moved to the
+ * clone.
+ * @param {Node|undefined} firstChild The first child of the new cloned element.
+ * @return {!Node} The cloned node that now contains the children after
+ * startNode.
+ * @private
+ */
+goog.editor.node.getSecondHalfOfNode_ = function(node, startNode, firstChild) {
+ var secondHalf = /** @type {!Node} */(node.cloneNode(false));
+ while (startNode.nextSibling) {
+ goog.dom.appendChild(secondHalf, startNode.nextSibling);
+ }
+ if (firstChild) {
+ secondHalf.insertBefore(firstChild, secondHalf.firstChild);
+ }
+ return secondHalf;
+};
+
+
+/**
+ * Appends all of oldNode's children to newNode. This removes all children from
+ * oldNode and appends them to newNode. oldNode is left with no children.
+ * @param {!Node} newNode Node to transfer children to.
+ * @param {Node} oldNode Node to transfer children from.
+ * @deprecated Use goog.dom.append directly instead.
+ */
+goog.editor.node.transferChildren = function(newNode, oldNode) {
+ goog.dom.append(newNode, oldNode.childNodes);
+};
+
+
+/**
+ * Replaces the innerHTML of a node.
+ *
+ * IE has serious problems if you try to set innerHTML of an editable node with
+ * any selection. Early versions of IE tear up the old internal tree storage, to
+ * help avoid ref-counting loops. But this sometimes leaves the selection object
+ * in a bad state and leads to segfaults.
+ *
+ * Removing the nodes first prevents IE from tearing them up. This is not
+ * strictly necessary in nodes that do not have the selection. You should always
+ * use this function when setting innerHTML inside of a field.
+ *
+ * @param {Node} node A node.
+ * @param {string} html The innerHTML to set on the node.
+ */
+goog.editor.node.replaceInnerHtml = function(node, html) {
+ // Only do this IE. On gecko, we use element change events, and don't
+ // want to trigger spurious events.
+ if (goog.userAgent.IE) {
+ goog.dom.removeChildren(node);
+ }
+ node.innerHTML = html;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugin.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugin.js b/externs/GCL/externs/goog/editor/plugin.js
new file mode 100644
index 0000000..d823ccb
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugin.js
@@ -0,0 +1,463 @@
+// 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.
+// All Rights Reserved.
+
+/**
+ * @fileoverview Abstract API for TrogEdit plugins.
+ *
+ * @see ../demos/editor/editor.html
+ */
+
+goog.provide('goog.editor.Plugin');
+
+// TODO(user): Remove the dependency on goog.editor.Command asap. Currently only
+// needed for execCommand issues with links.
+goog.require('goog.events.EventTarget');
+goog.require('goog.functions');
+goog.require('goog.log');
+goog.require('goog.object');
+goog.require('goog.reflect');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Abstract API for trogedit plugins.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ */
+goog.editor.Plugin = function() {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * Whether this plugin is enabled for the registered field object.
+ * @type {boolean}
+ * @private
+ */
+ this.enabled_ = this.activeOnUneditableFields();
+};
+goog.inherits(goog.editor.Plugin, goog.events.EventTarget);
+
+
+/**
+ * The field object this plugin is attached to.
+ * @type {goog.editor.Field}
+ * @protected
+ * @deprecated Use goog.editor.Plugin.getFieldObject and
+ * goog.editor.Plugin.setFieldObject.
+ */
+goog.editor.Plugin.prototype.fieldObject = null;
+
+
+/**
+ * @return {goog.dom.DomHelper?} The dom helper object associated with the
+ * currently active field.
+ */
+goog.editor.Plugin.prototype.getFieldDomHelper = function() {
+ return this.getFieldObject() && this.getFieldObject().getEditableDomHelper();
+};
+
+
+/**
+ * Indicates if this plugin should be automatically disposed when the
+ * registered field is disposed. This should be changed to false for
+ * plugins used as multi-field plugins.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.Plugin.prototype.autoDispose_ = true;
+
+
+/**
+ * The logger for this plugin.
+ * @type {goog.log.Logger}
+ * @protected
+ */
+goog.editor.Plugin.prototype.logger =
+ goog.log.getLogger('goog.editor.Plugin');
+
+
+/**
+ * Sets the field object for use with this plugin.
+ * @return {goog.editor.Field} The editable field object.
+ * @protected
+ * @suppress {deprecated} Until fieldObject can be made private.
+ */
+goog.editor.Plugin.prototype.getFieldObject = function() {
+ return this.fieldObject;
+};
+
+
+/**
+ * Sets the field object for use with this plugin.
+ * @param {goog.editor.Field} fieldObject The editable field object.
+ * @protected
+ * @suppress {deprecated} Until fieldObject can be made private.
+ */
+goog.editor.Plugin.prototype.setFieldObject = function(fieldObject) {
+ this.fieldObject = fieldObject;
+};
+
+
+/**
+ * Registers the field object for use with this plugin.
+ * @param {goog.editor.Field} fieldObject The editable field object.
+ */
+goog.editor.Plugin.prototype.registerFieldObject = function(fieldObject) {
+ this.setFieldObject(fieldObject);
+};
+
+
+/**
+ * Unregisters and disables this plugin for the current field object.
+ * @param {goog.editor.Field} fieldObj The field object. For single-field
+ * plugins, this parameter is ignored.
+ */
+goog.editor.Plugin.prototype.unregisterFieldObject = function(fieldObj) {
+ if (this.getFieldObject()) {
+ this.disable(this.getFieldObject());
+ this.setFieldObject(null);
+ }
+};
+
+
+/**
+ * Enables this plugin for the specified, registered field object. A field
+ * object should only be enabled when it is loaded.
+ * @param {goog.editor.Field} fieldObject The field object.
+ */
+goog.editor.Plugin.prototype.enable = function(fieldObject) {
+ if (this.getFieldObject() == fieldObject) {
+ this.enabled_ = true;
+ } else {
+ goog.log.error(this.logger, 'Trying to enable an unregistered field with ' +
+ 'this plugin.');
+ }
+};
+
+
+/**
+ * Disables this plugin for the specified, registered field object.
+ * @param {goog.editor.Field} fieldObject The field object.
+ */
+goog.editor.Plugin.prototype.disable = function(fieldObject) {
+ if (this.getFieldObject() == fieldObject) {
+ this.enabled_ = false;
+ } else {
+ goog.log.error(this.logger, 'Trying to disable an unregistered field ' +
+ 'with this plugin.');
+ }
+};
+
+
+/**
+ * Returns whether this plugin is enabled for the field object.
+ *
+ * @param {goog.editor.Field} fieldObject The field object.
+ * @return {boolean} Whether this plugin is enabled for the field object.
+ */
+goog.editor.Plugin.prototype.isEnabled = function(fieldObject) {
+ return this.getFieldObject() == fieldObject ? this.enabled_ : false;
+};
+
+
+/**
+ * Set if this plugin should automatically be disposed when the registered
+ * field is disposed.
+ * @param {boolean} autoDispose Whether to autoDispose.
+ */
+goog.editor.Plugin.prototype.setAutoDispose = function(autoDispose) {
+ this.autoDispose_ = autoDispose;
+};
+
+
+/**
+ * @return {boolean} Whether or not this plugin should automatically be disposed
+ * when it's registered field is disposed.
+ */
+goog.editor.Plugin.prototype.isAutoDispose = function() {
+ return this.autoDispose_;
+};
+
+
+/**
+ * @return {boolean} If true, field will not disable the command
+ * when the field becomes uneditable.
+ */
+goog.editor.Plugin.prototype.activeOnUneditableFields = goog.functions.FALSE;
+
+
+/**
+ * @param {string} command The command to check.
+ * @return {boolean} If true, field will not dispatch change events
+ * for commands of this type. This is useful for "seamless" plugins like
+ * dialogs and lorem ipsum.
+ */
+goog.editor.Plugin.prototype.isSilentCommand = goog.functions.FALSE;
+
+
+/** @override */
+goog.editor.Plugin.prototype.disposeInternal = function() {
+ if (this.getFieldObject()) {
+ this.unregisterFieldObject(this.getFieldObject());
+ }
+
+ goog.editor.Plugin.superClass_.disposeInternal.call(this);
+};
+
+
+/**
+ * @return {string} The ID unique to this plugin class. Note that different
+ * instances off the plugin share the same classId.
+ */
+goog.editor.Plugin.prototype.getTrogClassId;
+
+
+/**
+ * An enum of operations that plugins may support.
+ * @enum {number}
+ */
+goog.editor.Plugin.Op = {
+ KEYDOWN: 1,
+ KEYPRESS: 2,
+ KEYUP: 3,
+ SELECTION: 4,
+ SHORTCUT: 5,
+ EXEC_COMMAND: 6,
+ QUERY_COMMAND: 7,
+ PREPARE_CONTENTS_HTML: 8,
+ CLEAN_CONTENTS_HTML: 10,
+ CLEAN_CONTENTS_DOM: 11
+};
+
+
+/**
+ * A map from plugin operations to the names of the methods that
+ * invoke those operations.
+ */
+goog.editor.Plugin.OPCODE = goog.object.transpose(
+ goog.reflect.object(goog.editor.Plugin, {
+ handleKeyDown: goog.editor.Plugin.Op.KEYDOWN,
+ handleKeyPress: goog.editor.Plugin.Op.KEYPRESS,
+ handleKeyUp: goog.editor.Plugin.Op.KEYUP,
+ handleSelectionChange: goog.editor.Plugin.Op.SELECTION,
+ handleKeyboardShortcut: goog.editor.Plugin.Op.SHORTCUT,
+ execCommand: goog.editor.Plugin.Op.EXEC_COMMAND,
+ queryCommandValue: goog.editor.Plugin.Op.QUERY_COMMAND,
+ prepareContentsHtml: goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML,
+ cleanContentsHtml: goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML,
+ cleanContentsDom: goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM
+ }));
+
+
+/**
+ * A set of op codes that run even on disabled plugins.
+ */
+goog.editor.Plugin.IRREPRESSIBLE_OPS = goog.object.createSet(
+ goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML,
+ goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML,
+ goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM);
+
+
+/**
+ * Handles keydown. It is run before handleKeyboardShortcut and if it returns
+ * true handleKeyboardShortcut will not be called.
+ * @param {!goog.events.BrowserEvent} e The browser event.
+ * @return {boolean} Whether the event was handled and thus should *not* be
+ * propagated to other plugins or handleKeyboardShortcut.
+ */
+goog.editor.Plugin.prototype.handleKeyDown;
+
+
+/**
+ * Handles keypress. It is run before handleKeyboardShortcut and if it returns
+ * true handleKeyboardShortcut will not be called.
+ * @param {!goog.events.BrowserEvent} e The browser event.
+ * @return {boolean} Whether the event was handled and thus should *not* be
+ * propagated to other plugins or handleKeyboardShortcut.
+ */
+goog.editor.Plugin.prototype.handleKeyPress;
+
+
+/**
+ * Handles keyup.
+ * @param {!goog.events.BrowserEvent} e The browser event.
+ * @return {boolean} Whether the event was handled and thus should *not* be
+ * propagated to other plugins.
+ */
+goog.editor.Plugin.prototype.handleKeyUp;
+
+
+/**
+ * Handles selection change.
+ * @param {!goog.events.BrowserEvent=} opt_e The browser event.
+ * @param {!Node=} opt_target The node the selection changed to.
+ * @return {boolean} Whether the event was handled and thus should *not* be
+ * propagated to other plugins.
+ */
+goog.editor.Plugin.prototype.handleSelectionChange;
+
+
+/**
+ * Handles keyboard shortcuts. Preferred to using handleKey* as it will use
+ * the proper event based on browser and will be more performant. If
+ * handleKeyPress/handleKeyDown returns true, this will not be called. If the
+ * plugin handles the shortcut, it is responsible for dispatching appropriate
+ * events (change, selection change at the time of this comment). If the plugin
+ * calls execCommand on the editable field, then execCommand already takes care
+ * of dispatching events.
+ * NOTE: For performance reasons this is only called when any key is pressed
+ * in conjunction with ctrl/meta keys OR when a small subset of keys (defined
+ * in goog.editor.Field.POTENTIAL_SHORTCUT_KEYCODES_) are pressed without
+ * ctrl/meta keys. We specifically don't invoke it when altKey is pressed since
+ * alt key is used in many i8n UIs to enter certain characters.
+ * @param {!goog.events.BrowserEvent} e The browser event.
+ * @param {string} key The key pressed.
+ * @param {boolean} isModifierPressed Whether the ctrl/meta key was pressed or
+ * not.
+ * @return {boolean} Whether the event was handled and thus should *not* be
+ * propagated to other plugins. We also call preventDefault on the event if
+ * the return value is true.
+ */
+goog.editor.Plugin.prototype.handleKeyboardShortcut;
+
+
+/**
+ * Handles execCommand. This default implementation handles dispatching
+ * BEFORECHANGE, CHANGE, and SELECTIONCHANGE events, and calls
+ * execCommandInternal to perform the actual command. Plugins that want to
+ * do their own event dispatching should override execCommand, otherwise
+ * it is preferred to only override execCommandInternal.
+ *
+ * This version of execCommand will only work for single field plugins.
+ * Multi-field plugins must override execCommand.
+ *
+ * @param {string} command The command to execute.
+ * @param {...*} var_args Any additional parameters needed to
+ * execute the command.
+ * @return {*} The result of the execCommand, if any.
+ */
+goog.editor.Plugin.prototype.execCommand = function(command, var_args) {
+ // TODO(user): Replace all uses of isSilentCommand with plugins that just
+ // override this base execCommand method.
+ var silent = this.isSilentCommand(command);
+ if (!silent) {
+ // Stop listening to mutation events in Firefox while text formatting
+ // is happening. This prevents us from trying to size the field in the
+ // middle of an execCommand, catching the field in a strange intermediary
+ // state where both replacement nodes and original nodes are appended to
+ // the dom. Note that change events get turned back on by
+ // fieldObj.dispatchChange.
+ if (goog.userAgent.GECKO) {
+ this.getFieldObject().stopChangeEvents(true, true);
+ }
+
+ this.getFieldObject().dispatchBeforeChange();
+ }
+
+ try {
+ var result = this.execCommandInternal.apply(this, arguments);
+ } finally {
+ // If the above execCommandInternal call throws an exception, we still need
+ // to turn change events back on (see http://b/issue?id=1471355).
+ // NOTE: If if you add to or change the methods called in this finally
+ // block, please add them as expected calls to the unit test function
+ // testExecCommandException().
+ if (!silent) {
+ // dispatchChange includes a call to startChangeEvents, which unwinds the
+ // call to stopChangeEvents made before the try block.
+ this.getFieldObject().dispatchChange();
+ this.getFieldObject().dispatchSelectionChangeEvent();
+ }
+ }
+
+ return result;
+};
+
+
+/**
+ * Handles execCommand. This default implementation does nothing, and is
+ * called by execCommand, which handles event dispatching. This method should
+ * be overriden by plugins that don't need to do their own event dispatching.
+ * If custom event dispatching is needed, execCommand shoul be overriden
+ * instead.
+ *
+ * @param {string} command The command to execute.
+ * @param {...*} var_args Any additional parameters needed to
+ * execute the command.
+ * @return {*} The result of the execCommand, if any.
+ * @protected
+ */
+goog.editor.Plugin.prototype.execCommandInternal;
+
+
+/**
+ * Gets the state of this command if this plugin serves that command.
+ * @param {string} command The command to check.
+ * @return {*} The value of the command.
+ */
+goog.editor.Plugin.prototype.queryCommandValue;
+
+
+/**
+ * Prepares the given HTML for editing. Strips out content that should not
+ * appear in an editor, and normalizes content as appropriate. The inverse
+ * of cleanContentsHtml.
+ *
+ * This op is invoked even on disabled plugins.
+ *
+ * @param {string} originalHtml The original HTML.
+ * @param {Object} styles A map of strings. If the plugin wants to add
+ * any styles to the field element, it should add them as key-value
+ * pairs to this object.
+ * @return {string} New HTML that's ok for editing.
+ */
+goog.editor.Plugin.prototype.prepareContentsHtml;
+
+
+/**
+ * Cleans the contents of the node passed to it. The node contents are modified
+ * directly, and the modifications will subsequently be used, for operations
+ * such as saving the innerHTML of the editor etc. Since the plugins act on
+ * the DOM directly, this method can be very expensive.
+ *
+ * This op is invoked even on disabled plugins.
+ *
+ * @param {!Element} fieldCopy The copy of the editable field which
+ * needs to be cleaned up.
+ */
+goog.editor.Plugin.prototype.cleanContentsDom;
+
+
+/**
+ * Cleans the html contents of Trogedit. Both cleanContentsDom and
+ * and cleanContentsHtml will be called on contents extracted from Trogedit.
+ * The inverse of prepareContentsHtml.
+ *
+ * This op is invoked even on disabled plugins.
+ *
+ * @param {string} originalHtml The trogedit HTML.
+ * @return {string} Cleaned-up HTML.
+ */
+goog.editor.Plugin.prototype.cleanContentsHtml;
+
+
+/**
+ * Whether the string corresponds to a command this plugin handles.
+ * @param {string} command Command string to check.
+ * @return {boolean} Whether the plugin handles this type of command.
+ */
+goog.editor.Plugin.prototype.isSupportedCommand = function(command) {
+ return false;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/abstractbubbleplugin.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/abstractbubbleplugin.js b/externs/GCL/externs/goog/editor/plugins/abstractbubbleplugin.js
new file mode 100644
index 0000000..4951ed6
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/abstractbubbleplugin.js
@@ -0,0 +1,712 @@
+// 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 Base class for bubble plugins.
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.AbstractBubblePlugin');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.classlist');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.style');
+goog.require('goog.events');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventType');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.events.actionEventWrapper');
+goog.require('goog.functions');
+goog.require('goog.string.Unicode');
+goog.require('goog.ui.Component');
+goog.require('goog.ui.editor.Bubble');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Base class for bubble plugins. This is used for to connect user behavior
+ * in the editor to a goog.ui.editor.Bubble UI element that allows
+ * the user to modify the properties of an element on their page (e.g. the alt
+ * text of an image tag).
+ *
+ * Subclasses should override the abstract method getBubbleTargetFromSelection()
+ * with code to determine if the current selection should activate the bubble
+ * type. The other abstract method createBubbleContents() should be overriden
+ * with code to create the inside markup of the bubble. The base class creates
+ * the rest of the bubble.
+ *
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ */
+goog.editor.plugins.AbstractBubblePlugin = function() {
+ goog.editor.plugins.AbstractBubblePlugin.base(this, 'constructor');
+
+ /**
+ * Place to register events the plugin listens to.
+ * @type {goog.events.EventHandler<
+ * !goog.editor.plugins.AbstractBubblePlugin>}
+ * @protected
+ */
+ this.eventRegister = new goog.events.EventHandler(this);
+
+ /**
+ * Instance factory function that creates a bubble UI component. If set to a
+ * non-null value, this function will be used to create a bubble instead of
+ * the global factory function. It takes as parameters the bubble parent
+ * element and the z index to draw the bubble at.
+ * @type {?function(!Element, number): !goog.ui.editor.Bubble}
+ * @private
+ */
+ this.bubbleFactory_ = null;
+};
+goog.inherits(goog.editor.plugins.AbstractBubblePlugin, goog.editor.Plugin);
+
+
+/**
+ * The css class name of option link elements.
+ * @type {string}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.OPTION_LINK_CLASSNAME_ =
+ goog.getCssName('tr_option-link');
+
+
+/**
+ * The css class name of link elements.
+ * @type {string}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.LINK_CLASSNAME_ =
+ goog.getCssName('tr_bubble_link');
+
+
+/**
+ * A class name to mark elements that should be reachable by keyboard tabbing.
+ * @type {string}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_ =
+ goog.getCssName('tr_bubble_tabbable');
+
+
+/**
+ * The constant string used to separate option links.
+ * @type {string}
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.DASH_NBSP_STRING =
+ goog.string.Unicode.NBSP + '-' + goog.string.Unicode.NBSP;
+
+
+/**
+ * Default factory function for creating a bubble UI component.
+ * @param {!Element} parent The parent element for the bubble.
+ * @param {number} zIndex The z index to draw the bubble at.
+ * @return {!goog.ui.editor.Bubble} The new bubble component.
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.defaultBubbleFactory_ = function(
+ parent, zIndex) {
+ return new goog.ui.editor.Bubble(parent, zIndex);
+};
+
+
+/**
+ * Global factory function that creates a bubble UI component. It takes as
+ * parameters the bubble parent element and the z index to draw the bubble at.
+ * @type {function(!Element, number): !goog.ui.editor.Bubble}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.globalBubbleFactory_ =
+ goog.editor.plugins.AbstractBubblePlugin.defaultBubbleFactory_;
+
+
+/**
+ * Sets the global bubble factory function.
+ * @param {function(!Element, number): !goog.ui.editor.Bubble}
+ * bubbleFactory Function that creates a bubble for the given bubble parent
+ * element and z index.
+ */
+goog.editor.plugins.AbstractBubblePlugin.setBubbleFactory = function(
+ bubbleFactory) {
+ goog.editor.plugins.AbstractBubblePlugin.globalBubbleFactory_ = bubbleFactory;
+};
+
+
+/**
+ * Map from field id to shared bubble object.
+ * @type {!Object<goog.ui.editor.Bubble>}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.bubbleMap_ = {};
+
+
+/**
+ * The optional parent of the bubble. If null or not set, we will use the
+ * application document. This is useful when you have an editor embedded in
+ * a scrolling DIV.
+ * @type {Element|undefined}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.bubbleParent_;
+
+
+/**
+ * The id of the panel this plugin added to the shared bubble. Null when
+ * this plugin doesn't currently have a panel in a bubble.
+ * @type {string?}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.panelId_ = null;
+
+
+/**
+ * Whether this bubble should support tabbing through elements. False
+ * by default.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.keyboardNavigationEnabled_ =
+ false;
+
+
+/**
+ * Sets the instance bubble factory function. If set to a non-null value, this
+ * function will be used to create a bubble instead of the global factory
+ * function.
+ * @param {?function(!Element, number): !goog.ui.editor.Bubble} bubbleFactory
+ * Function that creates a bubble for the given bubble parent element and z
+ * index. Null to reset the factory function.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.setBubbleFactory = function(
+ bubbleFactory) {
+ this.bubbleFactory_ = bubbleFactory;
+};
+
+
+/**
+ * Sets whether the bubble should support tabbing through elements.
+ * @param {boolean} keyboardNavigationEnabled
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.enableKeyboardNavigation =
+ function(keyboardNavigationEnabled) {
+ this.keyboardNavigationEnabled_ = keyboardNavigationEnabled;
+};
+
+
+/**
+ * Sets the bubble parent.
+ * @param {Element} bubbleParent An element where the bubble will be
+ * anchored. If null, we will use the application document. This
+ * is useful when you have an editor embedded in a scrolling div.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.setBubbleParent = function(
+ bubbleParent) {
+ this.bubbleParent_ = bubbleParent;
+};
+
+
+/**
+ * Returns the bubble map. Subclasses may override to use a separate map.
+ * @return {!Object<goog.ui.editor.Bubble>}
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleMap = function() {
+ return goog.editor.plugins.AbstractBubblePlugin.bubbleMap_;
+};
+
+
+/**
+ * @return {goog.dom.DomHelper} The dom helper for the bubble window.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleDom = function() {
+ return this.dom_;
+};
+
+
+/** @override */
+goog.editor.plugins.AbstractBubblePlugin.prototype.getTrogClassId =
+ goog.functions.constant('AbstractBubblePlugin');
+
+
+/**
+ * Returns the element whose properties the bubble manipulates.
+ * @return {Element} The target element.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.getTargetElement =
+ function() {
+ return this.targetElement_;
+};
+
+
+/** @override */
+goog.editor.plugins.AbstractBubblePlugin.prototype.handleKeyUp = function(e) {
+ // For example, when an image is selected, pressing any key overwrites
+ // the image and the panel should be hidden.
+ // Therefore we need to track key presses when the bubble is showing.
+ if (this.isVisible()) {
+ this.handleSelectionChange();
+ }
+ return false;
+};
+
+
+/**
+ * Pops up a property bubble for the given selection if appropriate and closes
+ * open property bubbles if no longer needed. This should not be overridden.
+ * @override
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.handleSelectionChange =
+ function(opt_e, opt_target) {
+ var selectedElement;
+ if (opt_e) {
+ selectedElement = /** @type {Element} */ (opt_e.target);
+ } else if (opt_target) {
+ selectedElement = /** @type {Element} */ (opt_target);
+ } else {
+ var range = this.getFieldObject().getRange();
+ if (range) {
+ var startNode = range.getStartNode();
+ var endNode = range.getEndNode();
+ var startOffset = range.getStartOffset();
+ var endOffset = range.getEndOffset();
+ // Sometimes in IE, the range will be collapsed, but think the end node
+ // and start node are different (although in the same visible position).
+ // In this case, favor the position IE thinks is the start node.
+ if (goog.userAgent.IE && range.isCollapsed() && startNode != endNode) {
+ range = goog.dom.Range.createCaret(startNode, startOffset);
+ }
+ if (startNode.nodeType == goog.dom.NodeType.ELEMENT &&
+ startNode == endNode && startOffset == endOffset - 1) {
+ var element = startNode.childNodes[startOffset];
+ if (element.nodeType == goog.dom.NodeType.ELEMENT) {
+ selectedElement = element;
+ }
+ }
+ }
+ selectedElement = selectedElement || range && range.getContainerElement();
+ }
+ return this.handleSelectionChangeInternal(selectedElement);
+};
+
+
+/**
+ * Pops up a property bubble for the given selection if appropriate and closes
+ * open property bubbles if no longer needed.
+ * @param {Element?} selectedElement The selected element.
+ * @return {boolean} Always false, allowing every bubble plugin to handle the
+ * event.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.
+ handleSelectionChangeInternal = function(selectedElement) {
+ if (selectedElement) {
+ var bubbleTarget = this.getBubbleTargetFromSelection(selectedElement);
+ if (bubbleTarget) {
+ if (bubbleTarget != this.targetElement_ || !this.panelId_) {
+ // Make sure any existing panel of the same type is closed before
+ // creating a new one.
+ if (this.panelId_) {
+ this.closeBubble();
+ }
+ this.createBubble(bubbleTarget);
+ }
+ return false;
+ }
+ }
+
+ if (this.panelId_) {
+ this.closeBubble();
+ }
+
+ return false;
+};
+
+
+/**
+ * Should be overriden by subclasses to return the bubble target element or
+ * null if an element of their required type isn't found.
+ * @param {Element} selectedElement The target of the selection change event or
+ * the parent container of the current entire selection.
+ * @return {Element?} The HTML bubble target element or null if no element of
+ * the required type is not found.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.
+ getBubbleTargetFromSelection = goog.abstractMethod;
+
+
+/** @override */
+goog.editor.plugins.AbstractBubblePlugin.prototype.disable = function(field) {
+ // When the field is made uneditable, dispose of the bubble. We do this
+ // because the next time the field is made editable again it may be in
+ // a different document / iframe.
+ if (field.isUneditable()) {
+ var bubbleMap = this.getBubbleMap();
+ var bubble = bubbleMap[field.id];
+ if (bubble) {
+ if (field == this.getFieldObject()) {
+ this.closeBubble();
+ }
+ bubble.dispose();
+ delete bubbleMap[field.id];
+ }
+ }
+};
+
+
+/**
+ * @return {!goog.ui.editor.Bubble} The shared bubble object for the field this
+ * plugin is registered on. Creates it if necessary.
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.getSharedBubble_ =
+ function() {
+ var bubbleParent = /** @type {!Element} */ (this.bubbleParent_ ||
+ this.getFieldObject().getAppWindow().document.body);
+ this.dom_ = goog.dom.getDomHelper(bubbleParent);
+
+ var bubbleMap = this.getBubbleMap();
+ var bubble = bubbleMap[this.getFieldObject().id];
+ if (!bubble) {
+ var factory = this.bubbleFactory_ ||
+ goog.editor.plugins.AbstractBubblePlugin.globalBubbleFactory_;
+ bubble = factory.call(null, bubbleParent,
+ this.getFieldObject().getBaseZindex());
+ bubbleMap[this.getFieldObject().id] = bubble;
+ }
+ return bubble;
+};
+
+
+/**
+ * Creates and shows the property bubble.
+ * @param {Element} targetElement The target element of the bubble.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.createBubble = function(
+ targetElement) {
+ var bubble = this.getSharedBubble_();
+ if (!bubble.hasPanelOfType(this.getBubbleType())) {
+ this.targetElement_ = targetElement;
+
+ this.panelId_ = bubble.addPanel(this.getBubbleType(), this.getBubbleTitle(),
+ targetElement,
+ goog.bind(this.createBubbleContents, this),
+ this.shouldPreferBubbleAboveElement());
+ this.eventRegister.listen(bubble, goog.ui.Component.EventType.HIDE,
+ this.handlePanelClosed_);
+
+ this.onShow();
+
+ if (this.keyboardNavigationEnabled_) {
+ this.eventRegister.listen(bubble.getContentElement(),
+ goog.events.EventType.KEYDOWN, this.onBubbleKey_);
+ }
+ }
+};
+
+
+/**
+ * @return {string} The type of bubble shown by this plugin. Usually the tag
+ * name of the element this bubble targets.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleType = function() {
+ return '';
+};
+
+
+/**
+ * @return {string} The title for bubble shown by this plugin. Defaults to no
+ * title. Should be overridden by subclasses.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleTitle = function() {
+ return '';
+};
+
+
+/**
+ * @return {boolean} Whether the bubble should prefer placement above the
+ * target element.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.
+ shouldPreferBubbleAboveElement = goog.functions.FALSE;
+
+
+/**
+ * Should be overriden by subclasses to add the type specific contents to the
+ * bubble.
+ * @param {Element} bubbleContainer The container element of the bubble to
+ * which the contents should be added.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.createBubbleContents =
+ goog.abstractMethod;
+
+
+/**
+ * Register the handler for the target's CLICK event.
+ * @param {Element} target The event source element.
+ * @param {Function} handler The event handler.
+ * @protected
+ * @deprecated Use goog.editor.plugins.AbstractBubblePlugin.
+ * registerActionHandler to register click and enter events.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.registerClickHandler =
+ function(target, handler) {
+ this.registerActionHandler(target, handler);
+};
+
+
+/**
+ * Register the handler for the target's CLICK and ENTER key events.
+ * @param {Element} target The event source element.
+ * @param {Function} handler The event handler.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.registerActionHandler =
+ function(target, handler) {
+ this.eventRegister.listenWithWrapper(target, goog.events.actionEventWrapper,
+ handler);
+};
+
+
+/**
+ * Closes the bubble.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.closeBubble = function() {
+ if (this.panelId_) {
+ this.getSharedBubble_().removePanel(this.panelId_);
+ this.handlePanelClosed_();
+ }
+};
+
+
+/**
+ * Called after the bubble is shown. The default implementation does nothing.
+ * Override it to provide your own one.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.onShow = goog.nullFunction;
+
+
+/**
+ * Called when the bubble is closed or hidden. The default implementation does
+ * nothing.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.cleanOnBubbleClose =
+ goog.nullFunction;
+
+
+/**
+ * Handles when the bubble panel is closed. Invoked when the entire bubble is
+ * hidden and also directly when the panel is closed manually.
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.handlePanelClosed_ =
+ function() {
+ this.targetElement_ = null;
+ this.panelId_ = null;
+ this.eventRegister.removeAll();
+ this.cleanOnBubbleClose();
+};
+
+
+/**
+ * In case the keyboard navigation is enabled, this will set focus on the first
+ * tabbable element in the bubble when TAB is clicked.
+ * @override
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.handleKeyDown = function(e) {
+ if (this.keyboardNavigationEnabled_ &&
+ this.isVisible() &&
+ e.keyCode == goog.events.KeyCodes.TAB && !e.shiftKey) {
+ var bubbleEl = this.getSharedBubble_().getContentElement();
+ var tabbable = goog.dom.getElementByClass(
+ goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_, bubbleEl);
+ if (tabbable) {
+ tabbable.focus();
+ e.preventDefault();
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Handles a key event on the bubble. This ensures that the focus loops through
+ * the tabbable elements found in the bubble and then the focus is got by the
+ * field element.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.onBubbleKey_ = function(e) {
+ if (this.isVisible() &&
+ e.keyCode == goog.events.KeyCodes.TAB) {
+ var bubbleEl = this.getSharedBubble_().getContentElement();
+ var tabbables = goog.dom.getElementsByClass(
+ goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_, bubbleEl);
+ var tabbable = e.shiftKey ? tabbables[0] : goog.array.peek(tabbables);
+ var tabbingOutOfBubble = tabbable == e.target;
+ if (tabbingOutOfBubble) {
+ this.getFieldObject().focus();
+ e.preventDefault();
+ }
+ }
+};
+
+
+/**
+ * @return {boolean} Whether the bubble is visible.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.isVisible = function() {
+ return !!this.panelId_;
+};
+
+
+/**
+ * Reposition the property bubble.
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.reposition = function() {
+ var bubble = this.getSharedBubble_();
+ if (bubble) {
+ bubble.reposition();
+ }
+};
+
+
+/**
+ * Helper method that creates option links (such as edit, test, remove)
+ * @param {string} id String id for the span id.
+ * @return {Element} The option link element.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.createLinkOption = function(
+ id) {
+ // Dash plus link are together in a span so we can hide/show them easily
+ return this.dom_.createDom(goog.dom.TagName.SPAN,
+ {
+ id: id,
+ className:
+ goog.editor.plugins.AbstractBubblePlugin.OPTION_LINK_CLASSNAME_
+ },
+ this.dom_.createTextNode(
+ goog.editor.plugins.AbstractBubblePlugin.DASH_NBSP_STRING));
+};
+
+
+/**
+ * Helper method that creates a link with text set to linkText and optionally
+ * wires up a listener for the CLICK event or the link. The link is navigable by
+ * tabs if {@code enableKeyboardNavigation(true)} was called.
+ * @param {string} linkId The id of the link.
+ * @param {string} linkText Text of the link.
+ * @param {Function=} opt_onClick Optional function to call when the link is
+ * clicked.
+ * @param {Element=} opt_container If specified, location to insert link. If no
+ * container is specified, the old link is removed and replaced.
+ * @return {Element} The link element.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.createLink = function(
+ linkId, linkText, opt_onClick, opt_container) {
+ var link = this.createLinkHelper(linkId, linkText, false, opt_container);
+ if (opt_onClick) {
+ this.registerActionHandler(link, opt_onClick);
+ }
+ return link;
+};
+
+
+/**
+ * Helper method to create a link to insert into the bubble. The link is
+ * navigable by tabs if {@code enableKeyboardNavigation(true)} was called.
+ * @param {string} linkId The id of the link.
+ * @param {string} linkText Text of the link.
+ * @param {boolean} isAnchor Set to true to create an actual anchor tag
+ * instead of a span. Actual links are right clickable (e.g. to open in
+ * a new window) and also update window status on hover.
+ * @param {Element=} opt_container If specified, location to insert link. If no
+ * container is specified, the old link is removed and replaced.
+ * @return {Element} The link element.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.createLinkHelper = function(
+ linkId, linkText, isAnchor, opt_container) {
+ var link = this.dom_.createDom(
+ isAnchor ? goog.dom.TagName.A : goog.dom.TagName.SPAN,
+ {className: goog.editor.plugins.AbstractBubblePlugin.LINK_CLASSNAME_},
+ linkText);
+ if (this.keyboardNavigationEnabled_) {
+ this.setTabbable(link);
+ }
+ link.setAttribute('role', 'link');
+ this.setupLink(link, linkId, opt_container);
+ goog.editor.style.makeUnselectable(link, this.eventRegister);
+ return link;
+};
+
+
+/**
+ * Makes the given element tabbable.
+ *
+ * <p>Elements created by createLink[Helper] are tabbable even without
+ * calling this method. Call it for other elements if needed.
+ *
+ * <p>If tabindex is not already set in the element, this function sets it to 0.
+ * You'll usually want to also call {@code enableKeyboardNavigation(true)}.
+ *
+ * @param {!Element} element
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.setTabbable =
+ function(element) {
+ if (!element.hasAttribute('tabindex')) {
+ element.setAttribute('tabindex', 0);
+ }
+ goog.dom.classlist.add(element,
+ goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_);
+};
+
+
+/**
+ * Inserts a link in the given container if it is specified or removes
+ * the old link with this id and replaces it with the new link
+ * @param {Element} link Html element to insert.
+ * @param {string} linkId Id of the link.
+ * @param {Element=} opt_container If specified, location to insert link.
+ * @protected
+ */
+goog.editor.plugins.AbstractBubblePlugin.prototype.setupLink = function(
+ link, linkId, opt_container) {
+ if (opt_container) {
+ opt_container.appendChild(link);
+ } else {
+ var oldLink = this.dom_.getElement(linkId);
+ if (oldLink) {
+ goog.dom.replaceNode(link, oldLink);
+ }
+ }
+
+ link.id = linkId;
+};
[47/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/base.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/base.js b/externs/GCL/externs/goog/base.js
new file mode 100644
index 0000000..bb232f8
--- /dev/null
+++ b/externs/GCL/externs/goog/base.js
@@ -0,0 +1,2547 @@
+// 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 Bootstrap for the Google JS Library (Closure).
+ *
+ * In uncompiled mode base.js will write out Closure's deps file, unless the
+ * global <code>CLOSURE_NO_DEPS</code> is set to true. This allows projects to
+ * include their own deps file(s) from different locations.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * @provideGoog
+ */
+
+
+/**
+ * @define {boolean} Overridden to true by the compiler when --closure_pass
+ * or --mark_as_compiled is specified.
+ */
+var COMPILED = false;
+
+
+/**
+ * Base namespace for the Closure library. Checks to see goog is already
+ * defined in the current scope before assigning to prevent clobbering if
+ * base.js is loaded more than once.
+ *
+ * @const
+ */
+var goog = goog || {};
+
+
+/**
+ * Reference to the global context. In most cases this will be 'window'.
+ */
+goog.global = this;
+
+
+/**
+ * A hook for overriding the define values in uncompiled mode.
+ *
+ * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before
+ * loading base.js. If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES},
+ * {@code goog.define} will use the value instead of the default value. This
+ * allows flags to be overwritten without compilation (this is normally
+ * accomplished with the compiler's "define" flag).
+ *
+ * Example:
+ * <pre>
+ * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
+ * </pre>
+ *
+ * @type {Object<string, (string|number|boolean)>|undefined}
+ */
+goog.global.CLOSURE_UNCOMPILED_DEFINES;
+
+
+/**
+ * A hook for overriding the define values in uncompiled or compiled mode,
+ * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In
+ * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.
+ *
+ * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or
+ * string literals or the compiler will emit an error.
+ *
+ * While any @define value may be set, only those set with goog.define will be
+ * effective for uncompiled code.
+ *
+ * Example:
+ * <pre>
+ * var CLOSURE_DEFINES = {'goog.DEBUG': false} ;
+ * </pre>
+ *
+ * @type {Object<string, (string|number|boolean)>|undefined}
+ */
+goog.global.CLOSURE_DEFINES;
+
+
+/**
+ * Returns true if the specified value is not undefined.
+ * WARNING: Do not use this to test if an object has a property. Use the in
+ * operator instead.
+ *
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is defined.
+ */
+goog.isDef = function(val) {
+ // void 0 always evaluates to undefined and hence we do not need to depend on
+ // the definition of the global variable named 'undefined'.
+ return val !== void 0;
+};
+
+
+/**
+ * Builds an object structure for the provided namespace path, ensuring that
+ * names that already exist are not overwritten. For example:
+ * "a.b.c" -> a = {};a.b={};a.b.c={};
+ * Used by goog.provide and goog.exportSymbol.
+ * @param {string} name name of the object that this file defines.
+ * @param {*=} opt_object the object to expose at the end of the path.
+ * @param {Object=} opt_objectToExportTo The object to add the path to; default
+ * is |goog.global|.
+ * @private
+ */
+goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
+ var parts = name.split('.');
+ var cur = opt_objectToExportTo || goog.global;
+
+ // Internet Explorer exhibits strange behavior when throwing errors from
+ // methods externed in this manner. See the testExportSymbolExceptions in
+ // base_test.html for an example.
+ if (!(parts[0] in cur) && cur.execScript) {
+ cur.execScript('var ' + parts[0]);
+ }
+
+ // Certain browsers cannot parse code in the form for((a in b); c;);
+ // This pattern is produced by the JSCompiler when it collapses the
+ // statement above into the conditional loop below. To prevent this from
+ // happening, use a for-loop and reserve the init logic as below.
+
+ // Parentheses added to eliminate strict JS warning in Firefox.
+ for (var part; parts.length && (part = parts.shift());) {
+ if (!parts.length && goog.isDef(opt_object)) {
+ // last part and we have an object; use it
+ cur[part] = opt_object;
+ } else if (cur[part]) {
+ cur = cur[part];
+ } else {
+ cur = cur[part] = {};
+ }
+ }
+};
+
+
+/**
+ * Defines a named value. In uncompiled mode, the value is retrieved from
+ * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and
+ * has the property specified, and otherwise used the defined defaultValue.
+ * When compiled the default can be overridden using the compiler
+ * options or the value set in the CLOSURE_DEFINES object.
+ *
+ * @param {string} name The distinguished name to provide.
+ * @param {string|number|boolean} defaultValue
+ */
+goog.define = function(name, defaultValue) {
+ var value = defaultValue;
+ if (!COMPILED) {
+ if (goog.global.CLOSURE_UNCOMPILED_DEFINES &&
+ Object.prototype.hasOwnProperty.call(
+ goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
+ value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
+ } else if (goog.global.CLOSURE_DEFINES &&
+ Object.prototype.hasOwnProperty.call(
+ goog.global.CLOSURE_DEFINES, name)) {
+ value = goog.global.CLOSURE_DEFINES[name];
+ }
+ }
+ goog.exportPath_(name, value);
+};
+
+
+/**
+ * @define {boolean} DEBUG is provided as a convenience so that debugging code
+ * that should not be included in a production js_binary can be easily stripped
+ * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
+ * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
+ * because they are generally used for debugging purposes and it is difficult
+ * for the JSCompiler to statically determine whether they are used.
+ */
+goog.define('goog.DEBUG', true);
+
+
+/**
+ * @define {string} LOCALE defines the locale being used for compilation. It is
+ * used to select locale specific data to be compiled in js binary. BUILD rule
+ * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler
+ * option.
+ *
+ * Take into account that the locale code format is important. You should use
+ * the canonical Unicode format with hyphen as a delimiter. Language must be
+ * lowercase, Language Script - Capitalized, Region - UPPERCASE.
+ * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
+ *
+ * See more info about locale codes here:
+ * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
+ *
+ * For language codes you should use values defined by ISO 693-1. See it here
+ * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
+ * this rule: the Hebrew language. For legacy reasons the old code (iw) should
+ * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.
+ */
+goog.define('goog.LOCALE', 'en'); // default to en
+
+
+/**
+ * @define {boolean} Whether this code is running on trusted sites.
+ *
+ * On untrusted sites, several native functions can be defined or overridden by
+ * external libraries like Prototype, Datejs, and JQuery and setting this flag
+ * to false forces closure to use its own implementations when possible.
+ *
+ * If your JavaScript can be loaded by a third party site and you are wary about
+ * relying on non-standard implementations, specify
+ * "--define goog.TRUSTED_SITE=false" to the JSCompiler.
+ */
+goog.define('goog.TRUSTED_SITE', true);
+
+
+/**
+ * @define {boolean} Whether a project is expected to be running in strict mode.
+ *
+ * This define can be used to trigger alternate implementations compatible with
+ * running in EcmaScript Strict mode or warn about unavailable functionality.
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
+ *
+ */
+goog.define('goog.STRICT_MODE_COMPATIBLE', false);
+
+
+/**
+ * @define {boolean} Whether code that calls {@link goog.setTestOnly} should
+ * be disallowed in the compilation unit.
+ */
+goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG);
+
+
+/**
+ * @define {boolean} Whether to use a Chrome app CSP-compliant method for
+ * loading scripts via goog.require. @see appendScriptSrcNode_.
+ */
+goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false);
+
+
+/**
+ * Defines a namespace in Closure.
+ *
+ * A namespace may only be defined once in a codebase. It may be defined using
+ * goog.provide() or goog.module().
+ *
+ * The presence of one or more goog.provide() calls in a file indicates
+ * that the file defines the given objects/namespaces.
+ * Provided symbols must not be null or undefined.
+ *
+ * In addition, goog.provide() creates the object stubs for a namespace
+ * (for example, goog.provide("goog.foo.bar") will create the object
+ * goog.foo.bar if it does not already exist).
+ *
+ * Build tools also scan for provide/require/module statements
+ * to discern dependencies, build dependency files (see deps.js), etc.
+ *
+ * @see goog.require
+ * @see goog.module
+ * @param {string} name Namespace provided by this file in the form
+ * "goog.package.part".
+ */
+goog.provide = function(name) {
+ if (!COMPILED) {
+ // Ensure that the same namespace isn't provided twice.
+ // A goog.module/goog.provide maps a goog.require to a specific file
+ if (goog.isProvided_(name)) {
+ throw Error('Namespace "' + name + '" already declared.');
+ }
+ }
+
+ goog.constructNamespace_(name);
+};
+
+
+/**
+ * @param {string} name Namespace provided by this file in the form
+ * "goog.package.part".
+ * @param {Object=} opt_obj The object to embed in the namespace.
+ * @private
+ */
+goog.constructNamespace_ = function(name, opt_obj) {
+ if (!COMPILED) {
+ delete goog.implicitNamespaces_[name];
+
+ var namespace = name;
+ while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
+ if (goog.getObjectByName(namespace)) {
+ break;
+ }
+ goog.implicitNamespaces_[namespace] = true;
+ }
+ }
+
+ goog.exportPath_(name, opt_obj);
+};
+
+
+/**
+ * Module identifier validation regexp.
+ * Note: This is a conservative check, it is very possible to be more lenient,
+ * the primary exclusion here is "/" and "\" and a leading ".", these
+ * restrictions are intended to leave the door open for using goog.require
+ * with relative file paths rather than module identifiers.
+ * @private
+ */
+goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
+
+
+/**
+ * Defines a module in Closure.
+ *
+ * Marks that this file must be loaded as a module and claims the namespace.
+ *
+ * A namespace may only be defined once in a codebase. It may be defined using
+ * goog.provide() or goog.module().
+ *
+ * goog.module() has three requirements:
+ * - goog.module may not be used in the same file as goog.provide.
+ * - goog.module must be the first statement in the file.
+ * - only one goog.module is allowed per file.
+ *
+ * When a goog.module annotated file is loaded, it is enclosed in
+ * a strict function closure. This means that:
+ * - any variables declared in a goog.module file are private to the file
+ * (not global), though the compiler is expected to inline the module.
+ * - The code must obey all the rules of "strict" JavaScript.
+ * - the file will be marked as "use strict"
+ *
+ * NOTE: unlike goog.provide, goog.module does not declare any symbols by
+ * itself. If declared symbols are desired, use
+ * goog.module.declareLegacyNamespace().
+ *
+ *
+ * See the public goog.module proposal: http://goo.gl/Va1hin
+ *
+ * @param {string} name Namespace provided by this file in the form
+ * "goog.package.part", is expected but not required.
+ */
+goog.module = function(name) {
+ if (!goog.isString(name) ||
+ !name ||
+ name.search(goog.VALID_MODULE_RE_) == -1) {
+ throw Error('Invalid module identifier');
+ }
+ if (!goog.isInModuleLoader_()) {
+ throw Error('Module ' + name + ' has been loaded incorrectly.');
+ }
+ if (goog.moduleLoaderState_.moduleName) {
+ throw Error('goog.module may only be called once per module.');
+ }
+
+ // Store the module name for the loader.
+ goog.moduleLoaderState_.moduleName = name;
+ if (!COMPILED) {
+ // Ensure that the same namespace isn't provided twice.
+ // A goog.module/goog.provide maps a goog.require to a specific file
+ if (goog.isProvided_(name)) {
+ throw Error('Namespace "' + name + '" already declared.');
+ }
+ delete goog.implicitNamespaces_[name];
+ }
+};
+
+
+/**
+ * @param {string} name The module identifier.
+ * @return {?} The module exports for an already loaded module or null.
+ *
+ * Note: This is not an alternative to goog.require, it does not
+ * indicate a hard dependency, instead it is used to indicate
+ * an optional dependency or to access the exports of a module
+ * that has already been loaded.
+ * @suppress {missingProvide}
+ */
+goog.module.get = function(name) {
+ return goog.module.getInternal_(name);
+};
+
+
+/**
+ * @param {string} name The module identifier.
+ * @return {?} The module exports for an already loaded module or null.
+ * @private
+ */
+goog.module.getInternal_ = function(name) {
+ if (!COMPILED) {
+ if (goog.isProvided_(name)) {
+ // goog.require only return a value with-in goog.module files.
+ return name in goog.loadedModules_ ?
+ goog.loadedModules_[name] :
+ goog.getObjectByName(name);
+ } else {
+ return null;
+ }
+ }
+};
+
+
+/**
+ * @private {?{
+ * moduleName: (string|undefined),
+ * declareTestMethods: boolean
+ * }}
+ */
+goog.moduleLoaderState_ = null;
+
+
+/**
+ * @private
+ * @return {boolean} Whether a goog.module is currently being initialized.
+ */
+goog.isInModuleLoader_ = function() {
+ return goog.moduleLoaderState_ != null;
+};
+
+
+/**
+ * Indicate that a module's exports that are known test methods should
+ * be copied to the global object. This makes the test methods visible to
+ * test runners that inspect the global object.
+ *
+ * TODO(johnlenz): Make the test framework aware of goog.module so
+ * that this isn't necessary. Alternately combine this with goog.setTestOnly
+ * to minimize boiler plate.
+ * @suppress {missingProvide}
+ * @deprecated This approach does not translate to ES6 module syntax, instead
+ * use goog.testing.testSuite to declare the test methods.
+ */
+goog.module.declareTestMethods = function() {
+ if (!goog.isInModuleLoader_()) {
+ throw new Error('goog.module.declareTestMethods must be called from ' +
+ 'within a goog.module');
+ }
+ goog.moduleLoaderState_.declareTestMethods = true;
+};
+
+
+/**
+ * Provide the module's exports as a globally accessible object under the
+ * module's declared name. This is intended to ease migration to goog.module
+ * for files that have existing usages.
+ * @suppress {missingProvide}
+ */
+goog.module.declareLegacyNamespace = function() {
+ if (!COMPILED && !goog.isInModuleLoader_()) {
+ throw new Error('goog.module.declareLegacyNamespace must be called from ' +
+ 'within a goog.module');
+ }
+ if (!COMPILED && !goog.moduleLoaderState_.moduleName) {
+ throw Error('goog.module must be called prior to ' +
+ 'goog.module.declareLegacyNamespace.');
+ }
+ goog.moduleLoaderState_.declareLegacyNamespace = true;
+};
+
+
+/**
+ * Marks that the current file should only be used for testing, and never for
+ * live code in production.
+ *
+ * In the case of unit tests, the message may optionally be an exact namespace
+ * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra
+ * provide (if not explicitly defined in the code).
+ *
+ * @param {string=} opt_message Optional message to add to the error that's
+ * raised when used in production code.
+ */
+goog.setTestOnly = function(opt_message) {
+ if (goog.DISALLOW_TEST_ONLY_CODE) {
+ opt_message = opt_message || '';
+ throw Error('Importing test-only code into non-debug environment' +
+ (opt_message ? ': ' + opt_message : '.'));
+ }
+};
+
+
+/**
+ * Forward declares a symbol. This is an indication to the compiler that the
+ * symbol may be used in the source yet is not required and may not be provided
+ * in compilation.
+ *
+ * The most common usage of forward declaration is code that takes a type as a
+ * function parameter but does not need to require it. By forward declaring
+ * instead of requiring, no hard dependency is made, and (if not required
+ * elsewhere) the namespace may never be required and thus, not be pulled
+ * into the JavaScript binary. If it is required elsewhere, it will be type
+ * checked as normal.
+ *
+ *
+ * @param {string} name The namespace to forward declare in the form of
+ * "goog.package.part".
+ */
+goog.forwardDeclare = function(name) {};
+
+
+if (!COMPILED) {
+
+ /**
+ * Check if the given name has been goog.provided. This will return false for
+ * names that are available only as implicit namespaces.
+ * @param {string} name name of the object to look for.
+ * @return {boolean} Whether the name has been provided.
+ * @private
+ */
+ goog.isProvided_ = function(name) {
+ return (name in goog.loadedModules_) ||
+ (!goog.implicitNamespaces_[name] &&
+ goog.isDefAndNotNull(goog.getObjectByName(name)));
+ };
+
+ /**
+ * Namespaces implicitly defined by goog.provide. For example,
+ * goog.provide('goog.events.Event') implicitly declares that 'goog' and
+ * 'goog.events' must be namespaces.
+ *
+ * @type {!Object<string, (boolean|undefined)>}
+ * @private
+ */
+ goog.implicitNamespaces_ = {'goog.module': true};
+
+ // NOTE: We add goog.module as an implicit namespace as goog.module is defined
+ // here and because the existing module package has not been moved yet out of
+ // the goog.module namespace. This satisifies both the debug loader and
+ // ahead-of-time dependency management.
+}
+
+
+/**
+ * Returns an object based on its fully qualified external name. The object
+ * is not found if null or undefined. If you are using a compilation pass that
+ * renames property names beware that using this function will not find renamed
+ * properties.
+ *
+ * @param {string} name The fully qualified name.
+ * @param {Object=} opt_obj The object within which to look; default is
+ * |goog.global|.
+ * @return {?} The value (object or primitive) or, if not found, null.
+ */
+goog.getObjectByName = function(name, opt_obj) {
+ var parts = name.split('.');
+ var cur = opt_obj || goog.global;
+ for (var part; part = parts.shift(); ) {
+ if (goog.isDefAndNotNull(cur[part])) {
+ cur = cur[part];
+ } else {
+ return null;
+ }
+ }
+ return cur;
+};
+
+
+/**
+ * Globalizes a whole namespace, such as goog or goog.lang.
+ *
+ * @param {!Object} obj The namespace to globalize.
+ * @param {Object=} opt_global The object to add the properties to.
+ * @deprecated Properties may be explicitly exported to the global scope, but
+ * this should no longer be done in bulk.
+ */
+goog.globalize = function(obj, opt_global) {
+ var global = opt_global || goog.global;
+ for (var x in obj) {
+ global[x] = obj[x];
+ }
+};
+
+
+/**
+ * Adds a dependency from a file to the files it requires.
+ * @param {string} relPath The path to the js file.
+ * @param {!Array<string>} provides An array of strings with
+ * the names of the objects this file provides.
+ * @param {!Array<string>} requires An array of strings with
+ * the names of the objects this file requires.
+ * @param {boolean=} opt_isModule Whether this dependency must be loaded as
+ * a module as declared by goog.module.
+ */
+goog.addDependency = function(relPath, provides, requires, opt_isModule) {
+ if (goog.DEPENDENCIES_ENABLED) {
+ var provide, require;
+ var path = relPath.replace(/\\/g, '/');
+ var deps = goog.dependencies_;
+ for (var i = 0; provide = provides[i]; i++) {
+ deps.nameToPath[provide] = path;
+ deps.pathIsModule[path] = !!opt_isModule;
+ }
+ for (var j = 0; require = requires[j]; j++) {
+ if (!(path in deps.requires)) {
+ deps.requires[path] = {};
+ }
+ deps.requires[path][require] = true;
+ }
+ }
+};
+
+
+
+
+// NOTE(nnaze): The debug DOM loader was included in base.js as an original way
+// to do "debug-mode" development. The dependency system can sometimes be
+// confusing, as can the debug DOM loader's asynchronous nature.
+//
+// With the DOM loader, a call to goog.require() is not blocking -- the script
+// will not load until some point after the current script. If a namespace is
+// needed at runtime, it needs to be defined in a previous script, or loaded via
+// require() with its registered dependencies.
+// User-defined namespaces may need their own deps file. See http://go/js_deps,
+// http://go/genjsdeps, or, externally, DepsWriter.
+// https://developers.google.com/closure/library/docs/depswriter
+//
+// Because of legacy clients, the DOM loader can't be easily removed from
+// base.js. Work is being done to make it disableable or replaceable for
+// different environments (DOM-less JavaScript interpreters like Rhino or V8,
+// for example). See bootstrap/ for more information.
+
+
+/**
+ * @define {boolean} Whether to enable the debug loader.
+ *
+ * If enabled, a call to goog.require() will attempt to load the namespace by
+ * appending a script tag to the DOM (if the namespace has been registered).
+ *
+ * If disabled, goog.require() will simply assert that the namespace has been
+ * provided (and depend on the fact that some outside tool correctly ordered
+ * the script).
+ */
+goog.define('goog.ENABLE_DEBUG_LOADER', true);
+
+
+/**
+ * @param {string} msg
+ * @private
+ */
+goog.logToConsole_ = function(msg) {
+ if (goog.global.console) {
+ goog.global.console['error'](msg);
+ }
+};
+
+
+/**
+ * Implements a system for the dynamic resolution of dependencies that works in
+ * parallel with the BUILD system. Note that all calls to goog.require will be
+ * stripped by the JSCompiler when the --closure_pass option is used.
+ * @see goog.provide
+ * @param {string} name Namespace to include (as was given in goog.provide()) in
+ * the form "goog.package.part".
+ * @return {?} If called within a goog.module file, the associated namespace or
+ * module otherwise null.
+ */
+goog.require = function(name) {
+
+ // If the object already exists we do not need do do anything.
+ if (!COMPILED) {
+ if (goog.ENABLE_DEBUG_LOADER && goog.IS_OLD_IE_) {
+ goog.maybeProcessDeferredDep_(name);
+ }
+
+ if (goog.isProvided_(name)) {
+ if (goog.isInModuleLoader_()) {
+ return goog.module.getInternal_(name);
+ } else {
+ return null;
+ }
+ }
+
+ if (goog.ENABLE_DEBUG_LOADER) {
+ var path = goog.getPathFromDeps_(name);
+ if (path) {
+ goog.included_[path] = true;
+ goog.writeScripts_();
+ return null;
+ }
+ }
+
+ var errorMessage = 'goog.require could not find: ' + name;
+ goog.logToConsole_(errorMessage);
+
+ throw Error(errorMessage);
+ }
+};
+
+
+/**
+ * Path for included scripts.
+ * @type {string}
+ */
+goog.basePath = '';
+
+
+/**
+ * A hook for overriding the base path.
+ * @type {string|undefined}
+ */
+goog.global.CLOSURE_BASE_PATH;
+
+
+/**
+ * Whether to write out Closure's deps file. By default, the deps are written.
+ * @type {boolean|undefined}
+ */
+goog.global.CLOSURE_NO_DEPS;
+
+
+/**
+ * A function to import a single script. This is meant to be overridden when
+ * Closure is being run in non-HTML contexts, such as web workers. It's defined
+ * in the global scope so that it can be set before base.js is loaded, which
+ * allows deps.js to be imported properly.
+ *
+ * The function is passed the script source, which is a relative URI. It should
+ * return true if the script was imported, false otherwise.
+ * @type {(function(string): boolean)|undefined}
+ */
+goog.global.CLOSURE_IMPORT_SCRIPT;
+
+
+/**
+ * Null function used for default values of callbacks, etc.
+ * @return {void} Nothing.
+ */
+goog.nullFunction = function() {};
+
+
+
+/**
+ * When defining a class Foo with an abstract method bar(), you can do:
+ * Foo.prototype.bar = goog.abstractMethod
+ *
+ * Now if a subclass of Foo fails to override bar(), an error will be thrown
+ * when bar() is invoked.
+ *
+ * Note: This does not take the name of the function to override as an argument
+ * because that would make it more difficult to obfuscate our JavaScript code.
+ *
+ * @type {!Function}
+ * @throws {Error} when invoked to indicate the method should be overridden.
+ */
+goog.abstractMethod = function() {
+ throw Error('unimplemented abstract method');
+};
+
+
+/**
+ * Adds a {@code getInstance} static method that always returns the same
+ * instance object.
+ * @param {!Function} ctor The constructor for the class to add the static
+ * method to.
+ */
+goog.addSingletonGetter = function(ctor) {
+ ctor.getInstance = function() {
+ if (ctor.instance_) {
+ return ctor.instance_;
+ }
+ if (goog.DEBUG) {
+ // NOTE: JSCompiler can't optimize away Array#push.
+ goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
+ }
+ return ctor.instance_ = new ctor;
+ };
+};
+
+
+/**
+ * All singleton classes that have been instantiated, for testing. Don't read
+ * it directly, use the {@code goog.testing.singleton} module. The compiler
+ * removes this variable if unused.
+ * @type {!Array<!Function>}
+ * @private
+ */
+goog.instantiatedSingletons_ = [];
+
+
+/**
+ * @define {boolean} Whether to load goog.modules using {@code eval} when using
+ * the debug loader. This provides a better debugging experience as the
+ * source is unmodified and can be edited using Chrome Workspaces or similar.
+ * However in some environments the use of {@code eval} is banned
+ * so we provide an alternative.
+ */
+goog.define('goog.LOAD_MODULE_USING_EVAL', true);
+
+
+/**
+ * @define {boolean} Whether the exports of goog.modules should be sealed when
+ * possible.
+ */
+goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG);
+
+
+/**
+ * The registry of initialized modules:
+ * the module identifier to module exports map.
+ * @private @const {!Object<string, ?>}
+ */
+goog.loadedModules_ = {};
+
+
+/**
+ * True if goog.dependencies_ is available.
+ * @const {boolean}
+ */
+goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
+
+
+if (goog.DEPENDENCIES_ENABLED) {
+ /**
+ * Object used to keep track of urls that have already been added. This record
+ * allows the prevention of circular dependencies.
+ * @private {!Object<string, boolean>}
+ */
+ goog.included_ = {};
+
+
+ /**
+ * This object is used to keep track of dependencies and other data that is
+ * used for loading scripts.
+ * @private
+ * @type {{
+ * pathIsModule: !Object<string, boolean>,
+ * nameToPath: !Object<string, string>,
+ * requires: !Object<string, !Object<string, boolean>>,
+ * visited: !Object<string, boolean>,
+ * written: !Object<string, boolean>,
+ * deferred: !Object<string, string>
+ * }}
+ */
+ goog.dependencies_ = {
+ pathIsModule: {}, // 1 to 1
+
+ nameToPath: {}, // 1 to 1
+
+ requires: {}, // 1 to many
+
+ // Used when resolving dependencies to prevent us from visiting file twice.
+ visited: {},
+
+ written: {}, // Used to keep track of script files we have written.
+
+ deferred: {} // Used to track deferred module evaluations in old IEs
+ };
+
+
+ /**
+ * Tries to detect whether is in the context of an HTML document.
+ * @return {boolean} True if it looks like HTML document.
+ * @private
+ */
+ goog.inHtmlDocument_ = function() {
+ var doc = goog.global.document;
+ return typeof doc != 'undefined' &&
+ 'write' in doc; // XULDocument misses write.
+ };
+
+
+ /**
+ * Tries to detect the base path of base.js script that bootstraps Closure.
+ * @private
+ */
+ goog.findBasePath_ = function() {
+ if (goog.global.CLOSURE_BASE_PATH) {
+ goog.basePath = goog.global.CLOSURE_BASE_PATH;
+ return;
+ } else if (!goog.inHtmlDocument_()) {
+ return;
+ }
+ var doc = goog.global.document;
+ var scripts = doc.getElementsByTagName('SCRIPT');
+ // Search backwards since the current script is in almost all cases the one
+ // that has base.js.
+ for (var i = scripts.length - 1; i >= 0; --i) {
+ var script = /** @type {!HTMLScriptElement} */ (scripts[i]);
+ var src = script.src;
+ var qmark = src.lastIndexOf('?');
+ var l = qmark == -1 ? src.length : qmark;
+ if (src.substr(l - 7, 7) == 'base.js') {
+ goog.basePath = src.substr(0, l - 7);
+ return;
+ }
+ }
+ };
+
+
+ /**
+ * Imports a script if, and only if, that script hasn't already been imported.
+ * (Must be called at execution time)
+ * @param {string} src Script source.
+ * @param {string=} opt_sourceText The optionally source text to evaluate
+ * @private
+ */
+ goog.importScript_ = function(src, opt_sourceText) {
+ var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
+ goog.writeScriptTag_;
+ if (importScript(src, opt_sourceText)) {
+ goog.dependencies_.written[src] = true;
+ }
+ };
+
+
+ /** @const @private {boolean} */
+ goog.IS_OLD_IE_ = !goog.global.atob && goog.global.document &&
+ goog.global.document.all;
+
+
+ /**
+ * Given a URL initiate retrieval and execution of the module.
+ * @param {string} src Script source URL.
+ * @private
+ */
+ goog.importModule_ = function(src) {
+ // In an attempt to keep browsers from timing out loading scripts using
+ // synchronous XHRs, put each load in its own script block.
+ var bootstrap = 'goog.retrieveAndExecModule_("' + src + '");';
+
+ if (goog.importScript_('', bootstrap)) {
+ goog.dependencies_.written[src] = true;
+ }
+ };
+
+
+ /** @private {!Array<string>} */
+ goog.queuedModules_ = [];
+
+
+ /**
+ * Return an appropriate module text. Suitable to insert into
+ * a script tag (that is unescaped).
+ * @param {string} srcUrl
+ * @param {string} scriptText
+ * @return {string}
+ * @private
+ */
+ goog.wrapModule_ = function(srcUrl, scriptText) {
+ if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) {
+ return '' +
+ 'goog.loadModule(function(exports) {' +
+ '"use strict";' +
+ scriptText +
+ '\n' + // terminate any trailing single line comment.
+ ';return exports' +
+ '});' +
+ '\n//# sourceURL=' + srcUrl + '\n';
+ } else {
+ return '' +
+ 'goog.loadModule(' +
+ goog.global.JSON.stringify(
+ scriptText + '\n//# sourceURL=' + srcUrl + '\n') +
+ ');';
+ }
+ };
+
+ // On IE9 and earlier, it is necessary to handle
+ // deferred module loads. In later browsers, the
+ // code to be evaluated is simply inserted as a script
+ // block in the correct order. To eval deferred
+ // code at the right time, we piggy back on goog.require to call
+ // goog.maybeProcessDeferredDep_.
+ //
+ // The goog.requires are used both to bootstrap
+ // the loading process (when no deps are available) and
+ // declare that they should be available.
+ //
+ // Here we eval the sources, if all the deps are available
+ // either already eval'd or goog.require'd. This will
+ // be the case when all the dependencies have already
+ // been loaded, and the dependent module is loaded.
+ //
+ // But this alone isn't sufficient because it is also
+ // necessary to handle the case where there is no root
+ // that is not deferred. For that there we register for an event
+ // and trigger goog.loadQueuedModules_ handle any remaining deferred
+ // evaluations.
+
+ /**
+ * Handle any remaining deferred goog.module evals.
+ * @private
+ */
+ goog.loadQueuedModules_ = function() {
+ var count = goog.queuedModules_.length;
+ if (count > 0) {
+ var queue = goog.queuedModules_;
+ goog.queuedModules_ = [];
+ for (var i = 0; i < count; i++) {
+ var path = queue[i];
+ goog.maybeProcessDeferredPath_(path);
+ }
+ }
+ };
+
+
+ /**
+ * Eval the named module if its dependencies are
+ * available.
+ * @param {string} name The module to load.
+ * @private
+ */
+ goog.maybeProcessDeferredDep_ = function(name) {
+ if (goog.isDeferredModule_(name) &&
+ goog.allDepsAreAvailable_(name)) {
+ var path = goog.getPathFromDeps_(name);
+ goog.maybeProcessDeferredPath_(goog.basePath + path);
+ }
+ };
+
+ /**
+ * @param {string} name The module to check.
+ * @return {boolean} Whether the name represents a
+ * module whose evaluation has been deferred.
+ * @private
+ */
+ goog.isDeferredModule_ = function(name) {
+ var path = goog.getPathFromDeps_(name);
+ if (path && goog.dependencies_.pathIsModule[path]) {
+ var abspath = goog.basePath + path;
+ return (abspath) in goog.dependencies_.deferred;
+ }
+ return false;
+ };
+
+ /**
+ * @param {string} name The module to check.
+ * @return {boolean} Whether the name represents a
+ * module whose declared dependencies have all been loaded
+ * (eval'd or a deferred module load)
+ * @private
+ */
+ goog.allDepsAreAvailable_ = function(name) {
+ var path = goog.getPathFromDeps_(name);
+ if (path && (path in goog.dependencies_.requires)) {
+ for (var requireName in goog.dependencies_.requires[path]) {
+ if (!goog.isProvided_(requireName) &&
+ !goog.isDeferredModule_(requireName)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ };
+
+
+ /**
+ * @param {string} abspath
+ * @private
+ */
+ goog.maybeProcessDeferredPath_ = function(abspath) {
+ if (abspath in goog.dependencies_.deferred) {
+ var src = goog.dependencies_.deferred[abspath];
+ delete goog.dependencies_.deferred[abspath];
+ goog.globalEval(src);
+ }
+ };
+
+
+ /**
+ * @param {function(?):?|string} moduleDef The module definition.
+ */
+ goog.loadModule = function(moduleDef) {
+ // NOTE: we allow function definitions to be either in the from
+ // of a string to eval (which keeps the original source intact) or
+ // in a eval forbidden environment (CSP) we allow a function definition
+ // which in its body must call {@code goog.module}, and return the exports
+ // of the module.
+ var previousState = goog.moduleLoaderState_;
+ try {
+ goog.moduleLoaderState_ = {
+ moduleName: undefined, declareTestMethods: false};
+ var exports;
+ if (goog.isFunction(moduleDef)) {
+ exports = moduleDef.call(goog.global, {});
+ } else if (goog.isString(moduleDef)) {
+ exports = goog.loadModuleFromSource_.call(goog.global, moduleDef);
+ } else {
+ throw Error('Invalid module definition');
+ }
+
+ var moduleName = goog.moduleLoaderState_.moduleName;
+ if (!goog.isString(moduleName) || !moduleName) {
+ throw Error('Invalid module name \"' + moduleName + '\"');
+ }
+
+ // Don't seal legacy namespaces as they may be uses as a parent of
+ // another namespace
+ if (goog.moduleLoaderState_.declareLegacyNamespace) {
+ goog.constructNamespace_(moduleName, exports);
+ } else if (goog.SEAL_MODULE_EXPORTS && Object.seal) {
+ Object.seal(exports);
+ }
+
+ goog.loadedModules_[moduleName] = exports;
+ if (goog.moduleLoaderState_.declareTestMethods) {
+ for (var entry in exports) {
+ if (entry.indexOf('test', 0) === 0 ||
+ entry == 'tearDown' ||
+ entry == 'setUp' ||
+ entry == 'setUpPage' ||
+ entry == 'tearDownPage') {
+ goog.global[entry] = exports[entry];
+ }
+ }
+ }
+ } finally {
+ goog.moduleLoaderState_ = previousState;
+ }
+ };
+
+
+ /**
+ * @param {string} source
+ * @return {!Object}
+ * @private
+ */
+ goog.loadModuleFromSource_ = function(source) {
+ // NOTE: we avoid declaring parameters or local variables here to avoid
+ // masking globals or leaking values into the module definition.
+ 'use strict';
+ var exports = {};
+ eval(arguments[0]);
+ return exports;
+ };
+
+
+ /**
+ * Writes a new script pointing to {@code src} directly into the DOM.
+ *
+ * NOTE: This method is not CSP-compliant. @see goog.appendScriptSrcNode_ for
+ * the fallback mechanism.
+ *
+ * @param {string} src The script URL.
+ * @private
+ */
+ goog.writeScriptSrcNode_ = function(src) {
+ goog.global.document.write(
+ '<script type="text/javascript" src="' + src + '"></' + 'script>');
+ };
+
+
+ /**
+ * Appends a new script node to the DOM using a CSP-compliant mechanism. This
+ * method exists as a fallback for document.write (which is not allowed in a
+ * strict CSP context, e.g., Chrome apps).
+ *
+ * NOTE: This method is not analogous to using document.write to insert a
+ * <script> tag; specifically, the user agent will execute a script added by
+ * document.write immediately after the current script block finishes
+ * executing, whereas the DOM-appended script node will not be executed until
+ * the entire document is parsed and executed. That is to say, this script is
+ * added to the end of the script execution queue.
+ *
+ * The page must not attempt to call goog.required entities until after the
+ * document has loaded, e.g., in or after the window.onload callback.
+ *
+ * @param {string} src The script URL.
+ * @private
+ */
+ goog.appendScriptSrcNode_ = function(src) {
+ var doc = goog.global.document;
+ var scriptEl = doc.createElement('script');
+ scriptEl.type = 'text/javascript';
+ scriptEl.src = src;
+ scriptEl.defer = false;
+ scriptEl.async = false;
+ doc.head.appendChild(scriptEl);
+ };
+
+
+ /**
+ * The default implementation of the import function. Writes a script tag to
+ * import the script.
+ *
+ * @param {string} src The script url.
+ * @param {string=} opt_sourceText The optionally source text to evaluate
+ * @return {boolean} True if the script was imported, false otherwise.
+ * @private
+ */
+ goog.writeScriptTag_ = function(src, opt_sourceText) {
+ if (goog.inHtmlDocument_()) {
+ var doc = goog.global.document;
+
+ // If the user tries to require a new symbol after document load,
+ // something has gone terribly wrong. Doing a document.write would
+ // wipe out the page. This does not apply to the CSP-compliant method
+ // of writing script tags.
+ if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING &&
+ doc.readyState == 'complete') {
+ // Certain test frameworks load base.js multiple times, which tries
+ // to write deps.js each time. If that happens, just fail silently.
+ // These frameworks wipe the page between each load of base.js, so this
+ // is OK.
+ var isDeps = /\bdeps.js$/.test(src);
+ if (isDeps) {
+ return false;
+ } else {
+ throw Error('Cannot write "' + src + '" after document load');
+ }
+ }
+
+ var isOldIE = goog.IS_OLD_IE_;
+
+ if (opt_sourceText === undefined) {
+ if (!isOldIE) {
+ if (goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) {
+ goog.appendScriptSrcNode_(src);
+ } else {
+ goog.writeScriptSrcNode_(src);
+ }
+ } else {
+ var state = " onreadystatechange='goog.onScriptLoad_(this, " +
+ ++goog.lastNonModuleScriptIndex_ + ")' ";
+ doc.write(
+ '<script type="text/javascript" src="' +
+ src + '"' + state + '></' + 'script>');
+ }
+ } else {
+ doc.write(
+ '<script type="text/javascript">' +
+ opt_sourceText +
+ '</' + 'script>');
+ }
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+
+ /** @private {number} */
+ goog.lastNonModuleScriptIndex_ = 0;
+
+
+ /**
+ * A readystatechange handler for legacy IE
+ * @param {!HTMLScriptElement} script
+ * @param {number} scriptIndex
+ * @return {boolean}
+ * @private
+ */
+ goog.onScriptLoad_ = function(script, scriptIndex) {
+ // for now load the modules when we reach the last script,
+ // later allow more inter-mingling.
+ if (script.readyState == 'complete' &&
+ goog.lastNonModuleScriptIndex_ == scriptIndex) {
+ goog.loadQueuedModules_();
+ }
+ return true;
+ };
+
+ /**
+ * Resolves dependencies based on the dependencies added using addDependency
+ * and calls importScript_ in the correct order.
+ * @private
+ */
+ goog.writeScripts_ = function() {
+ /** @type {!Array<string>} The scripts we need to write this time. */
+ var scripts = [];
+ var seenScript = {};
+ var deps = goog.dependencies_;
+
+ /** @param {string} path */
+ function visitNode(path) {
+ if (path in deps.written) {
+ return;
+ }
+
+ // We have already visited this one. We can get here if we have cyclic
+ // dependencies.
+ if (path in deps.visited) {
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ return;
+ }
+
+ deps.visited[path] = true;
+
+ if (path in deps.requires) {
+ for (var requireName in deps.requires[path]) {
+ // If the required name is defined, we assume that it was already
+ // bootstrapped by other means.
+ if (!goog.isProvided_(requireName)) {
+ if (requireName in deps.nameToPath) {
+ visitNode(deps.nameToPath[requireName]);
+ } else {
+ throw Error('Undefined nameToPath for ' + requireName);
+ }
+ }
+ }
+ }
+
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ }
+
+ for (var path in goog.included_) {
+ if (!deps.written[path]) {
+ visitNode(path);
+ }
+ }
+
+ // record that we are going to load all these scripts.
+ for (var i = 0; i < scripts.length; i++) {
+ var path = scripts[i];
+ goog.dependencies_.written[path] = true;
+ }
+
+ // If a module is loaded synchronously then we need to
+ // clear the current inModuleLoader value, and restore it when we are
+ // done loading the current "requires".
+ var moduleState = goog.moduleLoaderState_;
+ goog.moduleLoaderState_ = null;
+
+ var loadingModule = false;
+ for (var i = 0; i < scripts.length; i++) {
+ var path = scripts[i];
+ if (path) {
+ if (!deps.pathIsModule[path]) {
+ goog.importScript_(goog.basePath + path);
+ } else {
+ loadingModule = true;
+ goog.importModule_(goog.basePath + path);
+ }
+ } else {
+ goog.moduleLoaderState_ = moduleState;
+ throw Error('Undefined script input');
+ }
+ }
+
+ // restore the current "module loading state"
+ goog.moduleLoaderState_ = moduleState;
+ };
+
+
+ /**
+ * Looks at the dependency rules and tries to determine the script file that
+ * fulfills a particular rule.
+ * @param {string} rule In the form goog.namespace.Class or project.script.
+ * @return {?string} Url corresponding to the rule, or null.
+ * @private
+ */
+ goog.getPathFromDeps_ = function(rule) {
+ if (rule in goog.dependencies_.nameToPath) {
+ return goog.dependencies_.nameToPath[rule];
+ } else {
+ return null;
+ }
+ };
+
+ goog.findBasePath_();
+
+ // Allow projects to manage the deps files themselves.
+ if (!goog.global.CLOSURE_NO_DEPS) {
+ goog.importScript_(goog.basePath + 'deps.js');
+ }
+}
+
+
+/**
+ * Normalize a file path by removing redundant ".." and extraneous "." file
+ * path components.
+ * @param {string} path
+ * @return {string}
+ * @private
+ */
+goog.normalizePath_ = function(path) {
+ var components = path.split('/');
+ var i = 0;
+ while (i < components.length) {
+ if (components[i] == '.') {
+ components.splice(i, 1);
+ } else if (i && components[i] == '..' &&
+ components[i - 1] && components[i - 1] != '..') {
+ components.splice(--i, 2);
+ } else {
+ i++;
+ }
+ }
+ return components.join('/');
+};
+
+
+/**
+ * Loads file by synchronous XHR. Should not be used in production environments.
+ * @param {string} src Source URL.
+ * @return {string} File contents.
+ * @private
+ */
+goog.loadFileSync_ = function(src) {
+ if (goog.global.CLOSURE_LOAD_FILE_SYNC) {
+ return goog.global.CLOSURE_LOAD_FILE_SYNC(src);
+ } else {
+ var xhr = new goog.global['XMLHttpRequest']();
+ xhr.open('get', src, false);
+ xhr.send();
+ return xhr.responseText;
+ }
+};
+
+
+/**
+ * Retrieve and execute a module.
+ * @param {string} src Script source URL.
+ * @private
+ */
+goog.retrieveAndExecModule_ = function(src) {
+ if (!COMPILED) {
+ // The full but non-canonicalized URL for later use.
+ var originalPath = src;
+ // Canonicalize the path, removing any /./ or /../ since Chrome's debugging
+ // console doesn't auto-canonicalize XHR loads as it does <script> srcs.
+ src = goog.normalizePath_(src);
+
+ var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
+ goog.writeScriptTag_;
+
+ var scriptText = goog.loadFileSync_(src);
+
+ if (scriptText != null) {
+ var execModuleScript = goog.wrapModule_(src, scriptText);
+ var isOldIE = goog.IS_OLD_IE_;
+ if (isOldIE) {
+ goog.dependencies_.deferred[originalPath] = execModuleScript;
+ goog.queuedModules_.push(originalPath);
+ } else {
+ importScript(src, execModuleScript);
+ }
+ } else {
+ throw new Error('load of ' + src + 'failed');
+ }
+ }
+};
+
+
+//==============================================================================
+// Language Enhancements
+//==============================================================================
+
+
+/**
+ * This is a "fixed" version of the typeof operator. It differs from the typeof
+ * operator in such a way that null returns 'null' and arrays return 'array'.
+ * @param {*} value The value to get the type of.
+ * @return {string} The name of the type.
+ */
+goog.typeOf = function(value) {
+ var s = typeof value;
+ if (s == 'object') {
+ if (value) {
+ // Check these first, so we can avoid calling Object.prototype.toString if
+ // possible.
+ //
+ // IE improperly marshals tyepof across execution contexts, but a
+ // cross-context object will still return false for "instanceof Object".
+ if (value instanceof Array) {
+ return 'array';
+ } else if (value instanceof Object) {
+ return s;
+ }
+
+ // HACK: In order to use an Object prototype method on the arbitrary
+ // value, the compiler requires the value be cast to type Object,
+ // even though the ECMA spec explicitly allows it.
+ var className = Object.prototype.toString.call(
+ /** @type {Object} */ (value));
+ // In Firefox 3.6, attempting to access iframe window objects' length
+ // property throws an NS_ERROR_FAILURE, so we need to special-case it
+ // here.
+ if (className == '[object Window]') {
+ return 'object';
+ }
+
+ // We cannot always use constructor == Array or instanceof Array because
+ // different frames have different Array objects. In IE6, if the iframe
+ // where the array was created is destroyed, the array loses its
+ // prototype. Then dereferencing val.splice here throws an exception, so
+ // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
+ // so that will work. In this case, this function will return false and
+ // most array functions will still work because the array is still
+ // array-like (supports length and []) even though it has lost its
+ // prototype.
+ // Mark Miller noticed that Object.prototype.toString
+ // allows access to the unforgeable [[Class]] property.
+ // 15.2.4.2 Object.prototype.toString ( )
+ // When the toString method is called, the following steps are taken:
+ // 1. Get the [[Class]] property of this object.
+ // 2. Compute a string value by concatenating the three strings
+ // "[object ", Result(1), and "]".
+ // 3. Return Result(2).
+ // and this behavior survives the destruction of the execution context.
+ if ((className == '[object Array]' ||
+ // In IE all non value types are wrapped as objects across window
+ // boundaries (not iframe though) so we have to do object detection
+ // for this edge case.
+ typeof value.length == 'number' &&
+ typeof value.splice != 'undefined' &&
+ typeof value.propertyIsEnumerable != 'undefined' &&
+ !value.propertyIsEnumerable('splice')
+
+ )) {
+ return 'array';
+ }
+ // HACK: There is still an array case that fails.
+ // function ArrayImpostor() {}
+ // ArrayImpostor.prototype = [];
+ // var impostor = new ArrayImpostor;
+ // this can be fixed by getting rid of the fast path
+ // (value instanceof Array) and solely relying on
+ // (value && Object.prototype.toString.vall(value) === '[object Array]')
+ // but that would require many more function calls and is not warranted
+ // unless closure code is receiving objects from untrusted sources.
+
+ // IE in cross-window calls does not correctly marshal the function type
+ // (it appears just as an object) so we cannot use just typeof val ==
+ // 'function'. However, if the object has a call property, it is a
+ // function.
+ if ((className == '[object Function]' ||
+ typeof value.call != 'undefined' &&
+ typeof value.propertyIsEnumerable != 'undefined' &&
+ !value.propertyIsEnumerable('call'))) {
+ return 'function';
+ }
+
+ } else {
+ return 'null';
+ }
+
+ } else if (s == 'function' && typeof value.call == 'undefined') {
+ // In Safari typeof nodeList returns 'function', and on Firefox typeof
+ // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We
+ // would like to return object for those and we can detect an invalid
+ // function by making sure that the function object has a call method.
+ return 'object';
+ }
+ return s;
+};
+
+
+/**
+ * Returns true if the specified value is null.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is null.
+ */
+goog.isNull = function(val) {
+ return val === null;
+};
+
+
+/**
+ * Returns true if the specified value is defined and not null.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is defined and not null.
+ */
+goog.isDefAndNotNull = function(val) {
+ // Note that undefined == null.
+ return val != null;
+};
+
+
+/**
+ * Returns true if the specified value is an array.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArray = function(val) {
+ return goog.typeOf(val) == 'array';
+};
+
+
+/**
+ * Returns true if the object looks like an array. To qualify as array like
+ * the value needs to be either a NodeList or an object with a Number length
+ * property. As a special case, a function value is not array like, because its
+ * length property is fixed to correspond to the number of expected arguments.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArrayLike = function(val) {
+ var type = goog.typeOf(val);
+ // We do not use goog.isObject here in order to exclude function values.
+ return type == 'array' || type == 'object' && typeof val.length == 'number';
+};
+
+
+/**
+ * Returns true if the object looks like a Date. To qualify as Date-like the
+ * value needs to be an object and have a getFullYear() function.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a like a Date.
+ */
+goog.isDateLike = function(val) {
+ return goog.isObject(val) && typeof val.getFullYear == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is a string.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a string.
+ */
+goog.isString = function(val) {
+ return typeof val == 'string';
+};
+
+
+/**
+ * Returns true if the specified value is a boolean.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is boolean.
+ */
+goog.isBoolean = function(val) {
+ return typeof val == 'boolean';
+};
+
+
+/**
+ * Returns true if the specified value is a number.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a number.
+ */
+goog.isNumber = function(val) {
+ return typeof val == 'number';
+};
+
+
+/**
+ * Returns true if the specified value is a function.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is a function.
+ */
+goog.isFunction = function(val) {
+ return goog.typeOf(val) == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is an object. This includes arrays and
+ * functions.
+ * @param {?} val Variable to test.
+ * @return {boolean} Whether variable is an object.
+ */
+goog.isObject = function(val) {
+ var type = typeof val;
+ return type == 'object' && val != null || type == 'function';
+ // return Object(val) === val also works, but is slower, especially if val is
+ // not an object.
+};
+
+
+/**
+ * Gets a unique ID for an object. This mutates the object so that further calls
+ * with the same object as a parameter returns the same value. The unique ID is
+ * guaranteed to be unique across the current session amongst objects that are
+ * passed into {@code getUid}. There is no guarantee that the ID is unique or
+ * consistent across sessions. It is unsafe to generate unique ID for function
+ * prototypes.
+ *
+ * @param {Object} obj The object to get the unique ID for.
+ * @return {number} The unique ID for the object.
+ */
+goog.getUid = function(obj) {
+ // TODO(arv): Make the type stricter, do not accept null.
+
+ // In Opera window.hasOwnProperty exists but always returns false so we avoid
+ // using it. As a consequence the unique ID generated for BaseClass.prototype
+ // and SubClass.prototype will be the same.
+ return obj[goog.UID_PROPERTY_] ||
+ (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
+};
+
+
+/**
+ * Whether the given object is already assigned a unique ID.
+ *
+ * This does not modify the object.
+ *
+ * @param {!Object} obj The object to check.
+ * @return {boolean} Whether there is an assigned unique id for the object.
+ */
+goog.hasUid = function(obj) {
+ return !!obj[goog.UID_PROPERTY_];
+};
+
+
+/**
+ * Removes the unique ID from an object. This is useful if the object was
+ * previously mutated using {@code goog.getUid} in which case the mutation is
+ * undone.
+ * @param {Object} obj The object to remove the unique ID field from.
+ */
+goog.removeUid = function(obj) {
+ // TODO(arv): Make the type stricter, do not accept null.
+
+ // In IE, DOM nodes are not instances of Object and throw an exception if we
+ // try to delete. Instead we try to use removeAttribute.
+ if ('removeAttribute' in obj) {
+ obj.removeAttribute(goog.UID_PROPERTY_);
+ }
+ /** @preserveTry */
+ try {
+ delete obj[goog.UID_PROPERTY_];
+ } catch (ex) {
+ }
+};
+
+
+/**
+ * Name for unique ID property. Initialized in a way to help avoid collisions
+ * with other closure JavaScript on the same page.
+ * @type {string}
+ * @private
+ */
+goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);
+
+
+/**
+ * Counter for UID.
+ * @type {number}
+ * @private
+ */
+goog.uidCounter_ = 0;
+
+
+/**
+ * Adds a hash code field to an object. The hash code is unique for the
+ * given object.
+ * @param {Object} obj The object to get the hash code for.
+ * @return {number} The hash code for the object.
+ * @deprecated Use goog.getUid instead.
+ */
+goog.getHashCode = goog.getUid;
+
+
+/**
+ * Removes the hash code field from an object.
+ * @param {Object} obj The object to remove the field from.
+ * @deprecated Use goog.removeUid instead.
+ */
+goog.removeHashCode = goog.removeUid;
+
+
+/**
+ * Clones a value. The input may be an Object, Array, or basic type. Objects and
+ * arrays will be cloned recursively.
+ *
+ * WARNINGS:
+ * <code>goog.cloneObject</code> does not detect reference loops. Objects that
+ * refer to themselves will cause infinite recursion.
+ *
+ * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
+ * UIDs created by <code>getUid</code> into cloned results.
+ *
+ * @param {*} obj The value to clone.
+ * @return {*} A clone of the input value.
+ * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
+ */
+goog.cloneObject = function(obj) {
+ var type = goog.typeOf(obj);
+ if (type == 'object' || type == 'array') {
+ if (obj.clone) {
+ return obj.clone();
+ }
+ var clone = type == 'array' ? [] : {};
+ for (var key in obj) {
+ clone[key] = goog.cloneObject(obj[key]);
+ }
+ return clone;
+ }
+
+ return obj;
+};
+
+
+/**
+ * A native implementation of goog.bind.
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which this should
+ * point to when the function is run.
+ * @param {...*} var_args Additional arguments that are partially applied to the
+ * function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ * @private
+ * @suppress {deprecated} The compiler thinks that Function.prototype.bind is
+ * deprecated because some people have declared a pure-JS version.
+ * Only the pure-JS version is truly deprecated.
+ */
+goog.bindNative_ = function(fn, selfObj, var_args) {
+ return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
+};
+
+
+/**
+ * A pure-JS implementation of goog.bind.
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which this should
+ * point to when the function is run.
+ * @param {...*} var_args Additional arguments that are partially applied to the
+ * function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ * @private
+ */
+goog.bindJs_ = function(fn, selfObj, var_args) {
+ if (!fn) {
+ throw new Error();
+ }
+
+ if (arguments.length > 2) {
+ var boundArgs = Array.prototype.slice.call(arguments, 2);
+ return function() {
+ // Prepend the bound arguments to the current arguments.
+ var newArgs = Array.prototype.slice.call(arguments);
+ Array.prototype.unshift.apply(newArgs, boundArgs);
+ return fn.apply(selfObj, newArgs);
+ };
+
+ } else {
+ return function() {
+ return fn.apply(selfObj, arguments);
+ };
+ }
+};
+
+
+/**
+ * Partially applies this function to a particular 'this object' and zero or
+ * more arguments. The result is a new function with some arguments of the first
+ * function pre-filled and the value of this 'pre-specified'.
+ *
+ * Remaining arguments specified at call-time are appended to the pre-specified
+ * ones.
+ *
+ * Also see: {@link #partial}.
+ *
+ * Usage:
+ * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
+ * barMethBound('arg3', 'arg4');</pre>
+ *
+ * @param {?function(this:T, ...)} fn A function to partially apply.
+ * @param {T} selfObj Specifies the object which this should point to when the
+ * function is run.
+ * @param {...*} var_args Additional arguments that are partially applied to the
+ * function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ * @template T
+ * @suppress {deprecated} See above.
+ */
+goog.bind = function(fn, selfObj, var_args) {
+ // TODO(nicksantos): narrow the type signature.
+ if (Function.prototype.bind &&
+ // NOTE(nicksantos): Somebody pulled base.js into the default Chrome
+ // extension environment. This means that for Chrome extensions, they get
+ // the implementation of Function.prototype.bind that calls goog.bind
+ // instead of the native one. Even worse, we don't want to introduce a
+ // circular dependency between goog.bind and Function.prototype.bind, so
+ // we have to hack this to make sure it works correctly.
+ Function.prototype.bind.toString().indexOf('native code') != -1) {
+ goog.bind = goog.bindNative_;
+ } else {
+ goog.bind = goog.bindJs_;
+ }
+ return goog.bind.apply(null, arguments);
+};
+
+
+/**
+ * Like bind(), except that a 'this object' is not required. Useful when the
+ * target function is already bound.
+ *
+ * Usage:
+ * var g = partial(f, arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {...*} var_args Additional arguments that are partially applied to fn.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+goog.partial = function(fn, var_args) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function() {
+ // Clone the array (with slice()) and append additional arguments
+ // to the existing arguments.
+ var newArgs = args.slice();
+ newArgs.push.apply(newArgs, arguments);
+ return fn.apply(this, newArgs);
+ };
+};
+
+
+/**
+ * Copies all the members of a source object to a target object. This method
+ * does not work on all browsers for all objects that contain keys such as
+ * toString or hasOwnProperty. Use goog.object.extend for this purpose.
+ * @param {Object} target Target.
+ * @param {Object} source Source.
+ */
+goog.mixin = function(target, source) {
+ for (var x in source) {
+ target[x] = source[x];
+ }
+
+ // For IE7 or lower, the for-in-loop does not contain any properties that are
+ // not enumerable on the prototype object (for example, isPrototypeOf from
+ // Object.prototype) but also it will not include 'replace' on objects that
+ // extend String and change 'replace' (not that it is common for anyone to
+ // extend anything except Object).
+};
+
+
+/**
+ * @return {number} An integer value representing the number of milliseconds
+ * between midnight, January 1, 1970 and the current time.
+ */
+goog.now = (goog.TRUSTED_SITE && Date.now) || (function() {
+ // Unary plus operator converts its operand to a number which in the case of
+ // a date is done by calling getTime().
+ return +new Date();
+});
+
+
+/**
+ * Evals JavaScript in the global scope. In IE this uses execScript, other
+ * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
+ * global scope (for example, in Safari), appends a script tag instead.
+ * Throws an exception if neither execScript or eval is defined.
+ * @param {string} script JavaScript string.
+ */
+goog.globalEval = function(script) {
+ if (goog.global.execScript) {
+ goog.global.execScript(script, 'JavaScript');
+ } else if (goog.global.eval) {
+ // Test to see if eval works
+ if (goog.evalWorksForGlobals_ == null) {
+ goog.global.eval('var _et_ = 1;');
+ if (typeof goog.global['_et_'] != 'undefined') {
+ delete goog.global['_et_'];
+ goog.evalWorksForGlobals_ = true;
+ } else {
+ goog.evalWorksForGlobals_ = false;
+ }
+ }
+
+ if (goog.evalWorksForGlobals_) {
+ goog.global.eval(script);
+ } else {
+ var doc = goog.global.document;
+ var scriptElt = doc.createElement('SCRIPT');
+ scriptElt.type = 'text/javascript';
+ scriptElt.defer = false;
+ // Note(user): can't use .innerHTML since "t('<test>')" will fail and
+ // .text doesn't work in Safari 2. Therefore we append a text node.
+ scriptElt.appendChild(doc.createTextNode(script));
+ doc.body.appendChild(scriptElt);
+ doc.body.removeChild(scriptElt);
+ }
+ } else {
+ throw Error('goog.globalEval not available');
+ }
+};
+
+
+/**
+ * Indicates whether or not we can call 'eval' directly to eval code in the
+ * global scope. Set to a Boolean by the first call to goog.globalEval (which
+ * empirically tests whether eval works for globals). @see goog.globalEval
+ * @type {?boolean}
+ * @private
+ */
+goog.evalWorksForGlobals_ = null;
+
+
+/**
+ * Optional map of CSS class names to obfuscated names used with
+ * goog.getCssName().
+ * @private {!Object<string, string>|undefined}
+ * @see goog.setCssNameMapping
+ */
+goog.cssNameMapping_;
+
+
+/**
+ * Optional obfuscation style for CSS class names. Should be set to either
+ * 'BY_WHOLE' or 'BY_PART' if defined.
+ * @type {string|undefined}
+ * @private
+ * @see goog.setCssNameMapping
+ */
+goog.cssNameMappingStyle_;
+
+
+/**
+ * Handles strings that are intended to be used as CSS class names.
+ *
+ * This function works in tandem with @see goog.setCssNameMapping.
+ *
+ * Without any mapping set, the arguments are simple joined with a hyphen and
+ * passed through unaltered.
+ *
+ * When there is a mapping, there are two possible styles in which these
+ * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)
+ * of the passed in css name is rewritten according to the map. In the BY_WHOLE
+ * style, the full css name is looked up in the map directly. If a rewrite is
+ * not specified by the map, the compiler will output a warning.
+ *
+ * When the mapping is passed to the compiler, it will replace calls to
+ * goog.getCssName with the strings from the mapping, e.g.
+ * var x = goog.getCssName('foo');
+ * var y = goog.getCssName(this.baseClass, 'active');
+ * becomes:
+ * var x= 'foo';
+ * var y = this.baseClass + '-active';
+ *
+ * If one argument is passed it will be processed, if two are passed only the
+ * modifier will be processed, as it is assumed the first argument was generated
+ * as a result of calling goog.getCssName.
+ *
+ * @param {string} className The class name.
+ * @param {string=} opt_modifier A modifier to be appended to the class name.
+ * @return {string} The class name or the concatenation of the class name and
+ * the modifier.
+ */
+goog.getCssName = function(className, opt_modifier) {
+ var getMapping = function(cssName) {
+ return goog.cssNameMapping_[cssName] || cssName;
+ };
+
+ var renameByParts = function(cssName) {
+ // Remap all the parts individually.
+ var parts = cssName.split('-');
+ var mapped = [];
+ for (var i = 0; i < parts.length; i++) {
+ mapped.push(getMapping(parts[i]));
+ }
+ return mapped.join('-');
+ };
+
+ var rename;
+ if (goog.cssNameMapping_) {
+ rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?
+ getMapping : renameByParts;
+ } else {
+ rename = function(a) {
+ return a;
+ };
+ }
+
+ if (opt_modifier) {
+ return className + '-' + rename(opt_modifier);
+ } else {
+ return rename(className);
+ }
+};
+
+
+/**
+ * Sets the map to check when returning a value from goog.getCssName(). Example:
+ * <pre>
+ * goog.setCssNameMapping({
+ * "goog": "a",
+ * "disabled": "b",
+ * });
+ *
+ * var x = goog.getCssName('goog');
+ * // The following evaluates to: "a a-b".
+ * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
+ * </pre>
+ * When declared as a map of string literals to string literals, the JSCompiler
+ * will replace all calls to goog.getCssName() using the supplied map if the
+ * --closure_pass flag is set.
+ *
+ * @param {!Object} mapping A map of strings to strings where keys are possible
+ * arguments to goog.getCssName() and values are the corresponding values
+ * that should be returned.
+ * @param {string=} opt_style The style of css name mapping. There are two valid
+ * options: 'BY_PART', and 'BY_WHOLE'.
+ * @see goog.getCssName for a description.
+ */
+goog.setCssNameMapping = function(mapping, opt_style) {
+ goog.cssNameMapping_ = mapping;
+ goog.cssNameMappingStyle_ = opt_style;
+};
+
+
+/**
+ * To use CSS renaming in compiled mode, one of the input files should have a
+ * call to goog.setCssNameMapping() with an object literal that the JSCompiler
+ * can extract and use to replace all calls to goog.getCssName(). In uncompiled
+ * mode, JavaScript code should be loaded before this base.js file that declares
+ * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is
+ * to ensure that the mapping is loaded before any calls to goog.getCssName()
+ * are made in uncompiled mode.
+ *
+ * A hook for overriding the CSS name mapping.
+ * @type {!Object<string, string>|undefined}
+ */
+goog.global.CLOSURE_CSS_NAME_MAPPING;
+
+
+if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
+ // This does not call goog.setCssNameMapping() because the JSCompiler
+ // requires that goog.setCssNameMapping() be called with an object literal.
+ goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
+}
+
+
+/**
+ * Gets a localized message.
+ *
+ * This function is a compiler primitive. If you give the compiler a localized
+ * message bundle, it will replace the string at compile-time with a localized
+ * version, and expand goog.getMsg call to a concatenated string.
+ *
+ * Messages must be initialized in the form:
+ * <code>
+ * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});
+ * </code>
+ *
+ * @param {string} str Translatable string, places holders in the form {$foo}.
+ * @param {Object<string, string>=} opt_values Maps place holder name to value.
+ * @return {string} message with placeholders filled.
+ */
+goog.getMsg = function(str, opt_values) {
+ if (opt_values) {
+ str = str.replace(/\{\$([^}]+)}/g, function(match, key) {
+ return key in opt_values ? opt_values[key] : match;
+ });
+ }
+ return str;
+};
+
+
+/**
+ * Gets a localized message. If the message does not have a translation, gives a
+ * fallback message.
+ *
+ * This is useful when introducing a new message that has not yet been
+ * translated into all languages.
+ *
+ * This function is a compiler primitive. Must be used in the form:
+ * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>
+ * where MSG_A and MSG_B were initialized with goog.getMsg.
+ *
+ * @param {string} a The preferred message.
+ * @param {string} b The fallback message.
+ * @return {string} The best translated message.
+ */
+goog.getMsgWithFallback = function(a, b) {
+ return a;
+};
+
+
+/**
+ * Exposes an unobfuscated global namespace path for the given object.
+ * Note that fields of the exported object *will* be obfuscated, unless they are
+ * exported in turn via this function or goog.exportProperty.
+ *
+ * Also handy for making public items that are defined in anonymous closures.
+ *
+ * ex. goog.exportSymbol('public.path.Foo', Foo);
+ *
+ * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);
+ * public.path.Foo.staticFunction();
+ *
+ * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
+ * Foo.prototype.myMethod);
+ * new public.path.Foo().myMethod();
+ *
+ * @param {string} publicPath Unobfuscated name to export.
+ * @param {*} object Object the name should point to.
+ * @param {Object=} opt_objectToExportTo The object to add the path to; default
+ * is goog.global.
+ */
+goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
+ goog.exportPath_(publicPath, object, opt_objectToExportTo);
+};
+
+
+/**
+ * Exports a property unobfuscated into the object's namespace.
+ * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
+ * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
+ * @param {Object} object Object whose static property is being exported.
+ * @param {string} publicName Unobfuscated name to export.
+ * @param {*} symbol Object the name should point to.
+ */
+goog.exportProperty = function(object, publicName, symbol) {
+ object[publicName] = symbol;
+};
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * Usage:
+ * <pre>
+ * function ParentClass(a, b) { }
+ * ParentClass.prototype.foo = function(a) { };
+ *
+ * function ChildClass(a, b, c) {
+ * ChildClass.base(this, 'constructor', a, b);
+ * }
+ * goog.inherits(ChildClass, ParentClass);
+ *
+ * var child = new ChildClass('a', 'b', 'see');
+ * child.foo(); // This works.
+ * </pre>
+ *
+ * @param {Function} childCtor Child class.
+ * @param {Function} parentCtor Parent class.
+ */
+goog.inherits = function(childCtor, parentCtor) {
+ /** @constructor */
+ function tempCtor() {};
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.superClass_ = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+ /** @override */
+ childCtor.prototype.constructor = childCtor;
+
+ /**
+ * Calls superclass constructor/method.
+ *
+ * This function is only available if you use goog.inherits to
+ * express inheritance relationships between classes.
+ *
+ * NOTE: This is a replacement for goog.base and for superClass_
+ * property defined in childCtor.
+ *
+ * @param {!Object} me Should always be "this".
+ * @param {string} methodName The method name to call. Calling
+ * superclass constructor can be done with the special string
+ * 'constructor'.
+ * @param {...*} var_args The arguments to pass to superclass
+ * method/constructor.
+ * @return {*} The return value of the superclass method/constructor.
+ */
+ childCtor.base = function(me, methodName, var_args) {
+ // Copying using loop to avoid deop due to passing arguments object to
+ // function. This is faster in many JS engines as of late 2014.
+ var args = new Array(arguments.length - 2);
+ for (var i = 2; i < arguments.length; i++) {
+ args[i - 2] = arguments[i];
+ }
+ return parentCtor.prototype[methodName].apply(me, args);
+ };
+};
+
+
+/**
+ * Call up to the superclass.
+ *
+ * If this is called from a constructor, then this calls the superclass
+ * constructor with arguments 1-N.
+ *
+ * If this is called from a prototype method, then you must pass the name of the
+ * method as the second argument to this function. If you do not, you will get a
+ * runtime error. This calls the superclass' method with arguments 2-N.
+ *
+ * This function only works if you use goog.inherits to express inheritance
+ * relationships between your classes.
+ *
+ * This function is a compiler primitive. At compile-time, the compiler will do
+ * macro expansion to remove a lot of the extra overhead that this function
+ * introduces. The compiler will also enforce a lot of the assumptions that this
+ * function makes, and treat it as a compiler error if you break them.
+ *
+ * @param {!Object} me Should always be "this".
+ * @param {*=} opt_methodName The method name if calling a super method.
+ * @param {...*} var_args The rest of the arguments.
+ * @return {*} The return value of the superclass method.
+ * @suppress {es5Strict} This method can not be used in strict mode, but
+ * all Closure Library consumers must depend on this file.
+ */
+goog.base = function(me, opt_methodName, var_args) {
+ var caller = arguments.callee.caller;
+
+ if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {
+ throw Error('arguments.caller not defined. goog.base() cannot be used ' +
+ 'with strict mode code. See ' +
+ 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');
+ }
+
+ if (caller.superClass_) {
+ // Copying using loop to avoid deop due to passing arguments object to
+ // function. This is faster in many JS engines as of late 2014.
+ var ctorArgs = new Array(arguments.length - 1);
+ for (var i = 1; i < arguments.length; i++) {
+ ctorArgs[i - 1] = arguments[i];
+ }
+ // This is a constructor. Call the superclass constructor.
+ return caller.superClass_.constructor.apply(me, ctorArgs);
+ }
+
+ // Copying using loop to avoid deop due to passing arguments object to
+ // function. This is faster in many JS engines as of late 2014.
+ var args = new Array(arguments.length - 2);
+ for (var i = 2; i < arguments.length; i++) {
+ args[i - 2] = arguments[i];
+ }
+ var foundCaller = false;
+ for (var ctor = me.constructor;
+ ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
+ if (ctor.prototype[opt_methodName] === caller) {
+ foundCaller = true;
+ } else if (foundCaller) {
+ return ctor.prototype[opt_methodName].apply(me, args);
+ }
+ }
+
+ // If we did not find the caller in the prototype chain, then one of two
+ // things happened:
+ // 1) The caller is an instance method.
+ // 2) This method was not called by the right caller.
+ if (me[opt_methodName] === caller) {
+ return me.constructor.prototype[opt_methodName].apply(me, args);
+ } else {
+ throw Error(
+ 'goog.base called from a method of one name ' +
+ 'to a method of a different name');
+ }
+};
+
+
+/**
+ * Allow for aliasing within scope functions. This function exists for
+ * uncompiled code - in compiled code the calls will be inlined and the aliases
+ * applied. In uncompiled code the function is simply run since the aliases as
+ * written are valid JavaScript.
+ *
+ *
+ * @param {function()} fn Function to call. This function can contain aliases
+ * to namespaces (e.g. "var dom = goog.dom") or classes
+ * (e.g. "var Timer = goog.Timer").
+ */
+goog.scope = function(fn) {
+ fn.call(goog.global);
+};
+
+
+/*
+ * To support uncompiled, strict mode bundles that use eval to divide source
+ * like so:
+ * eval('someSource;//# sourceUrl sourcefile.js');
+ * We need to export the globally defined symbols "goog" and "COMPILED".
+ * Exporting "goog" breaks the compiler optimizations, so we required that
+ * be defined externally.
+ * NOTE: We don't use goog.exportSymbol here because we don't want to trigger
+ * extern generation when that compiler option is enabled.
+ */
+if (!COMPILED) {
+ goog.global['COMPILED'] = COMPILED;
+}
+
+
+
+//==============================================================================
+// goog.defineClass implementation
+//==============================================================================
+
+
+/**
+ * Creates a restricted form of a Closure "class":
+ * - from the compiler's perspective, the instance returned from the
+ * constructor is sealed (no new properties may be added). This enables
+ * better checks.
+ * - the compiler will rewrite this definition to a form that is optimal
+ * for type checking and optimization (initially this will be a more
+ * traditional form).
+ *
+ * @param {Function} superClass The superclass, Object or null.
+ * @param {goog.defineClass.ClassDescriptor} def
+ * An object literal describing
+ * the class. It may have the following properties:
+ * "constructor": the constructor function
+ * "statics": an object literal containing methods to add to the constructor
+ * as "static" methods or a function that will receive the constructor
+ * function as its only parameter to which static properties can
+ * be added.
+ * all other properties are added to the prototype.
+ * @return {!Function} The class constructor.
+ */
+goog.defineClass = function(superClass, def) {
+ // TODO(johnlenz): consider making the superClass an optional parameter.
+ var constructor = def.constructor;
+ var statics = def.statics;
+ // Wrap the constructor prior to setting up the prototype and static methods.
+ if (!constructor || constructor == Object.prototype.constructor) {
+ constructor = function() {
+ throw Error('cannot instantiate an interface (no constructor defined).');
+ };
+ }
+
+ var cls = goog.defineClass.createSealingConstructor_(constructor, superClass);
+ if (superClass) {
+ goog.inherits(cls, superClass);
+ }
+
+ // Remove all the properties that should not be copied to the prototype.
+ delete def.constructor;
+ delete def.statics;
+
+ goog.defineClass.applyProperties_(cls.prototype, def);
+ if (statics != null) {
+ if (statics instanceof Function) {
+ statics(cls);
+ } else {
+ goog.defineClass.applyProperties_(cls, statics);
+ }
+ }
+
+ return cls;
+};
+
+
+/**
+ * @typedef {
+ * !Object|
+ * {constructor:!Function}|
+ * {constructor:!Function, statics:(Object|function(Function):void)}}
+ * @suppress {missingProvide}
+ */
+goog.defineClass.ClassDescriptor;
+
+
+/**
+ * @define {boolean} Whether the instances returned by
+ * goog.defineClass should be sealed when possible.
+ */
+goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG);
+
+
+/**
+ * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is
+ * defined, this function will wrap the constructor in a function that seals the
+ * results of the provided constructor function.
+ *
+ * @param {!Function} ctr The constructor whose results maybe be sealed.
+ * @param {Function} superClass The superclass constructor.
+ * @return {!Function} The replacement constructor.
+ * @private
+ */
+goog.defineClass.createSealingConstructor_ = function(ctr, superClass) {
+ if (goog.defineClass.SEAL_CLASS_INSTANCES &&
+ Object.seal instanceof Function) {
+ // Don't seal subclasses of unsealable-tagged legacy classes.
+ if (superClass && superClass.prototype &&
+ superClass.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]) {
+ return ctr;
+ }
+ /**
+ * @this {Object}
+ * @return {?}
+ */
+ var wrappedCtr = function() {
+ // Don't seal an instance of a subclass when it calls the constructor of
+ // its super class as there is most likely still setup to do.
+ var instance = ctr.apply(this, arguments) || this;
+ instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];
+ if (this.constructor === wrappedCtr) {
+ Object.seal(instance);
+ }
+ return instance;
+ };
+ return wrappedCtr;
+ }
+ return ctr;
+};
+
+
+// TODO(johnlenz): share these values with the goog.object
+/**
+ * The names of the fields that are defined on Object.prototype.
+ * @type {!Array<string>}
+ * @private
+ * @const
+ */
+goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [
+ 'constructor',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'toLocaleString',
+ 'toString',
+ 'valueOf'
+];
+
+
+// TODO(johnlenz): share this function with the goog.object
+/**
+ * @param {!Object} target The object to add properties to.
+ * @param {!Object} source The object to copy properties from.
+ * @private
+ */
+goog.defineClass.applyProperties_ = function(target, source) {
+ // TODO(johnlenz): update this to support ES5 getters/setters
+
+ var key;
+ for (key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+
+ // For IE the for-in-loop does not contain any properties that are not
+ // enumerable on the prototype object (for example isPrototypeOf from
+ // Object.prototype) and it will also not include 'replace' on objects that
+ // extend String and change 'replace' (not that it is common for anyone to
+ // extend anything except Object).
+ for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) {
+ key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i];
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+};
+
+
+/**
+ * Sealing classes breaks the older idiom of assigning properties on the
+ * prototype rather than in the constructor. As such, goog.defineClass
+ * must not seal subclasses of these old-style classes until they are fixed.
+ * Until then, this marks a class as "broken", instructing defineClass
+ * not to seal subclasses.
+ * @param {!Function} ctr The legacy constructor to tag as unsealable.
+ */
+goog.tagUnsealableClass = function(ctr) {
+ if (!COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES) {
+ ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = true;
+ }
+};
+
+
+/**
+ * Name for unsealable tag property.
+ * @const @private {string}
+ */
+goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = 'goog_defineClass_legacy_unsealable';
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/bootstrap/nodejs.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/bootstrap/nodejs.js b/externs/GCL/externs/goog/bootstrap/nodejs.js
new file mode 100644
index 0000000..bde163d
--- /dev/null
+++ b/externs/GCL/externs/goog/bootstrap/nodejs.js
@@ -0,0 +1,110 @@
+// Copyright 2013 The Closure Library Authors.
+//
+// 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 nodejs script for dynamically requiring Closure within
+ * nodejs.
+ *
+ * Example of usage:
+ * <code>
+ * require('./bootstrap/nodejs')
+ * goog.require('goog.ui.Component')
+ * </code>
+ *
+ * This loads goog.ui.Component in the global scope.
+ *
+ * If you want to load custom libraries, you can require the custom deps file
+ * directly. If your custom libraries introduce new globals, you may
+ * need to run goog.nodeGlobalRequire to get them to load correctly.
+ *
+ * <code>
+ * require('./path/to/my/deps.js')
+ * goog.bootstrap.nodeJs.nodeGlobalRequire('./path/to/my/base.js')
+ * goog.require('my.Class')
+ * </code>
+ *
+ * @author nick@medium.com (Nick Santos)
+ *
+ * @nocompile
+ */
+
+
+var fs = require('fs');
+var path = require('path');
+var vm = require('vm');
+
+
+/**
+ * The goog namespace in the global scope.
+ */
+global.goog = {};
+
+
+/**
+ * Imports a script using Node's require() API.
+ *
+ * @param {string} src The script source.
+ * @param {string=} opt_sourceText The optional source text to evaluate.
+ * @return {boolean} True if the script was imported, false otherwise.
+ */
+global.CLOSURE_IMPORT_SCRIPT = function(src, opt_sourceText) {
+ // Sources are always expressed relative to closure's base.js, but
+ // require() is always relative to the current source.
+ if (opt_sourceText === undefined) {
+ require('./../' + src);
+ } else {
+ eval(opt_sourceText);
+ }
+ return true;
+};
+
+
+/**
+ * Loads a file when using Closure's goog.require() API with goog.modules.
+ *
+ * @param {string} src The file source.
+ * @return {string} The file contents.
+ */
+
+global.CLOSURE_LOAD_FILE_SYNC = function(src) {
+ return fs.readFileSync(
+ path.resolve(__dirname, '..', src), { encoding: 'utf-8' });
+};
+
+
+// Declared here so it can be used to require base.js
+function nodeGlobalRequire(file) {
+ vm.runInThisContext.call(
+ global, fs.readFileSync(file), file);
+}
+
+
+// Load Closure's base.js into memory. It is assumed base.js is in the
+// directory above this directory given this script's location in
+// bootstrap/nodejs.js.
+nodeGlobalRequire(path.resolve(__dirname, '..', 'base.js'));
+
+
+/**
+ * Bootstraps a file into the global scope.
+ *
+ * This is strictly for cases where normal require() won't work,
+ * because the file declares global symbols with 'var' that need to
+ * be added to the global scope.
+ * @suppress {missingProvide}
+ *
+ * @param {string} file The path to the file.
+ */
+goog.nodeGlobalRequire = nodeGlobalRequire;
+
[07/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/safestylesheet.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/safestylesheet.js b/externs/GCL/externs/goog/html/safestylesheet.js
new file mode 100644
index 0000000..79e8b51
--- /dev/null
+++ b/externs/GCL/externs/goog/html/safestylesheet.js
@@ -0,0 +1,276 @@
+// 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 The SafeStyleSheet type and its builders.
+ *
+ * TODO(user): Link to document stating type contract.
+ */
+
+goog.provide('goog.html.SafeStyleSheet');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+goog.require('goog.string.TypedString');
+
+
+
+/**
+ * A string-like object which represents a CSS style sheet and that carries the
+ * security type contract that its value, as a string, will not cause untrusted
+ * script execution (XSS) when evaluated as CSS in a browser.
+ *
+ * Instances of this type must be created via the factory method
+ * {@code goog.html.SafeStyleSheet.fromConstant} and not by invoking its
+ * constructor. The constructor intentionally takes no parameters and the type
+ * is immutable; hence only a default instance corresponding to the empty string
+ * can be obtained via constructor invocation.
+ *
+ * A SafeStyleSheet's string representation can safely be interpolated as the
+ * content of a style element within HTML. The SafeStyleSheet string should
+ * not be escaped before interpolation.
+ *
+ * Values of this type must be composable, i.e. for any two values
+ * {@code styleSheet1} and {@code styleSheet2} of this type,
+ * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1) +
+ * goog.html.SafeStyleSheet.unwrap(styleSheet2)} must itself be a value that
+ * satisfies the SafeStyleSheet type constraint. This requirement implies that
+ * for any value {@code styleSheet} of this type,
+ * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1)} must end in
+ * "beginning of rule" context.
+
+ * A SafeStyleSheet can be constructed via security-reviewed unchecked
+ * conversions. In this case producers of SafeStyleSheet must ensure themselves
+ * that the SafeStyleSheet does not contain unsafe script. Note in particular
+ * that {@code <} is dangerous, even when inside CSS strings, and so should
+ * always be forbidden or CSS-escaped in user controlled input. For example, if
+ * {@code </style><script>evil</script>"} were interpolated
+ * inside a CSS string, it would break out of the context of the original
+ * style element and {@code evil} would execute. Also note that within an HTML
+ * style (raw text) element, HTML character references, such as
+ * {@code &lt;}, are not allowed. See
+ * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements
+ * (similar considerations apply to the style element).
+ *
+ * @see goog.html.SafeStyleSheet#fromConstant
+ * @constructor
+ * @final
+ * @struct
+ * @implements {goog.string.TypedString}
+ */
+goog.html.SafeStyleSheet = function() {
+ /**
+ * The contained value of this SafeStyleSheet. The field has a purposely
+ * ugly name to make (non-compiled) code that attempts to directly access this
+ * field stand out.
+ * @private {string}
+ */
+ this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = '';
+
+ /**
+ * A type marker used to implement additional run-time type checking.
+ * @see goog.html.SafeStyleSheet#unwrap
+ * @const
+ * @private
+ */
+ this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
+ goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.SafeStyleSheet.prototype.implementsGoogStringTypedString = true;
+
+
+/**
+ * Type marker for the SafeStyleSheet type, used to implement additional
+ * run-time type checking.
+ * @const
+ * @private
+ */
+goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
+
+
+/**
+ * Creates a new SafeStyleSheet object by concatenating values.
+ * @param {...(!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>)}
+ * var_args Values to concatenate.
+ * @return {!goog.html.SafeStyleSheet}
+ */
+goog.html.SafeStyleSheet.concat = function(var_args) {
+ var result = '';
+
+ /**
+ * @param {!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>}
+ * argument
+ */
+ var addArgument = function(argument) {
+ if (goog.isArray(argument)) {
+ goog.array.forEach(argument, addArgument);
+ } else {
+ result += goog.html.SafeStyleSheet.unwrap(argument);
+ }
+ };
+
+ goog.array.forEach(arguments, addArgument);
+ return goog.html.SafeStyleSheet
+ .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(result);
+};
+
+
+/**
+ * Creates a SafeStyleSheet object from a compile-time constant string.
+ *
+ * {@code styleSheet} must not have any < characters in it, so that
+ * the syntactic structure of the surrounding HTML is not affected.
+ *
+ * @param {!goog.string.Const} styleSheet A compile-time-constant string from
+ * which to create a SafeStyleSheet.
+ * @return {!goog.html.SafeStyleSheet} A SafeStyleSheet object initialized to
+ * {@code styleSheet}.
+ */
+goog.html.SafeStyleSheet.fromConstant = function(styleSheet) {
+ var styleSheetString = goog.string.Const.unwrap(styleSheet);
+ if (styleSheetString.length === 0) {
+ return goog.html.SafeStyleSheet.EMPTY;
+ }
+ // > is a valid character in CSS selectors and there's no strict need to
+ // block it if we already block <.
+ goog.asserts.assert(!goog.string.contains(styleSheetString, '<'),
+ "Forbidden '<' character in style sheet string: " + styleSheetString);
+ return goog.html.SafeStyleSheet.
+ createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheetString);
+};
+
+
+/**
+ * Returns this SafeStyleSheet's value as a string.
+ *
+ * IMPORTANT: In code where it is security relevant that an object's type is
+ * indeed {@code SafeStyleSheet}, use {@code goog.html.SafeStyleSheet.unwrap}
+ * instead of this method. If in doubt, assume that it's security relevant. In
+ * particular, note that goog.html functions which return a goog.html type do
+ * not guarantee the returned instance is of the right type. For example:
+ *
+ * <pre>
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
+ * // instanceof goog.html.SafeHtml.
+ * </pre>
+ *
+ * @see goog.html.SafeStyleSheet#unwrap
+ * @override
+ */
+goog.html.SafeStyleSheet.prototype.getTypedStringValue = function() {
+ return this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;
+};
+
+
+if (goog.DEBUG) {
+ /**
+ * Returns a debug string-representation of this value.
+ *
+ * To obtain the actual string value wrapped in a SafeStyleSheet, use
+ * {@code goog.html.SafeStyleSheet.unwrap}.
+ *
+ * @see goog.html.SafeStyleSheet#unwrap
+ * @override
+ */
+ goog.html.SafeStyleSheet.prototype.toString = function() {
+ return 'SafeStyleSheet{' +
+ this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ + '}';
+ };
+}
+
+
+/**
+ * Performs a runtime check that the provided object is indeed a
+ * SafeStyleSheet object, and returns its value.
+ *
+ * @param {!goog.html.SafeStyleSheet} safeStyleSheet The object to extract from.
+ * @return {string} The safeStyleSheet object's contained string, unless
+ * the run-time type check fails. In that case, {@code unwrap} returns an
+ * innocuous string, or, if assertions are enabled, throws
+ * {@code goog.asserts.AssertionError}.
+ */
+goog.html.SafeStyleSheet.unwrap = function(safeStyleSheet) {
+ // Perform additional Run-time type-checking to ensure that
+ // safeStyleSheet is indeed an instance of the expected type. This
+ // provides some additional protection against security bugs due to
+ // application code that disables type checks.
+ // Specifically, the following checks are performed:
+ // 1. The object is an instance of the expected type.
+ // 2. The object is not an instance of a subclass.
+ // 3. The object carries a type marker for the expected type. "Faking" an
+ // object requires a reference to the type marker, which has names intended
+ // to stand out in code reviews.
+ if (safeStyleSheet instanceof goog.html.SafeStyleSheet &&
+ safeStyleSheet.constructor === goog.html.SafeStyleSheet &&
+ safeStyleSheet.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
+ return safeStyleSheet.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;
+ } else {
+ goog.asserts.fail(
+ "expected object of type SafeStyleSheet, got '" + safeStyleSheet +
+ "'");
+ return 'type_error:SafeStyleSheet';
+ }
+};
+
+
+/**
+ * Package-internal utility method to create SafeStyleSheet instances.
+ *
+ * @param {string} styleSheet The string to initialize the SafeStyleSheet
+ * object with.
+ * @return {!goog.html.SafeStyleSheet} The initialized SafeStyleSheet object.
+ * @package
+ */
+goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse =
+ function(styleSheet) {
+ return new goog.html.SafeStyleSheet().initSecurityPrivateDoNotAccessOrElse_(
+ styleSheet);
+};
+
+
+/**
+ * Called from createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(). This
+ * method exists only so that the compiler can dead code eliminate static
+ * fields (like EMPTY) when they're not accessed.
+ * @param {string} styleSheet
+ * @return {!goog.html.SafeStyleSheet}
+ * @private
+ */
+goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_ =
+ function(styleSheet) {
+ this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = styleSheet;
+ return this;
+};
+
+
+/**
+ * A SafeStyleSheet instance corresponding to the empty string.
+ * @const {!goog.html.SafeStyleSheet}
+ */
+goog.html.SafeStyleSheet.EMPTY =
+ goog.html.SafeStyleSheet.
+ createSafeStyleSheetSecurityPrivateDoNotAccessOrElse('');
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/safeurl.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/safeurl.js b/externs/GCL/externs/goog/html/safeurl.js
new file mode 100644
index 0000000..6d2f871
--- /dev/null
+++ b/externs/GCL/externs/goog/html/safeurl.js
@@ -0,0 +1,431 @@
+// 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 The SafeUrl type and its builders.
+ *
+ * TODO(user): Link to document stating type contract.
+ */
+
+goog.provide('goog.html.SafeUrl');
+
+goog.require('goog.asserts');
+goog.require('goog.fs.url');
+goog.require('goog.i18n.bidi.Dir');
+goog.require('goog.i18n.bidi.DirectionalString');
+goog.require('goog.string.Const');
+goog.require('goog.string.TypedString');
+
+
+
+/**
+ * A string that is safe to use in URL context in DOM APIs and HTML documents.
+ *
+ * A SafeUrl is a string-like object that carries the security type contract
+ * that its value as a string will not cause untrusted script execution
+ * when evaluated as a hyperlink URL in a browser.
+ *
+ * Values of this type are guaranteed to be safe to use in URL/hyperlink
+ * contexts, such as, assignment to URL-valued DOM properties, or
+ * interpolation into a HTML template in URL context (e.g., inside a href
+ * attribute), in the sense that the use will not result in a
+ * Cross-Site-Scripting vulnerability.
+ *
+ * Note that, as documented in {@code goog.html.SafeUrl.unwrap}, this type's
+ * contract does not guarantee that instances are safe to interpolate into HTML
+ * without appropriate escaping.
+ *
+ * Note also that this type's contract does not imply any guarantees regarding
+ * the resource the URL refers to. In particular, SafeUrls are <b>not</b>
+ * safe to use in a context where the referred-to resource is interpreted as
+ * trusted code, e.g., as the src of a script tag.
+ *
+ * Instances of this type must be created via the factory methods
+ * ({@code goog.html.SafeUrl.fromConstant}, {@code goog.html.SafeUrl.sanitize}),
+ * etc and not by invoking its constructor. The constructor intentionally
+ * takes no parameters and the type is immutable; hence only a default instance
+ * corresponding to the empty string can be obtained via constructor invocation.
+ *
+ * @see goog.html.SafeUrl#fromConstant
+ * @see goog.html.SafeUrl#from
+ * @see goog.html.SafeUrl#sanitize
+ * @constructor
+ * @final
+ * @struct
+ * @implements {goog.i18n.bidi.DirectionalString}
+ * @implements {goog.string.TypedString}
+ */
+goog.html.SafeUrl = function() {
+ /**
+ * The contained value of this SafeUrl. The field has a purposely ugly
+ * name to make (non-compiled) code that attempts to directly access this
+ * field stand out.
+ * @private {string}
+ */
+ this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = '';
+
+ /**
+ * A type marker used to implement additional run-time type checking.
+ * @see goog.html.SafeUrl#unwrap
+ * @const
+ * @private
+ */
+ this.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
+ goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
+};
+
+
+/**
+ * The innocuous string generated by goog.html.SafeUrl.sanitize when passed
+ * an unsafe URL.
+ *
+ * about:invalid is registered in
+ * http://www.w3.org/TR/css3-values/#about-invalid.
+ * http://tools.ietf.org/html/rfc6694#section-2.2.1 permits about URLs to
+ * contain a fragment, which is not to be considered when determining if an
+ * about URL is well-known.
+ *
+ * Using about:invalid seems preferable to using a fixed data URL, since
+ * browsers might choose to not report CSP violations on it, as legitimate
+ * CSS function calls to attr() can result in this URL being produced. It is
+ * also a standard URL which matches exactly the semantics we need:
+ * "The about:invalid URI references a non-existent document with a generic
+ * error condition. It can be used when a URI is necessary, but the default
+ * value shouldn't be resolveable as any type of document".
+ *
+ * @const {string}
+ */
+goog.html.SafeUrl.INNOCUOUS_STRING = 'about:invalid#zClosurez';
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.SafeUrl.prototype.implementsGoogStringTypedString = true;
+
+
+/**
+ * Returns this SafeUrl's value a string.
+ *
+ * IMPORTANT: In code where it is security relevant that an object's type is
+ * indeed {@code SafeUrl}, use {@code goog.html.SafeUrl.unwrap} instead of this
+ * method. If in doubt, assume that it's security relevant. In particular, note
+ * that goog.html functions which return a goog.html type do not guarantee that
+ * the returned instance is of the right type. For example:
+ *
+ * <pre>
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof
+ * // goog.html.SafeHtml.
+ * </pre>
+ *
+ * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the
+ * behavior of browsers when interpreting URLs. Values of SafeUrl objects MUST
+ * be appropriately escaped before embedding in a HTML document. Note that the
+ * required escaping is context-sensitive (e.g. a different escaping is
+ * required for embedding a URL in a style property within a style
+ * attribute, as opposed to embedding in a href attribute).
+ *
+ * @see goog.html.SafeUrl#unwrap
+ * @override
+ */
+goog.html.SafeUrl.prototype.getTypedStringValue = function() {
+ return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.SafeUrl.prototype.implementsGoogI18nBidiDirectionalString = true;
+
+
+/**
+ * Returns this URLs directionality, which is always {@code LTR}.
+ * @override
+ */
+goog.html.SafeUrl.prototype.getDirection = function() {
+ return goog.i18n.bidi.Dir.LTR;
+};
+
+
+if (goog.DEBUG) {
+ /**
+ * Returns a debug string-representation of this value.
+ *
+ * To obtain the actual string value wrapped in a SafeUrl, use
+ * {@code goog.html.SafeUrl.unwrap}.
+ *
+ * @see goog.html.SafeUrl#unwrap
+ * @override
+ */
+ goog.html.SafeUrl.prototype.toString = function() {
+ return 'SafeUrl{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ +
+ '}';
+ };
+}
+
+
+/**
+ * Performs a runtime check that the provided object is indeed a SafeUrl
+ * object, and returns its value.
+ *
+ * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the
+ * behavior of browsers when interpreting URLs. Values of SafeUrl objects MUST
+ * be appropriately escaped before embedding in a HTML document. Note that the
+ * required escaping is context-sensitive (e.g. a different escaping is
+ * required for embedding a URL in a style property within a style
+ * attribute, as opposed to embedding in a href attribute).
+ *
+ * Note that the returned value does not necessarily correspond to the string
+ * with which the SafeUrl was constructed, since goog.html.SafeUrl.sanitize
+ * will percent-encode many characters.
+ *
+ * @param {!goog.html.SafeUrl} safeUrl The object to extract from.
+ * @return {string} The SafeUrl object's contained string, unless the run-time
+ * type check fails. In that case, {@code unwrap} returns an innocuous
+ * string, or, if assertions are enabled, throws
+ * {@code goog.asserts.AssertionError}.
+ */
+goog.html.SafeUrl.unwrap = function(safeUrl) {
+ // Perform additional Run-time type-checking to ensure that safeUrl is indeed
+ // an instance of the expected type. This provides some additional protection
+ // against security bugs due to application code that disables type checks.
+ // Specifically, the following checks are performed:
+ // 1. The object is an instance of the expected type.
+ // 2. The object is not an instance of a subclass.
+ // 3. The object carries a type marker for the expected type. "Faking" an
+ // object requires a reference to the type marker, which has names intended
+ // to stand out in code reviews.
+ if (safeUrl instanceof goog.html.SafeUrl &&
+ safeUrl.constructor === goog.html.SafeUrl &&
+ safeUrl.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
+ return safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
+ } else {
+ goog.asserts.fail('expected object of type SafeUrl, got \'' +
+ safeUrl + '\'');
+ return 'type_error:SafeUrl';
+
+ }
+};
+
+
+/**
+ * Creates a SafeUrl object from a compile-time constant string.
+ *
+ * Compile-time constant strings are inherently program-controlled and hence
+ * trusted.
+ *
+ * @param {!goog.string.Const} url A compile-time-constant string from which to
+ * create a SafeUrl.
+ * @return {!goog.html.SafeUrl} A SafeUrl object initialized to {@code url}.
+ */
+goog.html.SafeUrl.fromConstant = function(url) {
+ return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(
+ goog.string.Const.unwrap(url));
+};
+
+
+/**
+ * A pattern that matches Blob types that can have SafeUrls created from
+ * URL.createObjectURL(blob). Only matches image types, currently.
+ * @const
+ * @private
+ */
+goog.html.SAFE_BLOB_TYPE_PATTERN_ =
+ /^image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)$/i;
+
+
+/**
+ * Creates a SafeUrl wrapping a blob URL for the given {@code blob}. The
+ * blob URL is created with {@code URL.createObjectURL}. If the MIME type
+ * for {@code blob} is not of a known safe image MIME type, then the
+ * SafeUrl will wrap {@link #INNOCUOUS_STRING}.
+ * @see http://www.w3.org/TR/FileAPI/#url
+ * @param {!Blob} blob
+ * @return {!goog.html.SafeUrl} The blob URL, or an innocuous string wrapped
+ * as a SafeUrl.
+ */
+goog.html.SafeUrl.fromBlob = function(blob) {
+ var url = goog.html.SAFE_BLOB_TYPE_PATTERN_.test(blob.type) ?
+ goog.fs.url.createObjectUrl(blob) : goog.html.SafeUrl.INNOCUOUS_STRING;
+ return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
+};
+
+
+/**
+ * A pattern that recognizes a commonly useful subset of URLs that satisfy
+ * the SafeUrl contract.
+ *
+ * This regular expression matches a subset of URLs that will not cause script
+ * execution if used in URL context within a HTML document. Specifically, this
+ * regular expression matches if (comment from here on and regex copied from
+ * Soy's EscapingConventions):
+ * (1) Either a protocol in a whitelist (http, https, mailto or ftp).
+ * (2) or no protocol. A protocol must be followed by a colon. The below
+ * allows that by allowing colons only after one of the characters [/?#].
+ * A colon after a hash (#) must be in the fragment.
+ * Otherwise, a colon after a (?) must be in a query.
+ * Otherwise, a colon after a single solidus (/) must be in a path.
+ * Otherwise, a colon after a double solidus (//) must be in the authority
+ * (before port).
+ *
+ * The pattern disallows &, used in HTML entity declarations before
+ * one of the characters in [/?#]. This disallows HTML entities used in the
+ * protocol name, which should never happen, e.g. "http" for "http".
+ * It also disallows HTML entities in the first path part of a relative path,
+ * e.g. "foo<bar/baz". Our existing escaping functions should not produce
+ * that. More importantly, it disallows masking of a colon,
+ * e.g. "javascript:...".
+ *
+ * @private
+ * @const {!RegExp}
+ */
+goog.html.SAFE_URL_PATTERN_ =
+ /^(?:(?:https?|mailto|ftp):|[^&:/?#]*(?:[/?#]|$))/i;
+
+
+/**
+ * Creates a SafeUrl object from {@code url}. If {@code url} is a
+ * goog.html.SafeUrl then it is simply returned. Otherwise the input string is
+ * validated to match a pattern of commonly used safe URLs. The string is
+ * converted to UTF-8 and non-whitelisted characters are percent-encoded. The
+ * string wrapped by the created SafeUrl will thus contain only ASCII printable
+ * characters.
+ *
+ * {@code url} may be a URL with the http, https, mailto or ftp scheme,
+ * or a relative URL (i.e., a URL without a scheme; specifically, a
+ * scheme-relative, absolute-path-relative, or path-relative URL).
+ *
+ * {@code url} is converted to UTF-8 and non-whitelisted characters are
+ * percent-encoded. Whitelisted characters are '%' and, from RFC 3986,
+ * unreserved characters and reserved characters, with the exception of '\'',
+ * '(' and ')'. This ensures the the SafeUrl contains only ASCII-printable
+ * characters and reduces the chance of security bugs were it to be
+ * interpolated into a specific context without the necessary escaping.
+ *
+ * If {@code url} fails validation or does not UTF-16 decode correctly
+ * (JavaScript strings are UTF-16 encoded), this function returns a SafeUrl
+ * object containing an innocuous string, goog.html.SafeUrl.INNOCUOUS_STRING.
+ *
+ * @see http://url.spec.whatwg.org/#concept-relative-url
+ * @param {string|!goog.string.TypedString} url The URL to validate.
+ * @return {!goog.html.SafeUrl} The validated URL, wrapped as a SafeUrl.
+ */
+goog.html.SafeUrl.sanitize = function(url) {
+ if (url instanceof goog.html.SafeUrl) {
+ return url;
+ }
+ else if (url.implementsGoogStringTypedString) {
+ url = url.getTypedStringValue();
+ } else {
+ url = String(url);
+ }
+ if (!goog.html.SAFE_URL_PATTERN_.test(url)) {
+ url = goog.html.SafeUrl.INNOCUOUS_STRING;
+ } else {
+ url = goog.html.SafeUrl.normalize_(url);
+ }
+ return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
+};
+
+
+/**
+ * Normalizes {@code url} the UTF-8 encoding of url, using a whitelist of
+ * characters. Whitelisted characters are not percent-encoded.
+ * @param {string} url The URL to normalize.
+ * @return {string} The normalized URL.
+ * @private
+ */
+goog.html.SafeUrl.normalize_ = function(url) {
+ try {
+ var normalized = encodeURI(url);
+ } catch (e) { // Happens if url contains invalid surrogate sequences.
+ return goog.html.SafeUrl.INNOCUOUS_STRING;
+ }
+
+ return normalized.replace(
+ goog.html.SafeUrl.NORMALIZE_MATCHER_,
+ function(match) {
+ return goog.html.SafeUrl.NORMALIZE_REPLACER_MAP_[match];
+ });
+};
+
+
+/**
+ * Matches characters and strings which need to be replaced in the string
+ * generated by encodeURI. Specifically:
+ *
+ * - '\'', '(' and ')' are not encoded. They are part of the reserved
+ * characters group in RFC 3986 but only appear in the obsolete mark
+ * production in Appendix D.2 of RFC 3986, so they can be encoded without
+ * changing semantics.
+ * - '[' and ']' are encoded by encodeURI, despite being reserved characters
+ * which can be used to represent IPv6 addresses. So they need to be decoded.
+ * - '%' is encoded by encodeURI. However, encoding '%' characters that are
+ * already part of a valid percent-encoded sequence changes the semantics of a
+ * URL, and hence we need to preserve them. Note that this may allow
+ * non-encoded '%' characters to remain in the URL (i.e., occurrences of '%'
+ * that are not part of a valid percent-encoded sequence, for example,
+ * 'ab%xy').
+ *
+ * @const {!RegExp}
+ * @private
+ */
+goog.html.SafeUrl.NORMALIZE_MATCHER_ = /[()']|%5B|%5D|%25/g;
+
+
+/**
+ * Map of replacements to be done in string generated by encodeURI.
+ * @const {!Object<string, string>}
+ * @private
+ */
+goog.html.SafeUrl.NORMALIZE_REPLACER_MAP_ = {
+ '\'': '%27',
+ '(': '%28',
+ ')': '%29',
+ '%5B': '[',
+ '%5D': ']',
+ '%25': '%'
+};
+
+
+/**
+ * Type marker for the SafeUrl type, used to implement additional run-time
+ * type checking.
+ * @const
+ * @private
+ */
+goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
+
+
+/**
+ * Package-internal utility method to create SafeUrl instances.
+ *
+ * @param {string} url The string to initialize the SafeUrl object with.
+ * @return {!goog.html.SafeUrl} The initialized SafeUrl object.
+ * @package
+ */
+goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse = function(
+ url) {
+ var safeUrl = new goog.html.SafeUrl();
+ safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = url;
+ return safeUrl;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/silverlight.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/silverlight.js b/externs/GCL/externs/goog/html/silverlight.js
new file mode 100644
index 0000000..6aed4e2
--- /dev/null
+++ b/externs/GCL/externs/goog/html/silverlight.js
@@ -0,0 +1,92 @@
+// 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 SafeHtml factory methods for creating object tags for
+ * loading Silverlight files.
+ */
+
+goog.provide('goog.html.silverlight');
+
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.TrustedResourceUrl');
+goog.require('goog.html.flash');
+goog.require('goog.string.Const');
+
+
+/**
+ * Attributes and param tag name attributes not allowed to be overriden
+ * when calling createObjectForSilverlight().
+ *
+ * While values that should be specified as params are probably not
+ * recognized as attributes, we block them anyway just to be sure.
+ * @const {!Array<string>}
+ * @private
+ */
+goog.html.silverlight.FORBIDDEN_ATTRS_AND_PARAMS_ON_SILVERLIGHT_ = [
+ 'data', // Always set to a fixed value.
+ 'source', // Specifies the URL for the Silverlight file.
+ 'type', // Always set to a fixed value.
+ 'typemustmatch' // Always set to a fixed value.
+];
+
+
+/**
+ * Creates a SafeHtml representing an object tag, for loading Silverlight files.
+ *
+ * The following attributes are set to these fixed values:
+ * - data: data:application/x-silverlight-2,
+ * - type: application/x-silverlight-2
+ * - typemustmatch: "" (the empty string, meaning true for a boolean attribute)
+ *
+ * @param {!goog.html.TrustedResourceUrl} source The value of the source param.
+ * @param {!Object<string, string>=} opt_params Mapping used to generate child
+ * param tags. Each tag has a name and value attribute, as defined in
+ * mapping. Only names consisting of [a-zA-Z0-9-] are allowed. Value of
+ * null or undefined causes the param tag to be omitted.
+ * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
+ * opt_attributes Mapping from other attribute names to their values. Only
+ * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
+ * undefined causes the attribute to be omitted.
+ * @return {!goog.html.SafeHtml} The SafeHtml content with the object tag.
+ * @throws {Error} If invalid attribute or param name, or attribute or param
+ * value is provided. Also if opt_attributes or opt_params contains any of
+ * the attributes set to fixed values, documented above, or contains source.
+ *
+ */
+goog.html.silverlight.createObject = function(
+ source, opt_params, opt_attributes) {
+ goog.html.flash.verifyKeysNotInMaps(
+ goog.html.silverlight.FORBIDDEN_ATTRS_AND_PARAMS_ON_SILVERLIGHT_,
+ opt_attributes,
+ opt_params);
+
+ // We don't set default for Silverlight's EnableHtmlAccess and
+ // AllowHtmlPopupwindow because their default changes depending on whether
+ // a file loaded from the same domain.
+ var paramTags = goog.html.flash.combineParams(
+ {'source': source}, opt_params);
+ var fixedAttributes = {
+ 'data': goog.html.TrustedResourceUrl.fromConstant(
+ goog.string.Const.from('data:application/x-silverlight-2,')),
+ 'type': 'application/x-silverlight-2',
+ 'typemustmatch': ''
+ };
+ var attributes = goog.html.SafeHtml.combineAttributes(
+ fixedAttributes, {}, opt_attributes);
+
+ return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
+ 'object', attributes, paramTags);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/trustedresourceurl.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/trustedresourceurl.js b/externs/GCL/externs/goog/html/trustedresourceurl.js
new file mode 100644
index 0000000..e7c7bf5
--- /dev/null
+++ b/externs/GCL/externs/goog/html/trustedresourceurl.js
@@ -0,0 +1,224 @@
+// 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 The TrustedResourceUrl type and its builders.
+ *
+ * TODO(user): Link to document stating type contract.
+ */
+
+goog.provide('goog.html.TrustedResourceUrl');
+
+goog.require('goog.asserts');
+goog.require('goog.i18n.bidi.Dir');
+goog.require('goog.i18n.bidi.DirectionalString');
+goog.require('goog.string.Const');
+goog.require('goog.string.TypedString');
+
+
+
+/**
+ * A URL which is under application control and from which script, CSS, and
+ * other resources that represent executable code, can be fetched.
+ *
+ * Given that the URL can only be constructed from strings under application
+ * control and is used to load resources, bugs resulting in a malformed URL
+ * should not have a security impact and are likely to be easily detectable
+ * during testing. Given the wide number of non-RFC compliant URLs in use,
+ * stricter validation could prevent some applications from being able to use
+ * this type.
+ *
+ * Instances of this type must be created via the factory method,
+ * ({@code goog.html.TrustedResourceUrl.fromConstant}), and not by invoking its
+ * constructor. The constructor intentionally takes no parameters and the type
+ * is immutable; hence only a default instance corresponding to the empty
+ * string can be obtained via constructor invocation.
+ *
+ * @see goog.html.TrustedResourceUrl#fromConstant
+ * @constructor
+ * @final
+ * @struct
+ * @implements {goog.i18n.bidi.DirectionalString}
+ * @implements {goog.string.TypedString}
+ */
+goog.html.TrustedResourceUrl = function() {
+ /**
+ * The contained value of this TrustedResourceUrl. The field has a purposely
+ * ugly name to make (non-compiled) code that attempts to directly access this
+ * field stand out.
+ * @private {string}
+ */
+ this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = '';
+
+ /**
+ * A type marker used to implement additional run-time type checking.
+ * @see goog.html.TrustedResourceUrl#unwrap
+ * @const
+ * @private
+ */
+ this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
+ goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString = true;
+
+
+/**
+ * Returns this TrustedResourceUrl's value as a string.
+ *
+ * IMPORTANT: In code where it is security relevant that an object's type is
+ * indeed {@code TrustedResourceUrl}, use
+ * {@code goog.html.TrustedResourceUrl.unwrap} instead of this method. If in
+ * doubt, assume that it's security relevant. In particular, note that
+ * goog.html functions which return a goog.html type do not guarantee that
+ * the returned instance is of the right type. For example:
+ *
+ * <pre>
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof
+ * // goog.html.SafeHtml.
+ * </pre>
+ *
+ * @see goog.html.TrustedResourceUrl#unwrap
+ * @override
+ */
+goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() {
+ return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
+};
+
+
+/**
+ * @override
+ * @const
+ */
+goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString =
+ true;
+
+
+/**
+ * Returns this URLs directionality, which is always {@code LTR}.
+ * @override
+ */
+goog.html.TrustedResourceUrl.prototype.getDirection = function() {
+ return goog.i18n.bidi.Dir.LTR;
+};
+
+
+if (goog.DEBUG) {
+ /**
+ * Returns a debug string-representation of this value.
+ *
+ * To obtain the actual string value wrapped in a TrustedResourceUrl, use
+ * {@code goog.html.TrustedResourceUrl.unwrap}.
+ *
+ * @see goog.html.TrustedResourceUrl#unwrap
+ * @override
+ */
+ goog.html.TrustedResourceUrl.prototype.toString = function() {
+ return 'TrustedResourceUrl{' +
+ this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ + '}';
+ };
+}
+
+
+/**
+ * Performs a runtime check that the provided object is indeed a
+ * TrustedResourceUrl object, and returns its value.
+ *
+ * @param {!goog.html.TrustedResourceUrl} trustedResourceUrl The object to
+ * extract from.
+ * @return {string} The trustedResourceUrl object's contained string, unless
+ * the run-time type check fails. In that case, {@code unwrap} returns an
+ * innocuous string, or, if assertions are enabled, throws
+ * {@code goog.asserts.AssertionError}.
+ */
+goog.html.TrustedResourceUrl.unwrap = function(trustedResourceUrl) {
+ // Perform additional Run-time type-checking to ensure that
+ // trustedResourceUrl is indeed an instance of the expected type. This
+ // provides some additional protection against security bugs due to
+ // application code that disables type checks.
+ // Specifically, the following checks are performed:
+ // 1. The object is an instance of the expected type.
+ // 2. The object is not an instance of a subclass.
+ // 3. The object carries a type marker for the expected type. "Faking" an
+ // object requires a reference to the type marker, which has names intended
+ // to stand out in code reviews.
+ if (trustedResourceUrl instanceof goog.html.TrustedResourceUrl &&
+ trustedResourceUrl.constructor === goog.html.TrustedResourceUrl &&
+ trustedResourceUrl
+ .TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
+ goog.html.TrustedResourceUrl
+ .TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
+ return trustedResourceUrl
+ .privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
+ } else {
+ goog.asserts.fail('expected object of type TrustedResourceUrl, got \'' +
+ trustedResourceUrl + '\'');
+ return 'type_error:TrustedResourceUrl';
+
+ }
+};
+
+
+/**
+ * Creates a TrustedResourceUrl object from a compile-time constant string.
+ *
+ * Compile-time constant strings are inherently program-controlled and hence
+ * trusted.
+ *
+ * @param {!goog.string.Const} url A compile-time-constant string from which to
+ * create a TrustedResourceUrl.
+ * @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object
+ * initialized to {@code url}.
+ */
+goog.html.TrustedResourceUrl.fromConstant = function(url) {
+ return goog.html.TrustedResourceUrl
+ .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(
+ goog.string.Const.unwrap(url));
+};
+
+
+/**
+ * Type marker for the TrustedResourceUrl type, used to implement additional
+ * run-time type checking.
+ * @const
+ * @private
+ */
+goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
+
+
+/**
+ * Package-internal utility method to create TrustedResourceUrl instances.
+ *
+ * @param {string} url The string to initialize the TrustedResourceUrl object
+ * with.
+ * @return {!goog.html.TrustedResourceUrl} The initialized TrustedResourceUrl
+ * object.
+ * @package
+ */
+goog.html.TrustedResourceUrl.
+ createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) {
+ var trustedResourceUrl = new goog.html.TrustedResourceUrl();
+ trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ =
+ url;
+ return trustedResourceUrl;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/uncheckedconversions.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/uncheckedconversions.js b/externs/GCL/externs/goog/html/uncheckedconversions.js
new file mode 100644
index 0000000..a1a5a9a
--- /dev/null
+++ b/externs/GCL/externs/goog/html/uncheckedconversions.js
@@ -0,0 +1,231 @@
+// 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 Unchecked conversions to create values of goog.html types from
+ * plain strings. Use of these functions could potentially result in instances
+ * of goog.html types that violate their type contracts, and hence result in
+ * security vulnerabilties.
+ *
+ * Therefore, all uses of the methods herein must be carefully security
+ * reviewed. Avoid use of the methods in this file whenever possible; instead
+ * prefer to create instances of goog.html types using inherently safe builders
+ * or template systems.
+ *
+ *
+ * @visibility {//closure/goog/html:approved_for_unchecked_conversion}
+ * @visibility {//closure/goog/bin/sizetests:__pkg__}
+ */
+
+
+goog.provide('goog.html.uncheckedconversions');
+
+goog.require('goog.asserts');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.html.SafeScript');
+goog.require('goog.html.SafeStyle');
+goog.require('goog.html.SafeStyleSheet');
+goog.require('goog.html.SafeUrl');
+goog.require('goog.html.TrustedResourceUrl');
+goog.require('goog.string');
+goog.require('goog.string.Const');
+
+
+/**
+ * Performs an "unchecked conversion" to SafeHtml from a plain string that is
+ * known to satisfy the SafeHtml type contract.
+ *
+ * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
+ * that the value of {@code html} satisfies the SafeHtml type contract in all
+ * possible program states.
+ *
+ *
+ * @param {!goog.string.Const} justification A constant string explaining why
+ * this use of this method is safe. May include a security review ticket
+ * number.
+ * @param {string} html A string that is claimed to adhere to the SafeHtml
+ * contract.
+ * @param {?goog.i18n.bidi.Dir=} opt_dir The optional directionality of the
+ * SafeHtml to be constructed. A null or undefined value signifies an
+ * unknown directionality.
+ * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml
+ * object.
+ * @suppress {visibility} For access to SafeHtml.create... Note that this
+ * use is appropriate since this method is intended to be "package private"
+ * withing goog.html. DO NOT call SafeHtml.create... from outside this
+ * package; use appropriate wrappers instead.
+ */
+goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract =
+ function(justification, html, opt_dir) {
+ // unwrap() called inside an assert so that justification can be optimized
+ // away in production code.
+ goog.asserts.assertString(goog.string.Const.unwrap(justification),
+ 'must provide justification');
+ goog.asserts.assert(
+ !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
+ 'must provide non-empty justification');
+ return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
+ html, opt_dir || null);
+};
+
+
+/**
+ * Performs an "unchecked conversion" to SafeScript from a plain string that is
+ * known to satisfy the SafeScript type contract.
+ *
+ * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
+ * that the value of {@code script} satisfies the SafeScript type contract in
+ * all possible program states.
+ *
+ *
+ * @param {!goog.string.Const} justification A constant string explaining why
+ * this use of this method is safe. May include a security review ticket
+ * number.
+ * @param {string} script The string to wrap as a SafeScript.
+ * @return {!goog.html.SafeScript} The value of {@code script}, wrapped in a
+ * SafeScript object.
+ */
+goog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract =
+ function(justification, script) {
+ // unwrap() called inside an assert so that justification can be optimized
+ // away in production code.
+ goog.asserts.assertString(goog.string.Const.unwrap(justification),
+ 'must provide justification');
+ goog.asserts.assert(
+ !goog.string.isEmpty(goog.string.Const.unwrap(justification)),
+ 'must provide non-empty justification');
+ return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(
+ script);
+};
+
+
+/**
+ * Performs an "unchecked conversion" to SafeStyle from a plain string that is
+ * known to satisfy the SafeStyle type contract.
+ *
+ * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
+ * that the value of {@code style} satisfies the SafeUrl type contract in all
+ * possible program states.
+ *
+ *
+ * @param {!goog.string.Const} justification A constant string explaining why
+ * this use of this method is safe. May include a security review ticket
+ * number.
+ * @param {string} style The string to wrap as a SafeStyle.
+ * @return {!goog.html.SafeStyle} The value of {@code style}, wrapped in a
+ * SafeStyle object.
+ */
+goog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract =
+ function(justification, style) {
+ // unwrap() called inside an assert so that justification can be optimized
+ // away in production code.
+ goog.asserts.assertString(goog.string.Const.unwrap(justification),
+ 'must provide justification');
+ goog.asserts.assert(
+ !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
+ 'must provide non-empty justification');
+ return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
+ style);
+};
+
+
+/**
+ * Performs an "unchecked conversion" to SafeStyleSheet from a plain string
+ * that is known to satisfy the SafeStyleSheet type contract.
+ *
+ * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
+ * that the value of {@code styleSheet} satisfies the SafeUrl type contract in
+ * all possible program states.
+ *
+ *
+ * @param {!goog.string.Const} justification A constant string explaining why
+ * this use of this method is safe. May include a security review ticket
+ * number.
+ * @param {string} styleSheet The string to wrap as a SafeStyleSheet.
+ * @return {!goog.html.SafeStyleSheet} The value of {@code styleSheet}, wrapped
+ * in a SafeStyleSheet object.
+ */
+goog.html.uncheckedconversions.
+ safeStyleSheetFromStringKnownToSatisfyTypeContract =
+ function(justification, styleSheet) {
+ // unwrap() called inside an assert so that justification can be optimized
+ // away in production code.
+ goog.asserts.assertString(goog.string.Const.unwrap(justification),
+ 'must provide justification');
+ goog.asserts.assert(
+ !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
+ 'must provide non-empty justification');
+ return goog.html.SafeStyleSheet.
+ createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet);
+};
+
+
+/**
+ * Performs an "unchecked conversion" to SafeUrl from a plain string that is
+ * known to satisfy the SafeUrl type contract.
+ *
+ * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
+ * that the value of {@code url} satisfies the SafeUrl type contract in all
+ * possible program states.
+ *
+ *
+ * @param {!goog.string.Const} justification A constant string explaining why
+ * this use of this method is safe. May include a security review ticket
+ * number.
+ * @param {string} url The string to wrap as a SafeUrl.
+ * @return {!goog.html.SafeUrl} The value of {@code url}, wrapped in a SafeUrl
+ * object.
+ */
+goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract =
+ function(justification, url) {
+ // unwrap() called inside an assert so that justification can be optimized
+ // away in production code.
+ goog.asserts.assertString(goog.string.Const.unwrap(justification),
+ 'must provide justification');
+ goog.asserts.assert(
+ !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
+ 'must provide non-empty justification');
+ return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
+};
+
+
+/**
+ * Performs an "unchecked conversion" to TrustedResourceUrl from a plain string
+ * that is known to satisfy the TrustedResourceUrl type contract.
+ *
+ * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
+ * that the value of {@code url} satisfies the TrustedResourceUrl type contract
+ * in all possible program states.
+ *
+ *
+ * @param {!goog.string.Const} justification A constant string explaining why
+ * this use of this method is safe. May include a security review ticket
+ * number.
+ * @param {string} url The string to wrap as a TrustedResourceUrl.
+ * @return {!goog.html.TrustedResourceUrl} The value of {@code url}, wrapped in
+ * a TrustedResourceUrl object.
+ */
+goog.html.uncheckedconversions.
+ trustedResourceUrlFromStringKnownToSatisfyTypeContract =
+ function(justification, url) {
+ // unwrap() called inside an assert so that justification can be optimized
+ // away in production code.
+ goog.asserts.assertString(goog.string.Const.unwrap(justification),
+ 'must provide justification');
+ goog.asserts.assert(
+ !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
+ 'must provide non-empty justification');
+ return goog.html.TrustedResourceUrl.
+ createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/utils.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/html/utils.js b/externs/GCL/externs/goog/html/utils.js
new file mode 100644
index 0000000..c54381b
--- /dev/null
+++ b/externs/GCL/externs/goog/html/utils.js
@@ -0,0 +1,67 @@
+// 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 HTML processing utilities for HTML in string form.
+ */
+
+goog.provide('goog.html.utils');
+
+goog.require('goog.string');
+
+
+/**
+ * Extracts plain text from HTML.
+ *
+ * This behaves similarly to extracting textContent from a hypothetical DOM
+ * element containing the specified HTML. Block-level elements such as div are
+ * surrounded with whitespace, but inline elements are not. Span is treated as
+ * a block level element because it is often used as a container. Breaking
+ * spaces are compressed and trimmed.
+ *
+ * @param {string} value The input HTML to have tags removed.
+ * @return {string} The plain text of value without tags, HTML comments, or
+ * other non-text content. Does NOT return safe HTML!
+ */
+goog.html.utils.stripHtmlTags = function(value) {
+ // TODO(user): Make a version that extracts text attributes such as alt.
+ return goog.string.unescapeEntities(goog.string.trim(value.replace(
+ goog.html.utils.HTML_TAG_REGEX_, function(fullMatch, tagName) {
+ return goog.html.utils.INLINE_HTML_TAG_REGEX_.test(tagName) ? '' : ' ';
+ }).
+ replace(/[\t\n ]+/g, ' ')));
+};
+
+
+/**
+ * Matches all tags that do not require extra space.
+ *
+ * @const
+ * @private {RegExp}
+ */
+goog.html.utils.INLINE_HTML_TAG_REGEX_ =
+ /^(?:abbr|acronym|address|b|em|i|small|strong|su[bp]|u)$/i;
+
+
+/**
+ * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML.
+ * By removing these, and replacing any '<' or '>' characters with
+ * entities we guarantee that the result can be embedded into
+ * an attribute without introducing a tag boundary.
+ *
+ * @private {RegExp}
+ * @const
+ */
+goog.html.utils.HTML_TAG_REGEX_ = /<[!\/]?([a-z0-9]+)([\/ ][^>]*)?>/gi;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/bidi.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/i18n/bidi.js b/externs/GCL/externs/goog/i18n/bidi.js
new file mode 100644
index 0000000..0f85cc2
--- /dev/null
+++ b/externs/GCL/externs/goog/i18n/bidi.js
@@ -0,0 +1,897 @@
+// 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 Utility functions for supporting Bidi issues.
+ */
+
+
+/**
+ * Namespace for bidi supporting functions.
+ */
+goog.provide('goog.i18n.bidi');
+goog.provide('goog.i18n.bidi.Dir');
+goog.provide('goog.i18n.bidi.DirectionalString');
+goog.provide('goog.i18n.bidi.Format');
+
+
+/**
+ * @define {boolean} FORCE_RTL forces the {@link goog.i18n.bidi.IS_RTL} constant
+ * to say that the current locale is a RTL locale. This should only be used
+ * if you want to override the default behavior for deciding whether the
+ * current locale is RTL or not.
+ *
+ * {@see goog.i18n.bidi.IS_RTL}
+ */
+goog.define('goog.i18n.bidi.FORCE_RTL', false);
+
+
+/**
+ * Constant that defines whether or not the current locale is a RTL locale.
+ * If {@link goog.i18n.bidi.FORCE_RTL} is not true, this constant will default
+ * to check that {@link goog.LOCALE} is one of a few major RTL locales.
+ *
+ * <p>This is designed to be a maximally efficient compile-time constant. For
+ * example, for the default goog.LOCALE, compiling
+ * "if (goog.i18n.bidi.IS_RTL) alert('rtl') else {}" should produce no code. It
+ * is this design consideration that limits the implementation to only
+ * supporting a few major RTL locales, as opposed to the broader repertoire of
+ * something like goog.i18n.bidi.isRtlLanguage.
+ *
+ * <p>Since this constant refers to the directionality of the locale, it is up
+ * to the caller to determine if this constant should also be used for the
+ * direction of the UI.
+ *
+ * {@see goog.LOCALE}
+ *
+ * @type {boolean}
+ *
+ * TODO(user): write a test that checks that this is a compile-time constant.
+ */
+goog.i18n.bidi.IS_RTL = goog.i18n.bidi.FORCE_RTL ||
+ (
+ (goog.LOCALE.substring(0, 2).toLowerCase() == 'ar' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'fa' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'he' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'iw' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'ps' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'sd' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'ug' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'ur' ||
+ goog.LOCALE.substring(0, 2).toLowerCase() == 'yi') &&
+ (goog.LOCALE.length == 2 ||
+ goog.LOCALE.substring(2, 3) == '-' ||
+ goog.LOCALE.substring(2, 3) == '_')
+ ) || (
+ goog.LOCALE.length >= 3 &&
+ goog.LOCALE.substring(0, 3).toLowerCase() == 'ckb' &&
+ (goog.LOCALE.length == 3 ||
+ goog.LOCALE.substring(3, 4) == '-' ||
+ goog.LOCALE.substring(3, 4) == '_')
+ );
+
+
+/**
+ * Unicode formatting characters and directionality string constants.
+ * @enum {string}
+ */
+goog.i18n.bidi.Format = {
+ /** Unicode "Left-To-Right Embedding" (LRE) character. */
+ LRE: '\u202A',
+ /** Unicode "Right-To-Left Embedding" (RLE) character. */
+ RLE: '\u202B',
+ /** Unicode "Pop Directional Formatting" (PDF) character. */
+ PDF: '\u202C',
+ /** Unicode "Left-To-Right Mark" (LRM) character. */
+ LRM: '\u200E',
+ /** Unicode "Right-To-Left Mark" (RLM) character. */
+ RLM: '\u200F'
+};
+
+
+/**
+ * Directionality enum.
+ * @enum {number}
+ */
+goog.i18n.bidi.Dir = {
+ /**
+ * Left-to-right.
+ */
+ LTR: 1,
+
+ /**
+ * Right-to-left.
+ */
+ RTL: -1,
+
+ /**
+ * Neither left-to-right nor right-to-left.
+ */
+ NEUTRAL: 0
+};
+
+
+/**
+ * 'right' string constant.
+ * @type {string}
+ */
+goog.i18n.bidi.RIGHT = 'right';
+
+
+/**
+ * 'left' string constant.
+ * @type {string}
+ */
+goog.i18n.bidi.LEFT = 'left';
+
+
+/**
+ * 'left' if locale is RTL, 'right' if not.
+ * @type {string}
+ */
+goog.i18n.bidi.I18N_RIGHT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.LEFT :
+ goog.i18n.bidi.RIGHT;
+
+
+/**
+ * 'right' if locale is RTL, 'left' if not.
+ * @type {string}
+ */
+goog.i18n.bidi.I18N_LEFT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT :
+ goog.i18n.bidi.LEFT;
+
+
+/**
+ * Convert a directionality given in various formats to a goog.i18n.bidi.Dir
+ * constant. Useful for interaction with different standards of directionality
+ * representation.
+ *
+ * @param {goog.i18n.bidi.Dir|number|boolean|null} givenDir Directionality given
+ * in one of the following formats:
+ * 1. A goog.i18n.bidi.Dir constant.
+ * 2. A number (positive = LTR, negative = RTL, 0 = neutral).
+ * 3. A boolean (true = RTL, false = LTR).
+ * 4. A null for unknown directionality.
+ * @param {boolean=} opt_noNeutral Whether a givenDir of zero or
+ * goog.i18n.bidi.Dir.NEUTRAL should be treated as null, i.e. unknown, in
+ * order to preserve legacy behavior.
+ * @return {?goog.i18n.bidi.Dir} A goog.i18n.bidi.Dir constant matching the
+ * given directionality. If given null, returns null (i.e. unknown).
+ */
+goog.i18n.bidi.toDir = function(givenDir, opt_noNeutral) {
+ if (typeof givenDir == 'number') {
+ // This includes the non-null goog.i18n.bidi.Dir case.
+ return givenDir > 0 ? goog.i18n.bidi.Dir.LTR :
+ givenDir < 0 ? goog.i18n.bidi.Dir.RTL :
+ opt_noNeutral ? null : goog.i18n.bidi.Dir.NEUTRAL;
+ } else if (givenDir == null) {
+ return null;
+ } else {
+ // Must be typeof givenDir == 'boolean'.
+ return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR;
+ }
+};
+
+
+/**
+ * A practical pattern to identify strong LTR characters. This pattern is not
+ * theoretically correct according to the Unicode standard. It is simplified for
+ * performance and small code size.
+ * @type {string}
+ * @private
+ */
+goog.i18n.bidi.ltrChars_ =
+ 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' +
+ '\u200E\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF';
+
+
+/**
+ * A practical pattern to identify strong RTL character. This pattern is not
+ * theoretically correct according to the Unicode standard. It is simplified
+ * for performance and small code size.
+ * @type {string}
+ * @private
+ */
+goog.i18n.bidi.rtlChars_ = '\u0591-\u07FF\u200F\uFB1D-\uFDFF\uFE70-\uFEFC';
+
+
+/**
+ * Simplified regular expression for an HTML tag (opening or closing) or an HTML
+ * escape. We might want to skip over such expressions when estimating the text
+ * directionality.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.htmlSkipReg_ = /<[^>]*>|&[^;]+;/g;
+
+
+/**
+ * Returns the input text with spaces instead of HTML tags or HTML escapes, if
+ * opt_isStripNeeded is true. Else returns the input as is.
+ * Useful for text directionality estimation.
+ * Note: the function should not be used in other contexts; it is not 100%
+ * correct, but rather a good-enough implementation for directionality
+ * estimation purposes.
+ * @param {string} str The given string.
+ * @param {boolean=} opt_isStripNeeded Whether to perform the stripping.
+ * Default: false (to retain consistency with calling functions).
+ * @return {string} The given string cleaned of HTML tags / escapes.
+ * @private
+ */
+goog.i18n.bidi.stripHtmlIfNeeded_ = function(str, opt_isStripNeeded) {
+ return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, '') :
+ str;
+};
+
+
+/**
+ * Regular expression to check for RTL characters.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.rtlCharReg_ = new RegExp('[' + goog.i18n.bidi.rtlChars_ + ']');
+
+
+/**
+ * Regular expression to check for LTR characters.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.ltrCharReg_ = new RegExp('[' + goog.i18n.bidi.ltrChars_ + ']');
+
+
+/**
+ * Test whether the given string has any RTL characters in it.
+ * @param {string} str The given string that need to be tested.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether the string contains RTL characters.
+ */
+goog.i18n.bidi.hasAnyRtl = function(str, opt_isHtml) {
+ return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
+ str, opt_isHtml));
+};
+
+
+/**
+ * Test whether the given string has any RTL characters in it.
+ * @param {string} str The given string that need to be tested.
+ * @return {boolean} Whether the string contains RTL characters.
+ * @deprecated Use hasAnyRtl.
+ */
+goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl;
+
+
+/**
+ * Test whether the given string has any LTR characters in it.
+ * @param {string} str The given string that need to be tested.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether the string contains LTR characters.
+ */
+goog.i18n.bidi.hasAnyLtr = function(str, opt_isHtml) {
+ return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
+ str, opt_isHtml));
+};
+
+
+/**
+ * Regular expression pattern to check if the first character in the string
+ * is LTR.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.ltrRe_ = new RegExp('^[' + goog.i18n.bidi.ltrChars_ + ']');
+
+
+/**
+ * Regular expression pattern to check if the first character in the string
+ * is RTL.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.rtlRe_ = new RegExp('^[' + goog.i18n.bidi.rtlChars_ + ']');
+
+
+/**
+ * Check if the first character in the string is RTL or not.
+ * @param {string} str The given string that need to be tested.
+ * @return {boolean} Whether the first character in str is an RTL char.
+ */
+goog.i18n.bidi.isRtlChar = function(str) {
+ return goog.i18n.bidi.rtlRe_.test(str);
+};
+
+
+/**
+ * Check if the first character in the string is LTR or not.
+ * @param {string} str The given string that need to be tested.
+ * @return {boolean} Whether the first character in str is an LTR char.
+ */
+goog.i18n.bidi.isLtrChar = function(str) {
+ return goog.i18n.bidi.ltrRe_.test(str);
+};
+
+
+/**
+ * Check if the first character in the string is neutral or not.
+ * @param {string} str The given string that need to be tested.
+ * @return {boolean} Whether the first character in str is a neutral char.
+ */
+goog.i18n.bidi.isNeutralChar = function(str) {
+ return !goog.i18n.bidi.isLtrChar(str) && !goog.i18n.bidi.isRtlChar(str);
+};
+
+
+/**
+ * Regular expressions to check if a piece of text is of LTR directionality
+ * on first character with strong directionality.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.ltrDirCheckRe_ = new RegExp(
+ '^[^' + goog.i18n.bidi.rtlChars_ + ']*[' + goog.i18n.bidi.ltrChars_ + ']');
+
+
+/**
+ * Regular expressions to check if a piece of text is of RTL directionality
+ * on first character with strong directionality.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.rtlDirCheckRe_ = new RegExp(
+ '^[^' + goog.i18n.bidi.ltrChars_ + ']*[' + goog.i18n.bidi.rtlChars_ + ']');
+
+
+/**
+ * Check whether the first strongly directional character (if any) is RTL.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether RTL directionality is detected using the first
+ * strongly-directional character method.
+ */
+goog.i18n.bidi.startsWithRtl = function(str, opt_isHtml) {
+ return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
+ str, opt_isHtml));
+};
+
+
+/**
+ * Check whether the first strongly directional character (if any) is RTL.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether RTL directionality is detected using the first
+ * strongly-directional character method.
+ * @deprecated Use startsWithRtl.
+ */
+goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl;
+
+
+/**
+ * Check whether the first strongly directional character (if any) is LTR.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether LTR directionality is detected using the first
+ * strongly-directional character method.
+ */
+goog.i18n.bidi.startsWithLtr = function(str, opt_isHtml) {
+ return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
+ str, opt_isHtml));
+};
+
+
+/**
+ * Check whether the first strongly directional character (if any) is LTR.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether LTR directionality is detected using the first
+ * strongly-directional character method.
+ * @deprecated Use startsWithLtr.
+ */
+goog.i18n.bidi.isLtrText = goog.i18n.bidi.startsWithLtr;
+
+
+/**
+ * Regular expression to check if a string looks like something that must
+ * always be LTR even in RTL text, e.g. a URL. When estimating the
+ * directionality of text containing these, we treat these as weakly LTR,
+ * like numbers.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.isRequiredLtrRe_ = /^http:\/\/.*/;
+
+
+/**
+ * Check whether the input string either contains no strongly directional
+ * characters or looks like a url.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether neutral directionality is detected.
+ */
+goog.i18n.bidi.isNeutralText = function(str, opt_isHtml) {
+ str = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml);
+ return goog.i18n.bidi.isRequiredLtrRe_.test(str) ||
+ !goog.i18n.bidi.hasAnyLtr(str) && !goog.i18n.bidi.hasAnyRtl(str);
+};
+
+
+/**
+ * Regular expressions to check if the last strongly-directional character in a
+ * piece of text is LTR.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.ltrExitDirCheckRe_ = new RegExp(
+ '[' + goog.i18n.bidi.ltrChars_ + '][^' + goog.i18n.bidi.rtlChars_ + ']*$');
+
+
+/**
+ * Regular expressions to check if the last strongly-directional character in a
+ * piece of text is RTL.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.rtlExitDirCheckRe_ = new RegExp(
+ '[' + goog.i18n.bidi.rtlChars_ + '][^' + goog.i18n.bidi.ltrChars_ + ']*$');
+
+
+/**
+ * Check if the exit directionality a piece of text is LTR, i.e. if the last
+ * strongly-directional character in the string is LTR.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether LTR exit directionality was detected.
+ */
+goog.i18n.bidi.endsWithLtr = function(str, opt_isHtml) {
+ return goog.i18n.bidi.ltrExitDirCheckRe_.test(
+ goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
+};
+
+
+/**
+ * Check if the exit directionality a piece of text is LTR, i.e. if the last
+ * strongly-directional character in the string is LTR.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether LTR exit directionality was detected.
+ * @deprecated Use endsWithLtr.
+ */
+goog.i18n.bidi.isLtrExitText = goog.i18n.bidi.endsWithLtr;
+
+
+/**
+ * Check if the exit directionality a piece of text is RTL, i.e. if the last
+ * strongly-directional character in the string is RTL.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether RTL exit directionality was detected.
+ */
+goog.i18n.bidi.endsWithRtl = function(str, opt_isHtml) {
+ return goog.i18n.bidi.rtlExitDirCheckRe_.test(
+ goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
+};
+
+
+/**
+ * Check if the exit directionality a piece of text is RTL, i.e. if the last
+ * strongly-directional character in the string is RTL.
+ * @param {string} str String being checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether RTL exit directionality was detected.
+ * @deprecated Use endsWithRtl.
+ */
+goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl;
+
+
+/**
+ * A regular expression for matching right-to-left language codes.
+ * See {@link #isRtlLanguage} for the design.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.rtlLocalesRe_ = new RegExp(
+ '^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|' +
+ '.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))' +
+ '(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)',
+ 'i');
+
+
+/**
+ * Check if a BCP 47 / III language code indicates an RTL language, i.e. either:
+ * - a language code explicitly specifying one of the right-to-left scripts,
+ * e.g. "az-Arab", or<p>
+ * - a language code specifying one of the languages normally written in a
+ * right-to-left script, e.g. "fa" (Farsi), except ones explicitly specifying
+ * Latin or Cyrillic script (which are the usual LTR alternatives).<p>
+ * The list of right-to-left scripts appears in the 100-199 range in
+ * http://www.unicode.org/iso15924/iso15924-num.html, of which Arabic and
+ * Hebrew are by far the most widely used. We also recognize Thaana, N'Ko, and
+ * Tifinagh, which also have significant modern usage. The rest (Syriac,
+ * Samaritan, Mandaic, etc.) seem to have extremely limited or no modern usage
+ * and are not recognized to save on code size.
+ * The languages usually written in a right-to-left script are taken as those
+ * with Suppress-Script: Hebr|Arab|Thaa|Nkoo|Tfng in
+ * http://www.iana.org/assignments/language-subtag-registry,
+ * as well as Central (or Sorani) Kurdish (ckb), Sindhi (sd) and Uyghur (ug).
+ * Other subtags of the language code, e.g. regions like EG (Egypt), are
+ * ignored.
+ * @param {string} lang BCP 47 (a.k.a III) language code.
+ * @return {boolean} Whether the language code is an RTL language.
+ */
+goog.i18n.bidi.isRtlLanguage = function(lang) {
+ return goog.i18n.bidi.rtlLocalesRe_.test(lang);
+};
+
+
+/**
+ * Regular expression for bracket guard replacement in html.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.bracketGuardHtmlRe_ =
+ /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(<.*?(>)+)/g;
+
+
+/**
+ * Regular expression for bracket guard replacement in text.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.bracketGuardTextRe_ =
+ /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(<.*?>+)/g;
+
+
+/**
+ * Apply bracket guard using html span tag. This is to address the problem of
+ * messy bracket display frequently happens in RTL layout.
+ * @param {string} s The string that need to be processed.
+ * @param {boolean=} opt_isRtlContext specifies default direction (usually
+ * direction of the UI).
+ * @return {string} The processed string, with all bracket guarded.
+ */
+goog.i18n.bidi.guardBracketInHtml = function(s, opt_isRtlContext) {
+ var useRtl = opt_isRtlContext === undefined ?
+ goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext;
+ if (useRtl) {
+ return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
+ '<span dir=rtl>$&</span>');
+ }
+ return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
+ '<span dir=ltr>$&</span>');
+};
+
+
+/**
+ * Apply bracket guard using LRM and RLM. This is to address the problem of
+ * messy bracket display frequently happens in RTL layout.
+ * This version works for both plain text and html. But it does not work as
+ * good as guardBracketInHtml in some cases.
+ * @param {string} s The string that need to be processed.
+ * @param {boolean=} opt_isRtlContext specifies default direction (usually
+ * direction of the UI).
+ * @return {string} The processed string, with all bracket guarded.
+ */
+goog.i18n.bidi.guardBracketInText = function(s, opt_isRtlContext) {
+ var useRtl = opt_isRtlContext === undefined ?
+ goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext;
+ var mark = useRtl ? goog.i18n.bidi.Format.RLM : goog.i18n.bidi.Format.LRM;
+ return s.replace(goog.i18n.bidi.bracketGuardTextRe_, mark + '$&' + mark);
+};
+
+
+/**
+ * Enforce the html snippet in RTL directionality regardless overall context.
+ * If the html piece was enclosed by tag, dir will be applied to existing
+ * tag, otherwise a span tag will be added as wrapper. For this reason, if
+ * html snippet start with with tag, this tag must enclose the whole piece. If
+ * the tag already has a dir specified, this new one will override existing
+ * one in behavior (tested on FF and IE).
+ * @param {string} html The string that need to be processed.
+ * @return {string} The processed string, with directionality enforced to RTL.
+ */
+goog.i18n.bidi.enforceRtlInHtml = function(html) {
+ if (html.charAt(0) == '<') {
+ return html.replace(/<\w+/, '$& dir=rtl');
+ }
+ // '\n' is important for FF so that it won't incorrectly merge span groups
+ return '\n<span dir=rtl>' + html + '</span>';
+};
+
+
+/**
+ * Enforce RTL on both end of the given text piece using unicode BiDi formatting
+ * characters RLE and PDF.
+ * @param {string} text The piece of text that need to be wrapped.
+ * @return {string} The wrapped string after process.
+ */
+goog.i18n.bidi.enforceRtlInText = function(text) {
+ return goog.i18n.bidi.Format.RLE + text + goog.i18n.bidi.Format.PDF;
+};
+
+
+/**
+ * Enforce the html snippet in RTL directionality regardless overall context.
+ * If the html piece was enclosed by tag, dir will be applied to existing
+ * tag, otherwise a span tag will be added as wrapper. For this reason, if
+ * html snippet start with with tag, this tag must enclose the whole piece. If
+ * the tag already has a dir specified, this new one will override existing
+ * one in behavior (tested on FF and IE).
+ * @param {string} html The string that need to be processed.
+ * @return {string} The processed string, with directionality enforced to RTL.
+ */
+goog.i18n.bidi.enforceLtrInHtml = function(html) {
+ if (html.charAt(0) == '<') {
+ return html.replace(/<\w+/, '$& dir=ltr');
+ }
+ // '\n' is important for FF so that it won't incorrectly merge span groups
+ return '\n<span dir=ltr>' + html + '</span>';
+};
+
+
+/**
+ * Enforce LTR on both end of the given text piece using unicode BiDi formatting
+ * characters LRE and PDF.
+ * @param {string} text The piece of text that need to be wrapped.
+ * @return {string} The wrapped string after process.
+ */
+goog.i18n.bidi.enforceLtrInText = function(text) {
+ return goog.i18n.bidi.Format.LRE + text + goog.i18n.bidi.Format.PDF;
+};
+
+
+/**
+ * Regular expression to find dimensions such as "padding: .3 0.4ex 5px 6;"
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.dimensionsRe_ =
+ /:\s*([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)/g;
+
+
+/**
+ * Regular expression for left.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.leftRe_ = /left/gi;
+
+
+/**
+ * Regular expression for right.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.rightRe_ = /right/gi;
+
+
+/**
+ * Placeholder regular expression for swapping.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.tempRe_ = /%%%%/g;
+
+
+/**
+ * Swap location parameters and 'left'/'right' in CSS specification. The
+ * processed string will be suited for RTL layout. Though this function can
+ * cover most cases, there are always exceptions. It is suggested to put
+ * those exceptions in separate group of CSS string.
+ * @param {string} cssStr CSS spefication string.
+ * @return {string} Processed CSS specification string.
+ */
+goog.i18n.bidi.mirrorCSS = function(cssStr) {
+ return cssStr.
+ // reverse dimensions
+ replace(goog.i18n.bidi.dimensionsRe_, ':$1 $4 $3 $2').
+ replace(goog.i18n.bidi.leftRe_, '%%%%'). // swap left and right
+ replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT).
+ replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT);
+};
+
+
+/**
+ * Regular expression for hebrew double quote substitution, finding quote
+ * directly after hebrew characters.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.doubleQuoteSubstituteRe_ = /([\u0591-\u05f2])"/g;
+
+
+/**
+ * Regular expression for hebrew single quote substitution, finding quote
+ * directly after hebrew characters.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\u0591-\u05f2])'/g;
+
+
+/**
+ * Replace the double and single quote directly after a Hebrew character with
+ * GERESH and GERSHAYIM. In such case, most likely that's user intention.
+ * @param {string} str String that need to be processed.
+ * @return {string} Processed string with double/single quote replaced.
+ */
+goog.i18n.bidi.normalizeHebrewQuote = function(str) {
+ return str.
+ replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, '$1\u05f4').
+ replace(goog.i18n.bidi.singleQuoteSubstituteRe_, '$1\u05f3');
+};
+
+
+/**
+ * Regular expression to split a string into "words" for directionality
+ * estimation based on relative word counts.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.wordSeparatorRe_ = /\s+/;
+
+
+/**
+ * Regular expression to check if a string contains any numerals. Used to
+ * differentiate between completely neutral strings and those containing
+ * numbers, which are weakly LTR.
+ * @type {RegExp}
+ * @private
+ */
+goog.i18n.bidi.hasNumeralsRe_ = /\d/;
+
+
+/**
+ * This constant controls threshold of RTL directionality.
+ * @type {number}
+ * @private
+ */
+goog.i18n.bidi.rtlDetectionThreshold_ = 0.40;
+
+
+/**
+ * Estimates the directionality of a string based on relative word counts.
+ * If the number of RTL words is above a certain percentage of the total number
+ * of strongly directional words, returns RTL.
+ * Otherwise, if any words are strongly or weakly LTR, returns LTR.
+ * Otherwise, returns UNKNOWN, which is used to mean "neutral".
+ * Numbers are counted as weakly LTR.
+ * @param {string} str The string to be checked.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}.
+ */
+goog.i18n.bidi.estimateDirection = function(str, opt_isHtml) {
+ var rtlCount = 0;
+ var totalCount = 0;
+ var hasWeaklyLtr = false;
+ var tokens = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml).
+ split(goog.i18n.bidi.wordSeparatorRe_);
+ for (var i = 0; i < tokens.length; i++) {
+ var token = tokens[i];
+ if (goog.i18n.bidi.startsWithRtl(token)) {
+ rtlCount++;
+ totalCount++;
+ } else if (goog.i18n.bidi.isRequiredLtrRe_.test(token)) {
+ hasWeaklyLtr = true;
+ } else if (goog.i18n.bidi.hasAnyLtr(token)) {
+ totalCount++;
+ } else if (goog.i18n.bidi.hasNumeralsRe_.test(token)) {
+ hasWeaklyLtr = true;
+ }
+ }
+
+ return totalCount == 0 ?
+ (hasWeaklyLtr ? goog.i18n.bidi.Dir.LTR : goog.i18n.bidi.Dir.NEUTRAL) :
+ (rtlCount / totalCount > goog.i18n.bidi.rtlDetectionThreshold_ ?
+ goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR);
+};
+
+
+/**
+ * Check the directionality of a piece of text, return true if the piece of
+ * text should be laid out in RTL direction.
+ * @param {string} str The piece of text that need to be detected.
+ * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
+ * Default: false.
+ * @return {boolean} Whether this piece of text should be laid out in RTL.
+ */
+goog.i18n.bidi.detectRtlDirectionality = function(str, opt_isHtml) {
+ return goog.i18n.bidi.estimateDirection(str, opt_isHtml) ==
+ goog.i18n.bidi.Dir.RTL;
+};
+
+
+/**
+ * Sets text input element's directionality and text alignment based on a
+ * given directionality. Does nothing if the given directionality is unknown or
+ * neutral.
+ * @param {Element} element Input field element to set directionality to.
+ * @param {goog.i18n.bidi.Dir|number|boolean|null} dir Desired directionality,
+ * given in one of the following formats:
+ * 1. A goog.i18n.bidi.Dir constant.
+ * 2. A number (positive = LRT, negative = RTL, 0 = neutral).
+ * 3. A boolean (true = RTL, false = LTR).
+ * 4. A null for unknown directionality.
+ */
+goog.i18n.bidi.setElementDirAndAlign = function(element, dir) {
+ if (element) {
+ dir = goog.i18n.bidi.toDir(dir);
+ if (dir) {
+ element.style.textAlign =
+ dir == goog.i18n.bidi.Dir.RTL ?
+ goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT;
+ element.dir = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr';
+ }
+ }
+};
+
+
+/**
+ * Sets element dir based on estimated directionality of the given text.
+ * @param {!Element} element
+ * @param {string} text
+ */
+goog.i18n.bidi.setElementDirByTextDirectionality = function(element, text) {
+ switch (goog.i18n.bidi.estimateDirection(text)) {
+ case (goog.i18n.bidi.Dir.LTR):
+ element.dir = 'ltr';
+ break;
+ case (goog.i18n.bidi.Dir.RTL):
+ element.dir = 'rtl';
+ break;
+ default:
+ // Default for no direction, inherit from document.
+ element.removeAttribute('dir');
+ }
+};
+
+
+
+/**
+ * Strings that have an (optional) known direction.
+ *
+ * Implementations of this interface are string-like objects that carry an
+ * attached direction, if known.
+ * @interface
+ */
+goog.i18n.bidi.DirectionalString = function() {};
+
+
+/**
+ * Interface marker of the DirectionalString interface.
+ *
+ * This property can be used to determine at runtime whether or not an object
+ * implements this interface. All implementations of this interface set this
+ * property to {@code true}.
+ * @type {boolean}
+ */
+goog.i18n.bidi.DirectionalString.prototype.
+ implementsGoogI18nBidiDirectionalString;
+
+
+/**
+ * Retrieves this object's known direction (if any).
+ * @return {?goog.i18n.bidi.Dir} The known direction. Null if unknown.
+ */
+goog.i18n.bidi.DirectionalString.prototype.getDirection;
[30/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/dom.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/dom.js b/externs/GCL/externs/goog/dom/dom.js
new file mode 100644
index 0000000..ad4f430
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/dom.js
@@ -0,0 +1,2990 @@
+// 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 manipulating the browser's Document Object Model
+ * Inspiration taken *heavily* from mochikit (http://mochikit.com/).
+ *
+ * You can use {@link goog.dom.DomHelper} to create new dom helpers that refer
+ * to a different document object. This is useful if you are working with
+ * frames or multiple windows.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+// TODO(arv): Rename/refactor getTextContent and getRawTextContent. The problem
+// is that getTextContent should mimic the DOM3 textContent. We should add a
+// getInnerText (or getText) which tries to return the visible text, innerText.
+
+
+goog.provide('goog.dom');
+goog.provide('goog.dom.Appendable');
+goog.provide('goog.dom.DomHelper');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.dom.BrowserFeature');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.safe');
+goog.require('goog.html.SafeHtml');
+goog.require('goog.math.Coordinate');
+goog.require('goog.math.Size');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.string.Unicode');
+goog.require('goog.userAgent');
+
+
+/**
+ * @define {boolean} Whether we know at compile time that the browser is in
+ * quirks mode.
+ */
+goog.define('goog.dom.ASSUME_QUIRKS_MODE', false);
+
+
+/**
+ * @define {boolean} Whether we know at compile time that the browser is in
+ * standards compliance mode.
+ */
+goog.define('goog.dom.ASSUME_STANDARDS_MODE', false);
+
+
+/**
+ * Whether we know the compatibility mode at compile time.
+ * @type {boolean}
+ * @private
+ */
+goog.dom.COMPAT_MODE_KNOWN_ =
+ goog.dom.ASSUME_QUIRKS_MODE || goog.dom.ASSUME_STANDARDS_MODE;
+
+
+/**
+ * Gets the DomHelper object for the document where the element resides.
+ * @param {(Node|Window)=} opt_element If present, gets the DomHelper for this
+ * element.
+ * @return {!goog.dom.DomHelper} The DomHelper.
+ */
+goog.dom.getDomHelper = function(opt_element) {
+ return opt_element ?
+ new goog.dom.DomHelper(goog.dom.getOwnerDocument(opt_element)) :
+ (goog.dom.defaultDomHelper_ ||
+ (goog.dom.defaultDomHelper_ = new goog.dom.DomHelper()));
+};
+
+
+/**
+ * Cached default DOM helper.
+ * @type {goog.dom.DomHelper}
+ * @private
+ */
+goog.dom.defaultDomHelper_;
+
+
+/**
+ * Gets the document object being used by the dom library.
+ * @return {!Document} Document object.
+ */
+goog.dom.getDocument = function() {
+ return document;
+};
+
+
+/**
+ * Gets an element from the current document by element id.
+ *
+ * If an Element is passed in, it is returned.
+ *
+ * @param {string|Element} element Element ID or a DOM node.
+ * @return {Element} The element with the given ID, or the node passed in.
+ */
+goog.dom.getElement = function(element) {
+ return goog.dom.getElementHelper_(document, element);
+};
+
+
+/**
+ * Gets an element by id from the given document (if present).
+ * If an element is given, it is returned.
+ * @param {!Document} doc
+ * @param {string|Element} element Element ID or a DOM node.
+ * @return {Element} The resulting element.
+ * @private
+ */
+goog.dom.getElementHelper_ = function(doc, element) {
+ return goog.isString(element) ?
+ doc.getElementById(element) :
+ element;
+};
+
+
+/**
+ * Gets an element by id, asserting that the element is found.
+ *
+ * This is used when an element is expected to exist, and should fail with
+ * an assertion error if it does not (if assertions are enabled).
+ *
+ * @param {string} id Element ID.
+ * @return {!Element} The element with the given ID, if it exists.
+ */
+goog.dom.getRequiredElement = function(id) {
+ return goog.dom.getRequiredElementHelper_(document, id);
+};
+
+
+/**
+ * Helper function for getRequiredElementHelper functions, both static and
+ * on DomHelper. Asserts the element with the given id exists.
+ * @param {!Document} doc
+ * @param {string} id
+ * @return {!Element} The element with the given ID, if it exists.
+ * @private
+ */
+goog.dom.getRequiredElementHelper_ = function(doc, id) {
+ // To prevent users passing in Elements as is permitted in getElement().
+ goog.asserts.assertString(id);
+ var element = goog.dom.getElementHelper_(doc, id);
+ element = goog.asserts.assertElement(element,
+ 'No element found with id: ' + id);
+ return element;
+};
+
+
+/**
+ * Alias for getElement.
+ * @param {string|Element} element Element ID or a DOM node.
+ * @return {Element} The element with the given ID, or the node passed in.
+ * @deprecated Use {@link goog.dom.getElement} instead.
+ */
+goog.dom.$ = goog.dom.getElement;
+
+
+/**
+ * Looks up elements by both tag and class name, using browser native functions
+ * ({@code querySelectorAll}, {@code getElementsByTagName} or
+ * {@code getElementsByClassName}) where possible. This function
+ * is a useful, if limited, way of collecting a list of DOM elements
+ * with certain characteristics. {@code goog.dom.query} offers a
+ * more powerful and general solution which allows matching on CSS3
+ * selector expressions, but at increased cost in code size. If all you
+ * need is particular tags belonging to a single class, this function
+ * is fast and sleek.
+ *
+ * Note that tag names are case sensitive in the SVG namespace, and this
+ * function converts opt_tag to uppercase for comparisons. For queries in the
+ * SVG namespace you should use querySelector or querySelectorAll instead.
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=963870
+ * https://bugs.webkit.org/show_bug.cgi?id=83438
+ *
+ * @see {goog.dom.query}
+ *
+ * @param {?string=} opt_tag Element tag name.
+ * @param {?string=} opt_class Optional class name.
+ * @param {(Document|Element)=} opt_el Optional element to look in.
+ * @return { {length: number} } Array-like list of elements (only a length
+ * property and numerical indices are guaranteed to exist).
+ */
+goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
+ return goog.dom.getElementsByTagNameAndClass_(document, opt_tag, opt_class,
+ opt_el);
+};
+
+
+/**
+ * Returns a static, array-like list of the elements with the provided
+ * className.
+ * @see {goog.dom.query}
+ * @param {string} className the name of the class to look for.
+ * @param {(Document|Element)=} opt_el Optional element to look in.
+ * @return { {length: number} } The items found with the class name provided.
+ */
+goog.dom.getElementsByClass = function(className, opt_el) {
+ var parent = opt_el || document;
+ if (goog.dom.canUseQuerySelector_(parent)) {
+ return parent.querySelectorAll('.' + className);
+ }
+ return goog.dom.getElementsByTagNameAndClass_(
+ document, '*', className, opt_el);
+};
+
+
+/**
+ * Returns the first element with the provided className.
+ * @see {goog.dom.query}
+ * @param {string} className the name of the class to look for.
+ * @param {Element|Document=} opt_el Optional element to look in.
+ * @return {Element} The first item with the class name provided.
+ */
+goog.dom.getElementByClass = function(className, opt_el) {
+ var parent = opt_el || document;
+ var retVal = null;
+ if (parent.getElementsByClassName) {
+ retVal = parent.getElementsByClassName(className)[0];
+ } else if (goog.dom.canUseQuerySelector_(parent)) {
+ retVal = parent.querySelector('.' + className);
+ } else {
+ retVal = goog.dom.getElementsByTagNameAndClass_(
+ document, '*', className, opt_el)[0];
+ }
+ return retVal || null;
+};
+
+
+/**
+ * Ensures an element with the given className exists, and then returns the
+ * first element with the provided className.
+ * @see {goog.dom.query}
+ * @param {string} className the name of the class to look for.
+ * @param {!Element|!Document=} opt_root Optional element or document to look
+ * in.
+ * @return {!Element} The first item with the class name provided.
+ * @throws {goog.asserts.AssertionError} Thrown if no element is found.
+ */
+goog.dom.getRequiredElementByClass = function(className, opt_root) {
+ var retValue = goog.dom.getElementByClass(className, opt_root);
+ return goog.asserts.assert(retValue,
+ 'No element found with className: ' + className);
+};
+
+
+/**
+ * Prefer the standardized (http://www.w3.org/TR/selectors-api/), native and
+ * fast W3C Selectors API.
+ * @param {!(Element|Document)} parent The parent document object.
+ * @return {boolean} whether or not we can use parent.querySelector* APIs.
+ * @private
+ */
+goog.dom.canUseQuerySelector_ = function(parent) {
+ return !!(parent.querySelectorAll && parent.querySelector);
+};
+
+
+/**
+ * Helper for {@code getElementsByTagNameAndClass}.
+ * @param {!Document} doc The document to get the elements in.
+ * @param {?string=} opt_tag Element tag name.
+ * @param {?string=} opt_class Optional class name.
+ * @param {(Document|Element)=} opt_el Optional element to look in.
+ * @return { {length: number} } Array-like list of elements (only a length
+ * property and numerical indices are guaranteed to exist).
+ * @private
+ */
+goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class,
+ opt_el) {
+ var parent = opt_el || doc;
+ var tagName = (opt_tag && opt_tag != '*') ? opt_tag.toUpperCase() : '';
+
+ if (goog.dom.canUseQuerySelector_(parent) &&
+ (tagName || opt_class)) {
+ var query = tagName + (opt_class ? '.' + opt_class : '');
+ return parent.querySelectorAll(query);
+ }
+
+ // Use the native getElementsByClassName if available, under the assumption
+ // that even when the tag name is specified, there will be fewer elements to
+ // filter through when going by class than by tag name
+ if (opt_class && parent.getElementsByClassName) {
+ var els = parent.getElementsByClassName(opt_class);
+
+ if (tagName) {
+ var arrayLike = {};
+ var len = 0;
+
+ // Filter for specific tags if requested.
+ for (var i = 0, el; el = els[i]; i++) {
+ if (tagName == el.nodeName) {
+ arrayLike[len++] = el;
+ }
+ }
+ arrayLike.length = len;
+
+ return arrayLike;
+ } else {
+ return els;
+ }
+ }
+
+ var els = parent.getElementsByTagName(tagName || '*');
+
+ if (opt_class) {
+ var arrayLike = {};
+ var len = 0;
+ for (var i = 0, el; el = els[i]; i++) {
+ var className = el.className;
+ // Check if className has a split function since SVG className does not.
+ if (typeof className.split == 'function' &&
+ goog.array.contains(className.split(/\s+/), opt_class)) {
+ arrayLike[len++] = el;
+ }
+ }
+ arrayLike.length = len;
+ return arrayLike;
+ } else {
+ return els;
+ }
+};
+
+
+/**
+ * Alias for {@code getElementsByTagNameAndClass}.
+ * @param {?string=} opt_tag Element tag name.
+ * @param {?string=} opt_class Optional class name.
+ * @param {Element=} opt_el Optional element to look in.
+ * @return { {length: number} } Array-like list of elements (only a length
+ * property and numerical indices are guaranteed to exist).
+ * @deprecated Use {@link goog.dom.getElementsByTagNameAndClass} instead.
+ */
+goog.dom.$$ = goog.dom.getElementsByTagNameAndClass;
+
+
+/**
+ * Sets multiple properties on a node.
+ * @param {Element} element DOM node to set properties on.
+ * @param {Object} properties Hash of property:value pairs.
+ */
+goog.dom.setProperties = function(element, properties) {
+ goog.object.forEach(properties, function(val, key) {
+ if (key == 'style') {
+ element.style.cssText = val;
+ } else if (key == 'class') {
+ element.className = val;
+ } else if (key == 'for') {
+ element.htmlFor = val;
+ } else if (key in goog.dom.DIRECT_ATTRIBUTE_MAP_) {
+ element.setAttribute(goog.dom.DIRECT_ATTRIBUTE_MAP_[key], val);
+ } else if (goog.string.startsWith(key, 'aria-') ||
+ goog.string.startsWith(key, 'data-')) {
+ element.setAttribute(key, val);
+ } else {
+ element[key] = val;
+ }
+ });
+};
+
+
+/**
+ * Map of attributes that should be set using
+ * element.setAttribute(key, val) instead of element[key] = val. Used
+ * by goog.dom.setProperties.
+ *
+ * @private {!Object<string, string>}
+ * @const
+ */
+goog.dom.DIRECT_ATTRIBUTE_MAP_ = {
+ 'cellpadding': 'cellPadding',
+ 'cellspacing': 'cellSpacing',
+ 'colspan': 'colSpan',
+ 'frameborder': 'frameBorder',
+ 'height': 'height',
+ 'maxlength': 'maxLength',
+ 'role': 'role',
+ 'rowspan': 'rowSpan',
+ 'type': 'type',
+ 'usemap': 'useMap',
+ 'valign': 'vAlign',
+ 'width': 'width'
+};
+
+
+/**
+ * Gets the dimensions of the viewport.
+ *
+ * Gecko Standards mode:
+ * docEl.clientWidth Width of viewport excluding scrollbar.
+ * win.innerWidth Width of viewport including scrollbar.
+ * body.clientWidth Width of body element.
+ *
+ * docEl.clientHeight Height of viewport excluding scrollbar.
+ * win.innerHeight Height of viewport including scrollbar.
+ * body.clientHeight Height of document.
+ *
+ * Gecko Backwards compatible mode:
+ * docEl.clientWidth Width of viewport excluding scrollbar.
+ * win.innerWidth Width of viewport including scrollbar.
+ * body.clientWidth Width of viewport excluding scrollbar.
+ *
+ * docEl.clientHeight Height of document.
+ * win.innerHeight Height of viewport including scrollbar.
+ * body.clientHeight Height of viewport excluding scrollbar.
+ *
+ * IE6/7 Standards mode:
+ * docEl.clientWidth Width of viewport excluding scrollbar.
+ * win.innerWidth Undefined.
+ * body.clientWidth Width of body element.
+ *
+ * docEl.clientHeight Height of viewport excluding scrollbar.
+ * win.innerHeight Undefined.
+ * body.clientHeight Height of document element.
+ *
+ * IE5 + IE6/7 Backwards compatible mode:
+ * docEl.clientWidth 0.
+ * win.innerWidth Undefined.
+ * body.clientWidth Width of viewport excluding scrollbar.
+ *
+ * docEl.clientHeight 0.
+ * win.innerHeight Undefined.
+ * body.clientHeight Height of viewport excluding scrollbar.
+ *
+ * Opera 9 Standards and backwards compatible mode:
+ * docEl.clientWidth Width of viewport excluding scrollbar.
+ * win.innerWidth Width of viewport including scrollbar.
+ * body.clientWidth Width of viewport excluding scrollbar.
+ *
+ * docEl.clientHeight Height of document.
+ * win.innerHeight Height of viewport including scrollbar.
+ * body.clientHeight Height of viewport excluding scrollbar.
+ *
+ * WebKit:
+ * Safari 2
+ * docEl.clientHeight Same as scrollHeight.
+ * docEl.clientWidth Same as innerWidth.
+ * win.innerWidth Width of viewport excluding scrollbar.
+ * win.innerHeight Height of the viewport including scrollbar.
+ * frame.innerHeight Height of the viewport exluding scrollbar.
+ *
+ * Safari 3 (tested in 522)
+ *
+ * docEl.clientWidth Width of viewport excluding scrollbar.
+ * docEl.clientHeight Height of viewport excluding scrollbar in strict mode.
+ * body.clientHeight Height of viewport excluding scrollbar in quirks mode.
+ *
+ * @param {Window=} opt_window Optional window element to test.
+ * @return {!goog.math.Size} Object with values 'width' and 'height'.
+ */
+goog.dom.getViewportSize = function(opt_window) {
+ // TODO(arv): This should not take an argument
+ return goog.dom.getViewportSize_(opt_window || window);
+};
+
+
+/**
+ * Helper for {@code getViewportSize}.
+ * @param {Window} win The window to get the view port size for.
+ * @return {!goog.math.Size} Object with values 'width' and 'height'.
+ * @private
+ */
+goog.dom.getViewportSize_ = function(win) {
+ var doc = win.document;
+ var el = goog.dom.isCss1CompatMode_(doc) ? doc.documentElement : doc.body;
+ return new goog.math.Size(el.clientWidth, el.clientHeight);
+};
+
+
+/**
+ * Calculates the height of the document.
+ *
+ * @return {number} The height of the current document.
+ */
+goog.dom.getDocumentHeight = function() {
+ return goog.dom.getDocumentHeight_(window);
+};
+
+
+/**
+ * Calculates the height of the document of the given window.
+ *
+ * Function code copied from the opensocial gadget api:
+ * gadgets.window.adjustHeight(opt_height)
+ *
+ * @private
+ * @param {!Window} win The window whose document height to retrieve.
+ * @return {number} The height of the document of the given window.
+ */
+goog.dom.getDocumentHeight_ = function(win) {
+ // NOTE(eae): This method will return the window size rather than the document
+ // size in webkit quirks mode.
+ var doc = win.document;
+ var height = 0;
+
+ if (doc) {
+ // Calculating inner content height is hard and different between
+ // browsers rendering in Strict vs. Quirks mode. We use a combination of
+ // three properties within document.body and document.documentElement:
+ // - scrollHeight
+ // - offsetHeight
+ // - clientHeight
+ // These values differ significantly between browsers and rendering modes.
+ // But there are patterns. It just takes a lot of time and persistence
+ // to figure out.
+
+ var body = doc.body;
+ var docEl = doc.documentElement;
+ if (!(docEl && body)) {
+ return 0;
+ }
+
+ // Get the height of the viewport
+ var vh = goog.dom.getViewportSize_(win).height;
+ if (goog.dom.isCss1CompatMode_(doc) && docEl.scrollHeight) {
+ // In Strict mode:
+ // The inner content height is contained in either:
+ // document.documentElement.scrollHeight
+ // document.documentElement.offsetHeight
+ // Based on studying the values output by different browsers,
+ // use the value that's NOT equal to the viewport height found above.
+ height = docEl.scrollHeight != vh ?
+ docEl.scrollHeight : docEl.offsetHeight;
+ } else {
+ // In Quirks mode:
+ // documentElement.clientHeight is equal to documentElement.offsetHeight
+ // except in IE. In most browsers, document.documentElement can be used
+ // to calculate the inner content height.
+ // However, in other browsers (e.g. IE), document.body must be used
+ // instead. How do we know which one to use?
+ // If document.documentElement.clientHeight does NOT equal
+ // document.documentElement.offsetHeight, then use document.body.
+ var sh = docEl.scrollHeight;
+ var oh = docEl.offsetHeight;
+ if (docEl.clientHeight != oh) {
+ sh = body.scrollHeight;
+ oh = body.offsetHeight;
+ }
+
+ // Detect whether the inner content height is bigger or smaller
+ // than the bounding box (viewport). If bigger, take the larger
+ // value. If smaller, take the smaller value.
+ if (sh > vh) {
+ // Content is larger
+ height = sh > oh ? sh : oh;
+ } else {
+ // Content is smaller
+ height = sh < oh ? sh : oh;
+ }
+ }
+ }
+
+ return height;
+};
+
+
+/**
+ * Gets the page scroll distance as a coordinate object.
+ *
+ * @param {Window=} opt_window Optional window element to test.
+ * @return {!goog.math.Coordinate} Object with values 'x' and 'y'.
+ * @deprecated Use {@link goog.dom.getDocumentScroll} instead.
+ */
+goog.dom.getPageScroll = function(opt_window) {
+ var win = opt_window || goog.global || window;
+ return goog.dom.getDomHelper(win.document).getDocumentScroll();
+};
+
+
+/**
+ * Gets the document scroll distance as a coordinate object.
+ *
+ * @return {!goog.math.Coordinate} Object with values 'x' and 'y'.
+ */
+goog.dom.getDocumentScroll = function() {
+ return goog.dom.getDocumentScroll_(document);
+};
+
+
+/**
+ * Helper for {@code getDocumentScroll}.
+ *
+ * @param {!Document} doc The document to get the scroll for.
+ * @return {!goog.math.Coordinate} Object with values 'x' and 'y'.
+ * @private
+ */
+goog.dom.getDocumentScroll_ = function(doc) {
+ var el = goog.dom.getDocumentScrollElement_(doc);
+ var win = goog.dom.getWindow_(doc);
+ if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('10') &&
+ win.pageYOffset != el.scrollTop) {
+ // The keyboard on IE10 touch devices shifts the page using the pageYOffset
+ // without modifying scrollTop. For this case, we want the body scroll
+ // offsets.
+ return new goog.math.Coordinate(el.scrollLeft, el.scrollTop);
+ }
+ return new goog.math.Coordinate(win.pageXOffset || el.scrollLeft,
+ win.pageYOffset || el.scrollTop);
+};
+
+
+/**
+ * Gets the document scroll element.
+ * @return {!Element} Scrolling element.
+ */
+goog.dom.getDocumentScrollElement = function() {
+ return goog.dom.getDocumentScrollElement_(document);
+};
+
+
+/**
+ * Helper for {@code getDocumentScrollElement}.
+ * @param {!Document} doc The document to get the scroll element for.
+ * @return {!Element} Scrolling element.
+ * @private
+ */
+goog.dom.getDocumentScrollElement_ = function(doc) {
+ // WebKit needs body.scrollLeft in both quirks mode and strict mode. We also
+ // default to the documentElement if the document does not have a body (e.g.
+ // a SVG document).
+ if (!goog.userAgent.WEBKIT && goog.dom.isCss1CompatMode_(doc)) {
+ return doc.documentElement;
+ }
+ return doc.body || doc.documentElement;
+};
+
+
+/**
+ * Gets the window object associated with the given document.
+ *
+ * @param {Document=} opt_doc Document object to get window for.
+ * @return {!Window} The window associated with the given document.
+ */
+goog.dom.getWindow = function(opt_doc) {
+ // TODO(arv): This should not take an argument.
+ return opt_doc ? goog.dom.getWindow_(opt_doc) : window;
+};
+
+
+/**
+ * Helper for {@code getWindow}.
+ *
+ * @param {!Document} doc Document object to get window for.
+ * @return {!Window} The window associated with the given document.
+ * @private
+ */
+goog.dom.getWindow_ = function(doc) {
+ return doc.parentWindow || doc.defaultView;
+};
+
+
+/**
+ * Returns a dom node with a set of attributes. This function accepts varargs
+ * for subsequent nodes to be added. Subsequent nodes will be added to the
+ * first node as childNodes.
+ *
+ * So:
+ * <code>createDom('div', null, createDom('p'), createDom('p'));</code>
+ * would return a div with two child paragraphs
+ *
+ * @param {string} tagName Tag to create.
+ * @param {(Object|Array<string>|string)=} opt_attributes If object, then a map
+ * of name-value pairs for attributes. If a string, then this is the
+ * className of the new element. If an array, the elements will be joined
+ * together as the className of the new element.
+ * @param {...(Object|string|Array|NodeList)} var_args Further DOM nodes or
+ * strings for text nodes. If one of the var_args is an array or NodeList,i
+ * its elements will be added as childNodes instead.
+ * @return {!Element} Reference to a DOM node.
+ */
+goog.dom.createDom = function(tagName, opt_attributes, var_args) {
+ return goog.dom.createDom_(document, arguments);
+};
+
+
+/**
+ * Helper for {@code createDom}.
+ * @param {!Document} doc The document to create the DOM in.
+ * @param {!Arguments} args Argument object passed from the callers. See
+ * {@code goog.dom.createDom} for details.
+ * @return {!Element} Reference to a DOM node.
+ * @private
+ */
+goog.dom.createDom_ = function(doc, args) {
+ var tagName = args[0];
+ var attributes = args[1];
+
+ // Internet Explorer is dumb: http://msdn.microsoft.com/workshop/author/
+ // dhtml/reference/properties/name_2.asp
+ // Also does not allow setting of 'type' attribute on 'input' or 'button'.
+ if (!goog.dom.BrowserFeature.CAN_ADD_NAME_OR_TYPE_ATTRIBUTES && attributes &&
+ (attributes.name || attributes.type)) {
+ var tagNameArr = ['<', tagName];
+ if (attributes.name) {
+ tagNameArr.push(' name="', goog.string.htmlEscape(attributes.name),
+ '"');
+ }
+ if (attributes.type) {
+ tagNameArr.push(' type="', goog.string.htmlEscape(attributes.type),
+ '"');
+
+ // Clone attributes map to remove 'type' without mutating the input.
+ var clone = {};
+ goog.object.extend(clone, attributes);
+
+ // JSCompiler can't see how goog.object.extend added this property,
+ // because it was essentially added by reflection.
+ // So it needs to be quoted.
+ delete clone['type'];
+
+ attributes = clone;
+ }
+ tagNameArr.push('>');
+ tagName = tagNameArr.join('');
+ }
+
+ var element = doc.createElement(tagName);
+
+ if (attributes) {
+ if (goog.isString(attributes)) {
+ element.className = attributes;
+ } else if (goog.isArray(attributes)) {
+ element.className = attributes.join(' ');
+ } else {
+ goog.dom.setProperties(element, attributes);
+ }
+ }
+
+ if (args.length > 2) {
+ goog.dom.append_(doc, element, args, 2);
+ }
+
+ return element;
+};
+
+
+/**
+ * Appends a node with text or other nodes.
+ * @param {!Document} doc The document to create new nodes in.
+ * @param {!Node} parent The node to append nodes to.
+ * @param {!Arguments} args The values to add. See {@code goog.dom.append}.
+ * @param {number} startIndex The index of the array to start from.
+ * @private
+ */
+goog.dom.append_ = function(doc, parent, args, startIndex) {
+ function childHandler(child) {
+ // TODO(user): More coercion, ala MochiKit?
+ if (child) {
+ parent.appendChild(goog.isString(child) ?
+ doc.createTextNode(child) : child);
+ }
+ }
+
+ for (var i = startIndex; i < args.length; i++) {
+ var arg = args[i];
+ // TODO(attila): Fix isArrayLike to return false for a text node.
+ if (goog.isArrayLike(arg) && !goog.dom.isNodeLike(arg)) {
+ // If the argument is a node list, not a real array, use a clone,
+ // because forEach can't be used to mutate a NodeList.
+ goog.array.forEach(goog.dom.isNodeList(arg) ?
+ goog.array.toArray(arg) : arg,
+ childHandler);
+ } else {
+ childHandler(arg);
+ }
+ }
+};
+
+
+/**
+ * Alias for {@code createDom}.
+ * @param {string} tagName Tag to create.
+ * @param {(string|Object)=} opt_attributes If object, then a map of name-value
+ * pairs for attributes. If a string, then this is the className of the new
+ * element.
+ * @param {...(Object|string|Array|NodeList)} var_args Further DOM nodes or
+ * strings for text nodes. If one of the var_args is an array, its
+ * children will be added as childNodes instead.
+ * @return {!Element} Reference to a DOM node.
+ * @deprecated Use {@link goog.dom.createDom} instead.
+ */
+goog.dom.$dom = goog.dom.createDom;
+
+
+/**
+ * Creates a new element.
+ * @param {string} name Tag name.
+ * @return {!Element} The new element.
+ */
+goog.dom.createElement = function(name) {
+ return document.createElement(name);
+};
+
+
+/**
+ * Creates a new text node.
+ * @param {number|string} content Content.
+ * @return {!Text} The new text node.
+ */
+goog.dom.createTextNode = function(content) {
+ return document.createTextNode(String(content));
+};
+
+
+/**
+ * Create a table.
+ * @param {number} rows The number of rows in the table. Must be >= 1.
+ * @param {number} columns The number of columns in the table. Must be >= 1.
+ * @param {boolean=} opt_fillWithNbsp If true, fills table entries with
+ * {@code goog.string.Unicode.NBSP} characters.
+ * @return {!Element} The created table.
+ */
+goog.dom.createTable = function(rows, columns, opt_fillWithNbsp) {
+ // TODO(user): Return HTMLTableElement, also in prototype function.
+ // Callers need to be updated to e.g. not assign numbers to table.cellSpacing.
+ return goog.dom.createTable_(document, rows, columns, !!opt_fillWithNbsp);
+};
+
+
+/**
+ * Create a table.
+ * @param {!Document} doc Document object to use to create the table.
+ * @param {number} rows The number of rows in the table. Must be >= 1.
+ * @param {number} columns The number of columns in the table. Must be >= 1.
+ * @param {boolean} fillWithNbsp If true, fills table entries with
+ * {@code goog.string.Unicode.NBSP} characters.
+ * @return {!HTMLTableElement} The created table.
+ * @private
+ */
+goog.dom.createTable_ = function(doc, rows, columns, fillWithNbsp) {
+ var table = /** @type {!HTMLTableElement} */
+ (doc.createElement(goog.dom.TagName.TABLE));
+ var tbody = table.appendChild(doc.createElement(goog.dom.TagName.TBODY));
+ for (var i = 0; i < rows; i++) {
+ var tr = doc.createElement(goog.dom.TagName.TR);
+ for (var j = 0; j < columns; j++) {
+ var td = doc.createElement(goog.dom.TagName.TD);
+ // IE <= 9 will create a text node if we set text content to the empty
+ // string, so we avoid doing it unless necessary. This ensures that the
+ // same DOM tree is returned on all browsers.
+ if (fillWithNbsp) {
+ goog.dom.setTextContent(td, goog.string.Unicode.NBSP);
+ }
+ tr.appendChild(td);
+ }
+ tbody.appendChild(tr);
+ }
+ return table;
+};
+
+
+/**
+ * Converts HTML markup into a node.
+ * @param {!goog.html.SafeHtml} html The HTML markup to convert.
+ * @return {!Node} The resulting node.
+ */
+goog.dom.safeHtmlToNode = function(html) {
+ return goog.dom.safeHtmlToNode_(document, html);
+};
+
+
+/**
+ * Helper for {@code safeHtmlToNode}.
+ * @param {!Document} doc The document.
+ * @param {!goog.html.SafeHtml} html The HTML markup to convert.
+ * @return {!Node} The resulting node.
+ * @private
+ */
+goog.dom.safeHtmlToNode_ = function(doc, html) {
+ var tempDiv = doc.createElement(goog.dom.TagName.DIV);
+ if (goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) {
+ goog.dom.safe.setInnerHtml(tempDiv,
+ goog.html.SafeHtml.concat(goog.html.SafeHtml.create('br'), html));
+ tempDiv.removeChild(tempDiv.firstChild);
+ } else {
+ goog.dom.safe.setInnerHtml(tempDiv, html);
+ }
+ return goog.dom.childrenToNode_(doc, tempDiv);
+};
+
+
+/**
+ * Converts an HTML string into a document fragment. The string must be
+ * sanitized in order to avoid cross-site scripting. For example
+ * {@code goog.dom.htmlToDocumentFragment('<img src=x onerror=alert(0)>')}
+ * triggers an alert in all browsers, even if the returned document fragment
+ * is thrown away immediately.
+ *
+ * @param {string} htmlString The HTML string to convert.
+ * @return {!Node} The resulting document fragment.
+ */
+goog.dom.htmlToDocumentFragment = function(htmlString) {
+ return goog.dom.htmlToDocumentFragment_(document, htmlString);
+};
+
+
+// TODO(jakubvrana): Merge with {@code safeHtmlToNode_}.
+/**
+ * Helper for {@code htmlToDocumentFragment}.
+ *
+ * @param {!Document} doc The document.
+ * @param {string} htmlString The HTML string to convert.
+ * @return {!Node} The resulting document fragment.
+ * @private
+ */
+goog.dom.htmlToDocumentFragment_ = function(doc, htmlString) {
+ var tempDiv = doc.createElement(goog.dom.TagName.DIV);
+ if (goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) {
+ tempDiv.innerHTML = '<br>' + htmlString;
+ tempDiv.removeChild(tempDiv.firstChild);
+ } else {
+ tempDiv.innerHTML = htmlString;
+ }
+ return goog.dom.childrenToNode_(doc, tempDiv);
+};
+
+
+/**
+ * Helper for {@code htmlToDocumentFragment_}.
+ * @param {!Document} doc The document.
+ * @param {!Node} tempDiv The input node.
+ * @return {!Node} The resulting node.
+ * @private
+ */
+goog.dom.childrenToNode_ = function(doc, tempDiv) {
+ if (tempDiv.childNodes.length == 1) {
+ return tempDiv.removeChild(tempDiv.firstChild);
+ } else {
+ var fragment = doc.createDocumentFragment();
+ while (tempDiv.firstChild) {
+ fragment.appendChild(tempDiv.firstChild);
+ }
+ return fragment;
+ }
+};
+
+
+/**
+ * Returns true if the browser is in "CSS1-compatible" (standards-compliant)
+ * mode, false otherwise.
+ * @return {boolean} True if in CSS1-compatible mode.
+ */
+goog.dom.isCss1CompatMode = function() {
+ return goog.dom.isCss1CompatMode_(document);
+};
+
+
+/**
+ * Returns true if the browser is in "CSS1-compatible" (standards-compliant)
+ * mode, false otherwise.
+ * @param {!Document} doc The document to check.
+ * @return {boolean} True if in CSS1-compatible mode.
+ * @private
+ */
+goog.dom.isCss1CompatMode_ = function(doc) {
+ if (goog.dom.COMPAT_MODE_KNOWN_) {
+ return goog.dom.ASSUME_STANDARDS_MODE;
+ }
+
+ return doc.compatMode == 'CSS1Compat';
+};
+
+
+/**
+ * Determines if the given node can contain children, intended to be used for
+ * HTML generation.
+ *
+ * IE natively supports node.canHaveChildren but has inconsistent behavior.
+ * Prior to IE8 the base tag allows children and in IE9 all nodes return true
+ * for canHaveChildren.
+ *
+ * In practice all non-IE browsers allow you to add children to any node, but
+ * the behavior is inconsistent:
+ *
+ * <pre>
+ * var a = document.createElement(goog.dom.TagName.BR);
+ * a.appendChild(document.createTextNode('foo'));
+ * a.appendChild(document.createTextNode('bar'));
+ * console.log(a.childNodes.length); // 2
+ * console.log(a.innerHTML); // Chrome: "", IE9: "foobar", FF3.5: "foobar"
+ * </pre>
+ *
+ * For more information, see:
+ * http://dev.w3.org/html5/markup/syntax.html#syntax-elements
+ *
+ * TODO(user): Rename shouldAllowChildren() ?
+ *
+ * @param {Node} node The node to check.
+ * @return {boolean} Whether the node can contain children.
+ */
+goog.dom.canHaveChildren = function(node) {
+ if (node.nodeType != goog.dom.NodeType.ELEMENT) {
+ return false;
+ }
+ switch (node.tagName) {
+ case goog.dom.TagName.APPLET:
+ case goog.dom.TagName.AREA:
+ case goog.dom.TagName.BASE:
+ case goog.dom.TagName.BR:
+ case goog.dom.TagName.COL:
+ case goog.dom.TagName.COMMAND:
+ case goog.dom.TagName.EMBED:
+ case goog.dom.TagName.FRAME:
+ case goog.dom.TagName.HR:
+ case goog.dom.TagName.IMG:
+ case goog.dom.TagName.INPUT:
+ case goog.dom.TagName.IFRAME:
+ case goog.dom.TagName.ISINDEX:
+ case goog.dom.TagName.KEYGEN:
+ case goog.dom.TagName.LINK:
+ case goog.dom.TagName.NOFRAMES:
+ case goog.dom.TagName.NOSCRIPT:
+ case goog.dom.TagName.META:
+ case goog.dom.TagName.OBJECT:
+ case goog.dom.TagName.PARAM:
+ case goog.dom.TagName.SCRIPT:
+ case goog.dom.TagName.SOURCE:
+ case goog.dom.TagName.STYLE:
+ case goog.dom.TagName.TRACK:
+ case goog.dom.TagName.WBR:
+ return false;
+ }
+ return true;
+};
+
+
+/**
+ * Appends a child to a node.
+ * @param {Node} parent Parent.
+ * @param {Node} child Child.
+ */
+goog.dom.appendChild = function(parent, child) {
+ parent.appendChild(child);
+};
+
+
+/**
+ * Appends a node with text or other nodes.
+ * @param {!Node} parent The node to append nodes to.
+ * @param {...goog.dom.Appendable} var_args The things to append to the node.
+ * If this is a Node it is appended as is.
+ * If this is a string then a text node is appended.
+ * If this is an array like object then fields 0 to length - 1 are appended.
+ */
+goog.dom.append = function(parent, var_args) {
+ goog.dom.append_(goog.dom.getOwnerDocument(parent), parent, arguments, 1);
+};
+
+
+/**
+ * Removes all the child nodes on a DOM node.
+ * @param {Node} node Node to remove children from.
+ */
+goog.dom.removeChildren = function(node) {
+ // Note: Iterations over live collections can be slow, this is the fastest
+ // we could find. The double parenthesis are used to prevent JsCompiler and
+ // strict warnings.
+ var child;
+ while ((child = node.firstChild)) {
+ node.removeChild(child);
+ }
+};
+
+
+/**
+ * Inserts a new node before an existing reference node (i.e. as the previous
+ * sibling). If the reference node has no parent, then does nothing.
+ * @param {Node} newNode Node to insert.
+ * @param {Node} refNode Reference node to insert before.
+ */
+goog.dom.insertSiblingBefore = function(newNode, refNode) {
+ if (refNode.parentNode) {
+ refNode.parentNode.insertBefore(newNode, refNode);
+ }
+};
+
+
+/**
+ * Inserts a new node after an existing reference node (i.e. as the next
+ * sibling). If the reference node has no parent, then does nothing.
+ * @param {Node} newNode Node to insert.
+ * @param {Node} refNode Reference node to insert after.
+ */
+goog.dom.insertSiblingAfter = function(newNode, refNode) {
+ if (refNode.parentNode) {
+ refNode.parentNode.insertBefore(newNode, refNode.nextSibling);
+ }
+};
+
+
+/**
+ * Insert a child at a given index. If index is larger than the number of child
+ * nodes that the parent currently has, the node is inserted as the last child
+ * node.
+ * @param {Element} parent The element into which to insert the child.
+ * @param {Node} child The element to insert.
+ * @param {number} index The index at which to insert the new child node. Must
+ * not be negative.
+ */
+goog.dom.insertChildAt = function(parent, child, index) {
+ // Note that if the second argument is null, insertBefore
+ // will append the child at the end of the list of children.
+ parent.insertBefore(child, parent.childNodes[index] || null);
+};
+
+
+/**
+ * Removes a node from its parent.
+ * @param {Node} node The node to remove.
+ * @return {Node} The node removed if removed; else, null.
+ */
+goog.dom.removeNode = function(node) {
+ return node && node.parentNode ? node.parentNode.removeChild(node) : null;
+};
+
+
+/**
+ * Replaces a node in the DOM tree. Will do nothing if {@code oldNode} has no
+ * parent.
+ * @param {Node} newNode Node to insert.
+ * @param {Node} oldNode Node to replace.
+ */
+goog.dom.replaceNode = function(newNode, oldNode) {
+ var parent = oldNode.parentNode;
+ if (parent) {
+ parent.replaceChild(newNode, oldNode);
+ }
+};
+
+
+/**
+ * Flattens an element. That is, removes it and replace it with its children.
+ * Does nothing if the element is not in the document.
+ * @param {Element} element The element to flatten.
+ * @return {Element|undefined} The original element, detached from the document
+ * tree, sans children; or undefined, if the element was not in the document
+ * to begin with.
+ */
+goog.dom.flattenElement = function(element) {
+ var child, parent = element.parentNode;
+ if (parent && parent.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) {
+ // Use IE DOM method (supported by Opera too) if available
+ if (element.removeNode) {
+ return /** @type {Element} */ (element.removeNode(false));
+ } else {
+ // Move all children of the original node up one level.
+ while ((child = element.firstChild)) {
+ parent.insertBefore(child, element);
+ }
+
+ // Detach the original element.
+ return /** @type {Element} */ (goog.dom.removeNode(element));
+ }
+ }
+};
+
+
+/**
+ * Returns an array containing just the element children of the given element.
+ * @param {Element} element The element whose element children we want.
+ * @return {!(Array|NodeList)} An array or array-like list of just the element
+ * children of the given element.
+ */
+goog.dom.getChildren = function(element) {
+ // We check if the children attribute is supported for child elements
+ // since IE8 misuses the attribute by also including comments.
+ if (goog.dom.BrowserFeature.CAN_USE_CHILDREN_ATTRIBUTE &&
+ element.children != undefined) {
+ return element.children;
+ }
+ // Fall back to manually filtering the element's child nodes.
+ return goog.array.filter(element.childNodes, function(node) {
+ return node.nodeType == goog.dom.NodeType.ELEMENT;
+ });
+};
+
+
+/**
+ * Returns the first child node that is an element.
+ * @param {Node} node The node to get the first child element of.
+ * @return {Element} The first child node of {@code node} that is an element.
+ */
+goog.dom.getFirstElementChild = function(node) {
+ if (node.firstElementChild != undefined) {
+ return /** @type {!Element} */(node).firstElementChild;
+ }
+ return goog.dom.getNextElementNode_(node.firstChild, true);
+};
+
+
+/**
+ * Returns the last child node that is an element.
+ * @param {Node} node The node to get the last child element of.
+ * @return {Element} The last child node of {@code node} that is an element.
+ */
+goog.dom.getLastElementChild = function(node) {
+ if (node.lastElementChild != undefined) {
+ return /** @type {!Element} */(node).lastElementChild;
+ }
+ return goog.dom.getNextElementNode_(node.lastChild, false);
+};
+
+
+/**
+ * Returns the first next sibling that is an element.
+ * @param {Node} node The node to get the next sibling element of.
+ * @return {Element} The next sibling of {@code node} that is an element.
+ */
+goog.dom.getNextElementSibling = function(node) {
+ if (node.nextElementSibling != undefined) {
+ return /** @type {!Element} */(node).nextElementSibling;
+ }
+ return goog.dom.getNextElementNode_(node.nextSibling, true);
+};
+
+
+/**
+ * Returns the first previous sibling that is an element.
+ * @param {Node} node The node to get the previous sibling element of.
+ * @return {Element} The first previous sibling of {@code node} that is
+ * an element.
+ */
+goog.dom.getPreviousElementSibling = function(node) {
+ if (node.previousElementSibling != undefined) {
+ return /** @type {!Element} */(node).previousElementSibling;
+ }
+ return goog.dom.getNextElementNode_(node.previousSibling, false);
+};
+
+
+/**
+ * Returns the first node that is an element in the specified direction,
+ * starting with {@code node}.
+ * @param {Node} node The node to get the next element from.
+ * @param {boolean} forward Whether to look forwards or backwards.
+ * @return {Element} The first element.
+ * @private
+ */
+goog.dom.getNextElementNode_ = function(node, forward) {
+ while (node && node.nodeType != goog.dom.NodeType.ELEMENT) {
+ node = forward ? node.nextSibling : node.previousSibling;
+ }
+
+ return /** @type {Element} */ (node);
+};
+
+
+/**
+ * Returns the next node in source order from the given node.
+ * @param {Node} node The node.
+ * @return {Node} The next node in the DOM tree, or null if this was the last
+ * node.
+ */
+goog.dom.getNextNode = function(node) {
+ if (!node) {
+ return null;
+ }
+
+ if (node.firstChild) {
+ return node.firstChild;
+ }
+
+ while (node && !node.nextSibling) {
+ node = node.parentNode;
+ }
+
+ return node ? node.nextSibling : null;
+};
+
+
+/**
+ * Returns the previous node in source order from the given node.
+ * @param {Node} node The node.
+ * @return {Node} The previous node in the DOM tree, or null if this was the
+ * first node.
+ */
+goog.dom.getPreviousNode = function(node) {
+ if (!node) {
+ return null;
+ }
+
+ if (!node.previousSibling) {
+ return node.parentNode;
+ }
+
+ node = node.previousSibling;
+ while (node && node.lastChild) {
+ node = node.lastChild;
+ }
+
+ return node;
+};
+
+
+/**
+ * Whether the object looks like a DOM node.
+ * @param {?} obj The object being tested for node likeness.
+ * @return {boolean} Whether the object looks like a DOM node.
+ */
+goog.dom.isNodeLike = function(obj) {
+ return goog.isObject(obj) && obj.nodeType > 0;
+};
+
+
+/**
+ * Whether the object looks like an Element.
+ * @param {?} obj The object being tested for Element likeness.
+ * @return {boolean} Whether the object looks like an Element.
+ */
+goog.dom.isElement = function(obj) {
+ return goog.isObject(obj) && obj.nodeType == goog.dom.NodeType.ELEMENT;
+};
+
+
+/**
+ * Returns true if the specified value is a Window object. This includes the
+ * global window for HTML pages, and iframe windows.
+ * @param {?} obj Variable to test.
+ * @return {boolean} Whether the variable is a window.
+ */
+goog.dom.isWindow = function(obj) {
+ return goog.isObject(obj) && obj['window'] == obj;
+};
+
+
+/**
+ * Returns an element's parent, if it's an Element.
+ * @param {Element} element The DOM element.
+ * @return {Element} The parent, or null if not an Element.
+ */
+goog.dom.getParentElement = function(element) {
+ var parent;
+ if (goog.dom.BrowserFeature.CAN_USE_PARENT_ELEMENT_PROPERTY) {
+ var isIe9 = goog.userAgent.IE &&
+ goog.userAgent.isVersionOrHigher('9') &&
+ !goog.userAgent.isVersionOrHigher('10');
+ // SVG elements in IE9 can't use the parentElement property.
+ // goog.global['SVGElement'] is not defined in IE9 quirks mode.
+ if (!(isIe9 && goog.global['SVGElement'] &&
+ element instanceof goog.global['SVGElement'])) {
+ parent = element.parentElement;
+ if (parent) {
+ return parent;
+ }
+ }
+ }
+ parent = element.parentNode;
+ return goog.dom.isElement(parent) ? /** @type {!Element} */ (parent) : null;
+};
+
+
+/**
+ * Whether a node contains another node.
+ * @param {Node} parent The node that should contain the other node.
+ * @param {Node} descendant The node to test presence of.
+ * @return {boolean} Whether the parent node contains the descendent node.
+ */
+goog.dom.contains = function(parent, descendant) {
+ // We use browser specific methods for this if available since it is faster
+ // that way.
+
+ // IE DOM
+ if (parent.contains && descendant.nodeType == goog.dom.NodeType.ELEMENT) {
+ return parent == descendant || parent.contains(descendant);
+ }
+
+ // W3C DOM Level 3
+ if (typeof parent.compareDocumentPosition != 'undefined') {
+ return parent == descendant ||
+ Boolean(parent.compareDocumentPosition(descendant) & 16);
+ }
+
+ // W3C DOM Level 1
+ while (descendant && parent != descendant) {
+ descendant = descendant.parentNode;
+ }
+ return descendant == parent;
+};
+
+
+/**
+ * Compares the document order of two nodes, returning 0 if they are the same
+ * node, a negative number if node1 is before node2, and a positive number if
+ * node2 is before node1. Note that we compare the order the tags appear in the
+ * document so in the tree <b><i>text</i></b> the B node is considered to be
+ * before the I node.
+ *
+ * @param {Node} node1 The first node to compare.
+ * @param {Node} node2 The second node to compare.
+ * @return {number} 0 if the nodes are the same node, a negative number if node1
+ * is before node2, and a positive number if node2 is before node1.
+ */
+goog.dom.compareNodeOrder = function(node1, node2) {
+ // Fall out quickly for equality.
+ if (node1 == node2) {
+ return 0;
+ }
+
+ // Use compareDocumentPosition where available
+ if (node1.compareDocumentPosition) {
+ // 4 is the bitmask for FOLLOWS.
+ return node1.compareDocumentPosition(node2) & 2 ? 1 : -1;
+ }
+
+ // Special case for document nodes on IE 7 and 8.
+ if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
+ if (node1.nodeType == goog.dom.NodeType.DOCUMENT) {
+ return -1;
+ }
+ if (node2.nodeType == goog.dom.NodeType.DOCUMENT) {
+ return 1;
+ }
+ }
+
+ // Process in IE using sourceIndex - we check to see if the first node has
+ // a source index or if its parent has one.
+ if ('sourceIndex' in node1 ||
+ (node1.parentNode && 'sourceIndex' in node1.parentNode)) {
+ var isElement1 = node1.nodeType == goog.dom.NodeType.ELEMENT;
+ var isElement2 = node2.nodeType == goog.dom.NodeType.ELEMENT;
+
+ if (isElement1 && isElement2) {
+ return node1.sourceIndex - node2.sourceIndex;
+ } else {
+ var parent1 = node1.parentNode;
+ var parent2 = node2.parentNode;
+
+ if (parent1 == parent2) {
+ return goog.dom.compareSiblingOrder_(node1, node2);
+ }
+
+ if (!isElement1 && goog.dom.contains(parent1, node2)) {
+ return -1 * goog.dom.compareParentsDescendantNodeIe_(node1, node2);
+ }
+
+
+ if (!isElement2 && goog.dom.contains(parent2, node1)) {
+ return goog.dom.compareParentsDescendantNodeIe_(node2, node1);
+ }
+
+ return (isElement1 ? node1.sourceIndex : parent1.sourceIndex) -
+ (isElement2 ? node2.sourceIndex : parent2.sourceIndex);
+ }
+ }
+
+ // For Safari, we compare ranges.
+ var doc = goog.dom.getOwnerDocument(node1);
+
+ var range1, range2;
+ range1 = doc.createRange();
+ range1.selectNode(node1);
+ range1.collapse(true);
+
+ range2 = doc.createRange();
+ range2.selectNode(node2);
+ range2.collapse(true);
+
+ return range1.compareBoundaryPoints(goog.global['Range'].START_TO_END,
+ range2);
+};
+
+
+/**
+ * Utility function to compare the position of two nodes, when
+ * {@code textNode}'s parent is an ancestor of {@code node}. If this entry
+ * condition is not met, this function will attempt to reference a null object.
+ * @param {!Node} textNode The textNode to compare.
+ * @param {Node} node The node to compare.
+ * @return {number} -1 if node is before textNode, +1 otherwise.
+ * @private
+ */
+goog.dom.compareParentsDescendantNodeIe_ = function(textNode, node) {
+ var parent = textNode.parentNode;
+ if (parent == node) {
+ // If textNode is a child of node, then node comes first.
+ return -1;
+ }
+ var sibling = node;
+ while (sibling.parentNode != parent) {
+ sibling = sibling.parentNode;
+ }
+ return goog.dom.compareSiblingOrder_(sibling, textNode);
+};
+
+
+/**
+ * Utility function to compare the position of two nodes known to be non-equal
+ * siblings.
+ * @param {Node} node1 The first node to compare.
+ * @param {!Node} node2 The second node to compare.
+ * @return {number} -1 if node1 is before node2, +1 otherwise.
+ * @private
+ */
+goog.dom.compareSiblingOrder_ = function(node1, node2) {
+ var s = node2;
+ while ((s = s.previousSibling)) {
+ if (s == node1) {
+ // We just found node1 before node2.
+ return -1;
+ }
+ }
+
+ // Since we didn't find it, node1 must be after node2.
+ return 1;
+};
+
+
+/**
+ * Find the deepest common ancestor of the given nodes.
+ * @param {...Node} var_args The nodes to find a common ancestor of.
+ * @return {Node} The common ancestor of the nodes, or null if there is none.
+ * null will only be returned if two or more of the nodes are from different
+ * documents.
+ */
+goog.dom.findCommonAncestor = function(var_args) {
+ var i, count = arguments.length;
+ if (!count) {
+ return null;
+ } else if (count == 1) {
+ return arguments[0];
+ }
+
+ var paths = [];
+ var minLength = Infinity;
+ for (i = 0; i < count; i++) {
+ // Compute the list of ancestors.
+ var ancestors = [];
+ var node = arguments[i];
+ while (node) {
+ ancestors.unshift(node);
+ node = node.parentNode;
+ }
+
+ // Save the list for comparison.
+ paths.push(ancestors);
+ minLength = Math.min(minLength, ancestors.length);
+ }
+ var output = null;
+ for (i = 0; i < minLength; i++) {
+ var first = paths[0][i];
+ for (var j = 1; j < count; j++) {
+ if (first != paths[j][i]) {
+ return output;
+ }
+ }
+ output = first;
+ }
+ return output;
+};
+
+
+/**
+ * Returns the owner document for a node.
+ * @param {Node|Window} node The node to get the document for.
+ * @return {!Document} The document owning the node.
+ */
+goog.dom.getOwnerDocument = function(node) {
+ // TODO(nnaze): Update param signature to be non-nullable.
+ goog.asserts.assert(node, 'Node cannot be null or undefined.');
+ return /** @type {!Document} */ (
+ node.nodeType == goog.dom.NodeType.DOCUMENT ? node :
+ node.ownerDocument || node.document);
+};
+
+
+/**
+ * Cross-browser function for getting the document element of a frame or iframe.
+ * @param {Element} frame Frame element.
+ * @return {!Document} The frame content document.
+ */
+goog.dom.getFrameContentDocument = function(frame) {
+ var doc = frame.contentDocument || frame.contentWindow.document;
+ return doc;
+};
+
+
+/**
+ * Cross-browser function for getting the window of a frame or iframe.
+ * @param {Element} frame Frame element.
+ * @return {Window} The window associated with the given frame.
+ */
+goog.dom.getFrameContentWindow = function(frame) {
+ return frame.contentWindow ||
+ goog.dom.getWindow(goog.dom.getFrameContentDocument(frame));
+};
+
+
+/**
+ * Sets the text content of a node, with cross-browser support.
+ * @param {Node} node The node to change the text content of.
+ * @param {string|number} text The value that should replace the node's content.
+ */
+goog.dom.setTextContent = function(node, text) {
+ goog.asserts.assert(node != null,
+ 'goog.dom.setTextContent expects a non-null value for node');
+
+ if ('textContent' in node) {
+ node.textContent = text;
+ } else if (node.nodeType == goog.dom.NodeType.TEXT) {
+ node.data = text;
+ } else if (node.firstChild &&
+ node.firstChild.nodeType == goog.dom.NodeType.TEXT) {
+ // If the first child is a text node we just change its data and remove the
+ // rest of the children.
+ while (node.lastChild != node.firstChild) {
+ node.removeChild(node.lastChild);
+ }
+ node.firstChild.data = text;
+ } else {
+ goog.dom.removeChildren(node);
+ var doc = goog.dom.getOwnerDocument(node);
+ node.appendChild(doc.createTextNode(String(text)));
+ }
+};
+
+
+/**
+ * Gets the outerHTML of a node, which islike innerHTML, except that it
+ * actually contains the HTML of the node itself.
+ * @param {Element} element The element to get the HTML of.
+ * @return {string} The outerHTML of the given element.
+ */
+goog.dom.getOuterHtml = function(element) {
+ // IE, Opera and WebKit all have outerHTML.
+ if ('outerHTML' in element) {
+ return element.outerHTML;
+ } else {
+ var doc = goog.dom.getOwnerDocument(element);
+ var div = doc.createElement(goog.dom.TagName.DIV);
+ div.appendChild(element.cloneNode(true));
+ return div.innerHTML;
+ }
+};
+
+
+/**
+ * Finds the first descendant node that matches the filter function, using
+ * a depth first search. This function offers the most general purpose way
+ * of finding a matching element. You may also wish to consider
+ * {@code goog.dom.query} which can express many matching criteria using
+ * CSS selector expressions. These expressions often result in a more
+ * compact representation of the desired result.
+ * @see goog.dom.query
+ *
+ * @param {Node} root The root of the tree to search.
+ * @param {function(Node) : boolean} p The filter function.
+ * @return {Node|undefined} The found node or undefined if none is found.
+ */
+goog.dom.findNode = function(root, p) {
+ var rv = [];
+ var found = goog.dom.findNodes_(root, p, rv, true);
+ return found ? rv[0] : undefined;
+};
+
+
+/**
+ * Finds all the descendant nodes that match the filter function, using a
+ * a depth first search. This function offers the most general-purpose way
+ * of finding a set of matching elements. You may also wish to consider
+ * {@code goog.dom.query} which can express many matching criteria using
+ * CSS selector expressions. These expressions often result in a more
+ * compact representation of the desired result.
+
+ * @param {Node} root The root of the tree to search.
+ * @param {function(Node) : boolean} p The filter function.
+ * @return {!Array<!Node>} The found nodes or an empty array if none are found.
+ */
+goog.dom.findNodes = function(root, p) {
+ var rv = [];
+ goog.dom.findNodes_(root, p, rv, false);
+ return rv;
+};
+
+
+/**
+ * Finds the first or all the descendant nodes that match the filter function,
+ * using a depth first search.
+ * @param {Node} root The root of the tree to search.
+ * @param {function(Node) : boolean} p The filter function.
+ * @param {!Array<!Node>} rv The found nodes are added to this array.
+ * @param {boolean} findOne If true we exit after the first found node.
+ * @return {boolean} Whether the search is complete or not. True in case findOne
+ * is true and the node is found. False otherwise.
+ * @private
+ */
+goog.dom.findNodes_ = function(root, p, rv, findOne) {
+ if (root != null) {
+ var child = root.firstChild;
+ while (child) {
+ if (p(child)) {
+ rv.push(child);
+ if (findOne) {
+ return true;
+ }
+ }
+ if (goog.dom.findNodes_(child, p, rv, findOne)) {
+ return true;
+ }
+ child = child.nextSibling;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Map of tags whose content to ignore when calculating text length.
+ * @private {!Object<string, number>}
+ * @const
+ */
+goog.dom.TAGS_TO_IGNORE_ = {
+ 'SCRIPT': 1,
+ 'STYLE': 1,
+ 'HEAD': 1,
+ 'IFRAME': 1,
+ 'OBJECT': 1
+};
+
+
+/**
+ * Map of tags which have predefined values with regard to whitespace.
+ * @private {!Object<string, string>}
+ * @const
+ */
+goog.dom.PREDEFINED_TAG_VALUES_ = {'IMG': ' ', 'BR': '\n'};
+
+
+/**
+ * Returns true if the element has a tab index that allows it to receive
+ * keyboard focus (tabIndex >= 0), false otherwise. Note that some elements
+ * natively support keyboard focus, even if they have no tab index.
+ * @param {!Element} element Element to check.
+ * @return {boolean} Whether the element has a tab index that allows keyboard
+ * focus.
+ * @see http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ */
+goog.dom.isFocusableTabIndex = function(element) {
+ return goog.dom.hasSpecifiedTabIndex_(element) &&
+ goog.dom.isTabIndexFocusable_(element);
+};
+
+
+/**
+ * Enables or disables keyboard focus support on the element via its tab index.
+ * Only elements for which {@link goog.dom.isFocusableTabIndex} returns true
+ * (or elements that natively support keyboard focus, like form elements) can
+ * receive keyboard focus. See http://go/tabindex for more info.
+ * @param {Element} element Element whose tab index is to be changed.
+ * @param {boolean} enable Whether to set or remove a tab index on the element
+ * that supports keyboard focus.
+ */
+goog.dom.setFocusableTabIndex = function(element, enable) {
+ if (enable) {
+ element.tabIndex = 0;
+ } else {
+ // Set tabIndex to -1 first, then remove it. This is a workaround for
+ // Safari (confirmed in version 4 on Windows). When removing the attribute
+ // without setting it to -1 first, the element remains keyboard focusable
+ // despite not having a tabIndex attribute anymore.
+ element.tabIndex = -1;
+ element.removeAttribute('tabIndex'); // Must be camelCase!
+ }
+};
+
+
+/**
+ * Returns true if the element can be focused, i.e. it has a tab index that
+ * allows it to receive keyboard focus (tabIndex >= 0), or it is an element
+ * that natively supports keyboard focus.
+ * @param {!Element} element Element to check.
+ * @return {boolean} Whether the element allows keyboard focus.
+ */
+goog.dom.isFocusable = function(element) {
+ var focusable;
+ // Some elements can have unspecified tab index and still receive focus.
+ if (goog.dom.nativelySupportsFocus_(element)) {
+ // Make sure the element is not disabled ...
+ focusable = !element.disabled &&
+ // ... and if a tab index is specified, it allows focus.
+ (!goog.dom.hasSpecifiedTabIndex_(element) ||
+ goog.dom.isTabIndexFocusable_(element));
+ } else {
+ focusable = goog.dom.isFocusableTabIndex(element);
+ }
+
+ // IE requires elements to be visible in order to focus them.
+ return focusable && goog.userAgent.IE ?
+ goog.dom.hasNonZeroBoundingRect_(element) : focusable;
+};
+
+
+/**
+ * Returns true if the element has a specified tab index.
+ * @param {!Element} element Element to check.
+ * @return {boolean} Whether the element has a specified tab index.
+ * @private
+ */
+goog.dom.hasSpecifiedTabIndex_ = function(element) {
+ // IE returns 0 for an unset tabIndex, so we must use getAttributeNode(),
+ // which returns an object with a 'specified' property if tabIndex is
+ // specified. This works on other browsers, too.
+ var attrNode = element.getAttributeNode('tabindex'); // Must be lowercase!
+ return goog.isDefAndNotNull(attrNode) && attrNode.specified;
+};
+
+
+/**
+ * Returns true if the element's tab index allows the element to be focused.
+ * @param {!Element} element Element to check.
+ * @return {boolean} Whether the element's tab index allows focus.
+ * @private
+ */
+goog.dom.isTabIndexFocusable_ = function(element) {
+ var index = element.tabIndex;
+ // NOTE: IE9 puts tabIndex in 16-bit int, e.g. -2 is 65534.
+ return goog.isNumber(index) && index >= 0 && index < 32768;
+};
+
+
+/**
+ * Returns true if the element is focusable even when tabIndex is not set.
+ * @param {!Element} element Element to check.
+ * @return {boolean} Whether the element natively supports focus.
+ * @private
+ */
+goog.dom.nativelySupportsFocus_ = function(element) {
+ return element.tagName == goog.dom.TagName.A ||
+ element.tagName == goog.dom.TagName.INPUT ||
+ element.tagName == goog.dom.TagName.TEXTAREA ||
+ element.tagName == goog.dom.TagName.SELECT ||
+ element.tagName == goog.dom.TagName.BUTTON;
+};
+
+
+/**
+ * Returns true if the element has a bounding rectangle that would be visible
+ * (i.e. its width and height are greater than zero).
+ * @param {!Element} element Element to check.
+ * @return {boolean} Whether the element has a non-zero bounding rectangle.
+ * @private
+ */
+goog.dom.hasNonZeroBoundingRect_ = function(element) {
+ var rect = goog.isFunction(element['getBoundingClientRect']) ?
+ element.getBoundingClientRect() :
+ {'height': element.offsetHeight, 'width': element.offsetWidth};
+ return goog.isDefAndNotNull(rect) && rect.height > 0 && rect.width > 0;
+};
+
+
+/**
+ * Returns the text content of the current node, without markup and invisible
+ * symbols. New lines are stripped and whitespace is collapsed,
+ * such that each character would be visible.
+ *
+ * In browsers that support it, innerText is used. Other browsers attempt to
+ * simulate it via node traversal. Line breaks are canonicalized in IE.
+ *
+ * @param {Node} node The node from which we are getting content.
+ * @return {string} The text content.
+ */
+goog.dom.getTextContent = function(node) {
+ var textContent;
+ // Note(arv): IE9, Opera, and Safari 3 support innerText but they include
+ // text nodes in script tags. So we revert to use a user agent test here.
+ if (goog.dom.BrowserFeature.CAN_USE_INNER_TEXT && ('innerText' in node)) {
+ textContent = goog.string.canonicalizeNewlines(node.innerText);
+ // Unfortunately .innerText() returns text with ­ symbols
+ // We need to filter it out and then remove duplicate whitespaces
+ } else {
+ var buf = [];
+ goog.dom.getTextContent_(node, buf, true);
+ textContent = buf.join('');
+ }
+
+ // Strip ­ entities. goog.format.insertWordBreaks inserts them in Opera.
+ textContent = textContent.replace(/ \xAD /g, ' ').replace(/\xAD/g, '');
+ // Strip ​ entities. goog.format.insertWordBreaks inserts them in IE8.
+ textContent = textContent.replace(/\u200B/g, '');
+
+ // Skip this replacement on old browsers with working innerText, which
+ // automatically turns into ' ' and / +/ into ' ' when reading
+ // innerText.
+ if (!goog.dom.BrowserFeature.CAN_USE_INNER_TEXT) {
+ textContent = textContent.replace(/ +/g, ' ');
+ }
+ if (textContent != ' ') {
+ textContent = textContent.replace(/^\s*/, '');
+ }
+
+ return textContent;
+};
+
+
+/**
+ * Returns the text content of the current node, without markup.
+ *
+ * Unlike {@code getTextContent} this method does not collapse whitespaces
+ * or normalize lines breaks.
+ *
+ * @param {Node} node The node from which we are getting content.
+ * @return {string} The raw text content.
+ */
+goog.dom.getRawTextContent = function(node) {
+ var buf = [];
+ goog.dom.getTextContent_(node, buf, false);
+
+ return buf.join('');
+};
+
+
+/**
+ * Recursive support function for text content retrieval.
+ *
+ * @param {Node} node The node from which we are getting content.
+ * @param {Array<string>} buf string buffer.
+ * @param {boolean} normalizeWhitespace Whether to normalize whitespace.
+ * @private
+ */
+goog.dom.getTextContent_ = function(node, buf, normalizeWhitespace) {
+ if (node.nodeName in goog.dom.TAGS_TO_IGNORE_) {
+ // ignore certain tags
+ } else if (node.nodeType == goog.dom.NodeType.TEXT) {
+ if (normalizeWhitespace) {
+ buf.push(String(node.nodeValue).replace(/(\r\n|\r|\n)/g, ''));
+ } else {
+ buf.push(node.nodeValue);
+ }
+ } else if (node.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) {
+ buf.push(goog.dom.PREDEFINED_TAG_VALUES_[node.nodeName]);
+ } else {
+ var child = node.firstChild;
+ while (child) {
+ goog.dom.getTextContent_(child, buf, normalizeWhitespace);
+ child = child.nextSibling;
+ }
+ }
+};
+
+
+/**
+ * Returns the text length of the text contained in a node, without markup. This
+ * is equivalent to the selection length if the node was selected, or the number
+ * of cursor movements to traverse the node. Images & BRs take one space. New
+ * lines are ignored.
+ *
+ * @param {Node} node The node whose text content length is being calculated.
+ * @return {number} The length of {@code node}'s text content.
+ */
+goog.dom.getNodeTextLength = function(node) {
+ return goog.dom.getTextContent(node).length;
+};
+
+
+/**
+ * Returns the text offset of a node relative to one of its ancestors. The text
+ * length is the same as the length calculated by goog.dom.getNodeTextLength.
+ *
+ * @param {Node} node The node whose offset is being calculated.
+ * @param {Node=} opt_offsetParent The node relative to which the offset will
+ * be calculated. Defaults to the node's owner document's body.
+ * @return {number} The text offset.
+ */
+goog.dom.getNodeTextOffset = function(node, opt_offsetParent) {
+ var root = opt_offsetParent || goog.dom.getOwnerDocument(node).body;
+ var buf = [];
+ while (node && node != root) {
+ var cur = node;
+ while ((cur = cur.previousSibling)) {
+ buf.unshift(goog.dom.getTextContent(cur));
+ }
+ node = node.parentNode;
+ }
+ // Trim left to deal with FF cases when there might be line breaks and empty
+ // nodes at the front of the text
+ return goog.string.trimLeft(buf.join('')).replace(/ +/g, ' ').length;
+};
+
+
+/**
+ * Returns the node at a given offset in a parent node. If an object is
+ * provided for the optional third parameter, the node and the remainder of the
+ * offset will stored as properties of this object.
+ * @param {Node} parent The parent node.
+ * @param {number} offset The offset into the parent node.
+ * @param {Object=} opt_result Object to be used to store the return value. The
+ * return value will be stored in the form {node: Node, remainder: number}
+ * if this object is provided.
+ * @return {Node} The node at the given offset.
+ */
+goog.dom.getNodeAtOffset = function(parent, offset, opt_result) {
+ var stack = [parent], pos = 0, cur = null;
+ while (stack.length > 0 && pos < offset) {
+ cur = stack.pop();
+ if (cur.nodeName in goog.dom.TAGS_TO_IGNORE_) {
+ // ignore certain tags
+ } else if (cur.nodeType == goog.dom.NodeType.TEXT) {
+ var text = cur.nodeValue.replace(/(\r\n|\r|\n)/g, '').replace(/ +/g, ' ');
+ pos += text.length;
+ } else if (cur.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) {
+ pos += goog.dom.PREDEFINED_TAG_VALUES_[cur.nodeName].length;
+ } else {
+ for (var i = cur.childNodes.length - 1; i >= 0; i--) {
+ stack.push(cur.childNodes[i]);
+ }
+ }
+ }
+ if (goog.isObject(opt_result)) {
+ opt_result.remainder = cur ? cur.nodeValue.length + offset - pos - 1 : 0;
+ opt_result.node = cur;
+ }
+
+ return cur;
+};
+
+
+/**
+ * Returns true if the object is a {@code NodeList}. To qualify as a NodeList,
+ * the object must have a numeric length property and an item function (which
+ * has type 'string' on IE for some reason).
+ * @param {Object} val Object to test.
+ * @return {boolean} Whether the object is a NodeList.
+ */
+goog.dom.isNodeList = function(val) {
+ // TODO(attila): Now the isNodeList is part of goog.dom we can use
+ // goog.userAgent to make this simpler.
+ // A NodeList must have a length property of type 'number' on all platforms.
+ if (val && typeof val.length == 'number') {
+ // A NodeList is an object everywhere except Safari, where it's a function.
+ if (goog.isObject(val)) {
+ // A NodeList must have an item function (on non-IE platforms) or an item
+ // property of type 'string' (on IE).
+ return typeof val.item == 'function' || typeof val.item == 'string';
+ } else if (goog.isFunction(val)) {
+ // On Safari, a NodeList is a function with an item property that is also
+ // a function.
+ return typeof val.item == 'function';
+ }
+ }
+
+ // Not a NodeList.
+ return false;
+};
+
+
+/**
+ * Walks up the DOM hierarchy returning the first ancestor that has the passed
+ * tag name and/or class name. If the passed element matches the specified
+ * criteria, the element itself is returned.
+ * @param {Node} element The DOM node to start with.
+ * @param {?(goog.dom.TagName|string)=} opt_tag The tag name to match (or
+ * null/undefined to match only based on class name).
+ * @param {?string=} opt_class The class name to match (or null/undefined to
+ * match only based on tag name).
+ * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the
+ * dom.
+ * @return {Element} The first ancestor that matches the passed criteria, or
+ * null if no match is found.
+ */
+goog.dom.getAncestorByTagNameAndClass = function(element, opt_tag, opt_class,
+ opt_maxSearchSteps) {
+ if (!opt_tag && !opt_class) {
+ return null;
+ }
+ var tagName = opt_tag ? opt_tag.toUpperCase() : null;
+ return /** @type {Element} */ (goog.dom.getAncestor(element,
+ function(node) {
+ return (!tagName || node.nodeName == tagName) &&
+ (!opt_class || goog.isString(node.className) &&
+ goog.array.contains(node.className.split(/\s+/), opt_class));
+ }, true, opt_maxSearchSteps));
+};
+
+
+/**
+ * Walks up the DOM hierarchy returning the first ancestor that has the passed
+ * class name. If the passed element matches the specified criteria, the
+ * element itself is returned.
+ * @param {Node} element The DOM node to start with.
+ * @param {string} className The class name to match.
+ * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the
+ * dom.
+ * @return {Element} The first ancestor that matches the passed criteria, or
+ * null if none match.
+ */
+goog.dom.getAncestorByClass = function(element, className, opt_maxSearchSteps) {
+ return goog.dom.getAncestorByTagNameAndClass(element, null, className,
+ opt_maxSearchSteps);
+};
+
+
+/**
+ * Walks up the DOM hierarchy returning the first ancestor that passes the
+ * matcher function.
+ * @param {Node} element The DOM node to start with.
+ * @param {function(Node) : boolean} matcher A function that returns true if the
+ * passed node matches the desired criteria.
+ * @param {boolean=} opt_includeNode If true, the node itself is included in
+ * the search (the first call to the matcher will pass startElement as
+ * the node to test).
+ * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the
+ * dom.
+ * @return {Node} DOM node that matched the matcher, or null if there was
+ * no match.
+ */
+goog.dom.getAncestor = function(
+ element, matcher, opt_includeNode, opt_maxSearchSteps) {
+ if (!opt_includeNode) {
+ element = element.parentNode;
+ }
+ var ignoreSearchSteps = opt_maxSearchSteps == null;
+ var steps = 0;
+ while (element && (ignoreSearchSteps || steps <= opt_maxSearchSteps)) {
+ goog.asserts.assert(element.name != 'parentNode');
+ if (matcher(element)) {
+ return element;
+ }
+ element = element.parentNode;
+ steps++;
+ }
+ // Reached the root of the DOM without a match
+ return null;
+};
+
+
+/**
+ * Determines the active element in the given document.
+ * @param {Document} doc The document to look in.
+ * @return {Element} The active element.
+ */
+goog.dom.getActiveElement = function(doc) {
+ try {
+ return doc && doc.activeElement;
+ } catch (e) {
+ // NOTE(nicksantos): Sometimes, evaluating document.activeElement in IE
+ // throws an exception. I'm not 100% sure why, but I suspect it chokes
+ // on document.activeElement if the activeElement has been recently
+ // removed from the DOM by a JS operation.
+ //
+ // We assume that an exception here simply means
+ // "there is no active element."
+ }
+
+ return null;
+};
+
+
+/**
+ * Gives the current devicePixelRatio.
+ *
+ * By default, this is the value of window.devicePixelRatio (which should be
+ * preferred if present).
+ *
+ * If window.devicePixelRatio is not present, the ratio is calculated with
+ * window.matchMedia, if present. Otherwise, gives 1.0.
+ *
+ * Some browsers (including Chrome) consider the browser zoom level in the pixel
+ * ratio, so the value may change across multiple calls.
+ *
+ * @return {number} The number of actual pixels per virtual pixel.
+ */
+goog.dom.getPixelRatio = function() {
+ var win = goog.dom.getWindow();
+
+ // devicePixelRatio does not work on Mobile firefox.
+ // TODO(user): Enable this check on a known working mobile Gecko version.
+ // Filed a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=896804
+ var isFirefoxMobile = goog.userAgent.GECKO && goog.userAgent.MOBILE;
+
+ if (goog.isDef(win.devicePixelRatio) && !isFirefoxMobile) {
+ return win.devicePixelRatio;
+ } else if (win.matchMedia) {
+ return goog.dom.matchesPixelRatio_(.75) ||
+ goog.dom.matchesPixelRatio_(1.5) ||
+ goog.dom.matchesPixelRatio_(2) ||
+ goog.dom.matchesPixelRatio_(3) || 1;
+ }
+ return 1;
+};
+
+
+/**
+ * Calculates a mediaQuery to check if the current device supports the
+ * given actual to virtual pixel ratio.
+ * @param {number} pixelRatio The ratio of actual pixels to virtual pixels.
+ * @return {number} pixelRatio if applicable, otherwise 0.
+ * @private
+ */
+goog.dom.matchesPixelRatio_ = function(pixelRatio) {
+ var win = goog.dom.getWindow();
+ var query = ('(-webkit-min-device-pixel-ratio: ' + pixelRatio + '),' +
+ '(min--moz-device-pixel-ratio: ' + pixelRatio + '),' +
+ '(min-resolution: ' + pixelRatio + 'dppx)');
+ return win.matchMedia(query).matches ? pixelRatio : 0;
+};
+
+
+
+/**
+ * Create an instance of a DOM helper with a new document object.
+ * @param {Document=} opt_document Document object to associate with this
+ * DOM helper.
+ * @constructor
+ */
+goog.dom.DomHelper = function(opt_document) {
+ /**
+ * Reference to the document object to use
+ * @type {!Document}
+ * @private
+ */
+ this.document_ = opt_document || goog.global.document || document;
+};
+
+
+/**
+ * Gets the dom helper object for the document where the element resides.
+ * @param {Node=} opt_node If present, gets the DomHelper for this node.
+ * @return {!goog.dom.DomHelper} The DomHelper.
+ */
+goog.dom.DomHelper.prototype.getDomHelper = goog.dom.getDomHelper;
+
+
+/**
+ * Sets the document object.
+ * @param {!Document} document Document object.
+ */
+goog.dom.DomHelper.prototype.setDocument = function(document) {
+ this.document_ = document;
+};
+
+
+/**
+ * Gets the document object being used by the dom library.
+ * @return {!Document} Document object.
+ */
+goog.dom.DomHelper.prototype.getDocument = function() {
+ return this.document_;
+};
+
+
+/**
+ * Alias for {@code getElementById}. If a DOM node is passed in then we just
+ * return that.
+ * @param {string|Element} element Element ID or a DOM node.
+ * @return {Element} The element with the given ID, or the node passed in.
+ */
+goog.dom.DomHelper.prototype.getElement = function(element) {
+ return goog.dom.getElementHelper_(this.document_, element);
+};
+
+
+/**
+ * Gets an element by id, asserting that the element is found.
+ *
+ * This is used when an element is expected to exist, and should fail with
+ * an assertion error if it does not (if assertions are enabled).
+ *
+ * @param {string} id Element ID.
+ * @return {!Element} The element with the given ID, if it exists.
+ */
+goog.dom.DomHelper.prototype.getRequiredElement = function(id) {
+ return goog.dom.getRequiredElementHelper_(this.document_, id);
+};
+
+
+/**
+ * Alias for {@code getElement}.
+ * @param {string|Element} element Element ID or a DOM node.
+ * @return {Element} The element with the given ID, or the node passed in.
+ * @deprecated Use {@link goog.dom.DomHelper.prototype.getElement} instead.
+ */
+goog.dom.DomHelper.prototype.$ = goog.dom.DomHelper.prototype.getElement;
+
+
+/**
+ * Looks up elements by both tag and class name, using browser native functions
+ * ({@code querySelectorAll}, {@code getElementsByTagName} or
+ * {@code getElementsByClassName}) where possible. The returned array is a live
+ * NodeList or a static list depending on the code path taken.
+ *
+ * @see goog.dom.query
+ *
+ * @param {?string=} opt_tag Element tag name or * for all tags.
+ * @param {?string=} opt_class Optional class name.
+ * @param {(Document|Element)=} opt_el Optional element to look in.
+ * @return { {length: number} } Array-like list of elements (only a length
+ * property and numerical indices are guaranteed to exist).
+ */
+goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function(opt_tag,
+ opt_class,
+ opt_el) {
+ return goog.dom.getElementsByTagNameAndClass_(this.document_, opt_tag,
+ opt_class, opt_el);
+};
+
+
+/**
+ * Returns an array of all the elements with the provided className.
+ * @see {goog.dom.query}
+ * @param {string} className the name of the class to look for.
+ * @param {Element|Document=} opt_el Optional element to look in.
+ * @return { {length: number} } The items found with the class name provided.
+ */
+goog.dom.DomHelper.prototype.getElementsByClass = function(className, opt_el) {
+ var doc = opt_el || this.document_;
+ return goog.dom.getElementsByClass(className, doc);
+};
+
+
+/**
+ * Returns the first element we find matching the provided class name.
+ * @see {goog.dom.query}
+ * @param {string} className the name of the class to look for.
+ * @param {(Element|Document)=} opt_el Optional element to look in.
+ * @return {Element} The first item found with the class name provided.
+ */
+goog.dom.DomHelper.prototype.getElementByClass = function(className, opt_el) {
+ var doc = opt_el || this.document_;
+ return goog.dom.getElementByClass(className, doc);
+};
+
+
+/**
+ * Ensures an element with the given className exists, and then returns the
+ * first element with the provided className.
+ * @see {goog.dom.query}
+ * @param {string} className the name of the class to look for.
+ * @param {(!Element|!Document)=} opt_root Optional element or document to look
+ * in.
+ * @return {!Element} The first item found with the class name provided.
+ * @throws {goog.asserts.AssertionError} Thrown if no element is found.
+ */
+goog.dom.DomHelper.prototype.getRequiredElementByClass = function(className,
+ opt_root) {
+ var root = opt_root || this.document_;
+ return goog.dom.getRequiredElementByClass(className, root);
+};
+
+
+/**
+ * Alias for {@code getElementsByTagNameAndClass}.
+ * @deprecated Use DomHelper getElementsByTagNameAndClass.
+ * @see goog.dom.query
+ *
+ * @param {?string=} opt_tag Element tag name.
+ * @param {?string=} opt_class Optional class name.
+ * @param {Element=} opt_el Optional element to look in.
+ * @return { {length: number} } Array-like list of elements (only a length
+ * property and numerical indices are guaranteed to exist).
+ */
+goog.dom.DomHelper.prototype.$$ =
+ goog.dom.DomHelper.prototype.getElementsByTagNameAndClass;
+
+
+/**
+ * Sets a number of properties on a node.
+ * @param {Element} element DOM node to set properties on.
+ * @param {Object} properties Hash of property:value pairs.
+ */
+goog.dom.DomHelper.prototype.setProperties = goog.dom.setProperties;
+
+
+/**
+ * Gets the dimensions of the viewport.
+ * @param {Window=} opt_window Optional window element to test. Defaults to
+ * the window of the Dom Helper.
+ * @return {!goog.math.Size} Object with values 'width' and 'height'.
+ */
+goog.dom.DomHelper.prototype.getViewportSize = function(opt_window) {
+ // TODO(arv): This should not take an argument. That breaks the rule of a
+ // a DomHelper representing a single frame/window/document.
+ return goog.dom.getViewportSize(opt_window || this.getWindow());
+};
+
+
+/**
+ * Calculates the height of the document.
+ *
+ * @return {number} The height of the document.
+ */
+goog.dom.DomHelper.prototype.getDocumentHeight = function() {
+ return goog.dom.getDocumentHeight_(this.getWindow());
+};
+
+
+/**
+ * Typedef for use with goog.dom.createDom and goog.dom.append.
+ * @typedef {Object|string|Array|NodeList}
+ */
+goog.dom.Appendable;
+
+
+/**
+ * Returns a dom node with a set of attributes. This function accepts varargs
+ * for subsequent nodes to be added. Subsequent nodes will be added to the
+ * first node as childNodes.
+ *
+ * So:
+ * <code>createDom('div', null, createDom('p'), createDom('p'));</code>
+ * would return a div with two child paragraphs
+ *
+ * An easy way to move all child nodes of an existing element to a new parent
+ * element is:
+ * <code>createDom('div', null, oldElement.childNodes);</code>
+ * which will remove all child nodes from the old element and add them as
+ * child nodes of the new DIV.
+ *
+ * @param {string} tagName Tag to create.
+ * @param {Object|string=} opt_attributes If object, then a map of name-value
+ * pairs for attributes. If a string, then this is the className of the new
+ * element.
+ * @param {...goog.dom.Appendable} var_args Further DOM nodes or
+ * strings for text nodes. If one of the var_args is an array or
+ * NodeList, its elements will be added as childNodes instead.
+ * @return {!Element} Reference to a DOM node.
+ */
+goog.dom.DomHelper.prototype.createDom = function(tagName,
+ opt_attributes,
+ var_args) {
+ return goog.dom.createDom_(this.document_, arguments);
+};
+
+
+/**
+ * Alias for {@code createDom}.
+ * @param {string} tagName Tag to create.
+ * @param {(Object|string)=} opt_attributes If object, then a map of name-value
+ * pairs for attributes. If a string, then this is the className of the new
+ * element.
+ * @param {...goog.dom.Appendable} var_args Further DOM nodes or strings for
+ * text nodes. If one of the var_args is an array, its children will be
+ * added as childNodes instead.
+ * @return {!Element} Reference to a DOM node.
+ * @deprecated Use {@link goog.dom.DomHelper.prototype.createDom} instead.
+ */
+goog.dom.DomHelper.prototype.$dom = goog.dom.DomHelper.prototype.createDom;
+
+
+/**
+ * Creates a new element.
+ * @param {string} name Tag name.
+ * @return {!Element} The new element.
+ */
+goog.dom.DomHelper.prototype.createElement = function(name) {
+ return this.document_.createElement(name);
+};
+
+
+/**
+ * Creates a new text node.
+ * @param {number|string} content Content.
+ * @return {!Text} The new text node.
+ */
+goog.dom.DomHelper.prototype.createTextNode = function(content) {
+ return this.document_.createTextNode(String(content));
+};
+
+
+/**
+ * Create a table.
+ * @param {number} rows The number of rows in the table. Must be >= 1.
+ * @param {number} columns The number of columns in the table. Must be >= 1.
+ * @param {boolean=} opt_fillWithNbsp If true, fills table entries with
+ * {@code goog.string.Unicode.NBSP} characters.
+ * @return {!HTMLElement} The created table.
+ */
+goog.dom.DomHelper.prototype.createTable = function(rows, columns,
+ opt_fillWithNbsp) {
+ return goog.dom.createTable_(this.document_, rows, columns,
+ !!opt_fillWithNbsp);
+};
+
+
+/**
+ * Converts an HTML into a node or a document fragment. A single Node is used if
+ * {@code html} only generates a single node. If {@code html} generates multiple
+ * nodes then these are put inside a {@code DocumentFragment}.
+ * @param {!goog.html.SafeHtml} html The HTML markup to convert.
+ * @return {!Node} The resulting node.
+ */
+goog.dom.DomHelper.prototype.safeHtmlToNode = function(html) {
+ return goog.dom.safeHtmlToNode_(this.document_, html);
+};
+
+
+/**
+ * Converts an HTML string into a node or a document fragment. A single Node
+ * is used if the {@code htmlString} only generates a single node. If the
+ * {@code htmlString} generates multiple nodes then these are put inside a
+ * {@code DocumentFragment}.
+ *
+ * @param {string} htmlString The HTML string to convert.
+ * @return {!Node} The resulting node.
+ */
+goog.dom.DomHelper.prototype.htmlToDocumentFragment = function(htmlString) {
+ return goog.dom.htmlToDocumentFragment_(this.document_, htmlString);
+};
+
+
+/**
+ * Returns true if the browser is in "CSS1-compatible" (standards-compliant)
+ * mode, false otherwise.
+ * @return {boolean} True if in CSS1-compatible mode.
+ */
+goog.dom.DomHelper.prototype.isCss1CompatMode = function() {
+ return goog.dom.isCss1CompatMode_(this.document_);
+};
+
+
+/**
+ * Gets the window object associated with the document.
+ * @return {!Window} The window associated with the given document.
+ */
+goog.dom.DomHelper.prototype.getWindow = function() {
+ return goog.dom.getWindow_(this.document_);
+};
+
+
+/**
+ * Gets the document scroll element.
+ * @return {!Element} Scrolling element.
+ */
+goog.dom.DomHelper.prototype.getDocumentScrollElement = function() {
+ return goog.dom.getDocumentScrollElement_(this.document_);
+};
+
+
+/**
+ * Gets the document scroll distance as a coordinate object.
+ * @return {!goog.math.Coordinate} Object with properties 'x' and 'y'.
+ */
+goog.dom.DomHelper.prototype.getDocumentScroll = function() {
+ return goog.dom.getDocumentScroll_(this.document_);
+};
+
+
+/**
+ * Determines the active element in the given document.
+ * @param {Document=} opt_doc The document to look in.
+ * @return {Element} The active element.
+ */
+goog.dom.DomHelper.prototype.getActiveElement = function(opt_doc) {
+ return goog.dom.getActiveElement(opt_doc || this.document_);
+};
+
+
+/**
+ * Appends a child to a node.
+ * @param {Node} parent Parent.
+ * @param {Node} child Child.
+ */
+goog.dom.DomHelper.prototype.appendChild = goog.dom.appendChild;
+
+
+/**
+ * Appends a node with text or other nodes.
+ * @param {!Node} parent The node to append nodes to.
+ * @param {...goog.dom.Appendable} var_args The things to append to the node.
+ * If this is a Node it is appended as is.
+ * If this is a string then a text node is appended.
+ * If this is an array like object then fields 0 to length - 1 are appended.
+ */
+goog.dom.DomHelper.prototype.append = goog.dom.append;
+
+
+/**
+ * Determines if the given node can contain children, intended to be used for
+ * HTML generation.
+ *
+ * @param {Node} node The node to check.
+ * @return {boolean} Whether the node can contain children.
+ */
+goog.dom.DomHelper.prototype.canHaveChildren = goog.dom.canHaveChildren;
+
+
+/**
+ * Removes all the child nodes on a DOM node.
+ * @param {Node} node Node to remove children from.
+ */
+goog.dom.DomHelper.prototype.removeChildren = goog.dom.removeChildren;
+
+
+/**
+ * Inserts a new node before an existing reference node (i.e., as the previous
+ * sibling). If the reference node has no parent, then does nothing.
+ * @param {Node} newNode Node to insert.
+ * @param {Node} refNode Reference node to insert before.
+ */
+goog.dom.DomHelper.prototype.insertSiblingBefore = goog.dom.insertSiblingBefore;
+
+
+/**
+ * Inserts a new node after an existing reference node (i.e., as the next
+ * sibling). If the reference node has no parent, then does nothing.
+ * @param {Node} newNode Node to insert.
+ * @param {Node} refNode Reference node to insert after.
+ */
+goog.dom.DomHelper.prototype.insertSiblingAfter = goog.dom.insertSiblingAfter;
+
+
+/**
+ * Insert a child at a given index. If index is larger than the number of child
+ * nodes that the parent currently has, the node is inserted as the last child
<TRUNCATED>
[23/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/blockquote.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/blockquote.js b/externs/GCL/externs/goog/editor/plugins/blockquote.js
new file mode 100644
index 0000000..5f0387d
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/blockquote.js
@@ -0,0 +1,451 @@
+// 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 goog.editor plugin to handle splitting block quotes.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.Blockquote');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.classlist');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.node');
+goog.require('goog.functions');
+goog.require('goog.log');
+
+
+
+/**
+ * Plugin to handle splitting block quotes. This plugin does nothing on its
+ * own and should be used in conjunction with EnterHandler or one of its
+ * subclasses.
+ * @param {boolean} requiresClassNameToSplit Whether to split only blockquotes
+ * that have the given classname.
+ * @param {string=} opt_className The classname to apply to generated
+ * blockquotes. Defaults to 'tr_bq'.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.Blockquote = function(requiresClassNameToSplit,
+ opt_className) {
+ goog.editor.Plugin.call(this);
+
+ /**
+ * Whether we only split blockquotes that have {@link classname}, or whether
+ * all blockquote tags should be split on enter.
+ * @type {boolean}
+ * @private
+ */
+ this.requiresClassNameToSplit_ = requiresClassNameToSplit;
+
+ /**
+ * Classname to put on blockquotes that are generated via the toolbar for
+ * blockquote, so that we can internally distinguish these from blockquotes
+ * that are used for indentation. This classname can be over-ridden by
+ * clients for styling or other purposes.
+ * @type {string}
+ * @private
+ */
+ this.className_ = opt_className || goog.getCssName('tr_bq');
+};
+goog.inherits(goog.editor.plugins.Blockquote, goog.editor.Plugin);
+
+
+/**
+ * Command implemented by this plugin.
+ * @type {string}
+ */
+goog.editor.plugins.Blockquote.SPLIT_COMMAND = '+splitBlockquote';
+
+
+/**
+ * Class ID used to identify this plugin.
+ * @type {string}
+ */
+goog.editor.plugins.Blockquote.CLASS_ID = 'Blockquote';
+
+
+/**
+ * Logging object.
+ * @type {goog.log.Logger}
+ * @protected
+ * @override
+ */
+goog.editor.plugins.Blockquote.prototype.logger =
+ goog.log.getLogger('goog.editor.plugins.Blockquote');
+
+
+/** @override */
+goog.editor.plugins.Blockquote.prototype.getTrogClassId = function() {
+ return goog.editor.plugins.Blockquote.CLASS_ID;
+};
+
+
+/**
+ * Since our exec command is always called from elsewhere, we make it silent.
+ * @override
+ */
+goog.editor.plugins.Blockquote.prototype.isSilentCommand = goog.functions.TRUE;
+
+
+/**
+ * Checks if a node is a blockquote which can be split. A splittable blockquote
+ * meets the following criteria:
+ * <ol>
+ * <li>Node is a blockquote element</li>
+ * <li>Node has the blockquote classname if the classname is required to
+ * split</li>
+ * </ol>
+ *
+ * @param {Node} node DOM node in question.
+ * @return {boolean} Whether the node is a splittable blockquote.
+ */
+goog.editor.plugins.Blockquote.prototype.isSplittableBlockquote =
+ function(node) {
+ if (node.tagName != goog.dom.TagName.BLOCKQUOTE) {
+ return false;
+ }
+
+ if (!this.requiresClassNameToSplit_) {
+ return true;
+ }
+
+ return goog.dom.classlist.contains(/** @type {!Element} */ (node),
+ this.className_);
+};
+
+
+/**
+ * Checks if a node is a blockquote element which has been setup.
+ * @param {Node} node DOM node to check.
+ * @return {boolean} Whether the node is a blockquote with the required class
+ * name applied.
+ */
+goog.editor.plugins.Blockquote.prototype.isSetupBlockquote =
+ function(node) {
+ return node.tagName == goog.dom.TagName.BLOCKQUOTE &&
+ goog.dom.classlist.contains(/** @type {!Element} */ (node),
+ this.className_);
+};
+
+
+/**
+ * Checks if a node is a blockquote element which has not been setup yet.
+ * @param {Node} node DOM node to check.
+ * @return {boolean} Whether the node is a blockquote without the required
+ * class name applied.
+ */
+goog.editor.plugins.Blockquote.prototype.isUnsetupBlockquote =
+ function(node) {
+ return node.tagName == goog.dom.TagName.BLOCKQUOTE &&
+ !this.isSetupBlockquote(node);
+};
+
+
+/**
+ * Gets the class name required for setup blockquotes.
+ * @return {string} The blockquote class name.
+ */
+goog.editor.plugins.Blockquote.prototype.getBlockquoteClassName = function() {
+ return this.className_;
+};
+
+
+/**
+ * Helper routine which walks up the tree to find the topmost
+ * ancestor with only a single child. The ancestor node or the original
+ * node (if no ancestor was found) is then removed from the DOM.
+ *
+ * @param {Node} node The node whose ancestors have to be searched.
+ * @param {Node} root The root node to stop the search at.
+ * @private
+ */
+goog.editor.plugins.Blockquote.findAndRemoveSingleChildAncestor_ = function(
+ node, root) {
+ var predicateFunc = function(parentNode) {
+ return parentNode != root && parentNode.childNodes.length == 1;
+ };
+ var ancestor = goog.editor.node.findHighestMatchingAncestor(node,
+ predicateFunc);
+ if (!ancestor) {
+ ancestor = node;
+ }
+ goog.dom.removeNode(ancestor);
+};
+
+
+/**
+ * Remove every nodes from the DOM tree that are all white space nodes.
+ * @param {Array<Node>} nodes Nodes to be checked.
+ * @private
+ */
+goog.editor.plugins.Blockquote.removeAllWhiteSpaceNodes_ = function(nodes) {
+ for (var i = 0; i < nodes.length; ++i) {
+ if (goog.editor.node.isEmpty(nodes[i], true)) {
+ goog.dom.removeNode(nodes[i]);
+ }
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.Blockquote.prototype.isSupportedCommand = function(
+ command) {
+ return command == goog.editor.plugins.Blockquote.SPLIT_COMMAND;
+};
+
+
+/**
+ * Splits a quoted region if any. To be called on a key press event. When this
+ * function returns true, the event that caused it to be called should be
+ * canceled.
+ * @param {string} command The command to execute.
+ * @param {...*} var_args Single additional argument representing the current
+ * cursor position. If BrowserFeature.HAS_W3C_RANGES it is an object with a
+ * {@code node} key and an {@code offset} key. In other cases (legacy IE)
+ * it is a single node.
+ * @return {boolean|undefined} Boolean true when the quoted region has been
+ * split, false or undefined otherwise.
+ * @override
+ */
+goog.editor.plugins.Blockquote.prototype.execCommandInternal = function(
+ command, var_args) {
+ var pos = arguments[1];
+ if (command == goog.editor.plugins.Blockquote.SPLIT_COMMAND && pos &&
+ (this.className_ || !this.requiresClassNameToSplit_)) {
+ return goog.editor.BrowserFeature.HAS_W3C_RANGES ?
+ this.splitQuotedBlockW3C_(pos) :
+ this.splitQuotedBlockIE_(/** @type {Node} */ (pos));
+ }
+};
+
+
+/**
+ * Version of splitQuotedBlock_ that uses W3C ranges.
+ * @param {Object} anchorPos The current cursor position.
+ * @return {boolean} Whether the blockquote was split.
+ * @private
+ */
+goog.editor.plugins.Blockquote.prototype.splitQuotedBlockW3C_ =
+ function(anchorPos) {
+ var cursorNode = anchorPos.node;
+ var quoteNode = goog.editor.node.findTopMostEditableAncestor(
+ cursorNode.parentNode, goog.bind(this.isSplittableBlockquote, this));
+
+ var secondHalf, textNodeToRemove;
+ var insertTextNode = false;
+ // There are two special conditions that we account for here.
+ //
+ // 1. Whenever the cursor is after (one<BR>|) or just before a BR element
+ // (one|<BR>) and the user presses enter, the second quoted block starts
+ // with a BR which appears to the user as an extra newline. This stems
+ // from the fact that we create two text nodes as our split boundaries
+ // and the BR becomes a part of the second half because of this.
+ //
+ // 2. When the cursor is at the end of a text node with no siblings and
+ // the user presses enter, the second blockquote might contain a
+ // empty subtree that ends in a 0 length text node. We account for that
+ // as a post-splitting operation.
+ if (quoteNode) {
+
+ // selection is in a line that has text in it
+ if (cursorNode.nodeType == goog.dom.NodeType.TEXT) {
+ if (anchorPos.offset == cursorNode.length) {
+ var siblingNode = cursorNode.nextSibling;
+
+ // This accounts for the condition where the cursor appears at the
+ // end of a text node and right before the BR eg: one|<BR>. We ensure
+ // that we split on the BR in that case.
+ if (siblingNode && siblingNode.tagName == goog.dom.TagName.BR) {
+ cursorNode = siblingNode;
+ // This might be null but splitDomTreeAt accounts for the null case.
+ secondHalf = siblingNode.nextSibling;
+ } else {
+ textNodeToRemove = cursorNode.splitText(anchorPos.offset);
+ secondHalf = textNodeToRemove;
+ }
+ } else {
+ secondHalf = cursorNode.splitText(anchorPos.offset);
+ }
+ } else if (cursorNode.tagName == goog.dom.TagName.BR) {
+ // This might be null but splitDomTreeAt accounts for the null case.
+ secondHalf = cursorNode.nextSibling;
+ } else {
+ // The selection is in a line that is empty, with more than 1 level
+ // of quote.
+ insertTextNode = true;
+ }
+ } else {
+ // Check if current node is a quote node.
+ // This will happen if user clicks in an empty line in the quote,
+ // when there is 1 level of quote.
+ if (this.isSetupBlockquote(cursorNode)) {
+ quoteNode = cursorNode;
+ insertTextNode = true;
+ }
+ }
+
+ if (insertTextNode) {
+ // Create two empty text nodes to split between.
+ cursorNode = this.insertEmptyTextNodeBeforeRange_();
+ secondHalf = this.insertEmptyTextNodeBeforeRange_();
+ }
+
+ if (!quoteNode) {
+ return false;
+ }
+
+ secondHalf = goog.editor.node.splitDomTreeAt(cursorNode, secondHalf,
+ quoteNode);
+ goog.dom.insertSiblingAfter(secondHalf, quoteNode);
+
+ // Set the insertion point.
+ var dh = this.getFieldDomHelper();
+ var tagToInsert =
+ this.getFieldObject().queryCommandValue(
+ goog.editor.Command.DEFAULT_TAG) ||
+ goog.dom.TagName.DIV;
+ var container = dh.createElement(/** @type {string} */ (tagToInsert));
+ container.innerHTML = ' '; // Prevent the div from collapsing.
+ quoteNode.parentNode.insertBefore(container, secondHalf);
+ dh.getWindow().getSelection().collapse(container, 0);
+
+ // We need to account for the condition where the second blockquote
+ // might contain an empty DOM tree. This arises from trying to split
+ // at the end of an empty text node. We resolve this by walking up the tree
+ // till we either reach the blockquote or till we hit a node with more
+ // than one child. The resulting node is then removed from the DOM.
+ if (textNodeToRemove) {
+ goog.editor.plugins.Blockquote.findAndRemoveSingleChildAncestor_(
+ textNodeToRemove, secondHalf);
+ }
+
+ goog.editor.plugins.Blockquote.removeAllWhiteSpaceNodes_(
+ [quoteNode, secondHalf]);
+ return true;
+};
+
+
+/**
+ * Inserts an empty text node before the field's range.
+ * @return {!Node} The empty text node.
+ * @private
+ */
+goog.editor.plugins.Blockquote.prototype.insertEmptyTextNodeBeforeRange_ =
+ function() {
+ var range = this.getFieldObject().getRange();
+ var node = this.getFieldDomHelper().createTextNode('');
+ range.insertNode(node, true);
+ return node;
+};
+
+
+/**
+ * IE version of splitQuotedBlock_.
+ * @param {Node} splitNode The current cursor position.
+ * @return {boolean} Whether the blockquote was split.
+ * @private
+ */
+goog.editor.plugins.Blockquote.prototype.splitQuotedBlockIE_ =
+ function(splitNode) {
+ var dh = this.getFieldDomHelper();
+ var quoteNode = goog.editor.node.findTopMostEditableAncestor(
+ splitNode.parentNode, goog.bind(this.isSplittableBlockquote, this));
+
+ if (!quoteNode) {
+ return false;
+ }
+
+ var clone = splitNode.cloneNode(false);
+
+ // Whenever the cursor is just before a BR element (one|<BR>) and the user
+ // presses enter, the second quoted block starts with a BR which appears
+ // to the user as an extra newline. This stems from the fact that the
+ // dummy span that we create (splitNode) occurs before the BR and we split
+ // on that.
+ if (splitNode.nextSibling &&
+ splitNode.nextSibling.tagName == goog.dom.TagName.BR) {
+ splitNode = splitNode.nextSibling;
+ }
+ var secondHalf = goog.editor.node.splitDomTreeAt(splitNode, clone, quoteNode);
+ goog.dom.insertSiblingAfter(secondHalf, quoteNode);
+
+ // Set insertion point.
+ var tagToInsert =
+ this.getFieldObject().queryCommandValue(
+ goog.editor.Command.DEFAULT_TAG) ||
+ goog.dom.TagName.DIV;
+ var div = dh.createElement(/** @type {string} */ (tagToInsert));
+ quoteNode.parentNode.insertBefore(div, secondHalf);
+
+ // The div needs non-whitespace contents in order for the insertion point
+ // to get correctly inserted.
+ div.innerHTML = ' ';
+
+ // Moving the range 1 char isn't enough when you have markup.
+ // This moves the range to the end of the nbsp.
+ var range = dh.getDocument().selection.createRange();
+ range.moveToElementText(splitNode);
+ range.move('character', 2);
+ range.select();
+
+ // Remove the no-longer-necessary nbsp.
+ div.innerHTML = '';
+
+ // Clear the original selection.
+ range.pasteHTML('');
+
+ // We need to remove clone from the DOM but just removing clone alone will
+ // not suffice. Let's assume we have the following DOM structure and the
+ // cursor is placed after the first numbered list item "one".
+ //
+ // <blockquote class="gmail-quote">
+ // <div><div>a</div><ol><li>one|</li></ol></div>
+ // <div>b</div>
+ // </blockquote>
+ //
+ // After pressing enter, we have the following structure.
+ //
+ // <blockquote class="gmail-quote">
+ // <div><div>a</div><ol><li>one|</li></ol></div>
+ // </blockquote>
+ // <div> </div>
+ // <blockquote class="gmail-quote">
+ // <div><ol><li><span id=""></span></li></ol></div>
+ // <div>b</div>
+ // </blockquote>
+ //
+ // The clone is contained in a subtree which should be removed. This stems
+ // from the fact that we invoke splitDomTreeAt with the dummy span
+ // as the starting splitting point and this results in the empty subtree
+ // <div><ol><li><span id=""></span></li></ol></div>.
+ //
+ // We resolve this by walking up the tree till we either reach the
+ // blockquote or till we hit a node with more than one child. The resulting
+ // node is then removed from the DOM.
+ goog.editor.plugins.Blockquote.findAndRemoveSingleChildAncestor_(
+ clone, secondHalf);
+
+ goog.editor.plugins.Blockquote.removeAllWhiteSpaceNodes_(
+ [quoteNode, secondHalf]);
+ return true;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/emoticons.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/emoticons.js b/externs/GCL/externs/goog/editor/plugins/emoticons.js
new file mode 100644
index 0000000..4d0c065
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/emoticons.js
@@ -0,0 +1,89 @@
+// Copyright 2009 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.
+// All Rights Reserved
+
+/**
+ * @fileoverview Plugin for generating emoticons.
+ *
+ * @author nicksantos@google.com (Nick Santos)
+ */
+
+goog.provide('goog.editor.plugins.Emoticons');
+
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.range');
+goog.require('goog.functions');
+goog.require('goog.ui.emoji.Emoji');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Plugin for generating emoticons.
+ *
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.Emoticons = function() {
+ goog.editor.plugins.Emoticons.base(this, 'constructor');
+};
+goog.inherits(goog.editor.plugins.Emoticons, goog.editor.Plugin);
+
+
+/** The emoticon command. */
+goog.editor.plugins.Emoticons.COMMAND = '+emoticon';
+
+
+/** @override */
+goog.editor.plugins.Emoticons.prototype.getTrogClassId =
+ goog.functions.constant(goog.editor.plugins.Emoticons.COMMAND);
+
+
+/** @override */
+goog.editor.plugins.Emoticons.prototype.isSupportedCommand = function(
+ command) {
+ return command == goog.editor.plugins.Emoticons.COMMAND;
+};
+
+
+/**
+ * Inserts an emoticon into the editor at the cursor location. Places the
+ * cursor to the right of the inserted emoticon.
+ * @param {string} command Command to execute.
+ * @param {*=} opt_arg Emoji to insert.
+ * @return {!Object|undefined} The result of the command.
+ * @override
+ */
+goog.editor.plugins.Emoticons.prototype.execCommandInternal = function(
+ command, opt_arg) {
+ var emoji = /** @type {goog.ui.emoji.Emoji} */ (opt_arg);
+ var dom = this.getFieldDomHelper();
+ var img = dom.createDom(goog.dom.TagName.IMG, {
+ 'src': emoji.getUrl(),
+ 'style': 'margin:0 0.2ex;vertical-align:middle'
+ });
+ img.setAttribute(goog.ui.emoji.Emoji.ATTRIBUTE, emoji.getId());
+
+ this.getFieldObject().getRange().replaceContentsWithNode(img);
+
+ // IE8 does the right thing with the cursor, and has a js error when we try
+ // to place the cursor manually.
+ // IE9 loses the cursor when the window is focused, so focus first.
+ if (!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9)) {
+ this.getFieldObject().focus();
+ goog.editor.range.placeCursorNextTo(img, false);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/enterhandler.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/enterhandler.js b/externs/GCL/externs/goog/editor/plugins/enterhandler.js
new file mode 100644
index 0000000..b6ebc1d
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/enterhandler.js
@@ -0,0 +1,768 @@
+// 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 Plugin to handle enter keys.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+goog.provide('goog.editor.plugins.EnterHandler');
+
+goog.require('goog.dom');
+goog.require('goog.dom.NodeOffset');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.Range');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.BrowserFeature');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.node');
+goog.require('goog.editor.plugins.Blockquote');
+goog.require('goog.editor.range');
+goog.require('goog.editor.style');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.functions');
+goog.require('goog.object');
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Plugin to handle enter keys. This does all the crazy to normalize (as much as
+ * is reasonable) what happens when you hit enter. This also handles the
+ * special casing of hitting enter in a blockquote.
+ *
+ * In IE, Webkit, and Opera, the resulting HTML uses one DIV tag per line. In
+ * Firefox, the resulting HTML uses BR tags at the end of each line.
+ *
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ */
+goog.editor.plugins.EnterHandler = function() {
+ goog.editor.Plugin.call(this);
+};
+goog.inherits(goog.editor.plugins.EnterHandler, goog.editor.Plugin);
+
+
+/**
+ * The type of block level tag to add on enter, for browsers that support
+ * specifying the default block-level tag. Can be overriden by subclasses; must
+ * be either DIV or P.
+ * @type {goog.dom.TagName}
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.tag = goog.dom.TagName.DIV;
+
+
+/** @override */
+goog.editor.plugins.EnterHandler.prototype.getTrogClassId = function() {
+ return 'EnterHandler';
+};
+
+
+/** @override */
+goog.editor.plugins.EnterHandler.prototype.enable = function(fieldObject) {
+ goog.editor.plugins.EnterHandler.base(this, 'enable', fieldObject);
+
+ if (goog.editor.BrowserFeature.SUPPORTS_OPERA_DEFAULTBLOCK_COMMAND &&
+ (this.tag == goog.dom.TagName.P || this.tag == goog.dom.TagName.DIV)) {
+ var doc = this.getFieldDomHelper().getDocument();
+ doc.execCommand('opera-defaultBlock', false, this.tag);
+ }
+};
+
+
+/**
+ * If the contents are empty, return the 'default' html for the field.
+ * The 'default' contents depend on the enter handling mode, so it
+ * makes the most sense in this plugin.
+ * @param {string} html The html to prepare.
+ * @return {string} The original HTML, or default contents if that
+ * html is empty.
+ * @override
+ */
+goog.editor.plugins.EnterHandler.prototype.prepareContentsHtml = function(
+ html) {
+ if (!html || goog.string.isBreakingWhitespace(html)) {
+ return goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES ?
+ this.getNonCollapsingBlankHtml() : '';
+ }
+ return html;
+};
+
+
+/**
+ * Gets HTML with no contents that won't collapse, for browsers that
+ * collapse the empty string.
+ * @return {string} Blank html.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.getNonCollapsingBlankHtml =
+ goog.functions.constant('<br>');
+
+
+/**
+ * Internal backspace handler.
+ * @param {goog.events.Event} e The keypress event.
+ * @param {goog.dom.AbstractRange} range The closure range object.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.handleBackspaceInternal = function(e,
+ range) {
+ var field = this.getFieldObject().getElement();
+ var container = range && range.getStartNode();
+
+ if (field.firstChild == container && goog.editor.node.isEmpty(container)) {
+ e.preventDefault();
+ // TODO(user): I think we probably don't need to stopPropagation here
+ e.stopPropagation();
+ }
+};
+
+
+/**
+ * Fix paragraphs to be the correct type of node.
+ * @param {goog.events.Event} e The <enter> key event.
+ * @param {boolean} split Whether we already split up a blockquote by
+ * manually inserting elements.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.processParagraphTagsInternal =
+ function(e, split) {
+ // Force IE to turn the node we are leaving into a DIV. If we do turn
+ // it into a DIV, the node IE creates in response to ENTER will also be
+ // a DIV. If we don't, it will be a P. We handle that case
+ // in handleKeyUpIE_
+ if (goog.userAgent.IE || goog.userAgent.OPERA) {
+ this.ensureBlockIeOpera(goog.dom.TagName.DIV);
+ } else if (!split && goog.userAgent.WEBKIT) {
+ // WebKit duplicates a blockquote when the user hits enter. Let's cancel
+ // this and insert a BR instead, to make it more consistent with the other
+ // browsers.
+ var range = this.getFieldObject().getRange();
+ if (!range || !goog.editor.plugins.EnterHandler.isDirectlyInBlockquote(
+ range.getContainerElement())) {
+ return;
+ }
+
+ var dh = this.getFieldDomHelper();
+ var br = dh.createElement(goog.dom.TagName.BR);
+ range.insertNode(br, true);
+
+ // If the BR is at the end of a block element, Safari still thinks there is
+ // only one line instead of two, so we need to add another BR in that case.
+ if (goog.editor.node.isBlockTag(br.parentNode) &&
+ !goog.editor.node.skipEmptyTextNodes(br.nextSibling)) {
+ goog.dom.insertSiblingBefore(
+ dh.createElement(goog.dom.TagName.BR), br);
+ }
+
+ goog.editor.range.placeCursorNextTo(br, false);
+ e.preventDefault();
+ }
+};
+
+
+/**
+ * Determines whether the lowest containing block node is a blockquote.
+ * @param {Node} n The node.
+ * @return {boolean} Whether the deepest block ancestor of n is a blockquote.
+ */
+goog.editor.plugins.EnterHandler.isDirectlyInBlockquote = function(n) {
+ for (var current = n; current; current = current.parentNode) {
+ if (goog.editor.node.isBlockTag(current)) {
+ return current.tagName == goog.dom.TagName.BLOCKQUOTE;
+ }
+ }
+
+ return false;
+};
+
+
+/**
+ * Internal delete key handler.
+ * @param {goog.events.Event} e The keypress event.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.handleDeleteGecko = function(e) {
+ this.deleteBrGecko(e);
+};
+
+
+/**
+ * Deletes the element at the cursor if it is a BR node, and if it does, calls
+ * e.preventDefault to stop the browser from deleting. Only necessary in Gecko
+ * as a workaround for mozilla bug 205350 where deleting a BR that is followed
+ * by a block element doesn't work (the BR gets immediately replaced). We also
+ * need to account for an ill-formed cursor which occurs from us trying to
+ * stop the browser from deleting.
+ *
+ * @param {goog.events.Event} e The DELETE keypress event.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.deleteBrGecko = function(e) {
+ var range = this.getFieldObject().getRange();
+ if (range.isCollapsed()) {
+ var container = range.getEndNode();
+ if (container.nodeType == goog.dom.NodeType.ELEMENT) {
+ var nextNode = container.childNodes[range.getEndOffset()];
+ if (nextNode && nextNode.tagName == goog.dom.TagName.BR) {
+ // We want to retrieve the first non-whitespace previous sibling
+ // as we could have added an empty text node below and want to
+ // properly handle deleting a sequence of BR's.
+ var previousSibling = goog.editor.node.getPreviousSibling(nextNode);
+ var nextSibling = nextNode.nextSibling;
+
+ container.removeChild(nextNode);
+ e.preventDefault();
+
+ // When we delete a BR followed by a block level element, the cursor
+ // has a line-height which spans the height of the block level element.
+ // e.g. If we delete a BR followed by a UL, the resulting HTML will
+ // appear to the end user like:-
+ //
+ // | * one
+ // | * two
+ // | * three
+ //
+ // There are a couple of cases that we have to account for in order to
+ // properly conform to what the user expects when DELETE is pressed.
+ //
+ // 1. If the BR has a previous sibling and the previous sibling is
+ // not a block level element or a BR, we place the cursor at the
+ // end of that.
+ // 2. If the BR doesn't have a previous sibling or the previous sibling
+ // is a block level element or a BR, we place the cursor at the
+ // beginning of the leftmost leaf of its next sibling.
+ if (nextSibling && goog.editor.node.isBlockTag(nextSibling)) {
+ if (previousSibling &&
+ !(previousSibling.tagName == goog.dom.TagName.BR ||
+ goog.editor.node.isBlockTag(previousSibling))) {
+ goog.dom.Range.createCaret(
+ previousSibling,
+ goog.editor.node.getLength(previousSibling)).select();
+ } else {
+ var leftMostLeaf = goog.editor.node.getLeftMostLeaf(nextSibling);
+ goog.dom.Range.createCaret(leftMostLeaf, 0).select();
+ }
+ }
+ }
+ }
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.EnterHandler.prototype.handleKeyPress = function(e) {
+ // If a dialog doesn't have selectable field, Gecko grabs the event and
+ // performs actions in editor window. This solves that problem and allows
+ // the event to be passed on to proper handlers.
+ if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) {
+ return false;
+ }
+
+ // Firefox will allow the first node in an iframe to be deleted
+ // on a backspace. Disallow it if the node is empty.
+ if (e.keyCode == goog.events.KeyCodes.BACKSPACE) {
+ this.handleBackspaceInternal(e, this.getFieldObject().getRange());
+
+ } else if (e.keyCode == goog.events.KeyCodes.ENTER) {
+ if (goog.userAgent.GECKO) {
+ if (!e.shiftKey) {
+ // Behave similarly to IE's content editable return carriage:
+ // If the shift key is down or specified by the application, insert a
+ // BR, otherwise split paragraphs
+ this.handleEnterGecko_(e);
+ }
+ } else {
+ // In Gecko-based browsers, this is handled in the handleEnterGecko_
+ // method.
+ this.getFieldObject().dispatchBeforeChange();
+ var cursorPosition = this.deleteCursorSelection_();
+
+ var split = !!this.getFieldObject().execCommand(
+ goog.editor.plugins.Blockquote.SPLIT_COMMAND, cursorPosition);
+ if (split) {
+ // TODO(user): I think we probably don't need to stopPropagation here
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ this.releasePositionObject_(cursorPosition);
+
+ if (goog.userAgent.WEBKIT) {
+ this.handleEnterWebkitInternal(e);
+ }
+
+ this.processParagraphTagsInternal(e, split);
+ this.getFieldObject().dispatchChange();
+ }
+
+ } else if (goog.userAgent.GECKO && e.keyCode == goog.events.KeyCodes.DELETE) {
+ this.handleDeleteGecko(e);
+ }
+
+ return false;
+};
+
+
+/** @override */
+goog.editor.plugins.EnterHandler.prototype.handleKeyUp = function(e) {
+ // If a dialog doesn't have selectable field, Gecko grabs the event and
+ // performs actions in editor window. This solves that problem and allows
+ // the event to be passed on to proper handlers.
+ if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) {
+ return false;
+ }
+ this.handleKeyUpInternal(e);
+ return false;
+};
+
+
+/**
+ * Internal handler for keyup events.
+ * @param {goog.events.Event} e The key event.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.handleKeyUpInternal = function(e) {
+ if ((goog.userAgent.IE || goog.userAgent.OPERA) &&
+ e.keyCode == goog.events.KeyCodes.ENTER) {
+ this.ensureBlockIeOpera(goog.dom.TagName.DIV, true);
+ }
+};
+
+
+/**
+ * Handles an enter keypress event on fields in Gecko.
+ * @param {goog.events.BrowserEvent} e The key event.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.prototype.handleEnterGecko_ = function(e) {
+ // Retrieve whether the selection is collapsed before we delete it.
+ var range = this.getFieldObject().getRange();
+ var wasCollapsed = !range || range.isCollapsed();
+ var cursorPosition = this.deleteCursorSelection_();
+
+ var handled = this.getFieldObject().execCommand(
+ goog.editor.plugins.Blockquote.SPLIT_COMMAND, cursorPosition);
+ if (handled) {
+ // TODO(user): I think we probably don't need to stopPropagation here
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ this.releasePositionObject_(cursorPosition);
+ if (!handled) {
+ this.handleEnterAtCursorGeckoInternal(e, wasCollapsed, range);
+ }
+};
+
+
+/**
+ * Handle an enter key press in WebKit.
+ * @param {goog.events.BrowserEvent} e The key press event.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.handleEnterWebkitInternal =
+ goog.nullFunction;
+
+
+/**
+ * Handle an enter key press on collapsed selection. handleEnterGecko_ ensures
+ * the selection is collapsed by deleting its contents if it is not. The
+ * default implementation does nothing.
+ * @param {goog.events.BrowserEvent} e The key press event.
+ * @param {boolean} wasCollapsed Whether the selection was collapsed before
+ * the key press. If it was not, code before this function has already
+ * cleared the contents of the selection.
+ * @param {goog.dom.AbstractRange} range Object representing the selection.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.handleEnterAtCursorGeckoInternal =
+ goog.nullFunction;
+
+
+/**
+ * Names of all the nodes that we don't want to turn into block nodes in IE when
+ * the user hits enter.
+ * @type {Object}
+ * @private
+ */
+goog.editor.plugins.EnterHandler.DO_NOT_ENSURE_BLOCK_NODES_ =
+ goog.object.createSet(
+ goog.dom.TagName.LI, goog.dom.TagName.DIV, goog.dom.TagName.H1,
+ goog.dom.TagName.H2, goog.dom.TagName.H3, goog.dom.TagName.H4,
+ goog.dom.TagName.H5, goog.dom.TagName.H6);
+
+
+/**
+ * Whether this is a node that contains a single BR tag and non-nbsp
+ * whitespace.
+ * @param {Node} node Node to check.
+ * @return {boolean} Whether this is an element that only contains a BR.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.isBrElem = function(node) {
+ return goog.editor.node.isEmpty(node) &&
+ node.getElementsByTagName(goog.dom.TagName.BR).length == 1;
+};
+
+
+/**
+ * Ensures all text in IE and Opera to be in the given tag in order to control
+ * Enter spacing. Call this when Enter is pressed if desired.
+ *
+ * We want to make sure the user is always inside of a block (or other nodes
+ * listed in goog.editor.plugins.EnterHandler.IGNORE_ENSURE_BLOCK_NODES_). We
+ * listen to keypress to force nodes that the user is leaving to turn into
+ * blocks, but we also need to listen to keyup to force nodes that the user is
+ * entering to turn into blocks.
+ * Example: html is: "<h2>foo[cursor]</h2>", and the user hits enter. We
+ * don't want to format the h2, but we do want to format the P that is
+ * created on enter. The P node is not available until keyup.
+ * @param {goog.dom.TagName} tag The tag name to convert to.
+ * @param {boolean=} opt_keyUp Whether the function is being called on key up.
+ * When called on key up, the cursor is in the newly created node, so the
+ * semantics for when to change it to a block are different. Specifically,
+ * if the resulting node contains only a BR, it is converted to <tag>.
+ * @protected
+ */
+goog.editor.plugins.EnterHandler.prototype.ensureBlockIeOpera = function(tag,
+ opt_keyUp) {
+ var range = this.getFieldObject().getRange();
+ var container = range.getContainer();
+ var field = this.getFieldObject().getElement();
+
+ var paragraph;
+ while (container && container != field) {
+ // We don't need to ensure a block if we are already in the same block, or
+ // in another block level node that we don't want to change the format of
+ // (unless we're handling keyUp and that block node just contains a BR).
+ var nodeName = container.nodeName;
+ // Due to @bug 2455389, the call to isBrElem needs to be inlined in the if
+ // instead of done before and saved in a variable, so that it can be
+ // short-circuited and avoid a weird IE edge case.
+ if (nodeName == tag ||
+ (goog.editor.plugins.EnterHandler.
+ DO_NOT_ENSURE_BLOCK_NODES_[nodeName] && !(opt_keyUp &&
+ goog.editor.plugins.EnterHandler.isBrElem(container)))) {
+ // Opera can create a <p> inside of a <div> in some situations,
+ // such as when breaking out of a list that is contained in a <div>.
+ if (goog.userAgent.OPERA && paragraph) {
+ if (nodeName == tag &&
+ paragraph == container.lastChild &&
+ goog.editor.node.isEmpty(paragraph)) {
+ goog.dom.insertSiblingAfter(paragraph, container);
+ goog.dom.Range.createFromNodeContents(paragraph).select();
+ }
+ break;
+ }
+ return;
+ }
+ if (goog.userAgent.OPERA && opt_keyUp && nodeName == goog.dom.TagName.P &&
+ nodeName != tag) {
+ paragraph = container;
+ }
+
+ container = container.parentNode;
+ }
+
+
+ if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9)) {
+ // IE (before IE9) has a bug where if the cursor is directly before a block
+ // node (e.g., the content is "foo[cursor]<blockquote>bar</blockquote>"),
+ // the FormatBlock command actually formats the "bar" instead of the "foo".
+ // This is just wrong. To work-around this, we want to move the
+ // selection back one character, and then restore it to its prior position.
+ // NOTE: We use the following "range math" to detect this situation because
+ // using Closure ranges here triggers a bug in IE that causes a crash.
+ // parent2 != parent3 ensures moving the cursor forward one character
+ // crosses at least 1 element boundary, and therefore tests if the cursor is
+ // at such a boundary. The second check, parent3 != range.parentElement()
+ // weeds out some cases where the elements are siblings instead of cousins.
+ var needsHelp = false;
+ range = range.getBrowserRangeObject();
+ var range2 = range.duplicate();
+ range2.moveEnd('character', 1);
+ // In whitebox mode, when the cursor is at the end of the field, trying to
+ // move the end of the range will do nothing, and hence the range's text
+ // will be empty. In this case, the cursor clearly isn't sitting just
+ // before a block node, since it isn't before anything.
+ if (range2.text.length) {
+ var parent2 = range2.parentElement();
+
+ var range3 = range2.duplicate();
+ range3.collapse(false);
+ var parent3 = range3.parentElement();
+
+ if ((needsHelp = parent2 != parent3 &&
+ parent3 != range.parentElement())) {
+ range.move('character', -1);
+ range.select();
+ }
+ }
+ }
+
+ this.getFieldObject().getEditableDomHelper().getDocument().execCommand(
+ 'FormatBlock', false, '<' + tag + '>');
+
+ if (needsHelp) {
+ range.move('character', 1);
+ range.select();
+ }
+};
+
+
+/**
+ * Deletes the content at the current cursor position.
+ * @return {!Node|!Object} Something representing the current cursor position.
+ * See deleteCursorSelectionIE_ and deleteCursorSelectionW3C_ for details.
+ * Should be passed to releasePositionObject_ when no longer in use.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.prototype.deleteCursorSelection_ = function() {
+ return goog.editor.BrowserFeature.HAS_W3C_RANGES ?
+ this.deleteCursorSelectionW3C_() : this.deleteCursorSelectionIE_();
+};
+
+
+/**
+ * Releases the object returned by deleteCursorSelection_.
+ * @param {Node|Object} position The object returned by deleteCursorSelection_.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.prototype.releasePositionObject_ =
+ function(position) {
+ if (!goog.editor.BrowserFeature.HAS_W3C_RANGES) {
+ (/** @type {Node} */ (position)).removeNode(true);
+ }
+};
+
+
+/**
+ * Delete the selection at the current cursor position, then returns a temporary
+ * node at the current position.
+ * @return {!Node} A temporary node marking the current cursor position. This
+ * node should eventually be removed from the DOM.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.prototype.deleteCursorSelectionIE_ =
+ function() {
+ var doc = this.getFieldDomHelper().getDocument();
+ var range = doc.selection.createRange();
+
+ var id = goog.string.createUniqueString();
+ range.pasteHTML('<span id="' + id + '"></span>');
+ var splitNode = doc.getElementById(id);
+ splitNode.id = '';
+ return splitNode;
+};
+
+
+/**
+ * Delete the selection at the current cursor position, then returns the node
+ * at the current position.
+ * @return {!goog.editor.range.Point} The current cursor position. Note that
+ * unlike simulateEnterIE_, this should not be removed from the DOM.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.prototype.deleteCursorSelectionW3C_ =
+ function() {
+ var range = this.getFieldObject().getRange();
+
+ // Delete the current selection if it's is non-collapsed.
+ // Although this is redundant in FF, it's necessary for Safari
+ if (!range.isCollapsed()) {
+ var shouldDelete = true;
+ // Opera selects the <br> in an empty block if there is no text node
+ // preceding it. To preserve inline formatting when pressing [enter] inside
+ // an empty block, don't delete the selection if it only selects a <br> at
+ // the end of the block.
+ // TODO(user): Move this into goog.dom.Range. It should detect this state
+ // when creating a range from the window selection and fix it in the created
+ // range.
+ if (goog.userAgent.OPERA) {
+ var startNode = range.getStartNode();
+ var startOffset = range.getStartOffset();
+ if (startNode == range.getEndNode() &&
+ // This weeds out cases where startNode is a text node.
+ startNode.lastChild &&
+ startNode.lastChild.tagName == goog.dom.TagName.BR &&
+ // If this check is true, then endOffset is implied to be
+ // startOffset + 1, because the selection is not collapsed and
+ // it starts and ends within the same element.
+ startOffset == startNode.childNodes.length - 1) {
+ shouldDelete = false;
+ }
+ }
+ if (shouldDelete) {
+ goog.editor.plugins.EnterHandler.deleteW3cRange_(range);
+ }
+ }
+
+ return goog.editor.range.getDeepEndPoint(range, true);
+};
+
+
+/**
+ * Deletes the contents of the selection from the DOM.
+ * @param {goog.dom.AbstractRange} range The range to remove contents from.
+ * @return {goog.dom.AbstractRange} The resulting range. Used for testing.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.deleteW3cRange_ = function(range) {
+ if (range && !range.isCollapsed()) {
+ var reselect = true;
+ var baseNode = range.getContainerElement();
+ var nodeOffset = new goog.dom.NodeOffset(range.getStartNode(), baseNode);
+ var rangeOffset = range.getStartOffset();
+
+ // Whether the selection crosses no container boundaries.
+ var isInOneContainer =
+ goog.editor.plugins.EnterHandler.isInOneContainerW3c_(range);
+
+ // Whether the selection ends in a container it doesn't fully select.
+ var isPartialEnd = !isInOneContainer &&
+ goog.editor.plugins.EnterHandler.isPartialEndW3c_(range);
+
+ // Remove The range contents, and ensure the correct content stays selected.
+ range.removeContents();
+ var node = nodeOffset.findTargetNode(baseNode);
+ if (node) {
+ range = goog.dom.Range.createCaret(node, rangeOffset);
+ } else {
+ // This occurs when the node that would have been referenced has now been
+ // deleted and there are no other nodes in the baseNode. Thus need to
+ // set the caret to the end of the base node.
+ range =
+ goog.dom.Range.createCaret(baseNode, baseNode.childNodes.length);
+ reselect = false;
+ }
+ range.select();
+
+ // If we just deleted everything from the container, add an nbsp
+ // to the container, and leave the cursor inside of it
+ if (isInOneContainer) {
+ var container = goog.editor.style.getContainer(range.getStartNode());
+ if (goog.editor.node.isEmpty(container, true)) {
+ var html = ' ';
+ if (goog.userAgent.OPERA &&
+ container.tagName == goog.dom.TagName.LI) {
+ // Don't break Opera's native break-out-of-lists behavior.
+ html = '<br>';
+ }
+ goog.editor.node.replaceInnerHtml(container, html);
+ goog.editor.range.selectNodeStart(container.firstChild);
+ reselect = false;
+ }
+ }
+
+ if (isPartialEnd) {
+ /*
+ This code handles the following, where | is the cursor:
+ <div>a|b</div><div>c|d</div>
+ After removeContents, the remaining HTML is
+ <div>a</div><div>d</div>
+ which means the line break between the two divs remains. This block
+ moves children of the second div in to the first div to get the correct
+ result:
+ <div>ad</div>
+
+ TODO(robbyw): Should we wrap the second div's contents in a span if they
+ have inline style?
+ */
+ var rangeStart = goog.editor.style.getContainer(range.getStartNode());
+ var redundantContainer = goog.editor.node.getNextSibling(rangeStart);
+ if (rangeStart && redundantContainer) {
+ goog.dom.append(rangeStart, redundantContainer.childNodes);
+ goog.dom.removeNode(redundantContainer);
+ }
+ }
+
+ if (reselect) {
+ // The contents of the original range are gone, so restore the cursor
+ // position at the start of where the range once was.
+ range = goog.dom.Range.createCaret(nodeOffset.findTargetNode(baseNode),
+ rangeOffset);
+ range.select();
+ }
+ }
+
+ return range;
+};
+
+
+/**
+ * Checks whether the whole range is in a single block-level element.
+ * @param {goog.dom.AbstractRange} range The range to check.
+ * @return {boolean} Whether the whole range is in a single block-level element.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.isInOneContainerW3c_ = function(range) {
+ // Find the block element containing the start of the selection.
+ var startContainer = range.getStartNode();
+ if (goog.editor.style.isContainer(startContainer)) {
+ startContainer = startContainer.childNodes[range.getStartOffset()] ||
+ startContainer;
+ }
+ startContainer = goog.editor.style.getContainer(startContainer);
+
+ // Find the block element containing the end of the selection.
+ var endContainer = range.getEndNode();
+ if (goog.editor.style.isContainer(endContainer)) {
+ endContainer = endContainer.childNodes[range.getEndOffset()] ||
+ endContainer;
+ }
+ endContainer = goog.editor.style.getContainer(endContainer);
+
+ // Compare the two.
+ return startContainer == endContainer;
+};
+
+
+/**
+ * Checks whether the end of the range is not at the end of a block-level
+ * element.
+ * @param {goog.dom.AbstractRange} range The range to check.
+ * @return {boolean} Whether the end of the range is not at the end of a
+ * block-level element.
+ * @private
+ */
+goog.editor.plugins.EnterHandler.isPartialEndW3c_ = function(range) {
+ var endContainer = range.getEndNode();
+ var endOffset = range.getEndOffset();
+ var node = endContainer;
+ if (goog.editor.style.isContainer(node)) {
+ var child = node.childNodes[endOffset];
+ // Child is null when end offset is >= length, which indicates the entire
+ // container is selected. Otherwise, we also know the entire container
+ // is selected if the selection ends at a new container.
+ if (!child ||
+ child.nodeType == goog.dom.NodeType.ELEMENT &&
+ goog.editor.style.isContainer(child)) {
+ return false;
+ }
+ }
+
+ var container = goog.editor.style.getContainer(node);
+ while (container != node) {
+ if (goog.editor.node.getNextSibling(node)) {
+ return true;
+ }
+ node = node.parentNode;
+ }
+
+ return endOffset != goog.editor.node.getLength(endContainer);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/firststrong.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/firststrong.js b/externs/GCL/externs/goog/editor/plugins/firststrong.js
new file mode 100644
index 0000000..7342bad
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/firststrong.js
@@ -0,0 +1,334 @@
+// Copyright 2012 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 plugin to enable the First Strong Bidi algorithm. The First
+ * Strong algorithm as a heuristic used to automatically set paragraph direction
+ * depending on its content.
+ *
+ * In the documentation below, a 'paragraph' is the local element which we
+ * evaluate as a whole for purposes of determining directionality. It may be a
+ * block-level element (e.g. <div>) or a whole list (e.g. <ul>).
+ *
+ * This implementation is based on, but is not identical to, the original
+ * First Strong algorithm defined in Unicode
+ * @see http://www.unicode.org/reports/tr9/
+ * The central difference from the original First Strong algorithm is that this
+ * implementation decides the paragraph direction based on the first strong
+ * character that is <em>typed</em> into the paragraph, regardless of its
+ * location in the paragraph, as opposed to the original algorithm where it is
+ * the first character in the paragraph <em>by location</em>, regardless of
+ * whether other strong characters already appear in the paragraph, further its
+ * start.
+ *
+ * <em>Please note</em> that this plugin does not perform the direction change
+ * itself. Rather, it fires editor commands upon the key up event when a
+ * direction change needs to be performed; {@code goog.editor.Command.DIR_RTL}
+ * or {@code goog.editor.Command.DIR_RTL}.
+ *
+ */
+
+goog.provide('goog.editor.plugins.FirstStrong');
+
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.TagIterator');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Field');
+goog.require('goog.editor.Plugin');
+goog.require('goog.editor.node');
+goog.require('goog.editor.range');
+goog.require('goog.i18n.bidi');
+goog.require('goog.i18n.uChar');
+goog.require('goog.iter');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * First Strong plugin.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.FirstStrong = function() {
+ goog.editor.plugins.FirstStrong.base(this, 'constructor');
+
+ /**
+ * Indicates whether or not the cursor is in a paragraph we have not yet
+ * finished evaluating for directionality. This is set to true whenever the
+ * cursor is moved, and set to false after seeing a strong character in the
+ * paragraph the cursor is currently in.
+ *
+ * @type {boolean}
+ * @private
+ */
+ this.isNewBlock_ = true;
+
+ /**
+ * Indicates whether or not the current paragraph the cursor is in should be
+ * set to Right-To-Left directionality.
+ *
+ * @type {boolean}
+ * @private
+ */
+ this.switchToRtl_ = false;
+
+ /**
+ * Indicates whether or not the current paragraph the cursor is in should be
+ * set to Left-To-Right directionality.
+ *
+ * @type {boolean}
+ * @private
+ */
+ this.switchToLtr_ = false;
+};
+goog.inherits(goog.editor.plugins.FirstStrong, goog.editor.Plugin);
+
+
+/** @override */
+goog.editor.plugins.FirstStrong.prototype.getTrogClassId = function() {
+ return 'FirstStrong';
+};
+
+
+/** @override */
+goog.editor.plugins.FirstStrong.prototype.queryCommandValue =
+ function(command) {
+ return false;
+};
+
+
+/** @override */
+goog.editor.plugins.FirstStrong.prototype.handleSelectionChange =
+ function(e, node) {
+ this.isNewBlock_ = true;
+ return false;
+};
+
+
+/**
+ * The name of the attribute which records the input text.
+ *
+ * @type {string}
+ * @const
+ */
+goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE = 'fs-input';
+
+
+/** @override */
+goog.editor.plugins.FirstStrong.prototype.handleKeyPress = function(e) {
+ if (goog.editor.Field.SELECTION_CHANGE_KEYCODES[e.keyCode]) {
+ // Key triggered selection change event (e.g. on ENTER) is throttled and a
+ // later LTR/RTL strong keypress may come before it. Need to capture it.
+ this.isNewBlock_ = true;
+ return false; // A selection-changing key is not LTR/RTL strong.
+ }
+ if (!this.isNewBlock_) {
+ return false; // We've already determined this paragraph's direction.
+ }
+ // Ignore non-character key press events.
+ if (e.ctrlKey || e.metaKey) {
+ return false;
+ }
+ var newInput = goog.i18n.uChar.fromCharCode(e.charCode);
+
+ // IME's may return 0 for the charCode, which is a legitimate, non-Strong
+ // charCode, or they may return an illegal charCode (for which newInput will
+ // be false).
+ if (!newInput || !e.charCode) {
+ var browserEvent = e.getBrowserEvent();
+ if (browserEvent) {
+ if (goog.userAgent.IE && browserEvent['getAttribute']) {
+ newInput = browserEvent['getAttribute'](
+ goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE);
+ } else {
+ newInput = browserEvent[
+ goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE];
+ }
+ }
+ }
+
+ if (!newInput) {
+ return false; // Unrecognized key.
+ }
+
+ var isLtr = goog.i18n.bidi.isLtrChar(newInput);
+ var isRtl = !isLtr && goog.i18n.bidi.isRtlChar(newInput);
+ if (!isLtr && !isRtl) {
+ return false; // This character cannot change anything (it is not Strong).
+ }
+ // This character is Strongly LTR or Strongly RTL. We might switch direction
+ // on it now, but in any case we do not need to check any more characters in
+ // this paragraph after it.
+ this.isNewBlock_ = false;
+
+ // Are there no Strong characters already in the paragraph?
+ if (this.isNeutralBlock_()) {
+ this.switchToRtl_ = isRtl;
+ this.switchToLtr_ = isLtr;
+ }
+ return false;
+};
+
+
+/**
+ * Calls the flip directionality commands. This is done here so things go into
+ * the redo-undo stack at the expected order; fist enter the input, then flip
+ * directionality.
+ * @override
+ */
+goog.editor.plugins.FirstStrong.prototype.handleKeyUp = function(e) {
+ if (this.switchToRtl_) {
+ var field = this.getFieldObject();
+ field.dispatchChange(true);
+ field.execCommand(goog.editor.Command.DIR_RTL);
+ this.switchToRtl_ = false;
+ } else if (this.switchToLtr_) {
+ var field = this.getFieldObject();
+ field.dispatchChange(true);
+ field.execCommand(goog.editor.Command.DIR_LTR);
+ this.switchToLtr_ = false;
+ }
+ return false;
+};
+
+
+/**
+ * @return {Element} The lowest Block element ancestor of the node where the
+ * next character will be placed.
+ * @private
+ */
+goog.editor.plugins.FirstStrong.prototype.getBlockAncestor_ = function() {
+ var start = this.getFieldObject().getRange().getStartNode();
+ // Go up in the DOM until we reach a Block element.
+ while (!goog.editor.plugins.FirstStrong.isBlock_(start)) {
+ start = start.parentNode;
+ }
+ return /** @type {Element} */ (start);
+};
+
+
+/**
+ * @return {boolean} Whether the paragraph where the next character will be
+ * entered contains only non-Strong characters.
+ * @private
+ */
+goog.editor.plugins.FirstStrong.prototype.isNeutralBlock_ = function() {
+ var root = this.getBlockAncestor_();
+ // The exact node with the cursor location. Simply calling getStartNode() on
+ // the range only returns the containing block node.
+ var cursor = goog.editor.range.getDeepEndPoint(
+ this.getFieldObject().getRange(), false).node;
+
+ // In FireFox the BR tag also represents a change in paragraph if not inside a
+ // list. So we need special handling to only look at the sub-block between
+ // BR elements.
+ var blockFunction = (goog.userAgent.GECKO &&
+ !this.isList_(root)) ?
+ goog.editor.plugins.FirstStrong.isGeckoBlock_ :
+ goog.editor.plugins.FirstStrong.isBlock_;
+ var paragraph = this.getTextAround_(root, cursor,
+ blockFunction);
+ // Not using {@code goog.i18n.bidi.isNeutralText} as it contains additional,
+ // unwanted checks to the content.
+ return !goog.i18n.bidi.hasAnyLtr(paragraph) &&
+ !goog.i18n.bidi.hasAnyRtl(paragraph);
+};
+
+
+/**
+ * Checks if an element is a list element ('UL' or 'OL').
+ *
+ * @param {Element} element The element to test.
+ * @return {boolean} Whether the element is a list element ('UL' or 'OL').
+ * @private
+ */
+goog.editor.plugins.FirstStrong.prototype.isList_ = function(element) {
+ if (!element) {
+ return false;
+ }
+ var tagName = element.tagName;
+ return tagName == goog.dom.TagName.UL || tagName == goog.dom.TagName.OL;
+};
+
+
+/**
+ * Returns the text within the local paragraph around the cursor.
+ * Notice that for GECKO a BR represents a pargraph change despite not being a
+ * block element.
+ *
+ * @param {Element} root The first block element ancestor of the node the cursor
+ * is in.
+ * @param {Node} cursorLocation Node where the cursor currently is, marking the
+ * paragraph whose text we will return.
+ * @param {function(Node): boolean} isParagraphBoundary The function to
+ * determine if a node represents the start or end of the paragraph.
+ * @return {string} the text in the paragraph around the cursor location.
+ * @private
+ */
+goog.editor.plugins.FirstStrong.prototype.getTextAround_ = function(root,
+ cursorLocation, isParagraphBoundary) {
+ // The buffer where we're collecting the text.
+ var buffer = [];
+ // Have we reached the cursor yet, or are we still before it?
+ var pastCursorLocation = false;
+
+ if (root && cursorLocation) {
+ goog.iter.some(new goog.dom.TagIterator(root), function(node) {
+ if (node == cursorLocation) {
+ pastCursorLocation = true;
+ } else if (isParagraphBoundary(node)) {
+ if (pastCursorLocation) {
+ // This is the end of the paragraph containing the cursor. We're done.
+ return true;
+ } else {
+ // All we collected so far does not count; it was in a previous
+ // paragraph that did not contain the cursor.
+ buffer = [];
+ }
+ }
+ if (node.nodeType == goog.dom.NodeType.TEXT) {
+ buffer.push(node.nodeValue);
+ }
+ return false; // Keep going.
+ });
+ }
+ return buffer.join('');
+};
+
+
+/**
+ * @param {Node} node Node to check.
+ * @return {boolean} Does the given node represent a Block element? Notice we do
+ * not consider list items as Block elements in the algorithm.
+ * @private
+ */
+goog.editor.plugins.FirstStrong.isBlock_ = function(node) {
+ return !!node && goog.editor.node.isBlockTag(node) &&
+ node.tagName != goog.dom.TagName.LI;
+};
+
+
+/**
+ * @param {Node} node Node to check.
+ * @return {boolean} Does the given node represent a Block element from the
+ * point of view of FireFox? Notice we do not consider list items as Block
+ * elements in the algorithm.
+ * @private
+ */
+goog.editor.plugins.FirstStrong.isGeckoBlock_ = function(node) {
+ return !!node && (node.tagName == goog.dom.TagName.BR ||
+ goog.editor.plugins.FirstStrong.isBlock_(node));
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/headerformatter.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/headerformatter.js b/externs/GCL/externs/goog/editor/plugins/headerformatter.js
new file mode 100644
index 0000000..fa4bb1f
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/headerformatter.js
@@ -0,0 +1,96 @@
+// 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 Handles applying header styles to text.
+ *
+ */
+
+goog.provide('goog.editor.plugins.HeaderFormatter');
+
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Plugin');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * Applies header styles to text.
+ * @constructor
+ * @extends {goog.editor.Plugin}
+ * @final
+ */
+goog.editor.plugins.HeaderFormatter = function() {
+ goog.editor.Plugin.call(this);
+};
+goog.inherits(goog.editor.plugins.HeaderFormatter, goog.editor.Plugin);
+
+
+/** @override */
+goog.editor.plugins.HeaderFormatter.prototype.getTrogClassId = function() {
+ return 'HeaderFormatter';
+};
+
+// TODO(user): Move execCommand functionality from basictextformatter into
+// here for headers. I'm not doing this now because it depends on the
+// switch statements in basictextformatter and we'll need to abstract that out
+// in order to seperate out any of the functions from basictextformatter.
+
+
+/**
+ * Commands that can be passed as the optional argument to execCommand.
+ * @enum {string}
+ */
+goog.editor.plugins.HeaderFormatter.HEADER_COMMAND = {
+ H1: 'H1',
+ H2: 'H2',
+ H3: 'H3',
+ H4: 'H4'
+};
+
+
+/**
+ * @override
+ */
+goog.editor.plugins.HeaderFormatter.prototype.handleKeyboardShortcut = function(
+ e, key, isModifierPressed) {
+ if (!isModifierPressed) {
+ return false;
+ }
+ var command = null;
+ switch (key) {
+ case '1':
+ command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H1;
+ break;
+ case '2':
+ command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H2;
+ break;
+ case '3':
+ command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H3;
+ break;
+ case '4':
+ command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H4;
+ break;
+ }
+ if (command) {
+ this.getFieldObject().execCommand(
+ goog.editor.Command.FORMAT_BLOCK, command);
+ // Prevent default isn't enough to cancel tab navigation in FF.
+ if (goog.userAgent.GECKO) {
+ e.stopPropagation();
+ }
+ return true;
+ }
+ return false;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/editor/plugins/linkbubble.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/editor/plugins/linkbubble.js b/externs/GCL/externs/goog/editor/plugins/linkbubble.js
new file mode 100644
index 0000000..01c84f3
--- /dev/null
+++ b/externs/GCL/externs/goog/editor/plugins/linkbubble.js
@@ -0,0 +1,585 @@
+// 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 Base class for bubble plugins.
+ *
+ */
+
+goog.provide('goog.editor.plugins.LinkBubble');
+goog.provide('goog.editor.plugins.LinkBubble.Action');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.editor.Command');
+goog.require('goog.editor.Link');
+goog.require('goog.editor.plugins.AbstractBubblePlugin');
+goog.require('goog.editor.range');
+goog.require('goog.functions');
+goog.require('goog.string');
+goog.require('goog.style');
+goog.require('goog.ui.editor.messages');
+goog.require('goog.uri.utils');
+goog.require('goog.window');
+
+
+
+/**
+ * Property bubble plugin for links.
+ * @param {...!goog.editor.plugins.LinkBubble.Action} var_args List of
+ * extra actions supported by the bubble.
+ * @constructor
+ * @extends {goog.editor.plugins.AbstractBubblePlugin}
+ */
+goog.editor.plugins.LinkBubble = function(var_args) {
+ goog.editor.plugins.LinkBubble.base(this, 'constructor');
+
+ /**
+ * List of extra actions supported by the bubble.
+ * @type {Array<!goog.editor.plugins.LinkBubble.Action>}
+ * @private
+ */
+ this.extraActions_ = goog.array.toArray(arguments);
+
+ /**
+ * List of spans corresponding to the extra actions.
+ * @type {Array<!Element>}
+ * @private
+ */
+ this.actionSpans_ = [];
+
+ /**
+ * A list of whitelisted URL schemes which are safe to open.
+ * @type {Array<string>}
+ * @private
+ */
+ this.safeToOpenSchemes_ = ['http', 'https', 'ftp'];
+};
+goog.inherits(goog.editor.plugins.LinkBubble,
+ goog.editor.plugins.AbstractBubblePlugin);
+
+
+/**
+ * Element id for the link text.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.LINK_TEXT_ID_ = 'tr_link-text';
+
+
+/**
+ * Element id for the test link span.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.TEST_LINK_SPAN_ID_ = 'tr_test-link-span';
+
+
+/**
+ * Element id for the test link.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.TEST_LINK_ID_ = 'tr_test-link';
+
+
+/**
+ * Element id for the change link span.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.CHANGE_LINK_SPAN_ID_ = 'tr_change-link-span';
+
+
+/**
+ * Element id for the link.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.CHANGE_LINK_ID_ = 'tr_change-link';
+
+
+/**
+ * Element id for the delete link span.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.DELETE_LINK_SPAN_ID_ = 'tr_delete-link-span';
+
+
+/**
+ * Element id for the delete link.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.DELETE_LINK_ID_ = 'tr_delete-link';
+
+
+/**
+ * Element id for the link bubble wrapper div.
+ * type {string}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.LINK_DIV_ID_ = 'tr_link-div';
+
+
+/**
+ * @desc Text label for link that lets the user click it to see where the link
+ * this bubble is for point to.
+ */
+goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_TEST_LINK = goog.getMsg(
+ 'Go to link: ');
+
+
+/**
+ * @desc Label that pops up a dialog to change the link.
+ */
+goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_CHANGE = goog.getMsg(
+ 'Change');
+
+
+/**
+ * @desc Label that allow the user to remove this link.
+ */
+goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_REMOVE = goog.getMsg(
+ 'Remove');
+
+
+/**
+ * @desc Message shown in a link bubble when the link is not a valid url.
+ */
+goog.editor.plugins.LinkBubble.MSG_INVALID_URL_LINK_BUBBLE = goog.getMsg(
+ 'invalid url');
+
+
+/**
+ * Whether to stop leaking the page's url via the referrer header when the
+ * link text link is clicked.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.stopReferrerLeaks_ = false;
+
+
+/**
+ * Whether to block opening links with a non-whitelisted URL scheme.
+ * @type {boolean}
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.blockOpeningUnsafeSchemes_ =
+ true;
+
+
+/**
+ * Tells the plugin to stop leaking the page's url via the referrer header when
+ * the link text link is clicked. When the user clicks on a link, the
+ * browser makes a request for the link url, passing the url of the current page
+ * in the request headers. If the user wants the current url to be kept secret
+ * (e.g. an unpublished document), the owner of the url that was clicked will
+ * see the secret url in the request headers, and it will no longer be a secret.
+ * Calling this method will not send a referrer header in the request, just as
+ * if the user had opened a blank window and typed the url in themselves.
+ */
+goog.editor.plugins.LinkBubble.prototype.stopReferrerLeaks = function() {
+ // TODO(user): Right now only 2 plugins have this API to stop
+ // referrer leaks. If more plugins need to do this, come up with a way to
+ // enable the functionality in all plugins at once. Same thing for
+ // setBlockOpeningUnsafeSchemes and associated functionality.
+ this.stopReferrerLeaks_ = true;
+};
+
+
+/**
+ * Tells the plugin whether to block URLs with schemes not in the whitelist.
+ * If blocking is enabled, this plugin will not linkify the link in the bubble
+ * popup.
+ * @param {boolean} blockOpeningUnsafeSchemes Whether to block non-whitelisted
+ * schemes.
+ */
+goog.editor.plugins.LinkBubble.prototype.setBlockOpeningUnsafeSchemes =
+ function(blockOpeningUnsafeSchemes) {
+ this.blockOpeningUnsafeSchemes_ = blockOpeningUnsafeSchemes;
+};
+
+
+/**
+ * Sets a whitelist of allowed URL schemes that are safe to open.
+ * Schemes should all be in lowercase. If the plugin is set to block opening
+ * unsafe schemes, user-entered URLs will be converted to lowercase and checked
+ * against this list. The whitelist has no effect if blocking is not enabled.
+ * @param {Array<string>} schemes String array of URL schemes to allow (http,
+ * https, etc.).
+ */
+goog.editor.plugins.LinkBubble.prototype.setSafeToOpenSchemes =
+ function(schemes) {
+ this.safeToOpenSchemes_ = schemes;
+};
+
+
+/** @override */
+goog.editor.plugins.LinkBubble.prototype.getTrogClassId = function() {
+ return 'LinkBubble';
+};
+
+
+/** @override */
+goog.editor.plugins.LinkBubble.prototype.isSupportedCommand =
+ function(command) {
+ return command == goog.editor.Command.UPDATE_LINK_BUBBLE;
+};
+
+
+/** @override */
+goog.editor.plugins.LinkBubble.prototype.execCommandInternal =
+ function(command, var_args) {
+ if (command == goog.editor.Command.UPDATE_LINK_BUBBLE) {
+ this.updateLink_();
+ }
+};
+
+
+/**
+ * Updates the href in the link bubble with a new link.
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.updateLink_ = function() {
+ var targetEl = this.getTargetElement();
+ if (targetEl) {
+ this.closeBubble();
+ this.createBubble(targetEl);
+ }
+};
+
+
+/** @override */
+goog.editor.plugins.LinkBubble.prototype.getBubbleTargetFromSelection =
+ function(selectedElement) {
+ var bubbleTarget = goog.dom.getAncestorByTagNameAndClass(selectedElement,
+ goog.dom.TagName.A);
+
+ if (!bubbleTarget) {
+ // See if the selection is touching the right side of a link, and if so,
+ // show a bubble for that link. The check for "touching" is very brittle,
+ // and currently only guarantees that it will pop up a bubble at the
+ // position the cursor is placed at after the link dialog is closed.
+ // NOTE(robbyw): This assumes this method is always called with
+ // selected element = range.getContainerElement(). Right now this is true,
+ // but attempts to re-use this method for other purposes could cause issues.
+ // TODO(robbyw): Refactor this method to also take a range, and use that.
+ var range = this.getFieldObject().getRange();
+ if (range && range.isCollapsed() && range.getStartOffset() == 0) {
+ var startNode = range.getStartNode();
+ var previous = startNode.previousSibling;
+ if (previous && previous.tagName == goog.dom.TagName.A) {
+ bubbleTarget = previous;
+ }
+ }
+ }
+
+ return /** @type {Element} */ (bubbleTarget);
+};
+
+
+/**
+ * Set the optional function for getting the "test" link of a url.
+ * @param {function(string) : string} func The function to use.
+ */
+goog.editor.plugins.LinkBubble.prototype.setTestLinkUrlFn = function(func) {
+ this.testLinkUrlFn_ = func;
+};
+
+
+/**
+ * Returns the target element url for the bubble.
+ * @return {string} The url href.
+ * @protected
+ */
+goog.editor.plugins.LinkBubble.prototype.getTargetUrl = function() {
+ // Get the href-attribute through getAttribute() rather than the href property
+ // because Google-Toolbar on Firefox with "Send with Gmail" turned on
+ // modifies the href-property of 'mailto:' links but leaves the attribute
+ // untouched.
+ return this.getTargetElement().getAttribute('href') || '';
+};
+
+
+/** @override */
+goog.editor.plugins.LinkBubble.prototype.getBubbleType = function() {
+ return goog.dom.TagName.A;
+};
+
+
+/** @override */
+goog.editor.plugins.LinkBubble.prototype.getBubbleTitle = function() {
+ return goog.ui.editor.messages.MSG_LINK_CAPTION;
+};
+
+
+/**
+ * Returns the message to display for testing a link.
+ * @return {string} The message for testing a link.
+ * @protected
+ */
+goog.editor.plugins.LinkBubble.prototype.getTestLinkMessage = function() {
+ return goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_TEST_LINK;
+};
+
+
+/** @override */
+goog.editor.plugins.LinkBubble.prototype.createBubbleContents = function(
+ bubbleContainer) {
+ var linkObj = this.getLinkToTextObj_();
+
+ // Create linkTextSpan, show plain text for e-mail address or truncate the
+ // text to <= 48 characters so that property bubbles don't grow too wide and
+ // create a link if URL. Only linkify valid links.
+ // TODO(robbyw): Repalce this color with a CSS class.
+ var color = linkObj.valid ? 'black' : 'red';
+ var shouldOpenUrl = this.shouldOpenUrl(linkObj.linkText);
+ var linkTextSpan;
+ if (goog.editor.Link.isLikelyEmailAddress(linkObj.linkText) ||
+ !linkObj.valid || !shouldOpenUrl) {
+ linkTextSpan = this.dom_.createDom(goog.dom.TagName.SPAN,
+ {
+ id: goog.editor.plugins.LinkBubble.LINK_TEXT_ID_,
+ style: 'color:' + color
+ }, this.dom_.createTextNode(linkObj.linkText));
+ } else {
+ var testMsgSpan = this.dom_.createDom(goog.dom.TagName.SPAN,
+ {id: goog.editor.plugins.LinkBubble.TEST_LINK_SPAN_ID_},
+ this.getTestLinkMessage());
+ linkTextSpan = this.dom_.createDom(goog.dom.TagName.SPAN,
+ {
+ id: goog.editor.plugins.LinkBubble.LINK_TEXT_ID_,
+ style: 'color:' + color
+ }, '');
+ var linkText = goog.string.truncateMiddle(linkObj.linkText, 48);
+ // Actually creates a pseudo-link that can't be right-clicked to open in a
+ // new tab, because that would avoid the logic to stop referrer leaks.
+ this.createLink(goog.editor.plugins.LinkBubble.TEST_LINK_ID_,
+ this.dom_.createTextNode(linkText).data,
+ this.testLink,
+ linkTextSpan);
+ }
+
+ var changeLinkSpan = this.createLinkOption(
+ goog.editor.plugins.LinkBubble.CHANGE_LINK_SPAN_ID_);
+ this.createLink(goog.editor.plugins.LinkBubble.CHANGE_LINK_ID_,
+ goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_CHANGE,
+ this.showLinkDialog_, changeLinkSpan);
+
+ // This function is called multiple times - we have to reset the array.
+ this.actionSpans_ = [];
+ for (var i = 0; i < this.extraActions_.length; i++) {
+ var action = this.extraActions_[i];
+ var actionSpan = this.createLinkOption(action.spanId_);
+ this.actionSpans_.push(actionSpan);
+ this.createLink(action.linkId_, action.message_,
+ function() {
+ action.actionFn_(this.getTargetUrl());
+ },
+ actionSpan);
+ }
+
+ var removeLinkSpan = this.createLinkOption(
+ goog.editor.plugins.LinkBubble.DELETE_LINK_SPAN_ID_);
+ this.createLink(goog.editor.plugins.LinkBubble.DELETE_LINK_ID_,
+ goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_REMOVE,
+ this.deleteLink_, removeLinkSpan);
+
+ this.onShow();
+
+ var bubbleContents = this.dom_.createDom(goog.dom.TagName.DIV,
+ {id: goog.editor.plugins.LinkBubble.LINK_DIV_ID_},
+ testMsgSpan || '', linkTextSpan, changeLinkSpan);
+
+ for (i = 0; i < this.actionSpans_.length; i++) {
+ bubbleContents.appendChild(this.actionSpans_[i]);
+ }
+ bubbleContents.appendChild(removeLinkSpan);
+
+ goog.dom.appendChild(bubbleContainer, bubbleContents);
+};
+
+
+/**
+ * Tests the link by opening it in a new tab/window. Should be used as the
+ * click event handler for the test pseudo-link.
+ * @protected
+ */
+goog.editor.plugins.LinkBubble.prototype.testLink = function() {
+ goog.window.open(this.getTestLinkAction_(),
+ {
+ 'target': '_blank',
+ 'noreferrer': this.stopReferrerLeaks_
+ }, this.getFieldObject().getAppWindow());
+};
+
+
+/**
+ * Returns whether the URL should be considered invalid. This always returns
+ * false in the base class, and should be overridden by subclasses that wish
+ * to impose validity rules on URLs.
+ * @param {string} url The url to check.
+ * @return {boolean} Whether the URL should be considered invalid.
+ */
+goog.editor.plugins.LinkBubble.prototype.isInvalidUrl = goog.functions.FALSE;
+
+
+/**
+ * Gets the text to display for a link, based on the type of link
+ * @return {!Object} Returns an object of the form:
+ * {linkText: displayTextForLinkTarget, valid: ifTheLinkIsValid}.
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.getLinkToTextObj_ = function() {
+ var isError;
+ var targetUrl = this.getTargetUrl();
+
+ if (this.isInvalidUrl(targetUrl)) {
+
+ targetUrl = goog.editor.plugins.LinkBubble.MSG_INVALID_URL_LINK_BUBBLE;
+ isError = true;
+ } else if (goog.editor.Link.isMailto(targetUrl)) {
+ targetUrl = targetUrl.substring(7); // 7 == "mailto:".length
+ }
+
+ return {linkText: targetUrl, valid: !isError};
+};
+
+
+/**
+ * Shows the link dialog.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.showLinkDialog_ = function(e) {
+ // Needed when this occurs due to an ENTER key event, else the newly created
+ // dialog manages to have its OK button pressed, causing it to disappear.
+ e.preventDefault();
+
+ this.getFieldObject().execCommand(goog.editor.Command.MODAL_LINK_EDITOR,
+ new goog.editor.Link(
+ /** @type {HTMLAnchorElement} */ (this.getTargetElement()),
+ false));
+ this.closeBubble();
+};
+
+
+/**
+ * Deletes the link associated with the bubble
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.deleteLink_ = function() {
+ this.getFieldObject().dispatchBeforeChange();
+
+ var link = this.getTargetElement();
+ var child = link.lastChild;
+ goog.dom.flattenElement(link);
+ goog.editor.range.placeCursorNextTo(child, false);
+
+ this.closeBubble();
+
+ this.getFieldObject().dispatchChange();
+ this.getFieldObject().focus();
+};
+
+
+/**
+ * Sets the proper state for the action links.
+ * @protected
+ * @override
+ */
+goog.editor.plugins.LinkBubble.prototype.onShow = function() {
+ var linkDiv = this.dom_.getElement(
+ goog.editor.plugins.LinkBubble.LINK_DIV_ID_);
+ if (linkDiv) {
+ var testLinkSpan = this.dom_.getElement(
+ goog.editor.plugins.LinkBubble.TEST_LINK_SPAN_ID_);
+ if (testLinkSpan) {
+ var url = this.getTargetUrl();
+ goog.style.setElementShown(testLinkSpan, !goog.editor.Link.isMailto(url));
+ }
+
+ for (var i = 0; i < this.extraActions_.length; i++) {
+ var action = this.extraActions_[i];
+ var actionSpan = this.dom_.getElement(action.spanId_);
+ if (actionSpan) {
+ goog.style.setElementShown(actionSpan, action.toShowFn_(
+ this.getTargetUrl()));
+ }
+ }
+ }
+};
+
+
+/**
+ * Gets the url for the bubble test link. The test link is the link in the
+ * bubble the user can click on to make sure the link they entered is correct.
+ * @return {string} The url for the bubble link href.
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.getTestLinkAction_ = function() {
+ var targetUrl = this.getTargetUrl();
+ return this.testLinkUrlFn_ ? this.testLinkUrlFn_(targetUrl) : targetUrl;
+};
+
+
+/**
+ * Checks whether the plugin should open the given url in a new window.
+ * @param {string} url The url to check.
+ * @return {boolean} If the plugin should open the given url in a new window.
+ * @protected
+ */
+goog.editor.plugins.LinkBubble.prototype.shouldOpenUrl = function(url) {
+ return !this.blockOpeningUnsafeSchemes_ || this.isSafeSchemeToOpen_(url);
+};
+
+
+/**
+ * Determines whether or not a url has a scheme which is safe to open.
+ * Schemes like javascript are unsafe due to the possibility of XSS.
+ * @param {string} url A url.
+ * @return {boolean} Whether the url has a safe scheme.
+ * @private
+ */
+goog.editor.plugins.LinkBubble.prototype.isSafeSchemeToOpen_ =
+ function(url) {
+ var scheme = goog.uri.utils.getScheme(url) || 'http';
+ return goog.array.contains(this.safeToOpenSchemes_, scheme.toLowerCase());
+};
+
+
+
+/**
+ * Constructor for extra actions that can be added to the link bubble.
+ * @param {string} spanId The ID for the span showing the action.
+ * @param {string} linkId The ID for the link showing the action.
+ * @param {string} message The text for the link showing the action.
+ * @param {function(string):boolean} toShowFn Test function to determine whether
+ * to show the action for the given URL.
+ * @param {function(string):void} actionFn Action function to run when the
+ * action is clicked. Takes the current target URL as a parameter.
+ * @constructor
+ * @final
+ */
+goog.editor.plugins.LinkBubble.Action = function(spanId, linkId, message,
+ toShowFn, actionFn) {
+ this.spanId_ = spanId;
+ this.linkId_ = linkId;
+ this.message_ = message;
+ this.toShowFn_ = toShowFn;
+ this.actionFn_ = actionFn;
+};
[13/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/dragger.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/dragger.js b/externs/GCL/externs/goog/fx/dragger.js
new file mode 100644
index 0000000..30a5a57
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/dragger.js
@@ -0,0 +1,869 @@
+// 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 Drag Utilities.
+ *
+ * Provides extensible functionality for drag & drop behaviour.
+ *
+ * @see ../demos/drag.html
+ * @see ../demos/dragger.html
+ */
+
+
+goog.provide('goog.fx.DragEvent');
+goog.provide('goog.fx.Dragger');
+goog.provide('goog.fx.Dragger.EventType');
+
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+goog.require('goog.events');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.math.Coordinate');
+goog.require('goog.math.Rect');
+goog.require('goog.style');
+goog.require('goog.style.bidi');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * A class that allows mouse or touch-based dragging (moving) of an element
+ *
+ * @param {Element} target The element that will be dragged.
+ * @param {Element=} opt_handle An optional handle to control the drag, if null
+ * the target is used.
+ * @param {goog.math.Rect=} opt_limits Object containing left, top, width,
+ * and height.
+ *
+ * @extends {goog.events.EventTarget}
+ * @constructor
+ */
+goog.fx.Dragger = function(target, opt_handle, opt_limits) {
+ goog.events.EventTarget.call(this);
+ this.target = target;
+ this.handle = opt_handle || target;
+ this.limits = opt_limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
+
+ this.document_ = goog.dom.getOwnerDocument(target);
+ this.eventHandler_ = new goog.events.EventHandler(this);
+ this.registerDisposable(this.eventHandler_);
+
+ // Add listener. Do not use the event handler here since the event handler is
+ // used for listeners added and removed during the drag operation.
+ goog.events.listen(this.handle,
+ [goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
+ this.startDrag, false, this);
+};
+goog.inherits(goog.fx.Dragger, goog.events.EventTarget);
+// Dragger is meant to be extended, but defines most properties on its
+// prototype, thus making it unsuitable for sealing.
+goog.tagUnsealableClass(goog.fx.Dragger);
+
+
+/**
+ * Whether setCapture is supported by the browser.
+ * @private {boolean}
+ * @const
+ */
+goog.fx.Dragger.HAS_SET_CAPTURE_ =
+ // IE (up to and including IE 11) and Gecko after 1.9.3 have setCapture
+ // WebKit does not yet: https://bugs.webkit.org/show_bug.cgi?id=27330
+ (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('12')) ||
+ (goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.3'));
+
+
+/**
+ * Creates copy of node being dragged. This is a utility function to be used
+ * wherever it is inappropriate for the original source to follow the mouse
+ * cursor itself.
+ *
+ * @param {Element} sourceEl Element to copy.
+ * @return {!Element} The clone of {@code sourceEl}.
+ */
+goog.fx.Dragger.cloneNode = function(sourceEl) {
+ var clonedEl = /** @type {Element} */ (sourceEl.cloneNode(true)),
+ origTexts = sourceEl.getElementsByTagName(goog.dom.TagName.TEXTAREA),
+ dragTexts = clonedEl.getElementsByTagName(goog.dom.TagName.TEXTAREA);
+ // Cloning does not copy the current value of textarea elements, so correct
+ // this manually.
+ for (var i = 0; i < origTexts.length; i++) {
+ dragTexts[i].value = origTexts[i].value;
+ }
+ switch (sourceEl.tagName) {
+ case goog.dom.TagName.TR:
+ return goog.dom.createDom(goog.dom.TagName.TABLE, null,
+ goog.dom.createDom(goog.dom.TagName.TBODY,
+ null, clonedEl));
+ case goog.dom.TagName.TD:
+ case goog.dom.TagName.TH:
+ return goog.dom.createDom(
+ goog.dom.TagName.TABLE, null, goog.dom.createDom(
+ goog.dom.TagName.TBODY, null, goog.dom.createDom(
+ goog.dom.TagName.TR, null, clonedEl)));
+ case goog.dom.TagName.TEXTAREA:
+ clonedEl.value = sourceEl.value;
+ default:
+ return clonedEl;
+ }
+};
+
+
+/**
+ * Constants for event names.
+ * @enum {string}
+ */
+goog.fx.Dragger.EventType = {
+ // The drag action was canceled before the START event. Possible reasons:
+ // disabled dragger, dragging with the right mouse button or releasing the
+ // button before reaching the hysteresis distance.
+ EARLY_CANCEL: 'earlycancel',
+ START: 'start',
+ BEFOREDRAG: 'beforedrag',
+ DRAG: 'drag',
+ END: 'end'
+};
+
+
+/**
+ * Reference to drag target element.
+ * @type {Element}
+ */
+goog.fx.Dragger.prototype.target;
+
+
+/**
+ * Reference to the handler that initiates the drag.
+ * @type {Element}
+ */
+goog.fx.Dragger.prototype.handle;
+
+
+/**
+ * Object representing the limits of the drag region.
+ * @type {goog.math.Rect}
+ */
+goog.fx.Dragger.prototype.limits;
+
+
+/**
+ * Whether the element is rendered right-to-left. We initialize this lazily.
+ * @type {boolean|undefined}}
+ * @private
+ */
+goog.fx.Dragger.prototype.rightToLeft_;
+
+
+/**
+ * Current x position of mouse or touch relative to viewport.
+ * @type {number}
+ */
+goog.fx.Dragger.prototype.clientX = 0;
+
+
+/**
+ * Current y position of mouse or touch relative to viewport.
+ * @type {number}
+ */
+goog.fx.Dragger.prototype.clientY = 0;
+
+
+/**
+ * Current x position of mouse or touch relative to screen. Deprecated because
+ * it doesn't take into affect zoom level or pixel density.
+ * @type {number}
+ * @deprecated Consider switching to clientX instead.
+ */
+goog.fx.Dragger.prototype.screenX = 0;
+
+
+/**
+ * Current y position of mouse or touch relative to screen. Deprecated because
+ * it doesn't take into affect zoom level or pixel density.
+ * @type {number}
+ * @deprecated Consider switching to clientY instead.
+ */
+goog.fx.Dragger.prototype.screenY = 0;
+
+
+/**
+ * The x position where the first mousedown or touchstart occurred.
+ * @type {number}
+ */
+goog.fx.Dragger.prototype.startX = 0;
+
+
+/**
+ * The y position where the first mousedown or touchstart occurred.
+ * @type {number}
+ */
+goog.fx.Dragger.prototype.startY = 0;
+
+
+/**
+ * Current x position of drag relative to target's parent.
+ * @type {number}
+ */
+goog.fx.Dragger.prototype.deltaX = 0;
+
+
+/**
+ * Current y position of drag relative to target's parent.
+ * @type {number}
+ */
+goog.fx.Dragger.prototype.deltaY = 0;
+
+
+/**
+ * The current page scroll value.
+ * @type {goog.math.Coordinate}
+ */
+goog.fx.Dragger.prototype.pageScroll;
+
+
+/**
+ * Whether dragging is currently enabled.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.Dragger.prototype.enabled_ = true;
+
+
+/**
+ * Whether object is currently being dragged.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.Dragger.prototype.dragging_ = false;
+
+
+/**
+ * Whether mousedown should be default prevented.
+ * @private {boolean}
+ */
+goog.fx.Dragger.prototype.preventMouseDown_ = true;
+
+
+/**
+ * The amount of distance, in pixels, after which a mousedown or touchstart is
+ * considered a drag.
+ * @type {number}
+ * @private
+ */
+goog.fx.Dragger.prototype.hysteresisDistanceSquared_ = 0;
+
+
+/**
+ * Timestamp of when the mousedown or touchstart occurred.
+ * @type {number}
+ * @private
+ */
+goog.fx.Dragger.prototype.mouseDownTime_ = 0;
+
+
+/**
+ * Reference to a document object to use for the events.
+ * @type {Document}
+ * @private
+ */
+goog.fx.Dragger.prototype.document_;
+
+
+/**
+ * The SCROLL event target used to make drag element follow scrolling.
+ * @type {EventTarget}
+ * @private
+ */
+goog.fx.Dragger.prototype.scrollTarget_;
+
+
+/**
+ * Whether IE drag events cancelling is on.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.Dragger.prototype.ieDragStartCancellingOn_ = false;
+
+
+/**
+ * Whether the dragger implements the changes described in http://b/6324964,
+ * making it truly RTL. This is a temporary flag to allow clients to transition
+ * to the new behavior at their convenience. At some point it will be the
+ * default.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.Dragger.prototype.useRightPositioningForRtl_ = false;
+
+
+/**
+ * Turns on/off true RTL behavior. This should be called immediately after
+ * construction. This is a temporary flag to allow clients to transition
+ * to the new component at their convenience. At some point true will be the
+ * default.
+ * @param {boolean} useRightPositioningForRtl True if "right" should be used for
+ * positioning, false if "left" should be used for positioning.
+ */
+goog.fx.Dragger.prototype.enableRightPositioningForRtl =
+ function(useRightPositioningForRtl) {
+ this.useRightPositioningForRtl_ = useRightPositioningForRtl;
+};
+
+
+/**
+ * Returns the event handler, intended for subclass use.
+ * @return {!goog.events.EventHandler<T>} The event handler.
+ * @this T
+ * @template T
+ */
+goog.fx.Dragger.prototype.getHandler = function() {
+ // TODO(user): templated "this" values currently result in "this" being
+ // "unknown" in the body of the function.
+ var self = /** @type {goog.fx.Dragger} */ (this);
+ return self.eventHandler_;
+};
+
+
+/**
+ * Sets (or reset) the Drag limits after a Dragger is created.
+ * @param {goog.math.Rect?} limits Object containing left, top, width,
+ * height for new Dragger limits. If target is right-to-left and
+ * enableRightPositioningForRtl(true) is called, then rect is interpreted as
+ * right, top, width, and height.
+ */
+goog.fx.Dragger.prototype.setLimits = function(limits) {
+ this.limits = limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
+};
+
+
+/**
+ * Sets the distance the user has to drag the element before a drag operation is
+ * started.
+ * @param {number} distance The number of pixels after which a mousedown and
+ * move is considered a drag.
+ */
+goog.fx.Dragger.prototype.setHysteresis = function(distance) {
+ this.hysteresisDistanceSquared_ = Math.pow(distance, 2);
+};
+
+
+/**
+ * Gets the distance the user has to drag the element before a drag operation is
+ * started.
+ * @return {number} distance The number of pixels after which a mousedown and
+ * move is considered a drag.
+ */
+goog.fx.Dragger.prototype.getHysteresis = function() {
+ return Math.sqrt(this.hysteresisDistanceSquared_);
+};
+
+
+/**
+ * Sets the SCROLL event target to make drag element follow scrolling.
+ *
+ * @param {EventTarget} scrollTarget The event target that dispatches SCROLL
+ * events.
+ */
+goog.fx.Dragger.prototype.setScrollTarget = function(scrollTarget) {
+ this.scrollTarget_ = scrollTarget;
+};
+
+
+/**
+ * Enables cancelling of built-in IE drag events.
+ * @param {boolean} cancelIeDragStart Whether to enable cancelling of IE
+ * dragstart event.
+ */
+goog.fx.Dragger.prototype.setCancelIeDragStart = function(cancelIeDragStart) {
+ this.ieDragStartCancellingOn_ = cancelIeDragStart;
+};
+
+
+/**
+ * @return {boolean} Whether the dragger is enabled.
+ */
+goog.fx.Dragger.prototype.getEnabled = function() {
+ return this.enabled_;
+};
+
+
+/**
+ * Set whether dragger is enabled
+ * @param {boolean} enabled Whether dragger is enabled.
+ */
+goog.fx.Dragger.prototype.setEnabled = function(enabled) {
+ this.enabled_ = enabled;
+};
+
+
+/**
+ * Set whether mousedown should be default prevented.
+ * @param {boolean} preventMouseDown Whether mousedown should be default
+ * prevented.
+ */
+goog.fx.Dragger.prototype.setPreventMouseDown = function(preventMouseDown) {
+ this.preventMouseDown_ = preventMouseDown;
+};
+
+
+/** @override */
+goog.fx.Dragger.prototype.disposeInternal = function() {
+ goog.fx.Dragger.superClass_.disposeInternal.call(this);
+ goog.events.unlisten(this.handle,
+ [goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
+ this.startDrag, false, this);
+ this.cleanUpAfterDragging_();
+
+ this.target = null;
+ this.handle = null;
+};
+
+
+/**
+ * Whether the DOM element being manipulated is rendered right-to-left.
+ * @return {boolean} True if the DOM element is rendered right-to-left, false
+ * otherwise.
+ * @private
+ */
+goog.fx.Dragger.prototype.isRightToLeft_ = function() {
+ if (!goog.isDef(this.rightToLeft_)) {
+ this.rightToLeft_ = goog.style.isRightToLeft(this.target);
+ }
+ return this.rightToLeft_;
+};
+
+
+/**
+ * Event handler that is used to start the drag
+ * @param {goog.events.BrowserEvent} e Event object.
+ */
+goog.fx.Dragger.prototype.startDrag = function(e) {
+ var isMouseDown = e.type == goog.events.EventType.MOUSEDOWN;
+
+ // Dragger.startDrag() can be called by AbstractDragDrop with a mousemove
+ // event and IE does not report pressed mouse buttons on mousemove. Also,
+ // it does not make sense to check for the button if the user is already
+ // dragging.
+
+ if (this.enabled_ && !this.dragging_ &&
+ (!isMouseDown || e.isMouseActionButton())) {
+ this.maybeReinitTouchEvent_(e);
+ if (this.hysteresisDistanceSquared_ == 0) {
+ if (this.fireDragStart_(e)) {
+ this.dragging_ = true;
+ if (this.preventMouseDown_) {
+ e.preventDefault();
+ }
+ } else {
+ // If the start drag is cancelled, don't setup for a drag.
+ return;
+ }
+ } else if (this.preventMouseDown_) {
+ // Need to preventDefault for hysteresis to prevent page getting selected.
+ e.preventDefault();
+ }
+ this.setupDragHandlers();
+
+ this.clientX = this.startX = e.clientX;
+ this.clientY = this.startY = e.clientY;
+ this.screenX = e.screenX;
+ this.screenY = e.screenY;
+ this.computeInitialPosition();
+ this.pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
+
+ this.mouseDownTime_ = goog.now();
+ } else {
+ this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
+ }
+};
+
+
+/**
+ * Sets up event handlers when dragging starts.
+ * @protected
+ */
+goog.fx.Dragger.prototype.setupDragHandlers = function() {
+ var doc = this.document_;
+ var docEl = doc.documentElement;
+ // Use bubbling when we have setCapture since we got reports that IE has
+ // problems with the capturing events in combination with setCapture.
+ var useCapture = !goog.fx.Dragger.HAS_SET_CAPTURE_;
+
+ this.eventHandler_.listen(doc,
+ [goog.events.EventType.TOUCHMOVE, goog.events.EventType.MOUSEMOVE],
+ this.handleMove_, useCapture);
+ this.eventHandler_.listen(doc,
+ [goog.events.EventType.TOUCHEND, goog.events.EventType.MOUSEUP],
+ this.endDrag, useCapture);
+
+ if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
+ docEl.setCapture(false);
+ this.eventHandler_.listen(docEl,
+ goog.events.EventType.LOSECAPTURE,
+ this.endDrag);
+ } else {
+ // Make sure we stop the dragging if the window loses focus.
+ // Don't use capture in this listener because we only want to end the drag
+ // if the actual window loses focus. Since blur events do not bubble we use
+ // a bubbling listener on the window.
+ this.eventHandler_.listen(goog.dom.getWindow(doc),
+ goog.events.EventType.BLUR,
+ this.endDrag);
+ }
+
+ if (goog.userAgent.IE && this.ieDragStartCancellingOn_) {
+ // Cancel IE's 'ondragstart' event.
+ this.eventHandler_.listen(doc, goog.events.EventType.DRAGSTART,
+ goog.events.Event.preventDefault);
+ }
+
+ if (this.scrollTarget_) {
+ this.eventHandler_.listen(this.scrollTarget_, goog.events.EventType.SCROLL,
+ this.onScroll_, useCapture);
+ }
+};
+
+
+/**
+ * Fires a goog.fx.Dragger.EventType.START event.
+ * @param {goog.events.BrowserEvent} e Browser event that triggered the drag.
+ * @return {boolean} False iff preventDefault was called on the DragEvent.
+ * @private
+ */
+goog.fx.Dragger.prototype.fireDragStart_ = function(e) {
+ return this.dispatchEvent(new goog.fx.DragEvent(
+ goog.fx.Dragger.EventType.START, this, e.clientX, e.clientY, e));
+};
+
+
+/**
+ * Unregisters the event handlers that are only active during dragging, and
+ * releases mouse capture.
+ * @private
+ */
+goog.fx.Dragger.prototype.cleanUpAfterDragging_ = function() {
+ this.eventHandler_.removeAll();
+ if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
+ this.document_.releaseCapture();
+ }
+};
+
+
+/**
+ * Event handler that is used to end the drag.
+ * @param {goog.events.BrowserEvent} e Event object.
+ * @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
+ */
+goog.fx.Dragger.prototype.endDrag = function(e, opt_dragCanceled) {
+ this.cleanUpAfterDragging_();
+
+ if (this.dragging_) {
+ this.maybeReinitTouchEvent_(e);
+ this.dragging_ = false;
+
+ var x = this.limitX(this.deltaX);
+ var y = this.limitY(this.deltaY);
+ var dragCanceled = opt_dragCanceled ||
+ e.type == goog.events.EventType.TOUCHCANCEL;
+ this.dispatchEvent(new goog.fx.DragEvent(
+ goog.fx.Dragger.EventType.END, this, e.clientX, e.clientY, e, x, y,
+ dragCanceled));
+ } else {
+ this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
+ }
+};
+
+
+/**
+ * Event handler that is used to end the drag by cancelling it.
+ * @param {goog.events.BrowserEvent} e Event object.
+ */
+goog.fx.Dragger.prototype.endDragCancel = function(e) {
+ this.endDrag(e, true);
+};
+
+
+/**
+ * Re-initializes the event with the first target touch event or, in the case
+ * of a stop event, the last changed touch.
+ * @param {goog.events.BrowserEvent} e A TOUCH... event.
+ * @private
+ */
+goog.fx.Dragger.prototype.maybeReinitTouchEvent_ = function(e) {
+ var type = e.type;
+
+ if (type == goog.events.EventType.TOUCHSTART ||
+ type == goog.events.EventType.TOUCHMOVE) {
+ e.init(e.getBrowserEvent().targetTouches[0], e.currentTarget);
+ } else if (type == goog.events.EventType.TOUCHEND ||
+ type == goog.events.EventType.TOUCHCANCEL) {
+ e.init(e.getBrowserEvent().changedTouches[0], e.currentTarget);
+ }
+};
+
+
+/**
+ * Event handler that is used on mouse / touch move to update the drag
+ * @param {goog.events.BrowserEvent} e Event object.
+ * @private
+ */
+goog.fx.Dragger.prototype.handleMove_ = function(e) {
+ if (this.enabled_) {
+ this.maybeReinitTouchEvent_(e);
+ // dx in right-to-left cases is relative to the right.
+ var sign = this.useRightPositioningForRtl_ &&
+ this.isRightToLeft_() ? -1 : 1;
+ var dx = sign * (e.clientX - this.clientX);
+ var dy = e.clientY - this.clientY;
+ this.clientX = e.clientX;
+ this.clientY = e.clientY;
+ this.screenX = e.screenX;
+ this.screenY = e.screenY;
+
+ if (!this.dragging_) {
+ var diffX = this.startX - this.clientX;
+ var diffY = this.startY - this.clientY;
+ var distance = diffX * diffX + diffY * diffY;
+ if (distance > this.hysteresisDistanceSquared_) {
+ if (this.fireDragStart_(e)) {
+ this.dragging_ = true;
+ } else {
+ // DragListGroup disposes of the dragger if BEFOREDRAGSTART is
+ // canceled.
+ if (!this.isDisposed()) {
+ this.endDrag(e);
+ }
+ return;
+ }
+ }
+ }
+
+ var pos = this.calculatePosition_(dx, dy);
+ var x = pos.x;
+ var y = pos.y;
+
+ if (this.dragging_) {
+
+ var rv = this.dispatchEvent(new goog.fx.DragEvent(
+ goog.fx.Dragger.EventType.BEFOREDRAG, this, e.clientX, e.clientY,
+ e, x, y));
+
+ // Only do the defaultAction and dispatch drag event if predrag didn't
+ // prevent default
+ if (rv) {
+ this.doDrag(e, x, y, false);
+ e.preventDefault();
+ }
+ }
+ }
+};
+
+
+/**
+ * Calculates the drag position.
+ *
+ * @param {number} dx The horizontal movement delta.
+ * @param {number} dy The vertical movement delta.
+ * @return {!goog.math.Coordinate} The newly calculated drag element position.
+ * @private
+ */
+goog.fx.Dragger.prototype.calculatePosition_ = function(dx, dy) {
+ // Update the position for any change in body scrolling
+ var pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
+ dx += pageScroll.x - this.pageScroll.x;
+ dy += pageScroll.y - this.pageScroll.y;
+ this.pageScroll = pageScroll;
+
+ this.deltaX += dx;
+ this.deltaY += dy;
+
+ var x = this.limitX(this.deltaX);
+ var y = this.limitY(this.deltaY);
+ return new goog.math.Coordinate(x, y);
+};
+
+
+/**
+ * Event handler for scroll target scrolling.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.fx.Dragger.prototype.onScroll_ = function(e) {
+ var pos = this.calculatePosition_(0, 0);
+ e.clientX = this.clientX;
+ e.clientY = this.clientY;
+ this.doDrag(e, pos.x, pos.y, true);
+};
+
+
+/**
+ * @param {goog.events.BrowserEvent} e The closure object
+ * representing the browser event that caused a drag event.
+ * @param {number} x The new horizontal position for the drag element.
+ * @param {number} y The new vertical position for the drag element.
+ * @param {boolean} dragFromScroll Whether dragging was caused by scrolling
+ * the associated scroll target.
+ * @protected
+ */
+goog.fx.Dragger.prototype.doDrag = function(e, x, y, dragFromScroll) {
+ this.defaultAction(x, y);
+ this.dispatchEvent(new goog.fx.DragEvent(
+ goog.fx.Dragger.EventType.DRAG, this, e.clientX, e.clientY, e, x, y));
+};
+
+
+/**
+ * Returns the 'real' x after limits are applied (allows for some
+ * limits to be undefined).
+ * @param {number} x X-coordinate to limit.
+ * @return {number} The 'real' X-coordinate after limits are applied.
+ */
+goog.fx.Dragger.prototype.limitX = function(x) {
+ var rect = this.limits;
+ var left = !isNaN(rect.left) ? rect.left : null;
+ var width = !isNaN(rect.width) ? rect.width : 0;
+ var maxX = left != null ? left + width : Infinity;
+ var minX = left != null ? left : -Infinity;
+ return Math.min(maxX, Math.max(minX, x));
+};
+
+
+/**
+ * Returns the 'real' y after limits are applied (allows for some
+ * limits to be undefined).
+ * @param {number} y Y-coordinate to limit.
+ * @return {number} The 'real' Y-coordinate after limits are applied.
+ */
+goog.fx.Dragger.prototype.limitY = function(y) {
+ var rect = this.limits;
+ var top = !isNaN(rect.top) ? rect.top : null;
+ var height = !isNaN(rect.height) ? rect.height : 0;
+ var maxY = top != null ? top + height : Infinity;
+ var minY = top != null ? top : -Infinity;
+ return Math.min(maxY, Math.max(minY, y));
+};
+
+
+/**
+ * Overridable function for computing the initial position of the target
+ * before dragging begins.
+ * @protected
+ */
+goog.fx.Dragger.prototype.computeInitialPosition = function() {
+ this.deltaX = this.useRightPositioningForRtl_ ?
+ goog.style.bidi.getOffsetStart(this.target) : this.target.offsetLeft;
+ this.deltaY = this.target.offsetTop;
+};
+
+
+/**
+ * Overridable function for handling the default action of the drag behaviour.
+ * Normally this is simply moving the element to x,y though in some cases it
+ * might be used to resize the layer. This is basically a shortcut to
+ * implementing a default ondrag event handler.
+ * @param {number} x X-coordinate for target element. In right-to-left, x this
+ * is the number of pixels the target should be moved to from the right.
+ * @param {number} y Y-coordinate for target element.
+ */
+goog.fx.Dragger.prototype.defaultAction = function(x, y) {
+ if (this.useRightPositioningForRtl_ && this.isRightToLeft_()) {
+ this.target.style.right = x + 'px';
+ } else {
+ this.target.style.left = x + 'px';
+ }
+ this.target.style.top = y + 'px';
+};
+
+
+/**
+ * @return {boolean} Whether the dragger is currently in the midst of a drag.
+ */
+goog.fx.Dragger.prototype.isDragging = function() {
+ return this.dragging_;
+};
+
+
+
+/**
+ * Object representing a drag event
+ * @param {string} type Event type.
+ * @param {goog.fx.Dragger} dragobj Drag object initiating event.
+ * @param {number} clientX X-coordinate relative to the viewport.
+ * @param {number} clientY Y-coordinate relative to the viewport.
+ * @param {goog.events.BrowserEvent} browserEvent The closure object
+ * representing the browser event that caused this drag event.
+ * @param {number=} opt_actX Optional actual x for drag if it has been limited.
+ * @param {number=} opt_actY Optional actual y for drag if it has been limited.
+ * @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
+ * @constructor
+ * @extends {goog.events.Event}
+ */
+goog.fx.DragEvent = function(type, dragobj, clientX, clientY, browserEvent,
+ opt_actX, opt_actY, opt_dragCanceled) {
+ goog.events.Event.call(this, type);
+
+ /**
+ * X-coordinate relative to the viewport
+ * @type {number}
+ */
+ this.clientX = clientX;
+
+ /**
+ * Y-coordinate relative to the viewport
+ * @type {number}
+ */
+ this.clientY = clientY;
+
+ /**
+ * The closure object representing the browser event that caused this drag
+ * event.
+ * @type {goog.events.BrowserEvent}
+ */
+ this.browserEvent = browserEvent;
+
+ /**
+ * The real x-position of the drag if it has been limited
+ * @type {number}
+ */
+ this.left = goog.isDef(opt_actX) ? opt_actX : dragobj.deltaX;
+
+ /**
+ * The real y-position of the drag if it has been limited
+ * @type {number}
+ */
+ this.top = goog.isDef(opt_actY) ? opt_actY : dragobj.deltaY;
+
+ /**
+ * Reference to the drag object for this event
+ * @type {goog.fx.Dragger}
+ */
+ this.dragger = dragobj;
+
+ /**
+ * Whether drag was canceled with this event. Used to differentiate between
+ * a legitimate drag END that can result in an action and a drag END which is
+ * a result of a drag cancelation. For now it can happen 1) with drag END
+ * event on FireFox when user drags the mouse out of the window, 2) with
+ * drag END event on IE7 which is generated on MOUSEMOVE event when user
+ * moves the mouse into the document after the mouse button has been
+ * released, 3) when TOUCHCANCEL is raised instead of TOUCHEND (on touch
+ * events).
+ * @type {boolean}
+ */
+ this.dragCanceled = !!opt_dragCanceled;
+};
+goog.inherits(goog.fx.DragEvent, goog.events.Event);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/draglistgroup.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/draglistgroup.js b/externs/GCL/externs/goog/fx/draglistgroup.js
new file mode 100644
index 0000000..dc20ec0
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/draglistgroup.js
@@ -0,0 +1,1312 @@
+// 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 A DragListGroup is a class representing a group of one or more
+ * "drag lists" with items that can be dragged within them and between them.
+ *
+ * @see ../demos/draglistgroup.html
+ */
+
+
+goog.provide('goog.fx.DragListDirection');
+goog.provide('goog.fx.DragListGroup');
+goog.provide('goog.fx.DragListGroup.EventType');
+goog.provide('goog.fx.DragListGroupEvent');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.dom');
+goog.require('goog.dom.classlist');
+goog.require('goog.events');
+goog.require('goog.events.Event');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+goog.require('goog.fx.Dragger');
+goog.require('goog.math.Coordinate');
+goog.require('goog.string');
+goog.require('goog.style');
+
+
+
+/**
+ * A class representing a group of one or more "drag lists" with items that can
+ * be dragged within them and between them.
+ *
+ * Example usage:
+ * var dragListGroup = new goog.fx.DragListGroup();
+ * dragListGroup.setDragItemHandleHoverClass(className1, className2);
+ * dragListGroup.setDraggerElClass(className3);
+ * dragListGroup.addDragList(vertList, goog.fx.DragListDirection.DOWN);
+ * dragListGroup.addDragList(horizList, goog.fx.DragListDirection.RIGHT);
+ * dragListGroup.init();
+ *
+ * @extends {goog.events.EventTarget}
+ * @constructor
+ */
+goog.fx.DragListGroup = function() {
+ goog.events.EventTarget.call(this);
+
+ /**
+ * The drag lists.
+ * @type {Array<Element>}
+ * @private
+ */
+ this.dragLists_ = [];
+
+ /**
+ * All the drag items. Set by init().
+ * @type {Array<Element>}
+ * @private
+ */
+ this.dragItems_ = [];
+
+ /**
+ * Which drag item corresponds to a given handle. Set by init().
+ * Specifically, this maps from the unique ID (as given by goog.getUid)
+ * of the handle to the drag item.
+ * @type {Object}
+ * @private
+ */
+ this.dragItemForHandle_ = {};
+
+ /**
+ * The event handler for this instance.
+ * @type {goog.events.EventHandler<!goog.fx.DragListGroup>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ /**
+ * Whether the setup has been done to make all items in all lists draggable.
+ * @type {boolean}
+ * @private
+ */
+ this.isInitialized_ = false;
+
+ /**
+ * Whether the currDragItem is always displayed. By default the list
+ * collapses, the currDragItem's display is set to none, when we do not
+ * hover over a draglist.
+ * @type {boolean}
+ * @private
+ */
+ this.isCurrDragItemAlwaysDisplayed_ = false;
+
+ /**
+ * Whether to update the position of the currDragItem as we drag, i.e.,
+ * insert the currDragItem each time to the position where it would land if
+ * we were to end the drag at that point. Defaults to true.
+ * @type {boolean}
+ * @private
+ */
+ this.updateWhileDragging_ = true;
+};
+goog.inherits(goog.fx.DragListGroup, goog.events.EventTarget);
+
+
+/**
+ * Enum to indicate the direction that a drag list grows.
+ * @enum {number}
+ */
+goog.fx.DragListDirection = {
+ DOWN: 0, // common
+ RIGHT: 2, // common
+ LEFT: 3, // uncommon (except perhaps for right-to-left interfaces)
+ RIGHT_2D: 4, // common + handles multiple lines if items are wrapped
+ LEFT_2D: 5 // for rtl languages
+};
+
+
+/**
+ * Events dispatched by this class.
+ * @const
+ */
+goog.fx.DragListGroup.EventType = {
+ BEFOREDRAGSTART: 'beforedragstart',
+ DRAGSTART: 'dragstart',
+ BEFOREDRAGMOVE: 'beforedragmove',
+ DRAGMOVE: 'dragmove',
+ BEFOREDRAGEND: 'beforedragend',
+ DRAGEND: 'dragend'
+};
+
+
+// The next 4 are user-supplied CSS classes.
+
+
+/**
+ * The user-supplied CSS classes to add to a drag item on hover (not during a
+ * drag action).
+ * @type {Array|undefined}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.dragItemHoverClasses_;
+
+
+/**
+ * The user-supplied CSS classes to add to a drag item handle on hover (not
+ * during a drag action).
+ * @type {Array|undefined}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.dragItemHandleHoverClasses_;
+
+
+/**
+ * The user-supplied CSS classes to add to the current drag item (during a drag
+ * action).
+ * @type {Array|undefined}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.currDragItemClasses_;
+
+
+/**
+ * The user-supplied CSS classes to add to the clone of the current drag item
+ * that's actually being dragged around (during a drag action).
+ * @type {Array<string>|undefined}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.draggerElClasses_;
+
+
+// The next 5 are info applicable during a drag action.
+
+
+/**
+ * The current drag item being moved.
+ * Note: This is only defined while a drag action is happening.
+ * @type {Element}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.currDragItem_;
+
+
+/**
+ * The drag list that {@code this.currDragItem_} is currently hovering over, or
+ * null if it is not hovering over a list.
+ * @type {Element}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.currHoverList_;
+
+
+/**
+ * The original drag list that the current drag item came from. We need to
+ * remember this in case the user drops the item outside of any lists, in which
+ * case we return the item to its original location.
+ * Note: This is only defined while a drag action is happening.
+ * @type {Element}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.origList_;
+
+
+/**
+ * The original next item in the original list that the current drag item came
+ * from. We need to remember this in case the user drops the item outside of
+ * any lists, in which case we return the item to its original location.
+ * Note: This is only defined while a drag action is happening.
+ * @type {Element}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.origNextItem_;
+
+
+/**
+ * The current item in the list we are hovering over. We need to remember
+ * this in case we do not update the position of the current drag item while
+ * dragging (see {@code updateWhileDragging_}). In this case the current drag
+ * item will be inserted into the list before this element when the drag ends.
+ * @type {Element}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.currHoverItem_;
+
+
+/**
+ * The clone of the current drag item that's actually being dragged around.
+ * Note: This is only defined while a drag action is happening.
+ * @type {Element}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.draggerEl_;
+
+
+/**
+ * The dragger object.
+ * Note: This is only defined while a drag action is happening.
+ * @type {goog.fx.Dragger}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.dragger_;
+
+
+/**
+ * The amount of distance, in pixels, after which a mousedown or touchstart is
+ * considered a drag.
+ * @type {number}
+ * @private
+ */
+goog.fx.DragListGroup.prototype.hysteresisDistance_ = 0;
+
+
+/**
+ * Sets the property of the currDragItem that it is always displayed in the
+ * list.
+ */
+goog.fx.DragListGroup.prototype.setIsCurrDragItemAlwaysDisplayed = function() {
+ this.isCurrDragItemAlwaysDisplayed_ = true;
+};
+
+
+/**
+ * Sets the private property updateWhileDragging_ to false. This disables the
+ * update of the position of the currDragItem while dragging. It will only be
+ * placed to its new location once the drag ends.
+ */
+goog.fx.DragListGroup.prototype.setNoUpdateWhileDragging = function() {
+ this.updateWhileDragging_ = false;
+};
+
+
+/**
+ * Sets the distance the user has to drag the element before a drag operation
+ * is started.
+ * @param {number} distance The number of pixels after which a mousedown and
+ * move is considered a drag.
+ */
+goog.fx.DragListGroup.prototype.setHysteresis = function(distance) {
+ this.hysteresisDistance_ = distance;
+};
+
+
+/**
+ * @return {number} distance The number of pixels after which a mousedown and
+ * move is considered a drag.
+ */
+goog.fx.DragListGroup.prototype.getHysteresis = function() {
+ return this.hysteresisDistance_;
+};
+
+
+/**
+ * Adds a drag list to this DragListGroup.
+ * All calls to this method must happen before the call to init().
+ * Remember that all child nodes (except text nodes) will be made draggable to
+ * any other drag list in this group.
+ *
+ * @param {Element} dragListElement Must be a container for a list of items
+ * that should all be made draggable.
+ * @param {goog.fx.DragListDirection} growthDirection The direction that this
+ * drag list grows in (i.e. if an item is appended to the DOM, the list's
+ * bounding box expands in this direction).
+ * @param {boolean=} opt_unused Unused argument.
+ * @param {string=} opt_dragHoverClass CSS class to apply to this drag list when
+ * the draggerEl hovers over it during a drag action. If present, must be a
+ * single, valid classname (not a string of space-separated classnames).
+ */
+goog.fx.DragListGroup.prototype.addDragList = function(
+ dragListElement, growthDirection, opt_unused, opt_dragHoverClass) {
+ goog.asserts.assert(!this.isInitialized_);
+
+ dragListElement.dlgGrowthDirection_ = growthDirection;
+ dragListElement.dlgDragHoverClass_ = opt_dragHoverClass;
+ this.dragLists_.push(dragListElement);
+};
+
+
+/**
+ * Sets a user-supplied function used to get the "handle" element for a drag
+ * item. The function must accept exactly one argument. The argument may be
+ * any drag item element.
+ *
+ * If not set, the default implementation uses the whole drag item as the
+ * handle.
+ *
+ * @param {function(Element): Element} getHandleForDragItemFn A function that,
+ * given any drag item, returns a reference to its "handle" element
+ * (which may be the drag item element itself).
+ */
+goog.fx.DragListGroup.prototype.setFunctionToGetHandleForDragItem = function(
+ getHandleForDragItemFn) {
+ goog.asserts.assert(!this.isInitialized_);
+ this.getHandleForDragItem_ = getHandleForDragItemFn;
+};
+
+
+/**
+ * Sets a user-supplied CSS class to add to a drag item on hover (not during a
+ * drag action).
+ * @param {...!string} var_args The CSS class or classes.
+ */
+goog.fx.DragListGroup.prototype.setDragItemHoverClass = function(var_args) {
+ goog.asserts.assert(!this.isInitialized_);
+ this.dragItemHoverClasses_ = goog.array.slice(arguments, 0);
+};
+
+
+/**
+ * Sets a user-supplied CSS class to add to a drag item handle on hover (not
+ * during a drag action).
+ * @param {...!string} var_args The CSS class or classes.
+ */
+goog.fx.DragListGroup.prototype.setDragItemHandleHoverClass = function(
+ var_args) {
+ goog.asserts.assert(!this.isInitialized_);
+ this.dragItemHandleHoverClasses_ = goog.array.slice(arguments, 0);
+};
+
+
+/**
+ * Sets a user-supplied CSS class to add to the current drag item (during a
+ * drag action).
+ *
+ * If not set, the default behavior adds visibility:hidden to the current drag
+ * item so that it is a block of empty space in the hover drag list (if any).
+ * If this class is set by the user, then the default behavior does not happen
+ * (unless, of course, the class also contains visibility:hidden).
+ *
+ * @param {...!string} var_args The CSS class or classes.
+ */
+goog.fx.DragListGroup.prototype.setCurrDragItemClass = function(var_args) {
+ goog.asserts.assert(!this.isInitialized_);
+ this.currDragItemClasses_ = goog.array.slice(arguments, 0);
+};
+
+
+/**
+ * Sets a user-supplied CSS class to add to the clone of the current drag item
+ * that's actually being dragged around (during a drag action).
+ * @param {string} draggerElClass The CSS class.
+ */
+goog.fx.DragListGroup.prototype.setDraggerElClass = function(draggerElClass) {
+ goog.asserts.assert(!this.isInitialized_);
+ // Split space-separated classes up into an array.
+ this.draggerElClasses_ = goog.string.trim(draggerElClass).split(' ');
+};
+
+
+/**
+ * Performs the initial setup to make all items in all lists draggable.
+ */
+goog.fx.DragListGroup.prototype.init = function() {
+ if (this.isInitialized_) {
+ return;
+ }
+
+ for (var i = 0, numLists = this.dragLists_.length; i < numLists; i++) {
+ var dragList = this.dragLists_[i];
+
+ var dragItems = goog.dom.getChildren(dragList);
+ for (var j = 0, numItems = dragItems.length; j < numItems; ++j) {
+ this.listenForDragEvents(dragItems[j]);
+ }
+ }
+
+ this.isInitialized_ = true;
+};
+
+
+/**
+ * Adds a single item to the given drag list and sets up the drag listeners for
+ * it.
+ * If opt_index is specified the item is inserted at this index, otherwise the
+ * item is added as the last child of the list.
+ *
+ * @param {!Element} list The drag list where to add item to.
+ * @param {!Element} item The new element to add.
+ * @param {number=} opt_index Index where to insert the item in the list. If not
+ * specified item is inserted as the last child of list.
+ */
+goog.fx.DragListGroup.prototype.addItemToDragList = function(list, item,
+ opt_index) {
+ if (goog.isDef(opt_index)) {
+ goog.dom.insertChildAt(list, item, opt_index);
+ } else {
+ goog.dom.appendChild(list, item);
+ }
+ this.listenForDragEvents(item);
+};
+
+
+/** @override */
+goog.fx.DragListGroup.prototype.disposeInternal = function() {
+ this.eventHandler_.dispose();
+
+ for (var i = 0, n = this.dragLists_.length; i < n; i++) {
+ var dragList = this.dragLists_[i];
+ // Note: IE doesn't allow 'delete' for fields on HTML elements (because
+ // they're not real JS objects in IE), so we just set them to undefined.
+ dragList.dlgGrowthDirection_ = undefined;
+ dragList.dlgDragHoverClass_ = undefined;
+ }
+
+ this.dragLists_.length = 0;
+ this.dragItems_.length = 0;
+ this.dragItemForHandle_ = null;
+
+ // In the case where a drag event is currently in-progress and dispose is
+ // called, this cleans up the extra state.
+ this.cleanupDragDom_();
+
+ goog.fx.DragListGroup.superClass_.disposeInternal.call(this);
+};
+
+
+/**
+ * Caches the heights of each drag list and drag item, except for the current
+ * drag item.
+ *
+ * @param {Element} currDragItem The item currently being dragged.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.recacheListAndItemBounds_ = function(
+ currDragItem) {
+ for (var i = 0, n = this.dragLists_.length; i < n; i++) {
+ var dragList = this.dragLists_[i];
+ dragList.dlgBounds_ = goog.style.getBounds(dragList);
+ }
+
+ for (var i = 0, n = this.dragItems_.length; i < n; i++) {
+ var dragItem = this.dragItems_[i];
+ if (dragItem != currDragItem) {
+ dragItem.dlgBounds_ = goog.style.getBounds(dragItem);
+ }
+ }
+};
+
+
+/**
+ * Listens for drag events on the given drag item. This method is currently used
+ * to initialize drag items.
+ *
+ * @param {Element} dragItem the element to initialize. This element has to be
+ * in one of the drag lists.
+ * @protected
+ */
+goog.fx.DragListGroup.prototype.listenForDragEvents = function(dragItem) {
+ var dragItemHandle = this.getHandleForDragItem_(dragItem);
+ var uid = goog.getUid(dragItemHandle);
+ this.dragItemForHandle_[uid] = dragItem;
+
+ if (this.dragItemHoverClasses_) {
+ this.eventHandler_.listen(
+ dragItem, goog.events.EventType.MOUSEOVER,
+ this.handleDragItemMouseover_);
+ this.eventHandler_.listen(
+ dragItem, goog.events.EventType.MOUSEOUT,
+ this.handleDragItemMouseout_);
+ }
+ if (this.dragItemHandleHoverClasses_) {
+ this.eventHandler_.listen(
+ dragItemHandle, goog.events.EventType.MOUSEOVER,
+ this.handleDragItemHandleMouseover_);
+ this.eventHandler_.listen(
+ dragItemHandle, goog.events.EventType.MOUSEOUT,
+ this.handleDragItemHandleMouseout_);
+ }
+
+ this.dragItems_.push(dragItem);
+ this.eventHandler_.listen(dragItemHandle,
+ [goog.events.EventType.MOUSEDOWN, goog.events.EventType.TOUCHSTART],
+ this.handlePotentialDragStart_);
+};
+
+
+/**
+ * Handles mouse and touch events which may start a drag action.
+ * @param {!goog.events.BrowserEvent} e MOUSEDOWN or TOUCHSTART event.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handlePotentialDragStart_ = function(e) {
+ var uid = goog.getUid(/** @type {Node} */ (e.currentTarget));
+ this.currDragItem_ = /** @type {Element} */ (this.dragItemForHandle_[uid]);
+
+ this.draggerEl_ = this.createDragElementInternal(this.currDragItem_);
+ if (this.draggerElClasses_) {
+ // Add CSS class for the clone, if any.
+ goog.dom.classlist.addAll(
+ goog.asserts.assert(this.draggerEl_), this.draggerElClasses_ || []);
+ }
+
+ // Place the clone (i.e. draggerEl) at the same position as the actual
+ // current drag item. This is a bit tricky since
+ // goog.style.getPageOffset() gets the left-top pos of the border, but
+ // goog.style.setPageOffset() sets the left-top pos of the margin.
+ // It's difficult to adjust for the margins of the clone because it's
+ // difficult to read it: goog.style.getComputedStyle() doesn't work for IE.
+ // Instead, our workaround is simply to set the clone's margins to 0px.
+ this.draggerEl_.style.margin = '0';
+ this.draggerEl_.style.position = 'absolute';
+ this.draggerEl_.style.visibility = 'hidden';
+ var doc = goog.dom.getOwnerDocument(this.currDragItem_);
+ doc.body.appendChild(this.draggerEl_);
+
+ // Important: goog.style.setPageOffset() only works correctly for IE when the
+ // element is already in the document.
+ var currDragItemPos = goog.style.getPageOffset(this.currDragItem_);
+ goog.style.setPageOffset(this.draggerEl_, currDragItemPos);
+
+ this.dragger_ = new goog.fx.Dragger(this.draggerEl_);
+ this.dragger_.setHysteresis(this.hysteresisDistance_);
+
+ // Listen to events on the dragger. These handlers will be unregistered at
+ // DRAGEND, when the dragger is disposed of. We can't use eventHandler_,
+ // because it creates new references to the handler functions at each
+ // dragging action, and keeps them until DragListGroup is disposed of.
+ goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.START,
+ this.handleDragStart_, false, this);
+ goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.END,
+ this.handleDragEnd_, false, this);
+ goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.EARLY_CANCEL,
+ this.cleanup_, false, this);
+ this.dragger_.startDrag(e);
+};
+
+
+/**
+ * Creates copy of node being dragged.
+ *
+ * @param {Element} sourceEl Element to copy.
+ * @return {!Element} The clone of {@code sourceEl}.
+ * @deprecated Use goog.fx.Dragger.cloneNode().
+ * @private
+ */
+goog.fx.DragListGroup.prototype.cloneNode_ = function(sourceEl) {
+ return goog.fx.Dragger.cloneNode(sourceEl);
+};
+
+
+/**
+ * Generates an element to follow the cursor during dragging, given a drag
+ * source element. The default behavior is simply to clone the source element,
+ * but this may be overridden in subclasses. This method is called by
+ * {@code createDragElement()} before the drag class is added.
+ *
+ * @param {Element} sourceEl Drag source element.
+ * @return {!Element} The new drag element.
+ * @protected
+ * @suppress {deprecated}
+ */
+goog.fx.DragListGroup.prototype.createDragElementInternal =
+ function(sourceEl) {
+ return this.cloneNode_(sourceEl);
+};
+
+
+/**
+ * Handles the start of a drag action.
+ * @param {!goog.fx.DragEvent} e goog.fx.Dragger.EventType.START event.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handleDragStart_ = function(e) {
+ if (!this.dispatchEvent(new goog.fx.DragListGroupEvent(
+ goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, this, e.browserEvent,
+ this.currDragItem_, null, null))) {
+ e.preventDefault();
+ this.cleanup_();
+ return;
+ }
+
+ // Record the original location of the current drag item.
+ // Note: this.origNextItem_ may be null.
+ this.origList_ = /** @type {Element} */ (this.currDragItem_.parentNode);
+ this.origNextItem_ = goog.dom.getNextElementSibling(this.currDragItem_);
+ this.currHoverItem_ = this.origNextItem_;
+ this.currHoverList_ = this.origList_;
+
+ // If there's a CSS class specified for the current drag item, add it.
+ // Otherwise, make the actual current drag item hidden (takes up space).
+ if (this.currDragItemClasses_) {
+ goog.dom.classlist.addAll(
+ goog.asserts.assert(this.currDragItem_),
+ this.currDragItemClasses_ || []);
+ } else {
+ this.currDragItem_.style.visibility = 'hidden';
+ }
+
+ // Precompute distances from top-left corner to center for efficiency.
+ var draggerElSize = goog.style.getSize(this.draggerEl_);
+ this.draggerEl_.halfWidth = draggerElSize.width / 2;
+ this.draggerEl_.halfHeight = draggerElSize.height / 2;
+
+ this.draggerEl_.style.visibility = '';
+
+ // Record the bounds of all the drag lists and all the other drag items. This
+ // caching is for efficiency, so that we don't have to recompute the bounds on
+ // each drag move. Do this in the state where the current drag item is not in
+ // any of the lists, except when update while dragging is disabled, as in this
+ // case the current drag item does not get removed until drag ends.
+ if (this.updateWhileDragging_) {
+ this.currDragItem_.style.display = 'none';
+ }
+ this.recacheListAndItemBounds_(this.currDragItem_);
+ this.currDragItem_.style.display = '';
+
+ // Listen to events on the dragger.
+ goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.DRAG,
+ this.handleDragMove_, false, this);
+
+ this.dispatchEvent(
+ new goog.fx.DragListGroupEvent(
+ goog.fx.DragListGroup.EventType.DRAGSTART, this, e.browserEvent,
+ this.currDragItem_, this.draggerEl_, this.dragger_));
+};
+
+
+/**
+ * Handles a drag movement (i.e. DRAG event fired by the dragger).
+ *
+ * @param {goog.fx.DragEvent} dragEvent Event object fired by the dragger.
+ * @return {boolean} The return value for the event.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handleDragMove_ = function(dragEvent) {
+
+ // Compute the center of the dragger element (i.e. the cloned drag item).
+ var draggerElPos = goog.style.getPageOffset(this.draggerEl_);
+ var draggerElCenter = new goog.math.Coordinate(
+ draggerElPos.x + this.draggerEl_.halfWidth,
+ draggerElPos.y + this.draggerEl_.halfHeight);
+
+ // Check whether the center is hovering over one of the drag lists.
+ var hoverList = this.getHoverDragList_(draggerElCenter);
+
+ // If hovering over a list, find the next item (if drag were to end now).
+ var hoverNextItem =
+ hoverList ? this.getHoverNextItem_(hoverList, draggerElCenter) : null;
+
+ var rv = this.dispatchEvent(
+ new goog.fx.DragListGroupEvent(
+ goog.fx.DragListGroup.EventType.BEFOREDRAGMOVE, this, dragEvent,
+ this.currDragItem_, this.draggerEl_, this.dragger_,
+ draggerElCenter, hoverList, hoverNextItem));
+ if (!rv) {
+ return false;
+ }
+
+ if (hoverList) {
+ if (this.updateWhileDragging_) {
+ this.insertCurrDragItem_(hoverList, hoverNextItem);
+ } else {
+ // If update while dragging is disabled do not insert
+ // the dragged item, but update the hovered item instead.
+ this.updateCurrHoverItem(hoverNextItem, draggerElCenter);
+ }
+ this.currDragItem_.style.display = '';
+ // Add drag list's hover class (if any).
+ if (hoverList.dlgDragHoverClass_) {
+ goog.dom.classlist.add(
+ goog.asserts.assert(hoverList), hoverList.dlgDragHoverClass_);
+ }
+
+ } else {
+ // Not hovering over a drag list, so remove the item altogether unless
+ // specified otherwise by the user.
+ if (!this.isCurrDragItemAlwaysDisplayed_) {
+ this.currDragItem_.style.display = 'none';
+ }
+
+ // Remove hover classes (if any) from all drag lists.
+ for (var i = 0, n = this.dragLists_.length; i < n; i++) {
+ var dragList = this.dragLists_[i];
+ if (dragList.dlgDragHoverClass_) {
+ goog.dom.classlist.remove(
+ goog.asserts.assert(dragList), dragList.dlgDragHoverClass_);
+ }
+ }
+ }
+
+ // If the current hover list is different than the last, the lists may have
+ // shrunk, so we should recache the bounds.
+ if (hoverList != this.currHoverList_) {
+ this.currHoverList_ = hoverList;
+ this.recacheListAndItemBounds_(this.currDragItem_);
+ }
+
+ this.dispatchEvent(
+ new goog.fx.DragListGroupEvent(
+ goog.fx.DragListGroup.EventType.DRAGMOVE, this, dragEvent,
+ /** @type {Element} */ (this.currDragItem_),
+ this.draggerEl_, this.dragger_,
+ draggerElCenter, hoverList, hoverNextItem));
+
+ // Return false to prevent selection due to mouse drag.
+ return false;
+};
+
+
+/**
+ * Clear all our temporary fields that are only defined while dragging, and
+ * all the bounds info stored on the drag lists and drag elements.
+ * @param {!goog.events.Event=} opt_e EARLY_CANCEL event from the dragger if
+ * cleanup_ was called as an event handler.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.cleanup_ = function(opt_e) {
+ this.cleanupDragDom_();
+
+ this.currDragItem_ = null;
+ this.currHoverList_ = null;
+ this.origList_ = null;
+ this.origNextItem_ = null;
+ this.draggerEl_ = null;
+ this.dragger_ = null;
+
+ // Note: IE doesn't allow 'delete' for fields on HTML elements (because
+ // they're not real JS objects in IE), so we just set them to null.
+ for (var i = 0, n = this.dragLists_.length; i < n; i++) {
+ this.dragLists_[i].dlgBounds_ = null;
+ }
+ for (var i = 0, n = this.dragItems_.length; i < n; i++) {
+ this.dragItems_[i].dlgBounds_ = null;
+ }
+};
+
+
+/**
+ * Handles the end or the cancellation of a drag action, i.e. END or CLEANUP
+ * event fired by the dragger.
+ *
+ * @param {!goog.fx.DragEvent} dragEvent Event object fired by the dragger.
+ * @return {boolean} Whether the event was handled.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handleDragEnd_ = function(dragEvent) {
+ var rv = this.dispatchEvent(
+ new goog.fx.DragListGroupEvent(
+ goog.fx.DragListGroup.EventType.BEFOREDRAGEND, this, dragEvent,
+ /** @type {Element} */ (this.currDragItem_),
+ this.draggerEl_, this.dragger_));
+ if (!rv) {
+ return false;
+ }
+
+ // If update while dragging is disabled insert the current drag item into
+ // its intended location.
+ if (!this.updateWhileDragging_) {
+ this.insertCurrHoverItem();
+ }
+
+ // The DRAGEND handler may need the new order of the list items. Clean up the
+ // garbage.
+ // TODO(user): Regression test.
+ this.cleanupDragDom_();
+
+ this.dispatchEvent(
+ new goog.fx.DragListGroupEvent(
+ goog.fx.DragListGroup.EventType.DRAGEND, this, dragEvent,
+ this.currDragItem_, this.draggerEl_, this.dragger_));
+
+ this.cleanup_();
+
+ return true;
+};
+
+
+/**
+ * Cleans up DOM changes that are made by the {@code handleDrag*} methods.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.cleanupDragDom_ = function() {
+ // Disposes of the dragger and remove the cloned drag item.
+ goog.dispose(this.dragger_);
+ if (this.draggerEl_) {
+ goog.dom.removeNode(this.draggerEl_);
+ }
+
+ // If the current drag item is not in any list, put it back in its original
+ // location.
+ if (this.currDragItem_ && this.currDragItem_.style.display == 'none') {
+ // Note: this.origNextItem_ may be null, but insertBefore() still works.
+ this.origList_.insertBefore(this.currDragItem_, this.origNextItem_);
+ this.currDragItem_.style.display = '';
+ }
+
+ // If there's a CSS class specified for the current drag item, remove it.
+ // Otherwise, make the current drag item visible (instead of empty space).
+ if (this.currDragItemClasses_ && this.currDragItem_) {
+ goog.dom.classlist.removeAll(
+ goog.asserts.assert(this.currDragItem_),
+ this.currDragItemClasses_ || []);
+ } else if (this.currDragItem_) {
+ this.currDragItem_.style.visibility = 'visible';
+ }
+
+ // Remove hover classes (if any) from all drag lists.
+ for (var i = 0, n = this.dragLists_.length; i < n; i++) {
+ var dragList = this.dragLists_[i];
+ if (dragList.dlgDragHoverClass_) {
+ goog.dom.classlist.remove(
+ goog.asserts.assert(dragList), dragList.dlgDragHoverClass_);
+ }
+ }
+};
+
+
+/**
+ * Default implementation of the function to get the "handle" element for a
+ * drag item. By default, we use the whole drag item as the handle. Users can
+ * change this by calling setFunctionToGetHandleForDragItem().
+ *
+ * @param {Element} dragItem The drag item to get the handle for.
+ * @return {Element} The dragItem element itself.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.getHandleForDragItem_ = function(dragItem) {
+ return dragItem;
+};
+
+
+/**
+ * Handles a MOUSEOVER event fired on a drag item.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handleDragItemMouseover_ = function(e) {
+ var targetEl = goog.asserts.assertElement(e.currentTarget);
+ goog.dom.classlist.addAll(targetEl, this.dragItemHoverClasses_ || []);
+};
+
+
+/**
+ * Handles a MOUSEOUT event fired on a drag item.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handleDragItemMouseout_ = function(e) {
+ var targetEl = goog.asserts.assertElement(e.currentTarget);
+ goog.dom.classlist.removeAll(targetEl, this.dragItemHoverClasses_ || []);
+};
+
+
+/**
+ * Handles a MOUSEOVER event fired on the handle element of a drag item.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handleDragItemHandleMouseover_ = function(e) {
+ var targetEl = goog.asserts.assertElement(e.currentTarget);
+ goog.dom.classlist.addAll(targetEl, this.dragItemHandleHoverClasses_ || []);
+};
+
+
+/**
+ * Handles a MOUSEOUT event fired on the handle element of a drag item.
+ * @param {goog.events.BrowserEvent} e The event.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.handleDragItemHandleMouseout_ = function(e) {
+ var targetEl = goog.asserts.assertElement(e.currentTarget);
+ goog.dom.classlist.removeAll(targetEl,
+ this.dragItemHandleHoverClasses_ || []);
+};
+
+
+/**
+ * Helper for handleDragMove_().
+ * Given the position of the center of the dragger element, figures out whether
+ * it's currently hovering over any of the drag lists.
+ *
+ * @param {goog.math.Coordinate} draggerElCenter The center position of the
+ * dragger element.
+ * @return {Element} If currently hovering over a drag list, returns the drag
+ * list element. Else returns null.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.getHoverDragList_ = function(draggerElCenter) {
+
+ // If the current drag item was in a list last time we did this, then check
+ // that same list first.
+ var prevHoverList = null;
+ if (this.currDragItem_.style.display != 'none') {
+ prevHoverList = /** @type {Element} */ (this.currDragItem_.parentNode);
+ // Important: We can't use the cached bounds for this list because the
+ // cached bounds are based on the case where the current drag item is not
+ // in the list. Since the current drag item is known to be in this list, we
+ // must recompute the list's bounds.
+ var prevHoverListBounds = goog.style.getBounds(prevHoverList);
+ if (this.isInRect_(draggerElCenter, prevHoverListBounds)) {
+ return prevHoverList;
+ }
+ }
+
+ for (var i = 0, n = this.dragLists_.length; i < n; i++) {
+ var dragList = this.dragLists_[i];
+ if (dragList == prevHoverList) {
+ continue;
+ }
+ if (this.isInRect_(draggerElCenter, dragList.dlgBounds_)) {
+ return dragList;
+ }
+ }
+
+ return null;
+};
+
+
+/**
+ * Checks whether a coordinate position resides inside a rectangle.
+ * @param {goog.math.Coordinate} pos The coordinate position.
+ * @param {goog.math.Rect} rect The rectangle.
+ * @return {boolean} True if 'pos' is within the bounds of 'rect'.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.isInRect_ = function(pos, rect) {
+ return pos.x > rect.left && pos.x < rect.left + rect.width &&
+ pos.y > rect.top && pos.y < rect.top + rect.height;
+};
+
+
+/**
+ * Updates the value of currHoverItem_.
+ *
+ * This method is used for insertion only when updateWhileDragging_ is false.
+ * The below implementation is the basic one. This method can be extended by
+ * a subclass to support changes to hovered item (eg: highlighting). Parametr
+ * opt_draggerElCenter can be used for more sophisticated effects.
+ *
+ * @param {Element} hoverNextItem element of the list that is hovered over.
+ * @param {goog.math.Coordinate=} opt_draggerElCenter current position of
+ * the dragged element.
+ * @protected
+ */
+goog.fx.DragListGroup.prototype.updateCurrHoverItem = function(
+ hoverNextItem, opt_draggerElCenter) {
+ if (hoverNextItem) {
+ this.currHoverItem_ = hoverNextItem;
+ }
+};
+
+
+/**
+ * Inserts the currently dragged item in its new place.
+ *
+ * This method is used for insertion only when updateWhileDragging_ is false
+ * (otherwise there is no need for that). In the basic implementation
+ * the element is inserted before the currently hovered over item (this can
+ * be changed by overriding the method in subclasses).
+ *
+ * @protected
+ */
+goog.fx.DragListGroup.prototype.insertCurrHoverItem = function() {
+ this.origList_.insertBefore(this.currDragItem_, this.currHoverItem_);
+};
+
+
+/**
+ * Helper for handleDragMove_().
+ * Given the position of the center of the dragger element, plus the drag list
+ * that it's currently hovering over, figures out the next drag item in the
+ * list that follows the current position of the dragger element. (I.e. if
+ * the drag action ends right now, it would become the item after the current
+ * drag item.)
+ *
+ * @param {Element} hoverList The drag list that we're hovering over.
+ * @param {goog.math.Coordinate} draggerElCenter The center position of the
+ * dragger element.
+ * @return {Element} Returns the earliest item in the hover list that belongs
+ * after the current position of the dragger element. If all items in the
+ * list should come before the current drag item, then returns null.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.getHoverNextItem_ = function(
+ hoverList, draggerElCenter) {
+ if (hoverList == null) {
+ throw Error('getHoverNextItem_ called with null hoverList.');
+ }
+
+ // The definition of what it means for the draggerEl to be "before" a given
+ // item in the hover drag list is not always the same. It changes based on
+ // the growth direction of the hover drag list in question.
+ /** @type {number} */
+ var relevantCoord;
+ var getRelevantBoundFn;
+ var isBeforeFn;
+ var pickClosestRow = false;
+ var distanceToClosestRow = undefined;
+ switch (hoverList.dlgGrowthDirection_) {
+ case goog.fx.DragListDirection.DOWN:
+ // "Before" means draggerElCenter.y is less than item's bottom y-value.
+ relevantCoord = draggerElCenter.y;
+ getRelevantBoundFn = goog.fx.DragListGroup.getBottomBound_;
+ isBeforeFn = goog.fx.DragListGroup.isLessThan_;
+ break;
+ case goog.fx.DragListDirection.RIGHT_2D:
+ pickClosestRow = true;
+ case goog.fx.DragListDirection.RIGHT:
+ // "Before" means draggerElCenter.x is less than item's right x-value.
+ relevantCoord = draggerElCenter.x;
+ getRelevantBoundFn = goog.fx.DragListGroup.getRightBound_;
+ isBeforeFn = goog.fx.DragListGroup.isLessThan_;
+ break;
+ case goog.fx.DragListDirection.LEFT_2D:
+ pickClosestRow = true;
+ case goog.fx.DragListDirection.LEFT:
+ // "Before" means draggerElCenter.x is greater than item's left x-value.
+ relevantCoord = draggerElCenter.x;
+ getRelevantBoundFn = goog.fx.DragListGroup.getLeftBound_;
+ isBeforeFn = goog.fx.DragListGroup.isGreaterThan_;
+ break;
+ }
+
+ // This holds the earliest drag item found so far that should come after
+ // this.currDragItem_ in the hover drag list (based on draggerElCenter).
+ var earliestAfterItem = null;
+ // This is the position of the relevant bound for the earliestAfterItem,
+ // where "relevant" is determined by the growth direction of hoverList.
+ var earliestAfterItemRelevantBound;
+
+ var hoverListItems = goog.dom.getChildren(hoverList);
+ for (var i = 0, n = hoverListItems.length; i < n; i++) {
+ var item = hoverListItems[i];
+ if (item == this.currDragItem_) {
+ continue;
+ }
+
+ var relevantBound = getRelevantBoundFn(item.dlgBounds_);
+ // When the hoverlist is broken into multiple rows (i.e., in the case of
+ // LEFT_2D and RIGHT_2D) it is no longer enough to only look at the
+ // x-coordinate alone in order to find the {@earliestAfterItem} in the
+ // hoverlist. Make sure it is chosen from the row closest to the
+ // {@code draggerElCenter}.
+ if (pickClosestRow) {
+ var distanceToRow = goog.fx.DragListGroup.verticalDistanceFromItem_(item,
+ draggerElCenter);
+ // Initialize the distance to the closest row to the current value if
+ // undefined.
+ if (!goog.isDef(distanceToClosestRow)) {
+ distanceToClosestRow = distanceToRow;
+ }
+ if (isBeforeFn(relevantCoord, relevantBound) &&
+ (earliestAfterItemRelevantBound == undefined ||
+ (distanceToRow < distanceToClosestRow) ||
+ ((distanceToRow == distanceToClosestRow) &&
+ (isBeforeFn(relevantBound, earliestAfterItemRelevantBound) ||
+ relevantBound == earliestAfterItemRelevantBound)))) {
+ earliestAfterItem = item;
+ earliestAfterItemRelevantBound = relevantBound;
+ }
+ // Update distance to closest row.
+ if (distanceToRow < distanceToClosestRow) {
+ distanceToClosestRow = distanceToRow;
+ }
+ } else if (isBeforeFn(relevantCoord, relevantBound) &&
+ (earliestAfterItemRelevantBound == undefined ||
+ isBeforeFn(relevantBound, earliestAfterItemRelevantBound))) {
+ earliestAfterItem = item;
+ earliestAfterItemRelevantBound = relevantBound;
+ }
+ }
+ // If we ended up picking an element that is not in the closest row it can
+ // only happen if we should have picked the last one in which case there is
+ // no consecutive element.
+ if (!goog.isNull(earliestAfterItem) &&
+ goog.fx.DragListGroup.verticalDistanceFromItem_(
+ earliestAfterItem, draggerElCenter) > distanceToClosestRow) {
+ return null;
+ } else {
+ return earliestAfterItem;
+ }
+};
+
+
+/**
+ * Private helper for getHoverNextItem().
+ * Given an item and a target determine the vertical distance from the item's
+ * center to the target.
+ * @param {Element} item The item to measure the distance from.
+ * @param {goog.math.Coordinate} target The (x,y) coordinate of the target
+ * to measure the distance to.
+ * @return {number} The vertical distance between the center of the item and
+ * the target.
+ * @private
+ */
+goog.fx.DragListGroup.verticalDistanceFromItem_ = function(item, target) {
+ var itemBounds = item.dlgBounds_;
+ var itemCenterY = itemBounds.top + (itemBounds.height - 1) / 2;
+ return Math.abs(target.y - itemCenterY);
+};
+
+
+/**
+ * Private helper for getHoverNextItem_().
+ * Given the bounds of an item, computes the item's bottom y-value.
+ * @param {goog.math.Rect} itemBounds The bounds of the item.
+ * @return {number} The item's bottom y-value.
+ * @private
+ */
+goog.fx.DragListGroup.getBottomBound_ = function(itemBounds) {
+ return itemBounds.top + itemBounds.height - 1;
+};
+
+
+/**
+ * Private helper for getHoverNextItem_().
+ * Given the bounds of an item, computes the item's right x-value.
+ * @param {goog.math.Rect} itemBounds The bounds of the item.
+ * @return {number} The item's right x-value.
+ * @private
+ */
+goog.fx.DragListGroup.getRightBound_ = function(itemBounds) {
+ return itemBounds.left + itemBounds.width - 1;
+};
+
+
+/**
+ * Private helper for getHoverNextItem_().
+ * Given the bounds of an item, computes the item's left x-value.
+ * @param {goog.math.Rect} itemBounds The bounds of the item.
+ * @return {number} The item's left x-value.
+ * @private
+ */
+goog.fx.DragListGroup.getLeftBound_ = function(itemBounds) {
+ return itemBounds.left || 0;
+};
+
+
+/**
+ * Private helper for getHoverNextItem_().
+ * @param {number} a Number to compare.
+ * @param {number} b Number to compare.
+ * @return {boolean} Whether a is less than b.
+ * @private
+ */
+goog.fx.DragListGroup.isLessThan_ = function(a, b) {
+ return a < b;
+};
+
+
+/**
+ * Private helper for getHoverNextItem_().
+ * @param {number} a Number to compare.
+ * @param {number} b Number to compare.
+ * @return {boolean} Whether a is greater than b.
+ * @private
+ */
+goog.fx.DragListGroup.isGreaterThan_ = function(a, b) {
+ return a > b;
+};
+
+
+/**
+ * Inserts the current drag item to the appropriate location in the drag list
+ * that we're hovering over (if the current drag item is not already there).
+ *
+ * @param {Element} hoverList The drag list we're hovering over.
+ * @param {Element} hoverNextItem The next item in the hover drag list.
+ * @private
+ */
+goog.fx.DragListGroup.prototype.insertCurrDragItem_ = function(
+ hoverList, hoverNextItem) {
+ if (this.currDragItem_.parentNode != hoverList ||
+ goog.dom.getNextElementSibling(this.currDragItem_) != hoverNextItem) {
+ // The current drag item is not in the correct location, so we move it.
+ // Note: hoverNextItem may be null, but insertBefore() still works.
+ hoverList.insertBefore(this.currDragItem_, hoverNextItem);
+ }
+};
+
+
+
+/**
+ * The event object dispatched by DragListGroup.
+ * The fields draggerElCenter, hoverList, and hoverNextItem are only available
+ * for the BEFOREDRAGMOVE and DRAGMOVE events.
+ *
+ * @param {string} type The event type string.
+ * @param {goog.fx.DragListGroup} dragListGroup A reference to the associated
+ * DragListGroup object.
+ * @param {goog.events.BrowserEvent|goog.fx.DragEvent} event The event fired
+ * by the browser or fired by the dragger.
+ * @param {Element} currDragItem The current drag item being moved.
+ * @param {Element} draggerEl The clone of the current drag item that's actually
+ * being dragged around.
+ * @param {goog.fx.Dragger} dragger The dragger object.
+ * @param {goog.math.Coordinate=} opt_draggerElCenter The current center
+ * position of the draggerEl.
+ * @param {Element=} opt_hoverList The current drag list that's being hovered
+ * over, or null if the center of draggerEl is outside of any drag lists.
+ * If not null and the drag action ends right now, then currDragItem will
+ * end up in this list.
+ * @param {Element=} opt_hoverNextItem The current next item in the hoverList
+ * that the draggerEl is hovering over. (I.e. If the drag action ends
+ * right now, then this item would become the next item after the new
+ * location of currDragItem.) May be null if not applicable or if
+ * currDragItem would be added to the end of hoverList.
+ * @constructor
+ * @extends {goog.events.Event}
+ */
+goog.fx.DragListGroupEvent = function(
+ type, dragListGroup, event, currDragItem, draggerEl, dragger,
+ opt_draggerElCenter, opt_hoverList, opt_hoverNextItem) {
+ goog.events.Event.call(this, type);
+
+ /**
+ * A reference to the associated DragListGroup object.
+ * @type {goog.fx.DragListGroup}
+ */
+ this.dragListGroup = dragListGroup;
+
+ /**
+ * The event fired by the browser or fired by the dragger.
+ * @type {goog.events.BrowserEvent|goog.fx.DragEvent}
+ */
+ this.event = event;
+
+ /**
+ * The current drag item being move.
+ * @type {Element}
+ */
+ this.currDragItem = currDragItem;
+
+ /**
+ * The clone of the current drag item that's actually being dragged around.
+ * @type {Element}
+ */
+ this.draggerEl = draggerEl;
+
+ /**
+ * The dragger object.
+ * @type {goog.fx.Dragger}
+ */
+ this.dragger = dragger;
+
+ /**
+ * The current center position of the draggerEl.
+ * @type {goog.math.Coordinate|undefined}
+ */
+ this.draggerElCenter = opt_draggerElCenter;
+
+ /**
+ * The current drag list that's being hovered over, or null if the center of
+ * draggerEl is outside of any drag lists. (I.e. If not null and the drag
+ * action ends right now, then currDragItem will end up in this list.)
+ * @type {Element|undefined}
+ */
+ this.hoverList = opt_hoverList;
+
+ /**
+ * The current next item in the hoverList that the draggerEl is hovering over.
+ * (I.e. If the drag action ends right now, then this item would become the
+ * next item after the new location of currDragItem.) May be null if not
+ * applicable or if currDragItem would be added to the end of hoverList.
+ * @type {Element|undefined}
+ */
+ this.hoverNextItem = opt_hoverNextItem;
+};
+goog.inherits(goog.fx.DragListGroupEvent, goog.events.Event);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/dragscrollsupport.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/dragscrollsupport.js b/externs/GCL/externs/goog/fx/dragscrollsupport.js
new file mode 100644
index 0000000..66072e8
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/dragscrollsupport.js
@@ -0,0 +1,300 @@
+// 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 Class to support scrollable containers for drag and drop.
+ *
+ * @author dgajda@google.com (Damian Gajda)
+ */
+
+goog.provide('goog.fx.DragScrollSupport');
+
+goog.require('goog.Disposable');
+goog.require('goog.Timer');
+goog.require('goog.dom');
+goog.require('goog.events.EventHandler');
+goog.require('goog.events.EventType');
+goog.require('goog.math.Coordinate');
+goog.require('goog.style');
+
+
+
+/**
+ * A scroll support class. Currently this class will automatically scroll
+ * a scrollable container node and scroll it by a fixed amount at a timed
+ * interval when the mouse is moved above or below the container or in vertical
+ * margin areas. Intended for use in drag and drop. This could potentially be
+ * made more general and could support horizontal scrolling.
+ *
+ * @param {Element} containerNode A container that can be scrolled.
+ * @param {number=} opt_margin Optional margin to use while scrolling.
+ * @param {boolean=} opt_externalMouseMoveTracking Whether mouse move events
+ * are tracked externally by the client object which calls the mouse move
+ * event handler, useful when events are generated for more than one source
+ * element and/or are not real mousemove events.
+ * @constructor
+ * @extends {goog.Disposable}
+ * @see ../demos/dragscrollsupport.html
+ */
+goog.fx.DragScrollSupport = function(containerNode, opt_margin,
+ opt_externalMouseMoveTracking) {
+ goog.Disposable.call(this);
+
+ /**
+ * The container to be scrolled.
+ * @type {Element}
+ * @private
+ */
+ this.containerNode_ = containerNode;
+
+ /**
+ * Scroll timer that will scroll the container until it is stopped.
+ * It will scroll when the mouse is outside the scrolling area of the
+ * container.
+ *
+ * @type {goog.Timer}
+ * @private
+ */
+ this.scrollTimer_ = new goog.Timer(goog.fx.DragScrollSupport.TIMER_STEP_);
+
+ /**
+ * EventHandler used to set up and tear down listeners.
+ * @type {goog.events.EventHandler<!goog.fx.DragScrollSupport>}
+ * @private
+ */
+ this.eventHandler_ = new goog.events.EventHandler(this);
+
+ /**
+ * The current scroll delta.
+ * @type {goog.math.Coordinate}
+ * @private
+ */
+ this.scrollDelta_ = new goog.math.Coordinate();
+
+ /**
+ * The container bounds.
+ * @type {goog.math.Rect}
+ * @private
+ */
+ this.containerBounds_ = goog.style.getBounds(containerNode);
+
+ /**
+ * The margin for triggering a scroll.
+ * @type {number}
+ * @private
+ */
+ this.margin_ = opt_margin || 0;
+
+ /**
+ * The bounding rectangle which if left triggers scrolling.
+ * @type {goog.math.Rect}
+ * @private
+ */
+ this.scrollBounds_ = opt_margin ?
+ this.constrainBounds_(this.containerBounds_.clone()) :
+ this.containerBounds_;
+
+ this.setupListeners_(!!opt_externalMouseMoveTracking);
+};
+goog.inherits(goog.fx.DragScrollSupport, goog.Disposable);
+
+
+/**
+ * The scroll timer step in ms.
+ * @type {number}
+ * @private
+ */
+goog.fx.DragScrollSupport.TIMER_STEP_ = 50;
+
+
+/**
+ * The scroll step in pixels.
+ * @type {number}
+ * @private
+ */
+goog.fx.DragScrollSupport.SCROLL_STEP_ = 8;
+
+
+/**
+ * The suggested scrolling margin.
+ * @type {number}
+ */
+goog.fx.DragScrollSupport.MARGIN = 32;
+
+
+/**
+ * Whether scrolling should be constrained to happen only when the cursor is
+ * inside the container node.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.DragScrollSupport.prototype.constrainScroll_ = false;
+
+
+/**
+ * Whether horizontal scrolling is allowed.
+ * @type {boolean}
+ * @private
+ */
+goog.fx.DragScrollSupport.prototype.horizontalScrolling_ = true;
+
+
+/**
+ * Sets whether scrolling should be constrained to happen only when the cursor
+ * is inside the container node.
+ * NOTE: If a margin is not set, then it does not make sense to
+ * contain the scroll, because in that case scroll will never be triggered.
+ * @param {boolean} constrain Whether scrolling should be constrained to happen
+ * only when the cursor is inside the container node.
+ */
+goog.fx.DragScrollSupport.prototype.setConstrainScroll = function(constrain) {
+ this.constrainScroll_ = !!this.margin_ && constrain;
+};
+
+
+/**
+ * Sets whether horizontal scrolling is allowed.
+ * @param {boolean} scrolling Whether horizontal scrolling is allowed.
+ */
+goog.fx.DragScrollSupport.prototype.setHorizontalScrolling =
+ function(scrolling) {
+ this.horizontalScrolling_ = scrolling;
+};
+
+
+/**
+ * Constrains the container bounds with respect to the margin.
+ *
+ * @param {goog.math.Rect} bounds The container element.
+ * @return {goog.math.Rect} The bounding rectangle used to calculate scrolling
+ * direction.
+ * @private
+ */
+goog.fx.DragScrollSupport.prototype.constrainBounds_ = function(bounds) {
+ var margin = this.margin_;
+ if (margin) {
+ var quarterHeight = bounds.height * 0.25;
+ var yMargin = Math.min(margin, quarterHeight);
+ bounds.top += yMargin;
+ bounds.height -= 2 * yMargin;
+
+ var quarterWidth = bounds.width * 0.25;
+ var xMargin = Math.min(margin, quarterWidth);
+ bounds.top += xMargin;
+ bounds.height -= 2 * xMargin;
+ }
+ return bounds;
+};
+
+
+/**
+ * Attaches listeners and activates automatic scrolling.
+ * @param {boolean} externalMouseMoveTracking Whether to enable internal
+ * mouse move event handling.
+ * @private
+ */
+goog.fx.DragScrollSupport.prototype.setupListeners_ = function(
+ externalMouseMoveTracking) {
+ if (!externalMouseMoveTracking) {
+ // Track mouse pointer position to determine scroll direction.
+ this.eventHandler_.listen(goog.dom.getOwnerDocument(this.containerNode_),
+ goog.events.EventType.MOUSEMOVE, this.onMouseMove);
+ }
+
+ // Scroll with a constant speed.
+ this.eventHandler_.listen(this.scrollTimer_, goog.Timer.TICK, this.onTick_);
+};
+
+
+/**
+ * Handler for timer tick event, scrolls the container by one scroll step if
+ * needed.
+ * @param {goog.events.Event} event Timer tick event.
+ * @private
+ */
+goog.fx.DragScrollSupport.prototype.onTick_ = function(event) {
+ this.containerNode_.scrollTop += this.scrollDelta_.y;
+ this.containerNode_.scrollLeft += this.scrollDelta_.x;
+};
+
+
+/**
+ * Handler for mouse moves events.
+ * @param {goog.events.Event} event Mouse move event.
+ */
+goog.fx.DragScrollSupport.prototype.onMouseMove = function(event) {
+ var deltaX = this.horizontalScrolling_ ? this.calculateScrollDelta(
+ event.clientX, this.scrollBounds_.left, this.scrollBounds_.width) : 0;
+ var deltaY = this.calculateScrollDelta(event.clientY,
+ this.scrollBounds_.top, this.scrollBounds_.height);
+ this.scrollDelta_.x = deltaX;
+ this.scrollDelta_.y = deltaY;
+
+ // If the scroll data is 0 or the event fired outside of the
+ // bounds of the container node.
+ if ((!deltaX && !deltaY) ||
+ (this.constrainScroll_ &&
+ !this.isInContainerBounds_(event.clientX, event.clientY))) {
+ this.scrollTimer_.stop();
+ } else if (!this.scrollTimer_.enabled) {
+ this.scrollTimer_.start();
+ }
+};
+
+
+/**
+ * Gets whether the input coordinate is in the container bounds.
+ * @param {number} x The x coordinate.
+ * @param {number} y The y coordinate.
+ * @return {boolean} Whether the input coordinate is in the container bounds.
+ * @private
+ */
+goog.fx.DragScrollSupport.prototype.isInContainerBounds_ = function(x, y) {
+ var containerBounds = this.containerBounds_;
+ return containerBounds.left <= x &&
+ containerBounds.left + containerBounds.width >= x &&
+ containerBounds.top <= y &&
+ containerBounds.top + containerBounds.height >= y;
+};
+
+
+/**
+ * Calculates scroll delta.
+ *
+ * @param {number} coordinate Current mouse pointer coordinate.
+ * @param {number} min The coordinate value below which scrolling up should be
+ * started.
+ * @param {number} rangeLength The length of the range in which scrolling should
+ * be disabled and above which scrolling down should be started.
+ * @return {number} The calculated scroll delta.
+ * @protected
+ */
+goog.fx.DragScrollSupport.prototype.calculateScrollDelta = function(
+ coordinate, min, rangeLength) {
+ var delta = 0;
+ if (coordinate < min) {
+ delta = -goog.fx.DragScrollSupport.SCROLL_STEP_;
+ } else if (coordinate > min + rangeLength) {
+ delta = goog.fx.DragScrollSupport.SCROLL_STEP_;
+ }
+ return delta;
+};
+
+
+/** @override */
+goog.fx.DragScrollSupport.prototype.disposeInternal = function() {
+ goog.fx.DragScrollSupport.superClass_.disposeInternal.call(this);
+ this.eventHandler_.dispose();
+ this.scrollTimer_.dispose();
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/easing.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/easing.js b/externs/GCL/externs/goog/fx/easing.js
new file mode 100644
index 0000000..fda5122
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/easing.js
@@ -0,0 +1,85 @@
+// 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 Easing functions for animations.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+goog.provide('goog.fx.easing');
+
+
+/**
+ * Ease in - Start slow and speed up.
+ * @param {number} t Input between 0 and 1.
+ * @return {number} Output between 0 and 1.
+ */
+goog.fx.easing.easeIn = function(t) {
+ return goog.fx.easing.easeInInternal_(t, 3);
+};
+
+
+/**
+ * Ease in with specifiable exponent.
+ * @param {number} t Input between 0 and 1.
+ * @param {number} exp Ease exponent.
+ * @return {number} Output between 0 and 1.
+ * @private
+ */
+goog.fx.easing.easeInInternal_ = function(t, exp) {
+ return Math.pow(t, exp);
+};
+
+
+/**
+ * Ease out - Start fastest and slows to a stop.
+ * @param {number} t Input between 0 and 1.
+ * @return {number} Output between 0 and 1.
+ */
+goog.fx.easing.easeOut = function(t) {
+ return goog.fx.easing.easeOutInternal_(t, 3);
+};
+
+
+/**
+ * Ease out with specifiable exponent.
+ * @param {number} t Input between 0 and 1.
+ * @param {number} exp Ease exponent.
+ * @return {number} Output between 0 and 1.
+ * @private
+ */
+goog.fx.easing.easeOutInternal_ = function(t, exp) {
+ return 1 - goog.fx.easing.easeInInternal_(1 - t, exp);
+};
+
+
+/**
+ * Ease out long - Start fastest and slows to a stop with a long ease.
+ * @param {number} t Input between 0 and 1.
+ * @return {number} Output between 0 and 1.
+ */
+goog.fx.easing.easeOutLong = function(t) {
+ return goog.fx.easing.easeOutInternal_(t, 4);
+};
+
+
+/**
+ * Ease in and out - Start slow, speed up, then slow down.
+ * @param {number} t Input between 0 and 1.
+ * @return {number} Output between 0 and 1.
+ */
+goog.fx.easing.inAndOut = function(t) {
+ return 3 * t * t - 2 * t * t * t;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/fx.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/fx.js b/externs/GCL/externs/goog/fx/fx.js
new file mode 100644
index 0000000..10314b6
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/fx.js
@@ -0,0 +1,34 @@
+// 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 Legacy stub for the goog.fx namespace. Requires the moved
+ * namespaces. Animation and easing have been moved to animation.js and
+ * easing.js. Users of this stub should move off so we may remove it in the
+ * future.
+ *
+ * @author nnaze@google.com (Nathan Naze)
+ * @suppress {extraRequire} All the requires in this file are "extra"
+ * because this file is not actually using them.
+ */
+
+goog.provide('goog.fx');
+
+goog.require('goog.asserts');
+goog.require('goog.fx.Animation');
+goog.require('goog.fx.Animation.EventType');
+goog.require('goog.fx.Animation.State');
+goog.require('goog.fx.AnimationEvent');
+goog.require('goog.fx.Transition.EventType');
+goog.require('goog.fx.easing');
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/fx/transition.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/fx/transition.js b/externs/GCL/externs/goog/fx/transition.js
new file mode 100644
index 0000000..57c4304
--- /dev/null
+++ b/externs/GCL/externs/goog/fx/transition.js
@@ -0,0 +1,76 @@
+// 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 An interface for transition animation. This is a simple
+ * interface that allows for playing and stopping a transition. It adds
+ * a simple event model with BEGIN and END event.
+ *
+ * @author chrishenry@google.com (Chris Henry)
+ */
+
+goog.provide('goog.fx.Transition');
+goog.provide('goog.fx.Transition.EventType');
+
+
+
+/**
+ * An interface for programmatic transition. Must extend
+ * {@code goog.events.EventTarget}.
+ * @interface
+ */
+goog.fx.Transition = function() {};
+
+
+/**
+ * Transition event types.
+ * @enum {string}
+ */
+goog.fx.Transition.EventType = {
+ /** Dispatched when played for the first time OR when it is resumed. */
+ PLAY: 'play',
+
+ /** Dispatched only when the animation starts from the beginning. */
+ BEGIN: 'begin',
+
+ /** Dispatched only when animation is restarted after a pause. */
+ RESUME: 'resume',
+
+ /**
+ * Dispatched when animation comes to the end of its duration OR stop
+ * is called.
+ */
+ END: 'end',
+
+ /** Dispatched only when stop is called. */
+ STOP: 'stop',
+
+ /** Dispatched only when animation comes to its end naturally. */
+ FINISH: 'finish',
+
+ /** Dispatched when an animation is paused. */
+ PAUSE: 'pause'
+};
+
+
+/**
+ * Plays the transition.
+ */
+goog.fx.Transition.prototype.play;
+
+
+/**
+ * Stops the transition.
+ */
+goog.fx.Transition.prototype.stop;
[32/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserrange/browserrange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/browserrange/browserrange.js b/externs/GCL/externs/goog/dom/browserrange/browserrange.js
new file mode 100644
index 0000000..0cd70e7
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/browserrange/browserrange.js
@@ -0,0 +1,149 @@
+// 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 namespace and interface, as
+ * well as several useful utility functions.
+ *
+ * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ *
+ * @supported IE6, IE7, FF1.5+, Safari.
+ */
+
+
+goog.provide('goog.dom.browserrange');
+goog.provide('goog.dom.browserrange.Error');
+
+goog.require('goog.dom');
+goog.require('goog.dom.BrowserFeature');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.browserrange.GeckoRange');
+goog.require('goog.dom.browserrange.IeRange');
+goog.require('goog.dom.browserrange.OperaRange');
+goog.require('goog.dom.browserrange.W3cRange');
+goog.require('goog.dom.browserrange.WebKitRange');
+goog.require('goog.userAgent');
+
+
+/**
+ * Common error constants.
+ * @enum {string}
+ */
+goog.dom.browserrange.Error = {
+ NOT_IMPLEMENTED: 'Not Implemented'
+};
+
+
+// NOTE(robbyw): While it would be nice to eliminate the duplicate switches
+// below, doing so uncovers bugs in the JsCompiler in which
+// necessary code is stripped out.
+
+
+/**
+ * Static method that returns the proper type of browser range.
+ * @param {Range|TextRange} range A browser range object.
+ * @return {!goog.dom.browserrange.AbstractRange} A wrapper object.
+ */
+goog.dom.browserrange.createRange = function(range) {
+ if (goog.dom.BrowserFeature.LEGACY_IE_RANGES) {
+ return new goog.dom.browserrange.IeRange(
+ /** @type {TextRange} */ (range),
+ goog.dom.getOwnerDocument(range.parentElement()));
+ } else if (goog.userAgent.WEBKIT) {
+ return new goog.dom.browserrange.WebKitRange(
+ /** @type {Range} */ (range));
+ } else if (goog.userAgent.GECKO) {
+ return new goog.dom.browserrange.GeckoRange(
+ /** @type {Range} */ (range));
+ } else if (goog.userAgent.OPERA) {
+ return new goog.dom.browserrange.OperaRange(
+ /** @type {Range} */ (range));
+ } else {
+ // Default other browsers, including Opera, to W3c ranges.
+ return new goog.dom.browserrange.W3cRange(
+ /** @type {Range} */ (range));
+ }
+};
+
+
+/**
+ * Static method that returns the proper type of browser range.
+ * @param {Node} node The node to select.
+ * @return {!goog.dom.browserrange.AbstractRange} A wrapper object.
+ */
+goog.dom.browserrange.createRangeFromNodeContents = function(node) {
+ if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
+ return goog.dom.browserrange.IeRange.createFromNodeContents(node);
+ } else if (goog.userAgent.WEBKIT) {
+ return goog.dom.browserrange.WebKitRange.createFromNodeContents(node);
+ } else if (goog.userAgent.GECKO) {
+ return goog.dom.browserrange.GeckoRange.createFromNodeContents(node);
+ } else if (goog.userAgent.OPERA) {
+ return goog.dom.browserrange.OperaRange.createFromNodeContents(node);
+ } else {
+ // Default other browsers to W3c ranges.
+ return goog.dom.browserrange.W3cRange.createFromNodeContents(node);
+ }
+};
+
+
+/**
+ * Static method that returns the proper type of browser range.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the node to start. This is
+ * either the index into the childNodes array for element startNodes or
+ * the index into the character array for text startNodes.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the node to end. This is
+ * either the index into the childNodes array for element endNodes or
+ * the index into the character array for text endNodes.
+ * @return {!goog.dom.browserrange.AbstractRange} A wrapper object.
+ */
+goog.dom.browserrange.createRangeFromNodes = function(startNode, startOffset,
+ endNode, endOffset) {
+ if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
+ return goog.dom.browserrange.IeRange.createFromNodes(startNode, startOffset,
+ endNode, endOffset);
+ } else if (goog.userAgent.WEBKIT) {
+ return goog.dom.browserrange.WebKitRange.createFromNodes(startNode,
+ startOffset, endNode, endOffset);
+ } else if (goog.userAgent.GECKO) {
+ return goog.dom.browserrange.GeckoRange.createFromNodes(startNode,
+ startOffset, endNode, endOffset);
+ } else if (goog.userAgent.OPERA) {
+ return goog.dom.browserrange.OperaRange.createFromNodes(startNode,
+ startOffset, endNode, endOffset);
+ } else {
+ // Default other browsers to W3c ranges.
+ return goog.dom.browserrange.W3cRange.createFromNodes(startNode,
+ startOffset, endNode, endOffset);
+ }
+};
+
+
+/**
+ * Tests whether the given node can contain a range end point.
+ * @param {Node} node The node to check.
+ * @return {boolean} Whether the given node can contain a range end point.
+ */
+goog.dom.browserrange.canContainRangeEndpoint = function(node) {
+ // NOTE(user, bloom): This is not complete, as divs with style -
+ // 'display:inline-block' or 'position:absolute' can also not contain range
+ // endpoints. A more complete check is to see if that element can be partially
+ // selected (can be container) or not.
+ return goog.dom.canHaveChildren(node) ||
+ node.nodeType == goog.dom.NodeType.TEXT;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserrange/geckorange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/browserrange/geckorange.js b/externs/GCL/externs/goog/dom/browserrange/geckorange.js
new file mode 100644
index 0000000..b01f2dd
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/browserrange/geckorange.js
@@ -0,0 +1,88 @@
+// 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 Gecko specific range wrapper. Inherits most
+ * functionality from W3CRange, but adds exceptions as necessary.
+ *
+ * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.browserrange.GeckoRange');
+
+goog.require('goog.dom.browserrange.W3cRange');
+
+
+
+/**
+ * The constructor for Gecko specific browser ranges.
+ * @param {Range} range The range object.
+ * @constructor
+ * @extends {goog.dom.browserrange.W3cRange}
+ * @final
+ */
+goog.dom.browserrange.GeckoRange = function(range) {
+ goog.dom.browserrange.W3cRange.call(this, range);
+};
+goog.inherits(goog.dom.browserrange.GeckoRange, goog.dom.browserrange.W3cRange);
+
+
+/**
+ * Creates a range object that selects the given node's text.
+ * @param {Node} node The node to select.
+ * @return {!goog.dom.browserrange.GeckoRange} A Gecko range wrapper object.
+ */
+goog.dom.browserrange.GeckoRange.createFromNodeContents = function(node) {
+ return new goog.dom.browserrange.GeckoRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
+};
+
+
+/**
+ * Creates a range object that selects between the given nodes.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the node to start.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the node to end.
+ * @return {!goog.dom.browserrange.GeckoRange} A wrapper object.
+ */
+goog.dom.browserrange.GeckoRange.createFromNodes = function(startNode,
+ startOffset, endNode, endOffset) {
+ return new goog.dom.browserrange.GeckoRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode,
+ startOffset, endNode, endOffset));
+};
+
+
+/** @override */
+goog.dom.browserrange.GeckoRange.prototype.selectInternal = function(
+ selection, reversed) {
+ if (!reversed || this.isCollapsed()) {
+ // The base implementation for select() is more robust, and works fine for
+ // collapsed and forward ranges. This works around
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=773137, and is tested by
+ // range_test.html's testFocusedElementDisappears.
+ goog.dom.browserrange.GeckoRange.base(
+ this, 'selectInternal', selection, reversed);
+ } else {
+ // Reversed selection -- start with a caret on the end node, and extend it
+ // back to the start. Unfortunately, collapse() fails when focus is
+ // invalid.
+ selection.collapse(this.getEndNode(), this.getEndOffset());
+ selection.extend(this.getStartNode(), this.getStartOffset());
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserrange/ierange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/browserrange/ierange.js b/externs/GCL/externs/goog/dom/browserrange/ierange.js
new file mode 100644
index 0000000..a2add21
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/browserrange/ierange.js
@@ -0,0 +1,935 @@
+// 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 IE browser specific range wrapper.
+ *
+ * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.browserrange.IeRange');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.RangeEndpoint');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.browserrange.AbstractRange');
+goog.require('goog.log');
+goog.require('goog.string');
+
+
+
+/**
+ * The constructor for IE specific browser ranges.
+ * @param {TextRange} range The range object.
+ * @param {Document} doc The document the range exists in.
+ * @constructor
+ * @extends {goog.dom.browserrange.AbstractRange}
+ * @final
+ */
+goog.dom.browserrange.IeRange = function(range, doc) {
+ /**
+ * Lazy cache of the node containing the entire selection.
+ * @private {Node}
+ */
+ this.parentNode_ = null;
+
+ /**
+ * Lazy cache of the node containing the start of the selection.
+ * @private {Node}
+ */
+ this.startNode_ = null;
+
+ /**
+ * Lazy cache of the node containing the end of the selection.
+ * @private {Node}
+ */
+ this.endNode_ = null;
+
+ /**
+ * Lazy cache of the offset in startNode_ where this range starts.
+ * @private {number}
+ */
+ this.startOffset_ = -1;
+
+ /**
+ * Lazy cache of the offset in endNode_ where this range ends.
+ * @private {number}
+ */
+ this.endOffset_ = -1;
+
+ /**
+ * The browser range object this class wraps.
+ * @private {TextRange}
+ */
+ this.range_ = range;
+
+ /**
+ * The document the range exists in.
+ * @private {Document}
+ */
+ this.doc_ = doc;
+};
+goog.inherits(goog.dom.browserrange.IeRange,
+ goog.dom.browserrange.AbstractRange);
+
+
+/**
+ * Logging object.
+ * @type {goog.log.Logger}
+ * @private
+ */
+goog.dom.browserrange.IeRange.logger_ =
+ goog.log.getLogger('goog.dom.browserrange.IeRange');
+
+
+/**
+ * Returns a browser range spanning the given node's contents.
+ * @param {Node} node The node to select.
+ * @return {!TextRange} A browser range spanning the node's contents.
+ * @private
+ */
+goog.dom.browserrange.IeRange.getBrowserRangeForNode_ = function(node) {
+ var nodeRange = goog.dom.getOwnerDocument(node).body.createTextRange();
+ if (node.nodeType == goog.dom.NodeType.ELEMENT) {
+ // Elements are easy.
+ nodeRange.moveToElementText(node);
+ // Note(user) : If there are no child nodes of the element, the
+ // range.htmlText includes the element's outerHTML. The range created above
+ // is not collapsed, and should be collapsed explicitly.
+ // Example : node = <div></div>
+ // But if the node is sth like <br>, it shouldnt be collapsed.
+ if (goog.dom.browserrange.canContainRangeEndpoint(node) &&
+ !node.childNodes.length) {
+ nodeRange.collapse(false);
+ }
+ } else {
+ // Text nodes are hard.
+ // Compute the offset from the nearest element related position.
+ var offset = 0;
+ var sibling = node;
+ while (sibling = sibling.previousSibling) {
+ var nodeType = sibling.nodeType;
+ if (nodeType == goog.dom.NodeType.TEXT) {
+ offset += sibling.length;
+ } else if (nodeType == goog.dom.NodeType.ELEMENT) {
+ // Move to the space after this element.
+ nodeRange.moveToElementText(sibling);
+ break;
+ }
+ }
+
+ if (!sibling) {
+ nodeRange.moveToElementText(node.parentNode);
+ }
+
+ nodeRange.collapse(!sibling);
+
+ if (offset) {
+ nodeRange.move('character', offset);
+ }
+
+ nodeRange.moveEnd('character', node.length);
+ }
+
+ return nodeRange;
+};
+
+
+/**
+ * Returns a browser range spanning the given nodes.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the start node.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the end node.
+ * @return {!TextRange} A browser range spanning the node's contents.
+ * @private
+ */
+goog.dom.browserrange.IeRange.getBrowserRangeForNodes_ = function(startNode,
+ startOffset, endNode, endOffset) {
+ // Create a range starting at the correct start position.
+ var child, collapse = false;
+ if (startNode.nodeType == goog.dom.NodeType.ELEMENT) {
+ if (startOffset > startNode.childNodes.length) {
+ goog.log.error(goog.dom.browserrange.IeRange.logger_,
+ 'Cannot have startOffset > startNode child count');
+ }
+ child = startNode.childNodes[startOffset];
+ collapse = !child;
+ startNode = child || startNode.lastChild || startNode;
+ startOffset = 0;
+ }
+ var leftRange = goog.dom.browserrange.IeRange.
+ getBrowserRangeForNode_(startNode);
+
+ // This happens only when startNode is a text node.
+ if (startOffset) {
+ leftRange.move('character', startOffset);
+ }
+
+
+ // The range movements in IE are still an approximation to the standard W3C
+ // behavior, and IE has its trickery when it comes to htmlText and text
+ // properties of the range. So we short-circuit computation whenever we can.
+ if (startNode == endNode && startOffset == endOffset) {
+ leftRange.collapse(true);
+ return leftRange;
+ }
+
+ // This can happen only when the startNode is an element, and there is no node
+ // at the given offset. We start at the last point inside the startNode in
+ // that case.
+ if (collapse) {
+ leftRange.collapse(false);
+ }
+
+ // Create a range that ends at the right position.
+ collapse = false;
+ if (endNode.nodeType == goog.dom.NodeType.ELEMENT) {
+ if (endOffset > endNode.childNodes.length) {
+ goog.log.error(goog.dom.browserrange.IeRange.logger_,
+ 'Cannot have endOffset > endNode child count');
+ }
+ child = endNode.childNodes[endOffset];
+ endNode = child || endNode.lastChild || endNode;
+ endOffset = 0;
+ collapse = !child;
+ }
+ var rightRange = goog.dom.browserrange.IeRange.
+ getBrowserRangeForNode_(endNode);
+ rightRange.collapse(!collapse);
+ if (endOffset) {
+ rightRange.moveEnd('character', endOffset);
+ }
+
+ // Merge and return.
+ leftRange.setEndPoint('EndToEnd', rightRange);
+ return leftRange;
+};
+
+
+/**
+ * Create a range object that selects the given node's text.
+ * @param {Node} node The node to select.
+ * @return {!goog.dom.browserrange.IeRange} An IE range wrapper object.
+ */
+goog.dom.browserrange.IeRange.createFromNodeContents = function(node) {
+ var range = new goog.dom.browserrange.IeRange(
+ goog.dom.browserrange.IeRange.getBrowserRangeForNode_(node),
+ goog.dom.getOwnerDocument(node));
+
+ if (!goog.dom.browserrange.canContainRangeEndpoint(node)) {
+ range.startNode_ = range.endNode_ = range.parentNode_ = node.parentNode;
+ range.startOffset_ = goog.array.indexOf(range.parentNode_.childNodes, node);
+ range.endOffset_ = range.startOffset_ + 1;
+ } else {
+ // Note(user) : Emulate the behavior of W3CRange - Go to deepest possible
+ // range containers on both edges. It seems W3CRange did this to match the
+ // IE behavior, and now it is a circle. Changing W3CRange may break clients
+ // in all sorts of ways.
+ var tempNode, leaf = node;
+ while ((tempNode = leaf.firstChild) &&
+ goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
+ leaf = tempNode;
+ }
+ range.startNode_ = leaf;
+ range.startOffset_ = 0;
+
+ leaf = node;
+ while ((tempNode = leaf.lastChild) &&
+ goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
+ leaf = tempNode;
+ }
+ range.endNode_ = leaf;
+ range.endOffset_ = leaf.nodeType == goog.dom.NodeType.ELEMENT ?
+ leaf.childNodes.length : leaf.length;
+ range.parentNode_ = node;
+ }
+ return range;
+};
+
+
+/**
+ * Static method that returns the proper type of browser range.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the start node.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the end node.
+ * @return {!goog.dom.browserrange.AbstractRange} A wrapper object.
+ */
+goog.dom.browserrange.IeRange.createFromNodes = function(startNode,
+ startOffset, endNode, endOffset) {
+ var range = new goog.dom.browserrange.IeRange(
+ goog.dom.browserrange.IeRange.getBrowserRangeForNodes_(startNode,
+ startOffset, endNode, endOffset),
+ goog.dom.getOwnerDocument(startNode));
+ range.startNode_ = startNode;
+ range.startOffset_ = startOffset;
+ range.endNode_ = endNode;
+ range.endOffset_ = endOffset;
+ return range;
+};
+
+
+/**
+ * @return {!goog.dom.browserrange.IeRange} A clone of this range.
+ * @override
+ */
+goog.dom.browserrange.IeRange.prototype.clone = function() {
+ var range = new goog.dom.browserrange.IeRange(
+ this.range_.duplicate(), this.doc_);
+ range.parentNode_ = this.parentNode_;
+ range.startNode_ = this.startNode_;
+ range.endNode_ = this.endNode_;
+ return range;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getBrowserRange = function() {
+ return this.range_;
+};
+
+
+/**
+ * Clears the cached values for containers.
+ * @private
+ */
+goog.dom.browserrange.IeRange.prototype.clearCachedValues_ = function() {
+ this.parentNode_ = this.startNode_ = this.endNode_ = null;
+ this.startOffset_ = this.endOffset_ = -1;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getContainer = function() {
+ if (!this.parentNode_) {
+ var selectText = this.range_.text;
+
+ // If the selection ends with spaces, we need to remove these to get the
+ // parent container of only the real contents. This is to get around IE's
+ // inconsistency where it selects the spaces after a word when you double
+ // click, but leaves out the spaces during execCommands.
+ var range = this.range_.duplicate();
+ // We can't use goog.string.trimRight, as that will remove other whitespace
+ // too.
+ var rightTrimmedSelectText = selectText.replace(/ +$/, '');
+ var numSpacesAtEnd = selectText.length - rightTrimmedSelectText.length;
+ if (numSpacesAtEnd) {
+ range.moveEnd('character', -numSpacesAtEnd);
+ }
+
+ // Get the parent node. This should be the end, but alas, it is not.
+ var parent = range.parentElement();
+
+ var htmlText = range.htmlText;
+ var htmlTextLen = goog.string.stripNewlines(htmlText).length;
+ if (this.isCollapsed() && htmlTextLen > 0) {
+ return (this.parentNode_ = parent);
+ }
+
+ // Deal with selection bug where IE thinks one of the selection's children
+ // is actually the selection's parent. Relies on the assumption that the
+ // HTML text of the parent container is longer than the length of the
+ // selection's HTML text.
+
+ // Also note IE will sometimes insert \r and \n whitespace, which should be
+ // disregarded. Otherwise the loop may run too long and return wrong parent
+ while (htmlTextLen > goog.string.stripNewlines(parent.outerHTML).length) {
+ parent = parent.parentNode;
+ }
+
+ // Deal with IE's selecting the outer tags when you double click
+ // If the innerText is the same, then we just want the inner node
+ while (parent.childNodes.length == 1 &&
+ parent.innerText == goog.dom.browserrange.IeRange.getNodeText_(
+ parent.firstChild)) {
+ // A container should be an element which can have children or a text
+ // node. Elements like IMG, BR, etc. can not be containers.
+ if (!goog.dom.browserrange.canContainRangeEndpoint(parent.firstChild)) {
+ break;
+ }
+ parent = parent.firstChild;
+ }
+
+ // If the selection is empty, we may need to do extra work to position it
+ // properly.
+ if (selectText.length == 0) {
+ parent = this.findDeepestContainer_(parent);
+ }
+
+ this.parentNode_ = parent;
+ }
+
+ return this.parentNode_;
+};
+
+
+/**
+ * Helper method to find the deepest parent for this range, starting
+ * the search from {@code node}, which must contain the range.
+ * @param {Node} node The node to start the search from.
+ * @return {Node} The deepest parent for this range.
+ * @private
+ */
+goog.dom.browserrange.IeRange.prototype.findDeepestContainer_ = function(node) {
+ var childNodes = node.childNodes;
+ for (var i = 0, len = childNodes.length; i < len; i++) {
+ var child = childNodes[i];
+
+ if (goog.dom.browserrange.canContainRangeEndpoint(child)) {
+ var childRange =
+ goog.dom.browserrange.IeRange.getBrowserRangeForNode_(child);
+ var start = goog.dom.RangeEndpoint.START;
+ var end = goog.dom.RangeEndpoint.END;
+
+ // There are two types of erratic nodes where the range over node has
+ // different htmlText than the node's outerHTML.
+ // Case 1 - A node with magic child. In this case :
+ // nodeRange.htmlText shows ('<p> </p>), while
+ // node.outerHTML doesn't show the magic node (<p></p>).
+ // Case 2 - Empty span. In this case :
+ // node.outerHTML shows '<span></span>'
+ // node.htmlText is just empty string ''.
+ var isChildRangeErratic = (childRange.htmlText != child.outerHTML);
+
+ // Moreover the inRange comparison fails only when the
+ var isNativeInRangeErratic = this.isCollapsed() && isChildRangeErratic;
+
+ // In case 2 mentioned above, childRange is also collapsed. So we need to
+ // compare start of this range with both start and end of child range.
+ var inChildRange = isNativeInRangeErratic ?
+ (this.compareBrowserRangeEndpoints(childRange, start, start) >= 0 &&
+ this.compareBrowserRangeEndpoints(childRange, start, end) <= 0) :
+ this.range_.inRange(childRange);
+ if (inChildRange) {
+ return this.findDeepestContainer_(child);
+ }
+ }
+ }
+
+ return node;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getStartNode = function() {
+ if (!this.startNode_) {
+ this.startNode_ = this.getEndpointNode_(goog.dom.RangeEndpoint.START);
+ if (this.isCollapsed()) {
+ this.endNode_ = this.startNode_;
+ }
+ }
+ return this.startNode_;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getStartOffset = function() {
+ if (this.startOffset_ < 0) {
+ this.startOffset_ = this.getOffset_(goog.dom.RangeEndpoint.START);
+ if (this.isCollapsed()) {
+ this.endOffset_ = this.startOffset_;
+ }
+ }
+ return this.startOffset_;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getEndNode = function() {
+ if (this.isCollapsed()) {
+ return this.getStartNode();
+ }
+ if (!this.endNode_) {
+ this.endNode_ = this.getEndpointNode_(goog.dom.RangeEndpoint.END);
+ }
+ return this.endNode_;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getEndOffset = function() {
+ if (this.isCollapsed()) {
+ return this.getStartOffset();
+ }
+ if (this.endOffset_ < 0) {
+ this.endOffset_ = this.getOffset_(goog.dom.RangeEndpoint.END);
+ if (this.isCollapsed()) {
+ this.startOffset_ = this.endOffset_;
+ }
+ }
+ return this.endOffset_;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.compareBrowserRangeEndpoints = function(
+ range, thisEndpoint, otherEndpoint) {
+ return this.range_.compareEndPoints(
+ (thisEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End') +
+ 'To' +
+ (otherEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End'),
+ range);
+};
+
+
+/**
+ * Recurses to find the correct node for the given endpoint.
+ * @param {goog.dom.RangeEndpoint} endpoint The endpoint to get the node for.
+ * @param {Node=} opt_node Optional node to start the search from.
+ * @return {Node} The deepest node containing the endpoint.
+ * @private
+ */
+goog.dom.browserrange.IeRange.prototype.getEndpointNode_ = function(endpoint,
+ opt_node) {
+
+ /** @type {Node} */
+ var node = opt_node || this.getContainer();
+
+ // If we're at a leaf in the DOM, we're done.
+ if (!node || !node.firstChild) {
+ return node;
+ }
+
+ var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END;
+ var isStartEndpoint = endpoint == start;
+
+ // Find the first/last child that overlaps the selection.
+ // NOTE(user) : One of the children can be the magic node. This
+ // node will have only nodeType property as valid and accessible. All other
+ // dom related properties like ownerDocument, parentNode, nextSibling etc
+ // cause error when accessed. Therefore use the for-loop on childNodes to
+ // iterate.
+ for (var j = 0, length = node.childNodes.length; j < length; j++) {
+ var i = isStartEndpoint ? j : length - j - 1;
+ var child = node.childNodes[i];
+ var childRange;
+ try {
+ childRange = goog.dom.browserrange.createRangeFromNodeContents(child);
+ } catch (e) {
+ // If the child is the magic node, then the above will throw
+ // error. The magic node exists only when editing using keyboard, so can
+ // not add any unit test.
+ continue;
+ }
+ var ieRange = childRange.getBrowserRange();
+
+ // Case 1 : Finding end points when this range is collapsed.
+ // Note that in case of collapsed range, getEnd{Node,Offset} call
+ // getStart{Node,Offset}.
+ if (this.isCollapsed()) {
+ // Handle situations where caret is not in a text node. In such cases,
+ // the adjacent child won't be a valid range endpoint container.
+ if (!goog.dom.browserrange.canContainRangeEndpoint(child)) {
+ // The following handles a scenario like <div><BR>[caret]<BR></div>,
+ // where point should be (div, 1).
+ if (this.compareBrowserRangeEndpoints(ieRange, start, start) == 0) {
+ this.startOffset_ = this.endOffset_ = i;
+ return node;
+ }
+ } else if (childRange.containsRange(this)) {
+ // For collapsed range, we should invert the containsRange check with
+ // childRange.
+ return this.getEndpointNode_(endpoint, child);
+ }
+
+ // Case 2 - The first child encountered to have overlap this range is
+ // contained entirely in this range.
+ } else if (this.containsRange(childRange)) {
+ // If it is an element which can not be a range endpoint container, the
+ // current child offset can be used to deduce the endpoint offset.
+ if (!goog.dom.browserrange.canContainRangeEndpoint(child)) {
+
+ // Container can't be any deeper, so current node is the container.
+ if (isStartEndpoint) {
+ this.startOffset_ = i;
+ } else {
+ this.endOffset_ = i + 1;
+ }
+ return node;
+ }
+
+ // If child can contain range endpoints, recurse inside this child.
+ return this.getEndpointNode_(endpoint, child);
+
+ // Case 3 - Partial non-adjacency overlap.
+ } else if (this.compareBrowserRangeEndpoints(ieRange, start, end) < 0 &&
+ this.compareBrowserRangeEndpoints(ieRange, end, start) > 0) {
+ // If this child overlaps the selection partially, recurse down to find
+ // the first/last child the next level down that overlaps the selection
+ // completely. We do not consider edge-adjacency (== 0) as overlap.
+ return this.getEndpointNode_(endpoint, child);
+ }
+
+ }
+
+ // None of the children of this node overlapped the selection, that means
+ // the selection starts/ends in this node directly.
+ return node;
+};
+
+
+/**
+ * Compares one endpoint of this range with the endpoint of a node.
+ * For internal methods, we should prefer this method to containsNode.
+ * containsNode has a lot of false negatives when we're dealing with
+ * {@code <br>} tags.
+ *
+ * @param {Node} node The node 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 node
+ * to compare with.
+ * @return {number} 0 if the endpoints are equal, negative if this range
+ * endpoint comes before the other node endpoint, and positive otherwise.
+ * @private
+ */
+goog.dom.browserrange.IeRange.prototype.compareNodeEndpoints_ =
+ function(node, thisEndpoint, otherEndpoint) {
+ return this.range_.compareEndPoints(
+ (thisEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End') +
+ 'To' +
+ (otherEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End'),
+ goog.dom.browserrange.createRangeFromNodeContents(node).
+ getBrowserRange());
+};
+
+
+/**
+ * Returns the offset into the start/end container.
+ * @param {goog.dom.RangeEndpoint} endpoint The endpoint to get the offset for.
+ * @param {Node=} opt_container The container to get the offset relative to.
+ * Defaults to the value returned by getStartNode/getEndNode.
+ * @return {number} The offset.
+ * @private
+ */
+goog.dom.browserrange.IeRange.prototype.getOffset_ = function(endpoint,
+ opt_container) {
+ var isStartEndpoint = endpoint == goog.dom.RangeEndpoint.START;
+ var container = opt_container ||
+ (isStartEndpoint ? this.getStartNode() : this.getEndNode());
+
+ if (container.nodeType == goog.dom.NodeType.ELEMENT) {
+ // Find the first/last child that overlaps the selection
+ var children = container.childNodes;
+ var len = children.length;
+ var edge = isStartEndpoint ? 0 : len - 1;
+ var sign = isStartEndpoint ? 1 : - 1;
+
+ // We find the index in the child array of the endpoint of the selection.
+ for (var i = edge; i >= 0 && i < len; i += sign) {
+ var child = children[i];
+ // Ignore the child nodes, which could be end point containers.
+ if (goog.dom.browserrange.canContainRangeEndpoint(child)) {
+ continue;
+ }
+ // Stop looping when we reach the edge of the selection.
+ var endPointCompare =
+ this.compareNodeEndpoints_(child, endpoint, endpoint);
+ if (endPointCompare == 0) {
+ return isStartEndpoint ? i : i + 1;
+ }
+ }
+
+ // When starting from the end in an empty container, we erroneously return
+ // -1: fix this to return 0.
+ return i == -1 ? 0 : i;
+ } else {
+ // Get a temporary range object.
+ var range = this.range_.duplicate();
+
+ // Create a range that selects the entire container.
+ var nodeRange = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(
+ container);
+
+ // Now, intersect our range with the container range - this should give us
+ // the part of our selection that is in the container.
+ range.setEndPoint(isStartEndpoint ? 'EndToEnd' : 'StartToStart', nodeRange);
+
+ var rangeLength = range.text.length;
+ return isStartEndpoint ? container.length - rangeLength : rangeLength;
+ }
+};
+
+
+/**
+ * Returns the text of the given node. Uses IE specific properties.
+ * @param {Node} node The node to retrieve the text of.
+ * @return {string} The node's text.
+ * @private
+ */
+goog.dom.browserrange.IeRange.getNodeText_ = function(node) {
+ return node.nodeType == goog.dom.NodeType.TEXT ?
+ node.nodeValue : node.innerText;
+};
+
+
+/**
+ * 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.browserrange.IeRange.prototype.isRangeInDocument = function() {
+ var range = this.doc_.body.createTextRange();
+ range.moveToElementText(this.doc_.body);
+
+ return this.containsRange(
+ new goog.dom.browserrange.IeRange(range, this.doc_), true);
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.isCollapsed = function() {
+ // Note(user) : The earlier implementation used (range.text == ''), but this
+ // fails when (range.htmlText == '<br>')
+ // Alternative: this.range_.htmlText == '';
+ return this.range_.compareEndPoints('StartToEnd', this.range_) == 0;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getText = function() {
+ return this.range_.text;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.getValidHtml = function() {
+ return this.range_.htmlText;
+};
+
+
+// SELECTION MODIFICATION
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.select = function(opt_reverse) {
+ // IE doesn't support programmatic reversed selections.
+ this.range_.select();
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.removeContents = function() {
+ // NOTE: Sometimes htmlText is non-empty, but the range is actually empty.
+ // TODO(gboyer): The htmlText check is probably unnecessary, but I left it in
+ // for paranoia.
+ if (!this.isCollapsed() && this.range_.htmlText) {
+ // Store some before-removal state.
+ var startNode = this.getStartNode();
+ var endNode = this.getEndNode();
+ var oldText = this.range_.text;
+
+ // IE sometimes deletes nodes unrelated to the selection. This trick fixes
+ // that problem most of the time. Even though it looks like a no-op, it is
+ // somehow changing IE's internal state such that empty unrelated nodes are
+ // no longer deleted.
+ var clone = this.range_.duplicate();
+ clone.moveStart('character', 1);
+ clone.moveStart('character', -1);
+
+ // However, sometimes moving the start back and forth ends up changing the
+ // range.
+ // TODO(gboyer): This condition used to happen for empty ranges, but (1)
+ // never worked, and (2) the isCollapsed call should protect against empty
+ // ranges better than before. However, this is left for paranoia.
+ if (clone.text == oldText) {
+ this.range_ = clone;
+ }
+
+ // Use the browser's native deletion code.
+ this.range_.text = '';
+ this.clearCachedValues_();
+
+ // Unfortunately, when deleting a portion of a single text node, IE creates
+ // an extra text node unlike other browsers which just change the text in
+ // the node. We normalize for that behavior here, making IE behave like all
+ // the other browsers.
+ var newStartNode = this.getStartNode();
+ var newStartOffset = this.getStartOffset();
+ /** @preserveTry */
+ try {
+ var sibling = startNode.nextSibling;
+ if (startNode == endNode && startNode.parentNode &&
+ startNode.nodeType == goog.dom.NodeType.TEXT &&
+ sibling && sibling.nodeType == goog.dom.NodeType.TEXT) {
+ startNode.nodeValue += sibling.nodeValue;
+ goog.dom.removeNode(sibling);
+
+ // Make sure to reselect the appropriate position.
+ this.range_ = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(
+ newStartNode);
+ this.range_.move('character', newStartOffset);
+ this.clearCachedValues_();
+ }
+ } catch (e) {
+ // IE throws errors on orphaned nodes.
+ }
+ }
+};
+
+
+/**
+ * @param {TextRange} range The range to get a dom helper for.
+ * @return {!goog.dom.DomHelper} A dom helper for the document the range
+ * resides in.
+ * @private
+ */
+goog.dom.browserrange.IeRange.getDomHelper_ = function(range) {
+ return goog.dom.getDomHelper(range.parentElement());
+};
+
+
+/**
+ * Pastes the given element into the given range, returning the resulting
+ * element.
+ * @param {TextRange} range The range to paste into.
+ * @param {Element} element The node to insert a copy of.
+ * @param {goog.dom.DomHelper=} opt_domHelper DOM helper object for the document
+ * the range resides in.
+ * @return {Element} The resulting copy of element.
+ * @private
+ */
+goog.dom.browserrange.IeRange.pasteElement_ = function(range, element,
+ opt_domHelper) {
+ opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_(
+ range);
+
+ // Make sure the node has a unique id.
+ var id;
+ var originalId = id = element.id;
+ if (!id) {
+ id = element.id = goog.string.createUniqueString();
+ }
+
+ // Insert (a clone of) the node.
+ range.pasteHTML(element.outerHTML);
+
+ // Pasting the outerHTML of the modified element into the document creates
+ // a clone of the element argument. We want to return a reference to the
+ // clone, not the original. However we need to remove the temporary ID
+ // first.
+ element = opt_domHelper.getElement(id);
+
+ // If element is null here, we failed.
+ if (element) {
+ if (!originalId) {
+ element.removeAttribute('id');
+ }
+ }
+
+ return element;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.surroundContents = function(element) {
+ // Make sure the element is detached from the document.
+ goog.dom.removeNode(element);
+
+ // IE more or less guarantees that range.htmlText is well-formed & valid.
+ element.innerHTML = this.range_.htmlText;
+ element = goog.dom.browserrange.IeRange.pasteElement_(this.range_, element);
+
+ // If element is null here, we failed.
+ if (element) {
+ this.range_.moveToElementText(element);
+ }
+
+ this.clearCachedValues_();
+
+ return element;
+};
+
+
+/**
+ * Internal handler for inserting a node.
+ * @param {TextRange} clone A clone of this range's browser range object.
+ * @param {Node} node The node to insert.
+ * @param {boolean} before Whether to insert the node before or after the range.
+ * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use.
+ * @return {Node} The resulting copy of node.
+ * @private
+ */
+goog.dom.browserrange.IeRange.insertNode_ = function(clone, node,
+ before, opt_domHelper) {
+ // Get a DOM helper.
+ opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_(
+ clone);
+
+ // If it's not an element, wrap it in one.
+ var isNonElement;
+ if (node.nodeType != goog.dom.NodeType.ELEMENT) {
+ isNonElement = true;
+ node = opt_domHelper.createDom(goog.dom.TagName.DIV, null, node);
+ }
+
+ clone.collapse(before);
+ node = goog.dom.browserrange.IeRange.pasteElement_(clone,
+ /** @type {!Element} */ (node), opt_domHelper);
+
+ // If we didn't want an element, unwrap the element and return the node.
+ if (isNonElement) {
+ // pasteElement_() may have returned a copy of the wrapper div, and the
+ // node it wraps could also be a new copy. So we must extract that new
+ // node from the new wrapper.
+ var newNonElement = node.firstChild;
+ opt_domHelper.flattenElement(node);
+ node = newNonElement;
+ }
+
+ return node;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.insertNode = function(node, before) {
+ var output = goog.dom.browserrange.IeRange.insertNode_(
+ this.range_.duplicate(), node, before);
+ this.clearCachedValues_();
+ return output;
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.surroundWithNodes = function(
+ startNode, endNode) {
+ var clone1 = this.range_.duplicate();
+ var clone2 = this.range_.duplicate();
+ goog.dom.browserrange.IeRange.insertNode_(clone1, startNode, true);
+ goog.dom.browserrange.IeRange.insertNode_(clone2, endNode, false);
+
+ this.clearCachedValues_();
+};
+
+
+/** @override */
+goog.dom.browserrange.IeRange.prototype.collapse = function(toStart) {
+ this.range_.collapse(toStart);
+
+ if (toStart) {
+ this.endNode_ = this.startNode_;
+ this.endOffset_ = this.startOffset_;
+ } else {
+ this.startNode_ = this.endNode_;
+ this.startOffset_ = this.endOffset_;
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserrange/operarange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/browserrange/operarange.js b/externs/GCL/externs/goog/dom/browserrange/operarange.js
new file mode 100644
index 0000000..f277dc1
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/browserrange/operarange.js
@@ -0,0 +1,84 @@
+// Copyright 2009 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 Opera specific range wrapper. Inherits most
+ * functionality from W3CRange, but adds exceptions as necessary.
+ *
+ * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead.
+ *
+ */
+
+
+goog.provide('goog.dom.browserrange.OperaRange');
+
+goog.require('goog.dom.browserrange.W3cRange');
+
+
+
+/**
+ * The constructor for Opera specific browser ranges.
+ * @param {Range} range The range object.
+ * @constructor
+ * @extends {goog.dom.browserrange.W3cRange}
+ * @final
+ */
+goog.dom.browserrange.OperaRange = function(range) {
+ goog.dom.browserrange.W3cRange.call(this, range);
+};
+goog.inherits(goog.dom.browserrange.OperaRange, goog.dom.browserrange.W3cRange);
+
+
+/**
+ * Creates a range object that selects the given node's text.
+ * @param {Node} node The node to select.
+ * @return {!goog.dom.browserrange.OperaRange} A Opera range wrapper object.
+ */
+goog.dom.browserrange.OperaRange.createFromNodeContents = function(node) {
+ return new goog.dom.browserrange.OperaRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
+};
+
+
+/**
+ * Creates a range object that selects between the given nodes.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the node to start.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the node to end.
+ * @return {!goog.dom.browserrange.OperaRange} A wrapper object.
+ */
+goog.dom.browserrange.OperaRange.createFromNodes = function(startNode,
+ startOffset, endNode, endOffset) {
+ return new goog.dom.browserrange.OperaRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode,
+ startOffset, endNode, endOffset));
+};
+
+
+/** @override */
+goog.dom.browserrange.OperaRange.prototype.selectInternal = function(
+ selection, reversed) {
+ // Avoid using addRange as we have to removeAllRanges first, which
+ // blurs editable fields in Opera.
+ selection.collapse(this.getStartNode(), this.getStartOffset());
+ if (this.getEndNode() != this.getStartNode() ||
+ this.getEndOffset() != this.getStartOffset()) {
+ selection.extend(this.getEndNode(), this.getEndOffset());
+ }
+ // This can happen if the range isn't in an editable field.
+ if (selection.rangeCount == 0) {
+ selection.addRange(this.range_);
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserrange/w3crange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/browserrange/w3crange.js b/externs/GCL/externs/goog/dom/browserrange/w3crange.js
new file mode 100644
index 0000000..994f19f
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/browserrange/w3crange.js
@@ -0,0 +1,396 @@
+// 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 W3C spec following range wrapper.
+ *
+ * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.browserrange.W3cRange');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.NodeType');
+goog.require('goog.dom.RangeEndpoint');
+goog.require('goog.dom.TagName');
+goog.require('goog.dom.browserrange.AbstractRange');
+goog.require('goog.string');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * The constructor for W3C specific browser ranges.
+ * @param {Range} range The range object.
+ * @constructor
+ * @extends {goog.dom.browserrange.AbstractRange}
+ */
+goog.dom.browserrange.W3cRange = function(range) {
+ this.range_ = range;
+};
+goog.inherits(goog.dom.browserrange.W3cRange,
+ goog.dom.browserrange.AbstractRange);
+
+
+/**
+ * Returns a browser range spanning the given node's contents.
+ * @param {Node} node The node to select.
+ * @return {!Range} A browser range spanning the node's contents.
+ * @protected
+ */
+goog.dom.browserrange.W3cRange.getBrowserRangeForNode = function(node) {
+ var nodeRange = goog.dom.getOwnerDocument(node).createRange();
+
+ if (node.nodeType == goog.dom.NodeType.TEXT) {
+ nodeRange.setStart(node, 0);
+ nodeRange.setEnd(node, node.length);
+ } else {
+ /** @suppress {missingRequire} */
+ if (!goog.dom.browserrange.canContainRangeEndpoint(node)) {
+ var rangeParent = node.parentNode;
+ var rangeStartOffset = goog.array.indexOf(rangeParent.childNodes, node);
+ nodeRange.setStart(rangeParent, rangeStartOffset);
+ nodeRange.setEnd(rangeParent, rangeStartOffset + 1);
+ } else {
+ var tempNode, leaf = node;
+ while ((tempNode = leaf.firstChild) &&
+ /** @suppress {missingRequire} */
+ goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
+ leaf = tempNode;
+ }
+ nodeRange.setStart(leaf, 0);
+
+ leaf = node;
+ while ((tempNode = leaf.lastChild) &&
+ /** @suppress {missingRequire} */
+ goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
+ leaf = tempNode;
+ }
+ nodeRange.setEnd(leaf, leaf.nodeType == goog.dom.NodeType.ELEMENT ?
+ leaf.childNodes.length : leaf.length);
+ }
+ }
+
+ return nodeRange;
+};
+
+
+/**
+ * Returns a browser range spanning the given nodes.
+ * @param {Node} startNode The node to start with - should not be a BR.
+ * @param {number} startOffset The offset within the start node.
+ * @param {Node} endNode The node to end with - should not be a BR.
+ * @param {number} endOffset The offset within the end node.
+ * @return {!Range} A browser range spanning the node's contents.
+ * @protected
+ */
+goog.dom.browserrange.W3cRange.getBrowserRangeForNodes = function(startNode,
+ startOffset, endNode, endOffset) {
+ // Create and return the range.
+ var nodeRange = goog.dom.getOwnerDocument(startNode).createRange();
+ nodeRange.setStart(startNode, startOffset);
+ nodeRange.setEnd(endNode, endOffset);
+ return nodeRange;
+};
+
+
+/**
+ * Creates a range object that selects the given node's text.
+ * @param {Node} node The node to select.
+ * @return {!goog.dom.browserrange.W3cRange} A Gecko range wrapper object.
+ */
+goog.dom.browserrange.W3cRange.createFromNodeContents = function(node) {
+ return new goog.dom.browserrange.W3cRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
+};
+
+
+/**
+ * Creates a range object that selects between the given nodes.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the start node.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the end node.
+ * @return {!goog.dom.browserrange.W3cRange} A wrapper object.
+ */
+goog.dom.browserrange.W3cRange.createFromNodes = function(startNode,
+ startOffset, endNode, endOffset) {
+ return new goog.dom.browserrange.W3cRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode,
+ startOffset, endNode, endOffset));
+};
+
+
+/**
+ * @return {!goog.dom.browserrange.W3cRange} A clone of this range.
+ * @override
+ */
+goog.dom.browserrange.W3cRange.prototype.clone = function() {
+ return new this.constructor(this.range_.cloneRange());
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getBrowserRange = function() {
+ return this.range_;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getContainer = function() {
+ return this.range_.commonAncestorContainer;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getStartNode = function() {
+ return this.range_.startContainer;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getStartOffset = function() {
+ return this.range_.startOffset;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getEndNode = function() {
+ return this.range_.endContainer;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getEndOffset = function() {
+ return this.range_.endOffset;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.compareBrowserRangeEndpoints =
+ function(range, thisEndpoint, otherEndpoint) {
+ return this.range_.compareBoundaryPoints(
+ otherEndpoint == goog.dom.RangeEndpoint.START ?
+ (thisEndpoint == goog.dom.RangeEndpoint.START ?
+ goog.global['Range'].START_TO_START :
+ goog.global['Range'].START_TO_END) :
+ (thisEndpoint == goog.dom.RangeEndpoint.START ?
+ goog.global['Range'].END_TO_START :
+ goog.global['Range'].END_TO_END),
+ /** @type {Range} */ (range));
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.isCollapsed = function() {
+ return this.range_.collapsed;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getText = function() {
+ return this.range_.toString();
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.getValidHtml = function() {
+ var div = goog.dom.getDomHelper(this.range_.startContainer).createDom(
+ goog.dom.TagName.DIV);
+ div.appendChild(this.range_.cloneContents());
+ var result = div.innerHTML;
+
+ if (goog.string.startsWith(result, '<') ||
+ !this.isCollapsed() && !goog.string.contains(result, '<')) {
+ // We attempt to mimic IE, which returns no containing element when a
+ // only text nodes are selected, does return the containing element when
+ // the selection is empty, and does return the element when multiple nodes
+ // are selected.
+ return result;
+ }
+
+ var container = this.getContainer();
+ container = container.nodeType == goog.dom.NodeType.ELEMENT ? container :
+ container.parentNode;
+
+ var html = goog.dom.getOuterHtml(
+ /** @type {!Element} */ (container.cloneNode(false)));
+ return html.replace('>', '>' + result);
+};
+
+
+// SELECTION MODIFICATION
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.select = function(reverse) {
+ var win = goog.dom.getWindow(goog.dom.getOwnerDocument(this.getStartNode()));
+ this.selectInternal(win.getSelection(), reverse);
+};
+
+
+/**
+ * Select this range.
+ * @param {Selection} selection Browser selection object.
+ * @param {*} reverse Whether to select this range in reverse.
+ * @protected
+ */
+goog.dom.browserrange.W3cRange.prototype.selectInternal = function(selection,
+ reverse) {
+ // Browser-specific tricks are needed to create reversed selections
+ // programatically. For this generic W3C codepath, ignore the reverse
+ // parameter.
+ selection.removeAllRanges();
+ selection.addRange(this.range_);
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.removeContents = function() {
+ var range = this.range_;
+ range.extractContents();
+
+ if (range.startContainer.hasChildNodes()) {
+ // Remove any now empty nodes surrounding the extracted contents.
+ var rangeStartContainer =
+ range.startContainer.childNodes[range.startOffset];
+ if (rangeStartContainer) {
+ var rangePrevious = rangeStartContainer.previousSibling;
+
+ if (goog.dom.getRawTextContent(rangeStartContainer) == '') {
+ goog.dom.removeNode(rangeStartContainer);
+ }
+
+ if (rangePrevious && goog.dom.getRawTextContent(rangePrevious) == '') {
+ goog.dom.removeNode(rangePrevious);
+ }
+ }
+ }
+
+ if (goog.userAgent.IE) {
+ // Unfortunately, when deleting a portion of a single text node, IE creates
+ // an extra text node instead of modifying the nodeValue of the start node.
+ // We normalize for that behavior here, similar to code in
+ // goog.dom.browserrange.IeRange#removeContents
+ // See https://connect.microsoft.com/IE/feedback/details/746591
+ var startNode = this.getStartNode();
+ var startOffset = this.getStartOffset();
+ var endNode = this.getEndNode();
+ var endOffset = this.getEndOffset();
+ var sibling = startNode.nextSibling;
+ if (startNode == endNode && startNode.parentNode &&
+ startNode.nodeType == goog.dom.NodeType.TEXT &&
+ sibling && sibling.nodeType == goog.dom.NodeType.TEXT) {
+ startNode.nodeValue += sibling.nodeValue;
+ goog.dom.removeNode(sibling);
+
+ // Modifying the node value clears the range offsets. Reselect the
+ // position in the modified start node.
+ range.setStart(startNode, startOffset);
+ range.setEnd(endNode, endOffset);
+ }
+ }
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.surroundContents = function(element) {
+ this.range_.surroundContents(element);
+ return element;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.insertNode = function(node, before) {
+ var range = this.range_.cloneRange();
+ range.collapse(before);
+ range.insertNode(node);
+ range.detach();
+
+ return node;
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.surroundWithNodes = function(
+ startNode, endNode) {
+ var win = goog.dom.getWindow(
+ goog.dom.getOwnerDocument(this.getStartNode()));
+ /** @suppress {missingRequire} */
+ var selectionRange = goog.dom.Range.createFromWindow(win);
+ if (selectionRange) {
+ var sNode = selectionRange.getStartNode();
+ var eNode = selectionRange.getEndNode();
+ var sOffset = selectionRange.getStartOffset();
+ var eOffset = selectionRange.getEndOffset();
+ }
+
+ var clone1 = this.range_.cloneRange();
+ var clone2 = this.range_.cloneRange();
+
+ clone1.collapse(false);
+ clone2.collapse(true);
+
+ clone1.insertNode(endNode);
+ clone2.insertNode(startNode);
+
+ clone1.detach();
+ clone2.detach();
+
+ if (selectionRange) {
+ // There are 4 ways that surroundWithNodes can wreck the saved
+ // selection object. All of them happen when an inserted node splits
+ // a text node, and one of the end points of the selection was in the
+ // latter half of that text node.
+ //
+ // Clients of this library should use saveUsingCarets to avoid this
+ // problem. Unfortunately, saveUsingCarets uses this method, so that's
+ // not really an option for us. :( We just recompute the offsets.
+ var isInsertedNode = function(n) {
+ return n == startNode || n == endNode;
+ };
+ if (sNode.nodeType == goog.dom.NodeType.TEXT) {
+ while (sOffset > sNode.length) {
+ sOffset -= sNode.length;
+ do {
+ sNode = sNode.nextSibling;
+ } while (isInsertedNode(sNode));
+ }
+ }
+
+ if (eNode.nodeType == goog.dom.NodeType.TEXT) {
+ while (eOffset > eNode.length) {
+ eOffset -= eNode.length;
+ do {
+ eNode = eNode.nextSibling;
+ } while (isInsertedNode(eNode));
+ }
+ }
+
+ /** @suppress {missingRequire} */
+ goog.dom.Range.createFromNodes(
+ sNode, /** @type {number} */ (sOffset),
+ eNode, /** @type {number} */ (eOffset)).select();
+ }
+};
+
+
+/** @override */
+goog.dom.browserrange.W3cRange.prototype.collapse = function(toStart) {
+ this.range_.collapse(toStart);
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/browserrange/webkitrange.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/browserrange/webkitrange.js b/externs/GCL/externs/goog/dom/browserrange/webkitrange.js
new file mode 100644
index 0000000..dd428bd
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/browserrange/webkitrange.js
@@ -0,0 +1,108 @@
+// 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 WebKit specific range wrapper. Inherits most
+ * functionality from W3CRange, but adds exceptions as necessary.
+ *
+ * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+
+goog.provide('goog.dom.browserrange.WebKitRange');
+
+goog.require('goog.dom.RangeEndpoint');
+goog.require('goog.dom.browserrange.W3cRange');
+goog.require('goog.userAgent');
+
+
+
+/**
+ * The constructor for WebKit specific browser ranges.
+ * @param {Range} range The range object.
+ * @constructor
+ * @extends {goog.dom.browserrange.W3cRange}
+ * @final
+ */
+goog.dom.browserrange.WebKitRange = function(range) {
+ goog.dom.browserrange.W3cRange.call(this, range);
+};
+goog.inherits(goog.dom.browserrange.WebKitRange,
+ goog.dom.browserrange.W3cRange);
+
+
+/**
+ * Creates a range object that selects the given node's text.
+ * @param {Node} node The node to select.
+ * @return {!goog.dom.browserrange.WebKitRange} A WebKit range wrapper object.
+ */
+goog.dom.browserrange.WebKitRange.createFromNodeContents = function(node) {
+ return new goog.dom.browserrange.WebKitRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
+};
+
+
+/**
+ * Creates a range object that selects between the given nodes.
+ * @param {Node} startNode The node to start with.
+ * @param {number} startOffset The offset within the start node.
+ * @param {Node} endNode The node to end with.
+ * @param {number} endOffset The offset within the end node.
+ * @return {!goog.dom.browserrange.WebKitRange} A wrapper object.
+ */
+goog.dom.browserrange.WebKitRange.createFromNodes = function(startNode,
+ startOffset, endNode, endOffset) {
+ return new goog.dom.browserrange.WebKitRange(
+ goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode,
+ startOffset, endNode, endOffset));
+};
+
+
+/** @override */
+goog.dom.browserrange.WebKitRange.prototype.compareBrowserRangeEndpoints =
+ function(range, thisEndpoint, otherEndpoint) {
+ // Webkit pre-528 has some bugs where compareBoundaryPoints() doesn't work the
+ // way it is supposed to, but if we reverse the sense of two comparisons,
+ // it works fine.
+ // https://bugs.webkit.org/show_bug.cgi?id=20738
+ if (goog.userAgent.isVersionOrHigher('528')) {
+ return (goog.dom.browserrange.WebKitRange.superClass_.
+ compareBrowserRangeEndpoints.call(
+ this, range, thisEndpoint, otherEndpoint));
+ }
+ return this.range_.compareBoundaryPoints(
+ otherEndpoint == goog.dom.RangeEndpoint.START ?
+ (thisEndpoint == goog.dom.RangeEndpoint.START ?
+ goog.global['Range'].START_TO_START :
+ goog.global['Range'].END_TO_START) : // Sense reversed
+ (thisEndpoint == goog.dom.RangeEndpoint.START ?
+ goog.global['Range'].START_TO_END : // Sense reversed
+ goog.global['Range'].END_TO_END),
+ /** @type {Range} */ (range));
+};
+
+
+/** @override */
+goog.dom.browserrange.WebKitRange.prototype.selectInternal = function(
+ selection, reversed) {
+ if (reversed) {
+ selection.setBaseAndExtent(this.getEndNode(), this.getEndOffset(),
+ this.getStartNode(), this.getStartOffset());
+ } else {
+ selection.setBaseAndExtent(this.getStartNode(), this.getStartOffset(),
+ this.getEndNode(), this.getEndOffset());
+ }
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/bufferedviewportsizemonitor.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/bufferedviewportsizemonitor.js b/externs/GCL/externs/goog/dom/bufferedviewportsizemonitor.js
new file mode 100644
index 0000000..2909d26
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/bufferedviewportsizemonitor.js
@@ -0,0 +1,201 @@
+// Copyright 2012 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 viewport size monitor that buffers RESIZE events until the
+ * window size has stopped changing, within a specified period of time. For
+ * every RESIZE event dispatched, this will dispatch up to two *additional*
+ * events:
+ * - {@link #EventType.RESIZE_WIDTH} if the viewport's width has changed since
+ * the last buffered dispatch.
+ * - {@link #EventType.RESIZE_HEIGHT} if the viewport's height has changed since
+ * the last buffered dispatch.
+ * You likely only need to listen to one of the three events. But if you need
+ * more, just be cautious of duplicating effort.
+ *
+ */
+
+goog.provide('goog.dom.BufferedViewportSizeMonitor');
+
+goog.require('goog.asserts');
+goog.require('goog.async.Delay');
+goog.require('goog.events');
+goog.require('goog.events.EventTarget');
+goog.require('goog.events.EventType');
+
+
+
+/**
+ * Creates a new BufferedViewportSizeMonitor.
+ * @param {!goog.dom.ViewportSizeMonitor} viewportSizeMonitor The
+ * underlying viewport size monitor.
+ * @param {number=} opt_bufferMs The buffer time, in ms. If not specified, this
+ * value defaults to {@link #RESIZE_EVENT_DELAY_MS_}.
+ * @constructor
+ * @extends {goog.events.EventTarget}
+ * @final
+ */
+goog.dom.BufferedViewportSizeMonitor = function(
+ viewportSizeMonitor, opt_bufferMs) {
+ goog.dom.BufferedViewportSizeMonitor.base(this, 'constructor');
+
+ /**
+ * Delay for the resize event.
+ * @private {goog.async.Delay}
+ */
+ this.resizeDelay_;
+
+ /**
+ * The underlying viewport size monitor.
+ * @type {goog.dom.ViewportSizeMonitor}
+ * @private
+ */
+ this.viewportSizeMonitor_ = viewportSizeMonitor;
+
+ /**
+ * The current size of the viewport.
+ * @type {goog.math.Size}
+ * @private
+ */
+ this.currentSize_ = this.viewportSizeMonitor_.getSize();
+
+ /**
+ * The resize buffer time in ms.
+ * @type {number}
+ * @private
+ */
+ this.resizeBufferMs_ = opt_bufferMs ||
+ goog.dom.BufferedViewportSizeMonitor.RESIZE_EVENT_DELAY_MS_;
+
+ /**
+ * Listener key for the viewport size monitor.
+ * @type {goog.events.Key}
+ * @private
+ */
+ this.listenerKey_ = goog.events.listen(
+ viewportSizeMonitor,
+ goog.events.EventType.RESIZE,
+ this.handleResize_,
+ false,
+ this);
+};
+goog.inherits(goog.dom.BufferedViewportSizeMonitor, goog.events.EventTarget);
+
+
+/**
+ * Additional events to dispatch.
+ * @enum {string}
+ */
+goog.dom.BufferedViewportSizeMonitor.EventType = {
+ RESIZE_HEIGHT: goog.events.getUniqueId('resizeheight'),
+ RESIZE_WIDTH: goog.events.getUniqueId('resizewidth')
+};
+
+
+/**
+ * Default number of milliseconds to wait after a resize event to relayout the
+ * page.
+ * @type {number}
+ * @const
+ * @private
+ */
+goog.dom.BufferedViewportSizeMonitor.RESIZE_EVENT_DELAY_MS_ = 100;
+
+
+/** @override */
+goog.dom.BufferedViewportSizeMonitor.prototype.disposeInternal =
+ function() {
+ goog.events.unlistenByKey(this.listenerKey_);
+ goog.dom.BufferedViewportSizeMonitor.base(this, 'disposeInternal');
+};
+
+
+/**
+ * Handles resize events on the underlying ViewportMonitor.
+ * @private
+ */
+goog.dom.BufferedViewportSizeMonitor.prototype.handleResize_ =
+ function() {
+ // Lazily create when needed.
+ if (!this.resizeDelay_) {
+ this.resizeDelay_ = new goog.async.Delay(
+ this.onWindowResize_,
+ this.resizeBufferMs_,
+ this);
+ this.registerDisposable(this.resizeDelay_);
+ }
+ this.resizeDelay_.start();
+};
+
+
+/**
+ * Window resize callback that determines whether to reflow the view contents.
+ * @private
+ */
+goog.dom.BufferedViewportSizeMonitor.prototype.onWindowResize_ =
+ function() {
+ if (this.viewportSizeMonitor_.isDisposed()) {
+ return;
+ }
+
+ var previousSize = this.currentSize_;
+ var currentSize = this.viewportSizeMonitor_.getSize();
+
+ goog.asserts.assert(currentSize,
+ 'Viewport size should be set at this point');
+
+ this.currentSize_ = currentSize;
+
+ if (previousSize) {
+
+ var resized = false;
+
+ // Width has changed
+ if (previousSize.width != currentSize.width) {
+ this.dispatchEvent(
+ goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_WIDTH);
+ resized = true;
+ }
+
+ // Height has changed
+ if (previousSize.height != currentSize.height) {
+ this.dispatchEvent(
+ goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_HEIGHT);
+ resized = true;
+ }
+
+ // If either has changed, this is a resize event.
+ if (resized) {
+ this.dispatchEvent(goog.events.EventType.RESIZE);
+ }
+
+ } else {
+ // If we didn't have a previous size, we consider all events to have
+ // changed.
+ this.dispatchEvent(
+ goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_HEIGHT);
+ this.dispatchEvent(
+ goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_WIDTH);
+ this.dispatchEvent(goog.events.EventType.RESIZE);
+ }
+};
+
+
+/**
+ * Returns the current size of the viewport.
+ * @return {goog.math.Size?} The current viewport size.
+ */
+goog.dom.BufferedViewportSizeMonitor.prototype.getSize = function() {
+ return this.currentSize_ ? this.currentSize_.clone() : null;
+};
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/dom/classes.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/dom/classes.js b/externs/GCL/externs/goog/dom/classes.js
new file mode 100644
index 0000000..0f1db74
--- /dev/null
+++ b/externs/GCL/externs/goog/dom/classes.js
@@ -0,0 +1,239 @@
+// 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 adding, removing and setting classes. Prefer
+ * {@link goog.dom.classlist} over these utilities since goog.dom.classlist
+ * conforms closer to the semantics of Element.classList, is faster (uses
+ * native methods rather than parsing strings on every call) and compiles
+ * to smaller code as a result.
+ *
+ * Note: these utilities are meant to operate on HTMLElements and
+ * will not work on elements with differing interfaces (such as SVGElements).
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+
+goog.provide('goog.dom.classes');
+
+goog.require('goog.array');
+
+
+/**
+ * Sets the entire class name of an element.
+ * @param {Node} element DOM node to set class of.
+ * @param {string} className Class name(s) to apply to element.
+ * @deprecated Use goog.dom.classlist.set instead.
+ */
+goog.dom.classes.set = function(element, className) {
+ element.className = className;
+};
+
+
+/**
+ * Gets an array of class names on an element
+ * @param {Node} element DOM node to get class of.
+ * @return {!Array<?>} Class names on {@code element}. Some browsers add extra
+ * properties to the array. Do not depend on any of these!
+ * @deprecated Use goog.dom.classlist.get instead.
+ */
+goog.dom.classes.get = function(element) {
+ var className = element.className;
+ // Some types of elements don't have a className in IE (e.g. iframes).
+ // Furthermore, in Firefox, className is not a string when the element is
+ // an SVG element.
+ return goog.isString(className) && className.match(/\S+/g) || [];
+};
+
+
+/**
+ * Adds a class or classes to an element. Does not add multiples of class names.
+ * @param {Node} element DOM node to add class to.
+ * @param {...string} var_args Class names to add.
+ * @return {boolean} Whether class was added (or all classes were added).
+ * @deprecated Use goog.dom.classlist.add or goog.dom.classlist.addAll instead.
+ */
+goog.dom.classes.add = function(element, var_args) {
+ var classes = goog.dom.classes.get(element);
+ var args = goog.array.slice(arguments, 1);
+ var expectedCount = classes.length + args.length;
+ goog.dom.classes.add_(classes, args);
+ goog.dom.classes.set(element, classes.join(' '));
+ return classes.length == expectedCount;
+};
+
+
+/**
+ * Removes a class or classes from an element.
+ * @param {Node} element DOM node to remove class from.
+ * @param {...string} var_args Class name(s) to remove.
+ * @return {boolean} Whether all classes in {@code var_args} were found and
+ * removed.
+ * @deprecated Use goog.dom.classlist.remove or goog.dom.classlist.removeAll
+ * instead.
+ */
+goog.dom.classes.remove = function(element, var_args) {
+ var classes = goog.dom.classes.get(element);
+ var args = goog.array.slice(arguments, 1);
+ var newClasses = goog.dom.classes.getDifference_(classes, args);
+ goog.dom.classes.set(element, newClasses.join(' '));
+ return newClasses.length == classes.length - args.length;
+};
+
+
+/**
+ * Helper method for {@link goog.dom.classes.add} and
+ * {@link goog.dom.classes.addRemove}. Adds one or more classes to the supplied
+ * classes array.
+ * @param {Array<string>} classes All class names for the element, will be
+ * updated to have the classes supplied in {@code args} added.
+ * @param {Array<string>} args Class names to add.
+ * @private
+ */
+goog.dom.classes.add_ = function(classes, args) {
+ for (var i = 0; i < args.length; i++) {
+ if (!goog.array.contains(classes, args[i])) {
+ classes.push(args[i]);
+ }
+ }
+};
+
+
+/**
+ * Helper method for {@link goog.dom.classes.remove} and
+ * {@link goog.dom.classes.addRemove}. Calculates the difference of two arrays.
+ * @param {!Array<string>} arr1 First array.
+ * @param {!Array<string>} arr2 Second array.
+ * @return {!Array<string>} The first array without the elements of the second
+ * array.
+ * @private
+ */
+goog.dom.classes.getDifference_ = function(arr1, arr2) {
+ return goog.array.filter(arr1, function(item) {
+ return !goog.array.contains(arr2, item);
+ });
+};
+
+
+/**
+ * Switches a class on an element from one to another without disturbing other
+ * classes. If the fromClass isn't removed, the toClass won't be added.
+ * @param {Node} element DOM node to swap classes on.
+ * @param {string} fromClass Class to remove.
+ * @param {string} toClass Class to add.
+ * @return {boolean} Whether classes were switched.
+ * @deprecated Use goog.dom.classlist.swap instead.
+ */
+goog.dom.classes.swap = function(element, fromClass, toClass) {
+ var classes = goog.dom.classes.get(element);
+
+ var removed = false;
+ for (var i = 0; i < classes.length; i++) {
+ if (classes[i] == fromClass) {
+ goog.array.splice(classes, i--, 1);
+ removed = true;
+ }
+ }
+
+ if (removed) {
+ classes.push(toClass);
+ goog.dom.classes.set(element, classes.join(' '));
+ }
+
+ return removed;
+};
+
+
+/**
+ * Adds zero or more classes to an element and removes zero or more as a single
+ * operation. Unlike calling {@link goog.dom.classes.add} and
+ * {@link goog.dom.classes.remove} separately, this is more efficient as it only
+ * parses the class property once.
+ *
+ * If a class is in both the remove and add lists, it will be added. Thus,
+ * you can use this instead of {@link goog.dom.classes.swap} when you have
+ * more than two class names that you want to swap.
+ *
+ * @param {Node} element DOM node to swap classes on.
+ * @param {?(string|Array<string>)} classesToRemove Class or classes to
+ * remove, if null no classes are removed.
+ * @param {?(string|Array<string>)} classesToAdd Class or classes to add, if
+ * null no classes are added.
+ * @deprecated Use goog.dom.classlist.addRemove instead.
+ */
+goog.dom.classes.addRemove = function(element, classesToRemove, classesToAdd) {
+ var classes = goog.dom.classes.get(element);
+ if (goog.isString(classesToRemove)) {
+ goog.array.remove(classes, classesToRemove);
+ } else if (goog.isArray(classesToRemove)) {
+ classes = goog.dom.classes.getDifference_(classes, classesToRemove);
+ }
+
+ if (goog.isString(classesToAdd) &&
+ !goog.array.contains(classes, classesToAdd)) {
+ classes.push(classesToAdd);
+ } else if (goog.isArray(classesToAdd)) {
+ goog.dom.classes.add_(classes, classesToAdd);
+ }
+
+ goog.dom.classes.set(element, classes.join(' '));
+};
+
+
+/**
+ * Returns true if an element has a class.
+ * @param {Node} element DOM node to test.
+ * @param {string} className Class name to test for.
+ * @return {boolean} Whether element has the class.
+ * @deprecated Use goog.dom.classlist.contains instead.
+ */
+goog.dom.classes.has = function(element, className) {
+ return goog.array.contains(goog.dom.classes.get(element), className);
+};
+
+
+/**
+ * Adds or removes a class depending on the enabled argument.
+ * @param {Node} element DOM node to add or remove the class on.
+ * @param {string} className Class name to add or remove.
+ * @param {boolean} enabled Whether to add or remove the class (true adds,
+ * false removes).
+ * @deprecated Use goog.dom.classlist.enable or goog.dom.classlist.enableAll
+ * instead.
+ */
+goog.dom.classes.enable = function(element, className, enabled) {
+ if (enabled) {
+ goog.dom.classes.add(element, className);
+ } else {
+ goog.dom.classes.remove(element, className);
+ }
+};
+
+
+/**
+ * Removes a class if an element has it, and adds it the element doesn't have
+ * it. Won't affect other classes on the node.
+ * @param {Node} element DOM node to toggle class on.
+ * @param {string} className Class to toggle.
+ * @return {boolean} True if class was added, false if it was removed
+ * (in other words, whether element has the class after this function has
+ * been called).
+ * @deprecated Use goog.dom.classlist.toggle instead.
+ */
+goog.dom.classes.toggle = function(element, className) {
+ var add = !goog.dom.classes.has(element, className);
+ goog.dom.classes.enable(element, className, add);
+ return add;
+};
[43/51] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/JsToAs] - Added GCL extern.
Posted by ft...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/flatbutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/flatbutton.css b/externs/GCL/externs/goog/css/flatbutton.css
new file mode 100644
index 0000000..1cc39b6
--- /dev/null
+++ b/externs/GCL/externs/goog/css/flatbutton.css
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styling for flat buttons created by goog.ui.FlatButtonRenderer.
+ *
+ * @author brianp@google.com (Brian Peterson)
+ */
+
+.goog-flat-button {
+ position: relative;
+ /*width: 20ex;*/
+ margin: 2px;
+ border: 1px solid #000;
+ padding: 2px 6px;
+ font: normal 13px "Trebuchet MS", Tahoma, Arial, sans-serif;
+ color: #fff;
+ background-color: #8c2425;
+ cursor: pointer;
+ outline: none;
+}
+
+/* State: disabled. */
+.goog-flat-button-disabled {
+ border-color: #888;
+ color: #888;
+ background-color: #ccc;
+ cursor: default;
+}
+
+/* State: hover. */
+.goog-flat-button-hover {
+ border-color: #8c2425;
+ color: #8c2425;
+ background-color: #eaa4a5;
+}
+
+/* State: active, selected, checked. */
+.goog-flat-button-active,
+.goog-flat-button-selected,
+.goog-flat-button-checked {
+ border-color: #5b4169;
+ color: #5b4169;
+ background-color: #d1a8ea;
+}
+
+/* State: focused. */
+.goog-flat-button-focused {
+ border-color: #5b4169;
+}
+
+/* Pill (collapsed border) styles. */
+.goog-flat-button-collapse-right {
+ margin-right: 0;
+}
+
+.goog-flat-button-collapse-left {
+ margin-left: 0;
+ border-left: none;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/flatmenubutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/flatmenubutton.css b/externs/GCL/externs/goog/css/flatmenubutton.css
new file mode 100644
index 0000000..5778217
--- /dev/null
+++ b/externs/GCL/externs/goog/css/flatmenubutton.css
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for buttons created by goog.ui.FlatMenuButtonRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ * @author tlb@google.com (Thierry Le Boulenge)
+ */
+
+
+.goog-flat-menu-button {
+ background-color: #fff;
+ border: 1px solid #c9c9c9;
+ color: #333;
+ cursor: pointer;
+ font: normal 95%;
+ list-style: none;
+ margin: 0 2px;
+ outline: none;
+ padding: 1px 4px;
+ position: relative;
+ text-decoration: none;
+ vertical-align: middle;
+}
+
+.goog-flat-menu-button-disabled * {
+ border-color: #ccc;
+ color: #999;
+ cursor: default;
+}
+
+.goog-flat-menu-button-hover {
+ border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */
+}
+
+.goog-flat-menu-button-active {
+ background-color: #bbb;
+ background-position: bottom left;
+}
+
+.goog-flat-menu-button-focused {
+ border-color: #bbb;
+}
+
+.goog-flat-menu-button-caption {
+ padding-right: 10px;
+ vertical-align: top;
+}
+
+.goog-flat-menu-button-dropdown {
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0;
+ position: absolute;
+ right: 2px;
+ top: 0;
+ vertical-align: top;
+ width: 7px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/hovercard.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/hovercard.css b/externs/GCL/externs/goog/css/hovercard.css
new file mode 100644
index 0000000..2d64e4f
--- /dev/null
+++ b/externs/GCL/externs/goog/css/hovercard.css
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: larrypo@google.com (Larry Powelson) */
+
+.goog-hovercard div {
+ border: solid 5px #69748C;
+ width: 300px;
+ height: 115px;
+ background-color: white;
+ font-family: arial, sans-serif;
+}
+
+.goog-hovercard .goog-shadow {
+ border: transparent;
+ background-color: black;
+ filter: alpha(Opacity=1);
+ opacity: 0.01;
+ -moz-opacity: 0.01;
+}
+
+.goog-hovercard table {
+ border-collapse: collapse;
+ border-spacing: 0px;
+}
+
+.goog-hovercard-icons td {
+ border-bottom: 1px solid #ccc;
+ padding: 0px;
+ margin: 0px;
+ text-align: center;
+ height: 19px;
+ width: 100px;
+ font-size: 90%;
+}
+
+.goog-hovercard-icons td + td {
+ border-left: 1px solid #ccc;
+}
+
+.goog-hovercard-content {
+ border-collapse: collapse;
+}
+
+.goog-hovercard-content td {
+ padding-left: 15px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/hsvapalette.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/hsvapalette.css b/externs/GCL/externs/goog/css/hsvapalette.css
new file mode 100644
index 0000000..ec52e39
--- /dev/null
+++ b/externs/GCL/externs/goog/css/hsvapalette.css
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * All Rights Reserved.
+ *
+ * Styles for the HSV color palette.
+ *
+ * @author smcbride@google.com (Sean McBride)
+ * @author arv@google.com (Erik Arvidsson)
+ * @author manucornet@google.com (Manu Cornet)
+ */
+
+.goog-hsva-palette,
+.goog-hsva-palette-sm {
+ position: relative;
+ border: 1px solid #999;
+ border-color: #ccc #999 #999 #ccc;
+ width: 442px;
+ height: 276px;
+}
+
+.goog-hsva-palette-sm {
+ width: 205px;
+ height: 185px;
+}
+
+.goog-hsva-palette label span,
+.goog-hsva-palette-sm label span {
+ display: none;
+}
+
+.goog-hsva-palette-hs-backdrop,
+.goog-hsva-palette-sm-hs-backdrop,
+.goog-hsva-palette-hs-image,
+.goog-hsva-palette-sm-hs-image {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ width: 256px;
+ height: 256px;
+ border: 1px solid #999;
+}
+
+.goog-hsva-palette-sm-hs-backdrop,
+.goog-hsva-palette-sm-hs-image {
+ top: 45px;
+ width: 128px;
+ height: 128px;
+}
+
+.goog-hsva-palette-hs-backdrop,
+.goog-hsva-palette-sm-hs-backdrop {
+ background-color: #000;
+}
+
+.goog-hsva-palette-hs-image,
+.goog-hsva-palette-v-image,
+.goog-hsva-palette-a-image,
+.goog-hsva-palette-hs-handle,
+.goog-hsva-palette-v-handle,
+.goog-hsva-palette-a-handle,
+.goog-hsva-palette-swatch-backdrop {
+ background-image: url(//ssl.gstatic.com/closure/hsva-sprite.png);
+}
+
+.goog-hsva-palette-noalpha .goog-hsva-palette-hs-image,
+.goog-hsva-palette-noalpha .goog-hsva-palette-v-image,
+.goog-hsva-palette-noalpha .goog-hsva-palette-a-image,
+.goog-hsva-palette-noalpha .goog-hsva-palette-hs-handle,
+.goog-hsva-palette-noalpha .goog-hsva-palette-v-handle,
+.goog-hsva-palette-noalpha .goog-hsva-palette-a-handle,
+.goog-hsva-palette-noalpha .goog-hsva-palette-swatch-backdrop {
+ background-image: url(//ssl.gstatic.com/closure/hsva-sprite.gif);
+}
+
+.goog-hsva-palette-sm-hs-image,
+.goog-hsva-palette-sm-v-image,
+.goog-hsva-palette-sm-a-image,
+.goog-hsva-palette-sm-hs-handle,
+.goog-hsva-palette-sm-v-handle,
+.goog-hsva-palette-sm-a-handle,
+.goog-hsva-palette-sm-swatch-backdrop {
+ background-image: url(//ssl.gstatic.com/closure/hsva-sprite-sm.png);
+}
+
+.goog-hsva-palette-noalpha .goog-hsva-palette-sm-hs-image,
+.goog-hsva-palette-noalpha .goog-hsva-palette-sm-v-image,
+.goog-hsva-palette-noalpha .goog-hsva-palette-sm-a-image,
+.goog-hsva-palette-noalpha .goog-hsva-palette-sm-hs-handle,
+.goog-hsva-palette-noalpha .goog-hsva-palette-sm-v-handle,
+.goog-hsva-palette-noalpha .goog-hsva-palette-sm-a-handle,
+.goog-hsva-palette-noalpha .goog-hsva-palette-swatch-backdrop {
+ background-image: url(//ssl.gstatic.com/closure/hsva-sprite-sm.gif);
+}
+
+.goog-hsva-palette-hs-image,
+.goog-hsva-palette-sm-hs-image {
+ background-position: 0 0;
+}
+
+.goog-hsva-palette-hs-handle,
+.goog-hsva-palette-sm-hs-handle {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ width: 11px;
+ height: 11px;
+ overflow: hidden;
+ background-position: 0 -256px;
+}
+
+.goog-hsva-palette-sm-hs-handle {
+ top: 40px;
+ background-position: 0 -128px;
+}
+
+.goog-hsva-palette-v-image,
+.goog-hsva-palette-a-image,
+.goog-hsva-palette-sm-v-image,
+.goog-hsva-palette-sm-a-image {
+ position: absolute;
+ top: 10px;
+ left: 286px;
+ width: 19px;
+ height: 256px;
+ border: 1px solid #999;
+ background-color: #fff;
+ background-position: -256px 0;
+}
+
+.goog-hsva-palette-a-image {
+ left: 325px;
+ background-position: -275px 0;
+}
+
+.goog-hsva-palette-sm-v-image,
+.goog-hsva-palette-sm-a-image {
+ top: 45px;
+ left: 155px;
+ width: 9px;
+ height: 128px;
+ background-position: -128px 0;
+}
+
+.goog-hsva-palette-sm-a-image {
+ left: 182px;
+ background-position: -137px 0;
+}
+
+.goog-hsva-palette-v-handle,
+.goog-hsva-palette-a-handle,
+.goog-hsva-palette-sm-v-handle,
+.goog-hsva-palette-sm-a-handle {
+ position: absolute;
+ top: 5px;
+ left: 279px;
+ width: 35px;
+ height: 11px;
+ background-position: -11px -256px;
+ overflow: hidden;
+}
+
+.goog-hsva-palette-a-handle {
+ left: 318px;
+}
+
+.goog-hsva-palette-sm-v-handle,
+.goog-hsva-palette-sm-a-handle {
+ top: 40px;
+ left: 148px;
+ width: 25px;
+ background-position: -11px -128px;
+}
+
+.goog-hsva-palette-sm-a-handle {
+ left: 175px;
+}
+
+.goog-hsva-palette-swatch,
+.goog-hsva-palette-swatch-backdrop,
+.goog-hsva-palette-sm-swatch,
+.goog-hsva-palette-sm-swatch-backdrop {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ width: 65px;
+ height: 65px;
+ border: 1px solid #999;
+ background-color: #fff;
+ background-position: -294px 0;
+}
+
+.goog-hsva-palette-sm-swatch,
+.goog-hsva-palette-sm-swatch-backdrop {
+ top: 10px;
+ right: auto;
+ left: 10px;
+ width: 30px;
+ height: 22px;
+ background-position: -36px -128px;
+}
+
+.goog-hsva-palette-swatch,
+.goog-hsva-palette-sm-swatch {
+ z-index: 5;
+}
+
+.goog-hsva-palette-swatch-backdrop,
+.goog-hsva-palette-sm-swatch-backdrop {
+ z-index: 1;
+}
+
+.goog-hsva-palette-input,
+.goog-hsva-palette-sm-input {
+ position: absolute;
+ top: 85px;
+ right: 10px;
+ width: 65px;
+ font-size: 80%;
+}
+
+.goog-hsva-palette-sm-input {
+ top: 10px;
+ right: auto;
+ left: 50px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/hsvpalette.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/hsvpalette.css b/externs/GCL/externs/goog/css/hsvpalette.css
new file mode 100644
index 0000000..8449ed5
--- /dev/null
+++ b/externs/GCL/externs/goog/css/hsvpalette.css
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * All Rights Reserved.
+ *
+ * Styles for the HSV color palette.
+ *
+ * @author smcbride@google.com (Sean McBride)
+ * @author arv@google.com (Erik Arvidsson)
+ * @author manucornet@google.com (Manu Cornet)
+ */
+
+.goog-hsv-palette,
+.goog-hsv-palette-sm {
+ position: relative;
+ border: 1px solid #999;
+ border-color: #ccc #999 #999 #ccc;
+ width: 400px;
+ height: 276px;
+}
+
+.goog-hsv-palette-sm {
+ width: 182px;
+ height: 185px;
+}
+
+.goog-hsv-palette label span,
+.goog-hsv-palette-sm label span {
+ display: none;
+}
+
+.goog-hsv-palette-hs-backdrop,
+.goog-hsv-palette-sm-hs-backdrop,
+.goog-hsv-palette-hs-image,
+.goog-hsv-palette-sm-hs-image {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ width: 256px;
+ height: 256px;
+ border: 1px solid #999;
+}
+
+.goog-hsv-palette-sm-hs-backdrop,
+.goog-hsv-palette-sm-hs-image {
+ top: 45px;
+ width: 128px;
+ height: 128px;
+}
+
+.goog-hsv-palette-hs-backdrop,
+.goog-hsv-palette-sm-hs-backdrop {
+ background-color: #000;
+}
+
+.goog-hsv-palette-hs-image,
+.goog-hsv-palette-v-image,
+.goog-hsv-palette-hs-handle,
+.goog-hsv-palette-v-handle {
+ background-image: url(//ssl.gstatic.com/closure/hsv-sprite.png);
+}
+
+.goog-hsv-palette-noalpha .goog-hsv-palette-hs-image,
+.goog-hsv-palette-noalpha .goog-hsv-palette-v-image,
+.goog-hsv-palette-noalpha .goog-hsv-palette-hs-handle,
+.goog-hsv-palette-noalpha .goog-hsv-palette-v-handle {
+ background-image: url(//ssl.gstatic.com/closure/hsv-sprite.gif);
+}
+
+.goog-hsv-palette-sm-hs-image,
+.goog-hsv-palette-sm-v-image,
+.goog-hsv-palette-sm-hs-handle,
+.goog-hsv-palette-sm-v-handle {
+ background-image: url(//ssl.gstatic.com/closure/hsv-sprite-sm.png);
+}
+
+.goog-hsv-palette-noalpha .goog-hsv-palette-sm-hs-image,
+.goog-hsv-palette-noalpha .goog-hsv-palette-sm-v-image,
+.goog-hsv-palette-noalpha .goog-hsv-palette-sm-hs-handle,
+.goog-hsv-palette-noalpha .goog-hsv-palette-sm-v-handle {
+ background-image: url(//ssl.gstatic.com/closure/hsv-sprite-sm.gif);
+}
+
+.goog-hsv-palette-hs-image,
+.goog-hsv-palette-sm-hs-image {
+ background-position: 0 0;
+}
+
+.goog-hsv-palette-hs-handle,
+.goog-hsv-palette-sm-hs-handle {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ width: 11px;
+ height: 11px;
+ overflow: hidden;
+ background-position: 0 -256px;
+}
+
+.goog-hsv-palette-sm-hs-handle {
+ top: 40px;
+ background-position: 0 -128px;
+}
+
+.goog-hsv-palette-v-image,
+.goog-hsv-palette-sm-v-image {
+ position: absolute;
+ top: 10px;
+ left: 286px;
+ width: 19px;
+ height: 256px;
+ border: 1px solid #999;
+ background-color: #fff;
+ background-position: -256px 0;
+}
+
+.goog-hsv-palette-sm-v-image {
+ top: 45px;
+ left: 155px;
+ width: 9px;
+ height: 128px;
+ background-position: -128px 0;
+}
+
+.goog-hsv-palette-v-handle,
+.goog-hsv-palette-sm-v-handle {
+ position: absolute;
+ top: 5px;
+ left: 279px;
+ width: 35px;
+ height: 11px;
+ background-position: -11px -256px;
+ overflow: hidden;
+}
+
+.goog-hsv-palette-sm-v-handle {
+ top: 40px;
+ left: 148px;
+ width: 25px;
+ background-position: -11px -128px;
+}
+
+.goog-hsv-palette-swatch,
+.goog-hsv-palette-sm-swatch {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ width: 65px;
+ height: 65px;
+ border: 1px solid #999;
+ background-color: #fff;
+}
+
+.goog-hsv-palette-sm-swatch {
+ top: 10px;
+ right: auto;
+ left: 10px;
+ width: 30px;
+ height: 22px;
+}
+
+.goog-hsv-palette-input,
+.goog-hsv-palette-sm-input {
+ position: absolute;
+ top: 85px;
+ right: 10px;
+ width: 65px;
+}
+
+.goog-hsv-palette-sm-input {
+ top: 10px;
+ right: auto;
+ left: 50px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/imagelessbutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/imagelessbutton.css b/externs/GCL/externs/goog/css/imagelessbutton.css
new file mode 100644
index 0000000..23c7fee
--- /dev/null
+++ b/externs/GCL/externs/goog/css/imagelessbutton.css
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styling for buttons created by goog.ui.ImagelessButtonRenderer.
+ *
+ * WARNING: This file uses some ineffecient selectors and it may be
+ * best to avoid using this file in extremely large, or performance
+ * critical applications.
+ *
+ * @author: eae@google.com (Emil A Eklund)
+ * @author: gboyer@google.com (Garrett Boyer)
+ */
+
+
+/* Imageless button styles. */
+
+/* The base element of the button. */
+.goog-imageless-button {
+ /* Set the background color at the outermost level. */
+ background: #e3e3e3;
+ /* Place a top and bottom border. Do it on this outermost div so that
+ * it is easier to make pill buttons work properly. */
+ border-color: #bbb;
+ border-style: solid;
+ border-width: 1px 0;
+ color: #222; /* Text content color. */
+ cursor: default;
+ font-family: Arial, sans-serif;
+ line-height: 0; /* For Opera and old WebKit. */
+ list-style: none;
+ /* Built-in margin for the component. Because of the negative margins
+ * used to simulate corner rounding, the effective left and right margin is
+ * actually only 1px. */
+ margin: 2px;
+ outline: none;
+ padding: 0;
+ text-decoration: none;
+ vertical-align: middle;
+}
+
+/*
+ * Pseudo-rounded corners. Works by pulling the left and right sides slightly
+ * outside of the parent bounding box before drawing the left and right
+ * borders.
+ */
+.goog-imageless-button-outer-box {
+ /* Left and right border that protrude outside the parent. */
+ border-color: #bbb;
+ border-style: solid;
+ border-width: 0 1px;
+ /* Same as margin: 0 -1px, except works better cross browser. These are
+ * intended to be RTL flipped to work better in IE7. */
+ left: -1px;
+ margin-right: -2px;
+}
+
+/*
+ * A div to give the light and medium shades of the button that takes up no
+ * vertical space.
+ */
+.goog-imageless-button-top-shadow {
+ /* Light top color in the content. */
+ background: #f9f9f9;
+ /* Thin medium shade. */
+ border-bottom: 3px solid #eee;
+ /* Control height with line-height, since height: will trigger hasLayout.
+ * Specified in pixels, as a compromise to avoid rounding errors. */
+ line-height: 9px;
+ /* Undo all space this takes up. */
+ margin-bottom: -12px;
+}
+
+/* Actual content area for the button. */
+.goog-imageless-button-content {
+ line-height: 1.5em;
+ padding: 0px 4px;
+ text-align: center;
+}
+
+
+/* Pill (collapsed border) styles. */
+.goog-imageless-button-collapse-right {
+ /* Draw a border on the root element to square the button off. The border
+ * on the outer-box element remains, but gets obscured by the next button. */
+ border-right-width: 1px;
+ margin-right: -2px; /* Undoes the margins between the two buttons. */
+}
+
+.goog-imageless-button-collapse-left .goog-imageless-button-outer-box {
+ /* Don't bleed to the left -- keep the border self contained in the box. */
+ border-left-color: #eee;
+ left: 0;
+ margin-right: -1px; /* Versus the default of -2px. */
+}
+
+
+/* Disabled styles. */
+.goog-imageless-button-disabled,
+.goog-imageless-button-disabled .goog-imageless-button-outer-box {
+ background: #eee;
+ border-color: #ccc;
+ color: #666; /* For text */
+}
+
+.goog-imageless-button-disabled .goog-imageless-button-top-shadow {
+ /* Just hide the shadow instead of setting individual colors. */
+ visibility: hidden;
+}
+
+
+/*
+ * Active and checked styles.
+ * Identical except for text color according to GUIG.
+ */
+.goog-imageless-button-active, .goog-imageless-button-checked {
+ background: #f9f9f9;
+}
+
+.goog-imageless-button-active .goog-imageless-button-top-shadow,
+.goog-imageless-button-checked .goog-imageless-button-top-shadow {
+ background: #e3e3e3;
+}
+
+.goog-imageless-button-active {
+ color: #000;
+}
+
+
+/* Hover styles. Higher priority to override other border styles. */
+.goog-imageless-button-hover,
+.goog-imageless-button-hover .goog-imageless-button-outer-box,
+.goog-imageless-button-focused,
+.goog-imageless-button-focused .goog-imageless-button-outer-box {
+ border-color: #000;
+}
+
+
+/* IE6 hacks. This is the only place inner-box is used. */
+* html .goog-imageless-button-inner-box {
+ /* Give the element inline-block behavior so that the shadow appears.
+ * The main requirement is to give the element layout without having the side
+ * effect of taking up a full line. */
+ display: inline;
+ /* Allow the shadow to show through, overriding position:relative from the
+ * goog-inline-block styles. */
+ position: static;
+ zoom: 1;
+}
+
+* html .goog-imageless-button-outer-box {
+ /* In RTL mode, IE is off by one pixel. To fix, override the left: -1px
+ * (which was flipped to right) without having any effect on LTR mode
+ * (where IE ignores right when left is specified). */
+ /* @noflip */ right: 0;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/imagelessmenubutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/imagelessmenubutton.css b/externs/GCL/externs/goog/css/imagelessmenubutton.css
new file mode 100644
index 0000000..0c8b6fd
--- /dev/null
+++ b/externs/GCL/externs/goog/css/imagelessmenubutton.css
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for buttons created by goog.ui.ImagelessMenuButtonRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ * @author dalewis@google.com (Darren Lewis)
+ */
+
+/* Dropdown arrow style. */
+.goog-imageless-button-dropdown {
+ height: 16px;
+ width: 7px;
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0;
+ vertical-align: top;
+ margin-right: 2px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/inputdatepicker.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/inputdatepicker.css b/externs/GCL/externs/goog/css/inputdatepicker.css
new file mode 100644
index 0000000..4f93182
--- /dev/null
+++ b/externs/GCL/externs/goog/css/inputdatepicker.css
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: arv@google.com (Erik Arvidsson) */
+
+/* goog.ui.InputDatePicker */
+
+@import url(popupdatepicker.css);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/linkbutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/linkbutton.css b/externs/GCL/externs/goog/css/linkbutton.css
new file mode 100644
index 0000000..9f9ec3a
--- /dev/null
+++ b/externs/GCL/externs/goog/css/linkbutton.css
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Styling for link buttons created by goog.ui.LinkButtonRenderer.
+ *
+ * @author robbyw@google.com (Robby Walker)
+ */
+
+.goog-link-button {
+ position: relative;
+ color: #00f;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+/* State: disabled. */
+.goog-link-button-disabled {
+ color: #888;
+ text-decoration: none;
+ cursor: default;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/menu.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/menu.css b/externs/GCL/externs/goog/css/menu.css
new file mode 100644
index 0000000..da66222
--- /dev/null
+++ b/externs/GCL/externs/goog/css/menu.css
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for menus created by goog.ui.MenuRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+.goog-menu {
+ background: #fff;
+ border-color: #ccc #666 #666 #ccc;
+ border-style: solid;
+ border-width: 1px;
+ cursor: default;
+ font: normal 13px Arial, sans-serif;
+ margin: 0;
+ outline: none;
+ padding: 4px 0;
+ position: absolute;
+ z-index: 20000; /* Arbitrary, but some apps depend on it... */
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/menubar.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/menubar.css b/externs/GCL/externs/goog/css/menubar.css
new file mode 100644
index 0000000..6f69b46
--- /dev/null
+++ b/externs/GCL/externs/goog/css/menubar.css
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * styling for goog.ui.menuBar and child buttons.
+ *
+ * @author tvykruta@google.com (Tomas Vykruta)
+ */
+
+
+.goog-menubar {
+ cursor: default;
+ outline: none;
+ position: relative;
+ white-space: nowrap;
+ background: #fff;
+}
+
+.goog-menubar .goog-menu-button {
+ padding: 1px 1px;
+ margin: 0px 0px;
+ outline: none;
+ border: none;
+ background: #fff;
+ /* @alternate */ border: 1px solid #fff;
+}
+
+.goog-menubar .goog-menu-button-dropdown {
+ display: none;
+}
+
+.goog-menubar .goog-menu-button-outer-box {
+ border: none;
+}
+
+.goog-menubar .goog-menu-button-inner-box {
+ border: none;
+}
+
+.goog-menubar .goog-menu-button-hover {
+ background: #eee;
+ border: 1px solid #eee;
+}
+
+.goog-menubar .goog-menu-button-open {
+ background: #fff;
+ border-left: 1px solid #ccc;
+ border-right: 1px solid #ccc;
+}
+
+.goog-menubar .goog-menu-button-disabled {
+ color: #ccc;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/menubutton.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/menubutton.css b/externs/GCL/externs/goog/css/menubutton.css
new file mode 100644
index 0000000..82c94b2
--- /dev/null
+++ b/externs/GCL/externs/goog/css/menubutton.css
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for buttons created by goog.ui.MenuButtonRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+/* State: resting. */
+.goog-menu-button {
+ /* Client apps may override the URL at which they serve the image. */
+ background: #ddd url(//ssl.gstatic.com/editor/button-bg.png) repeat-x top left;
+ border: 0;
+ color: #000;
+ cursor: pointer;
+ list-style: none;
+ margin: 2px;
+ outline: none;
+ padding: 0;
+ text-decoration: none;
+ vertical-align: middle;
+}
+
+/* Pseudo-rounded corners. */
+.goog-menu-button-outer-box,
+.goog-menu-button-inner-box {
+ border-style: solid;
+ border-color: #aaa;
+ vertical-align: top;
+}
+.goog-menu-button-outer-box {
+ margin: 0;
+ border-width: 1px 0;
+ padding: 0;
+}
+.goog-menu-button-inner-box {
+ margin: 0 -1px;
+ border-width: 0 1px;
+ padding: 3px 4px;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-menu-button-inner-box {
+ /* IE6 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+
+/* Pre-IE7 BiDi fixes. */
+* html .goog-menu-button-rtl .goog-menu-button-outer-box {
+ /* @noflip */ left: -1px;
+ /* @noflip */ right: auto;
+}
+* html .goog-menu-button-rtl .goog-menu-button-inner-box {
+ /* @noflip */ right: auto;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-menu-button-inner-box {
+ /* IE7 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+/* IE7 BiDi fix. */
+*:first-child+html .goog-menu-button-rtl .goog-menu-button-inner-box {
+ /* @noflip */ left: 1px;
+ /* @noflip */ right: auto;
+}
+
+/* Safari-only hacks. */
+::root .goog-menu-button,
+::root .goog-menu-button-outer-box,
+::root .goog-menu-button-inner-box {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: 0;
+}
+::root .goog-menu-button-caption,
+::root .goog-menu-button-dropdown {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: normal;
+}
+
+/* State: disabled. */
+.goog-menu-button-disabled {
+ background-image: none !important;
+ opacity: 0.3;
+ -moz-opacity: 0.3;
+ filter: alpha(opacity=30);
+}
+.goog-menu-button-disabled .goog-menu-button-outer-box,
+.goog-menu-button-disabled .goog-menu-button-inner-box,
+.goog-menu-button-disabled .goog-menu-button-caption,
+.goog-menu-button-disabled .goog-menu-button-dropdown {
+ color: #333 !important;
+ border-color: #999 !important;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-menu-button-disabled {
+ margin: 2px 1px !important;
+ padding: 0 1px !important;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-menu-button-disabled {
+ margin: 2px 1px !important;
+ padding: 0 1px !important;
+}
+
+/* State: hover. */
+.goog-menu-button-hover .goog-menu-button-outer-box,
+.goog-menu-button-hover .goog-menu-button-inner-box {
+ border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */
+}
+
+/* State: active, open. */
+.goog-menu-button-active,
+.goog-menu-button-open {
+ background-color: #bbb;
+ background-position: bottom left;
+}
+
+/* State: focused. */
+.goog-menu-button-focused .goog-menu-button-outer-box,
+.goog-menu-button-focused .goog-menu-button-inner-box {
+ border-color: orange;
+}
+
+/* Caption style. */
+.goog-menu-button-caption {
+ padding: 0 4px 0 0;
+ vertical-align: top;
+}
+
+/* Dropdown arrow style. */
+.goog-menu-button-dropdown {
+ height: 15px;
+ width: 7px;
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0;
+ vertical-align: top;
+}
+
+/* Pill (collapsed border) styles. */
+/* TODO(gboyer): Remove specific menu button styles and have any button support being a menu button. */
+.goog-menu-button-collapse-right,
+.goog-menu-button-collapse-right .goog-menu-button-outer-box,
+.goog-menu-button-collapse-right .goog-menu-button-inner-box {
+ margin-right: 0;
+}
+
+.goog-menu-button-collapse-left,
+.goog-menu-button-collapse-left .goog-menu-button-outer-box,
+.goog-menu-button-collapse-left .goog-menu-button-inner-box {
+ margin-left: 0;
+}
+
+.goog-menu-button-collapse-left .goog-menu-button-inner-box {
+ border-left: 1px solid #fff;
+}
+
+.goog-menu-button-collapse-left.goog-menu-button-checked
+.goog-menu-button-inner-box {
+ border-left: 1px solid #ddd;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/menuitem.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/menuitem.css b/externs/GCL/externs/goog/css/menuitem.css
new file mode 100644
index 0000000..cea9de6
--- /dev/null
+++ b/externs/GCL/externs/goog/css/menuitem.css
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for menus created by goog.ui.MenuItemRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+/**
+ * State: resting.
+ *
+ * NOTE(mleibman,chrishenry):
+ * The RTL support in Closure is provided via two mechanisms -- "rtl" CSS
+ * classes and BiDi flipping done by the CSS compiler. Closure supports RTL
+ * with or without the use of the CSS compiler. In order for them not
+ * to conflict with each other, the "rtl" CSS classes need to have the @noflip
+ * annotation. The non-rtl counterparts should ideally have them as well, but,
+ * since .goog-menuitem existed without .goog-menuitem-rtl for so long before
+ * being added, there is a risk of people having templates where they are not
+ * rendering the .goog-menuitem-rtl class when in RTL and instead rely solely
+ * on the BiDi flipping by the CSS compiler. That's why we're not adding the
+ * @noflip to .goog-menuitem.
+ */
+.goog-menuitem {
+ color: #000;
+ font: normal 13px Arial, sans-serif;
+ list-style: none;
+ margin: 0;
+ /* 28px on the left for icon or checkbox; 7em on the right for shortcut. */
+ padding: 4px 7em 4px 28px;
+ white-space: nowrap;
+}
+
+/* BiDi override for the resting state. */
+/* @noflip */
+.goog-menuitem.goog-menuitem-rtl {
+ /* Flip left/right padding for BiDi. */
+ padding-left: 7em;
+ padding-right: 28px;
+}
+
+/* If a menu doesn't have checkable items or items with icons, remove padding. */
+.goog-menu-nocheckbox .goog-menuitem,
+.goog-menu-noicon .goog-menuitem {
+ padding-left: 12px;
+}
+
+/*
+ * If a menu doesn't have items with shortcuts, leave just enough room for
+ * submenu arrows, if they are rendered.
+ */
+.goog-menu-noaccel .goog-menuitem {
+ padding-right: 20px;
+}
+
+.goog-menuitem-content {
+ color: #000;
+ font: normal 13px Arial, sans-serif;
+}
+
+/* State: disabled. */
+.goog-menuitem-disabled .goog-menuitem-accel,
+.goog-menuitem-disabled .goog-menuitem-content {
+ color: #ccc !important;
+}
+.goog-menuitem-disabled .goog-menuitem-icon {
+ opacity: 0.3;
+ -moz-opacity: 0.3;
+ filter: alpha(opacity=30);
+}
+
+/* State: hover. */
+.goog-menuitem-highlight,
+.goog-menuitem-hover {
+ background-color: #d6e9f8;
+ /* Use an explicit top and bottom border so that the selection is visible
+ * in high contrast mode. */
+ border-color: #d6e9f8;
+ border-style: dotted;
+ border-width: 1px 0;
+ padding-bottom: 3px;
+ padding-top: 3px;
+}
+
+/* State: selected/checked. */
+.goog-menuitem-checkbox,
+.goog-menuitem-icon {
+ background-repeat: no-repeat;
+ height: 16px;
+ left: 6px;
+ position: absolute;
+ right: auto;
+ vertical-align: middle;
+ width: 16px;
+}
+
+/* BiDi override for the selected/checked state. */
+/* @noflip */
+.goog-menuitem-rtl .goog-menuitem-checkbox,
+.goog-menuitem-rtl .goog-menuitem-icon {
+ /* Flip left/right positioning. */
+ left: auto;
+ right: 6px;
+}
+
+.goog-option-selected .goog-menuitem-checkbox,
+.goog-option-selected .goog-menuitem-icon {
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -512px 0;
+}
+
+/* Keyboard shortcut ("accelerator") style. */
+.goog-menuitem-accel {
+ color: #999;
+ /* Keyboard shortcuts are untranslated; always left-to-right. */
+ /* @noflip */ direction: ltr;
+ left: auto;
+ padding: 0 6px;
+ position: absolute;
+ right: 0;
+ text-align: right;
+}
+
+/* BiDi override for shortcut style. */
+/* @noflip */
+.goog-menuitem-rtl .goog-menuitem-accel {
+ /* Flip left/right positioning and text alignment. */
+ left: 0;
+ right: auto;
+ text-align: left;
+}
+
+/* Mnemonic styles. */
+.goog-menuitem-mnemonic-hint {
+ text-decoration: underline;
+}
+
+.goog-menuitem-mnemonic-separator {
+ color: #999;
+ font-size: 12px;
+ padding-left: 4px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/menuseparator.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/menuseparator.css b/externs/GCL/externs/goog/css/menuseparator.css
new file mode 100644
index 0000000..de1354f
--- /dev/null
+++ b/externs/GCL/externs/goog/css/menuseparator.css
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for menus created by goog.ui.MenuSeparatorRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+.goog-menuseparator {
+ border-top: 1px solid #ccc;
+ margin: 4px 0;
+ padding: 0;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/multitestrunner.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/multitestrunner.css b/externs/GCL/externs/goog/css/multitestrunner.css
new file mode 100644
index 0000000..2cdffea
--- /dev/null
+++ b/externs/GCL/externs/goog/css/multitestrunner.css
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pupius@google.com (Daniel Pupius) */
+
+.goog-testrunner {
+ background-color: #EEE;
+ border: 1px solid #999;
+ padding: 10px;
+ padding-bottom: 25px;
+}
+
+.goog-testrunner-progress {
+ width: auto;
+ height: 20px;
+ background-color: #FFF;
+ border: 1px solid #999;
+}
+
+.goog-testrunner-progress table {
+ width: 100%;
+ height: 20px;
+ border-collapse: collapse;
+}
+
+.goog-testrunner-buttons {
+ margin-top: 7px;
+}
+
+.goog-testrunner-buttons button {
+ width: 75px;
+}
+
+.goog-testrunner-log,
+.goog-testrunner-report,
+.goog-testrunner-stats {
+ margin-top: 7px;
+ width: auto;
+ height: 400px;
+ background-color: #FFF;
+ border: 1px solid #999;
+ font: normal medium monospace;
+ padding: 5px;
+ overflow: auto; /* Opera doesn't support overflow-y. */
+ overflow-y: scroll;
+ overflow-x: auto;
+}
+
+.goog-testrunner-report div {
+ margin-bottom: 6px;
+ border-bottom: 1px solid #999;
+}
+
+.goog-testrunner-stats table {
+ margin-top: 20px;
+ border-collapse: collapse;
+ border: 1px solid #EEE;
+}
+
+.goog-testrunner-stats td,
+.goog-testrunner-stats th {
+ padding: 2px 6px;
+ border: 1px solid #F0F0F0;
+}
+
+.goog-testrunner-stats th {
+ font-weight: bold;
+}
+
+.goog-testrunner-stats .center {
+ text-align: center;
+}
+
+.goog-testrunner-progress-summary {
+ font: bold small sans-serif;
+}
+
+.goog-testrunner iframe {
+ position: absolute;
+ left: -640px;
+ top: -480px;
+ width: 640px;
+ height: 480px;
+ margin: 0;
+ border: 0;
+ padding: 0;
+}
+
+.goog-testrunner-report-failure {
+ color: #900;
+}
+
+.goog-testrunner-reporttab,
+.goog-testrunner-logtab,
+.goog-testrunner-statstab {
+ float: left;
+ width: 50px;
+ height: 16px;
+ text-align: center;
+ font: normal small arial, helvetica, sans-serif;
+ color: #666;
+ background-color: #DDD;
+ border: 1px solid #999;
+ border-top: 0;
+ cursor: pointer;
+}
+
+.goog-testrunner-reporttab,
+.goog-testrunner-logtab {
+ border-right: 0;
+}
+
+.goog-testrunner-activetab {
+ font-weight: bold;
+ color: #000;
+ background-color: #CCC;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/palette.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/palette.css b/externs/GCL/externs/goog/css/palette.css
new file mode 100644
index 0000000..8360afc
--- /dev/null
+++ b/externs/GCL/externs/goog/css/palette.css
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for palettes created by goog.ui.PaletteRenderer.
+ *
+ * @author pupius@google.com (Daniel Pupius)
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+.goog-palette {
+ cursor: default;
+ outline: none;
+}
+
+.goog-palette-table {
+ border: 1px solid #666;
+ border-collapse: collapse;
+ margin: 5px;
+}
+
+.goog-palette-cell {
+ border: 0;
+ border-right: 1px solid #666;
+ cursor: pointer;
+ height: 18px;
+ margin: 0;
+ text-align: center;
+ vertical-align: middle;
+ width: 18px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/popupdatepicker.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/popupdatepicker.css b/externs/GCL/externs/goog/css/popupdatepicker.css
new file mode 100644
index 0000000..133173a
--- /dev/null
+++ b/externs/GCL/externs/goog/css/popupdatepicker.css
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for a goog.ui.PopupDatePicker.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ */
+
+.goog-date-picker {
+ position: absolute;
+}
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/roundedpanel.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/roundedpanel.css b/externs/GCL/externs/goog/css/roundedpanel.css
new file mode 100644
index 0000000..d931e41
--- /dev/null
+++ b/externs/GCL/externs/goog/css/roundedpanel.css
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styles for RoundedPanel.
+ *
+ * @author pallosp@google.com (Peter Pallos)
+ */
+
+.goog-roundedpanel {
+ position: relative;
+ z-index: 0;
+}
+
+.goog-roundedpanel-background {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ z-index: -1;
+}
+
+.goog-roundedpanel-content {
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/roundedtab.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/roundedtab.css b/externs/GCL/externs/goog/css/roundedtab.css
new file mode 100644
index 0000000..17fe155
--- /dev/null
+++ b/externs/GCL/externs/goog/css/roundedtab.css
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: attila@google.com (Attila Bodis) */
+
+
+/*
+ * Styles used by goog.ui.RoundedTabRenderer.
+ */
+.goog-rounded-tab {
+ border: 0;
+ cursor: default;
+ padding: 0;
+}
+
+.goog-tab-bar-top .goog-rounded-tab,
+.goog-tab-bar-bottom .goog-rounded-tab {
+ float: left;
+ margin: 0 4px 0 0;
+}
+
+.goog-tab-bar-start .goog-rounded-tab,
+.goog-tab-bar-end .goog-rounded-tab {
+ margin: 0 0 4px 0;
+}
+
+.goog-rounded-tab-caption {
+ border: 0;
+ color: #fff;
+ margin: 0;
+ padding: 4px 8px;
+}
+
+.goog-rounded-tab-caption,
+.goog-rounded-tab-inner-edge,
+.goog-rounded-tab-outer-edge {
+ background: #036;
+ border-right: 1px solid #003;
+}
+
+.goog-rounded-tab-inner-edge,
+.goog-rounded-tab-outer-edge {
+ font-size: 1px;
+ height: 1px;
+ overflow: hidden;
+}
+
+/* State: Hover */
+.goog-rounded-tab-hover .goog-rounded-tab-caption,
+.goog-rounded-tab-hover .goog-rounded-tab-inner-edge,
+.goog-rounded-tab-hover .goog-rounded-tab-outer-edge {
+ background-color: #69c;
+ border-right: 1px solid #369;
+}
+
+/* State: Disabled */
+.goog-rounded-tab-disabled .goog-rounded-tab-caption,
+.goog-rounded-tab-disabled .goog-rounded-tab-inner-edge,
+.goog-rounded-tab-disabled .goog-rounded-tab-outer-edge {
+ background: #ccc;
+ border-right: 1px solid #ccc;
+}
+
+/* State: Selected */
+.goog-rounded-tab-selected .goog-rounded-tab-caption,
+.goog-rounded-tab-selected .goog-rounded-tab-inner-edge,
+.goog-rounded-tab-selected .goog-rounded-tab-outer-edge {
+ background: #369 !important; /* Selected trumps hover. */
+ border-right: 1px solid #036 !important;
+}
+
+
+/*
+ * Styles for horizontal (top or bottom) tabs.
+ */
+.goog-tab-bar-top .goog-rounded-tab {
+ vertical-align: bottom;
+}
+
+.goog-tab-bar-bottom .goog-rounded-tab {
+ vertical-align: top;
+}
+
+.goog-tab-bar-top .goog-rounded-tab-outer-edge,
+.goog-tab-bar-bottom .goog-rounded-tab-outer-edge {
+ margin: 0 3px;
+}
+
+.goog-tab-bar-top .goog-rounded-tab-inner-edge,
+.goog-tab-bar-bottom .goog-rounded-tab-inner-edge {
+ margin: 0 1px;
+}
+
+
+/*
+ * Styles for vertical (start or end) tabs.
+ */
+.goog-tab-bar-start .goog-rounded-tab-table,
+.goog-tab-bar-end .goog-rounded-tab-table {
+ width: 100%;
+}
+
+.goog-tab-bar-start .goog-rounded-tab-inner-edge {
+ margin-left: 1px;
+}
+
+.goog-tab-bar-start .goog-rounded-tab-outer-edge {
+ margin-left: 3px;
+}
+
+.goog-tab-bar-end .goog-rounded-tab-inner-edge {
+ margin-right: 1px;
+}
+
+.goog-tab-bar-end .goog-rounded-tab-outer-edge {
+ margin-right: 3px;
+}
+
+
+/*
+ * Overrides for start tabs.
+ */
+.goog-tab-bar-start .goog-rounded-tab-table,
+.goog-tab-bar-end .goog-rounded-tab-table {
+ width: 12ex; /* TODO(attila): Make this work for variable width. */
+}
+
+.goog-tab-bar-start .goog-rounded-tab-caption,
+.goog-tab-bar-start .goog-rounded-tab-inner-edge,
+.goog-tab-bar-start .goog-rounded-tab-outer-edge {
+ border-left: 1px solid #003;
+ border-right: 0;
+}
+
+.goog-tab-bar-start .goog-rounded-tab-hover .goog-rounded-tab-caption,
+.goog-tab-bar-start .goog-rounded-tab-hover .goog-rounded-tab-inner-edge,
+.goog-tab-bar-start .goog-rounded-tab-hover .goog-rounded-tab-outer-edge {
+ border-left: 1px solid #369 !important;
+ border-right: 0 !important;
+}
+
+.goog-tab-bar-start .goog-rounded-tab-selected .goog-rounded-tab-outer-edge,
+.goog-tab-bar-start .goog-rounded-tab-selected .goog-rounded-tab-inner-edge,
+.goog-tab-bar-start .goog-rounded-tab-selected .goog-rounded-tab-caption {
+ border-left: 1px solid #036 !important;
+ border-right: 0 !important;
+}
+
+.goog-tab-bar-start .goog-rounded-tab-disabled .goog-rounded-tab-outer-edge,
+.goog-tab-bar-start .goog-rounded-tab-disabled .goog-rounded-tab-inner-edge,
+.goog-tab-bar-start .goog-rounded-tab-disabled .goog-rounded-tab-caption {
+ border-left: 1px solid #ccc !important;
+ border-right: 0 !important;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/submenu.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/submenu.css b/externs/GCL/externs/goog/css/submenu.css
new file mode 100644
index 0000000..1159b28
--- /dev/null
+++ b/externs/GCL/externs/goog/css/submenu.css
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for menus created by goog.ui.SubMenuRenderer.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+/* State: resting. */
+/* @noflip */
+.goog-submenu-arrow {
+ color: #000;
+ left: auto;
+ padding-right: 6px;
+ position: absolute;
+ right: 0;
+ text-align: right;
+}
+
+/* BiDi override. */
+/* @noflip */
+.goog-menuitem-rtl .goog-submenu-arrow {
+ text-align: left;
+ left: 0;
+ right: auto;
+ padding-left: 6px;
+}
+
+/* State: disabled. */
+.goog-menuitem-disabled .goog-submenu-arrow {
+ color: #ccc;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/tab.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/tab.css b/externs/GCL/externs/goog/css/tab.css
new file mode 100644
index 0000000..6c7dfe2
--- /dev/null
+++ b/externs/GCL/externs/goog/css/tab.css
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: attila@google.com (Attila Bodis) */
+/* Author: eae@google.com (Emil A. Eklund) */
+
+
+/*
+ * Styles used by goog.ui.TabRenderer.
+ */
+.goog-tab {
+ position: relative;
+ padding: 4px 8px;
+ color: #00c;
+ text-decoration: underline;
+ cursor: default;
+}
+
+.goog-tab-bar-top .goog-tab {
+ margin: 1px 4px 0 0;
+ border-bottom: 0;
+ float: left;
+}
+
+.goog-tab-bar-top:after,
+.goog-tab-bar-bottom:after {
+ content: " ";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+}
+
+.goog-tab-bar-bottom .goog-tab {
+ margin: 0 4px 1px 0;
+ border-top: 0;
+ float: left;
+}
+
+.goog-tab-bar-start .goog-tab {
+ margin: 0 0 4px 1px;
+ border-right: 0;
+}
+
+.goog-tab-bar-end .goog-tab {
+ margin: 0 1px 4px 0;
+ border-left: 0;
+}
+
+/* State: Hover */
+.goog-tab-hover {
+ background: #eee;
+}
+
+/* State: Disabled */
+.goog-tab-disabled {
+ color: #666;
+}
+
+/* State: Selected */
+.goog-tab-selected {
+ color: #000;
+ background: #fff;
+ text-decoration: none;
+ font-weight: bold;
+ border: 1px solid #6b90da;
+}
+
+.goog-tab-bar-top {
+ padding-top: 5px !important;
+ padding-left: 5px !important;
+ border-bottom: 1px solid #6b90da !important;
+}
+/*
+ * Shift selected tabs 1px towards the contents (and compensate via margin and
+ * padding) to visually merge the borders of the tab with the borders of the
+ * content area.
+ */
+.goog-tab-bar-top .goog-tab-selected {
+ top: 1px;
+ margin-top: 0;
+ padding-bottom: 5px;
+}
+
+.goog-tab-bar-bottom .goog-tab-selected {
+ top: -1px;
+ margin-bottom: 0;
+ padding-top: 5px;
+}
+
+.goog-tab-bar-start .goog-tab-selected {
+ left: 1px;
+ margin-left: 0;
+ padding-right: 9px;
+}
+
+.goog-tab-bar-end .goog-tab-selected {
+ left: -1px;
+ margin-right: 0;
+ padding-left: 9px;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/tabbar.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/tabbar.css b/externs/GCL/externs/goog/css/tabbar.css
new file mode 100644
index 0000000..514aa9b
--- /dev/null
+++ b/externs/GCL/externs/goog/css/tabbar.css
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: attila@google.com (Attila Bodis) */
+/* Author: eae@google.com (Emil A. Eklund) */
+
+
+/*
+ * Styles used by goog.ui.TabBarRenderer.
+ */
+.goog-tab-bar {
+ margin: 0;
+ border: 0;
+ padding: 0;
+ list-style: none;
+ cursor: default;
+ outline: none;
+ background: #ebeff9;
+}
+
+.goog-tab-bar-clear {
+ clear: both;
+ height: 0;
+ overflow: hidden;
+}
+
+.goog-tab-bar-start {
+ float: left;
+}
+
+.goog-tab-bar-end {
+ float: right;
+}
+
+
+/*
+ * IE6-only hacks to fix the gap between the floated tabs and the content.
+ * IE7 and later will ignore these.
+ */
+/* @if user.agent ie6 */
+* html .goog-tab-bar-start {
+ margin-right: -3px;
+}
+
+* html .goog-tab-bar-end {
+ margin-left: -3px;
+}
+/* @endif */
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/tablesorter.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/tablesorter.css b/externs/GCL/externs/goog/css/tablesorter.css
new file mode 100644
index 0000000..126f007
--- /dev/null
+++ b/externs/GCL/externs/goog/css/tablesorter.css
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2008 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: robbyw@google.com (Robby Walker) */
+
+/* Styles for goog.ui.TableSorter. */
+
+.goog-tablesorter-header {
+ cursor: pointer
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/toolbar.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/toolbar.css b/externs/GCL/externs/goog/css/toolbar.css
new file mode 100644
index 0000000..5c39dde
--- /dev/null
+++ b/externs/GCL/externs/goog/css/toolbar.css
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2009 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/*
+ * Standard styling for toolbars and toolbar items.
+ *
+ * @author attila@google.com (Attila Bodis)
+ */
+
+
+/*
+ * Styles used by goog.ui.ToolbarRenderer.
+ */
+
+.goog-toolbar {
+ /* Client apps may override the URL at which they serve the image. */
+ background: #fafafa url(//ssl.gstatic.com/editor/toolbar-bg.png) repeat-x bottom left;
+ border-bottom: 1px solid #d5d5d5;
+ cursor: default;
+ font: normal 12px Arial, sans-serif;
+ margin: 0;
+ outline: none;
+ padding: 2px;
+ position: relative;
+ zoom: 1; /* The toolbar element must have layout on IE. */
+}
+
+/*
+ * Styles used by goog.ui.ToolbarButtonRenderer.
+ */
+
+.goog-toolbar-button {
+ margin: 0 2px;
+ border: 0;
+ padding: 0;
+ font-family: Arial, sans-serif;
+ color: #333;
+ text-decoration: none;
+ list-style: none;
+ vertical-align: middle;
+ cursor: default;
+ outline: none;
+}
+
+/* Pseudo-rounded corners. */
+.goog-toolbar-button-outer-box,
+.goog-toolbar-button-inner-box {
+ border: 0;
+ vertical-align: top;
+}
+
+.goog-toolbar-button-outer-box {
+ margin: 0;
+ padding: 1px 0;
+}
+
+.goog-toolbar-button-inner-box {
+ margin: 0 -1px;
+ padding: 3px 4px;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-toolbar-button-inner-box {
+ /* IE6 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+
+/* Pre-IE7 BiDi fixes. */
+* html .goog-toolbar-button-rtl .goog-toolbar-button-outer-box {
+ /* @noflip */ left: -1px;
+}
+* html .goog-toolbar-button-rtl .goog-toolbar-button-inner-box {
+ /* @noflip */ right: auto;
+}
+
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-toolbar-button-inner-box {
+ /* IE7 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+
+/* IE7 BiDi fix. */
+*:first-child+html .goog-toolbar-button-rtl .goog-toolbar-button-inner-box {
+ /* @noflip */ left: 1px;
+ /* @noflip */ right: auto;
+}
+
+/* Safari-only hacks. */
+::root .goog-toolbar-button,
+::root .goog-toolbar-button-outer-box {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: 0;
+}
+
+::root .goog-toolbar-button-inner-box {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: normal;
+}
+
+/* Disabled styles. */
+.goog-toolbar-button-disabled {
+ opacity: 0.3;
+ -moz-opacity: 0.3;
+ filter: alpha(opacity=30);
+}
+
+.goog-toolbar-button-disabled .goog-toolbar-button-outer-box,
+.goog-toolbar-button-disabled .goog-toolbar-button-inner-box {
+ /* Disabled text/border color trumps everything else. */
+ color: #333 !important;
+ border-color: #999 !important;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-toolbar-button-disabled {
+ /* IE can't apply alpha to an element with a transparent background... */
+ background-color: #f0f0f0;
+ margin: 0 1px;
+ padding: 0 1px;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-toolbar-button-disabled {
+ /* IE can't apply alpha to an element with a transparent background... */
+ background-color: #f0f0f0;
+ margin: 0 1px;
+ padding: 0 1px;
+}
+
+/* Only draw borders when in a non-default state. */
+.goog-toolbar-button-hover .goog-toolbar-button-outer-box,
+.goog-toolbar-button-active .goog-toolbar-button-outer-box,
+.goog-toolbar-button-checked .goog-toolbar-button-outer-box,
+.goog-toolbar-button-selected .goog-toolbar-button-outer-box {
+ border-width: 1px 0;
+ border-style: solid;
+ padding: 0;
+}
+
+.goog-toolbar-button-hover .goog-toolbar-button-inner-box,
+.goog-toolbar-button-active .goog-toolbar-button-inner-box,
+.goog-toolbar-button-checked .goog-toolbar-button-inner-box,
+.goog-toolbar-button-selected .goog-toolbar-button-inner-box {
+ border-width: 0 1px;
+ border-style: solid;
+ padding: 3px;
+}
+
+/* Hover styles. */
+.goog-toolbar-button-hover .goog-toolbar-button-outer-box,
+.goog-toolbar-button-hover .goog-toolbar-button-inner-box {
+ /* Hover border style wins over active/checked/selected. */
+ border-color: #a1badf !important;
+}
+
+/* Active/checked/selected styles. */
+.goog-toolbar-button-active,
+.goog-toolbar-button-checked,
+.goog-toolbar-button-selected {
+ /* Active/checked/selected background color always wins. */
+ background-color: #dde1eb !important;
+}
+
+.goog-toolbar-button-active .goog-toolbar-button-outer-box,
+.goog-toolbar-button-active .goog-toolbar-button-inner-box,
+.goog-toolbar-button-checked .goog-toolbar-button-outer-box,
+.goog-toolbar-button-checked .goog-toolbar-button-inner-box,
+.goog-toolbar-button-selected .goog-toolbar-button-outer-box,
+.goog-toolbar-button-selected .goog-toolbar-button-inner-box {
+ border-color: #729bd1;
+}
+
+/* Pill (collapsed border) styles. */
+.goog-toolbar-button-collapse-right,
+.goog-toolbar-button-collapse-right .goog-toolbar-button-outer-box,
+.goog-toolbar-button-collapse-right .goog-toolbar-button-inner-box {
+ margin-right: 0;
+}
+
+.goog-toolbar-button-collapse-left,
+.goog-toolbar-button-collapse-left .goog-toolbar-button-outer-box,
+.goog-toolbar-button-collapse-left .goog-toolbar-button-inner-box {
+ margin-left: 0;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-toolbar-button-collapse-left .goog-toolbar-button-inner-box {
+ left: 0;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-toolbar-button-collapse-left
+.goog-toolbar-button-inner-box {
+ left: 0;
+}
+
+
+/*
+ * Styles used by goog.ui.ToolbarMenuButtonRenderer.
+ */
+
+.goog-toolbar-menu-button {
+ margin: 0 2px;
+ border: 0;
+ padding: 0;
+ font-family: Arial, sans-serif;
+ color: #333;
+ text-decoration: none;
+ list-style: none;
+ vertical-align: middle;
+ cursor: default;
+ outline: none;
+}
+
+/* Pseudo-rounded corners. */
+.goog-toolbar-menu-button-outer-box,
+.goog-toolbar-menu-button-inner-box {
+ border: 0;
+ vertical-align: top;
+}
+
+.goog-toolbar-menu-button-outer-box {
+ margin: 0;
+ padding: 1px 0;
+}
+
+.goog-toolbar-menu-button-inner-box {
+ margin: 0 -1px;
+ padding: 3px 4px;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-toolbar-menu-button-inner-box {
+ /* IE6 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+
+/* Pre-IE7 BiDi fixes. */
+* html .goog-toolbar-menu-button-rtl .goog-toolbar-menu-button-outer-box {
+ /* @noflip */ left: -1px;
+}
+* html .goog-toolbar-menu-button-rtl .goog-toolbar-menu-button-inner-box {
+ /* @noflip */ right: auto;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-toolbar-menu-button-inner-box {
+ /* IE7 needs to have the box shifted to make the borders line up. */
+ left: -1px;
+}
+
+/* IE7 BiDi fix. */
+*:first-child+html .goog-toolbar-menu-button-rtl
+ .goog-toolbar-menu-button-inner-box {
+ /* @noflip */ left: 1px;
+ /* @noflip */ right: auto;
+}
+
+/* Safari-only hacks. */
+::root .goog-toolbar-menu-button,
+::root .goog-toolbar-menu-button-outer-box,
+::root .goog-toolbar-menu-button-inner-box {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: 0;
+}
+
+::root .goog-toolbar-menu-button-caption,
+::root .goog-toolbar-menu-button-dropdown {
+ /* Required to make pseudo-rounded corners work on Safari. */
+ line-height: normal;
+}
+
+/* Disabled styles. */
+.goog-toolbar-menu-button-disabled {
+ opacity: 0.3;
+ -moz-opacity: 0.3;
+ filter: alpha(opacity=30);
+}
+
+.goog-toolbar-menu-button-disabled .goog-toolbar-menu-button-outer-box,
+.goog-toolbar-menu-button-disabled .goog-toolbar-menu-button-inner-box {
+ /* Disabled text/border color trumps everything else. */
+ color: #333 !important;
+ border-color: #999 !important;
+}
+
+/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */
+* html .goog-toolbar-menu-button-disabled {
+ /* IE can't apply alpha to an element with a transparent background... */
+ background-color: #f0f0f0;
+ margin: 0 1px;
+ padding: 0 1px;
+}
+
+/* IE7-only hack; ignored by all other browsers. */
+*:first-child+html .goog-toolbar-menu-button-disabled {
+ /* IE can't apply alpha to an element with a transparent background... */
+ background-color: #f0f0f0;
+ margin: 0 1px;
+ padding: 0 1px;
+}
+
+/* Only draw borders when in a non-default state. */
+.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-outer-box,
+.goog-toolbar-menu-button-active .goog-toolbar-menu-button-outer-box,
+.goog-toolbar-menu-button-open .goog-toolbar-menu-button-outer-box {
+ border-width: 1px 0;
+ border-style: solid;
+ padding: 0;
+}
+
+.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-inner-box,
+.goog-toolbar-menu-button-active .goog-toolbar-menu-button-inner-box,
+.goog-toolbar-menu-button-open .goog-toolbar-menu-button-inner-box {
+ border-width: 0 1px;
+ border-style: solid;
+ padding: 3px;
+}
+
+/* Hover styles. */
+.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-outer-box,
+.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-inner-box {
+ /* Hover border color trumps active/open style. */
+ border-color: #a1badf !important;
+}
+
+/* Active/open styles. */
+.goog-toolbar-menu-button-active,
+.goog-toolbar-menu-button-open {
+ /* Active/open background color wins. */
+ background-color: #dde1eb !important;
+}
+
+.goog-toolbar-menu-button-active .goog-toolbar-menu-button-outer-box,
+.goog-toolbar-menu-button-active .goog-toolbar-menu-button-inner-box,
+.goog-toolbar-menu-button-open .goog-toolbar-menu-button-outer-box,
+.goog-toolbar-menu-button-open .goog-toolbar-menu-button-inner-box {
+ border-color: #729bd1;
+}
+
+/* Menu button caption style. */
+.goog-toolbar-menu-button-caption {
+ padding: 0 4px 0 0;
+ vertical-align: middle;
+}
+
+/* Dropdown style. */
+.goog-toolbar-menu-button-dropdown {
+ width: 7px;
+ /* Client apps may override the URL at which they serve the sprite. */
+ background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0;
+ vertical-align: middle;
+}
+
+
+/*
+ * Styles used by goog.ui.ToolbarSeparatorRenderer.
+ */
+
+.goog-toolbar-separator {
+ margin: 0 2px;
+ border-left: 1px solid #d6d6d6;
+ border-right: 1px solid #f7f7f7;
+ padding: 0;
+ width: 0;
+ text-decoration: none;
+ list-style: none;
+ outline: none;
+ vertical-align: middle;
+ line-height: normal;
+ font-size: 120%;
+ overflow: hidden;
+}
+
+
+/*
+ * Additional styling for toolbar select controls, which always have borders.
+ */
+
+.goog-toolbar-select .goog-toolbar-menu-button-outer-box {
+ border-width: 1px 0;
+ border-style: solid;
+ padding: 0;
+}
+
+.goog-toolbar-select .goog-toolbar-menu-button-inner-box {
+ border-width: 0 1px;
+ border-style: solid;
+ padding: 3px;
+}
+
+.goog-toolbar-select .goog-toolbar-menu-button-outer-box,
+.goog-toolbar-select .goog-toolbar-menu-button-inner-box {
+ border-color: #bfcbdf;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/tooltip.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/tooltip.css b/externs/GCL/externs/goog/css/tooltip.css
new file mode 100644
index 0000000..0264583
--- /dev/null
+++ b/externs/GCL/externs/goog/css/tooltip.css
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+.goog-tooltip {
+ background: #ffe;
+ border: 1px solid #999;
+ border-width: 1px 2px 2px 1px;
+ padding: 6px;
+ z-index: 30000;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/tree.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/tree.css b/externs/GCL/externs/goog/css/tree.css
new file mode 100644
index 0000000..aeb1d0b
--- /dev/null
+++ b/externs/GCL/externs/goog/css/tree.css
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: arv@google.com (Erik Arvidsson) */
+/* Author: eae@google.com (Emil A Eklund) */
+/* Author: jonp@google.com (Jon Perlow) */
+
+/*
+ TODO(arv): Currently the sprite image has the height 16px. We should make the
+ image taller which would allow better flexibility when it comes to the height
+ of a tree row.
+*/
+
+.goog-tree-root:focus {
+ outline: none;
+}
+
+.goog-tree-row {
+ white-space: nowrap;
+ font: icon;
+ line-height: 16px;
+ height: 16px;
+}
+
+.goog-tree-row span {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.goog-tree-children {
+ background-repeat: repeat-y;
+ background-image: url(//ssl.gstatic.com/closure/tree/I.png) !important;
+ background-position-y: 1px !important; /* IE only */
+ font: icon;
+}
+
+.goog-tree-children-nolines {
+ font: icon;
+}
+
+.goog-tree-icon {
+ background-image: url(//ssl.gstatic.com/closure/tree/tree.png);
+}
+
+.goog-tree-expand-icon {
+ vertical-align: middle;
+ height: 16px;
+ width: 16px;
+ cursor: default;
+}
+
+.goog-tree-expand-icon-plus {
+ width: 19px;
+ background-position: 0 0;
+}
+
+.goog-tree-expand-icon-minus {
+ width: 19px;
+ background-position: -24px 0;
+}
+
+.goog-tree-expand-icon-tplus {
+ width: 19px;
+ background-position: -48px 0;
+}
+
+.goog-tree-expand-icon-tminus {
+ width: 19px;
+ background-position: -72px 0;
+}
+
+.goog-tree-expand-icon-lplus {
+ width: 19px;
+ background-position: -96px 0;
+}
+
+.goog-tree-expand-icon-lminus {
+ width: 19px;
+ background-position: -120px 0;
+}
+
+.goog-tree-expand-icon-t {
+ width: 19px;
+ background-position: -144px 0;
+}
+
+.goog-tree-expand-icon-l {
+ width: 19px;
+ background-position: -168px 0;
+}
+
+.goog-tree-expand-icon-blank {
+ width: 19px;
+ background-position: -168px -24px;
+}
+
+.goog-tree-collapsed-folder-icon {
+ vertical-align: middle;
+ height: 16px;
+ width: 16px;
+ background-position: -0px -24px;
+}
+
+.goog-tree-expanded-folder-icon {
+ vertical-align: middle;
+ height: 16px;
+ width: 16px;
+ background-position: -24px -24px;
+}
+
+.goog-tree-file-icon {
+ vertical-align: middle;
+ height: 16px;
+ width: 16px;
+ background-position: -48px -24px;
+}
+
+.goog-tree-item-label {
+ margin-left: 3px;
+ padding: 1px 2px 1px 2px;
+ text-decoration: none;
+ color: WindowText;
+ cursor: default;
+}
+
+.goog-tree-item-label:hover {
+ text-decoration: underline;
+}
+
+.selected .goog-tree-item-label {
+ background-color: ButtonFace;
+ color: ButtonText;
+}
+
+.focused .selected .goog-tree-item-label {
+ background-color: Highlight;
+ color: HighlightText;
+}
+
+.goog-tree-hide-root {
+ display: none;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/css/tristatemenuitem.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/css/tristatemenuitem.css b/externs/GCL/externs/goog/css/tristatemenuitem.css
new file mode 100644
index 0000000..8c98448
--- /dev/null
+++ b/externs/GCL/externs/goog/css/tristatemenuitem.css
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+/* Author: pupius@google.com (Daniel Pupius) */
+
+/* goog.ui.TriStateMenuItem */
+
+.goog-tristatemenuitem {
+ padding: 2px 5px;
+ margin: 0;
+ list-style: none;
+}
+
+.goog-tristatemenuitem-highlight {
+ background-color: #4279A5;
+ color: #FFF;
+}
+
+.goog-tristatemenuitem-disabled {
+ color: #999;
+}
+
+.goog-tristatemenuitem-checkbox {
+ float: left;
+ width: 10px;
+ height: 1.1em;
+}
+
+.goog-tristatemenuitem-partially-checked {
+ background-image: url(//ssl.gstatic.com/closure/check-outline.gif);
+ background-position: 4px 50%;
+ background-repeat: no-repeat;
+}
+
+.goog-tristatemenuitem-fully-checked {
+ background-image: url(//ssl.gstatic.com/closure/check.gif);
+ background-position: 4px 50%;
+ background-repeat: no-repeat;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/cssom/cssom.js
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/cssom/cssom.js b/externs/GCL/externs/goog/cssom/cssom.js
new file mode 100644
index 0000000..86a4235
--- /dev/null
+++ b/externs/GCL/externs/goog/cssom/cssom.js
@@ -0,0 +1,455 @@
+// 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 CSS Object Model helper functions.
+ * References:
+ * - W3C: http://dev.w3.org/csswg/cssom/
+ * - MSDN: http://msdn.microsoft.com/en-us/library/ms531209(VS.85).aspx.
+ * @supported in FF3, IE6, IE7, Safari 3.1.2, Chrome
+ * TODO(user): Fix in Opera.
+ * TODO(user): Consider hacking page, media, etc.. to work.
+ * This would be pretty challenging. IE returns the text for any rule
+ * regardless of whether or not the media is correct or not. Firefox at
+ * least supports CSSRule.type to figure out if it's a media type and then
+ * we could do something interesting, but IE offers no way for us to tell.
+ */
+
+goog.provide('goog.cssom');
+goog.provide('goog.cssom.CssRuleType');
+
+goog.require('goog.array');
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+
+
+/**
+ * Enumeration of {@code CSSRule} types.
+ * @enum {number}
+ */
+goog.cssom.CssRuleType = {
+ STYLE: 1,
+ IMPORT: 3,
+ MEDIA: 4,
+ FONT_FACE: 5,
+ PAGE: 6,
+ NAMESPACE: 7
+};
+
+
+/**
+ * Recursively gets all CSS as text, optionally starting from a given
+ * CSSStyleSheet.
+ * @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet.
+ * @return {string} css text.
+ */
+goog.cssom.getAllCssText = function(opt_styleSheet) {
+ var styleSheet = opt_styleSheet || document.styleSheets;
+ return /** @type {string} */ (goog.cssom.getAllCss_(styleSheet, true));
+};
+
+
+/**
+ * Recursively gets all CSSStyleRules, optionally starting from a given
+ * CSSStyleSheet.
+ * Note that this excludes any CSSImportRules, CSSMediaRules, etc..
+ * @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet.
+ * @return {Array<CSSStyleRule>} A list of CSSStyleRules.
+ */
+goog.cssom.getAllCssStyleRules = function(opt_styleSheet) {
+ var styleSheet = opt_styleSheet || document.styleSheets;
+ return /** @type {!Array<CSSStyleRule>} */ (
+ goog.cssom.getAllCss_(styleSheet, false));
+};
+
+
+/**
+ * Returns the CSSRules from a styleSheet.
+ * Worth noting here is that IE and FF differ in terms of what they will return.
+ * Firefox will return styleSheet.cssRules, which includes ImportRules and
+ * anything which implements the CSSRules interface. IE returns simply a list of
+ * CSSRules.
+ * @param {CSSStyleSheet} styleSheet The CSSStyleSheet.
+ * @throws {Error} If we cannot access the rules on a stylesheet object - this
+ * can happen if a stylesheet object's rules are accessed before the rules
+ * have been downloaded and parsed and are "ready".
+ * @return {CSSRuleList} An array of CSSRules or null.
+ */
+goog.cssom.getCssRulesFromStyleSheet = function(styleSheet) {
+ var cssRuleList = null;
+ try {
+ // Select cssRules unless it isn't present. For pre-IE9 IE, use the rules
+ // collection instead.
+ // It's important to be consistent in using only the W3C or IE apis on
+ // IE9+ where both are present to ensure that there is no indexing
+ // mismatches - the collections are subtly different in what the include or
+ // exclude which can lead to one collection being longer than the other
+ // depending on the page's construction.
+ cssRuleList = styleSheet.cssRules /* W3C */ || styleSheet.rules /* IE */;
+ } catch (e) {
+ // This can happen if we try to access the CSSOM before it's "ready".
+ if (e.code == 15) {
+ // Firefox throws an NS_ERROR_DOM_INVALID_ACCESS_ERR error if a stylesheet
+ // is read before it has been fully parsed. Let the caller know which
+ // stylesheet failed.
+ e.styleSheet = styleSheet;
+ throw e;
+ }
+ }
+ return cssRuleList;
+};
+
+
+/**
+ * Gets all CSSStyleSheet objects starting from some CSSStyleSheet. Note that we
+ * want to return the sheets in the order of the cascade, therefore if we
+ * encounter an import, we will splice that CSSStyleSheet object in front of
+ * the CSSStyleSheet that contains it in the returned array of CSSStyleSheets.
+ * @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet A CSSStyleSheet.
+ * @param {boolean=} opt_includeDisabled If true, includes disabled stylesheets,
+ * defaults to false.
+ * @return {!Array<CSSStyleSheet>} A list of CSSStyleSheet objects.
+ */
+goog.cssom.getAllCssStyleSheets = function(opt_styleSheet,
+ opt_includeDisabled) {
+ var styleSheetsOutput = [];
+ var styleSheet = opt_styleSheet || document.styleSheets;
+ var includeDisabled = goog.isDef(opt_includeDisabled) ? opt_includeDisabled :
+ false;
+
+ // Imports need to go first.
+ if (styleSheet.imports && styleSheet.imports.length) {
+ for (var i = 0, n = styleSheet.imports.length; i < n; i++) {
+ goog.array.extend(styleSheetsOutput,
+ goog.cssom.getAllCssStyleSheets(styleSheet.imports[i]));
+ }
+
+ } else if (styleSheet.length) {
+ // In case we get a StyleSheetList object.
+ // http://dev.w3.org/csswg/cssom/#the-stylesheetlist
+ for (var i = 0, n = styleSheet.length; i < n; i++) {
+ goog.array.extend(styleSheetsOutput,
+ goog.cssom.getAllCssStyleSheets(styleSheet[i]));
+ }
+ } else {
+ // We need to walk through rules in browsers which implement .cssRules
+ // to see if there are styleSheets buried in there.
+ // If we have a CSSStyleSheet within CssRules.
+ var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(
+ /** @type {!CSSStyleSheet} */ (styleSheet));
+ if (cssRuleList && cssRuleList.length) {
+ // Chrome does not evaluate cssRuleList[i] to undefined when i >=n;
+ // so we use a (i < n) check instead of cssRuleList[i] in the loop below
+ // and in other places where we iterate over a rules list.
+ // See issue # 5917 in Chromium.
+ for (var i = 0, n = cssRuleList.length, cssRule; i < n; i++) {
+ cssRule = cssRuleList[i];
+ // There are more stylesheets to get on this object..
+ if (cssRule.styleSheet) {
+ goog.array.extend(styleSheetsOutput,
+ goog.cssom.getAllCssStyleSheets(cssRule.styleSheet));
+ }
+ }
+ }
+ }
+
+ // This is a CSSStyleSheet. (IE uses .rules, W3c and Opera cssRules.)
+ if ((styleSheet.type || styleSheet.rules || styleSheet.cssRules) &&
+ (!styleSheet.disabled || includeDisabled)) {
+ styleSheetsOutput.push(styleSheet);
+ }
+
+ return styleSheetsOutput;
+};
+
+
+/**
+ * Gets the cssText from a CSSRule object cross-browserly.
+ * @param {CSSRule} cssRule A CSSRule.
+ * @return {string} cssText The text for the rule, including the selector.
+ */
+goog.cssom.getCssTextFromCssRule = function(cssRule) {
+ var cssText = '';
+
+ if (cssRule.cssText) {
+ // W3C.
+ cssText = cssRule.cssText;
+ } else if (cssRule.style && cssRule.style.cssText && cssRule.selectorText) {
+ // IE: The spacing here is intended to make the result consistent with
+ // FF and Webkit.
+ // We also remove the special properties that we may have added in
+ // getAllCssStyleRules since IE includes those in the cssText.
+ var styleCssText = cssRule.style.cssText.
+ replace(/\s*-closure-parent-stylesheet:\s*\[object\];?\s*/gi, '').
+ replace(/\s*-closure-rule-index:\s*[\d]+;?\s*/gi, '');
+ var thisCssText = cssRule.selectorText + ' { ' + styleCssText + ' }';
+ cssText = thisCssText;
+ }
+
+ return cssText;
+};
+
+
+/**
+ * Get the index of the CSSRule in it's CSSStyleSheet.
+ * @param {CSSRule} cssRule A CSSRule.
+ * @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet
+ * object this cssRule belongs to.
+ * @throws {Error} When we cannot get the parentStyleSheet.
+ * @return {number} The index of the CSSRule, or -1.
+ */
+goog.cssom.getCssRuleIndexInParentStyleSheet = function(cssRule,
+ opt_parentStyleSheet) {
+ // Look for our special style.ruleIndex property from getAllCss.
+ if (cssRule.style && cssRule.style['-closure-rule-index']) {
+ return cssRule.style['-closure-rule-index'];
+ }
+
+ var parentStyleSheet = opt_parentStyleSheet ||
+ goog.cssom.getParentStyleSheet(cssRule);
+
+ if (!parentStyleSheet) {
+ // We could call getAllCssStyleRules() here to get our special indexes on
+ // the style object, but that seems like it could be wasteful.
+ throw Error('Cannot find a parentStyleSheet.');
+ }
+
+ var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(parentStyleSheet);
+ if (cssRuleList && cssRuleList.length) {
+ for (var i = 0, n = cssRuleList.length, thisCssRule; i < n; i++) {
+ thisCssRule = cssRuleList[i];
+ if (thisCssRule == cssRule) {
+ return i;
+ }
+ }
+ }
+ return -1;
+};
+
+
+/**
+ * We do some trickery in getAllCssStyleRules that hacks this in for IE.
+ * If the cssRule object isn't coming from a result of that function call, this
+ * method will return undefined in IE.
+ * @param {CSSRule} cssRule The CSSRule.
+ * @return {CSSStyleSheet} A styleSheet object.
+ */
+goog.cssom.getParentStyleSheet = function(cssRule) {
+ return cssRule.parentStyleSheet ||
+ cssRule.style &&
+ cssRule.style['-closure-parent-stylesheet'];
+};
+
+
+/**
+ * Replace a cssRule with some cssText for a new rule.
+ * If the cssRule object is not one of objects returned by
+ * getAllCssStyleRules, then you'll need to provide both the styleSheet and
+ * possibly the index, since we can't infer them from the standard cssRule
+ * object in IE. We do some trickery in getAllCssStyleRules to hack this in.
+ * @param {CSSRule} cssRule A CSSRule.
+ * @param {string} cssText The text for the new CSSRule.
+ * @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet
+ * object this cssRule belongs to.
+ * @param {number=} opt_index The index of the cssRule in its parentStylesheet.
+ * @throws {Error} If we cannot find a parentStyleSheet.
+ * @throws {Error} If we cannot find a css rule index.
+ */
+goog.cssom.replaceCssRule = function(cssRule, cssText, opt_parentStyleSheet,
+ opt_index) {
+ var parentStyleSheet = opt_parentStyleSheet ||
+ goog.cssom.getParentStyleSheet(cssRule);
+ if (parentStyleSheet) {
+ var index = opt_index >= 0 ? opt_index :
+ goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule, parentStyleSheet);
+ if (index >= 0) {
+ goog.cssom.removeCssRule(parentStyleSheet, index);
+ goog.cssom.addCssRule(parentStyleSheet, cssText, index);
+ } else {
+ throw Error('Cannot proceed without the index of the cssRule.');
+ }
+ } else {
+ throw Error('Cannot proceed without the parentStyleSheet.');
+ }
+};
+
+
+/**
+ * Cross browser function to add a CSSRule into a CSSStyleSheet, optionally
+ * at a given index.
+ * @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet.
+ * @param {string} cssText The text for the new CSSRule.
+ * @param {number=} opt_index The index of the cssRule in its parentStylesheet.
+ * @throws {Error} If the css rule text appears to be ill-formatted.
+ * TODO(bowdidge): Inserting at index 0 fails on Firefox 2 and 3 with an
+ * exception warning "Node cannot be inserted at the specified point in
+ * the hierarchy."
+ */
+goog.cssom.addCssRule = function(cssStyleSheet, cssText, opt_index) {
+ var index = opt_index;
+ if (index < 0 || index == undefined) {
+ // If no index specified, insert at the end of the current list
+ // of rules.
+ var rules = goog.cssom.getCssRulesFromStyleSheet(cssStyleSheet);
+ index = rules.length;
+ }
+ if (cssStyleSheet.insertRule) {
+ // W3C (including IE9+).
+ cssStyleSheet.insertRule(cssText, index);
+
+ } else {
+ // IE, pre 9: We have to parse the cssRule text to get the selector
+ // separated from the style text.
+ // aka Everything that isn't a colon, followed by a colon, then
+ // the rest is the style part.
+ var matches = /^([^\{]+)\{([^\{]+)\}/.exec(cssText);
+ if (matches.length == 3) {
+ var selector = matches[1];
+ var style = matches[2];
+ cssStyleSheet.addRule(selector, style, index);
+ } else {
+ throw Error('Your CSSRule appears to be ill-formatted.');
+ }
+ }
+};
+
+
+/**
+ * Cross browser function to remove a CSSRule in a CSSStyleSheet at an index.
+ * @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet.
+ * @param {number} index The CSSRule's index in the parentStyleSheet.
+ */
+goog.cssom.removeCssRule = function(cssStyleSheet, index) {
+ if (cssStyleSheet.deleteRule) {
+ // W3C.
+ cssStyleSheet.deleteRule(index);
+
+ } else {
+ // IE.
+ cssStyleSheet.removeRule(index);
+ }
+};
+
+
+/**
+ * Appends a DOM node to HEAD containing the css text that's passed in.
+ * @param {string} cssText CSS to add to the end of the document.
+ * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper user for
+ * document interactions.
+ * @return {!Element} The newly created STYLE element.
+ */
+goog.cssom.addCssText = function(cssText, opt_domHelper) {
+ var document = opt_domHelper ? opt_domHelper.getDocument() :
+ goog.dom.getDocument();
+ var cssNode = document.createElement(goog.dom.TagName.STYLE);
+ cssNode.type = 'text/css';
+ var head = document.getElementsByTagName(goog.dom.TagName.HEAD)[0];
+ head.appendChild(cssNode);
+ if (cssNode.styleSheet) {
+ // IE.
+ cssNode.styleSheet.cssText = cssText;
+ } else {
+ // W3C.
+ var cssTextNode = document.createTextNode(cssText);
+ cssNode.appendChild(cssTextNode);
+ }
+ return cssNode;
+};
+
+
+/**
+ * Cross browser method to get the filename from the StyleSheet's href.
+ * Explorer only returns the filename in the href, while other agents return
+ * the full path.
+ * @param {!StyleSheet} styleSheet Any valid StyleSheet object with an href.
+ * @throws {Error} When there's no href property found.
+ * @return {?string} filename The filename, or null if not an external
+ * styleSheet.
+ */
+goog.cssom.getFileNameFromStyleSheet = function(styleSheet) {
+ var href = styleSheet.href;
+
+ // Another IE/FF difference. IE returns an empty string, while FF and others
+ // return null for CSSStyleSheets not from an external file.
+ if (!href) {
+ return null;
+ }
+
+ // We need the regexp to ensure we get the filename minus any query params.
+ var matches = /([^\/\?]+)[^\/]*$/.exec(href);
+ var filename = matches[1];
+ return filename;
+};
+
+
+/**
+ * Recursively gets all CSS text or rules.
+ * @param {CSSStyleSheet|StyleSheetList} styleSheet The CSSStyleSheet.
+ * @param {boolean} isTextOutput If true, output is cssText, otherwise cssRules.
+ * @return {string|!Array<CSSRule>} cssText or cssRules.
+ * @private
+ */
+goog.cssom.getAllCss_ = function(styleSheet, isTextOutput) {
+ var cssOut = [];
+ var styleSheets = goog.cssom.getAllCssStyleSheets(styleSheet);
+
+ for (var i = 0; styleSheet = styleSheets[i]; i++) {
+ var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
+
+ if (cssRuleList && cssRuleList.length) {
+
+ // We're going to track cssRule index if we want rule output.
+ if (!isTextOutput) {
+ var ruleIndex = 0;
+ }
+
+ for (var j = 0, n = cssRuleList.length, cssRule; j < n; j++) {
+ cssRule = cssRuleList[j];
+ // Gets cssText output, ignoring CSSImportRules.
+ if (isTextOutput && !cssRule.href) {
+ var res = goog.cssom.getCssTextFromCssRule(cssRule);
+ cssOut.push(res);
+
+ } else if (!cssRule.href) {
+ // Gets cssRules output, ignoring CSSImportRules.
+ if (cssRule.style) {
+ // This is a fun little hack to get parentStyleSheet into the rule
+ // object for IE since it failed to implement rule.parentStyleSheet.
+ // We can later read this property when doing things like hunting
+ // for indexes in order to delete a given CSSRule.
+ // Unfortunately we have to use the style object to store these
+ // pieces of info since the rule object is read-only.
+ if (!cssRule.parentStyleSheet) {
+ cssRule.style['-closure-parent-stylesheet'] = styleSheet;
+ }
+
+ // This is a hack to help with possible removal of the rule later,
+ // where we just append the rule's index in its parentStyleSheet
+ // onto the style object as a property.
+ // Unfortunately we have to use the style object to store these
+ // pieces of info since the rule object is read-only.
+ cssRule.style['-closure-rule-index'] = ruleIndex;
+ }
+ cssOut.push(cssRule);
+ }
+
+ if (!isTextOutput) {
+ ruleIndex++;
+ }
+ }
+ }
+ }
+ return isTextOutput ? cssOut.join(' ') : cssOut;
+};
+
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/cssom/cssom_test_import_1.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/cssom/cssom_test_import_1.css b/externs/GCL/externs/goog/cssom/cssom_test_import_1.css
new file mode 100644
index 0000000..566f907
--- /dev/null
+++ b/externs/GCL/externs/goog/cssom/cssom_test_import_1.css
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+@import "cssom_test_import_2.css";
+.css-import-1 {
+ display: block;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/cssom/cssom_test_import_2.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/cssom/cssom_test_import_2.css b/externs/GCL/externs/goog/cssom/cssom_test_import_2.css
new file mode 100644
index 0000000..dc31c96
--- /dev/null
+++ b/externs/GCL/externs/goog/cssom/cssom_test_import_2.css
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+.css-import-2 {
+ display: block;
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/cssom/cssom_test_link_1.css
----------------------------------------------------------------------
diff --git a/externs/GCL/externs/goog/cssom/cssom_test_link_1.css b/externs/GCL/externs/goog/cssom/cssom_test_link_1.css
new file mode 100644
index 0000000..832a8e3
--- /dev/null
+++ b/externs/GCL/externs/goog/cssom/cssom_test_link_1.css
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2010 The Closure Library Authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by the Apache License, Version 2.0.
+ * See the COPYING file for details.
+ */
+
+.css-link-1 {
+ display: block;
+}